pan-wizard 3.31.0 → 3.32.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 +28 -24
- package/agents/pan-design-checker.md +18 -0
- package/agents/pan-optimizer.md +5 -1
- package/agents/pan-plan-checker.md +23 -0
- package/agents/pan-reviewer.md +19 -0
- package/agents/pan-verifier.md +23 -0
- package/commands/pan/design-phase.md +8 -0
- package/commands/pan/exec-phase.md +1 -1
- package/commands/pan/git.md +2 -2
- package/commands/pan/learn.md +2 -0
- package/commands/pan/optimize.md +14 -2
- package/commands/pan/review-deep.md +5 -5
- package/hooks/dist/pan-context-monitor.js +1 -1
- package/hooks/dist/pan-cost-logger.js +63 -11
- package/hooks/dist/pan-state-reinject.js +2 -2
- package/hooks/dist/pan-stop-guard.js +2 -2
- package/hooks/dist/pan-trace-logger.js +283 -18
- package/package.json +1 -1
- package/pan-wizard-core/bin/lib/commands.cjs +2 -1
- package/pan-wizard-core/bin/lib/constants.cjs +28 -0
- package/pan-wizard-core/bin/lib/cost.cjs +3 -3
- package/pan-wizard-core/bin/lib/findings.cjs +381 -0
- package/pan-wizard-core/bin/lib/focus.cjs +72 -19
- package/pan-wizard-core/bin/lib/foreign-planning.cjs +24 -6
- package/pan-wizard-core/bin/lib/hygiene.cjs +12 -2
- package/pan-wizard-core/bin/lib/init.cjs +4 -1
- package/pan-wizard-core/bin/lib/optimize.cjs +349 -21
- package/pan-wizard-core/bin/lib/review-deep.cjs +36 -0
- package/pan-wizard-core/bin/lib/state.cjs +7 -2
- package/pan-wizard-core/bin/lib/verdict.cjs +431 -0
- package/pan-wizard-core/bin/lib/verify-preflight.cjs +4 -2
- package/pan-wizard-core/bin/lib/verify-scope.cjs +156 -0
- package/pan-wizard-core/bin/lib/verify.cjs +25 -2
- package/pan-wizard-core/bin/pan-tools.cjs +59 -5
- package/pan-wizard-core/learnings/README.md +10 -7
- package/pan-wizard-core/mcp/tool-registry.cjs +2 -0
- package/pan-wizard-core/references/verdict-contract.md +101 -0
- package/pan-wizard-core/templates/verification-report.md +16 -0
- package/pan-wizard-core/workflows/exec-phase.md +65 -47
- package/pan-wizard-core/workflows/health.md +2 -0
- package/pan-wizard-core/workflows/learn.md +4 -2
- package/pan-wizard-core/workflows/milestone-audit.md +15 -3
- package/pan-wizard-core/workflows/optimize.md +14 -1
- package/pan-wizard-core/workflows/plan-phase.md +20 -15
- package/pan-wizard-core/workflows/verify-phase.md +3 -13
- package/pan-zcode/README.md +3 -3
- package/scripts/git-hooks/pre-commit +2 -1
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
* history-digest Aggregate all summary.md data
|
|
29
29
|
* summary-extract <path> [--fields] Extract structured data from summary.md
|
|
30
30
|
* state-snapshot Structured parse of state.md (alias: state snapshot)
|
|
31
|
+
* findings record|list|dispose|debt Judges' verdicts and their findings ledger (evidence loop)
|
|
31
32
|
* phase-plan-index <phase> Index plans with waves and status
|
|
32
33
|
* websearch <query> Search web via Brave API (if configured)
|
|
33
34
|
* [--limit N] [--freshness day|week|month]
|
|
@@ -206,6 +207,7 @@ const cost = require('./lib/cost.cjs');
|
|
|
206
207
|
const costRebuild = require('./lib/cost-rebuild.cjs');
|
|
207
208
|
const preview = require('./lib/preview.cjs');
|
|
208
209
|
const reviewDeep = require('./lib/review-deep.cjs');
|
|
210
|
+
const findings = require('./lib/findings.cjs');
|
|
209
211
|
const knowledge = require('./lib/knowledge.cjs');
|
|
210
212
|
const skillAlign = require('./lib/skill-align.cjs');
|
|
211
213
|
const hygiene = require('./lib/hygiene.cjs');
|
|
@@ -331,7 +333,7 @@ async function main() {
|
|
|
331
333
|
+ ' --planning-dir <path> act on an arbitrary project-relative planning tree\n'
|
|
332
334
|
+ ' --all-tracks (hygiene) act on the root tree AND every discovered track\n'
|
|
333
335
|
+ ' env: PAN_TRACK, PAN_PLANNING_DIR (flags win)\n'
|
|
334
|
-
+ '\nCommands: state, resolve-model, estimate-cost, find-phase, git, distill, experiment, commit, verify-summary, template, frontmatter, verify, generate-slug, current-timestamp, list-todos, verify-path-exists, config-ensure-section, config-set, config-get, history-digest, phases, roadmap, requirements, phase, milestone, validate, progress, context-budget, todo, scaffold, init, phase-plan-index, state-snapshot, summary-extract, rollback-snapshot, batch-commit, websearch, focus, preflight, dashboard, hud, report, learnings, deps, drift-check, memory, bridge, whatif, knowledge, skills, hygiene, review-deep, preview, cost, models, squad, worktree, campaign, bus, cache, retro, codebase, standards, optimize, doc-lint, learn, links';
|
|
336
|
+
+ '\nCommands: state, resolve-model, estimate-cost, find-phase, git, distill, experiment, commit, verify-summary, template, frontmatter, verify, generate-slug, current-timestamp, list-todos, verify-path-exists, config-ensure-section, config-set, config-get, history-digest, phases, roadmap, requirements, phase, milestone, validate, progress, context-budget, todo, scaffold, init, phase-plan-index, state-snapshot, summary-extract, rollback-snapshot, batch-commit, websearch, focus, preflight, dashboard, hud, report, learnings, deps, drift-check, memory, bridge, whatif, knowledge, skills, hygiene, review-deep, findings, preview, cost, models, squad, worktree, campaign, bus, cache, retro, codebase, standards, optimize, doc-lint, learn, links';
|
|
335
337
|
|
|
336
338
|
if (!command) {
|
|
337
339
|
error(USAGE);
|
|
@@ -412,7 +414,7 @@ async function main() {
|
|
|
412
414
|
} else if (subcommand === 'load' || !subcommand) {
|
|
413
415
|
state.cmdStateLoad(cwd, raw);
|
|
414
416
|
} else {
|
|
415
|
-
error(`Unknown state subcommand: ${subcommand}. Available: json, update, get, patch, advance-plan, record-metric, update-progress, add-decision, add-blocker, resolve-blocker, record-session, load, snapshot`);
|
|
417
|
+
error(`Unknown state subcommand: ${subcommand}. Available: json, update, get, patch, compact, advance-plan, record-metric, update-progress, add-decision, add-blocker, resolve-blocker, record-session, load, snapshot`);
|
|
416
418
|
}
|
|
417
419
|
break;
|
|
418
420
|
}
|
|
@@ -607,8 +609,10 @@ async function main() {
|
|
|
607
609
|
verify.cmdVerifyReconcile(cwd, args[2], raw);
|
|
608
610
|
} else if (subcommand === 'stubs') {
|
|
609
611
|
verify.cmdVerifyStubs(cwd, { gate: args.includes('--gate') }, raw);
|
|
612
|
+
} else if (subcommand === 'scope') {
|
|
613
|
+
verify.cmdVerifyScope(cwd, args[2], raw);
|
|
610
614
|
} else {
|
|
611
|
-
error('Unknown verify subcommand. Available: plan-structure, phase-completeness, references, commits, artifacts, key-links, reconcile, stubs');
|
|
615
|
+
error('Unknown verify subcommand. Available: plan-structure, phase-completeness, references, commits, artifacts, key-links, reconcile, stubs, scope');
|
|
612
616
|
}
|
|
613
617
|
break;
|
|
614
618
|
}
|
|
@@ -914,7 +918,13 @@ async function main() {
|
|
|
914
918
|
output({ error: 'No batch file found. Run focus plan first.' }, raw);
|
|
915
919
|
break;
|
|
916
920
|
}
|
|
917
|
-
|
|
921
|
+
if (batch.error) {
|
|
922
|
+
// The newest batch is the one /pan:focus-exec runs; classifying another would
|
|
923
|
+
// hand it waves for the wrong items, so an unusable newest batch is an error.
|
|
924
|
+
output({ error: batch.error }, raw);
|
|
925
|
+
break;
|
|
926
|
+
}
|
|
927
|
+
items = batch.batch;
|
|
918
928
|
}
|
|
919
929
|
output(focus.classifyStageDependencies(items), raw);
|
|
920
930
|
} else if (subcommand === 'reflection') {
|
|
@@ -1177,6 +1187,44 @@ async function main() {
|
|
|
1177
1187
|
break;
|
|
1178
1188
|
}
|
|
1179
1189
|
|
|
1190
|
+
case 'findings': {
|
|
1191
|
+
// Evidence loop (ADR-0049): judges' verdicts recorded from their reports, and
|
|
1192
|
+
// the dispositions workflows give the findings they continue past.
|
|
1193
|
+
const subcommand = args[1];
|
|
1194
|
+
const filters = {
|
|
1195
|
+
phase: getArgValue(args, '--phase'),
|
|
1196
|
+
agent: getArgValue(args, '--agent'),
|
|
1197
|
+
status: getArgValue(args, '--status'),
|
|
1198
|
+
class: getArgValue(args, '--class'),
|
|
1199
|
+
milestone: getArgValue(args, '--milestone'),
|
|
1200
|
+
};
|
|
1201
|
+
if (subcommand === 'record') {
|
|
1202
|
+
findings.cmdFindingsRecord(cwd, {
|
|
1203
|
+
phase: filters.phase,
|
|
1204
|
+
agent: filters.agent,
|
|
1205
|
+
file: getArgValue(args, '--file'),
|
|
1206
|
+
text: getArgValue(args, '--text'),
|
|
1207
|
+
stdin: args.includes('--stdin'),
|
|
1208
|
+
}, raw);
|
|
1209
|
+
} else if (subcommand === 'list') {
|
|
1210
|
+
findings.cmdFindingsList(cwd, filters, raw);
|
|
1211
|
+
} else if (subcommand === 'dispose') {
|
|
1212
|
+
findings.cmdFindingsDispose(cwd, {
|
|
1213
|
+
ids: findings.findingIdsIn(args.slice(2)),
|
|
1214
|
+
phase: filters.phase,
|
|
1215
|
+
agent: filters.agent,
|
|
1216
|
+
open: args.includes('--open'),
|
|
1217
|
+
as: getArgValue(args, '--as'),
|
|
1218
|
+
reason: getArgValue(args, '--reason'),
|
|
1219
|
+
}, raw);
|
|
1220
|
+
} else if (subcommand === 'debt') {
|
|
1221
|
+
findings.cmdFindingsDebt(cwd, { milestone: filters.milestone }, raw);
|
|
1222
|
+
} else {
|
|
1223
|
+
error('Unknown findings subcommand. Available: record, list, dispose, debt');
|
|
1224
|
+
}
|
|
1225
|
+
break;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1180
1228
|
case 'preview': {
|
|
1181
1229
|
const subcommand = args[1];
|
|
1182
1230
|
if (subcommand === 'phase') {
|
|
@@ -1408,17 +1456,23 @@ async function main() {
|
|
|
1408
1456
|
} else if (subcommand === 'learn') {
|
|
1409
1457
|
optimize.cmdOptimizeLearn(cwd, {
|
|
1410
1458
|
sessionId: getArgValue(args, '--session'),
|
|
1459
|
+
sessions: getArgValue(args, '--sessions'),
|
|
1411
1460
|
}, raw);
|
|
1412
1461
|
} else if (subcommand === 'apply') {
|
|
1413
1462
|
optimize.cmdOptimizeApply(cwd, {
|
|
1414
1463
|
reportPath: getArgValue(args, '--report'),
|
|
1415
1464
|
}, raw);
|
|
1465
|
+
} else if (subcommand === 'revert') {
|
|
1466
|
+
optimize.cmdOptimizeRevert(cwd, {
|
|
1467
|
+
applyId: args[2] && !args[2].startsWith('--') ? args[2] : null,
|
|
1468
|
+
last: args.includes('--last'),
|
|
1469
|
+
}, raw);
|
|
1416
1470
|
} else if (subcommand === 'list') {
|
|
1417
1471
|
optimize.cmdOptimizeList(cwd, raw);
|
|
1418
1472
|
} else if (subcommand === 'stats') {
|
|
1419
1473
|
optimize.cmdOptimizeStats(cwd, raw);
|
|
1420
1474
|
} else {
|
|
1421
|
-
error('Unknown optimize subcommand. Available: trace, learn, apply, list, stats');
|
|
1475
|
+
error('Unknown optimize subcommand. Available: trace, learn, apply, revert, list, stats');
|
|
1422
1476
|
}
|
|
1423
1477
|
break;
|
|
1424
1478
|
}
|
|
@@ -4,7 +4,7 @@ This directory holds AI-derived behavioral patterns extracted from real PAN
|
|
|
4
4
|
Wizard sessions via the **self-improvement loop** (v3.7.0+, see
|
|
5
5
|
[ADR-0026](../../docs/decisions/ADR-0026-self-improvement-loop.md)).
|
|
6
6
|
|
|
7
|
-
Patterns are
|
|
7
|
+
Patterns are promoted by hand with `pan-tools learn promote` (see Lifecycle) from
|
|
8
8
|
harvested experiment data. They are **advisory** — orchestrators weight them
|
|
9
9
|
against current context, not as hard rules.
|
|
10
10
|
|
|
@@ -46,9 +46,10 @@ patterns:
|
|
|
46
46
|
|
|
47
47
|
## Lifecycle
|
|
48
48
|
|
|
49
|
-
1. **Promote** — `pan-tools learn promote --pattern <id> --scope universal --topic <name>` appends a pattern to the topic file (creates the file if absent).
|
|
50
|
-
2. **Unpromote** — `pan-tools learn unpromote --pattern <id> --topic <name>` removes a pattern (for rollback).
|
|
49
|
+
1. **Promote** — `pan-tools learn promote --pattern <id> --scope universal --topic <name> --summary <text> --rule <text>` appends a pattern to the topic file (creates the file if absent); `--evidence`, `--applies-in` and `--source-experiments` fill in the rest of the entry.
|
|
50
|
+
2. **Unpromote** — `pan-tools learn unpromote --pattern <id> --scope <universal|internal> --topic <name>` removes a pattern (for rollback) and deletes the topic file once it holds none.
|
|
51
51
|
3. **List** — `pan-tools learn list-promoted` shows the inventory across both tiers.
|
|
52
|
+
4. **Index** — `pan-tools learn build-index` regenerates `index.json`, the topic index `pan-tools learn topics-for --agent <name>` reads; promote and unpromote do not update it.
|
|
52
53
|
|
|
53
54
|
## Why two tiers
|
|
54
55
|
|
|
@@ -58,13 +59,15 @@ apply when the project *is* PAN. Examples:
|
|
|
58
59
|
- **PAN-internal**: "Always commit individually, never `git add -A`" (because of source repo's pre-commit hooks)
|
|
59
60
|
- **Universal**: "Run the full test suite before marking a phase complete"
|
|
60
61
|
|
|
61
|
-
The promote step
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
The promote step warns when a universal-scope pattern reads like a prompt
|
|
63
|
+
fragment rather than a structural pattern (P-RES-007), and `pan-tools learn lint`
|
|
64
|
+
warns when a universal pattern's heading or Rule names PAN-internal terms such as
|
|
65
|
+
`pan-wizard-core` or `pan-tools`, a candidate for `internal` scope. The human
|
|
66
|
+
running `promote` makes the final call.
|
|
64
67
|
|
|
65
68
|
## Maintenance
|
|
66
69
|
|
|
67
70
|
These files are **AI-managed**. Direct human edits create drift between
|
|
68
|
-
the frontmatter `
|
|
71
|
+
the frontmatter `patterns` list and the body content. For human-authored
|
|
69
72
|
behavioral content, use `references/` instead — that's the canonical
|
|
70
73
|
hand-authored channel (e.g., `references/guardrails.md` shipped in v3.6.0).
|
|
@@ -69,6 +69,8 @@ const RESOURCES = [
|
|
|
69
69
|
description: 'Doc↔code link graph verdict: forward links, backlink contracts, and anchor targets, with finding codes.' },
|
|
70
70
|
{ uri: 'pan://cost', name: 'Token cost', verb: 'cost', args: ['report'],
|
|
71
71
|
description: 'Aggregated token spend from the .planning/metrics ledger. Reads as zeros on a project with no recorded calls.' },
|
|
72
|
+
{ uri: 'pan://findings', name: 'Findings', verb: 'findings', args: ['list'],
|
|
73
|
+
description: 'Every finding PAN\'s judges recorded (verifier, plan checker, reviewer, design checker), with its folded status — open, fixed, deferred, dismissed or decision — and the reason given. Reads as an empty list on a project with no recorded verdicts.' },
|
|
72
74
|
];
|
|
73
75
|
|
|
74
76
|
/** Actionable pan-tools verbs → MCP tools (each spawns `node pan-tools.cjs <verb>`). */
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# The `pan-verdict` block
|
|
2
|
+
|
|
3
|
+
A judging agent ends its report with one fenced `pan-verdict` block. The block is the machine-readable form of the verdict the report already gives in prose. The orchestrator records it with `pan-tools findings record`, and that record is what the workflow branches on. It also feeds the findings ledger that milestone audits read for tech debt. The prose stays for people, and the block states the same verdict for code.
|
|
4
|
+
|
|
5
|
+
## Rules
|
|
6
|
+
|
|
7
|
+
1. **Place it last.** The block is the final element of your return. When a report holds more than one block, the recorder reads the last one.
|
|
8
|
+
2. **Valid JSON only.** No comments and no trailing commas. One line or pretty-printed are both fine.
|
|
9
|
+
3. **Same verdict as the prose.** `verdict` is the word your report already uses, and `outcome` is what that word means (see the table below). The block never disagrees with the report.
|
|
10
|
+
4. **One finding per issue.** List the findings the report lists, each as its own entry, most severe first. A clean pass has `"findings": []`.
|
|
11
|
+
5. **Plain summaries.** State each finding in one sentence of 300 characters or fewer. Put the location in `where`, not in `summary`.
|
|
12
|
+
|
|
13
|
+
````markdown
|
|
14
|
+
```pan-verdict
|
|
15
|
+
{"contract":"1.0","agent":"pan-reviewer","phase":"03","verdict":"NEEDS_FIXES","outcome":"fail","findings":[{"class":"defect","severity":"high","where":"src/utils/parser.ts:42","summary":"parse() drops the final token of every line"}]}
|
|
16
|
+
```
|
|
17
|
+
````
|
|
18
|
+
|
|
19
|
+
## Fields
|
|
20
|
+
|
|
21
|
+
| Field | Required | Value |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| `contract` | yes | `"1.0"` |
|
|
24
|
+
| `agent` | yes | your agent name, e.g. `pan-reviewer` |
|
|
25
|
+
| `phase` | when you know it | the phase number you were asked about, e.g. `"03"` |
|
|
26
|
+
| `verdict` | yes | your own verdict word (table below) |
|
|
27
|
+
| `outcome` | yes | `pass`, `fail` or `needs_human` |
|
|
28
|
+
| `findings` | yes (may be empty) | a list of `{class, severity, where, summary}` |
|
|
29
|
+
|
|
30
|
+
| Agent | `verdict` → `outcome` |
|
|
31
|
+
|---|---|
|
|
32
|
+
| pan-plan-checker | `passed` → `pass` · `issues_found` → `fail` |
|
|
33
|
+
| pan-reviewer | `PASS` → `pass` · `PASS_WITH_WARNINGS` → `pass` · `NEEDS_FIXES` → `fail` |
|
|
34
|
+
| pan-design-checker | `PASS` → `pass` · `GAPS` → `fail` |
|
|
35
|
+
|
|
36
|
+
The verifier does not emit this block. Its verification.md frontmatter (`status`, `gaps`, `human_verification`, `unrequested`) is its machine contract, and the recorder reads that directly.
|
|
37
|
+
|
|
38
|
+
## `class`: what kind of finding
|
|
39
|
+
|
|
40
|
+
| Class | Use when |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `missing` | Something required is absent: a requirement with no task, a must-have not built, an unplanned key link |
|
|
43
|
+
| `partial` | Present but incomplete: a task missing its verify/done fields, a stub, a half-derived criterion |
|
|
44
|
+
| `contradicts` | It conflicts with a requirement, a locked decision (context.md) or the codebase's established architecture |
|
|
45
|
+
| `unrequested` | Work, a file or a behaviour that no plan or requirement asked for (scope creep) |
|
|
46
|
+
| `defect` | Incorrect behaviour or a code error; a broken dependency order in a plan |
|
|
47
|
+
| `risk` | A security, reliability or scale exposure; a plan whose scope will not fit its budget |
|
|
48
|
+
| `quality` | Convention, naming, style or maintainability, with no correctness impact |
|
|
49
|
+
| `human` | Cannot be settled by a check, so a person must look |
|
|
50
|
+
|
|
51
|
+
## `severity`: how much it matters
|
|
52
|
+
|
|
53
|
+
`critical` · `high` · `medium` · `low` · `info`. This is the same ladder `/pan:review-deep` uses.
|
|
54
|
+
|
|
55
|
+
## Mapping for each judge
|
|
56
|
+
|
|
57
|
+
**pan-plan-checker.**
|
|
58
|
+
- Classes by dimension:
|
|
59
|
+
- Requirement coverage, key links, test coverage, Nyquist → `missing`
|
|
60
|
+
- Task completeness, verification derivation, spec sufficiency, decision trace → `partial`
|
|
61
|
+
- Dependency correctness → `defect`
|
|
62
|
+
- Scope sanity → `risk`
|
|
63
|
+
- Context compliance → `contradicts`
|
|
64
|
+
- Standards → `quality`
|
|
65
|
+
- Severity: blocker → `high`, warning → `medium`, info → `info`.
|
|
66
|
+
- `where`: `NN-MM-plan.md` or `NN-MM-plan.md#task-N`.
|
|
67
|
+
|
|
68
|
+
**pan-reviewer.**
|
|
69
|
+
- Classes by category: Convention → `quality`, Security → `risk`, Code Quality → `defect`, work no plan asked for → `unrequested`.
|
|
70
|
+
- Severity: ERROR → `high`, WARNING → `medium`, INFO → `info`.
|
|
71
|
+
- `where`: `path:line`.
|
|
72
|
+
|
|
73
|
+
**pan-design-checker.**
|
|
74
|
+
- Classes by dimension:
|
|
75
|
+
- Requirement coverage → `missing`
|
|
76
|
+
- Architecture conformance → `contradicts`
|
|
77
|
+
- Threat coverage → `risk`
|
|
78
|
+
- Scope discipline → `unrequested`
|
|
79
|
+
- Every other dimension → `partial`
|
|
80
|
+
- Severity: each gap is `high`. A gap you report as a caveat on the final iteration is `medium`.
|
|
81
|
+
- `where`: the design section, e.g. `03-design.md#interfaces`.
|
|
82
|
+
|
|
83
|
+
## Examples
|
|
84
|
+
|
|
85
|
+
A plan check that passes:
|
|
86
|
+
|
|
87
|
+
````markdown
|
|
88
|
+
```pan-verdict
|
|
89
|
+
{"contract":"1.0","agent":"pan-plan-checker","phase":"05","verdict":"passed","outcome":"pass","findings":[]}
|
|
90
|
+
```
|
|
91
|
+
````
|
|
92
|
+
|
|
93
|
+
A design check with two gaps:
|
|
94
|
+
|
|
95
|
+
````markdown
|
|
96
|
+
```pan-verdict
|
|
97
|
+
{"contract":"1.0","agent":"pan-design-checker","phase":"05","verdict":"GAPS","outcome":"fail","findings":[
|
|
98
|
+
{"class":"missing","severity":"high","where":"05-design.md#requirements","summary":"REQ-12 (export to CSV) maps to no design element"},
|
|
99
|
+
{"class":"risk","severity":"high","where":"05-design.md#threats","summary":"the upload endpoint accepts any file type and no threat entry covers it"}]}
|
|
100
|
+
```
|
|
101
|
+
````
|
|
@@ -12,6 +12,9 @@ phase: XX-name
|
|
|
12
12
|
verified: YYYY-MM-DDTHH:MM:SSZ
|
|
13
13
|
status: passed | gaps_found | human_needed
|
|
14
14
|
score: N/M must-haves verified
|
|
15
|
+
unrequested: # Only when the scope check (`pan-tools verify scope <phase>`) found work no plan asked for
|
|
16
|
+
- path: "src/admin/panel.tsx"
|
|
17
|
+
what: "An admin panel no plan or requirement asked for"
|
|
15
18
|
---
|
|
16
19
|
|
|
17
20
|
# Phase {X}: {Name} Verification Report
|
|
@@ -89,6 +92,19 @@ None — all verifiable items checked programmatically.
|
|
|
89
92
|
**Expected:** {What should happen}
|
|
90
93
|
**Why human:** {Why can't verify programmatically}
|
|
91
94
|
|
|
95
|
+
## Unrequested Work
|
|
96
|
+
|
|
97
|
+
{If the scope check found none:}
|
|
98
|
+
None: every change traces to a plan.
|
|
99
|
+
|
|
100
|
+
{Otherwise, one row per `unrequested:` entry:}
|
|
101
|
+
|
|
102
|
+
| File | What it adds | Why no plan covers it |
|
|
103
|
+
|------|--------------|-----------------------|
|
|
104
|
+
| src/admin/panel.tsx | An admin panel | No requirement mentions admin tooling |
|
|
105
|
+
|
|
106
|
+
Unrequested work is recorded, not blocking: the status does not change because of it.
|
|
107
|
+
|
|
92
108
|
## Gaps Summary
|
|
93
109
|
|
|
94
110
|
{If no gaps:}
|
|
@@ -425,13 +425,21 @@ Task(
|
|
|
425
425
|
)
|
|
426
426
|
```
|
|
427
427
|
|
|
428
|
-
3.
|
|
428
|
+
3. **Save the report.** Use the Write tool to write the reviewer's returned text, verbatim and in full (including its closing `pan-verdict` block), to `{phase_dir}/{phase_number}-review.md`. The reviewer is read-only by design, so the orchestrator saves the report. `/pan:review-deep` and the findings ledger read this file.
|
|
429
|
+
|
|
430
|
+
4. **Record the verdict, then act on it.** The record is what this step branches on. It also adds the findings to the ledger (`.planning/findings.jsonl`) and logs the verdict to the trace, so no separate trace call is needed:
|
|
431
|
+
```bash
|
|
432
|
+
REVIEW_FILE="{phase_dir}/{phase_number}-review.md"
|
|
433
|
+
REVIEW_VERDICT=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings record --phase "${PHASE_NUMBER}" --agent pan-reviewer --file "$REVIEW_FILE" --raw 2>/dev/null) \
|
|
434
|
+
|| REVIEW_VERDICT=$(grep -A1 '^### Verdict' "$REVIEW_FILE" | tail -1 | tr -d ' ')
|
|
435
|
+
```
|
|
436
|
+
The fallback reads the word under `### Verdict` when the report carries no valid `pan-verdict` block.
|
|
429
437
|
|
|
430
438
|
| Verdict | Action |
|
|
431
439
|
|---------|--------|
|
|
432
440
|
| `PASS` | Continue to verification |
|
|
433
|
-
| `PASS_WITH_WARNINGS` | Report warnings, continue to verification |
|
|
434
|
-
| `NEEDS_FIXES` | Present ERROR findings to user: "Fix before verification?" or "Continue anyway?" |
|
|
441
|
+
| `PASS_WITH_WARNINGS` | Report the warnings, then record that the phase continues past them (below), and continue to verification |
|
|
442
|
+
| `NEEDS_FIXES` | Present the ERROR findings to the user: "Fix before verification?" or "Continue anyway?" |
|
|
435
443
|
|
|
436
444
|
```
|
|
437
445
|
## Code Review Results
|
|
@@ -442,34 +450,60 @@ Task(
|
|
|
442
450
|
{If errors: list top 5 with file:line}
|
|
443
451
|
```
|
|
444
452
|
|
|
445
|
-
**
|
|
453
|
+
**Never continue past findings silently.** Whenever the phase moves on with review findings still open, record why. The reason is what a milestone audit later reports as tech debt:
|
|
454
|
+
- `PASS_WITH_WARNINGS`:
|
|
455
|
+
```bash
|
|
456
|
+
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"
|
|
457
|
+
```
|
|
458
|
+
- **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.
|
|
459
|
+
- **The user chooses "Fix before verification"**: apply the fixes, then run the review once more (steps 2–4). The new record closes the findings it no longer reports.
|
|
446
460
|
|
|
447
|
-
|
|
461
|
+
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.
|
|
448
462
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
463
|
+
6. **Deep review — only when `--deep-review` is in $ARGUMENTS.** The security pass and cross-check that `/pan:review-deep` runs, done inline right after the normal review. If the normal review was skipped (`--skip-review` or `--fast`), say that `--deep-review` needs the review it builds on, and continue without it.
|
|
464
|
+
|
|
465
|
+
a. Spawn the hardener. Its output path is `.planning/reviews/${PHASE_NUMBER}/hardener.md`:
|
|
466
|
+
```
|
|
467
|
+
Task(
|
|
468
|
+
subagent_type="pan-hardener",
|
|
469
|
+
model="$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs resolve-model pan-hardener --raw)",
|
|
470
|
+
prompt="
|
|
471
|
+
<files_to_read>
|
|
472
|
+
- {phase_dir}/{phase_number}-review.md (the first-pass review)
|
|
473
|
+
- the phase plans: {phase_dir}/*-plan.md
|
|
474
|
+
Changed files to audit:
|
|
475
|
+
${CHANGED_FILES_LIST}
|
|
476
|
+
</files_to_read>
|
|
477
|
+
<output_path>.planning/reviews/${PHASE_NUMBER}/hardener.md</output_path>
|
|
478
|
+
<framework_scope>OWASP Top 10 (2025) and STRIDE, across every changed file.</framework_scope>
|
|
479
|
+
"
|
|
480
|
+
)
|
|
460
481
|
```
|
|
461
482
|
|
|
462
|
-
|
|
463
|
-
```bash
|
|
464
|
-
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize trace log \
|
|
465
|
-
--type decision --category reviewer_warnings \
|
|
466
|
-
--description "Phase ${PHASE_NUMBER} reviewer: PASS_WITH_WARNINGS — warnings present" \
|
|
467
|
-
--agent pan-reviewer --impact trivial \
|
|
468
|
-
--context "{\"phase\":\"${PHASE_NUMBER}\",\"verdict\":\"PASS_WITH_WARNINGS\"}" \
|
|
469
|
-
2>/dev/null || true
|
|
483
|
+
b. Spawn the meta-reviewer on both first-pass reports. Its output path is `.planning/reviews/${PHASE_NUMBER}/meta.md`:
|
|
470
484
|
```
|
|
485
|
+
Task(
|
|
486
|
+
subagent_type="pan-meta-reviewer",
|
|
487
|
+
model="$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs resolve-model pan-meta-reviewer --raw)",
|
|
488
|
+
prompt="
|
|
489
|
+
<files_to_read>
|
|
490
|
+
- {phase_dir}/{phase_number}-review.md
|
|
491
|
+
- .planning/reviews/${PHASE_NUMBER}/hardener.md
|
|
492
|
+
</files_to_read>
|
|
493
|
+
<output_path>.planning/reviews/${PHASE_NUMBER}/meta.md</output_path>
|
|
494
|
+
"
|
|
495
|
+
)
|
|
496
|
+
```
|
|
497
|
+
If either agent returns its report instead of writing the output path, save the returned text there with the Write tool before the merge.
|
|
471
498
|
|
|
472
|
-
|
|
499
|
+
c. Merge the three reports:
|
|
500
|
+
```bash
|
|
501
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs review-deep merge "${PHASE_NUMBER}" \
|
|
502
|
+
--reviewer-file "{phase_dir}/{phase_number}-review.md" \
|
|
503
|
+
--hardener-file ".planning/reviews/${PHASE_NUMBER}/hardener.md" \
|
|
504
|
+
--meta-file ".planning/reviews/${PHASE_NUMBER}/meta.md"
|
|
505
|
+
```
|
|
506
|
+
This writes `.planning/reviews/${PHASE_NUMBER}/deep-review.md` and prints its verdict (`ok` · `ok_with_minor` · `fix_before_merge` · `review_required` · `block`). Report the verdict and the finding count. On `review_required` or `block`, stop before verification and present the high and critical findings to the user, as with `NEEDS_FIXES`.
|
|
473
507
|
</step>
|
|
474
508
|
|
|
475
509
|
<step name="close_parent_artifacts">
|
|
@@ -539,31 +573,15 @@ Create verification.md.",
|
|
|
539
573
|
)
|
|
540
574
|
```
|
|
541
575
|
|
|
542
|
-
|
|
576
|
+
Record the verification and read its status:
|
|
543
577
|
```bash
|
|
544
|
-
|
|
578
|
+
VERIF_FILE=$(ls "$PHASE_DIR"/*-verification.md 2>/dev/null | head -1)
|
|
579
|
+
VERIF_STATUS=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings record --phase "${PHASE_NUMBER}" --file "$VERIF_FILE" --raw 2>/dev/null) \
|
|
580
|
+
|| VERIF_STATUS=$(grep "^status:" "$VERIF_FILE" | cut -d: -f2 | tr -d ' ')
|
|
545
581
|
```
|
|
582
|
+
`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 no longer reports are closed, 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.
|
|
546
583
|
|
|
547
|
-
**
|
|
548
|
-
|
|
549
|
-
```bash
|
|
550
|
-
if [ "$VERIF_STATUS" = "passed" ]; then
|
|
551
|
-
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize trace log \
|
|
552
|
-
--type decision --category verification_passed \
|
|
553
|
-
--description "Phase ${PHASE_NUMBER} verification passed (logged from exec-phase, P-1806)" \
|
|
554
|
-
--agent pan-verifier --impact minor 2>/dev/null || true
|
|
555
|
-
elif [ "$VERIF_STATUS" = "gaps_found" ]; then
|
|
556
|
-
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize trace log \
|
|
557
|
-
--type error --category verification_gaps \
|
|
558
|
-
--description "Phase ${PHASE_NUMBER} verification found gaps" \
|
|
559
|
-
--agent pan-verifier --impact major 2>/dev/null || true
|
|
560
|
-
elif [ "$VERIF_STATUS" = "human_needed" ]; then
|
|
561
|
-
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize trace log \
|
|
562
|
-
--type decision --category verification_human_needed \
|
|
563
|
-
--description "Phase ${PHASE_NUMBER} verification awaiting human review" \
|
|
564
|
-
--agent pan-verifier --impact minor 2>/dev/null || true
|
|
565
|
-
fi
|
|
566
|
-
```
|
|
584
|
+
**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.
|
|
567
585
|
|
|
568
586
|
| Status | Action |
|
|
569
587
|
|--------|--------|
|
|
@@ -163,6 +163,8 @@ Report final status.
|
|
|
163
163
|
| I001 | info | Plan without SUMMARY (may be in progress) | No |
|
|
164
164
|
| I002 | info | Phase in ROADMAP ahead of current phase, not planned yet | No |
|
|
165
165
|
| I003 | info | Focus-model or campaign tree — the phase-model checks do not apply | No |
|
|
166
|
+
| I004 | info | planning-with-files shares the tree — PAN leaves its files alone | No |
|
|
167
|
+
| I005 | info | The planning tree is gitignored while commit_docs is true — planning commits commit nothing | No |
|
|
166
168
|
| STATE_REQ_DRIFT | warning | state.md complete but REQUIREMENTS.md has unchecked boxes | Yes |
|
|
167
169
|
| STATE_ROADMAP_DRIFT | warning | state.md complete but roadmap.md has unchecked plan boxes | Yes |
|
|
168
170
|
| VERIFICATION_GATE_MISSING | warning | Phase has completed plans but no verification record | No |
|
|
@@ -31,10 +31,10 @@ If `--session <id>` was specified, use that session ID.
|
|
|
31
31
|
|
|
32
32
|
Run:
|
|
33
33
|
```
|
|
34
|
-
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize learn [--session <id>]
|
|
34
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize learn [--session <id> | --sessions <n>]
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
This produces `.planning/optimization/reports/{session}-analysis.json`.
|
|
37
|
+
This produces `.planning/optimization/reports/{session}-analysis.json`. With `--sessions <n>` it pools the last n sessions into `pooled-<n>-{session}-analysis.json`: a recommendation should explain failures that recur across runs, not one run's accident.
|
|
38
38
|
|
|
39
39
|
Read the output and note:
|
|
40
40
|
- `summary.errors` — how many error events
|
|
@@ -42,6 +42,8 @@ Read the output and note:
|
|
|
42
42
|
- `summary.memory_misses` — how many memory miss events
|
|
43
43
|
- `summary.wasted_tokens` — tokens wasted on redundancies
|
|
44
44
|
- `top_error_patterns` — most frequent error categories
|
|
45
|
+
- `top_tool_error_patterns` — failed tool calls captured from the subagents' own transcripts, ranked by how many spawns hit them
|
|
46
|
+
- `verdict_stats` — each judge's pass/fail counts, retries, and the retries that resolved a failure
|
|
45
47
|
- `top_memory_misses` — most frequent memory miss topics
|
|
46
48
|
|
|
47
49
|
## Step 3 — Invoke pan-optimizer agent
|
|
@@ -82,6 +82,18 @@ From each verification.md, extract:
|
|
|
82
82
|
|
|
83
83
|
If a phase is missing verification.md, flag it as "unverified phase" — this is a blocker.
|
|
84
84
|
|
|
85
|
+
### 2b. Read the Recorded Findings
|
|
86
|
+
|
|
87
|
+
What the judges found in this milestone, and what was decided about each finding, is on record. Read it rather than reconstructing it from prose:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings debt --milestone "{version}"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- **`deferred`** findings were continued past on purpose, and each carries the reason recorded at the time. They are the milestone's tech debt: put every one in `tech_debt`, with its id and reason.
|
|
94
|
+
- **`open`** findings were never disposed (no fix, deferral, dismissal or decision). List them under "Undisposed findings" in the report. They are not blockers by themselves: the verification gate handles blockers. They do mean the milestone cannot be `passed`, so the status is at least `tech_debt`.
|
|
95
|
+
- A dismissal or decision is settled and not debt. `findings list --milestone "{version}" --status dismissed` shows the dismissals and their reasons when the report needs them.
|
|
96
|
+
|
|
85
97
|
## 3. Spawn Integration Checker
|
|
86
98
|
|
|
87
99
|
With phase context collected:
|
|
@@ -181,11 +193,11 @@ gaps: # Critical blockers
|
|
|
181
193
|
evidence: "{specific evidence or lack thereof}"
|
|
182
194
|
integration: [...]
|
|
183
195
|
flows: [...]
|
|
184
|
-
tech_debt: # Non-critical, deferred
|
|
196
|
+
tech_debt: # Non-critical, deferred — from `findings debt` (step 2b) plus anything the verifications list
|
|
185
197
|
- phase: 01-auth
|
|
186
198
|
items:
|
|
199
|
+
- "[f_81ab3c9d20] no password strength validation — deferred: accepted at review: PASS_WITH_WARNINGS"
|
|
187
200
|
- "TODO: add rate limiting"
|
|
188
|
-
- "Warning: no password strength validation"
|
|
189
201
|
- phase: 03-dashboard
|
|
190
202
|
items:
|
|
191
203
|
- "Deferred: mobile responsive layout"
|
|
@@ -197,7 +209,7 @@ Plus full markdown report with tables for requirements, phases, integration, tec
|
|
|
197
209
|
**Status values:**
|
|
198
210
|
- `passed` — all requirements met, no critical gaps, minimal tech debt
|
|
199
211
|
- `gaps_found` — critical blockers exist
|
|
200
|
-
- `tech_debt` — no blockers but accumulated deferred items need review
|
|
212
|
+
- `tech_debt` — no blockers but accumulated deferred items need review, or recorded findings were never disposed
|
|
201
213
|
|
|
202
214
|
## 7. Present Results
|
|
203
215
|
|
|
@@ -8,6 +8,7 @@ Manage the circular optimization loop — apply reports, check stats, control tr
|
|
|
8
8
|
|------------|--------|
|
|
9
9
|
| `apply` | Apply safe recommendations from most recent report |
|
|
10
10
|
| `apply --report <file>` | Apply from a specific report |
|
|
11
|
+
| `revert <apply_id>` / `revert --last` | Undo one apply exactly |
|
|
11
12
|
| `list` | List all reports |
|
|
12
13
|
| `stats` | Show cumulative stats |
|
|
13
14
|
| `trace init` | Start a new trace session |
|
|
@@ -40,8 +41,9 @@ node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize apply [--report <path>
|
|
|
40
41
|
|
|
41
42
|
Show the user:
|
|
42
43
|
- **Applied** — each item that was written (memory entries, notes)
|
|
43
|
-
- **Skipped** — items that already exist or had unknown types
|
|
44
|
+
- **Skipped** — items that already exist, that an earlier apply already wrote, or that had unknown types
|
|
44
45
|
- **Still needs review** — prompt/workflow suggestions in `suggestions.md`
|
|
46
|
+
- **The `apply_id`**, and how to undo the apply: `/pan:optimize revert <apply_id>`
|
|
45
47
|
|
|
46
48
|
If memory entries were written, tell the user:
|
|
47
49
|
> Memory entries have been added to `.planning/memory/`. They will be loaded on the next agent run, reducing future memory misses for these topics.
|
|
@@ -54,6 +56,17 @@ If `.planning/optimization/suggestions.md` exists, tell the user to review it fo
|
|
|
54
56
|
|
|
55
57
|
---
|
|
56
58
|
|
|
59
|
+
## revert
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize revert <apply_id>
|
|
63
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize revert --last
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Show the user each reverted action and each refused one, with its reason. A refusal means someone edited the file after the apply, or a later apply also wrote it. Revert that later apply first; never force it. The status is `reverted`, `partial`, `refused` or `nothing_to_revert`.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
57
70
|
## trace init
|
|
58
71
|
|
|
59
72
|
### Step 1 — Extract description
|
|
@@ -222,7 +222,7 @@ In that case, log a `decision` trace event (`type: "decision", category: "skip-r
|
|
|
222
222
|
|
|
223
223
|
This is a workflow-level optimization — the planner still produces a plan, just without per-phase research.md. Phase 2+ phases with substantive build work still go through full research.
|
|
224
224
|
|
|
225
|
-
**P-1602 phase_record_compact (v3.7.5+):** When `workflow.phase_record_compact: true` AND the lightweight-phase bypass above triggers, also skip per-phase context.md creation (step 4) and emit a single combined `${PHASE_NUM}-record.md` after planning containing: goal, locked decisions (from project-level context), plan summary, must_haves. Reduces
|
|
225
|
+
**P-1602 phase_record_compact (v3.7.5+):** When `workflow.phase_record_compact: true` AND the lightweight-phase bypass above triggers, also skip per-phase context.md creation (step 4) and emit a single combined `${PHASE_NUM}-record.md` after planning containing: goal, locked decisions (from project-level context), plan summary, must_haves. Reduces the planning output (context, research, plan) to a record and a plan for trivial phases; execution still writes the plan's summary. Off by default — opt-in via `pan-tools config-set workflow.phase_record_compact true`. Substantive phases (>1 plan or non-trivial change_class) still produce full per-phase artifacts regardless of this flag.
|
|
226
226
|
|
|
227
227
|
**If `has_research` is true (from init) AND no `--research` flag:** Use existing, skip to step 6.
|
|
228
228
|
|
|
@@ -448,20 +448,20 @@ Task(
|
|
|
448
448
|
|
|
449
449
|
## 11. Handle Checker Return
|
|
450
450
|
|
|
451
|
-
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
451
|
+
Save the checker's returned text, verbatim and in full (including its closing `pan-verdict` block), to `{phase_dir}/{padded_phase}-plan-check.md` with the Write tool. Then record it, and branch on the record. The record also adds the issues to the findings ledger and logs the check to the trace; there is no separate trace call:
|
|
452
|
+
|
|
453
|
+
```bash
|
|
454
|
+
CHECK_FILE="{phase_dir}/{padded_phase}-plan-check.md"
|
|
455
|
+
CHECK_VERDICT=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings record --phase "${PHASE_NUMBER}" --agent pan-plan-checker --file "$CHECK_FILE" --raw 2>/dev/null) \
|
|
456
|
+
|| CHECK_VERDICT=$(grep -q '^## VERIFICATION PASSED' "$CHECK_FILE" && echo passed || echo issues_found)
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
The fallback reads the heading when the report carries no valid `pan-verdict` block.
|
|
460
|
+
|
|
461
|
+
- **`passed`:** Display confirmation, proceed to step 13.
|
|
462
|
+
- **`issues_found`:** Display issues, check iteration count, proceed to step 12.
|
|
463
|
+
|
|
464
|
+
Each re-check in the revision loop overwrites the same file and is recorded again as the next attempt. The issues a revision resolved are closed by that record.
|
|
465
465
|
|
|
466
466
|
## 12. Revision Loop (Max 3 Iterations)
|
|
467
467
|
|
|
@@ -510,6 +510,11 @@ Display: `Max iterations reached. {N} issues remain:` + issue list
|
|
|
510
510
|
|
|
511
511
|
Offer: 1) Force proceed, 2) Provide guidance and retry, 3) Abandon
|
|
512
512
|
|
|
513
|
+
**On "Force proceed":** record that planning continues past the remaining issues. Execution and the milestone audit will see them as deferred, with this reason:
|
|
514
|
+
```bash
|
|
515
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings dispose --phase "${PHASE_NUMBER}" --agent pan-plan-checker --open --as deferred --reason "force proceed after 3 plan revision iterations"
|
|
516
|
+
```
|
|
517
|
+
|
|
513
518
|
## 13. Present Final Status
|
|
514
519
|
|
|
515
520
|
**Sync state.md first** — without this, state.md says "Ready to plan" until the
|