pan-wizard 2.9.1 → 3.5.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 (75) hide show
  1. package/README.md +31 -9
  2. package/agents/pan-conductor.md +189 -0
  3. package/agents/pan-counterfactual.md +112 -0
  4. package/agents/pan-debugger.md +15 -1
  5. package/agents/pan-distiller.md +82 -0
  6. package/agents/pan-document_code.md +21 -0
  7. package/agents/pan-executor.md +16 -0
  8. package/agents/pan-hardener.md +113 -0
  9. package/agents/pan-integration-checker.md +2 -0
  10. package/agents/pan-knowledge.md +81 -0
  11. package/agents/pan-meta-reviewer.md +91 -0
  12. package/agents/pan-optimizer.md +242 -0
  13. package/agents/pan-plan-checker.md +2 -0
  14. package/agents/pan-previewer.md +98 -0
  15. package/agents/pan-project-researcher.md +4 -4
  16. package/agents/pan-reviewer.md +2 -0
  17. package/agents/pan-verifier.md +2 -0
  18. package/bin/install-lib.cjs +197 -0
  19. package/bin/install.js +2048 -1959
  20. package/commands/pan/cost.md +132 -0
  21. package/commands/pan/exec-phase.md +15 -0
  22. package/commands/pan/focus-auto.md +168 -3
  23. package/commands/pan/focus-exec.md +21 -1
  24. package/commands/pan/focus-scan.md +6 -0
  25. package/commands/pan/git.md +223 -0
  26. package/commands/pan/knowledge.md +129 -0
  27. package/commands/pan/learn.md +61 -0
  28. package/commands/pan/map-codebase.md +15 -0
  29. package/commands/pan/mcp-bridge.md +145 -0
  30. package/commands/pan/milestone-done.md +9 -0
  31. package/commands/pan/optimize.md +86 -0
  32. package/commands/pan/plan-phase.md +11 -0
  33. package/commands/pan/preview.md +114 -0
  34. package/commands/pan/profile.md +37 -0
  35. package/commands/pan/review-deep.md +128 -0
  36. package/commands/pan/verify-phase.md +11 -0
  37. package/commands/pan/what-if.md +146 -0
  38. package/hooks/dist/pan-cost-logger.js +102 -0
  39. package/hooks/dist/pan-statusline.js +154 -108
  40. package/hooks/dist/pan-trace-logger.js +197 -0
  41. package/package.json +1 -1
  42. package/pan-wizard-core/bin/lib/bridge.cjs +269 -0
  43. package/pan-wizard-core/bin/lib/bus.cjs +251 -0
  44. package/pan-wizard-core/bin/lib/codebase.cjs +118 -0
  45. package/pan-wizard-core/bin/lib/commands.cjs +1 -0
  46. package/pan-wizard-core/bin/lib/constants.cjs +44 -1
  47. package/pan-wizard-core/bin/lib/context-budget.cjs +27 -0
  48. package/pan-wizard-core/bin/lib/core.cjs +91 -6
  49. package/pan-wizard-core/bin/lib/cost.cjs +359 -0
  50. package/pan-wizard-core/bin/lib/distill.cjs +510 -0
  51. package/pan-wizard-core/bin/lib/focus.cjs +108 -3
  52. package/pan-wizard-core/bin/lib/git.cjs +407 -0
  53. package/pan-wizard-core/bin/lib/init.cjs +5 -5
  54. package/pan-wizard-core/bin/lib/knowledge.cjs +331 -0
  55. package/pan-wizard-core/bin/lib/memory.cjs +252 -0
  56. package/pan-wizard-core/bin/lib/optimize.cjs +653 -0
  57. package/pan-wizard-core/bin/lib/phase.cjs +40 -13
  58. package/pan-wizard-core/bin/lib/preview.cjs +480 -0
  59. package/pan-wizard-core/bin/lib/review-deep.cjs +280 -0
  60. package/pan-wizard-core/bin/lib/roadmap.cjs +4 -4
  61. package/pan-wizard-core/bin/lib/state.cjs +2 -2
  62. package/pan-wizard-core/bin/lib/verify.cjs +34 -1
  63. package/pan-wizard-core/bin/lib/whatif.cjs +289 -0
  64. package/pan-wizard-core/bin/pan-tools.cjs +317 -4
  65. package/pan-wizard-core/templates/playbook.md +53 -0
  66. package/pan-wizard-core/templates/preview-report.md +93 -0
  67. package/pan-wizard-core/templates/roadmap.md +24 -24
  68. package/pan-wizard-core/templates/state.md +12 -9
  69. package/pan-wizard-core/workflows/exec-phase.md +97 -0
  70. package/pan-wizard-core/workflows/learn.md +91 -0
  71. package/pan-wizard-core/workflows/optimize.md +139 -0
  72. package/pan-wizard-core/workflows/plan-phase.md +28 -1
  73. package/pan-wizard-core/workflows/quick.md +7 -0
  74. package/pan-wizard-core/workflows/verify-phase.md +16 -0
  75. package/scripts/build-hooks.js +3 -1
@@ -164,11 +164,27 @@
164
164
  * standards recommend Recommend standards based on project.md
165
165
  * standards phase-track <phase> Show standards relevant to a phase
166
166
  * standards tools [id] List external scanning tools for standards
167
+ *
168
+ * Circular Optimization Loop:
169
+ * optimize trace init Start a new trace session
170
+ * [--description "..."]
171
+ * optimize trace end Finalize trace session + write summary
172
+ * optimize trace current Show active session ID
173
+ * optimize trace list List all sessions
174
+ * optimize trace log Log a trace event to the active session
175
+ * --type <type> --description "..." [--agent a] [--category c] [--impact i]
176
+ * optimize learn [--session <id>] Analyze session, write analysis JSON
177
+ * optimize apply [--report <path>] Apply safe recommendations from report
178
+ * optimize list List optimization reports
179
+ * optimize stats Cumulative optimization statistics
180
+ *
181
+ * Self-Learn:
182
+ * learn [--session <id>] Alias for optimize learn + invoke pan-optimizer
167
183
  */
168
184
 
169
185
  const fs = require('fs');
170
186
  const path = require('path');
171
- const { error, output } = require('./lib/core.cjs');
187
+ const { error, output, buildCachedContext } = require('./lib/core.cjs');
172
188
  const state = require('./lib/state.cjs');
173
189
  const phase = require('./lib/phase.cjs');
174
190
  const roadmap = require('./lib/roadmap.cjs');
@@ -182,6 +198,17 @@ const frontmatter = require('./lib/frontmatter.cjs');
182
198
  const contextBudget = require('./lib/context-budget.cjs');
183
199
  const focus = require('./lib/focus.cjs');
184
200
  const codebase = require('./lib/codebase.cjs');
201
+ const memory = require('./lib/memory.cjs');
202
+ const bus = require('./lib/bus.cjs');
203
+ const cost = require('./lib/cost.cjs');
204
+ const preview = require('./lib/preview.cjs');
205
+ const reviewDeep = require('./lib/review-deep.cjs');
206
+ const knowledge = require('./lib/knowledge.cjs');
207
+ const whatif = require('./lib/whatif.cjs');
208
+ const bridge = require('./lib/bridge.cjs');
209
+ const optimize = require('./lib/optimize.cjs');
210
+ const git = require('./lib/git.cjs');
211
+ const distill = require('./lib/distill.cjs');
185
212
 
186
213
  /**
187
214
  * Get the value following a flag in the args array.
@@ -326,6 +353,20 @@ async function main() {
326
353
  break;
327
354
  }
328
355
 
356
+ case 'git': {
357
+ const subcommand = args[1];
358
+ if (!subcommand) { error('git subcommand required. Available: commit, branch, push, status, log, stash, diff, rollback, tag, sync'); }
359
+ git.cmdGit(cwd, subcommand, args.slice(1), raw);
360
+ break;
361
+ }
362
+
363
+ case 'distill': {
364
+ const subcommand = args[1];
365
+ if (!subcommand) { error('distill subcommand required. Available: scan, analyze, report'); }
366
+ distill.cmdDistill(cwd, subcommand, args.slice(1), raw);
367
+ break;
368
+ }
369
+
329
370
  case 'commit': {
330
371
  const amend = args.includes('--amend');
331
372
  const force = args.includes('--force');
@@ -684,8 +725,39 @@ async function main() {
684
725
  // design is a workflow-only command (no core function)
685
726
  // The AI reads commands/pan/focus-design.md directly
686
727
  output({ command: 'focus-design', type: 'workflow', message: 'Use /pan:focus-design to invoke the 10-phase investigation pipeline' }, raw);
728
+ } else if (subcommand === 'classify-stages') {
729
+ const useStdin = args.includes('--stdin');
730
+ let items;
731
+ if (useStdin) {
732
+ try {
733
+ items = JSON.parse(fs.readFileSync(0, 'utf-8'));
734
+ } catch (e) {
735
+ error(`Failed to parse stdin JSON: ${e.message}`);
736
+ }
737
+ } else {
738
+ const batch = focus.readLatestBatch(cwd);
739
+ if (!batch) {
740
+ output({ error: 'No batch file found. Run focus plan first.' }, raw);
741
+ break;
742
+ }
743
+ items = batch.batch || [];
744
+ }
745
+ output(focus.classifyStageDependencies(items), raw);
746
+ } else if (subcommand === 'reflection') {
747
+ let payload;
748
+ try {
749
+ payload = JSON.parse(fs.readFileSync(0, 'utf-8'));
750
+ } catch (e) {
751
+ error(`Failed to parse stdin JSON for focus reflection: ${e.message}`);
752
+ }
753
+ output(focus.determineContinuation(
754
+ payload.run || {},
755
+ payload.cycle || {},
756
+ payload.batch || [],
757
+ { tier: payload.tier }
758
+ ), raw);
687
759
  } else {
688
- error('Unknown focus subcommand. Available: scan, plan, sync, exec, auto, design');
760
+ error('Unknown focus subcommand. Available: scan, plan, sync, exec, auto, design, classify-stages, reflection');
689
761
  }
690
762
  break;
691
763
  }
@@ -733,8 +805,202 @@ async function main() {
733
805
  break;
734
806
  }
735
807
 
808
+ case 'memory': {
809
+ const subcommand = args[1];
810
+ if (subcommand === 'read') {
811
+ memory.cmdMemoryRead(cwd, args[2], raw);
812
+ } else if (subcommand === 'append') {
813
+ memory.cmdMemoryAppend(cwd, args[2], args.slice(3).join(' '), raw);
814
+ } else if (subcommand === 'list') {
815
+ memory.cmdMemoryList(cwd, raw);
816
+ } else if (subcommand === 'compact') {
817
+ memory.cmdMemoryCompact(cwd, args[2], args[3], raw);
818
+ } else {
819
+ error('Unknown memory subcommand. Available: read, append, list, compact');
820
+ }
821
+ break;
822
+ }
823
+
824
+ case 'bridge': {
825
+ const subcommand = args[1];
826
+ if (subcommand === 'list') {
827
+ bridge.cmdBridgeList(cwd, raw);
828
+ } else if (subcommand === 'recommend') {
829
+ bridge.cmdBridgeRecommend(cwd, args[2], {
830
+ max_recommendations: Number(getArgValue(args, '--max') || 10),
831
+ min_score: Number(getArgValue(args, '--min-score') || 1),
832
+ }, raw);
833
+ } else if (subcommand === 'cache') {
834
+ bridge.cmdBridgeCache(cwd, getArgValue(args, '--servers'), getArgValue(args, '--runtime'), raw);
835
+ } else {
836
+ error('Unknown bridge subcommand. Available: list, recommend, cache');
837
+ }
838
+ break;
839
+ }
840
+
841
+ case 'whatif': {
842
+ const subcommand = args[1];
843
+ if (subcommand === 'prepare') {
844
+ const phaseNum = args[2];
845
+ const scenario = args.slice(3).filter(a => !a.startsWith('--')).join(' ');
846
+ whatif.cmdWhatifPrepare(cwd, phaseNum, scenario, raw);
847
+ } else if (subcommand === 'report') {
848
+ const phaseNum = args[2];
849
+ const scenarioParts = [];
850
+ for (let i = 3; i < args.length; i++) {
851
+ if (args[i] === '--comparison') break;
852
+ scenarioParts.push(args[i]);
853
+ }
854
+ const scenario = scenarioParts.join(' ');
855
+ const comparisonJson = getArgValue(args, '--comparison');
856
+ whatif.cmdWhatifReport(cwd, phaseNum, scenario, comparisonJson, raw);
857
+ } else if (subcommand === 'cleanup') {
858
+ whatif.cmdWhatifCleanup(
859
+ cwd,
860
+ getArgValue(args, '--worktree'),
861
+ getArgValue(args, '--branch'),
862
+ args.includes('--force'),
863
+ raw
864
+ );
865
+ } else {
866
+ error('Unknown whatif subcommand. Available: prepare, report, cleanup');
867
+ }
868
+ break;
869
+ }
870
+
871
+ case 'knowledge': {
872
+ const subcommand = args[1];
873
+ if (subcommand === 'ask') {
874
+ const question = args.slice(2).filter(a => !a.startsWith('--')).join(' ');
875
+ const maxSources = getArgValue(args, '--max-sources');
876
+ knowledge.cmdKnowledgeAsk(cwd, question, {
877
+ max_sources: maxSources ? Number(maxSources) : undefined,
878
+ }, raw);
879
+ } else if (subcommand === 'discuss') {
880
+ const phaseNum = args[2];
881
+ knowledge.cmdKnowledgeDiscuss(cwd, phaseNum, {
882
+ subcmd: getArgValue(args, '--subcmd'),
883
+ role: getArgValue(args, '--role'),
884
+ content: getArgValue(args, '--content'),
885
+ cites: getArgValue(args, '--cites'),
886
+ }, raw);
887
+ } else if (subcommand === 'playbook') {
888
+ knowledge.cmdKnowledgePlaybook(cwd, {
889
+ preview: args.includes('--preview'),
890
+ }, raw);
891
+ } else {
892
+ error('Unknown knowledge subcommand. Available: ask, discuss, playbook');
893
+ }
894
+ break;
895
+ }
896
+
897
+ case 'review-deep': {
898
+ const subcommand = args[1];
899
+ const phaseNum = args[2];
900
+ const opts = {
901
+ reviewerFile: getArgValue(args, '--reviewer-file'),
902
+ hardenerFile: getArgValue(args, '--hardener-file'),
903
+ metaFile: getArgValue(args, '--meta-file'),
904
+ };
905
+ if (subcommand === 'merge') {
906
+ reviewDeep.cmdReviewDeepMerge(cwd, phaseNum, opts, raw);
907
+ } else if (subcommand === 'analyze') {
908
+ reviewDeep.cmdReviewDeepAnalyze(cwd, phaseNum, opts, raw);
909
+ } else {
910
+ error('Unknown review-deep subcommand. Available: merge, analyze');
911
+ }
912
+ break;
913
+ }
914
+
915
+ case 'preview': {
916
+ const subcommand = args[1];
917
+ if (subcommand === 'phase') {
918
+ preview.cmdPreviewPhase(cwd, args[2], raw);
919
+ } else if (subcommand === 'phases') {
920
+ preview.cmdPreviewPhases(cwd, raw);
921
+ } else if (subcommand === 'milestone') {
922
+ preview.cmdPreviewMilestone(cwd, raw);
923
+ } else {
924
+ error('Unknown preview subcommand. Available: phase <N>, phases, milestone');
925
+ }
926
+ break;
927
+ }
928
+
929
+ case 'cost': {
930
+ const subcommand = args[1];
931
+ if (subcommand === 'report' || !subcommand) {
932
+ const format = getArgValue(args, '--format', 'json');
933
+ const since = getArgValue(args, '--since');
934
+ const until = getArgValue(args, '--until');
935
+ cost.cmdCostReport(cwd, { format, since, until }, raw);
936
+ } else if (subcommand === 'append') {
937
+ const rec = {
938
+ agent: getArgValue(args, '--agent'),
939
+ command: getArgValue(args, '--command'),
940
+ model: getArgValue(args, '--model'),
941
+ tier: getArgValue(args, '--tier'),
942
+ input_tokens: Number(getArgValue(args, '--input-tokens', 0)),
943
+ output_tokens: Number(getArgValue(args, '--output-tokens', 0)),
944
+ cache_read_tokens: Number(getArgValue(args, '--cache-read-tokens', 0)),
945
+ cache_write_tokens: Number(getArgValue(args, '--cache-write-tokens', 0)),
946
+ phase: getArgValue(args, '--phase'),
947
+ session: getArgValue(args, '--session'),
948
+ };
949
+ cost.cmdCostAppend(cwd, rec, raw);
950
+ } else if (subcommand === 'clear') {
951
+ cost.cmdCostClear(cwd, raw);
952
+ } else {
953
+ error('Unknown cost subcommand. Available: report, append, clear');
954
+ }
955
+ break;
956
+ }
957
+
958
+ case 'bus': {
959
+ const subcommand = args[1];
960
+ if (subcommand === 'publish') {
961
+ bus.cmdBusPublish(cwd, args[2], args[3], { source: getArgValue(args, '--source') }, raw);
962
+ } else if (subcommand === 'drain') {
963
+ const mode = getArgValue(args, '--mode', 'peek');
964
+ const limit = getArgValue(args, '--limit');
965
+ const offset = getArgValue(args, '--offset');
966
+ bus.cmdBusDrain(cwd, args[2], {
967
+ mode,
968
+ limit: limit ? Number(limit) : undefined,
969
+ offset: offset ? Number(offset) : undefined,
970
+ }, raw);
971
+ } else if (subcommand === 'list') {
972
+ bus.cmdBusList(cwd, raw);
973
+ } else {
974
+ error('Unknown bus subcommand. Available: publish, drain, list');
975
+ }
976
+ break;
977
+ }
978
+
979
+ case 'cache': {
980
+ const subcommand = args[1];
981
+ if (subcommand === 'prime') {
982
+ const result = buildCachedContext(cwd);
983
+ if (args.includes('--summary')) {
984
+ // Metadata-only form: hide full block content so agents can decide
985
+ // whether to request the full payload.
986
+ const summary = {
987
+ blocks: result.blocks.map(b => ({ path: b.path, bytes: Buffer.byteLength(b.content, 'utf-8'), cache: b.cache })),
988
+ total_bytes: result.total_bytes,
989
+ sha: result.sha,
990
+ };
991
+ output(summary, raw);
992
+ } else {
993
+ output(result, raw);
994
+ }
995
+ } else {
996
+ error('Unknown cache subcommand. Available: prime [--summary]');
997
+ }
998
+ break;
999
+ }
1000
+
1001
+
736
1002
  case 'retro': {
737
- verify.cmdRetro(cwd, raw);
1003
+ verify.cmdRetro(cwd, raw, args);
738
1004
  break;
739
1005
  }
740
1006
 
@@ -746,8 +1012,10 @@ async function main() {
746
1012
  codebase.cmdDetectLanguages(cwd, raw);
747
1013
  } else if (subcommand === 'best-practices') {
748
1014
  codebase.cmdBestPractices(cwd, raw);
1015
+ } else if (subcommand === 'estimate-size') {
1016
+ codebase.cmdEstimateRepoSize(cwd, raw, args);
749
1017
  } else {
750
- error('Unknown codebase subcommand. Available: analyze-imports, detect-languages, best-practices');
1018
+ error('Unknown codebase subcommand. Available: analyze-imports, detect-languages, best-practices, estimate-size');
751
1019
  }
752
1020
  break;
753
1021
  }
@@ -774,6 +1042,51 @@ async function main() {
774
1042
  break;
775
1043
  }
776
1044
 
1045
+ case 'optimize': {
1046
+ const subcommand = args[1];
1047
+ if (subcommand === 'trace') {
1048
+ const traceSub = args[2];
1049
+ optimize.cmdOptimizeTrace(cwd, traceSub, {
1050
+ sessionId: getArgValue(args, '--session'),
1051
+ description: getArgValue(args, '--description'),
1052
+ command: getArgValue(args, '--command'),
1053
+ phase: getArgValue(args, '--phase'),
1054
+ // trace log opts
1055
+ agent: getArgValue(args, '--agent'),
1056
+ type: getArgValue(args, '--type'),
1057
+ category: getArgValue(args, '--category'),
1058
+ impact: getArgValue(args, '--impact'),
1059
+ description: getArgValue(args, '--description'),
1060
+ correction: getArgValue(args, '--correction'),
1061
+ tokens_wasted: getArgValue(args, '--tokens-wasted') ? Number(getArgValue(args, '--tokens-wasted')) : null,
1062
+ context: (() => { const v = getArgValue(args, '--context'); if (!v) return null; try { return JSON.parse(v); } catch { return null; } })(),
1063
+ }, raw);
1064
+ } else if (subcommand === 'learn') {
1065
+ optimize.cmdOptimizeLearn(cwd, {
1066
+ sessionId: getArgValue(args, '--session'),
1067
+ }, raw);
1068
+ } else if (subcommand === 'apply') {
1069
+ optimize.cmdOptimizeApply(cwd, {
1070
+ reportPath: getArgValue(args, '--report'),
1071
+ }, raw);
1072
+ } else if (subcommand === 'list') {
1073
+ optimize.cmdOptimizeList(cwd, raw);
1074
+ } else if (subcommand === 'stats') {
1075
+ optimize.cmdOptimizeStats(cwd, raw);
1076
+ } else {
1077
+ error('Unknown optimize subcommand. Available: trace, learn, apply, list, stats');
1078
+ }
1079
+ break;
1080
+ }
1081
+
1082
+ case 'learn': {
1083
+ // Convenience alias: pan-tools learn = optimize learn
1084
+ optimize.cmdOptimizeLearn(cwd, {
1085
+ sessionId: getArgValue(args, '--session'),
1086
+ }, raw);
1087
+ break;
1088
+ }
1089
+
777
1090
  default:
778
1091
  error(`Unknown command: ${command}. Run pan-tools without arguments to see available commands.`);
779
1092
  }
@@ -0,0 +1,53 @@
1
+ <!--
2
+ Template for .planning/PLAYBOOK.md generated by `/pan:knowledge playbook`.
3
+ Populated by knowledge.cjs buildPlaybook() + writePlaybook() from the
4
+ accumulated lessons in `.planning/memory/*.md`.
5
+
6
+ Categories (in order):
7
+ - Conventions — preferred patterns / naming / style
8
+ - Gotchas — edge cases and surprises
9
+ - Decisions — architecture choices with rationale
10
+ - Tool choices — library / framework picks
11
+ - Anti-patterns — things to avoid
12
+ - Recurring gaps — patterns that keep appearing in verification
13
+ - General — uncategorized
14
+ -->
15
+
16
+ ---
17
+ type: playbook
18
+ generated: {{generated_at}}
19
+ source_agents: {{agent_count}}
20
+ entries: {{entry_count}}
21
+ ---
22
+
23
+ # PAN Playbook
24
+
25
+ Accumulated lessons across {{agent_count}} agents and {{entry_count}} memory entries. Regenerated from `.planning/memory/*.md`.
26
+
27
+ ## Conventions
28
+
29
+ - {{entry}} _— from `{{agent}}`_
30
+
31
+ ## Gotchas
32
+
33
+ - {{entry}} _— from `{{agent}}`_
34
+
35
+ ## Decisions
36
+
37
+ - {{entry}} _— from `{{agent}}`_
38
+
39
+ ## Tool choices
40
+
41
+ - {{entry}} _— from `{{agent}}`_
42
+
43
+ ## Anti-patterns
44
+
45
+ - {{entry}} _— from `{{agent}}`_
46
+
47
+ ## Recurring gaps
48
+
49
+ - {{entry}} _— from `{{agent}}`_
50
+
51
+ ## General
52
+
53
+ - {{entry}} _— from `{{agent}}`_
@@ -0,0 +1,93 @@
1
+ <!--
2
+ Template for pan-previewer output. Agent fills in sections based on mode
3
+ (phase | phases | milestone). Not all sections apply to all modes — see
4
+ commands/pan/preview.md for the per-mode contract.
5
+
6
+ Placeholders:
7
+ {{mode}} — "phase" | "phases" | "milestone"
8
+ {{title}} — e.g. "Phase 7 — API Refactor" or "v3.1"
9
+ {{generated_at}} — ISO timestamp
10
+ {{risk_score}} — 1-10 (phase mode)
11
+ {{confidence}} — 0-100 (milestone mode)
12
+ -->
13
+
14
+ ---
15
+ mode: {{mode}}
16
+ generated_at: {{generated_at}}
17
+ source: pan-previewer
18
+ ---
19
+
20
+ # Preview: {{title}}
21
+
22
+ ## Summary
23
+
24
+ {{one-paragraph-verdict}}
25
+
26
+ ## Files likely touched
27
+
28
+ <!-- phase mode only; grouped by source/tests/docs -->
29
+ - `{{file_path}}` — {{role}}
30
+
31
+ ## Tests at risk
32
+
33
+ <!-- phase mode only -->
34
+ - `{{test_path}}` — {{reason}}
35
+
36
+ ## Migration steps
37
+
38
+ <!-- phase mode, only when risk_signals.migrate is true -->
39
+ 1. {{step}}
40
+
41
+ ## External deps
42
+
43
+ <!-- phase mode, only when relevant -->
44
+ - {{package}} — {{version_concern}}
45
+
46
+ ## Mermaid
47
+
48
+ <!-- phases mode only; raw source from data layer inside a fenced mermaid block -->
49
+ ```mermaid
50
+ {{mermaid_source}}
51
+ ```
52
+
53
+ ## Parallel batches
54
+
55
+ <!-- phases mode only -->
56
+ ### Batch 1
57
+ - Phase {{num}} — {{name}}
58
+
59
+ ## Hidden coupling
60
+
61
+ <!-- phases mode only; may be "none found" -->
62
+ - Phase {{from}} → Phase {{to}} — inferred from prose mention; consider promoting to `depends_on:` frontmatter.
63
+
64
+ ## Current state
65
+
66
+ <!-- milestone mode only -->
67
+ - Phases completed: {{completed}} / {{total}}
68
+ - Velocity: {{phases_per_week}} phases/week (sample size {{sample_size}})
69
+
70
+ ## Projection
71
+
72
+ <!-- milestone mode only -->
73
+ - ETA: **{{eta_date}}**
74
+ - Confidence: {{confidence}}%
75
+
76
+ ## Bottleneck
77
+
78
+ <!-- milestone mode only -->
79
+ - Phase {{phase_num}} — {{reason}}
80
+
81
+ ## Caveats
82
+
83
+ <!-- milestone mode only -->
84
+ - {{caveat}}
85
+
86
+ ## Risk assessment
87
+
88
+ <!-- phase mode only; narrative, cites specific signals -->
89
+ {{narrative}}
90
+
91
+ ## Bottom line
92
+
93
+ **{{one-sentence-verdict}}**
@@ -27,14 +27,14 @@ Decimal phases appear between their surrounding integers in numeric order.
27
27
  ## Phase Details
28
28
 
29
29
  ### Phase 1: [Name]
30
- **Goal**: [What this phase delivers]
31
- **Depends on**: Nothing (first phase)
32
- **Requirements**: [REQ-01, REQ-02, REQ-03] <!-- brackets optional, parser handles both formats -->
30
+ **Goal:** [What this phase delivers]
31
+ **Depends on:** Nothing (first phase)
32
+ **Requirements:** [REQ-01, REQ-02, REQ-03] <!-- brackets optional, parser handles both formats -->
33
33
  **Success Criteria** (what must be TRUE):
34
34
  1. [Observable behavior from user perspective]
35
35
  2. [Observable behavior from user perspective]
36
36
  3. [Observable behavior from user perspective]
37
- **Plans**: [Number of plans, e.g., "3 plans" or "TBD"]
37
+ **Plans:** [Number of plans, e.g., "3 plans" or "TBD"]
38
38
 
39
39
  Plans:
40
40
  - [ ] 01-01: [Brief description of first plan]
@@ -42,50 +42,50 @@ Plans:
42
42
  - [ ] 01-03: [Brief description of third plan]
43
43
 
44
44
  ### Phase 2: [Name]
45
- **Goal**: [What this phase delivers]
46
- **Depends on**: Phase 1
47
- **Requirements**: [REQ-04, REQ-05]
45
+ **Goal:** [What this phase delivers]
46
+ **Depends on:** Phase 1
47
+ **Requirements:** [REQ-04, REQ-05]
48
48
  **Success Criteria** (what must be TRUE):
49
49
  1. [Observable behavior from user perspective]
50
50
  2. [Observable behavior from user perspective]
51
- **Plans**: [Number of plans]
51
+ **Plans:** [Number of plans]
52
52
 
53
53
  Plans:
54
54
  - [ ] 02-01: [Brief description]
55
55
  - [ ] 02-02: [Brief description]
56
56
 
57
57
  ### Phase 2.1: Critical Fix (INSERTED)
58
- **Goal**: [Urgent work inserted between phases]
59
- **Depends on**: Phase 2
58
+ **Goal:** [Urgent work inserted between phases]
59
+ **Depends on:** Phase 2
60
60
  **Success Criteria** (what must be TRUE):
61
61
  1. [What the fix achieves]
62
- **Plans**: 1 plan
62
+ **Plans:** 1 plan
63
63
 
64
64
  Plans:
65
65
  - [ ] 02.1-01: [Description]
66
66
 
67
67
  ### Phase 3: [Name]
68
- **Goal**: [What this phase delivers]
69
- **Depends on**: Phase 2
70
- **Requirements**: [REQ-06, REQ-07, REQ-08]
68
+ **Goal:** [What this phase delivers]
69
+ **Depends on:** Phase 2
70
+ **Requirements:** [REQ-06, REQ-07, REQ-08]
71
71
  **Success Criteria** (what must be TRUE):
72
72
  1. [Observable behavior from user perspective]
73
73
  2. [Observable behavior from user perspective]
74
74
  3. [Observable behavior from user perspective]
75
- **Plans**: [Number of plans]
75
+ **Plans:** [Number of plans]
76
76
 
77
77
  Plans:
78
78
  - [ ] 03-01: [Brief description]
79
79
  - [ ] 03-02: [Brief description]
80
80
 
81
81
  ### Phase 4: [Name]
82
- **Goal**: [What this phase delivers]
83
- **Depends on**: Phase 3
84
- **Requirements**: [REQ-09, REQ-10]
82
+ **Goal:** [What this phase delivers]
83
+ **Depends on:** Phase 3
84
+ **Requirements:** [REQ-09, REQ-10]
85
85
  **Success Criteria** (what must be TRUE):
86
86
  1. [Observable behavior from user perspective]
87
87
  2. [Observable behavior from user perspective]
88
- **Plans**: [Number of plans]
88
+ **Plans:** [Number of plans]
89
89
 
90
90
  Plans:
91
91
  - [ ] 04-01: [Brief description]
@@ -152,8 +152,8 @@ After completing first milestone, reorganize with milestone groupings:
152
152
  <summary>✅ v1.0 MVP (Phases 1-4) - SHIPPED YYYY-MM-DD</summary>
153
153
 
154
154
  ### Phase 1: [Name]
155
- **Goal**: [What this phase delivers]
156
- **Plans**: 3 plans
155
+ **Goal:** [What this phase delivers]
156
+ **Plans:** 3 plans
157
157
 
158
158
  Plans:
159
159
  - [x] 01-01: [Brief description]
@@ -169,9 +169,9 @@ Plans:
169
169
  **Milestone Goal:** [What v1.1 delivers]
170
170
 
171
171
  #### Phase 5: [Name]
172
- **Goal**: [What this phase delivers]
173
- **Depends on**: Phase 4
174
- **Plans**: 2 plans
172
+ **Goal:** [What this phase delivers]
173
+ **Depends on:** Phase 4
174
+ **Plans:** 2 plans
175
175
 
176
176
  Plans:
177
177
  - [ ] 05-01: [Brief description]
@@ -18,12 +18,15 @@ See: .planning/project.md (updated [date])
18
18
 
19
19
  ## Current Position
20
20
 
21
- Phase: [X] of [Y] ([Phase name])
22
- Plan: [A] of [B] in current phase
23
- Status: [Ready to plan / Planning / Ready to execute / In progress / Phase complete]
24
- Last activity: [YYYY-MM-DD] [What happened]
25
-
26
- Progress: [░░░░░░░░░░] 0%
21
+ **Current Phase:** [X]
22
+ **Current Phase Name:** [Phase name]
23
+ **Current Plan:** [A]
24
+ **Total Plans in Phase:** [B]
25
+ **Total Phases:** [Y]
26
+ **Status:** [Ready to plan / Planning / Ready to execute / In progress / Phase complete]
27
+ **Last Activity:** [YYYY-MM-DD]
28
+ **Last Activity Description:** [What happened]
29
+ **Progress:** [░░░░░░░░░░] 0%
27
30
 
28
31
  ## Performance Metrics
29
32
 
@@ -68,9 +71,9 @@ None yet.
68
71
 
69
72
  ## Session Continuity
70
73
 
71
- Last session: [YYYY-MM-DD HH:MM]
72
- Stopped at: [Description of last completed action]
73
- Resume file: [Path to .continue-here*.md if exists, otherwise "None"]
74
+ **Last session:** [YYYY-MM-DD HH:MM]
75
+ **Stopped At:** [Description of last completed action]
76
+ **Resume File:** [Path to .continue-here*.md if exists, otherwise "None"]
74
77
  ```
75
78
 
76
79
  <purpose>