/** * @fileoverview `indexLocalSkill` — pure core helper that registers a single * SKILL.md file's metadata into the local manifest snapshot * consumed by the namespace-audit collision detector * (SMI-4587 Wave 1 PR #4 / NEW-E-2). * @module @skillsmith/core/skills/index-local * * Extracted from `executeIndexLocal` in `@skillsmith/mcp-server/tools/index-local` * so the audit's `bootstrapUnmanagedSkills` callback can wire a real * implementation instead of the no-op stub. The MCP tool delegates to this * helper and adds the MCP envelope (timing, formatted summaries) on top. * * Pure-ish contract: * - Input: absolute path to a SKILL.md file (or its containing directory). * - Output: deterministic `IndexLocalSkillResult` with frontmatter-derived * metadata + a quality score. No global state mutated, no network IO. * - Filesystem reads only (`fs.readFileSync` on the SKILL.md). Throws if the * path resolves outside the caller's expected root — caller layers * `path-traversal` checks; this helper trusts what it's given. * * Surface kept narrow on purpose: Wave 2/3/4 callers should NOT reach into * core internals. Anything beyond `indexLocalSkill(absPath, opts?)` belongs * in mcp-server's tool layer. * * @see SMI-4587 plan §466 (NEW-E-2 surface grounding). */ /** * Frontmatter shape parsed from `SKILL.md`. Matches the subset the local * skill indexer relies on; extra keys are ignored. */ export interface IndexLocalSkillFrontmatter { name: string | null; description: string | null; author: string | null; tags: string[]; version: string | null; repository: string | null; homepage: string | null; compatibility: string[]; } /** * Deterministic result shape returned by {@link indexLocalSkill}. Used by: * - mcp-server's `executeIndexLocal` tool (formatted into the response) * - the audit `bootstrapUnmanagedSkills` callback (treated as success when * no error is thrown) * - frozen-fixture regression tests in this package. */ export interface IndexLocalSkillResult { /** Skill ID in `local/{name}` shape — matches LocalIndexer.id. */ id: string; /** Skill name from frontmatter or the directory fallback. */ name: string; /** Description from frontmatter (may be null when missing). */ description: string | null; /** Author from frontmatter; defaults to `'local'` when absent. */ author: string; /** Tags from frontmatter (empty array when missing). */ tags: string[]; /** Quality score 0..100 derived from frontmatter completeness. */ qualityScore: number; /** Always `'local'` for this helper — local-only by definition. */ trustTier: 'local'; /** Always `'local'` for this helper. */ source: 'local'; /** Absolute path to the skill directory. */ path: string; /** Whether `SKILL.md` was actually found at the resolved path. */ hasSkillMd: boolean; /** ISO timestamp of last directory mtime (null when stat fails). */ lastModified: string | null; /** Source repository URL from frontmatter (null when missing). */ repository: string | null; /** Compatibility tags from frontmatter (undefined when none). */ compatibility?: string[]; } /** * Optional knobs for {@link indexLocalSkill}. Defaults wired so callers can * pass just `(absPath)` in the common case. */ export interface IndexLocalSkillOptions { /** * Override the SKILL.md filename when an alternate manifest layout is in * use. Defaults to `'SKILL.md'`. */ skillManifestName?: string; /** * Inject a frontmatter parser. Defaults to the bundled minimal parser. The * MCP tool layer can pass `parseFrontmatter` from the existing * `FrontmatterParser` to keep parity with the indexer. */ parseFrontmatter?: (content: string) => IndexLocalSkillFrontmatter; } /** * Index a single local skill given the absolute path to its `SKILL.md` file * (or the directory that contains it). * * Pure side-effect-light: reads filesystem, does not write anywhere. Returns * a deterministic `IndexLocalSkillResult`. Throws when the path doesn't * resolve to an existing directory — the caller (audit bootstrap) translates * thrown errors into typed warnings. * * Parity with `mcp-server/indexer/LocalIndexer.indexSkillDir` is intentional; * the MCP tool will delegate here once this lands. The split is along a * per-skill boundary (helper) vs. per-directory traversal (indexer). */ export declare function indexLocalSkill(absPath: string, opts?: IndexLocalSkillOptions): IndexLocalSkillResult; //# sourceMappingURL=index-local.d.ts.map