voidforge-build 23.18.0 → 23.20.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/dist/.claude/agents/celebrimbor-forge-artist.md +1 -0
- package/dist/.claude/agents/ducem-token-economics.md +1 -0
- package/dist/.claude/agents/galadriel-frontend.md +1 -0
- package/dist/.claude/agents/romanoff-integrations.md +4 -0
- package/dist/.claude/agents/silver-surfer-herald.md +19 -4
- package/dist/.claude/commands/architect.md +4 -3
- package/dist/.claude/commands/assemble.md +12 -0
- package/dist/.claude/commands/assess.md +1 -0
- package/dist/.claude/commands/build.md +8 -0
- package/dist/.claude/commands/contextmeter.md +56 -0
- package/dist/.claude/commands/debrief.md +10 -0
- package/dist/.claude/commands/engage.md +5 -0
- package/dist/.claude/commands/git.md +13 -1
- package/dist/.claude/commands/imagine.md +1 -1
- package/dist/.claude/commands/seal.md +80 -0
- package/dist/.claude/commands/ux.md +13 -0
- package/dist/.claude/workflows/assemble-review.workflow.js +26 -6
- package/dist/.claude/workflows/gauntlet.workflow.js +59 -12
- package/dist/CHANGELOG.md +73 -0
- package/dist/CLAUDE.md +9 -1
- package/dist/HOLOCRON.md +16 -2
- package/dist/VERSION.md +3 -1
- package/dist/docs/methods/AI_INTELLIGENCE.md +3 -0
- package/dist/docs/methods/ASSEMBLER.md +12 -0
- package/dist/docs/methods/BUILD_PROTOCOL.md +7 -0
- package/dist/docs/methods/CAMPAIGN.md +11 -0
- package/dist/docs/methods/DEVOPS_ENGINEER.md +56 -0
- package/dist/docs/methods/FIELD_MEDIC.md +1 -0
- package/dist/docs/methods/FORGE_ARTIST.md +3 -4
- package/dist/docs/methods/GAUNTLET.md +6 -0
- package/dist/docs/methods/MUSTER.md +2 -0
- package/dist/docs/methods/PRODUCT_DESIGN_FRONTEND.md +18 -0
- package/dist/docs/methods/QA_ENGINEER.md +17 -1
- package/dist/docs/methods/RELEASE_MANAGER.md +27 -0
- package/dist/docs/methods/SECURITY_AUDITOR.md +11 -1
- package/dist/docs/methods/SUB_AGENTS.md +31 -0
- package/dist/docs/methods/SYSTEMS_ARCHITECT.md +15 -0
- package/dist/docs/methods/TESTING.md +2 -0
- package/dist/docs/methods/TROUBLESHOOTING.md +2 -2
- package/dist/docs/methods/WORKFLOWS.md +18 -2
- package/dist/docs/patterns/ai-prompt-safety.ts +85 -0
- package/dist/docs/patterns/data-pipeline.ts +59 -1
- package/dist/docs/patterns/exclusion-set-invariant.md +62 -0
- package/dist/docs/patterns/multi-tenant-property-test.ts +64 -0
- package/dist/docs/patterns/oauth-token-lifecycle.ts +21 -0
- package/dist/scripts/statusline/README.md +38 -0
- package/dist/scripts/statusline/context-awareness-hook.sh +53 -0
- package/dist/scripts/statusline/settings-snippet.json +17 -0
- package/dist/scripts/statusline/voidforge-statusline.sh +91 -0
- package/dist/scripts/voidforge.js +69 -6
- package/dist/wizard/lib/claude-md-strategy.d.ts +87 -0
- package/dist/wizard/lib/claude-md-strategy.js +198 -0
- package/dist/wizard/lib/marker.d.ts +48 -1
- package/dist/wizard/lib/marker.js +58 -2
- package/dist/wizard/lib/patterns/oauth-token-lifecycle.d.ts +14 -0
- package/dist/wizard/lib/patterns/oauth-token-lifecycle.js +21 -0
- package/dist/wizard/lib/project-init.js +77 -0
- package/dist/wizard/lib/updater.d.ts +19 -0
- package/dist/wizard/lib/updater.js +91 -33
- package/package.json +2 -2
|
@@ -2,11 +2,29 @@
|
|
|
2
2
|
* Update mechanisms — methodology update (replaces /void git-fetch),
|
|
3
3
|
* self-update, and extension update.
|
|
4
4
|
*/
|
|
5
|
-
import { readFile, readdir, cp } from 'node:fs/promises';
|
|
5
|
+
import { readFile, readdir, cp, writeFile } from 'node:fs/promises';
|
|
6
6
|
import { existsSync } from 'node:fs';
|
|
7
7
|
import { join } from 'node:path';
|
|
8
8
|
import { execSync } from 'node:child_process';
|
|
9
|
-
import { readMarker, writeMarker } from './marker.js';
|
|
9
|
+
import { readMarker, writeMarker, DEFAULT_CLAUDE_MD_STRATEGY } from './marker.js';
|
|
10
|
+
import { planClaudeMdUpdate, UPSTREAM_SUFFIX } from './claude-md-strategy.js';
|
|
11
|
+
/**
|
|
12
|
+
* Decide which `update` mode the given argv selects. Pure — no I/O, no exit.
|
|
13
|
+
*
|
|
14
|
+
* Help MUST win over every action flag (issue #368): `update --help` printed
|
|
15
|
+
* usage but the OLD router fell through and EXECUTED the (destructive) update.
|
|
16
|
+
* Centralizing the precedence here makes that ordering testable and keeps the
|
|
17
|
+
* CLI from re-introducing the bug.
|
|
18
|
+
*/
|
|
19
|
+
export function resolveUpdateMode(args) {
|
|
20
|
+
if (args.includes('--help') || args.includes('-h'))
|
|
21
|
+
return 'help';
|
|
22
|
+
if (args.includes('--self'))
|
|
23
|
+
return 'self';
|
|
24
|
+
if (args.includes('--extensions'))
|
|
25
|
+
return 'extensions';
|
|
26
|
+
return 'methodology';
|
|
27
|
+
}
|
|
10
28
|
// ── Methodology Source Resolution ────────────────────────
|
|
11
29
|
async function resolveMethodologySource() {
|
|
12
30
|
const dir = import.meta.dirname ?? new URL('.', import.meta.url).pathname;
|
|
@@ -47,6 +65,23 @@ async function collectFiles(dir, base = '') {
|
|
|
47
65
|
}
|
|
48
66
|
return files;
|
|
49
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Compute the non-destructive CLAUDE.md plan for a project (issue #368).
|
|
70
|
+
* Reads the marker's `claudeMd` strategy (default 'preserve') and delegates the
|
|
71
|
+
* decision to the pure planner. Returns null only when there is no upstream
|
|
72
|
+
* CLAUDE.md to apply.
|
|
73
|
+
*/
|
|
74
|
+
async function planClaudeMd(sourceRoot, projectDir) {
|
|
75
|
+
const srcPath = join(sourceRoot, 'CLAUDE.md');
|
|
76
|
+
if (!existsSync(srcPath))
|
|
77
|
+
return null;
|
|
78
|
+
const upstream = await readFile(srcPath, 'utf-8');
|
|
79
|
+
const destPath = join(projectDir, 'CLAUDE.md');
|
|
80
|
+
const current = existsSync(destPath) ? await readFile(destPath, 'utf-8') : null;
|
|
81
|
+
const marker = await readMarker(projectDir);
|
|
82
|
+
const strategy = marker?.claudeMd ?? DEFAULT_CLAUDE_MD_STRATEGY;
|
|
83
|
+
return planClaudeMdUpdate(current, upstream, strategy);
|
|
84
|
+
}
|
|
50
85
|
/**
|
|
51
86
|
* Diff methodology source against project files.
|
|
52
87
|
* Returns a plan showing what would change.
|
|
@@ -58,12 +93,43 @@ export async function diffMethodology(projectDir) {
|
|
|
58
93
|
const dirs = [
|
|
59
94
|
{ src: '.claude/commands', dest: '.claude/commands' },
|
|
60
95
|
{ src: '.claude/agents', dest: '.claude/agents' },
|
|
96
|
+
// Dynamic Workflow scripts (ADR-067) and the Silver Surfer gate (ADR-051/060/064):
|
|
97
|
+
// both ship to new projects via init but were absent from the updater's diff list, so
|
|
98
|
+
// `npx voidforge-build update` never propagated them — existing projects were stranded
|
|
99
|
+
// on whatever gate/workflow scripts they were created with (e.g. a gate before this
|
|
100
|
+
// release's reap fix). Invocation is via `bash <script>` so exec bits are not required.
|
|
101
|
+
{ src: '.claude/workflows', dest: '.claude/workflows' },
|
|
61
102
|
{ src: 'docs/methods', dest: 'docs/methods' },
|
|
62
103
|
{ src: 'docs/patterns', dest: 'docs/patterns' },
|
|
63
104
|
{ src: 'scripts/thumper', dest: 'scripts/thumper' },
|
|
105
|
+
{ src: 'scripts/surfer-gate', dest: 'scripts/surfer-gate' },
|
|
106
|
+
// Context-meter status line + awareness hook (/contextmeter). Scripts propagate on
|
|
107
|
+
// update; activation (statusLine + UserPromptSubmit hook in settings.json) stays opt-in.
|
|
108
|
+
{ src: 'scripts/statusline', dest: 'scripts/statusline' },
|
|
64
109
|
];
|
|
65
|
-
//
|
|
66
|
-
|
|
110
|
+
// CLAUDE.md is handled via the non-destructive strategy mechanism (issue #368)
|
|
111
|
+
// — never the old "preserve first 10 lines, overwrite the rest" clobber.
|
|
112
|
+
const claudeMdPlan = await planClaudeMd(sourceRoot, projectDir);
|
|
113
|
+
if (claudeMdPlan) {
|
|
114
|
+
plan.claudeMd = {
|
|
115
|
+
action: claudeMdPlan.action,
|
|
116
|
+
droppedSections: claudeMdPlan.droppedSections,
|
|
117
|
+
warnings: claudeMdPlan.warnings,
|
|
118
|
+
sideFile: claudeMdPlan.sideFileContent !== null ? `CLAUDE.md${UPSTREAM_SUFFIX}` : undefined,
|
|
119
|
+
};
|
|
120
|
+
if (claudeMdPlan.action === 'unchanged' || claudeMdPlan.action === 'skip') {
|
|
121
|
+
plan.unchanged++;
|
|
122
|
+
}
|
|
123
|
+
else if (claudeMdPlan.action === 'side-file') {
|
|
124
|
+
// The side file is the only thing that changes; CLAUDE.md itself is untouched.
|
|
125
|
+
plan.modified.push(`CLAUDE.md${UPSTREAM_SUFFIX}`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
plan.modified.push('CLAUDE.md');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Other single files compare/copy verbatim (no special preservation needed).
|
|
132
|
+
const singleFiles = ['HOLOCRON.md', 'VERSION.md'];
|
|
67
133
|
// Check single files
|
|
68
134
|
for (const file of singleFiles) {
|
|
69
135
|
const srcPath = join(sourceRoot, file);
|
|
@@ -76,21 +142,10 @@ export async function diffMethodology(projectDir) {
|
|
|
76
142
|
else {
|
|
77
143
|
const srcContent = await readFile(srcPath, 'utf-8');
|
|
78
144
|
const destContent = await readFile(destPath, 'utf-8');
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (srcLines !== destLines)
|
|
84
|
-
plan.modified.push(file);
|
|
85
|
-
else
|
|
86
|
-
plan.unchanged++;
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
if (srcContent !== destContent)
|
|
90
|
-
plan.modified.push(file);
|
|
91
|
-
else
|
|
92
|
-
plan.unchanged++;
|
|
93
|
-
}
|
|
145
|
+
if (srcContent !== destContent)
|
|
146
|
+
plan.modified.push(file);
|
|
147
|
+
else
|
|
148
|
+
plan.unchanged++;
|
|
94
149
|
}
|
|
95
150
|
}
|
|
96
151
|
// Check directories
|
|
@@ -146,24 +201,27 @@ export async function applyUpdate(projectDir) {
|
|
|
146
201
|
if (plan.added.length === 0 && plan.modified.length === 0) {
|
|
147
202
|
return { applied: false, plan, newVersion };
|
|
148
203
|
}
|
|
204
|
+
// CLAUDE.md: apply the non-destructive strategy decision (issue #368).
|
|
205
|
+
// Never overwrite a customized CLAUDE.md in place. `preserve` writes a side
|
|
206
|
+
// file; `merge` replaces only the fenced block; `skip` does nothing.
|
|
207
|
+
const claudeMdPlan = await planClaudeMd(sourceRoot, projectDir);
|
|
208
|
+
const claudeMdDestPath = join(projectDir, 'CLAUDE.md');
|
|
209
|
+
if (claudeMdPlan) {
|
|
210
|
+
if (claudeMdPlan.claudeMdContent !== null) {
|
|
211
|
+
await writeFile(claudeMdDestPath, claudeMdPlan.claudeMdContent, 'utf-8');
|
|
212
|
+
}
|
|
213
|
+
if (claudeMdPlan.sideFileContent !== null) {
|
|
214
|
+
await writeFile(`${claudeMdDestPath}${UPSTREAM_SUFFIX}`, claudeMdPlan.sideFileContent, 'utf-8');
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// The CLAUDE.md plan entries are handled above — exclude them from the
|
|
218
|
+
// generic verbatim copy loop so we don't double-write or clobber.
|
|
219
|
+
const claudeMdEntries = new Set(['CLAUDE.md', `CLAUDE.md${UPSTREAM_SUFFIX}`]);
|
|
149
220
|
// Copy added + modified files
|
|
150
221
|
const { mkdir } = await import('node:fs/promises');
|
|
151
222
|
for (const file of [...plan.added, ...plan.modified]) {
|
|
152
|
-
|
|
153
|
-
if (file === 'CLAUDE.md') {
|
|
154
|
-
const srcContent = await readFile(join(sourceRoot, file), 'utf-8');
|
|
155
|
-
const destPath = join(projectDir, file);
|
|
156
|
-
if (existsSync(destPath)) {
|
|
157
|
-
const destContent = await readFile(destPath, 'utf-8');
|
|
158
|
-
const destIdentity = destContent.split('\n').slice(0, 10).join('\n');
|
|
159
|
-
const srcBody = srcContent.split('\n').slice(10).join('\n');
|
|
160
|
-
await import('node:fs/promises').then(fs => fs.writeFile(destPath, destIdentity + '\n' + srcBody, 'utf-8'));
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
await cp(join(sourceRoot, file), destPath);
|
|
164
|
-
}
|
|
223
|
+
if (claudeMdEntries.has(file))
|
|
165
224
|
continue;
|
|
166
|
-
}
|
|
167
225
|
const srcPath = join(sourceRoot, file);
|
|
168
226
|
const destPath = join(projectDir, file);
|
|
169
227
|
const destDir = join(destPath, '..');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "voidforge-build",
|
|
3
|
-
"version": "23.
|
|
3
|
+
"version": "23.20.0",
|
|
4
4
|
"description": "From nothing, everything. A methodology framework for building with Claude Code.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@aws-sdk/client-rds": "^3.700.0",
|
|
46
46
|
"@aws-sdk/client-s3": "^3.700.0",
|
|
47
47
|
"@aws-sdk/client-sts": "^3.700.0",
|
|
48
|
-
"voidforge-build-methodology": "^23.
|
|
48
|
+
"voidforge-build-methodology": "^23.20.0",
|
|
49
49
|
"node-pty": "^1.2.0-beta.12",
|
|
50
50
|
"ws": "^8.19.0"
|
|
51
51
|
},
|