@pareto4/pp-core 1.18.0 → 1.20.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 (194) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/agents/pp-code-fixer.md +9 -5
  3. package/agents/pp-code-reviewer.md +1 -0
  4. package/agents/pp-codebase-mapper.md +3 -0
  5. package/agents/pp-debugger.md +3 -2
  6. package/agents/pp-executor.md +16 -7
  7. package/agents/pp-integration-checker.md +1 -0
  8. package/agents/pp-phase-researcher.md +13 -1
  9. package/agents/pp-plan-checker.md +3 -0
  10. package/agents/pp-planner.md +20 -1
  11. package/agents/pp-research-synthesizer.md +1 -1
  12. package/agents/pp-ui-auditor.md +1 -0
  13. package/agents/pp-ui-researcher.md +3 -1
  14. package/agents/pp-vault-reviewer.md +2 -0
  15. package/agents/pp-verifier.md +22 -10
  16. package/commands/pp-add-tests.md +1 -1
  17. package/commands/pp-debug.md +1 -0
  18. package/commands/pp-discovery.md +3 -2
  19. package/commands/pp-init.md +4 -3
  20. package/commands/pp-quick.md +3 -0
  21. package/commands/pp-review-backlog.md +2 -1
  22. package/gemini-extension.json +1 -1
  23. package/package.json +6 -3
  24. package/pareto-skills/_shared/pp-claude-md-protocol.md +1 -1
  25. package/pareto-skills/pp-project-setup/SKILL.md +18 -343
  26. package/pp-core/bin/lib/capability-registry.cjs +3 -3
  27. package/pp-core/bin/lib/check-command-router.cjs +60 -20
  28. package/pp-core/bin/lib/commands.cjs +79 -4
  29. package/pp-core/bin/lib/compose-bindings.cjs +97 -14
  30. package/pp-core/bin/lib/discovery-access.cjs +276 -0
  31. package/pp-core/bin/lib/discovery-charter.cjs +664 -0
  32. package/pp-core/bin/lib/discovery-deviations.cjs +264 -0
  33. package/pp-core/bin/lib/discovery-entities.cjs +323 -0
  34. package/pp-core/bin/lib/discovery-for-phase.cjs +628 -0
  35. package/pp-core/bin/lib/discovery-integrations.cjs +286 -0
  36. package/pp-core/bin/lib/discovery-migration.cjs +246 -0
  37. package/pp-core/bin/lib/discovery-phases.cjs +233 -0
  38. package/pp-core/bin/lib/discovery-processes.cjs +355 -0
  39. package/pp-core/bin/lib/discovery-research-track.cjs +5 -4
  40. package/pp-core/bin/lib/discovery-rollup.cjs +12 -8
  41. package/pp-core/bin/lib/discovery-rules.cjs +216 -0
  42. package/pp-core/bin/lib/discovery-screens.cjs +21 -3
  43. package/pp-core/bin/lib/discovery-session-check.cjs +264 -0
  44. package/pp-core/bin/lib/discovery-stories.cjs +273 -0
  45. package/pp-core/bin/lib/discovery-sweep.cjs +13 -4
  46. package/pp-core/bin/lib/discovery-table.cjs +55 -0
  47. package/pp-core/bin/lib/discovery-vault-check.cjs +37 -3
  48. package/pp-core/bin/lib/init-contract.cjs +48 -7
  49. package/pp-core/bin/lib/io.cjs +22 -0
  50. package/pp-core/bin/lib/vault-coordinates.cjs +1 -1
  51. package/pp-core/bin/lib/vault-index.cjs +18 -5
  52. package/pp-core/bin/lib/vault-standards-review.cjs +50 -2
  53. package/pp-core/bin/lib/vault-update.cjs +4 -0
  54. package/pp-core/bin/lib/vault.cjs +2 -2
  55. package/pp-core/bin/pp-tools.cjs +153 -5
  56. package/pp-core/org-profile.json +1 -1
  57. package/pp-core/references/autonomous-best-effort.md +3 -2
  58. package/pp-core/references/autonomous-lifecycle.md +1 -0
  59. package/pp-core/references/autonomous-smart-discuss.md +5 -1
  60. package/pp-core/references/discovery-access.md +112 -0
  61. package/pp-core/references/discovery-build-consumption.md +256 -0
  62. package/pp-core/references/discovery-charter.md +127 -0
  63. package/pp-core/references/discovery-data-model.md +145 -0
  64. package/pp-core/references/discovery-id-conventions.md +77 -8
  65. package/pp-core/references/discovery-integrations.md +151 -0
  66. package/pp-core/references/discovery-processes.md +190 -0
  67. package/pp-core/references/discovery-rebaseline.md +2 -2
  68. package/pp-core/references/discovery-research-track.md +5 -6
  69. package/pp-core/references/discovery-session-output.md +70 -0
  70. package/pp-core/references/discovery-standards.md +107 -0
  71. package/pp-core/references/discovery-traceability.md +2 -2
  72. package/pp-core/references/execute-mvp-tdd.md +3 -3
  73. package/pp-core/references/git-integration.md +57 -33
  74. package/pp-core/references/git-planning-commit.md +31 -9
  75. package/pp-core/references/phase-argument-parsing.md +1 -0
  76. package/pp-core/references/planner-discovery-extract.md +35 -0
  77. package/pp-core/references/planner-gap-closure.md +1 -0
  78. package/pp-core/references/planner-revision.md +3 -1
  79. package/pp-core/references/planner-tdd.md +4 -4
  80. package/pp-core/references/planning-config.md +3 -3
  81. package/pp-core/references/shell-portability.md +28 -0
  82. package/pp-core/references/tdd.md +20 -16
  83. package/pp-core/references/verifier-discovery-conformance.md +36 -0
  84. package/pp-core/references/worktree-path-safety.md +1 -0
  85. package/pp-core/templates/milestone.md +5 -5
  86. package/pp-core/templates/project-charter.md +161 -100
  87. package/pp-core/templates/project.md +3 -3
  88. package/pp-core/templates/requirements.md +18 -0
  89. package/pp-core/templates/verification-report.md +16 -0
  90. package/pp-core/workflows/add-backlog.md +1 -1
  91. package/pp-core/workflows/add-tests.md +5 -2
  92. package/pp-core/workflows/add-todo.md +3 -1
  93. package/pp-core/workflows/ai-integration-phase.md +2 -1
  94. package/pp-core/workflows/audit-fix.md +4 -3
  95. package/pp-core/workflows/audit-milestone.md +1 -0
  96. package/pp-core/workflows/autonomous.md +6 -0
  97. package/pp-core/workflows/check-todos.md +2 -1
  98. package/pp-core/workflows/cleanup.md +3 -1
  99. package/pp-core/workflows/code-review-fix.md +12 -5
  100. package/pp-core/workflows/code-review.md +15 -1
  101. package/pp-core/workflows/complete-milestone.md +13 -3
  102. package/pp-core/workflows/debug.md +2 -0
  103. package/pp-core/workflows/diagnose-issues.md +1 -1
  104. package/pp-core/workflows/discovery-sprint/charter.md +114 -0
  105. package/pp-core/workflows/discovery-sprint/prefill.md +1 -1
  106. package/pp-core/workflows/discovery-sprint/prototype.md +4 -4
  107. package/pp-core/workflows/discovery-sprint/session-13-gates.md +11 -1
  108. package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +54 -7
  109. package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +31 -7
  110. package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +64 -37
  111. package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +12 -3
  112. package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +45 -22
  113. package/pp-core/workflows/discovery-sprint/sessions/06-security.md +30 -15
  114. package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +43 -25
  115. package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +63 -24
  116. package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +28 -13
  117. package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +35 -16
  118. package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +32 -8
  119. package/pp-core/workflows/discovery-sprint/sessions/12-delivery-model.md +21 -18
  120. package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +29 -12
  121. package/pp-core/workflows/discovery-sprint/vault-context.md +14 -3
  122. package/pp-core/workflows/discovery-sprint.md +23 -23
  123. package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +81 -29
  124. package/pp-core/workflows/discovery-to-build/steps/{screen-inventory-gate.md → handoff-gates.md} +111 -3
  125. package/pp-core/workflows/discovery-to-build/templates/discovery-references.md +12 -9
  126. package/pp-core/workflows/discovery-to-build/templates/pp-handoff.md +27 -26
  127. package/pp-core/workflows/discovery-to-build.md +70 -34
  128. package/pp-core/workflows/discuss-phase/discovery.md +83 -0
  129. package/pp-core/workflows/discuss-phase/templates/context.md +4 -0
  130. package/pp-core/workflows/discuss-phase-assumptions.md +5 -3
  131. package/pp-core/workflows/discuss-phase.md +18 -10
  132. package/pp-core/workflows/docs-update.md +1 -0
  133. package/pp-core/workflows/eval-review.md +2 -1
  134. package/pp-core/workflows/execute-phase/steps/check-query-gate.md +7 -6
  135. package/pp-core/workflows/execute-phase/steps/cross-ai-delegation.md +1 -0
  136. package/pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -0
  137. package/pp-core/workflows/execute-phase/steps/vault-fetch.md +12 -0
  138. package/pp-core/workflows/execute-phase.md +19 -7
  139. package/pp-core/workflows/execute-plan.md +18 -7
  140. package/pp-core/workflows/explore.md +1 -1
  141. package/pp-core/workflows/forensics.md +4 -2
  142. package/pp-core/workflows/health.md +1 -0
  143. package/pp-core/workflows/import.md +2 -1
  144. package/pp-core/workflows/ingest-docs.md +1 -0
  145. package/pp-core/workflows/init/steps/client-context-capture.md +1 -0
  146. package/pp-core/workflows/init/steps/github-provisioning.md +145 -0
  147. package/pp-core/workflows/init/steps/gitlab-provisioning.md +18 -4
  148. package/pp-core/workflows/init/steps/reachability-outcome.md +3 -1
  149. package/pp-core/workflows/init.md +56 -66
  150. package/pp-core/workflows/map-codebase.md +5 -1
  151. package/pp-core/workflows/milestone-summary.md +2 -1
  152. package/pp-core/workflows/mvp-phase.md +1 -0
  153. package/pp-core/workflows/new-milestone.md +9 -5
  154. package/pp-core/workflows/new-project.md +12 -11
  155. package/pp-core/workflows/new-workspace.md +1 -0
  156. package/pp-core/workflows/next.md +2 -1
  157. package/pp-core/workflows/pause-work.md +6 -4
  158. package/pp-core/workflows/plan-milestone-gaps.md +3 -1
  159. package/pp-core/workflows/plan-phase/steps/chunked-planning.md +1 -1
  160. package/pp-core/workflows/plan-phase/steps/discovery-extract.md +41 -0
  161. package/pp-core/workflows/plan-phase.md +36 -16
  162. package/pp-core/workflows/plan-review-convergence.md +2 -0
  163. package/pp-core/workflows/plant-seed.md +4 -2
  164. package/pp-core/workflows/pr-branch.md +2 -0
  165. package/pp-core/workflows/progress.md +5 -0
  166. package/pp-core/workflows/quick.md +11 -4
  167. package/pp-core/workflows/reapply-patches.md +3 -0
  168. package/pp-core/workflows/remove-phase.md +1 -1
  169. package/pp-core/workflows/resume-project.md +3 -0
  170. package/pp-core/workflows/review.md +7 -1
  171. package/pp-core/workflows/secure-phase.md +2 -1
  172. package/pp-core/workflows/session-report.md +1 -0
  173. package/pp-core/workflows/ship.md +8 -1
  174. package/pp-core/workflows/sketch-wrap-up.md +1 -1
  175. package/pp-core/workflows/sketch.md +3 -2
  176. package/pp-core/workflows/spec-phase.md +2 -1
  177. package/pp-core/workflows/spike-wrap-up.md +1 -1
  178. package/pp-core/workflows/spike.md +4 -3
  179. package/pp-core/workflows/sync-skills.md +5 -2
  180. package/pp-core/workflows/thread.md +3 -2
  181. package/pp-core/workflows/transition.md +6 -0
  182. package/pp-core/workflows/ui-phase.md +3 -1
  183. package/pp-core/workflows/ui-review.md +2 -1
  184. package/pp-core/workflows/ultraplan-phase.md +1 -0
  185. package/pp-core/workflows/undo.md +14 -10
  186. package/pp-core/workflows/update.md +5 -0
  187. package/pp-core/workflows/validate-phase.md +6 -3
  188. package/pp-core/workflows/vault-review.md +7 -1
  189. package/pp-core/workflows/vault-write-back.md +5 -0
  190. package/pp-core/workflows/verify-phase.md +5 -0
  191. package/pp-core/workflows/verify-work.md +8 -1
  192. package/scripts/prompt-injection-scan.sh +1 -1
  193. package/scripts/sync-runtime-launcher.cjs +115 -5
  194. package/pp-core/workflows/discovery-sprint/templates/context-template.md +0 -266
@@ -179,6 +179,7 @@ fi
179
179
 
180
180
  Resolve `MVP_MODE` once via the centralized `phase.mvp-mode` query verb (precedence chain: CLI flag → ROADMAP `**Mode:** mvp` → `workflow.mvp_mode` config → false):
181
181
  ```bash
182
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
182
183
  MVP_FLAG_ARG=""
183
184
  if [[ "$ARGUMENTS" =~ (^|[[:space:]])--mvp([[:space:]]|$) ]]; then MVP_FLAG_ARG="--cli-flag"; fi
184
185
  MVP_MODE=$(pp_run query phase.mvp-mode "${PHASE_NUMBER}" $MVP_FLAG_ARG --pick active)
@@ -218,7 +219,10 @@ Offer these recovery options:
218
219
  if [ "$MVP_MODE" = "true" ] && [ "$TDD_MODE" = "true" ]; then
219
220
  IS_BEHAVIOR_ADDING=$(pp_run query task.is-behavior-adding "$TASK_FILE" --pick is_behavior_adding)
220
221
  if [ "$IS_BEHAVIOR_ADDING" = "true" ]; then
221
- RED_COMMIT=$(git log --oneline --grep="^test(${PHASE_NUMBER}-${PLAN_ID}):" -- "**/*.test.*" "**/*.spec.*" "tests/" | head -1)
222
+ # A `test` commit (any scope) whose `Phase:` trailer is this plan; a `test(<plan>):`
223
+ # subject from before the trailer convention still counts.
224
+ RED_COMMIT=$(git log --format='%h%x09%s%x09%(trailers:key=Phase,valueonly,separator=%x2C)' -- "**/*.test.*" "**/*.spec.*" "tests/" \
225
+ | awk -F'\t' -v id="${PHASE_NUMBER}-${PLAN_ID}" '$2 ~ /^test(\([^)]*\))?!?:/ && ($3 == id || index($2, "(" id "):") > 0) { print; exit }')
222
226
  if [ -z "$RED_COMMIT" ]; then
223
227
  pp_run query state.update last_gate_trip "${PLAN_ID}/${TASK_ID}" || true
224
228
  echo "MVP+TDD GATE TRIPPED: missing RED commit for ${PLAN_ID}/${TASK_ID}"
@@ -236,6 +240,7 @@ Pure doc-only / config-only / test-only tasks return `is_behavior_adding=false`
236
240
  Look for a `.continue-here.md` in the current phase directory:
237
241
 
238
242
  ```bash
243
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
239
244
  ls ${phase_dir}/.continue-here.md 2>/dev/null || true
240
245
  ```
241
246
 
@@ -755,6 +760,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
755
760
  rerun the same command. Do not fall back to broad worktree discovery.
756
761
 
757
762
  ```bash
763
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
758
764
  [ -n "${WAVE_WORKTREE_MANIFEST:-}" ] && [ -f "$WAVE_WORKTREE_MANIFEST" ] || {
759
765
  echo "BLOCKED: missing WAVE_WORKTREE_MANIFEST; refusing broad worktree cleanup (#3384)." >&2
760
766
  exit 1
@@ -784,6 +790,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
784
790
  If the orchestrator deviated from the standard wave merge path (e.g., custom inter-worktree base-update merges with `merge: bring …` style messages), run this snippet after the custom merges are complete. It reads only `WAVE_WORKTREE_MANIFEST`; do not discover unrelated `worktree-agent-*` worktrees.
785
791
 
786
792
  ```bash
793
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
787
794
  # Cleanup-tail: pin orchestrator CWD to its OWN worktree before cleanup-tail (#3174, #630).
788
795
  # Same fix as the templated path: resolve the dispatch-time orchestrator root from the manifest,
789
796
  # not `git worktree list`'s first entry (always the main checkout — wrong for a lane orchestrator).
@@ -858,7 +865,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
858
865
 
859
866
  # Only commit tracking files if they actually changed
860
867
  if ! git diff --quiet .planning/ROADMAP.md .planning/STATE.md 2>/dev/null; then
861
- pp_run query commit "docs(phase-${PHASE_NUMBER}): update tracking after wave ${N}" --files .planning/ROADMAP.md .planning/STATE.md
868
+ pp_run query commit "docs(planning): update tracking after wave ${N}" --phase "${PHASE_NUMBER}" --files .planning/ROADMAP.md .planning/STATE.md
862
869
  fi
863
870
  elif [ "${TEST_EXIT}" -eq 124 ]; then
864
871
  echo "⚠ Skipping tracking update — test suite timed out. Plans remain in-progress. Run tests manually to confirm."
@@ -1062,6 +1069,7 @@ After all waves:
1062
1069
 
1063
1070
  **Security gate check:**
1064
1071
  ```bash
1072
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
1065
1073
  VERIFY_POST_HOOKS_JSON=$(pp_run loop render-hooks verify:post --raw)
1066
1074
  printf '%s' "$VERIFY_POST_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('VERIFY_POST_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
1067
1075
  SECURITY_FILE=$(ls "${PHASE_DIR}"/*-SECURITY.md 2>/dev/null | head -1)
@@ -1213,7 +1221,8 @@ mv .planning/debug/{slug}.md .planning/debug/resolved/
1213
1221
 
1214
1222
  **6. Commit updated artifacts:**
1215
1223
  ```bash
1216
- pp_run query commit "docs(phase-${PARENT_PHASE}): resolve UAT gaps and debug sessions after ${PHASE_NUMBER} gap closure" --files .planning/phases/*${PARENT_PHASE}*/*-UAT.md .planning/debug/resolved/*.md
1224
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
1225
+ pp_run query commit "docs(planning): resolve UAT gaps and debug sessions after ${PHASE_NUMBER} gap closure" --phase "${PARENT_PHASE}" --files .planning/phases/*${PARENT_PHASE}*/*-UAT.md .planning/debug/resolved/*.md
1217
1226
  ```
1218
1227
  </step>
1219
1228
 
@@ -1376,7 +1385,7 @@ blocked: 0
1376
1385
 
1377
1386
  Commit the file:
1378
1387
  ```bash
1379
- pp_run query commit "test({phase_num}): persist human verification items as UAT" --files "{phase_dir}/{phase_num}-UAT.md"
1388
+ pp_run query commit "docs(planning): persist human verification items as UAT" --phase "{phase_num}" --files "{phase_dir}/{phase_num}-UAT.md"
1380
1389
  ```
1381
1390
 
1382
1391
  **Step B: Present to user:**
@@ -1456,7 +1465,8 @@ These items are tracked and will appear in `/pp:progress` and `/pp:audit-uat`.
1456
1465
  ```
1457
1466
 
1458
1467
  ```bash
1459
- pp_run query commit "docs(phase-{X}): complete phase execution" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md {phase_dir}/*-VERIFICATION.md
1468
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
1469
+ pp_run query commit "docs(planning): complete phase execution" --phase "{X}" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md {phase_dir}/*-VERIFICATION.md
1460
1470
  ```
1461
1471
  </step>
1462
1472
 
@@ -1489,6 +1499,7 @@ Copy failure must NOT block phase completion.
1489
1499
  This step runs AFTER `update_roadmap` marks the phase complete. It moves any pending todos that carry `resolves_phase: <current-phase-number>` to the completed directory.
1490
1500
 
1491
1501
  ```bash
1502
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
1492
1503
  PHASE_NUM="${PHASE_NUMBER}"
1493
1504
  PENDING_DIR=".planning/todos/pending"
1494
1505
  COMPLETED_DIR=".planning/todos/completed"
@@ -1506,7 +1517,7 @@ for TODO_FILE in "$PENDING_DIR"/*.md; do
1506
1517
  done
1507
1518
 
1508
1519
  if [ ${#CLOSED[@]} -gt 0 ]; then
1509
- pp_run query commit "docs(phase-${PHASE_NUMBER}): auto-close ${#CLOSED[@]} todo(s) resolved by this phase" --files .planning/todos/completed/ .planning/STATE.md|| true
1520
+ pp_run query commit "docs(planning): auto-close ${#CLOSED[@]} todo(s) resolved by this phase" --phase "${PHASE_NUMBER}" --files .planning/todos/completed/ .planning/STATE.md|| true
1510
1521
  echo "◆ Closed ${#CLOSED[@]} todo(s) resolved by Phase ${PHASE_NUMBER}:"
1511
1522
  for f in "${CLOSED[@]}"; do echo " ✓ $f"; done
1512
1523
  fi
@@ -1531,7 +1542,7 @@ PROJECT.md falls behind silently over multiple phases.
1531
1542
  5. Commit the change:
1532
1543
 
1533
1544
  ```bash
1534
- pp_run query commit "docs(phase-{X}): evolve PROJECT.md after phase completion" --files .planning/PROJECT.md
1545
+ pp_run query commit "docs(planning): evolve PROJECT.md after phase completion" --phase "{X}" --files .planning/PROJECT.md
1535
1546
  ```
1536
1547
 
1537
1548
  **Skip this step if** `.planning/PROJECT.md` does not exist.
@@ -1594,6 +1605,7 @@ Read and follow `~/.claude/pp-core/workflows/transition.md`, passing through the
1594
1605
  Check whether CONTEXT.md already exists for the next phase:
1595
1606
 
1596
1607
  ```bash
1608
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
1597
1609
  ls .planning/phases/*{next}*/{next}-CONTEXT.md 2>/dev/null || echo "no-context"
1598
1610
  ```
1599
1611
 
@@ -77,6 +77,7 @@ hooks, mechanically in the fence (D-30): no other capability's hook is run or
77
77
  injected here, because execute-phase's dispatcher owns those for its own run.
78
78
 
79
79
  ```bash
80
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
80
81
  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');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
81
82
  printf '%s' "$EXECUTE_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('EXECUTE_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
82
83
  ```
@@ -91,6 +92,7 @@ the two-step contract, the halt and the message passthrough; none of them are re
91
92
 
92
93
  <step name="identify_plan">
93
94
  ```bash
95
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
94
96
  # Use plans/summaries from INIT JSON, or list files
95
97
  (ls .planning/phases/XX-name/*-PLAN.md 2>/dev/null || true) | sort
96
98
  (ls .planning/phases/XX-name/*-SUMMARY.md 2>/dev/null || true) | sort
@@ -122,6 +124,7 @@ positional is the plan file, not its phase directory: sibling plans mid-wave are
122
124
  business, and `check vault.trace <plan file> --stage plan` by hand gives this gate's verdict.
123
125
 
124
126
  ```bash
127
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
125
128
  PLAN_POST_HOOKS_JSON=$(pp_run loop render-hooks plan:post --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');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
126
129
  printf '%s' "$PLAN_POST_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('PLAN_POST_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
127
130
  ```
@@ -312,9 +315,11 @@ End with: **Total deviations:** N auto-fixed (breakdown). **Impact:** assessment
312
315
  For `type: tdd` plans — RED-GREEN-REFACTOR:
313
316
 
314
317
  1. **Infrastructure** (first TDD plan only): detect project, install framework, config, verify empty suite
315
- 2. **RED:** Read `<behavior>` → failing test(s) → run (MUST fail) → commit: `test({phase}-{plan}): add failing test for [feature]`
316
- 3. **GREEN:** Read `<implementation>` → minimal code → run (MUST pass) → commit: `feat({phase}-{plan}): implement [feature]`
317
- 4. **REFACTOR:** Clean up → tests MUST pass → commit: `refactor({phase}-{plan}): clean up [feature]`
318
+ 2. **RED:** Read `<behavior>` → failing test(s) → run (MUST fail) → commit: `test({area}): add failing test for [feature]`
319
+ 3. **GREEN:** Read `<implementation>` → minimal code → run (MUST pass) → commit: `feat({area}): implement [feature]`
320
+ 4. **REFACTOR:** Clean up → tests MUST pass → commit: `refactor({area}): clean up [feature]`
321
+
322
+ `{area}` names the part of the codebase (`auth`, `billing`), never the plan; every one of these commits ends with the trailer `Phase: {phase}-{plan}` after a blank line.
318
323
 
319
324
  Errors: RED doesn't fail → investigate test/existing feature. GREEN doesn't pass → debug, iterate. REFACTOR breaks → undo.
320
325
 
@@ -348,7 +353,7 @@ If a commit is BLOCKED by a hook:
348
353
  <task_commit>
349
354
  ## Task Commit Protocol
350
355
 
351
- Canonical per-task commit rules live in **`agents/pp-executor.md`** (`<task_commit_protocol>`). Follow that section for staging, `{type}({phase}-{plan})` messages, `commit-to-subrepo` when `sub_repos` is set, post-commit checks, and untracked-file handling — do not duplicate or paraphrase the full protocol here (single source of truth).
356
+ Canonical per-task commit rules live in **`agents/pp-executor.md`** (`<task_commit_protocol>`). Follow that section for staging, `{type}({area}): …` messages with the `Phase: {phase}-{plan}` trailer, `commit-to-subrepo` when `sub_repos` is set, post-commit checks, and untracked-file handling — do not duplicate or paraphrase the full protocol here (single source of truth).
352
357
 
353
358
  **Orchestrator note:** After each task, the spawned executor reports commit hashes; this workflow does not re-specify commit semantics beyond pointing at the executor.
354
359
 
@@ -523,6 +528,7 @@ Counts PLAN vs SUMMARY files on disk and updates the progress-table row with the
523
528
  Mark completed requirements from the PLAN.md frontmatter `requirements:` field:
524
529
 
525
530
  ```bash
531
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
526
532
  pp_run query requirements.mark-complete ${REQ_IDS}
527
533
  ```
528
534
 
@@ -543,9 +549,9 @@ IS_WORKTREE=$([ -f .git ] && echo "true" || echo "false")
543
549
 
544
550
  # In parallel mode: exclude STATE.md and ROADMAP.md (orchestrator commits these)
545
551
  if [ "$IS_WORKTREE" = "true" ]; then
546
- pp_run query commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/REQUIREMENTS.md
552
+ pp_run query commit "docs(planning): complete [plan-name] plan" --phase "{phase}-{plan}" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/REQUIREMENTS.md
547
553
  else
548
- pp_run query commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md
554
+ pp_run query commit "docs(planning): complete [plan-name] plan" --phase "{phase}-{plan}" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md
549
555
  fi
550
556
  ```
551
557
  </step>
@@ -554,13 +560,17 @@ fi
554
560
  If .planning/codebase/ doesn't exist: skip.
555
561
 
556
562
  ```bash
557
- FIRST_TASK=$(git log --oneline --grep="feat({phase}-{plan}):" --grep="fix({phase}-{plan}):" --grep="test({phase}-{plan}):" --reverse | head -1 | cut -d' ' -f1)
563
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
564
+ # Oldest feat/fix/test commit carrying the plan's `Phase:` trailer (or, from before the trailer, its scope)
565
+ FIRST_TASK=$(git log --reverse --format='%h%x09%s%x09%(trailers:key=Phase,valueonly,separator=%x2C)' \
566
+ | awk -F'\t' -v id="{phase}-{plan}" '$2 ~ /^(feat|fix|test)(\([^)]*\))?!?:/ && ($3 == id || index($2, "(" id "):") > 0) { print $1; exit }')
558
567
  git diff --name-only ${FIRST_TASK}^..HEAD 2>/dev/null || true
559
568
  ```
560
569
 
561
570
  Update only structural changes: new src/ dir → STRUCTURE.md | deps → STACK.md | file pattern → CONVENTIONS.md | API client → INTEGRATIONS.md | config → STACK.md | renamed → update paths. Skip code-only/bugfix/content changes.
562
571
 
563
572
  ```bash
573
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
564
574
  pp_run query commit "" --files .planning/codebase/*.md --amend
565
575
  ```
566
576
  </step>
@@ -569,6 +579,7 @@ pp_run query commit "" --files .planning/codebase/*.md --amend
569
579
  If `USER_SETUP_CREATED=true`: display `⚠️ USER SETUP REQUIRED` with path + env/config tasks at TOP.
570
580
 
571
581
  ```bash
582
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
572
583
  (ls -1 .planning/phases/[current-phase-dir]/*-PLAN.md 2>/dev/null || true) | wc -l
573
584
  (ls -1 .planning/phases/[current-phase-dir]/*-SUMMARY.md 2>/dev/null || true) | wc -l
574
585
  ```
@@ -118,7 +118,7 @@ For each selected output, write the file:
118
118
  Commit if `commit_docs` is enabled:
119
119
  ```bash
120
120
  _PP_SHIM_NAME="pp-tools.cjs"; _pp_root() { ( for _v in $(env | sed -n 's/^\(GIT_[A-Za-z0-9_]*\)=.*/\1/p'); do unset "$_v"; done; _c=$(git rev-parse --git-common-dir 2>/dev/null); if [ "${_c##*/}" = .git ] && cd "$_c/.." 2>/dev/null; then pwd -P; else git rev-parse --show-toplevel 2>/dev/null || pwd; fi ); }; pp_run() { case "$PP_TOOLS" in *.cjs) node "$PP_TOOLS" "$@";; *) "$PP_TOOLS" "$@";; esac; }; _PP_RUNTIME_ROOT="${RUNTIME_DIR:-$(_pp_root)}"; PP_TOOLS="${_PP_RUNTIME_ROOT}/pp-core/bin/${_PP_SHIM_NAME}"; if [ -f "$PP_TOOLS" ]; then :; elif [ -f "${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}"; elif command -v pp-tools >/dev/null 2>&1; then PP_TOOLS="$(command -v pp-tools)"; else echo "ERROR: pp-tools.cjs not found at $PP_TOOLS and pp-tools is not on PATH. Run: npx -y @pareto4/pp-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${PP_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${PP_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
121
- pp_run query commit "docs: capture exploration — {topic_slug}" --files {file_list}
121
+ pp_run query commit "docs(planning): capture exploration — {topic_slug}" --files {file_list}
122
122
  ```
123
123
 
124
124
  ## Step 6: Close
@@ -64,6 +64,7 @@ Extract:
64
64
  For each phase directory in `.planning/phases/*/`:
65
65
 
66
66
  ```bash
67
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
67
68
  ls .planning/phases/*/
68
69
  ```
69
70
 
@@ -255,15 +256,16 @@ If actionable anomalies were found (HIGH or MEDIUM confidence):
255
256
 
256
257
  If confirmed:
257
258
  ```bash
259
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
258
260
  # Check if "bug" label exists before using it
259
- BUG_LABEL=$(gh label list --repo open-gsd/pp-core --search "bug" --json name -q '.[0].name' 2>/dev/null)
261
+ BUG_LABEL=$(gh label list --repo pareto000/pp-core --search "bug" --json name -q '.[0].name' 2>/dev/null)
260
262
  LABEL_FLAG=""
261
263
  if [ -n "$BUG_LABEL" ]; then
262
264
  LABEL_FLAG="--label bug"
263
265
  fi
264
266
 
265
267
  gh issue create \
266
- --repo open-gsd/pp-core \
268
+ --repo pareto000/pp-core \
267
269
  --title "bug: {concise description from anomaly}" \
268
270
  $LABEL_FLAG \
269
271
  --body "{formatted findings from report}"
@@ -65,6 +65,7 @@ health output, the two modes are independent diagnostics.
65
65
  **Run health validation:**
66
66
 
67
67
  ```bash
68
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
68
69
  pp_run query validate.health $REPAIR_FLAG $BACKFILL_FLAG
69
70
  ```
70
71
 
@@ -42,6 +42,7 @@ Usage: /pp:import --from <path>
42
42
  Verify the path does not contain traversal sequences and the file exists:
43
43
 
44
44
  ```bash
45
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
45
46
  case "{FILEPATH}" in
46
47
  *..* ) echo "SECURITY_ERROR: path contains traversal sequence"; exit 1 ;;
47
48
  esac
@@ -228,7 +229,7 @@ Update `.planning/STATE.md` if appropriate (e.g., increment total plan count).
228
229
 
229
230
  Commit the imported plan and updated files:
230
231
  ```bash
231
- pp_run query commit "docs({phase}): import plan from {basename FILEPATH}" --files .planning/phases/{phase}/{plan}-PLAN.md .planning/ROADMAP.md
232
+ pp_run query commit "docs(planning): import plan from {basename FILEPATH}" --phase "{phase}" --files .planning/phases/{phase}/{plan}-PLAN.md .planning/ROADMAP.md
232
233
  ```
233
234
 
234
235
  Display completion:
@@ -33,6 +33,7 @@ Parse `$ARGUMENTS`:
33
33
  **Validate paths:**
34
34
 
35
35
  ```bash
36
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
36
37
  case "{SCAN_PATH}" in *..*) echo "SECURITY_ERROR: path contains traversal sequence"; exit 1 ;; esac
37
38
  test -d "{SCAN_PATH}" || echo "PATH_NOT_FOUND"
38
39
  if [ -n "{MANIFEST_PATH}" ]; then
@@ -61,6 +61,7 @@ Capture these fields, in this order:
61
61
  managed-block writer:
62
62
 
63
63
  ```bash
64
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
64
65
  if [ "$(pp_run query platform-bindings --pick present 2>/dev/null)" = "true" ]; then
65
66
  # Write collected values to a temp JSON file using node + JSON.stringify so that
66
67
  # multi-line values, embedded quotes, backslashes, and $(...) sequences are encoded
@@ -0,0 +1,145 @@
1
+ # Gated GitHub provisioning — H-2..H-5 (D-05, D-09, D-10, D-11, D-12, D-13)
2
+
3
+ Lazily Read by `pp-core/workflows/init.md` § "Gated GitLab/GitHub provisioning" — Step 3's
4
+ other sub-path — and ONLY when BOTH of that section's gates hold: `.platform-bindings.json`
5
+ is present AND `resolveProvider` answers `github`. Both gates, G-1's one-source-per-value
6
+ config reads and the empty-group guard stay in `init.md`; this file is the GitHub create
7
+ recipe those guards protect, the counterpart of `gitlab-provisioning.md` step for step.
8
+ `$GROUP` (the GitHub organization), `$SLUG`, `$VIS`, `$DESC` and `$HOST` are the variables
9
+ G-1 has already set. Every `gh` call names the host through `GH_HOST`, so a GitHub
10
+ Enterprise host in the binding is honored and `github.com` is the default:
11
+
12
+ ```bash
13
+ GH_HOSTNAME="${HOST:-github.com}"
14
+ ```
15
+
16
+ #### H-2. Auth verify-only (D-11)
17
+
18
+ `/pp-init` **never establishes auth and never reads or writes the user's token.**
19
+ Secrets stay in the environment or OS keyring. Only verify that a session exists:
20
+
21
+ ```bash
22
+ gh auth status --hostname "$GH_HOSTNAME" >/dev/null 2>&1 || {
23
+ echo "Not authenticated to GitHub ($GH_HOSTNAME). Run: gh auth login --hostname $GH_HOSTNAME"
24
+ exit 1
25
+ }
26
+ ```
27
+
28
+ If this check fails, stop immediately. Do not proceed to probe or create.
29
+ Never run `gh auth login` from within `/pp-init`.
30
+
31
+ #### H-3. Existence probe → adopt-if-exists (D-09, D-12)
32
+
33
+ Pre-check with a read-only probe before any create attempt. The create command is **not
34
+ idempotent** — re-running it against an existing repository fails, and a create whose
35
+ remote-add step fails has still created the repository. The probe avoids this landmine.
36
+
37
+ This is one self-contained block: it sets `PROJECT_EXISTS` and, on the exists path,
38
+ adopts (links the remote). It NEVER creates — create lives in its own H-4 block, gated
39
+ on `PROJECT_EXISTS=false`, so the create invocation can never fall inside the exists
40
+ branch.
41
+
42
+ ```bash
43
+ if GH_HOST="$GH_HOSTNAME" gh repo view "$GROUP/$SLUG" --json name >/dev/null 2>&1; then
44
+ # Repository already exists — ADOPT: link remote only, skip create (D-12)
45
+ PROJECT_EXISTS=true
46
+ echo "GitHub repository $GROUP/$SLUG already exists — adopting (linking remote, skipping create)."
47
+ # Match the remote scheme gh itself uses on the create path — honor the user's
48
+ # `gh config get git_protocol` (https default) instead of hardcoding SSH.
49
+ GIT_PROTO=$(gh config get git_protocol --host "$GH_HOSTNAME" 2>/dev/null || echo https)
50
+ if [ "$GIT_PROTO" = "ssh" ]; then
51
+ ADOPT_URL="git@$GH_HOSTNAME:$GROUP/$SLUG.git"
52
+ else
53
+ ADOPT_URL="https://$GH_HOSTNAME/$GROUP/$SLUG.git"
54
+ fi
55
+ git remote get-url origin >/dev/null 2>&1 || git remote add origin "$ADOPT_URL"
56
+ echo "Remote 'origin' → $ADOPT_URL"
57
+ else
58
+ # Repository not found — defer to H-4 for confirm-then-create
59
+ PROJECT_EXISTS=false
60
+ echo "GitHub repository $GROUP/$SLUG not found — will confirm before create."
61
+ fi
62
+ ```
63
+
64
+ If the repository exists (`PROJECT_EXISTS=true`), the remote is already linked above
65
+ (skipping create entirely) — proceed straight to H-5 reconciliation. The adopt path does
66
+ not show a create confirmation — it only links the remote, which is a local-only
67
+ operation and can be undone with `git remote remove origin`.
68
+
69
+ #### H-4. Per-action confirmation, then create (D-05, D-09, D-10, SAFE-01)
70
+
71
+ **Only run this step when `PROJECT_EXISTS=false`** (the existence probe in H-3 found no
72
+ repository). If `PROJECT_EXISTS=true`, skip H-4 entirely — the repository was already
73
+ adopted — and go to H-5. When creating, **show the exact command and target before
74
+ firing**. The user must confirm explicitly. Nothing is batched. (D-05)
75
+
76
+ Present to the user (via `AskUserQuestion` or TEXT_MODE numbered list):
77
+
78
+ ```text
79
+ About to create GitHub repository:
80
+ Command: gh repo create "$GROUP/$SLUG"
81
+ Host: $GH_HOSTNAME
82
+ Organization: $GROUP
83
+ Repository: $GROUP/$SLUG
84
+ Visibility: private (enforced --private)
85
+ Requested: $VIS (from project.visibility — see note below)
86
+ Source: this directory (--source .) — nothing is pushed
87
+ Remote name: origin
88
+
89
+ Proceed? [y/N]
90
+ ```
91
+
92
+ `$VIS` (from G-1) is surfaced in the confirmation so the requested visibility is never
93
+ silently ignored (WR-01). pp-core always **creates private** regardless; a non-private
94
+ repository must be a deliberate, separate post-create change.
95
+
96
+ Only after the user confirms — and only with `PROJECT_EXISTS=false` — run the locked
97
+ create recipe (D-09, D-10). This is a standalone block: it carries no `if`/`else`/`fi`, so
98
+ it can only ever run as the deliberate, confirmed not-exists path:
99
+
100
+ ```bash
101
+ GH_HOST="$GH_HOSTNAME" gh repo create "$GROUP/$SLUG" \
102
+ --description "$DESC" \
103
+ --private \
104
+ --source . \
105
+ --remote origin
106
+ ```
107
+
108
+ **Visibility hard-default (D-10):** the create invocation always carries `--private` and
109
+ never `--public` or `--internal`. `VIS` is read in G-1 and **surfaced in the H-4
110
+ confirmation** (WR-01) so a `public`/`internal` request is visible to the user — but
111
+ pp-core still creates the repository **private**. Applying a non-private visibility is a
112
+ deliberate, separate post-create action (e.g. `gh repo edit --visibility …`) the operator
113
+ performs knowingly; `/pp-init` never auto-relaxes visibility. The create pushes nothing
114
+ (no `--push`): the first push is Step 3's own confirmed push, and the repository's default
115
+ branch is whatever that push sends.
116
+
117
+ #### H-5. Post-create reconciliation (D-09)
118
+
119
+ After the create (or after the adopt path), re-probe existence. A non-zero exit from
120
+ `gh repo create` does **not** mean the repository was not created — the repository is
121
+ created before `--remote origin` is added, so an `origin` that already exists fails the
122
+ command after the create succeeded. The `repo view` probe is the source of truth, not the
123
+ exit code:
124
+
125
+ ```bash
126
+ if GH_HOST="$GH_HOSTNAME" gh repo view "$GROUP/$SLUG" --json name >/dev/null 2>&1; then
127
+ echo "Reconciled: GitHub repository $GROUP/$SLUG confirmed."
128
+ else
129
+ echo "WARN: gh repo view $GROUP/$SLUG returned non-zero — verify the repository was created before continuing."
130
+ fi
131
+ ```
132
+
133
+ If reconciliation warns, do not auto-retry. Prompt the user to check GitHub directly
134
+ before proceeding to Step 4 (handoff routing).
135
+
136
+ **Security invariants — landmine guards:**
137
+ - Always use the organization-qualified `$GROUP/$SLUG` — never a bare slug (T-08-04, D-09).
138
+ A bare slug creates under the user's personal account, not the client organization.
139
+ G-1's empty-group guard is what actually enforces this before any create attempt.
140
+ - Always pass `--private` explicitly — never `--public` or `--internal` (T-08-05, D-10).
141
+ - Always confirm immediately before each outward action — nothing batched (T-08-06, D-05).
142
+ - Verify-only auth via `gh auth status` — never run `gh auth login`, never read or write
143
+ the user's token (T-08-08, D-11). Bindings hold only non-secret routing data.
144
+ - Always reconcile create with a `gh repo view` probe — a non-zero create exit does NOT
145
+ mean nothing happened (T-08-09, D-09).
@@ -1,10 +1,11 @@
1
1
  # Gated GitLab provisioning — G-2..G-5 (D-05, D-09, D-10, D-11, D-12, D-13)
2
2
 
3
- Lazily Read by `pp-core/workflows/init.md` § "Gated GitLab/Azure provisioning" — Step 3's
3
+ Lazily Read by `pp-core/workflows/init.md` § "Gated GitLab/GitHub provisioning" — Step 3's
4
4
  other sub-path — and ONLY when BOTH of that section's gates hold: `.platform-bindings.json`
5
5
  is present AND `resolveProvider` answers `gitlab`. Both gates, G-1's one-source-per-value
6
- config reads, the empty-group guard and the security-invariant list stay in `init.md`; this
7
- file is the create recipe those guards protect. Extracted from `init.md` (07-10) so the
6
+ config reads and the empty-group guard stay in `init.md`; this file is the create recipe
7
+ those guards protect, and ends with its security invariants (moved here from `init.md`
8
+ beside `github-provisioning.md`'s own). Extracted from `init.md` (07-10) so the
8
9
  always-loaded workflow stays under its DEFAULT size cap — relocation, not deletion: this
9
10
  text is the authority for how `/pp-init` provisions a GitLab project, and `$GROUP`, `$SLUG`,
10
11
  `$VIS`, `$DESC` and `$HOST` are the variables G-1 has already set.
@@ -26,7 +27,7 @@ Never run `glab auth login` from within `/pp-init`.
26
27
 
27
28
  #### G-3. Existence probe → adopt-if-exists (D-09, D-12)
28
29
 
29
- Pre-check with a read-only probe before any create attempt. `glab repo create` is **not
30
+ Pre-check with a read-only probe before any create attempt. The create command is **not
30
31
  idempotent** — re-running it against an existing project errors but may still produce side
31
32
  effects (the GitLab project is created before the remote-add step that then fails). The
32
33
  probe avoids this landmine.
@@ -128,3 +129,16 @@ fi
128
129
 
129
130
  If reconciliation warns, do not auto-retry. Prompt the user to check GitLab directly
130
131
  before proceeding to Step 4 (handoff routing).
132
+
133
+ **Security invariants — landmine guards:**
134
+ - Always use the group-qualified `$GROUP/$SLUG` path — never a bare slug (T-08-04, D-09).
135
+ A bare slug creates under the user's personal namespace, not the client group. G-1's
136
+ empty-group guard in `init.md` is what actually enforces this before any create attempt.
137
+ - Always pass `--private` explicitly — never inherit `glab`'s default `--internal`
138
+ visibility (T-08-05, D-10). The `--internal` flag is what makes this dangerous; the
139
+ locked recipe must carry `--private` and must NOT emit `--internal`.
140
+ - Always confirm immediately before each outward action — nothing batched (T-08-06, D-05).
141
+ - Verify-only auth via `glab auth status` — never run `glab auth login`, never read
142
+ or write the user's token (T-08-08, D-11). Bindings hold only non-secret routing data.
143
+ - Always reconcile create with a `glab repo view` probe — a non-zero create exit does
144
+ NOT mean nothing happened (T-08-09, D-09).
@@ -16,7 +16,9 @@ the probe, or this step to the user.
16
16
  named ref exists, and the client vault landed with a written `SUMMARY.md` (INIT-02).
17
17
  Continue to Step 3. A `shared` line on that card is information about the fallback
18
18
  tier (OD-5) — it is probed and shown, never required; an unreachable shared vault does
19
- not fail the proof and is not in the recorded note.
19
+ not fail the proof and is not in the recorded note. A `platform` line reading
20
+ `unreachable (not required)` is information too: the platform repo is not required, and
21
+ the record states what was measured.
20
22
 
21
23
  **(c) `PP_INIT_PROBE=unbound` or `PP_INIT_PROBE=fail`** — **STOP. `/pp-init` is not
22
24
  complete (INIT-03).** Do not continue to Step 3, and do not re-run the probe hoping for a