/** * roadmap-item-fields migration (confirm tier): backfill a project-declared item * field that an item is missing, and report one whose value is the wrong shape. * * Requirements: item-extension-fields/AC-15, AC-16, AC-18, AC-19, AC-20 * * Declaring a field is cheap; retrofitting it across a roadmap that already holds * fifty items is not. Without a backfill, `roadmap.item_fields` would report fifty * problems on the day it was added and offer no way to act on any of them — the * shape of gate this project has learned to distrust. * * The line between what this repairs and what it only reports is the same line the * feature draws everywhere: **presence, never contents.** * * - A *missing* required field is repaired by writing the value the project itself * declared as the default. That is presence repair with the project's own answer, * not a semantic judgment, so it stays inside the boundary AC-17 sets. * - A *wrong-shaped* value is reported and never rewritten. Wrapping a scalar in a * list to make it fit would be the confident-wrong-fix `roadmap-item-titles` * already refuses, and only the person who wrote the value knows what they meant. * * Wrong shapes and an invalid declaration are both reported as NOT APPLICABLE * rather than pending, following `roadmap-item-titles` exactly: `aidlc doctor` * exits 1 on pending confirm work, so calling a condition `apply` will never fix * "pending" fails doctor forever on a repo holding one such item, which trains * people to ignore doctor output. `not-applicable` still prints the detail, which * is the entire point. * * Items whose frontmatter will not parse are skipped in silence. They are * `roadmap-item-titles`' condition, that migration is registered ahead of this one, * and reporting the same file from two migrations would double every line without * adding a fact. * * Confirm tier, because this edits the user's own content — the reason * `roadmap-layout` and `roadmap-item-titles` are confirm tier too. `check` and * `apply` both derive everything from `planItemFields` and nothing else computes * pending-ness, the rule `../types.ts` states, so a dry run and a real run cannot * disagree. */ import type { DoctorContext, Migration } from '../types.js'; import { type ItemFieldDecl, type ShapeMismatch } from '../../roadmap/item-fields.js'; /** One item with fields to add, and the rewritten contents that add them. */ export interface FieldBackfill { /** `/` — the form used in doctor output. */ label: string; file: string; fields: ItemFieldDecl[]; contents: string; } /** One item carrying a declared field of the wrong shape. */ export interface FieldShapeReport { label: string; mismatches: ShapeMismatch[]; } export interface ItemFieldsPlan { /** Null when the project declares nothing; a message when its declaration is wrong. */ notApplicable: string | null; backfills: FieldBackfill[]; shapes: FieldShapeReport[]; } /** * Insert `name: ` lines at the **end** of an item's frontmatter block. * * End-of-block rather than "after `history`", deliberately. `history` is a block * list whose extent has to be walked, and `writeHistoryEntry` appends to it — a key * inserted between the `history:` line and its last entry would be swallowed into * the list on the next move. End-of-block is unambiguous, needs no walk, and is * where `writeHistoryEntry` itself puts a `history` key when none exists. * * @returns The rewritten contents, or null when there is no frontmatter to edit. */ export declare function insertFields(raw: string, fields: readonly ItemFieldDecl[]): string | null; /** * Everything the migration would do, computed without writing. * * The single source of pending-ness. Items are walked in status order and then * filename order, so the plan never depends on directory read order. */ export declare function planItemFields(ctx: DoctorContext): ItemFieldsPlan; export declare const roadmapItemFields: Migration; //# sourceMappingURL=roadmap-item-fields.d.ts.map