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,27 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { readConfig, requireRoot } from '../core/config.js';
4
+ import { nextDecisionNumber, writeRecord } from '../core/repository.js';
5
+ import { decisionTemplate } from '../core/templates.js';
6
+ import { slugify } from '../core/slug.js';
7
+ export function decideCommand(title, cwd) {
8
+ const trimmed = title.trim();
9
+ if (trimmed.length === 0) {
10
+ throw new Error('title must not be empty');
11
+ }
12
+ if (/^\d{4}\s+/.test(trimmed)) {
13
+ throw new Error('title must not start with a four-digit number; OpenADR assigns decision numbers');
14
+ }
15
+ const root = requireRoot(cwd);
16
+ const number = nextDecisionNumber(root);
17
+ const padded = String(number).padStart(4, '0');
18
+ const fileName = `${padded}-${slugify(trimmed)}.md`;
19
+ const path = join(root, 'adr', 'decisions', fileName);
20
+ if (existsSync(path)) {
21
+ throw new Error(`decision already exists: adr/decisions/${fileName}`);
22
+ }
23
+ const content = decisionTemplate(number, trimmed, readConfig(root).context);
24
+ writeRecord(root, 'decisions', fileName, content);
25
+ return `created adr/decisions/${fileName}\n\nfill in the draft and validate it with:\n openadr validate ${padded}`;
26
+ }
27
+ //# sourceMappingURL=decide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decide.js","sourceRoot":"","sources":["../../src/commands/decide.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,GAAW;IACtD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAC;IACrG,CAAC;IACD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IACtD,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,0CAA0C,QAAQ,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;IAC5E,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClD,OAAO,yBAAyB,QAAQ,mEAAmE,MAAM,EAAE,CAAC;AACtH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function initCommand(targetDir: string, toolsValue?: string): string;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAc1E"}
@@ -0,0 +1,18 @@
1
+ import { initRepository } from '../core/repository.js';
2
+ import { integrationSummary, parseTools, writeToolIntegrations } from '../core/tool-integrations.js';
3
+ export function initCommand(targetDir, toolsValue) {
4
+ const tools = parseTools(toolsValue);
5
+ const { root, created } = initRepository(targetDir, tools);
6
+ const lines = created.map((path) => ` created ${path}`);
7
+ const integrations = writeToolIntegrations(root, tools);
8
+ return [
9
+ `OpenADR initialized at ${root}`,
10
+ ...lines,
11
+ ...integrationSummary(root, integrations),
12
+ '',
13
+ 'Next:',
14
+ ' openadr propose "your first decision" # start a proposal',
15
+ ' openadr decide "use sqlite for sessions" # record an accepted decision',
16
+ ].join('\n');
17
+ }
18
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErG,MAAM,UAAU,WAAW,CAAC,SAAiB,EAAE,UAAmB;IAChE,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;IACzD,MAAM,YAAY,GAAG,qBAAqB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACxD,OAAO;QACL,0BAA0B,IAAI,EAAE;QAChC,GAAG,KAAK;QACR,GAAG,kBAAkB,CAAC,IAAI,EAAE,YAAY,CAAC;QACzC,EAAE;QACF,OAAO;QACP,8DAA8D;QAC9D,0EAA0E;KAC3E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function instructionsCommand(cwd: string, asJson?: boolean): string;
2
+ //# sourceMappingURL=instructions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../src/commands/instructions.ts"],"names":[],"mappings":"AAIA,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,MAAM,CA8DvE"}
@@ -0,0 +1,60 @@
1
+ import { findRoot } from '../core/config.js';
2
+ import { listRecords } from '../core/repository.js';
3
+ import { formatIssues, validateRepository } from '../core/validate.js';
4
+ export function instructionsCommand(cwd, asJson = false) {
5
+ const root = findRoot(cwd);
6
+ if (root === undefined) {
7
+ const output = [
8
+ 'No OpenADR repository found.',
9
+ '',
10
+ 'Next:',
11
+ ' openadr init',
12
+ ' openadr propose "your first decision"',
13
+ ].join('\n');
14
+ return asJson
15
+ ? JSON.stringify({ step: 'init', message: output }, null, 2)
16
+ : output;
17
+ }
18
+ const issues = validateRepository(root);
19
+ if (issues.length > 0) {
20
+ const output = [
21
+ 'The repository has validation issues. Fix them before creating more records.',
22
+ '',
23
+ formatIssues(issues),
24
+ '',
25
+ 'Next:',
26
+ ' openadr validate',
27
+ ].join('\n');
28
+ return asJson
29
+ ? JSON.stringify({ step: 'fix-validation', issues, message: output }, null, 2)
30
+ : output;
31
+ }
32
+ const records = listRecords(root);
33
+ const proposed = records.filter((record) => record.folder === 'proposed');
34
+ if (proposed.length > 0) {
35
+ const names = proposed.map((record) => record.fileName).join(', ');
36
+ const output = [
37
+ `${proposed.length} proposal${proposed.length === 1 ? '' : 's'} waiting for a decision:`,
38
+ ` ${names}`,
39
+ '',
40
+ 'Next:',
41
+ ' openadr show <name>',
42
+ ' openadr accept <name> # accept it',
43
+ ' openadr reject <name> --reason "..." # reject it',
44
+ ].join('\n');
45
+ return asJson
46
+ ? JSON.stringify({ step: 'decide', pending: proposed.map((record) => record.fileName), message: output }, null, 2)
47
+ : output;
48
+ }
49
+ const output = [
50
+ 'No proposals waiting.',
51
+ '',
52
+ 'Next:',
53
+ ' openadr propose "your next decision"',
54
+ ' openadr decide "an already-made decision"',
55
+ ].join('\n');
56
+ return asJson
57
+ ? JSON.stringify({ step: 'propose', message: output }, null, 2)
58
+ : output;
59
+ }
60
+ //# sourceMappingURL=instructions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instructions.js","sourceRoot":"","sources":["../../src/commands/instructions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEvE,MAAM,UAAU,mBAAmB,CAAC,GAAW,EAAE,MAAM,GAAG,KAAK;IAC7D,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG;YACb,8BAA8B;YAC9B,EAAE;YACF,OAAO;YACP,gBAAgB;YAChB,yCAAyC;SAC1C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,OAAO,MAAM;YACX,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5D,CAAC,CAAC,MAAM,CAAC;IACb,CAAC;IAED,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG;YACb,8EAA8E;YAC9E,EAAE;YACF,YAAY,CAAC,MAAM,CAAC;YACpB,EAAE;YACF,OAAO;YACP,oBAAoB;SACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,OAAO,MAAM;YACX,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9E,CAAC,CAAC,MAAM,CAAC;IACb,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;IAC1E,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,MAAM,GAAG;YACb,GAAG,QAAQ,CAAC,MAAM,YAAY,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,0BAA0B;YACxF,KAAK,KAAK,EAAE;YACZ,EAAE;YACF,OAAO;YACP,uBAAuB;YACvB,0CAA0C;YAC1C,qDAAqD;SACtD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,OAAO,MAAM;YACX,CAAC,CAAC,IAAI,CAAC,SAAS,CACZ,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EACvF,IAAI,EACJ,CAAC,CACF;YACH,CAAC,CAAC,MAAM,CAAC;IACb,CAAC;IAED,MAAM,MAAM,GAAG;QACb,uBAAuB;QACvB,EAAE;QACF,OAAO;QACP,wCAAwC;QACxC,6CAA6C;KAC9C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,OAAO,MAAM;QACX,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,CAAC,CAAC,MAAM,CAAC;AACb,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function listCommand(cwd: string, asJson?: boolean): string;
2
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,MAAM,CAyC/D"}
@@ -0,0 +1,43 @@
1
+ import { requireRoot } from '../core/config.js';
2
+ import { displayName, listRecords, relativePath } from '../core/repository.js';
3
+ export function listCommand(cwd, asJson = false) {
4
+ const root = requireRoot(cwd);
5
+ const records = listRecords(root);
6
+ if (asJson) {
7
+ const payload = records.map((record) => ({
8
+ folder: record.folder,
9
+ status: record.status,
10
+ number: record.number,
11
+ title: record.title,
12
+ fileName: record.fileName,
13
+ path: relativePath(record),
14
+ rejectionReason: record.rejectionReason,
15
+ supersededBy: record.supersededBy,
16
+ }));
17
+ return JSON.stringify(payload, null, 2);
18
+ }
19
+ if (records.length === 0) {
20
+ return 'no ADRs yet — start one with "openadr propose <title>" or "openadr decide <title>"';
21
+ }
22
+ const labels = {
23
+ decisions: 'Accepted',
24
+ proposed: 'Proposed',
25
+ rejected: 'Rejected',
26
+ };
27
+ const lines = [];
28
+ for (const folder of ['decisions', 'proposed', 'rejected']) {
29
+ const group = records.filter((record) => record.folder === folder);
30
+ if (group.length === 0)
31
+ continue;
32
+ lines.push(labels[folder] ?? folder, '');
33
+ for (const record of group) {
34
+ const supersededNote = record.status === 'superseded' && record.supersededBy !== undefined
35
+ ? ` [superseded by ${String(record.supersededBy).padStart(4, '0')}]`
36
+ : '';
37
+ lines.push(` ${displayName(record)}${supersededNote} (${relativePath(record)})`);
38
+ }
39
+ lines.push('');
40
+ }
41
+ return lines.join('\n').trimEnd();
42
+ }
43
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE/E,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,MAAM,GAAG,KAAK;IACrD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAElC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACvC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC;YAC1B,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,YAAY,EAAE,MAAM,CAAC,YAAY;SAClC,CAAC,CAAC,CAAC;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,oFAAoF,CAAC;IAC9F,CAAC;IAED,MAAM,MAAM,GAA2B;QACrC,SAAS,EAAE,UAAU;QACrB,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,UAAU;KACrB,CAAC;IACF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,MAAM,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,UAAU,CAAU,EAAE,CAAC;QACpE,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACnE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACjC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;QACzC,KAAK,MAAM,MAAM,IAAI,KAAK,EAAE,CAAC;YAC3B,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,KAAK,YAAY,IAAI,MAAM,CAAC,YAAY,KAAK,SAAS;gBACxF,CAAC,CAAC,oBAAoB,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG;gBACrE,CAAC,CAAC,EAAE,CAAC;YACP,KAAK,CAAC,IAAI,CAAC,KAAK,WAAW,CAAC,MAAM,CAAC,GAAG,cAAc,MAAM,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACrF,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function proposeCommand(title: string, cwd: string): string;
2
+ //# sourceMappingURL=propose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"propose.d.ts","sourceRoot":"","sources":["../../src/commands/propose.ts"],"names":[],"mappings":"AAOA,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAkBjE"}
@@ -0,0 +1,26 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { readConfig, requireRoot } from '../core/config.js';
4
+ import { todayStamp, writeRecord } from '../core/repository.js';
5
+ import { proposalTemplate } from '../core/templates.js';
6
+ import { slugify } from '../core/slug.js';
7
+ export function proposeCommand(title, cwd) {
8
+ const trimmed = title.trim();
9
+ if (trimmed.length === 0) {
10
+ throw new Error('title must not be empty');
11
+ }
12
+ if (/^\d{4}\s+/.test(trimmed)) {
13
+ throw new Error('title must not start with a four-digit number; OpenADR assigns decision numbers');
14
+ }
15
+ const root = requireRoot(cwd);
16
+ const slug = slugify(trimmed);
17
+ const fileName = `${todayStamp()}-${slug}.md`;
18
+ const path = join(root, 'adr', 'proposed', fileName);
19
+ if (existsSync(path)) {
20
+ throw new Error(`proposal already exists: adr/proposed/${fileName}`);
21
+ }
22
+ const content = proposalTemplate(trimmed, readConfig(root).context);
23
+ writeRecord(root, 'proposed', fileName, content);
24
+ return `created adr/proposed/${fileName}\n\nvalidate it with:\n openadr validate ${fileName}`;
25
+ }
26
+ //# sourceMappingURL=propose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"propose.js","sourceRoot":"","sources":["../../src/commands/propose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,GAAW;IACvD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAC;IACrG,CAAC;IACD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,QAAQ,GAAG,GAAG,UAAU,EAAE,IAAI,IAAI,KAAK,CAAC;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IACrD,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,yCAAyC,QAAQ,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;IACpE,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACjD,OAAO,wBAAwB,QAAQ,6CAA6C,QAAQ,EAAE,CAAC;AACjG,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function rejectCommand(query: string, reason: string, cwd: string): string;
2
+ //# sourceMappingURL=reject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reject.d.ts","sourceRoot":"","sources":["../../src/commands/reject.ts"],"names":[],"mappings":"AAKA,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAsBhF"}
@@ -0,0 +1,26 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { requireRoot } from '../core/config.js';
4
+ import { removeRecord, resolveRecord, writeRecord } from '../core/repository.js';
5
+ export function rejectCommand(query, reason, cwd) {
6
+ const root = requireRoot(cwd);
7
+ const record = resolveRecord(root, query);
8
+ if (record.folder !== 'proposed') {
9
+ throw new Error(`"${query}" is not a proposal (it is in ${record.folder})`);
10
+ }
11
+ const trimmedReason = reason.trim();
12
+ if (trimmedReason.length === 0) {
13
+ throw new Error('a rejection reason is required: openadr reject <name> --reason "..."');
14
+ }
15
+ const path = join(root, 'adr', 'rejected', record.fileName);
16
+ if (existsSync(path)) {
17
+ throw new Error(`rejected record already exists: adr/rejected/${record.fileName}`);
18
+ }
19
+ const original = readFileSync(record.path, 'utf8');
20
+ const lines = original.split(/\r?\n/);
21
+ lines[1] = `Status: rejected — ${trimmedReason}`;
22
+ writeRecord(root, 'rejected', record.fileName, lines.join('\n'));
23
+ removeRecord(record);
24
+ return `rejected adr/proposed/${record.fileName} as adr/rejected/${record.fileName}`;
25
+ }
26
+ //# sourceMappingURL=reject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reject.js","sourceRoot":"","sources":["../../src/commands/reject.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEjF,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,MAAc,EAAE,GAAW;IACtE,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,iCAAiC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IACpC,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;IAC1F,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5D,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,gDAAgD,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtC,KAAK,CAAC,CAAC,CAAC,GAAG,sBAAsB,aAAa,EAAE,CAAC;IACjD,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACjE,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,OAAO,yBAAyB,MAAM,CAAC,QAAQ,oBAAoB,MAAM,CAAC,QAAQ,EAAE,CAAC;AACvF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function showCommand(query: string, cwd: string): string;
2
+ //# sourceMappingURL=show.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../src/commands/show.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAM9D"}
@@ -0,0 +1,11 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { requireRoot } from '../core/config.js';
3
+ import { relativePath, resolveRecord } from '../core/repository.js';
4
+ export function showCommand(query, cwd) {
5
+ const root = requireRoot(cwd);
6
+ const record = resolveRecord(root, query);
7
+ const path = relativePath(record);
8
+ const content = readFileSync(record.path, 'utf8');
9
+ return `${path}\n${'='.repeat(path.length)}\n\n${content.trimEnd()}`;
10
+ }
11
+ //# sourceMappingURL=show.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/commands/show.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEpE,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,GAAW;IACpD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAClD,OAAO,GAAG,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;AACvE,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface StatusResult {
2
+ valid: boolean;
3
+ output: string;
4
+ }
5
+ export declare function statusCommand(cwd: string, asJson?: boolean): StatusResult;
6
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,YAAY,CA0CvE"}
@@ -0,0 +1,46 @@
1
+ import { requireRoot } from '../core/config.js';
2
+ import { listRecords } from '../core/repository.js';
3
+ import { formatIssues, validateRepository } from '../core/validate.js';
4
+ export function statusCommand(cwd, asJson = false) {
5
+ const root = requireRoot(cwd);
6
+ const issues = validateRepository(root);
7
+ let records = [];
8
+ try {
9
+ records = listRecords(root);
10
+ }
11
+ catch {
12
+ // Validation already reported the parse failure above; keep counts empty.
13
+ }
14
+ const counts = { accepted: 0, superseded: 0, proposed: 0, rejected: 0 };
15
+ for (const record of records) {
16
+ if (record.folder === 'decisions') {
17
+ if (record.status === 'superseded')
18
+ counts.superseded += 1;
19
+ else
20
+ counts.accepted += 1;
21
+ }
22
+ else if (record.folder === 'proposed')
23
+ counts.proposed += 1;
24
+ else if (record.folder === 'rejected')
25
+ counts.rejected += 1;
26
+ }
27
+ if (asJson) {
28
+ return {
29
+ valid: issues.length === 0,
30
+ output: JSON.stringify({
31
+ valid: issues.length === 0,
32
+ counts,
33
+ issues,
34
+ }, null, 2),
35
+ };
36
+ }
37
+ const lines = ['Lifecycle', ''];
38
+ lines.push(` accepted: ${counts.accepted}`);
39
+ lines.push(` superseded: ${counts.superseded}`);
40
+ lines.push(` proposed: ${counts.proposed}`);
41
+ lines.push(` rejected: ${counts.rejected}`);
42
+ lines.push('');
43
+ lines.push(issues.length === 0 ? 'validation: OK' : `validation: ${formatIssues(issues)}`);
44
+ return { valid: issues.length === 0, output: lines.join('\n') };
45
+ }
46
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAOvE,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,MAAM,GAAG,KAAK;IACvD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,OAAO,GAAgB,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;IAC5E,CAAC;IAED,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACxE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY;gBAAE,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC;;gBACtD,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;QAC5B,CAAC;aAAM,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU;YAAE,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;aACzD,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU;YAAE,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;YAC1B,MAAM,EAAE,IAAI,CAAC,SAAS,CACpB;gBACE,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;gBAC1B,MAAM;gBACN,MAAM;aACP,EACD,IAAI,EACJ,CAAC,CACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAChC,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IACjD,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,eAAe,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3F,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAClE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function supersedeCommand(query: string, byQuery: string, cwd: string): string;
2
+ //# sourceMappingURL=supersede.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supersede.d.ts","sourceRoot":"","sources":["../../src/commands/supersede.ts"],"names":[],"mappings":"AAIA,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAmCpF"}
@@ -0,0 +1,36 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { requireRoot } from '../core/config.js';
3
+ import { resolveRecord, writeRecord } from '../core/repository.js';
4
+ export function supersedeCommand(query, byQuery, cwd) {
5
+ const root = requireRoot(cwd);
6
+ const record = resolveRecord(root, query);
7
+ if (record.folder !== 'decisions') {
8
+ throw new Error(`"${query}" is not an accepted decision (it is in ${record.folder})`);
9
+ }
10
+ if (record.status === 'superseded') {
11
+ const current = String(record.supersededBy ?? 0).padStart(4, '0');
12
+ throw new Error(`"${query}" is already superseded by ${current}; supersede that decision instead if it is now outdated`);
13
+ }
14
+ const replacement = resolveRecord(root, byQuery);
15
+ if (replacement.folder !== 'decisions') {
16
+ throw new Error(`"--by ${byQuery}" is not an accepted decision (it is in ${replacement.folder})`);
17
+ }
18
+ if (replacement.path === record.path) {
19
+ throw new Error('a decision cannot supersede itself');
20
+ }
21
+ if (replacement.status === 'superseded') {
22
+ throw new Error(`"--by ${byQuery}" is itself superseded; superseding with it would create a dangling chain`);
23
+ }
24
+ if (replacement.number === undefined) {
25
+ throw new Error(`"--by ${byQuery}" has no decision number`);
26
+ }
27
+ const original = readFileSync(record.path, 'utf8');
28
+ const lines = original.split(/\r?\n/);
29
+ if (lines[1] !== 'Status: accepted') {
30
+ throw new Error(`unexpected status line "${lines[1] ?? ''}" in ${record.fileName}`);
31
+ }
32
+ lines[1] = `Status: superseded by ${String(replacement.number).padStart(4, '0')}`;
33
+ writeRecord(root, 'decisions', record.fileName, lines.join('\n'));
34
+ return `superseded adr/decisions/${record.fileName} by adr/decisions/${replacement.fileName}`;
35
+ }
36
+ //# sourceMappingURL=supersede.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supersede.js","sourceRoot":"","sources":["../../src/commands/supersede.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEnE,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,OAAe,EAAE,GAAW;IAC1E,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,2CAA2C,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACxF,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAClE,MAAM,IAAI,KAAK,CACb,IAAI,KAAK,8BAA8B,OAAO,yDAAyD,CACxG,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACjD,IAAI,WAAW,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,SAAS,OAAO,2CAA2C,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IACpG,CAAC;IACD,IAAI,WAAW,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,SAAS,OAAO,2EAA2E,CAAC,CAAC;IAC/G,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,SAAS,OAAO,0BAA0B,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,kBAAkB,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,2BAA2B,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,KAAK,CAAC,CAAC,CAAC,GAAG,yBAAyB,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IAClF,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAClE,OAAO,4BAA4B,MAAM,CAAC,QAAQ,qBAAqB,WAAW,CAAC,QAAQ,EAAE,CAAC;AAChG,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function updateCommand(cwd: string, toolsValue?: string): string;
2
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAStE"}
@@ -0,0 +1,13 @@
1
+ import { readConfig, requireRoot } from '../core/config.js';
2
+ import { integrationSummary, parseTools, writeToolIntegrations } from '../core/tool-integrations.js';
3
+ export function updateCommand(cwd, toolsValue) {
4
+ const root = requireRoot(cwd);
5
+ const config = readConfig(root);
6
+ const tools = parseTools(toolsValue ?? (config.tools ?? []).join(','));
7
+ const integrations = writeToolIntegrations(root, tools);
8
+ return [
9
+ `updated AI tool integrations at ${root}`,
10
+ ...integrationSummary(root, integrations),
11
+ ].join('\n');
12
+ }
13
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErG,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,UAAmB;IAC5D,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACvE,MAAM,YAAY,GAAG,qBAAqB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACxD,OAAO;QACL,mCAAmC,IAAI,EAAE;QACzC,GAAG,kBAAkB,CAAC,IAAI,EAAE,YAAY,CAAC;KAC1C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface ValidateResult {
2
+ valid: boolean;
3
+ output: string;
4
+ }
5
+ export declare function validateCommand(cwd: string, query?: string, asJson?: boolean): ValidateResult;
6
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,cAAc,CAkC3F"}
@@ -0,0 +1,38 @@
1
+ import { requireRoot } from '../core/config.js';
2
+ import { relativePath, resolveRecord } from '../core/repository.js';
3
+ import { formatIssues, validateRecord, validateRepository } from '../core/validate.js';
4
+ export function validateCommand(cwd, query, asJson = false) {
5
+ const root = requireRoot(cwd);
6
+ if (query !== undefined && query.trim().length > 0) {
7
+ const record = resolveRecord(root, query);
8
+ const issues = validateRecord(root, record);
9
+ if (asJson) {
10
+ return {
11
+ valid: issues.length === 0,
12
+ output: JSON.stringify({
13
+ path: relativePath(record),
14
+ valid: issues.length === 0,
15
+ issues,
16
+ }, null, 2),
17
+ };
18
+ }
19
+ return {
20
+ valid: issues.length === 0,
21
+ output: issues.length === 0
22
+ ? `${relativePath(record)}: OK`
23
+ : formatIssues(issues),
24
+ };
25
+ }
26
+ const issues = validateRepository(root);
27
+ if (asJson) {
28
+ return {
29
+ valid: issues.length === 0,
30
+ output: JSON.stringify({ valid: issues.length === 0, issues }, null, 2),
31
+ };
32
+ }
33
+ return {
34
+ valid: issues.length === 0,
35
+ output: issues.length === 0 ? 'OK' : formatIssues(issues),
36
+ };
37
+ }
38
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAOvF,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,KAAc,EAAE,MAAM,GAAG,KAAK;IACzE,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,MAAM,EAAE,CAAC;YACX,OAAO;gBACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;gBAC1B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;oBACrB,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC;oBAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;oBAC1B,MAAM;iBACP,EAAE,IAAI,EAAE,CAAC,CAAC;aACZ,CAAC;QACJ,CAAC;QACD,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;YAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;gBACzB,CAAC,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,MAAM;gBAC/B,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC;SACzB,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,MAAM,EAAE,CAAC;QACX,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;YAC1B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;SACxE,CAAC;IACJ,CAAC;IACD,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC;KAC1D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ export type AdrStatus = 'proposed' | 'accepted' | 'rejected' | 'superseded';
2
+ export type AdrFolder = 'proposed' | 'decisions' | 'rejected';
3
+ export interface AdrSection {
4
+ heading: string;
5
+ body: string;
6
+ }
7
+ export interface AdrRecord {
8
+ folder: AdrFolder;
9
+ path: string;
10
+ fileName: string;
11
+ title: string;
12
+ status: AdrStatus;
13
+ rejectionReason?: string;
14
+ /** For superseded decisions: the number of the decision that replaced this one. */
15
+ supersededBy?: number;
16
+ number?: number;
17
+ sections: AdrSection[];
18
+ }
19
+ export declare class AdrFormatError extends Error {
20
+ readonly path: string;
21
+ constructor(message: string, path: string);
22
+ }
23
+ export declare function statusForFolder(folder: AdrFolder): AdrStatus;
24
+ export declare function folderForStatus(status: AdrStatus): AdrFolder;
25
+ export declare function section(record: AdrRecord, heading: string): string | undefined;
26
+ export declare function hasMeaningfulBody(body: string | undefined): boolean;
27
+ /**
28
+ * Parse a single ADR markdown file into its structured parts.
29
+ *
30
+ * The format is deliberately plain Markdown, with no front matter:
31
+ *
32
+ * # ADR: <title or "NNNN Title">
33
+ * Status: proposed | accepted | rejected — <reason>
34
+ * <blank line>
35
+ * ## Problem
36
+ * ...
37
+ */
38
+ export declare function parseAdrFile(filePath: string): AdrRecord;
39
+ export declare function renderAdr(options: {
40
+ title: string;
41
+ status: string;
42
+ sections: AdrSection[];
43
+ }): string;
44
+ //# sourceMappingURL=adr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adr.d.ts","sourceRoot":"","sources":["../../src/core/adr.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,YAAY,CAAC;AAC5E,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,CAAC;AAE9D,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,SAAS,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mFAAmF;IACnF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,qBAAa,cAAe,SAAQ,KAAK;aAGrB,IAAI,EAAE,MAAM;gBAD5B,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM;CAK/B;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAS5D;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAU5D;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE9E;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAInE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CA6ExD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB,GAAG,MAAM,CAWT"}