Repository navigation
fix(test): harden the new failure diagnostics - #2946
Conversation
… keys over all of stderr Findings 2025 and 2026. The failed image build evidence was only tested through the exported helpers, so the runner's wiring (redaction, the protected-output gate, recording at all) could regress unseen. The runner moves into an exported runQaCommand(f, ...) that f.run calls, and a test runs it with a real failing subprocess and no cluster: the evidence file is written, keeps the failed step, masks the registered, environment, bearer and PEM values the subprocess printed, cuts lines at 800 characters, and is not written for protected output. imageBuildFailureOutput cut stderr to the failed step's last 200 lines before redaction masked private keys, so an unterminated key whose BEGIN line fell outside the window kept its body. Keys are now masked over all of stderr first.
…in its bounds Findings 2027 and 2028. When the listing of what holds a Namespace hit its deadline, the whole description was replaced by 'listing what remains timed out', dropping the phase, finalizers and conditions already read. The listing now pushes lines as it reads them, and a timed-out listing reports them with the timeout note. withinDiagnosticDeadline takes an injectable sleep (as retryKubectlRead does), passed through deleteNamespaceExplained, so a test holds the deadline's timer and reads the 40 s default instead of waiting for it. New tests pin that default and the partial result (held and real timers), the 40-object cap, and the 300-character first-line cut of a failed read's stderr.
…turn's marker listing Findings 2029 and 2030. The session evidence script JSON-parsed every transcript row of the session, including rows long before the evidence window, so one malformed old row made it exit 1 on a passing run. Rows that are not JSON now establish nothing and are skipped. A new preflight test proves a passing turn with a malformed earlier row, and a denied Codex turn without its prompt mirror: its failure message names the denied turn and lists the newest ten marker-bearing user messages, reporting only string idempotency keys.
… malformed rows Two mutants survived the new tests: keeping every stderr line of a failed listing read (the 300-character cut hid it), and parsing in-window rows strictly (the window search stops at the marker before the old malformed row). A failed discovery read with a short two-line stderr and a malformed row inside the evidence window now kill them.
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
…s window Review of the finding 2029 fix: skipping every malformed transcript row let a truncated tool-call row inside the evidence window pass the disabled-tool phase's check that the turn made no call. Only rows before the window are skipped now; one inside it fails the evidence script, naming the row. The test keeps the earlier-turn malformed row passing and expects the no-call check to fail on an in-window truncated tool-call row. Also says in qa-installation why an unterminated private key earlier in stderr leaves the image build evidence all markers: masking runs to the end, the safe direction, as in redactedQaTail.
…isting Review of the finding 2028 fix: a read the deadline stops rejects with an AbortError as the deadline passes, and its partialKubectlRead catch could push 'listing objects failed: The operation was aborted' before the timed-out listing was reported. The catch now rethrows an AbortError, or any failure after the deadline, without adding a line. The new test runs a stand-in kubectl on PATH through the real client, so the stalled object read is a child process the deadline kills; it failed with the extra line before this change.
|
Codex review: needs maintainer review before merge. What this changesThis PR hardens build-output redaction, preserves partial namespace diagnostics, and confines strict transcript parsing to the current evidence window. Example: A failed image build prints an unterminated private key followed by 250 key-body lines.
Review scores
ProductKind: Bug fix · Worth it: Yes · Fix scope: Complete Merge readiness✅ Ready for maintainer review Keep this PR open for maintainer triage: it repairs concrete QA diagnostic failures, and the reviewed patch has no actionable findings. Priority: P3 Before mergeNone. FindingsNone. Agent review detailsHow this fits togetherQA helpers consume subprocess stderr, Kubernetes metadata, and SQLite transcript events, then produce bounded failure messages and redacted evidence artifacts. flowchart TD
A[QA scenarios] --> B[Command runner]
B --> C[Build output redaction]
C --> F[Failure evidence]
A --> D[Namespace diagnostics]
D --> F
A --> E[Transcript evidence reader]
E --> F
Technical reviewBest possible solution: Retain these focused repairs in the existing diagnostic owners and land them after required checks succeed. Do we have a high-confidence way to reproduce the issue? Current main visibly trims build output before key masking, discards partial namespace reads on timeout, and parses unrelated historical transcript rows strictly; focused regressions cover each path, but no tests were run during this review. Is this the best way to solve the issue? The repairs preserve existing owners, evidence-window boundaries, redaction gates, and diagnostic limits while addressing the failure causes directly. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against def181770d66. Provenance checked
TestingProof path: in-process harness. SecurityNone. EvidenceWhat I checked:
Likely related people:
Review metrics
LabelsLabel changes: No label changes. Label justifications:
Rating scale6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior. WorkflowClawSweeper edits this one comment on every review. Comment HistoryReview history (1 earlier review cycle)
Reviewed October 19, 2026, 11:44 AM ET / 15:44 UTC (Revision 2). |
|
@clawsweeper re-review |
|
🦞👀 Re-review progress:
|
Problem
bughunt-129 audited the new failure diagnostics from #2940, #2941 and #2942:
createQaInstallation'sf.runcallingrecordImageBuildFailure). Mutants that wrote raw, unredacted build output intoimage-build-failure-*.json, recorded nothing, or dropped theprivateFailureOutputgate passed all 33 tests.markerUserMessageswere untested.Change
Test helpers and their tests only:
tests/helpers/qa-installation.mjs: the body off.runmoves unchanged into an exportedrunQaCommand(f, command, args, options), whichf.runcalls, so a test can drive it with a real failing subprocess and no cluster (2025).imageBuildFailureOutputmasks private keys over all of stderr before taking the failed step and its last lines (2026).tests/helpers/kubernetes-real.mjs:withinDiagnosticDeadlinetakes an optionalsleep(asretryKubectlReadalready does), passed through bydeleteNamespaceExplained, so a test can hold the deadline's timer. The listing records each line as it reads it; a timed-out listing reports those lines, then "listing what remains timed out" (2028). A read that the deadline aborted adds no "listing ... failed" line, so that report is deterministic.tests/helpers/plugin-driver-real.mjs: the evidence script skips rows before the evidence window that are not JSON (parseEvent) instead of throwing (2029). A malformed row inside the window still fails the evidence ("transcript row N in the evidence window is not JSON"), so a no-tool-call or denied check can't pass over a row that might hide a call.tests/integration/qa-fixture-inputs.test.mjs: the runner records a failed build step as evidence with a registered secret, an environment secret, a bearer token and a PEM body all masked, lines cut at 800 characters, and nothing recorded for a protected command (2025, 2027); an unterminated key with 250 body lines leaves none in the 200 recorded lines (2026).tests/conformance/kubernetes-real-kubectl.test.mjs: the 40 s default deadline applies, a held or stalled listing keeps the phase, finalizers and conditions it read, a real stand-in kubectl killed by the deadline reports exactly the read lines plus the timeout, and the 40-object cap and stderr cuts hold (2027, 2028).tests/integration/plugin-driver-real-preflight.test.mjs: a malformed row before the window doesn't fail the run, and one inside the window fails the no-tool-call check (2029); a denied turn with 12 marker messages names the denial and lists the newest ten, and a non-string idempotency key reads as null (2030).All fake values; no secret is printed.
Verification
Promise.resolve(undefined); drop theprivateFailureOutputgatelineChars800 -> 1000withinDiagnosticDeadline;listTimeoutMs40000 -> 600000JSON.parsein the window search or the marker listingmarkerUserMessagesfrom the denied message; change its text; remove.slice(-10);.slice(0, 10); accept any idempotency key typeplugin-driver-real-preflight,qa-fixture-inputs,kubernetes-real-kubectl, before and after the internal review's changes (in-window malformed rows, aborted reads, masking comment). Two survivors after review: keeping only one half of the abort guard (AbortErroror deadline passed), since both are true together on this path.k3d-failure-diagnostics(also useswithinDiagnosticDeadline) passes. 113/113 across the four files in one run..mjshelpers are outsidetsc's project.git merge-tree, main vs this head): feat(runtime): apply Gateway tool policy to dedicated OCE deployments #2633 6/6, feat(plugins): let administrators approve pinned plugin releases #2398 3/3, fix(runtime): copy public install helpers for Podman builds #1543 19/19, Add OCE policy simulation and tester for network and plugin actions #2445 4/4, Draft implementation: managed outbound HTTPS for dedicated Gateways #2518 0/0.Risks
runQaCommandreadsenvand the directories from the installation objectf, which holds the same objectsf.runused before; behaviour is unchanged.