@izkac/forgekit 0.3.12 → 0.3.14

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 (120) hide show
  1. package/bin/forge.mjs +119 -107
  2. package/bin/forgekit.mjs +83 -83
  3. package/bin/review.mjs +81 -81
  4. package/package.json +2 -1
  5. package/scripts/prepack.mjs +78 -78
  6. package/scripts/run-tests.mjs +50 -50
  7. package/src/adr.mjs +236 -236
  8. package/src/adr.test.mjs +170 -170
  9. package/src/change.mjs +327 -234
  10. package/src/change.test.mjs +145 -83
  11. package/src/cleanup-sessions.mjs +84 -84
  12. package/src/config.mjs +103 -103
  13. package/src/defer.mjs +75 -75
  14. package/src/doctor.mjs +350 -341
  15. package/src/doctor.test.mjs +114 -114
  16. package/src/fleet.test.mjs +50 -0
  17. package/src/init.mjs +680 -621
  18. package/src/install.mjs +815 -815
  19. package/src/install.test.mjs +180 -180
  20. package/src/integrity-check.mjs +60 -60
  21. package/src/integrity.mjs +688 -682
  22. package/src/integrity.test.mjs +612 -566
  23. package/src/lib/fleet.mjs +61 -4
  24. package/src/lib.mjs +160 -143
  25. package/src/lib.test.mjs +128 -0
  26. package/src/models.defaults.json +41 -41
  27. package/src/new-session.mjs +99 -99
  28. package/src/openspec-overlays/README.md +19 -19
  29. package/src/openspec-overlays/openspec-apply-change-footer.md +14 -14
  30. package/src/openspec-overlays/opsx-apply-completion-step.md +1 -1
  31. package/src/openspec-overlays/opsx-apply-implement-step.md +11 -11
  32. package/src/paths.mjs +92 -92
  33. package/src/plan-engine.mjs +321 -278
  34. package/src/plan-engine.test.mjs +447 -283
  35. package/src/preferences.defaults.json +78 -78
  36. package/src/preferences.mjs +438 -438
  37. package/src/preferences.test.mjs +174 -174
  38. package/src/record-evidence.mjs +204 -204
  39. package/src/repo-root.mjs +33 -0
  40. package/src/resolve-model.mjs +312 -312
  41. package/src/resolve-model.test.mjs +194 -194
  42. package/src/review/cli.test.mjs +117 -117
  43. package/src/review/export.mjs +172 -172
  44. package/src/review/export.test.mjs +197 -197
  45. package/src/review/fixtures/valid-review.json +42 -42
  46. package/src/review/lib.mjs +894 -894
  47. package/src/review/lib.test.mjs +266 -266
  48. package/src/review/schema.json +196 -196
  49. package/src/review/signals.test.mjs +62 -62
  50. package/src/score-cli.mjs +68 -68
  51. package/src/score.mjs +568 -568
  52. package/src/score.test.mjs +366 -366
  53. package/src/session-reminder.mjs +207 -207
  54. package/src/session-status.mjs +70 -70
  55. package/src/set-models.mjs +186 -186
  56. package/src/set-phase.mjs +205 -205
  57. package/src/set-prefs.mjs +294 -294
  58. package/src/specs-sync.mjs +232 -0
  59. package/src/specs-sync.test.mjs +114 -0
  60. package/src/spine.mjs +93 -93
  61. package/src/triage-prompt.mjs +175 -175
  62. package/src/triage-prompt.test.mjs +50 -50
  63. package/src/vendor-openspec-overlays.mjs +176 -176
  64. package/src/vendor-openspec-overlays.test.mjs +62 -62
  65. package/vendor/skills/archive-to-adr/SKILL.md +149 -149
  66. package/vendor/skills/forge/SKILL.md +136 -136
  67. package/vendor/skills/forge/docs/forge.md +650 -647
  68. package/vendor/skills/forge/phases/brainstorm.md +23 -23
  69. package/vendor/skills/forge/phases/finish.md +90 -87
  70. package/vendor/skills/forge/phases/implement.md +77 -77
  71. package/vendor/skills/forge/phases/plan-openspec.md +60 -60
  72. package/vendor/skills/forge/phases/plan-specs.md +163 -117
  73. package/vendor/skills/forge/phases/review.md +25 -25
  74. package/vendor/skills/forge/phases/verify.md +124 -124
  75. package/vendor/skills/forge/references/forge-layout.md +85 -85
  76. package/vendor/skills/forge/references/pace.md +115 -115
  77. package/vendor/skills/forge/references/plan-routing.md +52 -51
  78. package/vendor/skills/forge/references/runtime-integrity.md +232 -232
  79. package/vendor/skills/forge/references/substantial-work.md +37 -37
  80. package/vendor/skills/forge/references/test-evidence.md +30 -30
  81. package/vendor/skills/forge/references/test-strategy.md +68 -68
  82. package/vendor/skills/forge/skills/subagent-driven-development/SKILL.md +87 -87
  83. package/vendor/skills/forge/subagents/final-reviewer-prompt.md +56 -56
  84. package/vendor/skills/forge/subagents/implementer-prompt.md +38 -38
  85. package/vendor/skills/git-resolve-adr-conflict/SKILL.md +132 -132
  86. package/vendor/skills/thorough-code-review/SKILL.md +290 -290
  87. package/vendor/skills/thorough-code-review/examples.md +133 -133
  88. package/vendor/skills/thorough-code-review/reference/accepted-risks.md +26 -26
  89. package/vendor/skills/thorough-code-review/reference/lenses.md +96 -96
  90. package/vendor/skills/thorough-code-review/reference/phase1-scout.md +62 -62
  91. package/vendor/skills/thorough-code-review/reference/phase2-skeptic.md +105 -105
  92. package/vendor/skills/thorough-code-review/reference/report-schema.json +222 -222
  93. package/vendor/skills/thorough-code-review/reference/report-template.md +115 -115
  94. package/vendor/skills/thorough-code-review/reference/severity-rubric.md +49 -49
  95. package/vendor/skills/thorough-code-review/reference/signals-preflight.md +55 -55
  96. package/vendor/templates/adr/README.md +7 -7
  97. package/vendor/templates/adr/decisions.md +141 -141
  98. package/vendor/templates/adr/hooks/check-pending-adrs.mjs +74 -74
  99. package/vendor/templates/adr/hooks/check-pending-adrs.sh +3 -3
  100. package/vendor/templates/adr/hooks/openspec-archive-agent-message.mjs +52 -52
  101. package/vendor/templates/adr/hooks/openspec-archive-agent-message.sh +3 -3
  102. package/vendor/templates/project/claude/commands/forge-apply.md +75 -75
  103. package/vendor/templates/project/claude/commands/forge-brainstorm.md +7 -7
  104. package/vendor/templates/project/claude/commands/forge-build.md +17 -17
  105. package/vendor/templates/project/claude/commands/forge-plan.md +12 -12
  106. package/vendor/templates/project/claude/commands/forge-skip.md +14 -14
  107. package/vendor/templates/project/claude/commands/forge-status.md +16 -16
  108. package/vendor/templates/project/claude/commands/forge.md +16 -16
  109. package/vendor/templates/project/claude/hooks/forge-prompt-hook.mjs +73 -73
  110. package/vendor/templates/project/claude/hooks/forge-session-start.mjs +19 -19
  111. package/vendor/templates/project/claude/hooks/forge-triage-hook.mjs +77 -77
  112. package/vendor/templates/project/cursor/commands/forge-apply.md +75 -75
  113. package/vendor/templates/project/cursor/commands/forge-brainstorm.md +10 -10
  114. package/vendor/templates/project/cursor/commands/forge-build.md +17 -17
  115. package/vendor/templates/project/cursor/commands/forge-plan.md +15 -15
  116. package/vendor/templates/project/cursor/commands/forge-skip.md +14 -14
  117. package/vendor/templates/project/cursor/commands/forge-status.md +16 -16
  118. package/vendor/templates/project/cursor/commands/forge.md +16 -16
  119. package/vendor/templates/project/cursor/hooks/forge-session-start.mjs +30 -30
  120. package/vendor/templates/project/cursor/hooks/forge-session-start.sh +3 -3
@@ -1,141 +1,141 @@
1
- # Architecture decision records (ADRs)
2
-
3
- > How this project captures **architectural** decisions. ADRs live next to OpenSpec
4
- > archives. Scaffolded by Forgekit (`forge init --adr` / `forgekit install` with ADRs on).
5
-
6
- ADR directory for this project: **`{{ADR_DIR}}`** (configured in `.forge/config.json`).
7
-
8
- ---
9
-
10
- ## 1. Why ADRs *and* OpenSpec archives?
11
-
12
- They overlap in “why we did something,” but they serve different lookups:
13
-
14
- | OpenSpec archive (verbose) | ADR (short) |
15
- | -------------------------- | ----------- |
16
- | `proposal.md`, `design.md`, `tasks.md`, specs | One file, one sharpened decision |
17
- | “Replay the implementation story” | “Why is X shaped this way?” |
18
-
19
- ---
20
-
21
- ## 2. When to write an ADR
22
-
23
- | Write an ADR when the change … | Skip the ADR when … |
24
- | ------------------------------ | ------------------- |
25
- | Establishes or moves a boundary | Bug fix / copy / docs-only |
26
- | Chooses among real alternatives | Refactor that changes no decision |
27
- | Adds a constraint future code must follow | Chore rename without semantics |
28
- | Picks a costly-to-swap vendor or protocol | Narrow feature inside a prior ADR |
29
- | Codifies a convention across the repo | Noise would drown readers |
30
-
31
- If you’re listing code edits, that belongs in `design.md`—not an ADR.
32
-
33
- ---
34
-
35
- ## 3. Format (`{{ADR_DIR}}/NNNN-short-topic.md`)
36
-
37
- ```markdown
38
- # NNNN. <Short, decision-shaped title>
39
-
40
- - **Status**: Proposed | Accepted | Superseded by ADR-NNNN (…)
41
- - **Date**: YYYY-MM-DD
42
- - **Area**: <product or layer>
43
- - **Related**: openspec/changes/archive/<change>/, …
44
-
45
- ## Context
46
-
47
- One paragraph: pressure or constraint forcing a decision.
48
-
49
- ## Decision
50
-
51
- One imperative paragraph stating what this project commits to.
52
-
53
- ## Alternatives considered
54
-
55
- - **Option A** — rejected because …
56
- - **Chosen** — …
57
-
58
- ## Consequences
59
-
60
- ### Positive
61
- ### Negative
62
- ### Neutral
63
-
64
- ## References
65
-
66
- - Archive: openspec/changes/archive/<name>/
67
- ```
68
-
69
- Keep ADRs terse (roughly tens to low hundreds of lines each).
70
-
71
- ---
72
-
73
- ## 4. Numbering
74
-
75
- - Sequential `NNNN`; never recycle numbers—supersede with a **new** ADR.
76
- - Prefer decision-shaped filenames: `0004-outbox-only-on-critical-path.md` not `0004-add-worker.md`.
77
-
78
- All ADRs sit under **`{{ADR_DIR}}/`** even when scoped to one area—the decision
79
- usually crosses layers.
80
-
81
- ---
82
-
83
- ## 5. Status index (`{{ADR_DIR}}/README.md`)
84
-
85
- Maintain the table of `#`, Title, Status, Date. Leave placeholder rows until real ADRs land.
86
-
87
- ---
88
-
89
- ## 6. Cross-link OpenSpec ↔ ADRs
90
-
91
- ADR **References** should point at the dated archive folder.
92
-
93
- Archived `proposal.md` should gain:
94
-
95
- ```markdown
96
- ## Decision record
97
-
98
- This change is recorded as ADR-NNNN ({{ADR_DIR}}/NNNN-short-topic.md).
99
- ```
100
-
101
- Or, for non-architectural archives, the one-line stamp:
102
-
103
- ```text
104
- No ADR — non-architectural change
105
- ```
106
-
107
- Capability specs may cite ADRs as normative “why.”
108
-
109
- ---
110
-
111
- ## 7. ADRs in agent retrieval
112
-
113
- Short, focused ADRs embed well. **Do not** add `{{ADR_DIR}}/` to
114
- `.cursorindexignore` (or equivalent).
115
-
116
- ---
117
-
118
- ## 7a. Hooks: archive → ADR
119
-
120
- When ADR wiring is enabled, archive hooks remind agents to run **archive-to-adr**
121
- after `openspec archive` or a move into `openspec/changes/archive/YYYY-MM-DD-…`.
122
-
123
- Session-start backstops list archives whose `proposal.md` lacks `ADR-[0-9]` **and**
124
- lacks the `No ADR — non-architectural change` stamp.
125
-
126
- ---
127
-
128
- ## 8. Maintenance habit
129
-
130
- - On each meaningful archive: decide ADR vs stamp.
131
- - Periodically skim the index for stale status.
132
- - Supersede with new ADRs—don’t delete old ones.
133
-
134
- ---
135
-
136
- ## 9. TL;DR
137
-
138
- - ADRs **distill** decisions; OpenSpec archives keep the **full** story.
139
- - Use this file + `{{ADR_DIR}}/README.md` + `{{ADR_DIR}}/NNNN-*.md`.
140
- - Cross-link archives and ADRs both directions.
141
- - After archive: run **archive-to-adr** (or stamp “No ADR”).
1
+ # Architecture decision records (ADRs)
2
+
3
+ > How this project captures **architectural** decisions. ADRs live next to OpenSpec
4
+ > archives. Scaffolded by Forgekit (`forge init --adr` / `forgekit install` with ADRs on).
5
+
6
+ ADR directory for this project: **`{{ADR_DIR}}`** (configured in `.forge/config.json`).
7
+
8
+ ---
9
+
10
+ ## 1. Why ADRs *and* OpenSpec archives?
11
+
12
+ They overlap in “why we did something,” but they serve different lookups:
13
+
14
+ | OpenSpec archive (verbose) | ADR (short) |
15
+ | -------------------------- | ----------- |
16
+ | `proposal.md`, `design.md`, `tasks.md`, specs | One file, one sharpened decision |
17
+ | “Replay the implementation story” | “Why is X shaped this way?” |
18
+
19
+ ---
20
+
21
+ ## 2. When to write an ADR
22
+
23
+ | Write an ADR when the change … | Skip the ADR when … |
24
+ | ------------------------------ | ------------------- |
25
+ | Establishes or moves a boundary | Bug fix / copy / docs-only |
26
+ | Chooses among real alternatives | Refactor that changes no decision |
27
+ | Adds a constraint future code must follow | Chore rename without semantics |
28
+ | Picks a costly-to-swap vendor or protocol | Narrow feature inside a prior ADR |
29
+ | Codifies a convention across the repo | Noise would drown readers |
30
+
31
+ If you’re listing code edits, that belongs in `design.md`—not an ADR.
32
+
33
+ ---
34
+
35
+ ## 3. Format (`{{ADR_DIR}}/NNNN-short-topic.md`)
36
+
37
+ ```markdown
38
+ # NNNN. <Short, decision-shaped title>
39
+
40
+ - **Status**: Proposed | Accepted | Superseded by ADR-NNNN (…)
41
+ - **Date**: YYYY-MM-DD
42
+ - **Area**: <product or layer>
43
+ - **Related**: openspec/changes/archive/<change>/, …
44
+
45
+ ## Context
46
+
47
+ One paragraph: pressure or constraint forcing a decision.
48
+
49
+ ## Decision
50
+
51
+ One imperative paragraph stating what this project commits to.
52
+
53
+ ## Alternatives considered
54
+
55
+ - **Option A** — rejected because …
56
+ - **Chosen** — …
57
+
58
+ ## Consequences
59
+
60
+ ### Positive
61
+ ### Negative
62
+ ### Neutral
63
+
64
+ ## References
65
+
66
+ - Archive: openspec/changes/archive/<name>/
67
+ ```
68
+
69
+ Keep ADRs terse (roughly tens to low hundreds of lines each).
70
+
71
+ ---
72
+
73
+ ## 4. Numbering
74
+
75
+ - Sequential `NNNN`; never recycle numbers—supersede with a **new** ADR.
76
+ - Prefer decision-shaped filenames: `0004-outbox-only-on-critical-path.md` not `0004-add-worker.md`.
77
+
78
+ All ADRs sit under **`{{ADR_DIR}}/`** even when scoped to one area—the decision
79
+ usually crosses layers.
80
+
81
+ ---
82
+
83
+ ## 5. Status index (`{{ADR_DIR}}/README.md`)
84
+
85
+ Maintain the table of `#`, Title, Status, Date. Leave placeholder rows until real ADRs land.
86
+
87
+ ---
88
+
89
+ ## 6. Cross-link OpenSpec ↔ ADRs
90
+
91
+ ADR **References** should point at the dated archive folder.
92
+
93
+ Archived `proposal.md` should gain:
94
+
95
+ ```markdown
96
+ ## Decision record
97
+
98
+ This change is recorded as ADR-NNNN ({{ADR_DIR}}/NNNN-short-topic.md).
99
+ ```
100
+
101
+ Or, for non-architectural archives, the one-line stamp:
102
+
103
+ ```text
104
+ No ADR — non-architectural change
105
+ ```
106
+
107
+ Capability specs may cite ADRs as normative “why.”
108
+
109
+ ---
110
+
111
+ ## 7. ADRs in agent retrieval
112
+
113
+ Short, focused ADRs embed well. **Do not** add `{{ADR_DIR}}/` to
114
+ `.cursorindexignore` (or equivalent).
115
+
116
+ ---
117
+
118
+ ## 7a. Hooks: archive → ADR
119
+
120
+ When ADR wiring is enabled, archive hooks remind agents to run **archive-to-adr**
121
+ after `openspec archive` or a move into `openspec/changes/archive/YYYY-MM-DD-…`.
122
+
123
+ Session-start backstops list archives whose `proposal.md` lacks `ADR-[0-9]` **and**
124
+ lacks the `No ADR — non-architectural change` stamp.
125
+
126
+ ---
127
+
128
+ ## 8. Maintenance habit
129
+
130
+ - On each meaningful archive: decide ADR vs stamp.
131
+ - Periodically skim the index for stale status.
132
+ - Supersede with new ADRs—don’t delete old ones.
133
+
134
+ ---
135
+
136
+ ## 9. TL;DR
137
+
138
+ - ADRs **distill** decisions; OpenSpec archives keep the **full** story.
139
+ - Use this file + `{{ADR_DIR}}/README.md` + `{{ADR_DIR}}/NNNN-*.md`.
140
+ - Cross-link archives and ADRs both directions.
141
+ - After archive: run **archive-to-adr** (or stamp “No ADR”).
@@ -1,74 +1,74 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Pending-ADR backstop: list archived proposals missing ADR link and No-ADR stamp.
4
- * Honors .forge/config.json adr.enabled === false.
5
- *
6
- * Usage: node check-pending-adrs.mjs [repoRoot]
7
- */
8
-
9
- import fs from 'node:fs';
10
- import path from 'node:path';
11
- import { spawnSync } from 'node:child_process';
12
-
13
- function gitRoot() {
14
- const r = spawnSync('git', ['rev-parse', '--show-toplevel'], {
15
- encoding: 'utf8',
16
- shell: process.platform === 'win32',
17
- });
18
- if (r.status !== 0) return null;
19
- return String(r.stdout || '').trim() || null;
20
- }
21
-
22
- function loadConfig(cwd) {
23
- const p = path.join(cwd, '.forge', 'config.json');
24
- if (!fs.existsSync(p)) return {};
25
- try {
26
- return JSON.parse(fs.readFileSync(p, 'utf8'));
27
- } catch {
28
- return {};
29
- }
30
- }
31
-
32
- function listProposals(cwd, archiveRoot) {
33
- const dir = path.join(cwd, ...archiveRoot.split('/'));
34
- if (!fs.existsSync(dir)) return [];
35
- /** @type {string[]} */
36
- const out = [];
37
- for (const name of fs.readdirSync(dir)) {
38
- const proposal = path.join(dir, name, 'proposal.md');
39
- if (fs.existsSync(proposal)) out.push(proposal);
40
- }
41
- return out;
42
- }
43
-
44
- const cwd = process.argv[2] || gitRoot();
45
- if (!cwd) process.exit(0);
46
-
47
- const cfg = loadConfig(cwd);
48
- if (cfg.adr && cfg.adr.enabled === false) process.exit(0);
49
-
50
- const archives = [
51
- 'openspec/changes/archive',
52
- `${(cfg.plan && typeof cfg.plan === 'object' && cfg.plan.dir) || 'specs'}/changes/archive`,
53
- ];
54
- /** @type {string[]} */
55
- const pending = [];
56
- for (const root of archives) {
57
- for (const proposal of listProposals(cwd, root)) {
58
- const body = fs.readFileSync(proposal, 'utf8');
59
- if (/ADR-[0-9]/.test(body)) continue;
60
- if (body.includes('No ADR — non-architectural change')) continue;
61
- pending.push(path.relative(cwd, proposal).replace(/\\/g, '/'));
62
- }
63
- }
64
-
65
- if (pending.length === 0) process.exit(0);
66
-
67
- const shown = pending.slice(0, 10).join('\n');
68
- process.stdout.write(
69
- `Archived changes whose proposal.md does not reference an ADR yet:\n\n${shown}\n\n` +
70
- `If any had architectural impact, run the archive-to-adr skill.\n` +
71
- `Otherwise add a one-line stamp to each proposal.md:\n` +
72
- ` 'No ADR — non-architectural change'\n`,
73
- );
74
- process.exit(0);
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Pending-ADR backstop: list archived proposals missing ADR link and No-ADR stamp.
4
+ * Honors .forge/config.json adr.enabled === false.
5
+ *
6
+ * Usage: node check-pending-adrs.mjs [repoRoot]
7
+ */
8
+
9
+ import fs from 'node:fs';
10
+ import path from 'node:path';
11
+ import { spawnSync } from 'node:child_process';
12
+
13
+ function gitRoot() {
14
+ const r = spawnSync('git', ['rev-parse', '--show-toplevel'], {
15
+ encoding: 'utf8',
16
+ shell: process.platform === 'win32',
17
+ });
18
+ if (r.status !== 0) return null;
19
+ return String(r.stdout || '').trim() || null;
20
+ }
21
+
22
+ function loadConfig(cwd) {
23
+ const p = path.join(cwd, '.forge', 'config.json');
24
+ if (!fs.existsSync(p)) return {};
25
+ try {
26
+ return JSON.parse(fs.readFileSync(p, 'utf8'));
27
+ } catch {
28
+ return {};
29
+ }
30
+ }
31
+
32
+ function listProposals(cwd, archiveRoot) {
33
+ const dir = path.join(cwd, ...archiveRoot.split('/'));
34
+ if (!fs.existsSync(dir)) return [];
35
+ /** @type {string[]} */
36
+ const out = [];
37
+ for (const name of fs.readdirSync(dir)) {
38
+ const proposal = path.join(dir, name, 'proposal.md');
39
+ if (fs.existsSync(proposal)) out.push(proposal);
40
+ }
41
+ return out;
42
+ }
43
+
44
+ const cwd = process.argv[2] || gitRoot();
45
+ if (!cwd) process.exit(0);
46
+
47
+ const cfg = loadConfig(cwd);
48
+ if (cfg.adr && cfg.adr.enabled === false) process.exit(0);
49
+
50
+ const archives = [
51
+ 'openspec/changes/archive',
52
+ `${(cfg.plan && typeof cfg.plan === 'object' && cfg.plan.dir) || 'specs'}/changes/archive`,
53
+ ];
54
+ /** @type {string[]} */
55
+ const pending = [];
56
+ for (const root of archives) {
57
+ for (const proposal of listProposals(cwd, root)) {
58
+ const body = fs.readFileSync(proposal, 'utf8');
59
+ if (/ADR-[0-9]/.test(body)) continue;
60
+ if (body.includes('No ADR — non-architectural change')) continue;
61
+ pending.push(path.relative(cwd, proposal).replace(/\\/g, '/'));
62
+ }
63
+ }
64
+
65
+ if (pending.length === 0) process.exit(0);
66
+
67
+ const shown = pending.slice(0, 10).join('\n');
68
+ process.stdout.write(
69
+ `Archived changes whose proposal.md does not reference an ADR yet:\n\n${shown}\n\n` +
70
+ `If any had architectural impact, run the archive-to-adr skill.\n` +
71
+ `Otherwise add a one-line stamp to each proposal.md:\n` +
72
+ ` 'No ADR — non-architectural change'\n`,
73
+ );
74
+ process.exit(0);
@@ -1,3 +1,3 @@
1
- #!/usr/bin/env bash
2
- # Thin wrapper around the Node implementation.
3
- exec node "$(dirname "$0")/check-pending-adrs.mjs" "$@"
1
+ #!/usr/bin/env bash
2
+ # Thin wrapper around the Node implementation.
3
+ exec node "$(dirname "$0")/check-pending-adrs.mjs" "$@"
@@ -1,52 +1,52 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Agent reminder after a successful change archive (stdout only).
4
- * Usage: node openspec-archive-agent-message.mjs <change-slug>
5
- */
6
-
7
- import fs from 'node:fs';
8
- import path from 'node:path';
9
-
10
- const changeName = process.argv[2];
11
- if (!changeName) {
12
- process.stderr.write('Usage: openspec-archive-agent-message.mjs <change-slug>\n');
13
- process.exit(1);
14
- }
15
-
16
- let adrDir = 'docs/adr';
17
- let decisionsDoc = 'docs/decisions.md';
18
- let archiveRoot = 'openspec/changes/archive';
19
- let adrEnabled = true;
20
-
21
- const cfgPath = path.join(process.cwd(), '.forge', 'config.json');
22
- if (fs.existsSync(cfgPath)) {
23
- try {
24
- const c = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
25
- if (c.plan?.engine === 'specs') {
26
- archiveRoot = `${c.plan.dir || 'specs'}/changes/archive`;
27
- }
28
- if (c.adr?.enabled === false) adrEnabled = false;
29
- if (c.adr?.dir) adrDir = c.adr.dir;
30
- if (c.adr?.decisionsDoc) decisionsDoc = c.adr.decisionsDoc;
31
- } catch {
32
- // keep defaults
33
- }
34
- }
35
-
36
- if (!adrEnabled) {
37
- process.stdout.write(
38
- `Change '${changeName}' was archived. ADRs are disabled for this project\n` +
39
- `(\`.forge/config.json\` → adr.enabled: false). No archive-to-adr follow-up.\n\n` +
40
- `Suggested commit (display only — do NOT commit unless the user asks):\n\n` +
41
- `openspec: archive ${changeName}\n`,
42
- );
43
- process.exit(0);
44
- }
45
-
46
- process.stdout.write(
47
- `Change '${changeName}' was just archived.\n\n` +
48
- `1. archive-to-adr: locate ${archiveRoot}/YYYY-MM-DD-${changeName}/, open proposal.md, and evaluate an ADR (${decisionsDoc}). If yes: ${adrDir}/NNNN-<topic>.md, update ${adrDir}/README.md, add a ## Decision record to proposal.md. If no: add one line to proposal.md: No ADR — non-architectural change.\n\n` +
49
- `2. Suggested commit (display only — do NOT run git commit / push / gh pr create unless the user explicitly asks):\n\n` +
50
- `openspec: archive ${changeName}\n`,
51
- );
52
- process.exit(0);
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Agent reminder after a successful change archive (stdout only).
4
+ * Usage: node openspec-archive-agent-message.mjs <change-slug>
5
+ */
6
+
7
+ import fs from 'node:fs';
8
+ import path from 'node:path';
9
+
10
+ const changeName = process.argv[2];
11
+ if (!changeName) {
12
+ process.stderr.write('Usage: openspec-archive-agent-message.mjs <change-slug>\n');
13
+ process.exit(1);
14
+ }
15
+
16
+ let adrDir = 'docs/adr';
17
+ let decisionsDoc = 'docs/decisions.md';
18
+ let archiveRoot = 'openspec/changes/archive';
19
+ let adrEnabled = true;
20
+
21
+ const cfgPath = path.join(process.cwd(), '.forge', 'config.json');
22
+ if (fs.existsSync(cfgPath)) {
23
+ try {
24
+ const c = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
25
+ if (c.plan?.engine === 'specs') {
26
+ archiveRoot = `${c.plan.dir || 'specs'}/changes/archive`;
27
+ }
28
+ if (c.adr?.enabled === false) adrEnabled = false;
29
+ if (c.adr?.dir) adrDir = c.adr.dir;
30
+ if (c.adr?.decisionsDoc) decisionsDoc = c.adr.decisionsDoc;
31
+ } catch {
32
+ // keep defaults
33
+ }
34
+ }
35
+
36
+ if (!adrEnabled) {
37
+ process.stdout.write(
38
+ `Change '${changeName}' was archived. ADRs are disabled for this project\n` +
39
+ `(\`.forge/config.json\` → adr.enabled: false). No archive-to-adr follow-up.\n\n` +
40
+ `Suggested commit (display only — do NOT commit unless the user asks):\n\n` +
41
+ `openspec: archive ${changeName}\n`,
42
+ );
43
+ process.exit(0);
44
+ }
45
+
46
+ process.stdout.write(
47
+ `Change '${changeName}' was just archived.\n\n` +
48
+ `1. archive-to-adr: locate ${archiveRoot}/YYYY-MM-DD-${changeName}/, open proposal.md, and evaluate an ADR (${decisionsDoc}). If yes: ${adrDir}/NNNN-<topic>.md, update ${adrDir}/README.md, add a ## Decision record to proposal.md. If no: add one line to proposal.md: No ADR — non-architectural change.\n\n` +
49
+ `2. Suggested commit (display only — do NOT run git commit / push / gh pr create unless the user explicitly asks):\n\n` +
50
+ `openspec: archive ${changeName}\n`,
51
+ );
52
+ process.exit(0);
@@ -1,3 +1,3 @@
1
- #!/usr/bin/env bash
2
- # Thin wrapper around the Node implementation.
3
- exec node "$(dirname "$0")/openspec-archive-agent-message.mjs" "$@"
1
+ #!/usr/bin/env bash
2
+ # Thin wrapper around the Node implementation.
3
+ exec node "$(dirname "$0")/openspec-archive-agent-message.mjs" "$@"