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.
- package/LICENSE +21 -0
- package/README.md +150 -0
- package/README.zh.md +131 -0
- package/bin/openadr.js +5 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +176 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/accept.d.ts +2 -0
- package/dist/commands/accept.d.ts.map +1 -0
- package/dist/commands/accept.js +33 -0
- package/dist/commands/accept.js.map +1 -0
- package/dist/commands/completion.d.ts +2 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +40 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +23 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/decide.d.ts +2 -0
- package/dist/commands/decide.d.ts.map +1 -0
- package/dist/commands/decide.js +27 -0
- package/dist/commands/decide.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +18 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/instructions.d.ts +2 -0
- package/dist/commands/instructions.d.ts.map +1 -0
- package/dist/commands/instructions.js +60 -0
- package/dist/commands/instructions.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +43 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/propose.d.ts +2 -0
- package/dist/commands/propose.d.ts.map +1 -0
- package/dist/commands/propose.js +26 -0
- package/dist/commands/propose.js.map +1 -0
- package/dist/commands/reject.d.ts +2 -0
- package/dist/commands/reject.d.ts.map +1 -0
- package/dist/commands/reject.js +26 -0
- package/dist/commands/reject.js.map +1 -0
- package/dist/commands/show.d.ts +2 -0
- package/dist/commands/show.d.ts.map +1 -0
- package/dist/commands/show.js +11 -0
- package/dist/commands/show.js.map +1 -0
- package/dist/commands/status.d.ts +6 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +46 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/supersede.d.ts +2 -0
- package/dist/commands/supersede.d.ts.map +1 -0
- package/dist/commands/supersede.js +36 -0
- package/dist/commands/supersede.js.map +1 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +13 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.d.ts +6 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +38 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/core/adr.d.ts +44 -0
- package/dist/core/adr.d.ts.map +1 -0
- package/dist/core/adr.js +143 -0
- package/dist/core/adr.js.map +1 -0
- package/dist/core/config.d.ts +22 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +63 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/repository.d.ts +19 -0
- package/dist/core/repository.d.ts.map +1 -0
- package/dist/core/repository.js +190 -0
- package/dist/core/repository.js.map +1 -0
- package/dist/core/slug.d.ts +10 -0
- package/dist/core/slug.d.ts.map +1 -0
- package/dist/core/slug.js +19 -0
- package/dist/core/slug.js.map +1 -0
- package/dist/core/templates.d.ts +11 -0
- package/dist/core/templates.d.ts.map +1 -0
- package/dist/core/templates.js +126 -0
- package/dist/core/templates.js.map +1 -0
- package/dist/core/tool-integrations.d.ts +16 -0
- package/dist/core/tool-integrations.d.ts.map +1 -0
- package/dist/core/tool-integrations.js +256 -0
- package/dist/core/tool-integrations.js.map +1 -0
- package/dist/core/validate.d.ts +9 -0
- package/dist/core/validate.d.ts.map +1 -0
- package/dist/core/validate.js +183 -0
- package/dist/core/validate.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- 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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|