Files
stack/docs/plans/reviews/webui-1507/clean-tests.txt
T

218 lines
18 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
✔ loadConfig: missing file throws ConfigError (2.069893ms)
✔ loadConfig: invalid JSON throws ConfigError (0.438417ms)
✔ loadConfig: missing dataRoot throws ConfigError (0.327993ms)
✔ loadConfig: relative dataRoot throws ConfigError (0.325869ms)
✔ loadConfig: valid config returns dataRoot (1.031496ms)
✔ findNewestSession: picks the newest by mtime among two files (0.731378ms)
✔ findNewestSession: finds files in nested subdirectories (0.449258ms)
✔ findNewestSession: returns null for a missing dir (0.190751ms)
✔ readSession: extracts fields, collapses/truncates text, counts a truncated final line (1.108679ms)
✔ readSession: model and provider follow the latest model_change entry or assistant turn; null when the log names neither; scanAgent carries them (2.038489ms)
✔ readSession: lastError carries the assistant errorMessage only when the last assistant turn errored (0.855495ms)
✔ findNewestSession/scan: never read sibling auth or secrets next to a sessions dir (2.03661ms)
✔ deriveState: full state table (0.313836ms)
✔ rule: newest entry is an assistant message with a tool call, after a question-looking text, is working (0.601595ms)
✔ rule: newest entry is a tool result with no assistant text after it is working (0.531506ms)
✔ rule: a finished turn (text-only assistant message, stopReason stop) is waiting (0.405072ms)
✔ task: the first user message of the session, from text blocks (0.491929ms)
✔ task: a plain-string user content is accepted, whitespace collapsed and long text capped (0.381223ms)
✔ task: no user message in the log means null (shown as unknown), never a guess (0.472373ms)
✔ workspace: the live tmux pane path wins; the session cwd is the fallback; neither means null (0.567966ms)
✔ activeProject: basename of the nearest .git directory or .git file above the workspace; none means null (0.643836ms)
✔ scan: the written record carries task, workspace and activeProject (0.745408ms)
✔ registration: overrides task, project and workspace; every source says registration; registered carries the launch fields; the grouping column is untouched (0.812363ms)
✔ registration: empty task and null project/workspace leave the derived values in place; registered is still non-null (0.549512ms)
✔ registration: a record whose pid is gone is stale; derived values win, sources say derived, registered stays with alive false; a pid the probe cannot decide is not stale; pidAlive itself (1.429642ms)
✔ registration: no registration leaves the Gate A fields exactly as before, and registered is null (0.623553ms)
✔ loadRegistrations: a missing seatsDir gives empty lists (0.275783ms)
✔ loadRegistrations: one good record, one malformed JSON, one with an unknown field; a stray file under seatsDir is ignored (1.147462ms)
✔ matchRegistration: matches by sessionsDir, and by realpath through a symlink; sessionsDir null never matches; same seat name with a different sessionsDir does not match (fleet vs repo darkwing) (1.76852ms)
✔ scan: writes the registration override to disk; index.json carries registered and registrationErrors (1.131616ms)
✔ scan: a relative seatsDir throws ConfigError; an omitted seatsDir behaves as before (0.313115ms)
✔ scanAgent: waitingOnYou is true for waiting/error and false otherwise (1.127154ms)
✔ scanAgent: ageSeconds is computed from the injected now (0.302815ms)
✔ scanAgent: sessionFile null and state idle when sessions dir is empty but alive (0.199626ms)
✔ discoverRepoAgents: finds agents with a sessions dir, skips those without, sorted by name (0.381178ms)
✔ discoverFleetAgents: finds agents with a sessions dir, sorted by name, fleet tmux fields (0.405132ms)
✔ scan: writes per-agent files and index.json, rerun overwrites, no leftover tmp files (1.289574ms)
✔ scan: relative boardDir throws ConfigError (0.150536ms)
✔ CLI: scan with assume-alive liveness exits 0, prints board summary, writes board files (89.928423ms)
✔ CLI: missing config exits 2 with a refused: message (80.253972ms)
✔ CLI: unknown command exits 2 (79.841572ms)
✔ CLI: unknown --liveness value exits 2 (90.403332ms)
✔ panesRunPi: true when any trimmed line equals 'pi' (0.356649ms)
✔ panesRunPi: false for bash-only, claude, empty, or node-pi-style lines (0.162436ms)
✔ tmuxIsAlive: a pane running pi is alive (0.297307ms)
✔ tmuxIsAlive: session exists but pi has exited is not alive (0.124004ms)
✔ tmuxIsAlive: no such tmux session is not alive (1.002756ms)
✔ tmuxIsAlive: tmux could not be run at all is unknown (null), never assumed alive (0.141834ms)
✔ tmuxIsAlive: passes -L <socket> only when a socket is given (0.188087ms)
✔ parsePanes: one pane per line, command and optional tab-separated path (0.141459ms)
✔ tmuxInspect: reports the path of the pane running pi, not of a shell pane (0.129298ms)
✔ tmuxInspect: no pi pane, no session, or no tmux gives no workspace and the matching liveness (0.172234ms)
✔ loadSeen: missing file returns {} (1.594824ms)
✔ loadSeen: invalid JSON throws ConfigError (2.10826ms)
✔ loadSeen: a JSON array throws ConfigError (0.343731ms)
✔ loadSeen: a non-string value throws ConfigError (4.345296ms)
✔ markSeen: seen true adds the key and writes seen.json mode 0600, no leftover tmp files (3.563497ms)
✔ markSeen: seen false deletes the key (1.941261ms)
✔ markSeen: missing, empty, or non-string fields throw ConfigError (0.477522ms)
✔ markSeen: project containing '/' throws ConfigError (0.231097ms)
✔ markSeen: non-boolean seen throws ConfigError (0.202643ms)
✔ scanAgent: a seen mark matching the waiting session's lastTimestamp clears waitingOnYou (2.88064ms)
✔ scanAgent: a stale mark (agent wrote something newer) is not seen and waitingOnYou is true (0.617591ms)
✔ scanAgent: a working session with a matching mark is not seen (marks only apply to waiting/error) (1.806863ms)
✔ scanAgent: an error-state session with a matching mark is seen (2.149805ms)
✔ scan: index.seen and waitingOnYou reflect seen.json, which scan never rewrites or deletes (1.045558ms)
✔ scan: a corrupt seen.json makes scan throw ConfigError (fail closed) (0.490992ms)
✔ isLoopbackHost: recognizes loopback hosts (2.380812ms)
✔ isLoopbackHost: rejects non-loopback hosts (6.201413ms)
✔ startServer: refuses a non-loopback host with ConfigError, never opens a socket (4.882151ms)
✔ startServer: serves page, healthz, and a rescanning /api/board (48.899289ms)
✔ startServer: a seatsDir registration overrides the row and index.registered reflects it (11.47682ms)
✔ startServer: /api/board returns 500 JSON with an error field when scan throws (4.702469ms)
✔ CLI: serve refuses a non-loopback host with exit 2 and a refused: message (78.932321ms)
✔ CLI: serve rejects a non-numeric --port with exit 2 (82.056496ms)
✔ CLI: scan still works after the async cli refactor (93.42089ms)
✔ CLI: live serve prints its URL and answers /healthz (134.584373ms)
✔ page.html: esc() escapes every HTML-significant character (1.293554ms)
✔ POST /api/seen marks a row; GET /api/board still shows it seen; seen:false clears it (19.569156ms)
✔ POST /api/seen without a JSON content-type returns 400 and does not write a mark (5.81507ms)
✔ POST /api/seen with invalid JSON returns 400 (8.413609ms)
✔ POST /api/seen with a body over 4096 bytes returns 400 (or resets the connection) and writes no mark (6.922079ms)
✔ POST /api/seen with a missing agent returns 400 (6.492325ms)
✔ POST /api/board returns 405; PUT /api/seen returns 405 (6.785092ms)
✔ CLI: scan --print marks a seen row with 's' and the summary line ends with 'N seen)' (93.27849ms)
✔ page.html: seenControl() escapes rec.project/agent/lastActivity, and the POST uses a JSON content-type (0.666541ms)
✔ page.html: has a collapsed Seen section that lists seen rows with the shared row builder (1.860189ms)
✔ page.html: each project has a Hide seen checkbox (default on) beside Hide offline, with a hidden-count note (0.458153ms)
✔ page.html: a project header reads "N of N" only while a checkbox hides rows (0.301181ms)
✔ page.html: every row shows Task and Active project, derived or the word unknown, with the workspace in the detail (0.522645ms)
✔ page.html: task and active project cells show their source via sourceTag(); the detail has a Registered row via registeredText(); SOURCE_LABEL maps registration to registered; every dynamic value in sourceTag/fromSource/registeredText is escaped (1.596776ms)
✔ POST /api/reply: runs agent-send.sh with -s from the registration, -S <host>:control-board, -m text plus the fixed trailer, no -L on the default socket, MOSAIC_TMUX_SOCKET stripped; answers delivered with the exit code and both streams (66.023811ms)
✔ POST /api/reply: a registration with a tmux socket adds -L <socket> (47.085295ms)
✔ POST /api/reply: a non-zero tool exit is a 200 with delivered false, the exit code and the stderr verbatim (44.906851ms)
✔ POST /api/reply: refusals before the tool runs: empty or blank or long text 400, unknown row 404, no registration 409, stale registration 409, no tmux session 409, bad JSON 400; the tool is never called (30.336458ms)
✔ POST /api/reply: a missing agent-send.sh is a 500 with the path in the error, not a crash (6.232881ms)
✔ replyToRow: DEFAULT_AGENT_SEND is the repository's tools/tmux/agent-send.sh and it is executable (0.196143ms)
✔ page.html: the reply box appears only where canReply() holds (live registration with a tmux session), the detail has a Reply row, the submit posts JSON to /api/reply, receipts and drafts survive a refresh, and every receipt value is escaped (0.713094ms)
✔ real helper GET HTTP 200 preserves exit 0 without credentials (16.87011ms)
✔ real helper POST HTTP 201 preserves exit 0 without credentials (19.904021ms)
✔ real helper GET HTTP 403 preserves exit 1 without credentials (14.960278ms)
✔ fixture git subjects only, follow-ups and three session kinds (150.605163ms)
✔ text and JSON carry same numbers, open and truncated title (323.809392ms)
✔ missing credentials exit 2, no-issues never calls API and shows unknown (256.457428ms)
✔ empty range gives no rows and zero totals (141.564883ms)
✔ inclusive UTC dates, first-line preamble only, role and seat boundaries (116.133329ms)
✔ close-only issue included, even median, missing metadata stays unknown (88.374838ms)
✔ unique commits but per-issue links count multiple tags once each (87.716176ms)
✔ page cap refuses rather than silently undercounting (101.467302ms)
✔ bad API payload not JSON refuses (91.969036ms)
✔ bad API payload {} refuses (86.830577ms)
✔ bad API payload [{"number":1}] refuses (77.291166ms)
✔ partial or malformed session log refuses with location, not content (91.720579ms)
✔ no sessions is an empty table; symlink source refuses (138.05013ms)
✔ reads only refactor even when another branch is checked out (85.265578ms)
✔ invalid dates, reverse dates and duplicate options refuse (46.116248ms)
✔ preamble parsing and issue number boundaries (0.357602ms)
✔ no closed issues with human messages means undefined ratio, not invented zero (0.191973ms)
✔ pure resolution selects current default or explicit enrolled account (3.452427ms)
✔ scope is explicit, bounded and never inferred (3.224534ms)
✔ fork pin is preserved against default change, override, missing account and revocation (2.07011ms)
✔ unenrolled account/provider, missing harness, model expansion and native model ceiling refuse (1.785801ms)
✔ only explicit synthetic credential forms and internal fixture stores admitted (12.853623ms)
✔ two concurrent workspaces of the same agent publish distinct complete private generations (89.218237ms)
✔ same execution ID is exclusively claimed and cannot overwrite a published generation (51.919745ms)
✔ failed generation after-auth preserves prior files, records failure and refuses blind same-ID retry (69.110981ms)
✔ failed generation before-publish preserves prior files, records failure and refuses blind same-ID retry (165.301085ms)
✔ credential lock contention refuses without duplicate side effects (34.503814ms)
✔ symlinked pre-existing final target is refused and never followed (76.344676ms)
✔ invalid registry cannot resolve; no fallback to supplied partial entries (0.585699ms)
✔ post-publication failure records uncertainty, preserves complete generation and prevents replay (90.149481ms)
✔ expired credentials refresh under transaction and subsequent generation reuses rotation (229.155792ms)
✔ refresh failure retains prior generation and store state (80.103824ms)
✔ refresh timeout retains prior generation and store state (166.055716ms)
✔ refresh malformed retains prior generation and store state (68.191722ms)
✔ concurrent refresh on same account refuses contention while unrelated account proceeds (218.21407ms)
✔ invalid refresh options refuse before burning claim (39.334705ms)
✔ fixed fake process rotates both OAuth fields without mutating caller input (51.399762ms)
✔ concurrent isolated processes preserve separate provider credentials (55.271858ms)
✔ fake failure is refused with fixed diagnostics (33.787807ms)
✔ fake malformed is refused with fixed diagnostics (47.268272ms)
✔ fake timeout is refused with fixed diagnostics (108.39385ms)
✔ fake unchanged is refused with fixed diagnostics (64.498115ms)
✔ caller executable/environment injection is rejected before spawning (0.483922ms)
✔ valid fixture tree validates and lists without secrets (112.29331ms)
✔ unknown-field refuses (0.679922ms)
✔ invalid-id refuses uppercase and traversal shapes (0.462347ms)
✔ plain-http baseUrl requires allowInsecureTransport (0.517778ms)
✔ native provider rejects allowInsecureTransport (0.232811ms)
✔ unsupported credential type and kind refuse (0.267028ms)
✔ account provider-path mismatch refuses (1.053032ms)
✔ profile account refs must be provider/account shaped (0.410258ms)
✔ seat selection accepts fork pin field, validates account refs (0.385189ms)
✔ harness manifest id must equal executable (gate 1) (0.471681ms)
✔ CLI validate: duplicate provider id across files refuses (49.292022ms)
✔ CLI validate: missing referenced provider/account refuse (56.231526ms)
✔ CLI validate: broken JSON refuses without secret echo (44.514594ms)
✔ CLI usage errors exit 2 (111.897184ms)
✔ credential.json sibling presence does not break validation and is never read (168.781797ms)
✔ D1 missing, empty and structurally empty roots refuse, no list projection (275.749732ms)
✔ D1 required directory auth cannot be absent (124.619472ms)
✔ D1 required directory auth/providers cannot be absent (136.518861ms)
✔ D1 required directory auth/accounts cannot be absent (117.238735ms)
✔ D1 required directory auth/settings cannot be absent (119.706456ms)
✔ D1 required directory harnesses cannot be absent (97.054141ms)
✔ D1 root file and unreadable metadata refuse (137.663685ms)
✔ D2 no symlink traversal at auth/providers/openai-codex.json (57.104514ms)
✔ D2 no symlink traversal at auth/accounts/openai-codex/homelab-openai (58.8982ms)
✔ D2 no symlink traversal at auth/providers (69.919373ms)
✔ D2 no symlink traversal at auth (66.585499ms)
✔ D2 root and ancestor symlinks and lexical traversal refuse (182.602198ms)
✔ private filesystem modes enforced for root (56.988873ms)
✔ private filesystem modes enforced for auth (54.402276ms)
✔ private filesystem modes enforced for auth/providers/openai-codex.json (55.196762ms)
✔ private filesystem modes enforced for auth/accounts/openai-codex/homelab-openai/account.json (62.434238ms)
✔ D3 numeric version 1 only across all record kinds (1.213381ms)
✔ D4 nested unknown keys and missing per-kind required fields refuse (51.243059ms)
✔ D5 unenrolled default refuses even when account exists (61.905203ms)
✔ D6 provider/account credential type must match (61.029479ms)
✔ D7 every harness endpoint enforces HTTP opt-in and shape (0.495449ms)
✔ D8 URLs reject embedded credentials and unsupported protocols without echo (164.103475ms)
✔ D9 malformed JSON diagnostics contain no content excerpt (61.131821ms)
✔ D10 missing metadata is missing-path, not invalid-json (61.521407ms)
✔ D10 library returns no partial entries on any invalid record (70.423693ms)
✔ null/scalar/array metadata refuses without stack or echo (216.403521ms)
✔ credential sibling is never opened, even when an unreadable symlink (34.349719ms)
✔ oversized metadata refuses before parsing (58.959915ms)
✔ resolveSeat: by name under --repo resolves the repo layout (2.244578ms)
✔ resolveSeat: by path resolves the fleet layout (0.655672ms)
✔ resolveSeat: refusals for missing dir, missing launch.sh, non-executable launch.sh, invalid name, and unknown layout (1.497292ms)
✔ tmuxContext: outside tmux, default socket, custom socket, and exec failure (1.278671ms)
✔ makeRegistration produces a record that validates; each shape violation throws SeatError (1.478842ms)
✔ writeRegistration/readRegistration: round trip, permissions, absence, and malformed records (1.781997ms)
✔ updateTask: changes task and updatedAt only, and refuses appropriately (2.864265ms)
✔ CLI launch: registers, execs the fake launch script, and passes args through (40.186244ms)
✔ CLI launch: --harness lands in the record (62.351088ms)
✔ CLI launch: the launch script's own exit code passes through (52.770779ms)
✔ CLI launch: relaunching a seat rewrites the one registration record (103.782698ms)
✔ CLI launch: omitting --task records an empty string, not null (68.271979ms)
✔ CLI seat task: updates only the task after a launch, and refuses on an unlaunched seat (201.947039ms)
✔ CLI refusals: no args, unknown flag, missing config, already-registered env, and exec failure (249.955376ms)
✔ samePath: equal paths, symlinked dirs, distinct dirs, and non-strings (0.580992ms)
✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (1340.984357ms)
Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286}
✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (1624.334009ms)
✔ loopback host and board origin fail closed (7.093521ms)
✔ real board fixture passes through WebUI; assets and isolated seen/reply work (97.215606ms)
✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (36.079167ms)
✔ unreachable board reports URL; CLI rejects unsupported options (389.105161ms)
tests 208
suites 0
pass 208
fail 0
cancelled 0
skipped 0
todo 0
duration_ms 2604.12737