@pareto4/pp-core 1.5.4 → 1.6.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.
@@ -16,7 +16,19 @@ First parse `SESSION_ARG` (the optional session number 1–13) from `$ARGUMENTS`
16
16
 
17
17
  ```bash
18
18
  _PP_SHIM_NAME="pp-tools.cjs"; _PP_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; PP_TOOLS="${_PP_RUNTIME_ROOT}/pp-core/bin/${_PP_SHIM_NAME}"; if [ -f "$PP_TOOLS" ]; then pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif command -v pp-tools >/dev/null 2>&1; then PP_TOOLS="$(command -v pp-tools)"; pp_run() { "$PP_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$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
19
- SESSION_ARG=$(printf '%s\n' "${ARGUMENTS:-}" | grep -oE '(1[0-3]|[1-9])' | head -1)
19
+ # WR-03: validate the FULL numeric token. The old pattern (1[0-3]|[1-9]) let grep
20
+ # truncate out-of-range input to a spuriously valid session (14→1, 25→2, 99→9).
21
+ # Extract the whole digit run, then range-check 1–13; flag anything else as invalid.
22
+ SESSION_RAW=$(printf '%s' "${ARGUMENTS:-}" | grep -oE '[0-9]+' | head -1)
23
+ SESSION_ARG=""
24
+ SESSION_INVALID=""
25
+ if [ -n "$SESSION_RAW" ]; then
26
+ if [ "$SESSION_RAW" -ge 1 ] 2>/dev/null && [ "$SESSION_RAW" -le 13 ] 2>/dev/null; then
27
+ SESSION_ARG="$SESSION_RAW"
28
+ else
29
+ SESSION_INVALID="$SESSION_RAW"
30
+ fi
31
+ fi
20
32
  INIT=$(pp_run query init.phase-op "${SESSION_ARG:-}")
21
33
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
22
34
  ```
@@ -26,9 +38,10 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
26
38
  **Text mode:** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS` OR `text_mode` from init JSON is `true`. When TEXT_MODE is active, replace every `AskUserQuestion` call with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available.
27
39
 
28
40
  **Dispatch:**
29
- - If `SESSION_ARG` is empty → execute **Flow 1: Show Progress**
30
- - If `SESSION_ARG` is a number 1–13 → execute **Flow 2: Facilitate Session N**
31
- - Otherwise → show usage error
41
+ - If `SESSION_INVALID` is non-empty → show a usage error: "Session `$SESSION_INVALID` is out
42
+ of range — valid sessions are 1–13." Do not run any session or the progress view.
43
+ - Else if `SESSION_ARG` is empty (no numeric argument) → execute **Flow 1: Show Progress**
44
+ - Else (`SESSION_ARG` is a number 1–13) → execute **Flow 2: Facilitate Session N**
32
45
 
33
46
  ---
34
47
 
@@ -694,8 +707,8 @@ This session uses the **Session 3: Process-First Protocol** (Steps 5A–5G descr
694
707
  2. **Technology stack selection**
695
708
  - What is the preferred frontend technology (React, Angular, Vue, Mendix, etc.)?
696
709
  - What is the preferred backend technology (Node.js, .NET, Java, Python)?
697
- - What database technology is appropriate (relational, document, graph, time-series)?
698
- - What messaging or eventing technology will be used (Kafka, RabbitMQ, Azure Service Bus)?
710
+ - What database technology is appropriate (relational e.g. Cloud SQL via pareto-platform-gcp, document, graph, time-series)?
711
+ - What messaging or eventing technology will be used (Google Cloud Pub/Sub via pareto-platform-gcp, Kafka, RabbitMQ)?
699
712
  - What caching strategy applies (Redis, in-memory, CDN)?
700
713
 
701
714
  3. **Key architectural components**
@@ -717,6 +730,8 @@ This session uses the **Session 3: Process-First Protocol** (Steps 5A–5G descr
717
730
 
718
731
  **Notes Template:**
719
732
 
733
+ > **Platform standard (D-08):** The Pareto platform standard is GCP / `pareto-platform-gcp`. Fill this table against that baseline unless the client has an overriding constraint.
734
+
720
735
  **Technology Stack Decisions**
721
736
 
722
737
  | Layer | Technology | Version | Rationale | Alternatives Considered | Risk |
@@ -1129,7 +1144,7 @@ This session uses the **Session 3: Process-First Protocol** (Steps 5A–5G descr
1129
1144
  **What We Cover:**
1130
1145
 
1131
1146
  1. **Cloud / hosting strategy**
1132
- - What cloud provider will be used (AWS, Azure, GCP, on-premises, hybrid)?
1147
+ - What cloud provider will be used (GCP / `pareto-platform-gcp` is the Pareto platform standard; or AWS, Azure, on-premises, hybrid)?
1133
1148
  - What is the account and subscription structure?
1134
1149
  - What regions and availability zones are required?
1135
1150
  - Are there data sovereignty or residency requirements that constrain hosting?
@@ -1138,12 +1153,12 @@ This session uses the **Session 3: Process-First Protocol** (Steps 5A–5G descr
1138
1153
  2. **Deployment strategy**
1139
1154
  - What deployment model will be used (blue-green, canary, rolling, immutable)?
1140
1155
  - How will the CI/CD pipeline be structured?
1141
- - What tools will be used for CI/CD (GitHub Actions, Azure DevOps, GitLab CI, Jenkins)?
1156
+ - What tools will be used for CI/CD (GitLab CI is the Pareto platform pipeline; or GitHub Actions, Azure DevOps, Jenkins)?
1142
1157
  - How will infrastructure be managed (IaC with Terraform, Pulumi, CloudFormation)?
1143
- - What is the approach to containerization (Docker, Kubernetes, ECS, App Service)?
1158
+ - What is the approach to containerization (GKE or Cloud Run via pareto-platform-gcp; Docker/Kubernetes on-prem; or other cloud options)?
1144
1159
 
1145
1160
  3. **Monitoring, logging, and alerting**
1146
- - What monitoring platform will be used (Datadog, New Relic, Azure Monitor, CloudWatch)?
1161
+ - What monitoring platform will be used (Google Cloud Monitoring / Cloud Logging via pareto-platform-gcp; or Datadog, New Relic, CloudWatch)?
1147
1162
  - What metrics will be tracked (latency, error rate, throughput, saturation)?
1148
1163
  - What is the alerting strategy (thresholds, escalation chains, on-call rotation)?
1149
1164
  - How will application logs be aggregated and queried?
@@ -1162,6 +1177,8 @@ This session uses the **Session 3: Process-First Protocol** (Steps 5A–5G descr
1162
1177
 
1163
1178
  **Notes Template:**
1164
1179
 
1180
+ > **Platform standard (D-08):** The Pareto deployment platform is GCP / `pareto-platform-gcp` with GitLab CI as the CI/CD pipeline and Google Cloud Monitoring / Cloud Logging for observability. Fill the tables below against this baseline unless the client has an overriding constraint.
1181
+
1165
1182
  **Infrastructure Architecture**
1166
1183
 
1167
1184
  | Component | Service / Product | Region | Tier / SKU | Redundancy | Est. Monthly Cost | Notes |
@@ -0,0 +1,37 @@
1
+ # Client-context gate (Build) — execute-phase sub-step
2
+
3
+ Confirms the Build agent has client context in hand before any executor is dispatched.
4
+ Gated entirely on `.platform-bindings.json` (D-13 / D-04, mirroring Phase 9): when no
5
+ bindings file is present this gate is a **no-op** — no prompt fires and Build proceeds
6
+ unchanged. All checks are **offline** — this gate never calls Obsidian, MCP, or any network
7
+ resource. The captured `## Client Context & Patterns` block in CLAUDE.md (the Phase 9
8
+ artifact, already on the Build/Validate read path) is the source of truth; the live vault is
9
+ out of scope here.
10
+
11
+ ```bash
12
+ _PP_SHIM_NAME="pp-tools.cjs"; _PP_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; PP_TOOLS="${_PP_RUNTIME_ROOT}/pp-core/bin/${_PP_SHIM_NAME}"; if [ -f "$PP_TOOLS" ]; then pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif command -v pp-tools >/dev/null 2>&1; then PP_TOOLS="$(command -v pp-tools)"; pp_run() { "$PP_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$PP_TOOLS" "$@"; }; 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}"; pp_run() { node "$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
13
+ CTX_GATE_PRESENT=$(pp_run query platform-bindings --pick present 2>/dev/null || echo false)
14
+ CTX_BLOCK=$(pp_run query generate-client-context --read 2>/dev/null || echo '{"present":false}')
15
+ CTX_BLOCK_PRESENT=$(printf '%s' "$CTX_BLOCK" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{process.stdout.write(String((JSON.parse(d).present)||false));}catch{process.stdout.write('false');}")
16
+ ```
17
+
18
+ **If `CTX_GATE_PRESENT` != `true`:** skip entirely (non-Pareto project — fully inert).
19
+
20
+ **If `CTX_GATE_PRESENT` == `true` and `CTX_BLOCK_PRESENT` == `true`:** the client-context
21
+ block exists and is on the executor's read path. Surface a one-line confirmation
22
+ ("Client context loaded from CLAUDE.md — Build will apply captured client patterns.") and
23
+ require an explicit `confirmed` acknowledgment (`AskUserQuestion`, or a typed `confirmed` in
24
+ TEXT_MODE) before dispatching any executor. Advisory checkpoint, not a hard block.
25
+
26
+ **If `CTX_GATE_PRESENT` == `true` and `CTX_BLOCK_PRESENT` == `false`:** bindings indicate a
27
+ Pareto/client engagement but no client-context block was captured. Warn: "No
28
+ `## Client Context & Patterns` block found in CLAUDE.md — Build may proceed without client
29
+ patterns." Offer (`AskUserQuestion` / TEXT_MODE numbered list):
30
+
31
+ - **Capture now (recommended)** — pause and run `/pp-init` (its gated client-context step) to
32
+ write the block, then re-run `/pp-execute-phase`.
33
+ - **Proceed without** — continue knowingly; the executor builds without captured client
34
+ context. Requires an explicit `confirmed`.
35
+
36
+ `TEXT_MODE` follows the same rule as the host workflow (`--text` in `$ARGUMENTS`): replace
37
+ `AskUserQuestion` with a plain-text numbered prompt.
@@ -336,6 +336,10 @@ pp_run query state.begin-phase --phase "${PHASE_NUMBER}" --name "${PHASE_NAME}"
336
336
  This updates Status, Last Activity, Current focus, Current Position, and plan counts in STATE.md so frontmatter and body text reflect the active phase immediately.
337
337
  </step>
338
338
 
339
+ <step name="client_context_gate">
340
+ Read and execute `pp-core/workflows/execute-phase/steps/client-context-gate.md` — Pareto client-context gate (inert without `.platform-bindings.json`; confirms the Phase 9 CLAUDE.md block first).
341
+ </step>
342
+
339
343
  <step name="discover_and_group_plans">
340
344
  Load plan inventory with wave grouping in one call:
341
345