Generate per-harness make targets from fragments - #50
Open
CrypticSwarm wants to merge 3 commits into
Open
Conversation
The root Makefile gains a harness_rules template that expands one harness's build/update/run/stop targets from declared knobs, and includes swarmforge/harness/*/harness.mk after the shared macros. Claude's knobs move to swarmforge/harness/claude/harness.mk under their existing names, so overrides like CLAUDE_HOME_DIR=... keep working unchanged. Generated recipes defer every expansion, preserving the target-scoped config-layer ?= defaults and command-line/environment override precedence of the hand-written rules. The template emits the SWARMFORGE_CONFIG_DEST default unconditionally; run_claude never set one, and an empty value is argv-identical to an unset one.
OpenCode, Grok, and Codex each get a swarmforge/harness/<name>/harness.mk declaring their knobs under the existing names and evaling harness_rules, completing what the Claude fragment started. The root Makefile keeps only the shared variables, macros, and the ollama/test/lint targets; .PHONY and clean accumulate their per-harness entries from the fragments. OpenCode keeps its bare DATA_DIR and PROFILE knob names and its RUN_ENV without SWARMFORGE_AGENT_BIN, both localized in its fragment: renaming or adding either would change the interface and the container argv. clean still removes the same five containers; only their removal order shifts, since the stop targets are now collected from the fragment includes instead of a hand-kept list.
An empty include glob would silently drop all sixteen harness targets, leaving "No rule to make target 'run_claude'" with no hint of the cause. Collect the fragment list first and fail with a message naming the expected location. Every fragment now declares its EXTRA_BUILD_ARGS, and the template references the knob by name in the generated recipe instead of splicing its value at eval time. That leaves MKDIRS as the only knob needing $$-escaped entries, and one convention for all the rest: plain $() references, expanded when the recipe runs. Comments on TEST_DATA_DIR and test-skills name the opencode fragment their DATA_DIR and OPENCODE_IMG references resolve against, since the declarations no longer sit in the same file.
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.
The root Makefile hand-maintained four target blocks, four build/update recipes, per-harness run env and mount lists, and the
.PHONY/cleanentries for all of them — eight scattered places to edit per harness. Each harness now declares its knobs inswarmforge/harness/<name>/harness.mkunder their existing names and evals a sharedharness_rulestemplate that generatesbuild_/update_/run_/stop_<name>and accumulates.PHONYandclean.Command-line overrides and target-scoped
?=defaults behave as before: generated recipes defer expansion with$$, and the one eval-time splice (the mkdir list) is escaped. OpenCode keeps its bareDATA_DIR/PROFILEknob names inside its own fragment. The root Makefile errors out if the fragment glob matches nothing — an empty include would otherwise drop all sixteen targets silently.The argv baseline snapshots pass unchanged: every generated target produces the same words the hand-written blocks did, across command-line, environment, and
-eoverride scenarios.