Port the semantic layer from Go to the compositor, with the Go tests as the oracle #333
Labels
No labels
burndown-2026-08
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/devrel
role/eval
role/exec
role/frontend
role/gamedev
role/human
role/platform
role/qa
role/sysadmin
role/tpm
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#333
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Parent
#329
What to build
Move every semantic step out of Go into a real Python compositor, replacing the throwaway from #332.
What moves:
The existing Go tests in
internal/personandinternal/colorare the specification. Read them as the requirements document rather than reimplementing from the prose docs, because the tests encode edge cases the prose does not.Differential testing is the point of this slice. Both engines still exist while this runs, so compose all seven roles with each and diff the resulting bundles byte for byte. That oracle disappears the moment #339 deletes the Go side, so every parity question has to be settled here.
Acceptance criteria
Blocked by
Landed as
e76e3cb, with29ed388and8389c3don top. The engine ishousecast/, 6 modules and 3 test files, readinghousecast/data/roster.yaml.Acceptance criteria
housecast/tests/test_parity.py, which builds the Go binary and diffs whole trees. 12 native-skills bundles plus 7 compiled ones.color.Favorites, asserted against the Gorostersnapshot.housecast/__init__.py.agent-compose verifyaccepts the Python output unmodified.Three things worth knowing
The float64 risk did not materialize, but one line carries it. Go's
math.Roundrounds half away from zero and Python'sround()rounds half to even.delinearizefloorsx + 0.5instead, and that is the whole reason the two engines agree on a hex digit through a 400-round optimization.The identity content digest was the only real debugging. It covers an anonymous struct in
manifestContentthat carries no json tags, so Go falls back to capitalized Go field names, and it is not a digest of the manifest's ownidentityblock. Everything else matched on the first or second attempt.One negative control was wrong and I only caught it by running it. I used
#808080as the too-gray case. It lands at OKLab lightness 0.5983 and trips the lightness floor before it ever reaches the chroma floor, so it tested nothing I meant.#a0a0a0is the real control.A process failure worth recording
3e8976fretitled the eval seat to Applied Scientist while this port was in flight. My generated YAML predated it, and I pushede76e3cbwith two failing parity tests because I chained the push after the test command instead of gating on it.29ed388fixes the drift and adds the guard that makes it loud: it compares every field housecast reads against both the Go person data and the Go roster snapshot, and names the file to regenerate. The body-level guard alone misseddisplay_name, so I mutated the YAML and watched each half fire rather than trusting a green suite.Two sources of truth exist until #339, and that is the cost of it.
#337 is now unblocked for the code half.