/** * Project-declared roadmap item frontmatter fields * (item-extension-fields/AC-1 … item-extension-fields/AC-6, AC-16, AC-17). * * The portable `roadmap-item` skill hands an agent a frontmatter template and one * absolute rule — *"Do not add any other field."* A project that has added a field * of its own and a check that enforces it cannot be served by that: following the * skill produces an item its build rejects, and satisfying the build means * disobeying a framework-owned file the project may not edit. The two rules are * individually correct and jointly unsatisfiable, and neither side can fix it * alone. This module is how a project tells the framework about its field. * * Two boundaries are drawn deliberately, both inherited from `sync/config.ts` * because a second convention for reading one file is how the two come to * disagree: * * - A malformed **container** reads as *not configured*: unparseable YAML, * `roadmap` not a mapping, `item_fields` absent. One bad section must never * break an unrelated command. * - Anything wrong **inside** a well-formed `item_fields` list is a *named * refusal*. `required: "yes"` is a mistake somebody made on purpose and wants * told about; reading it as "you have not configured this" sends them looking * in the wrong place. * * The section is read from the **primary checkout**, the same tree the items come * from. Items and their schema are one fact; reading them from two trees would let * a feature branch change what a colleague's items are validated against. * * The framework validates **presence and shape only** (AC-17). There is no key * here that could express a rule about a field's contents, and that absence is the * feature: `requirements: [not-a-real-id]` is the project's own script's business, * and a framework that adjudicated it would have become a general schema engine — * the overreach the roadmap item named as the main way this goes wrong. * * @module */ /** * The stock item keys, which a declaration may not shadow. * * `status` is absent on purpose — it is not merely taken, it is forbidden, and it * gets its own refusal below. */ export declare const RESERVED_ITEM_KEYS: readonly string[]; /** * Legal field names. * * Conservative on purpose: a YAML key that needs quoting, or one that differs from * another only by case, turns a declaration into a debugging session in a file * nobody looks at twice. */ export declare const ITEM_FIELD_NAME_RE: RegExp; /** One declared field. */ export interface ItemFieldDecl { name: string; /** Default `true` — see the roadmap item: an optional key silently under-reports. */ required: boolean; /** * Written into new items, and the shape every item's value is checked against. * * There is no separate `type:` key. The default is already a worked example of * the shape, so a second one would be two representations of one fact. */ default: unknown; } export type ItemFieldsResult = { kind: 'ok'; fields: ItemFieldDecl[]; } | { kind: 'not-configured'; } | { kind: 'invalid'; error: string; }; /** Absolute path of a checkout's config file. */ export declare function itemFieldsConfigPath(root: string): string; /** * Validate the `item_fields` list. * * Exported separately from the reader so any writer — `aidlc init`, a future * wizard — can check its own answer against the reader's rule rather than * reimplementing it. `validateStatuses` is exported for the same reason, after a * setup command produced a config its own reader rejected. */ export declare function validateItemFields(raw: unknown): { ok: true; fields: ItemFieldDecl[]; } | { ok: false; error: string; }; /** * Read and validate `roadmap.item_fields`. * * @param primaryCheckoutRoot - The primary checkout's working tree. */ export declare function readItemFields(primaryCheckoutRoot: string): ItemFieldsResult; /** * The shape every *consumer* wants: the fields, plus a warning when the section is * there but wrong. * * An invalid declaration yields no fields and a message, never a throw. A consumer * that refused to act would leave the project with no emitted skill at all, which * is worse than the contradiction this feature removes; one that acted silently * would restore that contradiction. Warning and continuing is the honest middle, * and `aidlc doctor` reports the same condition independently. */ export declare function itemFieldsOrEmpty(primaryCheckoutRoot: string): { fields: ItemFieldDecl[]; warning: string | null; }; /** * Serialize a declared default to **exactly one line** of YAML. * * One line is load-bearing, not cosmetic: every consumer inserts the field as a * single frontmatter line, so a block-style collection would break the insertion * rather than merely look odd. Hence `collectionStyle: 'flow'`. * * Strings are quoted unconditionally, the rule `title` follows — a plain scalar * may not begin with a reserved indicator character, and the characters that break * it are exactly the ones that look harmless. */ export declare function renderFieldDefault(value: unknown): string; /** One `name: ` frontmatter line per declared field, in declaration order. */ export declare function renderFieldLines(fields: readonly ItemFieldDecl[]): string[]; /** * The shape kinds a declared field is checked against. * * Deliberately coarse. `scalar` lumps string, number and boolean together because * a framework that distinguished `1` from `"1"` would be validating contents, not * shape. */ export type FieldShape = 'null' | 'list' | 'mapping' | 'scalar'; export declare function shapeOf(value: unknown): FieldShape; /** One field whose value is the wrong shape. */ export interface ShapeMismatch { field: ItemFieldDecl; found: FieldShape; expected: FieldShape; } /** * Check one item's parsed frontmatter against the declared fields. * * Presence and shape, nothing else (AC-17). * * A field whose default is `null` declares no shape, so only presence is checked — * nothing was declared to compare against, and inventing a constraint would be the * framework deciding what the project meant. * * A present-but-`null` value (`requirements:` with nothing after it) is reported as * a *mismatch*, not as missing: the key is there, so presence holds, and the value * is not the declared shape. It is deliberately not repairable — see the migration. */ export declare function checkItemFrontmatter(data: Record, fields: readonly ItemFieldDecl[]): { missing: ItemFieldDecl[]; mismatched: ShapeMismatch[]; }; //# sourceMappingURL=item-fields.d.ts.map