roadmapsmith 0.9.27 → 0.9.28
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +9 -2
- package/bin/cli.js +89 -3
- package/package.json +1 -1
- package/skills/roadmap/SKILL.md +1 -1
- package/skills/roadmap-maintain/SKILL.md +3 -2
- package/skills/roadmap-status/SKILL.md +1 -1
- package/skills/roadmap-sync/SKILL.md +3 -3
- package/skills/roadmap-sync/agents/openai.yaml +2 -2
- package/skills/roadmap-update/SKILL.md +6 -5
- package/skills.json +15 -16
- package/src/sync/index.js +12 -0
- package/src/validator/index.js +67 -8
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "roadmapsmith",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.28",
|
|
4
4
|
"description": "One-command evidence-backed ROADMAP.md generator and sync tool for AI coding agents, with shared RoadmapSmith plugin skills for Codex and Claude plus the roadmapsmith status readiness surface.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "PapiScholz"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "roadmapsmith",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.28",
|
|
4
4
|
"description": "One-command evidence-backed ROADMAP.md generator and sync tool for AI coding agents, with shared RoadmapSmith plugin skills for Codex and Claude plus the roadmapsmith status readiness surface.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "PapiScholz"
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ npx skills add PapiScholz/roadmapsmith --skill '*' -a claude-code
|
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
This is the recommended Claude Code install path for native GUI slash commands such as `/roadmap`, `/roadmap-zero`, `/roadmap-maintain`, `/roadmap-status`, `/roadmap-init`, `/roadmap-generate`, `/roadmap-validate`, `/roadmap-update`, `/roadmap-audit`, and `/roadmap-setup`.
|
|
31
|
-
|
|
31
|
+
`roadmap-sync` is deprecated compatibility only; install the full bundle for new workflows and use `/roadmap-maintain` or `/roadmap-update`.
|
|
32
32
|
The skill bundle does not install the CLI and it does not create visible VS Code actions by itself.
|
|
33
33
|
The published `roadmapsmith` package/plugin surface now also ships the shared bundle files for both hosts (`skills.json`, `skills/*`, `.codex-plugin/plugin.json`, `.claude-plugin/plugin.json`) for downstream host installers, but consuming the CLI alone still does not auto-register native Codex or Claude GUI commands.
|
|
34
34
|
|
|
@@ -101,7 +101,11 @@ Use the lower-level commands only when you want manual control over generation,
|
|
|
101
101
|
| CI | Use disposable checkouts if you run `sync --audit`, because it still mutates the roadmap today. |
|
|
102
102
|
| Other hosts | Use the skill plus manual CLI commands. |
|
|
103
103
|
|
|
104
|
-
If Node is installed outside PATH, set `ROADMAPSMITH_NODE` to a working `node` executable before using the generated VS Code tasks.
|
|
104
|
+
If Node is installed outside PATH, set `ROADMAPSMITH_NODE` to a working `node` executable before using the generated VS Code tasks. If the globally installed `roadmapsmith` shim itself cannot resolve Node, bypass it in PowerShell with:
|
|
105
|
+
|
|
106
|
+
```powershell
|
|
107
|
+
& "C:\Program Files\nodejs\node.exe" "$env:APPDATA\npm\node_modules\roadmapsmith\bin\cli.js" <command>
|
|
108
|
+
```
|
|
105
109
|
|
|
106
110
|
---
|
|
107
111
|
|
|
@@ -119,6 +123,7 @@ roadmapsmith maintain [--project-root <path>] [--config <path>] [--roadmap-file
|
|
|
119
123
|
roadmapsmith init [--roadmap-file <path>] [--agents-file <path>] [--dry-run]
|
|
120
124
|
roadmapsmith generate [--project-root <path>] [--config <path>] [--roadmap-file <path>] [--dry-run] [--audit] [--full-regen]
|
|
121
125
|
roadmapsmith sync [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--dry-run] [--audit]
|
|
126
|
+
roadmapsmith update --task <stable-id> --evidence <text> [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--dry-run]
|
|
122
127
|
roadmapsmith validate [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--task <id|text>] [--json]
|
|
123
128
|
roadmapsmith status [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--json]
|
|
124
129
|
roadmapsmith doctor [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--json] # compatibility alias
|
|
@@ -183,6 +188,8 @@ The repo does not remove user-global skills automatically. Use the `doctor` outp
|
|
|
183
188
|
- `- ⚠️ attempted but validation failed: <reason>` when there is concrete attempt evidence
|
|
184
189
|
- `- ⚠️ no implementation evidence found yet: <reason>` when there is not
|
|
185
190
|
- Preserves unmanaged markdown content by updating only the managed roadmap block.
|
|
191
|
+
- `validate` emits structured diagnostics in human and JSON output (`FAIL:NOT_IMPLEMENTED`, `FAIL:NO_TEST`, `FAIL:MISSING_REFERENCE`, and `WARN:STALE_EVIDENCE`).
|
|
192
|
+
- `update --task <id> --evidence <text>` writes only when the evidence validates at high confidence; otherwise the roadmap is unchanged.
|
|
186
193
|
|
|
187
194
|
## Defaults
|
|
188
195
|
|
package/bin/cli.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const readline = require('node:readline/promises');
|
|
7
|
-
const { parseArgv } = require('../src/utils');
|
|
7
|
+
const { ensureTrailingNewline, parseArgv } = require('../src/utils');
|
|
8
8
|
const { loadConfig, resolveRoadmapFile, resolveAgentsFile, loadPlugins, readUserConfig, resolveConfigPath } = require('../src/config');
|
|
9
9
|
const { readTextIfExists, writeText, printDryRunDiff } = require('../src/io');
|
|
10
10
|
const { buildSetupFiles, applySetupFiles, inspectHostSetup, parseHosts, assertSupportedEditor } = require('../src/host');
|
|
@@ -30,6 +30,7 @@ function printHelp() {
|
|
|
30
30
|
' roadmapsmith setup [--project-root <path>] [--config <path>] [--editor vscode] [--hosts <codex,claude>] [--dry-run]',
|
|
31
31
|
' roadmapsmith generate [--project-root <path>] [--config <path>] [--roadmap-file <path>] [--dry-run] [--audit] [--full-regen]',
|
|
32
32
|
' roadmapsmith sync [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--dry-run] [--audit]',
|
|
33
|
+
' roadmapsmith update --task <stable-id> --evidence <text> [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--dry-run]',
|
|
33
34
|
' roadmapsmith validate [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--task <id|text>] [--json]',
|
|
34
35
|
' roadmapsmith status [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--json]',
|
|
35
36
|
' roadmapsmith doctor [--roadmap-file <path>] [--project-root <path>] [--config <path>] [--json] # compatibility alias'
|
|
@@ -44,8 +45,13 @@ function isEnabled(value) {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
function formatResultLine(task, result) {
|
|
47
|
-
const
|
|
48
|
-
const
|
|
48
|
+
const diagnostics = Array.isArray(result.diagnostics) ? result.diagnostics : [];
|
|
49
|
+
const primaryError = diagnostics.find((item) => item.severity === 'error');
|
|
50
|
+
const warnings = diagnostics.filter((item) => item.severity === 'warning');
|
|
51
|
+
const status = primaryError ? `FAIL:${primaryError.code}` : (result.passed ? 'PASS' : 'FAIL');
|
|
52
|
+
const parts = [...result.reasons];
|
|
53
|
+
warnings.forEach((item) => parts.push(`WARN:${item.code} ${item.message}`));
|
|
54
|
+
const reason = parts.length > 0 ? ` :: ${parts.join('; ')}` : '';
|
|
49
55
|
return `${status} [${task.id}] ${task.text}${reason}`;
|
|
50
56
|
}
|
|
51
57
|
|
|
@@ -215,6 +221,77 @@ function runSyncCommand(projectRoot, config, flags, options = {}) {
|
|
|
215
221
|
}
|
|
216
222
|
}
|
|
217
223
|
|
|
224
|
+
function addEvidenceToTask(content, task, evidenceText) {
|
|
225
|
+
const lines = String(content || '').split(/\r?\n/);
|
|
226
|
+
const evidenceLine = `${task.indent || ''} - Evidence: ${evidenceText}`;
|
|
227
|
+
if (Array.isArray(task.evidenceLines) && task.evidenceLines.length > 0) {
|
|
228
|
+
lines[task.evidenceLines[0].lineIndex] = evidenceLine;
|
|
229
|
+
return ensureTrailingNewline(lines.join('\n'));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const insertionIndex = task.warningLineIndex != null
|
|
233
|
+
? task.warningLineIndex
|
|
234
|
+
: task.lastChildLineIndex + 1;
|
|
235
|
+
lines.splice(insertionIndex, 0, evidenceLine);
|
|
236
|
+
return ensureTrailingNewline(lines.join('\n'));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function runUpdateCommand(projectRoot, config, flags) {
|
|
240
|
+
const hasTask = flags.task != null;
|
|
241
|
+
const hasEvidence = flags.evidence != null;
|
|
242
|
+
if (!hasTask && !hasEvidence) {
|
|
243
|
+
runSyncCommand(projectRoot, config, flags);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (!hasTask || !hasEvidence || Array.isArray(flags.task) || Array.isArray(flags.evidence)) {
|
|
247
|
+
throw new Error('update requires exactly one --task <stable-id> and one --evidence <text> value');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const taskId = String(flags.task).trim();
|
|
251
|
+
const evidenceText = String(flags.evidence).trim();
|
|
252
|
+
if (!taskId || !evidenceText || /[\r\n]/.test(evidenceText)) {
|
|
253
|
+
throw new Error('update requires a non-empty single-line --task and --evidence value');
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const roadmapFile = resolveRoadmapFile(projectRoot, config, flags['roadmap-file']);
|
|
257
|
+
const content = readTextIfExists(roadmapFile);
|
|
258
|
+
if (content == null) {
|
|
259
|
+
throw new Error(`Roadmap not found: ${roadmapFile}`);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const parsedRoadmap = parseRoadmap(content);
|
|
263
|
+
const matches = tasksInManagedBlock(parsedRoadmap).filter((task) => task.id === taskId);
|
|
264
|
+
if (matches.length !== 1) {
|
|
265
|
+
throw new Error(matches.length === 0
|
|
266
|
+
? `Roadmap task not found: ${taskId}`
|
|
267
|
+
: `Roadmap task ID is ambiguous: ${taskId}`);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const draft = addEvidenceToTask(content, matches[0], evidenceText);
|
|
271
|
+
const draftTask = tasksInManagedBlock(parseRoadmap(draft)).find((task) => task.id === taskId);
|
|
272
|
+
const validationContext = buildValidationContext(projectRoot, config, loadPlugins(projectRoot, config.plugins));
|
|
273
|
+
const result = validateTasks([draftTask], validationContext, config, validationContext.plugins)[taskId];
|
|
274
|
+
const errors = (result.diagnostics || []).filter((item) => item.severity === 'error');
|
|
275
|
+
const suppliedEvidenceResolved = result.evidence.authoritative && result.evidence.authoritativeFiles.length > 0;
|
|
276
|
+
if (!suppliedEvidenceResolved || !result.passed || result.confidence !== 'high' || errors.length > 0) {
|
|
277
|
+
const reasons = result.reasons.length > 0 ? `: ${result.reasons.join('; ')}` : '';
|
|
278
|
+
throw new Error(`Task ${taskId} was not updated; supplied evidence must resolve in the repository and validate at high confidence${reasons}`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const next = applySync(draft, [draftTask], { [taskId]: result });
|
|
282
|
+
const dryRun = isEnabled(flags['dry-run']);
|
|
283
|
+
const writeResult = writeText(roadmapFile, next, { dryRun });
|
|
284
|
+
if (dryRun) {
|
|
285
|
+
if (writeResult.changed) {
|
|
286
|
+
printDryRunDiff(roadmapFile, writeResult.before, writeResult.after);
|
|
287
|
+
} else {
|
|
288
|
+
console.log(`No changes for ${roadmapFile}`);
|
|
289
|
+
}
|
|
290
|
+
} else {
|
|
291
|
+
console.log(writeResult.changed ? `Updated ${roadmapFile}` : `No changes for ${roadmapFile}`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
218
295
|
function printHumanStatus(payload) {
|
|
219
296
|
console.log('RoadmapSmith status\n');
|
|
220
297
|
console.log(`Project root: ${payload.projectRoot}`);
|
|
@@ -343,6 +420,8 @@ async function run() {
|
|
|
343
420
|
if (slashAction.id === 'audit') {
|
|
344
421
|
flags.audit = true;
|
|
345
422
|
effectiveCommand = 'sync';
|
|
423
|
+
} else if (slashAction.id === 'sync' && String(command).trim().toLowerCase() === '/roadmap-update') {
|
|
424
|
+
effectiveCommand = 'update';
|
|
346
425
|
} else {
|
|
347
426
|
effectiveCommand = slashAction.id;
|
|
348
427
|
}
|
|
@@ -411,6 +490,13 @@ async function run() {
|
|
|
411
490
|
return;
|
|
412
491
|
}
|
|
413
492
|
|
|
493
|
+
if (effectiveCommand === 'update') {
|
|
494
|
+
const projectRoot = path.resolve(String(flags['project-root'] || process.cwd()));
|
|
495
|
+
const config = loadConfig({ projectRoot, configPath: flags.config });
|
|
496
|
+
runUpdateCommand(projectRoot, config, flags);
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
|
|
414
500
|
if (effectiveCommand === 'validate') {
|
|
415
501
|
const projectRoot = path.resolve(String(flags['project-root'] || process.cwd()));
|
|
416
502
|
const config = loadConfig({ projectRoot, configPath: flags.config });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "roadmapsmith",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.28",
|
|
4
4
|
"description": "One-command evidence-backed ROADMAP.md generator and sync tool for AI coding agents, with shared RoadmapSmith plugin skills for Codex and Claude plus the roadmapsmith status readiness surface.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
package/skills/roadmap/SKILL.md
CHANGED
|
@@ -13,7 +13,7 @@ Use this command as the native discovery entrypoint for the shared RoadmapSmith
|
|
|
13
13
|
2. When working inside the RoadmapSmith repository itself and `roadmap-skill/bin/cli.js` exists, prefer the local engine:
|
|
14
14
|
- `node roadmap-skill/bin/cli.js /roadmap`
|
|
15
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.
|
|
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
17
|
4. If the CLI is missing, provide the palette manually and explain the install path:
|
|
18
18
|
- `npm install -g roadmapsmith`
|
|
19
19
|
- `npx skills add PapiScholz/roadmapsmith --skill '*' -a claude-code`
|
|
@@ -12,7 +12,8 @@ Use this command when the repository already has code, tests, docs, or an existi
|
|
|
12
12
|
1. Prefer the local engine inside this repository:
|
|
13
13
|
- `node roadmap-skill/bin/cli.js maintain --project-root .`
|
|
14
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 .`.
|
|
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
16
|
3. Treat this command as CLI-backed. Do not silently replace it with manual reasoning when the CLI is unavailable.
|
|
17
17
|
4. Mention that maintain runs preserve-first generate, sync, and audit in one invocation.
|
|
18
|
-
5.
|
|
18
|
+
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.
|
|
@@ -12,6 +12,6 @@ Use this command to inspect whether the shared bundle, native host surfaces, CLI
|
|
|
12
12
|
1. Prefer the local engine inside this repository:
|
|
13
13
|
- `node roadmap-skill/bin/cli.js doctor --json --project-root .`
|
|
14
14
|
- on this Windows machine, prefer `C:\Program Files\nodejs\node.exe roadmap-skill/bin/cli.js doctor --json --project-root .` if `node` is not in PATH
|
|
15
|
-
2. Otherwise prefer `roadmapsmith doctor --json --project-root .`.
|
|
15
|
+
2. Otherwise prefer `roadmapsmith doctor --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" doctor --json --project-root .`.
|
|
16
16
|
3. Parse and summarize the JSON output in plain language.
|
|
17
17
|
4. Explicitly call out missing commands or duplicate `/roadmap-sync` registration when doctor reports them.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: roadmap-sync
|
|
3
|
-
description:
|
|
3
|
+
description: DEPRECATED legacy root for RoadmapSmith slash workflows; use roadmap-maintain or roadmap-update.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# RoadmapSmith Legacy Root
|
|
6
|
+
# RoadmapSmith Legacy Root (Deprecated)
|
|
7
7
|
|
|
8
|
-
Use this skill when the host exposes or the user invokes `/roadmap-sync
|
|
8
|
+
Use this skill only when the host exposes or the user explicitly invokes `/roadmap-sync`. For new work, use `/roadmap-maintain` for the daily flow or `/roadmap-update` for evidence-backed completion.
|
|
9
9
|
|
|
10
10
|
## Required behavior
|
|
11
11
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"interface": {
|
|
3
|
-
"display_name": "Roadmap Sync",
|
|
4
|
-
"short_description": "
|
|
3
|
+
"display_name": "Roadmap Sync (Deprecated)",
|
|
4
|
+
"short_description": "DEPRECATED legacy root; use /roadmap-maintain or /roadmap-update.",
|
|
5
5
|
"default_prompt": "Prefer /roadmap, /roadmap-status, /roadmap-maintain, and /roadmap-update."
|
|
6
6
|
}
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: roadmap-update
|
|
3
|
-
description: Apply evidence-backed checklist sync through the RoadmapSmith CLI.
|
|
3
|
+
description: Apply evidence-backed checklist sync or complete one task with verified evidence through the RoadmapSmith CLI.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# RoadmapSmith Update
|
|
@@ -10,8 +10,9 @@ Use this command when the user wants the direct sync surface without routing thr
|
|
|
10
10
|
## Required behavior
|
|
11
11
|
|
|
12
12
|
1. Prefer the local engine inside this repository:
|
|
13
|
-
- `node roadmap-skill/bin/cli.js
|
|
14
|
-
- on this Windows machine, prefer `C:\Program Files\nodejs\node.exe roadmap-skill/bin/cli.js
|
|
15
|
-
2. Otherwise prefer `roadmapsmith
|
|
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 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" update --project-root .`.
|
|
16
16
|
3. Explain that `/roadmap-update` is the visible namespaced sync command, while `/roadmap-sync <action>` remains legacy compatibility.
|
|
17
|
-
4. Keep the evidence-backed sync semantics unchanged:
|
|
17
|
+
4. Keep the evidence-backed sync semantics unchanged: no-argument update syncs the roadmap from repository evidence; it is not a full regeneration path.
|
|
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.
|
package/skills.json
CHANGED
|
@@ -10,86 +10,85 @@
|
|
|
10
10
|
],
|
|
11
11
|
"usageExamples": [
|
|
12
12
|
"npx skills add PapiScholz/roadmapsmith --skill '*' -a claude-code",
|
|
13
|
-
"npx skills add PapiScholz/roadmapsmith --skill roadmap-sync",
|
|
14
13
|
"roadmapsmith setup",
|
|
15
14
|
"roadmapsmith zero",
|
|
16
15
|
"roadmapsmith maintain",
|
|
17
16
|
"roadmapsmith /roadmap",
|
|
18
|
-
"roadmapsmith
|
|
17
|
+
"roadmapsmith update --task p2-customer-history --evidence \"src/app/api/customers/route.ts, test/customers.test.js\"",
|
|
19
18
|
"roadmapsmith validate --json"
|
|
20
19
|
],
|
|
21
20
|
"install": {
|
|
22
21
|
"command": "npx skills add PapiScholz/roadmapsmith --skill '*' -a claude-code",
|
|
23
22
|
"source": "PapiScholz/roadmapsmith",
|
|
24
23
|
"skill": "*",
|
|
25
|
-
"notes": "Recommended Claude Code install path for native GUI slash commands like /roadmap, /roadmap-zero, /roadmap-maintain, /roadmap-status, /roadmap-init, /roadmap-generate, /roadmap-validate, /roadmap-update, /roadmap-audit, and /roadmap-setup.
|
|
24
|
+
"notes": "Recommended Claude Code install path for native GUI slash commands like /roadmap, /roadmap-zero, /roadmap-maintain, /roadmap-status, /roadmap-init, /roadmap-generate, /roadmap-validate, /roadmap-update, /roadmap-audit, and /roadmap-setup. 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 visible 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."
|
|
26
25
|
},
|
|
27
26
|
"skills": [
|
|
28
27
|
{
|
|
29
28
|
"name": "roadmap",
|
|
30
29
|
"path": "skills/roadmap",
|
|
31
30
|
"description": "Native slash palette for RoadmapSmith commands and recommended entrypoints across supported hosts.",
|
|
32
|
-
"version": "0.9.
|
|
31
|
+
"version": "0.9.28"
|
|
33
32
|
},
|
|
34
33
|
{
|
|
35
34
|
"name": "roadmap-zero",
|
|
36
35
|
"path": "skills/roadmap-zero",
|
|
37
36
|
"description": "Native slash entrypoint for the one-command Zero Mode CLI workflow.",
|
|
38
|
-
"version": "0.9.
|
|
37
|
+
"version": "0.9.28"
|
|
39
38
|
},
|
|
40
39
|
{
|
|
41
40
|
"name": "roadmap-maintain",
|
|
42
41
|
"path": "skills/roadmap-maintain",
|
|
43
42
|
"description": "Native slash entrypoint for the preserve-first generate + sync + audit flow.",
|
|
44
|
-
"version": "0.9.
|
|
43
|
+
"version": "0.9.28"
|
|
45
44
|
},
|
|
46
45
|
{
|
|
47
46
|
"name": "roadmap-status",
|
|
48
47
|
"path": "skills/roadmap-status",
|
|
49
48
|
"description": "Native slash readiness check grounded in roadmapsmith status JSON.",
|
|
50
|
-
"version": "0.9.
|
|
49
|
+
"version": "0.9.28"
|
|
51
50
|
},
|
|
52
51
|
{
|
|
53
52
|
"name": "roadmap-init",
|
|
54
53
|
"path": "skills/roadmap-init",
|
|
55
54
|
"description": "Native slash entrypoint for creating ROADMAP.md and AGENTS.md.",
|
|
56
|
-
"version": "0.9.
|
|
55
|
+
"version": "0.9.28"
|
|
57
56
|
},
|
|
58
57
|
{
|
|
59
58
|
"name": "roadmap-generate",
|
|
60
59
|
"path": "skills/roadmap-generate",
|
|
61
60
|
"description": "Native slash entrypoint for managed roadmap updates that require --full-regen before destructive replacement.",
|
|
62
|
-
"version": "0.9.
|
|
61
|
+
"version": "0.9.28"
|
|
63
62
|
},
|
|
64
63
|
{
|
|
65
64
|
"name": "roadmap-validate",
|
|
66
65
|
"path": "skills/roadmap-validate",
|
|
67
66
|
"description": "Native slash entrypoint for evidence-backed roadmap validation.",
|
|
68
|
-
"version": "0.9.
|
|
67
|
+
"version": "0.9.28"
|
|
69
68
|
},
|
|
70
69
|
{
|
|
71
70
|
"name": "roadmap-update",
|
|
72
71
|
"path": "skills/roadmap-update",
|
|
73
|
-
"description": "Native slash entrypoint for
|
|
74
|
-
"version": "0.9.
|
|
72
|
+
"description": "Native slash entrypoint for evidence-backed sync and verified single-task completion.",
|
|
73
|
+
"version": "0.9.28"
|
|
75
74
|
},
|
|
76
75
|
{
|
|
77
76
|
"name": "roadmap-sync",
|
|
78
77
|
"path": "skills/roadmap-sync",
|
|
79
|
-
"description": "
|
|
80
|
-
"version": "0.9.
|
|
78
|
+
"description": "DEPRECATED legacy compatibility root; use roadmap-maintain or roadmap-update.",
|
|
79
|
+
"version": "0.9.28"
|
|
81
80
|
},
|
|
82
81
|
{
|
|
83
82
|
"name": "roadmap-audit",
|
|
84
83
|
"path": "skills/roadmap-audit",
|
|
85
84
|
"description": "Native slash entrypoint for the current sync-plus-audit workflow.",
|
|
86
|
-
"version": "0.9.
|
|
85
|
+
"version": "0.9.28"
|
|
87
86
|
},
|
|
88
87
|
{
|
|
89
88
|
"name": "roadmap-setup",
|
|
90
89
|
"path": "skills/roadmap-setup",
|
|
91
90
|
"description": "Native slash entrypoint for generating RoadmapSmith host integration files.",
|
|
92
|
-
"version": "0.9.
|
|
91
|
+
"version": "0.9.28"
|
|
93
92
|
}
|
|
94
93
|
]
|
|
95
94
|
}
|
package/src/sync/index.js
CHANGED
|
@@ -142,6 +142,18 @@ function applySync(content, parsedTasks, results) {
|
|
|
142
142
|
lines.splice(warningIndex, 1);
|
|
143
143
|
offset -= 1;
|
|
144
144
|
}
|
|
145
|
+
if (
|
|
146
|
+
result.staleEvidenceResolved &&
|
|
147
|
+
(!Array.isArray(task.evidenceLines) || task.evidenceLines.length === 0) &&
|
|
148
|
+
result.discoveredEvidence
|
|
149
|
+
) {
|
|
150
|
+
const insertionIndex = Math.max(
|
|
151
|
+
lineIndex + 1,
|
|
152
|
+
(task.lastChildLineIndex + offset) + 1
|
|
153
|
+
);
|
|
154
|
+
lines.splice(insertionIndex, 0, `${task.indent || ''} - Evidence: ${result.discoveredEvidence}`);
|
|
155
|
+
offset += 1;
|
|
156
|
+
}
|
|
145
157
|
continue;
|
|
146
158
|
}
|
|
147
159
|
|
package/src/validator/index.js
CHANGED
|
@@ -1290,6 +1290,52 @@ function buildValidationContext(projectRoot, config, plugins) {
|
|
|
1290
1290
|
};
|
|
1291
1291
|
}
|
|
1292
1292
|
|
|
1293
|
+
function diagnosticCodeForReason(reason) {
|
|
1294
|
+
const normalized = String(reason || '').toLowerCase();
|
|
1295
|
+
if (normalized.includes('missing referenced file') || normalized.includes('evidence file(s) not found')) {
|
|
1296
|
+
return 'MISSING_REFERENCE';
|
|
1297
|
+
}
|
|
1298
|
+
if (normalized.includes('missing test evidence')) {
|
|
1299
|
+
return 'NO_TEST';
|
|
1300
|
+
}
|
|
1301
|
+
if (
|
|
1302
|
+
normalized.includes('no code, test, or artifact evidence found') ||
|
|
1303
|
+
normalized.includes('implementation task requires evidence line') ||
|
|
1304
|
+
normalized.includes('weak path') ||
|
|
1305
|
+
normalized.includes('file reference shows implementation location')
|
|
1306
|
+
) {
|
|
1307
|
+
return 'NOT_IMPLEMENTED';
|
|
1308
|
+
}
|
|
1309
|
+
return null;
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
function buildDiagnostics(reasons, options = {}) {
|
|
1313
|
+
const diagnostics = [];
|
|
1314
|
+
const seen = new Set();
|
|
1315
|
+
for (const reason of Array.isArray(reasons) ? reasons : []) {
|
|
1316
|
+
const code = diagnosticCodeForReason(reason);
|
|
1317
|
+
if (!code || seen.has(code)) {
|
|
1318
|
+
continue;
|
|
1319
|
+
}
|
|
1320
|
+
seen.add(code);
|
|
1321
|
+
diagnostics.push({ code, severity: 'error', message: reason });
|
|
1322
|
+
}
|
|
1323
|
+
if (options.staleEvidence) {
|
|
1324
|
+
diagnostics.push({
|
|
1325
|
+
code: 'STALE_EVIDENCE',
|
|
1326
|
+
severity: 'warning',
|
|
1327
|
+
message: 'historical validation warning conflicts with fresh repository evidence'
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
return diagnostics;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
function buildDiscoveredEvidenceLine(evidence) {
|
|
1334
|
+
const files = unionArrays(evidence.codeFiles, evidence.testFiles)
|
|
1335
|
+
.sort((left, right) => left.localeCompare(right));
|
|
1336
|
+
return files.length > 0 ? files.join(', ') : null;
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1293
1339
|
function validateTask(task, context, config, plugins) {
|
|
1294
1340
|
const {
|
|
1295
1341
|
paths: pathHints,
|
|
@@ -1467,8 +1513,15 @@ function validateTask(task, context, config, plugins) {
|
|
|
1467
1513
|
// evidence, artifact evidence, or strong code+test threshold to pass.
|
|
1468
1514
|
// Already-checked tasks with found path hints are preserved via shouldPreserveCheckedTask.
|
|
1469
1515
|
const hasHighConfidenceImplementationEvidence = meetsStrongThreshold && evidence.code && evidence.test;
|
|
1516
|
+
const hasFreshRepositoryEvidence = hasStrongEvidence || hasWeakEvidence;
|
|
1517
|
+
let staleEvidenceDetected = false;
|
|
1518
|
+
let staleEvidenceResolved = false;
|
|
1470
1519
|
let passed = authoritativeEvidence.passed || hasArtifactTaskPass || hasTrustedRuleEvidencePass || meetsStrongThreshold;
|
|
1471
1520
|
|
|
1521
|
+
if (task.warningText && !task.checked && hasFreshRepositoryEvidence && !authoritativeEvidence.passed) {
|
|
1522
|
+
staleEvidenceDetected = true;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1472
1525
|
if (!passed && !task.checked && hasDirectReferencePass) {
|
|
1473
1526
|
const locationReason = 'file reference shows implementation location, not confirmed completion';
|
|
1474
1527
|
if (!uniqueReasons.includes(locationReason)) {
|
|
@@ -1476,13 +1529,15 @@ function validateTask(task, context, config, plugins) {
|
|
|
1476
1529
|
}
|
|
1477
1530
|
}
|
|
1478
1531
|
|
|
1479
|
-
//
|
|
1480
|
-
// explicitly confirms implementation. meetsStrongThreshold (token match) cannot override a
|
|
1481
|
-
// human/agent judgment that the feature is incomplete.
|
|
1532
|
+
// Historical warnings are only cleared by independent, high-confidence repository evidence.
|
|
1482
1533
|
if (task.warningText && !task.checked && passed && !authoritativeEvidence.passed) {
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1534
|
+
if (hasHighConfidenceImplementationEvidence && negativeSignalMatches.length === 0 && uniqueReasons.length === 0) {
|
|
1535
|
+
staleEvidenceResolved = true;
|
|
1536
|
+
} else {
|
|
1537
|
+
passed = false;
|
|
1538
|
+
if (uniqueReasons.length === 0) {
|
|
1539
|
+
uniqueReasons.push('validation failed');
|
|
1540
|
+
}
|
|
1486
1541
|
}
|
|
1487
1542
|
}
|
|
1488
1543
|
if (negativeSignalMatches.length > 0) {
|
|
@@ -1533,17 +1588,21 @@ function validateTask(task, context, config, plugins) {
|
|
|
1533
1588
|
// Used by auditValidation to flag implementation tasks that pass solely via documentation.
|
|
1534
1589
|
const evidenceIsDocOnly = !evidence.code && !evidence.test && evidence.artifact && !isDocTask(task.text);
|
|
1535
1590
|
|
|
1591
|
+
const finalPassed = overrideResult ? overrideResult.passed !== false : (passed && uniqueReasons.length === 0);
|
|
1536
1592
|
return {
|
|
1537
1593
|
taskId: task.id,
|
|
1538
|
-
passed:
|
|
1594
|
+
passed: finalPassed,
|
|
1539
1595
|
confidence,
|
|
1540
1596
|
reasons: uniqueReasons,
|
|
1597
|
+
diagnostics: buildDiagnostics(uniqueReasons, { staleEvidence: staleEvidenceDetected }),
|
|
1541
1598
|
evidence,
|
|
1542
1599
|
evidenceIsDocOnly,
|
|
1543
1600
|
requiresTest,
|
|
1544
1601
|
hasEvidence: hasStrongEvidence || hasWeakEvidence,
|
|
1545
1602
|
attempted,
|
|
1546
|
-
preservedCheckedState
|
|
1603
|
+
preservedCheckedState,
|
|
1604
|
+
staleEvidenceResolved,
|
|
1605
|
+
discoveredEvidence: staleEvidenceResolved ? buildDiscoveredEvidenceLine(evidence) : null
|
|
1547
1606
|
};
|
|
1548
1607
|
}
|
|
1549
1608
|
|