feat(evalkit): project a committed run into a display payload, one way #290
No reviewers
Labels
No labels
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/agent-compose!290
Loading…
Reference in a new issue
No description provided.
Delete branch "aos/claude/xu59-eval-export"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The exporter from
coilyco-bridge/deploy#572. My seat owns this half; the Phoenix deployment is ops'.One way, and that is the whole design
Committed records stay canonical. The payload goes out, nothing comes back, and the display surface is a rebuildable projection rather than a second home for evidence.
That shape is what makes this cheap. #213 step 4 — returning label, critique, evidence, reviewer identity, and provenance to the owning records without manual reconstruction — is the hard requirement for a review UI. This is not one.
evalkit.annotatestays the grading surface and nothing is authored downstream.The grader's notes are withheld by default
critiqueandevidenceare free text a human writes for herself, mid-flow, in a keystroke-driven TUI. One committed critique inops-board-2026-08-12-regradedtrails off into a note about the terminal rendering badly.Nothing unsafe about it. But it was not written for an audience, and the display target is a permanent public recording. So those two fields need
--include-private, and the payload records which way it went inincludes_private_fields.Labels, prompts, targets, outputs, and the pair structure carry by default. That is what makes a board legible — the pass/fail shape and the pairing, not the margin notes.
It refuses rather than redacts
A scrubber that misses a pattern ships the secret. This stops instead, names every reason in one pass so a fix is not a loop, and exits non-zero.
Recognized: AWS key ids, bearer and API tokens, JWTs, private key blocks, SSM parameter paths, Discord snowflakes, tailnet hosts, email addresses.
Withheld text is not scanned, because text that never leaves cannot leak, and refusing on it would block an export that is safe. There is a test for exactly that asymmetry.
Two things worth reviewing
A test caught a real bug in the gate. My SSM pattern required the keyword at the start of the path segment, so
/sirens-echo/postgres-password— a real parameter in this estate — did not match, because the keyword has a prefix. Fixed, and the parametrized case is what found it.Verified against real data. Both committed pilot runs export without refusal, so the gate does not cry wolf on legitimate records. A gate that fires on real data gets turned off, which would be worse than not having one.
Pairs travel whole
The pair is the scoring unit, never the half, so the payload carries
completeandpassedas their own structure. A renderer rebuilding that from case rows would report a half-graded pair as a pass, which is the degenerate reading the board's pairing exists to prevent.Verified
ward exec testexits 0: ruff, ruff format, mypy, and 57 tests including 20 new ones.Not in this PR
The Phoenix client mapping. There is no instance yet, and this payload is the stable thing to map from.
ward exec evalkit-exportis usable now for screenshots of the payload itself.🤖 Generated with Claude Code