@brunosps00/dev-workflow 1.7.1 → 2.1.0

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 (114) hide show
  1. package/.claude-plugin/marketplace.json +1 -0
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +305 -0
  4. package/README.md +7 -5
  5. package/lib/agents.js +6 -1
  6. package/lib/build-plugin.js +4 -1
  7. package/lib/constants.js +4 -2
  8. package/lib/init.js +14 -0
  9. package/lib/install-state.js +8 -4
  10. package/lib/validate.js +21 -0
  11. package/package.json +2 -1
  12. package/scaffold/agents/core/dw-build-fixer.md +0 -1
  13. package/scaffold/agents/core/dw-code-explorer.md +0 -1
  14. package/scaffold/agents/core/dw-code-reviewer.md +0 -1
  15. package/scaffold/agents/core/dw-planner.md +0 -1
  16. package/scaffold/agents/core/dw-test-author.md +0 -1
  17. package/scaffold/agents/csharp/dw-csharp-reviewer.md +0 -1
  18. package/scaffold/agents/csharp/dw-dotnet-build-fixer.md +0 -1
  19. package/scaffold/agents/frontend/dw-qa-runner.md +0 -1
  20. package/scaffold/agents/python/dw-python-build-fixer.md +0 -1
  21. package/scaffold/agents/python/dw-python-reviewer.md +0 -1
  22. package/scaffold/agents/rust/dw-rust-build-fixer.md +0 -1
  23. package/scaffold/agents/rust/dw-rust-reviewer.md +0 -1
  24. package/scaffold/agents/security/dw-security-reviewer.md +0 -1
  25. package/scaffold/agents/security/dw-silent-failure-hunter.md +0 -1
  26. package/scaffold/agents/typescript/dw-typescript-build-fixer.md +0 -1
  27. package/scaffold/agents/typescript/dw-typescript-reviewer.md +0 -1
  28. package/scaffold/config/routing.json +60 -0
  29. package/scaffold/en/commands/dw-brainstorm.md +12 -8
  30. package/scaffold/en/commands/dw-bugfix.md +4 -2
  31. package/scaffold/en/commands/dw-claude-run.md +5 -1
  32. package/scaffold/en/commands/dw-codex-run.md +5 -1
  33. package/scaffold/en/commands/dw-dockerize.md +14 -7
  34. package/scaffold/en/commands/dw-generate-pr.md +13 -0
  35. package/scaffold/en/commands/dw-new-project.md +14 -13
  36. package/scaffold/en/commands/dw-plan.md +2 -2
  37. package/scaffold/en/commands/dw-refactor.md +1 -0
  38. package/scaffold/en/commands/dw-review.md +33 -2
  39. package/scaffold/en/commands/dw-run.md +2 -1
  40. package/scaffold/en/commands/dw-triage.md +220 -0
  41. package/scaffold/en/templates/idea-onepager.md +28 -0
  42. package/scaffold/en/templates/project-onepager.md +6 -5
  43. package/scaffold/en/templates/task-template.md +2 -1
  44. package/scaffold/en/templates/tasks-template.md +11 -8
  45. package/scaffold/en/templates/triage-needs-info-template.md +23 -0
  46. package/scaffold/en/templates/triage-out-of-scope-template.md +36 -0
  47. package/scaffold/en/templates/triage-record-template.md +88 -0
  48. package/scaffold/pt-br/commands/dw-autopilot.md +81 -81
  49. package/scaffold/pt-br/commands/dw-brainstorm.md +12 -9
  50. package/scaffold/pt-br/commands/dw-bugfix.md +4 -2
  51. package/scaffold/pt-br/commands/dw-claude-run.md +23 -19
  52. package/scaffold/pt-br/commands/dw-codex-run.md +22 -18
  53. package/scaffold/pt-br/commands/dw-context-budget.md +10 -10
  54. package/scaffold/pt-br/commands/dw-copilot-run.md +20 -20
  55. package/scaffold/pt-br/commands/dw-dockerize.md +106 -99
  56. package/scaffold/pt-br/commands/dw-find-skills.md +52 -52
  57. package/scaffold/pt-br/commands/dw-generate-pr.md +13 -0
  58. package/scaffold/pt-br/commands/dw-goal.md +41 -41
  59. package/scaffold/pt-br/commands/dw-harness-audit.md +11 -11
  60. package/scaffold/pt-br/commands/dw-intel.md +70 -70
  61. package/scaffold/pt-br/commands/dw-learn.md +24 -24
  62. package/scaffold/pt-br/commands/dw-new-project.md +93 -92
  63. package/scaffold/pt-br/commands/dw-open-design.md +53 -53
  64. package/scaffold/pt-br/commands/dw-opportunities.md +45 -45
  65. package/scaffold/pt-br/commands/dw-pause.md +39 -39
  66. package/scaffold/pt-br/commands/dw-plan.md +3 -3
  67. package/scaffold/pt-br/commands/dw-refactor.md +31 -30
  68. package/scaffold/pt-br/commands/dw-resume.md +22 -22
  69. package/scaffold/pt-br/commands/dw-review.md +33 -2
  70. package/scaffold/pt-br/commands/dw-run.md +2 -1
  71. package/scaffold/pt-br/commands/dw-skill-health.md +10 -10
  72. package/scaffold/pt-br/commands/dw-subtask-complete.md +4 -4
  73. package/scaffold/pt-br/commands/dw-subtask-start.md +4 -4
  74. package/scaffold/pt-br/commands/dw-triage.md +220 -0
  75. package/scaffold/pt-br/templates/bugfix-summary-template.md +20 -20
  76. package/scaffold/pt-br/templates/concerns-template.md +20 -20
  77. package/scaffold/pt-br/templates/idea-onepager.md +28 -0
  78. package/scaffold/pt-br/templates/project-onepager.md +35 -34
  79. package/scaffold/pt-br/templates/state-template.md +13 -13
  80. package/scaffold/pt-br/templates/task-template.md +2 -1
  81. package/scaffold/pt-br/templates/tasks-template.md +11 -8
  82. package/scaffold/pt-br/templates/triage-needs-info-template.md +23 -0
  83. package/scaffold/pt-br/templates/triage-out-of-scope-template.md +36 -0
  84. package/scaffold/pt-br/templates/triage-record-template.md +88 -0
  85. package/scaffold/scripts/hooks/git-guardrails.mjs +41 -24
  86. package/scaffold/skills/docker-compose-recipes/SKILL.md +2 -4
  87. package/scaffold/skills/docker-compose-recipes/references/compose-composition.md +2 -2
  88. package/scaffold/skills/docker-compose-recipes/references/env-conventions.md +16 -9
  89. package/scaffold/skills/docker-compose-recipes/references/healthcheck-patterns.md +0 -1
  90. package/scaffold/skills/docker-compose-recipes/references/prod-vs-dev.md +7 -2
  91. package/scaffold/skills/docker-compose-recipes/services/elasticsearch.yml +3 -3
  92. package/scaffold/skills/docker-compose-recipes/services/meilisearch.yml +2 -2
  93. package/scaffold/skills/docker-compose-recipes/services/minio.yml +8 -4
  94. package/scaffold/skills/docker-compose-recipes/services/mysql.yml +4 -4
  95. package/scaffold/skills/docker-compose-recipes/services/postgres.yml +2 -2
  96. package/scaffold/skills/docker-compose-recipes/services/rabbitmq.yml +3 -3
  97. package/scaffold/skills/docker-compose-recipes/services/typesense.yml +3 -3
  98. package/scaffold/skills/dw-cli-run/SKILL.md +42 -38
  99. package/scaffold/skills/dw-cli-run/references/dispatch-tuning.md +85 -0
  100. package/scaffold/skills/dw-debug-protocol/SKILL.md +2 -0
  101. package/scaffold/skills/dw-debug-protocol/references/six-step-triage.md +60 -1
  102. package/scaffold/skills/dw-execute-phase/SKILL.md +4 -2
  103. package/scaffold/skills/dw-execute-phase/agents/executor.md +4 -2
  104. package/scaffold/skills/dw-execute-phase/agents/plan-checker.md +9 -7
  105. package/scaffold/skills/dw-execute-phase/references/atomic-commits.md +12 -8
  106. package/scaffold/skills/dw-execute-phase/references/plan-verification.md +6 -4
  107. package/scaffold/skills/dw-execute-phase/references/wave-coordination.md +14 -14
  108. package/scaffold/skills/dw-grilling/SKILL.md +17 -7
  109. package/scaffold/skills/dw-grilling/references/decision-tree.md +30 -7
  110. package/scaffold/skills/dw-simplification/references/deep-modules.md +50 -0
  111. package/scaffold/skills/dw-testing-discipline/SKILL.md +3 -1
  112. package/scaffold/skills/dw-testing-discipline/references/tdd-loop.md +83 -0
  113. package/scaffold/skills/docker-compose-recipes/services/mailhog.yml +0 -23
  114. package/scaffold/skills/docker-compose-recipes/services/postgres-pgvector.yml +0 -31
@@ -14,12 +14,71 @@ Six discrete steps. Each has a specific output. Don't move to the next without f
14
14
  - From a log line → find the surrounding context (request ID, user ID, timestamp); reconstruct the scenario.
15
15
  - Write a failing test FIRST when the bug is in pure logic. The test commits the bug to record before you fix it.
16
16
 
17
+ ### Feedback loop contract
18
+
19
+ For a non-trivial bug, or whenever the first attempted fix did not work, do not theorize before you have a feedback loop. A good loop is:
20
+
21
+ - **Single:** one command or one executable artifact, not a hand-managed sequence.
22
+ - **Deterministic:** produces the same result often enough to trust the signal.
23
+ - **Fast:** runs quickly enough that you can use it repeatedly while narrowing the cause.
24
+ - **Agent-runnable:** executable by the agent without hidden credentials, private hardware, or unrecorded manual state.
25
+ - **Red-capable:** proven to fail now, with the failure already observed and saved. "It should fail" is not enough.
26
+
27
+ Small obvious bugs are exempt from the full checklist when the reproduction is already a single clear command or click path and the fix is truly surgical. The exemption ends immediately if the first fix fails or the bug touches multiple layers.
28
+
29
+ ### Loop repertoire
30
+
31
+ Pick the smallest loop that can show the bug:
32
+
33
+ | Loop type | Use when |
34
+ |-----------|----------|
35
+ | Focused test | The bug fits an existing unit, integration, contract, or E2E suite |
36
+ | `curl` / HTTP client | The bug is an API request/response behavior |
37
+ | CLI command | The symptom is triggered by a command-line entry point |
38
+ | Headless browser | The bug depends on browser rendering, routing, storage, or user events |
39
+ | Trace replay | You have a captured request/session/fixture that can be replayed |
40
+ | Dedicated harness | The production entry point is too slow or noisy, but a public seam can be exercised directly |
41
+ | Fuzz or repeat runner | The bug is input-sensitive or low-frequency but locally amplifiable |
42
+ | `git bisect` | A known-good revision exists and the regression window matters |
43
+ | Differential test | A new path should match an old implementation, another service, or a reference output |
44
+
45
+ ### HITL loop template
46
+
47
+ Use this when the loop cannot be run by the agent because it needs credentials, private data, hardware, or a human click. Do not continue in the dark; ask for the missing artifact or access.
48
+
49
+ ```
50
+ ## Human-in-the-loop reproduction needed
51
+
52
+ I cannot run the feedback loop myself because: <credential / hardware / private data / manual action>.
53
+
54
+ Please provide one of:
55
+ - A single command I can run locally or in CI.
56
+ - A sanitized fixture, trace, screenshot sequence, or log bundle.
57
+ - Temporary access or exact manual steps you will run.
58
+
59
+ What I already tried:
60
+ - <attempt 1 + result>
61
+ - <attempt 2 + result>
62
+
63
+ Once provided, I will first confirm the loop is red-capable before proposing the fix.
64
+ ```
65
+
66
+ ### After the loop is red-capable
67
+
68
+ Only after the failing loop is observed:
69
+
70
+ 1. Minimize the case by removing one variable at a time.
71
+ 2. List 3-5 falsifiable hypotheses and rank them before testing any one.
72
+ 3. Instrument one variable at a time, with removable log prefixes such as `[DW-DEBUG:<slug>]`, so cleanup is mechanical.
73
+ 4. Keep the regression test on the right public seam; do not lock the test to internals.
74
+ 5. Remove temporary instrumentation before final verification.
75
+
17
76
  **Common pitfall:** "It happens sometimes." This is not a reproduction. Either:
18
77
  - Find a deterministic trigger (often there's a state precondition you missed), OR
19
78
  - Quantify the rate (8/10 runs) and treat the test as flaky-but-progress.
20
79
  - See `non-reproducible-strategy.md` for state/timing/env-dependent cases.
21
80
 
22
- **Done when:** You have a one-line command (or a series of clicks) that produces the bug ≥80% of the time.
81
+ **Done when:** You have a one-line command, executable script, or short click path for a trivial UI bug that produces the bug ≥80% of the time. For non-trivial bugs, the loop also satisfies the feedback loop contract above, or the HITL blocker is recorded with explicit artifact/access requested from the user.
23
82
 
24
83
  ## Step 2 — Localize
25
84
 
@@ -80,7 +80,7 @@ Detail in `references/atomic-commits.md` (deviation entry format) and `reference
80
80
  Every task ends with exactly one git commit:
81
81
 
82
82
  ```
83
- feat(<scope>): <task title> (RF-XX)
83
+ feat(<scope>): <task title> (#<task-id>)
84
84
 
85
85
  <one-line summary of what this commit delivers>
86
86
 
@@ -89,9 +89,11 @@ feat(<scope>): <task title> (RF-XX)
89
89
  - Tests added/updated: <list>
90
90
  - Deviations: <link to deviations.md entry, if any>
91
91
 
92
- Closes RF-XX (partial — see tasks.md).
92
+ Closes <REQ-ID> (partial — see tasks.md).
93
93
  ```
94
94
 
95
+ `<REQ-ID>` is copied verbatim from `tasks.md` — `FR-N.M` in English projects, `RF-N.M` in Portuguese ones. This skill is shared by both; never hardcode a prefix.
96
+
95
97
  The commit message format is consistent across waves so `/dw-generate-pr` can build a clean PR body. See `references/atomic-commits.md`.
96
98
 
97
99
  ## De-Sloppify Pass (optional cleanup task)
@@ -88,7 +88,7 @@ For each wave:
88
88
  Format (per `references/atomic-commits.md`):
89
89
 
90
90
  ```
91
- <type>(<scope>): <task title> (RF-XX)
91
+ <type>(<scope>): <task title> (#<task-id>)
92
92
 
93
93
  <one-line summary>
94
94
 
@@ -97,9 +97,11 @@ Format (per `references/atomic-commits.md`):
97
97
  - Tests added/updated: <list>
98
98
  - Deviations: <link or "none">
99
99
 
100
- Closes RF-XX (partial — full close on tasks.md completion).
100
+ Closes <REQ-ID> (partial — full close on tasks.md completion).
101
101
  ```
102
102
 
103
+ `<REQ-ID>` is copied verbatim from `tasks.md` (`FR-N.M` in English projects, `RF-N.M` in Portuguese ones) — never assume a prefix.
104
+
103
105
  Type from Conventional Commits (`feat`, `fix`, `refactor`, `test`, `docs`, `chore`). Scope from task domain. Run `git add -A && git commit` once.
104
106
 
105
107
  ### Step 5: Deviation handling (when implementation diverges from plan)
@@ -50,7 +50,7 @@ Then verify each level against the actual plan files.
50
50
 
51
51
  - `prd_path` (from spawn prompt): `.dw/spec/prd-<slug>/`
52
52
  - Reads:
53
- - `<prd_path>/prd.md` — the goal, requirements (RF-XX), acceptance criteria
53
+ - `<prd_path>/prd.md` — the goal, requirements (`<REQ-ID>`, see Dimension 1), acceptance criteria
54
54
  - `<prd_path>/techspec.md` — architecture decisions
55
55
  - `<prd_path>/tasks.md` — the plan to verify
56
56
  - `<prd_path>/<NN>_task.md` — per-task detail
@@ -62,15 +62,17 @@ Then verify each level against the actual plan files.
62
62
 
63
63
  ### Dimension 1: Requirement Coverage
64
64
 
65
- **Question:** Does every PRD requirement (RF-XX) have at least one task addressing it?
65
+ <critical>Requirement IDs are language-dependent. English projects number them `FR-N.M`; Portuguese projects `RF-N.M`. This skill is shared by both — NEVER hardcode a prefix. Read the IDs verbatim from `prd.md` and match those exact strings in `tasks.md`. `<REQ-ID>` below stands for whichever form the project uses.</critical>
66
+
67
+ **Question:** Does every PRD requirement have at least one task addressing it?
66
68
 
67
69
  **Process:**
68
- 1. Extract every numbered requirement from `prd.md`
69
- 2. For each RF-XX, search `tasks.md` for tasks tagged with that RF
70
+ 1. Extract every numbered requirement ID from `prd.md` verbatim (`FR-1.1`, `RF-1.1`, …)
71
+ 2. For each `<REQ-ID>`, search `tasks.md` for tasks tagged with that exact ID
70
72
  3. List uncovered requirements
71
73
 
72
- **Pass:** every RF has at least one task.
73
- **Revise:** ≥1 RF has no task; the planner missed it.
74
+ **Pass:** every requirement has at least one task.
75
+ **Revise:** ≥1 requirement has no task; the planner missed it.
74
76
  **Block:** the PRD has no requirements at all (plan can't verify).
75
77
 
76
78
  ### Dimension 2: Task Completeness
@@ -174,7 +176,7 @@ After running all 6 dimensions:
174
176
 
175
177
  ### REVISE — Dimension 1: Requirement Coverage
176
178
 
177
- - **RF-04** ("user can reset password via email link") has no task. Suggested: add task between 05 and 06.
179
+ - **FR-4.1** ("user can reset password via email link") has no task. Suggested: add task between 05 and 06.
178
180
 
179
181
  ### REVISE — Dimension 2: Task Completeness
180
182
 
@@ -7,7 +7,7 @@ Every task in a phase commits exactly once. This drives traceability (a task's d
7
7
  Strict format. No deviations.
8
8
 
9
9
  ```
10
- <type>(<scope>): <task title> (RF-XX)
10
+ <type>(<scope>): <task title> (#<task-id>)
11
11
 
12
12
  <one-line summary>
13
13
 
@@ -16,9 +16,11 @@ Strict format. No deviations.
16
16
  - Tests added/updated: <comma-separated list, or "none">
17
17
  - Deviations: <link to deviations.md entry, or "none">
18
18
 
19
- Closes RF-XX (partial — full close on tasks.md completion).
19
+ Closes <REQ-ID> (partial — full close on tasks.md completion).
20
20
  ```
21
21
 
22
+ <critical>`<REQ-ID>` is the requirement ID exactly as `prd.md` and `tasks.md` write it. English projects use `FR-N.M`; Portuguese projects use `RF-N.M`. This skill is shared by both — copy the ID verbatim, never assume a prefix.</critical>
23
+
22
24
  ### Field rules
23
25
 
24
26
  **`<type>`** — Conventional Commits:
@@ -36,7 +38,7 @@ Closes RF-XX (partial — full close on tasks.md completion).
36
38
 
37
39
  **`<task title>`** — copy from `tasks.md` task line. Imperative, concise. "Add login endpoint", not "Added login endpoint" or "Adding login endpoint".
38
40
 
39
- **`(RF-XX)`** — the requirement this task closes. If the task contributes to multiple, list the primary; mention the others in the body.
41
+ **`(#<task-id>)`** — the task ID from `tasks.md` (`#1.0`, `#2.3`). This is what makes the commit findable from the task index — `/dw-run` writes the resulting SHA back into the `tasks.md` Commit column.
40
42
 
41
43
  **`<one-line summary>`** — one sentence answering "what does this commit deliver?". Different from the title (which is the task title); this is the OUTCOME.
42
44
 
@@ -44,12 +46,14 @@ Closes RF-XX (partial — full close on tasks.md completion).
44
46
 
45
47
  **Deviations link** — `.dw/spec/prd-<slug>/deviations.md#deviation-03-1` if the task triggered a Rule 1 or 2 deviation.
46
48
 
47
- **Closes line** — `Closes RF-XX (partial — full close on tasks.md completion)` because one task usually doesn't fully close a requirement; the whole phase does. Final task in the phase changes "(partial — ...)" to "(full)".
49
+ **Closes line** — `Closes <REQ-ID> (partial — full close on tasks.md completion)` because one task usually doesn't fully close a requirement; the whole phase does. Final task in the phase changes "(partial — ...)" to "(full)". If the task closes more than one requirement, list them comma-separated.
48
50
 
49
51
  ## Examples
50
52
 
53
+ Both examples come from an English project (`FR-`); a Portuguese project writes `RF-` in the same slots.
54
+
51
55
  ```
52
- feat(auth): wire JWT middleware to all /api/* routes (RF-04)
56
+ feat(auth): wire JWT middleware to all /api/* routes (#4.0)
53
57
 
54
58
  Authenticated routes now reject requests without valid Bearer tokens.
55
59
 
@@ -58,11 +62,11 @@ Authenticated routes now reject requests without valid Bearer tokens.
58
62
  - Tests added/updated: src/middleware/auth.test.ts (12 cases — happy path, expired, malformed, missing)
59
63
  - Deviations: none
60
64
 
61
- Closes RF-04 (partial — full close on tasks.md completion).
65
+ Closes FR-4.1 (partial — full close on tasks.md completion).
62
66
  ```
63
67
 
64
68
  ```
65
- test(orders): add integration tests for order creation flow (RF-07)
69
+ test(orders): add integration tests for order creation flow (#7.0)
66
70
 
67
71
  Covers happy path, payment failure, inventory mismatch.
68
72
 
@@ -71,7 +75,7 @@ Covers happy path, payment failure, inventory mismatch.
71
75
  - Tests added/updated: tests/integration/orders.test.ts (8 cases)
72
76
  - Deviations: .dw/spec/prd-checkout-v2/deviations.md#deviation-08-1
73
77
 
74
- Closes RF-07 (partial — full close on tasks.md completion).
78
+ Closes FR-7.2 (partial — full close on tasks.md completion).
75
79
  ```
76
80
 
77
81
  ## Verification before commit
@@ -10,12 +10,14 @@ Mid-execution discovery of plan flaws is expensive: context burned, partial comm
10
10
 
11
11
  ### 1. Requirement Coverage
12
12
 
13
- **Goal:** every PRD requirement (RF-XX) has at least one task addressing it.
13
+ **Goal:** every PRD requirement (`<REQ-ID>`) has at least one task addressing it.
14
+
15
+ <critical>`<REQ-ID>` is language-dependent: `FR-N.M` in English projects, `RF-N.M` in Portuguese ones. This skill is shared by both — extract the IDs verbatim from `prd.md` and match those exact strings downstream; never hardcode a prefix.</critical>
14
16
 
15
17
  **Steps:**
16
- 1. Extract numbered requirements from `prd.md`. Pattern: `### RF-NN` or `**RF-NN:**` or numbered list under "Functional Requirements".
17
- 2. Build `Set<RF>` of expected requirements.
18
- 3. Scan `tasks.md` and `<NN>_task.md` files for `Closes RF-XX` / `RF: RF-XX` / `Requirement: RF-XX` markers.
18
+ 1. Extract numbered requirements from `prd.md`. Pattern: `### <REQ-ID>` or `**<REQ-ID>:**` or numbered list under "Functional Requirements" / "Requisitos Funcionais".
19
+ 2. Build `Set<REQ-ID>` of expected requirements.
20
+ 3. Scan `tasks.md` and `<NN>_task.md` files for `Closes <REQ-ID>` / the `FRs`/`RFs` table column / `Requirement: <REQ-ID>` markers.
19
21
  4. Compute `uncovered = expected - addressed`.
20
22
 
21
23
  **Pass:** `uncovered` is empty.
@@ -4,7 +4,7 @@ Tasks within a phase have dependencies. Some can run in parallel; others must wa
4
4
 
5
5
  ## Wave computation
6
6
 
7
- Input: `tasks.md` with each task carrying a `Depends on:` field (none, or comma-separated task numbers).
7
+ Input: `tasks.md` with each task carrying a `Depends on:` field (none, or comma-separated task IDs).
8
8
 
9
9
  Algorithm: topological sort.
10
10
 
@@ -13,25 +13,25 @@ Algorithm: topological sort.
13
13
  3. Wave assignment:
14
14
  - Wave 1 = tasks with zero dependencies
15
15
  - Wave N = tasks whose all dependencies are in waves 1..N-1
16
- 4. Output: ordered list of waves, each wave a list of task numbers.
16
+ 4. Output: ordered list of waves, each wave a list of task IDs.
17
17
 
18
18
  ## Example
19
19
 
20
20
  ```
21
21
  tasks.md:
22
- - 01 Create user schema Depends on: none
23
- - 02 Create user model Depends on: 01
24
- - 03 Create order schema Depends on: none
25
- - 04 Wire auth middleware Depends on: 02
26
- - 05 Add login endpoint Depends on: 04
27
- - 06 Add order endpoint Depends on: 02, 03
28
- - 07 Wire validation rules Depends on: 04, 06
22
+ - 1.0 Create user schema Depends on: none
23
+ - 2.0 Create user model Depends on: 1.0
24
+ - 3.0 Create order schema Depends on: none
25
+ - 4.0 Wire auth middleware Depends on: 2.0
26
+ - 5.0 Add login endpoint Depends on: 4.0
27
+ - 6.0 Add order endpoint Depends on: 2.0, 3.0
28
+ - 7.0 Wire validation rules Depends on: 4.0, 6.0
29
29
 
30
30
  Computed waves:
31
- Wave 1: [01, 03] (no deps; can run in parallel)
32
- Wave 2: [02] (depends on 01)
33
- Wave 3: [04, 06] (depend on wave 2)
34
- Wave 4: [05, 07] (depend on wave 3)
31
+ Wave 1: [1.0, 3.0] (no deps; can run in parallel)
32
+ Wave 2: [2.0] (depends on 1.0)
33
+ Wave 3: [4.0, 6.0] (depend on wave 2)
34
+ Wave 4: [5.0, 7.0] (depend on wave 3)
35
35
  ```
36
36
 
37
37
  ## Parallel execution within a wave
@@ -73,7 +73,7 @@ Each wave is a checkpoint:
73
73
 
74
74
  ## Order within a wave
75
75
 
76
- Within a wave, order doesn't matter logically (no deps between same-wave tasks). But for **commit history readability**, the executor should commit in numeric order of task number (01 commit before 02 even if both are wave 1). The parallel subagent results may arrive out of order; the executor collects and commits sequentially.
76
+ Within a wave, order doesn't matter logically (no deps between same-wave tasks). But for **commit history readability**, the executor should commit in numeric order of task ID (1.0 commit before 2.0 even if both are wave 1). The parallel subagent results may arrive out of order; the executor collects and commits sequentially.
77
77
 
78
78
  This means: subagents return their changes (files written, but NOT committed). The executor commits them in numeric order.
79
79
 
@@ -36,17 +36,23 @@ vocabulary and the calling command for the idea one-pager / PRD.
36
36
  until every dependency branch is resolved, glossary/code contradictions are closed, no blocking decision
37
37
  remains, AND the user explicitly confirms. Otherwise persist a draft/paused state and stop.
38
38
 
39
- ## Before the first question — build the decision tree
39
+ ## Before the first question — resume or build the decision tree
40
40
 
41
- Inspect project facts and open questions, then order them by dependency (never ask a downstream decision before
42
- its blocker is resolved):
41
+ Inspect the active one-pager/PRD first. If it already has a `### Decision Map`, read it before reconstructing:
42
+ load its nodes, `Depends on:` fields, states, explicit **Frontier**, and `#### Decision Fog`; do not re-ask a
43
+ node already marked `resolved`. Continue from the Frontier when it exists. Only rebuild from scratch when no
44
+ durable map exists or the map is malformed.
45
+
46
+ When no resumable map exists, inspect project facts and open questions, then order them by dependency (never ask
47
+ a downstream decision before its blocker is resolved):
43
48
 
44
49
  1. Read what already exists: `.dw/rules/`, `.dw/intel/` (via `/dw-intel` when present), `.dw/constitution.md`,
45
50
  `.dw/domain/**` (glossary / context-map), current PRDs/TechSpecs, recent git activity.
46
51
  2. Extract the open decisions the plan/PRD implies. Fold in vocabulary tension surfaced by `dw-domain-modeling`
47
52
  (fuzzy or overloaded terms are decisions too).
48
- 3. Order them into a **dependency tree**: a node that constrains others comes first. Record it so a later turn
49
- (or `/dw-plan`) can resume. Full method + the shared-understanding gate: `references/decision-tree.md`.
53
+ 3. Order them into a **dependency tree**: a node that constrains others comes first. Record it in `### Decision
54
+ Map` so a later turn (or `/dw-plan`) can resume. Full method + the shared-understanding gate:
55
+ `references/decision-tree.md`.
50
56
 
51
57
  ## The loop
52
58
 
@@ -59,6 +65,9 @@ For each unresolved node, in dependency order:
59
65
  `dw-domain-modeling`; the caller persists to the one-pager/PRD). ADR creation still needs a separate explicit
60
66
  approval — never auto-create one.
61
67
  5. **Re-walk** the tree: the answer may unlock or reshape downstream nodes.
68
+ 6. **Persist the map** after each resolved answer when writes are authorized: update node state, `Depends on:`,
69
+ explicit **Frontier**, and `Decision Fog` without duplicating the decision outcome already recorded in
70
+ **Resolved Decisions**.
62
71
 
63
72
  When the tree is exhausted and contradictions are closed, present the shared-understanding summary and ask the
64
73
  user to confirm. Only then is the session `aligned`.
@@ -90,8 +99,9 @@ what you *would* persist.
90
99
  - **Scope:** the artifact under grill (one-pager / PRD / TechSpec), the decision tree size, and how many nodes
91
100
  are resolved vs open.
92
101
  - **Evidence:** the facts discovered from repo/rules/intel/docs (with sources) that were used instead of asking.
93
- - **Artifacts:** decision tree, resolved decisions with the recommended answer and the user's choice, and any
94
- authorized `.dw/domain/**` / one-pager / PRD updates (with paths).
102
+ - **Artifacts:** Decision Map (nodes, `Depends on:`, state, Frontier, Decision Fog), resolved decisions with the
103
+ recommended answer and the user's choice, and any authorized `.dw/domain/**` / one-pager / PRD updates (with
104
+ paths).
95
105
  - **Decisions:** each resolved decision, the alternative rejected, and why.
96
106
  - **Risks:** open decisions, unclosed glossary/code contradictions, and any decision made without full evidence.
97
107
  - **Next Step:** either "user to confirm shared understanding" (with the remaining nodes) or "aligned — hand off
@@ -3,7 +3,13 @@
3
3
  Grill is not a flat questionnaire. It is a walk down a **dependency-ordered decision tree**, so an upstream
4
4
  decision is never asked after the downstream decision it constrains.
5
5
 
6
- ## Build the tree (before the first question)
6
+ ## Resume or build the tree (before the first question)
7
+
8
+ Before rebuilding a tree, read the active one-pager/PRD for an existing `### Decision Map`. If present and
9
+ well-formed, resume from it instead of deriving the same tree again. Load the node IDs, `Depends on:` fields,
10
+ states, explicit **Frontier**, and `#### Decision Fog`; do not re-ask a node already marked `resolved`.
11
+
12
+ If there is no durable map yet:
7
13
 
8
14
  1. **Gather open decisions.** Read the plan/PRD and the project's durable facts (`.dw/rules/`, `.dw/intel/` via
9
15
  `/dw-intel`, `.dw/constitution.md`, `.dw/domain/**`, current PRDs/TechSpecs, recent git activity). List every
@@ -16,14 +22,31 @@ decision is never asked after the downstream decision it constrains.
16
22
  4. **Topologically order.** Ask parents before children. Independent branches can be walked in any order, but
17
23
  within a branch always resolve the blocker first.
18
24
 
19
- Record the tree (nodes, dependencies, resolved/open) so the session — or a later `/dw-plan` handoff — can resume
20
- exactly where it stopped.
25
+ Record the tree in the active artifact's `### Decision Map` so this session, a later Grill session, or a later
26
+ `/dw-plan` handoff can resume exactly where it stopped.
27
+
28
+ ## Durable Decision Map contract
29
+
30
+ - Keep one row per decision node with a stable ID (`D1`, `D2`, ...), a short node label, `State`, `Depends on:`,
31
+ `Frontier?`, and structural notes.
32
+ - Use the same dependency field shape as task plans: `Depends on: none` or `Depends on: D1, D2`. This keeps
33
+ dependency parsing consistent across durable artifacts.
34
+ - Allowed `State` values are `resolved`, `open-ready`, and `open-blocked`.
35
+ - Maintain an explicit `**Frontier:**` line listing all `open-ready` node IDs, or `none`. The next session reads
36
+ this line directly; it must not need to manually recompute the graph to know what can be asked next.
37
+ - Keep `#### Decision Fog` for known unresolved areas that are not yet crisp enough to phrase as a decision
38
+ node. Each item is one line and graduates into a real node once it becomes decidable.
39
+
40
+ Do not duplicate the content of `### Resolved Decisions` in the map. The map records structure and resume state;
41
+ `Resolved Decisions` records the recommended answer, user's choice, rejected alternative, and evidence.
21
42
 
22
43
  ## Walk the tree
23
44
 
24
45
  Resolve nodes in dependency order using the per-turn contract (`interview-loop.md`). After each answer, **re-walk
25
- the tree**: a resolved parent may add, remove, or reshape child nodes. New tension discovered mid-walk becomes a
26
- new node, inserted in dependency order — not asked immediately if a blocker is still open.
46
+ the tree** and persist the updated map when writes are authorized: a resolved parent may add, remove, or reshape
47
+ child nodes. New tension discovered mid-walk becomes a new node, inserted in dependency order — not asked
48
+ immediately if a blocker is still open. If a newly discovered uncertainty is real but still too vague to phrase
49
+ as a decision, add it to `Decision Fog` instead of pretending the tree is complete.
27
50
 
28
51
  ## The shared-understanding gate
29
52
 
@@ -44,8 +67,8 @@ terms, and the remaining (non-blocking) decisions with their owners.
44
67
  If the gate is not met — blocking decision open, contradiction unclosed, or the user not yet confirming — **do
45
68
  not** declare alignment. Persist a draft/paused state:
46
69
 
47
- - Keep the one-pager (or PRD) at its draft/paused status with the decision tree, resolved decisions, and the
48
- remaining open nodes recorded (the caller performs the write, only if authorized).
70
+ - Keep the one-pager (or PRD) at its draft/paused status with `### Decision Map`, resolved decisions, the
71
+ explicit Frontier, and remaining open nodes recorded (the caller performs the write, only if authorized).
49
72
  - Return `FINDINGS` with the open nodes as the Next Step, so the next turn resumes the same tree.
50
73
 
51
74
  ## Handoff to /dw-plan
@@ -91,6 +91,56 @@ The combined verdict:
91
91
 
92
92
  A flat "this is too long, extract method" recommendation is shallow analysis. Combining Fowler + deep-modules surfaces when the smell is actually a feature.
93
93
 
94
+ ## Dependency categories decide seam tests
95
+
96
+ When a finding is about a seam, classify the dependency that seam isolates before choosing the test strategy. The category drives the test plan; do not reflexively mock everything or run every dependency for every test.
97
+
98
+ This follows `dw-testing-discipline`: tests should sit at the lowest layer that can expose the defect, mocks isolate boundaries, and real systems validate before merge. If this section appears to conflict with `dw-testing-discipline`, prefer `dw-testing-discipline`.
99
+
100
+ | Category | What it means | Test strategy |
101
+ |----------|---------------|---------------|
102
+ | **In-process** | Same process and memory space: pure functions, formatters, policy objects, parser modules, local caches. | Prefer unit or characterization tests with real collaborators. Mocking here usually tests the mock or hides a shallow interface. |
103
+ | **Local-substitutable** | Real dependency can run locally with equivalent behavior: database, queue, object store emulator, search index, containerized service. | Use integration tests against the real local substitute for the merge gate. Unit tests may fake it for branch coverage, but at least one path must prove the real wiring. |
104
+ | **Remote owned** | A service the team/company owns across the network. | Use adapter unit tests for failure mapping, consumer/producer contract tests for the API shape, and staging/sandbox smoke checks for real network behavior before merge. |
105
+ | **True external** | Third-party service the team does not control: payments, email, identity provider, vendor API. | Keep a narrow adapter seam. Unit-test mapping and error policy with fixtures/fakes; validate contracts against provider sandbox or recorded contract fixtures where available. Do not make routine CI depend on a third-party public site being reachable. |
106
+
107
+ The output for a seam-related finding adds:
108
+
109
+ ```markdown
110
+ **Dependency category:** <in-process | local-substitutable | remote owned | true external>
111
+ **Seam test strategy:** <lowest layer that catches the defect + real-system gate, if applicable>
112
+ ```
113
+
114
+ ## Design It Twice for interface findings
115
+
116
+ When the surviving finding is **shallow interface**, **interface leak**, or **seam in the wrong place**, do not accept the first interface that works. Generate at least three radically different public-interface proposals for the same module before recommending one.
117
+
118
+ Each proposal must have a distinct constraint, for example:
119
+
120
+ - **Caller-minimal:** expose the fewest concepts to the caller, even if implementation grows.
121
+ - **Domain-language-first:** public methods use product/domain vocabulary and hide vendor or storage terms.
122
+ - **Test-boundary-first:** interface places the seam at the dependency category boundary and makes the real-system gate practical.
123
+ - **Migration-first:** supports incremental caller migration without a broad flag day.
124
+
125
+ Compare each proposal on:
126
+
127
+ - **Depth:** how much implementation complexity it hides per public concept exposed.
128
+ - **Locality:** whether inputs and outputs are explicit, with no hidden globals or ambient state.
129
+ - **Seam placement:** whether the boundary lands at the dependency category boundary, not halfway through a workflow.
130
+ - **Test cost:** which tests prove behavior without relying on mocks that can drift.
131
+
132
+ Use a local loop inside this analysis, not `dw-council`, by default. `dw-council` is for high-stakes product or architecture trade-offs with multiple stakeholder priorities; an interface-depth comparison is usually a scoped refactor design exercise. Escalate to `dw-council` only when the interface choice also changes product behavior, ownership boundaries, security posture, or a hard-to-reverse architecture decision.
133
+
134
+ The output for an interface finding adds:
135
+
136
+ ```markdown
137
+ **Interface alternatives considered:**
138
+ 1. <proposal + constraint + depth/locality/seam/test notes>
139
+ 2. <proposal + constraint + depth/locality/seam/test notes>
140
+ 3. <proposal + constraint + depth/locality/seam/test notes>
141
+ **Recommended interface:** <choice and why>
142
+ ```
143
+
94
144
  ## Output for refactor-audit findings
95
145
 
96
146
  When the audit flags a module as a shallow-wrapper or god-module candidate, the finding entry adds a `Deep-modules: <verdict>` line:
@@ -34,6 +34,7 @@ Each rule has nuance read `references/core-rules.md` for the long version with e
34
34
  - Reviewing a PR diff under test paths.
35
35
  - Debugging a flaky test (or considering retry-as-fix — read `references/flaky-discipline.md` first).
36
36
  - Generating tests via an AI agent → invokes `references/agent-guardrails.md` automatically.
37
+ - Explicit test-first requests ("TDD", "test first", "red-green-refactor") → use `references/tdd-loop.md` as an on-demand operating mode, not the default workflow.
37
38
  - Browser-based E2E with Playwright → recipes in `references/playwright-recipes.md`.
38
39
  - Verifying browser-side trust boundaries (auth, CSRF, headers) → `references/security-boundary.md`.
39
40
  - Picking which test workflow applies (UI / network / perf) → `references/three-workflow-patterns.md`.
@@ -61,6 +62,7 @@ Do not assume `npm test`. The package manager and the test runner are different
61
62
  |------------|------|
62
63
  | Placing a new test (which layer?) | `references/core-rules.md` (Rule 2 deep-dive) |
63
64
  | Writing new tests | `references/patterns.md` |
65
+ | Explicit test-first / TDD loop | `references/tdd-loop.md` |
64
66
  | Reviewing tests / spotting smells | `references/anti-patterns.md` |
65
67
  | Agent-generated tests | `references/agent-guardrails.md` + `references/anti-patterns.md` |
66
68
  | Flaky tests | `references/flaky-discipline.md` |
@@ -180,7 +182,7 @@ Any of these in a PR is enough to REJECT a verdict:
180
182
  ## Integration with dev-workflow commands
181
183
 
182
184
  - `/dw-plan tasks` applies the placement doctrine — each test-adding task names the invariant.
183
- - `/dw-run` runs the 6 agent guardrails when generating tests during implementation.
185
+ - `/dw-run` runs the 6 agent guardrails when generating tests during implementation. When the task or user explicitly requests test-first work, `/dw-run` switches to `references/tdd-loop.md` for that task only.
184
186
  - `/dw-review --code-only` runs the anti-pattern checks on diff hunks under test paths.
185
187
  - `/dw-qa --fix` applies the flaky-discipline taxonomy in retest cycles.
186
188
  - `/dw-qa` (UI mode) references `playwright-recipes.md` for concrete recipes.
@@ -0,0 +1,83 @@
1
+ # Test-first red-green loop
2
+
3
+ Use this procedure only when the user or task explicitly asks for test-first work: "TDD", "test first", "red-green-refactor", or equivalent wording. It operates inside the six core rules from `dw-testing-discipline`; it does not replace or weaken them.
4
+
5
+ ## 0. Confirm the public seam
6
+
7
+ Before writing the first test, identify the public boundary that should own the behavior:
8
+
9
+ - API route, CLI command, exported function, component behavior, contract test, browser flow, or other public seam.
10
+ - The invariant the user cares about, in one sentence.
11
+ - The lowest layer that can detect the defect or missing behavior.
12
+
13
+ Ask the user to confirm the seam before writing any code:
14
+
15
+ ```
16
+ I plan to test this at `<public seam>` because it is the lowest public boundary that proves `<invariant>`.
17
+ Confirm this seam, or point me at the boundary you want covered.
18
+ ```
19
+
20
+ If the user rejects the seam, revise it and ask again. Do not test private helpers or internals just to make the first test easier.
21
+
22
+ ## 1. Write one red test
23
+
24
+ Write exactly one test for the next vertical slice of behavior.
25
+
26
+ - The test must assert observable behavior through the confirmed public seam.
27
+ - The test must not be tautological: removing or breaking the production behavior should make it fail.
28
+ - The test must not couple to implementation details, private methods, internal call order, or mock shape.
29
+ - Mocks are allowed only at system boundaries you do not control.
30
+
31
+ Do not write a batch of future tests before the first implementation. A vertical slice is one failing test, one minimal implementation, one green run.
32
+
33
+ ## 2. Run and observe red
34
+
35
+ Run the narrowest test command that exercises the new test and capture the actual failure.
36
+
37
+ The red state is valid only when the observed failure is the expected failure:
38
+
39
+ - The test fails because the behavior is missing or wrong.
40
+ - The test does not fail because of syntax, import, fixture, selector, clock, network, or mock setup problems.
41
+ - The failure message points at the invariant under test.
42
+
43
+ If the failure is not the expected red, fix the test setup or seam choice before touching production code.
44
+
45
+ ## 3. Implement the minimum green
46
+
47
+ Change production code only as much as needed to satisfy the one failing test while preserving existing behavior.
48
+
49
+ - Prefer the existing codebase patterns.
50
+ - Do not add test-only branches, flags, exports, or helper methods to production.
51
+ - Do not broaden the solution for future slices that do not yet have a red test.
52
+
53
+ ## 4. Run and observe green
54
+
55
+ Run the same narrow command first. If it passes, run the relevant broader project test command before moving to the next slice.
56
+
57
+ Record the command and outcome. A presumed green is not enough.
58
+
59
+ ## 5. Continue vertically
60
+
61
+ Only after the current slice is green:
62
+
63
+ 1. Choose the next behavior slice.
64
+ 2. Write one new red test.
65
+ 3. Run and observe red.
66
+ 4. Implement the minimum green.
67
+ 5. Run and observe green.
68
+
69
+ Stop when the requested behavior is covered at the public seam and the relevant project gate is green.
70
+
71
+ ## Refactor happens after the loop
72
+
73
+ Refactoring is not part of the red-green cycle. After the behavior slices are green, run a separate review pass. If simplification is warranted, delegate that pass to `dw-simplification` and keep the tests green throughout.
74
+
75
+ ## Hard stops
76
+
77
+ Stop and ask for clarification when:
78
+
79
+ - No public seam is identifiable.
80
+ - The user will not confirm the seam.
81
+ - The only test you can write is tautological or coupled to internals.
82
+ - The required mock would replace behavior owned by this codebase.
83
+ - The next slice is unclear enough that the invariant cannot be stated in one sentence.
@@ -1,23 +0,0 @@
1
- # MailHog — DEV-ONLY email capture (NEVER sends real mail)
2
- # This is the dev-workflow DEFAULT for email-in-dev so the project cannot accidentally email real users.
3
- # Env vars: MAILHOG_SMTP_PORT (default 1025), MAILHOG_UI_PORT (default 8025)
4
- # Application-side SMTP config:
5
- # SMTP_HOST=mailhog ; SMTP_PORT=1025 ; SMTP_USER= ; SMTP_PASSWORD= ; SMTP_SECURE=false
6
-
7
- mailhog:
8
- image: mailhog/mailhog:latest
9
- restart: unless-stopped
10
- ports:
11
- - "${MAILHOG_SMTP_PORT:-1025}:1025"
12
- - "${MAILHOG_UI_PORT:-8025}:8025"
13
- healthcheck:
14
- test: ["CMD", "wget", "--quiet", "--spider", "http://localhost:8025"]
15
- interval: 10s
16
- timeout: 3s
17
- retries: 5
18
- start_period: 5s
19
-
20
- # Prod notes:
21
- # - MailHog must NEVER ship to prod. Replace with a real SMTP relay or transactional email API
22
- # (SendGrid, Resend, Postmark, SES) when promoting docker-compose.dev.yml to prod.
23
- # - Open the UI at http://localhost:8025 to inspect captured mail; nothing leaves the host.