Role adjacency in KDL, and evalkit as the Python half of the eval system #263
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!263
Loading…
Reference in a new issue
No description provided.
Delete branch "adjacency/262-role-adjacents"
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?
Eight commits in three groups. Refs #262 and #213.
Read this first: the failing test is pre-existing
TestLatestScoredResultsMatchCurrentPacksfails for all eight packs on this branch. It also fails on cleanmainat67fd5bcwith none of these commits applied.I diffed the expected-versus-computed digest pairs between clean main and this branch: identical, all eight. Nothing here moves a pack digest. Adding
Adjacentsto theRolestruct does not alter rendered pack content.The baseline was retired by work that landed before this branch, all of it changing pack content:
d09e97dandfb94739, the meld-to-boundary rename and renaming boundaries for the behavior they remove, both breaking09c9ec0,43739fd,9f8730d,67518b7, freeform personality bodies, flat data layout, prose bounds, second-person rewriteRe-earning the baseline is #262's job and is tracked there. This PR neither fixes nor worsens it.
Everything else is green:
go build ./...,go vet ./..., every other Go package, 26 Python tests, ruff, ruff format,mypy --strict, and the full pre-commit suite.1. Adjacency becomes a role property (
cdd293c)Adjacency lived in
internal/person/data/role-*/evals.yamlasadjacent_role, so it existed only where someone had written a case. The graph was incomplete: five of thirteen edges were one-directional, and QA declared none while being named by AI.It moves onto the role as a KDL node with a required
reason, plusvalidateRoleAdjacentsin the load chain,docs/role-adjacency.md, and four tests.Directed on purpose, so do not add a symmetry check. Absorption risk is not symmetric: DevOps sequencing follow-up work after an incident is a live confusion, while the Director rarely reaches for a runbook. Out-degree is fixed at two so the roster picks its sharpest confusions instead of listing every plausible neighbour. A roster declaring no adjacency at all is skipped, so external person packages keep loading.
The
reasonis generator input rather than commentary. An adjacency case has to construct one specific confusion, and a bare pair leads a generator to invent the wrong one on exactly the non-obvious edges.2. evalkit, the Python orchestration half (
9d22c27through533dbe8)The repo already ran its eval driver and reviewer in Python, but unmanaged: no project table, no declared dependencies, no lint, no types, no tests, no ward verbs. This promotes it to a real package pointed at the new board.
evalkit.schema- pipeline data modelevalkit.run- subject fan-out at n=5, transport recorded per response so a direct-provider fallback cannot be mistaken for a measured resultevalkit.filter- item analysis, drops candidates that pass or fail every run, reports every dropevalkit.grade- one case per screen, one keystroke per decision, saves after every grade, reports boundary pairs rather than halvesevalkit.board- derives the case list from the roster Go exportsThe seam: Go owns what a pack is and what a valid record is. Python owns running the subject, filtering, and putting a case in front of a human. Python consumes what Go emits and never restates it, because two parsers is the failure this split exists to avoid. Grades stay a dumb intermediate so the canonical record still comes from the owning marshaller.
The board is derived rather than maintained. Boundaries and owners produce the pairs, adjacency produces the role-fit targets, each role's meld produces the personality cases. 78 cases today.
ward evalkit-boardprints it.Gates run from
scripts/evalkit-check.shrather than pre-commit, because that file is managed by agentic-os between BEGIN and END markers and a hand-added hook would be overwritten on the next sync. CI'sagentic-os:releaseimage shipsuv, soward exec testresolves.3. Reference pages (
3aa9faf)Six external reference points, two papers, two platforms, two blogs, each with a page and an index at
docs/eval-references.md. Records two things a reader would otherwise trip on: the Pragmatic Engineer guide is paywalled after section 3, and the Phoenixllm-evalspage is the wrong citation for this work since it covers LLM-as-judge rather than human annotation.Notes that RULERS' three recommendations were already in place here independently, so nobody reads the design as having followed the paper.
Deliberately not in this PR
adjacent_roleentries inrole-*/evals.yaml. Removing them is a fork with real costs, discussed on #262, and that matrix retires anyway.substring_matcheris a placeholder. A prose discriminator cannot be matched reliably by substring, and the two real options are documented indocs/eval-orchestration.md.Size note
2782 insertions across 37 files, 520 of them generated
uv.lock.adjacency/262-role-adjacentsto Role adjacency in KDL, and evalkit as the Python half of the eval system