@soleur/opencode 3.354.7 → 3.354.8
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/package.json
CHANGED
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
"""One proxy session for the suite (#7980). stdlib only.
|
|
3
3
|
|
|
4
4
|
proxy-session-driver.py --out <dir> --proxy <proxy.py> --server <argv...>
|
|
5
|
-
[--proxy-arg <arg>]... [--env K=V]... [--send <json-line>]... [--end eof|sigterm|sigkill|killchild|none] [--timeout S]
|
|
5
|
+
[--proxy-arg <arg>]... [--env K=V]... [--send <json-line>]... [--end eof|sigterm|sigkill|killchild|none] [--timeout S] [--expect-death]
|
|
6
6
|
|
|
7
7
|
Launches `python3 <proxy.py> <proxy-arg...> -- <server argv...>` in a NEW SESSION (so the
|
|
8
8
|
proxy's own pid is the group we assert on for a SIGKILLed proxy), writes each
|
|
9
9
|
--send line, reads until every sent request id has a reply or the timeout
|
|
10
|
-
lapses, then ends the session per --end and waits.
|
|
10
|
+
lapses, then ends the session per --end and waits. With --expect-death the proxy is
|
|
11
|
+
expected to die at startup: the reply-wait phase is skipped (a stalled startup must
|
|
12
|
+
not burn a deadline window waiting for a reply that never comes) and the post-`--end`
|
|
13
|
+
wait is bounded by EXPECT_DEATH_TIMEOUT_S, so a slow-but-correct death records its real
|
|
14
|
+
exit code instead of "TIMEOUT". Under --expect-death, --timeout still applies to the
|
|
15
|
+
group_after poll but is inert for the death wait. Writes into <out>:
|
|
11
16
|
stdout.bin every byte the proxy wrote responses.json parsed objects
|
|
12
17
|
stderr.txt proxy + server stderr rc proxy exit code
|
|
13
18
|
child_pgid the pgid the proxy logged (or "")
|
|
@@ -28,8 +33,11 @@ import time
|
|
|
28
33
|
from pathlib import Path
|
|
29
34
|
|
|
30
35
|
|
|
36
|
+
EXPECT_DEATH_TIMEOUT_S = 30
|
|
37
|
+
|
|
38
|
+
|
|
31
39
|
def parse(argv):
|
|
32
|
-
o = {"env": {}, "send": [], "end": "eof", "timeout": 8.0, "out": None, "proxy": None, "proxy_args": [], "server": []}
|
|
40
|
+
o = {"env": {}, "send": [], "end": "eof", "timeout": 8.0, "out": None, "proxy": None, "proxy_args": [], "server": [], "expect_death": False}
|
|
33
41
|
i = 0
|
|
34
42
|
while i < len(argv):
|
|
35
43
|
a = argv[i]
|
|
@@ -40,6 +48,7 @@ def parse(argv):
|
|
|
40
48
|
elif a == "--send": o["send"].append(argv[i + 1]); i += 2
|
|
41
49
|
elif a == "--end": o["end"] = argv[i + 1]; i += 2
|
|
42
50
|
elif a == "--timeout": o["timeout"] = float(argv[i + 1]); i += 2
|
|
51
|
+
elif a == "--expect-death": o["expect_death"] = True; i += 1
|
|
43
52
|
elif a == "--server": o["server"] = argv[i + 1:]; break
|
|
44
53
|
else: sys.stderr.write(__doc__); sys.exit(2)
|
|
45
54
|
if not (o["out"] and o["proxy"] and o["server"]): sys.stderr.write(__doc__); sys.exit(2)
|
|
@@ -93,7 +102,7 @@ def main():
|
|
|
93
102
|
objs.append({"__unparsable__": line.decode("utf-8", "replace")})
|
|
94
103
|
return True
|
|
95
104
|
|
|
96
|
-
while want - got and time.monotonic() < deadline and p.stdout in [k.fileobj for k in sel.get_map().values()]:
|
|
105
|
+
while not o["expect_death"] and want - got and time.monotonic() < deadline and p.stdout in [k.fileobj for k in sel.get_map().values()]:
|
|
97
106
|
if pump(True) is None: break
|
|
98
107
|
while sel.get_map() and pump(False): pass
|
|
99
108
|
err.flush()
|
|
@@ -110,8 +119,10 @@ def main():
|
|
|
110
119
|
os.killpg(int(child_pgid), signal.SIGTERM)
|
|
111
120
|
elif o["end"] == "sigkill":
|
|
112
121
|
os.kill(p.pid, signal.SIGKILL)
|
|
113
|
-
# drain anything the proxy still says, then wait for it
|
|
114
|
-
|
|
122
|
+
# drain anything the proxy still says, then wait for it. An expect-death
|
|
123
|
+
# session is bounded by the death budget, not --timeout: a slow-but-correct
|
|
124
|
+
# startup death must record its real rc, never the deadline's TIMEOUT.
|
|
125
|
+
t_end = time.monotonic() + (EXPECT_DEATH_TIMEOUT_S if o["expect_death"] else o["timeout"])
|
|
115
126
|
while time.monotonic() < t_end:
|
|
116
127
|
if p.poll() is not None: break
|
|
117
128
|
with contextlib.suppress(Exception):
|
|
@@ -366,31 +366,31 @@ assert_true 'FR15: --user-data-dir=<XDG_CACHE_HOME>/<name> injected once, before
|
|
|
366
366
|
session argv-udd-home "$PROXY" "${UDD[@]}" --env "XDG_CACHE_HOME=" --env "HOME=$WORK/home" --env FAKE_PW_ARGV_OUT="$WORK/argv-udd-home" --send "$INIT" --end eof >/dev/null
|
|
367
367
|
assert_true 'FR15: XDG_CACHE_HOME empty → profile resolves under $HOME/.cache' bash -c 'test -f "$1" && grep -qxF -- "--user-data-dir=$2/.cache/soleur-test-profile" "$1"' _ "$WORK/argv-udd-home" "$WORK/home"
|
|
368
368
|
assert_true 'FR15: flag absent → child argv carries no --user-data-dir (unchanged behaviour)' bash -c 'test -f "$1" && ! grep -q -- "--user-data-dir" "$1"' _ "$WORK/argv-out"
|
|
369
|
-
r="$(session udd-dotdot "$PROXY" --proxy-arg --user-data-dir-name --proxy-arg '..' --send "$INIT" --end eof --
|
|
369
|
+
r="$(session udd-dotdot "$PROXY" --proxy-arg --user-data-dir-name --proxy-arg '..' --send "$INIT" --end eof --expect-death)"
|
|
370
370
|
assert_refused_start 'FR15: a .. basename refuses to start' "$r" '..'
|
|
371
|
-
r="$(session udd-sep "$PROXY" --proxy-arg --user-data-dir-name --proxy-arg 'a/b' --send "$INIT" --end eof --
|
|
371
|
+
r="$(session udd-sep "$PROXY" --proxy-arg --user-data-dir-name --proxy-arg 'a/b' --send "$INIT" --end eof --expect-death)"
|
|
372
372
|
assert_refused_start 'FR15: a basename containing / refuses to start' "$r" 'separator'
|
|
373
|
-
r="$(session udd-sep-bs "$PROXY" --proxy-arg --user-data-dir-name --proxy-arg 'a\b' --send "$INIT" --end eof --
|
|
373
|
+
r="$(session udd-sep-bs "$PROXY" --proxy-arg --user-data-dir-name --proxy-arg 'a\b' --send "$INIT" --end eof --expect-death)"
|
|
374
374
|
assert_refused_start 'FR15: a basename containing a backslash refuses to start' "$r" 'separator'
|
|
375
|
-
r="$(session udd-conflict "$PROXY" "${UDD[@]}" --send "$INIT" --end eof --
|
|
375
|
+
r="$(session udd-conflict "$PROXY" "${UDD[@]}" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --user-data-dir=/x)"
|
|
376
376
|
assert_refused_start 'FR15: the flag combined with an explicit --user-data-dir refuses to start' "$r" 'explicit'
|
|
377
|
-
r="$(session udd-relxdg "$PROXY" "${UDD[@]}" --env XDG_CACHE_HOME=relative/cache --send "$INIT" --end eof --
|
|
377
|
+
r="$(session udd-relxdg "$PROXY" "${UDD[@]}" --env XDG_CACHE_HOME=relative/cache --send "$INIT" --end eof --expect-death)"
|
|
378
378
|
assert_refused_start 'FR15: a relative XDG_CACHE_HOME refuses to start' "$r" 'absolute'
|
|
379
|
-
r="$(session udd-nohome "$PROXY" "${UDD[@]}" --env XDG_CACHE_HOME= --env HOME= --send "$INIT" --end eof --
|
|
379
|
+
r="$(session udd-nohome "$PROXY" "${UDD[@]}" --env XDG_CACHE_HOME= --env HOME= --send "$INIT" --end eof --expect-death)"
|
|
380
380
|
assert_refused_start 'FR15: XDG_CACHE_HOME and HOME both unset refuses to start' "$r" 'HOME is set'
|
|
381
|
-
r="$(session udd-missing "$PROXY" --proxy-arg --user-data-dir-name --send "$INIT" --end eof --
|
|
381
|
+
r="$(session udd-missing "$PROXY" --proxy-arg --user-data-dir-name --send "$INIT" --end eof --expect-death)"
|
|
382
382
|
assert_refused_start 'FR15: --user-data-dir-name with no argument refuses to start' "$r" 'basename argument'
|
|
383
|
-
r="$(session udd-unknown "$PROXY" --proxy-arg --bogus-flag --send "$INIT" --end eof --
|
|
383
|
+
r="$(session udd-unknown "$PROXY" --proxy-arg --bogus-flag --send "$INIT" --end eof --expect-death)"
|
|
384
384
|
assert_refused_start 'FR15: an unrecognised proxy flag refuses to start' "$r" 'unrecognised'
|
|
385
|
-
r="$(session udd-dup "$PROXY" --proxy-arg --user-data-dir-name --proxy-arg a --proxy-arg --user-data-dir-name=b --send "$INIT" --end eof --
|
|
385
|
+
r="$(session udd-dup "$PROXY" --proxy-arg --user-data-dir-name --proxy-arg a --proxy-arg --user-data-dir-name=b --send "$INIT" --end eof --expect-death)"
|
|
386
386
|
assert_refused_start 'FR15: the flag given twice refuses to start' "$r" 'twice'
|
|
387
|
-
r="$(session udd-dash "$PROXY" --proxy-arg --user-data-dir-name --proxy-arg '--bogus' --send "$INIT" --end eof --
|
|
387
|
+
r="$(session udd-dash "$PROXY" --proxy-arg --user-data-dir-name --proxy-arg '--bogus' --send "$INIT" --end eof --expect-death)"
|
|
388
388
|
assert_refused_start 'FR15: a basename beginning with - refuses to start' "$r" "leading '-'"
|
|
389
389
|
# the = spelling, and a root that only resolves after realpath normalisation
|
|
390
390
|
UDDEQ=(--proxy-arg --user-data-dir-name=eq-profile)
|
|
391
391
|
session argv-udd-eq "$PROXY" "${UDDEQ[@]}" --env "XDG_CACHE_HOME=$WORK/xdg" --env FAKE_PW_ARGV_OUT="$WORK/argv-udd-eq" --send "$INIT" --end eof >/dev/null
|
|
392
392
|
assert_true 'FR15: --user-data-dir-name=<name> injects the same profile dir' bash -c 'test -f "$1" && grep -qxF -- "--user-data-dir=$2/eq-profile" "$1"' _ "$WORK/argv-udd-eq" "$WORK/xdg"
|
|
393
|
-
r="$(session udd-eqempty "$PROXY" --proxy-arg '--user-data-dir-name=' --send "$INIT" --end eof --
|
|
393
|
+
r="$(session udd-eqempty "$PROXY" --proxy-arg '--user-data-dir-name=' --send "$INIT" --end eof --expect-death)"
|
|
394
394
|
assert_refused_start 'FR15: --user-data-dir-name= (empty value) refuses to start' "$r" 'basename'
|
|
395
395
|
mkdir -p "$WORK/sub" "$WORK/xdg-real"; ln -sfn "$WORK/xdg-real" "$WORK/xdg-link"
|
|
396
396
|
session argv-udd-dotroot "$PROXY" "${UDD[@]}" --env "XDG_CACHE_HOME=$WORK/sub/.." --env FAKE_PW_ARGV_OUT="$WORK/argv-udd-dotroot" --send "$INIT" --end eof >/dev/null
|
|
@@ -508,18 +508,18 @@ for node in tree.body:
|
|
|
508
508
|
found = ast.literal_eval(node.value)
|
|
509
509
|
sys.exit(0 if found == {"linux": [sys.argv[2]], "darwin": [sys.argv[3]]} else 1)
|
|
510
510
|
PY
|
|
511
|
-
r="$(session fb-twice "$PROXY" --proxy-arg --chromium-fallback --proxy-arg --chromium-fallback --send "$INIT" --end eof --
|
|
511
|
+
r="$(session fb-twice "$PROXY" --proxy-arg --chromium-fallback --proxy-arg --chromium-fallback --send "$INIT" --end eof --expect-death)"
|
|
512
512
|
assert_refused_start 'FR16: --chromium-fallback given twice refuses to start' "$r" 'twice'
|
|
513
|
-
r="$(session fb-eq "$PROXY" --proxy-arg --chromium-fallback=1 --send "$INIT" --end eof --
|
|
513
|
+
r="$(session fb-eq "$PROXY" --proxy-arg --chromium-fallback=1 --send "$INIT" --end eof --expect-death)"
|
|
514
514
|
assert_refused_start 'FR16: --chromium-fallback=<v> is not a recognised spelling (the flag is a boolean) and refuses to start' "$r" 'unrecognised'
|
|
515
|
-
r="$(session fb-trailing "$PROXY" "${CFB[@]}" --env "$NOCHROME" --send "$INIT" --end eof --
|
|
515
|
+
r="$(session fb-trailing "$PROXY" "${CFB[@]}" --env "$NOCHROME" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --browser)"
|
|
516
516
|
assert_refused_start 'FR16: a trailing --browser would bind the appended flag as its value — refuses even with the fallback on' "$r" 'expects a value'
|
|
517
|
-
r="$(session fb-name-swallow "$PROXY" --proxy-arg --user-data-dir-name --proxy-arg --chromium-fallback --send "$INIT" --end eof --
|
|
517
|
+
r="$(session fb-name-swallow "$PROXY" --proxy-arg --user-data-dir-name --proxy-arg --chromium-fallback --send "$INIT" --end eof --expect-death)"
|
|
518
518
|
assert_refused_start 'FR16: --user-data-dir-name never swallows the fallback flag as its basename (a leading - refuses)' "$r" "leading '-'"
|
|
519
519
|
# The sandbox refusals hold with the fallback ON: the fallback adds --sandbox, it never opens a bypass for the forbidden spelling.
|
|
520
|
-
r="$(session fb-nosandbox "$PROXY" "${CFB[@]}" --env "$NOCHROME" --send "$INIT" --end eof --
|
|
520
|
+
r="$(session fb-nosandbox "$PROXY" "${CFB[@]}" --env "$NOCHROME" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --no-sandbox)"
|
|
521
521
|
assert_refused_start 'FR16: --no-sandbox in the server argv still refuses to start with the fallback on' "$r" '--no-sandbox'
|
|
522
|
-
r="$(session fb-nosandbox-env "$PROXY" "${CFB[@]}" --env "$NOCHROME" --env PLAYWRIGHT_MCP_SANDBOX=1 --send "$INIT" --end eof --
|
|
522
|
+
r="$(session fb-nosandbox-env "$PROXY" "${CFB[@]}" --env "$NOCHROME" --env PLAYWRIGHT_MCP_SANDBOX=1 --send "$INIT" --end eof --expect-death)"
|
|
523
523
|
assert_refused_start 'FR16: PLAYWRIGHT_MCP_SANDBOX in the env still refuses to start with the fallback on' "$r" 'PLAYWRIGHT_MCP_SANDBOX'
|
|
524
524
|
session fb-udd "$PROXY" "${CFB[@]}" "${UDD[@]}" --env "$NOCHROME" --env "XDG_CACHE_HOME=$WORK/xdg" --env FAKE_PW_ARGV_OUT="$WORK/fb-udd" --send "$INIT" --end eof >/dev/null
|
|
525
525
|
assert_true 'FR16: with a profile flag too, the appended flags arrive as --browser chromium --sandbox, --user-data-dir=<dir>, --snapshot-mode none, in that order' python3 "$FBCHK" "$WORK/fb-udd" udd-order "$WORK/xdg/soleur-test-profile"
|
|
@@ -532,50 +532,50 @@ assert_true 'FR17 control: the stub reports <unset> when the variable is absent
|
|
|
532
532
|
# FR5 — refuse to start (no child spawned)
|
|
533
533
|
# ---------------------------------------------------------------------------
|
|
534
534
|
NOSIB="$WORK/nosib"; mkdir -p "$NOSIB"; cp "$PROXY" "$NOSIB/proxy.py"
|
|
535
|
-
r="$(session nosib "$NOSIB/proxy.py" --send "$INIT" --end eof --
|
|
535
|
+
r="$(session nosib "$NOSIB/proxy.py" --send "$INIT" --end eof --expect-death)"
|
|
536
536
|
assert_refused_start 'FR5: proxy beside no redactor refuses to start' "$r" 'missing'
|
|
537
|
-
r="$(session savesess "$PROXY" --send "$INIT" --end eof --
|
|
537
|
+
r="$(session savesess "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --save-session)"
|
|
538
538
|
assert_refused_start 'FR5: --save-session in the wrapped argv refuses to start' "$r" 'save-session'
|
|
539
539
|
printf '{"saveSession": true}\n' > "$WORK/cfg-save.json"
|
|
540
|
-
r="$(session savecfg "$PROXY" --send "$INIT" --end eof --
|
|
540
|
+
r="$(session savecfg "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config "$WORK/cfg-save.json")"
|
|
541
541
|
assert_refused_start 'FR5: config saveSession (via --config) refuses to start' "$r" 'saveSession'
|
|
542
|
-
r="$(session savecfgenv "$PROXY" --env PLAYWRIGHT_MCP_CONFIG="$WORK/cfg-save.json" --send "$INIT" --end eof --
|
|
542
|
+
r="$(session savecfgenv "$PROXY" --env PLAYWRIGHT_MCP_CONFIG="$WORK/cfg-save.json" --send "$INIT" --end eof --expect-death)"
|
|
543
543
|
assert_refused_start 'FR5: config saveSession (via $PLAYWRIGHT_MCP_CONFIG) refuses to start' "$r" 'saveSession'
|
|
544
544
|
printf 'saveSession = true\n' > "$WORK/cfg-save.ini"
|
|
545
|
-
r="$(session saveini "$PROXY" --send "$INIT" --end eof --
|
|
545
|
+
r="$(session saveini "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-save.ini")"
|
|
546
546
|
assert_refused_start 'FR5: a config the proxy cannot parse as JSON (the server reads INI) refuses to start' "$r" 'not JSON'
|
|
547
|
-
r="$(session cfgmissing "$PROXY" --send "$INIT" --end eof --
|
|
547
|
+
r="$(session cfgmissing "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/nope.json")"
|
|
548
548
|
assert_refused_start 'FR5: a --config that does not exist refuses to start with a named reason' "$r" 'does not exist'
|
|
549
549
|
printf '{"saveVideo": {"width": 800, "height": 600}}\n' > "$WORK/cfg-video.json"
|
|
550
|
-
r="$(session savevideo "$PROXY" --send "$INIT" --end eof --
|
|
550
|
+
r="$(session savevideo "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-video.json")"
|
|
551
551
|
assert_refused_start 'FR5: config saveVideo refuses to start' "$r" 'saveVideo'
|
|
552
552
|
printf '{"capabilities": ["devtools"]}\n' > "$WORK/cfg-caps.json"
|
|
553
|
-
r="$(session cfgcaps "$PROXY" --send "$INIT" --end eof --
|
|
553
|
+
r="$(session cfgcaps "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-caps.json")"
|
|
554
554
|
assert_refused_start 'FR5: config capabilities other than vision refuses to start' "$r" 'capabilities'
|
|
555
555
|
printf '{"server": {"port": 8931}}\n' > "$WORK/cfg-port.json"
|
|
556
|
-
r="$(session cfgport "$PROXY" --send "$INIT" --end eof --
|
|
556
|
+
r="$(session cfgport "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-port.json")"
|
|
557
557
|
assert_refused_start 'FR5: config server.port refuses to start' "$r" 'server.port'
|
|
558
|
-
r="$(session port "$PROXY" --send "$INIT" --end eof --
|
|
558
|
+
r="$(session port "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --port 8931)"
|
|
559
559
|
assert_refused_start 'FR5: --port (HTTP transport around the relay) refuses to start' "$r" '--port'
|
|
560
|
-
r="$(session portenv "$PROXY" --env PLAYWRIGHT_MCP_PORT=8931 --send "$INIT" --end eof --
|
|
560
|
+
r="$(session portenv "$PROXY" --env PLAYWRIGHT_MCP_PORT=8931 --send "$INIT" --end eof --expect-death)"
|
|
561
561
|
assert_refused_start 'FR5: PLAYWRIGHT_MCP_PORT refuses to start' "$r" '--port'
|
|
562
|
-
r="$(session host "$PROXY" --send "$INIT" --end eof --
|
|
562
|
+
r="$(session host "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --host=0.0.0.0)"
|
|
563
563
|
assert_refused_start 'FR5: --host refuses to start' "$r" '--host'
|
|
564
|
-
r="$(session caps "$PROXY" --send "$INIT" --end eof --
|
|
564
|
+
r="$(session caps "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --caps=vision,devtools)"
|
|
565
565
|
assert_refused_start 'FR5: --caps with devtools refuses to start' "$r" '--caps'
|
|
566
|
-
r="$(session capsenv "$PROXY" --env PLAYWRIGHT_MCP_CAPS=storage --send "$INIT" --end eof --
|
|
566
|
+
r="$(session capsenv "$PROXY" --env PLAYWRIGHT_MCP_CAPS=storage --send "$INIT" --end eof --expect-death)"
|
|
567
567
|
assert_refused_start 'FR5: PLAYWRIGHT_MCP_CAPS=storage refuses to start' "$r" '--caps'
|
|
568
|
-
r="$(session outmode "$PROXY" --send "$INIT" --end eof --
|
|
568
|
+
r="$(session outmode "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --output-mode file)"
|
|
569
569
|
assert_refused_start 'FR5: --output-mode file refuses to start' "$r" 'output-mode'
|
|
570
570
|
printf '{"snapshot": {"mode": "full"}, "capabilities": ["vision"]}\n' > "$WORK/cfg-ok.json"
|
|
571
571
|
r="$(session cfgok "$PROXY" --send "$INIT" --send "$SNAP" --end eof --server python3 "$STUB" --config="$WORK/cfg-ok.json" --caps vision)"
|
|
572
572
|
assert_redacted_result 'FR5 companion: a benign JSON --config=<file> and --caps vision start and serve' "$r" 3 1
|
|
573
573
|
for dbg in 'pw:mcp:server:response' '*' 'pw:*' 'pw:api *' '*:response' 'express:router, *' 'p*'; do
|
|
574
|
-
r="$(session "debug-$(printf '%s' "$dbg" | md5sum | cut -c1-8)" "$PROXY" --env "DEBUG=$dbg" --send "$INIT" --end eof --
|
|
574
|
+
r="$(session "debug-$(printf '%s' "$dbg" | md5sum | cut -c1-8)" "$PROXY" --env "DEBUG=$dbg" --send "$INIT" --end eof --expect-death)"
|
|
575
575
|
assert_refused_start "FR5: DEBUG='$dbg' (enables a pw:* logger) refuses to start" "$r" 'DEBUG'
|
|
576
576
|
done
|
|
577
577
|
assert_true 'FR5: the DEBUG reason never quotes the value' bash -c 'stderr_has "$1" "refusing to start" && ! grep -qF "p*" "$1/stderr.txt"' _ "$r"
|
|
578
|
-
r="$(session debugfile "$PROXY" --env DEBUG_FILE="$WORK/dbg" --send "$INIT" --end eof --
|
|
578
|
+
r="$(session debugfile "$PROXY" --env DEBUG_FILE="$WORK/dbg" --send "$INIT" --end eof --expect-death)"
|
|
579
579
|
assert_refused_start 'FR5: DEBUG_FILE refuses to start' "$r" 'DEBUG_FILE'
|
|
580
580
|
r="$(session debugother "$PROXY" --env 'DEBUG=express:router,-pw:*' --send "$INIT" --send "$SNAP" --end eof)"
|
|
581
581
|
assert_redacted_result 'FR5 companion: an unrelated DEBUG namespace (plus a pw exclusion) starts and serves' "$r" 3 1
|
|
@@ -599,78 +599,78 @@ for pair in \
|
|
|
599
599
|
'--no-sandbox:PLAYWRIGHT_MCP_SANDBOX' \
|
|
600
600
|
'--daemon:PLAYWRIGHT_MCP_DAEMON'; do
|
|
601
601
|
flag="${pair%%:*}"; envvar="${pair##*:}"
|
|
602
|
-
r="$(session "sink-$flag" "$PROXY" --send "$INIT" --end eof --
|
|
602
|
+
r="$(session "sink-$flag" "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" "$flag=/tmp/x")"
|
|
603
603
|
assert_refused_start "FR5: $flag=<v> in the wrapped argv refuses to start" "$r" "$flag"
|
|
604
|
-
r="$(session "sinkenv-${envvar#PLAYWRIGHT_MCP_}" "$PROXY" --env "$envvar=/tmp/x" --send "$INIT" --end eof --
|
|
604
|
+
r="$(session "sinkenv-${envvar#PLAYWRIGHT_MCP_}" "$PROXY" --env "$envvar=/tmp/x" --send "$INIT" --end eof --expect-death)"
|
|
605
605
|
assert_refused_start "FR5: $envvar refuses to start" "$r" "$envvar"
|
|
606
606
|
done
|
|
607
|
-
r="$(session sink-aufa "$PROXY" --send "$INIT" --end eof --
|
|
607
|
+
r="$(session sink-aufa "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --allow-unrestricted-file-access)"
|
|
608
608
|
assert_refused_start 'FR5: bare --allow-unrestricted-file-access refuses to start' "$r" 'allow-unrestricted-file-access'
|
|
609
|
-
r="$(session sinkenv-aufa "$PROXY" --env PLAYWRIGHT_MCP_ALLOW_UNRESTRICTED_FILE_ACCESS=1 --send "$INIT" --end eof --
|
|
609
|
+
r="$(session sinkenv-aufa "$PROXY" --env PLAYWRIGHT_MCP_ALLOW_UNRESTRICTED_FILE_ACCESS=1 --send "$INIT" --end eof --expect-death)"
|
|
610
610
|
assert_refused_start 'FR5: PLAYWRIGHT_MCP_ALLOW_UNRESTRICTED_FILE_ACCESS refuses to start' "$r" 'PLAYWRIGHT_MCP_ALLOW_UNRESTRICTED_FILE_ACCESS'
|
|
611
|
-
r="$(session sink-savesess-eq "$PROXY" --send "$INIT" --end eof --
|
|
611
|
+
r="$(session sink-savesess-eq "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --save-session=/x)"
|
|
612
612
|
assert_refused_start 'FR5: --save-session=<v> (the = spelling) refuses to start' "$r" 'save-session'
|
|
613
|
-
r="$(session sinkenv-savesess "$PROXY" --env PLAYWRIGHT_MCP_SAVE_SESSION=1 --send "$INIT" --end eof --
|
|
613
|
+
r="$(session sinkenv-savesess "$PROXY" --env PLAYWRIGHT_MCP_SAVE_SESSION=1 --send "$INIT" --end eof --expect-death)"
|
|
614
614
|
assert_refused_start 'FR5: PLAYWRIGHT_MCP_SAVE_SESSION refuses to start' "$r" 'PLAYWRIGHT_MCP_SAVE_SESSION'
|
|
615
|
-
r="$(session sinkenv-udd "$PROXY" --env PLAYWRIGHT_MCP_USER_DATA_DIR=/tmp/p --send "$INIT" --end eof --
|
|
615
|
+
r="$(session sinkenv-udd "$PROXY" --env PLAYWRIGHT_MCP_USER_DATA_DIR=/tmp/p --send "$INIT" --end eof --expect-death)"
|
|
616
616
|
assert_refused_start 'FR5: PLAYWRIGHT_MCP_USER_DATA_DIR refuses to start (the env form of an audited argv setting)' "$r" 'PLAYWRIGHT_MCP_USER_DATA_DIR'
|
|
617
|
-
r="$(session sinkenv-snap "$PROXY" --env PLAYWRIGHT_MCP_SNAPSHOT_MODE=full --send "$INIT" --end eof --
|
|
617
|
+
r="$(session sinkenv-snap "$PROXY" --env PLAYWRIGHT_MCP_SNAPSHOT_MODE=full --send "$INIT" --end eof --expect-death)"
|
|
618
618
|
assert_refused_start 'FR5: PLAYWRIGHT_MCP_SNAPSHOT_MODE refuses to start (the proxy owns the flag)' "$r" 'PLAYWRIGHT_MCP_SNAPSHOT_MODE'
|
|
619
619
|
# a bare valued flag as the LAST server arg would bind an appended
|
|
620
620
|
# `--user-data-dir=`/`--snapshot-mode` token as its value — refused, whatever
|
|
621
621
|
# the flag
|
|
622
|
-
r="$(session trailcfg "$PROXY" --send "$INIT" --end eof --
|
|
622
|
+
r="$(session trailcfg "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config)"
|
|
623
623
|
assert_refused_start 'FR5: a trailing --config would swallow an appended flag into its value — refuses' "$r" 'expects a value'
|
|
624
|
-
r="$(session trailua "$PROXY" --send "$INIT" --end eof --
|
|
624
|
+
r="$(session trailua "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --user-agent)"
|
|
625
625
|
assert_refused_start 'FR5: a trailing --user-agent (valued, not a sink) refuses the same way' "$r" 'expects a value'
|
|
626
626
|
r="$(session midua "$PROXY" --send "$INIT" --send "$SNAP" --end eof --server python3 "$STUB" --user-agent suite-ua)"
|
|
627
627
|
assert_redacted_result 'FR5 companion: a valued flag with its value mid-argv starts and serves' "$r" 3 1
|
|
628
628
|
# the config-file forms of the same sinks (audited argv stays allowed)
|
|
629
629
|
printf '{"saveTrace": true}\n' > "$WORK/cfg-trace.json"
|
|
630
|
-
r="$(session cfgtrace "$PROXY" --send "$INIT" --end eof --
|
|
630
|
+
r="$(session cfgtrace "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-trace.json")"
|
|
631
631
|
assert_refused_start 'FR5: config saveTrace refuses to start' "$r" 'saveTrace'
|
|
632
632
|
printf '{"secrets": "/tmp/s.json"}\n' > "$WORK/cfg-secrets.json"
|
|
633
|
-
r="$(session cfgsecrets "$PROXY" --send "$INIT" --end eof --
|
|
633
|
+
r="$(session cfgsecrets "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-secrets.json")"
|
|
634
634
|
assert_refused_start 'FR5: config secrets refuses to start' "$r" 'secrets'
|
|
635
635
|
printf '{"outputDir": "/tmp/o"}\n' > "$WORK/cfg-outdir.json"
|
|
636
|
-
r="$(session cfgoutdir "$PROXY" --send "$INIT" --end eof --
|
|
636
|
+
r="$(session cfgoutdir "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-outdir.json")"
|
|
637
637
|
assert_refused_start 'FR5: config outputDir refuses to start' "$r" 'outputDir'
|
|
638
638
|
printf '{"allowUnrestrictedFileAccess": true}\n' > "$WORK/cfg-aufa.json"
|
|
639
|
-
r="$(session cfgaufa "$PROXY" --send "$INIT" --end eof --
|
|
639
|
+
r="$(session cfgaufa "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-aufa.json")"
|
|
640
640
|
assert_refused_start 'FR5: config allowUnrestrictedFileAccess refuses to start' "$r" 'allowUnrestrictedFileAccess'
|
|
641
641
|
printf '{"extension": true}\n' > "$WORK/cfg-ext.json"
|
|
642
|
-
r="$(session cfgext "$PROXY" --send "$INIT" --end eof --
|
|
642
|
+
r="$(session cfgext "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-ext.json")"
|
|
643
643
|
assert_refused_start 'FR5: config extension refuses to start' "$r" 'extension'
|
|
644
644
|
printf '{"browser": {"cdpEndpoint": "ws://127.0.0.1:1"}}\n' > "$WORK/cfg-cdp.json"
|
|
645
|
-
r="$(session cfgcdp "$PROXY" --send "$INIT" --end eof --
|
|
645
|
+
r="$(session cfgcdp "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-cdp.json")"
|
|
646
646
|
assert_refused_start 'FR5: config browser.cdpEndpoint refuses to start' "$r" 'cdpEndpoint'
|
|
647
647
|
printf '{"browser": {"initScript": "/tmp/x.js"}}\n' > "$WORK/cfg-initscript.json"
|
|
648
|
-
r="$(session cfginitscript "$PROXY" --send "$INIT" --end eof --
|
|
648
|
+
r="$(session cfginitscript "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-initscript.json")"
|
|
649
649
|
assert_refused_start 'FR5: config browser.initScript refuses to start' "$r" 'initScript'
|
|
650
650
|
printf '{"browser": {"launchOptions": {"executablePath": "/tmp/x"}}}\n' > "$WORK/cfg-execpath.json"
|
|
651
|
-
r="$(session cfgexecpath "$PROXY" --send "$INIT" --end eof --
|
|
651
|
+
r="$(session cfgexecpath "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-execpath.json")"
|
|
652
652
|
assert_refused_start 'FR5: config browser.launchOptions.executablePath refuses to start' "$r" 'executablePath'
|
|
653
653
|
printf '{"browser": {"launchOptions": {"args": ["--remote-debugging-port=9222"]}}}\n' > "$WORK/cfg-rdbg.json"
|
|
654
|
-
r="$(session cfgrdbg "$PROXY" --send "$INIT" --end eof --
|
|
654
|
+
r="$(session cfgrdbg "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-rdbg.json")"
|
|
655
655
|
assert_refused_start 'FR5: config launchOptions.args with a remote debugging flag refuses to start' "$r" 'remote debugging'
|
|
656
656
|
printf '{"browser": {"userDataDir": "/tmp/p"}}\n' > "$WORK/cfg-udd.json"
|
|
657
|
-
r="$(session cfgudd "$PROXY" "${UDD[@]}" --env "XDG_CACHE_HOME=$WORK/xdg" --send "$INIT" --end eof --
|
|
657
|
+
r="$(session cfgudd "$PROXY" "${UDD[@]}" --env "XDG_CACHE_HOME=$WORK/xdg" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-udd.json")"
|
|
658
658
|
assert_refused_start 'FR5: config browser.userDataDir conflicts with --user-data-dir-name' "$r" 'userDataDir'
|
|
659
659
|
r="$(session cfgudd-ok "$PROXY" --send "$INIT" --send "$SNAP" --end eof --server python3 "$STUB" --config="$WORK/cfg-udd.json")"
|
|
660
660
|
assert_redacted_result 'FR5 companion: config browser.userDataDir WITHOUT the profile flag is the audited form — starts and serves' "$r" 3 1
|
|
661
661
|
printf '{"browser": {"contextOptions": {"storageState": "/tmp/s.json"}}}\n' > "$WORK/cfg-ctxstorage.json"
|
|
662
|
-
r="$(session cfgctxstorage "$PROXY" --send "$INIT" --end eof --
|
|
662
|
+
r="$(session cfgctxstorage "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-ctxstorage.json")"
|
|
663
663
|
assert_refused_start 'FR5: config browser.contextOptions.storageState refuses to start' "$r" 'storageState'
|
|
664
664
|
printf '{"browser": {"contextOptions": {"permissions": ["clipboard-read"]}}}\n' > "$WORK/cfg-ctxperms.json"
|
|
665
|
-
r="$(session cfgctxperms "$PROXY" --send "$INIT" --end eof --
|
|
665
|
+
r="$(session cfgctxperms "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-ctxperms.json")"
|
|
666
666
|
assert_refused_start 'FR5: config browser.contextOptions.permissions refuses to start' "$r" 'permissions'
|
|
667
667
|
printf '{"browser": {"contextOptions": {"ignoreHTTPSErrors": true}}}\n' > "$WORK/cfg-ctxhttps.json"
|
|
668
|
-
r="$(session cfgctxhttps "$PROXY" --send "$INIT" --end eof --
|
|
668
|
+
r="$(session cfgctxhttps "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-ctxhttps.json")"
|
|
669
669
|
assert_refused_start 'FR5: config browser.contextOptions.ignoreHTTPSErrors refuses to start' "$r" 'ignoreHTTPSErrors'
|
|
670
670
|
printf '{"browser": {"launchOptions": {"chromiumSandbox": false}}}\n' > "$WORK/cfg-sandbox.json"
|
|
671
|
-
r="$(session cfgsandbox "$PROXY" --send "$INIT" --end eof --
|
|
671
|
+
r="$(session cfgsandbox "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --config="$WORK/cfg-sandbox.json")"
|
|
672
672
|
assert_refused_start 'FR5: config browser.launchOptions.chromiumSandbox refuses to start' "$r" 'chromiumSandbox'
|
|
673
|
-
r="$(session traildaemon "$PROXY" --send "$INIT" --end eof --
|
|
673
|
+
r="$(session traildaemon "$PROXY" --send "$INIT" --end eof --expect-death --server python3 "$STUB" --daemon)"
|
|
674
674
|
assert_refused_start 'FR5: a trailing --daemon (hidden valued option) would swallow an appended flag — refuses' "$r" 'expects a value'
|
|
675
675
|
usage_rc=0; python3 "$PROXY" -- </dev/null >"$WORK/usage.out" 2>"$WORK/usage.err" || usage_rc=$?
|
|
676
676
|
assert_true 'B1: empty server argv → exit 2, usage on stderr, nothing on stdout' bash -c '[[ "$1" == "2" ]] && grep -qF "refusing to start: usage:" "$2" && [[ ! -s "$3" ]]' _ "$usage_rc" "$WORK/usage.err" "$WORK/usage.out"
|
|
@@ -690,13 +690,13 @@ open(sys.argv[2], "w").write(src.replace(old, new))
|
|
|
690
690
|
PY
|
|
691
691
|
}
|
|
692
692
|
mk_variant "$WORK/v-identity" "$PROXY" 'def redact_text(text: str) -> str:' 'def redact_text(text: str) -> str:\n return text\n\ndef _unused_redact_text(text: str) -> str:'
|
|
693
|
-
r="$(session v-identity "$WORK/v-identity/proxy.py" --send "$INIT" --end eof --
|
|
693
|
+
r="$(session v-identity "$WORK/v-identity/proxy.py" --send "$INIT" --end eof --expect-death)"
|
|
694
694
|
assert_refused_start 'FR6: a redactor returning its input unchanged → refuse to start' "$r" 'self-test'
|
|
695
695
|
mk_variant "$WORK/v-append" "$PROXY" 'def redact_text(text: str) -> str:' 'def redact_text(text: str) -> str:\n return text + " <redacted>"\n\ndef _unused_redact_text(text: str) -> str:'
|
|
696
|
-
r="$(session v-append "$WORK/v-append/proxy.py" --send "$INIT" --end eof --
|
|
696
|
+
r="$(session v-append "$WORK/v-append/proxy.py" --send "$INIT" --end eof --expect-death)"
|
|
697
697
|
assert_refused_start 'FR6/row 9 input: a redactor appending <redacted> without removing the value → refuse' "$r" 'self-test'
|
|
698
698
|
mk_variant "$WORK/v-false" "$PROXY" 'def looks_like_a11y_tree(value: str) -> bool:' 'def looks_like_a11y_tree(value: str) -> bool:\n return False\n\ndef _unused_looks(value: str) -> bool:'
|
|
699
|
-
r="$(session v-false "$WORK/v-false/proxy.py" --send "$INIT" --end eof --
|
|
699
|
+
r="$(session v-false "$WORK/v-false/proxy.py" --send "$INIT" --end eof --expect-death)"
|
|
700
700
|
assert_refused_start 'FR6/row 29 input: constant-False looks_like_a11y_tree → refuse' "$r" 'looks_like_a11y_tree'
|
|
701
701
|
# raises only for long text, so the startup self-test passes (row 34's input)
|
|
702
702
|
mk_variant "$WORK/v-raise" "$PROXY" 'def redact_text(text: str) -> str:' 'def redact_text(text: str) -> str:\n if len(text) > 200:\n raise RuntimeError("boom")\n return _orig_redact_text(text)\n\ndef _orig_redact_text(text: str) -> str:'
|
|
@@ -707,33 +707,49 @@ assert_stderr_marker 'FR7b: one withheld line for the raise' "$r" 'withheld tool
|
|
|
707
707
|
assert_rc 'FR7: the session ended cleanly after the withhold' "$r" 0
|
|
708
708
|
# the four-name contract: a redactor missing one name → refuse, not a per-result withhold
|
|
709
709
|
mk_variant "$WORK/v-rename" "$PROXY" 'def main() -> None:' 'del looks_like_a11y_tree\n\n\ndef main() -> None:'
|
|
710
|
-
r="$(session v-rename "$WORK/v-rename/proxy.py" --send "$INIT" --end eof --
|
|
710
|
+
r="$(session v-rename "$WORK/v-rename/proxy.py" --send "$INIT" --end eof --expect-death)"
|
|
711
711
|
assert_refused_start 'B2: a redactor missing one of the four names → refuse (not a per-result withhold)' "$r" 'does not export looks_like_a11y_tree'
|
|
712
712
|
# Startup refusal (slice 1 of #10331): the startup handlers catch (Exception, SystemExit, KeyboardInterrupt), not BaseException. Each excluded
|
|
713
713
|
# class must still refuse with rc 2 and the unchanged reason line, at every member: the import, the redact_text call and the
|
|
714
714
|
# looks_like_a11y_tree call in the self-test (a case for one member does not cover the other).
|
|
715
715
|
for cls in SystemExit KeyboardInterrupt; do
|
|
716
716
|
mk_variant "$WORK/v-load-$cls" "$PROXY" 'def main() -> None:' "raise $cls()\n\n\ndef main() -> None:"
|
|
717
|
-
r="$(session "v-load-$cls" "$WORK/v-load-$cls/proxy.py" --send "$INIT" --end eof --
|
|
717
|
+
r="$(session "v-load-$cls" "$WORK/v-load-$cls/proxy.py" --send "$INIT" --end eof --expect-death)"
|
|
718
718
|
assert_refused_start "G1: a redactor raising $cls at import → refuse to start (rc 2), class named" "$r" "cannot load redact-a11y-snapshot.py: $cls"
|
|
719
719
|
done
|
|
720
720
|
mk_variant "$WORK/v-st-redact" "$PROXY" 'def redact_text(text: str) -> str:' 'def redact_text(text: str) -> str:\n raise KeyboardInterrupt()\n\ndef _unused_redact_text(text: str) -> str:'
|
|
721
|
-
r="$(session v-st-redact "$WORK/v-st-redact/proxy.py" --send "$INIT" --end eof --
|
|
721
|
+
r="$(session v-st-redact "$WORK/v-st-redact/proxy.py" --send "$INIT" --end eof --expect-death)"
|
|
722
722
|
assert_refused_start 'G1: redact_text raising KeyboardInterrupt in the self-test → refuse (rc 2), class named' "$r" 'redactor self-test raised KeyboardInterrupt'
|
|
723
723
|
mk_variant "$WORK/v-st-redact-exit" "$PROXY" 'def redact_text(text: str) -> str:' 'def redact_text(text: str) -> str:\n raise SystemExit(3)\n\ndef _unused_redact_text(text: str) -> str:'
|
|
724
|
-
r="$(session v-st-redact-exit "$WORK/v-st-redact-exit/proxy.py" --send "$INIT" --end eof --
|
|
724
|
+
r="$(session v-st-redact-exit "$WORK/v-st-redact-exit/proxy.py" --send "$INIT" --end eof --expect-death)"
|
|
725
725
|
assert_refused_start 'G1: redact_text raising SystemExit in the self-test → refuse (rc 2), class named' "$r" 'redactor self-test raised SystemExit'
|
|
726
726
|
mk_variant "$WORK/v-st-looks" "$PROXY" 'def looks_like_a11y_tree(value: str) -> bool:' 'def looks_like_a11y_tree(value: str) -> bool:\n raise KeyboardInterrupt()\n\ndef _unused_looks(value: str) -> bool:'
|
|
727
|
-
r="$(session v-st-looks "$WORK/v-st-looks/proxy.py" --send "$INIT" --end eof --
|
|
727
|
+
r="$(session v-st-looks "$WORK/v-st-looks/proxy.py" --send "$INIT" --end eof --expect-death)"
|
|
728
728
|
assert_refused_start 'G1: looks_like_a11y_tree raising KeyboardInterrupt in the self-test → refuse (rc 2), class named' "$r" 'looks_like_a11y_tree raised KeyboardInterrupt'
|
|
729
729
|
mk_variant "$WORK/v-st-looks-exit" "$PROXY" 'def looks_like_a11y_tree(value: str) -> bool:' 'def looks_like_a11y_tree(value: str) -> bool:\n raise SystemExit(3)\n\ndef _unused_looks(value: str) -> bool:'
|
|
730
|
-
r="$(session v-st-looks-exit "$WORK/v-st-looks-exit/proxy.py" --send "$INIT" --end eof --
|
|
730
|
+
r="$(session v-st-looks-exit "$WORK/v-st-looks-exit/proxy.py" --send "$INIT" --end eof --expect-death)"
|
|
731
731
|
assert_refused_start 'G1: looks_like_a11y_tree raising SystemExit in the self-test → refuse (rc 2), class named' "$r" 'looks_like_a11y_tree raised SystemExit'
|
|
732
732
|
# The narrowing is deliberate: a BaseException subclass outside (Exception, SystemExit, KeyboardInterrupt) is not caught, so the proxy
|
|
733
733
|
# dies with rc 1 and a traceback. Still fail-closed (no stdout line, no child) -- pinned so widening back to BaseException (rc 2) is a decision.
|
|
734
734
|
mk_variant "$WORK/v-load-outside" "$PROXY" 'def main() -> None:' "class _OutsideBase(BaseException):\n pass\n\n\nraise _OutsideBase()\n\n\ndef main() -> None:"
|
|
735
|
-
r="$(session v-load-outside "$WORK/v-load-outside/proxy.py" --send "$INIT" --end eof --
|
|
736
|
-
|
|
735
|
+
r="$(session v-load-outside "$WORK/v-load-outside/proxy.py" --send "$INIT" --end eof --expect-death)"
|
|
736
|
+
# Split per-observable (#10919): a recurrence must name the failed conjunct, not
|
|
737
|
+
# just the label — the 4-in-1 assert_true is what made #10913 undiagnosable.
|
|
738
|
+
assert_rc 'G1: a BaseException subclass outside the narrowed tuple at import → proxy exit 1' "$r" 1
|
|
739
|
+
assert_true 'G1: … nothing relayed (zero stdout lines)' bash -c '[[ "$(fact "$1" 0 lines)" == "0" ]]' _ "$r"
|
|
740
|
+
assert_true 'G1: … no child spawned' bash -c '[[ -z "$(cat "$1/child_pgid" 2>/dev/null)" ]]' _ "$r"
|
|
741
|
+
assert_true 'G1: … _OutsideBase named on stderr' bash -c 'stderr_has "$1" "_OutsideBase"' _ "$r"
|
|
742
|
+
# Mechanism proof for the deadline→verdict decoupling (AC-2): a redactor whose
|
|
743
|
+
# module top sleeps well past BOTH 3s deadline windows (10s — the measured stall
|
|
744
|
+
# was 6.07s; margin covers driver descheduling between the phase-A deadline and
|
|
745
|
+
# computing t_end) then raises _OutsideBase must still record TIMEOUT under --timeout 3
|
|
746
|
+
# (negative control pinning the deadline arm) and the real rc 1 under
|
|
747
|
+
# --expect-death.
|
|
748
|
+
mk_variant "$WORK/v-load-outside-slow" "$PROXY" 'def main() -> None:' "import time\ntime.sleep(10)\n\n\nclass _OutsideBase(BaseException):\n pass\n\n\nraise _OutsideBase()\n\n\ndef main() -> None:"
|
|
749
|
+
r="$(session v-load-outside-slow-deadline "$WORK/v-load-outside-slow/proxy.py" --send "$INIT" --end eof --timeout 3)"
|
|
750
|
+
assert_rc 'G1b: negative control — a >6s-window slow death (10s for margin) still records TIMEOUT under --timeout 3' "$r" TIMEOUT
|
|
751
|
+
r="$(session v-load-outside-slow "$WORK/v-load-outside-slow/proxy.py" --send "$INIT" --end eof --expect-death)"
|
|
752
|
+
assert_rc 'G1b: the same slow death under --expect-death records the real exit 1' "$r" 1
|
|
737
753
|
# FR13 behavioural: a SPY redactor tags every string it is handed. Every text block
|
|
738
754
|
# the proxy delivers must carry the tag — a proxy-side predicate that skips some
|
|
739
755
|
# text (a literal, a tool-name allowlist, any spelling of either) cannot hide.
|
|
@@ -1146,9 +1162,9 @@ if [[ -n "$MUTANT_PATH" ]]; then r="$(session m60 "$MUTANT_PATH" "${UDD[@]}" --e
|
|
|
1146
1162
|
mutant 61-udd-conflict-ok refuse_argv_and_env ' if profile_dir is not None and (argv_values(server, "--user-data-dir") or flag_present(server, "--user-data-dir")):' ' if False:'
|
|
1147
1163
|
if [[ -n "$MUTANT_PATH" ]]; then r="$(session m61 "$MUTANT_PATH" "${UDD[@]}" --send "$INIT" --end eof --timeout 3 --server python3 "$STUB" --user-data-dir=/x)"; red 'row 61: the conflict check removed → flag + explicit --user-data-dir starts the proxy' started "$r"; fi
|
|
1148
1164
|
mutant 62-udd-nohome-ok profile_dir_from_args ' if not home:' ' if False:'
|
|
1149
|
-
if [[ -n "$MUTANT_PATH" ]]; then r="$(session m62 "$MUTANT_PATH" "${UDD[@]}" --env XDG_CACHE_HOME= --env HOME= --send "$INIT" --end eof --
|
|
1165
|
+
if [[ -n "$MUTANT_PATH" ]]; then r="$(session m62 "$MUTANT_PATH" "${UDD[@]}" --env XDG_CACHE_HOME= --env HOME= --send "$INIT" --end eof --expect-death)"; red 'row 62: the HOME check removed → the refusal no longer names the setting' bash -c 'started "$1" || { stderr_has "$1" "refusing to start" && ! stderr_has "$1" "HOME is set"; }' _ "$r"; fi
|
|
1150
1166
|
mutant 63-udd-missing-ok profile_dir_from_args ' if i + 1 >= len(args):' ' if False:'
|
|
1151
|
-
if [[ -n "$MUTANT_PATH" ]]; then r="$(session m63 "$MUTANT_PATH" --proxy-arg --user-data-dir-name --send "$INIT" --end eof --
|
|
1167
|
+
if [[ -n "$MUTANT_PATH" ]]; then r="$(session m63 "$MUTANT_PATH" --proxy-arg --user-data-dir-name --send "$INIT" --end eof --expect-death)"; red 'row 63: the missing-argument check removed → a bare flag crashes instead of refusing cleanly' bash -c '[[ "$(rcof "$1")" != "2" ]] || ! stderr_has "$1" "refusing to start"' _ "$r"; fi
|
|
1152
1168
|
mutant 64-udd-dup-ok profile_dir_from_args ' if name is not None:' ' if False:'
|
|
1153
1169
|
if [[ -n "$MUTANT_PATH" ]]; then r="$(session m64 "$MUTANT_PATH" --proxy-arg --user-data-dir-name --proxy-arg a --proxy-arg --user-data-dir-name=b --send "$INIT" --end eof --timeout 3)"; red 'row 64: the duplicate-flag check removed → the second value silently wins' started "$r"; fi
|
|
1154
1170
|
mutant 65-udd-dash-ok profile_dir_from_args ' if name.startswith("-"):' ' if False:'
|