adr-kit 0.2.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.
Files changed (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/README.zh.md +131 -0
  4. package/bin/openadr.js +5 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +176 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/commands/accept.d.ts +2 -0
  10. package/dist/commands/accept.d.ts.map +1 -0
  11. package/dist/commands/accept.js +33 -0
  12. package/dist/commands/accept.js.map +1 -0
  13. package/dist/commands/completion.d.ts +2 -0
  14. package/dist/commands/completion.d.ts.map +1 -0
  15. package/dist/commands/completion.js +40 -0
  16. package/dist/commands/completion.js.map +1 -0
  17. package/dist/commands/config.d.ts +2 -0
  18. package/dist/commands/config.d.ts.map +1 -0
  19. package/dist/commands/config.js +23 -0
  20. package/dist/commands/config.js.map +1 -0
  21. package/dist/commands/decide.d.ts +2 -0
  22. package/dist/commands/decide.d.ts.map +1 -0
  23. package/dist/commands/decide.js +27 -0
  24. package/dist/commands/decide.js.map +1 -0
  25. package/dist/commands/init.d.ts +2 -0
  26. package/dist/commands/init.d.ts.map +1 -0
  27. package/dist/commands/init.js +18 -0
  28. package/dist/commands/init.js.map +1 -0
  29. package/dist/commands/instructions.d.ts +2 -0
  30. package/dist/commands/instructions.d.ts.map +1 -0
  31. package/dist/commands/instructions.js +60 -0
  32. package/dist/commands/instructions.js.map +1 -0
  33. package/dist/commands/list.d.ts +2 -0
  34. package/dist/commands/list.d.ts.map +1 -0
  35. package/dist/commands/list.js +43 -0
  36. package/dist/commands/list.js.map +1 -0
  37. package/dist/commands/propose.d.ts +2 -0
  38. package/dist/commands/propose.d.ts.map +1 -0
  39. package/dist/commands/propose.js +26 -0
  40. package/dist/commands/propose.js.map +1 -0
  41. package/dist/commands/reject.d.ts +2 -0
  42. package/dist/commands/reject.d.ts.map +1 -0
  43. package/dist/commands/reject.js +26 -0
  44. package/dist/commands/reject.js.map +1 -0
  45. package/dist/commands/show.d.ts +2 -0
  46. package/dist/commands/show.d.ts.map +1 -0
  47. package/dist/commands/show.js +11 -0
  48. package/dist/commands/show.js.map +1 -0
  49. package/dist/commands/status.d.ts +6 -0
  50. package/dist/commands/status.d.ts.map +1 -0
  51. package/dist/commands/status.js +46 -0
  52. package/dist/commands/status.js.map +1 -0
  53. package/dist/commands/supersede.d.ts +2 -0
  54. package/dist/commands/supersede.d.ts.map +1 -0
  55. package/dist/commands/supersede.js +36 -0
  56. package/dist/commands/supersede.js.map +1 -0
  57. package/dist/commands/update.d.ts +2 -0
  58. package/dist/commands/update.d.ts.map +1 -0
  59. package/dist/commands/update.js +13 -0
  60. package/dist/commands/update.js.map +1 -0
  61. package/dist/commands/validate.d.ts +6 -0
  62. package/dist/commands/validate.d.ts.map +1 -0
  63. package/dist/commands/validate.js +38 -0
  64. package/dist/commands/validate.js.map +1 -0
  65. package/dist/core/adr.d.ts +44 -0
  66. package/dist/core/adr.d.ts.map +1 -0
  67. package/dist/core/adr.js +143 -0
  68. package/dist/core/adr.js.map +1 -0
  69. package/dist/core/config.d.ts +22 -0
  70. package/dist/core/config.d.ts.map +1 -0
  71. package/dist/core/config.js +63 -0
  72. package/dist/core/config.js.map +1 -0
  73. package/dist/core/repository.d.ts +19 -0
  74. package/dist/core/repository.d.ts.map +1 -0
  75. package/dist/core/repository.js +190 -0
  76. package/dist/core/repository.js.map +1 -0
  77. package/dist/core/slug.d.ts +10 -0
  78. package/dist/core/slug.d.ts.map +1 -0
  79. package/dist/core/slug.js +19 -0
  80. package/dist/core/slug.js.map +1 -0
  81. package/dist/core/templates.d.ts +11 -0
  82. package/dist/core/templates.d.ts.map +1 -0
  83. package/dist/core/templates.js +126 -0
  84. package/dist/core/templates.js.map +1 -0
  85. package/dist/core/tool-integrations.d.ts +16 -0
  86. package/dist/core/tool-integrations.d.ts.map +1 -0
  87. package/dist/core/tool-integrations.js +256 -0
  88. package/dist/core/tool-integrations.js.map +1 -0
  89. package/dist/core/validate.d.ts +9 -0
  90. package/dist/core/validate.d.ts.map +1 -0
  91. package/dist/core/validate.js +183 -0
  92. package/dist/core/validate.js.map +1 -0
  93. package/dist/version.d.ts +2 -0
  94. package/dist/version.d.ts.map +1 -0
  95. package/dist/version.js +2 -0
  96. package/dist/version.js.map +1 -0
  97. package/package.json +49 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/core/templates.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,SAAS,YAAY,CAAC,OAAuB;IAC3C,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACnC,oCAAoC;IACpC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5D,OAAO;EACP,IAAI;;CAEL,CAAC;AACF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,OAAgB;IAC9D,OAAO,UAAU,KAAK;;;EAGtB,YAAY,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;CAoBtB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,KAAa,EAAE,OAAgB;IAC9E,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC/C,OAAO,UAAU,MAAM,IAAI,KAAK;;;EAGhC,YAAY,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;CAgBtB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,OAAO,UAAU,KAAK;qBACH,MAAM;;;;;;;;;;;;;CAa1B,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAmB,EAAE,MAAc;IACpE,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,WAAW,CAAC,QAAQ,EAAE,yBAAyB,CAAC,CAAC;IACtE,MAAM,UAAU,GAAG,WAAW,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAE7C,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,YAAY,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,EAAE,UAAU,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,YAAY,CAAC,IAAI,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC/C,OAAO,UAAU,MAAM,IAAI,QAAQ,CAAC,KAAK;;;;;EAKzC,OAAO,CAAC,IAAI,EAAE,IAAI,wBAAwB;;;;EAI1C,QAAQ,CAAC,IAAI,EAAE,IAAI,yBAAyB;;;;EAI5C,YAAY,CAAC,IAAI,EAAE,IAAI,6BAA6B;;;;EAIpD,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AAC9B,CAAC;AAED,SAAS,WAAW,CAAC,MAAiB,EAAE,OAAe;IACrD,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,KAAK,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;AAC/F,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface ToolIntegration {
2
+ tool: string;
3
+ path: string;
4
+ }
5
+ export declare const SUPPORTED_TOOLS: readonly ["claude", "codex", "cursor", "github-copilot", "agents"];
6
+ export type ToolId = (typeof SUPPORTED_TOOLS)[number];
7
+ export declare const WORKFLOWS: {
8
+ name: string;
9
+ description: string;
10
+ body: string;
11
+ }[];
12
+ export declare function parseTools(value: string | undefined): ToolId[];
13
+ export declare function writeToolIntegrations(root: string, tools: ToolId[]): ToolIntegration[];
14
+ export declare function removeToolIntegrations(root: string, tools: ToolId[]): void;
15
+ export declare function integrationSummary(root: string, created: ToolIntegration[]): string[];
16
+ //# sourceMappingURL=tool-integrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-integrations.d.ts","sourceRoot":"","sources":["../../src/core/tool-integrations.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,eAAe,oEAAqE,CAAC;AAClG,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAYtD,eAAO,MAAM,SAAS;;;;GA2LrB,CAAC;AAEF,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAwB9D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,CAqBtF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAU1E;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,CAErF"}
@@ -0,0 +1,256 @@
1
+ import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { join, relative } from 'node:path';
3
+ export const SUPPORTED_TOOLS = ['claude', 'codex', 'cursor', 'github-copilot', 'agents'];
4
+ const TOOL_COMMAND_DIR = {
5
+ claude: '.claude/commands',
6
+ codex: '.codex/commands',
7
+ cursor: '.cursor/commands',
8
+ 'github-copilot': '.github/prompts',
9
+ agents: '.agents/commands',
10
+ };
11
+ // The bodies mirror skills/<name>/SKILL.md one-to-one; the sync is
12
+ // machine-checked in test/integrations.test.ts.
13
+ export const WORKFLOWS = [
14
+ {
15
+ name: 'openadr-init',
16
+ description: 'Use when initializing OpenADR in a repository or when the agent cannot find an adr/ directory.',
17
+ body: `# OpenADR Init
18
+
19
+ ## Overview
20
+
21
+ Create an \`adr/\` repository in the target directory.
22
+
23
+ ## Steps
24
+
25
+ 1. Decide the target directory (default: current working directory).
26
+ 2. Run:
27
+
28
+ \`\`\`bash
29
+ openadr init [path]
30
+ \`\`\`
31
+
32
+ 3. Confirm the output lists \`adr/config.yaml\`, \`adr/decisions\`,
33
+ \`adr/proposed\`, and \`adr/rejected\`.
34
+
35
+ ## Rules
36
+
37
+ - Never create \`adr/\` directories by hand; use the CLI so the config and
38
+ README stay canonical.
39
+ - After init, the next action is usually \`openadr propose "<title>"\`.`,
40
+ },
41
+ {
42
+ name: 'openadr-propose',
43
+ description: 'Use when starting a new architecture decision that still needs review before it is accepted.',
44
+ body: `# OpenADR Propose
45
+
46
+ ## Overview
47
+
48
+ Create a proposed ADR in \`adr/proposed/\`. The proposal is a draft and is
49
+ expected to fail \`openadr validate\` until every required section is filled.
50
+
51
+ ## Steps
52
+
53
+ 1. Run:
54
+
55
+ \`\`\`bash
56
+ openadr propose "<title>"
57
+ \`\`\`
58
+
59
+ 2. Edit the created file. Fill every section with real content:
60
+ \`## Problem\`, \`## Proposal\`, \`## Alternatives considered\`,
61
+ \`## Acceptance criteria\`, \`## Risks\`.
62
+ 3. Run \`openadr validate\` until it returns OK.
63
+
64
+ ## Rules
65
+
66
+ - Do not skip \`## Alternatives considered\`. A proposal without alternatives
67
+ is invalid by design.
68
+ - Keep the status line exactly \`Status: proposed\`.`,
69
+ },
70
+ {
71
+ name: 'openadr-decide',
72
+ description: 'Use when recording a decision that is already accepted and does not need a proposal phase.',
73
+ body: `# OpenADR Decide
74
+
75
+ ## Overview
76
+
77
+ Create an accepted decision draft directly in \`adr/decisions/\` with the
78
+ next \`NNNN\` number.
79
+
80
+ ## Steps
81
+
82
+ 1. Run:
83
+
84
+ \`\`\`bash
85
+ openadr decide "<title>"
86
+ \`\`\`
87
+
88
+ 2. Edit the created file and fill \`## Problem\`, \`## Decision\`,
89
+ \`## Alternatives considered\`, and \`## Consequences\`.
90
+ 3. Run \`openadr validate <NNNN>\` until it returns OK.
91
+
92
+ ## Rules
93
+
94
+ - Accepted decisions must not contain \`## Proposal\`, \`## Acceptance
95
+ criteria\`, or \`## Risks\` sections.
96
+ - \`openadr accept\` is the better path when a proposal already exists.`,
97
+ },
98
+ {
99
+ name: 'openadr-validate',
100
+ description: 'Use when checking whether ADR files follow the OpenADR format, especially before accepting a proposal or committing.',
101
+ body: `# OpenADR Validate
102
+
103
+ ## Overview
104
+
105
+ Run the machine checks for one record or the whole repository.
106
+
107
+ ## Steps
108
+
109
+ \`\`\`bash
110
+ openadr validate [name] [--json]
111
+ \`\`\`
112
+
113
+ - With no \`name\`, the whole repository is validated.
114
+ - \`name\` resolves by title, file name, or decision number.
115
+
116
+ ## Rules
117
+
118
+ - Treat any non-OK output as a blocker for \`openadr accept\`.
119
+ - A fresh draft is expected to fail until the required sections are
120
+ filled in; fix the exact issue printed rather than deleting sections.`,
121
+ },
122
+ {
123
+ name: 'openadr-accept',
124
+ description: 'Use when a proposed ADR is complete and validated, and the team has decided to accept it.',
125
+ body: `# OpenADR Accept
126
+
127
+ ## Overview
128
+
129
+ Accept a proposal. The CLI validates the proposal, assigns the next
130
+ \`NNNN\` decision number, rewrites \`## Proposal\` to \`## Decision\`, folds
131
+ \`Acceptance criteria\` and \`Risks\` into \`## Consequences\`, and moves the
132
+ file from \`adr/proposed/\` to \`adr/decisions/\`.
133
+
134
+ ## Steps
135
+
136
+ 1. Run \`openadr validate\` and confirm the proposal is OK.
137
+ 2. Run:
138
+
139
+ \`\`\`bash
140
+ openadr accept "<name>"
141
+ \`\`\`
142
+
143
+ 3. Confirm the output names the new \`adr/decisions/NNNN-*.md\` file.
144
+
145
+ ## Rules
146
+
147
+ - Never accept an invalid proposal; the command refuses.
148
+ - Review the generated \`## Consequences\` after accepting.`,
149
+ },
150
+ {
151
+ name: 'openadr-reject',
152
+ description: 'Use when a proposed ADR should be declined and frozen for future reference.',
153
+ body: `# OpenADR Reject
154
+
155
+ ## Overview
156
+
157
+ Reject a proposal. The CLI moves the file from \`adr/proposed/\` to
158
+ \`adr/rejected/\` and rewrites the status line with the reason.
159
+
160
+ ## Steps
161
+
162
+ \`\`\`bash
163
+ openadr reject "<name>" --reason "<why it was rejected>"
164
+ \`\`\`
165
+
166
+ ## Rules
167
+
168
+ - Always provide a concrete reason; the command refuses an empty one.
169
+ - A rejected record is frozen history. Do not edit it afterwards.`,
170
+ },
171
+ {
172
+ name: 'openadr-supersede',
173
+ description: 'Use when an accepted decision is replaced by a newer accepted decision and must be retired without deleting history.',
174
+ body: `# OpenADR Supersede
175
+
176
+ ## Overview
177
+
178
+ Mark an accepted decision as superseded. The CLI rewrites only its status
179
+ line to \`Status: superseded by NNNN\` and leaves the record in
180
+ \`adr/decisions/\` as frozen history.
181
+
182
+ ## Steps
183
+
184
+ 1. Record the replacement first (\`openadr decide\` or \`openadr propose\` +
185
+ \`openadr accept\`), and make sure it validates.
186
+ 2. Run:
187
+
188
+ \`\`\`bash
189
+ openadr supersede "<old name or number>" --by "<new name or number>"
190
+ \`\`\`
191
+
192
+ ## Rules
193
+
194
+ - \`--by\` must reference an existing accepted decision that is not itself
195
+ superseded; the command refuses dangling chains.
196
+ - Never hand-edit a superseded record afterwards; it is history.
197
+ - Mention what it supersedes in the new decision's \`## Problem\` section so
198
+ the causal link survives in prose.`,
199
+ },
200
+ ];
201
+ export function parseTools(value) {
202
+ if (value === undefined || value.trim() === '' || value.trim() === 'none') {
203
+ return [];
204
+ }
205
+ const requested = value
206
+ .split(',')
207
+ .map((entry) => entry.trim())
208
+ .filter((entry) => entry.length > 0);
209
+ if (requested.includes('all')) {
210
+ return [...SUPPORTED_TOOLS];
211
+ }
212
+ const tools = [];
213
+ for (const entry of requested) {
214
+ if (SUPPORTED_TOOLS.includes(entry)) {
215
+ tools.push(entry);
216
+ }
217
+ else {
218
+ throw new Error(`unknown tool "${entry}". Supported tools: ${SUPPORTED_TOOLS.join(', ')}, all, none`);
219
+ }
220
+ }
221
+ return [...new Set(tools)];
222
+ }
223
+ export function writeToolIntegrations(root, tools) {
224
+ const created = [];
225
+ for (const tool of tools) {
226
+ const dir = join(root, TOOL_COMMAND_DIR[tool]);
227
+ mkdirSync(dir, { recursive: true });
228
+ for (const workflow of WORKFLOWS) {
229
+ const fileName = `${workflow.name}.md`;
230
+ const path = join(dir, fileName);
231
+ writeFileSync(path, `---
232
+ description: ${workflow.description}
233
+ ---
234
+
235
+ ${workflow.body}
236
+ `);
237
+ created.push({ tool, path });
238
+ }
239
+ }
240
+ return created;
241
+ }
242
+ export function removeToolIntegrations(root, tools) {
243
+ for (const tool of tools) {
244
+ const dir = join(root, TOOL_COMMAND_DIR[tool]);
245
+ for (const workflow of WORKFLOWS) {
246
+ const path = join(dir, `${workflow.name}.md`);
247
+ if (existsSync(path)) {
248
+ rmSync(path);
249
+ }
250
+ }
251
+ }
252
+ }
253
+ export function integrationSummary(root, created) {
254
+ return created.map((item) => ` created ${relative(root, item.path)} (${item.tool})`);
255
+ }
256
+ //# sourceMappingURL=tool-integrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-integrations.js","sourceRoot":"","sources":["../../src/core/tool-integrations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { type AdrRecord } from './adr.js';
2
+ export interface ValidationIssue {
3
+ path: string;
4
+ message: string;
5
+ }
6
+ export declare function validateRecord(root: string, record: AdrRecord): ValidationIssue[];
7
+ export declare function validateRepository(root: string): ValidationIssue[];
8
+ export declare function formatIssues(issues: ValidationIssue[]): string;
9
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/core/validate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAI9E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAOD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,eAAe,EAAE,CA2GjF;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CAmElE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAI9D"}
@@ -0,0 +1,183 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { join, relative } from 'node:path';
3
+ import { hasMeaningfulBody, statusForFolder } from './adr.js';
4
+ import { ADR_DIR, CONFIG_FILE, readConfig } from './config.js';
5
+ import { FOLDERS, listRecords } from './repository.js';
6
+ const DECISION_REQUIRED = ['Problem', 'Decision', 'Alternatives considered', 'Consequences'];
7
+ const PROPOSED_REQUIRED = ['Problem', 'Proposal', 'Alternatives considered', 'Acceptance criteria', 'Risks'];
8
+ const REJECTED_REQUIRED = ['Problem', 'Proposal', 'Alternatives considered'];
9
+ const PROPOSAL_ERA_HEADINGS = ['Proposal', 'Acceptance criteria', 'Risks', 'Plan', 'Migration plan'];
10
+ export function validateRecord(root, record) {
11
+ const issues = [];
12
+ const path = relative(root, record.path);
13
+ const statusMatchesFolder = record.folder === 'decisions'
14
+ ? record.status === 'accepted' || record.status === 'superseded'
15
+ : record.status === statusForFolder(record.folder);
16
+ if (!statusMatchesFolder) {
17
+ issues.push({
18
+ path,
19
+ message: `status "${record.status}" does not match folder "${record.folder}"`,
20
+ });
21
+ }
22
+ if (record.status === 'superseded') {
23
+ if (record.supersededBy === undefined) {
24
+ issues.push({ path, message: 'superseded status must reference a decision number' });
25
+ }
26
+ else if (record.supersededBy === record.number) {
27
+ issues.push({ path, message: 'a decision cannot supersede itself' });
28
+ }
29
+ }
30
+ if (record.folder === 'decisions') {
31
+ if (!/^\d{4}-[a-z0-9\u4e00-\u9fff-]+\.md$/.test(record.fileName)) {
32
+ issues.push({ path, message: 'decision file name must be "NNNN-slug.md"' });
33
+ }
34
+ if (record.number === undefined) {
35
+ issues.push({ path, message: 'accepted decision title must be "# ADR: NNNN <title>"' });
36
+ }
37
+ else {
38
+ const padded = String(record.number).padStart(4, '0');
39
+ if (!record.fileName.startsWith(`${padded}-`)) {
40
+ issues.push({ path, message: `file name number must match title number ${padded}` });
41
+ }
42
+ }
43
+ }
44
+ else {
45
+ const datePattern = /^(\d{4})-(\d{2})-(\d{2})-[a-z0-9\u4e00-\u9fff-]+\.md$/;
46
+ const match = record.fileName.match(datePattern);
47
+ if (match === null) {
48
+ issues.push({ path, message: 'file name must be "YYYY-MM-DD-slug.md"' });
49
+ }
50
+ else {
51
+ const year = Number(match[1]);
52
+ const month = Number(match[2]);
53
+ const day = Number(match[3]);
54
+ const date = new Date(year, month - 1, day);
55
+ if (date.getFullYear() !== year ||
56
+ date.getMonth() !== month - 1 ||
57
+ date.getDate() !== day) {
58
+ issues.push({ path, message: 'file name contains an invalid calendar date' });
59
+ }
60
+ }
61
+ }
62
+ const required = record.folder === 'decisions'
63
+ ? DECISION_REQUIRED
64
+ : record.folder === 'proposed'
65
+ ? PROPOSED_REQUIRED
66
+ : REJECTED_REQUIRED;
67
+ const headings = new Set(record.sections.map((section) => section.heading));
68
+ for (const heading of required) {
69
+ if (!headings.has(heading)) {
70
+ issues.push({ path, message: `missing required section "## ${heading}"` });
71
+ }
72
+ }
73
+ const meaningfulHeadings = record.folder === 'decisions'
74
+ ? ['Problem', 'Decision']
75
+ : ['Problem', 'Proposal'];
76
+ for (const heading of meaningfulHeadings) {
77
+ const body = record.sections.find((section) => section.heading === heading)?.body;
78
+ if (!hasMeaningfulBody(body)) {
79
+ issues.push({
80
+ path,
81
+ message: `section "## ${heading}" must contain written content`,
82
+ });
83
+ }
84
+ }
85
+ const seen = new Set();
86
+ for (const section of record.sections) {
87
+ if (seen.has(section.heading)) {
88
+ issues.push({ path, message: `duplicate section "## ${section.heading}"` });
89
+ }
90
+ seen.add(section.heading);
91
+ }
92
+ if (record.folder === 'decisions') {
93
+ for (const heading of PROPOSAL_ERA_HEADINGS) {
94
+ if (headings.has(heading)) {
95
+ issues.push({
96
+ path,
97
+ message: `accepted decision must not contain proposal-era section "## ${heading}"`,
98
+ });
99
+ }
100
+ }
101
+ }
102
+ if (!hasMeaningfulBody(record.sections.find((section) => section.heading === 'Alternatives considered')?.body)) {
103
+ issues.push({
104
+ path,
105
+ message: 'section "## Alternatives considered" must contain at least one written alternative',
106
+ });
107
+ }
108
+ return issues;
109
+ }
110
+ export function validateRepository(root) {
111
+ const issues = [];
112
+ const configFile = join(root, ADR_DIR, CONFIG_FILE);
113
+ if (!existsSync(configFile)) {
114
+ issues.push({ path: `${ADR_DIR}/${CONFIG_FILE}`, message: 'missing config file' });
115
+ }
116
+ else {
117
+ try {
118
+ readConfig(root);
119
+ }
120
+ catch (error) {
121
+ issues.push({
122
+ path: `${ADR_DIR}/${CONFIG_FILE}`,
123
+ message: error instanceof Error ? error.message : String(error),
124
+ });
125
+ }
126
+ }
127
+ for (const folder of FOLDERS) {
128
+ if (!existsSync(join(root, ADR_DIR, folder))) {
129
+ issues.push({ path: `${ADR_DIR}/${folder}`, message: 'missing folder' });
130
+ }
131
+ }
132
+ let records;
133
+ try {
134
+ records = listRecords(root);
135
+ }
136
+ catch (error) {
137
+ issues.push({
138
+ path: ADR_DIR,
139
+ message: error instanceof Error ? error.message : String(error),
140
+ });
141
+ return issues;
142
+ }
143
+ const decisionRecords = new Map();
144
+ for (const record of records) {
145
+ issues.push(...validateRecord(root, record));
146
+ if (record.folder === 'decisions' && record.number !== undefined) {
147
+ if (decisionRecords.has(record.number)) {
148
+ issues.push({
149
+ path: relative(root, record.path),
150
+ message: `duplicate decision number ${String(record.number).padStart(4, '0')}`,
151
+ });
152
+ }
153
+ decisionRecords.set(record.number, record);
154
+ }
155
+ }
156
+ for (const record of records) {
157
+ if (record.supersededBy === undefined)
158
+ continue;
159
+ const path = relative(root, record.path);
160
+ const padded = String(record.supersededBy).padStart(4, '0');
161
+ const target = decisionRecords.get(record.supersededBy);
162
+ if (target === undefined) {
163
+ issues.push({
164
+ path,
165
+ message: `"superseded by ${padded}" references a missing decision`,
166
+ });
167
+ }
168
+ else if (target.status === 'superseded') {
169
+ issues.push({
170
+ path,
171
+ message: `"superseded by ${padded}" references a superseded decision; supersede that decision instead`,
172
+ });
173
+ }
174
+ }
175
+ return issues;
176
+ }
177
+ export function formatIssues(issues) {
178
+ if (issues.length === 0)
179
+ return 'OK';
180
+ const lines = issues.map((issue) => ` ${issue.path}: ${issue.message}`);
181
+ return `found ${issues.length} issue${issues.length === 1 ? '' : 's'}:\n${lines.join('\n')}`;
182
+ }
183
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/core/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const VERSION = "0.2.0";
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const VERSION = '0.2.0';
2
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "adr-kit",
3
+ "version": "0.2.0",
4
+ "description": "Open Architecture Decision Records \u2014 a lightweight ADR workflow for humans and agents.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "engines": {
8
+ "node": ">=20.19"
9
+ },
10
+ "bin": {
11
+ "openadr": "bin/openadr.js"
12
+ },
13
+ "files": [
14
+ "bin",
15
+ "dist",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc -p tsconfig.json",
21
+ "typecheck": "tsc -p tsconfig.json --noEmit",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "test:coverage": "vitest run --coverage",
25
+ "changeset": "changeset",
26
+ "release": "changeset publish",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "dependencies": {
30
+ "yaml": "^2.8.3"
31
+ },
32
+ "devDependencies": {
33
+ "@changesets/cli": "^3.0.0",
34
+ "@types/node": "^24.0.0",
35
+ "@vitest/coverage-v8": "^3.2.7",
36
+ "typescript": "^5.9.0",
37
+ "vitest": "^3.2.0"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "keywords": [
43
+ "adr",
44
+ "architecture-decision-records",
45
+ "cli",
46
+ "ai",
47
+ "development"
48
+ ]
49
+ }