voidforge-build 23.11.1 → 23.11.2

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/CHANGELOG.md CHANGED
@@ -6,6 +6,31 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
6
6
 
7
7
  ---
8
8
 
9
+ ## [23.11.2] - 2026-05-12
10
+
11
+ ### `voidforge init` mode prompt + methodology surfer-gate distribution
12
+
13
+ Two threads of polish: the CLI now asks before launching, and the Silver Surfer gate finally ships in the methodology npm package.
14
+
15
+ ### Added
16
+
17
+ - **`voidforge init` mode prompt.** With no flag, `init` now asks "Browser wizard or CLI (headless)?" instead of silently launching the browser server. Prompt appears only when stdin is a TTY.
18
+ - **`--browser` flag on `voidforge init`.** Explicit opt-in to the wizard UI — skips the prompt for users (or scripts) that want the prior default behavior.
19
+ - **Interactive headless init.** `voidforge init --headless` now prompts for project name (required), directory (defaulted to `~/Projects/<slug>`), and optional oneliner/domain/repo when `--name` is omitted in a TTY. Fully non-interactive when all flags are passed.
20
+ - **`packages/methodology/scripts/surfer-gate/`** (8 files) — the Silver Surfer PreToolUse hook scripts (`check.sh`, `record-roster.sh`, `bypass.sh`, `_paths.sh`, `validate.sh`, `test.sh`, `README.md`, `settings-snippet.json`) now ship via the `voidforge-build-methodology` npm package, closing the ADR-051 distribution gap (#317). Previously the scripts lived only at the repo root and never reached downstream projects via `npx voidforge-build update`.
21
+ - **9 pattern-table rows** in `packages/methodology/CLAUDE.md` — propagates the v23.11.0 pattern additions (adr-verification-gate, multi-tenant-property-test, multi-tenant-pool-bypass, rls-test-fixture, structural-sql-sentinel, audit-log, refactor-extraction, ai-prompt-safety, llm-state-dedup) into the methodology package copy so they reach downstream projects.
22
+
23
+ ### Changed
24
+
25
+ - **Non-TTY `voidforge init` without a flag** now exits with a clear error directing the user to `--browser` or `--headless`. Previously it silently launched a wizard server into a context where no browser would ever open — a latent bug.
26
+ - **Surfer Gate orchestrator-contract bash commands** in `packages/methodology/CLAUDE.md` are now wrapped in `[ -x ... ] && ... || true` existence guards with documented fallback ("if the script does not exist, your project predates v23.10.0; pull the gate or re-run `npx voidforge-build init`"). Lets the methodology cleanly cover both pre-#317 and post-#317 projects.
27
+
28
+ ### Why this exists
29
+
30
+ The init server-launch was the loudest "this CLI doesn't ask before doing things" surface in onboarding — first-run users got a server URL with no opportunity to choose CLI mode. Two flags (`--browser`, `--headless`) now span the choice; the bare command asks. Separately, the surfer-gate scripts had been documented as shipping in the methodology package since v23.11.0 changelog #317, but the scripts themselves were never copied into `packages/methodology/`. This release actually ships them.
31
+
32
+ ---
33
+
9
34
  ## [23.11.1] - 2026-05-10
10
35
 
11
36
  ### `/git` release-discipline patch — close the silent-release gap
package/dist/VERSION.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Version
2
2
 
3
- **Current:** 23.11.1
3
+ **Current:** 23.11.2
4
4
 
5
5
  ## Versioning Scheme
6
6
 
@@ -14,6 +14,7 @@ This project uses [Semantic Versioning](https://semver.org/):
14
14
 
15
15
  | Version | Date | Summary |
16
16
  |---------|------|---------|
17
+ | 23.11.2 | 2026-05-12 | `voidforge init` now prompts browser-vs-CLI when no mode flag is passed (TTY only) and `--browser` was added for explicit opt-in. Headless init prompts for name/dir/oneliner/domain/repo when `--name` is omitted in a TTY. Non-TTY no-flag now errors cleanly instead of silently launching a wizard server. Separately: `packages/methodology/scripts/surfer-gate/` (8 files) now ships in the npm methodology package — closes ADR-051 distribution gap (#317). 9 pattern-table rows + existence-guarded orchestrator-contract bash propagated into the methodology CLAUDE.md. |
17
18
  | 23.11.1 | 2026-05-10 | `/git` release-discipline patch — Step 4.5 (auto-tag, default-on) and Step 7 (`--npm` opt-in publish). Closes the silent-release gap that stranded v23.10.0 and v23.11.0 between GitHub and npm. Tag-push triggers the existing `publish.yml` workflow; `--npm` is a same-session fallback. Documents the `latest` dist-tag race when multiple tags are pushed simultaneously. RELEASE_MANAGER.md mirrored. |
18
19
  | 23.11.0 | 2026-05-10 | Field Report Triage — 18 reports closed (#313-#320, #322-#330). Two combined batches across multi-tenant retrofit campaigns (#313-#320) and autonomous-mode + AI-execution campaigns (#322-#330). 9 new patterns: adr-verification-gate.md, audit-log.ts, multi-tenant-{pool-bypass,property-test}.ts, rls-test-fixture.py, structural-sql-sentinel.py, refactor-extraction.md, ai-prompt-safety.ts, llm-state-dedup.ts. ai-eval.ts extended with Claude-prompt-eval template. middleware.ts extended with hot-path logging gate. 18 method-doc sections across CAMPAIGN, SYSTEMS_ARCHITECT, SECURITY_AUDITOR, QA_ENGINEER, SUB_AGENTS, BACKEND_ENGINEER, RELEASE_MANAGER, GAUNTLET, AI_INTELLIGENCE, DEVOPS_ENGINEER, FORGE_KEEPER, TESTING, TIME_VAULT. Surfer Gate now ships via npm methodology package + wizard project-init (closes ADR-051 distribution gap #317). Operational learnings added to Picard, Sisko, Coulson, Bashir, Loki, Irulan, Silver Surfer. |
19
20
  | 23.10.0 | 2026-04-20 | Field Report Triage — 6 reports closed (#303-#308). 33 approved fixes: SPEC_HANDOFF.md (new method doc), deploy-preflight.ts + post-deploy-probe.sh (new patterns), LEARNINGS LRN-5..10, Deploy Surface Boundary + Deployment Hygiene (field report #305 remediation), Step 2.5 pre-deploy secret scan + Step 4.5 post-deploy probe, TECH_DEBT SLA, npm-name pre-flight, ADR-050 Rename Verification Checklist, Silver Surfer HARD CONSTRAINT + 4 agent operational learnings. |
@@ -3,8 +3,10 @@
3
3
  * VoidForge CLI — v21.0 The Extraction
4
4
  *
5
5
  * npx voidforge Launch wizard (browser UI at :3141)
6
- * npx voidforge init Create new project (Gandalf flow)
7
- * npx voidforge init --headless Create project without browser
6
+ * npx voidforge init Create new project prompts: browser or CLI
7
+ * npx voidforge init --browser Skip the prompt, go straight to the browser wizard
8
+ * npx voidforge init --headless Create project without browser (CLI prompts for name/dir)
9
+ * npx voidforge init --headless --name "X" Fully non-interactive CLI init
8
10
  * npx voidforge init --core Minimal methodology (no Holocron, no patterns)
9
11
  * npx voidforge update Update project methodology (Bombadil)
10
12
  * npx voidforge update --self Update the wizard itself
@@ -3,8 +3,10 @@
3
3
  * VoidForge CLI — v21.0 The Extraction
4
4
  *
5
5
  * npx voidforge Launch wizard (browser UI at :3141)
6
- * npx voidforge init Create new project (Gandalf flow)
7
- * npx voidforge init --headless Create project without browser
6
+ * npx voidforge init Create new project prompts: browser or CLI
7
+ * npx voidforge init --browser Skip the prompt, go straight to the browser wizard
8
+ * npx voidforge init --headless Create project without browser (CLI prompts for name/dir)
9
+ * npx voidforge init --headless --name "X" Fully non-interactive CLI init
8
10
  * npx voidforge init --core Minimal methodology (no Holocron, no patterns)
9
11
  * npx voidforge update Update project methodology (Bombadil)
10
12
  * npx voidforge update --self Update the wizard itself
@@ -167,6 +169,41 @@ async function launchWizard(mode = 'init') {
167
169
  if (!isRemote && !isLan)
168
170
  await openBrowser(url);
169
171
  }
172
+ function slugifyName(name) {
173
+ return name.replace(/[^a-zA-Z0-9-_ ]/g, '').replace(/\s+/g, '-').toLowerCase();
174
+ }
175
+ function defaultProjectDir(name) {
176
+ return join(process.env['HOME'] ?? process.env['USERPROFILE'] ?? '.', 'Projects', slugifyName(name));
177
+ }
178
+ async function prompt(question) {
179
+ const { createInterface } = await import('node:readline');
180
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
181
+ return new Promise((res) => {
182
+ rl.question(question, (answer) => { rl.close(); res(answer.trim()); });
183
+ });
184
+ }
185
+ /**
186
+ * Asks the user to pick browser vs headless mode for `voidforge init`.
187
+ * Requires a TTY — caller must guard with process.stdin.isTTY.
188
+ */
189
+ async function promptInitMode() {
190
+ console.log('');
191
+ console.log(' VoidForge — init');
192
+ console.log('');
193
+ console.log(' How would you like to set up this project?');
194
+ console.log(' 1) Browser wizard (Gandalf) — interactive, guided UI');
195
+ console.log(' 2) CLI (headless) — prompts here in the terminal');
196
+ console.log('');
197
+ // Loop until we get a valid answer.
198
+ for (;;) {
199
+ const answer = (await prompt(' Choice [1]: ')).toLowerCase();
200
+ if (answer === '' || answer === '1' || answer === 'b' || answer === 'browser')
201
+ return 'browser';
202
+ if (answer === '2' || answer === 'c' || answer === 'cli' || answer === 'h' || answer === 'headless')
203
+ return 'headless';
204
+ console.log(' Please enter 1 (browser) or 2 (CLI).');
205
+ }
206
+ }
170
207
  async function cmdInitHeadless() {
171
208
  const nameFlag = args.find((a, i) => args[i - 1] === '--name');
172
209
  const dirFlag = args.find((a, i) => args[i - 1] === '--dir');
@@ -174,25 +211,61 @@ async function cmdInitHeadless() {
174
211
  const domainFlag = args.find((a, i) => args[i - 1] === '--domain');
175
212
  const repoFlag = args.find((a, i) => args[i - 1] === '--repo');
176
213
  const isCore = args.includes('--core');
177
- if (!nameFlag) {
178
- console.error('Error: --name is required for headless init.');
179
- console.error('Usage: npx voidforge init --headless --name "My Project" [--dir path] [--oneliner "..."]');
180
- process.exit(1);
214
+ let name = nameFlag;
215
+ let directory = dirFlag;
216
+ let oneliner = onelinerFlag;
217
+ let domain = domainFlag;
218
+ let repoUrl = repoFlag;
219
+ // If --name is missing, prompt interactively (TTY only).
220
+ if (!name) {
221
+ if (!process.stdin.isTTY) {
222
+ console.error('Error: --name is required for headless init in non-interactive contexts.');
223
+ console.error('Usage: npx voidforge init --headless --name "My Project" [--dir path] [--oneliner "..."]');
224
+ process.exit(1);
225
+ }
226
+ console.log('');
227
+ console.log(' VoidForge — Headless Init');
228
+ console.log(' Press Enter to accept defaults shown in [brackets]. Optional fields can be left blank.');
229
+ console.log('');
230
+ while (!name) {
231
+ const answer = await prompt(' Project name: ');
232
+ if (answer)
233
+ name = answer;
234
+ else
235
+ console.log(' Project name is required.');
236
+ }
237
+ const defaultDir = defaultProjectDir(name);
238
+ if (!directory) {
239
+ const answer = await prompt(` Directory [${defaultDir}]: `);
240
+ directory = answer || defaultDir;
241
+ }
242
+ if (!oneliner) {
243
+ const answer = await prompt(' One-line description (optional): ');
244
+ oneliner = answer || undefined;
245
+ }
246
+ if (!domain) {
247
+ const answer = await prompt(' Domain (optional): ');
248
+ domain = answer || undefined;
249
+ }
250
+ if (!repoUrl) {
251
+ const answer = await prompt(' Repo URL (optional): ');
252
+ repoUrl = answer || undefined;
253
+ }
181
254
  }
182
- const defaultDir = join(process.env['HOME'] ?? process.env['USERPROFILE'] ?? '.', 'Projects', nameFlag.replace(/[^a-zA-Z0-9-_ ]/g, '').replace(/\s+/g, '-').toLowerCase());
183
- const directory = dirFlag ?? defaultDir;
255
+ if (!directory)
256
+ directory = defaultProjectDir(name);
184
257
  const { createProject } = await import('../wizard/lib/project-init.js');
185
258
  const result = await createProject({
186
- name: nameFlag,
259
+ name,
187
260
  directory,
188
- oneliner: onelinerFlag,
189
- domain: domainFlag,
190
- repoUrl: repoFlag,
261
+ oneliner,
262
+ domain,
263
+ repoUrl,
191
264
  core: isCore,
192
265
  });
193
266
  console.log('');
194
267
  console.log(` VoidForge — Project Created`);
195
- console.log(` Name: ${nameFlag}`);
268
+ console.log(` Name: ${name}`);
196
269
  console.log(` Directory: ${result.projectDir}`);
197
270
  console.log(` Files: ${result.filesCreated} methodology files`);
198
271
  console.log(` Marker: ${result.markerId}`);
@@ -293,7 +366,8 @@ function showHelp() {
293
366
  console.log(' --help, -h Show this help');
294
367
  console.log(' --remote Launch in remote mode (0.0.0.0 + auth)');
295
368
  console.log(' --lan Launch in LAN mode');
296
- console.log(' --headless CLI-only (no browser)');
369
+ console.log(' --browser init: skip the mode prompt and launch the browser wizard');
370
+ console.log(' --headless init: CLI-only flow (prompts for name/dir if not passed)');
297
371
  console.log(' --self Deploy VoidForge itself');
298
372
  console.log(' --env-only Write vault credentials to .env');
299
373
  console.log('');
@@ -536,14 +610,29 @@ async function main() {
536
610
  console.log(' To rollback: restore from the backup directory.\n');
537
611
  break;
538
612
  }
539
- case 'init':
540
- if (args.includes('--headless')) {
613
+ case 'init': {
614
+ const wantsHeadless = args.includes('--headless');
615
+ const wantsBrowser = args.includes('--browser');
616
+ if (wantsHeadless) {
541
617
  await cmdInitHeadless();
542
618
  }
543
- else {
619
+ else if (wantsBrowser) {
544
620
  await launchWizard('init');
545
621
  }
622
+ else if (process.stdin.isTTY) {
623
+ const mode = await promptInitMode();
624
+ if (mode === 'headless')
625
+ await cmdInitHeadless();
626
+ else
627
+ await launchWizard('init');
628
+ }
629
+ else {
630
+ console.error('Error: `voidforge init` was run in a non-interactive context without a mode flag.');
631
+ console.error('Pass --browser to launch the wizard UI, or --headless [--name "..."] for CLI init.');
632
+ process.exit(1);
633
+ }
546
634
  break;
635
+ }
547
636
  case 'heartbeat': {
548
637
  const subCmd = args[1]; // start | stop | status
549
638
  if (subCmd !== 'start') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "voidforge-build",
3
- "version": "23.11.1",
3
+ "version": "23.11.2",
4
4
  "description": "From nothing, everything. A methodology framework for building with Claude Code.",
5
5
  "type": "module",
6
6
  "engines": {