@vpxa/aikit 0.1.73 → 0.1.75

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 (142) hide show
  1. package/package.json +9 -1
  2. package/packages/cli/dist/index.js +2 -2
  3. package/packages/cli/dist/{init-D_OGLUN1.js → init-CuRXmyD9.js} +4 -4
  4. package/packages/cli/dist/scaffold-WMQ2uQ48.js +2 -0
  5. package/packages/cli/dist/{templates-DJ7EC5vw.js → templates-ArdAVWoY.js} +13 -3
  6. package/packages/cli/dist/user-vbJwa7x2.js +5 -0
  7. package/packages/dashboard/dist/assets/index-C6D-PCp0.js.map +1 -1
  8. package/packages/flows/dist/index.d.ts +29 -0
  9. package/packages/flows/dist/index.js +1 -1
  10. package/packages/server/dist/index.js +1 -1
  11. package/packages/server/dist/{server-B9Mx1aK-.js → server-CVhVH5cT.js} +127 -127
  12. package/packages/tools/dist/index.d.ts +19 -1
  13. package/packages/tools/dist/index.js +39 -39
  14. package/scaffold/dist/adapters/claude-code.mjs +4 -0
  15. package/scaffold/dist/adapters/copilot.mjs +75 -0
  16. package/scaffold/dist/adapters/flows.mjs +1 -0
  17. package/scaffold/dist/adapters/skills.mjs +1 -0
  18. package/scaffold/dist/compiled/flows-data.mjs +1429 -0
  19. package/scaffold/dist/compiled/skills-data.mjs +9951 -0
  20. package/scaffold/dist/definitions/agents.mjs +9 -0
  21. package/scaffold/{definitions → dist/definitions}/bodies.mjs +6 -229
  22. package/scaffold/dist/definitions/exclusions.mjs +1 -0
  23. package/scaffold/dist/definitions/hooks.mjs +1 -0
  24. package/scaffold/dist/definitions/models.mjs +1 -0
  25. package/scaffold/dist/definitions/plugins.mjs +1 -0
  26. package/scaffold/{definitions → dist/definitions}/prompts.mjs +9 -149
  27. package/scaffold/{definitions → dist/definitions}/protocols.mjs +9 -37
  28. package/scaffold/dist/definitions/tools.mjs +1 -0
  29. package/packages/cli/dist/scaffold-CJwkHf-q.js +0 -2
  30. package/packages/cli/dist/user-BEmVW8Tp.js +0 -5
  31. package/scaffold/adapters/claude-code.mjs +0 -73
  32. package/scaffold/adapters/copilot.mjs +0 -292
  33. package/scaffold/definitions/agents.mjs +0 -266
  34. package/scaffold/definitions/hooks.mjs +0 -43
  35. package/scaffold/definitions/models.mjs +0 -84
  36. package/scaffold/definitions/plugins.mjs +0 -147
  37. package/scaffold/definitions/tools.mjs +0 -250
  38. package/scaffold/flows/_epilogue/steps/docs-sync/README.md +0 -120
  39. package/scaffold/flows/aikit-advanced/README.md +0 -70
  40. package/scaffold/flows/aikit-advanced/flow.json +0 -69
  41. package/scaffold/flows/aikit-advanced/steps/design/README.md +0 -178
  42. package/scaffold/flows/aikit-advanced/steps/execute/README.md +0 -145
  43. package/scaffold/flows/aikit-advanced/steps/plan/README.md +0 -122
  44. package/scaffold/flows/aikit-advanced/steps/spec/README.md +0 -121
  45. package/scaffold/flows/aikit-advanced/steps/task/README.md +0 -119
  46. package/scaffold/flows/aikit-advanced/steps/verify/README.md +0 -145
  47. package/scaffold/flows/aikit-basic/README.md +0 -51
  48. package/scaffold/flows/aikit-basic/flow.json +0 -45
  49. package/scaffold/flows/aikit-basic/steps/assess/README.md +0 -109
  50. package/scaffold/flows/aikit-basic/steps/design/README.md +0 -116
  51. package/scaffold/flows/aikit-basic/steps/implement/README.md +0 -131
  52. package/scaffold/flows/aikit-basic/steps/verify/README.md +0 -123
  53. package/scaffold/general/agents/Architect-Reviewer-Alpha.agent.md +0 -132
  54. package/scaffold/general/agents/Architect-Reviewer-Beta.agent.md +0 -132
  55. package/scaffold/general/agents/Code-Reviewer-Alpha.agent.md +0 -112
  56. package/scaffold/general/agents/Code-Reviewer-Beta.agent.md +0 -112
  57. package/scaffold/general/agents/Debugger.agent.md +0 -412
  58. package/scaffold/general/agents/Documenter.agent.md +0 -468
  59. package/scaffold/general/agents/Explorer.agent.md +0 -76
  60. package/scaffold/general/agents/Frontend.agent.md +0 -440
  61. package/scaffold/general/agents/Implementer.agent.md +0 -425
  62. package/scaffold/general/agents/Orchestrator.agent.md +0 -452
  63. package/scaffold/general/agents/Planner.agent.md +0 -481
  64. package/scaffold/general/agents/README.md +0 -57
  65. package/scaffold/general/agents/Refactor.agent.md +0 -435
  66. package/scaffold/general/agents/Researcher-Alpha.agent.md +0 -151
  67. package/scaffold/general/agents/Researcher-Beta.agent.md +0 -152
  68. package/scaffold/general/agents/Researcher-Delta.agent.md +0 -153
  69. package/scaffold/general/agents/Researcher-Gamma.agent.md +0 -152
  70. package/scaffold/general/agents/Security.agent.md +0 -433
  71. package/scaffold/general/agents/_shared/architect-reviewer-base.md +0 -104
  72. package/scaffold/general/agents/_shared/code-agent-base.md +0 -366
  73. package/scaffold/general/agents/_shared/code-reviewer-base.md +0 -87
  74. package/scaffold/general/agents/_shared/decision-protocol.md +0 -27
  75. package/scaffold/general/agents/_shared/forge-protocol.md +0 -90
  76. package/scaffold/general/agents/_shared/researcher-base.md +0 -114
  77. package/scaffold/general/agents/templates/adr-template.md +0 -28
  78. package/scaffold/general/agents/templates/execution-state.md +0 -26
  79. package/scaffold/general/prompts/aikit-ask.prompt.md +0 -13
  80. package/scaffold/general/prompts/aikit-debug.prompt.md +0 -15
  81. package/scaffold/general/prompts/aikit-design.prompt.md +0 -15
  82. package/scaffold/general/prompts/aikit-flow-add.prompt.md +0 -84
  83. package/scaffold/general/prompts/aikit-flow-create.prompt.md +0 -80
  84. package/scaffold/general/prompts/aikit-flow-manage.prompt.md +0 -24
  85. package/scaffold/general/prompts/aikit-implement.prompt.md +0 -17
  86. package/scaffold/general/prompts/aikit-plan.prompt.md +0 -15
  87. package/scaffold/general/prompts/aikit-review.prompt.md +0 -24
  88. package/scaffold/general/skills/adr-skill/SKILL.md +0 -335
  89. package/scaffold/general/skills/adr-skill/assets/templates/adr-madr.md +0 -89
  90. package/scaffold/general/skills/adr-skill/assets/templates/adr-readme.md +0 -20
  91. package/scaffold/general/skills/adr-skill/assets/templates/adr-simple.md +0 -46
  92. package/scaffold/general/skills/adr-skill/references/adr-conventions.md +0 -95
  93. package/scaffold/general/skills/adr-skill/references/examples.md +0 -193
  94. package/scaffold/general/skills/adr-skill/references/review-checklist.md +0 -77
  95. package/scaffold/general/skills/adr-skill/references/template-variants.md +0 -52
  96. package/scaffold/general/skills/adr-skill/scripts/bootstrap_adr.js +0 -259
  97. package/scaffold/general/skills/adr-skill/scripts/new_adr.js +0 -391
  98. package/scaffold/general/skills/adr-skill/scripts/set_adr_status.js +0 -169
  99. package/scaffold/general/skills/aikit/SKILL.md +0 -754
  100. package/scaffold/general/skills/brainstorming/SKILL.md +0 -265
  101. package/scaffold/general/skills/brainstorming/spec-document-reviewer-prompt.md +0 -49
  102. package/scaffold/general/skills/c4-architecture/SKILL.md +0 -389
  103. package/scaffold/general/skills/c4-architecture/references/advanced-patterns.md +0 -552
  104. package/scaffold/general/skills/c4-architecture/references/c4-syntax.md +0 -510
  105. package/scaffold/general/skills/c4-architecture/references/common-mistakes.md +0 -437
  106. package/scaffold/general/skills/c4-architecture/references/html-design-system.md +0 -337
  107. package/scaffold/general/skills/c4-architecture/references/html-template.html +0 -627
  108. package/scaffold/general/skills/docs/SKILL.md +0 -553
  109. package/scaffold/general/skills/docs/references/diataxis-anti-patterns.md +0 -147
  110. package/scaffold/general/skills/docs/references/diataxis-compass.md +0 -123
  111. package/scaffold/general/skills/docs/references/diataxis-quadrants.md +0 -192
  112. package/scaffold/general/skills/docs/references/diataxis-quality.md +0 -76
  113. package/scaffold/general/skills/docs/references/diataxis-templates.md +0 -120
  114. package/scaffold/general/skills/docs/references/flow-artifacts-guide.md +0 -70
  115. package/scaffold/general/skills/docs/references/project-knowledge-gotchas.md +0 -32
  116. package/scaffold/general/skills/docs/references/project-knowledge-templates.md +0 -281
  117. package/scaffold/general/skills/docs/references/project-knowledge-workflow.md +0 -80
  118. package/scaffold/general/skills/frontend-design/SKILL.md +0 -237
  119. package/scaffold/general/skills/lesson-learned/SKILL.md +0 -113
  120. package/scaffold/general/skills/lesson-learned/references/anti-patterns.md +0 -55
  121. package/scaffold/general/skills/lesson-learned/references/se-principles.md +0 -109
  122. package/scaffold/general/skills/multi-agents-development/SKILL.md +0 -448
  123. package/scaffold/general/skills/multi-agents-development/architecture-review-prompt.md +0 -81
  124. package/scaffold/general/skills/multi-agents-development/code-quality-review-prompt.md +0 -91
  125. package/scaffold/general/skills/multi-agents-development/implementer-prompt.md +0 -93
  126. package/scaffold/general/skills/multi-agents-development/parallel-dispatch-example.md +0 -167
  127. package/scaffold/general/skills/multi-agents-development/spec-review-prompt.md +0 -81
  128. package/scaffold/general/skills/present/SKILL.md +0 -616
  129. package/scaffold/general/skills/react/SKILL.md +0 -309
  130. package/scaffold/general/skills/repo-access/SKILL.md +0 -178
  131. package/scaffold/general/skills/repo-access/references/error-patterns.md +0 -116
  132. package/scaffold/general/skills/repo-access/references/platform-matrix.md +0 -142
  133. package/scaffold/general/skills/requirements-clarity/SKILL.md +0 -333
  134. package/scaffold/general/skills/session-handoff/SKILL.md +0 -199
  135. package/scaffold/general/skills/session-handoff/references/handoff-template.md +0 -139
  136. package/scaffold/general/skills/session-handoff/references/resume-checklist.md +0 -80
  137. package/scaffold/general/skills/session-handoff/scripts/check_staleness.js +0 -269
  138. package/scaffold/general/skills/session-handoff/scripts/create_handoff.js +0 -299
  139. package/scaffold/general/skills/session-handoff/scripts/list_handoffs.js +0 -113
  140. package/scaffold/general/skills/session-handoff/scripts/validate_handoff.js +0 -241
  141. package/scaffold/general/skills/typescript/SKILL.md +0 -405
  142. package/scaffold/generate.mjs +0 -82
@@ -1,391 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Create a new ADR markdown file using repo conventions and a template.
4
- *
5
- * Design goals:
6
- * - Safe defaults (auto-detect adr directory + numbering)
7
- * - No external deps
8
- * - Works even if the repo has no ADRs yet
9
- */
10
-
11
- const fs = require('node:fs');
12
- const path = require('node:path');
13
-
14
- function die(msg) {
15
- process.stderr.write(`${msg}\n`);
16
- process.exit(1);
17
- }
18
-
19
- function slugify(text) {
20
- const t = String(text || '')
21
- .trim()
22
- .toLowerCase();
23
- const noQuotes = t.replace(/['"`]/g, '');
24
- const dashed = noQuotes.replace(/[^a-z0-9]+/g, '-').replace(/-{2,}/g, '-');
25
- const trimmed = dashed.replace(/^-+/, '').replace(/-+$/, '');
26
- return trimmed || 'decision';
27
- }
28
-
29
- function toPosix(p) {
30
- return p.split(path.sep).join('/');
31
- }
32
-
33
- function parseArgs(argv) {
34
- const out = {
35
- repoRoot: '.',
36
- dir: null,
37
- noCreateDir: false,
38
- title: null,
39
- status: 'proposed',
40
- template: 'simple', // simple | madr
41
- strategy: 'auto', // auto | date | slug
42
- deciders: '',
43
- consulted: '',
44
- informed: '',
45
- technicalStory: '',
46
- chosenOption: '',
47
- updateIndex: false,
48
- indexFile: null,
49
- json: false,
50
- };
51
-
52
- for (let i = 2; i < argv.length; i++) {
53
- const a = argv[i];
54
- const next = () => {
55
- if (i + 1 >= argv.length) die(`Missing value for ${a}`);
56
- return argv[++i];
57
- };
58
-
59
- if (a === '--repo-root') out.repoRoot = next();
60
- else if (a === '--dir') out.dir = next();
61
- else if (a === '--no-create-dir') out.noCreateDir = true;
62
- else if (a === '--title') out.title = next();
63
- else if (a === '--status') out.status = next();
64
- else if (a === '--template') out.template = next();
65
- else if (a === '--strategy') out.strategy = next();
66
- else if (a === '--deciders') out.deciders = next();
67
- else if (a === '--consulted') out.consulted = next();
68
- else if (a === '--informed') out.informed = next();
69
- else if (a === '--technical-story') out.technicalStory = next();
70
- else if (a === '--chosen-option') out.chosenOption = next();
71
- else if (a === '--update-index') out.updateIndex = true;
72
- else if (a === '--index-file') out.indexFile = next();
73
- else if (a === '--json') out.json = true;
74
- else if (a === '--help' || a === '-h') {
75
- process.stdout.write(
76
- [
77
- 'Usage: node new_adr.js --title "Choose database" [options]',
78
- '',
79
- 'Options:',
80
- ' --repo-root <path> Repo root (default: .)',
81
- ' --dir <path> ADR directory (default: auto-detect, else adr/)',
82
- ' --no-create-dir Do not create ADR directory if missing',
83
- ' --status <value> ADR status (default: proposed)',
84
- ' --template simple|madr Template (default: simple)',
85
- ' --strategy auto|date|slug Filename strategy (default: auto)',
86
- ' --deciders "a,b" Deciders list',
87
- ' --consulted "a,b" Consulted experts (RACI)',
88
- ' --informed "a,b" Informed stakeholders (RACI)',
89
- ' --technical-story <x> Issue/ticket/PR link or short ref',
90
- ' --chosen-option <x> MADR template: chosen option label',
91
- ' --update-index Update adr/README.md (or existing index)',
92
- ' --index-file <path> Override index file (relative to repo root unless absolute)',
93
- ' --json Output machine-readable JSON (default: off)',
94
- '',
95
- ].join('\n'),
96
- );
97
- process.exit(0);
98
- } else {
99
- die(`Unknown arg: ${a}`);
100
- }
101
- }
102
-
103
- if (!out.title) die('Missing required --title');
104
-
105
- if (!['simple', 'madr'].includes(out.template)) die(`Invalid --template: ${out.template}`);
106
- if (!['auto', 'date', 'slug'].includes(out.strategy)) die(`Invalid --strategy: ${out.strategy}`);
107
-
108
- return out;
109
- }
110
-
111
- function detectAdrDir(repoRoot) {
112
- const candidates = [
113
- path.join(repoRoot, 'contributing', 'decisions'),
114
- path.join(repoRoot, 'docs', 'decisions'),
115
- path.join(repoRoot, 'adr'),
116
- path.join(repoRoot, 'docs', 'adr'),
117
- path.join(repoRoot, 'docs', 'adrs'),
118
- path.join(repoRoot, 'decisions'),
119
- ];
120
- for (const p of candidates) {
121
- try {
122
- if (fs.statSync(p).isDirectory()) return p;
123
- } catch {
124
- // ignore
125
- }
126
- }
127
- return null;
128
- }
129
-
130
- function listMdFiles(dir) {
131
- let entries = [];
132
- try {
133
- entries = fs.readdirSync(dir, { withFileTypes: true });
134
- } catch {
135
- return [];
136
- }
137
- return entries
138
- .filter((e) => e.isFile() && e.name.toLowerCase().endsWith('.md'))
139
- .map((e) => e.name);
140
- }
141
-
142
- function detectStrategy(adrDir) {
143
- const md = listMdFiles(adrDir);
144
- for (const name of md) {
145
- if (/^\d{4}-\d{2}-\d{2}-/.test(name)) return 'date';
146
- }
147
- if (md.length > 0) return 'slug';
148
- return 'date';
149
- }
150
-
151
- function todayISO() {
152
- return new Date().toISOString().slice(0, 10);
153
- }
154
-
155
- function loadTemplate(templateName) {
156
- const skillRoot = path.resolve(__dirname, '..');
157
- const templatePath = path.join(skillRoot, 'assets', 'templates', `adr-${templateName}.md`);
158
- if (!fs.existsSync(templatePath)) die(`Template not found: ${templatePath}`);
159
- return fs.readFileSync(templatePath, 'utf8');
160
- }
161
-
162
- function renderTemplate(raw, vars) {
163
- // Handle YAML front matter placeholders (quoted and unquoted)
164
- let out = raw;
165
-
166
- // YAML front matter fields — replace the whole placeholder pattern
167
- // e.g. status: "{proposed | accepted | ...}" → status: proposed
168
- out = out.replace(/^(status:\s*)["']?\{[^}]*\}["']?\s*$/m, `$1${vars.status}`);
169
- out = out.replace(/^(date:\s*)\{[^}]*\}\s*$/m, `$1${vars.date}`);
170
- out = out.replace(/^(decision-makers:\s*)["']?\{[^}]*\}["']?\s*$/m, `$1${vars.deciders || ''}`);
171
-
172
- // consulted / informed: replace if a value was provided, otherwise remove the
173
- // entire line so we don't leak placeholder text like "{list everyone...}"
174
- if (vars.consulted) {
175
- out = out.replace(/^(consulted:\s*)["']?\{[^}]*\}["']?\s*$/m, `$1${vars.consulted}`);
176
- } else {
177
- out = out.replace(/^consulted:\s*["']?\{[^}]*\}["']?\s*\n/m, '');
178
- }
179
- if (vars.informed) {
180
- out = out.replace(/^(informed:\s*)["']?\{[^}]*\}["']?\s*$/m, `$1${vars.informed}`);
181
- } else {
182
- out = out.replace(/^informed:\s*["']?\{[^}]*\}["']?\s*\n/m, '');
183
- }
184
-
185
- // Replace MADR-style heading placeholder
186
- out = out.replace(/^(#\s+)\{short title[^}]*\}\s*$/m, `$1${vars.title}`);
187
-
188
- // Inline placeholders (title in heading, etc.)
189
- out = out
190
- .replaceAll('{TITLE}', vars.title)
191
- .replaceAll('{STATUS}', vars.status)
192
- .replaceAll('{DATE}', vars.date)
193
- .replaceAll('{DECIDERS}', vars.deciders)
194
- .replaceAll('{TECHNICAL_STORY}', vars.technicalStory)
195
- .replaceAll('{CHOSEN_OPTION}', vars.chosenOption);
196
-
197
- return out;
198
- }
199
-
200
- function chooseIndexFile(adrDir) {
201
- for (const name of ['README.md', 'index.md']) {
202
- const p = path.join(adrDir, name);
203
- if (fs.existsSync(p)) return p;
204
- }
205
- return path.join(adrDir, 'README.md');
206
- }
207
-
208
- function insertIndexEntryUnderHeading(lines, headingRegex, entryLine) {
209
- // Returns { lines, inserted }
210
- const headingIndex = lines.findIndex((l) => headingRegex.test(l));
211
- if (headingIndex === -1) return { lines, inserted: false };
212
-
213
- let sectionEnd = lines.length;
214
- for (let i = headingIndex + 1; i < lines.length; i++) {
215
- if (/^##\s+/.test(lines[i])) {
216
- sectionEnd = i;
217
- break;
218
- }
219
- }
220
-
221
- // Prefer inserting at end of list in this section if there is a list.
222
- let lastListItem = -1;
223
- for (let i = sectionEnd - 1; i > headingIndex; i--) {
224
- if (/^[-*]\s+/.test(lines[i])) {
225
- lastListItem = i;
226
- break;
227
- }
228
- }
229
-
230
- const insertAt = lastListItem !== -1 ? lastListItem + 1 : sectionEnd;
231
-
232
- const out = [...lines];
233
-
234
- // Ensure there's a blank line after the heading if we're inserting immediately after it.
235
- if (insertAt === headingIndex + 1 && out[insertAt] !== '') {
236
- out.splice(insertAt, 0, '');
237
- }
238
-
239
- out.splice(insertAt, 0, entryLine);
240
- return { lines: out, inserted: true };
241
- }
242
-
243
- function updateIndex(indexFile, { relLink, title, status, date }) {
244
- let content = '';
245
- if (fs.existsSync(indexFile)) content = fs.readFileSync(indexFile, 'utf8');
246
- else content = '# ADR Log\n\n';
247
-
248
- if (content.includes(relLink)) return false;
249
-
250
- const normalized = content.replace(/\r\n/g, '\n');
251
- const hadTrailingNewline = normalized.endsWith('\n');
252
- let lines = normalized.split('\n');
253
- // Normalize away the trailing empty split element so insertion math is sane.
254
- if (hadTrailingNewline && lines.length > 0 && lines[lines.length - 1] === '') {
255
- lines = lines.slice(0, -1);
256
- }
257
- const entryLine = `- [${title}](${relLink}) (${status}, ${date})`;
258
-
259
- // Prefer inserting under "## ADRs" if it exists, otherwise append at EOF.
260
- const r = insertIndexEntryUnderHeading(lines, /^##\s+ADRs\s*$/i, entryLine);
261
- const nextLines = r.inserted ? r.lines : [...lines, entryLine];
262
-
263
- let next = nextLines.join('\n');
264
- if (hadTrailingNewline) next += '\n';
265
-
266
- fs.mkdirSync(path.dirname(indexFile), { recursive: true });
267
- fs.writeFileSync(indexFile, next, 'utf8');
268
- return true;
269
- }
270
-
271
- function main() {
272
- const args = parseArgs(process.argv);
273
-
274
- const repoRoot = path.resolve(process.cwd(), args.repoRoot);
275
- if (!fs.existsSync(repoRoot)) die(`Repo root does not exist: ${repoRoot}`);
276
-
277
- let adrDir;
278
- if (args.dir) adrDir = path.resolve(repoRoot, args.dir);
279
- else adrDir = detectAdrDir(repoRoot) || path.join(repoRoot, 'adr');
280
-
281
- if (!fs.existsSync(adrDir)) {
282
- if (args.noCreateDir) die(`ADR directory does not exist: ${adrDir}`);
283
- fs.mkdirSync(adrDir, { recursive: true });
284
- }
285
-
286
- let strategy = args.strategy;
287
- if (strategy === 'auto') strategy = detectStrategy(adrDir);
288
-
289
- const title = String(args.title).trim();
290
- const slug = slugify(title);
291
-
292
- const today = todayISO();
293
-
294
- let filename;
295
- if (strategy === 'date') {
296
- filename = `${today}-${slug}.md`;
297
- } else {
298
- filename = `${slug}.md`;
299
- }
300
-
301
- let out = path.join(adrDir, filename);
302
- if (fs.existsSync(out)) {
303
- if (strategy === 'date') die(`ADR already exists: ${out}`);
304
- let i = 2;
305
- while (true) {
306
- const candidate = path.join(adrDir, `${slug}-${i}.md`);
307
- if (!fs.existsSync(candidate)) {
308
- out = candidate;
309
- break;
310
- }
311
- i++;
312
- }
313
- }
314
-
315
- const deciders = String(args.deciders || '')
316
- .split(',')
317
- .map((s) => s.trim())
318
- .filter(Boolean)
319
- .join(', ');
320
-
321
- const consulted = String(args.consulted || '')
322
- .split(',')
323
- .map((s) => s.trim())
324
- .filter(Boolean)
325
- .join(', ');
326
- const informed = String(args.informed || '')
327
- .split(',')
328
- .map((s) => s.trim())
329
- .filter(Boolean)
330
- .join(', ');
331
-
332
- const raw = loadTemplate(args.template);
333
- const rendered = renderTemplate(raw, {
334
- title,
335
- status: String(args.status).trim(),
336
- date: today,
337
- deciders,
338
- consulted,
339
- informed,
340
- technicalStory: String(args.technicalStory || '').trim(),
341
- chosenOption: String(args.chosenOption || '').trim(),
342
- });
343
-
344
- fs.writeFileSync(out, `${rendered.trimEnd()}\n`, 'utf8');
345
-
346
- let updatedIndexPath = null;
347
- let indexChanged = false;
348
-
349
- if (args.updateIndex) {
350
- let indexFile;
351
- if (args.indexFile) {
352
- indexFile = path.isAbsolute(args.indexFile)
353
- ? args.indexFile
354
- : path.resolve(repoRoot, args.indexFile);
355
- } else {
356
- indexFile = chooseIndexFile(adrDir);
357
- }
358
-
359
- const relLink = toPosix(path.relative(path.dirname(indexFile), out));
360
- indexChanged = updateIndex(indexFile, {
361
- relLink,
362
- title,
363
- status: String(args.status).trim(),
364
- date: today,
365
- });
366
- updatedIndexPath = indexFile;
367
- }
368
-
369
- if (args.json) {
370
- const payload = {
371
- repoRoot,
372
- adrDir,
373
- createdAdrPath: out,
374
- createdAdrRelPath: toPosix(path.relative(repoRoot, out)),
375
- title,
376
- status: String(args.status).trim(),
377
- template: args.template,
378
- strategy,
379
- date: today,
380
- indexUpdated: Boolean(updatedIndexPath),
381
- indexChanged,
382
- indexPath: updatedIndexPath,
383
- indexRelPath: updatedIndexPath ? toPosix(path.relative(repoRoot, updatedIndexPath)) : null,
384
- };
385
- process.stdout.write(`${JSON.stringify(payload)}\n`);
386
- } else {
387
- process.stdout.write(`${out}\n`);
388
- }
389
- }
390
-
391
- main();
@@ -1,169 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Update an ADR's status in-place.
4
- *
5
- * Supported patterns:
6
- * - Bullet status: "- Status: proposed" or "* Status: proposed"
7
- * - Nygard-style section: "## Status" followed by a single-line status value
8
- */
9
-
10
- const fs = require('node:fs');
11
- const path = require('node:path');
12
-
13
- function die(msg) {
14
- process.stderr.write(`${msg}\n`);
15
- process.exit(1);
16
- }
17
-
18
- function toPosix(p) {
19
- return p.split(path.sep).join('/');
20
- }
21
-
22
- function parseArgs(argv) {
23
- if (argv.includes('--help') || argv.includes('-h')) {
24
- process.stdout.write(
25
- [
26
- 'Usage: node set_adr_status.js <path> --status <value> [--json]',
27
- '',
28
- 'Example:',
29
- ' node set_adr_status.js adr/2025-06-15-foo.md --status accepted',
30
- '',
31
- ].join('\n'),
32
- );
33
- process.exit(0);
34
- }
35
-
36
- if (argv.length < 3) die('Missing <path>');
37
- const file = argv[2];
38
-
39
- let status = null;
40
- let json = false;
41
- for (let i = 3; i < argv.length; i++) {
42
- const a = argv[i];
43
- if (a === '--status') {
44
- if (i + 1 >= argv.length) die('Missing value for --status');
45
- status = argv[++i];
46
- } else if (a === '--json') {
47
- json = true;
48
- } else {
49
- die(`Unknown arg: ${a}`);
50
- }
51
- }
52
- if (!status) die('Missing required --status');
53
- return { file, status: String(status).trim(), json };
54
- }
55
-
56
- function setYamlFrontMatterStatus(lines, newStatus) {
57
- // YAML front matter: starts with '---', ends with next '---'
58
- if (lines.length < 2 || lines[0].trim() !== '---') return { lines, changed: false };
59
-
60
- let changed = false;
61
- const out = [];
62
- let inFrontMatter = true;
63
- let passedOpening = false;
64
-
65
- for (let i = 0; i < lines.length; i++) {
66
- const line = lines[i];
67
-
68
- if (i === 0 && line.trim() === '---') {
69
- passedOpening = true;
70
- out.push(line);
71
- continue;
72
- }
73
-
74
- if (passedOpening && inFrontMatter && line.trim() === '---') {
75
- inFrontMatter = false;
76
- out.push(line);
77
- continue;
78
- }
79
-
80
- if (passedOpening && inFrontMatter && /^status\s*:/.test(line)) {
81
- out.push(`status: ${newStatus}`);
82
- changed = true;
83
- continue;
84
- }
85
-
86
- out.push(line);
87
- }
88
-
89
- return { lines: out, changed };
90
- }
91
-
92
- function setBulletStatus(lines, newStatus) {
93
- let changed = false;
94
- const out = lines.map((line) => {
95
- const m = line.match(/^([*-])\s*Status:\s*(.*)$/);
96
- if (!m) return line;
97
- changed = true;
98
- return `${m[1]} Status: ${newStatus}`;
99
- });
100
- return { lines: out, changed };
101
- }
102
-
103
- function setSectionStatus(lines, newStatus) {
104
- let changed = false;
105
- const out = [];
106
-
107
- for (let i = 0; i < lines.length; i++) {
108
- out.push(lines[i]);
109
-
110
- if (!/^##\s+Status\s*$/.test(lines[i])) continue;
111
-
112
- // Replace next non-empty, non-heading line. If not found, insert.
113
- let j = i + 1;
114
- while (j < lines.length && lines[j].trim() === '') {
115
- out.push(lines[j]);
116
- j++;
117
- }
118
-
119
- if (j < lines.length && !/^##\s+/.test(lines[j])) {
120
- out.push(newStatus);
121
- changed = true;
122
- i = j; // skip original status line
123
- continue;
124
- }
125
-
126
- out.push(newStatus);
127
- changed = true;
128
- i = j - 1;
129
- }
130
-
131
- return { lines: out, changed };
132
- }
133
-
134
- function main() {
135
- const args = parseArgs(process.argv);
136
- const filePath = path.resolve(process.cwd(), args.file);
137
- if (!fs.existsSync(filePath)) die(`File not found: ${filePath}`);
138
-
139
- const content = fs.readFileSync(filePath, 'utf8');
140
- const hadTrailingNewline = content.endsWith('\n');
141
- const lines = content.replace(/\r\n/g, '\n').split('\n');
142
-
143
- let r = setYamlFrontMatterStatus(lines, args.status);
144
- if (!r.changed) r = setBulletStatus(lines, args.status);
145
- if (!r.changed) r = setSectionStatus(lines, args.status);
146
- if (!r.changed) {
147
- die(
148
- "Could not find a status to update. Expected YAML front matter 'status:', '- Status:'/'* Status:', or a '## Status' section.",
149
- );
150
- }
151
-
152
- const newContent = r.lines.join('\n') + (hadTrailingNewline ? '\n' : '');
153
- fs.writeFileSync(filePath, newContent, 'utf8');
154
-
155
- if (args.json) {
156
- process.stdout.write(
157
- `${JSON.stringify({
158
- filePath,
159
- fileRelPath: toPosix(path.relative(process.cwd(), filePath)),
160
- status: args.status,
161
- changed: true,
162
- })}\n`,
163
- );
164
- } else {
165
- process.stdout.write(`${filePath}\n`);
166
- }
167
- }
168
-
169
- main();