/** * Change-management types: amendments parsed from requirements.md, the * read-only impact report, and the reopen plan. * * Design: design.md (change-management) §4 */ import type { TransitionRecord } from '../core/types.js'; /** One amendment section parsed from requirements.md (AC-51, AC-78). */ export interface Amendment { /** n in `Amendment n`; ≥1, no leading zeros. */ n: number; /** YYYY-MM-DD exactly as written. */ date: string; /** The optional `, ` tail from the heading. */ context?: string; /** 1-based heading line. */ line: number; /** Heading depth, 2 or 3 — bounds the section (AC-51). */ level: number; retires: number[]; issues: number[]; /** * Phase names AS WRITTEN. Never trusted until validated against the * template's applicable phase list and screened for traversal characters * (AC-82) — this field reaches a filename, so it is the untrusted input. */ reopens: string[]; /** * The author wrote `Reopens: none` — an explicit declaration that no completed * phase cites the retired criteria (first-run-gaps/AC-1). * * Distinct from `reopens: []`, which means the field was absent or empty. That * distinction is the whole point of the flag: an absent field is an author who * has not answered the question and is still refused (change-management/AC-60, * first-run-gaps/AC-3), while `none` is an answer. Before it existed, the only * accepted answer was to name a complete phase that needed nothing, which * reopened it and every phase after it and wrote rework into the transitions * log that never happened. */ reopensNone: boolean; /** * Whether a `Retires:` field was present at all, as distinct from present * and empty. A truncated field and a genuinely empty one must not render * identically (AC-88): the first is a parse failure, the second is a fact. */ retiresPresent: boolean; reason?: string; } /** Parse result for one requirements.md (AC-5, AC-7, AC-8, AC-53). */ export interface ParsedAmendments { /** Ordered by n; first occurrence wins on duplicates (AC-5). */ amendments: Amendment[]; /** Ordered by source line (AC-48). */ warnings: string[]; } /** * One impacted citation of a retired criterion. * * Identity is the triple `path:line:acId` (AC-71). `task` beats `artifact` * when the same triple is produced by both walks, because a task record * carries strictly more information — `tasks.md` is itself a declared design * artifact, so every task line is seen twice. */ export interface ImpactRef { /** Posix-separated, project-root-relative. */ path: string; /** 1-based. */ line: number; acId: number; source: 'test' | 'task' | 'artifact'; /** Present iff source === 'task'. */ taskId?: number; taskState?: 'open' | 'done' | 'deferred'; } /** * Four outcomes, not two (AC-88). `no-retirements` means the amendment * declared an empty `Retires:`; `retires-absent` means it declared none at * all, which after AC-78 should be rare and is worth saying out loud. */ export type ImpactOutcome = 'impacts' | 'none' | 'no-retirements' | 'retires-absent'; /** Full impact report — advisory, never consumed by the write path (AC-58). */ export interface ImpactReport { outcome: ImpactOutcome; retiredIds: number[]; /** Deduped on `path:line:acId`, ordered path → line → acId (AC-71, AC-48). */ refs: ImpactRef[]; /** * The phases whose declared artifacts carry impacts. A SUGGESTION the * author may paste into `Reopens:` — `aidlc amend` never reads it (AC-58). */ suggestedReopens: string[]; /** * Citations per owning phase, template order, only phases with at least one. * What `assessCoverage` reads (amend-cannot-reopen-current-phase/AC-3). */ phaseCitations: PhaseCitations[]; warnings: string[]; } /** A phase and how many retired-criterion citations its files carry. */ export interface PhaseCitations { phase: string; count: number; } /** * Which completed phases still cite a retired criterion, and whether a reopen * reaches them (amend-cannot-reopen-current-phase/AC-3, AC-10). */ export interface Coverage { currentPhase: string; /** Complete, strictly before the current phase, and cited (AC-3, AC-6). */ citing: PhaseCitations[]; /** The citing phases outside the reopen range that was checked. */ uncovered: PhaseCitations[]; /** The smallest `Reopens:` the write path accepts: `none` or the earliest citing phase. */ sufficientReopens: string; } /** Why `planReopen` refused on grounds other than a bad phase name. */ export type BlockedCode = 'current-phase-outside-template' | 'phase-state-missing'; /** * The five outcomes of planning a reopen. Every refusal is its own variant * with its own payload, so no caller has to interpret a message string, and * every branch is reachable without a filesystem. */ export type ReopenPlan = /** * Nothing to rewrite — `Reopens: none`, only the current phase named * (amend-cannot-reopen-current-phase/AC-7), or every phase in range skipped. * Still records the amendment (AC-87). */ { kind: 'noop'; reason: string; } /** A phase name is not a template member, or carries `/`, `\` or `..` (AC-82). */ | { kind: 'invalid-phase'; names: string[]; validPhases: string[]; } /** A named phase is after the current one, and none before it (AC-83). */ | { kind: 'phase-ahead'; names: string[]; currentPhase: string; } /** State the plan cannot proceed from, rather than repair (AC-92). */ | { kind: 'blocked'; code: BlockedCode; message: string; } | { kind: 'reopen'; /** * The contiguous range actually rewritten: template order, earliest * first, `skipped` phases removed (AC-85). This — not the names the * author wrote — is what `detail` records (AC-84). */ phases: string[]; /** The phase current before the reopen. */ from: string; /** Earliest rewritten phase; strictly earlier than `from` (AC-83). */ to: string; newCurrentPhase: string; record: TransitionRecord; }; /** * Closed set of `--json` error codes (AC-77). Closed on purpose: an error * shape invented per branch at implementation time is what makes `--json` * unparseable by anything downstream. */ export type AmendErrorCode = 'no-requirements-artifact' | 'no-requirements-file' | 'no-amendment-section' | 'amendment-not-found' | 'unapplied-predecessor' | 'no-reopens-field' | 'invalid-phase-name' | 'phase-ahead-of-current' | 'phase-state-missing' | 'current-phase-outside-template' | 'instance-complete' | 'confirm-required' | 'no-claim' | 'uncovered-citation' | 'human-required'; /** The one envelope every exit path emits under `--json` (AC-77). */ export interface AmendEnvelope { ok: boolean; exit_code: number; error?: { code: AmendErrorCode; message: string; }; amendment?: Amendment; impact?: ImpactReport; plan?: ReopenPlan; coverage?: Coverage; } //# sourceMappingURL=types.d.ts.map