dw-kit 1.3.6 → 1.6.0-rc.1

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 (52) hide show
  1. package/.claude/agents/executor.md +80 -80
  2. package/.claude/hooks/pre-commit-gate.sh +59 -0
  3. package/.claude/hooks/stop-check.sh +111 -31
  4. package/.claude/rules/commit-standards.md +48 -37
  5. package/.claude/rules/dw.md +47 -11
  6. package/.claude/skills/dw-archive/SKILL.md +14 -0
  7. package/.claude/skills/dw-commit/SKILL.md +7 -4
  8. package/.claude/skills/dw-decision/SKILL.md +5 -4
  9. package/.claude/skills/dw-execute/SKILL.md +18 -5
  10. package/.claude/skills/dw-handoff/SKILL.md +8 -3
  11. package/.claude/skills/dw-plan/SKILL.md +15 -2
  12. package/.claude/skills/dw-research/SKILL.md +7 -5
  13. package/.claude/skills/dw-retroactive/SKILL.md +75 -63
  14. package/.claude/skills/dw-review/SKILL.md +33 -2
  15. package/.claude/skills/dw-task-init/SKILL.md +40 -35
  16. package/.dw/adapters/generic/AGENT.md +171 -169
  17. package/.dw/config/config.schema.json +149 -121
  18. package/.dw/config/dw.config.yml +14 -0
  19. package/.dw/core/WORKFLOW.md +450 -450
  20. package/.dw/core/schemas/agent-claim.schema.json +127 -0
  21. package/.dw/core/schemas/agent-report.schema.json +72 -0
  22. package/.dw/core/schemas/task-frontmatter.schema.json +78 -0
  23. package/.dw/core/templates/v3/task.md +188 -0
  24. package/CLAUDE.md +2 -2
  25. package/MIGRATION-v1.5.md +330 -0
  26. package/README.md +18 -0
  27. package/package.json +4 -2
  28. package/src/cli.mjs +176 -0
  29. package/src/commands/agent-claim.mjs +235 -0
  30. package/src/commands/agent-inspect.mjs +123 -0
  31. package/src/commands/doctor.mjs +105 -1
  32. package/src/commands/lint-task.mjs +112 -0
  33. package/src/commands/review-render.mjs +255 -0
  34. package/src/commands/task-migrate.mjs +366 -0
  35. package/src/commands/task-new.mjs +90 -0
  36. package/src/commands/task-render.mjs +235 -0
  37. package/src/commands/task-rotate.mjs +168 -0
  38. package/src/commands/task-show.mjs +137 -0
  39. package/src/commands/task-view.mjs +386 -0
  40. package/src/commands/task-watch.mjs +223 -0
  41. package/src/lib/active-index.mjs +19 -1
  42. package/src/lib/agent-claim.mjs +173 -0
  43. package/src/lib/agent-conflict.mjs +137 -0
  44. package/src/lib/agent-events.mjs +43 -0
  45. package/src/lib/agent-report.mjs +96 -0
  46. package/src/lib/config.mjs +120 -104
  47. package/src/lib/frontmatter.mjs +72 -0
  48. package/src/lib/lint-rules.mjs +149 -0
  49. package/src/lib/review/manifest-schema.json +149 -0
  50. package/src/lib/review/manifest-validator.mjs +93 -0
  51. package/src/lib/review/scope-slug.mjs +68 -0
  52. package/src/lib/timeline-parser.mjs +80 -0
@@ -0,0 +1,330 @@
1
+ # Migration Guide — dw-kit v1.3/v1.4 → v1.5
2
+
3
+ **Status:** In active development (per ADR-0008)
4
+ **Breaking change:** Task docs format default switches from v2 (2-file) to v3 (1-file `task.md`).
5
+ **Backward compat:** v2 + v1 read paths preserved. Migration is opt-in per task via `dw task migrate`.
6
+
7
+ ---
8
+
9
+ ## At a Glance
10
+
11
+ | Area | Change | Impact |
12
+ |------|--------|--------|
13
+ | Task docs | New v3 single-file `task.md` (replaces v2 `spec.md` + `tracking.md`) | **Default for new tasks** — old tasks read-compat |
14
+ | Frontmatter | JSON-schema validated (ajv) via `.dw/core/schemas/task-frontmatter.schema.json` | Strict on save (per lint) |
15
+ | CLI | New `dw task` family: `show`, `new`, `migrate`, `lint`, `rotate` | New surface |
16
+ | Lint | `dw task lint` default `strict` — blocks drift markers in Section 2, line caps, schema | Opt-out via `task_lint: off` in `dw.config.yml` |
17
+ | Hook | `stop-check` now auto-rotates Section 4 > 400 lines → `timeline-history.md` + nudges `dw task show` | Automatic |
18
+ | Indexer | `active-index.mjs` reads v3 first, falls back to v2 / v1 | Backward compatible |
19
+ | Skills | 7 skills updated for v3 (task-init / execute / handoff / research / plan / decision / retroactive) | Auto-detect format |
20
+ | Migration backups | v2 spec.md / tracking.md preserved as `.v2bak` (gitignored) | Reversible via `--rollback` |
21
+
22
+ ---
23
+
24
+ ## The Drift Problem (Motivation)
25
+
26
+ Per ADR-0008 evidence:
27
+
28
+ - `dw-kit-v2-lean-optimization` task accumulated **1081 lines** across `spec.md` (227) + `tracking.md` (615) + ad-hoc `baseline.md` (89) + `execution-log.md` (150) — variance crossed beyond what the v2 template was designed for.
29
+ - Status markers leaked into `spec.md` ("✅ COMPLETED 2026-04-21" inline) while `tracking.md` had its own "Subtask Progress" table → **two sources of truth for the same field**.
30
+ - TechLead reviewer reported "rối, lười đọc" (cluttered, skipped) when reviewing v2 layouts.
31
+
32
+ v3 fixes structurally:
33
+
34
+ - **Single source of truth:** `task.md` contains Snapshot + Intent + Tracker + Changelog + Handoff in one file.
35
+ - **No drift surface:** there is no second file to paste status into. Lint enforces "status lives only in Section 3".
36
+ - **Bounded preview:** `timeline.svg` sidecar (when rendered) is fixed composition (~10-20KB) regardless of task lifetime.
37
+ - **Auto-rotation:** Section 4 (Changelog) overflow above 400 lines → `timeline-history.md` via `stop-check` hook.
38
+
39
+ Trade-off: cross-repo migration of existing v2 tasks. Tooling provided.
40
+
41
+ ---
42
+
43
+ ## New Format — `task.md` v3
44
+
45
+ ```
46
+ .dw/tasks/{name}/
47
+ ├── task.md # canonical SoT (Sections 1-5 + optional 6 Debate)
48
+ └── (free-form supplements — indexer ignores; lint warns on generic names):
49
+ ├── baseline.md # benchmark snapshots
50
+ ├── experiment-{id}.md # spike notes
51
+ ├── debate-r{N}.md # extended adversarial logs
52
+ └── timeline-history.md # auto-rotated changelog overflow
53
+ ```
54
+
55
+ **Section structure:**
56
+
57
+ | # | Section | Purpose | Lint rule |
58
+ |---|---------|---------|-----------|
59
+ | 1 | Snapshot | Always-visible ≤15-line header for fast scan | — |
60
+ | 2 | Intent & Scope | Stable intent, Subtasks list, Out of Scope, Success Criteria, Dependencies, Risk Register | **No status markers** (✅🟡 trigger error); line cap 200 |
61
+ | 3 | Subtask Tracker | Single source of truth for ST status | Status legend required; line cap 80 |
62
+ | 4 | Timeline / Changelog | Reverse-chronological session log | Auto-rotate > 400 lines |
63
+ | 5 | Handoff & Friction | For-next-session + friction journal | — |
64
+ | 6 | Annexes | List of supplementary files | — |
65
+ | 7 | Debate Log (optional) | Thorough-depth red/blue adversarial output | — |
66
+
67
+ **Frontmatter schema** (`.dw/core/schemas/task-frontmatter.schema.json`):
68
+
69
+ Required: `task_id`, `created`, `last_updated`, `status`, `owner`, `depth`, `schema_version` (= `v3.0`).
70
+ Optional: `phase`, `related_adr`, `target_ship`, `blockers`.
71
+ `status` enum: Draft | Approved | In Progress | Blocked | Paused | Done.
72
+ `depth` enum: quick | standard | thorough.
73
+ `related_adr` pattern: `ADR-NNNN` or `none`.
74
+
75
+ `additionalProperties: false` — typo fields rejected (drift prevention).
76
+
77
+ ---
78
+
79
+ ## CLI Reference
80
+
81
+ ### `dw task new <name> [options]`
82
+
83
+ Scaffold new v3 task from template.
84
+
85
+ ```
86
+ dw task new my-feature --depth standard --title "My feature" --adr ADR-0008
87
+ ```
88
+
89
+ Writes `.dw/tasks/my-feature/task.md` with filled frontmatter + Section skeletons.
90
+
91
+ ### `dw task show [name] [-v]`
92
+
93
+ ANSI terminal snapshot of Section 1 + Section 3.
94
+
95
+ ```
96
+ dw task show # auto-pick most recent v3 task
97
+ dw task show my-feature # specific task
98
+ dw task show -v # include Section 1 body
99
+ ```
100
+
101
+ ### `dw task lint [name] [-l level]`
102
+
103
+ Schema validate + drift marker scan + line caps + appendage name check.
104
+
105
+ ```
106
+ dw task lint # lint all v3 tasks
107
+ dw task lint my-feature # single task
108
+ dw task lint -l warn # downgrade errors to warnings
109
+ DW_NO_TELEMETRY=1 dw task lint # skip telemetry events
110
+ ```
111
+
112
+ Default level: `strict` (errors → exit 1). Override via `dw.config.yml`:
113
+
114
+ ```yaml
115
+ task:
116
+ lint: strict # strict | warn | off
117
+ ```
118
+
119
+ Or legacy flat key:
120
+ ```yaml
121
+ task_lint: strict
122
+ ```
123
+
124
+ Solo preset → `off`. Enterprise → `strict`.
125
+
126
+ ### `dw task migrate [name] [flags]`
127
+
128
+ Migrate v2 `spec.md` + `tracking.md` → v3 `task.md`.
129
+
130
+ ```
131
+ dw task migrate my-task --dry-run # preview without writing
132
+ dw task migrate my-task --diff # diff against existing task.md
133
+ dw task migrate my-task # apply (creates .v2bak backups)
134
+ dw task migrate --all --dry-run # preview all v2 tasks
135
+ dw task migrate --all # apply to all v2 tasks
136
+ dw task migrate my-task --rollback # restore from .v2bak
137
+ dw task migrate my-task --force # overwrite existing v3
138
+ dw task migrate my-task --remove-v2 # delete spec.md/tracking.md after migration (default keeps them)
139
+ ```
140
+
141
+ **Migration mapping:**
142
+
143
+ | v2 source | v3 destination |
144
+ |-----------|----------------|
145
+ | `spec.md` Intent + Why Now | Section 2 → Intent + Why Now |
146
+ | `spec.md` Scope → In Scope | Section 2 → Subtasks (status markers stripped) |
147
+ | `spec.md` Out of Scope | Section 2 → Out of Scope |
148
+ | `spec.md` Success Criteria | Section 2 → Success Criteria |
149
+ | `spec.md` Risks & Mitigations | Section 2 → Risk Register |
150
+ | `spec.md` Dependencies | Section 2 → Dependencies |
151
+ | `tracking.md` Status Snapshot | Section 1 |
152
+ | `tracking.md` Subtask Progress | Section 3 Subtask Tracker |
153
+ | `tracking.md` Changelog | Section 4 Timeline/Changelog |
154
+ | `tracking.md` Handoff Notes | Section 5 |
155
+ | `tracking.md` Friction Journal | Section 5 (Friction subsection) |
156
+ | `tracking.md` Agent Debate Log | Section 7 (if present) |
157
+ | Merged frontmatter | v3 frontmatter (status auto-normalized to enum) |
158
+
159
+ **Status normalization:** v2 freeform status (e.g., "v1.3.0 Verified Ship-Ready (audit passed)") maps to nearest v3 enum value via keyword priority: Blocked > Done > Paused > In Progress > Approved > Draft.
160
+
161
+ **Backups:** `spec.md` → `spec.md.v2bak`, `tracking.md` → `tracking.md.v2bak`. Both gitignored. Use `--rollback` to restore.
162
+
163
+ ### `dw task rotate [name] [-n] [-q]`
164
+
165
+ Auto-rotate Section 4 (Timeline/Changelog) > 400 lines into `timeline-history.md`. Keeps last 8 entries in `task.md`. Idempotent. Invoked automatically by `stop-check` hook.
166
+
167
+ ### `dw task render [name] [-n] [-f svg|png|svg,png] [--mermaid-only]`
168
+
169
+ Render `timeline.svg` sidecar from manifest via `dw-kit-render` sub-package. SVG is bounded composition (status card + Subtask Gantt + status transition strip) ~200-465KB per task. Gitignored by default (opt-in commit cho GitHub inline preview). Falls back to Mermaid Gantt block injection in Section 4 if sub-package absent.
170
+
171
+ ### `dw task view [name] [--no-open]`
172
+
173
+ Render full interactive HTML preview at `.dw/cache/preview/{task}.html` and open in browser. **Primary surface for human dev orchestrator tracking subtasks.** Self-contained (CSS + JS inlined, no CDN deps). Features:
174
+
175
+ - **Sticky snapshot card** (always visible): status badge + key meta + blocker banner + progress stats (✅/🟡/🔴/⬜ counts + percentage bar).
176
+ - **Sidebar navigation** with section anchors + search box (filter sections by keyword).
177
+ - **Sections rendered as proper HTML**: headings, tables, code blocks (Mermaid blocks render as text but visible), bullet/numbered lists, blockquotes.
178
+ - **Collapsible H2 sections** (click heading to fold).
179
+ - **Dark/light theme** via `prefers-color-scheme`.
180
+
181
+ Gitignored output (`.dw/cache/preview/`). Regenerates on each invocation — no caching.
182
+
183
+ ---
184
+
185
+ ## Migration Steps for Existing Projects
186
+
187
+ ### 1. Backup (recommended)
188
+
189
+ ```
190
+ git checkout -b task-migrate-v3
191
+ git status # confirm clean
192
+ ```
193
+
194
+ ### 2. Preview migration
195
+
196
+ ```
197
+ dw task migrate --all --dry-run
198
+ ```
199
+
200
+ Review proposed v3 output. Status normalization, section mapping, and frontmatter merge are shown.
201
+
202
+ ### 3. Apply per-task with diff
203
+
204
+ ```
205
+ dw task migrate task-1 --diff # if already migrated, show diff vs existing
206
+ dw task migrate task-1 # apply
207
+ dw task lint task-1 # verify clean
208
+ ```
209
+
210
+ Repeat for each task. Or batch:
211
+
212
+ ```
213
+ dw task migrate --all
214
+ dw task lint # verify all
215
+ ```
216
+
217
+ ### 4. Refresh ACTIVE.md
218
+
219
+ ```
220
+ dw active
221
+ ```
222
+
223
+ ### 5. Commit
224
+
225
+ ```
226
+ git add .dw/tasks/
227
+ git commit -m "chore(tasks): migrate v2 spec+tracking to v3 timeline (ADR-0008)"
228
+ ```
229
+
230
+ `.v2bak` files are gitignored — they stay locally for rollback if needed.
231
+
232
+ ### 6. Rollback path (if needed)
233
+
234
+ ```
235
+ dw task migrate task-1 --rollback
236
+ ```
237
+
238
+ Restores v2 files from `.v2bak`, deletes v3 `task.md`. ACTIVE.md falls back to reading `tracking.md`.
239
+
240
+ ---
241
+
242
+ ## Breaking Changes
243
+
244
+ ### 1. `dw active` v3 precedence
245
+
246
+ If both `task.md` and `tracking.md` exist in a task folder, **v3 wins**. To force v2 read during migration, delete `task.md` temporarily.
247
+
248
+ ### 2. Lint default strict
249
+
250
+ `dw task lint` exits non-zero on any error (drift markers, schema violations). To run advisory-only:
251
+
252
+ ```yaml
253
+ # .dw/config/dw.config.yml
254
+ task:
255
+ lint: warn # or "off"
256
+ ```
257
+
258
+ ### 3. Section 2 drift-marker enforcement
259
+
260
+ Pasting status markers (`✅ COMPLETED 2026-04-21`, `🟡 IN PROGRESS`, `Status: Done`) anywhere in Section 2 → lint error. Status only in Section 3 (Subtask Tracker). Backtick-quoted examples (e.g., discussing drift in docs) are skipped by lint.
261
+
262
+ ### 4. Generic appendage names → warning
263
+
264
+ Files named `notes.md`, `extra.md`, `wip.md`, etc. in task folders → lint warning. Prefer specific names: `baseline.md`, `experiment-{id}.md`, `debate-r{N}.md`.
265
+
266
+ ---
267
+
268
+ ## SVG Preview (Deferred to v1.6+)
269
+
270
+ Per ADR-0008 Option H, `task.md` references an inline `timeline.svg` sidecar that GitHub markdown viewer renders inline for human casual preview. The full render pipeline (extends ADR-0007 `dw-kit-render` sub-package) lands in v1.6 telemetry-gated.
271
+
272
+ For v1.5: the SVG reference is comment-suppressed in templates (`<!-- ![Timeline](./timeline.svg) -->`) so no broken-image icons appear in GitHub PR view. Mermaid Gantt + timeline blocks in Section 4 provide native GitHub-rendered fallback visualization.
273
+
274
+ When v1.6 ships:
275
+ - `dw task render <name>` produces `timeline.svg` (deterministic XML, ~10-20KB).
276
+ - `stop-check` + `pre-commit` hooks auto-regenerate on session end / commit.
277
+ - Template comment markers around the image ref are removed → inline render activates.
278
+ - Optional `dw task view` opens interactive HTML in browser.
279
+ - Optional `dw task watch` daemon for live preview during pair-with-agent dev.
280
+
281
+ ---
282
+
283
+ ## Telemetry
284
+
285
+ New events (under `event: 'task'`):
286
+
287
+ - `task.show.invoke`
288
+ - `task.new`
289
+ - `task.migrate.run` / `task.migrate.rollback`
290
+ - `task.lint.run` / `task.lint.violation`
291
+ - `task.rotate.run`
292
+
293
+ Inspected via `dw metrics show` (under "Task actions" bucket). Local-only, opt-out via `DW_NO_TELEMETRY=1`.
294
+
295
+ ---
296
+
297
+ ## Skills Updated
298
+
299
+ 7 skills now v3-aware (task.md preferred, v2 + v1 read-compat):
300
+
301
+ - `/dw:task-init` — defaults to `dw task new`; falls back to template fill.
302
+ - `/dw:execute` — reads task.md Sections 1/2/3; updates Section 3 tracker + Section 4 changelog.
303
+ - `/dw:handoff` — writes to Section 5 (Handoff & Friction).
304
+ - `/dw:research` — appends Research Findings subsection to Section 2.
305
+ - `/dw:plan` — fills Section 2 subsections; promotes status Draft → Approved.
306
+ - `/dw:decision` — cross-links ADR to task.md frontmatter + Changelog.
307
+ - `/dw:retroactive` — generates As-Built task.md from code + git history.
308
+
309
+ ---
310
+
311
+ ## Sunset Plan for v2
312
+
313
+ Per ADR-0008 Open Items:
314
+
315
+ - v2 templates at `.dw/core/templates/v2/` remain for legacy read.
316
+ - 60 days post-v1.5 ship: telemetry review `task.format.read` event distribution.
317
+ - If v2 reads < 5% of v3 reads → propose v2 template removal in v1.7.
318
+ - v2 read code path in `active-index.mjs` and skills stays (cheap to maintain, supports archived tasks).
319
+
320
+ v1 (3-file `context + plan + progress`) read path stays indefinitely (small set of legacy tasks).
321
+
322
+ ---
323
+
324
+ ## References
325
+
326
+ - ADR-0008: [.dw/decisions/0008-task-docs-format-one-file-timeline.md](.dw/decisions/0008-task-docs-format-one-file-timeline.md) (full debate, 7 rounds)
327
+ - Bootstrap task: [.dw/tasks/task-docs-v3/task.md](.dw/tasks/task-docs-v3/task.md) (dogfooded v3 format)
328
+ - Template: [.dw/core/templates/v3/task.md](.dw/core/templates/v3/task.md)
329
+ - Schema: [.dw/core/schemas/task-frontmatter.schema.json](.dw/core/schemas/task-frontmatter.schema.json)
330
+ - ADR-0007 (render infrastructure to be reused in v1.6): [.dw/decisions/0007-decoupled-review-render-pipeline.md](.dw/decisions/0007-decoupled-review-render-pipeline.md)
package/README.md CHANGED
@@ -36,6 +36,9 @@ It’s designed for collaboration (Dev / Tech Lead / QA / PM) and keeps work aud
36
36
 
37
37
  ## Release notes
38
38
 
39
+ - **v1.6.0-rc.1 (current)** — **Agent OS Multi-Agent Orchestration** ([ADR-0009](.dw/decisions/0009-agent-os-multi-agent-orchestration.md)): file-based cooperative protocol for Claude Code / Codex / Gemini / human agents to work from same `task.md` without conflict. 6-command CLI `dw agent *` (claim / release / expire / claims / reports / conflicts). Dual ownership model: `subtasks` (semantic) + `write_scope` (filesystem). Lifecycle states + lease (wall+relative) per Round 2. Audit trail via committed `reports/` + `events.jsonl`; claims gitignored ephemeral. Trust = cooperative, post-hoc conflict detection.
40
+ - **v1.5.0 — Task Docs v3** ([ADR-0008](.dw/decisions/0008-task-docs-format-one-file-timeline.md)): single-file `task.md` replaces v2 `spec.md` + `tracking.md` (drift fixed structurally). 8-command CLI `dw task *` (show / new / view / watch / render / lint / migrate / rotate). Lean HTML dashboard for human dev orchestrator (~10KB, scan-in-5-seconds) + bounded SVG sidecar via `dw-kit-render` v0.2. Live preview server with auto-refresh. Migration script with `--dry-run`, `--diff`, `--rollback`. Lint strict-default blocks drift markers. See [`MIGRATION-v1.5.md`](MIGRATION-v1.5.md).
41
+ - **v1.4 (in progress)** — Optional **Review Render Pipeline** ([ADR-0007](.dw/decisions/0007-decoupled-review-render-pipeline.md)): `/dw:review --visual` plus a separate `dw-kit-render` package turn findings into SVG + PNG cards for PR comments / Slack / stakeholders. Pure JS + WASM, universal `npm install`, no system deps. See [`docs/review-renderer.md`](docs/review-renderer.md).
39
42
  - **v1.3.6** (2026-05-14) — Supply-Chain Guard upgraded to 3-pillar architecture: OSV snapshot + curated IoC fixture (version-aware, wired into default scan) + **AI-Native NEW-package heuristic** that catches zero-day-ish risk at the AI-edit boundary. See [`CHANGELOG.md#v136--2026-05-14`](CHANGELOG.md#v136--2026-05-14) and [ADR-0006](.dw/decisions/0006-supply-chain-guard-heuristic.md).
40
43
  - v1.3.5 (2026-05-12) — AI-Native Supply-Chain Guard: `dw security-scan` CLI + OSV.dev auto-sync + Edit-lockfile hook + scoped `.gitignore` for end-user projects. See [ADR-0005](.dw/decisions/0005-supply-chain-guard.md). Public 90-day sunset review committed for 2026-08-12.
41
44
  - v1.3.4 (2026-04-21) — `/dw:plan` Quick Debate (red/blue self-critique), depth-driven activation
@@ -45,6 +48,21 @@ It’s designed for collaboration (Dev / Tech Lead / QA / PM) and keeps work aud
45
48
  - Full changelog: `CHANGELOG.md`
46
49
  - Latest release notes: [GitHub Releases](https://github.com/dv-workflow/dv-workflow/releases)
47
50
 
51
+ ### What's in v1.5.0-rc.1 for your team
52
+
53
+ **Drift fix structurally.** v2 split `spec.md` + `tracking.md` was leaking status markers across both files. v3 puts everything in one `task.md` (Sections 1-7: Snapshot · Intent · Tracker · Changelog · Handoff · Annexes · Debate). Status lives ONLY in Section 3 — enforced by `dw task lint` strict default.
54
+
55
+ - **`dw task new <name>`** — scaffold v3 task from template, frontmatter ajv-validated.
56
+ - **`dw task show [name]`** — ANSI terminal snapshot (~30 lines).
57
+ - **`dw task view [name]`** — lean HTML dashboard in browser. 4 cards: snapshot + progress bar + subtask tracker + recent activity + handoff. ~10KB, self-contained (no CDN), scan-in-5-seconds. Trace `task.md` for full details.
58
+ - **`dw task watch [name]`** — live-preview server. fs.watch + 800ms debounce + browser auto-refresh on save. Pair-with-agent workflow.
59
+ - **`dw task render [name]`** — `timeline.svg` sidecar via `dw-kit-render` (satori+resvg). Bounded composition. Mermaid Gantt fallback if sub-package absent.
60
+ - **`dw task lint [name]`** — schema validate + drift-marker detect + line-cap thresholds. Default `strict` (exit 1 on errors). Configurable via `task.lint: warn|off`.
61
+ - **`dw task migrate <name>`** — v2 → v3 with `--dry-run`, `--diff`, `--rollback`, `--all`. `.v2bak` backups preserved (gitignored).
62
+ - **`dw task rotate [name]`** — auto Section-4 overflow > 400 lines → `timeline-history.md`. Invoked by `stop-check` hook.
63
+ - **3-tier auto-sync**: `stop-check` (session end) · `pre-commit-gate` (commit gate) · `dw task watch` (real-time opt-in).
64
+ - **7 skills v3-aware** (task-init / execute / handoff / research / plan / decision / retroactive) — read v3 first, fall back v2/v1.
65
+
48
66
  ### What's in v1.3.6 for your team
49
67
 
50
68
  Reaction time when a supply-chain incident drops goes from 24-72 hours (wait for OSV index + npm publish cycle) to **~1 hour** (AI edits lockfile → hook fires → heuristic flags BEFORE anyone knows).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dw-kit",
3
- "version": "1.3.6",
3
+ "version": "1.6.0-rc.1",
4
4
  "description": "AI development workflow toolkit — structured, quality-assured, team-ready. From requirements to dashboard.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -49,13 +49,15 @@
49
49
  ".claude/templates/",
50
50
  ".claude/settings.json",
51
51
  "CLAUDE.md",
52
- "MIGRATION-v1.3.md"
52
+ "MIGRATION-v1.3.md",
53
+ "MIGRATION-v1.5.md"
53
54
  ],
54
55
  "engines": {
55
56
  "node": ">=18"
56
57
  },
57
58
  "scripts": {
58
59
  "test": "node src/smoke-test.mjs",
60
+ "test:renderer": "cd packages/dw-kit-render && npm test",
59
61
  "link": "npm link",
60
62
  "test:e2e-local": "bash scripts/e2e-local-check.sh"
61
63
  },
package/src/cli.mjs CHANGED
@@ -93,6 +93,167 @@ export function run(argv) {
93
93
  console.log(chalk.green('✓') + ` Wrote ${target}`);
94
94
  });
95
95
 
96
+ const taskCmd = program
97
+ .command('task')
98
+ .description('v3 task docs operations (ADR-0008): show · new · migrate · lint');
99
+
100
+ taskCmd
101
+ .command('show [task-name]')
102
+ .description('Print ANSI snapshot (status + subtask tracker) of a v3 task')
103
+ .option('-v, --verbose', 'Include Section 1 Snapshot body')
104
+ .action(async (taskName, opts) => {
105
+ const { taskShowCommand } = await import('./commands/task-show.mjs');
106
+ await taskShowCommand(taskName, opts);
107
+ });
108
+
109
+ taskCmd
110
+ .command('new <task-name>')
111
+ .description('Scaffold a new v3 task from template')
112
+ .option('-d, --depth <level>', 'quick | standard | thorough', 'standard')
113
+ .option('-t, --title <title>', 'Human-readable task title')
114
+ .option('-o, --owner <name>', 'Task owner', '')
115
+ .option('-a, --adr <ref>', 'Related ADR (ADR-NNNN or none)', 'none')
116
+ .option('--target <ship>', 'Target ship milestone', 'TBD')
117
+ .action(async (taskName, opts) => {
118
+ const { taskNewCommand } = await import('./commands/task-new.mjs');
119
+ await taskNewCommand(taskName, opts);
120
+ });
121
+
122
+ taskCmd
123
+ .command('migrate [task-name]')
124
+ .description('Migrate v2 spec.md + tracking.md → v3 task.md')
125
+ .option('-n, --dry-run', 'Preview without writing')
126
+ .option('--diff', 'Show diff against existing task.md')
127
+ .option('--all', 'Scan and migrate all v2 tasks')
128
+ .option('--force', 'Overwrite existing task.md')
129
+ .option('--remove-v2', 'Delete spec.md/tracking.md after backup (default keeps them)')
130
+ .option('--rollback', 'Restore v2 files from .v2bak backups (requires task name)')
131
+ .action(async (taskName, opts) => {
132
+ const { taskMigrateCommand } = await import('./commands/task-migrate.mjs');
133
+ await taskMigrateCommand(taskName, opts);
134
+ });
135
+
136
+ taskCmd
137
+ .command('lint [task-name]')
138
+ .description('Lint v3 task.md: schema validate + drift markers + line caps')
139
+ .option('-l, --level <level>', 'strict | warn | off (overrides config)', '')
140
+ .action(async (taskName, opts) => {
141
+ const { lintTaskCommand } = await import('./commands/lint-task.mjs');
142
+ await lintTaskCommand(taskName, opts);
143
+ });
144
+
145
+ taskCmd
146
+ .command('rotate [task-name]')
147
+ .description('Auto-rotate Section 4 (Timeline/Changelog) > 400 lines to timeline-history.md (keeps last 8 entries)')
148
+ .option('-n, --dry-run', 'Preview without writing')
149
+ .option('-q, --quiet', 'Suppress output (hook usage)')
150
+ .action(async (taskName, opts) => {
151
+ const { taskRotateCommand } = await import('./commands/task-rotate.mjs');
152
+ await taskRotateCommand(taskName, opts);
153
+ });
154
+
155
+ taskCmd
156
+ .command('render [task-name]')
157
+ .description('Render timeline.svg sidecar via dw-kit-render sub-package; falls back to Mermaid block in Section 4 if absent')
158
+ .option('-n, --dry-run', 'Print manifest without writing files')
159
+ .option('-f, --format <kind>', 'svg | png | svg,png', 'svg')
160
+ .option('--mermaid-only', 'Skip SVG, only inject Mermaid fallback block')
161
+ .option('--always-mermaid', 'Inject Mermaid block AND SVG (both)')
162
+ .action(async (taskName, opts) => {
163
+ const formats = String(opts.format || 'svg').split(',').map((s) => s.trim()).filter(Boolean);
164
+ const { taskRenderCommand } = await import('./commands/task-render.mjs');
165
+ await taskRenderCommand(taskName, { ...opts, formats });
166
+ });
167
+
168
+ taskCmd
169
+ .command('view [task-name]')
170
+ .description('Render lean HTML dashboard (snapshot + tracker + recent activity + handoff) and open in browser')
171
+ .option('--no-open', 'Generate HTML without opening browser (prints path)')
172
+ .action(async (taskName, opts) => {
173
+ const { taskViewCommand } = await import('./commands/task-view.mjs');
174
+ await taskViewCommand(taskName, opts);
175
+ });
176
+
177
+ taskCmd
178
+ .command('watch [task-name]')
179
+ .description('Watch task.md for changes and live-reload the HTML preview in browser (local server, debounced)')
180
+ .option('-p, --port <port>', 'Local server port (auto-finds next available if busy)', parseInt)
181
+ .action(async (taskName, opts) => {
182
+ const { taskWatchCommand } = await import('./commands/task-watch.mjs');
183
+ await taskWatchCommand(taskName, opts);
184
+ });
185
+
186
+ const agentCmd = program
187
+ .command('agent')
188
+ .description('Agent OS multi-agent orchestration (ADR-0009): claim · release · claims · reports · conflicts');
189
+
190
+ agentCmd
191
+ .command('claim <task-id>')
192
+ .description('Create a cooperative claim for a task (subtasks + write_scope)')
193
+ .option('-s, --subtasks <list>', 'Comma-separated subtask IDs (e.g. ST-1,ST-2)')
194
+ .option('-w, --write <paths>', 'Comma-separated write_scope glob paths')
195
+ .option('-r, --read <paths>', 'Comma-separated read_scope hint paths (informational)')
196
+ .option('-a, --agent <id>', 'Agent identifier (default: env DW_AGENT_ID or auto-generated)')
197
+ .option('-v, --vendor <name>', 'Vendor: claude | codex | gemini | human | other', 'claude')
198
+ .option('--role <role>', 'worker | reader | orchestrator | reviewer', 'worker')
199
+ .option('-l, --lease <duration>', 'Lease duration (e.g. 30m, 1h, 4h, 1d)', '1h')
200
+ .option('--worktree <path>', 'Worktree path if agent uses git worktree (R2-3)')
201
+ .option('-f, --force', 'Override conflict detection (use sparingly)')
202
+ .action(async (taskId, opts) => {
203
+ const { agentClaimCommand } = await import('./commands/agent-claim.mjs');
204
+ await agentClaimCommand(taskId, opts);
205
+ });
206
+
207
+ agentCmd
208
+ .command('release <claim-id>')
209
+ .description('Release a claim (clean exit; transitions status to "released")')
210
+ .option('-r, --reason <text>', 'Optional reason for release')
211
+ .action(async (claimId, opts) => {
212
+ const { agentReleaseCommand } = await import('./commands/agent-claim.mjs');
213
+ await agentReleaseCommand(claimId, opts);
214
+ });
215
+
216
+ agentCmd
217
+ .command('expire <claim-id>')
218
+ .description('Mark a claim as expired or invalidated (orchestrator action)')
219
+ .option('-r, --reason <text>', 'Reason for expiry')
220
+ .option('--invalidate', 'Invalidate instead of expire (orchestrator override)')
221
+ .action(async (claimId, opts) => {
222
+ const { agentExpireCommand } = await import('./commands/agent-claim.mjs');
223
+ await agentExpireCommand(claimId, opts);
224
+ });
225
+
226
+ agentCmd
227
+ .command('claims')
228
+ .description('List claims (default: active only). Filter by task / status / --all to include released')
229
+ .option('-t, --task <id>', 'Filter by task ID')
230
+ .option('-s, --status <status>', 'Filter by status: created | active | released | expired | invalidated')
231
+ .option('--all', 'Include released and invalidated claims')
232
+ .action(async (opts) => {
233
+ const { agentClaimsCommand } = await import('./commands/agent-inspect.mjs');
234
+ await agentClaimsCommand(opts);
235
+ });
236
+
237
+ agentCmd
238
+ .command('reports')
239
+ .description('List agent reports across tasks (read-only audit view)')
240
+ .option('-t, --task <id>', 'Filter by task ID')
241
+ .option('-a, --agent <id>', 'Filter by agent ID')
242
+ .action(async (opts) => {
243
+ const { agentReportsCommand } = await import('./commands/agent-inspect.mjs');
244
+ await agentReportsCommand(opts);
245
+ });
246
+
247
+ agentCmd
248
+ .command('conflicts')
249
+ .description('Detect overlapping active claims (subtask or write_scope). Exits 1 if conflicts found (use --no-strict to suppress).')
250
+ .option('-t, --task <id>', 'Filter by task ID')
251
+ .option('--no-strict', 'Do not exit 1 on conflict (just report)')
252
+ .action(async (opts) => {
253
+ const { agentConflictsCommand } = await import('./commands/agent-inspect.mjs');
254
+ await agentConflictsCommand(opts);
255
+ });
256
+
96
257
  program
97
258
  .command('dashboard')
98
259
  .description('Show team dashboard — active tasks, ADRs, telemetry summary, health')
@@ -131,6 +292,21 @@ export function run(argv) {
131
292
  await securityScanCommand(opts);
132
293
  });
133
294
 
295
+ const reviewCmd = program
296
+ .command('review')
297
+ .description('Review subcommands (ADR-0007)');
298
+
299
+ reviewCmd
300
+ .command('render <manifest>')
301
+ .description('Render a /dw:review --visual manifest into SVG/PNG (requires dw-kit-render) or markdown summary fallback')
302
+ .option('-f, --format <kind>', 'Override output formats: svg | png | both', null)
303
+ .option('-s, --strategy <name>', 'Override strategy: auto | plugin | markdown-only', null)
304
+ .option('-q, --quiet', 'Suppress info logs (still exits non-zero on hard errors)')
305
+ .action(async (manifest, opts) => {
306
+ const { reviewRenderCommand } = await import('./commands/review-render.mjs');
307
+ await reviewRenderCommand(manifest, opts);
308
+ });
309
+
134
310
  program
135
311
  .command('claude-vn-fix')
136
312
  .description('Patch Claude CLI to fix Vietnamese IME (local, with backup/restore)')