@pareto4/pp-core 1.13.0 → 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 (201) hide show
  1. package/.claude-plugin/plugin.json +3 -3
  2. package/README.md +26 -9
  3. package/agents/pp-code-reviewer.md +2 -1
  4. package/agents/pp-debug-session-manager.md +9 -6
  5. package/agents/pp-executor.md +10 -13
  6. package/agents/pp-plan-checker.md +4 -4
  7. package/agents/pp-planner.md +23 -9
  8. package/agents/pp-vault-reviewer.md +244 -21
  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 +1 -1
  13. package/commands/pp-plan-phase.md +1 -2
  14. package/commands/pp-vault-review.md +5 -3
  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 +396 -82
  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 +3334 -946
  35. package/pp-core/bin/lib/clusters.cjs +3 -0
  36. package/pp-core/bin/lib/command-aliases.cjs +0 -35
  37. package/pp-core/bin/lib/commands.cjs +9 -4
  38. package/pp-core/bin/lib/compose-bindings.cjs +251 -88
  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 +4 -4
  43. package/pp-core/bin/lib/discovery-vault-check.cjs +246 -0
  44. package/pp-core/bin/lib/frontmatter.cjs +1 -38
  45. package/pp-core/bin/lib/git-base-branch.cjs +13 -11
  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 +648 -738
  49. package/pp-core/bin/lib/init-interactive.cjs +76 -4
  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 +189 -129
  54. package/pp-core/bin/lib/org-profile.cjs +469 -152
  55. package/pp-core/bin/lib/package-identity.cjs +3 -3
  56. package/pp-core/bin/lib/phase-command-router.cjs +1 -29
  57. package/pp-core/bin/lib/phase-scope.cjs +1 -1
  58. package/pp-core/bin/lib/phase.cjs +11 -253
  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 +650 -126
  66. package/pp-core/bin/lib/vault-command-router.cjs +2604 -367
  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 +139 -72
  71. package/pp-core/bin/lib/vault-review.cjs +194 -451
  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 +607 -254
  75. package/pp-core/bin/lib/vault-update.cjs +9 -33
  76. package/pp-core/bin/lib/vault-write-back.cjs +70 -42
  77. package/pp-core/bin/lib/vault.cjs +2734 -920
  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 -54
  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 +2 -2
  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 -25
  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 +17 -34
  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 +20 -23
  100. package/pp-core/workflows/_runtime-launcher.snippet.sh +0 -0
  101. package/pp-core/workflows/add-tests.md +55 -4
  102. package/pp-core/workflows/audit-fix.md +63 -2
  103. package/pp-core/workflows/audit-milestone.md +1 -1
  104. package/pp-core/workflows/autonomous.md +85 -11
  105. package/pp-core/workflows/check-todos.md +13 -2
  106. package/pp-core/workflows/code-review-fix.md +59 -3
  107. package/pp-core/workflows/code-review.md +10 -1
  108. package/pp-core/workflows/complete-milestone.md +1 -1
  109. package/pp-core/workflows/debug.md +54 -4
  110. package/pp-core/workflows/discovery-sprint/prefill.md +19 -7
  111. package/pp-core/workflows/discovery-sprint/prototype.md +46 -49
  112. package/pp-core/workflows/discovery-sprint/session-13-gates.md +2 -0
  113. package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +1 -3
  114. package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +1 -3
  115. package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +1 -3
  116. package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +20 -24
  117. package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +1 -3
  118. package/pp-core/workflows/discovery-sprint/sessions/06-security.md +1 -3
  119. package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +1 -3
  120. package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +1 -3
  121. package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +1 -3
  122. package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +1 -6
  123. package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +1 -3
  124. package/pp-core/workflows/discovery-sprint/sessions/12-delivery-model.md +1 -3
  125. package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +1 -3
  126. package/pp-core/workflows/discovery-sprint/templates/context-template.md +1 -1
  127. package/pp-core/workflows/discovery-sprint/vault-context.md +213 -0
  128. package/pp-core/workflows/discovery-sprint.md +7 -3
  129. package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +4 -4
  130. package/pp-core/workflows/discovery-to-build/templates/pp-handoff.md +43 -1
  131. package/pp-core/workflows/discovery-to-build.md +10 -2
  132. package/pp-core/workflows/discuss-phase.md +3 -10
  133. package/pp-core/workflows/execute-phase/steps/check-query-gate.md +329 -0
  134. package/pp-core/workflows/execute-phase/steps/client-context-gate.md +3 -2
  135. package/pp-core/workflows/execute-phase/steps/cross-ai-delegation.md +1 -1
  136. package/pp-core/workflows/execute-phase/steps/execute-pre-dispatch.md +98 -0
  137. package/pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
  138. package/pp-core/workflows/execute-phase/steps/post-merge-gate.md +6 -8
  139. package/pp-core/workflows/execute-phase/steps/vault-fetch.md +115 -14
  140. package/pp-core/workflows/execute-phase/steps/vault-load-gate.md +322 -20
  141. package/pp-core/workflows/execute-phase/steps/verifier-practice-payload.md +165 -0
  142. package/pp-core/workflows/execute-phase/steps/verify-post-gate.md +163 -0
  143. package/pp-core/workflows/execute-phase.md +155 -128
  144. package/pp-core/workflows/execute-plan.md +56 -6
  145. package/pp-core/workflows/fast.md +53 -4
  146. package/pp-core/workflows/help/modes/full.md +3 -3
  147. package/pp-core/workflows/init/steps/client-context-capture.md +101 -0
  148. package/pp-core/workflows/init/steps/gitlab-provisioning.md +130 -0
  149. package/pp-core/workflows/init/steps/project-md-deferral-narration.md +66 -0
  150. package/pp-core/workflows/init/steps/reachability-outcome.md +70 -0
  151. package/pp-core/workflows/init.md +232 -272
  152. package/pp-core/workflows/new-project.md +31 -23
  153. package/pp-core/workflows/plan-phase.md +98 -45
  154. package/pp-core/workflows/quick.md +117 -3
  155. package/pp-core/workflows/secure-phase.md +1 -1
  156. package/pp-core/workflows/ship.md +57 -28
  157. package/pp-core/workflows/undo.md +1 -1
  158. package/pp-core/workflows/update.md +3 -3
  159. package/pp-core/workflows/validate-phase.md +58 -3
  160. package/pp-core/workflows/vault-review.md +282 -22
  161. package/pp-core/workflows/verify-work.md +12 -14
  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 -11
  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 +12 -10
  173. package/scripts/practice-arithmetic-contract.allow.json +35 -0
  174. package/scripts/prompt-injection-scan.sh +22 -17
  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 -483
  184. package/pp-core/bin/lib/install-run.cjs +0 -536
  185. package/pp-core/bin/lib/loop-gates.cjs +0 -213
  186. package/pp-core/bin/lib/phase-manifest.cjs +0 -527
  187. package/pp-core/bin/lib/phase-tier.cjs +0 -480
  188. package/pp-core/bin/lib/plan-graph.cjs +0 -368
  189. package/pp-core/references/executor-vault-trace.md +0 -47
  190. package/pp-core/references/planner-plan-graph.md +0 -66
  191. package/pp-core/workflows/discovery-sprint/vault-fetch.md +0 -37
  192. package/pp-core/workflows/execute-phase/steps/checkpoint-handling.md +0 -45
  193. package/pp-core/workflows/execute-phase/steps/install-run.md +0 -29
  194. package/pp-core/workflows/execute-phase/steps/phase-close-rebaseline.md +0 -23
  195. package/pp-core/workflows/execute-phase/steps/serial-group-dispatch.md +0 -73
  196. package/pp-core/workflows/execute-phase/steps/vault-door-gate.md +0 -19
  197. package/pp-core/workflows/plan-phase/steps/phase-tier.md +0 -43
  198. package/scripts/lib/size-budget.cjs +0 -311
  199. package/scripts/lint-neutrality-names.cjs +0 -694
  200. package/scripts/lint-org-coordinates.allowlist.json +0 -35
  201. package/scripts/lint-org-coordinates.cjs +0 -426
@@ -52,7 +52,6 @@ const { getDeclaredMilestoneInfo, stripShippedMilestones, extractCurrentMileston
52
52
  // eslint-disable-next-line @typescript-eslint/no-require-imports
53
53
  const worktreeSafetyMod = require("./worktree-safety.cjs");
54
54
  const { inspectWorktreeHealth } = worktreeSafetyMod;
55
- const plan_graph_cjs_1 = require("./plan-graph.cjs");
56
55
  const { planningDir, milestonePathsFor, resolveProjectFile } = planningWorkspace;
57
56
  const { extractFrontmatter, parseMustHavesBlock } = frontmatterMod;
58
57
  const { writeStateMd } = stateMod;
@@ -541,16 +540,6 @@ function cmdVerifyPlanStructure(cwd, filePath, raw) {
541
540
  if (fm[field] === undefined)
542
541
  errors.push(`Missing required frontmatter field: ${field}`);
543
542
  }
544
- // `title:` is required on every plan not yet executed. A plan that already has a
545
- // SUMMARY predates the rule (or ran without it): its missing title only warns.
546
- const titleProblem = (0, plan_graph_cjs_1.planTitleProblem)(fm['title']);
547
- if (titleProblem) {
548
- const summaryPath = fullPath.replace(/PLAN\.md$/, 'SUMMARY.md');
549
- if (summaryPath !== fullPath && node_fs_1.default.existsSync(summaryPath))
550
- warnings.push(`${titleProblem} (executed plan: warning only)`);
551
- else
552
- errors.push(titleProblem);
553
- }
554
543
  const taskPattern = /<task[^>]*>([\s\S]*?)<\/task>/g;
555
544
  const tasks = [];
556
545
  let taskMatch;
@@ -22,7 +22,7 @@
22
22
  #
23
23
  # MEASURED exit-code matrix (macOS 26.5, bash 3.2.57, no timeout and no
24
24
  # gtimeout on PATH, perl at /usr/bin/perl; re-measured 2026-09-19 and pinned by
25
- # tests/gate-shell-owners.test.cjs):
25
+ # tests/feat-73988-gate-shell-owners.test.cjs):
26
26
  #
27
27
  # run_with_timeout 1 sleep 5 -> 142 (perl) / 124 (GNU)
28
28
  # run_with_timeout 5 bash -c '<missing command>' -> 127 under every backend
@@ -178,7 +178,6 @@
178
178
  *
179
179
  * Loop Extension Point Queries (ADR-857 phase 3c):
180
180
  * loop render-hooks <point> Resolve + render active Capability hooks at a loop point
181
- * loop run-gates <point> Run the active gates at a loop point (exit 1 on a halt)
182
181
  * Returns JSON envelope { point, activeHooks, rendered }
183
182
  * Valid points: discuss:pre/post, plan:pre/post,
184
183
  * execute:pre/wave:pre/wave:post/post, verify:pre/post, ship:pre/post
@@ -530,7 +529,7 @@ async function main() {
530
529
  'current-timestamp, detect-custom-files, discovery, docs-init, drift-guard, effort, extract-messages, find-phase, ' +
531
530
  'from-gsd2, frontmatter, gap-analysis, generate-claude-md, generate-claude-profile, ' +
532
531
  'generate-client-context, generate-dev-preferences, generate-slug, graphify, history-digest, init, init-contract, intel, ' +
533
- 'capability, classify-confidence, git, learnings, list-todos, loop, milestone, package-legitimacy, phase, phase-plan-index, phases, platform-bindings, profile-questionnaire, ' +
532
+ 'capability, classify-confidence, git, learnings, list-todos, loop, milestone, package-legitimacy, phase, phase-plan-index, phases, platform-bindings, platform-latest-tag, profile-questionnaire, ' +
534
533
  'profile-sample, progress, prompt-budget, requirements, research-plan, research-store, resolve-granularity, resolve-model, roadmap, scaffold, state, ' +
535
534
  'task, template, user-story, validate, validate-bindings, verify, verify-path-exists, verify-summary, workstream, worktree\n\n' +
536
535
  'Global flags:\n' +
@@ -728,15 +727,13 @@ function createReadlinePrompter({ input = process.stdin, output = process.stdout
728
727
  .join(' / ');
729
728
  rendered += `\n Options: ${optionsRendered}`;
730
729
  }
731
- if (question.optionalAnswer) {
732
- // A detected org profile is a hint inside the prompt text, so no
733
- // option-less question carries a default and Enter always skips an
734
- // optional question. The question text may already carry the hint
735
- // (both org profile prompts do), so it is added only when absent (I-1).
736
- const skipHint = 'press Enter to skip';
737
- if (!String(question.prompt).toLowerCase().includes(skipHint.toLowerCase())) {
738
- rendered += `\n (${skipHint})`;
739
- }
730
+ if (question.optionalAnswer && !/press Enter to skip/i.test(question.prompt)) {
731
+ // UAT-13-F2: a detected org profile is a HINT inside the prompt text
732
+ // itself, so Enter always skips an optional question. The question
733
+ // text may already carry the skip hint (the org profile prompts do),
734
+ // so it is added only for an optional question whose text lacks it
735
+ // (I-1).
736
+ rendered += '\n (press Enter to skip)';
740
737
  }
741
738
  return new Promise((resolve) => {
742
739
  rl.question(`${rendered}\n> `, (answer) => resolve(answer));
@@ -751,6 +748,68 @@ function createReadlinePrompter({ input = process.stdin, output = process.stdout
751
748
  };
752
749
  }
753
750
 
751
+ /**
752
+ * The vault mode a mode-filtered hook is judged against (Phase 15 D-02). Built
753
+ * here, at the CLI entry, so the pure resolvers (`loop-resolver`,
754
+ * `capability-state`) never import the vault adapter. It asks
755
+ * `vaultModeVerdict`, the single mode owner that honours the org-profile
756
+ * ladder, and answers the mode only for an active gate with a cleanly
757
+ * resolved mode. Anything else, including a throw, is `null`: the undefined
758
+ * mode, fail-closed per D-28. `vault.cjs` is required lazily so commands that
759
+ * never render hooks do not load it.
760
+ */
761
+ function makeVaultModeResolver(cwd) {
762
+ return () => {
763
+ try {
764
+ const v = require('./lib/vault.cjs').vaultModeVerdict(cwd);
765
+ return v.active && v.ok ? v.mode : null;
766
+ } catch {
767
+ return null;
768
+ }
769
+ };
770
+ }
771
+
772
+ /**
773
+ * Does this project hold engine-written vault records? (Phase 16 D-19.) The
774
+ * predicate a seal gate (`onRecordedArtifacts: true`) is rendered under, built
775
+ * here at the CLI entry for the same reason as `makeVaultModeResolver`: the
776
+ * pure resolver never imports vault code. It asks the seal leaf's
777
+ * `hasRecordedVaultArtifacts`, which is bindings-first (D-42) and answers true
778
+ * when it cannot prove absence (D-44). A throw is `false`, the inert answer.
779
+ * Injected ONLY into `loop render-hooks`: `capability state` / `set` report
780
+ * activation, not render, so they never take it. Required lazily so commands
781
+ * that never render hooks do not load the leaf; the resolver memoises it per
782
+ * render and asks it only for an enabled, config-inactive seal gate.
783
+ */
784
+ function makeRecordedArtifactsResolver(cwd) {
785
+ return () => {
786
+ try {
787
+ return require('./lib/vault-seal.cjs').hasRecordedVaultArtifacts(cwd) === true;
788
+ } catch {
789
+ return false;
790
+ }
791
+ };
792
+ }
793
+
794
+ /**
795
+ * Quick 261015-ect (QD-13): the `.platform-bindings.json` measurement
796
+ * `loop render-hooks` injects, built here at the CLI entry for the same reason
797
+ * as `makeVaultModeResolver`: the resolver imports no vault code (D-02). The
798
+ * reader is EXISTENCE, admission's own step 1 (`hasPlatformBindings`), so a
799
+ * malformed file counts as present and the fence's `vault admission` decides
800
+ * (D-47 b). A throw answers `null`, "could not measure", which the resolver
801
+ * renders through.
802
+ */
803
+ function makePlatformBindingsPresentResolver(cwd) {
804
+ return () => {
805
+ try {
806
+ return require('./lib/vault.cjs').hasPlatformBindings(cwd) === true;
807
+ } catch {
808
+ return null;
809
+ }
810
+ };
811
+ }
812
+
754
813
  async function runCommand(command, args, cwd, raw, defaultValue, originalCommand, workstreamContext = null) {
755
814
  switch (command) {
756
815
  case 'agent': {
@@ -784,6 +843,14 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
784
843
  break;
785
844
  }
786
845
 
846
+ case 'platform-latest-tag': {
847
+ // quick 261003-my0: the init.md / new-project.md preflights read
848
+ // `--pick latest` from here instead of composing the platform URL in
849
+ // shell — one owner (compose-bindings resolveLatestPlatformTag).
850
+ composeBindings.cmdPlatformLatestTag(cwd, args.slice(1), raw);
851
+ break;
852
+ }
853
+
787
854
  case 'validate-bindings': {
788
855
  platformBindings.cmdValidateBindings(cwd, args.slice(1), raw);
789
856
  break;
@@ -820,7 +887,6 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
820
887
  case 'init-contract': {
821
888
  // init-contract [--questions] [--verify] [--session-next]
822
889
  // [--session-answer <stepId>=<value>] [--session-reset] [--offline]
823
- // [--arm-vault]
824
890
  // --questions (also the no-flag default, D-05): read-only, always
825
891
  // exits 0, prints the canonical /pp-init question set as data.
826
892
  // --verify: runs the end-state invariant check (Phase 34-07 gap
@@ -835,6 +901,20 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
835
901
  // BEFORE the unrecognized-flag scan below since the payload itself
836
902
  // is not a flag. --offline forwards to every composeBindings call
837
903
  // the session makes (parity with compose-bindings --offline).
904
+ // --record-probe <passed|failed>=<note> / --defer-probe <reason>
905
+ // (Phase 7, plan 07-01 — D-07-03, OD-2): the WRITE side of /pp-init
906
+ // Step 2.6's reachability proof. Both take their payload as the NEXT
907
+ // argv token for the same reason --session-answer does — the payload
908
+ // is operator prose and would otherwise be read as a flag — and both
909
+ // are extracted BEFORE the unrecognized-flag scan below. The record is
910
+ // written by recordProbeOutcome/recordProbeDeferral in
911
+ // src/init-contract.cts; --verify reads it back from plan 07-07 on
912
+ // (D-07-04), which is what stops a committed deferral from passing
913
+ // silently forever.
914
+ // --arm-vault (quick 261003-kmd): non-interactive — composes the
915
+ // client-vault binding from the resolved org profile and arms the three
916
+ // vault keys where absent; /pp-new-project calls it. Inert (exit 0,
917
+ // armed:false) when no profile resolves; ok:false means run /pp-init.
838
918
  const icArgs = args.slice(1);
839
919
  let sessionAnswerRaw;
840
920
  const saIdx = icArgs.indexOf('--session-answer');
@@ -849,12 +929,38 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
849
929
  }
850
930
  icArgs.splice(saIdx, 2);
851
931
  }
932
+ let recordProbeRaw;
933
+ const rpIdx = icArgs.indexOf('--record-probe');
934
+ if (rpIdx !== -1) {
935
+ recordProbeRaw = icArgs[rpIdx + 1];
936
+ if (!recordProbeRaw || recordProbeRaw.startsWith('--')) {
937
+ error(
938
+ 'Missing value for --record-probe. Usage: --record-probe <passed|failed>=<note>',
939
+ ERROR_REASON.SDK_MISSING_ARG,
940
+ );
941
+ break;
942
+ }
943
+ icArgs.splice(rpIdx, 2);
944
+ }
945
+ let deferProbeRaw;
946
+ const dpIdx = icArgs.indexOf('--defer-probe');
947
+ if (dpIdx !== -1) {
948
+ deferProbeRaw = icArgs[dpIdx + 1];
949
+ if (!deferProbeRaw || deferProbeRaw.startsWith('--')) {
950
+ error(
951
+ 'Missing value for --defer-probe. Usage: --defer-probe "<reason>"',
952
+ ERROR_REASON.SDK_MISSING_ARG,
953
+ );
954
+ break;
955
+ }
956
+ icArgs.splice(dpIdx, 2);
957
+ }
852
958
  const unrecognizedIcFlag = icArgs.find(
853
959
  (a) => a.startsWith('--') && !initContract.INIT_CONTRACT_FLAGS.includes(a),
854
960
  );
855
961
  if (unrecognizedIcFlag !== undefined) {
856
962
  error(
857
- `Unrecognized flag "${unrecognizedIcFlag}" for init-contract. Supported: --questions, --verify, --session-next, --session-answer, --session-reset, --offline, --arm-vault.`,
963
+ `Unrecognized flag "${unrecognizedIcFlag}" for init-contract. Supported: --questions, --verify, --session-next, --session-answer, --session-reset, --offline, --record-probe, --defer-probe, --arm-vault.`,
858
964
  ERROR_REASON.SDK_FAIL_FAST,
859
965
  );
860
966
  break;
@@ -873,7 +979,6 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
873
979
  } else if (a === '--offline') {
874
980
  icOptions.offline = true;
875
981
  } else if (a === '--arm-vault') {
876
- // Pack 6 D-09: set vault.enabled true only where absent.
877
982
  icOptions.armVault = true;
878
983
  }
879
984
  }
@@ -891,6 +996,25 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
891
996
  value: sessionAnswerRaw.slice(eqIdx + 1),
892
997
  };
893
998
  }
999
+ if (recordProbeRaw !== undefined) {
1000
+ // Split at the FIRST "=" only: the status is a closed vocabulary with
1001
+ // no "=" in it, and the note is free prose that may well contain one.
1002
+ const rpEq = recordProbeRaw.indexOf('=');
1003
+ if (rpEq === -1) {
1004
+ error(
1005
+ `Invalid --record-probe value "${recordProbeRaw}" — expected <passed|failed>=<note>.`,
1006
+ ERROR_REASON.USAGE,
1007
+ );
1008
+ break;
1009
+ }
1010
+ icOptions.recordProbe = {
1011
+ status: recordProbeRaw.slice(0, rpEq),
1012
+ note: recordProbeRaw.slice(rpEq + 1),
1013
+ };
1014
+ }
1015
+ if (deferProbeRaw !== undefined) {
1016
+ icOptions.deferProbe = deferProbeRaw;
1017
+ }
894
1018
  initContract.cmdInitContract(cwd, icOptions, raw);
895
1019
  break;
896
1020
  }
@@ -1547,7 +1671,7 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
1547
1671
  }
1548
1672
 
1549
1673
  case 'loop': {
1550
- // loop render-hooks <point> [--config-dir <dir>] [--active-cap <capId>] [--into <role>] [--phase <N>] [--tier <t>]
1674
+ // loop render-hooks <point> [--config-dir <dir>] [--active-cap <capId>] [--into <role>]
1551
1675
  const loopSubcommand = args[1];
1552
1676
  if (loopSubcommand === 'render-hooks') {
1553
1677
  let loopConfigDir = null;
@@ -1579,50 +1703,33 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
1579
1703
  }
1580
1704
  loopActiveCap = value;
1581
1705
  }
1582
- // --phase <N> / --tier <light|standard|heavy>: resolve the phase's
1583
- // ceremony tier and read the gate booleans from it (pack 9).
1584
- const loopValue = (flag) => {
1585
- const eq = args.find(arg => arg.startsWith(`--${flag}=`));
1586
- if (eq) return eq.slice(flag.length + 3).trim();
1587
- const idx = args.indexOf(`--${flag}`);
1588
- if (idx === -1) return undefined;
1589
- const value = args[idx + 1];
1706
+ // --into <role>: print the fragment text of active contributions into <role>
1707
+ // (Phase 15 D-12/D-30; execute-phase interpolates it into the spawn prompt)
1708
+ let loopInto = undefined;
1709
+ const intoEqArg = args.find(arg => arg.startsWith('--into='));
1710
+ const intoIdx = args.indexOf('--into');
1711
+ if (intoEqArg) {
1712
+ const value = intoEqArg.slice('--into='.length).trim();
1713
+ if (!value) error('Missing value for --into (e.g. --into executor)', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
1714
+ loopInto = value;
1715
+ } else if (intoIdx !== -1) {
1716
+ const value = args[intoIdx + 1];
1590
1717
  if (!value || value.startsWith('--')) {
1591
- error(`Missing value for --${flag}`, ERROR_REASON ? ERROR_REASON.USAGE : undefined);
1718
+ error('Missing value for --into (e.g. --into executor)', ERROR_REASON ? ERROR_REASON.USAGE : undefined);
1592
1719
  }
1593
- return value;
1594
- };
1720
+ loopInto = value;
1721
+ }
1595
1722
  loopResolver.cmdLoopRenderHooks(cwd, args[2], raw, {
1596
1723
  configDir: loopConfigDir ? path.resolve(loopConfigDir) : undefined,
1597
1724
  activeCap: loopActiveCap,
1598
- phase: loopValue('phase'),
1599
- tier: loopValue('tier'),
1600
- // --into <role>: print the fragment text of active contributions into <role>
1601
- into: loopValue('into'),
1602
- });
1603
- } else if (loopSubcommand === 'run-gates') {
1604
- // loop run-gates <point> [--phase <N>] [--tier <t>] [--query <q>]: run the point's
1605
- // active gates (only those whose check.query is <q>, when given) under the
1606
- // two-step gate contract; exit 1 on a halt.
1607
- const gateValue = (flag) => {
1608
- const eq = args.find(arg => arg.startsWith(`--${flag}=`));
1609
- if (eq) return eq.slice(flag.length + 3).trim();
1610
- const idx = args.indexOf(`--${flag}`);
1611
- if (idx === -1) return undefined;
1612
- const value = args[idx + 1];
1613
- if (!value || value.startsWith('--')) {
1614
- error(`Missing value for --${flag}`, ERROR_REASON ? ERROR_REASON.USAGE : undefined);
1615
- }
1616
- return value;
1617
- };
1618
- require('./lib/loop-gates.cjs').cmdLoopRunGates(cwd, args[2], raw, {
1619
- phase: gateValue('phase'),
1620
- tier: gateValue('tier'),
1621
- query: gateValue('query'),
1725
+ into: loopInto,
1726
+ resolveVaultMode: makeVaultModeResolver(cwd),
1727
+ resolveRecordedArtifacts: makeRecordedArtifactsResolver(cwd),
1728
+ resolvePlatformBindingsPresent: makePlatformBindingsPresentResolver(cwd),
1622
1729
  });
1623
1730
  } else {
1624
1731
  error(
1625
- `Unknown loop subcommand: ${loopSubcommand}. Available: render-hooks, run-gates`,
1732
+ `Unknown loop subcommand: ${loopSubcommand}. Available: render-hooks`,
1626
1733
  ERROR_REASON ? ERROR_REASON.SDK_UNKNOWN_COMMAND : undefined,
1627
1734
  );
1628
1735
  }
@@ -1649,7 +1756,9 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
1649
1756
  configDir = configDirVal;
1650
1757
  }
1651
1758
  const resolvedConfigDir = configDir ? path.resolve(configDir) : null;
1652
- capabilityState.cmdCapabilityState(cwd, resolvedConfigDir, raw, {});
1759
+ capabilityState.cmdCapabilityState(cwd, resolvedConfigDir, raw, {
1760
+ resolveVaultMode: makeVaultModeResolver(cwd),
1761
+ });
1653
1762
  } else if (capSubcommand === 'set') {
1654
1763
  // capability set <id> [--on|--off|--enable|--disable] [--gate <key>=<bool>]... [--config-dir <dir>] [--runtime <r>] [--scope <s>]
1655
1764
  const capId = args[2];
@@ -1723,7 +1832,14 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
1723
1832
  cwd,
1724
1833
  resolvedSetConfigDir,
1725
1834
  capId,
1726
- { enabled: setEnabled, gates: Object.keys(setGates).length > 0 ? setGates : undefined, runtime: setRuntime, scope: setScope },
1835
+ {
1836
+ enabled: setEnabled,
1837
+ gates: Object.keys(setGates).length > 0 ? setGates : undefined,
1838
+ runtime: setRuntime,
1839
+ scope: setScope,
1840
+ // 15-REVIEW WR-07: the same mode `capability state` and render-hooks use.
1841
+ resolveVaultMode: makeVaultModeResolver(cwd),
1842
+ },
1727
1843
  raw,
1728
1844
  );
1729
1845
  } else {
@@ -2410,6 +2526,13 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
2410
2526
  // Lists every functional element of the prototype under
2411
2527
  // .planning/discovery/prototype/ so each is decided once in _sweep.md;
2412
2528
  // --check fails (discovery_element_sweep_failed) while one is undecided.
2529
+ //
2530
+ // discovery vault-check <session>
2531
+ //
2532
+ // Checks the `## Vault Context` record of .planning/discovery/session-NN.md:
2533
+ // the index the selection used, one well-formed line per selected vault
2534
+ // document, and that each was cited [vault: <path>] in the notes or marked
2535
+ // not used with a reason. Any gap fails (discovery_vault_check_failed).
2413
2536
 
2414
2537
  case 'discovery': {
2415
2538
  const subcommand = args[1];
@@ -2455,13 +2578,20 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
2455
2578
  } catch (rebaselineCheckErr) {
2456
2579
  error(`discovery rebaseline-check: ${rebaselineCheckErr && rebaselineCheckErr.message ? rebaselineCheckErr.message : String(rebaselineCheckErr)}`, ERROR_REASON.UNKNOWN);
2457
2580
  }
2581
+ } else if (subcommand === 'vault-check') {
2582
+ const vaultCheck = require('./lib/discovery-vault-check.cjs');
2583
+ try {
2584
+ vaultCheck.cmdDiscoveryVaultCheck(cwd, args, raw);
2585
+ } catch (vaultCheckErr) {
2586
+ error(`discovery vault-check: ${vaultCheckErr && vaultCheckErr.message ? vaultCheckErr.message : String(vaultCheckErr)}`, ERROR_REASON.UNKNOWN);
2587
+ }
2458
2588
  } else {
2459
2589
  // WIRING, NOT HELP TEXT: tests/discovery-artifacts.test.cjs derives each
2460
2590
  // subcommand spelling by regexing `<namespace>_<subcommand>_failed` out of
2461
2591
  // the engine's exported exit identity, splits this string on commas and
2462
2592
  // asserts membership. A spelling missing here is a command the engine
2463
2593
  // claims to be and the router does not dispatch.
2464
- error('Unknown discovery subcommand. Available: rollup, input-check, research-check, screen-check, element-sweep, rebaseline-check', ERROR_REASON.SDK_UNKNOWN_COMMAND);
2594
+ error('Unknown discovery subcommand. Available: rollup, input-check, research-check, screen-check, element-sweep, rebaseline-check, vault-check', ERROR_REASON.SDK_UNKNOWN_COMMAND);
2465
2595
  }
2466
2596
  break;
2467
2597
  }
@@ -93,12 +93,5 @@
93
93
  "plan_review": {
94
94
  "source_grounding": true,
95
95
  "source_grounding_authority": "grep"
96
- },
97
- "size_budget": {
98
- "per_file_bytes": 1024,
99
- "per_commit_bytes": 4096
100
- },
101
- "phase": {
102
- "tier": "standard"
103
96
  }
104
97
  }
@@ -31,9 +31,6 @@
31
31
  "workflow.plan_bounce",
32
32
  "workflow.plan_bounce_script",
33
33
  "workflow.plan_bounce_passes",
34
- "size_budget.per_file_bytes",
35
- "size_budget.per_commit_bytes",
36
- "phase.tier",
37
34
  "workflow.plan_chunked",
38
35
  "workflow.plan_review_convergence",
39
36
  "code_quality.fallow.enabled",
@@ -155,7 +155,7 @@
155
155
  "pp-intel-updater": { "golden": "opus", "balanced": "sonnet", "budget": "haiku", "phaseType": "research", "routingTier": "light" },
156
156
  "pp-mempalace-curator": { "golden": "sonnet", "balanced": "sonnet", "budget": "haiku", "phaseType": "research", "routingTier": "light" },
157
157
  "pp-security-auditor": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "verification", "routingTier": "heavy" },
158
- "pp-user-profiler": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "research", "routingTier": "heavy" },
159
- "pp-vault-reviewer": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "verification", "routingTier": "heavy" }
158
+ "pp-vault-reviewer": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "verification", "routingTier": "heavy" },
159
+ "pp-user-profiler": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "research", "routingTier": "heavy" }
160
160
  }
161
161
  }
File without changes
@@ -0,0 +1,26 @@
1
+ {
2
+ "vault": {
3
+ "provider": "github",
4
+ "fallback_repo": ""
5
+ },
6
+ "platform": {
7
+ "host": "github.com"
8
+ },
9
+ "bindings": {
10
+ "platform": {
11
+ "repo": "pareto000/Pareto-Platform"
12
+ },
13
+ "client": {
14
+ "vaultRepo": "pareto000/Pareto-Vault",
15
+ "vaultHost": "github.com"
16
+ },
17
+ "provisioning": {
18
+ "group": "pareto000"
19
+ }
20
+ },
21
+ "init": {
22
+ "provider": "github",
23
+ "visibility": "private",
24
+ "derive_slugs": true
25
+ }
26
+ }
@@ -1,8 +1,9 @@
1
1
  # Autonomous — Best-Effort Rules
2
2
 
3
3
  This file is Read at the start of EVERY phase (`autonomous.md` §3, first line) and again at §6, so
4
- context compaction cannot erode the rules below. It contains bare `pp_run` calls and relies on the
5
- caller's launcher — it carries no preamble of its own.
4
+ context compaction cannot erode the rules below. It contains bare `pp_run` calls and, like
5
+ `pp-core/workflows/execute-phase/steps/check-query-gate.md`, relies on the caller's launcher — it
6
+ carries no preamble of its own.
6
7
 
7
8
  Mode model:
8
9
 
@@ -21,8 +22,8 @@ auto-advance into a second execute-phase.
21
22
 
22
23
  These stop the run in every mode. Best-effort never answers them.
23
24
 
24
- - Blocking capability `check.query` gates (`blocking: true` and `block: true`) — the host workflow
25
- HALTs, which ends the run like an `exit 1`; unchanged.
25
+ - Blocking `check.query` gates (vault `plan:pre`, security) — the enforcer prints its token and runs
26
+ `exit 1`; unchanged.
26
27
  - `human-action` checkpoints (auth/credentials) in execute-phase.
27
28
  - Any checkpoint with `gate="blocking-human"` — package legitimacy (`agents/pp-executor.md`,
28
29
  `agents/pp-planner.md`: never auto-approvable). Presented to the user under `UNATTENDED` and
@@ -297,13 +298,13 @@ calls (`pp-ui-phase`, `pp-code-review`, `pp-ui-review`) and the agents on the pa
297
298
  | execute-phase checkpoint_handling (`human-action`, `gate="blocking-human"`) | hard stop — U-E1 |
298
299
  | execute-phase/steps/cross-ai-delegation.md failure | converted — U-E8 |
299
300
  | execute-phase/steps/vault-load-gate.md, client-context-gate.md `confirmed` | hard stop (governance) |
300
- | execute-phase / plan-phase blocking capability `check.query` gates (`blocking: true`, `block: true`) | hard stop (HALT) |
301
+ | execute-phase/steps/check-query-gate.md, vault-fetch.md halt | hard stop (`exit 1`) |
301
302
  | execute-phase/steps/worktree-recovery-policy.md exit 42; execute-phase partial-execution recovery | hard stop (fail closed) |
302
303
  | execute-phase `state_exists` false; `--interactive` per-plan menu | unreachable — autonomous requires STATE.md and never passes `--interactive` to execute-phase |
303
304
  | post-merge-gate | build-failure "Fix now / Continue" (step 5.8) — this is the U-E2 site: fix once, then continue and record |
304
- | codebase-drift-gate, serial-group-dispatch, vault-fetch | no prompt (non-blocking) |
305
+ | codebase-drift-gate, per-plan-worktree-gate, execute-pre-dispatch, verify-post-gate, verifier-practice-payload | no prompt (non-blocking or gate-enforcer only) |
305
306
  | `pp-code-review --fix --auto` (3c.5) | no prompt |
306
- | **`pp-ui-phase`** (§3a.5): step 9 max-revision choice, and its `pp-ui-researcher` design questions | **remaining stop** — ui-phase has no non-interactive flag; filed as deferred |
307
+ | **`pp-ui-phase`** (§3a.5-ii): step 9 max-revision choice, and its `pp-ui-researcher` design questions | **remaining stop** — ui-phase has no non-interactive flag; filed as deferred |
307
308
  | **`pp-ui-review`** (§3d.5): "UI-REVIEW.md already exists" | **remaining stop** (only on a re-run) — no non-interactive flag; filed as deferred |
308
309
  | agents: `pp-planner` / `pp-phase-researcher` / `pp-executor` / `pp-verifier` returns | routed through the host sites above; `pp-executor`'s own auto-approve under `workflow.auto_advance` is filed as deferred (not reached — autonomous sets neither auto flag) |
309
310
 
@@ -5,14 +5,6 @@ in any host-loop workflow. This document is point-agnostic — it applies to eve
5
5
  extension point (discuss:pre, discuss:post, plan:pre, plan:post, execute:pre, execute:wave:pre,
6
6
  execute:wave:post, execute:post, verify:pre, verify:post, ship:pre, ship:post).
7
7
 
8
- Phase workflows pass `--phase <N> [--tier light|standard|heavy]`: the phase's ceremony tier
9
- (`pp_run query phase.tier <N>`) then decides the nine gate booleans (`workflow.research`,
10
- `workflow.pattern_mapper`, `workflow.plan_check`, `workflow.verifier`, `workflow.nyquist_validation`,
11
- `workflow.code_review`, `workflow.post_planning_gaps`, `workflow.security_enforcement`,
12
- `workflow.vault_review`) that hook
13
- `when` keys read, and the envelope carries `phase_tier`. Without `--phase` the project's own
14
- booleans are read.
15
-
16
8
  ## Envelope shape
17
9
 
18
10
  ```json
@@ -30,22 +22,12 @@ booleans are read.
30
22
  `activeHooks` is an array of enabled hook entries for the named point. It is empty (or absent)
31
23
  when no capability has registered an active hook at this point — treat that as a no-op.
32
24
 
33
- ## Refusal
34
-
35
- `render-hooks` refuses — exit 1, empty stdout, one stderr line naming each config file and its
36
- parse error — when a project config file exists but cannot be read (not JSON, or not a JSON
37
- object). A missing config is not refused. Every host writes `X=$(pp_run loop render-hooks …) || exit 1`,
38
- so a refusal stops the workflow: relay the stderr line and stop. Never read a refusal as "no hooks".
39
-
40
25
  ## Dispatch rules by `kind`
41
26
 
42
27
  ### `contribution`
43
28
 
44
29
  Inject `fragment.inline` verbatim into the context for the role named in `into`
45
30
  (e.g. `orchestrator`, `planner`). Do not paraphrase — the text is the product.
46
- `pp_run loop render-hooks <point> --into <role>` prints just those fragments, blank-line separated.
47
- An `execute:pre` contribution `into: executor` reaches every executor through `phase.dispatch-plan`:
48
- each spawn's `contributions[]` carries it, and the spawn prompt injects each `fragment` verbatim.
49
31
 
50
32
  ### `step`
51
33
 
@@ -73,13 +55,6 @@ Evaluate `check` (one of `query`, `predicate`, or `agentVerdict`). Then honor `b
73
55
  Honor `onError` if the check itself errors: `skip` means treat as non-blocking and continue;
74
56
  `fail` means surface the error and stop.
75
57
 
76
- `pp_run loop run-gates <point> --phase <N> [--query <q>]` applies this contract in code for every
77
- active `check.query` gate at the point (only those whose query is `<q>` with `--query`), appending
78
- the gate's declared `check.args` after the phase: exit 1 with a `⛔` line on a halt, `⚠` lines for
79
- advisories and skipped command errors, an `ℹ` line for a passing blocking gate's note, the verdict
80
- JSON on stdout. It runs every `verify:post` gate, and the `vault.trace` gate at `plan:post`,
81
- `execute:post` and `ship:pre` (`--query vault.trace`); the hosts' own gate loops skip that query.
82
-
83
58
  ## Empty / absent `activeHooks`
84
59
 
85
60
  If `activeHooks` is absent, null, or an empty array, skip silently and continue to the next
@@ -52,7 +52,6 @@ grep -l "status: diagnosed" "$phase_dir"/*-UAT.md 2>/dev/null
52
52
  ---
53
53
  phase: XX-name
54
54
  plan: NN # Sequential after existing
55
- title: "..." # REQUIRED one line
56
55
  type: execute
57
56
  wave: N # Computed from depends_on (see assign_waves)
58
57
  depends_on: [...] # Other plans this depends on (gap or existing)
@@ -18,7 +18,6 @@ TDD candidates identified in task_breakdown get dedicated plans (type: tdd). One
18
18
  ---
19
19
  phase: XX-name
20
20
  plan: NN
21
- title: "..."
22
21
  type: tdd
23
22
  ---
24
23