cc-devflow 4.5.3 → 4.5.5

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.
Files changed (104) hide show
  1. package/.claude/skills/cc-act/CHANGELOG.md +12 -0
  2. package/.claude/skills/cc-act/PLAYBOOK.md +28 -5
  3. package/.claude/skills/cc-act/SKILL.md +45 -12
  4. package/.claude/skills/cc-act/assets/PR_BRIEF_TEMPLATE.md +39 -0
  5. package/.claude/skills/cc-act/assets/RELEASE_NOTE_TEMPLATE.md +16 -0
  6. package/.claude/skills/cc-act/references/closure-contract.md +3 -0
  7. package/.claude/skills/cc-act/scripts/cc-act-common.sh +48 -0
  8. package/.claude/skills/cc-act/scripts/generate-status-report.sh +3 -0
  9. package/.claude/skills/cc-act/scripts/render-pr-brief.sh +6 -0
  10. package/.claude/skills/cc-act/scripts/sync-act-docs.sh +13 -0
  11. package/.claude/skills/cc-check/CHANGELOG.md +6 -0
  12. package/.claude/skills/cc-check/PLAYBOOK.md +4 -0
  13. package/.claude/skills/cc-check/SKILL.md +15 -2
  14. package/.claude/skills/cc-check/assets/REPORT_CARD_TEMPLATE.json +18 -0
  15. package/.claude/skills/cc-do/CHANGELOG.md +12 -0
  16. package/.claude/skills/cc-do/PLAYBOOK.md +13 -10
  17. package/.claude/skills/cc-do/SKILL.md +40 -16
  18. package/.claude/skills/cc-do/references/execution-recovery.md +12 -0
  19. package/.claude/skills/cc-do/references/parallel-dispatch.md +6 -4
  20. package/.claude/skills/cc-do/scripts/detect-file-conflicts.sh +49 -3
  21. package/.claude/skills/cc-investigate/CHANGELOG.md +12 -0
  22. package/.claude/skills/cc-investigate/PLAYBOOK.md +12 -1
  23. package/.claude/skills/cc-investigate/SKILL.md +31 -5
  24. package/.claude/skills/cc-investigate/assets/ANALYSIS_TEMPLATE.md +44 -0
  25. package/.claude/skills/cc-investigate/assets/TASKS_TEMPLATE.md +1 -0
  26. package/.claude/skills/cc-investigate/assets/TASK_MANIFEST_TEMPLATE.json +9 -1
  27. package/.claude/skills/cc-investigate/references/investigation-contract.md +2 -0
  28. package/.claude/skills/cc-plan/CHANGELOG.md +29 -0
  29. package/.claude/skills/cc-plan/PLAYBOOK.md +43 -17
  30. package/.claude/skills/cc-plan/SKILL.md +85 -44
  31. package/.claude/skills/cc-plan/assets/DESIGN_TEMPLATE.md +109 -3
  32. package/.claude/skills/cc-plan/assets/TASKS_TEMPLATE.md +32 -5
  33. package/.claude/skills/cc-plan/assets/TASK_MANIFEST_TEMPLATE.json +85 -4
  34. package/.claude/skills/cc-plan/assets/TINY_DESIGN_TEMPLATE.md +78 -0
  35. package/.claude/skills/cc-plan/references/planning-contract.md +29 -7
  36. package/.claude/skills/cc-roadmap/CHANGELOG.md +12 -0
  37. package/.claude/skills/cc-roadmap/PLAYBOOK.md +15 -9
  38. package/.claude/skills/cc-roadmap/SKILL.md +22 -16
  39. package/.claude/skills/cc-roadmap/assets/BACKLOG_TEMPLATE.md +3 -1
  40. package/.claude/skills/cc-roadmap/assets/ROADMAP_TEMPLATE.md +11 -1
  41. package/.claude/skills/cc-roadmap/assets/TRACKING_TEMPLATE.json +57 -10
  42. package/.claude/skills/cc-roadmap/scripts/lib/roadmap-tracking/markdown.js +68 -3
  43. package/.claude/skills/cc-roadmap/scripts/lib/roadmap-tracking/schema.js +120 -0
  44. package/.claude/skills/cc-roadmap/scripts/lib/roadmap-tracking/store.js +25 -1
  45. package/.claude/skills/cc-roadmap/scripts/locate-roadmap-item.sh +13 -5
  46. package/.claude/skills/cc-roadmap/scripts/roadmap-tracking.js +3 -3
  47. package/.claude/skills/cc-roadmap/scripts/sync-roadmap-progress.sh +3 -3
  48. package/CHANGELOG.md +15 -0
  49. package/README.md +5 -5
  50. package/README.zh-CN.md +5 -5
  51. package/bin/cc-devflow-cli.js +93 -2
  52. package/docs/CLAUDE.md +1 -1
  53. package/docs/examples/START-HERE.md +3 -3
  54. package/docs/examples/example-bindings.json +27 -10
  55. package/docs/examples/full-design-blocked/BACKLOG.md +4 -2
  56. package/docs/examples/full-design-blocked/README.md +4 -4
  57. package/docs/examples/full-design-blocked/ROADMAP.md +16 -2
  58. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/design.md +39 -1
  59. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/task-manifest.json +41 -0
  60. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/tasks.md +8 -1
  61. package/docs/examples/full-design-blocked/roadmap.json +123 -0
  62. package/docs/examples/local-handoff/BACKLOG.md +4 -2
  63. package/docs/examples/local-handoff/README.md +4 -4
  64. package/docs/examples/local-handoff/ROADMAP.md +16 -2
  65. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/design.md +19 -1
  66. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/task-manifest.json +26 -0
  67. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/tasks.md +8 -1
  68. package/docs/examples/local-handoff/roadmap.json +121 -0
  69. package/docs/examples/pdca-loop/BACKLOG.md +4 -2
  70. package/docs/examples/pdca-loop/README.md +4 -4
  71. package/docs/examples/pdca-loop/ROADMAP.md +16 -2
  72. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/design.md +19 -1
  73. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/task-manifest.json +22 -3
  74. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/tasks.md +8 -1
  75. package/docs/examples/pdca-loop/roadmap.json +191 -0
  76. package/docs/examples/scripts/check-example-bindings.sh +7 -4
  77. package/docs/get-shit-done-strategy-audit.md +518 -0
  78. package/docs/guides/getting-started.md +2 -2
  79. package/docs/guides/getting-started.zh-CN.md +2 -2
  80. package/lib/compiler/__tests__/inventory.test.js +51 -0
  81. package/lib/compiler/__tests__/skills-registry.test.js +17 -3
  82. package/lib/compiler/inventory.js +78 -0
  83. package/lib/skill-runtime/__tests__/approve.test.js +92 -0
  84. package/lib/skill-runtime/__tests__/autopilot.test.js +4 -0
  85. package/lib/skill-runtime/__tests__/cli-bootstrap.integration.test.js +9 -1
  86. package/lib/skill-runtime/__tests__/planner.tdd.test.js +20 -0
  87. package/lib/skill-runtime/__tests__/query.test.js +147 -1
  88. package/lib/skill-runtime/__tests__/readiness.test.js +53 -0
  89. package/lib/skill-runtime/__tests__/release.test.js +85 -0
  90. package/lib/skill-runtime/__tests__/runtime.integration.test.js +11 -0
  91. package/lib/skill-runtime/__tests__/schemas.test.js +56 -0
  92. package/lib/skill-runtime/__tests__/worker-run.test.js +29 -0
  93. package/lib/skill-runtime/errors.js +39 -0
  94. package/lib/skill-runtime/index.js +8 -0
  95. package/lib/skill-runtime/operations/approve.js +17 -2
  96. package/lib/skill-runtime/operations/release.js +6 -3
  97. package/lib/skill-runtime/operations/worker-run.js +30 -0
  98. package/lib/skill-runtime/planner.js +10 -2
  99. package/lib/skill-runtime/query-registry.js +101 -0
  100. package/lib/skill-runtime/query.js +159 -91
  101. package/lib/skill-runtime/readiness.js +84 -0
  102. package/lib/skill-runtime/schemas.js +28 -3
  103. package/lib/skill-runtime/trace.js +22 -0
  104. package/package.json +1 -1
@@ -23,20 +23,20 @@
23
23
 
24
24
  ## Local Kit
25
25
 
26
- - 生成骨架时用 `assets/ROADMAP_TEMPLATE.md` `assets/BACKLOG_TEMPLATE.md`
27
- - 需要结构化 tracking 时用 `assets/TRACKING_TEMPLATE.json`
26
+ - 生成骨架时先用 `assets/TRACKING_TEMPLATE.json` 写 `devflow/roadmap.json`,再渲染 `assets/ROADMAP_TEMPLATE.md` / `assets/BACKLOG_TEMPLATE.md` 形状
27
+ - 需要结构化 roadmap state 时用 `assets/TRACKING_TEMPLATE.json`
28
28
  - 需要追问脚本时看 `references/roadmap-dialogue.md`
29
29
  - 需要定位 / 回写条目时用 `scripts/locate-roadmap-item.sh` 和 `scripts/sync-roadmap-progress.sh`
30
- - `scripts/locate-roadmap-item.sh` 先读 `roadmap-tracking.json`,再回落到 `ROADMAP.md` / `BACKLOG.md`,避免定位依赖 markdown 列位或文案漂移
31
- - 只想把 sidecar 重渲染回 `ROADMAP.md` / `BACKLOG.md` 时,直接调用 `scripts/roadmap-tracking.js render`
32
- - `scripts/sync-roadmap-progress.sh` 会把 `roadmap-tracking.json` 当真相源,再回渲染 `ROADMAP.md` 和 `BACKLOG.md`
30
+ - `scripts/locate-roadmap-item.sh` 先读 `roadmap.json`,再回落到旧 `roadmap-tracking.json` Markdown,避免定位依赖 markdown 列位或文案漂移
31
+ - 只想把 state 重渲染回 `ROADMAP.md` / `BACKLOG.md` 时,直接调用 `scripts/roadmap-tracking.js render`
32
+ - `scripts/sync-roadmap-progress.sh` 会把 `roadmap.json` 当真相源,再回渲染 `ROADMAP.md` 和 deprecated `BACKLOG.md`
33
33
  - 变更版本时同步 `CHANGELOG.md`,必要时用 `scripts/bump-skill-version.sh`
34
34
 
35
35
  ## Context Sweep
36
36
 
37
37
  进入 roadmap 对话前,至少摸清:
38
38
 
39
- 1. 现有 `devflow/ROADMAP.md` / `devflow/BACKLOG.md`
39
+ 1. 现有 `devflow/roadmap.json` / `devflow/ROADMAP.md` / `devflow/BACKLOG.md`
40
40
  2. `CLAUDE.md`、`README*`、`TODOS.md`
41
41
  3. 项目语言和持久决策:`devflow/specs/INDEX.md`、相关 capability specs、当前 roadmap/backlog、历史 `planning/design.md` / `planning/analysis.md`、`change-meta.json`、长期 design decision
42
42
  4. 最近相关 docs / specs / plans
@@ -116,6 +116,11 @@
116
116
 
117
117
  ## Output Contract
118
118
 
119
+ `devflow/roadmap.json`
120
+ - single editable roadmap state
121
+ - output policy, meta, context, evidence, route, stages, items, handoff, and architecture
122
+ - flat `architecture.nodes` / `architecture.edges` used to generate Mermaid
123
+
119
124
  `devflow/ROADMAP.md`
120
125
  - version / skill version / context snapshot / evidence ledger
121
126
  - 1-3 个阶段
@@ -128,13 +133,14 @@
128
133
  - 非目标
129
134
  - `RM Dependency Graph`
130
135
  - `Parallel waves`
131
- - `Implementation Tracking` 由 `devflow/roadmap-tracking.json` 渲染,避免手改 markdown 表格列位
136
+ - `Implementation Tracking` 和 `Technical Architecture` 由 `devflow/roadmap.json` 渲染,避免手改 markdown 表格或 Mermaid
132
137
 
133
138
  `devflow/BACKLOG.md`
139
+ - deprecated compatibility projection; edit `devflow/roadmap.json` instead
134
140
  - 只保留会真的进入下一轮 `cc-plan` 的事项
135
141
  - 每项注明来源阶段、优先级、证据、`Depends On`、`Parallel With`、当前未知点、下一决策、是否 ready
136
142
  - developer-facing / operator-facing 条目要带 target user、time to first value、magic moment 和 adoption bottleneck,方便 `cc-plan` 继续做 DX 设计
137
- - `Backlog Meta`、`Queue`、`Dependency Handoff`、`Ready For Req-Plan`、`Parked` 可由 `devflow/roadmap-tracking.json` 回渲染,避免 roadmap truth 和 backlog handoff 分叉
143
+ - `Backlog Meta`、`Queue`、`Dependency Handoff`、`Ready For Req-Plan`、`Parked` `devflow/roadmap.json` 回渲染,避免 roadmap truth 和 backlog handoff 分叉
138
144
 
139
145
  ## Review Loop
140
146
 
@@ -153,7 +159,7 @@
153
159
  ## Versioning
154
160
 
155
161
  - `patch`: 文案澄清、模板说明、小修补
156
- - `minor`: 上下文收集、评审、字段增强,且不破坏既有 tracking 习惯
162
+ - `minor`: 上下文收集、评审、字段增强,且不破坏既有 roadmap state 习惯
157
163
  - `major`: 核心输出契约变化,需要 migration note
158
164
 
159
165
  ## Exit Rule
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: cc-roadmap
3
- version: 4.4.1
3
+ version: 5.0.0
4
4
  description: "Use when defining, resetting, or narrowing project direction, stage order, or backlog priority before a concrete requirement enters the PDCA loop."
5
5
  triggers:
6
6
  - "帮我定路线图"
@@ -19,16 +19,20 @@ reads:
19
19
  - "assets/TRACKING_TEMPLATE.json"
20
20
  - "references/roadmap-dialogue.md"
21
21
  writes:
22
+ - path: "devflow/roadmap.json"
23
+ durability: "durable"
24
+ required: true
22
25
  - path: "devflow/ROADMAP.md"
23
26
  durability: "durable"
24
27
  required: true
25
28
  - path: "devflow/BACKLOG.md"
26
29
  durability: "durable"
27
- required: true
30
+ required: false
31
+ when: "deprecated compatibility projection is generated for downstream readers"
28
32
  - path: "devflow/roadmap-tracking.json"
29
33
  durability: "durable"
30
34
  required: false
31
- when: "roadmap/backlog tracking is maintained through bundled helper scripts"
35
+ when: "legacy projects are being migrated into devflow/roadmap.json"
32
36
  entry_gate:
33
37
  - "Read current roadmap, backlog, related capability specs, and surrounding repo context before proposing direction."
34
38
  - "Load cc-devflow native language and durable-decision sources (`devflow/specs/`, current roadmap/backlog, prior `planning/design.md` or `planning/analysis.md`, and `change-meta.json`) before naming stages, capabilities, users, or backlog items."
@@ -68,7 +72,7 @@ tool_budget:
68
72
 
69
73
  写入任何 durable Markdown 或 JSON metadata 前,先运行 `cc-devflow config resolve --format policy`。
70
74
 
71
- - `Output language` 是机器约束,`devflow/ROADMAP.md`、`devflow/BACKLOG.md` 和 tracking metadata 必须记录并遵守它。
75
+ - `Output language` 是机器约束,`devflow/roadmap.json`、`devflow/ROADMAP.md` 和兼容投影必须记录并遵守它。
72
76
  - `agent_preferences` 是用户偏好建议,只影响表达方式和结构选择,不覆盖本 Skill 的工作流边界。
73
77
  - 如果配置解析失败,先修配置或向用户说明阻塞,不要用默认语言继续生成正式文档。
74
78
 
@@ -76,9 +80,10 @@ tool_budget:
76
80
 
77
81
  1. `PLAYBOOK.md`
78
82
  2. `CHANGELOG.md`
79
- 3. `assets/ROADMAP_TEMPLATE.md`
80
- 4. `assets/BACKLOG_TEMPLATE.md`
81
- 5. `references/roadmap-dialogue.md`
83
+ 3. `assets/TRACKING_TEMPLATE.json`
84
+ 4. `assets/ROADMAP_TEMPLATE.md`
85
+ 5. `assets/BACKLOG_TEMPLATE.md`
86
+ 6. `references/roadmap-dialogue.md`
82
87
 
83
88
  ## Use This Skill When
84
89
 
@@ -104,14 +109,14 @@ tool_budget:
104
109
 
105
110
  ## Harness Contract
106
111
 
107
- - Allowed actions: read current strategy files, repo context, and recent reality; compare route shapes; decompose independent subsystems into stages and RM candidates; write `devflow/ROADMAP.md`, `devflow/BACKLOG.md`, and the optional `devflow/roadmap-tracking.json` sidecar used by bundled helpers as the shared roadmap/backlog truth source.
112
+ - Allowed actions: read current strategy files, repo context, and recent reality; compare route shapes; decompose independent subsystems into stages and RM candidates; write `devflow/roadmap.json` as the editable roadmap state, then generate `devflow/ROADMAP.md` and the deprecated `devflow/BACKLOG.md` compatibility projection from that state.
108
113
  - Forbidden actions: decompose implementation tasks, invent hidden context, or jump into `cc-plan` before the roadmap is approved.
109
114
  - Required evidence: every stage and backlog item must point back to explicit repo facts, user constraints, or observed market signals.
110
115
  - Reroute rule: once the conversation collapses to one concrete requirement, stop strategic expansion and hand off to `cc-plan`.
111
116
 
112
117
  ## Entry Gate
113
118
 
114
- 1. 如果 `devflow/ROADMAP.md` / `devflow/BACKLOG.md` 已存在,先读现状再重写。
119
+ 1. 如果 `devflow/roadmap.json`、`devflow/ROADMAP.md`、`devflow/BACKLOG.md` 或旧 `devflow/roadmap-tracking.json` 已存在,先读现状再重写。
115
120
  2. 先判断这是“项目方向问题”还是“单 requirement 执行问题”。
116
121
  3. 如果输入是多个独立子系统的混合目标,先拆成阶段和 `RM` 候选;不要继续追问某个子系统的实现细节。
117
122
  4. 先做一次上下文扫描,不能跳过现有事实直接写愿景。
@@ -232,7 +237,7 @@ tool_budget:
232
237
 
233
238
  ## Review Loop
234
239
 
235
- 写完 `devflow/ROADMAP.md` / `devflow/BACKLOG.md` 后,至少完成这 6 个检查:
240
+ 写完 `devflow/roadmap.json` 并生成 `devflow/ROADMAP.md` / `devflow/BACKLOG.md` 后,至少完成这些检查:
236
241
 
237
242
  1. Placeholder scan:不能有 TBD、TODO、`[NEEDS CONTEXT]` 之类的逃避词。
238
243
  2. Evidence scan:每个阶段是否都能指回某个现实证据,而不是空洞愿景。
@@ -250,8 +255,9 @@ tool_budget:
250
255
  ## Output
251
256
 
252
257
  - `devflow/ROADMAP.md`
253
- - `devflow/BACKLOG.md`
254
- - `devflow/roadmap-tracking.json` when helper automation needs a shared roadmap/backlog truth source
258
+ - `devflow/roadmap.json`
259
+ - `devflow/BACKLOG.md` as a deprecated compatibility projection
260
+ - `devflow/roadmap-tracking.json` only when migrating legacy projects
255
261
 
256
262
  ## Good Output
257
263
 
@@ -270,13 +276,13 @@ tool_budget:
270
276
 
271
277
  - `patch`:措辞、模板字段说明、非契约性澄清
272
278
  - `minor`:新增兼容字段、上下文收集规则、评审规则、输出结构增强
273
- - `major`:改变 `devflow/ROADMAP.md` / `devflow/BACKLOG.md` 的核心契约、阶段模型或 handoff 预期
279
+ - `major`:改变 `devflow/roadmap.json`、生成投影、阶段模型或 handoff 预期
274
280
 
275
281
  每次修改都必须:
276
282
 
277
283
  1. 更新本文件 frontmatter 的 `version`
278
284
  2. 更新 `CHANGELOG.md`
279
- 3. 如果会影响已有 `devflow/ROADMAP.md` / `devflow/BACKLOG.md` 使用方式,在 `CHANGELOG.md` 写清 migration note
285
+ 3. 如果会影响已有 `devflow/ROADMAP.md` / `devflow/BACKLOG.md` / `devflow/roadmap-tracking.json` 使用方式,在 `CHANGELOG.md` 写清 migration note
280
286
 
281
287
  ## Bundled Resources
282
288
 
@@ -286,7 +292,7 @@ tool_budget:
286
292
  - 结构化 tracking 模板:`assets/TRACKING_TEMPLATE.json`
287
293
  - 对话骨架:`references/roadmap-dialogue.md`
288
294
  - 条目定位:`scripts/locate-roadmap-item.sh`
289
- - tracking 渲染器:`scripts/roadmap-tracking.js`
295
+ - roadmap state 渲染器:`scripts/roadmap-tracking.js`
290
296
  - 进度回写:`scripts/sync-roadmap-progress.sh`
291
297
  - 版本递增:`scripts/bump-skill-version.sh`
292
298
 
@@ -302,7 +308,7 @@ tool_budget:
302
308
 
303
309
  1. 先收上下文,再收意见。
304
310
  2. 没有现实证据时必须明确写成 assumption,而不是偷偷当事实。
305
- 3. `devflow/ROADMAP.md` 是方向真相源,`devflow/BACKLOG.md` 是进入下一轮规划的缓冲区。
311
+ 3. `devflow/roadmap.json` 是唯一可编辑方向真相源,`devflow/ROADMAP.md` 和 `devflow/BACKLOG.md` 是生成投影。
306
312
  4. 决策理由必须保留下来,方便以后重跑时比较版本差异。
307
313
  5. 路线图里的术语必须沿用项目语言;没有 canonical term 时写 assumption,不要创造第二套概念系统。
308
314
  6. 不要为了显得完整而写 6 个阶段,能打赢下一仗比画完整战争图更重要。
@@ -1,5 +1,7 @@
1
1
  # BACKLOG
2
2
 
3
+ > Deprecated projection. Edit `roadmap.json` instead.
4
+
3
5
  ## Backlog Meta
4
6
 
5
7
  - Roadmap version:
@@ -7,7 +9,7 @@
7
9
  - Output language:
8
10
  - Last synced:
9
11
  - Current focus stage:
10
- - Tracking source: `devflow/roadmap-tracking.json`
12
+ - Roadmap state source: `devflow/roadmap.json`
11
13
 
12
14
  ## Queue
13
15
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  ## Roadmap Meta
4
4
 
5
+ - Roadmap state source: `devflow/roadmap.json`
5
6
  - Roadmap version:
6
7
  - Skill version:
7
8
  - Output language:
@@ -178,6 +179,15 @@ flowchart LR
178
179
  - Serial spine:
179
180
  - Parallel-ready branches:
180
181
 
182
+ ## Technical Architecture
183
+
184
+ ```mermaid
185
+ flowchart TD
186
+ roadmap_json["roadmap.json"] --> roadmap_md["ROADMAP.md"]
187
+ roadmap_json --> backlog_md["BACKLOG.md (deprecated)"]
188
+ roadmap_md --> cc_plan["cc-plan"]
189
+ ```
190
+
181
191
  ## Parallel Waves
182
192
 
183
193
  | Wave | Ready when | Items | Why parallel |
@@ -197,7 +207,7 @@ flowchart LR
197
207
 
198
208
  ## Implementation Tracking
199
209
 
200
- - Tracking source: `devflow/roadmap-tracking.json`
210
+ - Roadmap state source: `devflow/roadmap.json`
201
211
 
202
212
  <!-- roadmap-tracking:start -->
203
213
  | RM-ID | Item | Stage | Priority | Primary Capability | Secondary Capabilities | Expected Spec Delta | Depends On | Status | REQ | Progress |
@@ -1,20 +1,30 @@
1
1
  {
2
- "version": 2,
2
+ "version": 3,
3
3
  "outputPolicy": {
4
4
  "documentLanguage": ""
5
5
  },
6
- "lastSyncedAt": "2026-04-19",
7
- "backlogMeta": {
6
+ "meta": {
8
7
  "roadmapVersion": "roadmap.v1",
9
- "skillVersion": "4.4.1",
8
+ "skillVersion": "5.0.0",
9
+ "status": "active",
10
+ "lastUpdated": "2026-05-01",
10
11
  "currentFocusStage": "Stage 1"
11
12
  },
12
- "dependencyHandoff": {
13
- "serialSpine": "RM-001",
14
- "parallelReadyNextWave": "-",
15
- "decompositionNotes": "-",
16
- "notesOnBlockers": "-"
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
- `- Tracking source: \`${displayPath}\``,
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
- return section
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
- `- Tracking source: \`${displayPath}\``,
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(trackingFile, tracking);
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',