@nikovirtala/adr 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-C3IW5WrA.js","names":["compiled","decoder"],"sources":["../src/config.ts","../src/log.ts","../src/verify.ts","../src/views.ts","../src/templates/builtin.ts","../src/write.ts"],"sourcesContent":["import { ConfigError, type Severity, type ToolConfig } from \"@nikovirtala/ledger\";\n\n/** adr's settings from `adr.toml` (design §5.3); every key is optional. */\nexport interface AdrConfig {\n /** `[log] default_template`: the template `adr new` uses without `--template`. */\n readonly defaultTemplate: string;\n /** `[log] main_branch`: the ref numbers come from; `null` resolves it automatically. */\n readonly mainBranch: string | null;\n /** `[log] index`: validated now, used in phase 2. */\n readonly index: \"committed\" | \"none\";\n /** `[policy] accept_requires_human`. */\n readonly acceptRequiresHuman: boolean;\n /** `[policy] auto_commit`: commit writes without `--commit`. */\n readonly autoCommit: boolean;\n /** `[policy] mcp_can_decide`: validated now, used in phase 3. */\n readonly mcpCanDecide: boolean;\n /** `[verify] fail_on`. */\n readonly failOn: Severity;\n}\n\nexport const DEFAULT_ADR_CONFIG: AdrConfig = Object.freeze({\n defaultTemplate: \"nygard\",\n mainBranch: null,\n index: \"none\",\n acceptRequiresHuman: true,\n autoCommit: false,\n mcpCanDecide: false,\n failOn: \"error\",\n});\n\nconst TEMPLATE = /^[a-z][a-z0-9-]*$/;\n\nfunction isTable(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v) && !(v instanceof Date);\n}\n\n/**\n * Validates `adr.toml` (ledger's parsed `ToolConfig`; `null` when there is none). A wrong type or\n * value throws `ConfigError` naming the file and key. Unknown keys are ignored, so newer files\n * still load. `[log] root` is ledger's (`openToolLog` already checked it).\n */\nexport function parseAdrConfig(config: ToolConfig | null, file: string | null): AdrConfig {\n if (config === null) return DEFAULT_ADR_CONFIG;\n const where = file ?? config.file ?? \"adr.toml\";\n const fail = (message: string) => new ConfigError(`${where}: ${message}`, { file: where });\n const table = (name: string): Record<string, unknown> => {\n const t = config.raw[name];\n if (t === undefined) return {};\n if (!isTable(t)) throw fail(`${name} must be a table`);\n return t;\n };\n const log = table(\"log\");\n const policy = table(\"policy\");\n const verify = table(\"verify\");\n const bool = (t: Record<string, unknown>, section: string, key: string, fallback: boolean) => {\n const v = t[key];\n if (v === undefined) return fallback;\n if (typeof v !== \"boolean\") throw fail(`${section}.${key} must be true or false`);\n return v;\n };\n const oneOf = <T extends string>(\n t: Record<string, unknown>,\n section: string,\n key: string,\n values: readonly T[],\n fallback: T,\n ): T => {\n const v = t[key];\n if (v === undefined) return fallback;\n if (typeof v !== \"string\" || !(values as readonly string[]).includes(v)) {\n throw fail(`${section}.${key} must be ${values.map((x) => JSON.stringify(x)).join(\" or \")}`);\n }\n return v as T;\n };\n\n const template = log.default_template;\n if (\n template !== undefined &&\n (typeof template !== \"string\" || template.length > 64 || !TEMPLATE.test(template))\n ) {\n throw fail(`log.default_template must be a template name matching ${TEMPLATE.source}`);\n }\n const main = log.main_branch;\n if (\n main !== undefined &&\n (typeof main !== \"string\" || main.trim() === \"\" || main.startsWith(\"-\") || main.includes(\"\\0\"))\n ) {\n throw fail(\"log.main_branch must be a ref name that doesn't start with -\");\n }\n return {\n defaultTemplate: typeof template === \"string\" ? template : DEFAULT_ADR_CONFIG.defaultTemplate,\n mainBranch: typeof main === \"string\" ? main : null,\n index: oneOf(log, \"log\", \"index\", [\"committed\", \"none\"] as const, \"none\"),\n acceptRequiresHuman: bool(policy, \"policy\", \"accept_requires_human\", true),\n autoCommit: bool(policy, \"policy\", \"auto_commit\", false),\n mcpCanDecide: bool(policy, \"policy\", \"mcp_can_decide\", false),\n failOn: oneOf(verify, \"verify\", \"fail_on\", [\"error\", \"warning\"] as const, \"error\"),\n };\n}\n","import {\n type CheckContext,\n compileKind,\n type Finding,\n type FoldedLogOf,\n foldLog,\n type GitOptions,\n invariantsCheck,\n type LogLayout,\n loadFindings,\n loadLog,\n type Numbering,\n numberLog,\n openToolLog,\n type Projection,\n projectLog,\n relateCheck,\n resolveSubjectInput,\n sortFindings,\n type ToolLog,\n type TreeReader,\n transitions,\n UsageError,\n} from \"@nikovirtala/ledger\";\nimport { type AdrConfig, parseAdrConfig } from \"./config.js\";\nimport { adrKind, type DecisionView } from \"./kind.js\";\n\n/** A decision log opened for the CLI or MCP: ledger's tool log plus adr's config. */\nexport interface DecisionLog extends ToolLog {\n readonly adr: AdrConfig;\n}\n\n/**\n * Opens the decision log (design D3): `--root`, else `adr.toml`'s `[log] root`, else `docs/adr`;\n * read from the `ref` tree, the index or the work tree.\n */\nexport async function openDecisionLog(o: {\n readonly cwd: string;\n readonly root?: string | null;\n readonly ref?: string | null;\n readonly reader?: \"worktree\" | \"index\";\n readonly gitOptions?: GitOptions;\n}): Promise<DecisionLog> {\n const log = await openToolLog({ ...o, tool: \"adr\", kind: adrKind });\n return { ...log, adr: parseAdrConfig(log.config, log.configPath) };\n}\n\n/** One read of a decision log: everything list, show and the write plans need. */\nexport interface DecisionsRead {\n /** The tree that was read, its layout and config; no `Git`, so plans can run on a MemoryTree. */\n readonly tree: TreeReader;\n readonly layout: LogLayout;\n readonly adr: AdrConfig;\n readonly root: string;\n readonly ref: string | null;\n readonly commit: string | null;\n readonly folded: FoldedLogOf<typeof adrKind>;\n readonly projection: Projection<DecisionView>;\n readonly numbering: Numbering;\n /** Load, transition, invariant and relate findings; no diff-based checks. */\n readonly findings: readonly Finding[];\n /** How the log was located (`ToolLog.notes`); `[]` for a MemoryTree read. */\n readonly notes: readonly string[];\n}\n\n/** `numberLog` on the repository, then `readDecisionsFrom(log.tree, …)`. */\nexport async function readDecisions(log: DecisionLog): Promise<DecisionsRead> {\n const numbering = await numberLog(log.git, {\n kind: adrKind,\n layout: log.layout,\n mainRef: log.adr.mainBranch,\n });\n return readDecisionsFrom(log.tree, {\n layout: log.layout,\n adr: log.adr,\n numbering,\n ref: log.ref,\n commit: log.commit,\n notes: log.notes,\n });\n}\n\nconst compiled = compileKind(adrKind);\n\n/** The git-free core of `readDecisions`; tests pass a MemoryTree and a hand-made `Numbering`. */\nexport async function readDecisionsFrom(\n tree: TreeReader,\n o: {\n readonly layout: LogLayout;\n readonly adr: AdrConfig;\n readonly numbering: Numbering;\n readonly ref?: string | null;\n readonly commit?: string | null;\n readonly notes?: readonly string[];\n },\n): Promise<DecisionsRead> {\n const { layout, adr, numbering } = o;\n const snapshot = await loadLog(tree, { kind: compiled, layout });\n const folded = foldLog(adrKind, snapshot);\n const ctx: CheckContext = {\n kind: compiled,\n layout,\n base: null,\n head: snapshot,\n changes: [],\n scope: \"all\",\n inScope: new Set(snapshot.subjects.keys()),\n folded: { head: folded, base: null },\n };\n const options = { acceptRequiresHuman: adr.acceptRequiresHuman };\n const findings: Finding[] = [];\n for (const check of [loadFindings, transitions, invariantsCheck(options), relateCheck(options)]) {\n findings.push(...(await check.run(ctx)));\n }\n return {\n tree,\n layout,\n adr,\n root: layout.root,\n ref: o.ref ?? null,\n commit: o.commit ?? null,\n folded,\n projection: projectLog(adrKind, folded, { numbering }),\n numbering,\n findings: sortFindings(findings.map((f) => ({ ...f, kind: adrKind.name }))),\n notes: o.notes ?? [],\n };\n}\n\n/** Why numbers are unavailable, in words: `shallow clone` or `no main branch`. */\nexport function unavailableReason(n: Numbering): string {\n return n.reason === \"shallow\" ? \"shallow clone\" : \"no main branch\";\n}\n\n/**\n * The id a decision argument names: an id, or a number in any form `parseDecisionNumber` takes.\n * Throws `UsageError` (exit 2) naming the reason when it names nothing.\n */\nexport function resolveDecision(read: DecisionsRead, input: string): string {\n const r = resolveSubjectInput(input, {\n subjects: new Set(read.folded.subjects.keys()),\n kind: adrKind,\n numbering: read.numbering,\n });\n if (r.ok) return r.id;\n const shown = JSON.stringify(input.trim());\n switch (r.reason) {\n case \"malformed\":\n throw new UsageError(`invalid decision ${JSON.stringify(input)}`);\n case \"qualified\":\n throw new UsageError(\n `decision ${shown} is in another log; cross-log references arrive in phase 2`,\n );\n case \"numbers-unavailable\":\n throw new UsageError(\n `decision numbers are unavailable (${unavailableReason(read.numbering)}); use the decision's id instead of ${shown}`,\n );\n case \"not-found\":\n throw new UsageError(`unknown decision ${input.trim()}`);\n }\n}\n","import {\n type Check,\n type Finding,\n foldChecks,\n gitTemplates,\n templateHistoryRef,\n type VerifyMode,\n verifyLog,\n} from \"@nikovirtala/ledger\";\nimport { adrKind } from \"./kind.js\";\nimport type { DecisionLog } from \"./log.js\";\n\n/**\n * Every phase-1 check for the log: ledger's mechanical and fold checks with adr's actor policy,\n * and template lint against the templates in the head tree and, for older versions, the history\n * of `historyRef`.\n */\nexport function adrChecks(log: DecisionLog, historyRef: string | null): readonly Check[] {\n return foldChecks(adrKind, {\n options: { acceptRequiresHuman: log.adr.acceptRequiresHuman },\n templates: gitTemplates(log.git, { historyRef }),\n });\n}\n\n/** Verifies the decision log in `mode` (staged, range or full) with `adrChecks`. */\nexport async function verifyDecisions(log: DecisionLog, mode: VerifyMode): Promise<Finding[]> {\n return verifyLog({\n git: log.git,\n kind: adrKind,\n layout: log.layout,\n mode,\n checks: adrChecks(log, await templateHistoryRef(log.git, mode)),\n });\n}\n","import {\n compareEvents,\n type EventEnvelope,\n type Finding,\n type StateHeader,\n UsageError,\n} from \"@nikovirtala/ledger\";\nimport type { DecisionStatus, DecisionView } from \"./kind.js\";\nimport type { DecisionsRead } from \"./log.js\";\n\n/** The `numbering` key of the read documents. */\nexport interface NumberingJson {\n readonly available: boolean;\n readonly reason: \"shallow\" | \"no-main-ref\" | null;\n readonly ref: string | null;\n}\n\n/** `adr list --json` (design §5.5). */\nexport interface DecisionListJson {\n readonly format: \"adr-list/v1\";\n readonly root: string;\n readonly ref: string | null;\n readonly commit: string | null;\n readonly numbering: NumberingJson;\n readonly decisions: readonly DecisionView[];\n /** Newer envelope or schema versions; upgrade adr. */\n readonly unreadable: readonly string[];\n /** First event not `proposed`, or a body with no events; run adr verify. */\n readonly unfoldable: readonly string[];\n readonly findings: readonly Finding[];\n readonly notes: readonly string[];\n}\n\n/** `adr show <decision> --json` (design §5.5). */\nexport interface DecisionShowJson {\n readonly format: \"adr-show/v1\";\n readonly root: string;\n readonly ref: string | null;\n readonly commit: string | null;\n readonly numbering: NumberingJson;\n readonly header: StateHeader;\n readonly decision: DecisionView;\n readonly body: string | null;\n /** Every valid event in fold order with `history`, else `null`. */\n readonly events: readonly EventEnvelope[] | null;\n readonly findings: readonly Finding[];\n readonly notes: readonly string[];\n}\n\nconst numberingJson = (read: DecisionsRead): NumberingJson => ({\n available: read.numbering.available,\n reason: read.numbering.reason,\n ref: read.numbering.ref,\n});\n\n/** Numbered decisions by number, then unnumbered ones by `proposed_at`, then id. */\nfunction compareViews(a: DecisionView, b: DecisionView): number {\n if (a.number !== null || b.number !== null) {\n if (a.number === null) return 1;\n if (b.number === null) return -1;\n return a.number - b.number;\n }\n if (a.proposed_at !== b.proposed_at) return a.proposed_at < b.proposed_at ? -1 : 1;\n return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;\n}\n\n/**\n * The `adr-list/v1` document: decisions in list order, filtered by `status` and truncated to\n * `limit` after ordering. `findings` are those of the listed decisions and of the log as a whole.\n */\nexport function listDecisions(\n read: DecisionsRead,\n o: { readonly status?: readonly DecisionStatus[]; readonly limit?: number } = {},\n): DecisionListJson {\n const statuses = o.status === undefined || o.status.length === 0 ? null : new Set(o.status);\n const decisions = [...read.projection.views.values()]\n .filter((v) => statuses === null || statuses.has(v.status))\n .sort(compareViews)\n .slice(0, o.limit ?? Number.POSITIVE_INFINITY);\n const listed = new Set(decisions.map((v) => v.id));\n return {\n format: \"adr-list/v1\",\n root: read.root,\n ref: read.ref,\n commit: read.commit,\n numbering: numberingJson(read),\n decisions,\n unreadable: read.projection.unreadable,\n unfoldable: read.projection.unfoldable,\n findings: read.findings.filter((f) => f.subject === null || listed.has(f.subject)),\n notes: read.notes,\n };\n}\n\nconst decoder = new TextDecoder();\n\n/**\n * The `adr-show/v1` document of the decision `id` (resolve it with `resolveDecision` first).\n * Throws `UsageError` for an unknown, unreadable or unfoldable decision.\n */\nexport async function showDecision(\n read: DecisionsRead,\n id: string,\n o: { readonly history?: boolean } = {},\n): Promise<DecisionShowJson> {\n const view = read.projection.views.get(id);\n if (view === undefined) {\n if (read.projection.unreadable.includes(id)) {\n throw new UsageError(`decision ${id} uses a newer format; upgrade adr`);\n }\n if (read.projection.unfoldable.includes(id)) {\n throw new UsageError(`decision ${id} can't be read; run adr verify`);\n }\n throw new UsageError(`unknown decision ${id}`);\n }\n const loaded = read.folded.subjects.get(id)?.loaded;\n const body = loaded?.body ?? null;\n const events =\n o.history === true\n ? (loaded?.events ?? [])\n .flatMap((e) => (e.event === null ? [] : [{ path: e.path, event: e.event }]))\n .sort((a, b) => compareEvents({ ...a.event, path: a.path }, { ...b.event, path: b.path }))\n .map((e) => e.event)\n : null;\n return {\n format: \"adr-show/v1\",\n root: read.root,\n ref: read.ref,\n commit: read.commit,\n numbering: numberingJson(read),\n header: stateHeader(view, read),\n decision: view,\n body: body === null ? null : decoder.decode(body.bytes),\n events,\n findings: read.findings.filter((f) => f.subject === id),\n notes: read.notes,\n };\n}\n\nconst day = (at: string | null) => (at ?? \"\").slice(0, 10);\n\n/** The reason on the applied event that produced the decision's current status, if any. */\nfunction statusReason(read: DecisionsRead, id: string): string | null {\n const applied = read.folded.subjects.get(id)?.applied ?? [];\n const last = applied.findLast((a) => a.from !== a.to);\n const reason = last?.event.reason;\n return typeof reason === \"string\" && reason.trim() !== \"\" ? reason.trim() : null;\n}\n\n/**\n * The state header (01:258–259): `<display> (<id>) · <status>`, and for a decision that isn't in\n * force a warning saying what to read instead. `refer` names where to read another decision. CLI\n * default: `display(id)`. Phase 3 MCP passes `id => \"adr://decision/\" + display(id)`, e.g.\n * `adr://decision/ADR-0012`, or the id when unnumbered.\n */\nexport function stateHeader(\n view: DecisionView,\n read: DecisionsRead,\n o: { readonly refer?: (id: string) => string } = {},\n): StateHeader {\n const display = (id: string) => read.projection.views.get(id)?.display ?? id;\n const refer = o.refer ?? display;\n const line =\n view.number === null\n ? `${view.id} · ${view.status}`\n : `${view.display} (${view.id}) · ${view.status}`;\n const parts: string[] = [];\n const reason = statusReason(read, view.id);\n const when = day(view.status_at);\n switch (view.status) {\n case \"superseded\": {\n const target = view.effective ?? view.superseded_by ?? view.id;\n const accepted = read.projection.views.get(target)?.decided_at ?? null;\n const date = accepted === null ? \"\" : ` (accepted ${day(accepted)})`;\n parts.push(\n `SUPERSEDED by ${display(target)}${date}. Do not apply this decision; read ${refer(target)} instead.`,\n );\n if (view.chain.length > 2) parts.push(`Chain: ${view.chain.map(display).join(\" → \")}.`);\n break;\n }\n case \"deprecated\":\n parts.push(`DEPRECATED on ${when}: ${reason ?? \"no reason given\"}. No decision replaces it.`);\n break;\n case \"rejected\":\n parts.push(\n `REJECTED on ${when}: ${reason ?? \"no reason given\"}. This decision was never in force.`,\n );\n break;\n case \"withdrawn\":\n parts.push(\n `WITHDRAWN on ${when}${reason === null ? \"\" : `: ${reason}`}. This decision was never in force.`,\n );\n break;\n default:\n break;\n }\n if (view.body_intact === false) {\n parts.push(\"WARNING: the body changed after acceptance; run adr verify.\");\n }\n return { line, warning: parts.length === 0 ? null : parts.join(\" \") };\n}\n","/**\n * The built-in decision templates, version 1 (design §5.7). `adr new` copies the one it uses into\n * `<root>/templates/<name>.md` on first use, so the team owns it and its versions live in git\n * (D4). Every section is required unless marked optional, and each has a required Scope section\n * (01:311).\n */\n\nconst NYGARD = `---\ntemplate: nygard\nversion: 1\nsections:\n - id: context\n heading: Context\n required: true\n guidance: What is the issue that motivates this decision? Describe the forces at play.\n - id: decision\n heading: Decision\n required: true\n guidance: What is the change that we're proposing or doing? Write it in the active voice.\n - id: scope\n heading: Scope\n required: true\n guidance: What does this decision govern? Name the systems, code paths or teams it applies to.\n - id: consequences\n heading: Consequences\n required: true\n guidance: What becomes easier or harder because of this change? Include the risks.\n---\n# {{title}}\n\n## Context\n{{context}}\n\n## Decision\n{{decision}}\n\n## Scope\n{{scope}}\n\n## Consequences\n{{consequences}}\n`;\n\nconst MADR = `---\ntemplate: madr\nversion: 1\nsections:\n - id: context\n heading: Context and Problem Statement\n required: true\n guidance: Describe the context and the problem in two or three sentences, or as a question.\n - id: drivers\n heading: Decision Drivers\n required: false\n guidance: List the forces and concerns that shape the decision.\n - id: options\n heading: Considered Options\n required: true\n guidance: List the options that were considered, one per line.\n - id: decision\n heading: Decision Outcome\n required: true\n guidance: Name the chosen option and say why it was chosen.\n - id: scope\n heading: Scope\n required: true\n guidance: What does this decision govern? Name the systems, code paths or teams it applies to.\n - id: consequences\n heading: Consequences\n required: true\n guidance: Describe the good and the bad consequences of the chosen option.\n---\n# {{title}}\n\n## Context and Problem Statement\n{{context}}\n\n## Decision Drivers\n{{drivers}}\n\n## Considered Options\n{{options}}\n\n## Decision Outcome\n{{decision}}\n\n## Scope\n{{scope}}\n\n## Consequences\n{{consequences}}\n`;\n\nconst Y_STATEMENT = `---\ntemplate: y-statement\nversion: 1\nsections:\n - id: statement\n heading: Statement\n required: true\n guidance: In the context of <use case>, facing <concern>, we decided for <option>, to achieve <quality>, accepting <downside>.\n - id: scope\n heading: Scope\n required: true\n guidance: What does this decision govern? Name the systems, code paths or teams it applies to.\n---\n# {{title}}\n\n## Statement\n{{statement}}\n\n## Scope\n{{scope}}\n`;\n\n/** The built-in templates by name: the file text `adr new` materializes. */\nexport const BUILTIN_TEMPLATES: Readonly<Record<string, string>> = Object.freeze({\n nygard: NYGARD,\n madr: MADR,\n \"y-statement\": Y_STATEMENT,\n});\n","import { readFile, rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n type Actor,\n bodyFileName,\n bodySha256,\n classifyPath,\n compileKind,\n ENVELOPE_VERSION,\n type EventEnvelope,\n EventExistsError,\n eventDir,\n eventPath,\n FileExistsError,\n type Finding,\n finding,\n historyTemplates,\n InvalidArgumentError,\n isSubjectId,\n lintDocument,\n lintTemplate,\n newSubjectId,\n nextEventIdentity,\n overlayTree,\n parseEventFileName,\n parseTemplate,\n renderTemplate,\n serializeEvent,\n slugify,\n type Template,\n type TemplateSource,\n type Trailer,\n templateHistoryRef,\n UsageError,\n writeEvents,\n writeNewFile,\n} from \"@nikovirtala/ledger\";\nimport { adrKind, type DecisionView } from \"./kind.js\";\nimport {\n type DecisionLog,\n type DecisionsRead,\n readDecisions,\n readDecisionsFrom,\n resolveDecision,\n} from \"./log.js\";\nimport { BUILTIN_TEMPLATES } from \"./templates/builtin.js\";\n\n/** `adr new|accept|supersede --json` (design §5.5). */\nexport interface WriteResultJson {\n readonly format: \"adr-write/v1\";\n readonly command: \"new\" | \"accept\" | \"supersede\";\n readonly ok: boolean;\n /**\n * The decision after the write; before it when `ok` is false (`null` for a refused `new`).\n * After a commit it is read again from the log, so an acceptance committed on the main ref\n * carries its number; otherwise `number` is `null` until the acceptance lands on main.\n */\n readonly decision: DecisionView | null;\n /** Each decision superseded by this write, after it (read again after a commit, like `decision`). */\n readonly affected: readonly DecisionView[];\n /** Repo-relative paths this command wrote, in write order. */\n readonly written: readonly string[];\n readonly commit: string | null;\n /** Refusal findings when `ok` is false; the draft's template lint for `new` (informational). */\n readonly findings: readonly Finding[];\n /** How the log was located (`ToolLog.notes`). */\n readonly notes: readonly string[];\n}\n\nexport interface ProposeInput {\n readonly title: string;\n /** Default `[log] default_template`. */\n readonly template?: string;\n /** Section id → markdown. */\n readonly sections?: Readonly<Record<string, string>>;\n /** Decisions this one is meant to replace, as ids or numbers. */\n readonly supersedes?: readonly string[];\n readonly actor: Actor;\n}\n\n/** What a plan needs besides the read: a clock, randomness and templates. */\nexport interface PlanContext {\n /** Clock for `nextEventIdentity`. */\n readonly now: () => number;\n /** ULID and subject-id randomness. */\n readonly random?: (buf: Uint8Array) => void;\n /** Drafts' recorded template versions. */\n readonly templates: TemplateSource;\n /** Built-in template texts by name (§5.7), for `new`. */\n readonly builtins: Readonly<Record<string, string>>;\n}\n\n/** Everything one write command does, computed without touching git or the disk. */\nexport interface WritePlan {\n readonly command: \"new\" | \"accept\" | \"supersede\" | \"event\";\n readonly subject: string;\n /** New files, repo-relative path → bytes, in write order: body, materialized template, events. */\n readonly files: Readonly<Record<string, Uint8Array>>;\n readonly events: readonly EventEnvelope[];\n /** Paths to stage: every new file, plus the existing body for accept. */\n readonly stage: readonly string[];\n /** Subject ids involved (D6): the subject, every superseded target, and `by` for supersede. Sorted. */\n readonly involved: readonly string[];\n /** Per involved subject: its body, its events dir and its recorded template. Sorted, deduplicated. */\n readonly commitScope: readonly string[];\n /** The events directories in `commitScope`, sorted; the rest of `commitScope` are file paths. */\n readonly eventDirs: readonly string[];\n /** For new: the body path, the rendered bytes and the template, for the editor step. */\n readonly draft: {\n readonly path: string;\n readonly rendered: Uint8Array;\n readonly template: Template;\n } | null;\n /** The D6 commit message. */\n readonly message: string;\n /** One `ADR`/`ADR-Event` pair per plan event, in write order. */\n readonly trailers: readonly Trailer[];\n /** Views after the write, computed on `overlayTree(read.tree, files)`. */\n readonly decision: DecisionView;\n readonly affected: readonly DecisionView[];\n /** Informational (new: the draft's template lint). */\n readonly findings: readonly Finding[];\n}\n\nexport type PlanResult =\n | { readonly ok: true; readonly plan: WritePlan }\n | {\n readonly ok: false;\n readonly decision: DecisionView | null;\n readonly findings: readonly Finding[];\n };\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\nconst compiled = compileKind(adrKind);\nconst TEMPLATE_NAME = /^[a-z][a-z0-9-]*$/;\nconst MAX_TEXT_BYTES = 64 * 1024;\nconst SUBJECT_ATTEMPTS = 5;\nconst QUALIFIED_SUPERSESSION = \"cross-log supersession arrives in phase 2\";\n\nconst sorted = (xs: Iterable<string>): string[] => [...new Set(xs)].sort();\nconst templatePath = (read: DecisionsRead, name: string) => `${read.root}/templates/${name}.md`;\n\n/** A text argument within the 64 KiB cap and without NUL characters, else `UsageError`. */\nfunction checkText(what: string, text: string): void {\n if (text.includes(\"\\0\")) throw new UsageError(`${what} must not contain NUL characters`);\n const size = encoder.encode(text).byteLength;\n if (size > MAX_TEXT_BYTES) {\n throw new UsageError(`${what} is ${size} bytes; the limit is ${MAX_TEXT_BYTES} (64 KiB)`);\n }\n}\n\nfunction checkReason(reason: string | null | undefined): string | null {\n if (reason === undefined || reason === null) return null;\n const r = reason.trim();\n if (r === \"\") throw new UsageError(\"--reason must not be empty\");\n checkText(\"--reason\", r);\n return r;\n}\n\n/** The view of a folded decision, else `UsageError` naming why it can't be used. */\nfunction viewOf(read: DecisionsRead, id: string): DecisionView {\n const view = read.projection.views.get(id);\n if (view !== undefined) return view;\n if (read.projection.unreadable.includes(id)) {\n throw new UsageError(`decision ${id} uses a newer format; upgrade adr`);\n }\n throw new UsageError(`decision ${id} can't be read; run adr verify`);\n}\n\n/** A refusal finding about decision `subject`, on its body (or events directory). */\nfunction refusal(read: DecisionsRead, rule: string, message: string, subject: string): Finding {\n const loaded = read.folded.subjects.get(subject)?.loaded;\n return finding({\n severity: \"error\",\n rule,\n message,\n file: loaded?.bodyPaths[0] ?? eventDir(read.layout, subject),\n subject,\n kind: adrKind.name,\n });\n}\n\n/** `\"<type> is not allowed while <status>[; <status> is terminal]\"`, as the fold words it. */\nfunction illegal(type: string, status: string): string {\n const terminal = adrKind.machine.terminal.includes(status as never)\n ? `; ${status} is terminal`\n : \"\";\n return `${type} is not allowed while ${status}${terminal}`;\n}\n\n/** A new event of `subject`, sorting after its existing ones. */\nfunction newEvent(\n read: DecisionsRead,\n c: PlanContext,\n o: {\n readonly subject: string;\n readonly type: string;\n readonly data: Record<string, unknown>;\n readonly reason?: string | null;\n readonly actor: Actor;\n readonly after?: readonly EventEnvelope[];\n },\n): EventEnvelope {\n const existing = (read.folded.subjects.get(o.subject)?.loaded.events ?? []).flatMap((e) =>\n e.event === null ? [] : [e.event],\n );\n const { at, id } = nextEventIdentity([...existing, ...(o.after ?? [])], {\n now: c.now,\n ...(c.random === undefined ? {} : { random: c.random }),\n });\n return {\n envelope: ENVELOPE_VERSION,\n kind: adrKind.name,\n schema: adrKind.schema,\n id,\n subject: o.subject,\n type: o.type,\n at,\n actor: o.actor,\n ...(o.reason === undefined || o.reason === null ? {} : { reason: o.reason }),\n data: o.data,\n };\n}\n\n/** Body, events directory and recorded template of each involved subject (D6). */\nfunction commitScope(\n read: DecisionsRead,\n involved: readonly string[],\n extra: { readonly body?: string; readonly template?: string } = {},\n): { scope: string[]; eventDirs: string[] } {\n const paths: string[] = [];\n const dirs: string[] = [];\n for (const id of involved) {\n const view = read.projection.views.get(id);\n if (view?.body_path !== null && view?.body_path !== undefined) paths.push(view.body_path);\n if (view !== undefined) paths.push(templatePath(read, view.template.name));\n dirs.push(eventDir(read.layout, id));\n }\n if (extra.body !== undefined) paths.push(extra.body);\n if (extra.template !== undefined) paths.push(extra.template);\n return { scope: sorted([...paths, ...dirs]), eventDirs: sorted(dirs) };\n}\n\nconst findingKey = (f: Finding) => [f.rule, f.subject ?? \"\", f.file ?? \"\", f.message].join(\"\\0\");\n\n/**\n * The precheck (§6.3): folds the would-be log and refuses when the write adds any finding. Problems\n * that were already there don't block; the write can only add findings about what it touches.\n */\nasync function precheck(\n read: DecisionsRead,\n files: Readonly<Record<string, Uint8Array>>,\n): Promise<{ after: DecisionsRead; added: Finding[] }> {\n const after = await readDecisionsFrom(overlayTree(read.tree, files), {\n layout: read.layout,\n adr: read.adr,\n numbering: read.numbering,\n ref: read.ref,\n commit: read.commit,\n notes: read.notes,\n });\n const before = new Set(read.findings.map(findingKey));\n return { after, added: after.findings.filter((f) => !before.has(findingKey(f))) };\n}\n\nfunction filesOf(\n events: readonly EventEnvelope[],\n read: DecisionsRead,\n): Record<string, Uint8Array> {\n return Object.fromEntries(\n events.map((e) => [eventPath(read.layout, e), encoder.encode(serializeEvent(e))]),\n );\n}\n\nconst pairsOf = (events: readonly EventEnvelope[]): Trailer[] =>\n events.flatMap((e): Trailer[] => [\n [\"ADR\", e.subject],\n [\"ADR-Event\", e.type],\n ]);\n\n/** The template `new` uses: the repo's `<root>/templates/<name>.md`, else a built-in to copy. */\nasync function chooseTemplate(\n read: DecisionsRead,\n name: string,\n c: PlanContext,\n): Promise<\n | { ok: true; template: Template; materialize: string | null; path: string }\n | { ok: false; findings: Finding[] }\n> {\n if (name.length > 64 || !TEMPLATE_NAME.test(name)) {\n throw new UsageError(`invalid template name ${JSON.stringify(name)}`);\n }\n const path = templatePath(read, name);\n const bytes = await read.tree.read(path);\n let text: string;\n let materialize: string | null = null;\n if (bytes !== null) {\n text = decoder.decode(bytes);\n } else {\n const builtin = Object.hasOwn(c.builtins, name) ? c.builtins[name] : undefined;\n if (builtin === undefined) {\n const known = Object.keys(c.builtins).sort().join(\", \");\n throw new UsageError(`unknown template ${name}; add ${path} or use one of ${known}`);\n }\n text = builtin;\n materialize = builtin;\n }\n const parsed = parseTemplate(text, { path });\n if (!parsed.ok) return { ok: false, findings: parsed.findings };\n const lint = lintTemplate(parsed.template, {\n requireSections: adrKind.def.templates?.requireSections ?? [],\n });\n if (lint.length > 0) return { ok: false, findings: lint };\n return { ok: true, template: parsed.template, materialize, path };\n}\n\n/** Plans `adr new`: a rendered body, a materialized template if needed, and `proposed`. */\nexport async function planPropose(\n read: DecisionsRead,\n input: ProposeInput,\n c: PlanContext,\n): Promise<PlanResult> {\n const title = input.title.trim();\n if (title === \"\" || title.length > 200 || /[\\r\\n]/.test(title)) {\n throw new UsageError(\"the title must be a single line of 1 to 200 characters\");\n }\n const supersedes = sorted(\n (input.supersedes ?? []).map((s) => {\n if (s.includes(\":\"))\n throw new UsageError(`cannot supersede ${s.trim()}: ${QUALIFIED_SUPERSESSION}`);\n return resolveDecision(read, s);\n }),\n );\n const chosen = await chooseTemplate(read, input.template ?? read.adr.defaultTemplate, c);\n if (!chosen.ok) return { ok: false, decision: null, findings: chosen.findings };\n const t = chosen.template;\n const sections = input.sections ?? {};\n for (const [id, text] of Object.entries(sections)) {\n if (!t.sections.some((s) => s.id === id)) {\n const ids = t.sections.map((s) => s.id).join(\", \");\n throw new UsageError(`template ${t.name} has no section ${id}; its sections are ${ids}`);\n }\n checkText(`section ${id}`, text);\n }\n const rendered = renderTemplate(t, { title, sections }, { missing: \"guidance\" });\n if (!rendered.ok) throw new UsageError(rendered.findings.map((f) => f.message).join(\"; \"));\n\n let id = \"\";\n let bodyPath = \"\";\n for (let attempt = 0; ; attempt++) {\n id = newSubjectId(c.random);\n bodyPath = `${read.root}/${read.layout.bodies}/${bodyFileName(id, slugify(title))}`;\n if (!read.folded.subjects.has(id) && (await read.tree.read(bodyPath)) === null) break;\n if (attempt + 1 >= SUBJECT_ATTEMPTS) throw new FileExistsError(bodyPath);\n }\n const event = newEvent(read, c, {\n subject: id,\n type: \"proposed\",\n data: {\n title,\n template: t.name,\n template_version: t.version,\n ...(supersedes.length === 0 ? {} : { supersedes }),\n },\n actor: input.actor,\n });\n const body = encoder.encode(rendered.text);\n const files: Record<string, Uint8Array> = { [bodyPath]: body };\n if (chosen.materialize !== null) files[chosen.path] = encoder.encode(chosen.materialize);\n Object.assign(files, filesOf([event], read));\n\n const { after, added } = await precheck(read, files);\n if (added.length > 0) return { ok: false, decision: null, findings: added };\n const { scope, eventDirs } = commitScope(read, [id], { body: bodyPath, template: chosen.path });\n return {\n ok: true,\n plan: {\n command: \"new\",\n subject: id,\n files,\n events: [event],\n stage: Object.keys(files),\n involved: [id],\n commitScope: scope,\n eventDirs,\n draft: { path: bodyPath, rendered: body, template: t },\n message: `Propose decision ${id}: ${title}`,\n trailers: pairsOf([event]),\n decision: viewOf(after, id),\n affected: [],\n findings: lintDocument(t, rendered.text, { file: bodyPath, subject: id }),\n },\n };\n}\n\n/** The draft lint of an `accept`: the body against the template version its proposal recorded. */\nasync function acceptLint(\n read: DecisionsRead,\n view: DecisionView,\n c: PlanContext,\n): Promise<{ findings: Finding[]; bytes: Uint8Array | null }> {\n const body = read.folded.subjects.get(view.id)?.loaded.body ?? null;\n if (body === null) {\n return {\n findings: [refusal(read, \"body/missing\", \"body file is missing\", view.id)],\n bytes: null,\n };\n }\n const { name, version } = view.template;\n const found = await c.templates.get(name, version);\n if (!found.ok) {\n const message =\n found.reason === \"not-found\"\n ? `template ${name} not found at ${found.path}`\n : `template ${name} has no version ${version} at ${found.path}`;\n return {\n findings: [refusal(read, `template/${found.reason}`, message, view.id)],\n bytes: body.bytes,\n };\n }\n let text: string;\n try {\n text = new TextDecoder(\"utf-8\", { fatal: true }).decode(body.bytes);\n } catch {\n return {\n findings: [refusal(read, \"body/not-utf8\", \"body is not valid UTF-8\", view.id)],\n bytes: body.bytes,\n };\n }\n const lint = lintDocument(found.template, text, { file: body.path, subject: view.id });\n return { findings: lint.map((f) => ({ ...f, kind: adrKind.name })), bytes: body.bytes };\n}\n\n/** Plans `adr accept`: `accepted` with the body hash, and `superseded` on each declared target. */\nexport async function planAccept(\n read: DecisionsRead,\n input: { readonly id: string; readonly actor: Actor },\n c: PlanContext,\n): Promise<PlanResult> {\n const id = resolveDecision(read, input.id);\n const view = viewOf(read, id);\n const refused = (findings: readonly Finding[]): PlanResult => ({\n ok: false,\n decision: view,\n findings,\n });\n const findings: Finding[] = [];\n if (view.status !== \"proposed\") {\n findings.push(refusal(read, \"transition/illegal\", illegal(\"accepted\", view.status), id));\n }\n const lint = await acceptLint(read, view, c);\n findings.push(...lint.findings);\n if (read.adr.acceptRequiresHuman && input.actor.kind === \"agent\") {\n findings.push(\n refusal(\n read,\n \"decision/agent-accepted\",\n `accepted by agent ${input.actor.name}; accept_requires_human needs a human`,\n id,\n ),\n );\n }\n const targets: string[] = [];\n for (const target of view.declared_supersedes) {\n if (target.includes(\":\")) {\n findings.push(\n refusal(\n read,\n \"decision/reference-missing\",\n `supersedes ${target}: ${QUALIFIED_SUPERSESSION}`,\n id,\n ),\n );\n continue;\n }\n const t = read.projection.views.get(target);\n if (t === undefined) {\n findings.push(\n refusal(\n read,\n \"decision/reference-missing\",\n `supersedes ${target}, which is not in the log`,\n id,\n ),\n );\n } else if (target === id) {\n findings.push(\n refusal(read, \"decision/supersession-cycle\", `supersession cycle: ${id} → ${id}`, id),\n );\n } else if (t.status !== \"accepted\" && t.status !== \"deprecated\") {\n findings.push(refusal(read, \"transition/illegal\", illegal(\"superseded\", t.status), target));\n } else {\n targets.push(target);\n }\n }\n if (findings.length > 0 || lint.bytes === null) return refused(findings);\n\n const accepted = newEvent(read, c, {\n subject: id,\n type: \"accepted\",\n data: { body_sha256: bodySha256(lint.bytes) },\n actor: input.actor,\n });\n const cascade = targets.map((target) =>\n newEvent(read, c, {\n subject: target,\n type: \"superseded\",\n data: { by: id },\n actor: input.actor,\n }),\n );\n const events = [accepted, ...cascade];\n const files = filesOf(events, read);\n const { after, added } = await precheck(read, files);\n if (added.length > 0) return refused(added);\n const involved = sorted([id, ...targets]);\n const { scope, eventDirs } = commitScope(read, involved);\n const bodyPath = view.body_path ?? \"\";\n return {\n ok: true,\n plan: {\n command: \"accept\",\n subject: id,\n files,\n events,\n stage: [...Object.keys(files), bodyPath],\n involved,\n commitScope: scope,\n eventDirs,\n draft: null,\n message: [\n `Accept decision ${id}: ${view.title}`,\n ...(targets.length === 0 ? [] : [\"\", ...targets.map((t) => `Supersedes ${t}.`)]),\n ].join(\"\\n\"),\n trailers: pairsOf(events),\n decision: viewOf(after, id),\n affected: targets.map((t) => viewOf(after, t)),\n findings: [],\n },\n };\n}\n\n/** Plans `adr supersede <id> --by <by>`: one `superseded` event on `id`. */\nexport async function planSupersede(\n read: DecisionsRead,\n input: {\n readonly id: string;\n readonly by: string;\n readonly reason?: string | null;\n readonly actor: Actor;\n },\n c: PlanContext,\n): Promise<PlanResult> {\n if (input.by.includes(\":\")) {\n throw new UsageError(`--by ${input.by.trim()}: ${QUALIFIED_SUPERSESSION}`);\n }\n const reason = checkReason(input.reason);\n const id = resolveDecision(read, input.id);\n const by = resolveDecision(read, input.by);\n const view = viewOf(read, id);\n const target = viewOf(read, by);\n const findings: Finding[] = [];\n if (view.status !== \"accepted\" && view.status !== \"deprecated\") {\n findings.push(refusal(read, \"transition/illegal\", illegal(\"superseded\", view.status), id));\n }\n if (by === id || target.chain.includes(id)) {\n const cycle =\n by === id ? [id, id] : [id, ...target.chain.slice(0, target.chain.indexOf(id) + 1)];\n findings.push(\n refusal(read, \"decision/supersession-cycle\", `supersession cycle: ${cycle.join(\" → \")}`, id),\n );\n } else if (target.status !== \"accepted\") {\n findings.push(\n refusal(\n read,\n \"decision/superseded-by-unaccepted\",\n `superseded by ${by}, which is not accepted`,\n id,\n ),\n );\n }\n const refused = (fs: readonly Finding[]): PlanResult => ({\n ok: false,\n decision: view,\n findings: fs,\n });\n if (findings.length > 0) return refused(findings);\n\n const event = newEvent(read, c, {\n subject: id,\n type: \"superseded\",\n data: { by },\n reason,\n actor: input.actor,\n });\n const files = filesOf([event], read);\n const { after, added } = await precheck(read, files);\n if (added.length > 0) return refused(added);\n const involved = sorted([id, by]);\n const { scope, eventDirs } = commitScope(read, involved);\n return {\n ok: true,\n plan: {\n command: \"supersede\",\n subject: id,\n files,\n events: [event],\n stage: Object.keys(files),\n involved,\n commitScope: scope,\n eventDirs,\n draft: null,\n message: `Supersede decision ${id}: ${view.title}\\n\\nSuperseded by ${by}.`,\n trailers: pairsOf([event]),\n decision: viewOf(after, id),\n affected: [viewOf(after, id)],\n findings: [],\n },\n };\n}\n\nconst VERBS: Readonly<Record<string, string>> = {\n proposed: \"Propose\",\n accepted: \"Accept\",\n rejected: \"Reject\",\n withdrawn: \"Withdraw\",\n deprecated: \"Deprecate\",\n superseded: \"Supersede\",\n noted: \"Note on\",\n linked: \"Link\",\n scoped: \"Scope\",\n};\n\n/**\n * Plans any one event on an existing decision: the state machine and the event's validation\n * decide, then the precheck. Phase 2's reject, withdraw, deprecate, note, link and scope wrap it.\n */\nexport async function planEvent(\n read: DecisionsRead,\n input: {\n readonly subject: string;\n readonly type: string;\n readonly data: Record<string, unknown>;\n readonly reason?: string | null;\n readonly actor: Actor;\n },\n c: PlanContext,\n): Promise<PlanResult> {\n const id = resolveDecision(read, input.subject);\n const view = viewOf(read, id);\n if (!adrKind.machine.types.has(input.type) || input.type === adrKind.machine.initial.type) {\n throw new InvalidArgumentError(`planEvent can't write a ${input.type} event`);\n }\n const reason = checkReason(input.reason);\n const refused = (fs: readonly Finding[]): PlanResult => ({\n ok: false,\n decision: view,\n findings: fs,\n });\n if (!adrKind.machine.allowed(view.status, input.type)) {\n return refused([refusal(read, \"transition/illegal\", illegal(input.type, view.status), id)]);\n }\n const event = newEvent(read, c, {\n subject: id,\n type: input.type,\n data: input.data,\n reason,\n actor: input.actor,\n });\n const valid = compiled.validate(event, { file: null });\n if (!valid.ok) {\n return refused(valid.findings.map((f) => ({ ...f, subject: id, kind: adrKind.name })));\n }\n const files = filesOf([event], read);\n const { after, added } = await precheck(read, files);\n if (added.length > 0) return refused(added);\n const by = input.type === \"superseded\" ? String(input.data.by) : null;\n const involved = sorted([id, ...(by !== null && isSubjectId(by) ? [by] : [])]);\n const { scope, eventDirs } = commitScope(read, involved);\n return {\n ok: true,\n plan: {\n command: \"event\",\n subject: id,\n files,\n events: [event],\n stage: Object.keys(files),\n involved,\n commitScope: scope,\n eventDirs,\n draft: null,\n message: `${VERBS[input.type] ?? input.type} decision ${id}: ${view.title}`,\n trailers: pairsOf([event]),\n decision: viewOf(after, id),\n affected: input.type === \"superseded\" ? [viewOf(after, id)] : [],\n findings: [],\n },\n };\n}\n\n/** What the editor step decided (§5.4 step 4a). */\nexport interface AfterStage {\n /** Draft lint findings to report instead of `plan.findings`; `null` keeps `plan.findings`. */\n readonly findings: readonly Finding[] | null;\n /** `false` skips the commit: the files stay written and staged, and `commit` is `null`. */\n readonly commit: boolean;\n}\n\nconst isYaml = (path: string) => /\\.ya?ml$/.test(path);\n\n/**\n * Applies a plan (§5.4): refuses a commit whose scope has unstaged or needed untracked paths,\n * writes the files (removing them again if a write fails), stages them, runs `afterStage`, and\n * commits `plan.stage` plus the involved subjects' already-staged files with exact trailers.\n */\nexport async function applyPlan(\n log: DecisionLog,\n plan: WritePlan,\n o: { readonly commit: boolean; readonly afterStage?: () => Promise<AfterStage> },\n): Promise<{ written: string[]; commit: string | null; findings: readonly Finding[] }> {\n const { git } = log;\n const stage = new Set(plan.stage);\n // This check runs before anything is written. It stays correct with an editor in between for\n // the body, which is in `plan.stage` and is re-staged after a successful edit; every other path\n // in the scope (a materialized template, say) is checked again by the editor step once the\n // editor has closed, because `--only` would commit its work-tree content.\n if (o.commit) {\n const unstaged = new Set(await git.unstagedPaths(plan.commitScope));\n const dirs = new Set(plan.eventDirs);\n const untracked = new Set([\n ...(await git.untrackedPaths(plan.commitScope.filter((p) => !dirs.has(p)))),\n ...(await git.untrackedPaths(plan.eventDirs)).filter(isYaml),\n ]);\n const dirty = sorted([...unstaged, ...untracked]).filter((p) => !stage.has(p));\n const [first] = dirty;\n if (first !== undefined) {\n throw new UsageError(\n unstaged.has(first)\n ? `${first} has unstaged changes; stage or discard them, or run without --commit`\n : `${first} is not tracked; git add it, or run without --commit`,\n );\n }\n }\n\n const eventPaths = new Set(plan.events.map((e) => eventPath(log.layout, e)));\n const written: string[] = [];\n try {\n for (const [path, bytes] of Object.entries(plan.files)) {\n if (eventPaths.has(path)) continue;\n await writeNewFile(git, path, bytes, { stage: false });\n written.push(path);\n }\n await writeEvents(git, log.layout, plan.events, { kind: log.compiled, stage: false });\n } catch (err) {\n const root = git.root ?? \"\";\n for (const path of written) await rm(join(root, path), { force: true });\n throw err;\n }\n await git.add(plan.stage);\n\n let findings = plan.findings;\n let commit = o.commit;\n if (o.afterStage !== undefined) {\n const after = await o.afterStage();\n findings = after.findings ?? plan.findings;\n commit = commit && after.commit;\n }\n\n let sha: string | null = null;\n if (commit) {\n const extra = (await git.stagedPaths(plan.commitScope)).filter((p) => !stage.has(p));\n const staged: Trailer[] = extra.filter(isYaml).flatMap((p): Trailer[] => {\n const c = classifyPath(log.layout, p);\n const name = c.area === \"event\" && !c.file.includes(\"/\") ? parseEventFileName(c.file) : null;\n return c.area === \"event\" && c.subject !== null && name !== null\n ? [\n [\"ADR\", c.subject],\n [\"ADR-Event\", name.type],\n ]\n : [];\n });\n sha = await git.commit({\n message: plan.message,\n trailers: [...staged, ...plan.trailers],\n only: sorted([...plan.stage, ...extra]),\n });\n }\n return { written: Object.keys(plan.files), commit: sha, findings };\n}\n\n/**\n * The clock, the randomness and `applyPlan` the write functions use. Only tests pass their own\n * (for example an `apply` that fails once); the default is the real ones.\n */\nexport interface WriteDeps {\n readonly now: () => number;\n readonly random?: (buf: Uint8Array) => void;\n readonly apply: typeof applyPlan;\n}\nconst DEFAULT_DEPS: WriteDeps = { now: Date.now, apply: applyPlan };\n\n/**\n * The views `adr-write/v1` reports. Without a commit they are the plan's, folded on the overlay.\n * After a commit they come from a new read of the log, so a commit on the main ref shows the\n * numbers it assigned, as the CLI text and phase 3's MCP tools do. A commit that failed threw in\n * `applyPlan`, so nothing is read for it.\n */\nasync function viewsAfter(\n log: DecisionLog,\n plan: WritePlan,\n sha: string | null,\n): Promise<{ decision: DecisionView; affected: readonly DecisionView[] }> {\n if (sha === null) return { decision: plan.decision, affected: plan.affected };\n const read = await readDecisions({ ...log, commit: sha });\n const view = (v: DecisionView) => read.projection.views.get(v.id) ?? v;\n return { decision: view(plan.decision), affected: plan.affected.map(view) };\n}\n\n/** Plan, then apply, with the single `EventExistsError` retry (§5.4 steps 1–5). */\nasync function write(\n log: DecisionLog,\n command: WriteResultJson[\"command\"],\n plan: (read: DecisionsRead, c: PlanContext) => Promise<PlanResult>,\n o: { readonly commit?: boolean },\n deps: WriteDeps,\n afterStage?: (plan: WritePlan, commit: boolean) => () => Promise<AfterStage>,\n): Promise<WriteResultJson> {\n if (log.ref !== null) {\n throw new InvalidArgumentError(\"writes read the work tree; open the log without a ref\");\n }\n if (log.tree.label !== \"worktree\") {\n throw new InvalidArgumentError(\n \"writes read the work tree; open the log with the worktree reader\",\n );\n }\n const commit = o.commit ?? log.adr.autoCommit;\n for (let attempt = 0; ; attempt++) {\n const read = await readDecisions(log);\n const ref = await templateHistoryRef(log.git, { type: \"full\" });\n const c: PlanContext = {\n now: deps.now,\n ...(deps.random === undefined ? {} : { random: deps.random }),\n templates: historyTemplates(log.git, log.tree, `${read.root}/templates`, { ref }),\n builtins: BUILTIN_TEMPLATES,\n };\n const r = await plan(read, c);\n if (!r.ok) {\n return {\n format: \"adr-write/v1\",\n command,\n ok: false,\n decision: r.decision,\n affected: [],\n written: [],\n commit: null,\n findings: r.findings,\n notes: log.notes,\n };\n }\n try {\n const applied = await deps.apply(log, r.plan, {\n commit,\n ...(afterStage === undefined ? {} : { afterStage: afterStage(r.plan, commit) }),\n });\n const views = await viewsAfter(log, r.plan, applied.commit);\n return {\n format: \"adr-write/v1\",\n command,\n ok: true,\n decision: views.decision,\n affected: views.affected,\n written: applied.written,\n commit: applied.commit,\n findings: applied.findings,\n notes: log.notes,\n };\n } catch (err) {\n // Another process wrote the same event path in the same instant: writeEvents removed this\n // batch and applyPlan the new body and template, so plan again with a fresh clock, once.\n if (!(err instanceof EventExistsError) || attempt > 0) throw err;\n }\n }\n}\n\nconst sameBytes = (a: Uint8Array, b: Uint8Array) =>\n a.byteLength === b.byteLength && a.every((x, i) => x === b[i]);\n\nasync function readIfPresent(path: string): Promise<Uint8Array | null> {\n try {\n return await readFile(path);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw err;\n }\n}\n\n/**\n * The editor step (§5.4): runs `edit` on the staged draft, re-stages the edited body when the\n * editor exited 0, and skips the commit when committing would take content nobody confirmed: the\n * body changed while the editor failed, the body is gone, or another path in the commit scope (a\n * materialized template, say) changed while the editor was open (design review NIT 2). The\n * findings are the lint of the draft as it now is.\n */\nfunction editorStep(\n log: DecisionLog,\n edit: (absBodyPath: string) => Promise<string | null>,\n onNote: ((note: string) => void) | undefined,\n): (plan: WritePlan, commitRequested: boolean) => () => Promise<AfterStage> {\n return (plan, commitRequested) => async () => {\n const d = plan.draft;\n if (d === null) return { findings: null, commit: true };\n const abs = join(log.git.root ?? \"\", d.path);\n const note = await edit(abs);\n const bytes = await readIfPresent(abs);\n let commit: boolean;\n if (bytes === null) {\n commit = false;\n onNote?.(\n `${d.path} was removed while editing; the rendered draft is still staged. Restore it with \\`git checkout -- ${d.path}\\``,\n );\n } else if (note === null) {\n await log.git.add([d.path]);\n commit = true;\n } else if (sameBytes(bytes, d.rendered)) {\n commit = true;\n } else {\n commit = false;\n if (commitRequested) {\n onNote?.(\n `${d.path} changed while the editor failed; review it, then git add it and commit`,\n );\n }\n }\n if (commit && commitRequested) {\n const late = (await log.git.unstagedPaths(plan.commitScope)).filter((p) => p !== d.path);\n const [first] = late;\n if (first !== undefined) {\n commit = false;\n onNote?.(\n `${first} changed while the editor was open; review it, then git add it and commit`,\n );\n }\n }\n const text = decoder.decode(bytes ?? d.rendered);\n return {\n findings: lintDocument(d.template, text, { file: d.path, subject: plan.subject }),\n commit,\n };\n };\n}\n\n/**\n * `adr new`: renders a draft, writes the body, any materialized template and the `proposed`\n * event, stages them, and commits with `commit` (default `[policy] auto_commit`).\n *\n * `edit` (CLI only; MCP never passes it) runs between staging and committing, on the absolute\n * body path. It resolves to `null` when the editor exited 0, else to a note for the user (spawn\n * error, exit status). `onNote` receives the notes about a skipped commit or a removed body,\n * without the \"not committed: \" prefix the CLI adds when a commit was requested.\n */\nexport async function proposeDecision(\n log: DecisionLog,\n input: ProposeInput,\n o: {\n readonly commit?: boolean;\n readonly edit?: (absBodyPath: string) => Promise<string | null>;\n readonly onNote?: (note: string) => void;\n } = {},\n deps: WriteDeps = DEFAULT_DEPS,\n): Promise<WriteResultJson> {\n return write(\n log,\n \"new\",\n (read, c) => planPropose(read, input, c),\n o,\n deps,\n o.edit === undefined ? undefined : editorStep(log, o.edit, o.onNote),\n );\n}\n\n/**\n * `adr accept`: lints the draft, hashes the body, writes `accepted` and a `superseded` event on\n * each declared target, stages them with the body, and commits with `commit`.\n */\nexport async function acceptDecision(\n log: DecisionLog,\n input: { readonly id: string; readonly actor: Actor },\n o: { readonly commit?: boolean } = {},\n deps: WriteDeps = DEFAULT_DEPS,\n): Promise<WriteResultJson> {\n return write(log, \"accept\", (read, c) => planAccept(read, input, c), o, deps);\n}\n\n/** `adr supersede <id> --by <by>`: writes `superseded`, stages it, and commits with `commit`. */\nexport async function supersedeDecision(\n log: DecisionLog,\n input: {\n readonly id: string;\n readonly by: string;\n readonly reason?: string | null;\n readonly actor: Actor;\n },\n o: { readonly commit?: boolean } = {},\n deps: WriteDeps = DEFAULT_DEPS,\n): Promise<WriteResultJson> {\n return write(log, \"supersede\", (read, c) => planSupersede(read, input, c), o, deps);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1 +1,55 @@
1
- {"name":"@nikovirtala/adr","version":"0.0.0","description":"placeholder","license":"MIT","repository":{"type":"git","url":"git+https://github.com/nikovirtala/ark.git"}}
1
+ {
2
+ "name": "@nikovirtala/adr",
3
+ "version": "0.1.0",
4
+ "description": "Architecture decision records kept as event logs in git: frozen bodies, computed status and supersession chains. CLI and library.",
5
+ "keywords": [
6
+ "adr",
7
+ "architecture-decision-records",
8
+ "git",
9
+ "event-sourcing",
10
+ "cli"
11
+ ],
12
+ "license": "MIT",
13
+ "homepage": "https://github.com/nikovirtala/ark/tree/main/packages/adr#readme",
14
+ "bugs": "https://github.com/nikovirtala/ark/issues",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/nikovirtala/ark.git",
18
+ "directory": "packages/adr"
19
+ },
20
+ "type": "module",
21
+ "sideEffects": false,
22
+ "bin": {
23
+ "adr": "./dist/cli.js"
24
+ },
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/types/index.d.ts",
28
+ "default": "./dist/index.js"
29
+ },
30
+ "./kind": {
31
+ "types": "./dist/types/kind.d.ts",
32
+ "default": "./dist/kind.js"
33
+ },
34
+ "./package.json": "./package.json"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "!dist/**/*.tsbuildinfo"
39
+ ],
40
+ "engines": {
41
+ "node": ">=24"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public",
45
+ "provenance": true
46
+ },
47
+ "dependencies": {
48
+ "@nikovirtala/ledger": "^0.3.0"
49
+ },
50
+ "scripts": {
51
+ "build": "tsdown",
52
+ "test": "vitest run",
53
+ "clean": "rm -rf dist"
54
+ }
55
+ }