@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.
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +299 -0
- package/DELIVERY.md +4 -3
- package/README.md +99 -67
- package/VERIFY.md +13 -7
- package/docs/acp-backend-rail.md +1 -1
- package/docs/external-mcp-host.md +147 -9
- package/docs/setup-clean-host.md +221 -16
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +65 -20
- package/mcp/entwurf-bridge/dist/pi-extensions/entwurf-capabilities.json +1 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +17 -6
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +1 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +172 -5
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +152 -17
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/omp-fresh-preflight.js +271 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-omp.js +988 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-receive-omp.js +574 -0
- package/mcp/entwurf-bridge/dist/scripts/omp-receive-facts.js +84 -0
- package/mcp/entwurf-bridge/src/index.ts +65 -19
- package/mcp/entwurf-bridge/tsconfig.build.json +19 -3
- package/mcp/tsconfig.json +10 -0
- package/package.json +14 -4
- package/pi/entwurf-capabilities.json +1 -0
- package/pi/meta-bridge-omp/entwurf-meta-omp/package.json +7 -0
- package/pi/omp-receive/entwurf-receive-omp/package.json +7 -0
- package/pi-extensions/entwurf-control.ts +12 -9
- package/pi-extensions/lib/entwurf-self-address.ts +18 -7
- package/pi-extensions/lib/meta-sender-identity.ts +1 -1
- package/pi-extensions/lib/meta-session.ts +219 -5
- package/pi-extensions/lib/mux-fresh-call.ts +171 -17
- package/pi-extensions/lib/omp-fresh-preflight.ts +275 -0
- package/pi-extensions/meta-bridge-omp.ts +1244 -0
- package/pi-extensions/meta-bridge-receive-omp.ts +666 -0
- package/run.sh +1041 -174
- package/scripts/agy-bridge.sh +4 -2
- package/scripts/check-copilot-birth-hook.ts +700 -23
- package/scripts/check-entwurf-self-address.ts +31 -0
- package/scripts/check-fresh-cut-gate.sh +12 -4
- package/scripts/check-gate-qualification.ts +8 -2
- package/scripts/check-harness-admission-parity.ts +143 -0
- package/scripts/check-meta-doctor-oracle.sh +20 -0
- package/scripts/check-omp-birth-hook.ts +1049 -0
- package/scripts/check-omp-fresh-preflight.ts +181 -0
- package/scripts/check-omp-receive-arm.ts +516 -0
- package/scripts/check-setup-qualification.sh +126 -0
- package/scripts/copilot-bridge-doctor.sh +104 -71
- package/scripts/copilot-bridge-install.sh +180 -20
- package/scripts/copilot-bridge-oracle.sh +223 -0
- package/scripts/copilot-bridge-uninstall.sh +137 -0
- package/scripts/dev-bin.sh +50 -9
- package/scripts/fake-copilot-vendor.sh +67 -0
- package/scripts/inventory-verification-surface.ts +1 -1
- package/scripts/meta-bridge-hook-log.sh +9 -1
- package/scripts/mutants/copilot-birth.json +96 -5
- package/scripts/mutants/mux-fresh-call.json +22 -22
- package/scripts/mutants/omp-birth.json +173 -0
- package/scripts/mutants/omp-fresh.json +300 -0
- package/scripts/mutants/omp-receive.json +135 -0
- package/scripts/mutants/pi-package-ownership.json +92 -0
- package/scripts/mutants/self-address.json +34 -0
- package/scripts/mutants/setup-verdict.json +148 -0
- package/scripts/mutants/source-install.json +32 -0
- package/scripts/omp-bridge-doctor.sh +315 -0
- package/scripts/omp-bridge-install.sh +221 -0
- package/scripts/omp-bridge-oracle.sh +154 -0
- package/scripts/omp-bridge-uninstall.sh +57 -0
- package/scripts/omp-mcp-bridge.sh +320 -0
- package/scripts/omp-mcp-config.py +392 -0
- package/scripts/omp-receive-doctor.sh +246 -0
- package/scripts/omp-receive-facts.ts +106 -0
- package/scripts/omp-receive-install.sh +228 -0
- package/scripts/omp-receive-uninstall.sh +60 -0
- package/scripts/omp-tool-surface.py +349 -0
- package/scripts/pi_settings_io.py +22 -0
- package/scripts/raw-omp-measure/README.md +420 -0
- package/scripts/raw-omp-measure/probe-extension.ts +76 -0
- package/scripts/raw-omp-measure/probe-receive-surface.ts +250 -0
- package/scripts/raw-omp-measure/source-audit.md +414 -0
- package/scripts/register-pi-package.py +525 -7
- package/scripts/register-pi-provider.py +162 -12
- package/scripts/smoke-agy-install-state.sh +86 -30
- package/scripts/smoke-agy-statusline-state.sh +9 -6
- package/scripts/smoke-omp-bridge-state.sh +221 -0
- package/scripts/smoke-omp-fresh-live.ts +497 -0
- package/scripts/smoke-omp-mcp-state.sh +327 -0
- package/scripts/smoke-omp-receive-live.ts +340 -0
- package/scripts/smoke-omp-receive-state.sh +196 -0
- package/scripts/smoke-setup-verdict.sh +291 -0
- package/scripts/smoke-user-scope-citizen.sh +388 -1
- package/scripts/tsconfig.json +2 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# smoke-omp-mcp-state — hermetic install/doctor/inverse contract for the OMP-native MCP
|
|
3
|
+
# adapter (#87 step 5). No omp process, no model turn, no writes outside the sandbox.
|
|
4
|
+
#
|
|
5
|
+
# The cell this file exists for, above the usual four install properties, is SHADOWING:
|
|
6
|
+
# the entry is only worth writing if it suppresses the Claude import, and it only does
|
|
7
|
+
# that while its key is byte-identical to the import's. So the key is asserted as a
|
|
8
|
+
# literal here, and the denylist that would kill both entries is asserted to be refused.
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
12
|
+
RUN="$REPO_DIR/run.sh"
|
|
13
|
+
pass=0
|
|
14
|
+
ok() { printf ' ok %s\n' "$1"; pass=$((pass + 1)); }
|
|
15
|
+
die() { printf 'FAIL: %s\n' "$1" >&2; exit 1; }
|
|
16
|
+
want() { eval "$2" && ok "$1" || die "$1"; }
|
|
17
|
+
|
|
18
|
+
REPO_BEFORE="$(cd "$REPO_DIR" && git status --porcelain)"
|
|
19
|
+
SB="$(mktemp -d)"
|
|
20
|
+
trap 'rm -rf "$SB"' EXIT
|
|
21
|
+
# HARD RULE 12, in full — see the same block in smoke-omp-bridge-state.sh. PI is poisoned
|
|
22
|
+
# on purpose and asserted empty at the end: after #87 B1 no OMP surface derives a garden
|
|
23
|
+
# root from it. The MCP TARGET is no longer configurable (#87 D1), so the only sandbox seam
|
|
24
|
+
# left is the vendor agent dir — which is the correct one, since the target is
|
|
25
|
+
# `<agent dir>/mcp.json` by construction.
|
|
26
|
+
export HOME="$SB/home"
|
|
27
|
+
export XDG_DATA_HOME="$SB/xdg"
|
|
28
|
+
export XDG_CONFIG_HOME="$SB/xdg-config"
|
|
29
|
+
export XDG_STATE_HOME="$SB/xdg-state"
|
|
30
|
+
export XDG_CACHE_HOME="$SB/xdg-cache"
|
|
31
|
+
export XDG_RUNTIME_DIR="$SB/xdg-runtime"
|
|
32
|
+
PI_POISON="$SB/pi-poison-agent"
|
|
33
|
+
export PI_CODING_AGENT_DIR="$PI_POISON"
|
|
34
|
+
export ENTWURF_OMP_AGENT_DIR="$SB/home/.omp/agent"
|
|
35
|
+
export ENTWURF_OMP_MCP_COMMAND="entwurf-bridge"
|
|
36
|
+
export ENTWURF_OMP_MCP_ARGS='[]'
|
|
37
|
+
CONFIG="$ENTWURF_OMP_AGENT_DIR/mcp.json"
|
|
38
|
+
STATE="$XDG_DATA_HOME/entwurf/omp-mcp/install-state.json"
|
|
39
|
+
mkdir -p "$ENTWURF_OMP_AGENT_DIR" "$SB/bin" "$XDG_CONFIG_HOME" "$XDG_STATE_HOME" "$XDG_CACHE_HOME" "$XDG_RUNTIME_DIR"
|
|
40
|
+
# Sandbox-only operator setting. The MCP-install cells expect doctor green; the
|
|
41
|
+
# default (file/key absent → tools.xdev true) is a RUNTIME red once the native
|
|
42
|
+
# hand is configured, and is exercised as its own cell below. Never the host's
|
|
43
|
+
# real ~/.omp/agent/config.yml — HOME and ENTWURF_OMP_AGENT_DIR are sandboxed.
|
|
44
|
+
cat > "$ENTWURF_OMP_AGENT_DIR/config.yml" <<'CFG'
|
|
45
|
+
tools:
|
|
46
|
+
xdev: false
|
|
47
|
+
CFG
|
|
48
|
+
|
|
49
|
+
# A fake bridge that answers initialize + tools/list, so the doctor's boot probe has a
|
|
50
|
+
# real command to drive without spawning the actual bridge.
|
|
51
|
+
cat > "$SB/bin/entwurf-bridge" <<'FAKE'
|
|
52
|
+
#!/usr/bin/env bash
|
|
53
|
+
while IFS= read -r line; do
|
|
54
|
+
case "$line" in
|
|
55
|
+
*'"id":1'*) printf '%s\n' '{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{},"serverInfo":{"name":"fake-entwurf-bridge","version":"0"}}}' ;;
|
|
56
|
+
*'"id":2'*) printf '%s\n' '{"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"entwurf_v2"},{"name":"entwurf_self"},{"name":"entwurf_peers"},{"name":"entwurf_inbox_read"},{"name":"entwurf_register_native"},{"name":"entwurf_fresh_call"},{"name":"entwurf_resume_call"}]}}' ;;
|
|
57
|
+
esac
|
|
58
|
+
done
|
|
59
|
+
FAKE
|
|
60
|
+
chmod +x "$SB/bin/entwurf-bridge"
|
|
61
|
+
_clean_path=""
|
|
62
|
+
while IFS= read -r dir; do
|
|
63
|
+
[ -n "$dir" ] || continue
|
|
64
|
+
{ [ -e "$dir/entwurf-bridge" ] || [ -L "$dir/entwurf-bridge" ]; } && continue
|
|
65
|
+
_clean_path="${_clean_path:+$_clean_path:}$dir"
|
|
66
|
+
done < <(printf '%s\n' "$PATH" | tr ':' '\n')
|
|
67
|
+
export PATH="$SB/bin:$_clean_path"
|
|
68
|
+
|
|
69
|
+
json() { python3 - "$CONFIG" "$@" <<'PY'
|
|
70
|
+
import json, sys
|
|
71
|
+
data = json.load(open(sys.argv[1]))
|
|
72
|
+
mode = sys.argv[2]
|
|
73
|
+
servers = data.get("mcpServers", {})
|
|
74
|
+
if mode == "keys":
|
|
75
|
+
print(" ".join(sorted(servers)))
|
|
76
|
+
elif mode == "entry":
|
|
77
|
+
print(json.dumps(servers.get("entwurf-bridge"), sort_keys=True))
|
|
78
|
+
elif mode == "top":
|
|
79
|
+
print(" ".join(sorted(data)))
|
|
80
|
+
PY
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# ── 1. create-new install ───────────────────────────────────────────────────
|
|
84
|
+
"$RUN" install-omp-mcp >/dev/null || die "install-omp-mcp failed on a clean host"
|
|
85
|
+
want "the omp-native user MCP file was created where the vendor reads it" "[ -f '$CONFIG' ]"
|
|
86
|
+
want "it carries the PINNED literal server key (byte-identical to the Claude import's)" "[ \"\$(json keys)\" = 'entwurf-bridge' ]"
|
|
87
|
+
want "the entry carries the omp provenance label, not Claude's" "json entry | grep -q 'external-mcp/omp'"
|
|
88
|
+
want "it does NOT carry Claude Code's label" "! json entry | grep -q 'external-mcp/claude-code'"
|
|
89
|
+
want "the file names omp's own schema so the operator's editor can validate it" "json top | grep -q '\\\$schema'"
|
|
90
|
+
want "no disabledServers denylist was written — that would kill the import AND this entry" "! grep -q disabledServers '$CONFIG'"
|
|
91
|
+
# CAPTURE, then match — never `cmd | grep -q`. grep exits at the first match and closes the
|
|
92
|
+
# pipe, the still-writing doctor dies of SIGPIPE, and `pipefail` reports that as a failed
|
|
93
|
+
# check: a FALSE red on a correctly configured host (the same race meta-bridge-install.sh
|
|
94
|
+
# documents at its `claude mcp get` probe).
|
|
95
|
+
OUT="$("$RUN" doctor-omp-mcp 2>&1)" || die "doctor red right after a clean install"
|
|
96
|
+
ok "doctor is green right after install"
|
|
97
|
+
printf '%s\n' "$OUT" | grep -q "native-wins" || die "doctor did not report the native entry as the effective source"
|
|
98
|
+
ok "doctor reports the EFFECTIVE source as the native entry"
|
|
99
|
+
printf '%s\n' "$OUT" | grep -q "tools.xdev is false" || die "doctor did not report tools.xdev false on the runtime axis"
|
|
100
|
+
ok "xdev false is ok on the runtime axis (MCP tools stay top-level)"
|
|
101
|
+
|
|
102
|
+
# ── 2. shadowing: a Claude import of the same name is suppressed, not removed ───
|
|
103
|
+
mkdir -p "$HOME"
|
|
104
|
+
cat > "$HOME/.claude.json" <<'IMPORT'
|
|
105
|
+
{ "mcpServers": { "entwurf-bridge": { "command": "bash", "args": ["/somewhere/start.sh"], "env": { "ENTWURF_BRIDGE_EXTERNAL_AGENT_ID": "external-mcp/claude-code" } } } }
|
|
106
|
+
IMPORT
|
|
107
|
+
OUT="$("$RUN" doctor-omp-mcp 2>&1)" || die "doctor red with a Claude import present"
|
|
108
|
+
printf '%s\n' "$OUT" | grep -q "key-present" || die "doctor did not see the Claude import's key"
|
|
109
|
+
printf '%s\n' "$OUT" | grep -q "native-wins" || die "doctor did not report native precedence over the import"
|
|
110
|
+
ok "with BOTH sources present the doctor reports native-wins — the import is shadowed by the shared key"
|
|
111
|
+
want "the Claude config was never touched (the vendor never writes another tool's config, and neither do we)" "grep -q 'external-mcp/claude-code' '$HOME/.claude.json'"
|
|
112
|
+
|
|
113
|
+
# ── 3. a denylist on our key is refused, and named for what it does ─────────
|
|
114
|
+
python3 - "$CONFIG" <<'PY'
|
|
115
|
+
import json, sys
|
|
116
|
+
data = json.load(open(sys.argv[1]))
|
|
117
|
+
data["disabledServers"] = ["entwurf-bridge"]
|
|
118
|
+
json.dump(data, open(sys.argv[1], "w"), indent=2)
|
|
119
|
+
PY
|
|
120
|
+
if OUT="$("$RUN" doctor-omp-mcp 2>&1)"; then
|
|
121
|
+
die "doctor stayed green with entwurf-bridge denylisted"
|
|
122
|
+
fi
|
|
123
|
+
printf '%s\n' "$OUT" | grep -q "kills the native entry AND the Claude import" || die "doctor went red without naming what the denylist actually does"
|
|
124
|
+
ok "a disabledServers denylist on our key is RED, and the doctor names that it kills both entries"
|
|
125
|
+
if OUT="$("$RUN" install-omp-mcp 2>&1)"; then
|
|
126
|
+
die "install wrote an entry into a config that denylists it"
|
|
127
|
+
fi
|
|
128
|
+
printf '%s\n' "$OUT" | grep -q "never the way to hide an import" || die "install refused without naming the reason"
|
|
129
|
+
ok "install REFUSES rather than writing a server the denylist would suppress"
|
|
130
|
+
python3 - "$CONFIG" <<'PY'
|
|
131
|
+
import json, sys
|
|
132
|
+
data = json.load(open(sys.argv[1]))
|
|
133
|
+
data.pop("disabledServers")
|
|
134
|
+
json.dump(data, open(sys.argv[1], "w"), indent=2)
|
|
135
|
+
PY
|
|
136
|
+
|
|
137
|
+
# ── 4. foreign provenance is red even with no ownership state ───────────────
|
|
138
|
+
cp "$STATE" "$SB/state.bak"
|
|
139
|
+
rm -f "$STATE"
|
|
140
|
+
python3 - "$CONFIG" <<'PY'
|
|
141
|
+
import json, sys
|
|
142
|
+
data = json.load(open(sys.argv[1]))
|
|
143
|
+
data["mcpServers"]["entwurf-bridge"]["env"]["ENTWURF_BRIDGE_EXTERNAL_AGENT_ID"] = "external-mcp/claude-code"
|
|
144
|
+
json.dump(data, open(sys.argv[1], "w"), indent=2)
|
|
145
|
+
PY
|
|
146
|
+
if "$RUN" doctor-omp-mcp >/dev/null 2>&1; then
|
|
147
|
+
die "doctor stayed green with a native entry carrying another harness's provenance"
|
|
148
|
+
fi
|
|
149
|
+
ok "an entry under our key that speaks as another harness is RED even with no install-state"
|
|
150
|
+
cp "$SB/state.bak" "$STATE"
|
|
151
|
+
"$RUN" install-omp-mcp >/dev/null || die "reinstall over the drifted entry failed"
|
|
152
|
+
"$RUN" doctor-omp-mcp >/dev/null || die "reinstall did not repair the provenance"
|
|
153
|
+
ok "reinstall repairs it"
|
|
154
|
+
|
|
155
|
+
# ── 5. the inverse ─────────────────────────────────────────────────────────
|
|
156
|
+
"$RUN" uninstall-omp-mcp >/dev/null || die "uninstall failed"
|
|
157
|
+
want "a file we CREATED is removed entirely, not left as an empty stub" "[ ! -e '$CONFIG' ]"
|
|
158
|
+
want "the ownership state is gone" "[ ! -e '$STATE' ]"
|
|
159
|
+
OUT="$("$RUN" doctor-omp-mcp 2>&1)" || die "doctor red on a clean uninstalled host"
|
|
160
|
+
printf '%s\n' "$OUT" | grep -q "CLAUDE IMPORT is currently the only source" || die "doctor did not name the import as the effective source after the inverse"
|
|
161
|
+
ok "after the inverse the Claude import is named as the effective source again — the honest state, not silence"
|
|
162
|
+
|
|
163
|
+
# ── 6. adopt an EXISTING operator file, and hand it back untouched ──────────
|
|
164
|
+
cat > "$CONFIG" <<'PRE'
|
|
165
|
+
{
|
|
166
|
+
"mcpServers": {
|
|
167
|
+
"someone-elses": { "command": "keep-me", "args": [] },
|
|
168
|
+
"entwurf-bridge": { "command": "operator-wired", "args": ["--by-hand"] }
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
PRE
|
|
172
|
+
"$RUN" install-omp-mcp >/dev/null || die "install failed to adopt an existing regular file"
|
|
173
|
+
want "our entry replaced the operator's under the same key" "json entry | grep -q 'external-mcp/omp'"
|
|
174
|
+
want "the operator's OTHER server is untouched" "json keys | grep -q 'someone-elses'"
|
|
175
|
+
want "the preimage was recorded even though a value already existed there" "grep -q 'operator-wired' '$STATE'"
|
|
176
|
+
"$RUN" uninstall-omp-mcp >/dev/null || die "uninstall failed on an adopted file"
|
|
177
|
+
want "the inverse restored the operator's ORIGINAL entry byte-for-byte" "json entry | grep -q 'operator-wired'"
|
|
178
|
+
want "and left their other server alone" "json keys | grep -q 'someone-elses'"
|
|
179
|
+
want "the adopted file itself survives — we never created it" "[ -f '$CONFIG' ]"
|
|
180
|
+
ok "adopt/restore is an honest inverse on a pre-existing operator file"
|
|
181
|
+
|
|
182
|
+
# ── 7. a symlinked config is refused, never written through ────────────────
|
|
183
|
+
rm -f "$CONFIG"
|
|
184
|
+
echo '{ "mcpServers": {} }' > "$SB/elsewhere.json"
|
|
185
|
+
ln -s "$SB/elsewhere.json" "$CONFIG"
|
|
186
|
+
if "$RUN" install-omp-mcp >/dev/null 2>&1; then
|
|
187
|
+
die "install wrote through a symlinked config"
|
|
188
|
+
fi
|
|
189
|
+
want "the symlink target is unchanged" "! grep -q entwurf-bridge '$SB/elsewhere.json'"
|
|
190
|
+
ok "a SYMLINKED config is refused (someone else's SSOT)"
|
|
191
|
+
rm -f "$CONFIG"
|
|
192
|
+
|
|
193
|
+
# ── 8. an ambiguous agent dir refuses instead of guessing (ledger M6) ──────
|
|
194
|
+
if env -u ENTWURF_OMP_AGENT_DIR PI_CODING_AGENT_DIR="$SB/ambiguous" "$RUN" install-omp-mcp >/dev/null 2>&1; then
|
|
195
|
+
die "install guessed an agent dir while PI_CODING_AGENT_DIR was set"
|
|
196
|
+
fi
|
|
197
|
+
ok "an inherited PI_CODING_AGENT_DIR REFUSES rather than writing a config omp may never read"
|
|
198
|
+
|
|
199
|
+
# ── 8b. the target is CONFINED to the resolved agent dir (#87 D1) ──────────
|
|
200
|
+
# There is no path override any more. The writer's target is `<agent dir>/mcp.json` and
|
|
201
|
+
# nothing else, so an operator file elsewhere cannot be aimed at: the retired
|
|
202
|
+
# `ENTWURF_OMP_MCP_CONFIG` accepted an arbitrary path with no descendant check, which made
|
|
203
|
+
# the "omp-only" writer able to rewrite ~/.claude.json or ~/.pi/... An explicit env seam
|
|
204
|
+
# lowers the odds of an accident; it grants no ownership.
|
|
205
|
+
env ENTWURF_OMP_MCP_CONFIG="$SB/hijack.json" "$RUN" install-omp-mcp >/dev/null 2>&1 || true
|
|
206
|
+
want "the retired override wrote NOTHING at its arbitrary path" "[ ! -e '$SB/hijack.json' ]"
|
|
207
|
+
want "the entry went to the agent-dir target instead" "[ -f '$CONFIG' ]"
|
|
208
|
+
ok "the target follows the resolved agent dir; no env seam can aim the writer elsewhere"
|
|
209
|
+
"$RUN" uninstall-omp-mcp >/dev/null || die "uninstall failed after the confinement cell"
|
|
210
|
+
|
|
211
|
+
# ── 8c. one state owns ONE target: a retarget REFUSES (#87 D1) ────────────
|
|
212
|
+
# Changing OMP_PROFILE / the agent dir used to capture a new preimage and overwrite the one
|
|
213
|
+
# state file, stranding the first profile's managed entry with no inverse.
|
|
214
|
+
"$RUN" install-omp-mcp >/dev/null || die "install failed before the retarget cell"
|
|
215
|
+
STATE_BEFORE="$(cat "$STATE")"
|
|
216
|
+
mkdir -p "$SB/home/.omp/profiles/other/agent"
|
|
217
|
+
if env ENTWURF_OMP_AGENT_DIR="$SB/home/.omp/profiles/other/agent" "$RUN" install-omp-mcp >/dev/null 2>&1; then
|
|
218
|
+
die "install retargeted to a second config while state named the first"
|
|
219
|
+
fi
|
|
220
|
+
want "the first target's state is byte-identical after the refusal" "[ \"\$(cat '$STATE')\" = \"\$STATE_BEFORE\" ]"
|
|
221
|
+
want "no config was written at the second target" "[ ! -e '$SB/home/.omp/profiles/other/agent/mcp.json' ]"
|
|
222
|
+
ok "a retarget REFUSES instead of orphaning the first managed entry"
|
|
223
|
+
"$RUN" uninstall-omp-mcp >/dev/null || die "uninstall failed after the retarget cell"
|
|
224
|
+
|
|
225
|
+
# ── 8d. an INVALID entry is runtime-red with NO ownership state (#87 B4) ───
|
|
226
|
+
# Runtime truth and ownership truth are separate axes (Hard Rule 13). A malformed value
|
|
227
|
+
# under our key still claims the dedupe slot — so the Claude import is suppressed AND
|
|
228
|
+
# nothing loads — and the doctor used to print `native-wins` + exit 0 for exactly that,
|
|
229
|
+
# because redness had been coupled to the presence of install-state.
|
|
230
|
+
python3 - "$CONFIG" <<'PY2'
|
|
231
|
+
import json, sys
|
|
232
|
+
json.dump({"mcpServers": {"entwurf-bridge": None}}, open(sys.argv[1], "w"), indent=2)
|
|
233
|
+
PY2
|
|
234
|
+
if OUT="$("$RUN" doctor-omp-mcp 2>&1)"; then
|
|
235
|
+
die "doctor exited 0 for a malformed native entry with no ownership state"
|
|
236
|
+
fi
|
|
237
|
+
printf '%s\n' "$OUT" | grep -q "native-invalid" || die "doctor did not name the entry as native-invalid"
|
|
238
|
+
if printf '%s\n' "$OUT" | grep -q "native-wins"; then
|
|
239
|
+
die "doctor still called a malformed entry native-wins"
|
|
240
|
+
fi
|
|
241
|
+
ok "a malformed entry under our key is RED on the runtime axis with zero install-state, and is never native-wins"
|
|
242
|
+
rm -f "$CONFIG"
|
|
243
|
+
|
|
244
|
+
# ── 8e. tools.xdev tool-surface — RUNTIME axis, never ownership (Hard Rule 13)
|
|
245
|
+
# The native hand is re-installed so redness is about the tool surface, not a
|
|
246
|
+
# missing mcp.json. Every write is inside the sandbox agent dir.
|
|
247
|
+
"$RUN" install-omp-mcp >/dev/null || die "reinstall failed before the tool-surface cells"
|
|
248
|
+
cat > "$ENTWURF_OMP_AGENT_DIR/config.yml" <<'CFG'
|
|
249
|
+
tools:
|
|
250
|
+
xdev: false
|
|
251
|
+
CFG
|
|
252
|
+
OUT="$("$RUN" doctor-omp-mcp 2>&1)" || die "doctor red with tools.xdev false"
|
|
253
|
+
printf '%s\n' "$OUT" | grep -q "tools.xdev is false" || die "doctor did not name tools.xdev false"
|
|
254
|
+
ok "xdev false is ok (required operator setting)"
|
|
255
|
+
|
|
256
|
+
cat > "$ENTWURF_OMP_AGENT_DIR/config.yml" <<'CFG'
|
|
257
|
+
tools:
|
|
258
|
+
xdev: true
|
|
259
|
+
xdevInlineDevices:
|
|
260
|
+
- mcp__entwurf_bridge_*
|
|
261
|
+
CFG
|
|
262
|
+
OUT="$("$RUN" doctor-omp-mcp 2>&1)" || die "doctor red with a covering xdevInlineDevices glob"
|
|
263
|
+
printf '%s\n' "$OUT" | grep -q "xdevInlineDevices glob covering mcp__entwurf_bridge_" || die "doctor did not note the covering glob"
|
|
264
|
+
if printf '%s\n' "$OUT" | grep -q "doctor found a broken OMP MCP configuration"; then
|
|
265
|
+
die "covering glob should be ok-with-note, not red"
|
|
266
|
+
fi
|
|
267
|
+
ok "xdev on with a covering glob is ok-with-note"
|
|
268
|
+
|
|
269
|
+
cat > "$ENTWURF_OMP_AGENT_DIR/config.yml" <<'CFG'
|
|
270
|
+
tools:
|
|
271
|
+
xdev: true
|
|
272
|
+
CFG
|
|
273
|
+
if OUT="$("$RUN" doctor-omp-mcp 2>&1)"; then
|
|
274
|
+
die "doctor stayed green with tools.xdev true and no covering glob"
|
|
275
|
+
fi
|
|
276
|
+
printf '%s\n' "$OUT" | grep -q "no xdevInlineDevices glob covering" || die "doctor went red without naming the uncovered xdev surface"
|
|
277
|
+
printf '%s\n' "$OUT" | grep -q "runtime axis" || die "uncovered xdev was not reported on the runtime axis"
|
|
278
|
+
ok "xdev on with no covering glob is RED on the runtime axis"
|
|
279
|
+
|
|
280
|
+
cat > "$ENTWURF_OMP_AGENT_DIR/config.yml" <<'CFG'
|
|
281
|
+
tools:
|
|
282
|
+
xdev: true
|
|
283
|
+
xdevInlineDevices:
|
|
284
|
+
- mcp__context_mode_*
|
|
285
|
+
CFG
|
|
286
|
+
if OUT="$("$RUN" doctor-omp-mcp 2>&1)"; then
|
|
287
|
+
die "doctor stayed green with a glob that does not cover our server"
|
|
288
|
+
fi
|
|
289
|
+
printf '%s\n' "$OUT" | grep -q "no xdevInlineDevices glob covering" || die "a non-covering glob was not treated as uncovered"
|
|
290
|
+
ok "a glob that does not cover mcp__entwurf_bridge_* is RED"
|
|
291
|
+
|
|
292
|
+
cat > "$ENTWURF_OMP_AGENT_DIR/config.yml" <<'CFG'
|
|
293
|
+
modelRoles:
|
|
294
|
+
default: sandbox-only
|
|
295
|
+
CFG
|
|
296
|
+
if OUT="$("$RUN" doctor-omp-mcp 2>&1)"; then
|
|
297
|
+
die "doctor stayed green when tools.xdev was unset"
|
|
298
|
+
fi
|
|
299
|
+
printf '%s\n' "$OUT" | grep -q "tools.xdev is UNSET" || die "doctor did not name the absent key"
|
|
300
|
+
printf '%s\n' "$OUT" | grep -q "vendor default applies" || die "absent key was not reported as the vendor default"
|
|
301
|
+
ok "absent key applies the vendor default and is RED; the file is named, not invented"
|
|
302
|
+
|
|
303
|
+
rm -f "$ENTWURF_OMP_AGENT_DIR/config.yml"
|
|
304
|
+
if OUT="$("$RUN" doctor-omp-mcp 2>&1)"; then
|
|
305
|
+
die "doctor stayed green when config.yml was absent (vendor default)"
|
|
306
|
+
fi
|
|
307
|
+
printf '%s\n' "$OUT" | grep -q "FILE ABSENT" || die "doctor did not say the file is absent"
|
|
308
|
+
printf '%s\n' "$OUT" | grep -q "vendor default applies" || die "absent file was not reported as the vendor default"
|
|
309
|
+
want "doctor did not write config.yml while reporting the absent default" "[ ! -e '$ENTWURF_OMP_AGENT_DIR/config.yml' ]"
|
|
310
|
+
ok "absent file applies the vendor default and is RED; doctor writes nothing"
|
|
311
|
+
|
|
312
|
+
# restore the required setting so later cells (none) and uninstall stay honest
|
|
313
|
+
cat > "$ENTWURF_OMP_AGENT_DIR/config.yml" <<'CFG'
|
|
314
|
+
tools:
|
|
315
|
+
xdev: false
|
|
316
|
+
CFG
|
|
317
|
+
"$RUN" uninstall-omp-mcp >/dev/null || die "uninstall failed after the tool-surface cells"
|
|
318
|
+
|
|
319
|
+
# ── 9. nothing resolved through the double-duty PI knob ───────────────────
|
|
320
|
+
want "the poisoned PI_CODING_AGENT_DIR tree was never created" "[ ! -e '$PI_POISON' ]"
|
|
321
|
+
|
|
322
|
+
# ── 10. the repo itself was never written ─────────────────────────────────
|
|
323
|
+
REPO_AFTER="$(cd "$REPO_DIR" && git status --porcelain)"
|
|
324
|
+
[ "$REPO_BEFORE" = "$REPO_AFTER" ] || die "the smoke mutated the repo working tree"
|
|
325
|
+
ok "the checkout is byte-identical to before the smoke"
|
|
326
|
+
|
|
327
|
+
printf '[smoke-omp-mcp-state] %d assertions ok\n' "$pass"
|