@junghanacs/entwurf 0.15.0 → 0.16.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 (90) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +299 -0
  3. package/DELIVERY.md +4 -3
  4. package/README.md +99 -67
  5. package/VERIFY.md +13 -7
  6. package/docs/acp-backend-rail.md +1 -1
  7. package/docs/external-mcp-host.md +147 -9
  8. package/docs/setup-clean-host.md +221 -16
  9. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +65 -20
  10. package/mcp/entwurf-bridge/dist/pi-extensions/entwurf-capabilities.json +1 -0
  11. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +17 -6
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +1 -1
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +172 -5
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +152 -17
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/omp-fresh-preflight.js +271 -0
  16. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-omp.js +988 -0
  17. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-receive-omp.js +574 -0
  18. package/mcp/entwurf-bridge/dist/scripts/omp-receive-facts.js +84 -0
  19. package/mcp/entwurf-bridge/src/index.ts +65 -19
  20. package/mcp/entwurf-bridge/tsconfig.build.json +19 -3
  21. package/mcp/tsconfig.json +10 -0
  22. package/package.json +14 -4
  23. package/pi/entwurf-capabilities.json +1 -0
  24. package/pi/meta-bridge-omp/entwurf-meta-omp/package.json +7 -0
  25. package/pi/omp-receive/entwurf-receive-omp/package.json +7 -0
  26. package/pi-extensions/entwurf-control.ts +12 -9
  27. package/pi-extensions/lib/entwurf-self-address.ts +18 -7
  28. package/pi-extensions/lib/meta-sender-identity.ts +1 -1
  29. package/pi-extensions/lib/meta-session.ts +219 -5
  30. package/pi-extensions/lib/mux-fresh-call.ts +171 -17
  31. package/pi-extensions/lib/omp-fresh-preflight.ts +275 -0
  32. package/pi-extensions/meta-bridge-omp.ts +1244 -0
  33. package/pi-extensions/meta-bridge-receive-omp.ts +666 -0
  34. package/run.sh +1041 -174
  35. package/scripts/agy-bridge.sh +4 -2
  36. package/scripts/check-copilot-birth-hook.ts +700 -23
  37. package/scripts/check-entwurf-self-address.ts +31 -0
  38. package/scripts/check-fresh-cut-gate.sh +12 -4
  39. package/scripts/check-gate-qualification.ts +8 -2
  40. package/scripts/check-harness-admission-parity.ts +143 -0
  41. package/scripts/check-meta-doctor-oracle.sh +20 -0
  42. package/scripts/check-omp-birth-hook.ts +1049 -0
  43. package/scripts/check-omp-fresh-preflight.ts +181 -0
  44. package/scripts/check-omp-receive-arm.ts +516 -0
  45. package/scripts/check-setup-qualification.sh +126 -0
  46. package/scripts/copilot-bridge-doctor.sh +104 -71
  47. package/scripts/copilot-bridge-install.sh +180 -20
  48. package/scripts/copilot-bridge-oracle.sh +223 -0
  49. package/scripts/copilot-bridge-uninstall.sh +137 -0
  50. package/scripts/dev-bin.sh +50 -9
  51. package/scripts/fake-copilot-vendor.sh +67 -0
  52. package/scripts/inventory-verification-surface.ts +1 -1
  53. package/scripts/meta-bridge-hook-log.sh +9 -1
  54. package/scripts/mutants/copilot-birth.json +96 -5
  55. package/scripts/mutants/mux-fresh-call.json +22 -22
  56. package/scripts/mutants/omp-birth.json +173 -0
  57. package/scripts/mutants/omp-fresh.json +300 -0
  58. package/scripts/mutants/omp-receive.json +135 -0
  59. package/scripts/mutants/pi-package-ownership.json +92 -0
  60. package/scripts/mutants/self-address.json +34 -0
  61. package/scripts/mutants/setup-verdict.json +148 -0
  62. package/scripts/mutants/source-install.json +32 -0
  63. package/scripts/omp-bridge-doctor.sh +315 -0
  64. package/scripts/omp-bridge-install.sh +221 -0
  65. package/scripts/omp-bridge-oracle.sh +154 -0
  66. package/scripts/omp-bridge-uninstall.sh +57 -0
  67. package/scripts/omp-mcp-bridge.sh +320 -0
  68. package/scripts/omp-mcp-config.py +392 -0
  69. package/scripts/omp-receive-doctor.sh +246 -0
  70. package/scripts/omp-receive-facts.ts +106 -0
  71. package/scripts/omp-receive-install.sh +228 -0
  72. package/scripts/omp-receive-uninstall.sh +60 -0
  73. package/scripts/omp-tool-surface.py +349 -0
  74. package/scripts/pi_settings_io.py +22 -0
  75. package/scripts/raw-omp-measure/README.md +420 -0
  76. package/scripts/raw-omp-measure/probe-extension.ts +76 -0
  77. package/scripts/raw-omp-measure/probe-receive-surface.ts +250 -0
  78. package/scripts/raw-omp-measure/source-audit.md +414 -0
  79. package/scripts/register-pi-package.py +525 -7
  80. package/scripts/register-pi-provider.py +162 -12
  81. package/scripts/smoke-agy-install-state.sh +86 -30
  82. package/scripts/smoke-agy-statusline-state.sh +9 -6
  83. package/scripts/smoke-omp-bridge-state.sh +221 -0
  84. package/scripts/smoke-omp-fresh-live.ts +497 -0
  85. package/scripts/smoke-omp-mcp-state.sh +327 -0
  86. package/scripts/smoke-omp-receive-live.ts +340 -0
  87. package/scripts/smoke-omp-receive-state.sh +196 -0
  88. package/scripts/smoke-setup-verdict.sh +291 -0
  89. package/scripts/smoke-user-scope-citizen.sh +388 -1
  90. package/scripts/tsconfig.json +2 -0
@@ -0,0 +1,221 @@
1
+ #!/usr/bin/env bash
2
+ # smoke-omp-bridge-state — hermetic install/doctor/inverse contract for the OMP BIRTH
3
+ # extension (#87). No omp process, no model turn, no writes outside the sandbox.
4
+ #
5
+ # The four properties an install surface owes (adding-a-harness.md step 4(b)), read for a
6
+ # unit that is a DIRECTORY rather than a config key:
7
+ # - it installs where the vendor actually looks, and the doctor agrees;
8
+ # - the inverse is honest — it removes exactly what the state records, and a host whose
9
+ # ownership cannot be established REFUSES rather than tidying up;
10
+ # - a foreign or symlinked artifact at our path is refused, never written through;
11
+ # - a stale deployed copy of the shared writer is named, because that is the failure
12
+ # mode a new backend id creates on every deployed reader (step 2(c)).
13
+ set -euo pipefail
14
+
15
+ REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
16
+ RUN="$REPO_DIR/run.sh"
17
+ pass=0
18
+ ok() { printf ' ok %s\n' "$1"; pass=$((pass + 1)); }
19
+ die() { printf 'FAIL: %s\n' "$1" >&2; exit 1; }
20
+ want() { eval "$2" && ok "$1" || die "$1"; }
21
+ wait_carrier() {
22
+ local pid="$1" key="$2" i=0
23
+ while [ "$i" -lt 50 ]; do
24
+ if kill -0 "$pid" 2>/dev/null && [ -r "/proc/$pid/environ" ]; then
25
+ if tr '\0' '\n' < "/proc/$pid/environ" 2>/dev/null | grep -q "^${key}"; then
26
+ return 0
27
+ fi
28
+ fi
29
+ sleep 0.05
30
+ i=$((i + 1))
31
+ done
32
+ die "carrier fixture pid $pid never showed ${key}"
33
+ }
34
+
35
+ REPO_BEFORE="$(cd "$REPO_DIR" && git status --porcelain)"
36
+ SB="$(mktemp -d)"
37
+ CARRIER_PID=""
38
+ cleanup() {
39
+ if [ -n "$CARRIER_PID" ]; then kill "$CARRIER_PID" 2>/dev/null || true; wait "$CARRIER_PID" 2>/dev/null || true; fi
40
+ rm -rf "$SB"
41
+ }
42
+ trap cleanup EXIT
43
+ # HARD RULE 12, in full. Not HOME + XDG_DATA_HOME alone: an inherited XDG_CONFIG_HOME or a
44
+ # PI_CODING_AGENT_DIR from the operator's shell would leave a writable real root reachable
45
+ # from inside this smoke. PI is set to a POISON path on purpose — after #87 B1 no OMP garden
46
+ # artifact may resolve through it, and the last check in this file asserts that tree stayed
47
+ # empty. (`ENTWURF_OMP_AGENT_DIR` still wins for the VENDOR agent dir, which is what keeps
48
+ # the installer from refusing on the ambiguity below.)
49
+ export HOME="$SB/home"
50
+ export XDG_DATA_HOME="$SB/xdg"
51
+ export XDG_CONFIG_HOME="$SB/xdg-config"
52
+ export XDG_STATE_HOME="$SB/xdg-state"
53
+ export XDG_CACHE_HOME="$SB/xdg-cache"
54
+ export XDG_RUNTIME_DIR="$SB/xdg-runtime"
55
+ PI_POISON="$SB/pi-poison-agent"
56
+ export PI_CODING_AGENT_DIR="$PI_POISON"
57
+ export ENTWURF_OMP_AGENT_DIR="$SB/home/.omp/agent"
58
+ mkdir -p "$ENTWURF_OMP_AGENT_DIR" "$SB/bin" "$XDG_CONFIG_HOME" "$XDG_STATE_HOME" "$XDG_CACHE_HOME" "$XDG_RUNTIME_DIR"
59
+ # The installer requires the vendor on PATH — entwurf never installs a harness, so an
60
+ # absent omp is a refusal rather than a silent no-op. This fixture also runs two bounded
61
+ # fake omp processes to prove the doctor's carrier distinction without a vendor process.
62
+ ln -s "$(command -v bash)" "$SB/bin/omp"
63
+ export PATH="$SB/bin:$PATH"
64
+
65
+ # Narrow the doctor's live-process scan to this smoke's fixtures. Unset would let
66
+ # `pgrep -x omp` see the operator host, and a presence-only mutant would then fail
67
+ # the first doctor call for the wrong reason.
68
+ export ENTWURF_OMP_CARRIER_PIDS=""
69
+ UNIT_DIR="$ENTWURF_OMP_AGENT_DIR/extensions/entwurf-meta-omp"
70
+ STATE="$XDG_DATA_HOME/entwurf/omp-bridge/install-state.json"
71
+ ASM="$XDG_DATA_HOME/entwurf/meta-bridge-omp/.assembled"
72
+
73
+ # ── 1. install ───────────────────────────────────────────────────────────────
74
+ "$RUN" install-omp-bridge >/dev/null || die "install-omp-bridge failed"
75
+ want "the unit lands where omp's native discovery looks" "[ -f '$UNIT_DIR/index.ts' ]"
76
+ want "it carries the shared V3 writer" "[ -f '$UNIT_DIR/lib/meta-session.ts' ]"
77
+ want "it carries the capability registry the writer resolves via ../" "[ -f '$UNIT_DIR/entwurf-capabilities.json' ]"
78
+ want "ownership state was written" "[ -f '$STATE' ]"
79
+ want "the state records the unit dir it placed" "grep -q '\"unitDir\"' '$STATE' && grep -q 'entwurf-meta-omp' '$STATE'"
80
+ want "config.yml was NOT created or touched — this unit owns no operator SSOT" "[ ! -e '$ENTWURF_OMP_AGENT_DIR/config.yml' ]"
81
+ "$RUN" doctor-omp-bridge >/dev/null || die "doctor red right after a clean install"
82
+ ok "doctor is green right after install"
83
+
84
+ # `tmux -e NAME=` preserves the variable with an empty value. The bridge trims before
85
+ # deciding whether a pi carrier is authoritative, so this doctor must do the same rather
86
+ # than turn Bundle C's deliberate scrub into a red floor. The positive cell keeps actual
87
+ # nonblank inheritance on its own fail-loud axis.
88
+ PI_SESSION_ID=" " PI_AGENT_ID=$'\t' "$SB/bin/omp" -c 'while :; do sleep 60; done' &
89
+ CARRIER_PID=$!
90
+ wait_carrier "$CARRIER_PID" "PI_SESSION_ID="
91
+ if OUT="$(ENTWURF_OMP_CARRIER_PIDS="$CARRIER_PID" "$RUN" doctor-omp-bridge 2>&1)"; then
92
+ ok "blank or whitespace-only PI carriers on a live omp process are nonauthoritative, matching the bridge reader and managed tmux scrub"
93
+ else
94
+ printf '%s\n' "$OUT" >&2
95
+ die "[QK:OMP-DOCTOR-CARRIER-TRIMS] blank or whitespace-only PI carriers made the doctor red"
96
+ fi
97
+ kill "$CARRIER_PID"
98
+ wait "$CARRIER_PID" 2>/dev/null || true
99
+ CARRIER_PID=""
100
+
101
+ PI_SESSION_ID="foreign-garden" PI_AGENT_ID="pi-agent-fixture" "$SB/bin/omp" -c 'while :; do sleep 60; done' &
102
+ CARRIER_PID=$!
103
+ wait_carrier "$CARRIER_PID" "PI_SESSION_ID=foreign-garden"
104
+ if OUT="$(ENTWURF_OMP_CARRIER_PIDS="$CARRIER_PID" "$RUN" doctor-omp-bridge 2>&1)"; then
105
+ printf '%s\n' "$OUT" >&2
106
+ die "doctor accepted the live omp fixture with nonblank inherited PI carriers"
107
+ fi
108
+ printf '%s\n' "$OUT" | grep -q "live omp process(es).* $CARRIER_PID" || die "doctor red without naming the nonblank-carrier fixture"
109
+ ok "a nonblank inherited PI carrier on a live omp process remains red"
110
+ kill "$CARRIER_PID"
111
+ wait "$CARRIER_PID" 2>/dev/null || true
112
+ CARRIER_PID=""
113
+
114
+ # ── 2. reinstall is idempotent ───────────────────────────────────────────────
115
+ "$RUN" install-omp-bridge >/dev/null || die "reinstall over our own state failed"
116
+ "$RUN" doctor-omp-bridge >/dev/null || die "doctor red after a reinstall"
117
+ ok "reinstall over our own state is idempotent and stays green"
118
+
119
+ # ── 3. a STALE deployed writer is named ──────────────────────────────────────
120
+ printf '\n// drifted\n' >> "$UNIT_DIR/lib/meta-session.ts"
121
+ if OUT="$("$RUN" doctor-omp-bridge 2>&1)"; then
122
+ die "doctor stayed green with a stale deployed writer"
123
+ fi
124
+ printf '%s\n' "$OUT" | grep -q "STALE" || die "doctor went red without naming the staleness"
125
+ ok "a drifted copy of the writer is reported as STALE, with the redeploy prescription"
126
+ "$RUN" install-omp-bridge >/dev/null
127
+ "$RUN" doctor-omp-bridge >/dev/null || die "reinstall did not repair the stale writer"
128
+ ok "reinstall repairs it"
129
+
130
+ # A byte-valid copy of our OWN unit, kept for the no-state cell below: it passes every
131
+ # structural check there is, which is exactly why a shape must not license adoption.
132
+ cp -r "$UNIT_DIR" "$SB/valid-unit"
133
+
134
+ # ── 4. the inverse is honest ─────────────────────────────────────────────────
135
+ "$RUN" uninstall-omp-bridge >/dev/null || die "uninstall failed"
136
+ want "the unit is gone" "[ ! -e '$UNIT_DIR' ]"
137
+ want "the assembly is gone" "[ ! -e '$ASM' ]"
138
+ want "the ownership state is gone" "[ ! -e '$STATE' ]"
139
+ want "the agent dir itself survives — we only ever owned our own subdirectory" "[ -d '$ENTWURF_OMP_AGENT_DIR' ]"
140
+ "$RUN" doctor-omp-bridge >/dev/null || die "doctor red on a clean uninstalled host (zero state is a SKIP, not a fault)"
141
+ ok "doctor reads a clean uninstalled host as zero-state, not as a fault"
142
+
143
+ if "$RUN" uninstall-omp-bridge >/dev/null 2>&1; then
144
+ die "uninstall on a no-state host reported success"
145
+ fi
146
+ ok "a second uninstall REFUSES — a no-state host is unproven ownership, not an empty one"
147
+
148
+ # ── 5. NOTHING at our path is adopted without ownership STATE (#87 B2) ───────
149
+ # The structurally VALID case first, because it is the one that used to pass: the old
150
+ # installer ran a shape oracle, called green "ours", moved the directory aside, published
151
+ # over it and DELETED the preimage — and the inverse then rm -rf'd the path on the same
152
+ # unproven claim. A hand-copied unit, or ours plus operator files beside it, was destroyed
153
+ # with no way back. A shape is not a proof of ownership.
154
+ cp -r "$SB/valid-unit" "$UNIT_DIR"
155
+ printf 'operator note\n' > "$UNIT_DIR/NOTES.md"
156
+ if "$RUN" install-omp-bridge >/dev/null 2>&1; then
157
+ die "install ADOPTED a structurally valid no-state unit — a shape is not ownership"
158
+ fi
159
+ want "the stranger's file beside it survives the refusal" "[ -f '$UNIT_DIR/NOTES.md' ]"
160
+ want "the unit's own entry is untouched" "[ -f '$UNIT_DIR/index.ts' ]"
161
+ want "no ownership state was invented by the refusal" "[ ! -e '$STATE' ]"
162
+ ok "a structurally VALID no-state unit is refused with zero writes — ownership state is the only licence"
163
+ rm -rf "$UNIT_DIR"
164
+
165
+ # ── 5b. a foreign unit at our path is refused, never written through ─────────
166
+ mkdir -p "$UNIT_DIR"
167
+ printf 'someone else\n' > "$UNIT_DIR/index.ts"
168
+ if "$RUN" install-omp-bridge >/dev/null 2>&1; then
169
+ die "install adopted a foreign directory that fails the structural oracle"
170
+ fi
171
+ want "the foreign file is byte-identical after the refusal" "grep -q 'someone else' '$UNIT_DIR/index.ts'"
172
+ want "no ownership state was written by the refusal" "[ ! -e '$STATE' ]"
173
+ ok "a foreign no-state unit is refused with zero writes"
174
+ rm -rf "$UNIT_DIR"
175
+
176
+ mkdir -p "$SB/elsewhere"
177
+ ln -s "$SB/elsewhere" "$UNIT_DIR"
178
+ if "$RUN" install-omp-bridge >/dev/null 2>&1; then
179
+ die "install wrote through a symlinked unit path"
180
+ fi
181
+ want "the symlink target is still empty — nothing was written through the link" "[ -z \"\$(ls -A '$SB/elsewhere')\" ]"
182
+ ok "a SYMLINK at the unit path is refused"
183
+ rm -f "$UNIT_DIR"
184
+
185
+ # ── 6. an ambiguous agent dir refuses instead of guessing (ledger M6) ────────
186
+ # omp is a pi fork and reads pi's env vocabulary, so an inherited PI_* knob does not say
187
+ # WHICH harness it is addressing. Installing into a directory chosen by that guess is how
188
+ # an operator ends up with a unit no live omp reads.
189
+ # Each variable is tested ALONE — the sandbox exports a poisoned PI_CODING_AGENT_DIR
190
+ # globally, and leaving it set would make every row below refuse on that one branch and
191
+ # prove nothing about the others.
192
+ for var in PI_CODING_AGENT_DIR PI_CONFIG_DIR; do
193
+ if env -u ENTWURF_OMP_AGENT_DIR -u PI_CODING_AGENT_DIR -u PI_CONFIG_DIR "$var=$SB/ambiguous" \
194
+ "$RUN" install-omp-bridge >/dev/null 2>&1; then
195
+ die "install guessed an agent dir while $var was set"
196
+ fi
197
+ ok "$var set (with no explicit override) REFUSES rather than guessing which harness it addresses"
198
+ done
199
+ if env -u ENTWURF_OMP_AGENT_DIR -u PI_CODING_AGENT_DIR PI_PROFILE=work "$RUN" install-omp-bridge >/dev/null 2>&1; then
200
+ die "install guessed an agent dir from PI_PROFILE alone"
201
+ fi
202
+ ok "PI_PROFILE without OMP_PROFILE REFUSES — pi and omp both read it"
203
+
204
+ # ── 7. --assemble-only never touches the live assembly ──────────────────────
205
+ if ENTWURF_OMP_ASM="$ASM" "$RUN" install-omp-bridge --assemble-only >/dev/null 2>&1; then
206
+ die "--assemble-only rebuilt the DEFAULT live assembly"
207
+ fi
208
+ ok "--assemble-only refuses the live assembly path (it writes no ownership state)"
209
+
210
+ # ── 8. nothing resolved through the double-duty PI knob ─────────────────────
211
+ # The whole run had PI_CODING_AGENT_DIR pointing at a poison path. After #87 B1 that
212
+ # variable is the VENDOR's agent dir for backend omp and is never a garden root, so a
213
+ # single artifact under it would mean some surface still derives its roots from it.
214
+ want "the poisoned PI_CODING_AGENT_DIR tree was never created" "[ ! -e '$PI_POISON' ]"
215
+
216
+ # ── 9. the repo itself was never written ────────────────────────────────────
217
+ REPO_AFTER="$(cd "$REPO_DIR" && git status --porcelain)"
218
+ [ "$REPO_BEFORE" = "$REPO_AFTER" ] || die "the smoke mutated the repo working tree"
219
+ ok "the checkout is byte-identical to before the smoke"
220
+
221
+ printf '[smoke-omp-bridge-state] %d assertions ok\n' "$pass"