Hold every registered harness to one conformance suite - #56
Open
CrypticSwarm wants to merge 6 commits into
Open
Conversation
The suite runs over the registry rather than naming harnesses, so a new harness is checked the moment it is registered: its descriptor is complete and well-shaped (an opted-out field carries a Waiver with a reason on record), a full root-phase run over staged layers lands config and assets at its declared destinations in layer order, its MCP fragment serializes and travels by a delivery the drivers implement, its exec is byte-identical for the default pre-exec hook, its recorded run argv carries the shared layer mounts and masks every asset directory a writable mount would carry to the next run, and the registry matches the harness directory listing with install.sh and harness.mk present. The staged-import-root suite also runs the root-phase driver the way the entrypoint invokes it, so the first python the container executes proves its imports resolve from the image's package copy.
The codex command translator's old module path was kept as a python -m shim while the container still invoked it there; the container drives translation through the codex harness module now, so the shim's package goes, its one test importing through it retargets, and the translator's own usage line and warning prefix name the module where it lives. The agent translator likewise re-exported the rendering helpers and per-harness tables of the modules they moved to. Nothing imports them through it anymore, so the pass-through imports and their __all__ entries go, keeping the names its CLI consumers still reach for. The per-harness override keys stay readable from swarmforge.harness.agent_override_keys(), which the harness modules already call.
The entrypoint carries no harness-specific logic: it invokes the config driver as root and the pre-exec driver as the anvil user, and those are what merge the layers, translate agents, install assets, build Claude's settings, and shape the exec. The README, AGENTS.md, and the comments that attributed that work to the entrypoint now name the drivers and hooks that do it, and the claim that Claude's translated agents land in ~/.claude/agents is corrected to the container-local config dir. A new README section documents the harness lifecycle end to end: the per-harness directory, the registry, the build events, the per-run phases, and what adding a harness takes.
- The recorded SWARMFORGE_AGENT_BIN is held to the registry name as well as the binary: the entrypoint hands the same word to both drivers as the registry key, so a spec whose name and recorded variable diverge is a container that refuses to start. - Only a tmpfs counts as a mask over an asset destination a writable bind mount carries; the mount itself is another host directory, not a mask, and a tmpfs standing anywhere above the destination covers it. - The staged run redirects every absolute non-template asset destination and Claude's wrapper directory, so a harness declaring a pinned skills or commands path cannot write outside the tmpdir. - The config-precedence run stages a file only the repo and user layers contest, pinning the repo-user order the org win says nothing about. - The exec checks scrub every launch variable, run with a built settings file standing so a flag-splicing hook takes its real branch, and read the shared read-only mounts as pairs rather than through a last-wins dict. - A waived mcp_fragment is accepted with its reason, matching the guards the fragment-shape tests already carry.
The anvil overview described the tong MCP delivery by naming two of the four harnesses; three deliver by the same env variable and only Claude takes the flag, so the paragraph states the split by the spec's delivery with the merges each route feeds. The initialize bullet orders the config phase the way the driver runs it, the repo-shape test list names all three files that hold it, and the test-naming convention covers the suites that span the repo.
The staged run redirects every pinned asset destination and three of Claude's module constants; the class docstring still described the narrower set it started with. A declared MCP merge also has to come with a shaped fragment, or the merge names a file nothing produces.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adding a harness is now one directory plus one registry line — and a conformance suite that checks the result with no new test-writing.
tests/test_harness_conformance.pyparameterizes over the registry: every spec field present with a shaped value and every waiver carrying a reason; a fullinitrun over staged tmpdir layers landing assets at the declared destinations with the layer precedence; MCP fragments and delivery modes consistent with each other;executepassthrough for default-hook harnesses; the recorded run argv carrying the shared layer mounts, tmpfs masks over every native asset destination under a writable bind, and no mount under the image's package path; and the registry matching the directory listing, each entry shipping its install script and make fragment.Cleanup rides along: the retired
swarmforge/commands/import path and the translator re-exports nothing consumes are gone, and the README and AGENTS.md describe the harness directory layout, the build events, and the per-run lifecycle as the container drivers implement them.