cc-devflow 4.5.4 → 4.5.6
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/skills/cc-act/CHANGELOG.md +6 -0
- package/.claude/skills/cc-act/PLAYBOOK.md +21 -5
- package/.claude/skills/cc-act/SKILL.md +21 -11
- package/.claude/skills/cc-act/assets/PR_BRIEF_TEMPLATE.md +10 -0
- package/.claude/skills/cc-act/assets/RELEASE_NOTE_TEMPLATE.md +8 -0
- package/.claude/skills/cc-act/references/closure-contract.md +3 -0
- package/.claude/skills/cc-act/scripts/cc-act-common.sh +48 -0
- package/.claude/skills/cc-act/scripts/generate-status-report.sh +3 -0
- package/.claude/skills/cc-act/scripts/render-pr-brief.sh +6 -0
- package/.claude/skills/cc-act/scripts/sync-act-docs.sh +13 -0
- package/.claude/skills/cc-do/CHANGELOG.md +6 -0
- package/.claude/skills/cc-do/PLAYBOOK.md +7 -6
- package/.claude/skills/cc-do/SKILL.md +27 -12
- package/.claude/skills/cc-do/references/execution-recovery.md +9 -0
- package/.claude/skills/cc-investigate/CHANGELOG.md +6 -0
- package/.claude/skills/cc-investigate/PLAYBOOK.md +5 -1
- package/.claude/skills/cc-investigate/SKILL.md +22 -5
- package/.claude/skills/cc-investigate/assets/ANALYSIS_TEMPLATE.md +14 -0
- package/.claude/skills/cc-investigate/assets/TASKS_TEMPLATE.md +1 -0
- package/.claude/skills/cc-investigate/assets/TASK_MANIFEST_TEMPLATE.json +9 -1
- package/.claude/skills/cc-investigate/references/investigation-contract.md +2 -0
- package/.claude/skills/cc-plan/CHANGELOG.md +35 -0
- package/.claude/skills/cc-plan/PLAYBOOK.md +41 -19
- package/.claude/skills/cc-plan/SKILL.md +132 -47
- package/.claude/skills/cc-plan/assets/DESIGN_TEMPLATE.md +77 -3
- package/.claude/skills/cc-plan/assets/TASKS_TEMPLATE.md +28 -5
- package/.claude/skills/cc-plan/assets/TASK_MANIFEST_TEMPLATE.json +84 -3
- package/.claude/skills/cc-plan/assets/TINY_DESIGN_TEMPLATE.md +51 -0
- package/.claude/skills/cc-plan/references/planning-contract.md +47 -15
- package/.claude/skills/cc-roadmap/CHANGELOG.md +12 -0
- package/.claude/skills/cc-roadmap/PLAYBOOK.md +15 -9
- package/.claude/skills/cc-roadmap/SKILL.md +22 -16
- package/.claude/skills/cc-roadmap/assets/BACKLOG_TEMPLATE.md +3 -1
- package/.claude/skills/cc-roadmap/assets/ROADMAP_TEMPLATE.md +11 -1
- package/.claude/skills/cc-roadmap/assets/TRACKING_TEMPLATE.json +57 -10
- package/.claude/skills/cc-roadmap/scripts/lib/roadmap-tracking/markdown.js +68 -3
- package/.claude/skills/cc-roadmap/scripts/lib/roadmap-tracking/schema.js +120 -0
- package/.claude/skills/cc-roadmap/scripts/lib/roadmap-tracking/store.js +25 -1
- package/.claude/skills/cc-roadmap/scripts/locate-roadmap-item.sh +13 -5
- package/.claude/skills/cc-roadmap/scripts/roadmap-tracking.js +3 -3
- package/.claude/skills/cc-roadmap/scripts/sync-roadmap-progress.sh +3 -3
- package/CHANGELOG.md +19 -0
- package/README.md +5 -5
- package/README.zh-CN.md +5 -5
- package/bin/cc-devflow-cli.js +16 -2
- package/docs/CLAUDE.md +1 -1
- package/docs/examples/START-HERE.md +3 -3
- package/docs/examples/example-bindings.json +26 -9
- package/docs/examples/full-design-blocked/BACKLOG.md +4 -2
- package/docs/examples/full-design-blocked/README.md +4 -4
- package/docs/examples/full-design-blocked/ROADMAP.md +16 -2
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/design.md +47 -1
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/task-manifest.json +97 -0
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/tasks.md +8 -1
- package/docs/examples/full-design-blocked/roadmap.json +123 -0
- package/docs/examples/local-handoff/BACKLOG.md +4 -2
- package/docs/examples/local-handoff/README.md +4 -4
- package/docs/examples/local-handoff/ROADMAP.md +16 -2
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/design.md +26 -1
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/task-manifest.json +55 -0
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/tasks.md +8 -1
- package/docs/examples/local-handoff/roadmap.json +121 -0
- package/docs/examples/pdca-loop/BACKLOG.md +4 -2
- package/docs/examples/pdca-loop/README.md +4 -4
- package/docs/examples/pdca-loop/ROADMAP.md +16 -2
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/design.md +26 -1
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/task-manifest.json +51 -3
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/tasks.md +8 -1
- package/docs/examples/pdca-loop/roadmap.json +191 -0
- package/docs/examples/scripts/check-example-bindings.sh +7 -4
- package/docs/guides/getting-started.md +2 -2
- package/docs/guides/getting-started.zh-CN.md +2 -2
- package/lib/compiler/__tests__/skills-registry.test.js +17 -3
- package/lib/skill-runtime/__tests__/autopilot.test.js +13 -10
- package/lib/skill-runtime/__tests__/cli-bootstrap.integration.test.js +9 -1
- package/lib/skill-runtime/__tests__/paths.test.js +25 -0
- package/lib/skill-runtime/__tests__/query.test.js +49 -0
- package/lib/skill-runtime/artifacts.js +2 -2
- package/lib/skill-runtime/intent.js +14 -14
- package/lib/skill-runtime/operations/autopilot-shared.js +4 -4
- package/lib/skill-runtime/paths.js +28 -7
- package/lib/skill-runtime/query-registry.js +3 -3
- package/lib/skill-runtime/query.js +30 -30
- package/package.json +1 -1
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version":
|
|
2
|
+
"version": 3,
|
|
3
3
|
"outputPolicy": {
|
|
4
4
|
"documentLanguage": ""
|
|
5
5
|
},
|
|
6
|
-
"
|
|
7
|
-
"backlogMeta": {
|
|
6
|
+
"meta": {
|
|
8
7
|
"roadmapVersion": "roadmap.v1",
|
|
9
|
-
"skillVersion": "
|
|
8
|
+
"skillVersion": "5.0.0",
|
|
9
|
+
"status": "active",
|
|
10
|
+
"lastUpdated": "2026-05-01",
|
|
10
11
|
"currentFocusStage": "Stage 1"
|
|
11
12
|
},
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
13
|
+
"context": {
|
|
14
|
+
"planningPosture": "",
|
|
15
|
+
"evidenceMaturity": "",
|
|
16
|
+
"canonicalTerms": [],
|
|
17
|
+
"durableDecisionSources": []
|
|
17
18
|
},
|
|
19
|
+
"evidence": [],
|
|
20
|
+
"route": {
|
|
21
|
+
"recommended": "",
|
|
22
|
+
"whyThisWinsNow": "",
|
|
23
|
+
"rejectedRoutes": [],
|
|
24
|
+
"firstSignal": "",
|
|
25
|
+
"killSignal": ""
|
|
26
|
+
},
|
|
27
|
+
"stages": [],
|
|
18
28
|
"items": [
|
|
19
29
|
{
|
|
20
30
|
"rmId": "RM-001",
|
|
@@ -48,5 +58,42 @@
|
|
|
48
58
|
"missingEvidence": ""
|
|
49
59
|
}
|
|
50
60
|
}
|
|
51
|
-
]
|
|
61
|
+
],
|
|
62
|
+
"handoff": {
|
|
63
|
+
"readyForCcPlan": [],
|
|
64
|
+
"parked": [],
|
|
65
|
+
"serialSpine": [
|
|
66
|
+
"RM-001"
|
|
67
|
+
],
|
|
68
|
+
"parallelWaves": []
|
|
69
|
+
},
|
|
70
|
+
"architecture": {
|
|
71
|
+
"diagramType": "flowchart",
|
|
72
|
+
"nodes": [
|
|
73
|
+
{
|
|
74
|
+
"id": "roadmap_json",
|
|
75
|
+
"label": "roadmap.json"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "roadmap_md",
|
|
79
|
+
"label": "ROADMAP.md"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"id": "cc_plan",
|
|
83
|
+
"label": "cc-plan"
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
"edges": [
|
|
87
|
+
{
|
|
88
|
+
"from": "roadmap_json",
|
|
89
|
+
"to": "roadmap_md",
|
|
90
|
+
"label": "renders"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"from": "roadmap_md",
|
|
94
|
+
"to": "cc_plan",
|
|
95
|
+
"label": "hands off"
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}
|
|
52
99
|
}
|
|
@@ -445,13 +445,18 @@ function renderRoadmapTable(tracking) {
|
|
|
445
445
|
return [header, separator, ...rows.map((row) => `| ${row} |`)].join('\n');
|
|
446
446
|
}
|
|
447
447
|
|
|
448
|
+
function isRoadmapState(tracking) {
|
|
449
|
+
return Number(tracking.version) === 3;
|
|
450
|
+
}
|
|
451
|
+
|
|
448
452
|
function buildTrackingBody(roadmapFile, trackingFile, tracking) {
|
|
449
453
|
const relativePath = path.relative(path.dirname(roadmapFile), trackingFile).replace(/\\/g, '/');
|
|
450
454
|
const displayPath = relativePath || path.basename(trackingFile);
|
|
455
|
+
const sourceLabel = isRoadmapState(tracking) ? 'Roadmap state source' : 'Tracking source';
|
|
451
456
|
|
|
452
457
|
return [
|
|
453
458
|
'',
|
|
454
|
-
`-
|
|
459
|
+
`- ${sourceLabel}: \`${displayPath}\``,
|
|
455
460
|
'',
|
|
456
461
|
'<!-- roadmap-tracking:start -->',
|
|
457
462
|
renderRoadmapTable(tracking),
|
|
@@ -460,14 +465,69 @@ function buildTrackingBody(roadmapFile, trackingFile, tracking) {
|
|
|
460
465
|
].join('\n');
|
|
461
466
|
}
|
|
462
467
|
|
|
468
|
+
function formatMermaidId(value) {
|
|
469
|
+
return String(value || '')
|
|
470
|
+
.trim()
|
|
471
|
+
.replace(/[^A-Za-z0-9_]/g, '_');
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
function formatMermaidLabel(value) {
|
|
475
|
+
return String(value || '').replace(/"/g, '\\"');
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function renderArchitectureDiagram(tracking) {
|
|
479
|
+
const architecture = tracking.architecture || {};
|
|
480
|
+
const nodes = Array.isArray(architecture.nodes) ? architecture.nodes : [];
|
|
481
|
+
const edges = Array.isArray(architecture.edges) ? architecture.edges : [];
|
|
482
|
+
|
|
483
|
+
if (!nodes.length && !edges.length) {
|
|
484
|
+
return '';
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
const lines = ['## Technical Architecture', '', '```mermaid', 'flowchart TD'];
|
|
488
|
+
|
|
489
|
+
nodes.forEach((node) => {
|
|
490
|
+
const id = formatMermaidId(node.id);
|
|
491
|
+
if (id) {
|
|
492
|
+
lines.push(` ${id}["${formatMermaidLabel(node.label || node.id)}"]`);
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
edges.forEach((edge) => {
|
|
497
|
+
const from = formatMermaidId(edge.from);
|
|
498
|
+
const to = formatMermaidId(edge.to);
|
|
499
|
+
if (!from || !to) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const label = String(edge.label || '').trim();
|
|
504
|
+
lines.push(label ? ` ${from} -->|${formatMermaidLabel(label)}| ${to}` : ` ${from} --> ${to}`);
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
lines.push('```', '');
|
|
508
|
+
return lines.join('\n');
|
|
509
|
+
}
|
|
510
|
+
|
|
463
511
|
function renderRoadmapDocument({ original = '# ROADMAP\n', roadmapFile, trackingFile, tracking }) {
|
|
464
512
|
const section = extractSection(original, 'Implementation Tracking');
|
|
465
513
|
const body = buildTrackingBody(roadmapFile, trackingFile, tracking);
|
|
466
514
|
const nextSection = `## Implementation Tracking${body}`;
|
|
515
|
+
const architectureSection = isRoadmapState(tracking) ? `\n${renderArchitectureDiagram(tracking)}` : '';
|
|
467
516
|
|
|
468
|
-
|
|
517
|
+
const rendered = section
|
|
469
518
|
? `${original.slice(0, section.start)}${nextSection}${original.slice(section.end)}`
|
|
470
519
|
: `${original.replace(/\s*$/, '')}\n\n${nextSection}\n`;
|
|
520
|
+
|
|
521
|
+
if (!architectureSection.trim()) {
|
|
522
|
+
return rendered;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
const existingArchitecture = extractSection(rendered, 'Technical Architecture');
|
|
526
|
+
if (existingArchitecture) {
|
|
527
|
+
return `${rendered.slice(0, existingArchitecture.start)}${architectureSection.trimEnd()}\n${rendered.slice(existingArchitecture.end)}`;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
return `${rendered.replace(/\s*$/, '')}\n\n${architectureSection}`;
|
|
471
531
|
}
|
|
472
532
|
|
|
473
533
|
function renderBacklogQueue(tracking) {
|
|
@@ -564,17 +624,22 @@ function renderParked(tracking) {
|
|
|
564
624
|
function renderBacklogDocument({ backlogFile, trackingFile, tracking }) {
|
|
565
625
|
const relativePath = path.relative(path.dirname(backlogFile), trackingFile).replace(/\\/g, '/');
|
|
566
626
|
const displayPath = relativePath || path.basename(trackingFile);
|
|
627
|
+
const sourceLabel = isRoadmapState(tracking) ? 'Roadmap state source' : 'Tracking source';
|
|
628
|
+
const deprecationNotice = isRoadmapState(tracking)
|
|
629
|
+
? ['> Deprecated projection. Edit `roadmap.json` instead.', '']
|
|
630
|
+
: [];
|
|
567
631
|
|
|
568
632
|
return [
|
|
569
633
|
'# BACKLOG',
|
|
570
634
|
'',
|
|
635
|
+
...deprecationNotice,
|
|
571
636
|
'## Backlog Meta',
|
|
572
637
|
'',
|
|
573
638
|
`- Roadmap version: ${formatInlineCode(tracking.backlogMeta.roadmapVersion)}`,
|
|
574
639
|
`- Skill version: ${formatInlineCode(tracking.backlogMeta.skillVersion)}`,
|
|
575
640
|
`- Last synced: ${formatInlineCode(tracking.lastSyncedAt)}`,
|
|
576
641
|
`- Current focus stage: ${formatInlineCode(tracking.backlogMeta.currentFocusStage)}`,
|
|
577
|
-
`-
|
|
642
|
+
`- ${sourceLabel}: \`${displayPath}\``,
|
|
578
643
|
'',
|
|
579
644
|
'## Queue',
|
|
580
645
|
'',
|
|
@@ -65,6 +65,47 @@ const DEFAULT_TRACKING = {
|
|
|
65
65
|
items: []
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
+
const DEFAULT_ROADMAP_STATE = {
|
|
69
|
+
version: 3,
|
|
70
|
+
outputPolicy: {
|
|
71
|
+
documentLanguage: 'en'
|
|
72
|
+
},
|
|
73
|
+
meta: {
|
|
74
|
+
roadmapVersion: '',
|
|
75
|
+
skillVersion: '',
|
|
76
|
+
status: 'active',
|
|
77
|
+
lastUpdated: '',
|
|
78
|
+
currentFocusStage: ''
|
|
79
|
+
},
|
|
80
|
+
context: {
|
|
81
|
+
planningPosture: '',
|
|
82
|
+
evidenceMaturity: '',
|
|
83
|
+
canonicalTerms: [],
|
|
84
|
+
durableDecisionSources: []
|
|
85
|
+
},
|
|
86
|
+
evidence: [],
|
|
87
|
+
route: {
|
|
88
|
+
recommended: '',
|
|
89
|
+
whyThisWinsNow: '',
|
|
90
|
+
rejectedRoutes: [],
|
|
91
|
+
firstSignal: '',
|
|
92
|
+
killSignal: ''
|
|
93
|
+
},
|
|
94
|
+
stages: [],
|
|
95
|
+
items: [],
|
|
96
|
+
handoff: {
|
|
97
|
+
readyForCcPlan: [],
|
|
98
|
+
parked: [],
|
|
99
|
+
serialSpine: [],
|
|
100
|
+
parallelWaves: []
|
|
101
|
+
},
|
|
102
|
+
architecture: {
|
|
103
|
+
diagramType: 'flowchart',
|
|
104
|
+
nodes: [],
|
|
105
|
+
edges: []
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
68
109
|
function normalizeHeader(value) {
|
|
69
110
|
return String(value || '')
|
|
70
111
|
.trim()
|
|
@@ -188,6 +229,83 @@ function normalizeTracking(raw) {
|
|
|
188
229
|
};
|
|
189
230
|
}
|
|
190
231
|
|
|
232
|
+
function normalizeStringList(value) {
|
|
233
|
+
if (Array.isArray(value)) {
|
|
234
|
+
return value.map((entry) => String(entry).trim()).filter(Boolean);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return parseList(value);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function buildRoadmapHandoff(tracking, handoff = {}) {
|
|
241
|
+
const items = Array.isArray(tracking.items) ? tracking.items : [];
|
|
242
|
+
const dependencyHandoff = tracking.dependencyHandoff || {};
|
|
243
|
+
const readyForCcPlan = normalizeStringList(handoff.readyForCcPlan);
|
|
244
|
+
const parked = normalizeStringList(handoff.parked);
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
readyForCcPlan: readyForCcPlan.length
|
|
248
|
+
? readyForCcPlan
|
|
249
|
+
: items.filter((item) => item.backlog.ready && !item.backlog.parked).map((item) => item.rmId),
|
|
250
|
+
parked: parked.length
|
|
251
|
+
? parked
|
|
252
|
+
: items.filter((item) => item.backlog.parked).map((item) => item.rmId),
|
|
253
|
+
serialSpine: normalizeStringList(handoff.serialSpine || dependencyHandoff.serialSpine),
|
|
254
|
+
parallelWaves: normalizeStringList(
|
|
255
|
+
handoff.parallelWaves || dependencyHandoff.parallelReadyNextWave
|
|
256
|
+
)
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function normalizeRoadmapState(raw = {}) {
|
|
261
|
+
const tracking = normalizeTracking(raw);
|
|
262
|
+
const meta = raw.meta || {};
|
|
263
|
+
const context = raw.context || {};
|
|
264
|
+
const route = raw.route || {};
|
|
265
|
+
const architecture = raw.architecture || {};
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
...DEFAULT_ROADMAP_STATE,
|
|
269
|
+
version: 3,
|
|
270
|
+
outputPolicy: {
|
|
271
|
+
...DEFAULT_ROADMAP_STATE.outputPolicy,
|
|
272
|
+
...(raw.outputPolicy || {})
|
|
273
|
+
},
|
|
274
|
+
meta: {
|
|
275
|
+
...DEFAULT_ROADMAP_STATE.meta,
|
|
276
|
+
roadmapVersion: String(meta.roadmapVersion || tracking.backlogMeta.roadmapVersion).trim(),
|
|
277
|
+
skillVersion: String(meta.skillVersion || tracking.backlogMeta.skillVersion).trim(),
|
|
278
|
+
status: String(meta.status || DEFAULT_ROADMAP_STATE.meta.status).trim(),
|
|
279
|
+
lastUpdated: String(meta.lastUpdated || tracking.lastSyncedAt).trim(),
|
|
280
|
+
currentFocusStage: String(meta.currentFocusStage || tracking.backlogMeta.currentFocusStage).trim()
|
|
281
|
+
},
|
|
282
|
+
context: {
|
|
283
|
+
...DEFAULT_ROADMAP_STATE.context,
|
|
284
|
+
...context,
|
|
285
|
+
canonicalTerms: normalizeStringList(context.canonicalTerms),
|
|
286
|
+
durableDecisionSources: normalizeStringList(context.durableDecisionSources)
|
|
287
|
+
},
|
|
288
|
+
evidence: Array.isArray(raw.evidence) ? raw.evidence : [],
|
|
289
|
+
route: {
|
|
290
|
+
...DEFAULT_ROADMAP_STATE.route,
|
|
291
|
+
...route,
|
|
292
|
+
rejectedRoutes: Array.isArray(route.rejectedRoutes) ? route.rejectedRoutes : []
|
|
293
|
+
},
|
|
294
|
+
stages: Array.isArray(raw.stages) ? raw.stages : [],
|
|
295
|
+
items: tracking.items,
|
|
296
|
+
backlogMeta: tracking.backlogMeta,
|
|
297
|
+
dependencyHandoff: tracking.dependencyHandoff,
|
|
298
|
+
lastSyncedAt: tracking.lastSyncedAt,
|
|
299
|
+
handoff: buildRoadmapHandoff(tracking, raw.handoff || {}),
|
|
300
|
+
architecture: {
|
|
301
|
+
...DEFAULT_ROADMAP_STATE.architecture,
|
|
302
|
+
...architecture,
|
|
303
|
+
nodes: Array.isArray(architecture.nodes) ? architecture.nodes : [],
|
|
304
|
+
edges: Array.isArray(architecture.edges) ? architecture.edges : []
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
191
309
|
const ROADMAP_HEADER_TO_KEY = new Map(
|
|
192
310
|
ROADMAP_COLUMNS.map(([header, key]) => [normalizeHeader(header), key])
|
|
193
311
|
);
|
|
@@ -225,6 +343,7 @@ const PARKED_FIELD_MAP = new Map(
|
|
|
225
343
|
module.exports = {
|
|
226
344
|
BACKLOG_QUEUE_COLUMNS,
|
|
227
345
|
BACKLOG_QUEUE_HEADER_TO_KEY,
|
|
346
|
+
DEFAULT_ROADMAP_STATE,
|
|
228
347
|
DEFAULT_TRACKING,
|
|
229
348
|
PARKED_FIELD_MAP,
|
|
230
349
|
READY_FIELD_MAP,
|
|
@@ -240,6 +359,7 @@ module.exports = {
|
|
|
240
359
|
normalizeCell,
|
|
241
360
|
normalizeHeader,
|
|
242
361
|
normalizeItem,
|
|
362
|
+
normalizeRoadmapState,
|
|
243
363
|
normalizeTracking,
|
|
244
364
|
parseList
|
|
245
365
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
2
3
|
|
|
3
4
|
const {
|
|
4
5
|
emptyBacklog,
|
|
5
6
|
normalizeItem,
|
|
7
|
+
normalizeRoadmapState,
|
|
6
8
|
normalizeTracking,
|
|
7
9
|
parseList
|
|
8
10
|
} = require('./schema');
|
|
@@ -63,7 +65,26 @@ function upgradeLegacyTracking(parsed) {
|
|
|
63
65
|
});
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
function isRoadmapStateFile(filePath) {
|
|
69
|
+
return path.basename(filePath || '') === 'roadmap.json';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function legacyTrackingFileFor(filePath) {
|
|
73
|
+
return path.join(path.dirname(filePath), 'roadmap-tracking.json');
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
function loadTracking({ trackingFile, roadmapFile = '', backlogFile = '' }) {
|
|
77
|
+
if (isRoadmapStateFile(trackingFile)) {
|
|
78
|
+
if (fs.existsSync(trackingFile)) {
|
|
79
|
+
return normalizeRoadmapState(readJson(trackingFile));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const legacyTrackingFile = legacyTrackingFileFor(trackingFile);
|
|
83
|
+
if (fs.existsSync(legacyTrackingFile)) {
|
|
84
|
+
return normalizeRoadmapState(readJson(legacyTrackingFile));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
67
88
|
if (trackingFile && fs.existsSync(trackingFile)) {
|
|
68
89
|
return upgradeLegacyTracking(readJson(trackingFile));
|
|
69
90
|
}
|
|
@@ -112,7 +133,10 @@ function applySyncArgs(tracking, args) {
|
|
|
112
133
|
}
|
|
113
134
|
|
|
114
135
|
function persistTrackingFiles({ trackingFile, roadmapFile, backlogFile, tracking }) {
|
|
115
|
-
writeJson(
|
|
136
|
+
writeJson(
|
|
137
|
+
trackingFile,
|
|
138
|
+
isRoadmapStateFile(trackingFile) ? normalizeRoadmapState(tracking) : tracking
|
|
139
|
+
);
|
|
116
140
|
|
|
117
141
|
const roadmapOutput = renderRoadmapDocument({
|
|
118
142
|
original: readFileIfExists(roadmapFile) || '# ROADMAP\n',
|
|
@@ -8,7 +8,7 @@ set -euo pipefail
|
|
|
8
8
|
|
|
9
9
|
usage() {
|
|
10
10
|
cat <<'EOF'
|
|
11
|
-
Usage: locate-roadmap-item.sh <ID> [--roadmap devflow/ROADMAP.md] [--backlog devflow/BACKLOG.md] [--tracking-file devflow/roadmap
|
|
11
|
+
Usage: locate-roadmap-item.sh <ID> [--roadmap devflow/ROADMAP.md] [--backlog devflow/BACKLOG.md] [--tracking-file devflow/roadmap.json]
|
|
12
12
|
|
|
13
13
|
ID can be RM-xxx or REQ-xxx.
|
|
14
14
|
EOF
|
|
@@ -22,8 +22,10 @@ LEGACY_ROADMAP_FILE="$REPO_ROOT/devflow/roadmap/roadmap.md"
|
|
|
22
22
|
DEFAULT_BACKLOG_FILE="$REPO_ROOT/devflow/BACKLOG.md"
|
|
23
23
|
ROOT_BACKLOG_FILE="$REPO_ROOT/BACKLOG.md"
|
|
24
24
|
LEGACY_BACKLOG_FILE="$REPO_ROOT/devflow/roadmap/backlog.md"
|
|
25
|
-
DEFAULT_TRACKING_FILE="$REPO_ROOT/devflow/roadmap
|
|
26
|
-
ROOT_TRACKING_FILE="$REPO_ROOT/roadmap
|
|
25
|
+
DEFAULT_TRACKING_FILE="$REPO_ROOT/devflow/roadmap.json"
|
|
26
|
+
ROOT_TRACKING_FILE="$REPO_ROOT/roadmap.json"
|
|
27
|
+
LEGACY_DEFAULT_TRACKING_FILE="$REPO_ROOT/devflow/roadmap-tracking.json"
|
|
28
|
+
LEGACY_ROOT_TRACKING_FILE="$REPO_ROOT/roadmap-tracking.json"
|
|
27
29
|
LEGACY_TRACKING_FILE="$REPO_ROOT/devflow/roadmap/roadmap-tracking.json"
|
|
28
30
|
ROADMAP_FILE="$DEFAULT_ROADMAP_FILE"
|
|
29
31
|
BACKLOG_FILE="$DEFAULT_BACKLOG_FILE"
|
|
@@ -40,7 +42,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
40
42
|
case "$1" in
|
|
41
43
|
--roadmap) ROADMAP_FILE="$2"; shift 2 ;;
|
|
42
44
|
--backlog) BACKLOG_FILE="$2"; shift 2 ;;
|
|
43
|
-
--tracking-file) TRACKING_FILE="$2"; shift 2 ;;
|
|
45
|
+
--tracking|--tracking-file) TRACKING_FILE="$2"; shift 2 ;;
|
|
44
46
|
-h|--help) usage; exit 0 ;;
|
|
45
47
|
*) echo "Unknown arg: $1" >&2; usage; exit 1 ;;
|
|
46
48
|
esac
|
|
@@ -64,10 +66,16 @@ fi
|
|
|
64
66
|
|
|
65
67
|
if [[ "$TRACKING_FILE" == "$DEFAULT_TRACKING_FILE" && ! -f "$TRACKING_FILE" ]]; then
|
|
66
68
|
roadmap_dir="$(cd "$(dirname "$ROADMAP_FILE")" 2>/dev/null && pwd || true)"
|
|
67
|
-
if [[ -n "$roadmap_dir" && -f "$roadmap_dir/roadmap
|
|
69
|
+
if [[ -n "$roadmap_dir" && -f "$roadmap_dir/roadmap.json" ]]; then
|
|
70
|
+
TRACKING_FILE="$roadmap_dir/roadmap.json"
|
|
71
|
+
elif [[ -n "$roadmap_dir" && -f "$roadmap_dir/roadmap-tracking.json" ]]; then
|
|
68
72
|
TRACKING_FILE="$roadmap_dir/roadmap-tracking.json"
|
|
69
73
|
elif [[ -f "$ROOT_TRACKING_FILE" ]]; then
|
|
70
74
|
TRACKING_FILE="$ROOT_TRACKING_FILE"
|
|
75
|
+
elif [[ -f "$LEGACY_DEFAULT_TRACKING_FILE" ]]; then
|
|
76
|
+
TRACKING_FILE="$LEGACY_DEFAULT_TRACKING_FILE"
|
|
77
|
+
elif [[ -f "$LEGACY_ROOT_TRACKING_FILE" ]]; then
|
|
78
|
+
TRACKING_FILE="$LEGACY_ROOT_TRACKING_FILE"
|
|
71
79
|
elif [[ -f "$LEGACY_TRACKING_FILE" ]]; then
|
|
72
80
|
TRACKING_FILE="$LEGACY_TRACKING_FILE"
|
|
73
81
|
fi
|
|
@@ -9,9 +9,9 @@ function usage() {
|
|
|
9
9
|
process.stderr.write(
|
|
10
10
|
[
|
|
11
11
|
'Usage:',
|
|
12
|
-
' roadmap-tracking.js sync --roadmap <ROADMAP.md> --backlog <BACKLOG.md> --tracking <roadmap
|
|
13
|
-
' roadmap-tracking.js render --roadmap <ROADMAP.md> --backlog <BACKLOG.md> --tracking <roadmap
|
|
14
|
-
' roadmap-tracking.js find --tracking <roadmap
|
|
12
|
+
' roadmap-tracking.js sync --roadmap <ROADMAP.md> --backlog <BACKLOG.md> --tracking <roadmap.json> --rm <RM-ID> [field updates]',
|
|
13
|
+
' roadmap-tracking.js render --roadmap <ROADMAP.md> --backlog <BACKLOG.md> --tracking <roadmap.json>',
|
|
14
|
+
' roadmap-tracking.js find --tracking <roadmap.json> --id <RM-ID|REQ-ID>',
|
|
15
15
|
'',
|
|
16
16
|
'Fields:',
|
|
17
17
|
' --item <title>',
|
|
@@ -11,7 +11,7 @@ usage() {
|
|
|
11
11
|
Usage: sync-roadmap-progress.sh --rm RM-001 [--status Planned] [--req REQ-001] [--progress 50%] [--file devflow/ROADMAP.md]
|
|
12
12
|
[--item "Add copy action"] [--stage "Stage 1"] [--priority P1] [--depends-on "RM-000"]
|
|
13
13
|
[--primary-capability cap-example] [--secondary-capabilities "cap-a,cap-b"] [--spec-delta "tighten truth"]
|
|
14
|
-
[--tracking-file devflow/roadmap
|
|
14
|
+
[--tracking-file devflow/roadmap.json] [--backlog-file devflow/BACKLOG.md]
|
|
15
15
|
EOF
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -49,7 +49,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
49
49
|
--secondary-capabilities) SECONDARY_CAPABILITIES="$2"; shift 2 ;;
|
|
50
50
|
--spec-delta) SPEC_DELTA="$2"; shift 2 ;;
|
|
51
51
|
--file) FILE="$2"; shift 2 ;;
|
|
52
|
-
--tracking-file) TRACKING_FILE="$2"; shift 2 ;;
|
|
52
|
+
--tracking|--tracking-file) TRACKING_FILE="$2"; shift 2 ;;
|
|
53
53
|
--backlog-file) BACKLOG_FILE="$2"; shift 2 ;;
|
|
54
54
|
-h|--help) usage; exit 0 ;;
|
|
55
55
|
*) echo "Unknown arg: $1" >&2; usage; exit 1 ;;
|
|
@@ -70,7 +70,7 @@ if [[ -z "$RM_ID" || ! -f "$FILE" ]]; then
|
|
|
70
70
|
fi
|
|
71
71
|
|
|
72
72
|
if [[ -z "$TRACKING_FILE" ]]; then
|
|
73
|
-
TRACKING_FILE="$(cd "$(dirname "$FILE")" && pwd)/roadmap
|
|
73
|
+
TRACKING_FILE="$(cd "$(dirname "$FILE")" && pwd)/roadmap.json"
|
|
74
74
|
fi
|
|
75
75
|
|
|
76
76
|
if [[ -z "$BACKLOG_FILE" ]]; then
|
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [4.5.6] - 2026-05-08
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Updated `cc-plan` with a fixed Decision Question Protocol so approval gates use numbered questions, recommendations, option tradeoffs, impact, and STOP instead of ad hoc prose.
|
|
17
|
+
- Updated `cc-plan` to treat the full `REQ/FIX-<number>-<description>` change key as identity, so repeated numbers from parallel worktrees stay distinct.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Fixed typed runtime queries and `cc-devflow query` so duplicate local change numbers can be resolved with an explicit `--change-key`.
|
|
22
|
+
- Fixed ambiguous query path resolution so duplicate change ids return a structured JSON failure instead of escaping the query registry.
|
|
23
|
+
|
|
24
|
+
## [4.5.5] - 2026-05-06
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- Updated `cc-plan` and `cc-investigate` with Roadmap Sync Gates so frozen planning and root-cause handoffs reconcile source RM progress before moving to `cc-do`.
|
|
29
|
+
- Updated `cc-act` to check roadmap progress during closeout and to write source RM status through `devflow/roadmap.json` with regenerated `ROADMAP.md` / `BACKLOG.md` projections.
|
|
30
|
+
|
|
12
31
|
## [4.5.4] - 2026-04-29
|
|
13
32
|
|
|
14
33
|
### Fixed
|
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ After installation, ask your agent to use the workflow skills directly. Start wi
|
|
|
62
62
|
|
|
63
63
|
| Skill | Use it when | Main output |
|
|
64
64
|
| --- | --- | --- |
|
|
65
|
-
| `cc-roadmap` | You need product direction, staged scope, or backlog order | `devflow/ROADMAP.md`, `devflow/BACKLOG.md` |
|
|
65
|
+
| `cc-roadmap` | You need product direction, staged scope, or backlog order | `devflow/roadmap.json`, `devflow/ROADMAP.md`, deprecated `devflow/BACKLOG.md` |
|
|
66
66
|
| `cc-plan` | A feature or change needs scope, design, and task freezing | `planning/design.md`, `planning/tasks.md`, `task-manifest.json` |
|
|
67
67
|
| `cc-investigate` | A bug needs symptom, reproduction, root cause, and repair boundary | `planning/analysis.md`, `planning/tasks.md`, `task-manifest.json` |
|
|
68
68
|
| `cc-do` | Planned or investigated work needs implementation | code, tests, checkpoints, scratch runtime |
|
|
@@ -78,15 +78,15 @@ Maintenance skills are shipped with the pack:
|
|
|
78
78
|
|
|
79
79
|
`cc-roadmap` now records planning posture, evidence maturity, canonical project language, and durable decision context before recommending a route. That keeps idea-stage, active-user, paying-customer, infrastructure, and recovery work from being forced through the same questions, and prevents roadmap items from inventing a second vocabulary. Developer-facing or operator-facing roadmap items also carry target user, time to first value, magic moment, adoption bottleneck, and domain handoff into `cc-plan`.
|
|
80
80
|
|
|
81
|
-
Canonical language and durable decisions stay inside cc-devflow-native sources: `devflow/specs/`, `devflow/
|
|
81
|
+
Canonical language and durable decisions stay inside cc-devflow-native sources: `devflow/specs/`, `devflow/roadmap.json`, `devflow/ROADMAP.md`, `planning/design.md`, `planning/analysis.md`, and `change-meta.json`.
|
|
82
82
|
|
|
83
|
-
`cc-plan` freezes more implementation decisions before `cc-do` starts. Non-trivial plans compare minimal viable and ideal architecture options, full designs include decision horizon plus error/rescue mapping, and test-first plans record test framework evidence, public test seams, behavior assertions, mock boundaries, coverage quality, mandatory regression tests, interface depth, and vertical tracer-bullet slices when existing behavior changes.
|
|
83
|
+
`cc-plan` freezes more implementation decisions before `cc-do` starts. Non-trivial plans compare minimal viable and ideal architecture options, full designs include decision horizon plus error/rescue mapping, and test-first plans record test framework evidence, public test seams, spec-style test names, public verification paths, behavior assertions, mock boundaries, coverage quality, mandatory regression tests, interface depth, Green minimality guards, refactor candidates, and vertical tracer-bullet slices when existing behavior changes. Before handoff, `cc-plan` and `cc-investigate` also reconcile the source roadmap item so RM status, REQ/FIX binding, progress, and spec diagnosis do not drift from the frozen change artifacts.
|
|
84
84
|
|
|
85
85
|
## Verification And Ship Gates
|
|
86
86
|
|
|
87
87
|
`cc-check` now treats QA as a feedback-loop problem, not only a green-test problem. Bugfix and behavior work records the loop used to prove reality, expected versus actual behavior, reproduction steps, test boundary quality, and architecture follow-ups when no clean public test seam exists.
|
|
88
88
|
|
|
89
|
-
`cc-act` carries that evidence into PR briefs, handoffs, and release notes. Follow-ups must be durable behavior briefs with current behavior, desired behavior, key interfaces, acceptance criteria, and explicit out-of-scope notes before they are written back to roadmap or backlog.
|
|
89
|
+
`cc-act` carries that evidence into PR briefs, handoffs, and release notes. It checks source roadmap progress during closeout, updates `devflow/roadmap.json`, and regenerates `devflow/ROADMAP.md` / `devflow/BACKLOG.md` when verified reality changes. Follow-ups must be durable behavior briefs with current behavior, desired behavior, key interfaces, acceptance criteria, and explicit out-of-scope notes before they are written back to roadmap or backlog.
|
|
90
90
|
|
|
91
91
|
## Installation Modes
|
|
92
92
|
|
|
@@ -193,7 +193,7 @@ The currently distributed skill folders are:
|
|
|
193
193
|
## Durable vs Ephemeral
|
|
194
194
|
|
|
195
195
|
- `devflow/specs/` stores durable capability truth: `INDEX.md` plus `capabilities/*.md`.
|
|
196
|
-
- New change directories use `REQ-<number>-<description>` for requirements or `FIX-<number>-<description>` for bug fixes.
|
|
196
|
+
- New change directories use `REQ-<number>-<description>` for requirements or `FIX-<number>-<description>` for bug fixes. `REQ` and `FIX` numbers advance independently, so the same number may exist in both prefixes. Parallel worktrees may also create repeated numbers; the full change key must use a specific description to distinguish the work.
|
|
197
197
|
- `devflow/changes/<change>/` stores durable change truth: `change-state.json`, `change-meta.json`, planning docs, `task-manifest.json`, `team-state.json`, task `checkpoint.json`, `report-card.json`, and one final handoff file.
|
|
198
198
|
- `devflow/workspaces/<change>/` stores ephemeral runtime scratch such as worker assignment, journals, prompts, and session logs.
|
|
199
199
|
- Regenerable files should not be persisted under `devflow/changes/`.
|
package/README.zh-CN.md
CHANGED
|
@@ -62,7 +62,7 @@ npx cc-devflow@latest adapt --cwd /path/to/your/project --all
|
|
|
62
62
|
|
|
63
63
|
| Skill | 什么时候用 | 主要产物 |
|
|
64
64
|
| --- | --- | --- |
|
|
65
|
-
| `cc-roadmap` | 需要产品方向、阶段范围或 backlog 顺序 | `devflow/ROADMAP.md
|
|
65
|
+
| `cc-roadmap` | 需要产品方向、阶段范围或 backlog 顺序 | `devflow/roadmap.json`、`devflow/ROADMAP.md`、deprecated `devflow/BACKLOG.md` |
|
|
66
66
|
| `cc-plan` | 新功能或变更需要澄清范围、设计方案、冻结任务 | `planning/design.md`、`planning/tasks.md`、`task-manifest.json` |
|
|
67
67
|
| `cc-investigate` | Bug 需要症状、复现、根因和修复边界 | `planning/analysis.md`、`planning/tasks.md`、`task-manifest.json` |
|
|
68
68
|
| `cc-do` | 已计划或已调查的任务需要实现 | 代码、测试、checkpoint、scratch runtime |
|
|
@@ -78,15 +78,15 @@ npx cc-devflow@latest adapt --cwd /path/to/your/project --all
|
|
|
78
78
|
|
|
79
79
|
`cc-roadmap` 现在会先记录 planning posture、evidence maturity、项目 canonical language 和持久决策上下文,再推荐路线。idea、已有用户、付费客户、infra、recovery 场景不会被套进同一组问题,也不会让 roadmap item 发明第二套词汇。面向开发者或操作者的 roadmap item 还会把目标用户、time to first value、magic moment、adoption bottleneck 和 domain handoff 交给 `cc-plan`。
|
|
80
80
|
|
|
81
|
-
Canonical language 和 durable decisions 只收敛到 cc-devflow 原生真相源:`devflow/specs/`、`devflow/
|
|
81
|
+
Canonical language 和 durable decisions 只收敛到 cc-devflow 原生真相源:`devflow/specs/`、`devflow/roadmap.json`、`devflow/ROADMAP.md`、`planning/design.md`、`planning/analysis.md` 和 `change-meta.json`。
|
|
82
82
|
|
|
83
|
-
`cc-plan` 会在 `cc-do` 开始前冻结更多实现决策。非 trivial 计划需要比较 minimal viable 和 ideal architecture,full-design 需要包含 implementation decision horizon 和 error/rescue map;测试计划要记录测试框架证据、public test seam、behavior assertion、mock boundary、覆盖质量、强制 regression test、interface depth 和 vertical tracer-bullet slices
|
|
83
|
+
`cc-plan` 会在 `cc-do` 开始前冻结更多实现决策。非 trivial 计划需要比较 minimal viable 和 ideal architecture,full-design 需要包含 implementation decision horizon 和 error/rescue map;测试计划要记录测试框架证据、public test seam、spec-style test name、public verification path、behavior assertion、mock boundary、覆盖质量、强制 regression test、interface depth、Green minimality guard、refactor candidates 和 vertical tracer-bullet slices。交接前,`cc-plan` 和 `cc-investigate` 还会校准 source roadmap item,让 RM 状态、REQ/FIX 绑定、progress 和 spec diagnosis 不再漂移。
|
|
84
84
|
|
|
85
85
|
## 验证与交付门禁
|
|
86
86
|
|
|
87
87
|
`cc-check` 现在把 QA 当成反馈环问题,而不是只看测试是否绿。Bugfix 和行为变更需要记录证明现实的 loop、expected / actual、复现步骤、测试边界质量;如果没有干净的 public test seam,要留下架构 follow-up。
|
|
88
88
|
|
|
89
|
-
`cc-act` 会把这些证据带进 PR brief、handoff 和 release note
|
|
89
|
+
`cc-act` 会把这些证据带进 PR brief、handoff 和 release note。它会在 closeout 检查 source roadmap progress,必要时更新 `devflow/roadmap.json` 并重新生成 `devflow/ROADMAP.md` / `devflow/BACKLOG.md`。Follow-up 必须写成 durable behavior brief,包含 current behavior、desired behavior、key interfaces、acceptance criteria 和 out-of-scope,再回写 roadmap 或 backlog。
|
|
90
90
|
|
|
91
91
|
## 安装方式
|
|
92
92
|
|
|
@@ -193,7 +193,7 @@ npx cc-devflow config doctor --cwd /path/to/your/project
|
|
|
193
193
|
## Durable 与 Ephemeral
|
|
194
194
|
|
|
195
195
|
- `devflow/specs/` 保存 durable capability truth:`INDEX.md` 和 `capabilities/*.md`。
|
|
196
|
-
- 新 change 目录使用 `REQ-<number>-<description>` 表示需求,使用 `FIX-<number>-<description>` 表示 Bug
|
|
196
|
+
- 新 change 目录使用 `REQ-<number>-<description>` 表示需求,使用 `FIX-<number>-<description>` 表示 Bug 修复。`REQ` 和 `FIX` 各自递增自己的编号,跨前缀同号允许共存。并行工作树也可能产生重复编号,必须用完整 change key 的描述区分业务内容。
|
|
197
197
|
- `devflow/changes/<change>/` 保存 durable change truth:`change-state.json`、`change-meta.json`、planning 文档、`task-manifest.json`、`team-state.json`、任务级 `checkpoint.json`、`report-card.json` 和唯一最终 handoff 文件。
|
|
198
198
|
- `devflow/workspaces/<change>/` 保存 ephemeral runtime scratch,例如 worker assignment、journal、prompt 和 session log。
|
|
199
199
|
- 能从 durable truth 再生成的文件,不应该持久化到 `devflow/changes/`。
|
package/bin/cc-devflow-cli.js
CHANGED
|
@@ -89,6 +89,7 @@ Query options:
|
|
|
89
89
|
--cwd <path> Project path used for devflow artifact lookup
|
|
90
90
|
--change <id> Change id, for example REQ-123
|
|
91
91
|
--change-id <id> Alias for --change
|
|
92
|
+
--change-key <key> Full change key, for example REQ-123-my-feature
|
|
92
93
|
|
|
93
94
|
Examples:
|
|
94
95
|
cc-devflow init
|
|
@@ -101,6 +102,7 @@ Examples:
|
|
|
101
102
|
cc-devflow config resolve --cwd /path/to/project --format policy
|
|
102
103
|
cc-devflow query list
|
|
103
104
|
cc-devflow query ship-readiness --cwd /path/to/project --change REQ-123
|
|
105
|
+
cc-devflow query progress --change REQ-123 --change-key REQ-123-my-feature
|
|
104
106
|
`);
|
|
105
107
|
}
|
|
106
108
|
|
|
@@ -449,6 +451,7 @@ function parseQueryArgs(args) {
|
|
|
449
451
|
const parsed = {
|
|
450
452
|
cwd: null,
|
|
451
453
|
changeId: null,
|
|
454
|
+
changeKey: null,
|
|
452
455
|
rest: []
|
|
453
456
|
};
|
|
454
457
|
|
|
@@ -480,6 +483,16 @@ function parseQueryArgs(args) {
|
|
|
480
483
|
continue;
|
|
481
484
|
}
|
|
482
485
|
|
|
486
|
+
if (arg === '--change-key') {
|
|
487
|
+
parsed.changeKey = args[++i];
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
if (arg.startsWith('--change-key=')) {
|
|
492
|
+
parsed.changeKey = arg.slice('--change-key='.length);
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
|
|
483
496
|
parsed.rest.push(arg);
|
|
484
497
|
}
|
|
485
498
|
|
|
@@ -490,7 +503,7 @@ async function runQueryCommand(args) {
|
|
|
490
503
|
const [subcommand, ...rest] = args;
|
|
491
504
|
|
|
492
505
|
if (!subcommand || subcommand === '--help' || subcommand === '-h') {
|
|
493
|
-
console.error('Use: cc-devflow query list OR cc-devflow query <id> --change <changeId> [--cwd <path>]');
|
|
506
|
+
console.error('Use: cc-devflow query list OR cc-devflow query <id> --change <changeId> [--change-key <key>] [--cwd <path>]');
|
|
494
507
|
return 3;
|
|
495
508
|
}
|
|
496
509
|
|
|
@@ -507,7 +520,8 @@ async function runQueryCommand(args) {
|
|
|
507
520
|
|
|
508
521
|
const result = await runQuery(subcommand, {
|
|
509
522
|
repoRoot: path.resolve(options.cwd || process.cwd()),
|
|
510
|
-
changeId: options.changeId
|
|
523
|
+
changeId: options.changeId,
|
|
524
|
+
changeKey: options.changeKey
|
|
511
525
|
});
|
|
512
526
|
|
|
513
527
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
package/docs/CLAUDE.md
CHANGED
|
@@ -27,4 +27,4 @@ docs/
|
|
|
27
27
|
- 面向使用者:优先写“怎么用/怎么做”,其次再写“为什么”。
|
|
28
28
|
- 可检索:标题清晰、关键词统一(`/flow-*`、`/core-*`、`/speckit.*`)。
|
|
29
29
|
- 可落地:结论必须能映射到具体命令、脚本或模板文件路径。
|
|
30
|
-
- change 目录命名必须保留大写逻辑 ID 前缀:`REQ-123-...` 表示需求变更,`FIX-123-...`
|
|
30
|
+
- change 目录命名必须保留大写逻辑 ID 前缀:`REQ-123-...` 表示需求变更,`FIX-123-...` 表示缺陷修复;`REQ` 和 `FIX` 各自递增自己的编号,跨前缀同号不是冲突;并行工作树造成重复编号时,完整 change key 依靠描述区分业务内容;描述部分使用 kebab-case。
|