@nikovirtala/adr 0.3.0 → 0.4.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.
@@ -4,7 +4,7 @@ import { type DecisionLog, type DecisionsRead } from "./log.js";
4
4
  /** `adr <write command> --json` (design §5.5, §6.1). */
5
5
  export interface WriteResultJson {
6
6
  readonly format: "adr-write/v1";
7
- readonly command: "new" | "accept" | "supersede" | "reject" | "withdraw" | "deprecate" | "note" | "link" | "scope";
7
+ readonly command: "new" | "accept" | "supersede" | "reject" | "withdraw" | "deprecate" | "note" | "link" | "scope" | "update";
8
8
  readonly ok: boolean;
9
9
  /**
10
10
  * The decision after the write; before it when `ok` is false (`null` for a refused `new`).
@@ -68,6 +68,14 @@ export interface WritePlan {
68
68
  readonly subject: string;
69
69
  /** New files, repo-relative path → bytes, in write order: body, materialized template, events. */
70
70
  readonly files: Readonly<Record<string, Uint8Array>>;
71
+ /**
72
+ * Existing files to replace, path → the new bytes and the bytes the plan read; written only if
73
+ * the file still holds `expected` (a draft update).
74
+ */
75
+ readonly replace?: Readonly<Record<string, {
76
+ readonly bytes: Uint8Array;
77
+ readonly expected: Uint8Array;
78
+ }>>;
71
79
  readonly events: readonly EventEnvelope[];
72
80
  /** Paths to stage: every new file, plus the existing body for accept. */
73
81
  readonly stage: readonly string[];
@@ -126,6 +134,21 @@ export type PlanResult = {
126
134
  export declare function planPropose(read: DecisionsRead, input: ProposeInput, c: PlanContext, o?: {
127
135
  readonly refuseIncomplete?: boolean;
128
136
  }): Promise<PlanResult>;
137
+ /** Input of a draft update: the decision and the sections to replace (section id → markdown). */
138
+ export interface UpdateDraftInput {
139
+ readonly id: string;
140
+ readonly sections: Readonly<Record<string, string>>;
141
+ }
142
+ /**
143
+ * Plans a draft update (design §6.6): the given sections of a proposed decision's body replaced in
144
+ * place, every other line kept, written only if the body still holds the bytes read. Refused
145
+ * (`ok: false`) when the decision isn't proposed or its body or template version is missing or
146
+ * unreadable, and with `refuseIncomplete` when the new draft fails its template lint. An unknown
147
+ * section, a missing heading or a heading in the content is a `UsageError`.
148
+ */
149
+ export declare function planUpdateDraft(read: DecisionsRead, input: UpdateDraftInput, c: PlanContext, o?: {
150
+ readonly refuseIncomplete?: boolean;
151
+ }): Promise<PlanResult>;
129
152
  /** Plans `adr accept`: `accepted` with the body hash, and `superseded` on each declared target. */
130
153
  export declare function planAccept(read: DecisionsRead, input: {
131
154
  readonly id: string;
@@ -250,6 +273,13 @@ export interface AppliedPlan {
250
273
  * 2b D5): the batch is already in the log, so a rerun is refused, writes nothing or duplicates it.
251
274
  */
252
275
  export declare const WRITE_RERUN = "Don't run the command again: the log already holds the change, so a rerun would be refused, do nothing, or write it a second time.";
276
+ /**
277
+ * Applies a plan (§5.4): refuses a commit whose scope has unstaged or needed untracked paths,
278
+ * writes the files (removing them again if a write fails), stages them, runs `afterStage`, and
279
+ * commits `plan.stage` plus the involved subjects' already-staged files with exact trailers. A
280
+ * failed `git commit` throws `CommitFailedError` with the manual command (design 2b D5) and the
281
+ * notes made so far.
282
+ */
253
283
  export declare function applyPlan(log: DecisionLog, plan: WritePlan, o: {
254
284
  readonly commit: boolean;
255
285
  /** The commit message, without trailers; required when committing. */
@@ -336,6 +366,14 @@ export declare function linkDecision(log: DecisionLog, input: LinkInput, o?: Wri
336
366
  * and commits with `commit`. An unchanged set writes nothing.
337
367
  */
338
368
  export declare function scopeDecision(log: DecisionLog, input: ScopeInput, o?: WriteOptions, deps?: WriteDeps): Promise<WriteResultJson>;
369
+ /**
370
+ * Replaces sections of a proposed decision's draft (design §6.6), stages the body, and commits
371
+ * with `commit` (default `[policy] auto_commit`). A body with unstaged changes is a `UsageError`,
372
+ * so nobody's unsaved edit is folded into this write; a body changed between plan and write is
373
+ * `FileChangedError`. A commit is never made of a draft that fails its template lint: it is
374
+ * refused (`ok: false`, nothing written), as for `proposeDecision` without an editor.
375
+ */
376
+ export declare function updateDraft(log: DecisionLog, input: UpdateDraftInput, o?: WriteOptions, deps?: WriteDeps): Promise<WriteResultJson>;
339
377
  /**
340
378
  * `adr scope [<decision>] --follow-renames` (design §6.8): rewrites the scope globs of the given
341
379
  * decision, or of every decision, after the renames staged against `HEAD`, and stages one
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nikovirtala/adr",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Architecture decision records kept as event logs in git: frozen bodies, computed status and supersession chains. CLI and library.",
5
5
  "keywords": [
6
6
  "adr",
@@ -45,7 +45,10 @@
45
45
  "provenance": true
46
46
  },
47
47
  "dependencies": {
48
- "@nikovirtala/ledger": "^0.5.0"
48
+ "@nikovirtala/ledger": "^0.6.0"
49
+ },
50
+ "devDependencies": {
51
+ "@modelcontextprotocol/sdk": "1.32.2"
49
52
  },
50
53
  "scripts": {
51
54
  "build": "tsdown",