@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,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,25 @@
1
+ import { type Severity, type ToolConfig } from "@nikovirtala/ledger";
2
+ /** adr's settings from `adr.toml` (design §5.3); every key is optional. */
3
+ export interface AdrConfig {
4
+ /** `[log] default_template`: the template `adr new` uses without `--template`. */
5
+ readonly defaultTemplate: string;
6
+ /** `[log] main_branch`: the ref numbers come from; `null` resolves it automatically. */
7
+ readonly mainBranch: string | null;
8
+ /** `[log] index`: validated now, used in phase 2. */
9
+ readonly index: "committed" | "none";
10
+ /** `[policy] accept_requires_human`. */
11
+ readonly acceptRequiresHuman: boolean;
12
+ /** `[policy] auto_commit`: commit writes without `--commit`. */
13
+ readonly autoCommit: boolean;
14
+ /** `[policy] mcp_can_decide`: validated now, used in phase 3. */
15
+ readonly mcpCanDecide: boolean;
16
+ /** `[verify] fail_on`. */
17
+ readonly failOn: Severity;
18
+ }
19
+ export declare const DEFAULT_ADR_CONFIG: AdrConfig;
20
+ /**
21
+ * Validates `adr.toml` (ledger's parsed `ToolConfig`; `null` when there is none). A wrong type or
22
+ * value throws `ConfigError` naming the file and key. Unknown keys are ignored, so newer files
23
+ * still load. `[log] root` is ledger's (`openToolLog` already checked it).
24
+ */
25
+ export declare function parseAdrConfig(config: ToolConfig | null, file: string | null): AdrConfig;
@@ -0,0 +1,6 @@
1
+ export { type AdrConfig, DEFAULT_ADR_CONFIG, parseAdrConfig } from "./config.js";
2
+ export { type AdrOptions, adrKind, DECISION_STATUSES, type DecisionEvents, type DecisionState, type DecisionStatus, type DecisionView, formatDecisionNumber, type LinkRel, parseDecisionNumber, REF, } from "./kind.js";
3
+ export { type DecisionLog, type DecisionsRead, openDecisionLog, readDecisions, readDecisionsFrom, resolveDecision, } from "./log.js";
4
+ export { adrChecks, verifyDecisions } from "./verify.js";
5
+ export { type DecisionListJson, type DecisionShowJson, listDecisions, type NumberingJson, showDecision, stateHeader, } from "./views.js";
6
+ export { acceptDecision, type ProposeInput, proposeDecision, supersedeDecision, type WriteResultJson, } from "./write.js";
@@ -0,0 +1,50 @@
1
+ import type { FoldedSubject, ProjectContext } from "@nikovirtala/ledger";
2
+ import type { DecisionState } from "./reduce.js";
3
+ import type { DecisionEvents, DecisionStatus } from "./schemas.js";
4
+ /** One decision as the CLI, the library and MCP show it (01:173–192, plus the added fields). */
5
+ export interface DecisionView {
6
+ readonly id: string;
7
+ readonly number: number | null;
8
+ /** `ADR-0007`, or the id when unnumbered. */
9
+ readonly display: string;
10
+ readonly title: string;
11
+ readonly status: DecisionStatus;
12
+ readonly superseded_by: string | null;
13
+ /** Ids whose applied `superseded.by` is this id, sorted. */
14
+ readonly supersedes: readonly string[];
15
+ /** The proposal's intent (01:164). */
16
+ readonly declared_supersedes: readonly string[];
17
+ /** Head of the `superseded_by` chain; `null` only on a cycle. */
18
+ readonly effective: string | null;
19
+ /** `[id, …, effective]`, following `superseded_by` forward. */
20
+ readonly chain: readonly string[];
21
+ readonly template: {
22
+ readonly name: string;
23
+ readonly version: number;
24
+ };
25
+ readonly body_path: string | null;
26
+ /** Recorded at acceptance. */
27
+ readonly body_sha256: string | null;
28
+ /** `null` until accepted; whether the current body hash equals the recorded one. */
29
+ readonly body_intact: boolean | null;
30
+ readonly links: readonly {
31
+ readonly to: string;
32
+ readonly rel: string;
33
+ }[];
34
+ readonly applies_to: readonly string[];
35
+ readonly notes: number;
36
+ readonly proposed_at: string;
37
+ readonly decided_at: string | null;
38
+ readonly status_at: string;
39
+ /** `proposed 2026-03-12`: state-changing events, in fold order. */
40
+ readonly history: readonly string[];
41
+ }
42
+ type Subject = FoldedSubject<DecisionStatus, DecisionState, DecisionEvents>;
43
+ type Context = ProjectContext<DecisionStatus, DecisionState, DecisionEvents>;
44
+ /** `ADR-0007`: at least 4 digits, growing past 9999. */
45
+ export declare function formatDecisionNumber(n: number): string;
46
+ /** `7`, `0007`, `ADR-7`, `adr-0007` → 7; `null` for anything else. */
47
+ export declare function parseDecisionNumber(s: string): number | null;
48
+ /** Pure: the view of one folded decision. */
49
+ export declare function project(subject: Subject, ctx: Context): DecisionView;
50
+ export {};
@@ -0,0 +1,35 @@
1
+ import type { Actor, FoldEvent } from "@nikovirtala/ledger";
2
+ import type { DecisionEvents } from "./schemas.js";
3
+ /** A decision's own state, maintained by `reduce` over its applied events. */
4
+ export interface DecisionState {
5
+ readonly title: string;
6
+ readonly template: {
7
+ readonly name: string;
8
+ readonly version: number;
9
+ };
10
+ readonly declaredSupersedes: readonly string[];
11
+ /** From the applied `accepted` event. */
12
+ readonly bodySha256: string | null;
13
+ readonly acceptedBy: Actor | null;
14
+ readonly supersededBy: string | null;
15
+ /** In fold order, duplicates kept once. */
16
+ readonly links: readonly {
17
+ readonly to: string;
18
+ readonly rel: string;
19
+ }[];
20
+ /** The latest `scoped` set (latest wins). */
21
+ readonly appliesTo: readonly string[];
22
+ readonly notes: number;
23
+ /** State-changing events only, in fold order. */
24
+ readonly history: readonly {
25
+ readonly type: string;
26
+ readonly at: string;
27
+ }[];
28
+ readonly proposedAt: string;
29
+ /** `at` of `accepted`, `rejected` or `withdrawn`. */
30
+ readonly decidedAt: string | null;
31
+ /** `at` of the latest state-changing event. */
32
+ readonly statusAt: string;
33
+ }
34
+ /** Pure: the state after one applied event. The fold only passes events the machine allows. */
35
+ export declare function reduce(state: DecisionState | null, e: FoldEvent<DecisionEvents>): DecisionState;
@@ -0,0 +1,20 @@
1
+ import type { FoldedLog, FoldedSubject, KindFinding } from "@nikovirtala/ledger";
2
+ import type { DecisionState } from "./reduce.js";
3
+ import type { DecisionEvents, DecisionStatus } from "./schemas.js";
4
+ /** Options of the decision kind's `invariants` and `relate`. */
5
+ export interface AdrOptions {
6
+ /** Default `true`: an agent may propose, but only a human may accept (01:98). */
7
+ readonly acceptRequiresHuman: boolean;
8
+ }
9
+ type Subject = FoldedSubject<DecisionStatus, DecisionState, DecisionEvents>;
10
+ type Log = FoldedLog<DecisionStatus, DecisionState, DecisionEvents>;
11
+ /** `decision/agent-accepted`: an applied `accepted` event written by an agent under the human policy. */
12
+ export declare function invariants(subject: Subject, options: AdrOptions): readonly KindFinding[];
13
+ /**
14
+ * Cross-subject rules: `decision/reference-missing` for a local `supersedes`, `superseded.by` or
15
+ * `linked.to` naming no subject in the log; `decision/superseded-by-unaccepted` when the target of
16
+ * an applied `superseded.by` has no applied `accepted` event in this tree; and
17
+ * `decision/supersession-cycle`, once per cycle on its smallest id.
18
+ */
19
+ export declare function relate(log: Log): readonly KindFinding[];
20
+ export {};
@@ -0,0 +1,37 @@
1
+ /** A decision's computed status. */
2
+ export type DecisionStatus = "proposed" | "accepted" | "rejected" | "withdrawn" | "deprecated" | "superseded";
3
+ /** Every status, in lifecycle order. */
4
+ export declare const DECISION_STATUSES: readonly DecisionStatus[];
5
+ /** A local subject id, or a qualified `<source>:<id>` one. */
6
+ export declare const REF = "^(?:[a-z][a-z0-9-]*:)?[0-9a-hjkmnp-tv-z]{8}$";
7
+ /** How a `linked` decision relates to its target. */
8
+ export type LinkRel = "relates-to" | "refines" | "depends-on";
9
+ /** The decision kind's event types (01:128–136): data schemas, allowed states and targets. */
10
+ export declare const decisionEvents: {
11
+ readonly proposed: import("@nikovirtala/ledger").EventTypeDef<"proposed", {
12
+ title: string;
13
+ template: string;
14
+ template_version: number;
15
+ supersedes?: string[];
16
+ }>;
17
+ readonly accepted: import("@nikovirtala/ledger").EventTypeDef<"accepted" | "proposed", {
18
+ body_sha256: string;
19
+ }>;
20
+ readonly rejected: import("@nikovirtala/ledger").EventTypeDef<"proposed" | "rejected", Record<string, never>>;
21
+ readonly withdrawn: import("@nikovirtala/ledger").EventTypeDef<"proposed" | "withdrawn", Record<string, never>>;
22
+ readonly deprecated: import("@nikovirtala/ledger").EventTypeDef<"accepted" | "deprecated", Record<string, never>>;
23
+ readonly superseded: import("@nikovirtala/ledger").EventTypeDef<"accepted" | "deprecated" | "superseded", {
24
+ by: string;
25
+ }>;
26
+ readonly noted: import("@nikovirtala/ledger").EventTypeDef<never, {
27
+ text: string;
28
+ }>;
29
+ readonly linked: import("@nikovirtala/ledger").EventTypeDef<never, {
30
+ to: string;
31
+ rel: LinkRel;
32
+ }>;
33
+ readonly scoped: import("@nikovirtala/ledger").EventTypeDef<"accepted" | "deprecated" | "proposed", {
34
+ set: string[];
35
+ }>;
36
+ };
37
+ export type DecisionEvents = typeof decisionEvents;
@@ -0,0 +1,18 @@
1
+ import { type Kind } from "@nikovirtala/ledger";
2
+ import { type DecisionView } from "./kind/project.js";
3
+ import { type DecisionState } from "./kind/reduce.js";
4
+ import { type AdrOptions } from "./kind/rules.js";
5
+ import { type DecisionEvents, type DecisionStatus } from "./kind/schemas.js";
6
+ export type { DecisionView } from "./kind/project.js";
7
+ export { formatDecisionNumber, parseDecisionNumber } from "./kind/project.js";
8
+ export type { DecisionState } from "./kind/reduce.js";
9
+ export type { AdrOptions } from "./kind/rules.js";
10
+ export { DECISION_STATUSES, type DecisionEvents, type DecisionStatus, type LinkRel, REF, } from "./kind/schemas.js";
11
+ /**
12
+ * The decision kind (01:128–194), as imported by other tools through `@nikovirtala/adr/kind`.
13
+ *
14
+ * Decisions are proposed, then accepted (which freezes the body and earns a number on main),
15
+ * rejected or withdrawn; accepted ones can be deprecated or superseded. This module imports only
16
+ * `@nikovirtala/ledger` and `./kind/*`, so importing the kind never loads CLI or MCP code.
17
+ */
18
+ export declare const adrKind: Kind<DecisionStatus, DecisionEvents, DecisionState, DecisionView, AdrOptions>;
@@ -0,0 +1,53 @@
1
+ import { type Finding, type FoldedLogOf, type GitOptions, type LogLayout, type Numbering, type Projection, type ToolLog, type TreeReader } from "@nikovirtala/ledger";
2
+ import { type AdrConfig } from "./config.js";
3
+ import { adrKind, type DecisionView } from "./kind.js";
4
+ /** A decision log opened for the CLI or MCP: ledger's tool log plus adr's config. */
5
+ export interface DecisionLog extends ToolLog {
6
+ readonly adr: AdrConfig;
7
+ }
8
+ /**
9
+ * Opens the decision log (design D3): `--root`, else `adr.toml`'s `[log] root`, else `docs/adr`;
10
+ * read from the `ref` tree, the index or the work tree.
11
+ */
12
+ export declare function openDecisionLog(o: {
13
+ readonly cwd: string;
14
+ readonly root?: string | null;
15
+ readonly ref?: string | null;
16
+ readonly reader?: "worktree" | "index";
17
+ readonly gitOptions?: GitOptions;
18
+ }): Promise<DecisionLog>;
19
+ /** One read of a decision log: everything list, show and the write plans need. */
20
+ export interface DecisionsRead {
21
+ /** The tree that was read, its layout and config; no `Git`, so plans can run on a MemoryTree. */
22
+ readonly tree: TreeReader;
23
+ readonly layout: LogLayout;
24
+ readonly adr: AdrConfig;
25
+ readonly root: string;
26
+ readonly ref: string | null;
27
+ readonly commit: string | null;
28
+ readonly folded: FoldedLogOf<typeof adrKind>;
29
+ readonly projection: Projection<DecisionView>;
30
+ readonly numbering: Numbering;
31
+ /** Load, transition, invariant and relate findings; no diff-based checks. */
32
+ readonly findings: readonly Finding[];
33
+ /** How the log was located (`ToolLog.notes`); `[]` for a MemoryTree read. */
34
+ readonly notes: readonly string[];
35
+ }
36
+ /** `numberLog` on the repository, then `readDecisionsFrom(log.tree, …)`. */
37
+ export declare function readDecisions(log: DecisionLog): Promise<DecisionsRead>;
38
+ /** The git-free core of `readDecisions`; tests pass a MemoryTree and a hand-made `Numbering`. */
39
+ export declare function readDecisionsFrom(tree: TreeReader, o: {
40
+ readonly layout: LogLayout;
41
+ readonly adr: AdrConfig;
42
+ readonly numbering: Numbering;
43
+ readonly ref?: string | null;
44
+ readonly commit?: string | null;
45
+ readonly notes?: readonly string[];
46
+ }): Promise<DecisionsRead>;
47
+ /** Why numbers are unavailable, in words: `shallow clone` or `no main branch`. */
48
+ export declare function unavailableReason(n: Numbering): string;
49
+ /**
50
+ * The id a decision argument names: an id, or a number in any form `parseDecisionNumber` takes.
51
+ * Throws `UsageError` (exit 2) naming the reason when it names nothing.
52
+ */
53
+ export declare function resolveDecision(read: DecisionsRead, input: string): string;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The built-in decision templates, version 1 (design §5.7). `adr new` copies the one it uses into
3
+ * `<root>/templates/<name>.md` on first use, so the team owns it and its versions live in git
4
+ * (D4). Every section is required unless marked optional, and each has a required Scope section
5
+ * (01:311).
6
+ */
7
+ /** The built-in templates by name: the file text `adr new` materializes. */
8
+ export declare const BUILTIN_TEMPLATES: Readonly<Record<string, string>>;
@@ -0,0 +1,10 @@
1
+ import { type Check, type Finding, type VerifyMode } from "@nikovirtala/ledger";
2
+ import type { DecisionLog } from "./log.js";
3
+ /**
4
+ * Every phase-1 check for the log: ledger's mechanical and fold checks with adr's actor policy,
5
+ * and template lint against the templates in the head tree and, for older versions, the history
6
+ * of `historyRef`.
7
+ */
8
+ export declare function adrChecks(log: DecisionLog, historyRef: string | null): readonly Check[];
9
+ /** Verifies the decision log in `mode` (staged, range or full) with `adrChecks`. */
10
+ export declare function verifyDecisions(log: DecisionLog, mode: VerifyMode): Promise<Finding[]>;
@@ -0,0 +1,63 @@
1
+ import { type EventEnvelope, type Finding, type StateHeader } from "@nikovirtala/ledger";
2
+ import type { DecisionStatus, DecisionView } from "./kind.js";
3
+ import type { DecisionsRead } from "./log.js";
4
+ /** The `numbering` key of the read documents. */
5
+ export interface NumberingJson {
6
+ readonly available: boolean;
7
+ readonly reason: "shallow" | "no-main-ref" | null;
8
+ readonly ref: string | null;
9
+ }
10
+ /** `adr list --json` (design §5.5). */
11
+ export interface DecisionListJson {
12
+ readonly format: "adr-list/v1";
13
+ readonly root: string;
14
+ readonly ref: string | null;
15
+ readonly commit: string | null;
16
+ readonly numbering: NumberingJson;
17
+ readonly decisions: readonly DecisionView[];
18
+ /** Newer envelope or schema versions; upgrade adr. */
19
+ readonly unreadable: readonly string[];
20
+ /** First event not `proposed`, or a body with no events; run adr verify. */
21
+ readonly unfoldable: readonly string[];
22
+ readonly findings: readonly Finding[];
23
+ readonly notes: readonly string[];
24
+ }
25
+ /** `adr show <decision> --json` (design §5.5). */
26
+ export interface DecisionShowJson {
27
+ readonly format: "adr-show/v1";
28
+ readonly root: string;
29
+ readonly ref: string | null;
30
+ readonly commit: string | null;
31
+ readonly numbering: NumberingJson;
32
+ readonly header: StateHeader;
33
+ readonly decision: DecisionView;
34
+ readonly body: string | null;
35
+ /** Every valid event in fold order with `history`, else `null`. */
36
+ readonly events: readonly EventEnvelope[] | null;
37
+ readonly findings: readonly Finding[];
38
+ readonly notes: readonly string[];
39
+ }
40
+ /**
41
+ * The `adr-list/v1` document: decisions in list order, filtered by `status` and truncated to
42
+ * `limit` after ordering. `findings` are those of the listed decisions and of the log as a whole.
43
+ */
44
+ export declare function listDecisions(read: DecisionsRead, o?: {
45
+ readonly status?: readonly DecisionStatus[];
46
+ readonly limit?: number;
47
+ }): DecisionListJson;
48
+ /**
49
+ * The `adr-show/v1` document of the decision `id` (resolve it with `resolveDecision` first).
50
+ * Throws `UsageError` for an unknown, unreadable or unfoldable decision.
51
+ */
52
+ export declare function showDecision(read: DecisionsRead, id: string, o?: {
53
+ readonly history?: boolean;
54
+ }): Promise<DecisionShowJson>;
55
+ /**
56
+ * The state header (01:258–259): `<display> (<id>) · <status>`, and for a decision that isn't in
57
+ * force a warning saying what to read instead. `refer` names where to read another decision. CLI
58
+ * default: `display(id)`. Phase 3 MCP passes `id => "adr://decision/" + display(id)`, e.g.
59
+ * `adr://decision/ADR-0012`, or the id when unnumbered.
60
+ */
61
+ export declare function stateHeader(view: DecisionView, read: DecisionsRead, o?: {
62
+ readonly refer?: (id: string) => string;
63
+ }): StateHeader;
@@ -0,0 +1,171 @@
1
+ import { type Actor, type EventEnvelope, type Finding, type Template, type TemplateSource, type Trailer } from "@nikovirtala/ledger";
2
+ import { type DecisionView } from "./kind.js";
3
+ import { type DecisionLog, type DecisionsRead } from "./log.js";
4
+ /** `adr new|accept|supersede --json` (design §5.5). */
5
+ export interface WriteResultJson {
6
+ readonly format: "adr-write/v1";
7
+ readonly command: "new" | "accept" | "supersede";
8
+ readonly ok: boolean;
9
+ /**
10
+ * The decision after the write; before it when `ok` is false (`null` for a refused `new`).
11
+ * After a commit it is read again from the log, so an acceptance committed on the main ref
12
+ * carries its number; otherwise `number` is `null` until the acceptance lands on main.
13
+ */
14
+ readonly decision: DecisionView | null;
15
+ /** Each decision superseded by this write, after it (read again after a commit, like `decision`). */
16
+ readonly affected: readonly DecisionView[];
17
+ /** Repo-relative paths this command wrote, in write order. */
18
+ readonly written: readonly string[];
19
+ readonly commit: string | null;
20
+ /** Refusal findings when `ok` is false; the draft's template lint for `new` (informational). */
21
+ readonly findings: readonly Finding[];
22
+ /** How the log was located (`ToolLog.notes`). */
23
+ readonly notes: readonly string[];
24
+ }
25
+ export interface ProposeInput {
26
+ readonly title: string;
27
+ /** Default `[log] default_template`. */
28
+ readonly template?: string;
29
+ /** Section id → markdown. */
30
+ readonly sections?: Readonly<Record<string, string>>;
31
+ /** Decisions this one is meant to replace, as ids or numbers. */
32
+ readonly supersedes?: readonly string[];
33
+ readonly actor: Actor;
34
+ }
35
+ /** What a plan needs besides the read: a clock, randomness and templates. */
36
+ export interface PlanContext {
37
+ /** Clock for `nextEventIdentity`. */
38
+ readonly now: () => number;
39
+ /** ULID and subject-id randomness. */
40
+ readonly random?: (buf: Uint8Array) => void;
41
+ /** Drafts' recorded template versions. */
42
+ readonly templates: TemplateSource;
43
+ /** Built-in template texts by name (§5.7), for `new`. */
44
+ readonly builtins: Readonly<Record<string, string>>;
45
+ }
46
+ /** Everything one write command does, computed without touching git or the disk. */
47
+ export interface WritePlan {
48
+ readonly command: "new" | "accept" | "supersede" | "event";
49
+ readonly subject: string;
50
+ /** New files, repo-relative path → bytes, in write order: body, materialized template, events. */
51
+ readonly files: Readonly<Record<string, Uint8Array>>;
52
+ readonly events: readonly EventEnvelope[];
53
+ /** Paths to stage: every new file, plus the existing body for accept. */
54
+ readonly stage: readonly string[];
55
+ /** Subject ids involved (D6): the subject, every superseded target, and `by` for supersede. Sorted. */
56
+ readonly involved: readonly string[];
57
+ /** Per involved subject: its body, its events dir and its recorded template. Sorted, deduplicated. */
58
+ readonly commitScope: readonly string[];
59
+ /** The events directories in `commitScope`, sorted; the rest of `commitScope` are file paths. */
60
+ readonly eventDirs: readonly string[];
61
+ /** For new: the body path, the rendered bytes and the template, for the editor step. */
62
+ readonly draft: {
63
+ readonly path: string;
64
+ readonly rendered: Uint8Array;
65
+ readonly template: Template;
66
+ } | null;
67
+ /** The D6 commit message. */
68
+ readonly message: string;
69
+ /** One `ADR`/`ADR-Event` pair per plan event, in write order. */
70
+ readonly trailers: readonly Trailer[];
71
+ /** Views after the write, computed on `overlayTree(read.tree, files)`. */
72
+ readonly decision: DecisionView;
73
+ readonly affected: readonly DecisionView[];
74
+ /** Informational (new: the draft's template lint). */
75
+ readonly findings: readonly Finding[];
76
+ }
77
+ export type PlanResult = {
78
+ readonly ok: true;
79
+ readonly plan: WritePlan;
80
+ } | {
81
+ readonly ok: false;
82
+ readonly decision: DecisionView | null;
83
+ readonly findings: readonly Finding[];
84
+ };
85
+ /** Plans `adr new`: a rendered body, a materialized template if needed, and `proposed`. */
86
+ export declare function planPropose(read: DecisionsRead, input: ProposeInput, c: PlanContext): Promise<PlanResult>;
87
+ /** Plans `adr accept`: `accepted` with the body hash, and `superseded` on each declared target. */
88
+ export declare function planAccept(read: DecisionsRead, input: {
89
+ readonly id: string;
90
+ readonly actor: Actor;
91
+ }, c: PlanContext): Promise<PlanResult>;
92
+ /** Plans `adr supersede <id> --by <by>`: one `superseded` event on `id`. */
93
+ export declare function planSupersede(read: DecisionsRead, input: {
94
+ readonly id: string;
95
+ readonly by: string;
96
+ readonly reason?: string | null;
97
+ readonly actor: Actor;
98
+ }, c: PlanContext): Promise<PlanResult>;
99
+ /**
100
+ * Plans any one event on an existing decision: the state machine and the event's validation
101
+ * decide, then the precheck. Phase 2's reject, withdraw, deprecate, note, link and scope wrap it.
102
+ */
103
+ export declare function planEvent(read: DecisionsRead, input: {
104
+ readonly subject: string;
105
+ readonly type: string;
106
+ readonly data: Record<string, unknown>;
107
+ readonly reason?: string | null;
108
+ readonly actor: Actor;
109
+ }, c: PlanContext): Promise<PlanResult>;
110
+ /** What the editor step decided (§5.4 step 4a). */
111
+ export interface AfterStage {
112
+ /** Draft lint findings to report instead of `plan.findings`; `null` keeps `plan.findings`. */
113
+ readonly findings: readonly Finding[] | null;
114
+ /** `false` skips the commit: the files stay written and staged, and `commit` is `null`. */
115
+ readonly commit: boolean;
116
+ }
117
+ /**
118
+ * Applies a plan (§5.4): refuses a commit whose scope has unstaged or needed untracked paths,
119
+ * writes the files (removing them again if a write fails), stages them, runs `afterStage`, and
120
+ * commits `plan.stage` plus the involved subjects' already-staged files with exact trailers.
121
+ */
122
+ export declare function applyPlan(log: DecisionLog, plan: WritePlan, o: {
123
+ readonly commit: boolean;
124
+ readonly afterStage?: () => Promise<AfterStage>;
125
+ }): Promise<{
126
+ written: string[];
127
+ commit: string | null;
128
+ findings: readonly Finding[];
129
+ }>;
130
+ /**
131
+ * The clock, the randomness and `applyPlan` the write functions use. Only tests pass their own
132
+ * (for example an `apply` that fails once); the default is the real ones.
133
+ */
134
+ export interface WriteDeps {
135
+ readonly now: () => number;
136
+ readonly random?: (buf: Uint8Array) => void;
137
+ readonly apply: typeof applyPlan;
138
+ }
139
+ /**
140
+ * `adr new`: renders a draft, writes the body, any materialized template and the `proposed`
141
+ * event, stages them, and commits with `commit` (default `[policy] auto_commit`).
142
+ *
143
+ * `edit` (CLI only; MCP never passes it) runs between staging and committing, on the absolute
144
+ * body path. It resolves to `null` when the editor exited 0, else to a note for the user (spawn
145
+ * error, exit status). `onNote` receives the notes about a skipped commit or a removed body,
146
+ * without the "not committed: " prefix the CLI adds when a commit was requested.
147
+ */
148
+ export declare function proposeDecision(log: DecisionLog, input: ProposeInput, o?: {
149
+ readonly commit?: boolean;
150
+ readonly edit?: (absBodyPath: string) => Promise<string | null>;
151
+ readonly onNote?: (note: string) => void;
152
+ }, deps?: WriteDeps): Promise<WriteResultJson>;
153
+ /**
154
+ * `adr accept`: lints the draft, hashes the body, writes `accepted` and a `superseded` event on
155
+ * each declared target, stages them with the body, and commits with `commit`.
156
+ */
157
+ export declare function acceptDecision(log: DecisionLog, input: {
158
+ readonly id: string;
159
+ readonly actor: Actor;
160
+ }, o?: {
161
+ readonly commit?: boolean;
162
+ }, deps?: WriteDeps): Promise<WriteResultJson>;
163
+ /** `adr supersede <id> --by <by>`: writes `superseded`, stages it, and commits with `commit`. */
164
+ export declare function supersedeDecision(log: DecisionLog, input: {
165
+ readonly id: string;
166
+ readonly by: string;
167
+ readonly reason?: string | null;
168
+ readonly actor: Actor;
169
+ }, o?: {
170
+ readonly commit?: boolean;
171
+ }, deps?: WriteDeps): Promise<WriteResultJson>;