@vpxa/aikit 0.1.74 → 0.1.76

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 (128) hide show
  1. package/package.json +5 -1
  2. package/packages/cli/dist/index.js +2 -2
  3. package/packages/cli/dist/{init-DQkar6Es.js → init-CuRXmyD9.js} +1 -1
  4. package/packages/cli/dist/scaffold-WMQ2uQ48.js +2 -0
  5. package/packages/cli/dist/{user-CopNWxHP.js → user-vbJwa7x2.js} +1 -1
  6. package/scaffold/dist/adapters/claude-code.mjs +4 -0
  7. package/scaffold/dist/adapters/copilot.mjs +75 -0
  8. package/scaffold/dist/adapters/flows.mjs +1 -0
  9. package/scaffold/dist/adapters/skills.mjs +1 -0
  10. package/scaffold/{compiled → dist/compiled}/flows-data.mjs +304 -446
  11. package/scaffold/{compiled → dist/compiled}/skills-data.mjs +554 -2281
  12. package/scaffold/dist/definitions/agents.mjs +9 -0
  13. package/scaffold/dist/definitions/bodies.mjs +512 -0
  14. package/scaffold/dist/definitions/exclusions.mjs +1 -0
  15. package/scaffold/dist/definitions/hooks.mjs +1 -0
  16. package/scaffold/dist/definitions/models.mjs +1 -0
  17. package/scaffold/dist/definitions/plugins.mjs +1 -0
  18. package/scaffold/dist/definitions/prompts.mjs +225 -0
  19. package/scaffold/dist/definitions/protocols.mjs +835 -0
  20. package/scaffold/dist/definitions/tools.mjs +1 -0
  21. package/packages/cli/dist/scaffold-ukCDW3wQ.js +0 -2
  22. package/scaffold/_preview/agents/Architect-Reviewer-Alpha.agent.md +0 -132
  23. package/scaffold/_preview/agents/Architect-Reviewer-Beta.agent.md +0 -132
  24. package/scaffold/_preview/agents/Code-Reviewer-Alpha.agent.md +0 -112
  25. package/scaffold/_preview/agents/Code-Reviewer-Beta.agent.md +0 -112
  26. package/scaffold/_preview/agents/Debugger.agent.md +0 -412
  27. package/scaffold/_preview/agents/Documenter.agent.md +0 -468
  28. package/scaffold/_preview/agents/Explorer.agent.md +0 -76
  29. package/scaffold/_preview/agents/Frontend.agent.md +0 -440
  30. package/scaffold/_preview/agents/Implementer.agent.md +0 -425
  31. package/scaffold/_preview/agents/Orchestrator.agent.md +0 -452
  32. package/scaffold/_preview/agents/Planner.agent.md +0 -481
  33. package/scaffold/_preview/agents/README.md +0 -57
  34. package/scaffold/_preview/agents/Refactor.agent.md +0 -435
  35. package/scaffold/_preview/agents/Researcher-Alpha.agent.md +0 -151
  36. package/scaffold/_preview/agents/Researcher-Beta.agent.md +0 -152
  37. package/scaffold/_preview/agents/Researcher-Delta.agent.md +0 -153
  38. package/scaffold/_preview/agents/Researcher-Gamma.agent.md +0 -152
  39. package/scaffold/_preview/agents/Security.agent.md +0 -433
  40. package/scaffold/_preview/agents/_shared/architect-reviewer-base.md +0 -104
  41. package/scaffold/_preview/agents/_shared/code-agent-base.md +0 -366
  42. package/scaffold/_preview/agents/_shared/code-reviewer-base.md +0 -87
  43. package/scaffold/_preview/agents/_shared/decision-protocol.md +0 -27
  44. package/scaffold/_preview/agents/_shared/forge-protocol.md +0 -90
  45. package/scaffold/_preview/agents/_shared/researcher-base.md +0 -114
  46. package/scaffold/_preview/agents/templates/adr-template.md +0 -28
  47. package/scaffold/_preview/agents/templates/execution-state.md +0 -26
  48. package/scaffold/_preview/flows/_epilogue/steps/docs-sync/README.md +0 -120
  49. package/scaffold/_preview/flows/aikit-advanced/README.md +0 -70
  50. package/scaffold/_preview/flows/aikit-advanced/steps/design/README.md +0 -178
  51. package/scaffold/_preview/flows/aikit-advanced/steps/execute/README.md +0 -145
  52. package/scaffold/_preview/flows/aikit-advanced/steps/plan/README.md +0 -122
  53. package/scaffold/_preview/flows/aikit-advanced/steps/spec/README.md +0 -121
  54. package/scaffold/_preview/flows/aikit-advanced/steps/task/README.md +0 -119
  55. package/scaffold/_preview/flows/aikit-advanced/steps/verify/README.md +0 -145
  56. package/scaffold/_preview/flows/aikit-basic/README.md +0 -51
  57. package/scaffold/_preview/flows/aikit-basic/steps/assess/README.md +0 -109
  58. package/scaffold/_preview/flows/aikit-basic/steps/design/README.md +0 -116
  59. package/scaffold/_preview/flows/aikit-basic/steps/implement/README.md +0 -131
  60. package/scaffold/_preview/flows/aikit-basic/steps/verify/README.md +0 -123
  61. package/scaffold/_preview/prompts/aikit-ask.prompt.md +0 -13
  62. package/scaffold/_preview/prompts/aikit-debug.prompt.md +0 -15
  63. package/scaffold/_preview/prompts/aikit-design.prompt.md +0 -15
  64. package/scaffold/_preview/prompts/aikit-flow-add.prompt.md +0 -84
  65. package/scaffold/_preview/prompts/aikit-flow-create.prompt.md +0 -80
  66. package/scaffold/_preview/prompts/aikit-flow-manage.prompt.md +0 -24
  67. package/scaffold/_preview/prompts/aikit-implement.prompt.md +0 -17
  68. package/scaffold/_preview/prompts/aikit-plan.prompt.md +0 -15
  69. package/scaffold/_preview/prompts/aikit-review.prompt.md +0 -24
  70. package/scaffold/_preview/skills/adr-skill/SKILL.md +0 -335
  71. package/scaffold/_preview/skills/adr-skill/assets/templates/adr-madr.md +0 -89
  72. package/scaffold/_preview/skills/adr-skill/assets/templates/adr-readme.md +0 -20
  73. package/scaffold/_preview/skills/adr-skill/assets/templates/adr-simple.md +0 -46
  74. package/scaffold/_preview/skills/adr-skill/references/adr-conventions.md +0 -95
  75. package/scaffold/_preview/skills/adr-skill/references/examples.md +0 -193
  76. package/scaffold/_preview/skills/adr-skill/references/review-checklist.md +0 -77
  77. package/scaffold/_preview/skills/adr-skill/references/template-variants.md +0 -52
  78. package/scaffold/_preview/skills/adr-skill/scripts/bootstrap_adr.js +0 -259
  79. package/scaffold/_preview/skills/adr-skill/scripts/new_adr.js +0 -391
  80. package/scaffold/_preview/skills/adr-skill/scripts/set_adr_status.js +0 -169
  81. package/scaffold/_preview/skills/aikit/SKILL.md +0 -754
  82. package/scaffold/_preview/skills/brainstorming/SKILL.md +0 -265
  83. package/scaffold/_preview/skills/brainstorming/spec-document-reviewer-prompt.md +0 -49
  84. package/scaffold/_preview/skills/c4-architecture/SKILL.md +0 -389
  85. package/scaffold/_preview/skills/c4-architecture/references/advanced-patterns.md +0 -552
  86. package/scaffold/_preview/skills/c4-architecture/references/c4-syntax.md +0 -510
  87. package/scaffold/_preview/skills/c4-architecture/references/common-mistakes.md +0 -437
  88. package/scaffold/_preview/skills/c4-architecture/references/html-design-system.md +0 -337
  89. package/scaffold/_preview/skills/c4-architecture/references/html-template.html +0 -627
  90. package/scaffold/_preview/skills/docs/SKILL.md +0 -553
  91. package/scaffold/_preview/skills/docs/references/diataxis-anti-patterns.md +0 -147
  92. package/scaffold/_preview/skills/docs/references/diataxis-compass.md +0 -123
  93. package/scaffold/_preview/skills/docs/references/diataxis-quadrants.md +0 -192
  94. package/scaffold/_preview/skills/docs/references/diataxis-quality.md +0 -76
  95. package/scaffold/_preview/skills/docs/references/diataxis-templates.md +0 -120
  96. package/scaffold/_preview/skills/docs/references/flow-artifacts-guide.md +0 -70
  97. package/scaffold/_preview/skills/docs/references/project-knowledge-gotchas.md +0 -32
  98. package/scaffold/_preview/skills/docs/references/project-knowledge-templates.md +0 -281
  99. package/scaffold/_preview/skills/docs/references/project-knowledge-workflow.md +0 -80
  100. package/scaffold/_preview/skills/frontend-design/SKILL.md +0 -237
  101. package/scaffold/_preview/skills/lesson-learned/SKILL.md +0 -113
  102. package/scaffold/_preview/skills/lesson-learned/references/anti-patterns.md +0 -55
  103. package/scaffold/_preview/skills/lesson-learned/references/se-principles.md +0 -109
  104. package/scaffold/_preview/skills/multi-agents-development/SKILL.md +0 -448
  105. package/scaffold/_preview/skills/multi-agents-development/architecture-review-prompt.md +0 -81
  106. package/scaffold/_preview/skills/multi-agents-development/code-quality-review-prompt.md +0 -91
  107. package/scaffold/_preview/skills/multi-agents-development/implementer-prompt.md +0 -93
  108. package/scaffold/_preview/skills/multi-agents-development/parallel-dispatch-example.md +0 -167
  109. package/scaffold/_preview/skills/multi-agents-development/spec-review-prompt.md +0 -81
  110. package/scaffold/_preview/skills/present/SKILL.md +0 -616
  111. package/scaffold/_preview/skills/react/SKILL.md +0 -309
  112. package/scaffold/_preview/skills/repo-access/SKILL.md +0 -178
  113. package/scaffold/_preview/skills/repo-access/references/error-patterns.md +0 -116
  114. package/scaffold/_preview/skills/repo-access/references/platform-matrix.md +0 -142
  115. package/scaffold/_preview/skills/requirements-clarity/SKILL.md +0 -333
  116. package/scaffold/_preview/skills/session-handoff/SKILL.md +0 -199
  117. package/scaffold/_preview/skills/session-handoff/references/handoff-template.md +0 -139
  118. package/scaffold/_preview/skills/session-handoff/references/resume-checklist.md +0 -80
  119. package/scaffold/_preview/skills/session-handoff/scripts/check_staleness.js +0 -269
  120. package/scaffold/_preview/skills/session-handoff/scripts/create_handoff.js +0 -299
  121. package/scaffold/_preview/skills/session-handoff/scripts/list_handoffs.js +0 -113
  122. package/scaffold/_preview/skills/session-handoff/scripts/validate_handoff.js +0 -241
  123. package/scaffold/_preview/skills/typescript/SKILL.md +0 -405
  124. package/scaffold/adapters/claude-code.mjs +0 -73
  125. package/scaffold/adapters/copilot.mjs +0 -292
  126. package/scaffold/adapters/flows.mjs +0 -27
  127. package/scaffold/adapters/skills.mjs +0 -25
  128. package/scaffold/generate.mjs +0 -92
@@ -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();