@junghanacs/entwurf 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/AGENTS.md +1 -1
  2. package/BASELINE.md +23 -5
  3. package/CHANGELOG.md +236 -0
  4. package/DELIVERY.md +59 -6
  5. package/README.md +40 -9
  6. package/VERIFY.md +9 -1
  7. package/docs/acp-backend-rail.md +9 -1
  8. package/docs/external-mcp-host.md +6 -3
  9. package/docs/setup-clean-host.md +93 -7
  10. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +3 -3
  11. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/overlay.js +6 -2
  12. package/package.json +2 -2
  13. package/pi-extensions/acp-provider.ts +1 -1
  14. package/pi-extensions/lib/acp/models.ts +3 -3
  15. package/pi-extensions/lib/acp/overlay.ts +6 -2
  16. package/pi-extensions/lib/meta-session.ts +25 -0
  17. package/run.sh +71 -26
  18. package/scripts/agy-bridge.sh +1 -1
  19. package/scripts/agy-imprint.sh +10 -7
  20. package/scripts/check-acp-carrier-augment.ts +6 -5
  21. package/scripts/check-acp-cortex.ts +41 -0
  22. package/scripts/check-acp-provider-surface.ts +9 -6
  23. package/scripts/check-copilot-birth-hook.ts +3 -1
  24. package/scripts/check-copilot-receive-arm.ts +169 -21
  25. package/scripts/check-copilot-statusline.ts +3 -1
  26. package/scripts/check-gate-qualification.ts +10 -9
  27. package/scripts/check-hook-launch-topology.ts +6 -5
  28. package/scripts/check-install-surface.ts +2 -1
  29. package/scripts/check-meta-facts.ts +6 -4
  30. package/scripts/check-meta-hook-session-switch.ts +4 -3
  31. package/scripts/check-meta-identity-consumers.ts +8 -7
  32. package/scripts/check-meta-receiver-marker.ts +2 -1
  33. package/scripts/check-omp-birth-hook.ts +3 -2
  34. package/scripts/check-probe-bridge-command.ts +3 -1
  35. package/scripts/check-setup-qualification.sh +21 -0
  36. package/scripts/copilot-bridge-doctor.sh +15 -5
  37. package/scripts/copilot-bridge-install.sh +6 -2
  38. package/scripts/copilot-launch.sh +16 -2
  39. package/scripts/copilot-receive-bridge.sh +80 -13
  40. package/scripts/lib/reclaim-on-exit.ts +86 -0
  41. package/scripts/meta-bridge-doctor.sh +56 -15
  42. package/scripts/meta-bridge-install.sh +13 -7
  43. package/scripts/meta-bridge-uninstall.sh +6 -4
  44. package/scripts/mutants/acp-cortex.json +26 -2
  45. package/scripts/mutants/copilot-receive.json +26 -0
  46. package/scripts/mutants/omp-birth.json +23 -6
  47. package/scripts/mutants/setup-verdict.json +13 -0
  48. package/scripts/omp-bridge-doctor.sh +110 -41
  49. package/scripts/omp-bridge-install.sh +6 -2
  50. package/scripts/omp-receive-install.sh +7 -2
  51. package/scripts/raw-async-delivery/README.md +10 -1
  52. package/scripts/raw-codex-measure/README.md +689 -0
  53. package/scripts/raw-codex-measure/source-audit.md +243 -0
  54. package/scripts/raw-macos-measure/README.md +148 -0
  55. package/scripts/raw-macos-measure/probe.sh +389 -0
  56. package/scripts/smoke-meta-async-drift.sh +7 -5
  57. package/scripts/smoke-meta-install-state.sh +70 -19
  58. package/scripts/smoke-omp-bridge-state.sh +38 -0
  59. package/scripts/smoke-setup-verdict.sh +100 -0
@@ -0,0 +1,389 @@
1
+ #!/bin/sh
2
+ # raw-macos-measure/probe.sh — Darwin host measurement for the macOS parity lane (#78).
3
+ #
4
+ # MEASUREMENT ONLY. This script writes nothing outside its own temp dir, installs
5
+ # nothing, needs no entwurf installation, and touches no operator config. It is
6
+ # meant to be run ONCE on a borrowed Mac and its whole stdout pasted into
7
+ # scripts/raw-macos-measure/README.md.
8
+ #
9
+ # It is /bin/sh (not bash) on purpose: macOS ships bash 3.2 and one of the things
10
+ # under measurement is what a shell can assume here at all.
11
+ #
12
+ # ./probe.sh # human-readable ledger on stdout
13
+ #
14
+ # Every cell prints its own verdict token so a reader never has to interpret raw
15
+ # tool output: PRESENT / ABSENT / OK / DIFFERS / FAIL / UNKNOWN.
16
+
17
+ set -u
18
+
19
+ TMP=$(mktemp -d "${TMPDIR:-/tmp}/entwurf-macos-probe.XXXXXX") || exit 1
20
+ trap 'rm -rf "$TMP"' EXIT INT TERM
21
+
22
+ hdr() {
23
+ printf '\n== %s ==\n' "$1"
24
+ }
25
+
26
+ # `have <cmd>` -> PRESENT/ABSENT plus the resolved path.
27
+ have() {
28
+ if p=$(command -v "$1" 2>/dev/null); then
29
+ printf ' %-18s PRESENT %s\n' "$1" "$p"
30
+ return 0
31
+ fi
32
+ printf ' %-18s ABSENT\n' "$1"
33
+ return 1
34
+ }
35
+
36
+ printf 'entwurf raw-macos-measure probe\n'
37
+ printf 'run at: %s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ') UTC"
38
+
39
+ hdr 'M1. host identity'
40
+ if command -v sw_vers >/dev/null 2>&1; then
41
+ sw_vers | sed 's/^/ /'
42
+ else
43
+ printf ' sw_vers ABSENT — this is not a Darwin host; the ledger cell is void.\n'
44
+ fi
45
+ printf ' uname -srm: %s\n' "$(uname -srm)"
46
+ printf ' hw.model: %s\n' "$(sysctl -n hw.model 2>/dev/null || echo UNKNOWN)"
47
+ printf ' cpu: %s\n' "$(sysctl -n machdep.cpu.brand_string 2>/dev/null || echo UNKNOWN)"
48
+
49
+ hdr 'M2. shell — what a script may assume'
50
+ printf ' /bin/sh -> %s\n' "$(/bin/sh -c 'echo ${BASH_VERSION:-not-bash}' 2>/dev/null)"
51
+ printf ' /bin/bash -> %s\n' "$(/bin/bash -c 'echo ${BASH_VERSION:-unknown}' 2>/dev/null || echo ABSENT)"
52
+ printf ' env bash -> %s (%s)\n' \
53
+ "$(env bash -c 'echo ${BASH_VERSION:-unknown}' 2>/dev/null || echo ABSENT)" \
54
+ "$(command -v bash 2>/dev/null || echo no-bash-on-PATH)"
55
+ # bash 4 features the repo's gates use: `declare -A`, `mapfile`.
56
+ if env bash -c 'declare -A _x' >/dev/null 2>&1; then
57
+ printf ' declare -A (bash4) OK\n'
58
+ else
59
+ printf ' declare -A (bash4) FAIL — associative arrays unavailable to `env bash`\n'
60
+ fi
61
+ if env bash -c 'mapfile -t _y < /dev/null' >/dev/null 2>&1; then
62
+ printf ' mapfile (bash4) OK\n'
63
+ else
64
+ printf ' mapfile (bash4) FAIL\n'
65
+ fi
66
+
67
+ hdr 'M3. runtime prerequisites'
68
+ have node && printf ' %-18s %s\n' 'node --version' "$(node --version 2>/dev/null)"
69
+ have npm && printf ' %-18s %s\n' 'npm --version' "$(npm --version 2>/dev/null)"
70
+ have pnpm && printf ' %-18s %s\n' 'pnpm --version' "$(pnpm --version 2>/dev/null)"
71
+ # python3 on macOS may be the CommandLineTools STUB at /usr/bin/python3, which
72
+ # prints nothing useful and pops a GUI installer instead. The shipped operator
73
+ # surface calls python3 in hundreds of places, so a stub is a total install
74
+ # failure, not a degraded cell.
75
+ if have python3; then
76
+ printf ' %-18s %s\n' 'python3 -V' "$(python3 -V 2>&1)"
77
+ if python3 -c 'print("live")' 2>/dev/null | grep -q live; then
78
+ printf ' %-18s REAL (executes code, no install prompt)\n' 'python3 kind'
79
+ else
80
+ printf ' %-18s STUB/BROKEN — the whole install+doctor surface dies here\n' 'python3 kind'
81
+ fi
82
+ fi
83
+ have git
84
+ have tmux && printf ' %-18s %s\n' 'tmux -V' "$(tmux -V 2>/dev/null)"
85
+
86
+ hdr 'M4. GNU-vs-BSD tool matrix (the P1 substitution surface)'
87
+ have sha256sum || true
88
+ have shasum || true
89
+ have openssl || true
90
+ have realpath || true
91
+ have timeout || true
92
+ have gtimeout || true
93
+ have gsed || true
94
+ have gstat || true
95
+ printf '\n -- behavioural probes (presence is not compatibility) --\n'
96
+ printf 'abc' >"$TMP/f"
97
+ # stat: GNU `-c %s` vs BSD `-f %z`
98
+ if stat -c %s "$TMP/f" >/dev/null 2>&1; then
99
+ printf ' stat -c %%s OK (GNU form works)\n'
100
+ else
101
+ printf ' stat -c %%s FAIL (GNU form rejected) — BSD `stat -f %%z` = %s\n' \
102
+ "$(stat -f %z "$TMP/f" 2>/dev/null || echo FAIL)"
103
+ fi
104
+ # readlink -f
105
+ ln -s "$TMP/f" "$TMP/link"
106
+ if readlink -f "$TMP/link" >/dev/null 2>&1; then
107
+ printf ' readlink -f OK\n'
108
+ else
109
+ printf ' readlink -f FAIL (no GNU -f)\n'
110
+ fi
111
+ # stat: both fields the repo reads (size AND mtime), because a working `-f %z`
112
+ # does not promise `-f %m`.
113
+ printf ' stat -f %%z (size) %s\n' "$(stat -f %z "$TMP/f" 2>/dev/null || echo FAIL)"
114
+ printf ' stat -f %%m (mtime) %s\n' "$(stat -f %m "$TMP/f" 2>/dev/null || echo FAIL)"
115
+ printf ' stat -c %%Y (mtime) %s\n' "$(stat -c %Y "$TMP/f" 2>/dev/null || echo FAIL)"
116
+ # sha256: which producer, and does the digest text match across producers?
117
+ S_SUM=$(sha256sum "$TMP/f" 2>/dev/null | awk '{print $1}')
118
+ S_SHA=$(shasum -a 256 "$TMP/f" 2>/dev/null | awk '{print $1}')
119
+ S_SSL=$(openssl dgst -sha256 "$TMP/f" 2>/dev/null | awk '{print $NF}')
120
+ printf ' sha256sum %s\n' "${S_SUM:-ABSENT}"
121
+ printf ' shasum -a 256 %s\n' "${S_SHA:-ABSENT}"
122
+ printf ' openssl dgst %s\n' "${S_SSL:-ABSENT}"
123
+ for v in "$S_SUM" "$S_SHA" "$S_SSL"; do
124
+ [ -n "$v" ] && [ "$v" != "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" ] &&
125
+ printf ' DIGEST MISMATCH a producer disagrees with the known sha256 of "abc"\n'
126
+ done
127
+ # NUL-delimited pipelines
128
+ if printf 'a\0b\0' | sort -z >/dev/null 2>&1; then
129
+ printf ' sort -z OK\n'
130
+ else
131
+ printf ' sort -z FAIL (no BSD equivalent flag)\n'
132
+ fi
133
+ if printf 'a\0' | xargs -0 true >/dev/null 2>&1; then
134
+ printf ' xargs -0 OK\n'
135
+ else
136
+ printf ' xargs -0 FAIL\n'
137
+ fi
138
+ if printf 'a\0' | xargs -0r true >/dev/null 2>&1; then
139
+ printf ' xargs -0r OK\n'
140
+ else
141
+ printf ' xargs -0r FAIL (GNU-only -r; BSD xargs already skips empty input)\n'
142
+ fi
143
+ # grep -P
144
+ if printf 'a\n' | grep -P 'a' >/dev/null 2>&1; then
145
+ printf ' grep -P OK\n'
146
+ else
147
+ printf ' grep -P FAIL (no PCRE); grep -E = %s\n' \
148
+ "$(printf 'a\n' | grep -E 'a' >/dev/null 2>&1 && echo OK || echo FAIL)"
149
+ fi
150
+ # date -d
151
+ if date -d '@0' >/dev/null 2>&1; then
152
+ printf ' date -d OK\n'
153
+ else
154
+ printf ' date -d FAIL (BSD date uses -r/-j -f)\n'
155
+ fi
156
+ # mktemp with a template (both accept it, but confirm)
157
+ printf ' mktemp -d %s\n' "$(mktemp -d "${TMPDIR:-/tmp}/probe.XXXXXX" >/dev/null 2>&1 && echo OK || echo FAIL)"
158
+
159
+ hdr 'M5. start-key sources — the identity rail (meta-session.ts:1554)'
160
+ printf ' /proc present? %s\n' "$([ -d /proc ] && echo YES || echo NO)"
161
+ SELF=$$
162
+ printf ' ps -o lstart= self: %s\n' "$(ps -o lstart= -p "$SELF" 2>/dev/null | sed 's/^ *//;s/ *$//')"
163
+ printf ' ps -o command= self: %s\n' "$(ps -o command= -p "$SELF" 2>/dev/null | sed 's/^ *//' | cut -c1-100)"
164
+ # RESOLUTION TEST: two children started back to back. If their lstart strings are
165
+ # equal, the `ps:` scheme's pid-reuse defense is 1-second granular.
166
+ sleep 4 &
167
+ C1=$!
168
+ sleep 4 &
169
+ C2=$!
170
+ L1=$(ps -o lstart= -p "$C1" 2>/dev/null | sed 's/^ *//;s/ *$//')
171
+ L2=$(ps -o lstart= -p "$C2" 2>/dev/null | sed 's/^ *//;s/ *$//')
172
+ printf ' child A (%s): %s\n' "$C1" "$L1"
173
+ printf ' child B (%s): %s\n' "$C2" "$L2"
174
+ if [ "$L1" = "$L2" ]; then
175
+ printf ' RESOLUTION 1-SECOND (two back-to-back starts share one key string)\n'
176
+ else
177
+ printf ' RESOLUTION SUB-SECOND (back-to-back starts differ) — re-run to confirm\n'
178
+ fi
179
+ # WIDENING candidate: would including argv in the key have separated them? Both
180
+ # children run the SAME argv on purpose — that is the WORST case for widening, and
181
+ # the worst case is the one a fail-closed identity rail has to survive.
182
+ W1=$(ps -o lstart=,command= -p "$C1" 2>/dev/null | sed 's/^ *//;s/ *$//')
183
+ W2=$(ps -o lstart=,command= -p "$C2" 2>/dev/null | sed 's/^ *//;s/ *$//')
184
+ printf ' widened key A %s\n' "$W1"
185
+ printf ' widened key B %s\n' "$W2"
186
+ if [ "$W1" = "$W2" ]; then
187
+ printf ' WIDENING INSUFFICIENT ALONE (identical argv collides even widened)\n'
188
+ else
189
+ printf ' WIDENING SEPARATES (argv distinguished two same-second starts)\n'
190
+ fi
191
+ kill "$C1" "$C2" 2>/dev/null
192
+ wait "$C1" 2>/dev/null
193
+ wait "$C2" 2>/dev/null
194
+ # MICROSECOND candidate: libproc proc_pidinfo(PROC_PIDTBSDINFO) via python3 ctypes.
195
+ if command -v python3 >/dev/null 2>&1; then
196
+ python3 - "$SELF" <<'PY' 2>&1 | sed 's/^/ /'
197
+ import ctypes, ctypes.util, sys
198
+ pid = int(sys.argv[1])
199
+ lib = ctypes.util.find_library("proc") or "/usr/lib/libproc.dylib"
200
+ try:
201
+ libproc = ctypes.CDLL(lib)
202
+ except OSError as e:
203
+ print(f"libproc UNAVAILABLE ({e})")
204
+ raise SystemExit(0)
205
+
206
+ PROC_PIDTBSDINFO = 3
207
+ class ProcBsdInfo(ctypes.Structure):
208
+ _fields_ = [
209
+ ("pbi_flags", ctypes.c_uint32), ("pbi_status", ctypes.c_uint32),
210
+ ("pbi_xstatus", ctypes.c_uint32), ("pbi_pid", ctypes.c_uint32),
211
+ ("pbi_ppid", ctypes.c_uint32), ("pbi_uid", ctypes.c_uint32),
212
+ ("pbi_gid", ctypes.c_uint32), ("pbi_ruid", ctypes.c_uint32),
213
+ ("pbi_rgid", ctypes.c_uint32), ("pbi_svuid", ctypes.c_uint32),
214
+ ("pbi_svgid", ctypes.c_uint32), ("rfu_1", ctypes.c_uint32),
215
+ ("pbi_comm", ctypes.c_char * 16), ("pbi_name", ctypes.c_char * 32),
216
+ ("pbi_nfiles", ctypes.c_uint32), ("pbi_pgid", ctypes.c_uint32),
217
+ ("pbi_pjobc", ctypes.c_uint32), ("e_tdev", ctypes.c_uint32),
218
+ ("e_tpgid", ctypes.c_uint32), ("pbi_nice", ctypes.c_int32),
219
+ ("pbi_start_tvsec", ctypes.c_uint64), ("pbi_start_tvusec", ctypes.c_uint64),
220
+ ]
221
+
222
+ info = ProcBsdInfo()
223
+ n = libproc.proc_pidinfo(pid, PROC_PIDTBSDINFO, ctypes.c_uint64(0),
224
+ ctypes.byref(info), ctypes.sizeof(info))
225
+ if n != ctypes.sizeof(info):
226
+ print(f"proc_pidinfo FAIL (returned {n}, expected {ctypes.sizeof(info)})")
227
+ else:
228
+ print(f"proc_pidinfo OK pid={info.pbi_pid} "
229
+ f"start={info.pbi_start_tvsec}.{info.pbi_start_tvusec:06d} "
230
+ f"comm={info.pbi_comm.decode(errors='replace')}")
231
+ print("RESOLUTION MICROSECOND (a sub-second start key IS reachable here)")
232
+ PY
233
+ else
234
+ printf ' proc_pidinfo SKIPPED (no python3)\n'
235
+ fi
236
+
237
+ hdr 'M6. process discovery — can a reader see another process at all?'
238
+ # The bridge/receiver doctors narrow candidates through /proc/<pid>/{environ,cmdline}
239
+ # (scripts/omp-bridge-doctor.sh:258-267, scripts/copilot-receive-bridge.sh:264-289).
240
+ # Darwin has neither, so `ps -E` is the only candidate — and WHICH PROCESS IS ASKED
241
+ # decides the answer. Apple-signed, SIP-protected binaries refuse environ reads by
242
+ # construction, so probing `/bin/sleep` would report a false REJECTED.
243
+ #
244
+ # SCOPE, STATED EXACTLY: the node group below is a PROXY for entwurf's own MCP child,
245
+ # which is a node process this probe can start. It is NOT a measurement of the Copilot
246
+ # CLI or of omp: those are different binaries with their own signing and hardened-
247
+ # runtime state, and a proxy result does not transfer to them. The optional group 3
248
+ # probes a REAL copilot/omp process only if the operator already has one running; when
249
+ # it does not, that is reported as NOT MEASURED, never as coverage.
250
+ probe_environ() {
251
+ # $1 = label, $2 = pid, $3 = marker expected in the environment (or "")
252
+ _lbl=$1
253
+ _pid=$2
254
+ _marker=$3
255
+ if ps -E -p "$_pid" >/dev/null 2>&1; then
256
+ _out=$(ps -Eww -p "$_pid" 2>/dev/null | tail -1)
257
+ if [ -n "$_marker" ]; then
258
+ if printf '%s' "$_out" | grep -q "$_marker"; then
259
+ printf ' %-22s VISIBLE — marker found in `ps -Eww` output\n' "$_lbl"
260
+ else
261
+ printf ' %-22s ACCEPTED-BUT-EMPTY — ps -E returned, marker ABSENT\n' "$_lbl"
262
+ fi
263
+ else
264
+ printf ' %-22s ACCEPTED (width %s chars)\n' "$_lbl" \
265
+ "$(printf '%s' "$_out" | wc -c | tr -d ' ')"
266
+ fi
267
+ else
268
+ printf ' %-22s REJECTED by ps -E\n' "$_lbl"
269
+ fi
270
+ }
271
+ # Group 1 — UNRESTRICTED target: a node process we start ourselves, carrying a marker.
272
+ # This is the group that decides whether the doctors' discovery path survives.
273
+ if command -v node >/dev/null 2>&1; then
274
+ ENTWURF_PROBE_MARKER=hello-entwurf \
275
+ node -e 'setTimeout(function(){}, 5000)' >/dev/null 2>&1 &
276
+ N1=$!
277
+ sleep 1
278
+ printf ' node target pid %s\n' "$N1"
279
+ printf ' node argv %s\n' \
280
+ "$(ps -o command= -p "$N1" 2>/dev/null | sed 's/^ *//' | cut -c1-120)"
281
+ probe_environ 'node environ' "$N1" 'ENTWURF_PROBE_MARKER=hello-entwurf'
282
+ printf ' node ppid %s (expect this shell, %s)\n' \
283
+ "$(ps -o ppid= -p "$N1" 2>/dev/null | tr -d ' ')" "$SELF"
284
+ kill "$N1" 2>/dev/null
285
+ wait "$N1" 2>/dev/null
286
+ else
287
+ printf ' node target SKIPPED (no node on PATH) — THIS CELL IS THE IMPORTANT ONE\n'
288
+ fi
289
+ # Group 2 — RESTRICTED control: an Apple-signed system binary. A REJECTED here beside
290
+ # a VISIBLE above is the proof that the refusal is SIP, not a missing capability.
291
+ sleep 5 &
292
+ D1=$!
293
+ printf ' sleep argv %s\n' \
294
+ "$(ps -o command= -p "$D1" 2>/dev/null | sed 's/^ *//' | cut -c1-100)"
295
+ probe_environ '/bin/sleep environ' "$D1" ''
296
+ kill "$D1" 2>/dev/null
297
+ wait "$D1" 2>/dev/null
298
+ # Group 3 — THE REAL TARGETS, when the operator already has one running. Group 1 is a
299
+ # proxy; these are the binaries the doctors actually interrogate. A different signing
300
+ # or hardened-runtime state here than on our own node child is exactly the result that
301
+ # would invalidate the proxy, so an absent process is NOT MEASURED, never coverage.
302
+ for real in copilot omp claude; do
303
+ _rp=$(pgrep -x "$real" 2>/dev/null | head -1)
304
+ if [ -n "${_rp:-}" ]; then
305
+ printf ' %-22s live pid %s\n' "$real (real target)" "$_rp"
306
+ probe_environ "$real environ" "$_rp" ''
307
+ else
308
+ printf ' %-22s NOT MEASURED — no live `%s` process on this host\n' \
309
+ "$real (real target)" "$real"
310
+ fi
311
+ done
312
+ # Full-table scan: the fallback if environ is unreadable is argv-only matching over
313
+ # every process. Measure that it works AND what it costs.
314
+ SCAN_START=$(date +%s)
315
+ SCAN_N=$(ps -A -o pid=,ppid=,command= 2>/dev/null | wc -l | tr -d ' ')
316
+ SCAN_END=$(date +%s)
317
+ printf ' ps -A scan %s rows in ~%ss\n' "$SCAN_N" "$((SCAN_END - SCAN_START))"
318
+ printf ' pgrep present? %s\n' "$(command -v pgrep >/dev/null 2>&1 && echo YES || echo NO)"
319
+ printf ' lsof present? %s\n' "$(command -v lsof >/dev/null 2>&1 && echo YES || echo NO)"
320
+
321
+ hdr 'M7. pid space — how reachable is a same-second pid reuse?'
322
+ printf ' kern.maxproc: %s\n' "$(sysctl -n kern.maxproc 2>/dev/null || echo UNKNOWN)"
323
+ printf ' kern.maxprocperuid: %s\n' "$(sysctl -n kern.maxprocperuid 2>/dev/null || echo UNKNOWN)"
324
+ printf ' current pid: %s\n' "$SELF"
325
+ printf ' (PID_MAX on Darwin is a compile-time 99999; a wrap needs that many spawns)\n'
326
+
327
+ hdr 'M8. filesystem semantics that installers depend on'
328
+ printf ' case-sensitive? '
329
+ touch "$TMP/CaseFile"
330
+ if [ -e "$TMP/casefile" ]; then printf 'NO (case-INSENSITIVE volume)\n'; else printf 'YES\n'; fi
331
+ printf ' HOME: %s\n' "${HOME:-UNSET}"
332
+ printf ' XDG_DATA_HOME: %s\n' "${XDG_DATA_HOME:-unset (entwurf defaults apply)}"
333
+ printf ' symlink support: %s\n' "$([ -L "$TMP/link" ] && echo OK || echo FAIL)"
334
+ printf ' ~/.local/bin on PATH? %s\n' \
335
+ "$(printf '%s' "${PATH:-}" | tr ':' '\n' | grep -qx "$HOME/.local/bin" && echo YES || echo NO)"
336
+
337
+ hdr 'M9. fs.watch rename semantics — the mailbox doorbell'
338
+ # The receiver arms a watch and a sender delivers by writing then renaming into
339
+ # place. Darwin's fs.watch is FSEvents-backed, not inotify: confirm a rename-over
340
+ # actually raises an event for the WATCHED path.
341
+ if command -v node >/dev/null 2>&1; then
342
+ mkdir -p "$TMP/watch"
343
+ printf 'v1\n' >"$TMP/watch/target"
344
+ node -e '
345
+ const fs = require("fs");
346
+ const dir = process.argv[1];
347
+ let fired = [];
348
+ let watchErr = null;
349
+ let w = null;
350
+ try {
351
+ w = fs.watch(dir + "/target", (ev) => fired.push(ev));
352
+ w.on("error", (e) => { watchErr = e; });
353
+ } catch (e) {
354
+ watchErr = e;
355
+ }
356
+ setTimeout(() => {
357
+ try {
358
+ fs.writeFileSync(dir + "/staged", "v2\n");
359
+ fs.renameSync(dir + "/staged", dir + "/target");
360
+ } catch (e) {
361
+ watchErr = watchErr || e;
362
+ }
363
+ }, 200);
364
+ setTimeout(() => {
365
+ try { if (w) w.close(); } catch (e) { /* closing a dead watcher is not the measurement */ }
366
+ // EVERY path prints exactly one verdict token. An error is an honest UNKNOWN, not a
367
+ // missing line: a borrowed host must never hand back a cell that simply is not there.
368
+ if (watchErr) {
369
+ console.log(" fs.watch rename UNKNOWN — watcher errored: " + (watchErr.code || watchErr.message));
370
+ } else if (fired.length) {
371
+ console.log(" fs.watch rename FIRED [" + fired.join(",") + "]");
372
+ } else {
373
+ console.log(" fs.watch rename SILENT — doorbell would not ring");
374
+ }
375
+ try {
376
+ const dw = fs.watch(dir, () => {});
377
+ dw.close();
378
+ console.log(" fs.watch on dir SUPPORTED");
379
+ } catch (e) {
380
+ console.log(" fs.watch on dir UNSUPPORTED — " + (e.code || e.message));
381
+ }
382
+ }, 1200);
383
+ ' "$TMP/watch" 2>&1 | sed 's/^/ /;s/^ \( *fs\.watch\)/\1/'
384
+ else
385
+ printf ' fs.watch SKIPPED (no node on PATH)\n'
386
+ fi
387
+
388
+ printf '\n== probe complete ==\n'
389
+ printf 'Paste this whole output into scripts/raw-macos-measure/README.md under the matching cell.\n'
@@ -62,11 +62,13 @@ RAW_DIR="$HERE/raw-async-delivery"
62
62
  # 1.0 -> 1.1) is the real "re-verify the markers + Gotchas + raw/LIVE probes"
63
63
  # trigger and DOES scream.
64
64
  PIN_CLAUDE_MINOR="2.1"
65
- # codex 0.144 (2026-07-14): OBSERVED bump, not a re-verification. Codex is not a shipped
66
- # native-citizen lane in 0.12.x; the probe evidence in DELIVERY.md §Codex was measured at
67
- # 0.136.0 and has NOT been re-run on 0.144 that explicit verdict lives there. Re-run the
68
- # raw probes before building any codex adapter on this line.
69
- PIN_CODEX_MINOR="0.144"
65
+ # codex 0.153 (2026-09-08): RE-VERIFIED, not merely observed. The archived 0.136.0 raw probe
66
+ # (codex-local-appserver.sh + raw-codex-ws-turn-start.py) was re-run AS SHIPPED on codex-cli
67
+ # 0.153.4 and went green idle plain `codex` auto-attached to a bare `codex app-server
68
+ # --listen` woke with zero typing and the model replied in the same visible session. Receipts
69
+ # and the six step-1 vendor measurements: scripts/raw-codex-measure/README.md (see raw-codex-
70
+ # measure); coordinates restated in DELIVERY.md §Codex. Codex is still NOT a citizen backend.
71
+ PIN_CODEX_MINOR="0.153"
70
72
  # agy 1.1 (2026-07-14): re-verified live — entwurf_self called without a permission prompt,
71
73
  # bidirectional native-push reply on the same gid, LIVE=1 smoke-agy-native-push-live 13/13
72
74
  # at agy 1.1.0 (evidence recorded in DELIVERY.md §Antigravity).
@@ -962,31 +962,82 @@ else
962
962
  bad "doctor did not surface enabled-but-cache-miss as a hard load failure:"$'\n'"$DOC_CACHE_OUT"
963
963
  fi
964
964
 
965
- # #51 repair support boundary. Fake only `uname -s`: no macOS implementation is
966
- # emulated. New Darwin install must refuse as not-yet-certified, doctor must stay
967
- # nonzero with the same evidence wording, while uninstall MUST get past the platform
968
- # gate so an older managed install is not stranded (it then honestly fails on our
969
- # fixture's intentionally absent state file).
970
- PLATFORM_BIN="$TMP/platform-bin"; mkdir -p "$PLATFORM_BIN"
971
- cat > "$PLATFORM_BIN/uname" <<'SH'
972
- #!/usr/bin/env bash
965
+ # 0.20.0 D4: the platform fence moved from a bare `uname -s` refusal to the
966
+ # installer's own REAL dependency (python3; see meta-bridge-install.sh's platform
967
+ # gate comment). This gate must therefore pin the NEW contract, not the retired one:
968
+ # (a) Darwin install no longer refuses on platform name it reaches PAST the
969
+ # platform line to its own toolchain gate, and dies there ONLY when a real
970
+ # dependency is actually missing;
971
+ # (b) with the real dependency present, Darwin clears the platform gate entirely
972
+ # and reaches the external claude-CLI toolchain step (never "unsupported
973
+ # platform", never the retired "not yet verified/certified" wording);
974
+ # (c) meta-bridge-doctor.sh's Darwin RAIL verdict is a SEPARATE, unmoved evidence
975
+ # axis (Hard Rule 17) — it still refuses (nonzero), on a narrowed reason (Q2:
976
+ # start-key no longer needs /proc; per-process environ discovery still does);
977
+ # (d) uninstall was ALREADY open to Darwin (precedent) and is untouched here.
978
+ FAKE_UNAME_BIN="$TMP/fake-uname-bin"; mkdir -p "$FAKE_UNAME_BIN"
979
+ # Bake the ABSOLUTE bash path into the shebang: the two cells below deliberately
980
+ # narrow PATH (no bash on it), and `#!/usr/bin/env bash` would need `env` to find
981
+ # `bash` on THAT narrowed PATH — this fixture's own launcher must not depend on it.
982
+ cat > "$FAKE_UNAME_BIN/uname" <<SH
983
+ #!$(command -v bash)
973
984
  printf '%s\n' Darwin
974
985
  SH
975
- chmod +x "$PLATFORM_BIN/uname"
986
+ chmod +x "$FAKE_UNAME_BIN/uname"
987
+
988
+ # (a) A minimal PATH carrying ONLY `dirname` (the sole external command
989
+ # meta-bridge-install.sh calls before its own python3 check) plus the fake Darwin
990
+ # `uname`. No real python3/node/claude can leak in from the host — the death point
991
+ # is fully controlled by this fixture, not by what happens to be installed here.
992
+ NOPY_BIN="$TMP/nopy-bin"; mkdir -p "$NOPY_BIN"
993
+ ln -sf "$(command -v dirname)" "$NOPY_BIN/dirname"
994
+ set +e
995
+ DARWIN_NOPY_OUT="$(env HOME="$TMP/darwin-nopy-home" XDG_DATA_HOME="$TMP/darwin-nopy-xdg" PATH="$FAKE_UNAME_BIN:$NOPY_BIN" "$BASH" "$REPO/scripts/meta-bridge-install.sh" 2>&1)"
996
+ DARWIN_NOPY_CODE=$?
997
+ set -e
998
+ if [ "$DARWIN_NOPY_CODE" -ne 0 ] \
999
+ && printf '%s\n' "$DARWIN_NOPY_OUT" | grep -q "python3' not on PATH" \
1000
+ && ! printf '%s\n' "$DARWIN_NOPY_OUT" | grep -qi 'unsupported platform'; then
1001
+ ok "Darwin install clears the platform gate and refuses on the REAL missing dependency (python3), never on platform name"
1002
+ else bad "Darwin install did not reach the python3 dependency gate as the new fence contract requires:"$'\n'"$DARWIN_NOPY_OUT"; fi
1003
+
1004
+ # (b) The mirror proof: Darwin WITH python3+node present must clear the platform
1005
+ # gate AND the toolchain gate, refusing only because `claude` is absent from this
1006
+ # fixture's deliberately narrow PATH (never on platform name, never on the retired
1007
+ # "not yet verified/certified" wording).
1008
+ OK_BIN="$TMP/darwin-ok-bin"; mkdir -p "$OK_BIN"
1009
+ ln -sf "$(command -v dirname)" "$OK_BIN/dirname"
1010
+ ln -sf "$(command -v node)" "$OK_BIN/node"
1011
+ ln -sf "$(command -v python3)" "$OK_BIN/python3"
1012
+ set +e
1013
+ DARWIN_OK_OUT="$(env HOME="$TMP/darwin-ok-home" XDG_DATA_HOME="$TMP/darwin-ok-xdg" PI_CODING_AGENT_DIR="$TMP/darwin-ok-agent" PATH="$FAKE_UNAME_BIN:$OK_BIN" "$BASH" "$REPO/scripts/meta-bridge-install.sh" 2>&1)"
1014
+ DARWIN_OK_CODE=$?
1015
+ set -e
1016
+ if [ "$DARWIN_OK_CODE" -ne 0 ] \
1017
+ && printf '%s\n' "$DARWIN_OK_OUT" | grep -q "'claude' CLI not on PATH" \
1018
+ && ! printf '%s\n' "$DARWIN_OK_OUT" | grep -qi 'unsupported platform' \
1019
+ && ! printf '%s\n' "$DARWIN_OK_OUT" | grep -qi 'not yet verified'; then
1020
+ ok "Darwin install with real python3+node clears BOTH the platform and toolchain-part-1 gates, reaching the external claude-CLI step"
1021
+ else bad "Darwin install with real python3+node did not clear the platform gate as the new contract requires:"$'\n'"$DARWIN_OK_OUT"; fi
1022
+
1023
+ # (c) The doctor's RAIL verdict is untouched by the fence change: still nonzero,
1024
+ # still reaches its final verdict line. Wording is narrowed under Q2/D1 (start-key
1025
+ # no longer blamed; only per-process environ discovery is), so pin the substring
1026
+ # that survives that rename, not the retired sentence.
976
1027
  set +e
977
- DARWIN_INSTALL_OUT="$(env HOME="$DOC_HOME" XDG_DATA_HOME="$TMP/darwin-xdg" PI_CODING_AGENT_DIR="$DOC_AGENT" PATH="$PLATFORM_BIN:$DOC_BIN:$PATH" bash "$REPO/scripts/meta-bridge-install.sh" 2>&1)"
978
- DARWIN_INSTALL_CODE=$?
979
- DARWIN_DOCTOR_OUT="$(env HOME="$DOC_HOME" CLAUDE_CONFIG_DIR="$DOC_CFG" PI_CODING_AGENT_DIR="$DOC_AGENT" ENTWURF_META_SESSIONS_DIR="$DOC_STORE" PATH="$PLATFORM_BIN:$DOC_BIN:$PATH" bash "$REPO/scripts/meta-bridge-doctor.sh" 2>&1)"
1028
+ DARWIN_DOCTOR_OUT="$(env HOME="$DOC_HOME" CLAUDE_CONFIG_DIR="$DOC_CFG" PI_CODING_AGENT_DIR="$DOC_AGENT" ENTWURF_META_SESSIONS_DIR="$DOC_STORE" PATH="$FAKE_UNAME_BIN:$DOC_BIN:$PATH" bash "$REPO/scripts/meta-bridge-doctor.sh" 2>&1)"
980
1029
  DARWIN_DOCTOR_CODE=$?
981
- DARWIN_UNINSTALL_OUT="$(env HOME="$TMP/darwin-clean-home" XDG_DATA_HOME="$TMP/darwin-clean-xdg" PATH="$PLATFORM_BIN:$PATH" bash "$REPO/scripts/meta-bridge-uninstall.sh" 2>&1)"
1030
+ set -e
1031
+ if [ "$DARWIN_DOCTOR_CODE" -ne 0 ] && printf '%s\n' "$DARWIN_DOCTOR_OUT" | grep -q 'NOT CERTIFIED' && printf '%s\n' "$DARWIN_DOCTOR_OUT" | grep -q 'meta-bridge doctor: FAIL'; then
1032
+ ok "Darwin doctor stays nonzero and reaches its final NOT-CERTIFIED verdict (rail certification is a separate, unmoved axis)"
1033
+ else bad "Darwin doctor did not hold the rail-certification evidence boundary:"$'\n'"$DARWIN_DOCTOR_OUT"; fi
1034
+
1035
+ # (d) Uninstall precedent, unchanged by this lane: it was ALREADY open to Darwin
1036
+ # before 0.20.0 (legacy-cleanup capability, never install certification).
1037
+ set +e
1038
+ DARWIN_UNINSTALL_OUT="$(env HOME="$TMP/darwin-clean-home" XDG_DATA_HOME="$TMP/darwin-clean-xdg" PATH="$FAKE_UNAME_BIN:$PATH" bash "$REPO/scripts/meta-bridge-uninstall.sh" 2>&1)"
982
1039
  DARWIN_UNINSTALL_CODE=$?
983
1040
  set -e
984
- if [ "$DARWIN_INSTALL_CODE" -ne 0 ] && printf '%s\n' "$DARWIN_INSTALL_OUT" | grep -q 'not yet verified/certified for this repair cut'; then
985
- ok "Darwin install is refused fail-loud as not-yet-certified (future validation may reopen)"
986
- else bad "Darwin install did not enforce the repair-cut evidence boundary:"$'\n'"$DARWIN_INSTALL_OUT"; fi
987
- if [ "$DARWIN_DOCTOR_CODE" -ne 0 ] && printf '%s\n' "$DARWIN_DOCTOR_OUT" | grep -q 'NOT YET VERIFIED/CERTIFIED for this repair cut' && printf '%s\n' "$DARWIN_DOCTOR_OUT" | grep -q 'meta-bridge doctor: FAIL'; then
988
- ok "Darwin doctor stays nonzero and reaches its final NOT-YET-CERTIFIED verdict"
989
- else bad "Darwin doctor did not hold the repair-cut evidence boundary:"$'\n'"$DARWIN_DOCTOR_OUT"; fi
990
1041
  if [ "$DARWIN_UNINSTALL_CODE" -ne 0 ] && printf '%s\n' "$DARWIN_UNINSTALL_OUT" | grep -q 'install state missing' && ! printf '%s\n' "$DARWIN_UNINSTALL_OUT" | grep -q 'unsupported platform'; then
991
1042
  ok "Darwin uninstall passes the platform gate and reaches honest state preflight (legacy inverse retained)"
992
1043
  else bad "Darwin uninstall was blocked by the support hard-cut instead of reaching honest inverse preflight:"$'\n'"$DARWIN_UNINSTALL_OUT"; fi
@@ -114,6 +114,44 @@ kill "$CARRIER_PID"
114
114
  wait "$CARRIER_PID" 2>/dev/null || true
115
115
  CARRIER_PID=""
116
116
 
117
+ # THE CANDIDATE SET ITSELF CAN BE UNKNOWN, AND UNKNOWN IS NOT EMPTY (#78 B1). `pgrep`
118
+ # answers three ways and only two of them are facts about omp: 0 = it enumerated and
119
+ # matched, 1 = it enumerated and NOTHING matched (a real, positive absence), anything
120
+ # else = it never enumerated. The doctor used to `|| true` that third answer into the
121
+ # second, so a broken enumeration produced an empty candidate set, the clean carrier
122
+ # line and a PASS — with a contaminated session possibly live on the host.
123
+ #
124
+ # BOTH DIRECTIONS ARE PINNED, because a repair that also reddened the honest "nothing
125
+ # matched" would be a different defect. `ENTWURF_OMP_CARRIER_PIDS` must be UNSET for
126
+ # these two: that seam short-circuits the very enumeration under test, which is why it
127
+ # is a narrowing seam and never production proof.
128
+ PGREP_SHIM="$SB/pgrep-shim"
129
+ mkdir -p "$PGREP_SHIM"
130
+ printf '#!/usr/bin/env bash\nexit 1\n' > "$PGREP_SHIM/pgrep"
131
+ chmod +x "$PGREP_SHIM/pgrep"
132
+ if OUT="$(env -u ENTWURF_OMP_CARRIER_PIDS PATH="$PGREP_SHIM:$PATH" "$RUN" doctor-omp-bridge 2>&1)"; then
133
+ printf '%s\n' "$OUT" | grep -q "no live omp process carries" || die "an enumerated-and-empty candidate set did not print the clean carrier verdict"
134
+ ok "a \`pgrep\` that enumerated and matched NOTHING is a real absence and stays green"
135
+ else
136
+ printf '%s\n' "$OUT" >&2
137
+ die "a \`pgrep\` exit 1 (nothing matched) turned the carrier axis red"
138
+ fi
139
+ printf '#!/usr/bin/env bash\nexit 2\n' > "$PGREP_SHIM/pgrep"
140
+ if OUT="$(env -u ENTWURF_OMP_CARRIER_PIDS PATH="$PGREP_SHIM:$PATH" "$RUN" doctor-omp-bridge 2>&1)"; then
141
+ printf '%s\n' "$OUT" >&2
142
+ die "[QK:OMP-DOCTOR-UNENUMERATED-IS-UNVERIFIABLE] a FAILED process enumeration left the doctor green — it printed a carrier verdict with no candidate set, so a live omp session carrying a foreign pi garden id would read as clean"
143
+ fi
144
+ if ! printf '%s\n' "$OUT" | grep -q "UNVERIFIABLE — 'pgrep -x omp' FAILED (exit 2)"; then
145
+ printf '%s\n' "$OUT" >&2
146
+ die "the doctor went red without naming the failed enumeration as UNVERIFIABLE"
147
+ fi
148
+ if printf '%s\n' "$OUT" | grep -q "no live omp process carries"; then
149
+ printf '%s\n' "$OUT" >&2
150
+ die "the doctor claimed a clean carrier axis while the candidate set was unknown"
151
+ fi
152
+ ok "a FAILED enumeration is UNVERIFIABLE and red, and it claims neither contamination nor absence"
153
+ rm -rf "$PGREP_SHIM"
154
+
117
155
  # ── 2. reinstall is idempotent ───────────────────────────────────────────────
118
156
  "$RUN" install-omp-bridge >/dev/null || die "reinstall over our own state failed"
119
157
  "$RUN" doctor-omp-bridge >/dev/null || die "doctor red after a reinstall"