roadmapsmith 0.9.32 → 0.9.34

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roadmapsmith",
3
- "version": "0.9.32",
3
+ "version": "0.9.34",
4
4
  "description": "Evidence-backed ROADMAP.md workflows for AI coding agents, with canonical RoadmapSmith status and maintain surfaces plus advanced sync/generate tools and legacy compatibility aliases.",
5
5
  "author": {
6
6
  "name": "PapiScholz"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roadmapsmith",
3
- "version": "0.9.32",
3
+ "version": "0.9.34",
4
4
  "description": "Evidence-backed ROADMAP.md workflows for AI coding agents, with canonical RoadmapSmith status and maintain surfaces plus advanced sync/generate tools and legacy compatibility aliases.",
5
5
  "author": {
6
6
  "name": "PapiScholz"
package/README.md CHANGED
@@ -8,7 +8,7 @@ This package owns the RoadmapSmith CLI, validator, sync engine, host setup files
8
8
 
9
9
  - `roadmapsmith setup`
10
10
  - `roadmapsmith zero`
11
- - `roadmapsmith maintain`
11
+ - `roadmapsmith maintain [--dry-run]`
12
12
  - `roadmapsmith status [--json]`
13
13
  - `roadmapsmith validate [--json] [--strict]`
14
14
  - `roadmapsmith update [--task <stable-id> --evidence "<single-line evidence>"]`
@@ -40,11 +40,39 @@ This package owns the RoadmapSmith CLI, validator, sync engine, host setup files
40
40
 
41
41
  ### Zero Mode
42
42
 
43
- Use for empty or low-context repositories. `roadmapsmith zero` runs the terminal interview, updates config, and generates the first roadmap.
43
+ Use for empty or low-context repositories. `roadmapsmith zero` runs the terminal interview when TTY is available, or consumes a complete brief from config plus flags in non-interactive environments.
44
+
45
+ Non-interactive inputs:
46
+
47
+ - `--product-name`
48
+ - `--primary-user`
49
+ - `--problem-statement`
50
+ - `--target-outcome`
51
+ - `--anti-goal` (repeatable)
52
+ - `--preferred-stack`
53
+ - `--constraint` (repeatable)
54
+ - `--done-criterion` (repeatable)
55
+
56
+ Without TTY, Zero Mode requires a complete brief from config/flags and fails clearly when required fields are missing.
44
57
 
45
58
  ### Sync/Audit Mode
46
59
 
47
- Use for repositories that already contain code, tests, docs, TODOs, or an existing roadmap. `roadmapsmith maintain` is the preserve-first one-command flow.
60
+ Use for repositories that already contain code, tests, docs, TODOs, or an existing roadmap. `roadmapsmith maintain` is the preserve-first one-command flow for an existing managed roadmap block.
61
+
62
+ If `ROADMAP.md` is authored and non-empty but has no `<!-- rs:managed:* -->` block:
63
+
64
+ - `maintain` refuses to seed managed content implicitly
65
+ - `update` is the conservative inline-annotation path
66
+ - `generate` is the explicit managed-section creation path
67
+
68
+ For write-capable surfaces (`maintain`, `generate`, `sync`, `update`), prefer `--dry-run` first.
69
+
70
+ ## Managed Block Ownership
71
+
72
+ - `maintain` owns the managed roadmap block only.
73
+ - `update` can annotate existing task lines even when no managed block exists.
74
+ - `generate` is the explicit path that creates or replaces managed roadmap content.
75
+ - Manually inserting empty `<!-- rs:managed:start -->` markers is no longer required as a workaround.
48
76
 
49
77
  ## Verification Model
50
78
 
package/bin/cli.js CHANGED
@@ -14,14 +14,21 @@ const { generateRoadmapDocument } = require('../src/generator');
14
14
  const { parseRoadmap, tasksInManagedBlock } = require('../src/parser');
15
15
  const { buildValidationContext, validateTasks, auditValidation, CONFIDENCE_RANK, applyMinimumConfidence } = require('../src/validator');
16
16
  const { applySync } = require('../src/sync');
17
- const { buildZeroModeConfigPatch, buildZeroModeDefaults, collectZeroModeAnswers, isInteractiveTerminal } = require('../src/zero');
17
+ const {
18
+ buildZeroModeConfigPatch,
19
+ collectZeroModeAnswers,
20
+ formatMissingZeroModeFields,
21
+ getMissingZeroModeFields,
22
+ isInteractiveTerminal,
23
+ resolveZeroModeAnswers
24
+ } = require('../src/zero');
18
25
 
19
26
  function printHelp() {
20
27
  console.log([
21
28
  'Usage:',
22
29
  ' Canonical commands:',
23
- ' roadmapsmith zero [--project-root <path>] [--config <path>]',
24
- ' roadmapsmith maintain [--project-root <path>] [--config <path>] [--roadmap-file <path>] [--full-regen] [--refresh-annotations]',
30
+ ' roadmapsmith zero [--project-root <path>] [--config <path>] [--product-name <text>] [--primary-user <text>] [--problem-statement <text>] [--target-outcome <text>] [--anti-goal <text> ...] [--preferred-stack <text>] [--constraint <text> ...] [--done-criterion <text> ...]',
31
+ ' roadmapsmith maintain [--project-root <path>] [--config <path>] [--roadmap-file <path>] [--dry-run] [--full-regen] [--refresh-annotations]',
25
32
  ' roadmapsmith status [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--json]',
26
33
  ' roadmapsmith validate [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--task <id|text>] [--json] [--strict]',
27
34
  ' roadmapsmith update [--task <stable-id> --evidence <text>] [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--dry-run]',
@@ -140,6 +147,42 @@ function formatSetupVerb(result, dryRun) {
140
147
  return result.before == null ? 'Created' : 'Updated';
141
148
  }
142
149
 
150
+ function emitPreWriteWarning(roadmapFile, options = {}) {
151
+ if (options.dryRun || options.suppressWarning) {
152
+ return;
153
+ }
154
+ if (options.warningState && options.warningState.emitted) {
155
+ return;
156
+ }
157
+
158
+ const commandName = options.commandName || 'roadmapsmith';
159
+ console.log(`Warning: ${commandName} will modify ${roadmapFile}. Review the preview first with --dry-run.`);
160
+ if (options.managedSectionNote) {
161
+ console.log(options.managedSectionNote);
162
+ }
163
+
164
+ if (options.warningState) {
165
+ options.warningState.emitted = true;
166
+ }
167
+ }
168
+
169
+ function assertMaintainCanWrite(roadmapFile, content) {
170
+ if (content == null || String(content).trim().length === 0) {
171
+ return;
172
+ }
173
+
174
+ const parsed = parseRoadmap(content);
175
+ if (parsed.hasManagedBlock) {
176
+ return;
177
+ }
178
+
179
+ throw new Error(
180
+ `Refusing to let roadmapsmith maintain seed a managed section into an authored roadmap without <!-- rs:managed:start --> markers: ${roadmapFile}\n` +
181
+ 'For conservative inline annotations, run `roadmapsmith update --dry-run` then `roadmapsmith update`.\n' +
182
+ 'To intentionally create a managed section, run `roadmapsmith generate --dry-run` then `roadmapsmith generate`.'
183
+ );
184
+ }
185
+
143
186
  function runInitCommand(projectRoot, config, flags) {
144
187
  const roadmapFile = resolveRoadmapFile(projectRoot, config, flags['roadmap-file']);
145
188
  const agentsFile = resolveAgentsFile(projectRoot, config, flags['agents-file']);
@@ -187,6 +230,13 @@ function runGenerateCommand(projectRoot, config, flags, options = {}) {
187
230
  forceFullRegenerate: options.forceFullRegenerate === true || isEnabled(flags['full-regen'])
188
231
  });
189
232
 
233
+ emitPreWriteWarning(roadmapFile, {
234
+ commandName: options.commandName || 'roadmapsmith generate',
235
+ dryRun,
236
+ suppressWarning: options.suppressPreWriteWarning,
237
+ warningState: options.warningState,
238
+ managedSectionNote: 'This command may create or replace a managed roadmap section depending on the current file state and flags.'
239
+ });
190
240
  const writeResult = writeText(roadmapFile, document, { dryRun });
191
241
  if (dryRun) {
192
242
  if (writeResult.changed) {
@@ -229,6 +279,12 @@ function runSyncCommand(projectRoot, config, flags, options = {}) {
229
279
  const forceRefresh = isEnabled(flags['refresh-annotations']);
230
280
  const next = applySync(content, syncTasks, results, { forceRefresh });
231
281
  const dryRun = isEnabled(flags['dry-run']);
282
+ emitPreWriteWarning(roadmapFile, {
283
+ commandName: options.commandName || 'roadmapsmith sync',
284
+ dryRun,
285
+ suppressWarning: options.suppressPreWriteWarning,
286
+ warningState: options.warningState
287
+ });
232
288
  const writeResult = writeText(roadmapFile, next, { dryRun });
233
289
 
234
290
  if (dryRun) {
@@ -266,7 +322,7 @@ function runUpdateCommand(projectRoot, config, flags) {
266
322
  const hasTask = flags.task != null;
267
323
  const hasEvidence = flags.evidence != null;
268
324
  if (!hasTask && !hasEvidence) {
269
- runSyncCommand(projectRoot, config, flags);
325
+ runSyncCommand(projectRoot, config, flags, { commandName: 'roadmapsmith update' });
270
326
  return;
271
327
  }
272
328
  if (!hasTask || !hasEvidence || Array.isArray(flags.task) || Array.isArray(flags.evidence)) {
@@ -306,6 +362,10 @@ function runUpdateCommand(projectRoot, config, flags) {
306
362
 
307
363
  const next = applySync(draft, [draftTask], { [taskId]: result });
308
364
  const dryRun = isEnabled(flags['dry-run']);
365
+ emitPreWriteWarning(roadmapFile, {
366
+ commandName: 'roadmapsmith update',
367
+ dryRun
368
+ });
309
369
  const writeResult = writeText(roadmapFile, next, { dryRun });
310
370
  if (dryRun) {
311
371
  if (writeResult.changed) {
@@ -371,40 +431,69 @@ function runStatusCommand(projectRoot, config, flags, options = {}) {
371
431
  async function runZeroCommand(projectRoot, flags) {
372
432
  const configPath = resolveConfigPath({ projectRoot, configPath: flags.config });
373
433
  const config = loadConfig({ projectRoot, configPath: flags.config });
374
- if (!isInteractiveTerminal(process.stdin, process.stdout)) {
375
- throw new Error('Zero Mode requires an interactive terminal. Run roadmapsmith zero from a terminal session, or add a config/brief workflow before retrying in non-interactive mode.');
434
+ const roadmapFile = resolveRoadmapFile(projectRoot, config, flags['roadmap-file']);
435
+ const roadmapExistedBeforeInit = fs.existsSync(roadmapFile);
436
+ const defaults = resolveZeroModeAnswers(projectRoot, config, flags);
437
+ const interactive = isInteractiveTerminal(process.stdin, process.stdout);
438
+ let answers = defaults;
439
+
440
+ if (!interactive) {
441
+ const missingFields = getMissingZeroModeFields(defaults);
442
+ if (missingFields.length > 0) {
443
+ throw new Error(
444
+ 'Zero Mode requires a complete brief in non-interactive environments. Missing: ' +
445
+ `${formatMissingZeroModeFields(missingFields).join(', ')}. ` +
446
+ 'Provide the missing values with CLI flags or in roadmap-skill.config.json before retrying.'
447
+ );
448
+ }
449
+ console.log('RoadmapSmith Zero Mode');
450
+ console.log('Using config/flag discovery inputs in non-interactive mode.\n');
451
+ } else {
452
+ const rl = readline.createInterface({
453
+ input: process.stdin,
454
+ output: process.stdout
455
+ });
456
+
457
+ try {
458
+ console.log('RoadmapSmith Zero Mode');
459
+ console.log('Answer the discovery interview to generate the first roadmap.\n');
460
+ answers = await collectZeroModeAnswers((prompt) => rl.question(prompt), defaults);
461
+ } finally {
462
+ rl.close();
463
+ }
376
464
  }
377
465
 
378
- const defaults = buildZeroModeDefaults(projectRoot, config);
379
- const rl = readline.createInterface({
380
- input: process.stdin,
381
- output: process.stdout
466
+ const existingUserConfig = readUserConfig({ projectRoot, configPath: flags.config });
467
+ const nextUserConfig = buildZeroModeConfigPatch(projectRoot, existingUserConfig, answers);
468
+ writeText(configPath, JSON.stringify(nextUserConfig, null, 2));
469
+ console.log(`Updated ${configPath}`);
470
+ const nextConfig = loadConfig({ projectRoot, configPath: flags.config });
471
+ runInitCommand(projectRoot, nextConfig, flags);
472
+ runGenerateCommand(projectRoot, nextConfig, flags, {
473
+ commandName: 'roadmapsmith zero',
474
+ suppressPreWriteWarning: true,
475
+ forceFullRegenerate: !roadmapExistedBeforeInit
382
476
  });
383
-
384
- try {
385
- console.log('RoadmapSmith Zero Mode');
386
- console.log('Answer the discovery interview to generate the first roadmap.\n');
387
- const answers = await collectZeroModeAnswers((prompt) => rl.question(prompt), defaults);
388
- const existingUserConfig = readUserConfig({ projectRoot, configPath: flags.config });
389
- const nextUserConfig = buildZeroModeConfigPatch(projectRoot, existingUserConfig, answers);
390
- writeText(configPath, JSON.stringify(nextUserConfig, null, 2));
391
- console.log(`Updated ${configPath}`);
392
- const nextConfig = loadConfig({ projectRoot, configPath: flags.config });
393
- runInitCommand(projectRoot, nextConfig, flags);
394
- runGenerateCommand(projectRoot, nextConfig, flags);
395
- } finally {
396
- rl.close();
397
- }
398
477
  }
399
478
 
400
479
  function runMaintainCommand(projectRoot, flags) {
401
480
  const config = loadConfig({ projectRoot, configPath: flags.config });
481
+ const roadmapFile = resolveRoadmapFile(projectRoot, config, flags['roadmap-file']);
482
+ const existingContent = readTextIfExists(roadmapFile);
483
+ assertMaintainCanWrite(roadmapFile, existingContent);
402
484
  const fullRegen = isEnabled(flags['full-regen']);
485
+ const warningState = { emitted: false };
403
486
  runGenerateCommand(projectRoot, config, flags, {
487
+ commandName: 'roadmapsmith maintain',
404
488
  preserveManagedBlock: !fullRegen,
405
- forceFullRegenerate: fullRegen
489
+ forceFullRegenerate: fullRegen,
490
+ warningState
491
+ });
492
+ runSyncCommand(projectRoot, config, { ...flags, audit: true }, {
493
+ audit: true,
494
+ commandName: 'roadmapsmith maintain',
495
+ warningState
406
496
  });
407
- runSyncCommand(projectRoot, config, { ...flags, audit: true }, { audit: true });
408
497
  }
409
498
 
410
499
  async function run() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roadmapsmith",
3
- "version": "0.9.32",
3
+ "version": "0.9.34",
4
4
  "description": "Evidence-backed ROADMAP.md workflows for AI coding agents, with canonical RoadmapSmith status and maintain surfaces plus advanced sync/generate tools and legacy compatibility aliases.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -10,21 +10,14 @@ Use this command as the native discovery entrypoint for the shared RoadmapSmith
10
10
  ## Required behavior
11
11
 
12
12
  1. Treat `/roadmap` as a no-side-effects palette. Do not run mutating commands from this skill.
13
- 2. When working inside the RoadmapSmith repository itself and `roadmap-skill/bin/cli.js` exists, prefer the local engine:
14
- - `node roadmap-skill/bin/cli.js /roadmap`
15
- - on this Windows machine, prefer `C:\Program Files\nodejs\node.exe roadmap-skill/bin/cli.js /roadmap` if `node` is not in PATH
16
- 3. Otherwise, if the `roadmapsmith` CLI is available, you may run `roadmapsmith /roadmap` from the project root and use that output directly. If its global shim cannot resolve `node`, use `& "C:\Program Files\nodejs\node.exe" "$env:APPDATA\npm\node_modules\roadmapsmith\bin\cli.js" /roadmap`.
17
- 4. If the CLI is missing, provide the palette manually and explain the install path:
18
- - `npm install -g roadmapsmith`
19
- - `npx skills add PapiScholz/roadmapsmith --skill '*' -a claude-code`
20
- - run `/reload-skills`
21
- - if RoadmapSmith was installed as a Claude plugin, also run `/reload-plugins`
22
- 5. Explain the preferred native host entrypoints:
13
+ 2. If the `roadmapsmith` CLI is available, run `roadmapsmith /roadmap` from the project root and use that output directly.
14
+ 3. If the CLI is missing, direct the user to the official repository README for installation instructions.
15
+ 4. Explain the preferred native host entrypoints:
23
16
  - `/roadmap-zero`
24
17
  - `/roadmap-maintain`
25
18
  - `/roadmap-status`
26
19
  - `/roadmap-init`, `/roadmap-generate`, `/roadmap-validate`, `/roadmap-update`, `/roadmap-audit`, and `/roadmap-setup`
27
- 6. Mention that `/roadmap-sync <action>` remains a deprecated legacy CLI compatibility root, and `/road` plus `/road <action>` remain deprecated CLI compatibility aliases.
20
+ 5. Mention that `/roadmap-sync <action>` remains a deprecated legacy CLI compatibility root, and `/road` plus `/road <action>` remain deprecated CLI compatibility aliases.
28
21
 
29
22
  ## Output contract
30
23
 
@@ -9,8 +9,5 @@ Use this command when the user wants the post-sync mismatch summary after applyi
9
9
 
10
10
  ## Required behavior
11
11
 
12
- 1. Prefer the local engine inside this repository:
13
- - `node roadmap-skill/bin/cli.js sync --audit --project-root .`
14
- - on this Windows machine, prefer `C:\Program Files\nodejs\node.exe roadmap-skill/bin/cli.js sync --audit --project-root .` if `node` is not in PATH
15
- 2. Otherwise prefer `roadmapsmith sync --audit --project-root .`.
16
- 3. Explain that this is the current sync-plus-audit flow, not a standalone read-only audit engine.
12
+ 1. Run `roadmapsmith sync --audit --project-root .`.
13
+ 2. Explain that this is the current sync-plus-audit flow, not a standalone read-only audit engine.
@@ -9,10 +9,7 @@ Use this command when the user wants the managed roadmap block updated from repo
9
9
 
10
10
  ## Required behavior
11
11
 
12
- 1. Prefer the local engine inside this repository:
13
- - `node roadmap-skill/bin/cli.js generate --project-root .`
14
- - on this Windows machine, prefer `C:\Program Files\nodejs\node.exe roadmap-skill/bin/cli.js generate --project-root .` if `node` is not in PATH
15
- 2. Otherwise prefer `roadmapsmith generate --project-root .`.
16
- 3. Explain that `generate` is preserve-first when a substantive managed block already exists.
17
- 4. When the user explicitly wants the destructive path, use `roadmapsmith generate --project-root . --full-regen`.
18
- 5. Summarize what stayed preserved, whether generation refused, and what new additions, if any, were inserted.
12
+ 1. Run `roadmapsmith generate --project-root .`.
13
+ 2. Explain that `generate` is preserve-first when a substantive managed block already exists.
14
+ 3. To allow full roadmap regeneration, add `--full-regen`: `roadmapsmith generate --project-root . --full-regen`.
15
+ 4. Summarize what stayed preserved, whether generation refused, and what new additions, if any, were inserted.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: roadmap-init
3
- description: Create ROADMAP.md and AGENTS.md through the RoadmapSmith CLI.
3
+ description: Initialize project governance files through the RoadmapSmith CLI.
4
4
  ---
5
5
 
6
6
  # RoadmapSmith Init
@@ -9,8 +9,5 @@ Use this command when the governance files are missing and the user wants them c
9
9
 
10
10
  ## Required behavior
11
11
 
12
- 1. Prefer the local engine inside this repository:
13
- - `node roadmap-skill/bin/cli.js init --project-root .`
14
- - on this Windows machine, prefer `C:\Program Files\nodejs\node.exe roadmap-skill/bin/cli.js init --project-root .` if `node` is not in PATH
15
- 2. Otherwise prefer `roadmapsmith init`.
16
- 3. Treat this command as CLI-backed and summarize whether files were created or skipped.
12
+ 1. Run `roadmapsmith init`.
13
+ 2. Summarize whether files were created or skipped.
@@ -9,12 +9,8 @@ Use this command when the repository already has code, tests, docs, or an existi
9
9
 
10
10
  ## Required behavior
11
11
 
12
- 1. Prefer the local engine inside this repository:
13
- - `node roadmap-skill/bin/cli.js maintain --project-root .`
14
- - on this Windows machine, prefer `C:\Program Files\nodejs\node.exe roadmap-skill/bin/cli.js maintain --project-root .` if `node` is not in PATH
15
- 2. Otherwise prefer `roadmapsmith maintain --project-root .`. If that global shim fails because `node` is not in PATH, run `& "C:\Program Files\nodejs\node.exe" "$env:APPDATA\npm\node_modules\roadmapsmith\bin\cli.js" maintain --project-root .`.
16
- 3. Treat this command as CLI-backed. Do not silently replace it with manual reasoning when the CLI is unavailable.
17
- 4. Mention that maintain runs preserve-first generate, sync, and audit in one invocation.
12
+ 1. Run `roadmapsmith maintain --project-root .`. Prefer `--dry-run` first when previewing impact.
13
+ 2. Treat this command as CLI-backed. Do not silently replace it with manual reasoning when the CLI is unavailable.
14
+ 3. Mention that maintain runs preserve-first generate, sync, and audit in one invocation, but only for an existing managed roadmap block.
15
+ 4. If the roadmap is non-empty and lacks `<!-- rs:managed:* -->`, direct the user to `roadmapsmith update` for conservative inline annotations or `roadmapsmith generate` for explicit managed-section creation.
18
16
  5. After a successful maintain cycle, do not propose generate, sync, or audit separately unless the user needs manual control or inspection.
19
- 6. Mention that `roadmapsmith maintain --full-regen` or `roadmapsmith generate --full-regen` is the explicit destructive rebuild path when the user truly wants a full managed-block replacement.
20
- 7. When the user wants stale or outdated warning annotations to be recomputed from scratch (including annotations that were written by a prior maintain run or an external agent), use `roadmapsmith maintain --refresh-annotations`. This forces all existing warning text to be replaced with the current deterministic result rather than preserved. It is distinct from `--full-regen` (which rebuilds the managed block structure) — `--refresh-annotations` only affects warning annotations on still-failing tasks.
@@ -9,9 +9,6 @@ Use this command when the user wants RoadmapSmith host integration files generat
9
9
 
10
10
  ## Required behavior
11
11
 
12
- 1. Prefer the local engine inside this repository:
13
- - `node roadmap-skill/bin/cli.js setup --project-root . --hosts codex,claude`
14
- - on this Windows machine, prefer `C:\Program Files\nodejs\node.exe roadmap-skill/bin/cli.js setup --project-root . --hosts codex,claude` if `node` is not in PATH
15
- 2. Otherwise prefer `roadmapsmith setup --project-root . --hosts codex,claude`.
16
- 3. Explain that setup affects the repository host layer: VS Code tasks, launcher/wrappers, and the optional repo-local Claude hook.
17
- 4. Do not claim that setup alone creates native host slash commands; those come from the installed bundle/plugin.
12
+ 1. Run `roadmapsmith setup --project-root . --hosts codex,claude`.
13
+ 2. Explain that setup generates VS Code task definitions for the current repository.
14
+ 3. Do not claim that setup alone creates native host slash commands; those come from the installed bundle/plugin.
@@ -9,10 +9,7 @@ Use this command to inspect whether the shared bundle, native host surfaces, CLI
9
9
 
10
10
  ## Required behavior
11
11
 
12
- 1. Prefer the local engine inside this repository:
13
- - `node roadmap-skill/bin/cli.js status --json --project-root .`
14
- - on this Windows machine, prefer `C:\Program Files\nodejs\node.exe roadmap-skill/bin/cli.js status --json --project-root .` if `node` is not in PATH
15
- 2. Otherwise prefer `roadmapsmith status --json --project-root .`. If its global shim cannot resolve `node`, use `& "C:\Program Files\nodejs\node.exe" "$env:APPDATA\npm\node_modules\roadmapsmith\bin\cli.js" status --json --project-root .`.
16
- 3. Treat `roadmapsmith doctor --json` as compatibility-only output for existing automation, not as the primary recommendation.
12
+ 1. Run `roadmapsmith status --json --project-root .`.
13
+ 2. Treat `roadmapsmith doctor --json` as compatibility-only output for existing automation, not as the primary recommendation.
17
14
  4. Parse and summarize the JSON output in plain language.
18
15
  5. Explicitly call out missing canonical commands, duplicate legacy `/roadmap-sync` registration, and any missing advanced VS Code labels as warnings rather than canonical-readiness failures.
@@ -16,5 +16,5 @@ Use this skill only when the host exposes or the user explicitly invokes `/roadm
16
16
  - `/roadmap-maintain`
17
17
  - `/roadmap-status`
18
18
  - `/roadmap-init`, `/roadmap-generate`, `/roadmap-validate`, `/roadmap-update`, `/roadmap-audit`, and `/roadmap-setup`
19
- 3. When the user explicitly invokes `/roadmap-sync <action>`, route to the matching CLI-backed action without changing semantics and mention the migration path to `/roadmap <action>` or the direct `/roadmap-*` command.
20
- 4. Preserve the operating rules for evidence-backed roadmap maintenance and checklist synchronization: heuristic file/token matches may diagnose candidates, but only explicit `Evidence:` or typed `Verify:` checks may complete an unchecked implementation task. Never claim a behavioral task is complete without fresh test evidence or human verification.
19
+ 3. When the user explicitly invokes `/roadmap-sync <action>`, route to the matching CLI-backed action without changing semantics and mention the migration path to the direct `/roadmap-*` command.
20
+ 4. When routing `/roadmap-sync validate`, the tool uses the same validation rules as `/roadmap-validate`. Implementation tasks require an explicit `Evidence:` line or a `Verify:` check to be marked complete.
@@ -2,6 +2,6 @@
2
2
  "interface": {
3
3
  "display_name": "Roadmap Sync (Deprecated)",
4
4
  "short_description": "DEPRECATED legacy root; use /roadmap-maintain or /roadmap-update.",
5
- "default_prompt": "Prefer /roadmap, /roadmap-status, /roadmap-maintain, and /roadmap-update."
5
+ "default_prompt": "Prefer /roadmap, /roadmap-status, /roadmap-maintain, and /roadmap-update; use /roadmap-update when markers are missing."
6
6
  }
7
7
  }
@@ -9,10 +9,7 @@ Use this command when the user wants the canonical public `update` surface witho
9
9
 
10
10
  ## Required behavior
11
11
 
12
- 1. Prefer the local engine inside this repository:
13
- - `node roadmap-skill/bin/cli.js update --project-root .`
14
- - on this Windows machine, prefer `C:\Program Files\nodejs\node.exe roadmap-skill/bin/cli.js update --project-root .` if `node` is not in PATH
15
- 2. Otherwise prefer `roadmapsmith update --project-root .`. If its global shim fails because `node` is not in PATH, run `& "C:\Program Files\nodejs\node.exe" "$env:APPDATA\npm\node_modules\roadmapsmith\bin\cli.js" update --project-root .`.
16
- 3. Explain that `/roadmap-update` is the visible namespaced command for the public `update` family, while `/roadmap-sync <action>` remains deprecated compatibility only.
17
- 4. Keep the evidence-backed refresh semantics unchanged: no-argument `update` syncs the roadmap from repository evidence, and `sync` remains the advanced CLI alias for that same mutating refresh path. It is not a full regeneration path and not an independent audit engine.
18
- 5. To complete one task, run `roadmapsmith update --task <stable-id> --evidence "<single-line evidence>"`. It writes only after the supplied evidence validates at high confidence; use `--dry-run` to preview it.
12
+ 1. Run `roadmapsmith update --project-root .`.
13
+ 2. Explain that `/roadmap-update` is the visible namespaced command for the public `update` family, while `/roadmap-sync <action>` remains deprecated compatibility only.
14
+ 3. The no-argument `update` syncs the roadmap from repository evidence. The `sync` alias covers the same refresh path. It is not a full regeneration path and not an independent audit engine.
15
+ 4. To mark a specific task complete, run `roadmapsmith update --task TASK-ID --evidence "description"`. The CLI validates before writing; use `--dry-run` to preview.
@@ -9,8 +9,5 @@ Use this command when the user wants per-task evidence status without mutating t
9
9
 
10
10
  ## Required behavior
11
11
 
12
- 1. Prefer the local engine inside this repository:
13
- - `node roadmap-skill/bin/cli.js validate --json --project-root .`
14
- - on this Windows machine, prefer `C:\Program Files\nodejs\node.exe roadmap-skill/bin/cli.js validate --json --project-root .` if `node` is not in PATH
15
- 2. Otherwise prefer `roadmapsmith validate --json --project-root .`.
16
- 3. Treat this command as CLI-backed and non-mutating.
12
+ 1. Run `roadmapsmith validate --json --project-root .`.
13
+ 2. This command is non-mutating.
@@ -9,9 +9,6 @@ Use this command when the repository is empty or low-context and the user needs
9
9
 
10
10
  ## Required behavior
11
11
 
12
- 1. Prefer the local engine inside this repository:
13
- - `node roadmap-skill/bin/cli.js zero --project-root .`
14
- - on this Windows machine, prefer `C:\Program Files\nodejs\node.exe roadmap-skill/bin/cli.js zero --project-root .` if `node` is not in PATH
15
- 2. Otherwise prefer `roadmapsmith zero --project-root .`.
16
- 3. Treat this command as CLI-backed and interactive.
17
- 4. If the CLI is missing, explain the install path instead of improvising the workflow manually.
12
+ 1. Run `roadmapsmith zero --project-root .`.
13
+ 2. In non-interactive environments, provide or reuse a complete brief from config plus flags such as `--primary-user`, `--problem-statement`, `--target-outcome`, and repeatable `--done-criterion`.
14
+ 3. If the CLI is missing, explain the install path instead of improvising the workflow manually.
package/skills.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "npx skills add PapiScholz/roadmapsmith --skill '*' -a claude-code",
13
13
  "roadmapsmith setup",
14
14
  "roadmapsmith zero",
15
- "roadmapsmith maintain",
15
+ "roadmapsmith maintain --dry-run",
16
16
  "roadmapsmith /roadmap",
17
17
  "roadmapsmith update --task p2-customer-history --evidence \"src/app/api/customers/route.ts, test/customers.test.js\"",
18
18
  "roadmapsmith validate --json"
@@ -21,74 +21,74 @@
21
21
  "command": "npx skills add PapiScholz/roadmapsmith --skill '*' -a claude-code",
22
22
  "source": "PapiScholz/roadmapsmith",
23
23
  "skill": "*",
24
- "notes": "Recommended Claude Code install path for native GUI slash commands. Canonical surfaces: /roadmap, /roadmap-zero, /roadmap-maintain, /roadmap-status, /roadmap-validate, /roadmap-update, /roadmap-setup. The public CLI update family covers both checklist refresh and verified single-task completion; sync remains the advanced alias for the mutating refresh path. Advanced surfaces: /roadmap-init, /roadmap-generate, /roadmap-audit. DEPRECATED: /roadmap-sync remains only as a compatibility root for existing automation; use /roadmap-maintain or /roadmap-update for new workflows. Install the roadmapsmith CLI separately for actual command execution; roadmapsmith status is the public readiness command and roadmapsmith doctor remains a compatibility alias. Then run /reload-skills and, if applicable, /reload-plugins. Codex native plugin installs use the repo/package .codex-plugin surface instead of this Claude-specific skills CLI path."
24
+ "notes": "Recommended Claude Code install path for native GUI slash commands. Canonical surfaces: /roadmap, /roadmap-zero, /roadmap-maintain, /roadmap-status, /roadmap-validate, /roadmap-update, /roadmap-setup. The public CLI update family covers both checklist refresh and verified single-task completion; sync remains the advanced alias for the mutating refresh path. /roadmap-maintain now owns only existing managed roadmap blocks, while /roadmap-update is the conservative annotation path for authored roadmaps without markers. /roadmap-zero can consume a complete discovery brief from config plus CLI flags in non-interactive environments. Advanced surfaces: /roadmap-init, /roadmap-generate, /roadmap-audit. DEPRECATED: /roadmap-sync remains only as a compatibility root for existing automation; use /roadmap-maintain or /roadmap-update for new workflows. Install the roadmapsmith CLI separately for actual command execution; roadmapsmith status is the public readiness command and roadmapsmith doctor remains a compatibility alias. Then run /reload-skills and, if applicable, /reload-plugins. Codex native plugin installs use the repo/package .codex-plugin surface instead of this Claude-specific skills CLI path."
25
25
  },
26
26
  "skills": [
27
27
  {
28
28
  "name": "roadmap",
29
29
  "path": "skills/roadmap",
30
30
  "description": "Native slash palette for RoadmapSmith commands and recommended entrypoints across supported hosts.",
31
- "version": "0.9.32"
31
+ "version": "0.9.34"
32
32
  },
33
33
  {
34
34
  "name": "roadmap-zero",
35
35
  "path": "skills/roadmap-zero",
36
- "description": "Native slash entrypoint for the one-command Zero Mode CLI workflow.",
37
- "version": "0.9.32"
36
+ "description": "Native slash entrypoint for Zero Mode, including non-interactive config-plus-flag discovery.",
37
+ "version": "0.9.34"
38
38
  },
39
39
  {
40
40
  "name": "roadmap-maintain",
41
41
  "path": "skills/roadmap-maintain",
42
- "description": "Native slash entrypoint for the preserve-first generate + sync + audit flow.",
43
- "version": "0.9.32"
42
+ "description": "Native slash entrypoint for conservative managed-block maintenance plus sync and audit output.",
43
+ "version": "0.9.34"
44
44
  },
45
45
  {
46
46
  "name": "roadmap-status",
47
47
  "path": "skills/roadmap-status",
48
48
  "description": "Native slash readiness check grounded in roadmapsmith status JSON.",
49
- "version": "0.9.32"
49
+ "version": "0.9.34"
50
50
  },
51
51
  {
52
52
  "name": "roadmap-init",
53
53
  "path": "skills/roadmap-init",
54
54
  "description": "Native slash entrypoint for creating ROADMAP.md and AGENTS.md.",
55
- "version": "0.9.32"
55
+ "version": "0.9.34"
56
56
  },
57
57
  {
58
58
  "name": "roadmap-generate",
59
59
  "path": "skills/roadmap-generate",
60
60
  "description": "Native slash entrypoint for managed roadmap updates that require --full-regen before destructive replacement.",
61
- "version": "0.9.32"
61
+ "version": "0.9.34"
62
62
  },
63
63
  {
64
64
  "name": "roadmap-validate",
65
65
  "path": "skills/roadmap-validate",
66
66
  "description": "Native slash entrypoint for evidence-backed roadmap validation.",
67
- "version": "0.9.32"
67
+ "version": "0.9.34"
68
68
  },
69
69
  {
70
70
  "name": "roadmap-update",
71
71
  "path": "skills/roadmap-update",
72
- "description": "Native slash entrypoint for evidence-backed sync and verified single-task completion.",
73
- "version": "0.9.32"
72
+ "description": "Native slash entrypoint for evidence-backed inline annotation refresh and verified single-task completion.",
73
+ "version": "0.9.34"
74
74
  },
75
75
  {
76
76
  "name": "roadmap-sync",
77
77
  "path": "skills/roadmap-sync",
78
78
  "description": "DEPRECATED legacy compatibility root; use roadmap-maintain or roadmap-update.",
79
- "version": "0.9.32"
79
+ "version": "0.9.34"
80
80
  },
81
81
  {
82
82
  "name": "roadmap-audit",
83
83
  "path": "skills/roadmap-audit",
84
84
  "description": "Native slash entrypoint for the advanced sync-plus-audit mutating summary workflow.",
85
- "version": "0.9.32"
85
+ "version": "0.9.34"
86
86
  },
87
87
  {
88
88
  "name": "roadmap-setup",
89
89
  "path": "skills/roadmap-setup",
90
90
  "description": "Native slash entrypoint for generating RoadmapSmith host integration files.",
91
- "version": "0.9.32"
91
+ "version": "0.9.34"
92
92
  }
93
93
  ]
94
94
  }
package/src/zero.js CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  const path = require('path');
4
4
 
5
+ const ZERO_MODE_FLAG_SPECS = {
6
+ productName: { flag: '--product-name', configPath: 'product.name', type: 'scalar' },
7
+ primaryUser: { flag: '--primary-user', configPath: 'product.primaryUser', type: 'scalar', required: true },
8
+ problemStatement: { flag: '--problem-statement', configPath: 'zeroMode.problemStatement', type: 'scalar', required: true },
9
+ targetOutcome: { flag: '--target-outcome', configPath: 'product.targetOutcome', type: 'scalar', required: true },
10
+ antiGoals: { flag: '--anti-goal', configPath: 'product.antiGoals', type: 'list' },
11
+ preferredStack: { flag: '--preferred-stack', configPath: 'zeroMode.preferredStack', type: 'scalar' },
12
+ constraints: { flag: '--constraint', configPath: 'zeroMode.constraints', type: 'list' },
13
+ doneCriteria: { flag: '--done-criterion', configPath: 'zeroMode.doneCriteria', type: 'list', required: true }
14
+ };
15
+
5
16
  const ZERO_MODE_QUESTIONS = [
6
17
  { id: 'productName', prompt: '1. What product are we building?' },
7
18
  { id: 'primaryUser', prompt: '2. Who is the target user?' },
@@ -54,6 +65,80 @@ function buildZeroModeDefaults(projectRoot, config) {
54
65
  };
55
66
  }
56
67
 
68
+ function getSingleFlagValue(value) {
69
+ if (Array.isArray(value)) {
70
+ return value[value.length - 1];
71
+ }
72
+ return value;
73
+ }
74
+
75
+ function getListFlagValues(value) {
76
+ const rawValues = Array.isArray(value) ? value : [value];
77
+ return rawValues.flatMap((item) => splitListAnswer(item));
78
+ }
79
+
80
+ function resolveZeroModeAnswers(projectRoot, config, flags = {}) {
81
+ const defaults = buildZeroModeDefaults(projectRoot, config);
82
+ const answers = { ...defaults };
83
+
84
+ for (const [field, spec] of Object.entries(ZERO_MODE_FLAG_SPECS)) {
85
+ const flagKey = spec.flag.slice(2);
86
+ if (!Object.prototype.hasOwnProperty.call(flags, flagKey)) {
87
+ continue;
88
+ }
89
+
90
+ if (spec.type === 'list') {
91
+ answers[field] = getListFlagValues(flags[flagKey]).join('; ');
92
+ continue;
93
+ }
94
+
95
+ const raw = getSingleFlagValue(flags[flagKey]);
96
+ answers[field] = String(raw == null ? '' : raw).trim();
97
+ }
98
+
99
+ if (!String(answers.productName || '').trim()) {
100
+ answers.productName = path.basename(projectRoot);
101
+ }
102
+
103
+ return answers;
104
+ }
105
+
106
+ function getMissingZeroModeFields(answers = {}) {
107
+ const missing = [];
108
+ for (const [field, spec] of Object.entries(ZERO_MODE_FLAG_SPECS)) {
109
+ if (!spec.required) {
110
+ continue;
111
+ }
112
+
113
+ if (spec.type === 'list') {
114
+ if (splitListAnswer(answers[field]).length === 0) {
115
+ missing.push({
116
+ field,
117
+ flag: spec.flag,
118
+ configPath: spec.configPath
119
+ });
120
+ }
121
+ continue;
122
+ }
123
+
124
+ if (!String(answers[field] || '').trim()) {
125
+ missing.push({
126
+ field,
127
+ flag: spec.flag,
128
+ configPath: spec.configPath
129
+ });
130
+ }
131
+ }
132
+ return missing;
133
+ }
134
+
135
+ function formatMissingZeroModeFields(missingFields) {
136
+ return missingFields.map((item) => {
137
+ const label = item.field.replace(/([A-Z])/g, ' $1').toLowerCase();
138
+ return `${label} (${item.flag} or config ${item.configPath})`;
139
+ });
140
+ }
141
+
57
142
  async function collectZeroModeAnswers(ask, defaults = {}) {
58
143
  const answers = {};
59
144
  for (const question of ZERO_MODE_QUESTIONS) {
@@ -124,6 +209,9 @@ module.exports = {
124
209
  buildZeroModeConfigPatch,
125
210
  buildZeroModeDefaults,
126
211
  collectZeroModeAnswers,
212
+ formatMissingZeroModeFields,
213
+ getMissingZeroModeFields,
127
214
  isInteractiveTerminal,
215
+ resolveZeroModeAnswers,
128
216
  splitListAnswer
129
217
  };