@pareto4/pp-core 1.12.1 → 1.17.1

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 (196) hide show
  1. package/.claude-plugin/plugin.json +3 -3
  2. package/README.md +26 -9
  3. package/agents/pp-code-reviewer.md +3 -2
  4. package/agents/pp-debug-session-manager.md +9 -6
  5. package/agents/pp-executor.md +7 -21
  6. package/agents/pp-plan-checker.md +4 -4
  7. package/agents/pp-planner.md +23 -9
  8. package/agents/pp-vault-reviewer.md +274 -0
  9. package/agents/pp-verifier.md +7 -3
  10. package/bin/install.js +10 -3
  11. package/commands/pp-execute-phase.md +1 -3
  12. package/commands/pp-ns-review.md +2 -1
  13. package/commands/pp-plan-phase.md +1 -2
  14. package/commands/pp-vault-review.md +35 -0
  15. package/commands/pp-verify-work.md +1 -2
  16. package/gemini-extension.json +1 -1
  17. package/hooks/dist/pp-check-update.js +0 -0
  18. package/hooks/dist/pp-cursor-session-start.js +1 -1
  19. package/hooks/dist/pp-statusline.js +1 -1
  20. package/hooks/dist/pp-update-banner.js +0 -0
  21. package/hooks/pp-check-update.js +0 -0
  22. package/hooks/pp-cursor-session-start.js +1 -1
  23. package/hooks/pp-statusline.js +1 -1
  24. package/hooks/pp-update-banner.js +0 -0
  25. package/package.json +14 -19
  26. package/pareto-skills/_shared/create-project-board.sh +0 -0
  27. package/pareto-skills/pp-project-setup/SKILL.md +1 -1
  28. package/pp-core/bin/check-latest-version.cjs +0 -0
  29. package/pp-core/bin/detect-build-commands.sh +2 -2
  30. package/pp-core/bin/lib/capability-activation.cjs +83 -9
  31. package/pp-core/bin/lib/capability-registry.cjs +526 -22
  32. package/pp-core/bin/lib/capability-state.cjs +160 -4
  33. package/pp-core/bin/lib/capability-writer.cjs +19 -5
  34. package/pp-core/bin/lib/check-command-router.cjs +3867 -274
  35. package/pp-core/bin/lib/clusters.cjs +4 -0
  36. package/pp-core/bin/lib/command-aliases.cjs +0 -28
  37. package/pp-core/bin/lib/commands.cjs +9 -4
  38. package/pp-core/bin/lib/compose-bindings.cjs +253 -76
  39. package/pp-core/bin/lib/config-loader.cjs +7 -103
  40. package/pp-core/bin/lib/config-schema.cjs +1 -1
  41. package/pp-core/bin/lib/config.cjs +154 -62
  42. package/pp-core/bin/lib/decisions.cjs +104 -27
  43. package/pp-core/bin/lib/discovery-vault-check.cjs +246 -0
  44. package/pp-core/bin/lib/frontmatter.cjs +1 -1
  45. package/pp-core/bin/lib/git-base-branch.cjs +138 -10
  46. package/pp-core/bin/lib/git-provider.cjs +4 -4
  47. package/pp-core/bin/lib/init-command-router.cjs +5 -8
  48. package/pp-core/bin/lib/init-contract.cjs +653 -629
  49. package/pp-core/bin/lib/init-interactive.cjs +77 -21
  50. package/pp-core/bin/lib/init.cjs +24 -51
  51. package/pp-core/bin/lib/install-profiles.cjs +1 -1
  52. package/pp-core/bin/lib/io.cjs +8 -0
  53. package/pp-core/bin/lib/loop-resolver.cjs +169 -47
  54. package/pp-core/bin/lib/org-profile.cjs +544 -53
  55. package/pp-core/bin/lib/package-identity.cjs +3 -3
  56. package/pp-core/bin/lib/phase-command-router.cjs +1 -23
  57. package/pp-core/bin/lib/phase-scope.cjs +1 -1
  58. package/pp-core/bin/lib/phase.cjs +11 -203
  59. package/pp-core/bin/lib/platform-bindings.cjs +40 -19
  60. package/pp-core/bin/lib/practices-review-check.cjs +15 -9
  61. package/pp-core/bin/lib/profile-output.cjs +1 -1
  62. package/pp-core/bin/lib/shell-command-projection.cjs +104 -1
  63. package/pp-core/bin/lib/state.cjs +11 -85
  64. package/pp-core/bin/lib/template.cjs +1 -1
  65. package/pp-core/bin/lib/vault-audit.cjs +2594 -0
  66. package/pp-core/bin/lib/vault-command-router.cjs +2756 -60
  67. package/pp-core/bin/lib/vault-coordinates.cjs +13 -4
  68. package/pp-core/bin/lib/vault-index.cjs +699 -0
  69. package/pp-core/bin/lib/vault-mode.cjs +235 -0
  70. package/pp-core/bin/lib/vault-practices.cjs +1194 -89
  71. package/pp-core/bin/lib/vault-review.cjs +2102 -0
  72. package/pp-core/bin/lib/vault-seal.cjs +1936 -0
  73. package/pp-core/bin/lib/vault-standards.cjs +1505 -0
  74. package/pp-core/bin/lib/vault-trace.cjs +3184 -0
  75. package/pp-core/bin/lib/vault-update.cjs +242 -0
  76. package/pp-core/bin/lib/vault-write-back.cjs +78 -31
  77. package/pp-core/bin/lib/vault.cjs +2713 -634
  78. package/pp-core/bin/lib/verify.cjs +0 -11
  79. package/pp-core/bin/portable-timeout.sh +1 -1
  80. package/pp-core/bin/pp-tools.cjs +184 -37
  81. package/pp-core/bin/shared/config-defaults.manifest.json +0 -7
  82. package/pp-core/bin/shared/config-schema.manifest.json +0 -3
  83. package/pp-core/bin/shared/model-catalog.json +1 -0
  84. package/pp-core/bin/verify-reapply-patches.cjs +0 -0
  85. package/pp-core/org-profile.json +26 -0
  86. package/pp-core/references/autonomous-best-effort.md +8 -7
  87. package/pp-core/references/loop-hook-dispatch.md +0 -14
  88. package/pp-core/references/planner-gap-closure.md +0 -1
  89. package/pp-core/references/planner-tdd.md +0 -1
  90. package/pp-core/references/planner-vault-practices.md +31 -3
  91. package/pp-core/references/planner-vault-standards.md +320 -0
  92. package/pp-core/references/planning-config.md +0 -8
  93. package/pp-core/references/practice-arithmetic-contract.md +121 -0
  94. package/pp-core/references/tdd.md +0 -1
  95. package/pp-core/references/verifier-practice-verdicts.md +263 -0
  96. package/pp-core/templates/README.md +1 -0
  97. package/pp-core/templates/VAULT-REVIEW.md +202 -0
  98. package/pp-core/templates/phase-prompt.md +2 -6
  99. package/pp-core/templates/practices/README.md +137 -11
  100. package/pp-core/templates/project-charter.md +226 -0
  101. package/pp-core/workflows/_runtime-launcher.snippet.sh +0 -0
  102. package/pp-core/workflows/add-tests.md +55 -0
  103. package/pp-core/workflows/audit-fix.md +63 -0
  104. package/pp-core/workflows/audit-milestone.md +1 -1
  105. package/pp-core/workflows/autonomous.md +85 -11
  106. package/pp-core/workflows/check-todos.md +13 -2
  107. package/pp-core/workflows/code-review-fix.md +59 -1
  108. package/pp-core/workflows/code-review.md +10 -1
  109. package/pp-core/workflows/complete-milestone.md +1 -1
  110. package/pp-core/workflows/debug.md +56 -2
  111. package/pp-core/workflows/discovery-sprint/prefill.md +21 -0
  112. package/pp-core/workflows/discovery-sprint/prototype.md +46 -48
  113. package/pp-core/workflows/discovery-sprint/session-13-gates.md +2 -0
  114. package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +1 -3
  115. package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +1 -3
  116. package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +1 -3
  117. package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +20 -24
  118. package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +1 -3
  119. package/pp-core/workflows/discovery-sprint/sessions/06-security.md +1 -3
  120. package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +1 -3
  121. package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +1 -3
  122. package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +1 -3
  123. package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +1 -6
  124. package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +1 -3
  125. package/pp-core/workflows/discovery-sprint/sessions/12-delivery-model.md +1 -3
  126. package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +1 -3
  127. package/pp-core/workflows/discovery-sprint/templates/context-template.md +1 -1
  128. package/pp-core/workflows/discovery-sprint/vault-context.md +213 -0
  129. package/pp-core/workflows/discovery-sprint.md +7 -3
  130. package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +4 -4
  131. package/pp-core/workflows/discovery-to-build/templates/pp-handoff.md +43 -1
  132. package/pp-core/workflows/discovery-to-build.md +9 -1
  133. package/pp-core/workflows/discuss-phase.md +3 -10
  134. package/pp-core/workflows/execute-phase/steps/check-query-gate.md +329 -0
  135. package/pp-core/workflows/execute-phase/steps/client-context-gate.md +3 -2
  136. package/pp-core/workflows/execute-phase/steps/cross-ai-delegation.md +1 -1
  137. package/pp-core/workflows/execute-phase/steps/execute-pre-dispatch.md +98 -0
  138. package/pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
  139. package/pp-core/workflows/execute-phase/steps/post-merge-gate.md +6 -8
  140. package/pp-core/workflows/execute-phase/steps/vault-fetch.md +115 -14
  141. package/pp-core/workflows/execute-phase/steps/vault-load-gate.md +322 -18
  142. package/pp-core/workflows/execute-phase/steps/verifier-practice-payload.md +165 -0
  143. package/pp-core/workflows/execute-phase/steps/verify-post-gate.md +163 -0
  144. package/pp-core/workflows/execute-phase.md +154 -110
  145. package/pp-core/workflows/execute-plan.md +58 -4
  146. package/pp-core/workflows/fast.md +53 -0
  147. package/pp-core/workflows/help/modes/full.md +1 -0
  148. package/pp-core/workflows/init/steps/client-context-capture.md +101 -0
  149. package/pp-core/workflows/init/steps/gitlab-provisioning.md +130 -0
  150. package/pp-core/workflows/init/steps/project-md-deferral-narration.md +66 -0
  151. package/pp-core/workflows/init/steps/reachability-outcome.md +70 -0
  152. package/pp-core/workflows/init.md +232 -272
  153. package/pp-core/workflows/new-project.md +31 -23
  154. package/pp-core/workflows/plan-phase.md +99 -43
  155. package/pp-core/workflows/quick.md +120 -2
  156. package/pp-core/workflows/secure-phase.md +1 -1
  157. package/pp-core/workflows/ship.md +57 -24
  158. package/pp-core/workflows/update.md +3 -3
  159. package/pp-core/workflows/validate-phase.md +60 -1
  160. package/pp-core/workflows/vault-review.md +325 -0
  161. package/pp-core/workflows/verify-work.md +13 -12
  162. package/scripts/changeset/cli.cjs +6 -5
  163. package/scripts/changeset/lint.cjs +0 -0
  164. package/scripts/changeset/new.cjs +33 -50
  165. package/scripts/dev-env.cjs +25 -85
  166. package/scripts/gen-capability-registry.cjs +199 -0
  167. package/scripts/gen-practice-arithmetic-contract.cjs +412 -0
  168. package/scripts/lib/allowlist-ratchet.cjs +1 -103
  169. package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -2
  170. package/scripts/lint-docs-required.cjs +0 -0
  171. package/scripts/lint-pr-check-project-dir.cjs +1 -3
  172. package/scripts/lint-test-file-count.allowlist.json +13 -2
  173. package/scripts/practice-arithmetic-contract.allow.json +35 -0
  174. package/scripts/prompt-injection-scan.sh +22 -15
  175. package/scripts/record-vault-mode-golden.cjs +89 -0
  176. package/scripts/release-channel.cjs +0 -0
  177. package/scripts/sync-manifest-versions.cjs +5 -4
  178. package/scripts/sync-rulesets.sh +1 -1
  179. package/scripts/update-size-baseline.cjs +30 -274
  180. package/scripts/vault-calibrate.cjs +996 -0
  181. package/scripts/verify-opengsd-sweep.cjs +3 -5
  182. package/scripts/workflow-size.cjs +9 -61
  183. package/pp-core/bin/lib/dispatch-plan.cjs +0 -472
  184. package/pp-core/bin/lib/install-run.cjs +0 -536
  185. package/pp-core/bin/lib/phase-tier.cjs +0 -467
  186. package/pp-core/bin/lib/plan-graph.cjs +0 -368
  187. package/pp-core/references/planner-plan-graph.md +0 -66
  188. package/pp-core/workflows/execute-phase/steps/checkpoint-handling.md +0 -45
  189. package/pp-core/workflows/execute-phase/steps/install-run.md +0 -29
  190. package/pp-core/workflows/execute-phase/steps/phase-close-rebaseline.md +0 -23
  191. package/pp-core/workflows/execute-phase/steps/serial-group-dispatch.md +0 -72
  192. package/pp-core/workflows/plan-phase/steps/phase-tier.md +0 -34
  193. package/scripts/lib/size-budget.cjs +0 -311
  194. package/scripts/lint-neutrality-names.cjs +0 -694
  195. package/scripts/lint-org-coordinates.allowlist.json +0 -35
  196. package/scripts/lint-org-coordinates.cjs +0 -426
@@ -21,14 +21,22 @@ folder and has two parts:
21
21
  frontmatter. This is what a person (or an AI agent quoting the practice
22
22
  back to a person) reads.
23
23
 
24
- A malformed practice file is never treated as a fatal error. If a file is
25
- missing a required field, or a field has an unrecognized value, it is simply
24
+ When practices are gathered for planning, a malformed file is not fatal. If a
25
+ file is missing a required field, or a field has an unrecognized value, it is
26
26
  skipped with a plain-English warning explaining what was wrong — the rest of
27
- your practices still load normally.
27
+ your practices still load normally. And if a file is *understandable but not
28
+ entirely recognized* — say it uses a key your pp-core version is too old to
29
+ know about — it is not skipped at all: it still applies, and a warning names
30
+ what was not understood.
28
31
 
29
- ## The five frontmatter keys
32
+ **The vault audit is stricter, and it blocks.** Do not read the paragraph above
33
+ as the whole story before merging into a shared vault — see *What happens if a
34
+ file is malformed* at the end of this page.
30
35
 
31
- Every practice file's frontmatter needs exactly these five keys:
36
+ ## The six frontmatter keys
37
+
38
+ Every practice file's frontmatter needs the first five keys below. The sixth,
39
+ `check`, is optional.
32
40
 
33
41
  | Key | Meaning |
34
42
  |-----|---------|
@@ -37,6 +45,7 @@ Every practice file's frontmatter needs exactly these five keys:
37
45
  | `severity` | How strongly this practice should be enforced: `critical`, `warning`, or `info`. This is the same three-level scale used elsewhere in code review. |
38
46
  | `applies-to` | A list of file-path patterns (globs) this practice applies to, e.g. `src/**/*.ts`. **Required when `scope: scoped`. Must be left out entirely when `scope: global`.** |
39
47
  | `schemaVersion` | Always `1` for now. This lets a future pp-core version recognize practice files written for an older or newer format. |
48
+ | `check` | *Optional.* A small block declaring how this practice can be checked **mechanically** against a change set: which files to look at, and what text must or must not appear in them. Its file patterns use exactly the same glob syntax as `applies-to` — the "Supported glob syntax" table below is the one and only description of that syntax. See "The `check:` block". |
40
49
 
41
50
  ### `scoped` vs `global`
42
51
 
@@ -77,6 +86,73 @@ supported**. A practice whose `applies-to` uses unsupported syntax is
77
86
  skipped with a warning naming the offending glob; the rest of your
78
87
  practices still load normally.
79
88
 
89
+ ### The `check:` block
90
+
91
+ Most practices are judged by a person or an agent reading your description. A
92
+ `check:` block adds a second, **mechanical** judgement on top of that: pp-core
93
+ looks at the files a change actually touched and decides deterministically
94
+ whether your rule was followed.
95
+
96
+ A block has one required key and needs at least one of the other three:
97
+
98
+ | Key | Meaning |
99
+ |-----|---------|
100
+ | `files` | **Required.** The file patterns to look at, using the same syntax as the "Supported glob syntax" table above. At most `CHECK_FILES_CAP` patterns. |
101
+ | `require` | Exact pieces of text that **must** appear in each matched file. |
102
+ | `forbid` | Exact pieces of text that **must not** appear in any matched file. |
103
+ | `forbidMatch` | `true` when the rule is that these files should not exist at all — matching anything is itself the violation. Cannot be combined with `require` or `forbid`. |
104
+
105
+ ```markdown
106
+ ---
107
+ id: vue-components-need-test-ids
108
+ scope: scoped
109
+ severity: warning
110
+ applies-to: [src/**/*.vue]
111
+ schemaVersion: 1
112
+ check:
113
+ files: [src/**/*.vue]
114
+ require: [data-testid]
115
+ ---
116
+
117
+ Every Vue component exposes a `data-testid` so end-to-end tests can address it
118
+ without depending on class names or DOM structure.
119
+ ```
120
+
121
+ Three rules govern what you may write here, and they are not negotiable:
122
+
123
+ 1. **A check block is data, never code.** It is not a command, not a script, not
124
+ a shell fragment, not a module path, and not an expression to evaluate. There
125
+ is no field that runs anything, and there will not be one. The reason is that
126
+ your vault repository is fetched and read by every developer machine and CI
127
+ runner on the fleet — if merging a markdown file could run code, merging a
128
+ markdown file would be equivalent to running code everywhere.
129
+ 2. **No regular expression.** `require` and `forbid` entries are *literal text*,
130
+ compared by plain substring containment. `(a+)+$` in a `forbid` list means
131
+ those exact eight characters, not a pattern.
132
+ 3. **The glob syntax is the table above, and only that table.** This section
133
+ deliberately does not restate it, so the two can never drift apart.
134
+
135
+ The full reasoning is recorded in
136
+ `docs/adr/71924-declarative-check-blocks.md`.
137
+
138
+ `require`/`forbid` entries are bounded in both count and length
139
+ (`CHECK_TOKEN_COUNT_CAP` and `CHECK_TOKEN_MAX`), as `files` is by
140
+ `CHECK_FILES_CAP`. Read the shipped values from the engine rather than from this
141
+ page — the numbers live in the code so there is one place to check them. Going
142
+ over a cap does not silently trim your block: the whole block is dropped and a
143
+ warning tells you which cap was exceeded. When practices are gathered for
144
+ planning the practice still applies through its description; at the vault audit
145
+ a dropped block is a failure and **blocks**, exactly as any other unparseable
146
+ `check:` does. See *What happens if a file is malformed* below.
147
+
148
+ **Rollout order.** Merge a practice carrying a `check:` block into your vault
149
+ repository **only after** the pp-core release that understands `check:` blocks
150
+ has been verified as rolled out to every machine that reads the vault. An older
151
+ pp-core meeting a `check:` block does not fail, but it does not check anything
152
+ either — it applies the practice's description and warns that it did not
153
+ understand the key. Merging first would leave a governance rule reporting
154
+ nothing on part of the fleet.
155
+
80
156
  ## Writing the description body
81
157
 
82
158
  Underneath the frontmatter, write one or two plain-English sentences that say
@@ -108,12 +184,62 @@ rather than a hard rule.
108
184
 
109
185
  ## What happens if a file is malformed
110
186
 
111
- If a practice file is missing `id`, uses an unrecognized `severity` or
112
- `scope`, declares `applies-to` on a `global` practice (or omits it on a
113
- `scoped` one), or sets a `schemaVersion` this pp-core version does not
114
- understand, that one file is skipped with a warning explaining exactly what
115
- was wrong. Every other well-formed practice file still loads and is applied
116
- normally — one bad file never breaks the run.
187
+ **Read this before you merge anything into a shared vault.** A malformed file
188
+ behaves differently in the two places pp-core reads your vault, and the
189
+ difference is the difference between a warning and a stopped build.
190
+
191
+ **When practices are gathered for planning**, a malformed file is tolerated.
192
+ That is the behaviour described below.
193
+
194
+ **When the vault audit runs**, it is not. The audit is a *blocking* gate at both
195
+ `verify:post` and `ship:pre`: a file it cannot load is a failure, an unparseable
196
+ `check:` block is a failure, and any failure stops the run. It is deliberately
197
+ fail-closed — a governance rule that quietly does nothing is worse than no rule
198
+ at all — so it refuses rather than skipping past something it could not read.
199
+
200
+ **The practical consequence: one malformed file merged into a shared vault stops
201
+ the build on every machine that fetches it, not just yours.** Use
202
+ `/pp-vault-promote`, which refuses an invalid `check:` block before it reaches
203
+ the vault, rather than committing one by hand.
204
+
205
+ ### Skipped
206
+
207
+ A practice file is skipped when it is missing `id`, has an `id` that does not
208
+ match its filename, uses an unrecognized `severity` or `scope`, declares
209
+ `applies-to` on a `global` practice (or omits it on a `scoped` one), uses
210
+ unsupported glob syntax, or sets a malformed `schemaVersion`.
211
+
212
+ *Gathering for planning:* that one file is skipped with a warning explaining
213
+ exactly what was wrong, and every other well-formed practice file still loads
214
+ and is applied normally.
215
+
216
+ *The audit:* the skipped file is reported as a failure and **blocks**.
217
+
218
+ ### Degraded
219
+
220
+ A practice file is degraded when it is structurally fine but uses something this
221
+ pp-core version does not recognize — a frontmatter key it has never heard of
222
+ (including a typo like `applies_to`), or a `schemaVersion` newer than it
223
+ supports. It is **not** skipped: it loads, its description still applies exactly
224
+ as written, and a warning names what was not understood. pp-core never drops a
225
+ practice merely because part of it was written for a newer engine.
226
+
227
+ *The audit:* a degraded file whose problem is only an unknown key or a newer
228
+ `schemaVersion` does not block. **A broken `check:` block is not in this
229
+ category** — see below.
230
+
231
+ ### A `check:` block that will not parse
232
+
233
+ This is the case authors most often expect to be lenient, and it is the least
234
+ lenient of the three. A `check:` block that breaks any of the rules above —
235
+ including going over `CHECK_FILES_CAP`, `CHECK_TOKEN_COUNT_CAP` or
236
+ `CHECK_TOKEN_MAX` — is dropped whole.
237
+
238
+ *Gathering for planning:* the practice still applies through its description,
239
+ and a warning names the defect.
240
+
241
+ *The audit:* an unparseable `check:` block is a failure and **blocks**. A
242
+ dropped block must never read as a check that passed.
117
243
 
118
244
  ## Getting started
119
245
 
@@ -0,0 +1,226 @@
1
+ # Project Charter Template
2
+
3
+ Template for `.planning/discovery/PROJECT-CHARTER.md`, the document every stakeholder signs at the end
4
+ of a Discovery Sprint.
5
+
6
+ **Purpose:** one short, fixed-shape document that states what will be built, why, for whom, how it will
7
+ be delivered and on what conditions, so that sign-off is a decision on the same questions in the same
8
+ order for every engagement. It summarises the thirteen session files; it does not replace them.
9
+
10
+ **When:** after Session 13 (wrap-up and Go / No-Go), before `/pp-discovery-to-build`.
11
+
12
+ **Shape is fixed.** Every charter has the same 14 numbered sections in the same order, with the same
13
+ headings and the same table columns. A section with nothing to report stays in place and says so; it is
14
+ never dropped, merged or renumbered. That is what lets a reader compare two charters side by side.
15
+
16
+ ---
17
+
18
+ ## File Template
19
+
20
+ ```markdown
21
+ ---
22
+ document: project-charter
23
+ project: [Project name]
24
+ client: [Client name]
25
+ version: [1.0]
26
+ status: [Draft | For sign-off | Signed | Signed with conditions | Rejected]
27
+ date: [YYYY-MM-DD]
28
+ discovery_sessions_completed: [N]/13
29
+ go_no_go: [Go | Go with conditions | No-Go]
30
+ ---
31
+
32
+ # [Project name] — Project Charter
33
+
34
+ > [One sentence: what this project delivers, for whom, and why now.]
35
+
36
+ | Document control | |
37
+ |---|---|
38
+ | Client | [Client name] |
39
+ | Version / status | [1.0] · [Draft] |
40
+ | Date | [YYYY-MM-DD] |
41
+ | Prepared by | [Name, role] |
42
+ | Based on | Discovery Sprint sessions 1–13, completed [YYYY-MM-DD] |
43
+
44
+ ---
45
+
46
+ ## 1. Purpose and background
47
+
48
+ [Two to four sentences: the business problem and why it matters now.]
49
+
50
+ **Top pain points today**
51
+
52
+ | # | Pain point | Who is affected | Impact |
53
+ |---|---|---|---|
54
+ | 1 | | | |
55
+
56
+ ## 2. Objectives and success measures
57
+
58
+ | # | Objective | KPI | Baseline | Target | Measured by |
59
+ |---|---|---|---|---|---|
60
+ | O-1 | | | | | |
61
+
62
+ ## 3. Scope
63
+
64
+ **In scope (MVP)**
65
+
66
+ | EPIC | Title | Priority |
67
+ |---|---|---|
68
+ | | | |
69
+
70
+ **Out of scope**
71
+
72
+ - [Item] — [reason or later release]
73
+
74
+ **Requirements:** [N] functional, [N] non-functional, [N] business rules, as registered in
75
+ `_requirements.md`.
76
+
77
+ ## 4. Stakeholders and users
78
+
79
+ | Stakeholder | Role | Decision authority | Involvement |
80
+ |---|---|---|---|
81
+ | | | | |
82
+
83
+ | Persona | Description | Main goal |
84
+ |---|---|---|
85
+ | | | |
86
+
87
+ ## 5. Solution overview
88
+
89
+ [Two to four sentences: the shape of the solution.]
90
+
91
+ | Layer | Choice | Decision |
92
+ |---|---|---|
93
+ | Frontend | | [D-05-n] |
94
+ | Backend | | |
95
+ | Data | | |
96
+ | Hosting | | |
97
+ | Identity | | |
98
+
99
+ **Integrations**
100
+
101
+ | System | Direction | Purpose |
102
+ |---|---|---|
103
+ | | | |
104
+
105
+ **Security and compliance:** [data classification, applicable regulations, availability target, in two to
106
+ four lines.]
107
+
108
+ ## 6. Quality and acceptance
109
+
110
+ | Gate | Criterion |
111
+ |---|---|
112
+ | UAT sign-off | [criteria] — approved by [role] |
113
+ | Go-live readiness | [criteria] |
114
+
115
+ ## 7. Delivery plan
116
+
117
+ | Milestone | Target date | Included EPICs | Exit criteria |
118
+ |---|---|---|---|
119
+ | [v1.0 — MVP] | | | |
120
+
121
+ **Build order:** [EPIC order and why.]
122
+
123
+ ## 8. Team and governance
124
+
125
+ | Role | Name / party | Responsibility |
126
+ |---|---|---|
127
+ | | | |
128
+
129
+ **Scope changes are approved by:** [role]. **Progress is reported:** [cadence, format].
130
+
131
+ ## 9. Budget, constraints and assumptions
132
+
133
+ | Type | Item | Source |
134
+ |---|---|---|
135
+ | Budget | [amount or "Not decided in Discovery — OI-n"] | |
136
+ | Constraint | | |
137
+ | Assumption | | |
138
+
139
+ ## 10. Risks
140
+
141
+ | # | Risk | Likelihood | Impact | Mitigation | Owner |
142
+ |---|---|---|---|---|---|
143
+ | R-1 | | | | | |
144
+
145
+ ## 11. Open items
146
+
147
+ | ID | Item | Must resolve before build? | Owner | Target date |
148
+ |---|---|---|---|---|
149
+ | OI-1 | | | | |
150
+
151
+ ## 12. Go / No-Go recommendation
152
+
153
+ | Criterion | Status | Note |
154
+ |---|---|---|
155
+ | Business requirements clarity | [Green / Amber / Red] | |
156
+ | Technical architecture feasibility | | |
157
+ | Security and compliance readiness | | |
158
+ | Integration dependencies resolved | | |
159
+ | Team and budget availability | | |
160
+ | Timeline confidence | | |
161
+ | Stakeholder alignment | | |
162
+ | **Overall recommendation** | **[Go / Go with conditions / No-Go]** | |
163
+
164
+ **Conditions:** [each condition attached to a Go, or "None".]
165
+
166
+ ## 13. Key decisions
167
+
168
+ | ID | Decision | Rationale | Owner |
169
+ |---|---|---|---|
170
+ | D-01-1 | | | |
171
+
172
+ ## 14. Sign-off
173
+
174
+ By signing, each party agrees that sections 1–13 describe the project to be built, subject to the
175
+ conditions stated.
176
+
177
+ | Role | Name | Decision | Conditions | Date | Signature |
178
+ |---|---|---|---|---|---|
179
+ | [Sponsor] | | [Approve / Approve with conditions / Reject] | | | |
180
+ | [Product owner] | | | | | |
181
+ | [Delivery lead] | | | | | |
182
+
183
+ ---
184
+
185
+ **Source files:** `.planning/discovery/session-01.md` … `session-13.md`, `_requirements.md`.
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Where each section comes from
191
+
192
+ Fill every section from the session tables below and nothing else. The session files are the source of
193
+ truth; the charter only condenses them.
194
+
195
+ | § | Section | Source (file § table) |
196
+ |---|---|---|
197
+ | — | Front matter, document control | `_progress.md` (completion dates); Session 1 § Stakeholder Register (client) |
198
+ | 1 | Purpose and background | Session 1 § Business Vision Summary; Session 2 § Pain Points Register (top 3–5 by impact) |
199
+ | 2 | Objectives and success measures | Session 3 § Business Objectives |
200
+ | 3 | Scope | Session 3 § MVP Scope Boundary and § EPIC Register; counts from the roll-up block in `_requirements.md` |
201
+ | 4 | Stakeholders and users | Session 1 § Stakeholder Register; Session 4 § Refined Personas (else Session 2 § User Personas) |
202
+ | 5 | Solution overview | Session 5 § Technology Stack Decisions and § Architecture Decision Records; Session 8 § Integration Design Register; Session 6 § Data Classification Matrix, § Compliance Requirements Register, § Availability and DR Targets; Session 7 § IdP Integration Design |
203
+ | 6 | Quality and acceptance | Session 9 § UAT Process and § Quality Gates; Session 10 § Go-Live Readiness Checklist |
204
+ | 7 | Delivery plan | Session 11 § Milestone Plan, § Project Timeline, § EPIC Build Order |
205
+ | 8 | Team and governance | Session 12 § Team Structure and § Governance Structure; reporting cadence from Session 12 topic "Communication and reporting" |
206
+ | 9 | Budget, constraints and assumptions | Session 1 § Constraints and Risks Register; any `[needs-business-input]` item still parked |
207
+ | 10 | Risks | Session 11 § Risk Register, plus open risks from Session 1 § Constraints and Risks Register |
208
+ | 11 | Open items | Session 13 § Open Items Register |
209
+ | 12 | Go / No-Go recommendation | Session 13 § Go / No-Go Assessment (copied as recorded, not re-scored) |
210
+ | 13 | Key decisions | § Key Decisions of every session — only decisions that change scope, architecture, cost or timeline |
211
+ | 14 | Sign-off | Session 1 § Stakeholder Register — every stakeholder with approval authority gets a row |
212
+
213
+ ## Fill rules
214
+
215
+ - **Never invent.** Every statement traces to a session table above. A value Discovery did not settle is
216
+ written as `Not decided in Discovery — OI-n`, and that item appears in § 11 Open items.
217
+ - **Keep the IDs.** Requirement, EPIC, decision (`D-<ss>-<n>`), risk and open-item IDs are copied
218
+ exactly as the session files write them, so every line can be traced back.
219
+ - **Condense, don't copy.** Tables carry the headline rows; the full detail stays in the session files.
220
+ Aim for a charter that reads in about fifteen minutes.
221
+ - **Fixed shape.** Keep all 14 sections, their numbers, headings and table columns. An empty section
222
+ says `None identified in Discovery.`
223
+ - **Go / No-Go is recorded, not re-judged.** § 12 copies Session 13's assessment and conditions verbatim.
224
+ - **Status follows the signatures.** `Draft` while being written, `For sign-off` once circulated,
225
+ `Signed` when every § 14 row says Approve, `Signed with conditions` when any row approves with
226
+ conditions, `Rejected` when any row rejects. A new version resets the status to `Draft`.
File without changes
@@ -67,6 +67,47 @@ Present banner:
67
67
  ```
68
68
  </step>
69
69
 
70
+ <step name="vault_admission_gate">
71
+ Vault admission and load gate (D-11, D-12, D-28): runs before a test is written or committed. A config the gate cannot
72
+ read halts here with the bindings present (D-05); without bindings, or with `vault.enabled` false,
73
+ nothing below prints or writes anything (D-13).
74
+
75
+ ```bash
76
+ VAULT_ADMIT_PRESENT=$(pp_run query platform-bindings --pick present 2>/dev/null || echo true)
77
+ VAULT_ADMIT=inert
78
+ if [ "$VAULT_ADMIT_PRESENT" = true ]; then VAULT_ADMIT=$(pp_run vault admission 2>/dev/null || echo unrecognised); fi
79
+ case "$VAULT_ADMIT" in on) echo "VAULT_ADMIT=on" ;; off|inert) : ;; *) pp_run vault admission --explain; echo "PARETO_GATE_BLOCKED:vault.admission"; exit 1 ;; esac
80
+ ```
81
+
82
+ **If the fence printed no `VAULT_ADMIT=on` line** (`off` and `inert` print nothing): skip the rest of this block silently. Otherwise run the load
83
+ gate on the `execute:pre` payload, filtered in the fence to the `vault` and `vault-practices`
84
+ capabilities (D-30):
85
+
86
+ ```bash
87
+ AT_EXECUTE_PRE_HOOKS_JSON=$(pp_run loop render-hooks execute:pre --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&(x.capId==='vault'||x.capId==='vault-practices'));process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
88
+ printf '%s' "$AT_EXECUTE_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('AT_EXECUTE_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
89
+ ```
90
+
91
+ Set `VAULT_FETCH_HOOKS_JSON=$AT_EXECUTE_PRE_HOOKS_JSON`, then Read and execute
92
+ `pp-core/workflows/execute-phase/steps/vault-fetch.md` (hook mode). Then, in the
93
+ `AT_EXECUTE_PRE_HOOKS_JSON=` line that fence printed, find active entries where `kind == "gate"` and `check.query ==
94
+ "vault.status"`; if none, skip silently. Otherwise set `GATE_POINT=execute:pre` and
95
+ `GATE_HOOKS_JSON=$AT_EXECUTE_PRE_HOOKS_JSON`, leave `GATE_POSITIONAL_ARG`, `GATE_WS` and
96
+ `GATE_STAGE` empty, then Read and follow `pp-core/workflows/execute-phase/steps/check-query-gate.md`;
97
+ it owns the halt.
98
+
99
+ Then record the door's START anchor, before the first test file is written (`execute_tdd_generation`) (D-31):
100
+
101
+ ```bash
102
+ pp_run vault door-record --begin --door add-tests --raw
103
+ ```
104
+
105
+ It records HEAD in `.planning/.vault-door-starts.json`, where the record step reads it back: a shell
106
+ variable would not survive into that later step, and the agent never types a sha. It prints nothing
107
+ and writes nothing unless `vault admission` answers `on`.
108
+ Take `padded_phase` from the same init JSON for the record below.
109
+ </step>
110
+
70
111
  <step name="analyze_implementation">
71
112
  Extract the list of files modified by the phase from SUMMARY.md ("Files Changed" or equivalent section).
72
113
 
@@ -311,6 +352,20 @@ git add {test files}
311
352
  git commit -m "test(phase-${phase_number}): add unit and E2E tests from add-tests command"
312
353
  ```
313
354
 
355
+ Vault door record (D-12): after the door's last source commit, set `DOOR_DIR="${phase_dir}"`,
356
+ `DOOR_PADDED="${padded_phase}"` and `DOOR_PHASE="${phase_number}"`, then run:
357
+
358
+ ```bash
359
+ DOOR_RUN=$(date -u +%Y%m%dT%H%M%SZ)
360
+ pp_run vault door-record --door add-tests --artifact "${DOOR_DIR}/${DOOR_PADDED}-door-${DOOR_RUN}-ADD-TESTS.md" --phase "$DOOR_PHASE" --raw
361
+ ```
362
+
363
+ The verb writes a `## Vault Door Record` (mode, vault ref and sha, governing phase, the start `--begin`
364
+ recorded and the end commit; the agent never types a sha) into a fresh per-run artifact, because it refuses a second record
365
+ in one file (D-57) and a rewritten report would drop the earlier run's coverage (D-79). It prints
366
+ nothing and writes nothing unless `vault admission` answers `on`. When it wrote the file and
367
+ `commit_docs` is true, commit the `artifact` path it printed: `pp_run query commit "docs(phase-${phase_number}): vault door record for add-tests" --files "<that artifact>"`.
368
+
314
369
  Present next steps:
315
370
 
316
371
  ```
@@ -91,6 +91,48 @@ If `--dry-run` was specified, **stop here and exit**. The classification table i
91
91
  final output — do not proceed to fixing.
92
92
  </step>
93
93
 
94
+ <step name="vault_admission_gate">
95
+ Skipped under `--dry-run` (nothing is fixed).
96
+
97
+ Vault admission and load gate (D-11, D-12, D-28): runs before any finding is fixed. A config the gate cannot
98
+ read halts here with the bindings present (D-05); without bindings, or with `vault.enabled` false,
99
+ nothing below prints or writes anything (D-13).
100
+
101
+ ```bash
102
+ VAULT_ADMIT_PRESENT=$(pp_run query platform-bindings --pick present 2>/dev/null || echo true)
103
+ VAULT_ADMIT=inert
104
+ if [ "$VAULT_ADMIT_PRESENT" = true ]; then VAULT_ADMIT=$(pp_run vault admission 2>/dev/null || echo unrecognised); fi
105
+ case "$VAULT_ADMIT" in on) echo "VAULT_ADMIT=on" ;; off|inert) : ;; *) pp_run vault admission --explain; echo "PARETO_GATE_BLOCKED:vault.admission"; exit 1 ;; esac
106
+ ```
107
+
108
+ **If the fence printed no `VAULT_ADMIT=on` line** (`off` and `inert` print nothing): skip the rest of this block silently. Otherwise run the load
109
+ gate on the `execute:pre` payload, filtered in the fence to the `vault` and `vault-practices`
110
+ capabilities (D-30):
111
+
112
+ ```bash
113
+ AF_EXECUTE_PRE_HOOKS_JSON=$(pp_run loop render-hooks execute:pre --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&(x.capId==='vault'||x.capId==='vault-practices'));process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
114
+ printf '%s' "$AF_EXECUTE_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('AF_EXECUTE_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
115
+ ```
116
+
117
+ Set `VAULT_FETCH_HOOKS_JSON=$AF_EXECUTE_PRE_HOOKS_JSON`, then Read and execute
118
+ `pp-core/workflows/execute-phase/steps/vault-fetch.md` (hook mode). Then, in the
119
+ `AF_EXECUTE_PRE_HOOKS_JSON=` line that fence printed, find active entries where `kind == "gate"` and `check.query ==
120
+ "vault.status"`; if none, skip silently. Otherwise set `GATE_POINT=execute:pre` and
121
+ `GATE_HOOKS_JSON=$AF_EXECUTE_PRE_HOOKS_JSON`, leave `GATE_POSITIONAL_ARG`, `GATE_WS` and
122
+ `GATE_STAGE` empty, then Read and follow `pp-core/workflows/execute-phase/steps/check-query-gate.md`;
123
+ it owns the halt.
124
+
125
+ Then record the door's START anchor, before the first `pp-executor` spawn of the fix loop (D-31):
126
+
127
+ ```bash
128
+ pp_run vault door-record --begin --door audit-fix --raw
129
+ ```
130
+
131
+ It records HEAD in `.planning/.vault-door-starts.json`, where the record step reads it back: a shell
132
+ variable would not survive into that later step, and the agent never types a sha. It prints nothing
133
+ and writes nothing unless `vault admission` answers `on`.
134
+ </step>
135
+
94
136
  <step name="fix-loop">
95
137
  For each **auto-fixable** finding (up to `--max`, ordered by severity desc):
96
138
 
@@ -140,6 +182,27 @@ must halt to avoid cascading issues. Remaining auto-fixable findings will appear
140
182
  report as `not-attempted`.
141
183
  </step>
142
184
 
185
+ <step name="vault_door_record">
186
+ After the loop, once for EACH phase directory whose findings were fixed in this run (the directory of
187
+ the UAT or VERIFICATION file the finding came from): the record's range, from the start captured
188
+ before the loop to HEAD now, covers every finding commit, and it lands in each fixed phase so that
189
+ phase's gate sees it.
190
+
191
+ Vault door record (D-12): after the door's last source commit, set `DOOR_DIR="<that phase directory>"`,
192
+ `DOOR_PADDED="<its padded phase>"` and `DOOR_PHASE="<that phase directory>"`, then run:
193
+
194
+ ```bash
195
+ DOOR_RUN=$(date -u +%Y%m%dT%H%M%SZ)
196
+ pp_run vault door-record --door audit-fix --artifact "${DOOR_DIR}/${DOOR_PADDED}-door-${DOOR_RUN}-AUDIT-FIX.md" --phase "$DOOR_PHASE" --raw
197
+ ```
198
+
199
+ The verb writes a `## Vault Door Record` (mode, vault ref and sha, governing phase, the start `--begin`
200
+ recorded and the end commit; the agent never types a sha) into a fresh per-run artifact, because it refuses a second record
201
+ in one file (D-57) and a rewritten report would drop the earlier run's coverage (D-79). It prints
202
+ nothing and writes nothing unless `vault admission` answers `on`. When it wrote the file and
203
+ `commit_docs` is true, commit the `artifact` path it printed: `pp_run query commit "docs: vault door record for audit-fix" --files "<that artifact>"`.
204
+ </step>
205
+
143
206
  <step name="report">
144
207
  Present the final summary:
145
208
 
@@ -146,7 +146,7 @@ For each REQ-ID, determine status using all three sources:
146
146
  Skip if the Nyquist capability is inactive.
147
147
 
148
148
  ```bash
149
- VERIFY_POST_HOOKS_JSON=$(pp_run loop render-hooks verify:post --raw) || exit 1
149
+ VERIFY_POST_HOOKS_JSON=$(pp_run loop render-hooks verify:post --raw)
150
150
  ```
151
151
 
152
152
  Resolve active step hooks from `VERIFY_POST_HOOKS_JSON` where `kind == "step"` and `ref.skill == "validate-phase"`.