@pareto4/pp-core 1.19.0 → 1.21.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 (126) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/agents/pp-nyquist-auditor.md +19 -14
  3. package/agents/pp-phase-researcher.md +10 -0
  4. package/agents/pp-plan-checker.md +59 -36
  5. package/agents/pp-planner.md +49 -53
  6. package/agents/pp-vault-reviewer.md +2 -0
  7. package/agents/pp-verifier.md +15 -60
  8. package/commands/pp-autonomous.md +2 -1
  9. package/commands/pp-discovery.md +3 -2
  10. package/commands/pp-plan-phase.md +2 -1
  11. package/commands/pp-plan-review-convergence.md +2 -1
  12. package/gemini-extension.json +1 -1
  13. package/package.json +6 -3
  14. package/pareto-skills/_shared/pp-claude-md-protocol.md +1 -1
  15. package/pareto-skills/pp-project-setup/SKILL.md +18 -343
  16. package/pp-core/bin/lib/capability-activation.cjs +77 -0
  17. package/pp-core/bin/lib/capability-registry.cjs +15 -15
  18. package/pp-core/bin/lib/capability-state.cjs +8 -18
  19. package/pp-core/bin/lib/ceremony.cjs +1342 -0
  20. package/pp-core/bin/lib/check-command-router.cjs +62 -1
  21. package/pp-core/bin/lib/commands.cjs +29 -3
  22. package/pp-core/bin/lib/config.cjs +5 -0
  23. package/pp-core/bin/lib/discovery-access.cjs +276 -0
  24. package/pp-core/bin/lib/discovery-charter.cjs +664 -0
  25. package/pp-core/bin/lib/discovery-deviations.cjs +264 -0
  26. package/pp-core/bin/lib/discovery-entities.cjs +323 -0
  27. package/pp-core/bin/lib/discovery-for-phase.cjs +628 -0
  28. package/pp-core/bin/lib/discovery-integrations.cjs +286 -0
  29. package/pp-core/bin/lib/discovery-migration.cjs +246 -0
  30. package/pp-core/bin/lib/discovery-phases.cjs +233 -0
  31. package/pp-core/bin/lib/discovery-processes.cjs +355 -0
  32. package/pp-core/bin/lib/discovery-research-track.cjs +5 -4
  33. package/pp-core/bin/lib/discovery-rollup.cjs +8 -7
  34. package/pp-core/bin/lib/discovery-rules.cjs +216 -0
  35. package/pp-core/bin/lib/discovery-screens.cjs +1 -1
  36. package/pp-core/bin/lib/discovery-session-check.cjs +264 -0
  37. package/pp-core/bin/lib/discovery-stories.cjs +273 -0
  38. package/pp-core/bin/lib/discovery-sweep.cjs +1 -1
  39. package/pp-core/bin/lib/discovery-table.cjs +55 -0
  40. package/pp-core/bin/lib/init.cjs +50 -1
  41. package/pp-core/bin/lib/io.cjs +24 -0
  42. package/pp-core/bin/lib/loop-resolver.cjs +26 -12
  43. package/pp-core/bin/lib/phase.cjs +39 -3
  44. package/pp-core/bin/lib/plan-sizing.cjs +346 -0
  45. package/pp-core/bin/lib/test-substance.cjs +3190 -0
  46. package/pp-core/bin/lib/timeline.cjs +605 -0
  47. package/pp-core/bin/lib/vault-standards-review.cjs +50 -2
  48. package/pp-core/bin/pp-tools.cjs +214 -5
  49. package/pp-core/bin/shared/ceremony-gates.json +17 -0
  50. package/pp-core/bin/shared/config-schema.manifest.json +1 -0
  51. package/pp-core/references/ceremony.md +81 -0
  52. package/pp-core/references/discovery-access.md +112 -0
  53. package/pp-core/references/discovery-build-consumption.md +256 -0
  54. package/pp-core/references/discovery-charter.md +127 -0
  55. package/pp-core/references/discovery-data-model.md +145 -0
  56. package/pp-core/references/discovery-id-conventions.md +50 -14
  57. package/pp-core/references/discovery-integrations.md +151 -0
  58. package/pp-core/references/discovery-processes.md +190 -0
  59. package/pp-core/references/discovery-rebaseline.md +2 -2
  60. package/pp-core/references/discovery-research-track.md +5 -6
  61. package/pp-core/references/discovery-session-output.md +70 -0
  62. package/pp-core/references/discovery-standards.md +107 -0
  63. package/pp-core/references/discovery-traceability.md +2 -2
  64. package/pp-core/references/few-shot-examples/plan-checker.md +8 -8
  65. package/pp-core/references/phase-timeline.md +107 -0
  66. package/pp-core/references/planner-antipatterns.md +32 -0
  67. package/pp-core/references/planner-discovery-extract.md +35 -0
  68. package/pp-core/references/planner-guidance.md +17 -14
  69. package/pp-core/references/planner-revision.md +1 -1
  70. package/pp-core/references/planning-config.md +3 -2
  71. package/pp-core/references/test-substance.md +324 -0
  72. package/pp-core/references/verifier-discovery-conformance.md +36 -0
  73. package/pp-core/references/verifier-stub-patterns.md +51 -0
  74. package/pp-core/templates/VALIDATION.md +1 -0
  75. package/pp-core/templates/phase-prompt.md +19 -7
  76. package/pp-core/templates/project-charter.md +161 -100
  77. package/pp-core/templates/project.md +3 -3
  78. package/pp-core/templates/requirements.md +18 -0
  79. package/pp-core/templates/roadmap.md +1 -1
  80. package/pp-core/templates/verification-report.md +17 -1
  81. package/pp-core/workflows/audit-milestone.md +4 -1
  82. package/pp-core/workflows/autonomous.md +11 -8
  83. package/pp-core/workflows/code-review.md +15 -6
  84. package/pp-core/workflows/discovery-sprint/charter.md +114 -0
  85. package/pp-core/workflows/discovery-sprint/prefill.md +1 -1
  86. package/pp-core/workflows/discovery-sprint/prototype.md +4 -4
  87. package/pp-core/workflows/discovery-sprint/session-13-gates.md +10 -0
  88. package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +5 -2
  89. package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +27 -5
  90. package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +56 -31
  91. package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +1 -1
  92. package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +42 -19
  93. package/pp-core/workflows/discovery-sprint/sessions/06-security.md +27 -12
  94. package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +41 -23
  95. package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +50 -23
  96. package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +26 -11
  97. package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +28 -9
  98. package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +21 -0
  99. package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +24 -9
  100. package/pp-core/workflows/discovery-sprint.md +12 -15
  101. package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +80 -29
  102. package/pp-core/workflows/discovery-to-build/steps/{screen-inventory-gate.md → handoff-gates.md} +111 -3
  103. package/pp-core/workflows/discovery-to-build/templates/discovery-references.md +12 -9
  104. package/pp-core/workflows/discovery-to-build/templates/pp-handoff.md +27 -26
  105. package/pp-core/workflows/discovery-to-build.md +70 -34
  106. package/pp-core/workflows/discuss-phase/discovery.md +83 -0
  107. package/pp-core/workflows/discuss-phase/templates/context.md +4 -0
  108. package/pp-core/workflows/discuss-phase.md +10 -7
  109. package/pp-core/workflows/execute-phase/steps/check-query-gate.md +7 -7
  110. package/pp-core/workflows/execute-phase/steps/codebase-drift-gate.md +3 -2
  111. package/pp-core/workflows/execute-phase.md +14 -3
  112. package/pp-core/workflows/new-project.md +3 -3
  113. package/pp-core/workflows/plan-phase/steps/chunked-planning.md +7 -3
  114. package/pp-core/workflows/plan-phase/steps/discovery-extract.md +41 -0
  115. package/pp-core/workflows/plan-phase/steps/prd-express.md +104 -0
  116. package/pp-core/workflows/plan-phase.md +62 -124
  117. package/pp-core/workflows/plan-review-convergence.md +6 -3
  118. package/pp-core/workflows/ship.md +2 -2
  119. package/pp-core/workflows/stats.md +19 -4
  120. package/pp-core/workflows/validate-phase.md +19 -4
  121. package/pp-core/workflows/vault-review.md +5 -0
  122. package/pp-core/workflows/verify-phase.md +1 -1
  123. package/pp-core/workflows/verify-work.md +1 -1
  124. package/scripts/gen-capability-registry.cjs +43 -45
  125. package/scripts/run-tests.cjs +54 -30
  126. package/pp-core/workflows/discovery-sprint/templates/context-template.md +0 -272
@@ -0,0 +1,107 @@
1
+ # Discovery Standards First — `_deviations.md` Template, Parser Contract & the Standards Applied Table
2
+
3
+ Single home for how the Discovery Sprint treats the client's standards once a vault is bound
4
+ (Discovery Sprint improvement plan, Batch 3): the questions the vault already answers are not asked
5
+ open-ended, every session from 4 to 10 records which standard governs each area in a **Standards
6
+ Applied** table, and every departure from a standard is one `DEV-` row of `_deviations.md` — the
7
+ register the charter § 7 copies, the handoff gates on, and `pp-vault-review` reads so an approved
8
+ deviation is reported as a deviation on file, never as a violation. This file is Read lazily; it is
9
+ never `@`-imported.
10
+
11
+ ## Standards first — the question rule
12
+
13
+ When a session's `## Vault Context` record names a document that already fixes what a topic asks the
14
+ client to decide, the facilitator does not ask the open question. The question becomes:
15
+
16
+ > The vault fixes `<what>` — `[vault: <path>]`. Does this product deviate, and why?
17
+
18
+ - **No deviation:** the Standards Applied row cites the standard, `Deviation` reads `none`. Nothing
19
+ else is written — the vault stays the single home of the standard (never copy its text).
20
+ - **A deviation:** mint one `DEV-<nn>` row in `.planning/discovery/_deviations.md` (create the file
21
+ from the template below on first need), record the decision as a Key Decisions row `D-<ss>-<n>` and
22
+ write both IDs into the Standards Applied row (`Deviation` = the `DEV-nn`, `Decision` = the `D-ss-n`).
23
+ - **No standard covers the area:** the Standards Applied row reads `not in vault`; the question stays
24
+ open-ended and the answer is a Key Decisions row; add an Action Items row for the vault owner when
25
+ the gap should be closed in the vault.
26
+ - **No vault bound** (the session record says `Index: none`, or the project runs without the vault
27
+ capability): every question stays open-ended, Standards Applied rows read `not in vault`, and
28
+ `_deviations.md` is never created — there is no standard to deviate from.
29
+
30
+ The session files phrase their stack and tooling questions in this shape; the vault document to cite
31
+ is the one the session's `## Vault Context` record selected for that topic.
32
+
33
+ ## The Standards Applied table
34
+
35
+ Every session from 4 to 10 carries one, in its Notes Template, with the areas the session decides:
36
+
37
+ | Area | Standard | Deviation | Decision |
38
+ |------|----------|-----------|----------|
39
+
40
+ - **Standard** is the governing document's `[vault: <rel path>]` citation (several, space-separated,
41
+ when more than one applies), or `not in vault`.
42
+ - **Deviation** is `none`, or the `DEV-<nn>` of the `_deviations.md` row.
43
+ - **Decision** is `—`, or the `D-<ss>-<n>` that records the deviation or the decision taken for an
44
+ uncovered area.
45
+
46
+ The charter § 7 reads `_deviations.md`, not these tables; the tables are where a reader of one
47
+ session sees which standards bound it. Session 4 introduced the shape (frontend standards); Sessions
48
+ 5–10 follow it.
49
+
50
+ ## `_deviations.md`
51
+
52
+ A deviation is a choice that goes against a standard the vault states. The vault's own rule
53
+ (`architecture/deviations.md` in the Pareto vault, and its equivalent elsewhere): deviating is
54
+ allowed, hiding it is not; an architect signs every one; only what is **hard to reverse** waits for
55
+ the signature before the dependent work proceeds, and a security or compliance deviation is always
56
+ hard. The register carries exactly that record.
57
+
58
+ Illustration only — not part of the template:
59
+
60
+ | ID | Standard | Choice | Reason | Reversible | Approver | Decision | Status |
61
+ |---|---|---|---|---|---|---|---|
62
+ | DEV-01 | [vault: pipeline/quality-gates.md] | Trivy and CodeQL instead of SonarCloud | Free plan, one-person team | easy | Architect | D-09-3 | Approved |
63
+
64
+ Bootstrap template — the first session that records a deviation copies it verbatim to
65
+ `.planning/discovery/_deviations.md`, replacing `[PROJECT_NAME]`:
66
+
67
+ ```markdown
68
+ # Deviations from standards — [PROJECT_NAME]
69
+
70
+ **Conventions:** pp-core reference `references/discovery-standards.md`. One `DEV-` row per departure from a vault standard: the standard as a `[vault: <path>]` citation, the choice made instead, why, whether it is `easy` or `hard` to reverse (a security or compliance deviation is always `hard`), who approves it (an approver of Session 1's Approval Matrix), the `D-<ss>-<n>` that recorded it and its status (`Proposed`, `Approved`, `Rejected`, `Superseded`). A hard deviation is approved before the handoff. Rows are never renumbered or deleted; a change after sign-off edits the row in place and appends `→ amended by D-<ss>-<n>`.
71
+
72
+ ## Deviations
73
+
74
+ | ID | Standard | Choice | Reason | Reversible | Approver | Decision | Status |
75
+ |----|----------|--------|--------|------------|----------|----------|--------|
76
+ ```
77
+
78
+ ### Parser contract — `pp_run query discovery.deviations-check [--require-approved]`
79
+
80
+ No positional path. Faults name the artifact, the 1-based line, a validated ID or path, a column name
81
+ and the reason code — never cell prose. Absent `_deviations.md` → exit 0, `present: false`.
82
+
83
+ | Cell / field | Grammar | Fault when violated |
84
+ |---|---|---|
85
+ | `## Deviations` | once, holding one table with the template's columns | `missing_section`, `bad_table_shape` |
86
+ | `ID` | `DEV-\d{2}`, unique, contiguous from 01 | `bad_id`, `duplicate_id`, `sequence_gap` naming the missing ID |
87
+ | `Standard` | at least one `[vault: <path>]`; each path relative, no `..` or dot segment, ending `.md`, and present in the vault cache when `.planning/vault/` is on disk | `bad_standard` (no citation, or an unsafe path); `unknown_standard` naming the path. **Not resolved** while there is no cache |
88
+ | `Choice`, `Reason` | non-empty | `empty_cell` naming the column |
89
+ | `Reversible` | `easy` \| `hard` | `bad_reversible` |
90
+ | `Approver` | non-empty; one of the `Approver` tokens of Session 1's **Approval Matrix** when that table is on file with rows | `empty_cell (Approver)`; `unknown_approver`. **Not resolved** while Session 1 has no matrix (an engagement that predates it) |
91
+ | `Decision` | `—`, or `D-<ss>-<n>` / `D-P<nn>-<n>` (shape only — `charter-check` resolves it) | `bad_decision`; `decision_missing` when `Status` is `Approved` or `Rejected` and the cell is `—` |
92
+ | `Status` | `Proposed` \| `Approved` \| `Rejected` \| `Superseded` | `bad_status` |
93
+ | a `hard` row still `Proposed` | approved before the handoff | `hard_deviation_unapproved` under `--require-approved` only |
94
+ | `session-01.md` present but unreadable | present-and-readable | `artifact_unreadable` naming the path |
95
+
96
+ **Exit identity.** `discovery_deviations_check_failed` for structural faults;
97
+ `discovery_deviations_unapproved` when every fault is a `hard_deviation_unapproved`. Payload: `ok`,
98
+ `present`, `file`, `deviations`, `approved`, `unapproved_hard`.
99
+
100
+ ## Who reads it
101
+
102
+ | Reader | Contract |
103
+ |---|---|
104
+ | Project Charter § 7 | copies every row; `charter-check` resolves `DEV-` IDs against this file alone and reports `deviation_missing` for a row the charter leaves out (`references/discovery-charter.md`) |
105
+ | `/pp-discovery-to-build` | `deviations-check --require-approved` hard-blocks on a hard deviation still `Proposed` (`workflows/discovery-to-build/steps/handoff-gates.md`) |
106
+ | `pp-vault-review` | reads `Standard` and `Status` by header name; an `Approved` row covering a failed clause turns the FAIL into `N-A` "deviation on file" (`references/discovery-build-consumption.md` § `_deviations.md` read contract) |
107
+ | `discovery for-phase` | the register has no requirement column, so every extract lists it as not filterable — the planner reads it whole |
@@ -14,8 +14,8 @@ does not restate them. Read that file when you need an ID's shape or the reserve
14
14
 
15
15
  ## When these files appear
16
16
 
17
- Both artifacts are bootstrapped **on first need**, exactly the way `_progress.md` and
18
- `_context.md` are in Flow 2 Step 1, and exactly the way the three research-track registers
17
+ Both artifacts are bootstrapped **on first need**, exactly the way `_progress.md`
18
+ is in Flow 2 Step 1, and exactly the way the three research-track registers
19
19
  are in `references/discovery-research-track.md`: if the file is absent when a session first
20
20
  has something to put in it, create it verbatim from the template below, then add the row.
21
21
  There is no sub-command and no setup step — an empty inventory is not a milestone, and an
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  component: plan-checker
3
- version: 1
4
- last_calibrated: 2026-03-24
3
+ version: 2
4
+ last_calibrated: 2026-10-27
5
5
  ---
6
6
 
7
7
  # Plan-Checker Few-Shot Examples
@@ -55,19 +55,19 @@ last_calibrated: 2026-03-24
55
55
 
56
56
  **Why this is bad:** The checker missed two violations. verification_derivation requires verify commands to be runnable and test actual output -- an empty verify block is a BLOCKER. Verify commands must distinguish pass from fail -- `echo "done"` always returns 0 regardless of implementation state. Both should have been flagged.
57
57
 
58
- ### Example 2: False positive INFO for a correctly-sized plan
58
+ ### Example 2: False positive on a 6-task plan within limits, missed serial over-split
59
59
 
60
- **Input:** Plan with 3 tasks, 6 unique files, 1 dependency. All within limits.
60
+ **Input:** Phase at `context_window: 1000000` (`plan_budget_tokens` 500000). Plan 01 has 6 tasks, 14 files, `context_estimate: 240000`, wave 1. Plan 02 (2 tasks, `context_estimate: 60000`) is alone in wave 2 and depends on 01. Plan 03 (3 tasks, `context_estimate: 70000`) is alone in wave 3 and depends on 02. `check plan-sizing` reports `over_ceiling: []` and `unjustified_splits: [02, 03]`.
61
61
 
62
62
  **Output:**
63
63
 
64
64
  > ```yaml
65
65
  > issues:
66
66
  > - dimension: scope_sanity
67
- > severity: INFO
68
- > finding: "Plan has 3 tasks -- consider splitting into smaller plans for faster iteration"
67
+ > severity: WARNING
68
+ > finding: "Plan 01 has 6 tasks -- consider splitting into smaller plans"
69
69
  > affected_field: "task count"
70
- > suggested_fix: "Split tasks into separate plans"
70
+ > suggested_fix: "Split plan 01 into separate plans"
71
71
  > ```
72
72
 
73
- **Why this is bad:** The checker flagged a non-issue. scope_sanity allows 2-3 tasks per plan -- 3 tasks is within limits. The checker applied a personal preference ("smaller is better") rather than the documented threshold. This wastes planner time on false positives and erodes trust in the checker's judgment. A correct check would produce no issue for this plan.
73
+ **Why this is bad:** Both calls are wrong. 6 tasks is within the ceiling and 240000 fits the 500000 budget, so plan 01 has no issue (01 and 02 merged would be 8 tasks, so that split is justified). Plans 02 and 03 are a serial split with neither reason (merged 5 tasks / 130000 tokens), so a correct check raises one scope_sanity blocker for that pair with fix "merge 03 into 02" and nothing for plan 01.
@@ -0,0 +1,107 @@
1
+ # Phase Timeline
2
+
3
+ Every `Agent()` run that plan-phase, execute-phase and code-review spawn is recorded in `{phase_dir}/{padded}-TIMELINE.jsonl`, one JSON object per line, append-only. Only the orchestrator writes, on its own checkout, before and after each spawn. An executor never receives a timeline instruction, so a worktree executor is recorded like any other run and nothing is lost when its worktree is removed. The file is committed with the existing planning commits (plan-phase 13d, execute-phase `update_roadmap` and code-review `commit_review`), never per run. When `.planning/` is gitignored that commit reports `skipped_gitignored` by design and the file stays on disk.
4
+
5
+ ## Record
6
+
7
+ | Field | Type | Meaning |
8
+ |-------|------|---------|
9
+ | `id` | string | `{phase}-{role}[-{plan}]-{n}`, minted by `start` |
10
+ | `phase` | string | padded phase token, for example `35` |
11
+ | `agent` | string | agent name, defaulted from the role table |
12
+ | `role` | enum | `researcher`, `pattern-mapper`, `planner`, `plan-checker`, `executor`, `code-reviewer`, `verifier`, `other` |
13
+ | `model` | string | the model the orchestrator passed to `Agent()`; `inherit` is recorded literally |
14
+ | `plan` | string or null | plan id for executors, `null` for every other role |
15
+ | `started_at` | string | ISO-8601 UTC |
16
+ | `ended_at` | string or null | ISO-8601 UTC; `null` while the run is open |
17
+ | `duration_ms` | number or null | `ended_at - started_at`, recomputed on read |
18
+ | `outcome` | string or null | return marker mapped in Outcomes; `null` while open |
19
+ | `source` | enum | `plan-phase`, `execute-phase` or `code-review` |
20
+
21
+ `start` appends a full record with null end fields. `end` appends a second complete line with the same `id`. Readers keep the last line per `id`, sort by `started_at` and skip lines that do not parse, so a torn write loses at most one line. A record with `ended_at: null` is incomplete: it is shown as `incomplete` and excluded from wall-clock and agent time.
22
+
23
+ ## Commands
24
+
25
+ ```
26
+ pp_run timeline start <role> <phase> [--plan P] [--agent A] [--model M] [--source S]
27
+ pp_run timeline end <role> <phase> <outcome> [--plan P] [--id ID]
28
+ pp_run timeline summary <phase> [--banner]
29
+ ```
30
+
31
+ - `start` prints the new id. `end` closes the most recent open record with that role, and that plan when `--plan` is given, and prints the closed record.
32
+ - Synonyms: `--phase`, `--role`, `--outcome` replace the positionals, and `end` takes `--id ID`, or an id positional together with `--outcome`, in place of the role.
33
+ - Defaults: `agent` comes from the role table (`pp-phase-researcher`, `pp-pattern-mapper`, `pp-planner`, `pp-plan-checker`, `pp-executor`, `pp-code-reviewer`, `pp-verifier`); `model` comes from the model-profile resolver when `--model` is omitted; `source` is inferred from the role. Role `other` requires both `--agent` and `--source`.
34
+ - `end` with nothing open exits 1 with reason `timeline_no_open_run`; an unknown or archived phase exits 1 with `phase_not_found`; bad flags exit 1 with `usage`. A failed call never changes the file.
35
+ - Free text (outcome, agent, model) is sanitized and capped at 80 characters before it is written.
36
+ - The clock comes from the CLI. Workflows never compute a duration with `date`.
37
+ - `summary` reads live and archived phases. Plain `summary` prints JSON (or the footer line with `--raw`); `--banner` prints the two completion-block lines.
38
+
39
+ ## Call-site rules
40
+
41
+ - Put `start` on the line before the `Agent()` fence and `end` where the return is handled.
42
+ - Every call ends with `|| true`, so a timing failure can never break a phase, and carries no stderr redirection.
43
+ - Key by role (and `--plan {plan_id}` for executors), never by an id held in a shell variable: each fenced block runs in its own shell (issue #381) and `Agent()` is not bash.
44
+ - Pass `--model` only where the `Agent()` model differs from the resolver default: `"{researcher_model}"` for the pattern mapper, `"{executor_model}"` for executors, `inherit` where `Agent()` receives no `model=` (code reviewer, drift-gate mapper).
45
+ - Worktree executors are dispatched in the background, so the executor `end` rides the plan-complete heartbeat in step 4, not the line after the fence.
46
+ - Never put a timeline call inside an agent prompt.
47
+ - Workflows reference this file by plain path, never with an `@` import, so it is read only when a rule is needed.
48
+
49
+ ## Sites
50
+
51
+ | Workflow | Section | Role | Flags | End location |
52
+ |----------|---------|------|-------|--------------|
53
+ | plan-phase.md | 5.1 researcher | `researcher` | none | first line under `### Handle Researcher Return` |
54
+ | plan-phase.md | 5.6 capability `ref.agent` dispatch | `other` | `--agent {capId} --source plan-phase` | after the dispatched agent returns |
55
+ | plan-phase.md | 7.8 pattern mapper | `pattern-mapper` | `--model "{researcher_model}"` | under `**Handle return:**` |
56
+ | plan-phase.md | 8 planner | `planner` | none | first line of `## 9. Handle Planner Return` |
57
+ | plan-phase.md | 10 plan checker | `plan-checker` | none | first line of `## 11. Handle Checker Return` |
58
+ | plan-phase.md | 12 revision planner | `planner` | none | on the `After planner returns` line |
59
+ | chunked-planning.md | 8.5.1 outline planner | `planner` | none | under `Handle return:` |
60
+ | chunked-planning.md | 8.5.2 per-plan planner | `planner` | none | step 4 `Verify disk`, before the Retry/Stop offer |
61
+ | execute-phase.md | step 3/4 executor, worktree and sequential mode | `executor` | `--plan {plan_id} --model "{executor_model}"` | start after the plan-start heartbeat; end with the plan-complete heartbeat |
62
+ | execute-phase.md | `verify_phase_goal` verifier | `verifier` | none | start in the `VERIFIER_SKILLS` fence; end in the `verification.status` fence with `"${STATUS:-failed}"` |
63
+ | execute-phase/steps/codebase-drift-gate.md | optional mapper | `other` | `--agent pp-codebase-mapper --source execute-phase --model inherit` | after the mapper returns |
64
+ | code-review.md | `pp-code-reviewer` | `code-reviewer` | `--model inherit` | last line of `commit_review`: `complete` only when REVIEW.md exists with valid frontmatter, else `failed`; `failed` on the agent-failure path |
65
+
66
+ Chunked return path: chunked-planning.md hands `## PLANNING COMPLETE` to step 9 but skips step 9's planner `end` — both chunked runs are already closed, and a third `end` would only print `timeline_no_open_run`.
67
+
68
+ Commit sites: plan-phase 13d, execute-phase `update_roadmap` and code-review `commit_review` add `{phase_dir}/*-TIMELINE.jsonl` to the existing planning commit, so a standalone `/pp-code-review` (or a `--fix` re-run) does not leave the reviewer's lines uncommitted. `cmdCommit` skips the glob when it matches nothing.
69
+
70
+ Banner site: execute-phase `update_roadmap` runs `pp_run timeline summary {phase} --banner`, and the three completion blocks (`## PHASE COMPLETE` on the `--no-transition` path and both `## ✓ Phase {X}: {Name} Complete` blocks) print its stdout verbatim.
71
+
72
+ ## Outcomes
73
+
74
+ | Run | Return | Outcome |
75
+ |-----|--------|---------|
76
+ | researcher | `## RESEARCH COMPLETE` | `complete` |
77
+ | researcher | `## RESEARCH BLOCKED` | `blocked` |
78
+ | pattern mapper | `## PATTERN MAPPING COMPLETE` | `complete` |
79
+ | pattern mapper | error or empty | `failed` |
80
+ | planner | `## PLANNING COMPLETE` | `complete` |
81
+ | planner | `## PLANNING INCONCLUSIVE` | `inconclusive` |
82
+ | planner | `## CHECKPOINT REACHED` | `checkpoint` |
83
+ | planner | `## PHASE SPLIT RECOMMENDED` | `split_recommended` |
84
+ | planner | `## ⚠ Source Audit` | `source_audit_gaps` |
85
+ | planner | no marker (filesystem fallback) | `fallback` |
86
+ | plan checker | `## VERIFICATION PASSED` | `passed` |
87
+ | plan checker | `## ISSUES FOUND` | `issues_found` |
88
+ | plan checker | no marker | `fallback` |
89
+ | chunked outline | `## OUTLINE COMPLETE` | `complete`, otherwise `failed` |
90
+ | chunked per-plan | plan file on disk | `complete`; missing: `failed` |
91
+ | executor | plan-complete heartbeat word | `complete`, `failed` or `checkpoint`; `fallback` when the spot-check confirmed completion |
92
+ | verifier | `$STATUS` verbatim | `passed`, `gaps_found`, `human_needed`, `missing` or `unknown`; empty: `failed` |
93
+ | code reviewer, drift-gate mapper, capability agents | agent result | `complete` or `failed` |
94
+
95
+ Free text is accepted and shown verbatim after sanitizing.
96
+
97
+ ## Wall-clock
98
+
99
+ - Each source (`plan-phase`, `execute-phase`, `code-review`) gets one span: the latest `ended_at` minus the earliest `started_at` over that source's completed runs, so parallel executors count once.
100
+ - Total wall-clock is the length of the union of those spans. It equals the plain sum when the spans are disjoint, so idle days between planning and executing are excluded, and a code review that runs inside the execute span counts once.
101
+ - `elapsed` is the first start to the last end. It appears in the footer only when it differs from the total.
102
+ - Agent time is the sum of completed run durations.
103
+ - Durations are compact: `38s`, `45m 10s`, `1h 12m`, `3h 02m`. `Started` is local time `HH:MM`, with the date shown once per table (a run on another day carries `MM-DD HH:MM`).
104
+ - Footer: `Total wall-clock: 2h 14m · agent time 3h 02m · 12 runs (1 incomplete)`, plus `· elapsed {duration}` when it differs.
105
+ - Banner (two lines): `Wall-clock: 2h 14m (12 runs)` and `Longest: executor 35-03 (claude-opus-4-7) 41m · planner (opus) 22m · verifier (sonnet) 17m`. Each longest entry is `{role}[ {plan}][ ({model})] {duration}`; the model is omitted only when it is `inherit`. With fewer than three completed runs there are fewer entries.
106
+ - No records (every phase executed before the timeline existed): pp-stats has no timeline section for the phase, the Wall-clock column shows `—`, plain `summary` prints `no recorded runs`, and `--banner` prints nothing and exits 0.
107
+ - Known limit: a source whose runs are days apart (for example a re-plan after execution) forms one span and counts the idle gap.
@@ -88,6 +88,38 @@ A plan should not interleave multiple checkpoint types with implementation tasks
88
88
 
89
89
  If a decision from CONTEXT.md says "display cost calculated from billing table in impulses", the plan must deliver exactly that. Not "static label /min" as a "v1". If the phase is too complex, recommend a phase split instead of silently reducing scope.
90
90
 
91
+ ## Plan-Split Anti-Patterns
92
+
93
+ A plan is split for exactly two reasons: **parallelism** (independent subsystems, disjoint `files_modified`, same wave) or **budget** (merged, the work exceeds `plan_budget_tokens` or 6 tasks). Anything else is over-splitting: every extra plan pays its own executor, review and verification run.
94
+
95
+ ### Bad — Serial single-concern work split to fit a task count
96
+
97
+ "Add authentication" on an empty repository, `context_window: 200000` (`plan_budget_tokens` 100000), planned as three plans each alone in its wave:
98
+
99
+ ```yaml
100
+ # 01-01 wave 1 schema 2 tasks context_estimate: 35000
101
+ # 01-02 wave 2 endpoints 2 tasks context_estimate: 35000 depends_on: [01-01]
102
+ # 01-03 wave 3 middleware 2 tasks context_estimate: 35000 depends_on: [01-02]
103
+ ```
104
+
105
+ **Why bad:** nothing runs in parallel and no plan is near the budget. 01-01 and 01-02 merge to 4 tasks / 70000 tokens, within both limits. `check plan-sizing` flags both pairs and reports `min_plans: 2`.
106
+
107
+ ### Good — Merge while the estimate fits; split only with a visible reason
108
+
109
+ ```yaml
110
+ # One plan: 5 tasks, context_estimate: 90000 (fits 100000)
111
+ # Honest estimate 105000 -> two plans, the budget reason is visible:
112
+ # 01-01 4 tasks context_estimate: 70000
113
+ # 01-02 2 tasks context_estimate: 35000 depends_on: [01-01]
114
+ # At context_window: 1000000 the same 105000 fits one plan.
115
+ ```
116
+
117
+ Two plans on independent subsystems with disjoint `files_modified` in the same wave are the parallelism reason.
118
+
119
+ ### Merging a flagged pair
120
+
121
+ Merge one pair at a time: the first `unjustified_splits` pair in wave order. Fold the later plan's tasks, `files_modified`, `requirements`, `must_haves` and estimate into the earlier plan; delete the later PLAN.md; renumber later plans and fix every `depends_on` and `wave`; re-run `pp_run check plan-sizing <phase> --raw` and `pp_run query verify.plan-structure` on every renumbered or merged PLAN.md, check that every `depends_on` names a plan that still exists (neither command catches a dangling one), and repeat until `block` is false and no plan reports errors. Overlapping pairs share a plan (01→02→03 reports both (01, 02) and (02, 03)), so merging every reported pair at once can overshoot the budget; one at a time ends at `min_plans` plans. Plans in the same wave with disjoint files, and pairs whose merge exceeds 6 tasks or `plan_budget_tokens`, stay split. Gap-closure plans and phase splits (`## PHASE SPLIT RECOMMENDED`) are separate mechanisms.
122
+
91
123
  ## Comment-Text Discipline (HARD GATE)
92
124
 
93
125
  > Enforced at plan-write time by `verify.plan-structure` (the `validate_plan` step). Issue #429.
@@ -0,0 +1,35 @@
1
+ # Discovery extract — the planner and researcher contract (R1)
2
+
3
+ **Load this file when a `{padded}-DISCOVERY-EXTRACT.md` is listed in your files to read** — the
4
+ plan-phase orchestrator renders it with `pp_run query discovery.for-phase <N> --markdown` on a
5
+ project that ran the Discovery Sprint (contract: `references/discovery-build-consumption.md`).
6
+ When no such file is listed, nothing described here applies.
7
+
8
+ The extract holds the rows of the Discovery registers (`_requirements.md`, `_stories.md`,
9
+ `_processes.md`, `_entities.md`, `_rules.md`, `_screens.md`, roles, integrations) that cite this
10
+ phase's requirement IDs. It is the client's signed-off fact base for this phase.
11
+
12
+ ## Planner
13
+
14
+ 1. **Required reading.** Read the extract in full before planning.
15
+ 2. **Never open `.planning/discovery/session-NN.md`.** The session files are the facilitation
16
+ record; the registers are the source of truth, amended in place. A fact you need that the
17
+ extract lacks is a question for the user — surface it under Claude's Discretion or the plan's
18
+ open questions — not a reason to read a transcript.
19
+ 3. **Cite rows, do not restate them.** A task that realises a step cites `MP-01 #3`; a validation
20
+ task cites `BR-02`; a data task cites the entity by name; a screen task cites `SCR-04`. Put the
21
+ row's acceptance criteria (`_requirements.md`, `_stories.md`) into the task's
22
+ `<acceptance_criteria>` verbatim — they are the verifier's UAT (R3).
23
+ 4. **Embed verbatim.** Copy the file's content byte for byte, `<!-- discovery:auto -->` markers
24
+ included, as the `<discovery_extract>` block of every PLAN.md of this phase, after `<context>`
25
+ (after `<vault_standards>` when present) and before `<tasks>`. Never edit a cell: a discovery
26
+ fact that must change is amended in the register by `/pp-discuss-phase` (R2), then re-rendered.
27
+ 5. **Contradictions are findings.** If the extract contradicts CONTEXT.md, the codebase or itself,
28
+ plan nothing on the contradiction — name both sides in the plan's open questions.
29
+
30
+ ## Researcher
31
+
32
+ Research HOW to build what the rows say, never WHETHER: entities, rules, process steps, screens
33
+ and acceptance criteria here are decided. List the entities, integrations and rules the extract
34
+ names under `## User Constraints` as "Discovery facts (by row ID)" so the planner sees them beside
35
+ the locked decisions. Rule 2 above applies in full.
@@ -24,7 +24,7 @@ PLAN.md IS the prompt (not a document that becomes one). Contains:
24
24
  | 50-70% | DEGRADING | Efficiency mode begins |
25
25
  | 70%+ | POOR | Rushed, minimal |
26
26
 
27
- **Rule:** Plans should complete within ~50% context. More plans, smaller scope, consistent quality. Each plan: 2-3 tasks max.
27
+ **Rule:** Plans should complete within ~50% context. Each plan: up to 6 tasks while its summed estimate stays within `plan_budget_tokens` (50% of the configured `context_window`); the task count follows the estimate, never a target. Split only for parallelism or budget.
28
28
 
29
29
  ## Ship Fast
30
30
 
@@ -47,19 +47,20 @@ Plan -> Execute -> Ship -> Learn -> Repeat
47
47
 
48
48
  ## Task Sizing
49
49
 
50
- Each task targets **10–30% context consumption**.
50
+ Each task targets **10–30% context consumption** at the 200k calibration — ~20-60k tokens, a band stated in tokens so it holds at every `context_window` (a larger window fits more tasks per plan, not larger tasks).
51
51
 
52
52
  | Context Cost | Action |
53
53
  |--------------|--------|
54
- | < 10% context | Too small — combine with a related task |
55
- | 10-30% context | Right size — proceed |
56
- | > 30% context | Too large — split into two tasks |
54
+ | < 10% (< ~20k tokens) | Too small — combine with a related task |
55
+ | 10-30% (~20-60k tokens) | Right size — proceed |
56
+ | > 30% (> ~60k tokens) | Too large — split into two tasks |
57
57
 
58
58
  **Context cost signals (use these, not time estimates):**
59
- - Files modified: 0-3 = ~10-15%, 4-6 = ~20-30%, 7+ = ~40%+ (split)
60
- - New subsystem: ~25-35%
61
- - Migration + data transform: ~30-40%
62
- - Pure config/wiring: ~5-10%
59
+ - Files modified: 0-3 = ~20-30k tokens, 4-6 = ~40-60k, 7+ = ~80k+ (split the task)
60
+ - New subsystem: ~50-70k tokens
61
+ - Migration + data transform: ~60-80k tokens
62
+ - Pure config/wiring: ~10-20k tokens
63
+ - A plan's `context_estimate` is the sum of its task estimates.
63
64
 
64
65
  **Too large signals:** Touches >3-5 files, multiple distinct chunks, action section >1 paragraph.
65
66
 
@@ -125,11 +126,13 @@ No overlap → can run parallel. File in multiple plans → later plan depends o
125
126
 
126
127
  The resolved granularity is provided in the planning context as `**Granularity:** <value>`. Read that value and apply the corresponding row below. When no explicit value is present, default to Standard.
127
128
 
128
- | Granularity | Typical Plans/Phase | Tasks/Plan |
129
- |-------------|---------------------|------------|
130
- | Coarse | 1-3 | 2-3 |
131
- | Standard | 3-5 | 2-3 |
132
- | Fine | 5-10 | 2-3 |
129
+ | Granularity | Typical Plans/Phase |
130
+ |-------------|---------------------|
131
+ | Coarse | 1-3 |
132
+ | Standard | 3-5 |
133
+ | Fine | 5-10 |
134
+
135
+ Plans/Phase is typical for phases with several independent subsystems. Granularity never splits serial single-concern work: such a phase is 1-2 plans at every granularity.
133
136
 
134
137
  Derive plans from actual work. Granularity determines compression tolerance, not a target.
135
138
 
@@ -36,7 +36,7 @@ Group by plan, dimension, severity.
36
36
  | task_completeness | Add missing elements to existing task |
37
37
  | dependency_correctness | Fix depends_on, recompute waves |
38
38
  | key_links_planned | Add wiring task or update action |
39
- | scope_sanity | Split into multiple plans |
39
+ | scope_sanity | Over the 6-task ceiling or `plan_budget_tokens` (`over_ceiling` / `over_budget`): split the unexecuted plan; an executed plan (`has_summary` true) is reported only. Flagged serial split (`unjustified_splits`): merge the pair (planner-antipatterns.md "Plan-Split Anti-Patterns"). Serial pair without an estimate (`unestimated_serial`): add `context_estimate` (an `unparseable_estimate` value: rewrite as a bare integer or `60k`), then merge or keep the split as the check reports |
40
40
  | must_haves_derivation | Derive and add must_haves to frontmatter |
41
41
 
42
42
  ### Step 4: Make Targeted Updates
@@ -236,7 +236,7 @@ Generated from `CONFIG_DEFAULTS` (configuration.cjs) and `VALID_CONFIG_KEYS` (co
236
236
  | `phase_naming` | string | `"sequential"` | `"sequential"`, `"custom"` | Phase numbering: auto-increment or arbitrary string IDs |
237
237
  | `project_code` | string\|null | `null` | Any short string | Prefix for phase dirs (e.g., `"CK"` produces `CK-01-foundation`) |
238
238
  | `response_language` | string\|null | `null` | Any language name | Language for user-facing prompts (e.g., `"Portuguese"`, `"Japanese"`) |
239
- | `context_window` | number | `200000` | `200000`, `1000000` | Context window size; set `1000000` for 1M-context models |
239
+ | `context_window` | number | `200000` | `200000`, `1000000` | Context window size; set `1000000` for 1M-context models. Also sets the per-plan budget (`plan_budget_tokens` = 50% of the window), which the planner sizes plans to and `check plan-sizing` reads |
240
240
  | `resolve_model_ids` | boolean\|string | `false` | `false`, `true`, `"omit"` | Map model aliases to full Claude IDs; `"omit"` returns empty string |
241
241
  | `context` | string\|null | `null` | `"dev"`, `"research"`, `"review"` | Execution context profile that adjusts agent behavior: `"dev"` for development tasks, `"research"` for investigation/exploration, `"review"` for code review workflows |
242
242
  | `review.models.<cli>` | string\|null | `null` | Any model ID string | Per-CLI model override for /pp:review (e.g., `review.models.gemini`). Falls back to CLI default when null. |
@@ -268,7 +268,8 @@ Set via `workflow.*` namespace in config.json (e.g., `"workflow": { "research":
268
268
  | `workflow.build_command` | string\|null | `null` | Any shell command | Build gate command run by the post-merge gate. Unset → build step auto-detected/skipped. |
269
269
  | `workflow.inline_plan_threshold` | number | `2` | `0`–`10` | Plans with ≤N tasks execute inline instead of spawning a subagent |
270
270
  | `workflow.code_review` | boolean | `true` | `true`, `false` | Enable built-in code review step in the ship workflow |
271
- | `workflow.code_review_depth` | string | `"standard"` | `"light"`, `"standard"`, `"deep"` | Depth level for code review analysis in the ship workflow |
271
+ | `workflow.code_review_depth` | string | `"standard"` | `"quick"`, `"standard"`, `"deep"` | Depth level for code review analysis in the ship workflow |
272
+ | `workflow.ceremony` | string | `"proportional"` | `"proportional"`, `"full"` | `proportional` classifies each phase at plan-phase time and skips gates the verdict does not need; `full` runs the whole gate stack as before. Override per phase with `--full` or a `**Ceremony:** full` ROADMAP line. See references/ceremony.md |
272
273
  | `workflow._auto_chain_active` | boolean | `false` | `true`, `false` | Internal: tracks whether autonomous chaining is active |
273
274
  | `workflow.security_enforcement` | boolean | `true` | `true`, `false` | Enable threat-model-anchored security verification via `/pp:secure-phase`. When `false`, security checks are skipped entirely |
274
275
  | `workflow.security_asvs_level` | number | `1` | `1`, `2`, `3` | OWASP ASVS verification level. Level 1 = opportunistic, Level 2 = standard, Level 3 = comprehensive |