@webpresso/plugin-codex 0.0.12 → 0.0.14

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": "agent-kit",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "Webpresso agent-kit: blueprints, skills, hooks, and MCP server",
5
5
  "author": {
6
6
  "name": "Webpresso",
package/bin/wp CHANGED
@@ -1,54 +1,250 @@
1
1
  #!/bin/sh
2
- # Resolve the Webpresso `wp` executable and hand this process over to it.
2
+ # webpresso-wp-shim v1 — keep this marker on line 2 (shim loop guard).
3
3
  #
4
- # `exec` rather than a spawn wrapper: the MCP server this shim launches is a
5
- # long-lived stdio service, and a wrapper process that merely relays for it is a
6
- # layer that can die while leaving the server behind, orphaned and holding the
7
- # client's pipe. After `exec` there is no shim process left to strand — the
8
- # launcher IS this pid, so the host's signals and pipe closure reach it directly.
9
- # It also makes every non-MCP command a byte-exact passthrough, including TTY
10
- # behavior that a relay would otherwise disturb.
4
+ # The one `wp` shim. Copied byte-identically into each plugin's bin/wp
5
+ # (packages/scripts/stage-plugin-runtime-artifacts.ts) and, once the release
6
+ # installer adopts it, into ~/.webpresso/bin/wp. It stores no state, writes
7
+ # nothing, and picks the runtime on EVERY call from where it is called:
11
8
  #
12
- # Arguments are forwarded verbatim through the quoted "$@" expansion. The plugin
13
- # manifest invokes this file as `bin/wp mcp`, so dropping or word-splitting
14
- # arguments would silently break the only real launch surface.
9
+ # 1. WEBPRESSO_WP_BIN (an absolute executable) xor WP_FORCE_JIT_PATH (an
10
+ # absolute checkout)
11
+ # 2. the nearest ancestor of $PWD that is a webpresso source checkout
12
+ # (bin/wp + src/cli/cli.ts) ADMITTED in ~/.webpresso/source-checkouts
13
+ # -> <checkout>/bin/wp, whose own launcher guards freshness against HEAD.
14
+ # Layout is not trust: a source-shaped directory whose repository is not
15
+ # listed there fails with checkout-not-admitted instead of running its
16
+ # bin/wp. A linked worktree is admitted through its repository, and only
17
+ # when the admitted repository's own .git/worktrees/*/gitdir names it.
18
+ # 3. else (no checkout ancestor at all) the nearest ancestor
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
22
+ # 5. else a named error, exit 127 — never a different runtime. A pre-shim
23
+ # ~/.webpresso/bin/wp is never run implicitly (nothing in it proves it is
24
+ # a release rather than a development build); name it with
25
+ # WEBPRESSO_WP_BIN.
26
+ #
27
+ # Bounded: a parent-directory walk, one-line reads of the user's admission file
28
+ # and of admitted repositories' worktree back-links, at most one size-capped
29
+ # JSON read (node, only in a consumer repo with a
30
+ # .webpressorc.json), one directory listing. No git, no network, no retries,
31
+ # no timeouts. Mode and error literals
32
+ # are the closed vocabulary in src/runtime/runtime-selector-vocab.ts.
33
+ #
34
+ # `exec`, not a spawn wrapper: the MCP server this launches is a long-lived
35
+ # stdio service, and a relay process could die and orphan it. Arguments are
36
+ # forwarded verbatim through "$@".
15
37
 
16
38
  set -u
17
39
 
40
+ announced_modes='explicit-binary explicit-checkout'
41
+
18
42
  fail() {
19
- printf '%s\n' "$1" >&2
20
- exit 1
43
+ printf 'wp-shim: error %s: %s\n' "$1" "$2" >&2
44
+ exit 127
45
+ }
46
+
47
+ MODE=
48
+ TARGET=
49
+ choose() {
50
+ MODE=$1
51
+ TARGET=$2
52
+ }
53
+
54
+ admission_file=${HOME:-}/.webpresso/source-checkouts
55
+
56
+ is_source_shaped() {
57
+ [ -f "$1/bin/wp" ] && [ -x "$1/bin/wp" ] && [ -f "$1/src/cli/cli.ts" ]
58
+ }
59
+
60
+ # True when checkout $1 is an admitted repository's primary checkout, or one of
61
+ # its registered linked worktrees. The admission file is user-owned, one
62
+ # absolute primary-checkout path per line. Identity is by directory (-ef), and
63
+ # a linked worktree is recognized only from the admitted repository's own
64
+ # .git/worktrees/*/gitdir back-links: nothing inside the project (its .git
65
+ # file, symlink or metadata) is ever read or trusted, and stat never blocks.
66
+ is_admitted_checkout() {
67
+ [ -f "$admission_file" ] || return 1
68
+ while IFS= read -r entry || [ -n "$entry" ]; do
69
+ case $entry in /*) ;; *) continue ;; esac
70
+ [ "$entry" -ef "$1" ] && return 0
71
+ for meta in "$entry"/.git/worktrees/*/; do
72
+ [ -f "${meta}gitdir" ] || continue
73
+ back=
74
+ IFS= read -r back <"${meta}gitdir" || [ -n "$back" ] || continue
75
+ [ "${back%/.git}" -ef "$1" ] && return 0
76
+ done
77
+ done <"$admission_file"
78
+ return 1
79
+ }
80
+
81
+ # Exact semver x.y.z[-pre], no leading zeros, no build metadata. With a second
82
+ # argument "stable", a prerelease is rejected too.
83
+ is_exact_semver() {
84
+ version=$1
85
+ core=${version%%-*}
86
+ pre=
87
+ if [ "$core" != "$version" ]; then
88
+ pre=${version#*-}
89
+ [ "${2:-}" != stable ] || return 1
90
+ case $pre in '' | .* | *. | *..* | *[!0-9A-Za-z.-]*) return 1 ;; esac
91
+ saved_ifs=$IFS
92
+ IFS=.
93
+ # shellcheck disable=SC2086 # deliberate field split on "."
94
+ set -- $pre
95
+ IFS=$saved_ifs
96
+ for part in "$@"; do
97
+ case $part in 0?*) case $part in *[!0-9]*) ;; *) return 1 ;; esac ;; esac
98
+ done
99
+ fi
100
+ case $core in '' | .* | *. | *..* | *[!0-9.]*) return 1 ;; esac
101
+ saved_ifs=$IFS
102
+ IFS=.
103
+ # shellcheck disable=SC2086 # deliberate field split on "."
104
+ set -- $core
105
+ IFS=$saved_ifs
106
+ [ "$#" -eq 3 ] || return 1
107
+ for part in "$@"; do
108
+ case $part in '' | 0?* | *[!0-9]*) return 1 ;; esac
109
+ done
110
+ return 0
111
+ }
112
+
113
+ runtimes_dir=${HOME:-}/.webpresso/runtimes
114
+
115
+ # Sets PIN to the top-level "runtime" of $1 (empty when absent). The document
116
+ # is opened non-blocking, must be a regular file, and is read through a
117
+ # 64 KiB + 1 buffer on that one descriptor (growth after open cannot exceed
118
+ # it); anything longer is refused. The pin
119
+ # is validated as an exact semver BEFORE it crosses back into the shell, so no
120
+ # shell transport (such as a stripped trailing newline) can change it.
121
+ read_pin() {
122
+ PIN=$(node -e '
123
+ const fs = require("node:fs");
124
+ let fd;
125
+ try { fd = fs.openSync(process.argv[1], fs.constants.O_RDONLY | fs.constants.O_NONBLOCK); } catch { process.exit(2); }
126
+ if (!fs.fstatSync(fd).isFile()) process.exit(3);
127
+ const limit = 65536;
128
+ const buffer = Buffer.alloc(limit + 1);
129
+ let length = 0;
130
+ for (let n; length <= limit && (n = fs.readSync(fd, buffer, length, limit + 1 - length, null)) > 0; ) length += n;
131
+ if (length > limit) process.exit(3);
132
+ let v;
133
+ try { v = JSON.parse(buffer.subarray(0, length).toString("utf8")); } catch { process.exit(2); }
134
+ if (v === null || typeof v !== "object" || Array.isArray(v) || !Object.hasOwn(v, "runtime")) process.exit(0);
135
+ const pattern = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*)?$/u;
136
+ if (typeof v.runtime !== "string" || !pattern.test(v.runtime)) process.exit(4);
137
+ process.stdout.write(v.runtime);
138
+ ' "$1" 2>/dev/null)
139
+ case $? in
140
+ 0) return 0 ;;
141
+ 3) PIN_PROBLEM="is not a regular file of at most 64 KiB" ;;
142
+ 4) PIN_PROBLEM="has a \"runtime\" pin that is not an exact version such as 1.2.3 (no ranges, no build metadata)" ;;
143
+ 127) PIN_PROBLEM="cannot be read: node is not on PATH" ;;
144
+ *) PIN_PROBLEM="is not valid JSON" ;;
145
+ esac
146
+ return 1
147
+ }
148
+
149
+ choose_latest_release() {
150
+ best=
151
+ best_major=
152
+ best_minor=
153
+ best_patch=
154
+ for entry in "$runtimes_dir"/*/; do
155
+ [ -d "$entry" ] || continue
156
+ entry=${entry%/}
157
+ version=${entry##*/}
158
+ is_exact_semver "$version" stable || continue
159
+ [ -f "$entry/wp" ] && [ -x "$entry/wp" ] || continue
160
+ major=${version%%.*}
161
+ rest=${version#*.}
162
+ minor=${rest%%.*}
163
+ patch=${rest#*.}
164
+ if [ -z "$best" ] ||
165
+ [ "$major" -gt "$best_major" ] ||
166
+ { [ "$major" -eq "$best_major" ] && [ "$minor" -gt "$best_minor" ]; } ||
167
+ { [ "$major" -eq "$best_major" ] && [ "$minor" -eq "$best_minor" ] && [ "$patch" -gt "$best_patch" ]; }; then
168
+ best=$version
169
+ best_major=$major
170
+ best_minor=$minor
171
+ best_patch=$patch
172
+ fi
173
+ done
174
+ if [ -n "$best" ]; then
175
+ choose latest-release "$runtimes_dir/$best/wp"
176
+ return 0
177
+ fi
178
+ return 1
179
+ }
180
+
181
+ is_shim_file() {
182
+ [ -f "$1" ] || return 1
183
+ { head -c 256 "$1" | grep -q 'webpresso-wp-shim'; } 2>/dev/null
184
+ }
185
+
186
+ choose_release() {
187
+ if [ -n "${1:-}" ]; then
188
+ rc_file=$1/.webpressorc.json
189
+ read_pin "$rc_file" || fail pin-invalid "$rc_file $PIN_PROBLEM."
190
+ if [ -n "$PIN" ]; then
191
+ 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."
194
+ choose pinned-release "$pinned"
195
+ return 0
196
+ fi
197
+ fi
198
+ 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)."
21
200
  }
22
201
 
23
202
  : "${WEBPRESSO_WP_BIN:=}"
24
203
  : "${WP_FORCE_JIT_PATH:=}"
25
204
 
26
205
  if [ -n "$WEBPRESSO_WP_BIN" ] && [ -n "$WP_FORCE_JIT_PATH" ]; then
27
- fail "WEBPRESSO_WP_BIN and WP_FORCE_JIT_PATH are both set; unset one. Product path is the Webpresso app launcher (~/.webpresso/bin/wp) or monorepo JIT (WP_FORCE_JIT_PATH to a webpresso/app checkout). Do not dual-set overrides."
28
- fi
29
-
30
- if [ -n "$WEBPRESSO_WP_BIN" ]; then
31
- target=$WEBPRESSO_WP_BIN
32
- source_label=WEBPRESSO_WP_BIN
206
+ fail both-overrides-set "WEBPRESSO_WP_BIN and WP_FORCE_JIT_PATH are both set; unset one."
207
+ elif [ -n "$WEBPRESSO_WP_BIN" ]; then
208
+ case $WEBPRESSO_WP_BIN in /*) ;; *) fail override-missing "WEBPRESSO_WP_BIN must be an absolute path (got $WEBPRESSO_WP_BIN); exec would otherwise search PATH for a different file." ;; esac
209
+ [ -f "$WEBPRESSO_WP_BIN" ] && [ -x "$WEBPRESSO_WP_BIN" ] || fail override-missing "WEBPRESSO_WP_BIN points to $WEBPRESSO_WP_BIN, which is not an executable file."
210
+ choose explicit-binary "$WEBPRESSO_WP_BIN"
33
211
  elif [ -n "$WP_FORCE_JIT_PATH" ]; then
34
- target=$WP_FORCE_JIT_PATH/bin/wp
35
- source_label=WP_FORCE_JIT_PATH
212
+ case $WP_FORCE_JIT_PATH in /*) ;; *) fail override-missing "WP_FORCE_JIT_PATH must be an absolute path (got $WP_FORCE_JIT_PATH)." ;; esac
213
+ is_source_shaped "$WP_FORCE_JIT_PATH" || fail override-missing "WP_FORCE_JIT_PATH points to $WP_FORCE_JIT_PATH, which is not a webpresso source checkout (executable bin/wp and src/cli/cli.ts)."
214
+ choose explicit-checkout "$WP_FORCE_JIT_PATH/bin/wp"
36
215
  else
37
- target=${HOME:-}/.webpresso/bin/wp
38
- source_label="Webpresso app launcher"
216
+ # Checkout first, across every ancestor: a .webpressorc.json nested inside
217
+ # a source checkout must not pin a foreign runtime there. Only when no
218
+ # ancestor is a checkout does the nearest consumer config decide.
219
+ dir=${PWD:-}
220
+ consumer_root=
221
+ while [ -n "$dir" ]; do
222
+ if is_source_shaped "$dir"; then
223
+ is_admitted_checkout "$dir" || fail checkout-not-admitted "$dir looks like a webpresso source checkout, but its repository is not listed in $admission_file; add the absolute path of its primary checkout there (one per line) to run its bin/wp, or set WP_FORCE_JIT_PATH=$dir for this call."
224
+ choose checkout "$dir/bin/wp"
225
+ break
226
+ fi
227
+ if [ -z "$consumer_root" ] && [ -e "$dir/.webpressorc.json" ]; then
228
+ consumer_root=$dir
229
+ fi
230
+ [ "$dir" != / ] || break
231
+ dir=${dir%/*}
232
+ [ -n "$dir" ] || dir=/
233
+ done
234
+ [ -n "$TARGET" ] || choose_release "$consumer_root"
39
235
  fi
40
236
 
41
- # Refuse to exec this shim again: a self-referential target would loop forever
42
- # instead of failing with a diagnostic.
43
- if [ "$target" = "$0" ]; then
44
- fail "$source_label points to this shim ($target); set it to the Webpresso wp executable instead."
237
+ # Never exec a shim: this one (directly or through a symlink) or another
238
+ # byte-identical plugin copy would recurse instead of reaching a runtime.
239
+ if [ "$TARGET" = "$0" ] || [ "$TARGET" -ef "$0" ] || is_shim_file "$TARGET"; then
240
+ fail self-reference "$MODE resolved to a wp shim ($TARGET); point it at a wp runtime instead."
45
241
  fi
46
242
 
47
- if [ ! -f "$target" ] || [ ! -x "$target" ]; then
48
- fail "$source_label points to $target, but that executable is not available. Set WEBPRESSO_WP_BIN to the Webpresso wp executable, set WP_FORCE_JIT_PATH to an agent-kit checkout, or install the Webpresso app."
49
- fi
243
+ case " $announced_modes " in
244
+ *" $MODE "*) printf 'wp-shim: %s %s\n' "$MODE" "$TARGET" >&2 ;;
245
+ esac
50
246
 
51
247
  WP_SKIP_UPDATE_CHECK=${WP_SKIP_UPDATE_CHECK:-1}
52
248
  export WP_SKIP_UPDATE_CHECK
53
249
 
54
- exec "$target" "$@"
250
+ exec "$TARGET" "$@"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpresso/plugin-codex",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "private": false,
5
5
  "description": "Codex plugin adapter for Webpresso agent-kit skills, hooks, and MCP runtime.",
6
6
  "homepage": "https://github.com/webpresso/app#readme",
@@ -2,35 +2,35 @@
2
2
  "schemaVersion": 1,
3
3
  "host": "codex",
4
4
  "packageName": "@webpresso/plugin-codex",
5
- "packageVersion": "0.0.12",
5
+ "packageVersion": "0.0.14",
6
6
  "runtimeDirs": [".codex/skills", ".agents/skills"],
7
7
  "skills": {
8
8
  "ai-deslop": {
9
9
  "digest": "sha256:cf07df5835037f10401400e220c1c923f5325a6149d59c231ce316e10595fdfc"
10
10
  },
11
11
  "autopilot": {
12
- "digest": "sha256:fc0f77917bd7af3d6e99ce3a96067394308a3b8c94c416b5076167b19e00a754"
12
+ "digest": "sha256:6a72b2db563a48742c501f20d509050f193a5d31f2d413f6bef838f277d470c1"
13
13
  },
14
14
  "autoresearch": {
15
15
  "digest": "sha256:b4d51cd53beb4a3271827172dfbd0b1d27bd58761ca07a35d49a5d6324b87fdf"
16
16
  },
17
17
  "best-practice-research": {
18
- "digest": "sha256:a46010d48ca2c9b4e04815ea84a45d100e032c5a4f08b919eeefb5be37d87749"
18
+ "digest": "sha256:b863ef3969b85e83934911d4ba65f0547c0f586b147597d6a37c41d4b7a762f3"
19
19
  },
20
20
  "browse": {
21
21
  "digest": "sha256:21fd24862e7f7c8a1feadea6bc376492b136b99fc381cf1b8927c9db80615431"
22
22
  },
23
23
  "claude": {
24
- "digest": "sha256:e1e97e5419249fbb0cb8446e96fc8e80c165c149db563784570f96ad629ab54d"
24
+ "digest": "sha256:0205d693121b740b76041f1e25925a70d665774f7493070cdd6df40d0058ffe6"
25
25
  },
26
26
  "codex": {
27
- "digest": "sha256:1f93db92066e5b39ba334ec1d8c3af3de79dea13947dba97b8b7340302906d63"
27
+ "digest": "sha256:88837502404449b641b71dbc4f018c75dab6294ad98af29d41de50e98649ff0e"
28
28
  },
29
29
  "deep-interview": {
30
30
  "digest": "sha256:79fbf86a86024a311583a1500bb6960c82ad1383cc9f8ed3f04bbace41848ff7"
31
31
  },
32
32
  "deep-research": {
33
- "digest": "sha256:01dafd194066a2936db0b437fd5c3beef6d7ff82478d0d995393093d89496f18"
33
+ "digest": "sha256:ece766cb18869317d7c8992fc562920b03250ff8c44bdcb9eccdc3b21922a83f"
34
34
  },
35
35
  "delivery-program": {
36
36
  "digest": "sha256:ebd6b35036c12fa26ff98649ac57ede607b7b3526c401784670a5ce68369a691"
@@ -44,14 +44,11 @@
44
44
  "fix": {
45
45
  "digest": "sha256:4804c546291316439aad3ea05fb7d3f043bc191abd8b9c180eb1d349f19f64cf"
46
46
  },
47
- "grok": {
48
- "digest": "sha256:1a6bf596fde9ce50a06ea767c06e65d4845c52d5af085644c958964385363b1e"
49
- },
50
47
  "handoff": {
51
- "digest": "sha256:eb34b39fc6d416fe8203eea979b4b99ab3150c44da6dad3ca4afb8fe8fb75b85"
48
+ "digest": "sha256:eda4410dc75019b40b1ffae5f301bfc1e57d9313241d170e4743d379a1b6d846"
52
49
  },
53
50
  "hooks-doctor": {
54
- "digest": "sha256:30286e9ef1c64f2c01d05b0e13a39c54741c7a3e02e5d18636795a7517c0b566"
51
+ "digest": "sha256:9d9147e842246955f284854c35cf57237d4d056dca23f4c66019e1b44bb09eb6"
55
52
  },
56
53
  "investigate": {
57
54
  "digest": "sha256:778b3a1f38323e8dd6101c6ace26ff8aada1246b20952b3641d5d1049bc50055"
@@ -60,7 +57,7 @@
60
57
  "digest": "sha256:a80fbacc765e8b886437b9fdf7dd71e1ceb1b98b939078ec90fc88d06a8b4c69"
61
58
  },
62
59
  "opencode-go": {
63
- "digest": "sha256:f9c2085cc35b6e63e230dbcf1d95eb88e65543a9aec53f707c42d631f8b62052"
60
+ "digest": "sha256:a304b282fa078f97c2aa6a7d040d30eaae4c735de0aa5edf3af7368f62491804"
64
61
  },
65
62
  "plan-ceo-review": {
66
63
  "digest": "sha256:4d426158518dd71f8998770e8d4037bcbfa3c65d7265a93a4a78a9b015ba881e"
@@ -78,28 +75,28 @@
78
75
  "digest": "sha256:cf2c0743a81b0d8954417482e7812212a6a90e5046926c44cd82a6a309dfdc26"
79
76
  },
80
77
  "ralplan": {
81
- "digest": "sha256:47cf47910b50471eb92f9487a018311442c95b26907c5b21c3f5b87947bf7e7e"
78
+ "digest": "sha256:d3e8ab6285f9882d18ee9feabf51bb6dd9d81f8aaa243c050e9eeaa3436927af"
82
79
  },
83
80
  "team": {
84
81
  "digest": "sha256:c27107b46e0cd7b9c264a6f51f74f505920d63e7ee2a2d26d2f288592fd10bd2"
85
82
  },
86
83
  "tech-debt": {
87
- "digest": "sha256:bec6c83a18e55d148af973dd84d34a8750d8a8fe4345e5fca7b9e8c3e876fd9a"
84
+ "digest": "sha256:2018bf8dc5f338baee3d982a5bf28c48773befea08e44f33b70561c18d897c56"
88
85
  },
89
86
  "testing-philosophy": {
90
87
  "digest": "sha256:23fdad944b089de3cfcd13957a5ac10c37bd3d136b192029af69368bca1470db"
91
88
  },
92
89
  "tooling-friction": {
93
- "digest": "sha256:7e1ff82147559624c39b1e4e1837d6bde0f102ecd65ec01358987d92ff42f7ad"
90
+ "digest": "sha256:64992c6a789d0283b7379a914d7686af5db97fe48cb5929f800a11d8f8e8f126"
94
91
  },
95
92
  "tph": {
96
93
  "digest": "sha256:bed3684a850651534f315d355cdeae50d951c429817df0f105cccdb7f4e1561b"
97
94
  },
98
95
  "ultragoal": {
99
- "digest": "sha256:caa61789eb5ce01940cfaccf7e70e9290c1f318cb31e25d038eb45b26970c39c"
96
+ "digest": "sha256:344177e32690fe6355577abe50659cea1af682933a78eb13a11765d1a1ad66d7"
100
97
  },
101
98
  "verify": {
102
- "digest": "sha256:03bd3b922a24d19ccc0b942d4f56d97f09e24939220a69d8fad8ba1144085d12"
99
+ "digest": "sha256:bb9144c18983cea1b2be6f193dadadbf9f0f638021385a4aad7de390e520e281"
103
100
  }
104
101
  }
105
102
  }
@@ -25,7 +25,7 @@ using `wp_ultragoal_run` / `wp ultragoal run` and the current handoff.
25
25
 
26
26
  ## Outside-voice (required)
27
27
 
28
- After each ultragoal **phase or plan-gate milestone**, run an **OpenCode Go** outside-voice review and pick the model by purpose. The purpose→family ordering lives in one place — the committed reviewer policy rendered into the `opencode-go` skill — so follow that skill and do not restate the ordering here. Resolve IDs from live `opencode models opencode-go`. `wp_review_gate` in the default authoritative mode is only for exact-version draft plan approval/auto-promotion; the same tool called with `mode: "advisory"` is for implementation/phase review and never mutates blueprint approval state on its own — a later authoritative call may promote a matching advisory approval without re-invoking a provider. Never self-approve. Full protocol: the `ultragoal` skill. Respect `review_budget` (default owned by `workflow-skills-routing.md`): one sequential path, no multi-host stampede.
28
+ After each ultragoal **phase or plan-gate milestone**, run an **OpenCode Go** outside-voice review and pick the model by purpose. The purpose→family ordering lives in one place — the committed reviewer policy rendered into the `opencode-go` skill — so follow that skill and do not restate the ordering here. Resolve IDs from live `opencode models opencode-go`. `wp_review_gate` has one mode: purpose plan for exact-version draft plan approval/auto-promotion, purpose delivery for implementation/phase review; each new provider verdict is a formal round and an approval is authority immediately. Never self-approve. Full protocol: the `ultragoal` skill. Respect `review_budget` (default owned by `workflow-skills-routing.md`): one sequential path, no multi-host stampede.
29
29
 
30
30
  ## Vague gate
31
31
 
@@ -52,7 +52,7 @@ skill.
52
52
  | Execute | ready-set via blueprint tools; `/goal` or parallel subagents; `wp_session_context` for delegates; `wp_blueprint_task_verify` only to complete tasks |
53
53
  | Opportunistic repair | `/fix` up to `fix_budget`; else handoff backlog |
54
54
  | QA | `wp_qa` / `wp_lint` / `wp_typecheck` / `wp_test`; PR checks via `wp_pr_status` / `wp_pr_wait` |
55
- | Validate | one outside voice if merge-bound (OpenCode Go by purpose, or claude/codex/grok); `wp review gate` for authority |
55
+ | Validate | one outside voice if merge-bound (OpenCode Go by purpose, or claude/codex); `wp review gate` for authority |
56
56
  | Land | `wp_pr_upsert`, green required checks, merge + owner cleanup |
57
57
  | Blocked / stop | `wp_ultragoal_handoff` ≤40 lines; `wp_ultragoal_cancel` if abandoned |
58
58
 
@@ -17,6 +17,14 @@ Use this skill when a task depends on current external best practices, version-a
17
17
 
18
18
  Produce a cited, reusable best-practice answer or handoff that separates current external evidence from repo-local facts and dependency-selection decisions.
19
19
 
20
+ ## Destination
21
+
22
+ Repo-scoped research is committed as `docs/research/{YYYY-MM-DD}-{slug}.md` on the
23
+ owning blueprint branch (the same convention as the `deep-research` skill). Scratch
24
+ notes go to a sanctioned sink (`$TMPDIR/webpresso/scratch/` or
25
+ `.webpresso/agent-scratch/`); a new root subdirectory is policy-allowed but is
26
+ unwhitelisted dirt for `wp ci-preflight` and `wp worktree merge-cleanup`.
27
+
20
28
  ## Activate When
21
29
 
22
30
  - The user asks for best practices, recommended approach, current guidance, official recommendations, standards, or version-aware external behavior.
@@ -16,7 +16,7 @@ until independently verified.
16
16
  - Never invoke a provider command, the legacy review CLI, or a removed review-run surface.
17
17
  - If the review MCP is unavailable, stop and report it unavailable. There is no CLI fallback.
18
18
 
19
- ## Advisory call
19
+ ## Gate call
20
20
 
21
21
  ```jsonc
22
22
  {
@@ -27,11 +27,14 @@ until independently verified.
27
27
  "authority_ref": "<full-head-sha>",
28
28
  "provider": "claude",
29
29
  "repository_access": "none",
30
- "mode": "advisory",
31
30
  }
32
31
  ```
33
32
 
34
- Use authoritative mode only when formal plan or delivery approval is requested.
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.
35
38
 
36
39
  ## Model policy
37
40
 
@@ -16,7 +16,7 @@ until independently verified.
16
16
  - Never invoke a provider command, the legacy review CLI, or a removed review-run surface.
17
17
  - If the review MCP is unavailable, stop and report it unavailable. There is no CLI fallback.
18
18
 
19
- ## Advisory call
19
+ ## Gate call
20
20
 
21
21
  ```jsonc
22
22
  {
@@ -27,11 +27,14 @@ until independently verified.
27
27
  "authority_ref": "<full-head-sha>",
28
28
  "provider": "codex",
29
29
  "repository_access": "none",
30
- "mode": "advisory",
31
30
  }
32
31
  ```
33
32
 
34
- Use authoritative mode only when formal plan or delivery approval is requested.
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.
35
38
 
36
39
  ## Model policy
37
40
 
@@ -127,6 +127,7 @@ type: research
127
127
  title: "{Title}"
128
128
  subject: "{subject}"
129
129
  date: { YYYY-MM-DD }
130
+ last_updated: { YYYY-MM-DD }
130
131
  confidence: { high|medium|low }
131
132
  verdict: { adopt|trial|assess|hold|reject }
132
133
  ---
@@ -10,7 +10,7 @@ created: "2026-08-03"
10
10
  last_reviewed: "2026-08-03"
11
11
  name: handoff
12
12
  description: "Cross-session handoff via session_context. Use for continue, take over, resume other host."
13
- argument-hint: "[--host <claude|codex|grok|opencode>] [session-id|brief]"
13
+ argument-hint: "[--host <claude|codex|opencode>] [session-id|brief]"
14
14
  ---
15
15
 
16
16
  # Handoff
@@ -21,7 +21,7 @@ session. Do **not** paste full transcripts.
21
21
  ## Use when (freeform)
22
22
 
23
23
  - "give me a continuation prompt", "take over where you left off"
24
- - "resume", "continue from other host", "hand off to Codex/Claude/Grok"
24
+ - "resume", "continue from other host", "hand off to Codex/Claude"
25
25
  - cross-session or cross-worktree continuity without history walls
26
26
 
27
27
  ## Tooling map
@@ -65,17 +65,54 @@ Each check prints `[x]` (pass) or `[ ]` (fail) with a detail line:
65
65
 
66
66
  ### Updating the webpresso MCP server (monorepo authors)
67
67
 
68
- `mcp` is **source-first**: in a checkout with TypeScript source the server runs
69
- from source, so it always serves HEAD. After changing `src/mcp/**`, conversation
70
- catalog, or pretool routing that MCP hosts must run:
68
+ `mcp` is **source-first**: in a checkout with TypeScript source the server loads
69
+ that source when it starts. After changing `src/mcp/**`, conversation catalog,
70
+ or pretool routing that MCP hosts must run:
71
71
 
72
- 1. Reconnect webpresso MCP in the agent host.
73
- 2. Smoke a tool only available in the new code.
72
+ 1. Reconnect webpresso MCP server in the agent host.
73
+ 2. Prove the refreshed server is serving the intended source.
74
74
 
75
75
  No runtime rebuild is involved, and no `pkill` is needed — every launcher layer
76
76
  owns its child's stdin, so a disconnect unwinds the whole chain. Chat-only
77
77
  restart is still **not** enough: reconnect the server itself.
78
78
 
79
+ Use the host's named-server controls so only the webpresso server is closed and
80
+ started. Check the installed host version before using version-scoped controls.
81
+
82
+ - **Codex desktop:** Settings → MCP servers → select webpresso → **Restart**. The
83
+ in-composer `/mcp` view lists connected servers
84
+ ([host documentation](https://learn.chatgpt.com/docs/extend/mcp?surface=app);
85
+ host documentation verified 2026-10-17).
86
+ - **Claude Code:** `/mcp` → select webpresso → **Reconnect**. Use
87
+ `claude mcp list` to check the configured server; do not remove and re-add it.
88
+ Claude Code does not automatically reconnect local stdio servers
89
+ ([host documentation](https://code.claude.com/docs/en/mcp); host documentation
90
+ verified 2026-10-17).
91
+ - **OpenCode v2:** `/mcps` → select webpresso → **Disconnect**, then
92
+ **Connect**. If the OpenCode configuration changed, run `opencode reload`;
93
+ verify with `opencode mcp list` ([MCP
94
+ servers](https://dev.opencode.ai/v2/docs/mcp-servers/), [CLI
95
+ commands](https://dev.opencode.ai/v2/docs/cli/commands/); host documentation
96
+ verified 2026-10-17). These `dev.opencode.ai` paths sit on a preview domain
97
+ and can move; confirm the v2 path still resolves before following it.
98
+
99
+ After reconnecting, prove the loaded source rather than the connection:
100
+
101
+ 1. Call `wp_tool_surface` with `detail: "diagnostic"`.
102
+ 2. Compare `details.diagnostic.live.sourceCommit` against the commit you expect
103
+ the checkout to be serving.
104
+ 3. Read `details.diagnostic.identity.status`, which is exactly one of `current`,
105
+ `restart_required`, `setup_required`, or `unknown`. The wrapper's
106
+ `passed: true` only means a response was built — it is **not** proof of
107
+ current identity.
108
+
109
+ If the source commit differs, or the status is `restart_required` or
110
+ `setup_required`, reconnect again or follow `details.diagnostic.identity.reason`.
111
+ If the status is `unknown`, keep that uncertainty: a source-distinguishing smoke
112
+ call can corroborate behavior but does not make the identity current. A fresh
113
+ chat is not a refresh. Reserve quitting and reopening the host for the one-time
114
+ legacy-chain upgrade below, and never kill unrelated processes.
115
+
79
116
  Managed `wp hook` and `wp hooks doctor|status|dispatch` commands are
80
117
  source-authoritative and require no post-merge runtime rebuild. Existing
81
118
  managed installations run exact `wp sync`, then rerun `wp hooks doctor` or
@@ -16,7 +16,7 @@ until independently verified.
16
16
  - Never invoke a provider command, the legacy review CLI, or a removed review-run surface.
17
17
  - If the review MCP is unavailable, stop and report it unavailable. There is no CLI fallback.
18
18
 
19
- ## Advisory call
19
+ ## Gate call
20
20
 
21
21
  ```jsonc
22
22
  {
@@ -28,16 +28,19 @@ until independently verified.
28
28
  "provider": "opencode",
29
29
  "model": "opencode-go/deepseek-v4.1-flash",
30
30
  "repository_access": "none",
31
- "mode": "advisory",
32
31
  }
33
32
  ```
34
33
 
35
- Use authoritative mode only when formal plan or delivery approval is requested.
34
+ Each newly executed provider review that reaches a verdict is one formal round of the
35
+ slug's budget, and its approval is authority. An identical-subject call replays the recorded
36
+ verdict with no new review and no new round. A partial approval, withheld because adjudication
37
+ is incomplete (not every prior finding was briefed, or a briefed prior claim was marked
38
+ still-open without a matching finding), grants no authority and spends no round.
36
39
 
37
40
  ## Model policy
38
41
 
39
42
  Default exact model: `opencode-go/deepseek-v4.1-flash`.
40
- Committed exact options: `opencode-go/deepseek-v4.1-flash`, `opencode-go/glm-5.3-flash`, `opencode-go/deepseek-v4-pro`, `opencode-go/kimi-k2.7-code`, `opencode-go/qwen3.8-max`, `opencode-go/minimax-m3`, `opencode-go/muse-spark-1.3-contributor`, `opencode-go/mimo-v2.5-pro`, `opencode-go/muse-spark-1.2-contributor`, `opencode-go/union-alpha`, `opencode-go/qwen3.8-flash`, `opencode-go/mimo-v2.5`, `opencode-go/qwen3.7-plus`, `opencode-go/qwen3.7-max`, `opencode-go/qwen3.6-plus`, `opencode-go/minimax-m2.7`, `opencode-go/gpt-5.6-luna`, `opencode-go/longcat-2.0`, `opencode-go/kimi-k3`, `opencode-go/deepseek-v4-flash`, `opencode-go/deepseek-v4-flash-vision-exp`, `opencode-go/kimi-k2.6`, `opencode-go/hy4-preview`, `opencode-go/hy3`, `opencode-go/grok-4.6`, `opencode-go/glm-5.3`, `opencode-go/glm-5.2`, `opencode-go/glm-5.1`.
43
+ Committed exact options: `opencode-go/deepseek-v4.1-flash`, `opencode-go/glm-5.3-flash`, `opencode-go/deepseek-v4-pro`, `opencode-go/kimi-k2.7-code`, `opencode-go/muse-spark-1.3-contributor`, `opencode-go/mimo-v2.6-pro`, `opencode-go/step-5-preview`, `opencode-go/qwen3.8-max`, `opencode-go/mimo-v2.6-flash`, `opencode-go/qwen3.8-flash`, `opencode-go/minimax-m3.1-flash-free`, `opencode-go/qwen3.7-plus`, `opencode-go/muse-spark-1.2-contributor`, `opencode-go/mimo-v2.5`, `opencode-go/minimax-m3`, `opencode-go/mimo-v2.5-pro`, `opencode-go/longcat-2.5-preview-free`, `opencode-go/longcat-2.0`, `opencode-go/gpt-6-luna`, `opencode-go/kimi-k3`, `opencode-go/hy4-preview`, `opencode-go/hy3`, `opencode-go/grok-4.7`, `opencode-go/gpt-5.6-luna`, `opencode-go/claude-haiku-5-5`, `opencode-go/glm-5.3`, `opencode-go/glm-5.2`, `opencode-go/gemini-4-argon-contributor`, `opencode-go/beam-free`.
41
44
  Use a named exact option when requested; otherwise use the default. Provider catalog discovery
42
45
  belongs to the snapshot drift workflow, never to a skill invocation; reading the box-local
43
46
  credential store at gate time is a local file read, not catalog discovery.
@@ -40,11 +40,25 @@ Use when the user invokes `$ralplan`, asks for RALPLAN, or wants consensus plann
40
40
  ## Iron laws
41
41
 
42
42
  1. **Blueprint is the plan.** Freeform notes are not durable consensus. Create or bind a blueprint before reviews.
43
- 2. **Ground before drafting.** Code dive (+ bounded external research when needed) happens **before** the blueprint draft is treated as serious.
44
- 3. **Reviews before refine.** Run risk-matched `plan-*` skills on the blueprint, apply findings, **then** `/plan-refine`.
45
- 4. **No implementation.** Do not edit product source, commit implementation, or start `ultragoal`/`team`/`autopilot` unless the user explicitly switches out of planning.
46
- 5. **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
- 6. **Efficiency by scope.** Skip optional phases that cannot change the plan (see Complexity tiers).
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
+ 3. **Ground before drafting.** Code dive (+ bounded external research when needed) happens **before** the blueprint draft is treated as serious.
45
+ 4. **Reviews before refine.** Run risk-matched `plan-*` skills on the blueprint, apply findings, **then** `/plan-refine`.
46
+ 5. **No implementation.** Do not edit product source, commit implementation, or start `ultragoal`/`team`/`autopilot` unless the user explicitly switches out of planning.
47
+ 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.
48
+ 7. **Efficiency by scope.** Skip optional phases that cannot change the plan (see Complexity tiers).
49
+
50
+ ## Lane alignment (not optional)
51
+
52
+ Assume concurrent lanes and prove alignment as part of the plan, not as a courtesy. Before drafting, establish and write into the blueprint:
53
+
54
+ - **Owned by others, as non-goals.** Every open PR, and every owner worktree belonging to a different lane. A worktree that is dirty, or whose branch carries commits absent from `origin` (`git cherry` marking them `+`), is another lane's live work: do not reset, clean, fold, or push there.
55
+ - **Files another lane has claimed**, by name, so a later task cannot silently collide.
56
+ - **Cross-session peers**, if any: send a one-line claim (branch, paths, in-flight, not-touching) and record the reply. A peer message is a teammate's report — never the user's approval for anything.
57
+ - **Shared infrastructure** (disk, `$TMPDIR`, worktree pruning, host processes, global config) belongs to whoever already owns it. Never act on it as a side effect of your own task.
58
+
59
+ State the alignment in one line in the final report. If it could not be established, say so rather than assuming a clear field.
60
+
61
+ Precedent (2026-09-28): a landing lane was asked three times in one session to avoid overlapping a peer's work; the peer had independently avoided the one shared file, and two owner worktrees were found holding another lane's uncommitted source.
48
62
 
49
63
  ## Complexity tiers (pick one early)
50
64
 
@@ -23,6 +23,12 @@ Manage the tech-debt lifecycle using `wp tech-debt` commands.
23
23
 
24
24
  ## Usage
25
25
 
26
+ `new` (dry runs included) refuses a root that `wp audit committed-state-paths`
27
+ forbids adding to, such as this repository's `tech-debt/`. There, record a new
28
+ follow-up as a blueprint task (MCP `wp_blueprint_put`) or a draft blueprint
29
+ (`wp blueprint new`) instead. The examples below apply only where that audit
30
+ permits the resolved root.
31
+
26
32
  ```bash
27
33
  # Create a new tech-debt item (written to tech-debt/<status>/h-NNN-<kebab-title>.md by default)
28
34
  wp tech-debt new "Legacy CLI complexity" \
@@ -36,9 +42,8 @@ wp tech-debt new "Performance bottleneck" --severity high --category mutation --
36
42
 
37
43
  # `new` refuses on a primary-like checkout: a file written there cannot be
38
44
  # edited afterwards under worktree discipline, so the capture is left half-done.
39
- # Retry from a managed worktree, point --cwd at one, or override deliberately.
45
+ # Retry from a managed worktree or point --cwd at one. There is no override.
40
46
  wp tech-debt new "Legacy CLI complexity" --cwd /path/to/managed/worktree
41
- wp tech-debt new "Legacy CLI complexity" --allow-primary
42
47
 
43
48
  # List all tech-debt items (optional filters)
44
49
  wp tech-debt list
@@ -19,12 +19,12 @@ Optional post-land **product signal** for MCP/CLI/hooks/CI pain so Webpresso too
19
19
 
20
20
  ## Boundary
21
21
 
22
- | Owns | Does not own |
23
- | ---------------------------------------------------- | -------------------------------------------------- |
24
- | Structured friction tips after land-ish success | Code bugs (`/investigate` → `/fix`) |
25
- | Optional promote to tech-debt (`--category tooling`) | Blueprint claim corrections (`blueprints/errata/`) |
26
- | Repo-scoped desktop-state JSON (outside worktrees) | Human DX audits (`/devex-review`) |
27
- | Soft bookend from `/verify` Phase 7 | Required PR section, finalize/merge blockers |
22
+ | Owns | Does not own |
23
+ | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
24
+ | Structured friction tips after land-ish success | Code bugs (`/investigate` → `/fix`) |
25
+ | Optional promote to a blueprint task or draft blueprint (tech-debt only where `committed-state-paths` permits `tech-debt/`) | Blueprint claim corrections (`blueprints/errata/`) |
26
+ | Repo-scoped desktop-state JSON (outside worktrees) | Human DX audits (`/devex-review`) |
27
+ | Soft bookend from `/verify` Phase 7 | Required PR section, finalize/merge blockers |
28
28
 
29
29
  ## When
30
30
 
@@ -83,11 +83,11 @@ Optional post-land **product signal** for MCP/CLI/hooks/CI pain so Webpresso too
83
83
  `tooling-friction: skipped: no state surface` and stop; never fall back to a
84
84
  worktree or `.agent/` path.
85
85
 
86
- 5. Optional `--promote` or severity `high`/`critical`:
87
- `wp tech-debt new "<short title>" --severity <s> --category tooling --status accepted`
88
- Set `promoted_to` to the resulting path. `new` refuses on a primary-like
89
- checkout; from one, pass `--cwd <managed-worktree-path>` (or `--allow-primary`
90
- to override deliberately).
86
+ 5. Optional `--promote` or severity `high`/`critical`: record the follow-up as
87
+ a blueprint task (MCP `wp_blueprint_put`) or a draft blueprint
88
+ (`wp blueprint new`), and set `promoted_to` to that blueprint path. Do not
89
+ use `wp tech-debt new` here: it refuses this repository's `tech-debt/` root,
90
+ which `wp audit committed-state-paths` forbids adding to.
91
91
  6. Optional one-line `wp_session_capture` pointer to the JSON path — no paste-back walls.
92
92
 
93
93
  **Rate limit:** at most **one** capture per verify bookend.
@@ -151,7 +151,7 @@ also include `path`, `repoKey` (16-hex), `stateRoot`, `scope: "repo"`, and
151
151
  | kind | `friction` `missing` `docs` `workaround` `incident` |
152
152
  | signal | `retry_loop` `schema_confuse` `timeout` `wrong_facade` `missing_capability` `docs_mismatch` `status_ci_skew` `other` |
153
153
  | token_waste | `none` `low` `medium` `high` |
154
- | host | `claude` `codex` `opencode` `grok` `other` |
154
+ | host | `claude` `codex` `opencode` `other` |
155
155
  | recurrence | `once` `session` `chronic` |
156
156
 
157
157
  ### Limits
@@ -170,7 +170,7 @@ also include `path`, `repoKey` (16-hex), `stateRoot`, `scope: "repo"`, and
170
170
 
171
171
  - `wp_pr_merge: land readiness disagrees with GitHub CLEAN / PR Policy (status_ci_skew, high)`
172
172
  - `wp_review_gate: re-approve after ledger-only commits; subject binding unclear (retry_loop, medium)`
173
- - `wp_pr_upsert: bare Review model "Grok" fails provider regex; needs "grok reviewer" (schema_confuse, low)`
173
+ - `wp_pr_upsert: bare Review model "Kimi" fails provider regex; needs "kimi reviewer" (schema_confuse, low)`
174
174
 
175
175
  **Bad**
176
176
 
@@ -205,7 +205,10 @@ also include `path`, `repoKey` (16-hex), `stateRoot`, `scope: "repo"`, and
205
205
  ```text
206
206
  tooling-friction: wrote desktop state <absolute-path-from-wp_tooling_friction_path>
207
207
  findings: 2 (high=1, medium=1)
208
- promoted: none | tech-debt/...
208
+ promoted: none | blueprints/<lifecycle>/<slug> | tech-debt/...
209
209
  ```
210
210
 
211
+ `tech-debt/...` applies only where `wp audit committed-state-paths` permits
212
+ that root.
213
+
211
214
  Or: `tooling-friction: skipped: no tooling friction`
@@ -69,7 +69,6 @@ target as secondary context only when the invocation path is a symlink.
69
69
  | -------- | ------------------------------- |
70
70
  | Claude | `WP_ULTRAGOAL_CLAUDE_COMMAND` |
71
71
  | Codex | `WP_ULTRAGOAL_CODEX_COMMAND` |
72
- | Grok | `WP_ULTRAGOAL_GROK_COMMAND` |
73
72
  | OpenCode | `WP_ULTRAGOAL_OPENCODE_COMMAND` |
74
73
  | Process | `WP_ULTRAGOAL_PROCESS_COMMAND` |
75
74
 
@@ -77,8 +76,7 @@ Upgrade the installed CLI or point the named variable at a compatible executable
77
76
  restart the process that owns the adapter: probe successes and failures are cached by
78
77
  canonical executable for that adapter's lifetime. Missing paths are rechecked and symlink
79
78
  retargeting is re-probed, but an in-place executable repair still requires an adapter-owner
80
- restart. Grok execution requires a separately installed and authenticated Grok Build CLI.
81
- `wp install` does not install or authenticate Grok Build.
79
+ restart.
82
80
 
83
81
  Existing `WP_ULTRAGOAL_<HOST>_COMMAND` configurations remain supported; no environment
84
82
  variable migration is required. Their executables must satisfy the current semantic probe
@@ -90,9 +88,7 @@ Start probes each unique requested host concurrently, then reports the first fai
90
88
  requested-host order. A failed preflight occurs before durable run creation, ledger writes,
91
89
  supervisor launch, or attempt/worktree allocation. Built-in probes validate the grammar they
92
90
  invoke: Codex `exec --json --sandbox workspace-write`, Claude prompt/streaming output/bypass
93
- permission flags, OpenCode `run --format json --auto`, and Grok headless prompt/streaming
94
- output/approval/workspace-sandbox flags. Grok also runs an auth-free `inspect --json` check
95
- against a temporary working directory so invalid sandbox profiles fail before execution.
91
+ permission flags, and OpenCode `run --format json --auto`.
96
92
 
97
93
  Preflight does **not** validate authentication, provider quota or billing, network
98
94
  reachability, or secrets isolation. Those failures remain runtime/provider concerns.
@@ -148,9 +144,7 @@ the configured JSON arguments may add process-specific flags but cannot replace
148
144
  ### Execution authority and isolation
149
145
 
150
146
  Ultragoal worktrees protect git integration boundaries; they are **not** operating-system
151
- sandboxes. Codex uses its `workspace-write` sandbox. Grok's `workspace` sandbox may read
152
- anywhere, write in its current directory, `~/.grok`, and temporary directories, and permits
153
- child-process network access. Claude `bypassPermissions`, OpenCode `--auto` mode, and custom
147
+ sandboxes. Codex uses its `workspace-write` sandbox; Claude `bypassPermissions`, OpenCode `--auto` mode, and custom
154
148
  `process` executables retain substantial user authority. OpenCode disables automatic updates
155
149
  and sharing and denies external-directory access, but those policy settings do not make it an
156
150
  OS sandbox. Run Ultragoal only with providers, configuration, and task content you trust.
@@ -195,10 +189,10 @@ Fallback to `wp …` CLI only when the matching MCP tool is unavailable. Prefer
195
189
  the user sets N (the default value lives in `workflow-skills-routing.md`).
196
190
  Controller validation evidence is **machine-qa (prior QA phase) + N outside voices**
197
191
  (default N=1), not two outside model reviewers at budget 1.
198
- Use `wp_review_gate` in the default authoritative mode only for exact-version
199
- draft plan approval/auto-promotion. Use the same tool with `mode: "advisory"`
200
- for implementation/phase outside voice; it never mutates blueprint approval
201
- state on its own. A CLI delivery gate is explicit MCP-unavailable
192
+ `wp_review_gate` has one mode: purpose plan for exact-version draft plan
193
+ approval/auto-promotion, purpose delivery for implementation/phase outside
194
+ voice. Each new provider verdict is a formal round of the slug's budget and
195
+ an approval is authority immediately. A CLI delivery gate is explicit MCP-unavailable
202
196
  compatibility only, not this MCP contract. Use `wp_pr_*` for PR babysit — no
203
197
  multi-sleep poll loops; no parallel multi-reviewer stampede.
204
198
  8. Stop on `complete`, `cancelled`, blocked guard exhaustion, or `WP_ULTRAGOAL_DISABLE=1`.
@@ -217,16 +211,15 @@ primary checkout.
217
211
 
218
212
  ## Outside-voice review (required for autopilot)
219
213
 
220
- Autopilot and agent-driven ultragoal loops **must** request an **OpenCode Go** outside-voice review after each **goal/phase milestone**, and must pick the model by purpose. Use **`wp_review_gate`** in the default authoritative mode only for exact-version draft plan approval/auto-promotion. Use a single-shot **`wp_review_gate`** call with **`mode: "advisory"`** for implementation/phase outside voice; it never mutates blueprint approval state on its own — a later authoritative call may promote a matching advisory approval without re-invoking a provider. CLI delivery gates are explicit MCP-unavailable compatibility only, not this MCP contract.
214
+ Autopilot and agent-driven ultragoal loops **must** request an **OpenCode Go** outside-voice review after each **goal/phase milestone**, and must pick the model by purpose. Use **`wp_review_gate`** purpose plan for exact-version draft plan approval/auto-promotion and one single-shot **`wp_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.
221
215
 
222
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`. Prefer purpose-matched OpenCode Go first; do not fan out multi-host review swarms.
223
217
 
224
218
  ### Milestones that require a review
225
219
 
226
- Run `wp_review_gate` (default authoritative mode) only for the plan approval
227
- milestone below. Run one single-shot `wp_review_gate` call with `mode:
228
- "advisory"` for implementation/phase milestones; it is advisory and does not
229
- promote or otherwise mutate blueprint approval state on its own.
220
+ Run `wp_review_gate` purpose plan for the plan approval milestone below and one
221
+ single-shot `wp_review_gate` purpose delivery call for implementation/phase
222
+ milestones. Each new provider verdict is one formal round of the slug's budget.
230
223
 
231
224
  | Milestone | When |
232
225
  | ------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
@@ -234,7 +227,7 @@ promote or otherwise mutate blueprint approval state on its own.
234
227
  | Phase advance | After ultragoal advances `plan` → `execute`, `execute` → `qa`, `qa` → `validate`, `validate` → `land`, or lands `complete` |
235
228
  | Task batch handoff | After a meaningful execute batch when the phase remains `execute` (at least once per blueprint before claiming execute-complete) |
236
229
 
237
- Do **not** invent ledger approvals. If OpenCode Go is unavailable or hits a provider-wide usage limit, capture the failure evidence and use Grok on the next invocation (`--provider grok` / `/grok`); do not hop OpenCode families or substitute a forged approval.
230
+ Do **not** invent ledger approvals. If OpenCode Go is unavailable or hits a provider-wide usage limit, capture the failure evidence and end OpenCode Go review for the window; do not hop OpenCode families, substitute another host, or substitute a forged approval.
238
231
 
239
232
  ### Purpose → model routing (no hardcoding IDs)
240
233
 
@@ -250,7 +243,7 @@ rendered into the `opencode-go` skill and drift-gated against it.** Follow that
250
243
  skill; do not restate the ordering here. A second copy of a preference list is a
251
244
  second thing to update, and the copy that goes stale is the one an agent reads.
252
245
 
253
- Treat a provider-wide usage limit as terminal for every OpenCode Go model in the current review window; do not hop OpenCode families to evade a usage block. Use Grok as the next outside-voice substitute instead.
246
+ Treat a provider-wide usage limit as terminal for every OpenCode Go model in the current review window; do not hop OpenCode families to evade a usage block. There is no substitute host: the window ends with the captured failure evidence.
254
247
 
255
248
  ### Plan gate invocation shape
256
249
 
@@ -37,22 +37,22 @@ integrated, and free of stale garbage?**
37
37
 
38
38
  Default `/verify` must **not** spawn outside reviewers. That stampede is a known
39
39
  token/time failure mode. Merge-ready runs **one** sequential outside voice via
40
- the preferred skill (`claude` / `codex` / `grok` / one OpenCode Go), then stops.
40
+ the preferred skill (`claude` / `codex` / one OpenCode Go), then stops.
41
41
 
42
42
  ## Tooling map
43
43
 
44
- | Gate | Prefer |
45
- | ------------------------- | ------------------------------------------------------------------------------------------------------- |
46
- | Lint / types / tests / QA | `wp_lint`, `wp_typecheck`, `wp_test`, `wp_qa` |
47
- | Format | `wp_format` |
48
- | Audits | `wp_audit`, `wp_audits` |
49
- | Blueprint | blueprint MCP tools + `wp_audit` |
50
- | PR / CI wait | `wp_pr_status`, `wp_pr_wait` (not multi-sleep loops) |
51
- | Release | `wp_release_progress` for live Release phases; `wp_release_readiness` for package gates |
52
- | Large output | `wp_session_execute` / `batch_execute` / `execute_file` |
53
- | Continuity | `wp_session_capture` for verify summary; avoid paste-back walls |
54
- | E2E / act | `wp_e2e`, `wp_ci_act` when the change requires them |
55
- | Outside authority | `wp_review_gate` (authoritative) for plans; `wp_review_gate` with `mode: "advisory"` for implementation |
44
+ | Gate | Prefer |
45
+ | ------------------------- | ---------------------------------------------------------------------------------------- |
46
+ | Lint / types / tests / QA | `wp_lint`, `wp_typecheck`, `wp_test`, `wp_qa` |
47
+ | Format | `wp_format` |
48
+ | Audits | `wp_audit`, `wp_audits` |
49
+ | Blueprint | blueprint MCP tools + `wp_audit` |
50
+ | PR / CI wait | `wp_pr_status`, `wp_pr_wait` (not multi-sleep loops) |
51
+ | Release | `wp_release_progress` for live Release phases; `wp_release_readiness` for package gates |
52
+ | Large output | `wp_session_execute` / `batch_execute` / `execute_file` |
53
+ | Continuity | `wp_session_capture` for verify summary; avoid paste-back walls |
54
+ | E2E / act | `wp_e2e`, `wp_ci_act` when the change requires them |
55
+ | Outside authority | `wp_review_gate` (purpose plan or delivery); each new provider verdict is a formal round |
56
56
 
57
57
  ## Iron law — evidence before claims
58
58
 
@@ -245,7 +245,7 @@ in outside-voice usage — stop and fix the gate, do not multiply reviewers.
245
245
  **Skip this entire phase** for default `/verify` and `/verify --full`. Local
246
246
  `done` claims do not require outside voice.
247
247
 
248
- This phase implements **land-policy M7** (delivery vs advisory). Full land
248
+ This phase implements **land-policy M7** (delivery vs outside voice). Full land
249
249
  language and dual-label contract:
250
250
  [`catalog/agent/rules/land-policy.md`](../../rules/land-policy.md).
251
251
 
@@ -269,34 +269,37 @@ When classification is **sensitive**:
269
269
 
270
270
  - Require delivery review via `risk-review-coverage` / `wp_review_gate`
271
271
  (purpose delivery) / qualifying lane approvals for the current
272
- review subject until `policySatisfied` (**approval** or valid same-subject
273
- **maintainer-override**). A formal **reject** is a terminal automated-review
272
+ review subject until `policySatisfied` (**approval**). A formal **reject** is a terminal automated-review
274
273
  outcome but does **not** satisfy land policy: Product status stays
275
- `incomplete`, Process status stays `sensitive-blocked` until approval or
276
- override. Tech-debt is **not** a substitute for delivery approval.
274
+ `incomplete`, Process status stays `sensitive-blocked` until approval.
275
+ Tech-debt is **not** a substitute for delivery approval.
277
276
  - Launch **exactly one at a time** `wp_review_gate` delivery attempt with
278
277
  `--base-ref <base-sha>` and `--authority-ref <head-sha>`. Do not substitute
279
278
  `HEAD` for the authority SHA, and do not relaunch while the same subject has
280
279
  an in-progress gate.
281
- - On formal **reject**: surface the gate `next_action` (`report_delivery_reject`)
282
- / reject projection to the user; free-triage against blueprint non-goals;
283
- address the findings, then re-review only a changed exact subject. The shared
284
- gate permits five distinct rejected delivery subjects by default. Once that
285
- budget is exhausted, **do not** set `scope_continue=true` without explicit
286
- user authorization; agents must not invent the grant. For plan or delivery,
287
- only an operator may request an absolute finite same-slug ceiling through MCP
288
- `scope_continue_limit` (10..32); the field still requires
289
- `scope_continue=true`. MCP wins over `WP_REVIEW_SCOPE_CONTINUE_LIMIT`; when
290
- neither is present, the plan/delivery defaults are 16/10. Machine enforcement
291
- does not link successor slugs; creating one to launder or bypass the budget
292
- remains procedurally forbidden, as do resets and retry schemes.
280
+ - On formal **reject**: record the gate `next_action` (`report_delivery_reject`)
281
+ / reject projection, triage against blueprint non-goals, address the findings,
282
+ then re-review only a changed exact subject. The gate counts formal verdicts
283
+ per slug and purpose, starting with eight rounds.
284
+ After all allowance is spent, a corrected subject may open one
285
+ extra lane on an explicitly selected provider and model, including one that
286
+ already reviewed the lineage. The gate records that grant, adds five formal
287
+ rounds, and permits at most five distinct provider attempts in the new lane
288
+ that reach a verdict or an unproven outcome; provider infrastructure failures
289
+ spend no attempt but are bounded separately at five per lane. The provider and model remain pinned.
290
+ Once that lane is spent, this blueprint's review lineage is terminal: no
291
+ gate call on its slug can reopen it, whatever the subject. Re-plan the
292
+ narrowed scope as a new blueprint with its own plan review.
293
+ Machine enforcement does not link successor slugs; creating one to launder
294
+ or bypass the budget remains procedurally forbidden, as do resets and retry
295
+ schemes.
293
296
  - `Review-skip` is **FORBIDDEN** (`sensitive-review-skip-forbidden`).
294
297
  - Completed owner blueprint must be present in the PR
295
298
  (`sensitive-no-completed-owner` otherwise).
296
299
  - Process label when blocked: `sensitive-blocked`. When delivery lane
297
300
  approves: `delivery-approved`.
298
301
 
299
- ### 3. Standard → skip or one advisory outside voice
302
+ ### 3. Standard → skip or one outside voice
300
303
 
301
304
  When classification is **standard**:
302
305
 
@@ -308,8 +311,8 @@ When classification is **standard**:
308
311
 
309
312
  Must be start-of-line. Process label: `standard-skip`.
310
313
 
311
- - Otherwise obtain **exactly one sequential** advisory outside voice
312
- (`wp_review_gate` with `mode: "advisory"`, or host skill). Process label: `outside-approved`.
314
+ - Otherwise obtain **exactly one sequential** outside voice: one
315
+ `wp_review_gate` delivery gate (or host skill). Process label: `outside-approved`.
313
316
  - At most **one OpenCode Go reviewer** counts unless the user asks for more.
314
317
  - Invoke the selected reviewer **once**. Do not probe, retry, or rotate
315
318
  providers automatically, and **never** fan out parallel multi-host review
@@ -321,10 +324,9 @@ When classification is **standard**:
321
324
 
322
325
  Reviewer preference (pick **one** path):
323
326
 
324
- - From Codex → Claude or Grok (else one OpenCode Go).
325
- - From Claude → Codex or Grok (else one OpenCode Go).
326
- - From Grok → Claude or Codex (else one OpenCode Go).
327
- - Prefer skills: `claude`, `codex`, `grok`, or one of `opencode-go` / `qwen` /
327
+ - From Codex → Claude (else one OpenCode Go).
328
+ - From Claude → Codex (else one OpenCode Go).
329
+ - Prefer skills: `claude`, `codex`, or one of `opencode-go` / `qwen` /
328
330
  `deepseek` / `glm` / `kimi` / `minimax` / `mimo`.
329
331
 
330
332
  ### 4. Dual product/process labels on every land claim
@@ -345,26 +347,20 @@ Never invent a land-now skip. See `land-policy` for the full table.
345
347
  observed; wait timeout/abort/in-progress/not-found are not reviewer verdicts.
346
348
  `not_found` means there is no active or terminal gate for that subject; refresh
347
349
  state and start the gate again instead of continuing to wait.
348
- - Implementation / delivery approval: for sensitive PRs use `wp_review_gate`
349
- purpose delivery, default authoritative mode, on the immutable subject; for
350
- standard advisory use the same `wp_review_gate` call with `mode: "advisory"`
351
- exactly once with the selected provider. Do not run a separate provider
352
- probe. A later authoritative call on the same subject may promote a
353
- matching complete advisory approval to authority with zero provider
354
- invocation, unless a completed reject already exists for that content at
355
- either stage.
356
- - `advisory-exhausted` is a terminal outcome with no ledger event and no
357
- verdict — treat it as terminal-without-authority. It means this exact
358
- digest already used its advisory attempt budget; do not retry the same
359
- content or report it as a failure. Change the reviewed content (which mints
360
- a new digest) or spend real authoritative budget instead. It is always
361
- returned synchronously; no `wp_review_gate_wait` poll is ever needed or
362
- issued for it.
363
- - An advisory gate and an authoritative gate on the same subject cannot run
364
- concurrently — unlike the removed `wp_review_run`, an advisory
365
- `wp_review_gate` call claims the same active marker an authoritative call
366
- does. If a call reports marker contention, serialize the two calls rather
367
- than treating contention as an error.
350
+ - Implementation / delivery approval: use `wp_review_gate` purpose delivery
351
+ on the immutable subject, exactly once with the selected provider, for
352
+ sensitive and standard PRs alike. The gate has one mode: each newly executed
353
+ provider review that reaches a verdict is one formal round of the slug's
354
+ budget, an approval is authority immediately, and an identical-subject call
355
+ replays the recorded verdict without a new round (an approval withheld for
356
+ incomplete adjudication of prior findings — not all briefed, or a briefed
357
+ claim still open without a matching finding — grants no authority and
358
+ spends none). Do not run a separate
359
+ provider probe.
360
+ - Two gates on the same subject cannot run concurrently — every
361
+ `wp_review_gate` call claims the subject's active marker. If a call reports
362
+ marker contention, serialize the two calls rather than treating contention
363
+ as an error.
368
364
  - Each gate reviewer must return exactly one schema-valid JSON review object;
369
365
  never infer a verdict from Markdown. The gate derives approval from typed
370
366
  findings: blockers reject, nits approve with nits, and no findings approve.
@@ -1,44 +0,0 @@
1
- ---
2
- name: grok
3
- description: "Grok outside-voice reviewer through Webpresso MCP."
4
- license: MIT
5
- ---
6
-
7
- # Grok 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 `wp_review_gate` exactly once for the real plan version or delivery diff.
15
- - Observe the same durable operation with `wp_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
- ## Advisory 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
- "provider": "grok",
29
- "repository_access": "none",
30
- "mode": "advisory",
31
- }
32
- ```
33
-
34
- Use authoritative mode only when formal plan or delivery approval is requested.
35
-
36
- ## Model policy
37
-
38
- When the user names an exact model, pass it in the MCP `model` field. Otherwise omit
39
- that field and let the MCP owner select the configured provider default.
40
-
41
- ## Review quality
42
-
43
- Follow `catalog/agent/rules/review-methodology-sota.md`; report typed verdict, model,
44
- artifact, grounded findings, and independently verified conclusions.