/** * Walk knowledgeDir recursively, parse each .md file's frontmatter, and * return the Set of `name:` slugs. Throws if knowledgeDir does not exist * or is not a directory. README.md files are excluded (matches the * assembly loader's behavior). * * Acceptance rule matches extractKBFrontmatter: any non-empty trimmed * `name:` value is accepted. The slug regex lives in the freshness * validator, not here — keeping the loader permissive prevents drift * between what the assembly engine sees and what suppression matches. * * Uses js-yaml (already a project dependency — see * src/core/assembly/knowledge-loader.ts, observability-config.ts, and * knowledge-frontmatter-validator.ts) rather than a regex so we accept * exactly the same shapes the assembly engine does (comments, quoted * values, nested structures). The "dependency-free" Cross-Cutting * principle applies only to the directory walk + file I/O — not to * the frontmatter parsing. */ export declare function loadKnowledgeIndex(knowledgeDir: string): Set; /** * Wrap a value for safe one-line stderr interpolation. Wraps in single * quotes, escapes embedded single quotes with backslash, replaces * newlines/control characters with `?`. Returns the literal `''` * for undefined or empty input. Used by Lens I when composing * warn-once messages that include operator-supplied paths or * loader-supplied error reasons. */ export declare function formatForStderr(value: string | undefined): string; /** * Walk parent directories of `startDir` and return the absolute path of * the first `/content/knowledge` where `/package.json` * declares `name: "@zigrivers/scaffold"`. Walks to the filesystem root * without any home-directory boundary (npm-global installs live in * /opt/homebrew/... or /usr/local/..., outside the user's home). * * Returns null when no matching parent is found. * * The argument is the starting directory; production callers pass * `path.dirname(fileURLToPath(import.meta.url))` from a module that * lives inside the install. Tests can pass any directory directly. */ export declare function findScaffoldKnowledgeRoot(startDir: string): string | null; /** Convenience for production callers — derives the start dir from a * module's import.meta.url. `runAudit` and `runFixFlow` call this * with their own `import.meta.url` to anchor the auto-detect walk to * the install location. Tests should call `findScaffoldKnowledgeRoot` * directly with a fixture path. */ export declare function findScaffoldKnowledgeRootFromImportMeta(metaUrl: string): string | null; export type ValidateResult = { ok: true; index: Set; } | { ok: false; reason: string; }; /** * Validate that `candidatePath` is a real scaffold knowledge directory. * Two checks: * * 1. The directory exists, IS a directory, and contains a `VERSION` * marker file. VERSION lives ONLY at content/knowledge/VERSION in * the scaffold repo (added in Phase 1); requiring it forecloses * "operator pointed at an ancestor" cases like * `--knowledge-root /content` that would otherwise pass an * empty-tree-loose validator (the recursive walk would find the * nested KB entries). * 2. loadKnowledgeIndex(candidatePath) succeeds. An empty Set is * valid (freshly-initialized KB). * * Returns { ok: true, index } on success so the resolver doesn't have * to walk a second time. */ export declare function validateKnowledgeRoot(candidatePath: string): ValidateResult; /** * Write `message` to process.stderr exactly once per (set, key) tuple. * The dedup state lives in the caller-provided `warnedKeys` Set, NOT * in module-level state — this is intentional so multiple runAudit * invocations in one process (e.g. the --fix flow's initial + verifier * + postfix audits, or vitest's shared-module-state tests) each get * their own dedup scope. runAudit creates a fresh Set for each * invocation; tests pass their own. * * Uses process.stderr.write directly rather than console.warn so the * output never collides with JSON renders of audit output on stdout. */ export declare function emitOnceForAudit(warnedKeys: Set, key: string, message: string): void; /** Thrown by `resolveKnowledgeRoot` when an operator-supplied CLI * override path fails validation. The CLI handler (handleAudit) * catches it and exits non-zero. */ export declare class KnowledgeRootCliInvalidError extends Error { readonly path: string; readonly reason: string; constructor(path: string, reason: string); } export interface KnowledgeRootAttempt { source: 'cli' | 'yaml' | 'auto-detect'; path?: string; outcome: 'used' | 'invalid' | 'not-provided' | 'not-found'; reason?: string; } export interface KnowledgeRootResolution { /** Validated absolute path to a knowledge directory, or null. */ root: string | null; /** Pre-loaded index Set, populated by the validator. Null when root * is null. Lens I reads this directly — no re-walk. */ index: Set | null; /** Audit trail of what was tried. Lens I uses this to compose a * precise warn-once message when root is null. */ attempts: KnowledgeRootAttempt[]; } export interface ResolveInput { /** Optional caller-supplied CLI override (operator-typed * --knowledge-root flag). Invalid paths throw * KnowledgeRootCliInvalidError. */ override?: string; /** Working directory for reading .scaffold/observability.yaml. When * undefined, the yaml tier is skipped (recorded as * outcome: 'not-provided'). Typically the audited project's root. */ cwd?: string; /** Optional starting directory for the auto-detect parent-walk. * Production callers (runAudit, runFixFlow) pass a directory * INSIDE the CLI install — typically * `dirname(fileURLToPath(import.meta.url))` of their own module — * so the walk finds the install's `package.json` and * `content/knowledge/`. When undefined, falls back to `cwd` (and * then `process.cwd()`); this fallback is intended for tests, NOT * production. Without selfLocation, auto-detect cannot succeed for * downstream users running scaffold from outside the scaffold repo. */ selfLocation?: string; } /** * 3-tier knowledge-root resolution per the design spec (§2): * 1. CLI override (hard-errors on validation failure) * 2. .scaffold/observability.yaml lenses.I-knowledge-gaps.knowledge_root * (soft-fails to auto-detect on validation failure) * 3. findScaffoldKnowledgeRoot starting from cwd (returns null if no * scaffold install is above the start dir) * * Returns a record carrying the validated root, the pre-loaded index * (eliminating the need for a second walk in Lens I), and the * attempts trail (used by Lens I's warning composition). */ export declare function resolveKnowledgeRoot(input: ResolveInput): KnowledgeRootResolution; //# sourceMappingURL=knowledge-index.d.ts.map