review: row 50 round 1, approve (darkwing)
Packet for #1536 comment 27055: suites, 13 mutants, review notes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
cfed0de2a8df99b15bc41509a4fb6a85fe70364fbae4c6e086aa9d771d18f678 agents/dewey/work/queue-50/evidence.md
|
||||
6bb747ac074012014070a1ec69582055a7cb633c3c702bd047b54402ea28ed57 packages/conversation/README.md
|
||||
17eb71ba3e84b6d59ed6e024fbf4055abab9df1d30368ce79dd0dc66f9477a4a packages/conversation/src/cohort.mjs
|
||||
7d22038f2cded1ec58855734a5a762671b4faa9003c6e47fe85be316f93ee970 packages/conversation/src/controller.mjs
|
||||
81b2d411f634601f923efb41c0e3dd2dcacccbf3224e30906e210b752de58a60 packages/conversation/tests/claim.test.mjs
|
||||
669999461ad994060d1414f517f2e9648b672a2d5c12aa6b19e0bc5561cfb249 packages/conversation/tests/cohort.test.mjs
|
||||
14f58a00844dab0cc25c993221a2651052df9fde57c9d94122b79093d8d521ac packages/conversation/tests/fake-pi.mjs
|
||||
e92bdb29ec5c33d490ab308581f82bb7dada08c741d23edbd9bde6a29cc44a49 packages/conversation/tests/harness.mjs
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
export TMPDIR=~/darkwing-scratch/r50a/tmp DOCKER_HOST=unix:///nonexistent.sock
|
||||
cd ~/darkwing-scratch/r50a/wt
|
||||
O=~/darkwing-scratch/r50a/out
|
||||
: > $O/summary.txt
|
||||
shims() { ps -eo pid,args | grep -F "$TMPDIR" | grep -F shim.mjs | grep -v grep | wc -l; }
|
||||
units() { systemctl --user list-units --all 'mosaic-chat-*' --no-legend | wc -l; }
|
||||
echo "start $(date -u +%FT%TZ) shims=$(shims) units=$(units)" >> $O/summary.txt
|
||||
for p in conversation webui; do
|
||||
node --test "packages/$p/tests/*.test.mjs" > $O/node-$p.txt 2>&1; e=$?
|
||||
echo "node-$p exit=$e $(grep -E '^ℹ (pass|fail)' $O/node-$p.txt | tr '\n' ' ') shims-left=$(shims) units=$(units)" >> $O/summary.txt
|
||||
done
|
||||
for f in scripts/test-*.sh; do
|
||||
s=$(basename $f .sh)
|
||||
$f > $O/$s.txt 2>&1; e=$?
|
||||
echo "$s exit=$e $(grep -E 'passed, [0-9]+ failed' $O/$s.txt | tail -1)" >> $O/summary.txt
|
||||
done
|
||||
echo "end $(date -u +%FT%TZ) shims-left=$(shims) units=$(units)" >> $O/summary.txt
|
||||
echo DONE >> $O/summary.txt
|
||||
@@ -0,0 +1,179 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (214.692766ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (35.281571ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (19.163359ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (364.532312ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (377.764228ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (300.852278ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (329.43766ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (281.021404ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.49468ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (11462.013958ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (41221.895274ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (262.033375ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (144.24079ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (650.326566ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (291.322554ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (352.891003ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (109.201416ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (215.426382ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (287.170582ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (956.719345ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (237.403628ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (94.218119ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (124.467226ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (5.326433ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.301771ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (3.089689ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (27.435756ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (946.55456ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (551.363423ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (902.476944ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (3019.596125ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (721.67872ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (789.127435ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (736.235267ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5543.534063ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (721.597132ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (816.575302ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (619.658275ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (672.240755ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (428.934148ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (447.676577ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3244.73205ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (28.056269ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (331.551762ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (289.443985ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (83.397498ms)
|
||||
✔ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (660.379397ms)
|
||||
✔ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (716.030096ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1571.840369ms)
|
||||
✔ R4: after a normal engine exit the scope stays until a proven force stop releases it (680.697711ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (469.881981ms)
|
||||
✔ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (383.359469ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.614452ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (213.913878ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (202.510628ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (208.304608ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (277.193011ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (183.688541ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.502702ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (284.669635ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (425.864917ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (253.762093ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (223.546652ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (222.749566ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (219.827577ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (9.822021ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (205.914706ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (233.034193ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (260.984066ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (214.478911ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.384792ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.255966ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.314452ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.471567ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (30.823854ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.392649ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (4.671493ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.346263ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.324006ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.09485ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (221.320831ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (256.999033ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (287.066551ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (914.50853ms)
|
||||
✔ H4: self-takeover is refused (342.427544ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (502.664919ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (1079.151522ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (246.762256ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (572.624718ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (266.594445ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (209.636318ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (190.364234ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (612.176306ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (300.766877ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (219.145789ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (908.054339ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (330.972574ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (759.177034ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (203.329728ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (344.558923ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.704325ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (655.713075ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (559.332315ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (683.460323ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (2988.767776ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (813.104398ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.100745ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (6.76514ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (1.764145ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (1.860771ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (2.501483ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.559726ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (1.99225ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (0.883923ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.251287ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (3.715171ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (6.551748ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (4.590313ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (4.530809ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (6.051209ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (7.22648ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (1.599878ms)
|
||||
✔ F9: registrations never add or redirect a root (1.922949ms)
|
||||
✔ F10: a header cwd naming another project is refused (4.623169ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.738107ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (3.765454ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (1.879358ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.364377ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.712237ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (550.683981ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (5.207212ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (1.826563ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.617974ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.249975ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (2.523566ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (847.570613ms)
|
||||
✔ the engine pin holds for the installed package (1.814212ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (274.302459ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (532.342398ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (284.79393ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (485.972173ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (430.186236ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (224.474896ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (21.01273ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (575.68202ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (268.344177ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (318.54659ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (496.492255ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (1910.454833ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (193.28303ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (300.805643ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (200.751771ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (225.31464ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (428.690849ms)
|
||||
✔ N10: fake conformance (31.727507ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (465.047877ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (275.008046ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (298.293847ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (369.68525ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (341.912018ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (363.219305ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (210.340268ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (337.62287ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (597.654958ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (477.886696ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (476.354205ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (202.361269ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (203.626415ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (185.493095ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (266.574958ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (191.942472ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 171
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 61552.029333
|
||||
@@ -0,0 +1,197 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (226.538765ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (34.268642ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (18.422735ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (377.164568ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (431.451613ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (280.533261ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (177.598291ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (184.000175ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.606349ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (11780.12298ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (34457.495069ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (250.688997ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (147.953925ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (619.220498ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (271.517832ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (337.776412ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (99.431855ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (191.77796ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (266.716649ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (754.992557ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (195.164155ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (88.420933ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (73.334283ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (4.091711ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.06084ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (1.714365ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (24.687783ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (966.015522ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (459.470974ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (785.668158ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (2972.466637ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (689.839064ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (783.388241ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (694.662392ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5805.491938ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (950.505915ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (889.439303ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (654.781853ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (651.721686ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (305.187926ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (458.226114ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3222.831765ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (22.901421ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (380.091672ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (306.358925ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (245.937337ms)
|
||||
✖ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (8752.531755ms)
|
||||
✔ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (484.261434ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1321.458437ms)
|
||||
✖ R4: after a normal engine exit the scope stays until a proven force stop releases it (8638.805908ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (468.847575ms)
|
||||
✔ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (135.291846ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (24.858227ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (230.941401ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (200.205285ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (203.404644ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (285.956646ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (199.274117ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.658149ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (198.814934ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (297.38075ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (199.967743ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (184.942994ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (205.001694ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (207.14911ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (11.166387ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (191.050687ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (212.584924ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (238.556153ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (188.14997ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.428012ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.27284ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.310939ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.505556ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (31.312106ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.492183ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (5.771178ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.401813ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.349021ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.102857ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (217.163099ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (252.50476ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (292.737298ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (799.408326ms)
|
||||
✔ H4: self-takeover is refused (180.422123ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (441.138012ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (961.852511ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (164.639843ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (493.79832ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (241.455843ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (126.772101ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (175.726861ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (537.948256ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (270.40096ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (192.225324ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (819.091249ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (320.018994ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (738.858601ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (186.015594ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (435.090407ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.710491ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (788.678038ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (573.59876ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (729.083187ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (2922.735072ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (628.576787ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (27.686027ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (10.335546ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (2.974704ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (2.982817ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (4.177387ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.695545ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (2.242896ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (0.947402ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.345194ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (4.122195ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (4.859061ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (5.658951ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (6.133022ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (9.720826ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (18.984176ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (1.866166ms)
|
||||
✔ F9: registrations never add or redirect a root (1.818595ms)
|
||||
✔ F10: a header cwd naming another project is refused (4.150549ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.90349ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (5.036037ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (2.594452ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.937937ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.924937ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (574.383504ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (4.399028ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (1.421105ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.162867ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.025159ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (1.827236ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (910.588679ms)
|
||||
✔ the engine pin holds for the installed package (1.996312ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (316.214368ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (590.898879ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (298.624996ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (514.208689ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (446.016438ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (237.853584ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (20.913513ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (346.327299ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (193.339483ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (287.50742ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (451.71746ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (1856.58794ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (178.411715ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (268.200087ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (135.709863ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (219.988297ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (328.423857ms)
|
||||
✔ N10: fake conformance (32.65928ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (412.128686ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (260.165173ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (277.358165ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (356.672295ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (348.833065ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (338.555879ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (296.757486ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (537.564445ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (720.638485ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (474.091393ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (481.958163ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (241.457842ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (147.404828ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (191.910818ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (217.258047ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (177.846399ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 169
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 54448.602276
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:767:1
|
||||
✖ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (8752.531755ms)
|
||||
Error: timed out waiting for the release
|
||||
at until (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:49:33)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:774:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:855:1
|
||||
✖ R4: after a normal engine exit the scope stays until a proven force stop releases it (8638.805908ms)
|
||||
Error: timed out waiting for the release
|
||||
at until (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:49:33)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:869:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
@@ -0,0 +1,179 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (217.437364ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (35.287716ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (18.275383ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (435.025429ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (469.934947ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (235.169757ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (188.361554ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (194.945317ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.686824ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (12004.075886ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (39780.915576ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (262.389653ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (145.367001ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (692.277541ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (277.712728ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (333.266579ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (104.5588ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (188.451758ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (248.869272ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (715.242301ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (175.024098ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (85.693007ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (74.073144ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (4.1928ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.016159ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (1.744248ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (24.811191ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (681.678313ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (586.381147ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (576.815328ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (2994.094089ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (706.883271ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (777.080197ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (720.20232ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5741.110911ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (1022.386797ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (877.425463ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (608.740496ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (729.442732ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (339.019259ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (532.059847ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3300.221832ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (32.31475ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (343.075206ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (658.700292ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (83.772229ms)
|
||||
✔ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (767.246826ms)
|
||||
✔ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (740.516167ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1109.722632ms)
|
||||
✔ R4: after a normal engine exit the scope stays until a proven force stop releases it (654.971565ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (446.856951ms)
|
||||
✔ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (115.816679ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (23.85077ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (213.313264ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (261.701969ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (199.898389ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (418.474269ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (190.693165ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.435084ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (192.457992ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (291.753187ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (215.302269ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (189.438552ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (213.869494ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (201.302397ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (11.237925ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (214.146727ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (270.063789ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (311.130976ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (223.387591ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.406729ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.263697ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.324578ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.483082ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (30.055237ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.498732ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (5.798485ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.467227ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.356714ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.10348ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (234.07889ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (259.557245ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (352.16091ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (907.683249ms)
|
||||
✔ H4: self-takeover is refused (187.73179ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (440.424074ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (1164.253826ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (241.239331ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (573.404858ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (256.51688ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (193.027945ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (197.708066ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (591.28546ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (282.4104ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (194.783597ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (886.689645ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (311.897148ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (751.010704ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (208.512644ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (358.334627ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.70851ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (671.255297ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (556.285268ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (787.434113ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (2957.376126ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (661.778715ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (26.236506ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (6.95878ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (1.567562ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (1.651404ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (2.56735ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.513114ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (2.48256ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (0.910714ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.285721ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (4.69642ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (5.261767ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (6.180982ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (5.006691ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (7.177121ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (8.805197ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (2.411125ms)
|
||||
✔ F9: registrations never add or redirect a root (2.26304ms)
|
||||
✔ F10: a header cwd naming another project is refused (4.895154ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.884505ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (4.486557ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (2.441582ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.561291ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (1.034111ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (509.355266ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (5.083237ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (1.580284ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.473366ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.275457ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (2.101512ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (747.525123ms)
|
||||
✔ the engine pin holds for the installed package (1.784386ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (264.135133ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (531.936436ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (237.293073ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (551.245113ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (576.311424ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (225.332594ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (22.065037ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (338.37759ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (197.412407ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (295.772071ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (472.33043ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (1912.031085ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (198.570749ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (288.331066ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (186.557763ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (207.68415ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (355.674046ms)
|
||||
✔ N10: fake conformance (31.915637ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (450.594266ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (283.377092ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (290.965603ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (356.663196ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (361.616015ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (370.687476ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (208.330566ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (338.791689ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (641.803164ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (486.758085ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (553.977848ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (249.946582ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (195.157166ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (206.967544ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (235.94119ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (207.906207ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 171
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 60060.417812
|
||||
@@ -0,0 +1,7 @@
|
||||
packages/conversation/README.md: OK
|
||||
packages/conversation/src/cohort.mjs: OK
|
||||
packages/conversation/src/controller.mjs: OK
|
||||
packages/conversation/tests/claim.test.mjs: OK
|
||||
packages/conversation/tests/cohort.test.mjs: OK
|
||||
packages/conversation/tests/fake-pi.mjs: OK
|
||||
packages/conversation/tests/harness.mjs: OK
|
||||
@@ -0,0 +1,41 @@
|
||||
# mutate.py <id>: apply one named mutant (each edit exact text, must match once). Run from the tree root.
|
||||
import sys
|
||||
C = "packages/conversation/"
|
||||
CT = C + "src/controller.mjs"
|
||||
CO = C + "src/cohort.mjs"
|
||||
RELSTOP = (CT, " await this.#releaseScope(\"force-stop\", proven);\n", "")
|
||||
RELCLOSE = (CT, " if (this.b?.state === \"stopped\" && this.#stopped(this.stops.get(this.b.stop))) await this.#releaseScope(\"close\");\n", "")
|
||||
GUARD = " if (!rec || rec.state !== \"stopped\" || rec.proof?.kind !== \"cohortProof\" || !rec.shim) return null;\n"
|
||||
M = {
|
||||
"norelstop": [RELSTOP],
|
||||
"norelclose": [RELCLOSE],
|
||||
"norel": [RELSTOP, RELCLOSE],
|
||||
# releaseCohort reports the unit absent without looking.
|
||||
"nowait": [(CO, " const end = Date.now() + waitMs;\n", " return { outcome: \"released\", unit: \"absent\" };\n const end = Date.now() + waitMs;\n")],
|
||||
# releaseCohort doesn't wait for systemd at all, and says so.
|
||||
"wait0": [(CO, "shimSocket, waitMs = 3000 })", "shimSocket, waitMs = 0 })")],
|
||||
# #releaseScope keeps only the shim check; callers unchanged.
|
||||
"noguard": [(CT, GUARD, " if (!rec || !rec.shim) return null;\n")],
|
||||
# close releases whenever the binding reads stopped, with no #stopped check.
|
||||
"closenoproof": [(CT, " if (this.b?.state === \"stopped\" && this.#stopped(this.stops.get(this.b.stop))) await", " if (this.b?.state === \"stopped\") await")],
|
||||
# The release result isn't pushed to observers.
|
||||
"nopush": [(CT, " this.#push({ kind: \"evidence\", evidence: entry });\n", "")],
|
||||
# The release result isn't recorded in evidence.releases.
|
||||
"noevid": [(CT, " this.evidence.releases.push(entry);\n", "")],
|
||||
# releaseCohort drops the null-ID check.
|
||||
"invnull": [(CO, "if (!invocationId || hello.invocationId !== invocationId)", "if (hello.invocationId !== invocationId)")],
|
||||
# releaseCohort sends release with no hello and no ID check.
|
||||
"nohello": [(CO, " const hello = await shimRequest(shimSocket, \"hello\");\n if (!hello.ok) return { outcome: \"unavailable\", reason: hello.unavailable };\n if (!invocationId || hello.invocationId !== invocationId) return { outcome: \"unavailable\", reason: \"the shim does not answer for the recorded scope; nothing released\" };\n", "")],
|
||||
# The force stop releases before the claim records stopped (guard intact).
|
||||
"early": [RELSTOP, (CT, " let session = null;\n try {\n session = this.#readSession();", " await this.#releaseScope(\"force-stop\", this.claim);\n let session = null;\n try {\n session = this.#readSession();")],
|
||||
# N2: killShims signals any unit.
|
||||
"n2": [(C + "tests/harness.mjs", " if (!/^mosaic-chat-/.test(s.unit ?? \"\")) {\n", " if (false) {\n")],
|
||||
}
|
||||
if "--files" in sys.argv:
|
||||
print(" ".join(sorted({f for f, _, _ in M[sys.argv[1]]}))); sys.exit(0)
|
||||
for f, old, new in M[sys.argv[1]]:
|
||||
s = open(f).read()
|
||||
n = s.count(old)
|
||||
if n != 1: sys.exit(f"{sys.argv[1]}: {n} matches in {f}")
|
||||
open(f, "w").write(s.replace(old, new))
|
||||
print(f)
|
||||
@@ -0,0 +1,206 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (214.832977ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (34.571677ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (18.879732ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (349.856205ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (468.272065ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (246.271703ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (192.56229ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (182.938147ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.954834ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (12454.017135ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (39976.388886ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (262.294369ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (142.541432ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (624.846842ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (286.900564ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (342.941382ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (104.478382ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (190.144174ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (268.593624ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (753.254962ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (186.586663ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (93.32013ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (64.398658ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (4.057996ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.037509ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (1.746168ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (23.881335ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (1036.304245ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (452.443886ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (735.320365ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (2967.485553ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (715.430564ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (825.969742ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (924.961689ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5737.072887ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (942.242091ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (905.786674ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (693.53554ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (775.787553ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (414.400446ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (442.580709ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3274.837948ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (24.64145ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (507.74544ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (286.272ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (100.961673ms)
|
||||
✔ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (784.259864ms)
|
||||
✔ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (768.208234ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1354.770418ms)
|
||||
✔ R4: after a normal engine exit the scope stays until a proven force stop releases it (675.069233ms)
|
||||
✖ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (453.184638ms)
|
||||
✔ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (134.193267ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (23.312722ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (207.223917ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (206.080832ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (191.759441ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (339.985059ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (197.965187ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.47993ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (200.687283ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (296.861259ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (209.740754ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (178.594626ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (195.227527ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (208.925959ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (11.060451ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (203.422354ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (207.897951ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (230.896474ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (217.397873ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.404488ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.278864ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.292223ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.521121ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (31.01716ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.49446ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (4.739719ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.366934ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.351546ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.103886ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (224.942482ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (253.890125ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (293.872273ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (868.419123ms)
|
||||
✔ H4: self-takeover is refused (179.079168ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (418.289419ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (990.164509ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (230.250826ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (537.189837ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (264.986708ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (124.086351ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (171.589576ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (598.687091ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (286.895845ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (199.560486ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (869.005692ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (438.820807ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (1007.925195ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (221.259857ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (345.731774ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.824252ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (682.841869ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (602.766646ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (674.939883ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (3399.227382ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (680.860103ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (30.517338ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (5.794644ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (1.662698ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (1.64933ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (2.495017ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.494239ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (1.989199ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (0.902555ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.329506ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (3.568865ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (4.766891ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (5.988037ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (4.686158ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (6.598091ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (8.271214ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (1.931874ms)
|
||||
✔ F9: registrations never add or redirect a root (1.698626ms)
|
||||
✔ F10: a header cwd naming another project is refused (4.397501ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.79825ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (5.444411ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (2.201517ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.572177ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.796574ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (501.901364ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (4.31991ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (1.386812ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.091305ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.087751ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (1.778953ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (772.978757ms)
|
||||
✔ the engine pin holds for the installed package (2.858036ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (261.191961ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (513.396416ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (258.172227ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (502.50312ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (485.301356ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (237.887749ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (21.972247ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (347.278229ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (187.964679ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (298.042589ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (472.695037ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (1869.203815ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (198.034335ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (283.172908ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (194.256775ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (202.536671ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (396.115669ms)
|
||||
✔ N10: fake conformance (30.808263ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (444.599863ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (270.756574ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (374.4837ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (575.793725ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (389.685398ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (380.19316ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (142.851081ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (317.626646ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (742.694744ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (487.790495ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (483.990364ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (230.539183ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (190.167064ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (401.425992ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (225.176688ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (179.416997ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 170
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 60546.123145
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:877:1
|
||||
✖ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (453.184638ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- [
|
||||
- 438467,
|
||||
- 'r5-not-mosaic-cfc8601f3b56'
|
||||
- ]
|
||||
- ]
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:898:14)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ [ 438467, 'r5-not-mosaic-cfc8601f3b56' ] ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (207.636312ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (31.671819ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (17.531549ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (365.224435ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (375.743275ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (238.900008ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (225.805156ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (299.615632ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.531001ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (13253.125745ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (39168.220723ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (265.09423ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (139.935762ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (610.02107ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (282.459774ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (329.709422ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (215.645266ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (283.574969ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (499.324428ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (949.098027ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (199.013326ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (91.935987ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (85.208259ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (4.098139ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.436034ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (1.844956ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (24.673716ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (976.65867ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (475.498215ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (942.748798ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (3043.619425ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (1136.345293ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (888.096775ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (768.265805ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5881.341427ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (1038.181376ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (778.528574ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (454.270423ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (731.569118ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (487.686365ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (880.595621ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3957.867674ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (60.917654ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (595.755511ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (476.456199ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (83.135937ms)
|
||||
✖ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (8643.176352ms)
|
||||
✖ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (576.569113ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1317.296796ms)
|
||||
✖ R4: after a normal engine exit the scope stays until a proven force stop releases it (8688.575873ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (596.211364ms)
|
||||
✔ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (122.08846ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.976516ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (202.474345ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (216.296105ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (198.638065ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (278.82666ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (194.620148ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.437381ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (200.939948ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (341.197899ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (337.851502ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (295.460905ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (239.146079ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (227.685473ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (10.981311ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (214.520823ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (221.356733ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (274.526795ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (217.87438ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.583858ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.288987ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.331664ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.50306ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (30.957714ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.461908ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (5.689579ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.378544ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.335821ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.093501ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (225.033292ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (246.890313ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (312.851641ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (811.813782ms)
|
||||
✔ H4: self-takeover is refused (297.074042ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (617.007528ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (1112.052305ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (251.177186ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (552.166906ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (270.296071ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (174.004826ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (239.627211ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (893.349674ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (654.644864ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (223.473935ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (972.900194ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (384.526377ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (830.365315ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (235.744185ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (364.981386ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.648115ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (726.725677ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (609.885128ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (777.19598ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (3161.318197ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (772.608145ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (26.243188ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (5.924855ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (1.71635ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (1.910233ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (2.719744ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.375009ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (1.976274ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (0.811346ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.381024ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (3.412276ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (5.38275ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (4.192834ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (4.362975ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (6.411819ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (7.614048ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (1.774105ms)
|
||||
✔ F9: registrations never add or redirect a root (1.893373ms)
|
||||
✔ F10: a header cwd naming another project is refused (5.077911ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.860447ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (4.159008ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (1.934562ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.296195ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.713412ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (514.555301ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (4.961625ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (1.499461ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.509135ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.110792ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (2.049583ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (771.592435ms)
|
||||
✔ the engine pin holds for the installed package (1.839777ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (258.023466ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (534.072833ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (237.137804ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (499.752552ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (433.973546ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (227.498429ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (21.085678ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (408.771003ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (319.475731ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (422.64905ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (536.684562ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (1926.54673ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (261.85206ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (526.165066ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (292.165984ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (556.174851ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (391.852322ms)
|
||||
✔ N10: fake conformance (31.082605ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (478.572614ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (311.539451ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (327.69438ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (377.85985ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (406.809075ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (415.148898ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (223.174587ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (362.138514ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (823.257562ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (522.049384ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (609.470456ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (310.027929ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (311.932454ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (200.59052ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (241.550105ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (205.758549ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 168
|
||||
ℹ fail 3
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 62347.19459
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:767:1
|
||||
✖ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (8643.176352ms)
|
||||
Error: timed out waiting for the release
|
||||
at until (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:49:33)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:774:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:784:1
|
||||
✖ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (576.569113ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- [
|
||||
- 'close',
|
||||
- 'released',
|
||||
- 'mosaic-chat-c113b34935ebb759fe6dcdcb4',
|
||||
- 'absent'
|
||||
- ]
|
||||
- ]
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:797:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ [ 'close', 'released', 'mosaic-chat-c113b34935ebb759fe6dcdcb4', 'absent' ] ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:855:1
|
||||
✖ R4: after a normal engine exit the scope stays until a proven force stop releases it (8688.575873ms)
|
||||
Error: timed out waiting for the release
|
||||
at until (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:49:33)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:869:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
@@ -0,0 +1,179 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (242.454215ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (52.417607ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (160.65193ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (691.684457ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (432.820347ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (253.91496ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (211.614144ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (208.267027ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.537314ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (11470.871921ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (38939.018387ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (278.675248ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (154.656012ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (646.680456ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (278.585947ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (359.19416ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (105.386296ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (202.941484ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (259.142319ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (827.508601ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (186.58325ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (96.006657ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (69.708438ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (4.133499ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.090929ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (1.773917ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (23.991006ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (1415.983918ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (524.641874ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (605.031463ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (2831.337028ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (576.370739ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (640.256395ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (506.917941ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5379.297787ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (778.851305ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (641.936043ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (520.03173ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (748.983034ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (330.971784ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (534.744906ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3289.235238ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (38.967813ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (343.168178ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (343.128554ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (182.540451ms)
|
||||
✔ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (602.938699ms)
|
||||
✔ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (606.854991ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1314.766263ms)
|
||||
✔ R4: after a normal engine exit the scope stays until a proven force stop releases it (930.984706ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (480.884572ms)
|
||||
✔ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (142.339444ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.722944ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (247.351219ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (420.645996ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (521.474171ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (341.666185ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (240.156116ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.40418ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (231.245874ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (319.232063ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (221.250466ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (202.770254ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (211.581179ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (215.479606ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (10.898457ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (225.85683ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (238.501084ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (275.812845ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (197.9187ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.423836ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.270355ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.321871ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.476881ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (30.293449ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.496557ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (5.904074ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.480359ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.348958ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.104714ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (240.114931ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (449.349522ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (659.741702ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (935.32517ms)
|
||||
✔ H4: self-takeover is refused (208.479759ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (447.288998ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (1098.784903ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (205.142031ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (648.251043ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (462.685827ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (328.233583ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (265.184216ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (616.056402ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (308.527542ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (192.810519ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (822.60304ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (339.630756ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (712.634315ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (189.604469ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (318.34834ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.636126ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (665.523681ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (547.749173ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (705.869893ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (2891.07586ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (642.516066ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (24.823327ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (9.549304ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (2.772234ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (2.76215ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (3.905107ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.598993ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (2.057413ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (0.904387ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.248313ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (3.214597ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (3.929992ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (4.295887ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (4.284949ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (6.156042ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (7.505119ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (1.595964ms)
|
||||
✔ F9: registrations never add or redirect a root (1.63173ms)
|
||||
✔ F10: a header cwd naming another project is refused (3.701919ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.657098ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (3.816836ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (1.963921ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.411975ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.82287ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (538.008331ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (4.843446ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (1.46375ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.297425ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.114937ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (2.057435ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (774.21722ms)
|
||||
✔ the engine pin holds for the installed package (2.880747ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (274.936394ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (541.096937ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (260.530316ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (1004.674992ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (554.175472ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (290.60681ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (22.238008ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (390.977012ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (205.52208ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (316.814445ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (502.975006ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (2028.624891ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (318.597754ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (330.129325ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (202.937284ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (229.999463ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (415.225114ms)
|
||||
✔ N10: fake conformance (31.200214ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (422.298086ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (261.198128ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (278.256096ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (346.926126ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (352.988913ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (323.874357ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (191.324181ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (323.262106ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (664.737663ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (507.685055ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (537.623524ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (241.815985ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (199.432894ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (160.372641ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (218.528118ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (191.594051ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 171
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 59472.098959
|
||||
@@ -0,0 +1,200 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (215.175505ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (32.123911ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (19.947087ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (361.835331ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (373.005155ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (238.513988ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (205.167951ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (202.383689ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.419459ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (11684.686206ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (39230.305323ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (236.41881ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (147.287367ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (613.636414ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (275.578534ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (341.422176ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (107.676756ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (198.072221ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (266.304495ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (730.669406ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (187.110567ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (95.851048ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (76.884194ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (3.539764ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.075101ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (1.806082ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.068002ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (997.736595ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (469.162088ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (804.119799ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (2997.757121ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (729.52872ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (792.205153ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (673.905973ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5486.250965ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (990.216545ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (837.495754ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (642.639592ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (678.955973ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (350.077895ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (518.641333ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3228.488102ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (23.172026ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (302.450932ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (260.286668ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (80.932038ms)
|
||||
✔ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (653.46987ms)
|
||||
✔ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (656.712268ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1060.158703ms)
|
||||
✔ R4: after a normal engine exit the scope stays until a proven force stop releases it (628.991464ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (446.077873ms)
|
||||
✖ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (331.786453ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.018511ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (188.241301ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (199.683994ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (193.024131ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (277.606543ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (194.693048ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.415239ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (198.310138ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (306.778869ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (206.138101ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (186.176669ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (211.784032ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (225.731411ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (10.913672ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (236.515098ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (225.947569ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (243.6901ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (196.128802ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.405605ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.279138ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.326428ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.494175ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (30.983743ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.45172ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (5.702253ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.366719ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.331497ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.101143ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (223.054032ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (250.788056ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (287.389348ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (814.418228ms)
|
||||
✔ H4: self-takeover is refused (195.676861ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (449.066449ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (1073.06667ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (143.437118ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (525.344102ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (285.372611ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (190.507347ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (167.462773ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (700.21254ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (318.071983ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (196.686314ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (867.634832ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (326.053962ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (762.791653ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (203.681651ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (349.783785ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.620231ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (667.892791ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (595.329767ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (742.930505ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (2985.741805ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (840.382607ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.361529ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (5.673021ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (1.518823ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (1.541892ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (2.29352ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.393107ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (1.794143ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (0.728582ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.271015ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (3.16817ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (5.241423ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (4.554433ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (4.648447ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (6.948451ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (8.568872ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (2.061596ms)
|
||||
✔ F9: registrations never add or redirect a root (1.853088ms)
|
||||
✔ F10: a header cwd naming another project is refused (3.964189ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.74024ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (4.214047ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (2.056795ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.35793ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.810101ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (522.05669ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (4.37069ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (1.399285ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.119375ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.001825ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (1.84706ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (753.612106ms)
|
||||
✔ the engine pin holds for the installed package (1.79135ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (276.769999ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (525.937309ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (242.117439ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (474.25551ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (430.225951ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (229.095402ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (20.780278ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (363.88483ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (201.996198ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (291.201265ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (538.966176ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (1893.839ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (178.846046ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (339.902106ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (261.426397ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (215.160915ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (385.564727ms)
|
||||
✔ N10: fake conformance (32.658519ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (434.018885ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (271.775909ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (288.577906ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (354.33718ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (365.912888ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (361.736564ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (210.771803ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (296.049537ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (692.843889ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (541.475301ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (529.983629ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (224.787674ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (215.336187ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (208.24288ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (223.435019ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (209.137688ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 170
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 59094.134786
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:912:1
|
||||
✖ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (331.786453ms)
|
||||
AssertionError [ERR_ASSERTION]: scope another-invocation: {"outcome":"released","unit":"absent"}
|
||||
+ actual - expected
|
||||
|
||||
+ 'released'
|
||||
- 'unavailable'
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:923:14)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'released',
|
||||
expected: 'unavailable',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (610.094505ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (33.12307ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (23.973168ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (384.038016ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (428.347034ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (241.353156ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (200.742859ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (206.818614ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.525433ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (12124.530569ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (40839.021146ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (250.397046ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (139.425969ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (583.534778ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (283.083002ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (330.086525ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (105.6266ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (191.542767ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (259.1853ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (724.437134ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (181.303625ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (90.716408ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (77.665155ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (4.509003ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.062282ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (1.738483ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (27.373037ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (1271.492539ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (458.680229ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (792.75075ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (3054.894774ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (692.192928ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (786.21189ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (760.868817ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5717.843605ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (956.549684ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (851.987246ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (676.552246ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (636.004254ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (325.995728ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (605.183971ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3226.919695ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (31.317048ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (426.608535ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (351.518947ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (301.803126ms)
|
||||
✔ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (754.50599ms)
|
||||
✔ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (793.335128ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1460.706899ms)
|
||||
✔ R4: after a normal engine exit the scope stays until a proven force stop releases it (707.820782ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (657.499706ms)
|
||||
✔ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (136.790576ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (23.117974ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (618.019409ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (224.991426ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (213.214083ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (322.033932ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (203.882941ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.436886ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (203.240369ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (299.252018ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (219.22757ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (186.117243ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (221.991726ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (210.761669ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (11.039911ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (211.16259ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (221.603278ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (242.256732ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (275.145616ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.588289ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.309744ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.382715ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.60344ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (31.480713ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.558933ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (5.874015ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.480526ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.39134ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.108651ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (242.468032ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (673.637213ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (306.495236ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (847.416441ms)
|
||||
✔ H4: self-takeover is refused (195.993008ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (443.154085ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (1069.92806ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (296.095444ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (710.574632ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (313.754055ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (226.490518ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (202.547513ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (608.495252ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (291.863531ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (172.161863ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (869.340732ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (372.192425ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (729.785777ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (190.018824ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (334.35663ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.667452ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (663.382785ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (555.842185ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (669.501961ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (3084.088943ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (662.615128ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (26.363449ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (5.61387ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (1.520597ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (1.553279ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (2.278146ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.547081ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (1.995354ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (0.832284ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.314726ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (3.314305ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (9.678218ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (4.811949ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (4.48356ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (6.049584ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (7.433738ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (1.874251ms)
|
||||
✔ F9: registrations never add or redirect a root (1.763297ms)
|
||||
✔ F10: a header cwd naming another project is refused (3.883323ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.65573ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (3.843136ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (1.94814ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.275445ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.720388ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (666.350283ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (5.268648ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (1.513312ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.481289ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.172609ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (2.391348ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (816.996812ms)
|
||||
✔ the engine pin holds for the installed package (1.614015ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (249.664164ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (584.126993ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (274.485645ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (923.194597ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (486.09061ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (237.842834ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (22.339844ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (353.311948ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (210.430558ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (311.426841ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (487.947066ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (1935.291269ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (203.686582ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (297.116229ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (204.010468ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (236.410034ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (353.208355ms)
|
||||
✔ N10: fake conformance (31.847987ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (430.153169ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (289.77623ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (288.056445ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (365.472373ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (349.061445ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (341.141324ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (190.364759ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (340.080589ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (581.159525ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (520.387ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (382.727521ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (203.365545ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (160.159886ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (319.398856ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (140.229846ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (208.737698ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 171
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 61444.862992
|
||||
@@ -0,0 +1,212 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (878.142482ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (38.642847ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (27.049701ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (423.115214ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (569.429638ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (291.024999ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (253.947539ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (369.718253ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.543172ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (13306.114572ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (42073.698569ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (417.874884ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (227.856985ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (685.775484ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (460.462733ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (583.079714ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (311.209318ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (370.989809ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (1009.400293ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (2258.036637ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (441.60858ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (165.913368ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (108.516068ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (3.474591ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.082517ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (1.800422ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (26.795539ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (3270.19909ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (544.687107ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (2669.762301ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (5019.494141ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (2606.491841ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (2636.874347ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (2748.981285ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5266.075278ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (754.554968ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (633.525859ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (525.698051ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (1174.519814ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (615.154411ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (731.49351ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3416.71319ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (46.311676ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (562.402939ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (893.973144ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (86.294421ms)
|
||||
✖ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (10630.94396ms)
|
||||
✖ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (1481.599963ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1885.303906ms)
|
||||
✖ R4: after a normal engine exit the scope stays until a proven force stop releases it (10743.860597ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (471.104443ms)
|
||||
✔ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (136.404351ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (24.052178ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (253.606154ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (873.176732ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (244.669154ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (452.468999ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (235.925916ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.534407ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (240.495052ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (357.955535ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (389.798238ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (327.826574ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (253.655188ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (250.015847ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (10.004271ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (254.498193ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (324.03991ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (372.942129ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (391.276216ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.400551ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.271842ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.309679ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.519175ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (30.955159ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.455663ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (4.642582ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.350907ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.336209ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.098638ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (229.244155ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (931.86434ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (347.41319ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (1085.910085ms)
|
||||
✔ H4: self-takeover is refused (257.530138ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (744.914659ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (1430.014975ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (442.990461ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (1167.352159ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (439.2164ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (258.76511ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (299.493422ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (772.790955ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (350.769507ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (379.676755ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (1281.275523ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (436.494525ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (971.17841ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (247.735368ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (414.280176ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.629383ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (715.260501ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (707.128591ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (951.012134ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (2918.165215ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (678.092719ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.84205ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (7.201719ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (2.090269ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (2.029281ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (2.52071ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.537232ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (2.247922ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (0.748357ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.263129ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (3.133351ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (3.893212ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (4.248625ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (4.739148ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (6.952127ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (8.336624ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (1.887238ms)
|
||||
✔ F9: registrations never add or redirect a root (1.948292ms)
|
||||
✔ F10: a header cwd naming another project is refused (4.378338ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.861924ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (4.579126ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (2.119264ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.57584ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.840877ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (595.010664ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (6.164318ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (2.538841ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.601523ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.160496ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (2.183738ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (1110.90821ms)
|
||||
✔ the engine pin holds for the installed package (2.212279ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (304.260419ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (547.754943ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (282.891716ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (1227.543291ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (642.528708ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (271.077926ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (21.35836ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (455.332863ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (369.101589ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (437.443115ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (584.582297ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (2020.161461ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (269.943094ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (409.352777ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (267.963605ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (305.256749ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (557.010403ms)
|
||||
✔ N10: fake conformance (32.716305ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (560.964562ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (320.358221ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (475.897401ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (611.31702ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (490.381303ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (436.854463ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (268.116114ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (446.490817ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (933.563392ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (673.656544ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (646.760684ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (418.093753ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (225.56854ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (211.51223ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (244.075296ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (240.028765ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 168
|
||||
ℹ fail 3
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 69590.726236
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:767:1
|
||||
✖ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (10630.94396ms)
|
||||
Error: timed out waiting for the release
|
||||
at until (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:49:33)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:774:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:784:1
|
||||
✖ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (1481.599963ms)
|
||||
AssertionError [ERR_ASSERTION]: {"loadState":"loaded","activeState":"active","invocationId":"94b85a3b308d429aa17d8c0ea60264a3","controlGroup":"/user.slice/user-1000.slice/[email protected]/app.slice/mosaic-chat-ca660028b2d51d3e4ca6fa194.scope"}
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:796:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: false,
|
||||
expected: true,
|
||||
operator: '==',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:855:1
|
||||
✖ R4: after a normal engine exit the scope stays until a proven force stop releases it (10743.860597ms)
|
||||
Error: timed out waiting for the release
|
||||
at until (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:49:33)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:869:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
@@ -0,0 +1,196 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (549.769276ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (183.832441ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (171.078605ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (550.102512ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (466.007231ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (272.268952ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (262.276804ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (243.861149ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (3.250658ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (13950.015565ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (44042.326088ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (404.17413ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (162.613114ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (511.703889ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (323.433367ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (422.41534ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (207.13533ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (478.974948ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (551.504938ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (1175.951132ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (295.599116ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (123.528054ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (215.900544ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (4.331908ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.119151ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (1.748078ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (24.636913ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (1314.738715ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (598.452181ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (692.138771ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (2938.209222ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (627.601475ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (873.322401ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (839.452405ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5526.357229ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (1129.148201ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (1127.737778ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (529.247992ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (887.403115ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (558.597602ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (934.096015ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3383.067677ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (47.709219ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (592.703545ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (353.427654ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (93.60854ms)
|
||||
✔ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (740.77988ms)
|
||||
✖ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (819.411715ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1925.429506ms)
|
||||
✔ R4: after a normal engine exit the scope stays until a proven force stop releases it (1005.792931ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (448.140958ms)
|
||||
✔ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (320.187336ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (24.78178ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (679.591127ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (533.221819ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (255.634857ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (352.961262ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (257.62546ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.421183ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (269.4411ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (338.499728ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (264.859211ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (278.887695ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (260.139551ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (258.33505ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (10.966316ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (254.533917ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (279.900767ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (395.124817ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (448.745428ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.402114ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.259207ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.314474ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.500785ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (31.097398ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.495254ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (5.797253ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.468983ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.348541ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.109974ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (229.555437ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (964.431602ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (412.139275ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (1041.323053ms)
|
||||
✔ H4: self-takeover is refused (243.288037ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (580.46802ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (1378.017816ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (527.766553ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (1228.54517ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (476.617114ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (246.871324ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (247.015852ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (781.859336ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (320.385825ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (263.893093ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (1056.487335ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (431.711242ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (985.215428ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (239.110923ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (405.514807ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.59531ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (811.725563ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (668.708387ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (867.311161ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (3541.272093ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (734.161313ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (35.901282ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (6.588807ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (2.072726ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (2.411299ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (2.92073ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (2.024187ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (3.544249ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (1.366745ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (2.067544ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (5.9044ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (5.755862ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (8.718923ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (9.2026ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (9.481285ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (8.301792ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (2.267328ms)
|
||||
✔ F9: registrations never add or redirect a root (1.873746ms)
|
||||
✔ F10: a header cwd naming another project is refused (4.416567ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.769206ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (4.308183ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (2.068615ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.374725ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.798119ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (585.33114ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (5.213778ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (15.711101ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.691723ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.24185ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (2.301964ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (824.23661ms)
|
||||
✔ the engine pin holds for the installed package (2.511902ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (305.937194ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (587.730228ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (282.523964ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (1315.855797ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (553.236509ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (303.895555ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (21.884309ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (454.595018ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (251.917455ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (374.217356ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (593.655539ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (2003.021059ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (428.78533ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (421.379902ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (277.127749ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (295.792929ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (470.222624ms)
|
||||
✔ N10: fake conformance (32.724154ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (597.907516ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (353.272679ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (346.004684ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (425.822733ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (449.275563ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (432.897328ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (266.807496ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (467.001478ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (944.08151ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (708.360088ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (800.573429ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (309.904989ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (249.235737ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (356.633631ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (348.562061ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (346.839073ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 170
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 69745.158869
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:784:1
|
||||
✖ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (819.411715ms)
|
||||
AssertionError [ERR_ASSERTION]: {"loadState":"loaded","activeState":"active","invocationId":"57f1c8ae68c94304aa7231301f396395","controlGroup":"/user.slice/user-1000.slice/[email protected]/app.slice/mosaic-chat-cdf9359d8fbf3a52888767148.scope"}
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:796:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: false,
|
||||
expected: true,
|
||||
operator: '==',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (272.264638ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (46.329468ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (29.629157ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (455.910736ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (2765.552141ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (381.851999ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (234.91902ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (240.827066ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.405225ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (17091.443612ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (44580.219596ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (2118.993554ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (918.667986ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (1230.632529ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (424.058027ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (438.232889ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (190.130178ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (327.538779ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (645.070589ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (1518.943207ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (293.724772ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (132.776026ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (94.056128ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (4.136685ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.061635ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (1.759315ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.163013ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (849.774057ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (3011.947819ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (645.23619ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (3084.539394ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (761.564834ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (797.010489ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (737.196813ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5888.672791ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (1025.526708ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (3073.695765ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (647.654801ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (947.863184ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (465.589036ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (737.958093ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3332.063326ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (39.969918ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (452.785563ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (425.873865ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (268.671198ms)
|
||||
✖ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (8674.808724ms)
|
||||
✔ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (674.743143ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1490.23582ms)
|
||||
✖ R4: after a normal engine exit the scope stays until a proven force stop releases it (8856.338719ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (515.110429ms)
|
||||
✔ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (139.672464ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (26.092152ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (465.73134ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (257.543969ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (237.447584ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (1128.448536ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (1841.007765ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.421681ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (357.53504ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (338.140709ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (265.05974ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (358.266257ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (255.276237ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (270.731886ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (11.078345ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (247.03924ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (278.379754ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (327.580008ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (249.016957ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.448978ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.280753ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.356273ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.552806ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (31.270809ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.531662ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (4.829284ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.452394ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.341027ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.111466ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (254.61014ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (328.058872ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (348.940465ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (3456.102016ms)
|
||||
✔ H4: self-takeover is refused (237.915598ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (669.9985ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (1328.085776ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (291.439922ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (1367.806925ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (371.710321ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (227.526813ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (240.804604ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (1021.792562ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (331.76346ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (229.639927ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (1043.206581ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (470.756353ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (1367.437572ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (275.008156ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (354.824834ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.740873ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (769.496129ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (768.18178ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (822.658509ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (3460.258012ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (775.97791ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (29.483937ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (10.400479ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (2.937108ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (2.996079ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (4.229465ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (2.183748ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (3.621972ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (1.023009ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.532727ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (3.70294ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (4.600597ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (5.203509ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (4.910249ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (10.371946ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (8.384324ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (1.742271ms)
|
||||
✔ F9: registrations never add or redirect a root (1.704415ms)
|
||||
✔ F10: a header cwd naming another project is refused (3.93946ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.738278ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (4.512252ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (2.638599ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.659874ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.824867ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (601.165424ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (4.562248ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (1.484325ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.304021ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.048542ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (1.891326ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (909.191684ms)
|
||||
✔ the engine pin holds for the installed package (2.587502ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (313.885817ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (615.161295ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (302.503555ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (812.346666ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (2501.404705ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (836.894821ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (20.854475ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (413.248551ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (241.83536ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (401.540736ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (637.727834ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (2037.89795ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (238.605688ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (323.516026ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (198.047343ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (248.830916ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (707.403322ms)
|
||||
✔ N10: fake conformance (33.353164ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (580.178916ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (316.306497ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (312.625659ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (439.691488ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (449.887357ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (481.666056ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (332.680695ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (717.400644ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (990.328961ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (701.020369ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (704.194245ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (269.707647ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (240.292236ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (206.512511ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (247.664468ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (251.334814ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 169
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 79035.778078
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:767:1
|
||||
✖ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (8674.808724ms)
|
||||
Error: timed out waiting for the release
|
||||
at until (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:49:33)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:774:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:855:1
|
||||
✖ R4: after a normal engine exit the scope stays until a proven force stop releases it (8856.338719ms)
|
||||
Error: timed out waiting for the release
|
||||
at until (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:49:33)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:869:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
@@ -0,0 +1,196 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (252.76282ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (32.556357ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (23.056491ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (709.066069ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (487.476367ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (290.628914ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (352.460511ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (229.582168ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.587924ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (13041.514028ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (40470.164105ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (280.637101ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (160.162383ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (791.514986ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (367.135166ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (548.575282ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (169.391239ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (266.952232ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (499.528577ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (1606.641257ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (392.417304ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (110.328189ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (88.7047ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (4.055344ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.136465ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (1.807747ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.778535ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (1097.941753ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (618.425444ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (959.312007ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (3012.796016ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (794.482542ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (673.800067ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (873.414434ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5494.475609ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (772.209986ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (754.563319ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (596.916384ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (681.141782ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (332.761399ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (508.513527ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3263.607563ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (24.114853ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (387.960821ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (415.559143ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (243.618098ms)
|
||||
✔ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (967.576995ms)
|
||||
✖ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (674.52603ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1353.719258ms)
|
||||
✔ R4: after a normal engine exit the scope stays until a proven force stop releases it (738.744565ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (446.962573ms)
|
||||
✔ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (118.674979ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.510928ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (257.589105ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (231.993134ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (484.002995ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (380.834001ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (289.182872ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.394518ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (247.512217ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (464.148543ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (244.096816ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (352.441912ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (397.702007ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (212.915926ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (11.075776ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (219.605725ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (240.216628ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (281.069388ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (229.441098ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.481992ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.338608ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.39528ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.606777ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (31.379216ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.552502ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (5.818644ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.413633ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.38506ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.120694ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (266.518531ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (286.026276ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (581.728097ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (1181.443655ms)
|
||||
✔ H4: self-takeover is refused (231.583804ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (809.591093ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (1121.925304ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (257.123691ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (650.332055ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (311.397017ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (213.879261ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (210.997592ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (635.224587ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (271.869765ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (303.468838ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (1275.205501ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (463.867075ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (961.835066ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (206.880232ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (333.570665ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.663248ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (693.643989ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (644.789588ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (735.74316ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (2947.181453ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (646.774776ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.490174ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (7.485981ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (2.037302ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (2.054753ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (2.891253ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.761099ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (2.178947ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (0.875889ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.419607ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (4.623648ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (4.828658ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (4.818748ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (4.671285ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (6.615005ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (7.774748ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (1.66851ms)
|
||||
✔ F9: registrations never add or redirect a root (1.67955ms)
|
||||
✔ F10: a header cwd naming another project is refused (3.746602ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.683687ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (3.930784ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (1.998835ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.373597ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.780304ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (590.588393ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (5.299081ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (1.873606ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.69062ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.297448ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (2.291493ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (889.67595ms)
|
||||
✔ the engine pin holds for the installed package (2.152405ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (295.814043ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (601.847147ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (296.510831ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (567.046979ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (822.431994ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (320.541931ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (19.956625ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (595.244054ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (221.753144ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (455.502753ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (684.586084ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (1892.468337ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (201.693573ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (310.100779ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (218.480251ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (244.626252ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (322.809538ms)
|
||||
✔ N10: fake conformance (31.769008ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (585.507375ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (450.251226ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (444.818254ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (430.114795ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (554.464333ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (425.659594ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (209.813615ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (361.98249ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (672.938897ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (619.23191ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (541.171274ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (214.004046ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (191.118767ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (203.283951ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (196.919531ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (220.471721ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 170
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 65439.044393
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:784:1
|
||||
✖ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (674.52603ms)
|
||||
AssertionError [ERR_ASSERTION]: {"loadState":"loaded","activeState":"active","invocationId":"903d188abad8438eb75b7267d831f154","controlGroup":"/user.slice/user-1000.slice/[email protected]/app.slice/mosaic-chat-c6faf7cc2470ee281a3187356.scope"}
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:796:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: false,
|
||||
expected: true,
|
||||
operator: '==',
|
||||
diff: 'simple'
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
# run.sh <mutant>: mutate, run the conversation suite, list and kill shims left under TMPDIR, restore from backups.
|
||||
m=$1
|
||||
export TMPDIR=~/darkwing-scratch/r50a/tmp/mut-$m DOCKER_HOST=unix:///nonexistent.sock
|
||||
mkdir -p $TMPDIR
|
||||
M=~/darkwing-scratch/r50a/mut; cd ~/darkwing-scratch/r50a/wt2
|
||||
files=$(python3 -I $M/mutate.py $m --files)
|
||||
for f in $files; do cp -p $f $f.mutbak; done
|
||||
if python3 -I $M/mutate.py $m > /dev/null; then
|
||||
node --test "packages/conversation/tests/*.test.mjs" > $M/$m-conversation.txt 2>&1; e=$?
|
||||
else e=mutate-failed; fi
|
||||
left=$(ps -eo pid=,args= | grep -F "$TMPDIR/" | grep -F /shim.mjs | grep -v grep)
|
||||
n=$(printf '%s' "$left" | grep -c .)
|
||||
echo "$left" > $M/$m-shims-left.txt
|
||||
printf '%s\n' "$left" | while read pid rest; do
|
||||
[ -n "$pid" ] || continue
|
||||
u=$(tr '/' '\n' < /proc/$pid/cgroup | grep '^mosaic-chat-.*\.scope$')
|
||||
[ -n "$u" ] && systemctl --user kill --signal=SIGKILL "$u"
|
||||
kill -9 $pid 2>/dev/null
|
||||
done
|
||||
for f in $files; do mv $f.mutbak $f; done
|
||||
echo "$m rc $e $(grep -E '^ℹ (pass|fail)' $M/$m-conversation.txt | tr '\n' ' ') shims-left $n" >> $M/summary.txt
|
||||
@@ -0,0 +1,14 @@
|
||||
norel rc 1 ℹ pass 168 ℹ fail 3 shims-left 0
|
||||
norelstop rc 1 ℹ pass 169 ℹ fail 2 shims-left 0
|
||||
norelclose rc 1 ℹ pass 170 ℹ fail 1 shims-left 0
|
||||
nowait rc 1 ℹ pass 170 ℹ fail 1 shims-left 0
|
||||
wait0 rc 1 ℹ pass 169 ℹ fail 2 shims-left 0
|
||||
noguard rc 0 ℹ pass 171 ℹ fail 0 shims-left 0
|
||||
closenoproof rc 0 ℹ pass 171 ℹ fail 0 shims-left 0
|
||||
nopush rc 0 ℹ pass 171 ℹ fail 0 shims-left 0
|
||||
noevid rc 1 ℹ pass 168 ℹ fail 3 shims-left 0
|
||||
invnull rc 0 ℹ pass 171 ℹ fail 0 shims-left 0
|
||||
nohello rc 1 ℹ pass 170 ℹ fail 1 shims-left 0
|
||||
early rc 1 ℹ pass 169 ℹ fail 2 shims-left 0
|
||||
n2 rc 1 ℹ pass 170 ℹ fail 1 shims-left 0
|
||||
DONE
|
||||
@@ -0,0 +1,219 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (290.086066ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (44.957773ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (23.131115ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (637.077785ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (445.374396ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (247.078742ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (193.718414ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (198.117338ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.57093ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (11582.486741ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (36849.564432ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (344.545779ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (157.940285ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (496.286315ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (307.145767ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (453.001185ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (118.883569ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (235.074309ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (359.521897ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (1109.483584ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (243.987603ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (92.123869ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (71.633006ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (4.100515ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.112855ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (1.73842ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (24.318472ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (1025.576574ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (498.159768ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (805.312115ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (2776.626878ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (482.958173ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (779.561732ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (487.064758ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (5459.394056ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (702.900055ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (708.316616ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (508.039153ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (662.64577ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (387.315208ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (475.764592ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3341.78803ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (28.977014ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (411.872051ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (492.194212ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (83.416036ms)
|
||||
✔ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (536.463311ms)
|
||||
✖ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (739.590671ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1777.090727ms)
|
||||
✔ R4: after a normal engine exit the scope stays until a proven force stop releases it (819.661307ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (446.507505ms)
|
||||
✖ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (330.896923ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (19.672169ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (287.978301ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (476.284741ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (241.431675ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (312.606888ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (215.419658ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.409586ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (204.220135ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (296.143242ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (211.891745ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (198.009772ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (206.011814ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (200.006331ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (11.117292ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (210.618805ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (222.467738ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (259.265241ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (206.623104ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.802571ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.265097ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.324645ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.476686ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (31.042282ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.467595ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (5.676827ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.353573ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.329601ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.098485ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (225.090887ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (361.002007ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (553.400747ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (864.284679ms)
|
||||
✔ H4: self-takeover is refused (186.534216ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (441.4328ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (1052.373092ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (226.552137ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (657.25826ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (307.357098ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (196.952325ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (195.873936ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (585.483429ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (280.739277ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (163.492716ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (831.00536ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (332.510684ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (733.367004ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (191.835028ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (326.708222ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.607798ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (672.085374ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (572.542485ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (827.570551ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (2943.56165ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (687.243041ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (25.284081ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (9.428768ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (2.971496ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (3.022339ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (4.371745ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.875348ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (2.187135ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (1.004779ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.326717ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (3.566749ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (4.541763ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (5.332726ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (4.875969ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (6.916127ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (7.846235ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (1.626777ms)
|
||||
✔ F9: registrations never add or redirect a root (1.544104ms)
|
||||
✔ F10: a header cwd naming another project is refused (3.56537ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.656435ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (3.898825ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (2.413419ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.416841ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.70107ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (562.113682ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (4.508955ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (6.985134ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.234355ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.069822ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (1.892989ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (863.91415ms)
|
||||
✔ the engine pin holds for the installed package (2.023096ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (277.982515ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (619.256472ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (294.766141ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (850.613698ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (490.164117ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (253.599078ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (21.468707ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (351.919672ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (195.160502ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (299.696553ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (460.785199ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (1903.747276ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (196.499786ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (279.099894ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (201.04823ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (226.114075ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (350.848844ms)
|
||||
✔ N10: fake conformance (33.049926ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (418.738876ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (267.052895ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (268.030311ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (344.129349ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (353.03057ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (339.672487ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (200.445622ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (331.449206ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (716.672109ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (824.094311ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (556.738754ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (220.09405ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (183.984904ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (201.017789ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (171.460445ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (198.694677ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 169
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 58592.66983
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:784:1
|
||||
✖ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (739.590671ms)
|
||||
AssertionError [ERR_ASSERTION]: {"loadState":"not-found","activeState":"inactive","invocationId":null,"controlGroup":null}
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:796:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: false,
|
||||
expected: true,
|
||||
operator: '==',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/conversation/tests/cohort.test.mjs:912:1
|
||||
✖ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (330.896923ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
outcome: 'released',
|
||||
+ unit: 'still listed'
|
||||
- unit: 'absent'
|
||||
}
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/darkwing-scratch/r50a/wt2/packages/conversation/tests/cohort.test.mjs:927:12)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { outcome: 'released', unit: 'still listed' },
|
||||
expected: { outcome: 'released', unit: 'absent' },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
✔ W1: two processes acquire the same pair at once; exactly one claim (263.835627ms)
|
||||
✔ W1: two writers publish the same revision at once: one wins, the other gets null, the winner's record stays (33.922714ms)
|
||||
✔ W1: a revision name appears only after its bytes are synced; before that, only a temp file exists (19.082087ms)
|
||||
✔ W2: acquire while a claim is reserved or active refuses already-active (344.995ms)
|
||||
✔ W3: acquire while stopping, uncertain, or stopped without proof refuses unsafe-replacement (393.771992ms)
|
||||
✔ W4: same session with another seat tuple, and the reverse, both refuse; a loser on the seat key closes it no-unit (236.263447ms)
|
||||
✔ W4: a hard link of one session under another seat is the same session: the second controller refuses already-active and launches nothing (195.450653ms)
|
||||
✔ W4: a copy of one session under another seat is the same session: the second controller refuses already-active and launches nothing (203.896544ms)
|
||||
✔ W4: a session header ID that changes after construction refuses target; nothing is claimed or launched (2.295169ms)
|
||||
✔ W5: SIGKILL between every publication barrier of acquire and transition; restart never finds two holders or a lost claim (13357.324433ms)
|
||||
✔ W5: SIGKILL between every publication barrier of release; restart finishes or holds the release (41363.212166ms)
|
||||
✔ W6: controller killed mid-turn while the engine lives; restart is uncertain, no launch, prompts refuse (378.679871ms)
|
||||
✔ W12: a live owner paused with SIGSTOP; a second controller refuses already-active and changes nothing (218.50041ms)
|
||||
✔ W13: crash after the engine spawns, before active; restart finds the live unit: uncertain, no second spawn, force stop only (626.283151ms)
|
||||
✔ W14: crash after reservation, before the spawn marker: stopped with a no-unit observation; the pair is free (395.139339ms)
|
||||
✔ W20: crash after the spawn marker, scope collected; uncertain in both runs, the marker is copied, no launch until a boot proof (522.985147ms)
|
||||
✔ W15: crash between the two keys during release; restart finishes it under the same claim ID (172.925678ms)
|
||||
✔ W7: recorded boot ID differs on the same machine: stopped with a boot proof; open tool calls become uncertain (329.404447ms)
|
||||
✔ W8: resume after a proven stop with the same pins: new claim ID, generation +1, same conversation, branch and leaf (564.288297ms)
|
||||
✔ W9: resume with a changed binary, argv digest, branch or leaf is refused and the claim is unchanged (1650.444223ms)
|
||||
✔ W11: the controller writes no session file; only the fake engine's own appends appear (570.416048ms)
|
||||
✔ W16: a highest revision that won't parse holds the pair uncertain; the older stopped revision is not reused (142.783122ms)
|
||||
✔ W17: a claim root copied from another host refuses foreign-host and promotes nothing (96.074527ms)
|
||||
✔ G1: a session path or claim root under .pi/state, ~/.claude, the data root or a registration refuses at construction (4.734535ms)
|
||||
✔ G2: a symlink inside the fixture root to a live session file is refused by the real-path check (1.221374ms)
|
||||
✔ G3: a fixture path swapped for a live path after construction is refused at bind (2.03125ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (27.882076ms)
|
||||
✔ K1: force stop kills a tool child that called setsid; stopped with a verified proof (986.339812ms)
|
||||
✔ K2: K1 on the process-group fallback ends uncertain, never stopped (435.76874ms)
|
||||
✔ K3: SIGTERM acknowledged while a member lives: stopping until the kill phase, never stopped from TERM (787.726583ms)
|
||||
✔ K4: two engines; force stop one; the other survives by independent observation (2967.369504ms)
|
||||
✔ K5: a stop during a tool call leaves the effect uncertain, and it is shown (671.674039ms)
|
||||
✔ K12: a member forking in a loop: the freeze stops it, enumeration is complete, populated 0 after cgroup.kill (786.857027ms)
|
||||
✔ K13: a member writing its pid into another cgroup is refused by the namespace; the kill is complete (752.58161ms)
|
||||
✔ K15: the shim gone, engine/cgroup.events unreadable, or the engine cgroup missing: evidence unavailable, not empty; uncertain (6071.418813ms)
|
||||
✔ K10: controller killed between the TERM and kill phases: restart checks the invocation ID and re-runs from TERM for the same stop (1108.339907ms)
|
||||
✔ K11: controller killed after the confirmation is recorded, before TERM: restart checks the invocation ID and re-runs from TERM for the same stop (752.39347ms)
|
||||
✔ K14: a unit with the recorded name but another invocation ID: evidence unavailable, no signals, uncertain (701.090707ms)
|
||||
✔ K6: recover without proof, without confirmation, or with changed pins is refused (838.697192ms)
|
||||
✔ K7: recover after proof, then launch: new claim and execution, generation +1, same leaf; the cancelled prompt is not replayed (451.857426ms)
|
||||
✔ K8: an engine that loads another leaf on resume is refused before admission; it stays claimed until a proven stop (621.992132ms)
|
||||
✔ K9: an interrupt that never settles stays uncertain; force stop stays available; takeover is refused while fenced (3265.179691ms)
|
||||
✔ K16: a claim from another machine ID refuses foreign-host; no boot proof is issued (61.608754ms)
|
||||
✔ K17: two launcher calls with one eligibility record: one launch, the other refuses, no second engine (505.268298ms)
|
||||
✔ K18: the leaf changes after eligibility: launch refused; the reservation stays until released with proof (315.958297ms)
|
||||
✔ K19: a scope launched with only the engine environment still reaches the user manager; the engine sees no other names (82.303955ms)
|
||||
✔ R1: after a proven force stop the controller releases the scope; the shim and the unit are gone (425.121302ms)
|
||||
✔ R2: close releases the scope of a binding proven stopped, once, when the stop's own release hasn't run (751.510622ms)
|
||||
✔ R3: no release after an unavailable stop or an unverified proof: the scope and its shim stay as evidence (1232.957678ms)
|
||||
✔ R4: after a normal engine exit the scope stays until a proven force stop releases it (725.078506ms)
|
||||
✔ R5: the harness finds a running shim and reaps it, and never signals a shim outside a mosaic-chat- scope (Filbert N1 and N2 on #1533) (451.512578ms)
|
||||
✔ R6: releaseCohort releases nothing for another invocation ID or a cohort without a scope (368.639222ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (26.198722ms)
|
||||
✔ S1: `/goal x`, with leading spaces or a tab, refuses text-policy at admission; zero engine bytes (272.764902ms)
|
||||
✔ S2: every prefix pinned Pi interprets is refused, from the list the code uses; the rest reach the engine exactly (202.783521ms)
|
||||
✔ S3: `/goal` on the second line is pinned from the source: Pi checks only index 0, so it is admitted and sent exactly (192.04678ms)
|
||||
✔ S4: a `/` left in the composer is cleared when control transfers and returns; the next submit sends only the new text (292.204887ms)
|
||||
✔ S5: an observer terminal gets a paste then Enter, as send-message.sh does: not admitted: controller, nothing sent (185.35431ms)
|
||||
✔ S6: a mediated-shaped registration (no tmux) passed to the board's replyToRow: 409 no tmux session; exec never runs (0.428619ms)
|
||||
✔ S7: ESC, bracketed-paste markers and U+2028/U+2029 travel as one JSON string; the engine receives the exact text in one record (183.490273ms)
|
||||
✔ P3: a Pi confirm, select, input or editor dialog is shown disabled with a reason and never answered (298.840349ms)
|
||||
✔ E1: send, ack, user, toolCall, toolResult, final answer: shown once, no refresh, draft and reading position kept (212.323776ms)
|
||||
✔ E2: U+2028, U+2029 inside JSON strings and CRLF line ends each parse as one record, on the splitter and through the controller (192.627695ms)
|
||||
✔ E3: a multipart final, two blocks, null request correlation and duplicate delivery (204.735193ms)
|
||||
✔ E4: a page read after message_end but before its entry is persisted: marker at the seam, re-read after run-settled, each message once (192.736293ms)
|
||||
✔ E4: a gap or a new epoch also reconciles; nothing is concatenated across a gap (11.677071ms)
|
||||
✔ E5: an unknown native event gives no client event; evidence records its type and bytes; the terminal count goes up (189.14845ms)
|
||||
✔ E6: a tool result delayed across a pause and a reconnect is reconciled without a manual refresh (208.784609ms)
|
||||
✔ E7: the terminal renders the same stream as the library client, as observer and then as controller, and submits only as controller (239.169678ms)
|
||||
✔ terminal: engine control characters are made visible; a lost connection refuses submit (189.290774ms)
|
||||
✔ terminal: outcome unknown is shown as such, with no resend offer, and nothing is resent (0.359494ms)
|
||||
✔ terminal: text after Enter in the same input chunk starts the next message; it never joins the one submitted (0.242336ms)
|
||||
✔ terminal: a paste-start marker split right after its ESC still opens the paste; the Enter inside it never submits (0.291083ms)
|
||||
✔ terminal: Ctrl-T then Enter in one chunk is judged after the takeover, as if typed one key at a time (Filbert F2, #1507) (0.462721ms)
|
||||
✔ terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending (Darkwing T1 on #1522) (30.936244ms)
|
||||
✔ terminal: a hold inside held input holds again, and once it is drained later input and Ctrl-C still reach the terminal (Darkwing note 1 on #1522) (0.441437ms)
|
||||
✔ terminal: an action that throws still releases the input held behind it, in order, then rethrows (5.7378ms)
|
||||
✔ terminal: after an action throws, later input still runs; input() puts the error in the status line (Filbert N1 on #1522) (0.881127ms)
|
||||
✔ terminal: input() reports an error when it happens, so it never overwrites a later status; held input's promise doesn't carry the holder's error (Filbert N4 on #1522) (0.323355ms)
|
||||
✔ terminal: invisible and bidi characters are made visible; head, status and notice lines stay one line (0.106354ms)
|
||||
✔ every record these fixtures produced is a valid CHAT-01 record (E5: no record fails the schema) (245.401454ms)
|
||||
✔ H1: two takeovers with the same expected generation: one wins, +1; the other refuses generation (316.698551ms)
|
||||
✔ H2: the old controller's prompt after a takeover commits is refused with zero engine bytes (281.770762ms)
|
||||
✔ H3: a takeover while a prompt holds the dispatch lock: written under the old actor, or refused; never both (780.661136ms)
|
||||
✔ H4: self-takeover is refused (197.794852ms)
|
||||
✔ H9: Interrupt racing a prompt's dispatch: before the write, dispatch-refused and no-turn; after, §3 rules (448.558157ms)
|
||||
✔ H10: Interrupt and force stop together: one stop chain, force stop supersedes (952.146653ms)
|
||||
✔ H10: an overlap during the pause before the abort: no abort, the stop ends uncertain (211.343989ms)
|
||||
✔ H10: a no-turn Interrupt lifts only its own fence; admission stays closed under force stop, overlap or revocation (526.32941ms)
|
||||
✔ H11: the controller disconnects mid-turn: work continues, the claim is unchanged, control stays put (256.594413ms)
|
||||
✔ H12: an exact retry after reconnecting to the same incarnation returns the same receipt; one dispatch (118.283417ms)
|
||||
✔ H13: a retry with the same request ID and different text is refused (127.511755ms)
|
||||
✔ H14: late stdout from the old engine after a replacement is dropped by incarnation, counted, never rendered (673.855095ms)
|
||||
✔ H15: a revoked connection's command is refused; the revocation fence holds (273.499143ms)
|
||||
✔ H16: a second controller for the same session refuses already-active; the first is untouched (195.757343ms)
|
||||
✔ H10: a second force stop while the first escalation runs refuses fenced; one escalation, and the claim records only the first stop's phases (850.768601ms)
|
||||
✔ a force stop whose fence throws leaves no escalation flag behind, so the next force stop runs (Darkwing F2, #1507) (359.42882ms)
|
||||
✔ H17: a confirmation reused, answered from another connection, or used after the stop changed is refused (792.521247ms)
|
||||
✔ H18: two prompts before any native output: the second refuses busy; one engine write (220.678937ms)
|
||||
✔ H19: the pipe fails mid-line under a large prompt: delivery-unknown transport-unknown, poisoned, no later write (439.158182ms)
|
||||
✔ H19: the link itself never writes again after an unknown outcome, whoever calls it (0.714627ms)
|
||||
✔ H19: the controller dies mid-write of a large line: after restart the outcome is unknown and nothing is resent (702.439075ms)
|
||||
✔ H20: the line is written but the ack is lost when the controller dies: orphan, outcome unknown, nothing resent (625.672005ms)
|
||||
✔ H21: a retry of the exact request with the old token after a crash is stale-incarnation; no second write (854.42331ms)
|
||||
✔ H22: after H21 and a valid recovery, a new request with the new token is admitted (3712.152072ms)
|
||||
✔ H23: requests pending at a restart are not resent; each shows outcome unknown (681.193471ms)
|
||||
✔ no shim from this file's tests is left running for the after hook (29.935584ms)
|
||||
✔ a plain conversation: catalogue row, one page, CHAT-01 records (6.241359ms)
|
||||
✔ native entries map to blocks: tools, thinking, bash, notices, ids that do not fit (1.707129ms)
|
||||
✔ F1: a malformed line is an unavailable part at its position, and reading continues (1.623821ms)
|
||||
✔ F1: a missing parent stops the history with a notice that names the unreadable lines (2.378358ms)
|
||||
✔ F1: an unreadable fork is never merged into another branch's history (1.457475ms)
|
||||
✔ F1: a follow stays on its branch when the next entry's parent is unreadable (1.752772ms)
|
||||
✔ F1: a file whose entries are all unreadable shows a notice per line (0.696341ms)
|
||||
✔ F2: a truncated trailing line marks the view incomplete, not an error (1.166625ms)
|
||||
✔ pagination: 100 parts, then the rest; parts concatenate to the whole branch (3.320688ms)
|
||||
✔ F3: a replaced file (new inode) refuses old cursors with reconcile (4.129842ms)
|
||||
✔ F4: a same-inode rewrite of the prefix refuses old cursors with reconcile (7.246193ms)
|
||||
✔ F5: growth between pages keeps the epoch and the page stops at the pinned length (4.676532ms)
|
||||
✔ F6: unknown, foreign and expired cursors refuse and leave the cursor usable (8.073628ms)
|
||||
✔ F7: a symlinked file and a symlinked directory component are refused, never opened (8.729989ms)
|
||||
✔ F8: a file swapped for a symlink after the catalogue is refused (2.25719ms)
|
||||
✔ F9: registrations never add or redirect a root (1.81179ms)
|
||||
✔ F10: a header cwd naming another project is refused (4.118106ms)
|
||||
✔ F11: parentSession renders with a marker and the parent is never opened (0.755575ms)
|
||||
✔ F12: two leaves: the default leaf is shown and the other branch reads alone (3.965672ms)
|
||||
✔ F12: a follow refuses when an appended duplicate id changes the branch's earlier parts (2.271547ms)
|
||||
✔ F12: a second root (Pi's resetLeaf) starts its own branch (1.430677ms)
|
||||
✔ F13: compaction is a marker in place, then the retained content (0.804749ms)
|
||||
✔ F14: long strings split into fragments and parts, reassemble exactly, and pages respect the byte cap (592.272297ms)
|
||||
✔ fragments never cut a surrogate pair and keep an empty string (4.739229ms)
|
||||
✔ F15: a Claude seat is an unsupported-harness placeholder whose directory is never read (1.569496ms)
|
||||
✔ unknown conversations, empty files and non-Pi files refuse (2.223314ms)
|
||||
✔ an unreadable file or root inside the roots is refused per row, not a failed catalogue (1.043444ms)
|
||||
✔ a seat directory without search permission refuses that root, not the catalogue (1.955125ms)
|
||||
✔ every page and cursor is a valid CHAT-01 record (960.991365ms)
|
||||
✔ the engine pin holds for the installed package (2.741243ms)
|
||||
✔ pinned Pi, sealed and without credentials, answers the controller's commands with the shapes the fake models (262.955034ms)
|
||||
✔ sealed, pinned Pi ignores a trusted project's .pi resources; --approve past the seal would load them, and checkSeal refuses it (Filbert F2 on #1522) (546.10653ms)
|
||||
✔ pinned Pi appends thinking_level_change at start when the branch lacks one, so the leaf moves (K8 then fails closed) (253.708654ms)
|
||||
✔ N25: ordinary Interrupt reconciles; a non-empty queue_update in the window is O5 (534.959461ms)
|
||||
✔ N1: an extension's follow-up queued after the fence is cleared before any abort; O5, Unknown (445.166724ms)
|
||||
✔ N1: a follow-up queued before the fence is O5 at once; the Interrupt refuses fenced (219.360271ms)
|
||||
✔ N2: with abort first, the fake runs the external item (the ordering guard has teeth) (22.20532ms)
|
||||
✔ N3: the fence lands in preflight, preflight errors, no run: failed, No run, uncertain (344.484361ms)
|
||||
✔ N4: the ack arrives after the first abort and a run starts: clear and abort again; Interrupted (201.035481ms)
|
||||
✔ N5: an input handler takes the prompt: ack, no run, delivery-unknown handled-without-run (297.93017ms)
|
||||
✔ N6: an extension queues between clear_queue and abort: O5 and O6, Unknown (447.556561ms)
|
||||
✔ N7: clear_queue times out: no abort, nativeQueue unknown, force stop still ends it (1947.319985ms)
|
||||
✔ N7: clear_queue answers an error: no abort, nativeQueue unknown, the link not poisoned (187.01804ms)
|
||||
✔ N8: an extension prompt starts a run during Mosaic preflight; the losing settle is O3 (270.242951ms)
|
||||
✔ N9: a run that started before the fence and ends aborted: failed interrupted, Interrupted (176.771626ms)
|
||||
✔ N9: decision 34: a run that ends aborted with no stop in progress: aborted-without-stop, uncertain, outcome unknown (167.551553ms)
|
||||
✔ N9: an aborted that lands after the fence but before any abort is written: aborted-without-stop, Unknown (385.524441ms)
|
||||
✔ N10: fake conformance (32.951805ms)
|
||||
✔ N11: the run fails before any user message_start: delivery-unknown ack-without-start, never failed (426.742908ms)
|
||||
✔ N12: input that starts a run after the final empty clear is O1 and not part of the stop's proof (260.482057ms)
|
||||
✔ N13: agent_start with no slot held is O1; a later prompt refuses with zero engine bytes (291.464907ms)
|
||||
✔ N14: the run completes while clear_queue is in flight: finished, Completed first, uncertain (393.617956ms)
|
||||
✔ N14: the run completes after the abort is written, before Pi applies it: finished, never relabelled (419.744423ms)
|
||||
✔ N15: the fence lands in preflight, then an input handler takes it: handled-without-run, No run (476.524004ms)
|
||||
✔ N16: Interrupt with no slot and no run refuses no-turn: no stop, no bytes, admission open (153.543702ms)
|
||||
✔ N17: the run fails on its own during the exchange: failed, Failed on its own (391.037765ms)
|
||||
✔ N18: no final assistant message_end, or a lost line: working stays working; before working, transport-unknown (1006.203048ms)
|
||||
✔ N19: a losing extension prompt settles inside the Mosaic run before its user message: O3, run-overlap (717.42288ms)
|
||||
✔ N20: an extension triggerTurn during Mosaic preflight starts first; while streaming it queues with no signal (1178.015027ms)
|
||||
✔ N21: a losing settle after the receipt settled finished is O2; the receipt stays finished (369.810097ms)
|
||||
✔ N22: an agent-level custom message is dropped by the clear with no signal; evidence names the seal (246.027664ms)
|
||||
✔ N23: a nextTurn message survives clear and abort and attaches to the next prompt, with no signal (265.937379ms)
|
||||
✔ N24: the seal is an allow-list: --extension, a missing --no-* flag, a second --mode or --session, a session or output flag, or a stray word refuses unsealed-engine; no engine starts (168.283323ms)
|
||||
✔ N24b: the seal covers the engine command and environment: config can't name either, the env is built from names, and a mutated command is refused at bind (267.538929ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 171
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 65892.627684
|
||||
@@ -0,0 +1,31 @@
|
||||
✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (5299.08924ms)
|
||||
Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286}
|
||||
✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (6116.773655ms)
|
||||
✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (6341.081545ms)
|
||||
✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (183.35217ms)
|
||||
✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (43.765615ms)
|
||||
✔ bus refusals map to statuses and never carry a path or a stack (20.4502ms)
|
||||
✔ humanCall speaks the human transport protocol without blocking the server (1823.840292ms)
|
||||
✔ busReader takes --business, else the live bus host, else refuses (207.085073ms)
|
||||
✔ humanCall kills a transport that runs past its timeout (537.55544ms)
|
||||
✔ serve refuses a --business value that is not a business id (229.139439ms)
|
||||
✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (5555.816009ms)
|
||||
✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (2267.152032ms)
|
||||
✔ conversation view: a newer session with no readable history keeps the marker (1320.558735ms)
|
||||
✔ conversation view: seats without history say so and offer no reply (857.529463ms)
|
||||
✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (5729.063679ms)
|
||||
✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (55107.601574ms)
|
||||
✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (5154.387337ms)
|
||||
✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (23649.947578ms)
|
||||
✔ loopback host and board origin fail closed (9.614816ms)
|
||||
✔ real board fixture passes through WebUI; assets and isolated seen/reply work (88.56432ms)
|
||||
✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (43.061019ms)
|
||||
✔ unreachable board reports URL; CLI rejects unsupported options (451.914656ms)
|
||||
ℹ tests 22
|
||||
ℹ suites 0
|
||||
ℹ pass 22
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 55406.577069
|
||||
@@ -0,0 +1,14 @@
|
||||
start 2026-10-10T04:51:00Z shims=0 units=0
|
||||
node-conversation exit=0 ℹ pass 171 ℹ fail 0 shims-left=0 units=3
|
||||
node-webui exit=0 ℹ pass 22 ℹ fail 0 shims-left=2 units=3
|
||||
test-auth exit=0 selftest: 15 passed, 0 failed
|
||||
test-conductor exit=0 selftest: 17 passed, 0 failed
|
||||
test-config exit=0 selftest: 24 passed, 0 failed
|
||||
test-discord exit=0 discord suite: 66 passed, 0 failed
|
||||
test-extension-package exit=0 extension package selftest: 18 passed, 0 failed
|
||||
test-foundation exit=0 selftest: 44 passed, 0 failed
|
||||
test-queue exit=0 queue suite: 27 passed, 0 failed
|
||||
test-release exit=0 selftest: 4 passed, 0 failed
|
||||
test-task exit=1 selftest: 26 passed, 2 failed
|
||||
end 2026-10-10T04:54:51Z shims-left=1 units=2
|
||||
DONE
|
||||
@@ -0,0 +1,17 @@
|
||||
OK status with missing harness credential exits 3 and still lists accounts
|
||||
OK status reports harness credential (read-only) + mosaic accounts
|
||||
OK api key material never reaches output
|
||||
OK oauth token material never reaches output
|
||||
OK unparseable credential file exits 2
|
||||
OK symlinked credential file exits 4
|
||||
OK env-side credential names reported
|
||||
OK env var values never reach output
|
||||
OK accounts without an accounts dir reports none and creates nothing
|
||||
OK accounts lists files and marks the active one
|
||||
OK loose account perms flagged in listing
|
||||
OK agent --auth with missing account file refuses (exit 4)
|
||||
OK agent --auth with non-0600 account file refuses
|
||||
OK agent --auth with invalid account name refuses
|
||||
OK auth.sh without valid config refuses
|
||||
|
||||
selftest: 15 passed, 0 failed
|
||||
@@ -0,0 +1,23 @@
|
||||
On branch refactor
|
||||
Your branch is up to date with 'origin/refactor'.
|
||||
|
||||
nothing to commit, working tree clean
|
||||
OK dry-run: allowed change, exit 0, nothing committed (exit 0)
|
||||
OK dry-run committed nothing
|
||||
OK apply: allowed change exits 0 (exit 0)
|
||||
OK apply: attribution in commit subject
|
||||
OK apply: target tree clean after commit
|
||||
OK disallowed path refused (exit 1)
|
||||
OK disallowed path: target untouched
|
||||
OK syntax gate refused broken .mjs (exit 1)
|
||||
OK syntax gate: target untouched
|
||||
OK suite failure refused (exit 1)
|
||||
OK suite failure: target reverted to clean
|
||||
OK disabled policy refused (exit 2)
|
||||
OK disabled policy: target untouched
|
||||
OK failed run refused (exit 1)
|
||||
OK failed run: target untouched
|
||||
OK missing run exits 4 (exit 4)
|
||||
OK invalid policy exits 2 (exit 2)
|
||||
|
||||
selftest: 17 passed, 0 failed
|
||||
@@ -0,0 +1,26 @@
|
||||
OK absent adapter defaults to pi
|
||||
OK adapter mock validates (exit 0)
|
||||
OK unsupported adapter exits 2 (exit 2)
|
||||
OK env exports adapter
|
||||
OK bootstrap creates default when absent (exit 0)
|
||||
OK bootstrap wrote config file
|
||||
OK bootstrap is idempotent on existing config (exit 0)
|
||||
OK bootstrap did not rewrite existing config
|
||||
OK validate missing config exits 3 (exit 3)
|
||||
OK malformed JSON exits 2 (exit 2)
|
||||
OK unsupported configVersion exits 2 (exit 2)
|
||||
OK unknown top-level key exits 2 (exit 2)
|
||||
OK unknown execution key exits 2 (exit 2)
|
||||
OK unsupported backend exits 2 (exit 2)
|
||||
OK unsupported environment exits 2 (exit 2)
|
||||
OK relative dataRoot exits 2 (exit 2)
|
||||
OK non-canonical dataRoot exits 2 (exit 2)
|
||||
OK filesystem root dataRoot exits 2 (exit 2)
|
||||
OK home directory dataRoot exits 2 (exit 2)
|
||||
OK dataRoot containing config dir exits 2 (exit 2)
|
||||
OK control character in provider exits 2 (exit 2)
|
||||
OK symlinked config file exits 2 (exit 2)
|
||||
OK env exports resolve correctly
|
||||
OK failed validation modified nothing
|
||||
|
||||
selftest: 24 passed, 0 failed
|
||||
@@ -0,0 +1,70 @@
|
||||
toolchain: node v26.8.1
|
||||
|
||||
OK syntax: packages/discord/src/approvals.mjs
|
||||
OK syntax: packages/discord/src/authorize.mjs
|
||||
OK syntax: packages/discord/src/binding.mjs
|
||||
OK syntax: packages/discord/src/cli.mjs
|
||||
OK syntax: packages/discord/src/connector.mjs
|
||||
OK syntax: packages/discord/src/context.mjs
|
||||
OK syntax: packages/discord/src/engine-pi.mjs
|
||||
OK syntax: packages/discord/src/errors.mjs
|
||||
OK syntax: packages/discord/src/gateway.mjs
|
||||
OK syntax: packages/discord/src/git.mjs
|
||||
OK syntax: packages/discord/src/journal.mjs
|
||||
OK syntax: packages/discord/src/notify.mjs
|
||||
OK syntax: packages/discord/src/rest.mjs
|
||||
OK syntax: packages/discord/src/setspark.mjs
|
||||
OK syntax: packages/discord/src/tools.mjs
|
||||
OK syntax: packages/discord/src/web.mjs
|
||||
OK syntax: packages/discord/bin/git-credential.mjs
|
||||
OK syntax: packages/discord/extension/tools.mjs
|
||||
OK syntax: packages/discord/tests/approvals.test.mjs
|
||||
OK syntax: packages/discord/tests/authorize.test.mjs
|
||||
OK syntax: packages/discord/tests/binding.test.mjs
|
||||
OK syntax: packages/discord/tests/connector.test.mjs
|
||||
OK syntax: packages/discord/tests/context.test.mjs
|
||||
OK syntax: packages/discord/tests/engine.test.mjs
|
||||
OK syntax: packages/discord/tests/fake-pi.mjs
|
||||
OK syntax: packages/discord/tests/gateway.test.mjs
|
||||
OK syntax: packages/discord/tests/git.test.mjs
|
||||
OK syntax: packages/discord/tests/helpers.mjs
|
||||
OK syntax: packages/discord/tests/journal.test.mjs
|
||||
OK syntax: packages/discord/tests/notify.test.mjs
|
||||
OK syntax: packages/discord/tests/recover.test.mjs
|
||||
OK syntax: packages/discord/tests/rest.test.mjs
|
||||
OK syntax: packages/discord/tests/setspark.test.mjs
|
||||
OK syntax: packages/discord/tests/tools.test.mjs
|
||||
OK syntax: packages/discord/tests/web.test.mjs
|
||||
OK syntax: packages/discord/fixtures/claim-worker.mjs
|
||||
OK syntax: packages/discord/fixtures/legacy-owner-worker.mjs
|
||||
OK syntax: scripts/discord.sh
|
||||
OK syntax: scripts/discord-service.sh
|
||||
OK packages/discord declares no dependencies
|
||||
OK no bot-token-shaped string in packages/discord
|
||||
OK fixture binding uses placeholder ids only
|
||||
OK fixture binding validates
|
||||
OK real pi with the extension exposes exactly list_dir, read_file, search and no built-in tool
|
||||
OK real pi with a writable root exposes exactly the three reads plus write_file and edit_file, and writes nothing at start
|
||||
OK real pi with a web key exposes the three reads plus web_fetch and web_search, and no write tool without a writable root
|
||||
OK real pi with a git root exposes the reads, writes and the four git verbs, commits nothing at start, and never shows the token
|
||||
OK real pi with protocol vault adds reserve_id to the git verbs
|
||||
OK real pi with a setspark key exposes the reads and the eight record verbs, no counters, and never shows the key
|
||||
OK real pi refuses a git key on a read-only root (fail closed)
|
||||
OK real pi with the pilot flags (--no-tools) exposes no tool at all
|
||||
OK real pi exits non-zero without MOSAIC_DISCORD_TOOLS: no session, no tools (fail closed)
|
||||
OK a failing nested test fails the run under a parent runner's NODE_TEST_CONTEXT
|
||||
OK node --test packages/discord/tests/ (ℹ pass 178)
|
||||
OK scripts/discord.sh --help exits 0
|
||||
OK scripts/discord.sh check without a binding exits 4
|
||||
OK scripts/discord.sh recover without a binding exits 4
|
||||
OK scripts/discord.sh reload without a binding exits 4
|
||||
OK scripts/discord-service.sh without a command exits 4
|
||||
OK service unit renders with the repository path, a supervised run as the main process, exit 3 never retried, and reload as SIGHUP
|
||||
OK service install writes the rendered unit (0644) and leaves no temp file
|
||||
OK service install a second time reports unchanged
|
||||
OK systemd-analyze verify accepts the rendered unit
|
||||
OK service uninstall removes the unit file
|
||||
OK service install with an unknown flag exits 4
|
||||
OK service install with USER unset finishes and names the account for lingering
|
||||
|
||||
discord suite: 66 passed, 0 failed
|
||||
@@ -0,0 +1,21 @@
|
||||
OK initial ordinary-file install
|
||||
OK installed tree matches canonical source
|
||||
OK installed tree has no symlinks
|
||||
OK check detects installation drift
|
||||
OK sync refuses to overwrite installation drift
|
||||
OK check detects an extra destination file
|
||||
OK check detects an extra destination directory
|
||||
OK check rejects a destination symlink
|
||||
OK sync accepts a canonical source update
|
||||
OK updated installation matches canonical source
|
||||
scripts/test-extension-package.sh: line 14: 176540 Killed "$@" > /dev/null 2>&1
|
||||
OK forced interruption kills the replacing process
|
||||
OK next invocation recovers old consistent installation
|
||||
OK interrupted replacement rolled back
|
||||
OK sync succeeds after interruption recovery
|
||||
OK unlocked stale lock file does not block
|
||||
OK active lock refuses a concurrent sync
|
||||
OK source symlink fails closed
|
||||
OK nested second entrypoint fails closed
|
||||
|
||||
extension package selftest: 18 passed, 0 failed
|
||||
@@ -0,0 +1,53 @@
|
||||
toolchain: node v26.8.1, python 3.12.8, jsonschema 4.26.0
|
||||
|
||||
OK syntax: scripts/foundation-inspect.mjs
|
||||
OK syntax: scripts/foundation/strict-json.mjs
|
||||
OK syntax: scripts/foundation/canonical.mjs
|
||||
OK syntax: scripts/foundation/resolve.mjs
|
||||
OK syntax: scripts/foundation/validate-record.mjs
|
||||
OK syntax: scripts/foundation/fixtures/build-fixtures.mjs
|
||||
OK syntax: scripts/foundation/canonical.test.mjs
|
||||
OK syntax: scripts/foundation/cli.test.mjs
|
||||
OK syntax: scripts/foundation/fixtures.test.mjs
|
||||
OK syntax: scripts/foundation/resolve.test.mjs
|
||||
OK syntax: scripts/foundation/strict-json.test.mjs
|
||||
OK syntax: scripts/foundation/verify-schema.py (ast only; no bytecode written)
|
||||
OK fixture generator runs
|
||||
OK checked-in fixtures/bundles equal a fresh generation
|
||||
OK checked-in fixtures/raw equal a fresh generation
|
||||
OK checked-in fixtures/index.json equal a fresh generation
|
||||
OK checked-in demo bundles equal a fresh generation
|
||||
OK a failing nested test fails the run under a parent runner's NODE_TEST_CONTEXT
|
||||
OK node --test scripts/foundation/ (ℹ pass 80)
|
||||
OK differential schema oracle: PASS: differential schema oracle (finite corpus; compatibility evidence, not equivalence proof)
|
||||
platform witness: strftime('%Y') for year 999 -> '999' (pinned checker refuses years 0001..0999)
|
||||
node v26.8.1; corpus 1568 records (38 pinned fixtures, 478 unique bundle records, 1052 typeCase/mutation/lexical cases)
|
||||
schema column: agree-valid 540, agree-invalid 991, DISAGREEMENTS 0; strict-only (parser-bound) cases: 27; unsupported-kind records not schema-assessed by the inspector: 10
|
||||
profile column (schema-valid records only): profile-valid 510, profile-invalid 30
|
||||
profile refusals asserted: 30 schema-agreed-valid records refused only by the strict typed-string profile (rule profile-pattern-mismatch), 12 declared by name; 73 named probes verified against declared schema/profile columns
|
||||
OK oracle: zero schema-column disagreements with the pinned checker
|
||||
OK oracle: strict-only profile refusals are counted and asserted
|
||||
OK demo: permitted read preview exits 0 (exit 0)
|
||||
OK demo: permitted file.change preview exits 0 (exit 0)
|
||||
OK demo: assignment.change proposal is unresolved (exit 3) (exit 3)
|
||||
OK demo: revoked registration is refused (exit 3) (exit 3)
|
||||
OK demo: message is not authority (exit 3) (exit 3)
|
||||
OK usage: no arguments exits 2 (exit 2)
|
||||
OK io: missing file exits 4 (exit 4)
|
||||
OK io: directory exits 4 (exit 4)
|
||||
OK io: symlink exits 4 (O_NOFOLLOW) (exit 4)
|
||||
OK bound: oversize fixture exits 2 (exit 2)
|
||||
OK profile: one final LF in a typed selection id is refused before admission (exit 2) (exit 2)
|
||||
OK profile: two final LFs fail the schema pattern itself (exit 2) (exit 2)
|
||||
OK profile: escaped newlines in free-form text stay allowed (exit 0) (exit 0)
|
||||
OK profile refusal is invalid-request/profile-pattern-mismatch with selection and operation withheld, value not echoed
|
||||
OK text output starts with the disclaimer
|
||||
OK json output is valid JSON with result allowed and exactly the charter §7 fields
|
||||
OK json golden matches byte-for-byte
|
||||
OK sandboxed bundle run (env -i, PATH=/nonexistent) produced the unresolved proposal
|
||||
OK sandbox inventory (path/type/size/mode/uid/gid/inode/mtime/sha256) unchanged by runs
|
||||
OK canary never printed (bundle run and credential-file run)
|
||||
OK a non-bundle JSON file is refused at the shape gate, not read into output
|
||||
OK no field of the non-bundle file is echoed
|
||||
|
||||
selftest: 44 passed, 0 failed
|
||||
@@ -0,0 +1,35 @@
|
||||
toolchain: node v26.8.1, git version 2.55.0
|
||||
|
||||
OK syntax: packages/queue/src/cli.mjs
|
||||
OK syntax: packages/queue/src/errors.mjs
|
||||
OK syntax: packages/queue/src/io.mjs
|
||||
OK syntax: packages/queue/src/lock.mjs
|
||||
OK syntax: packages/queue/src/queue.mjs
|
||||
OK syntax: packages/queue/src/review.mjs
|
||||
OK syntax: packages/queue/src/store.mjs
|
||||
OK syntax: packages/queue/tests/commit.test.mjs
|
||||
OK syntax: packages/queue/tests/data.test.mjs
|
||||
OK syntax: packages/queue/tests/dispatch.test.mjs
|
||||
OK syntax: packages/queue/tests/helpers.mjs
|
||||
OK syntax: packages/queue/tests/lock.test.mjs
|
||||
OK syntax: packages/queue/tests/migration.test.mjs
|
||||
OK syntax: packages/queue/tests/review.test.mjs
|
||||
OK syntax: packages/queue/tests/store.test.mjs
|
||||
OK syntax: packages/queue/tests/write.test.mjs
|
||||
OK syntax: packages/queue/tests/fixtures/fake-gitea.mjs
|
||||
OK syntax: packages/queue/tests/fixtures/kill-at.mjs
|
||||
OK syntax: packages/queue/tests/fixtures/lock-child.mjs
|
||||
OK syntax: packages/queue/tests/fixtures/mosaic-pre-a2.sh
|
||||
OK syntax: scripts/queue-commit.sh
|
||||
OK syntax: scripts/git-hooks/pre-commit
|
||||
OK syntax: scripts/mosaic
|
||||
OK queue-commit.sh, the guard and scripts/mosaic are executable
|
||||
OK packages/queue declares no dependencies
|
||||
ℹ tests 148
|
||||
ℹ pass 148
|
||||
ℹ fail 0
|
||||
OK node --test packages/queue/tests/
|
||||
OK scripts/mosaic queue help
|
||||
skip queue verify and render --check: this checkout (/home/jwoltje/darkwing-scratch/r50a/wt) is not the queue's canonical root (/mnt/storage/src/mosaic-stack)
|
||||
|
||||
queue suite: 27 passed, 0 failed
|
||||
@@ -0,0 +1,16 @@
|
||||
OK valid RELEASE resolves (exit 0)
|
||||
OK invalid RELEASE exits 1 (exit 1)
|
||||
OK missing RELEASE exits 1 (exit 1)
|
||||
OK valid RELEASE leaves image tag consistent with version
|
||||
OK status safe on empty state (exit 0)
|
||||
OK status created no pointer
|
||||
OK fault-injected activation refuses (exit 1)
|
||||
OK refused activation wrote no pointer
|
||||
OK refusal logged exactly once with valid fields
|
||||
OK healthy activation succeeds (exit 0)
|
||||
OK pointer written with valid fields
|
||||
OK repeat activation succeeds (log grows) (exit 0)
|
||||
OK log is append-only across activations
|
||||
OK rollback without previous refuses (exit 1)
|
||||
|
||||
selftest: 14 passed, 0 failed
|
||||
@@ -0,0 +1,7 @@
|
||||
OK valid RELEASE resolves (exit 0)
|
||||
OK invalid RELEASE exits 1 (exit 1)
|
||||
OK missing RELEASE exits 1 (exit 1)
|
||||
OK valid RELEASE leaves image tag consistent with version
|
||||
skip state-machine cases (docker daemon unavailable)
|
||||
|
||||
selftest: 4 passed, 0 failed
|
||||
@@ -0,0 +1,33 @@
|
||||
OK valid task validates (exit 0)
|
||||
OK unknown task key exits 2 (exit 2)
|
||||
OK unsupported taskVersion exits 2 (exit 2)
|
||||
OK invalid task id exits 2 (exit 2)
|
||||
OK empty prompt exits 2 (exit 2)
|
||||
OK NUL in expectExact exits 2 (exit 2)
|
||||
OK out-of-range timeout exits 2 (exit 2)
|
||||
OK missing mission file exits 4 (exit 4)
|
||||
OK task with valid mission validates (exit 0)
|
||||
OK invalid mission exits 2 (exit 2)
|
||||
OK validate missing task exits 4 (exit 4)
|
||||
OK validation does not modify the task file
|
||||
OK prune dry-run exits 0 (exit 0)
|
||||
OK dry-run deleted nothing
|
||||
OK prune --keep=2 --yes removes oldest (exit 0)
|
||||
OK kept exactly 2 newest runs
|
||||
OK newest run kept, oldest pruned
|
||||
OK append-only receipt written (3 entries)
|
||||
OK sessions/workspaces untouched by prune
|
||||
OK prune with invalid keep exits 4 (exit 4)
|
||||
skip adapter seam cases (docker daemon unavailable)
|
||||
skip workspace/capability cases (docker daemon unavailable)
|
||||
skip live task cases (docker unavailable)
|
||||
OK onboard without name exits 4 (non-interactive) (exit 4)
|
||||
OK onboard --name renders profile (exit 0)
|
||||
OK profile written
|
||||
OK canon structure: required filled, optional placeholdered
|
||||
OK canon sections present
|
||||
FAIL user recall run succeeds (exit 1)
|
||||
FAIL recalled user name (response: )
|
||||
OK no agent identity on headless run
|
||||
|
||||
selftest: 26 passed, 2 failed
|
||||
@@ -0,0 +1,175 @@
|
||||
# Row 50, cohort scope release after a force stop, round 1 review (Darkwing)
|
||||
|
||||
Issue #1536, request comment 27051, packet comment 27052, queue revs 285
|
||||
and 286 (`a400f521`). Brief: `docs/plans/2026-10-10_cohort-scope-release.md`,
|
||||
section "Cohort scope release after a force stop". Base `16a8d038`; I ran
|
||||
it on `a400f521`, which adds only the two queue files. Candidate manifest
|
||||
sha256
|
||||
`375594fc64b3e42be17a2b5f8983c0925eea37c928b1e8903640f4723c19bab9`,
|
||||
8 files: `cohort.mjs`, `controller.mjs`, four test files, the README and
|
||||
Dewey's `evidence.md`. `shim.mjs` is unchanged.
|
||||
|
||||
Verdict: **approve**, with one point Sage has to rule on. The release
|
||||
follows a proof in every path I could build: the force stop calls it only
|
||||
after the claim records `stopped`, close only for a binding that
|
||||
`#stopped()` accepts, and `releaseCohort` refuses a cohort that isn't a
|
||||
scope or a shim that answers for another invocation. The shim itself
|
||||
refuses `release` unless `engine` reads `populated 0`, so a release can't
|
||||
drop live members. 13 mutants: 9 killed, 4 survive, and none of the
|
||||
survivors is a gap I'd hold the row for. The one open point is the normal
|
||||
engine exit. The brief says to fix it in this row if it leaks. It leaks,
|
||||
and Dewey didn't fix it. I agree it can't be fixed here, for the reason
|
||||
below, but that's Sage's call, not mine.
|
||||
|
||||
## Method
|
||||
|
||||
- Detached worktree at `a400f521`, the seven candidate files copied from a
|
||||
snapshot of the canonical tree, `evidence.md` alongside, then
|
||||
`sha256sum -c`: 8 OK. A second worktree for the mutants; its seven files
|
||||
check OK after all runs (`r1/mut/manifest-after.txt`).
|
||||
- I read the diff in full, `shim.mjs` (`release` at lines 160-172),
|
||||
`#forceStop`, `#serveOrphan`, `#onEnd`/`#transport`/`#uncertain`,
|
||||
`#recover` and `close()` in `controller.mjs`, and R1-R6.
|
||||
- 13 mutants (`r1/mut/mutate.py`, `run.sh`), the whole conversation suite
|
||||
each, own TMPDIR each. After each run the runner lists any shim left
|
||||
under that TMPDIR, kills its `mosaic-chat-*` scope and the PID, and
|
||||
restores the files. No mutant left a shim.
|
||||
|
||||
Node v26.8.1, `TMPDIR=~/darkwing-scratch/r50a/tmp`, `gate.sh` with
|
||||
`DOCKER_HOST=unix:///nonexistent.sock`.
|
||||
|
||||
## Suites
|
||||
|
||||
| Suite | Result |
|
||||
|---|---|
|
||||
| conversation | 171/0 |
|
||||
| webui | 22/0 |
|
||||
| test-auth | 15/0 |
|
||||
| test-conductor | 17/0 |
|
||||
| test-config | 24/0 |
|
||||
| test-discord | 66/0 |
|
||||
| test-extension-package | 18/0 |
|
||||
| test-foundation | 44/0 |
|
||||
| test-queue | 27/0 |
|
||||
| test-release | 4/0 without Docker, 14/0 with it (`test-release-docker.txt`) |
|
||||
| test-task | 26/2 |
|
||||
|
||||
The two `test-task` failures are "user recall run succeeds" and "recalled
|
||||
user name", the live worker check that needs Docker and a model call, as in
|
||||
my row 41 and row 47 gates. Dewey's 98/0 ran them.
|
||||
|
||||
The shim and unit counts in `r1/out/summary.txt` aren't clean numbers.
|
||||
Filbert's row 50 runs were live on the same user manager (the three units
|
||||
after the conversation suite were in `~/filbert-scratch`), and my mutants
|
||||
started under `tmp/mut-*` while the gate was still running, inside the
|
||||
gate's `tmp` prefix. Checked directly at the end: no shim under my gate's
|
||||
`tmp/chat03-*`, and no `mosaic-chat-*` unit whose command line names
|
||||
`darkwing-scratch`.
|
||||
|
||||
## The change
|
||||
|
||||
`releaseCohort` (`cohort.mjs`) checks the kind, then `hello`, then the
|
||||
invocation ID, then sends `release` and polls the unit for up to 3 s. The
|
||||
order is right: every refusal comes before `release`, so an `unavailable`
|
||||
result never means a half-done release.
|
||||
|
||||
`#releaseScope` (`controller.mjs`) acts only on a claim record with state
|
||||
`stopped`, a `cohortProof` and a shim, and memoizes one promise per claim
|
||||
ID. The force stop takes `proven = this.claim` after `#claimFinish`, so it
|
||||
releases the claim it proved, even if the claim changes while the
|
||||
`scope-release` barrier holds. The force stop's reply is the
|
||||
`force-stop-fenced` outcome with the stop as its `after`, so the release
|
||||
doesn't delay the client's reply. Every `fail()` in `#forceStop` returns
|
||||
before the release, which R3 covers for both an unavailable outcome and a
|
||||
rejected proof.
|
||||
|
||||
Close calls it when `this.b.state === "stopped"` and `#stopped()` accepts
|
||||
the stop. After `recover` and `launch` the binding is no longer `stopped`,
|
||||
so close releases only the stopped binding's own claim.
|
||||
|
||||
## A normal engine exit (for Sage)
|
||||
|
||||
The brief: "First check whether a normal engine exit (no force stop) also
|
||||
leaves the shim. If it does, fix that path in the same row; if it doesn't,
|
||||
say why in the packet."
|
||||
|
||||
It does leave the shim. R4 shows it: after the fake engine exits 0 the
|
||||
binding is `uncertain`, the unit is active and the shim reports
|
||||
`engineExit {code: 0}`. Dewey didn't fix it, and gives reasons in the
|
||||
packet. I checked them against the code:
|
||||
|
||||
- A release with no recorded stop would leave the claim `uncertain` with
|
||||
its scope collected. The only way out of `uncertain` is a confirmed
|
||||
force stop (`#serveOrphan`'s comment, line 388), and that stop reads the
|
||||
cohort through the shim. With the shim gone it ends `unavailable`, and
|
||||
the seat stays `uncertain` for good. That's worse than the leak.
|
||||
- The fix that keeps the invariant is to prove the empty cohort on EOF and
|
||||
record `stopped`, which is what R4's force stop does. Doing that without
|
||||
a client's confirmation changes the force-stop and confirmation protocol
|
||||
(K6, confirmations bind target, operation and stop). The brief puts the
|
||||
force-stop phases and the claim protocol out of scope.
|
||||
|
||||
So the brief asks for two things that can't both hold. I agree with
|
||||
Dewey's reading, and the row still strictly reduces leaks. But the
|
||||
remaining leak is likely the larger one: every engine that exits on its own
|
||||
leaves a `mosaic-chat-*` scope and an idle node shim until someone runs a
|
||||
confirmed force stop or the user manager restarts. My recommendation:
|
||||
accept the row as is and open a follow-up for an engine exit, either a
|
||||
controller-run proof on EOF (no confirmation needed when the cohort is
|
||||
already empty) or a stated decision that the operator's force stop is the
|
||||
cleanup.
|
||||
|
||||
## Mutants
|
||||
|
||||
| Mutant | Change | Conversation | Result |
|
||||
|---|---|---|---|
|
||||
| norel | neither the force stop nor close releases | 168/3 | killed: R1, R2, R4 |
|
||||
| norelstop | the force stop doesn't release | 169/2 | killed: R1, R4 |
|
||||
| norelclose | close doesn't release | 170/1 | killed: R2 |
|
||||
| nowait | `releaseCohort` reports `absent` without looking | 170/1 | killed: R2 (unit still active right after close) |
|
||||
| wait0 | `releaseCohort` doesn't wait for systemd | 169/2 | killed: R2, R6 |
|
||||
| noevid | no entry in `evidence.releases` | 168/3 | killed: R1, R2, R4 |
|
||||
| nohello | no `hello` and no invocation check before `release` | 170/1 | killed: R6 |
|
||||
| early | the force stop releases before the claim records `stopped` | 169/2 | killed: R1, R4 (the guard refuses, nothing is released) |
|
||||
| n2 | `killShims` signals any unit | 170/1 | killed: R5 |
|
||||
| noguard | `#releaseScope` checks only the shim; callers unchanged | 171/0 | survives: both callers already gate on a proven stop |
|
||||
| closenoproof | close drops the `#stopped()` check | 171/0 | survives: the inner guard still needs `stopped` and a `cohortProof` |
|
||||
| invnull | `releaseCohort` drops the null-ID check | 171/0 | survives: a real shim always reports an ID, so `null !== id` refuses anyway |
|
||||
| nopush | the release entry isn't pushed to observers | 171/0 | survives: no test reads the pushed evidence |
|
||||
|
||||
`noguard` and `closenoproof` are two guards each covering for the other.
|
||||
Dewey's `relfail` and `closeany` weaken both at once and are killed by R3,
|
||||
so the pair is tested. `invnull` matters only for a shim that answers with
|
||||
no invocation ID, which `shim.mjs` can't produce today. `nopush` is the one
|
||||
real hole, and a small one: the board and terminal would get no release
|
||||
entry, and nothing would fail.
|
||||
|
||||
`early` is worth a line. With the release moved before `#claimFinish`, the
|
||||
guard sees `stopping` and refuses, so the stop never releases. That's the
|
||||
guard working; R1 and R4 catch the missing release.
|
||||
|
||||
## Notes (not blocking)
|
||||
|
||||
1. `nopush` survives. One assertion that an observer sees
|
||||
`{ kind: "evidence", evidence: { kind: "release", ... } }` in R1 would
|
||||
close it.
|
||||
2. `releaseCohort` polls `systemdUnits.lookup`, a `spawnSync` of
|
||||
`systemctl show`, every 20 ms for up to 3 s on the controller's event
|
||||
loop. One lookup takes about 4.5 ms here, so a unit that lingers costs
|
||||
about a fifth of the loop for 3 s. It's the codebase's existing call and
|
||||
the common case returns in one or two polls. An async lookup or a
|
||||
longer interval would be enough if it ever shows up.
|
||||
3. I agree with Dewey's two bounded follow-ups: the crash window between
|
||||
recording `stopped` and the release (a restart classifies the pair
|
||||
`stopped` and never releases), and `close({ killEngine: true })` sending
|
||||
SIGKILL to a recorded PID after a proven stop. A release that came back
|
||||
`unavailable` or `still listed` also has no retry once the binding moves
|
||||
on after `recover`. That fits in the same follow-up as the crash
|
||||
window.
|
||||
|
||||
## Files
|
||||
|
||||
- `r1/candidate-manifest.sha256`: copy of Dewey's.
|
||||
- `r1/gate.sh`, `r1/out/`: suite runs and `summary.txt`.
|
||||
- `r1/mut/`: mutant definitions, runner, per-mutant output and
|
||||
shims-left lists, `summary.txt`, and the manifest check after the runs.
|
||||
Reference in New Issue
Block a user