/**
 * Canonical Doc-Kind Taxonomy Registry (T9788).
 *
 * Single source of truth for the user-facing document-kind taxonomy consumed
 * by `cleo docs` (add / list / publish-pr / list-types / schema). Prior to
 * this module the taxonomy was duplicated across three files:
 *
 * - `packages/contracts/src/operations/docs.ts` — `DOCS_TYPE_VALUES` (6 kinds)
 * - `packages/core/src/docs/publish-pr.ts` — `KNOWN_DOC_TYPES` (6 kinds)
 * - `packages/cleo/src/dispatch/domains/docs.ts` — local mirror (6 kinds)
 *
 * The three copies drifted independently. T9788 consolidates them behind
 * {@link DocKindRegistry} so a new kind requires editing exactly one place
 * (or one config file for project-level extensions).
 *
 * IMPORTANT — relationship to {@link import('./docs-accessor.js').DocKind}:
 * `DocKind` in `docs-accessor.ts` is the STORAGE-LAYER discriminator (which
 * backing store holds the bytes — llmtxt.db vs manifest.db). The taxonomy
 * here is the USER-FACING DOCUMENT CLASSIFICATION (what kind of document
 * the human / agent authored). The two are intentionally distinct:
 *
 * - `docs-accessor.DocKind` answers "where is it stored?"
 * - `docs-taxonomy.DocKindMetadata.kind` answers "what is it about?"
 *
 * Most user-facing docs are stored under `docs-accessor.DocKind = 'adr'` or
 * `'agent-output'`; their taxonomy `kind` (this file) carries the semantic
 * classification.
 *
 * Backward compatibility (T9788 AC8):
 * - Every prior `DOCS_TYPE_VALUES` value remains in {@link BUILTIN_DOC_KINDS}.
 * - Tests using literal strings `'spec'`, `'adr'`, etc. continue to pass.
 * - The stored `type` column shape is unchanged (still a string).
 *
 * @epic T9787 (E-DOCS-TAXONOMY-V2)
 * @task T9788
 * @see ADR-073 §1 — Task Hierarchy Charter (sibling registry pattern)
 */
/**
 * Metadata for a single document kind in the canonical registry.
 *
 * Built-in kinds are declared in {@link BUILTIN_DOC_KINDS}; project-level
 * extensions are loaded from `.cleo/docs-config.json` via
 * {@link DocKindRegistry.load}.
 *
 * @see {@link DocKindRegistry} — runtime accessor and validator
 */
export interface DocKindMetadata {
    /** Canonical kind id, lowercase kebab-case. */
    readonly kind: string;
    /** Human label for display in CLI output and UIs. */
    readonly label: string;
    /** One-line description shown by `cleo docs list-types`. */
    readonly description: string;
    /**
     * Default owner kind prefix when no explicit owner is provided.
     *
     * - `task` — `T###`
     * - `session` — `ses_*`
     * - `observation` — `O-*`
     * - `project` — repo-root project doc (no entity owner)
     */
    readonly defaultOwnerKind: 'task' | 'session' | 'observation' | 'project';
    /**
     * Publish-dir under the repo root for `cleo docs publish-pr`.
     *
     * Examples: `docs/adr`, `docs/spec`, `.changeset`, `docs/release`.
     */
    readonly publishDir: string;
    /**
     * When `true`, every doc of this kind MUST carry a slug matching
     * {@link entityIdPattern}.
     *
     * Used by `cleo docs add --type X --slug Y` to enforce naming
     * conventions for kinds whose downstream consumers parse the slug
     * (e.g. ADRs expect `adr-NNN-<rest>`).
     */
    readonly requiresEntityId: boolean;
    /**
     * Regex slug pattern. Validated when {@link requiresEntityId} is `true`.
     *
     * Stored as a {@link RegExp} so the validator can run without a
     * compile step. Extensions loaded from `.cleo/docs-config.json` parse
     * their string pattern into a `RegExp` at load time.
     */
    readonly entityIdPattern?: RegExp;
    /**
     * Marks an entry that was loaded from `.cleo/docs-config.json` rather
     * than the built-in {@link BUILTIN_DOC_KINDS} array.
     *
     * Built-in kinds leave this unset; extensions set it to `true`.
     */
    readonly isExtension?: boolean;
    /**
     * Optional list of H2 section titles that MUST appear in the document
     * body. Validated by `validateDocBody(kind, body)` (T10160).
     *
     * Match is case-insensitive and tolerant of hyphen-vs-space variants
     * (e.g. `## Next Steps` and `## next-steps` both satisfy a required
     * section of `Next Steps`).
     *
     * Empty or omitted → no body schema requirements for this kind.
     *
     * @task T10160 (E12.C3 · absorbs T10154)
     * @epic T10157
     */
    readonly requiredSections?: ReadonlyArray<string>;
}
/**
 * Canonical list of built-in document kinds.
 *
 * Adding a kind requires:
 *   1. Append an entry here (preserving existing kinds for back-compat).
 *   2. Run the contracts build — every consumer picks the new kind up.
 *
 * Order is preserved by {@link DocKindRegistry.list}. Built-in kinds
 * always sort before extensions.
 *
 * @see {@link DocKindMetadata} — entry shape
 */
export declare const BUILTIN_DOC_KINDS: ReadonlyArray<DocKindMetadata>;
/**
 * Tuple of every built-in kind id (lowercase kebab-case).
 *
 * Useful for `satisfies` checks and union derivation in downstream
 * contracts (e.g. `operations/docs.ts`). Kept frozen.
 */
export declare const BUILTIN_DOC_KIND_VALUES: ReadonlyArray<string>;
/**
 * Union of every built-in kind id.
 *
 * Extensions loaded at runtime widen the runtime registry but NOT this
 * compile-time type — that is intentional: extensions are opt-in and
 * code that only handles the built-in surface stays type-safe.
 */
export type BuiltinDocKind = (typeof BUILTIN_DOC_KINDS)[number]['kind'];
/**
 * Wire shape of an extension entry in `.cleo/docs-config.json`.
 *
 * `entityIdPattern` is a string here (not a {@link RegExp}) because JSON
 * cannot carry compiled regexes. {@link DocKindRegistry.load} compiles it
 * to a `RegExp` while validating the config.
 */
export interface DocKindExtensionConfig {
    /** Canonical kind id, lowercase kebab-case. */
    readonly kind: string;
    /** Human label for display. */
    readonly label: string;
    /** One-line description for `cleo docs list-types`. */
    readonly description: string;
    /** Default owner kind prefix. */
    readonly defaultOwnerKind: 'task' | 'session' | 'observation' | 'project';
    /** Publish-dir under repo root. */
    readonly publishDir: string;
    /** When `true`, slug MUST match {@link entityIdPattern}. */
    readonly requiresEntityId: boolean;
    /**
     * Regex source string (no flags). Compiled to a `RegExp` at load time.
     *
     * Validated against {@link DocKindRegistry.SAFE_REGEX_LENGTH_LIMIT} so
     * a malformed config can't trigger pathological backtracking.
     */
    readonly entityIdPattern?: string;
    /**
     * Optional list of required H2 section titles for this extension kind.
     *
     * Same semantics as {@link DocKindMetadata.requiredSections} — matched
     * case-insensitively with hyphen/space normalisation. Omit or pass
     * `[]` for kinds that have no body schema.
     *
     * @task T10160
     */
    readonly requiredSections?: ReadonlyArray<string>;
}
/**
 * Top-level shape of `.cleo/docs-config.json`.
 *
 * Future fields stay backward compatible by being optional.
 */
export interface DocKindConfigFile {
    /** Project-level extension registry. */
    readonly extensions?: ReadonlyArray<DocKindExtensionConfig>;
}
/**
 * Result of {@link DocKindRegistry.validateSlug}.
 *
 * - `ok: true` — slug is valid for the given kind.
 * - `ok: false` — slug fails validation; `error` carries a human-readable
 *   reason and `example` shows a passing slug.
 */
export type SlugValidationResult = {
    readonly ok: true;
} | {
    readonly ok: false;
    readonly error: string;
    readonly example?: string;
};
/**
 * Runtime accessor for the canonical doc-kind registry.
 *
 * Combines {@link BUILTIN_DOC_KINDS} with project-level extensions loaded
 * from `.cleo/docs-config.json`. Built-in entries always win on collision
 * — extensions cannot override a built-in kind.
 *
 * Usage:
 * ```ts
 * const registry = DocKindRegistry.load(projectRoot);
 * const adr = registry.get('adr');
 * const check = registry.validateSlug('adr', 'adr-001-intro');
 * ```
 *
 * @task T9788
 */
export declare class DocKindRegistry {
    /**
     * Maximum allowed length of an `entityIdPattern` source string.
     *
     * Caps the input surface so a malformed extension config cannot trigger
     * pathological regex backtracking. 256 chars is far more than any
     * realistic slug pattern (typical: 30–60 chars).
     */
    static readonly SAFE_REGEX_LENGTH_LIMIT = 256;
    private readonly byKind;
    private readonly orderedEntries;
    /**
     * Construct a registry from an explicit array of entries.
     *
     * Most callers should use {@link DocKindRegistry.load} instead; this
     * constructor is exposed for tests that want to bypass filesystem I/O.
     *
     * @param entries - Pre-validated doc-kind metadata (built-in + extensions).
     */
    constructor(entries: ReadonlyArray<DocKindMetadata>);
    /**
     * Load the canonical registry, merging built-ins with extensions from
     * `<projectRoot>/.cleo/docs-config.json`.
     *
     * Missing or unreadable config file → returns the built-in-only registry.
     * Malformed config (bad JSON, invalid entry, regex too long, etc.) →
     * throws {@link DocKindConfigError} so the caller can surface a clear
     * envelope rather than silently dropping extensions.
     *
     * @param projectRoot - Absolute path to the repo root.
     * @throws DocKindConfigError when the config exists but is invalid.
     */
    static load(projectRoot: string): DocKindRegistry;
    /**
     * Build a registry from already-parsed config — bypasses filesystem I/O.
     *
     * Used by tests and HTTP-dispatch callers that hand-construct a config
     * object instead of reading from disk.
     *
     * @param config - Parsed config object (or `undefined` for built-ins only).
     * @param sourceLabel - Optional label used in error messages.
     * @throws DocKindConfigError when the config object is invalid.
     */
    static fromConfig(config: DocKindConfigFile | undefined, sourceLabel?: string): DocKindRegistry;
    /**
     * Default registry — built-in kinds only, no extensions.
     *
     * Suitable for code paths that never need project-level extensions
     * (e.g. unit tests, library-mode consumers).
     */
    static builtinOnly(): DocKindRegistry;
    /** True when `kind` is registered (built-in OR extension). */
    has(kind: string): boolean;
    /** Look up metadata for a registered kind. Returns `undefined` on miss. */
    get(kind: string): DocKindMetadata | undefined;
    /**
     * List every registered kind, built-ins first then extensions in
     * declaration order.
     *
     * Used by `cleo docs schema` and `cleo docs list-types`.
     */
    list(): ReadonlyArray<DocKindMetadata>;
    /**
     * Validate a slug against the registered pattern for `kind`.
     *
     * Behaviour:
     * - Unknown kind → `{ ok: false, error: "unknown kind '<kind>'" }`.
     * - Known kind with `requiresEntityId === false` → always `{ ok: true }`.
     * - Known kind with `requiresEntityId === true` and no pattern → defensive
     *   `{ ok: false }` since the registry entry is internally inconsistent.
     * - Known kind with pattern → tests `slug` against the pattern.
     *
     * @param kind - Registered kind id.
     * @param slug - Slug to validate.
     * @returns Pass/fail result with a human-readable error on failure.
     */
    validateSlug(kind: string, slug: string): SlugValidationResult;
    /**
     * Map a kind to its `publishDir` (e.g. `'adr'` → `'docs/adr'`).
     *
     * Returns `undefined` for unknown kinds — callers decide whether to
     * fall back to a default (e.g. `'docs/note'`) or surface an error.
     */
    publishDirFor(kind: string): string | undefined;
}
/**
 * Error thrown by {@link DocKindRegistry.load} and
 * {@link DocKindRegistry.fromConfig} when the supplied config is invalid.
 *
 * Carries the offending source path / label so the CLI surface can render
 * a `details` payload pointing the user at the right file.
 */
export declare class DocKindConfigError extends Error {
    /** Source identifier — file path on disk, or `<inline-config>` for tests. */
    readonly source: string;
    constructor(message: string, source: string);
}
//# sourceMappingURL=docs-taxonomy.d.ts.map