pan-wizard 3.34.0 → 3.35.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.
- package/README.md +6 -6
- package/agents/pan-conductor.md +2 -2
- package/agents/pan-debugger.md +3 -1
- package/agents/pan-design-checker.md +1 -0
- package/agents/pan-executor.md +18 -1
- package/agents/pan-experiment-runner.md +1 -1
- package/agents/pan-hardener.md +1 -1
- package/agents/pan-meta-reviewer.md +1 -1
- package/agents/pan-phase-researcher.md +2 -2
- package/agents/pan-plan-checker.md +9 -8
- package/agents/pan-planner.md +3 -1
- package/agents/pan-project-researcher.md +1 -1
- package/agents/pan-research-synthesizer.md +1 -1
- package/agents/pan-reviewer.md +3 -2
- package/agents/pan-verifier.md +1 -1
- package/bin/install-lib.cjs +119 -16
- package/bin/install.js +34 -62
- package/commands/pan/cost.md +0 -4
- package/commands/pan/dashboard.md +0 -3
- package/commands/pan/design-phase.md +2 -2
- package/commands/pan/hud.md +1 -5
- package/commands/pan/knowledge.md +0 -1
- package/commands/pan/mcp-bridge.md +1 -3
- package/commands/pan/optimize.md +2 -0
- package/commands/pan/phase-tests.md +1 -1
- package/commands/pan/preview.md +1 -2
- package/commands/pan/report.md +1 -5
- package/commands/pan/research-phase.md +4 -4
- package/commands/pan/review-deep.md +0 -2
- package/commands/pan/what-if.md +1 -2
- package/hooks/dist/pan-context-monitor.js +12 -3
- package/hooks/dist/pan-guard.js +244 -0
- package/hooks/dist/pan-statusline.js +5 -2
- package/package.json +1 -1
- package/pan-wizard-core/bin/lib/commands.cjs +24 -2
- package/pan-wizard-core/bin/lib/config.cjs +5 -0
- package/pan-wizard-core/bin/lib/findings.cjs +126 -19
- package/pan-wizard-core/bin/lib/hygiene.cjs +11 -5
- package/pan-wizard-core/bin/lib/init.cjs +6 -0
- package/pan-wizard-core/bin/lib/optimize.cjs +13 -1
- package/pan-wizard-core/bin/lib/phase-gate.cjs +174 -0
- package/pan-wizard-core/bin/lib/phase.cjs +24 -0
- package/pan-wizard-core/bin/lib/preview.cjs +32 -31
- package/pan-wizard-core/bin/lib/verdict.cjs +140 -10
- package/pan-wizard-core/bin/lib/verify-integrity.cjs +181 -0
- package/pan-wizard-core/bin/lib/verify-plan-set.cjs +230 -0
- package/pan-wizard-core/bin/lib/verify-scope.cjs +6 -5
- package/pan-wizard-core/bin/lib/whatif.cjs +48 -6
- package/pan-wizard-core/bin/pan-tools.cjs +13 -4
- package/pan-wizard-core/mcp/merge-gate.cjs +14 -3
- package/pan-wizard-core/mcp/native-tools.cjs +3 -3
- package/pan-wizard-core/opencode/pan-wizard.js +36 -8
- package/pan-wizard-core/references/model-profiles.md +1 -1
- package/pan-wizard-core/references/planning-config.md +3 -3
- package/pan-wizard-core/references/verdict-contract.md +6 -1
- package/pan-wizard-core/templates/config.json +2 -6
- package/pan-wizard-core/templates/debug-subagent-prompt.md +2 -1
- package/pan-wizard-core/templates/phase-prompt.md +2 -0
- package/pan-wizard-core/templates/planner-subagent-prompt.md +2 -0
- package/pan-wizard-core/templates/preview-report.md +1 -1
- package/pan-wizard-core/templates/state.md +4 -4
- package/pan-wizard-core/workflows/diagnose-issues.md +4 -4
- package/pan-wizard-core/workflows/discuss-phase.md +2 -1
- package/pan-wizard-core/workflows/exec-phase.md +51 -40
- package/pan-wizard-core/workflows/milestone-gaps.md +2 -2
- package/pan-wizard-core/workflows/new-project.md +8 -16
- package/pan-wizard-core/workflows/plan-phase.md +22 -8
- package/pan-wizard-core/workflows/progress.md +1 -1
- package/pan-wizard-core/workflows/quick.md +2 -2
- package/pan-wizard-core/workflows/todo-check.md +3 -2
- package/pan-wizard-core/workflows/transition.md +4 -0
- package/pan-wizard-core/workflows/verify-phase.md +6 -6
- package/scripts/build-hooks.js +1 -0
- package/scripts/generate-skills-docs.py +2 -2
- package/scripts/prompt-lint.cjs +167 -0
- package/scripts/test-surface.cjs +1 -0
|
@@ -59,7 +59,7 @@ source: pan-previewer
|
|
|
59
59
|
## Hidden coupling
|
|
60
60
|
|
|
61
61
|
<!-- phases mode only; may be "none found" -->
|
|
62
|
-
- Phase {{from}} → Phase {{to}} — inferred from prose mention; consider
|
|
62
|
+
- Phase {{from}} → Phase {{to}} — inferred from prose mention; consider adding it to Phase {{to}}'s `**Depends on:**` line in the roadmap.
|
|
63
63
|
|
|
64
64
|
## Current state
|
|
65
65
|
|
|
@@ -35,10 +35,10 @@ See: .planning/project.md (updated [date])
|
|
|
35
35
|
- Average duration: [X] min
|
|
36
36
|
- Total execution time: [X.X] hours
|
|
37
37
|
|
|
38
|
-
**By
|
|
38
|
+
**By Plan:** (one row per plan, written by `state record-metric`)
|
|
39
39
|
|
|
40
|
-
|
|
|
41
|
-
|
|
40
|
+
| Plan | Duration | Tasks | Files |
|
|
41
|
+
|------|----------|-------|-------|
|
|
42
42
|
| - | - | - | - |
|
|
43
43
|
|
|
44
44
|
**Recent Trend:**
|
|
@@ -139,7 +139,7 @@ Progress calculation: (completed plans) / (total plans across all phases) × 100
|
|
|
139
139
|
Track velocity to understand execution patterns:
|
|
140
140
|
- Total plans completed
|
|
141
141
|
- Average duration per plan
|
|
142
|
-
- Per-phase
|
|
142
|
+
- Per-plan rows (phase, plan, duration, tasks, files)
|
|
143
143
|
- Recent trend (improving/stable/degrading)
|
|
144
144
|
|
|
145
145
|
Updated after each plan completion.
|
|
@@ -81,6 +81,7 @@ For each gap, fill the debug-subagent-prompt template and spawn:
|
|
|
81
81
|
Task(
|
|
82
82
|
prompt=filled_debug_subagent_prompt + "\n\n<files_to_read>\n- {phase_dir}/{phase_num}-uat.md\n- .planning/state.md\n</files_to_read>",
|
|
83
83
|
subagent_type="pan-debugger",
|
|
84
|
+
model="{debugger_model}", # node ~/.claude/pan-wizard-core/bin/pan-tools.cjs resolve-model pan-debugger --raw
|
|
84
85
|
description="Debug: {issue_summary_short}"
|
|
85
86
|
)
|
|
86
87
|
```
|
|
@@ -181,11 +182,10 @@ Display:
|
|
|
181
182
|
|
|
182
183
|
Debug sessions: ${DEBUG_DIR}/
|
|
183
184
|
|
|
184
|
-
|
|
185
|
+
Next: /pan:plan-phase {phase_num} --gaps
|
|
185
186
|
```
|
|
186
187
|
|
|
187
|
-
|
|
188
|
-
Do NOT offer manual next steps - verify-phase handles the rest.
|
|
188
|
+
No command runs this workflow as a sub-step, so end by giving the user the next step: `/pan:plan-phase {phase_num} --gaps` (it reads the diagnosed uat.md).
|
|
189
189
|
</step>
|
|
190
190
|
|
|
191
191
|
</process>
|
|
@@ -217,5 +217,5 @@ Agents only diagnose—plan-phase --gaps handles fixes (no fix application).
|
|
|
217
217
|
- [ ] Root causes collected from all agents
|
|
218
218
|
- [ ] uat.md gaps updated with artifacts and missing
|
|
219
219
|
- [ ] Debug sessions saved to ${DEBUG_DIR}/
|
|
220
|
-
- [ ]
|
|
220
|
+
- [ ] Next step shown: /pan:plan-phase {phase_num} --gaps
|
|
221
221
|
</success_criteria>
|
|
@@ -130,7 +130,7 @@ Exit workflow.
|
|
|
130
130
|
</step>
|
|
131
131
|
|
|
132
132
|
<step name="auto_mode_bypass">
|
|
133
|
-
**P-1803 fix (v3.7.8):** When `--auto` is set or `workflow.auto_advance: true`, **skip the entire question-driven discussion** and synthesize a minimal `context.md` directly from upstream artifacts. The unguarded `AskUserQuestion` calls in `check_existing`, `present_gray_areas` and `discuss_areas` all stall headless `claude -p` sessions immediately. Surfaced by the wookie autonomous build (v3.7.7): retry attempts via `/pan:discuss-phase 3 --auto` exited in 75s with
|
|
133
|
+
**P-1803 fix (v3.7.8):** When `--auto` is set or `workflow.auto_advance: true`, **skip the entire question-driven discussion** and synthesize a minimal `context.md` directly from upstream artifacts. The unguarded `AskUserQuestion` calls in `check_existing`, `present_gray_areas` and `discuss_areas` all stall headless `claude -p` sessions immediately. Surfaced by the wookie autonomous build (v3.7.7): retry attempts via `/pan:discuss-phase 3 --auto` exited in 75s with 42 cents of cost and zero commits before plan-phase auto-mode was patched to bypass discuss-phase entirely. This step makes discuss-phase itself auto-mode-safe, so it can be re-introduced into the auto pipeline cleanly.
|
|
134
134
|
|
|
135
135
|
Detect auto mode:
|
|
136
136
|
|
|
@@ -599,6 +599,7 @@ Task(
|
|
|
599
599
|
</instructions>
|
|
600
600
|
",
|
|
601
601
|
subagent_type="general-purpose",
|
|
602
|
+
model="$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs resolve-model pan-conductor --raw)",
|
|
602
603
|
description="Plan Phase ${PHASE}"
|
|
603
604
|
)
|
|
604
605
|
```
|
|
@@ -34,12 +34,24 @@ Load all context in one call:
|
|
|
34
34
|
INIT=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs init execute-phase "${PHASE_ARG}")
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
Parse JSON for: `executor_model`, `verifier_model`, `reviewer_model`, `commit_docs`, `parallelization`, `branching_strategy`, `branch_name`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `plans`, `incomplete_plans`, `plan_count`, `incomplete_count`, `state_exists`, `roadmap_exists`, `phase_req_ids`, `verifier_enabled`.
|
|
37
|
+
Parse JSON for: `executor_model`, `verifier_model`, `reviewer_model`, `commit_docs`, `parallelization`, `branching_strategy`, `branch_name`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `plans`, `incomplete_plans`, `plan_count`, `incomplete_count`, `state_exists`, `roadmap_exists`, `phase_req_ids`, `verifier_enabled`, `plan_check`, `plan_drift`. In the shell steps below, `$PHASE_DIR` (and `$phase_dir`) is `phase_dir` and `$PHASE_NUMBER` is `phase_number`.
|
|
38
38
|
|
|
39
39
|
**If `phase_found` is false:** Error — phase directory not found.
|
|
40
40
|
**If `plan_count` is 0:** Error — no plans found in phase.
|
|
41
41
|
**If `state_exists` is false but `.planning/` exists:** Offer reconstruct or continue.
|
|
42
42
|
|
|
43
|
+
**The plans must be the plans that passed the plan check** (`plan_check.status`):
|
|
44
|
+
|
|
45
|
+
| Status | Action |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `ok`, `disabled` | Continue |
|
|
48
|
+
| `legacy` | Continue, and say: "the plan check predates plan hashing, so it cannot show these plans are unchanged" |
|
|
49
|
+
| `stale` | Stop: "The plans changed after they passed the plan check. Re-plan with `/pan:plan-phase {N} --skip-research`, which checks the new plans." Continue only if the user gives a reason, and record it: `pan-tools optimize trace log --type decision --category plan_check_overridden --description "<reason>"` |
|
|
50
|
+
| `failed` | Stop: "The last plan check found issues." Same override |
|
|
51
|
+
| `missing` | Stop: "No plan check is recorded for this phase." This includes plans made with `/pan:plan-phase --skip-verify` or with `workflow.plan_check` off after the fact. Same override |
|
|
52
|
+
|
|
53
|
+
**Drift.** For each `plan_drift` entry, tell the executor of that plan, in its prompt, which of its `files_modified` changed since it was planned (`files`), so it re-reads them before editing. An entry with `error` means its `planned_commit` is unknown: say so and continue.
|
|
54
|
+
|
|
43
55
|
When `parallelization` is false, plans within a wave execute sequentially.
|
|
44
56
|
|
|
45
57
|
**Circular optimization — start trace session for this exec:**
|
|
@@ -190,6 +202,8 @@ Execute each wave in sequence. Within a wave: parallel if `PARALLELIZATION=true`
|
|
|
190
202
|
|
|
191
203
|
If ANY spot-check fails: report which plan failed, route to failure handler — ask "Retry plan?" or "Continue with remaining waves?"
|
|
192
204
|
|
|
205
|
+
**An executor that returned `## BLOCKED_SPEC_CONFLICT`** found a test it cannot satisfy without weakening it. It is not a failure to retry: show the user its Test, Requirement and Options and ask for a ruling. "Change the test" means a revised plan that declares the test file in `files_modified` (`/pan:plan-phase {N} --gaps` or an edit to the plan), then re-run that plan; "change the requirement" means updating the requirement and the plan. Never re-run the same plan unchanged: it would meet the same test. Declaring the file permits rewriting its expectations; deleting the test, skipping it or dropping assertions still fails `verify test-integrity`, so a ruling to do that also needs `phase complete --force --reason`.
|
|
206
|
+
|
|
193
207
|
If pass:
|
|
194
208
|
```
|
|
195
209
|
---
|
|
@@ -319,7 +333,7 @@ After all waves:
|
|
|
319
333
|
|
|
320
334
|
1. Record baseline test count:
|
|
321
335
|
```bash
|
|
322
|
-
TEST_BASELINE=$(npm test 2>&1 | grep -E "
|
|
336
|
+
TEST_BASELINE=$(npm test 2>&1 | grep -E "^(ℹ|#) tests" | awk '{print $NF}')
|
|
323
337
|
```
|
|
324
338
|
|
|
325
339
|
2. Invoke phase-tests workflow for the completed phase:
|
|
@@ -331,7 +345,8 @@ Read each summary.md to understand what was built.
|
|
|
331
345
|
Generate unit and integration tests for the new code.
|
|
332
346
|
Discover the project's existing test patterns, directories, frameworks, and helpers before writing tests.
|
|
333
347
|
Follow whatever conventions the project already uses.",
|
|
334
|
-
subagent_type="general-purpose"
|
|
348
|
+
subagent_type="general-purpose",
|
|
349
|
+
model="{executor_model}",
|
|
335
350
|
)
|
|
336
351
|
```
|
|
337
352
|
|
|
@@ -342,7 +357,7 @@ Alternatively, if the user's AI tool supports it, invoke the command directly:
|
|
|
342
357
|
|
|
343
358
|
3. Record new test count:
|
|
344
359
|
```bash
|
|
345
|
-
TEST_AFTER=$(npm test 2>&1 | grep -E "
|
|
360
|
+
TEST_AFTER=$(npm test 2>&1 | grep -E "^(ℹ|#) tests" | awk '{print $NF}')
|
|
346
361
|
```
|
|
347
362
|
|
|
348
363
|
4. Report:
|
|
@@ -353,6 +368,8 @@ TEST_AFTER=$(npm test 2>&1 | grep -E "^ℹ tests" | awk '{print $NF}')
|
|
|
353
368
|
- New tests: +$((TEST_AFTER - TEST_BASELINE))
|
|
354
369
|
```
|
|
355
370
|
|
|
371
|
+
`ℹ tests N` (spec reporter) and `# tests N` (TAP, Node's default for piped output before Node 23) are the summary lines of Node's built-in test runner, and both greps above match either. With any other runner both counts come back empty, so report the runner's own summary line instead of `+0`.
|
|
372
|
+
|
|
356
373
|
**If tests fail after generation:** Report failures but continue to next step. Test issues are caught by the verify-phase test gate.
|
|
357
374
|
</step>
|
|
358
375
|
|
|
@@ -365,11 +382,14 @@ TEST_AFTER=$(npm test 2>&1 | grep -E "^ℹ tests" | awk '{print $NF}')
|
|
|
365
382
|
```bash
|
|
366
383
|
# Read each summary.md and extract key-files.created + key-files.modified
|
|
367
384
|
for summary in "$PHASE_DIR"/*-summary.md; do
|
|
368
|
-
|
|
385
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs summary-extract "$summary" --fields key_files | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{const k=JSON.parse(s).key_files||{};for(const f of [...(k.created||[]),...(k.modified||[])])console.log(f)})"
|
|
369
386
|
done | sort -u > /tmp/review-files.txt
|
|
370
387
|
```
|
|
371
388
|
|
|
372
|
-
2.
|
|
389
|
+
2. Collect the reviewer's earlier open findings on this phase (empty on a first review), then spawn pan-reviewer:
|
|
390
|
+
```bash
|
|
391
|
+
OPEN_REVIEW_FINDINGS=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings list --phase "${PHASE_NUMBER}" --agent pan-reviewer --status open 2>/dev/null)
|
|
392
|
+
```
|
|
373
393
|
```
|
|
374
394
|
Task(
|
|
375
395
|
subagent_type="pan-reviewer",
|
|
@@ -391,6 +411,10 @@ Task(
|
|
|
391
411
|
Phase: ${PHASE_NUMBER} - ${PHASE_NAME}
|
|
392
412
|
Phase directory: ${phase_dir}
|
|
393
413
|
</context>
|
|
414
|
+
|
|
415
|
+
<open_findings>
|
|
416
|
+
${OPEN_REVIEW_FINDINGS}
|
|
417
|
+
</open_findings>
|
|
394
418
|
"
|
|
395
419
|
)
|
|
396
420
|
```
|
|
@@ -426,7 +450,7 @@ The fallback reads the word under `### Verdict` when the report carries no valid
|
|
|
426
450
|
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings dispose --phase "${PHASE_NUMBER}" --agent pan-reviewer --open --as deferred --reason "accepted at review: PASS_WITH_WARNINGS"
|
|
427
451
|
```
|
|
428
452
|
- **The user chooses "Continue anyway"** at `NEEDS_FIXES`: the same command with `--reason "continued past NEEDS_FIXES at the user's choice"`, then proceed to verification.
|
|
429
|
-
- **The user chooses "Fix before verification"**: apply the fixes, then run the review once more (steps 2–4). The
|
|
453
|
+
- **The user chooses "Fix before verification"**: apply the fixes, then run the review once more (steps 2–4). The re-review answers each earlier finding in its `resolutions`; the record closes the ones it answers `resolved` with evidence, and one it neither reports nor answers stays open.
|
|
430
454
|
|
|
431
455
|
5. **No separate trace logging.** The record logs `verdict_passed` or `verdict_failed` for the reviewer on every runtime. The `reviewer_correction` and `reviewer_warnings` trace calls that used to sit here read the error count from a shell variable nothing ever set.
|
|
432
456
|
|
|
@@ -553,7 +577,7 @@ VERIF_FILE=$(ls "$PHASE_DIR"/*-verification.md 2>/dev/null | head -1)
|
|
|
553
577
|
VERIF_STATUS=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings record --phase "${PHASE_NUMBER}" --file "$VERIF_FILE" --raw 2>/dev/null) \
|
|
554
578
|
|| VERIF_STATUS=$(grep "^status:" "$VERIF_FILE" | cut -d: -f2 | tr -d ' ')
|
|
555
579
|
```
|
|
556
|
-
`findings record` reads the verdict from the verification frontmatter (`status`, `gaps`, `human_verification`, `unrequested`) and adds its findings to the ledger. A re-verification after a fix round is the next attempt: the gaps it
|
|
580
|
+
`findings record` reads the verdict from the verification frontmatter (`status`, `gaps`, `human_verification`, `unrequested`) and adds its findings to the ledger. A re-verification after a fix round is the next attempt: the gaps it lists under `re_verification.gaps_closed` are closed, a gap it neither reports nor answers stays open (listed in `unaddressed`), and the retry is logged. Recording the same file twice is a no-op, so verify-phase recording it too is safe. The grep fallback keeps the old reading when the record cannot parse the file.
|
|
557
581
|
|
|
558
582
|
**Trace logging happens in the record.** The record above logs the verification outcome (`verdict_passed`, `verdict_failed` or `verdict_needs_human`) here, after the verifier returns. That covers inline verification too, which is the reason P-1806 moved the trace call here (v3.7.8). No separate `optimize trace log` call is needed.
|
|
559
583
|
|
|
@@ -599,12 +623,26 @@ Gap closure cycle: `/pan:plan-phase {X} --gaps` reads verification.md → create
|
|
|
599
623
|
</step>
|
|
600
624
|
|
|
601
625
|
<step name="update_roadmap">
|
|
602
|
-
**Mark phase complete and update all tracking files
|
|
626
|
+
**Mark phase complete and update all tracking files.** `phase complete` runs the phase gate first, on every path (this step runs before `offer_next`, with or without `--no-transition`). The gate checks in code what this workflow used to ask for in prose: every plan has a summary, the verification passes (a failed test gate lowers it to gaps), human items have a recorded approval, the verification is fresh, reconcile finds no contradiction, no critical or high finding is left open, no stub was committed, and no test was weakened.
|
|
603
627
|
|
|
604
628
|
```bash
|
|
605
629
|
COMPLETION=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs phase complete "${PHASE_NUMBER}")
|
|
630
|
+
COMPLETION_EXIT=$?
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
| Result | Action |
|
|
634
|
+
|---|---|
|
|
635
|
+
| exit 1, `error: phase_gate_refused` (`workflow.phase_gate: enforce`) | The phase was NOT marked complete. Show each `gate.reasons` entry (`code`: `detail`) with its fix, and stop: no commit, no auto-advance. The user may complete anyway with a reason (below) |
|
|
636
|
+
| exit 0, `gate.ok` false (`warn`, the default) | The phase was marked complete. Show the reasons as warnings, run the rest of this step, and do NOT auto-advance (`offer_next` reads `GATE_OK`) |
|
|
637
|
+
| exit 0, `gate.ok` true | Continue |
|
|
638
|
+
|
|
639
|
+
**Completing past a refusal** is the user's decision, never yours, and needs their reason. It records a `decision` for every open finding the gate counted:
|
|
640
|
+
```bash
|
|
641
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs phase complete "${PHASE_NUMBER}" --force --reason "<the user's reason>"
|
|
606
642
|
```
|
|
607
643
|
|
|
644
|
+
Set `GATE_OK` to `gate.ok` from `COMPLETION` (`false` when the gate refused).
|
|
645
|
+
|
|
608
646
|
The CLI handles:
|
|
609
647
|
- Marking phase checkbox `[x]` with completion date
|
|
610
648
|
- Updating Progress table (Status → Complete, date)
|
|
@@ -659,7 +697,7 @@ Parse `--no-transition` flag from $ARGUMENTS.
|
|
|
659
697
|
**If `--no-transition` flag present:**
|
|
660
698
|
|
|
661
699
|
Execute-phase was spawned by plan-phase's auto-advance. Do NOT run transition.md.
|
|
662
|
-
If verification found gaps, return `## GAPS FOUND` with the phase, score and gap summaries (plan-phase and discuss-phase stop the chain on it). After
|
|
700
|
+
If verification found gaps, or `GATE_OK` is false, return `## GAPS FOUND` with the phase, score and the gap summaries or the gate's reasons (plan-phase and discuss-phase stop the chain on it). After the gate passes, return completion status to parent:
|
|
663
701
|
|
|
664
702
|
```
|
|
665
703
|
## PHASE COMPLETE
|
|
@@ -675,37 +713,10 @@ STOP. Do not proceed to auto-advance or transition.
|
|
|
675
713
|
|
|
676
714
|
**If `--no-transition` flag is NOT present:**
|
|
677
715
|
|
|
678
|
-
**
|
|
679
|
-
|
|
680
|
-
If `workflow.verifier` is true in config, confirm the current phase has a passing verification:
|
|
681
|
-
|
|
682
|
-
```bash
|
|
683
|
-
VERIF=$(ls "$phase_dir"/*-verification.md 2>/dev/null | head -1)
|
|
684
|
-
VERIF_STATUS=""
|
|
685
|
-
if [ -n "$VERIF" ]; then
|
|
686
|
-
VERIF_STATUS=$(grep "^status:" "$VERIF" | awk '{print $2}')
|
|
687
|
-
fi
|
|
688
|
-
```
|
|
689
|
-
|
|
690
|
-
**Cross-check the written verdict against the mechanical signals (anti-rubber-stamp, ADR-0036).** The `status:` string above is authored by the verifier agent; `reconcile` re-derives the artifact/key-link checks from disk and exits non-zero when a claimed pass contradicts them:
|
|
691
|
-
```bash
|
|
692
|
-
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs verify reconcile "${PHASE_NUMBER}" --raw
|
|
693
|
-
RECONCILE_EXIT=$?
|
|
694
|
-
```
|
|
695
|
-
If `RECONCILE_EXIT` is non-zero:
|
|
696
|
-
```
|
|
697
|
-
⚠ Reconcile gate: Phase ${PHASE_NUMBER} verification says "passed" but the mechanical
|
|
698
|
-
checks disagree — artifacts fail substance checks or key-links are unwired.
|
|
699
|
-
This is a rubber-stamped verification. Do NOT auto-advance.
|
|
700
|
-
Re-run /pan:verify-phase and fix the failing artifacts/key-links.
|
|
701
|
-
```
|
|
702
|
-
STOP — do not auto-advance. Return to user.
|
|
703
|
-
|
|
704
|
-
If `VERIF_STATUS` is not `passed`:
|
|
716
|
+
**Gate check (before auto-advance).** The phase gate already ran inside `phase complete` (`update_roadmap`), and it covers the verification status, reconcile (anti-rubber-stamp, ADR-0036), freshness, open findings, stubs and test integrity. If `GATE_OK` is false:
|
|
705
717
|
```
|
|
706
|
-
⚠
|
|
707
|
-
|
|
708
|
-
Run /pan:verify-phase to verify this phase first.
|
|
718
|
+
⚠ Phase gate: Phase ${PHASE_NUMBER} may not advance — {each gate reason: code and detail}.
|
|
719
|
+
Fix the reasons (or close the gaps with /pan:plan-phase ${PHASE_NUMBER} --gaps), then re-run.
|
|
709
720
|
```
|
|
710
721
|
STOP — do not auto-advance. Return to user.
|
|
711
722
|
|
|
@@ -64,8 +64,8 @@ Gap: Flow "View dashboard" broken at data fetch
|
|
|
64
64
|
|
|
65
65
|
Find highest existing phase:
|
|
66
66
|
```bash
|
|
67
|
-
#
|
|
68
|
-
HIGHEST=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs
|
|
67
|
+
# Highest phase number in roadmap.md — the same source `phase add` numbers from
|
|
68
|
+
HIGHEST=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs roadmap analyze | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{const n=JSON.parse(s).phases.map(p=>parseInt(p.number,10)).filter(Number.isFinite);console.log(n.length?Math.max(...n):0)})")
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
New phases continue from there:
|
|
@@ -525,9 +525,7 @@ Display spawning indicator:
|
|
|
525
525
|
Spawn 4 parallel pan-project-researcher agents with path references:
|
|
526
526
|
|
|
527
527
|
```
|
|
528
|
-
Task(prompt="
|
|
529
|
-
|
|
530
|
-
<research_type>
|
|
528
|
+
Task(prompt="<research_type>
|
|
531
529
|
Project Research — Stack dimension for [domain].
|
|
532
530
|
</research_type>
|
|
533
531
|
|
|
@@ -563,11 +561,9 @@ Your stack.md feeds into roadmap creation. Be prescriptive:
|
|
|
563
561
|
Write to: .planning/research/stack.md
|
|
564
562
|
Use template: ~/.claude/pan-wizard-core/templates/research-project/stack.md
|
|
565
563
|
</output>
|
|
566
|
-
", subagent_type="
|
|
567
|
-
|
|
568
|
-
Task(prompt="First, read ~/.claude/agents/pan-project-researcher.md for your role and instructions.
|
|
564
|
+
", subagent_type="pan-project-researcher", model="{researcher_model}", description="Stack research")
|
|
569
565
|
|
|
570
|
-
<research_type>
|
|
566
|
+
Task(prompt="<research_type>
|
|
571
567
|
Project Research — Features dimension for [domain].
|
|
572
568
|
</research_type>
|
|
573
569
|
|
|
@@ -603,11 +599,9 @@ Your features.md feeds into requirements definition. Categorize clearly:
|
|
|
603
599
|
Write to: .planning/research/features.md
|
|
604
600
|
Use template: ~/.claude/pan-wizard-core/templates/research-project/features.md
|
|
605
601
|
</output>
|
|
606
|
-
", subagent_type="
|
|
602
|
+
", subagent_type="pan-project-researcher", model="{researcher_model}", description="Features research")
|
|
607
603
|
|
|
608
|
-
Task(prompt="
|
|
609
|
-
|
|
610
|
-
<research_type>
|
|
604
|
+
Task(prompt="<research_type>
|
|
611
605
|
Project Research — Architecture dimension for [domain].
|
|
612
606
|
</research_type>
|
|
613
607
|
|
|
@@ -643,11 +637,9 @@ Your architecture.md informs phase structure in roadmap. Include:
|
|
|
643
637
|
Write to: .planning/research/architecture.md
|
|
644
638
|
Use template: ~/.claude/pan-wizard-core/templates/research-project/architecture.md
|
|
645
639
|
</output>
|
|
646
|
-
", subagent_type="
|
|
647
|
-
|
|
648
|
-
Task(prompt="First, read ~/.claude/agents/pan-project-researcher.md for your role and instructions.
|
|
640
|
+
", subagent_type="pan-project-researcher", model="{researcher_model}", description="Architecture research")
|
|
649
641
|
|
|
650
|
-
<research_type>
|
|
642
|
+
Task(prompt="<research_type>
|
|
651
643
|
Project Research — Pitfalls dimension for [domain].
|
|
652
644
|
</research_type>
|
|
653
645
|
|
|
@@ -683,7 +675,7 @@ Your pitfalls.md prevents mistakes in roadmap/planning. For each pitfall:
|
|
|
683
675
|
Write to: .planning/research/pitfalls.md
|
|
684
676
|
Use template: ~/.claude/pan-wizard-core/templates/research-project/pitfalls.md
|
|
685
677
|
</output>
|
|
686
|
-
", subagent_type="
|
|
678
|
+
", subagent_type="pan-project-researcher", model="{researcher_model}", description="Pitfalls research")
|
|
687
679
|
```
|
|
688
680
|
|
|
689
681
|
After all 4 agents complete, spawn synthesizer to create summary.md:
|
|
@@ -280,8 +280,8 @@ Write to: {phase_dir}/{padded_phase}-research.md
|
|
|
280
280
|
|
|
281
281
|
```
|
|
282
282
|
Task(
|
|
283
|
-
prompt=
|
|
284
|
-
subagent_type="
|
|
283
|
+
prompt=research_prompt,
|
|
284
|
+
subagent_type="pan-phase-researcher",
|
|
285
285
|
model="{researcher_model}",
|
|
286
286
|
description="Research Phase {phase}"
|
|
287
287
|
)
|
|
@@ -383,8 +383,8 @@ Output consumed by /pan:exec-phase. Plans need:
|
|
|
383
383
|
|
|
384
384
|
```
|
|
385
385
|
Task(
|
|
386
|
-
prompt=
|
|
387
|
-
subagent_type="
|
|
386
|
+
prompt=filled_prompt,
|
|
387
|
+
subagent_type="pan-planner",
|
|
388
388
|
model="{planner_model}",
|
|
389
389
|
description="Plan Phase {phase}"
|
|
390
390
|
)
|
|
@@ -392,12 +392,21 @@ Task(
|
|
|
392
392
|
|
|
393
393
|
## 9. Handle Planner Return
|
|
394
394
|
|
|
395
|
-
- **`## PLANNING COMPLETE`:** Display plan count. If `--skip-verify` or `plan_checker_enabled` is false (from init): skip to step 13. Otherwise: step 10.
|
|
395
|
+
- **`## PLANNING COMPLETE`:** Display plan count. If `--skip-verify` or `plan_checker_enabled` is false (from init): still run the code checks at the start of step 10 (`verify plan-set`; they cost no model call), send any errors back to the planner (step 12), then skip to step 13. Otherwise: step 10.
|
|
396
396
|
- **`## GAP CLOSURE PLANS CREATED`:** (`--gaps` mode) Handle as `## PLANNING COMPLETE`.
|
|
397
397
|
- **`## CHECKPOINT REACHED`:** Present to user, get response, spawn a fresh planner (step 8's Task) with the response added to its prompt
|
|
398
398
|
|
|
399
399
|
## 10. Spawn pan-plan-checker Agent
|
|
400
400
|
|
|
401
|
+
**First, the checks code can make.** Run them before spending a checker:
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
PLAN_SET=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs verify plan-set "${PHASE_NUMBER}")
|
|
405
|
+
PLAN_SET_EXIT=$?
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Exit 1 means the plan set is broken in a way no review can wave through: a roadmap requirement no plan lists, two plans in one wave modifying the same file, a `depends_on` that names no plan or a plan in the same or a later wave, or a cycle. Send `PLAN_SET`'s `errors` to the planner as the revision context (step 12; it counts as an iteration) and do not spawn the checker for this set. Exit 0: continue, and pass any `warnings` to the checker.
|
|
409
|
+
|
|
401
410
|
Display banner:
|
|
402
411
|
```
|
|
403
412
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
@@ -427,6 +436,10 @@ Checker prompt:
|
|
|
427
436
|
**Project skills:** Check .agents/skills/ directory (if exists) — verify plans account for project skill rules
|
|
428
437
|
</verification_context>
|
|
429
438
|
|
|
439
|
+
<open_findings>
|
|
440
|
+
{output of `pan-tools findings list --phase {phase_number} --agent pan-plan-checker --status open`: empty on the first check; on a re-check, answer each in `resolutions`}
|
|
441
|
+
</open_findings>
|
|
442
|
+
|
|
430
443
|
<expected_output>
|
|
431
444
|
- ## VERIFICATION PASSED — all checks pass
|
|
432
445
|
- ## ISSUES FOUND — structured issue list
|
|
@@ -457,7 +470,7 @@ The fallback reads the heading when the report carries no valid `pan-verdict` bl
|
|
|
457
470
|
- **`passed`:** Display confirmation, proceed to step 13.
|
|
458
471
|
- **`issues_found`:** Display issues, check iteration count, proceed to step 12.
|
|
459
472
|
|
|
460
|
-
Each re-check in the revision loop overwrites the same file and is recorded again as the next attempt. The
|
|
473
|
+
Each re-check in the revision loop overwrites the same file and is recorded again as the next attempt. The checker answers each earlier issue in `resolutions`; the record closes the ones it answers `resolved` with evidence, and one it neither reports nor answers stays open.
|
|
461
474
|
|
|
462
475
|
## 12. Revision Loop (At Most 2 Revisions, 3 Checks)
|
|
463
476
|
|
|
@@ -491,8 +504,8 @@ Return what changed.
|
|
|
491
504
|
|
|
492
505
|
```
|
|
493
506
|
Task(
|
|
494
|
-
prompt=
|
|
495
|
-
subagent_type="
|
|
507
|
+
prompt=revision_prompt,
|
|
508
|
+
subagent_type="pan-planner",
|
|
496
509
|
model="{planner_model}",
|
|
497
510
|
description="Revise Phase {phase} plans"
|
|
498
511
|
)
|
|
@@ -590,6 +603,7 @@ Task(
|
|
|
590
603
|
</instructions>
|
|
591
604
|
",
|
|
592
605
|
subagent_type="general-purpose",
|
|
606
|
+
model="$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs resolve-model pan-conductor --raw)",
|
|
593
607
|
description="Execute Phase ${PHASE}"
|
|
594
608
|
)
|
|
595
609
|
```
|
|
@@ -54,7 +54,7 @@ ROADMAP=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs roadmap analyze)
|
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
This returns structured JSON with:
|
|
57
|
-
- All phases with disk status (complete/partial/planned/empty/no_directory)
|
|
57
|
+
- All phases with disk status (complete/partial/planned/researched/discussed/empty/no_directory)
|
|
58
58
|
- Goal and dependencies per phase
|
|
59
59
|
- Plan and summary counts per phase
|
|
60
60
|
- Aggregated stats: total plans, summaries, progress percent
|
|
@@ -229,8 +229,8 @@ Return what changed.
|
|
|
229
229
|
|
|
230
230
|
```
|
|
231
231
|
Task(
|
|
232
|
-
prompt=
|
|
233
|
-
subagent_type="
|
|
232
|
+
prompt=revision_prompt,
|
|
233
|
+
subagent_type="pan-planner",
|
|
234
234
|
model="{planner_model}",
|
|
235
235
|
description="Revise quick plan: ${DESCRIPTION}"
|
|
236
236
|
)
|
|
@@ -12,7 +12,8 @@ Read all files referenced by the invoking prompt's execution_context before star
|
|
|
12
12
|
Load todo context:
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
|
|
15
|
+
AREA="" # the area argument when one was given: /pan:todo-check api → AREA="api"; empty lists every todo
|
|
16
|
+
INIT=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs init todos "$AREA")
|
|
16
17
|
```
|
|
17
18
|
|
|
18
19
|
Extract from init JSON: `todo_count`, `todos`, `pending_dir`.
|
|
@@ -35,7 +36,7 @@ Exit.
|
|
|
35
36
|
</step>
|
|
36
37
|
|
|
37
38
|
<step name="parse_filter">
|
|
38
|
-
|
|
39
|
+
The area filter was applied in init_context (AREA):
|
|
39
40
|
- `/pan:todo-check` → show all
|
|
40
41
|
- `/pan:todo-check api` → filter to area:api only
|
|
41
42
|
</step>
|
|
@@ -155,6 +155,8 @@ If found, delete them — phase is complete, handoffs are stale.
|
|
|
155
155
|
TRANSITION=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs phase complete "${current_phase}") # skip when exec-phase invoked this workflow: its `phase complete` already ran — reuse that result
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
+
`phase complete` runs the phase gate first. Exit 1 with `error: phase_gate_refused` (`workflow.phase_gate: enforce`) means the phase was not marked complete: show `gate.reasons` and stop the transition. With `gate.ok` false under `warn`, the phase was marked complete: show the reasons as warnings before continuing.
|
|
159
|
+
|
|
158
160
|
The CLI handles:
|
|
159
161
|
- Marking the phase checkbox as `[x]` complete with today's date
|
|
160
162
|
- Updating plan count to final (e.g., "3/3 plans complete")
|
|
@@ -453,6 +455,7 @@ Task(
|
|
|
453
455
|
</instructions>
|
|
454
456
|
",
|
|
455
457
|
subagent_type="general-purpose",
|
|
458
|
+
model="$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs resolve-model pan-conductor --raw)",
|
|
456
459
|
description="Plan Phase ${NEXT_PHASE}"
|
|
457
460
|
)
|
|
458
461
|
```
|
|
@@ -495,6 +498,7 @@ Task(
|
|
|
495
498
|
</instructions>
|
|
496
499
|
",
|
|
497
500
|
subagent_type="general-purpose",
|
|
501
|
+
model="$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs resolve-model pan-conductor --raw)",
|
|
498
502
|
description="Discuss Phase ${NEXT_PHASE}"
|
|
499
503
|
)
|
|
500
504
|
```
|
|
@@ -105,15 +105,15 @@ HAS_TEST=$(node -e "try{const p=require('./package.json');process.stdout.write(p
|
|
|
105
105
|
```bash
|
|
106
106
|
TEST_OUTPUT=$(npm test 2>&1)
|
|
107
107
|
TEST_EXIT=$?
|
|
108
|
-
TEST_COUNT=$(echo "$TEST_OUTPUT" | grep -E "
|
|
109
|
-
TEST_PASS=$(echo "$TEST_OUTPUT" | grep -E "
|
|
110
|
-
TEST_FAIL=$(echo "$TEST_OUTPUT" | grep -E "
|
|
108
|
+
TEST_COUNT=$(echo "$TEST_OUTPUT" | grep -E "^(ℹ|#) tests" | awk '{print $NF}')
|
|
109
|
+
TEST_PASS=$(echo "$TEST_OUTPUT" | grep -E "^(ℹ|#) pass" | awk '{print $NF}')
|
|
110
|
+
TEST_FAIL=$(echo "$TEST_OUTPUT" | grep -E "^(ℹ|#) fail" | awk '{print $NF}')
|
|
111
111
|
```
|
|
112
112
|
|
|
113
113
|
3. Evaluate results.
|
|
114
114
|
|
|
115
115
|
**Check `TEST_EXIT` FIRST, before any count.** A suite that did not run emits no
|
|
116
|
-
`ℹ fail` line at all, so `TEST_FAIL` comes back EMPTY — not `0`. Reading an empty
|
|
116
|
+
`ℹ fail` / `# fail` line at all, so `TEST_FAIL` comes back EMPTY — not `0`. Reading an empty
|
|
117
117
|
value as "no failures" scores a crashed suite as a pass, which is the worst
|
|
118
118
|
direction this gate can fail in: a phase ships green on a project whose tests never
|
|
119
119
|
executed. Empty is not zero. Judge the exit code, then the counts.
|
|
@@ -121,7 +121,7 @@ executed. Empty is not zero. Judge the exit code, then the counts.
|
|
|
121
121
|
| Condition | Action |
|
|
122
122
|
|-----------|--------|
|
|
123
123
|
| `TEST_EXIT` = 0 **and** `TEST_FAIL` = 0 (a real number) | Record counts, continue to must-haves |
|
|
124
|
-
| `TEST_EXIT` = 0 **and** no
|
|
124
|
+
| `TEST_EXIT` = 0 **and** no `ℹ`/`#` count lines (a runner other than Node's built-in one) | Set `test_gate_status: passed`; record the runner's own summary line as the counts |
|
|
125
125
|
| `TEST_EXIT` ≠ 0 **and** failures were reported | Set `test_gate_status: failed`, include failure details |
|
|
126
126
|
| `TEST_EXIT` ≠ 0 **and** `TEST_FAIL` is empty/absent — the suite CRASHED or could not run (syntax error, missing module, bad import, no runner) | Set `test_gate_status: failed`, and record the reason as `suite did not run`. **Never `skipped`, never `passed`.** A suite that cannot execute is stronger evidence of a broken phase than one that runs and fails |
|
|
127
127
|
| `HAS_TEST` = `no` (handled in step 1) | Record as `test_gate_status: skipped`, continue. This is the ONLY legitimate route to `skipped` |
|
|
@@ -328,7 +328,7 @@ If human_needed: list items requiring human testing.
|
|
|
328
328
|
|
|
329
329
|
Orchestrator routes: `passed` → update_roadmap | `gaps_found` → create/execute fixes, re-verify | `human_needed` → present to user.
|
|
330
330
|
|
|
331
|
-
**Record the verification.** The record adds its findings to the ledger and logs the outcome to the trace (`verdict_passed`, `verdict_failed` or `verdict_needs_human`). A re-verification is the next attempt
|
|
331
|
+
**Record the verification.** The record adds its findings to the ledger and logs the outcome to the trace (`verdict_passed`, `verdict_failed` or `verdict_needs_human`). A re-verification is the next attempt. It closes the gaps it lists under `re_verification.gaps_closed`; a gap it neither reports nor answers stays open:
|
|
332
332
|
```bash
|
|
333
333
|
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings record --phase "${phase_number}" --file "$REPORT_PATH" 2>/dev/null || true
|
|
334
334
|
```
|
package/scripts/build-hooks.js
CHANGED
|
@@ -391,11 +391,11 @@ def generate_reference(shipped: list[Skill], dev: list[Skill], version: str) ->
|
|
|
391
391
|
w(s.description)
|
|
392
392
|
w("")
|
|
393
393
|
if s.argument_hint:
|
|
394
|
-
w(
|
|
394
|
+
w("```text")
|
|
395
395
|
w(f"{s.command} {s.argument_hint}")
|
|
396
396
|
w(f"```")
|
|
397
397
|
else:
|
|
398
|
-
w(
|
|
398
|
+
w("```text")
|
|
399
399
|
w(f"{s.command}")
|
|
400
400
|
w(f"```")
|
|
401
401
|
w("")
|