@webpresso/plugin-codex 0.0.16 → 0.0.17

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wp",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "description": "Webpresso app: blueprints, skills, hooks, and MCP server",
5
5
  "author": {
6
6
  "name": "Webpresso",
package/bin/wp CHANGED
@@ -17,8 +17,11 @@
17
17
  # when the admitted repository's own .git/worktrees/*/gitdir names it.
18
18
  # 3. else (no checkout ancestor at all) the nearest ancestor
19
19
  # .webpressorc.json: its top-level exact-semver "runtime" pin
20
- # -> ~/.webpresso/runtimes/<pin>/wp (missing = error)
21
- # 4. else the newest stable ~/.webpresso/runtimes/<x.y.z>/wp
20
+ # -> ~/.webpresso/versions/<pin>/bin/wp, else the legacy
21
+ # ~/.webpresso/runtimes/<pin>/wp (missing = error)
22
+ # 4. else the installer's active release ~/.webpresso/current/bin/wp, else
23
+ # the newest stable ~/.webpresso/versions/<x.y.z>/bin/wp, else the legacy
24
+ # newest stable ~/.webpresso/runtimes/<x.y.z>/wp
22
25
  # 5. else a named error, exit 127 — never a different runtime. A pre-shim
23
26
  # ~/.webpresso/bin/wp is never run implicitly (nothing in it proves it is
24
27
  # a release rather than a development build); name it with
@@ -110,7 +113,12 @@ is_exact_semver() {
110
113
  return 0
111
114
  }
112
115
 
113
- runtimes_dir=${HOME:-}/.webpresso/runtimes
116
+ # Release layout literals; src/runtime/runtime-selector-vocab.ts (WP_RELEASE_LAYOUTS)
117
+ # is the authority and bin/wp-shim.subprocess.test.ts asserts both directions.
118
+ webpresso_home=${HOME:-}/.webpresso
119
+ current_release=$webpresso_home/current/bin/wp
120
+ versions_dir=$webpresso_home/versions
121
+ runtimes_dir=$webpresso_home/runtimes
114
122
 
115
123
  # Sets PIN to the top-level "runtime" of $1 (empty when absent). The document
116
124
  # is opened non-blocking, must be a regular file, and is read through a
@@ -146,33 +154,50 @@ read_pin() {
146
154
  return 1
147
155
  }
148
156
 
149
- choose_latest_release() {
150
- best=
157
+ # Sets BEST to the newest stable x.y.z under directory $1 whose release binary
158
+ # is "$1/<version>/$2" (an executable file); empty when there is none.
159
+ scan_releases() {
160
+ BEST=
151
161
  best_major=
152
162
  best_minor=
153
163
  best_patch=
154
- for entry in "$runtimes_dir"/*/; do
164
+ for entry in "$1"/*/; do
155
165
  [ -d "$entry" ] || continue
156
166
  entry=${entry%/}
157
167
  version=${entry##*/}
158
168
  is_exact_semver "$version" stable || continue
159
- [ -f "$entry/wp" ] && [ -x "$entry/wp" ] || continue
169
+ [ -f "$entry/$2" ] && [ -x "$entry/$2" ] || continue
160
170
  major=${version%%.*}
161
171
  rest=${version#*.}
162
172
  minor=${rest%%.*}
163
173
  patch=${rest#*.}
164
- if [ -z "$best" ] ||
174
+ if [ -z "$BEST" ] ||
165
175
  [ "$major" -gt "$best_major" ] ||
166
176
  { [ "$major" -eq "$best_major" ] && [ "$minor" -gt "$best_minor" ]; } ||
167
177
  { [ "$major" -eq "$best_major" ] && [ "$minor" -eq "$best_minor" ] && [ "$patch" -gt "$best_patch" ]; }; then
168
- best=$version
178
+ BEST=$version
169
179
  best_major=$major
170
180
  best_minor=$minor
171
181
  best_patch=$patch
172
182
  fi
173
183
  done
174
- if [ -n "$best" ]; then
175
- choose latest-release "$runtimes_dir/$best/wp"
184
+ }
185
+
186
+ # The installer's active release (the current link) wins, then the newest
187
+ # versions/x.y.z/bin/wp, then the legacy runtimes/x.y.z/wp.
188
+ choose_latest_release() {
189
+ if [ -f "$current_release" ] && [ -x "$current_release" ]; then
190
+ choose current-release "$current_release"
191
+ return 0
192
+ fi
193
+ scan_releases "$versions_dir" bin/wp
194
+ if [ -n "$BEST" ]; then
195
+ choose latest-release "$versions_dir/$BEST/bin/wp"
196
+ return 0
197
+ fi
198
+ scan_releases "$runtimes_dir" wp
199
+ if [ -n "$BEST" ]; then
200
+ choose latest-release "$runtimes_dir/$BEST/wp"
176
201
  return 0
177
202
  fi
178
203
  return 1
@@ -189,14 +214,15 @@ choose_release() {
189
214
  read_pin "$rc_file" || fail pin-invalid "$rc_file $PIN_PROBLEM."
190
215
  if [ -n "$PIN" ]; then
191
216
  is_exact_semver "$PIN" || fail pin-invalid "$rc_file pins runtime \"$PIN\"; use an exact version such as 1.2.3 (no ranges)."
192
- pinned=$runtimes_dir/$PIN/wp
193
- [ -f "$pinned" ] && [ -x "$pinned" ] || fail pin-not-installed "$rc_file pins runtime $PIN, but $pinned is not installed under $runtimes_dir."
217
+ pinned=$versions_dir/$PIN/bin/wp
218
+ [ -f "$pinned" ] && [ -x "$pinned" ] || pinned=$runtimes_dir/$PIN/wp
219
+ [ -f "$pinned" ] && [ -x "$pinned" ] || fail pin-not-installed "$rc_file pins runtime $PIN, but it is installed under neither $versions_dir/$PIN/bin/wp nor $runtimes_dir/$PIN/wp."
194
220
  choose pinned-release "$pinned"
195
221
  return 0
196
222
  fi
197
223
  fi
198
224
  choose_latest_release && return 0
199
- fail no-release-installed "no webpresso source checkout above $PWD and no release under $runtimes_dir; install the Webpresso app, or name a runtime explicitly with WEBPRESSO_WP_BIN (for example a pre-shim \$HOME/.webpresso/bin/wp release) or WP_FORCE_JIT_PATH (a source checkout)."
225
+ fail no-release-installed "no webpresso source checkout above $PWD and no release at $current_release, under $versions_dir or under $runtimes_dir; install the Webpresso app, or name a runtime explicitly with WEBPRESSO_WP_BIN (for example a pre-shim \$HOME/.webpresso/bin/wp release) or WP_FORCE_JIT_PATH (a source checkout)."
200
226
  }
201
227
 
202
228
  : "${WEBPRESSO_WP_BIN:=}"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpresso/plugin-codex",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "private": false,
5
5
  "description": "Codex plugin adapter for the Webpresso app (wp CLI) skills, hooks, and MCP runtime.",
6
6
  "homepage": "https://github.com/webpresso/app#readme",
@@ -2,12 +2,15 @@
2
2
  "schemaVersion": 1,
3
3
  "host": "codex",
4
4
  "packageName": "@webpresso/plugin-codex",
5
- "packageVersion": "0.0.16",
5
+ "packageVersion": "0.0.17",
6
6
  "runtimeDirs": [".codex/skills", ".agents/skills"],
7
7
  "skills": {
8
8
  "ai-deslop": {
9
9
  "digest": "sha256:cf07df5835037f10401400e220c1c923f5325a6149d59c231ce316e10595fdfc"
10
10
  },
11
+ "antigravity": {
12
+ "digest": "sha256:729c4dd74e5c6394c31de23d04f664140088ee58ddfc57f3a2751394945a938b"
13
+ },
11
14
  "autopilot": {
12
15
  "digest": "sha256:8355f6ddc6e53e68ada49248bdd8d8beb0069ed09d3f2d346debc2401270445c"
13
16
  },
@@ -27,7 +30,7 @@
27
30
  "digest": "sha256:574669e040141e9986e362e9f46e3176aa47eccfda0f4589205d9d6d65e57b8d"
28
31
  },
29
32
  "deep-interview": {
30
- "digest": "sha256:1d5bbb564dde9037722d2029f771afb52c2fe000a2b38822db430224cbe3407d"
33
+ "digest": "sha256:6feeaa35de63a0e1f39dbe2882ca91a72928a058f138d4d79e70d81d09209693"
31
34
  },
32
35
  "deep-research": {
33
36
  "digest": "sha256:ece766cb18869317d7c8992fc562920b03250ff8c44bdcb9eccdc3b21922a83f"
@@ -42,16 +45,16 @@
42
45
  "digest": "sha256:306355888da0827e3523022077f731845726bbaaf595ca12515cc91d8605b5e6"
43
46
  },
44
47
  "fix": {
45
- "digest": "sha256:cf5d74995a690307ebbc3f6b017b03a0c2b395acecccb16dcfedbb9674d0f155"
48
+ "digest": "sha256:aa5caa229f0a56290bd6ad4487f41fd2933ac9e9cf4fdf2191f04a559bf66943"
46
49
  },
47
50
  "handoff": {
48
51
  "digest": "sha256:5d40899f54fabe3f6ec8f99b417345a433850585086570872a137a1d0d837002"
49
52
  },
50
53
  "hooks-doctor": {
51
- "digest": "sha256:0a32515ba42755847552991fe5dafe5bd9572a9540e7b376f56d8549320a4cf2"
54
+ "digest": "sha256:6169e2b4b3638b9b5430811cd44e7952a54685b6f6556ebe81a9aee8ade1a3e0"
52
55
  },
53
56
  "investigate": {
54
- "digest": "sha256:44578904d967161b9128830c7c66f9684bb8c8257e8da7884dd6dbda88743b39"
57
+ "digest": "sha256:b6d82b2dc76297167a8fb75422d1f7037c4b9f0c74186cc4a2d719246764ca7e"
55
58
  },
56
59
  "lore-protocol": {
57
60
  "digest": "sha256:a80fbacc765e8b886437b9fdf7dd71e1ceb1b98b939078ec90fc88d06a8b4c69"
@@ -72,10 +75,10 @@
72
75
  "digest": "sha256:b728dad90254d4c9f81b3818321d34ab53519b79ce20ff3bfe08bfacb2aa3e86"
73
76
  },
74
77
  "plan-refine": {
75
- "digest": "sha256:3dccc4e85ff7f355b1d7297b636d7acf3c31658b749fc1778ffdd1a255b27300"
78
+ "digest": "sha256:8a0e38564627565d267b347a0361eb222b9ba230961998c2d6812874ea7cf608"
76
79
  },
77
80
  "ralplan": {
78
- "digest": "sha256:aa8879addccc19c0cdb69fce945fe54cf356380203f774080f8655211a5841c3"
81
+ "digest": "sha256:95d02771d3e3a46d225b1bf9dd12a33e83c9e0dbe2c126aad24986c4cb1d98a3"
79
82
  },
80
83
  "team": {
81
84
  "digest": "sha256:e403a5a92d145e777d7a344fe8fc6fe5df44640691aa2319b6dfd50b909166f5"
@@ -87,13 +90,13 @@
87
90
  "digest": "sha256:23fdad944b089de3cfcd13957a5ac10c37bd3d136b192029af69368bca1470db"
88
91
  },
89
92
  "tooling-friction": {
90
- "digest": "sha256:7f6e60a2c886e0c735135ab66926fbbd1b54d9291036fb0ddea020c7754f1534"
93
+ "digest": "sha256:6f94949b6910d88ff974a95f4cd67bbaca05579db88fbeacc50126a13faf800b"
91
94
  },
92
95
  "tph": {
93
96
  "digest": "sha256:bed3684a850651534f315d355cdeae50d951c429817df0f105cccdb7f4e1561b"
94
97
  },
95
98
  "ultragoal": {
96
- "digest": "sha256:8826e955c3a68f962d73a4b476d952574fa32e802c0d2616d569e58e7cfc29c3"
99
+ "digest": "sha256:e60091f795311fd4ee8779b60b04f835522163fcca5d27122740b66f66afeceb"
97
100
  },
98
101
  "verify": {
99
102
  "digest": "sha256:e1aa3baed96ef005b144e17fac8a2153b90a075b142acee2fdfba7c89e613765"
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: antigravity
3
+ description: "Antigravity outside-voice reviewer through Webpresso MCP."
4
+ license: MIT
5
+ ---
6
+
7
+ # Antigravity outside-voice review
8
+
9
+ Use only for a requested content-bound plan or delivery review. Treat output as external advice
10
+ until independently verified.
11
+
12
+ ## MCP-only contract
13
+
14
+ - Call `review_gate` exactly once for the real plan version or delivery diff.
15
+ - Observe the same durable operation with `review_gate_wait` when needed.
16
+ - Never invoke a provider command, the legacy review CLI, or a removed review-run surface.
17
+ - If the review MCP is unavailable, stop and report it unavailable. There is no CLI fallback.
18
+
19
+ ## Gate call
20
+
21
+ ```jsonc
22
+ {
23
+ "project_id": "<project>",
24
+ "slug": "<blueprint-slug>",
25
+ "purpose": "delivery",
26
+ "base_ref": "<full-base-sha>",
27
+ "authority_ref": "<full-head-sha>",
28
+ "caller_model": "<your own model id, exactly as your host reports it>",
29
+ "repository_access": "none",
30
+ }
31
+ ```
32
+
33
+ Each newly executed provider review that reaches a verdict is one formal round of the
34
+ slug's budget, and its approval is authority. An identical-subject call replays the recorded
35
+ verdict with no new review and no new round. A partial approval, withheld because adjudication
36
+ is incomplete (not every prior finding was briefed, or a briefed prior claim was marked
37
+ still-open without a matching finding), grants no authority and spends no round.
38
+
39
+ ## Reviewer selection
40
+
41
+ Pass `caller_model` with your OWN model id, exactly as your host reports it, and omit
42
+ `provider`, `model`, and `effort`: the gate selects the reviewer route itself — a cross-family
43
+ reviewer chosen for capability, current provider limits, and measured daily cost — and reports
44
+ the choice in `policy_selection`. Never name a reviewer model, probe a provider CLI for its
45
+ catalog, or read a credential store to discover models at invocation time; provider catalog
46
+ discovery belongs to the snapshot drift workflow. An operator may still pass an explicit
47
+ `provider`/`model` as a human override; agents must not.
48
+
49
+ ## Review quality
50
+
51
+ Follow `catalog/agent/rules/review-methodology-sota.md`; report typed verdict, model,
52
+ artifact, grounded findings, and independently verified conclusions.
@@ -219,7 +219,7 @@ Present execution options after artifact generation using explicit handoff contr
219
219
  - **`autopilot`** — when the spec is already strong enough for direct planning plus execution. Consumer uses the spec as the clarified execution brief with the non-goals and acceptance criteria as binding context.
220
220
  - **`ultragoal`** — when the clarified work should become durable, sequentially tracked goal-mode work.
221
221
  - **`team`** — when the task is large, multi-lane, or blocker-sensitive enough to justify coordinated parallel execution.
222
- - **Blueprint lifecycle** — refine with `blueprint_put`, review the exact version with `review_gate`, and inspect the auto-promoted result with `blueprint_get` when work should enter planned execution directly.
222
+ - **Blueprint lifecycle** — refine with `blueprint_put`, review the exact version with `review_gate`, then promote the approved version explicitly with `blueprint_promote` when work should enter planned execution directly (MCP `review_gate` never auto-promotes).
223
223
  - **Refine further** — re-enter the loop to resolve the highest-leverage remaining uncertainty when residual ambiguity is still too high or an early-exit/above-threshold warning indicates too much risk to proceed cleanly.
224
224
 
225
225
  For research-shaped requests (a research question, evaluator-backed analysis, or reference gathering), hand off to `autoresearch` after the interview converges on a validator-ready mission; keep the explicit `refine further` vs `launch` boundary and do not launch until the user confirms.
@@ -98,6 +98,19 @@ there, the investigation work is part of `fix`.
98
98
  - Read enough surrounding code to say the broken invariant in one sentence.
99
99
  - If the issue is nondeterministic, gather evidence until you can describe the slow/flaky/failing case without guessing.
100
100
 
101
+ **Prove the mechanism before naming it.** A cause that merely explains the
102
+ symptom is a hypothesis, not a finding. Run the failing thing with the candidate
103
+ values and read what it actually did; trace the claim to the code that executes,
104
+ not the code whose name matches the theory. If you cannot reproduce it, label it
105
+ unverified and keep investigating — do not write it into a plan, commit, or
106
+ report as the cause.
107
+
108
+ **When a cause is disproved, go back to the command, not to the next story.**
109
+ Substituting another plausible explanation without new observation is how one
110
+ dead route gets three confident, wrong diagnoses. If your second and third
111
+ explanations are still unobserved, you have not reproduced the failure yet.
112
+ Related: `catalog/agent/rules/evidence-discipline.md` § 6.
113
+
101
114
  If the "issue" is actually several unrelated failures, stop and ask which one to fix first.
102
115
 
103
116
  ### Step 2 — Decide where the fix belongs
@@ -7,7 +7,7 @@ scope: repo
7
7
  applies_to: [agents]
8
8
  related: []
9
9
  created: "2026-05-07"
10
- last_reviewed: "2026-05-07"
10
+ last_reviewed: "2026-11-01"
11
11
  name: hooks-doctor
12
12
  description: "Hook/plugin doctor for install health. Use for hook blocked, pretooluse, plugin broken."
13
13
  argument-hint: "[--skip-mcp]"
@@ -55,13 +55,13 @@ Each check prints `[x]` (pass) or `[ ]` (fail) with a detail line:
55
55
 
56
56
  ## Failure Remediation
57
57
 
58
- | Check | Likely Cause | Fix |
59
- | ------------------------------------------------ | -------------------------------------------------------------- | ----------------------------------------------------------------- |
60
- | `pretool-guard` / `post-tool` / etc. — not found | `wp run build` not run after install | `wp run build` |
61
- | `pretool-guard` / etc. — not executable | `chmod +x` not persisted | Re-run `wp run prepare` or `wp run build` which runs `chmod-bins` |
62
- | `plugin.json integrity` — missing | Claude adapter manifest absent from `@webpresso/plugin-claude` | Re-run `wp setup --host claude` or reinstall the Claude plugin |
63
- | `MCP server liveness` — timeout | MCP server cold-start too slow | Wait and retry, or run `wp hooks doctor --skip-mcp` |
64
- | Any check — not found at `dist/esm/...` | Build artifacts missing | Run `wp run build` in the webpresso repo |
58
+ | Check | Likely Cause | Fix |
59
+ | ------------------------------------------------ | ----------------------------------------------------------------- | ----------------------------------------------------------------- |
60
+ | `pretool-guard` / `post-tool` / etc. — not found | `wp run build` not run after install | `wp run build` |
61
+ | `pretool-guard` / etc. — not executable | `chmod +x` not persisted | Re-run `wp run prepare` or `wp run build` which runs `chmod-bins` |
62
+ | `plugin.json integrity` — missing | Claude or Antigravity adapter manifest absent from plugin package | Re-run `wp setup --host <host>` or reinstall the host plugin |
63
+ | `MCP server liveness` — timeout | MCP server cold-start too slow | Wait and retry, or run `wp hooks doctor --skip-mcp` |
64
+ | Any check — not found at `dist/esm/...` | Build artifacts missing | Run `wp run build` in the webpresso repo |
65
65
 
66
66
  ### Updating the webpresso MCP server (monorepo authors)
67
67
 
@@ -95,6 +95,8 @@ started. Check the installed host version before using version-scoped controls.
95
95
  commands](https://dev.opencode.ai/v2/docs/cli/commands/); host documentation
96
96
  verified 2026-10-17). These `dev.opencode.ai` paths sit on a preview domain
97
97
  and can move; confirm the v2 path still resolves before following it.
98
+ - **Antigravity:** Preferences / Settings → Plugins → reload or toggle `wp` plugin,
99
+ or restart the Antigravity session. Verify with `wp hooks doctor` or `wp hooks status`.
98
100
 
99
101
  After reconnecting, prove the loaded source rather than the connection:
100
102
 
@@ -42,9 +42,20 @@ flaky behavior, or confusing symptom before editing code.
42
42
  - Name the broken invariant in one sentence.
43
43
  - Name the owner that should enforce it.
44
44
  - Separate facts from guesses.
45
+ - **Every cause must carry the observation that proved it**: the command you
46
+ ran, its output, and the code path that produced it. A cause you have not
47
+ executed against the failing case is a guess and must be labelled as one.
45
48
  4. Disconfirm cheap alternatives.
46
49
  - Test the obvious competing explanations before settling on one cause.
47
50
  - Add temporary diagnostics only when needed, and remove them after one pass.
51
+ - **When a cause is disproved, return to the reproduction rather than
52
+ replacing it with the next plausible story.** Two or three confident
53
+ explanations in a row, none observed, means the failure has not been
54
+ reproduced yet — go back to step 1.
55
+ - A test fixture, capability object, or recorded tool output that asserts
56
+ behaviour is the weakest link: confirm at least one path against the real
57
+ binary, module, or service it stands in for.
58
+ - Related: `catalog/agent/rules/evidence-discipline.md` § 6.
48
59
  5. Produce failing proof.
49
60
  - Prefer a targeted failing test.
50
61
  - If test-first is impossible at this boundary, use the nearest deterministic
@@ -75,6 +75,7 @@ Run **1–3 (and relevant review lenses) in parallel** whenever tools allow. Do
75
75
  - Score alternatives on elegance, durability, and efficiency; keep only the winner and write the rejection rationale for heavier options.
76
76
 
77
77
  4. **Plan-review lenses (skip when the caller already ran them).** Folded `/autoplan`: run relevant CEO/founder, design, engineering, and DevEx lenses **in parallel when independent**; consolidate keep/change/drop, unresolved taste calls, tests, go/no-go.
78
+ - **Review cost — know it before you dispatch.** An `approve`, `approve-with-nits`, or `reject` verdict from a `review_gate` run spends ONE formal review round (per slug and purpose). A no-verdict attempt spends none; editing the plan spends and resets nothing already spent. `src/review/budgets.ts` owns the numeric allowance — never restate it in prose — and `wp review budget <slug>` reports remaining capacity live.
78
79
  - **Skip condition.** If the caller states `plan-* reviews complete for this pass`, do **not** re-run the lenses. `ralplan` runs them before handing off, so re-running them here is duplicated spend, not a second opinion.
79
80
  - **Re-entry.** If refinement itself **materially changes scope**, re-run only the affected lens — never the full set — then continue applying.
80
81
  - **Re-review rounds.** `catalog/agent/rules/review-methodology-sota.md` Principle 5 sets the delta-anchored adjudication contract subsequent `review_gate` rounds follow.
@@ -42,6 +42,10 @@ Use when the user invokes `$ralplan`, asks for RALPLAN, or wants consensus plann
42
42
  1. **Blueprint is the plan.** Freeform notes are not durable consensus. Create or bind a blueprint before reviews.
43
43
  2. **Align with other lanes before planning.** This repo is worked by many concurrent agent sessions. Before the code dive, establish which surfaces another live lane already owns and record them as explicit non-goals. See [Lane alignment](#lane-alignment-not-optional). The user should not have to re-assert this.
44
44
  3. **Ground before drafting.** Code dive (+ bounded external research when needed) happens **before** the blueprint draft is treated as serious.
45
+ - **A stated cause is a claim that must be observed.** When a plan explains
46
+ why something fails, it carries the command that produced that answer.
47
+ An unobserved cause is a guess laundered into consensus, and review will
48
+ spend rounds disproving it instead of improving the plan.
45
49
  4. **Reviews before refine.** Run risk-matched `plan-*` skills on the blueprint, apply findings, **then** `/plan-refine`.
46
50
  5. **No implementation.** Do not edit product source, commit implementation, or start `ultragoal`/`team`/`autopilot` unless the user explicitly switches out of planning.
47
51
  6. **No review stampede.** Do not fan out multi-host outside-voice swarms. Prefer in-host skill loads; at most one outside voice only if the user asks or the change is auth / data-loss / public-API sensitive.
@@ -47,10 +47,30 @@ Optional post-land **product signal** for MCP/CLI/hooks/CI pain so Webpresso too
47
47
  4. Write the capture with the validating verb — it is the only writer, and it
48
48
  puts the document at the central, repo-scoped desktop state surface:
49
49
 
50
+ First write the capture JSON to a scratch file with the host's file-write
51
+ tool, under the scratch directory `$TMPDIR/webpresso/scratch/` (outside every
52
+ worktree, per the agent scratch write policy; never the repo root, and never
53
+ committed). Resolve that directory to an **absolute path** yourself and use
54
+ the literal path below — hosts refuse a command that carries a shell
55
+ variable expansion. Then hand the file to the verb with `--from-file`; no
56
+ pipe, redirect or shell variable is involved:
57
+
58
+ ```bash
59
+ wp tooling-friction write --file YYYY-MM-DD-<slug|pr|session>.json --from-file <absolute-scratch-dir>/tooling-friction-capture.json
60
+ ```
61
+
62
+ If your `wp` predates `--from-file`, **redirect** the same file to stdin
63
+ instead:
64
+
50
65
  ```bash
51
- printf '%s' "$CAPTURE_JSON" | wp tooling-friction write --file YYYY-MM-DD-<slug|pr|session>.json
66
+ wp tooling-friction write --file YYYY-MM-DD-<slug|pr|session>.json < <absolute-scratch-dir>/tooling-friction-capture.json
52
67
  ```
53
68
 
69
+ Do not pipe a shell variable into the verb (`printf '%s' "$CAPTURE_JSON" | …`):
70
+ hosts refuse the unresolvable expansion, and the fallback — writing the JSON
71
+ straight into the store — skips validation, which is how a capture with ten
72
+ schema issues reached disk. Never write the capture into the store yourself.
73
+
54
74
  The verb parses the document through the shared schema helper **before** it
55
75
  touches disk, so a capture that violates v1 is refused (non-zero exit,
56
76
  naming every failing field path) and nothing is written. It prints the
@@ -190,7 +190,7 @@ Fallback to `wp …` CLI only when the matching MCP tool is unavailable. Prefer
190
190
  Controller validation evidence is **machine-qa (prior QA phase) + N outside voices**
191
191
  (default N=1), not two outside model reviewers at budget 1.
192
192
  `review_gate` has one mode: purpose plan for exact-version draft plan
193
- approval/auto-promotion, purpose delivery for implementation/phase outside
193
+ approval (then `blueprint_promote`), purpose delivery for implementation/phase outside
194
194
  voice. Each new provider verdict is a formal round of the slug's budget and
195
195
  an approval is authority immediately. A CLI delivery gate is explicit MCP-unavailable
196
196
  compatibility only, not this MCP contract. Use `pr_*` for PR babysit — no
@@ -211,7 +211,7 @@ primary checkout.
211
211
 
212
212
  ## Outside-voice review (required for autopilot)
213
213
 
214
- Autopilot and agent-driven ultragoal loops **must** request an outside-voice review after each **goal/phase milestone**. Use **`review_gate`** purpose plan for exact-version draft plan approval/auto-promotion and one single-shot **`review_gate`** purpose delivery call for implementation/phase outside voice. The gate has one mode: each newly executed provider review that reaches a verdict is a formal round of the slug's budget, an approval is authority immediately, and an identical-subject call replays the recorded verdict without a new round. CLI delivery gates are explicit MCP-unavailable compatibility only, not this MCP contract.
214
+ Autopilot and agent-driven ultragoal loops **must** request an outside-voice review after each **goal/phase milestone**. Use **`review_gate`** purpose plan for exact-version draft plan approval (then promote with `blueprint_promote`) and one single-shot **`review_gate`** purpose delivery call for implementation/phase outside voice. The gate has one mode: each newly executed provider review that reaches a verdict is a formal round of the slug's budget, an approval is authority immediately, and an identical-subject call replays the recorded verdict without a new round. CLI delivery gates are explicit MCP-unavailable compatibility only, not this MCP contract.
215
215
 
216
216
  Count each milestone review against `review_budget` for merge-ready claims: **exactly one sequential** reviewer path unless the user sets N; the default value is owned by `workflow-skills-routing.md`. Do not fan out multi-host review swarms.
217
217
 
@@ -223,7 +223,7 @@ milestones. Each new provider verdict is one formal round of the slug's budget.
223
223
 
224
224
  | Milestone | When |
225
225
  | ------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
226
- | Plan gate | Before `draft` → `planned`, using the exact version returned by `blueprint_put`; approval may auto-promote the same version |
226
+ | Plan gate | Before `draft` → `planned`, using the exact version returned by `blueprint_put`; then `blueprint_promote` the approved version |
227
227
  | Phase advance | After ultragoal advances `plan` → `execute`, `execute` → `qa`, `qa` → `validate`, `validate` → `land`, or lands `complete` |
228
228
  | Task batch handoff | After a meaningful execute batch when the phase remains `execute` (at least once per blueprint before claiming execute-complete) |
229
229