Skip to content

Drive the container config phase from Python - #52

Open
CrypticSwarm wants to merge 2 commits into
harness-dockerfile-localizationfrom
harness-container-init
Open

Drive the container config phase from Python#52
CrypticSwarm wants to merge 2 commits into
harness-dockerfile-localizationfrom
harness-container-init

Conversation

@CrypticSwarm

Copy link
Copy Markdown
Owner

The entrypoint's config phase — layer merges, keyed files, harness-specific config builds, and the tong MCP merge — was a couple hundred lines of shell branching on AGENT_BIN. It now runs as python3 -P -m swarmforge.harness.init, driven by the harness specs: repo→user→org merge order with the same tar invocations, the same-inode skip for bind-mounted layers, per-harness excludes and keyed merges, then a build_config hook, the MCP merge selected by the spec, a finalize_config hook, and a publish_config hook. Codex's off-home config rebuild and copy-back become its build_config/publish_config; claude's settings build becomes its finalize_config — the split exists because codex must run before the MCP merge and claude after it.

The replaced shell functions are deleted, and every text assertion over them is replaced by a behavior test in the same commit: tmpdir layer stagings covering precedence, conflicting keys, excludes, keyed merges, and the bind-mount-same-dir skip, parameterized per harness. The driver's output trees are byte-identical to the shell's across all four harnesses and the reset, tong, no-dest, and aliased-layer variants.

A Context record carries what one config run knows (home, destination,
the three layer sources, the tong MCP fragment), and three spec hooks
slot into the phase around the tong-MCP merge: build_config before it,
finalize_config after it, publish_config last. Defaults are no-ops.

- Codex fills build_config (rebuild config.toml key-wise from the
  layers) and publish_config (truncate-and-copy into its persistent
  home) because its config is excluded from the whole-file overlay.
- Claude fills finalize_config: the settings file its exec is handed
  is derived from the image defaults plus the layers on every run.
- The split exists because codex's build must precede the MCP merge
  while claude's settings build must follow it.
swarmforge.harness.init now owns the config phase the entrypoint ran as
shell: the repo -> user -> org layer merge (tar overlay with the same
exclude flags, same-inode skip via st_dev/st_ino), the key-wise merges
of each spec's keyed files, the tong-MCP merge dispatched by the spec's
mcp_merge value, and the build/finalize/publish config hooks around it.
The entrypoint invokes it as
`python3 -P -m swarmforge.harness.init "${AGENT_BIN}" "${ANVIL_HOME}"`
and keeps only the root-shell work: users, assets, agents, state links,
chown, exec.

The guarantees the deleted shell functions carried move from text
assertions over entrypoint.sh to behavior tests that run the driver over
staged layer trees: precedence, keyed merges, per-harness excludes, the
same-directory layer skip, reset semantics, empty layer variables, MCP
merge shapes, codex's rebuild-and-publish, claude's settings stack, hook
ordering, and the spec-to-entrypoint path agreements.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant