Skip to content

feat: bake the orchestrator into the outer image#58

Merged
lsfera merged 1 commit into
mainfrom
feat/bake-orchestrator-into-image
Jun 26, 2026
Merged

feat: bake the orchestrator into the outer image#58
lsfera merged 1 commit into
mainfrom
feat/bake-orchestrator-into-image

Conversation

@lsfera

@lsfera lsfera commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Makes the published outer image actually deliver the orchestrator, so adopters can run without vendoring .sandcastle/*.ts — and stops run.sh reinstalling deps on every launch (ADR-0016).

What

  • Bake the orchestrator source into /opt/agentic-orchestrator in the published image; adopters keep only their config in .sandcastle/ (orchestrator.env, .env, opencode.json).
  • run.sh / afk resolution: prefer the workspace .sandcastle/ when it carries the source (dogfood / vendored adopters → local edits win), else fall back to the baked copy (AGENTIC_ORCHESTRATOR_HOME overrides). afk also locates a project by its .devcontainer/.
  • Stop per-run npm install — guard on a missing/stale lockfile (Part A; helps all tiers). Baked copy installs into /opt once per container.

Three traps handled (each verified)

  1. Mount shadowing — the workspace bind mount hides anything baked at the workspace path → bake at the non-mounted /opt.
  2. Secret leakage — the image is public; COPYing the build context would bake gitignored .sandcastle/.env / orchestrator.env. Instead the Dockerfile git-fetches the committed code at AGENTIC_REF. ✅ Verified secrets are absent from the built image.
  3. No node at Dockerfile time — node arrives via a feature after the Dockerfile, so npm ci can't run there (confirmed devcontainer build does not bake onCreateCommand). Ship source only; install on first use into a vscode-owned /opt.

The bake is build-arg-gated (BAKE_ORCHESTRATOR), so the compose/runtime build stays lean and the dogfood is untouched. CI passes AGENTIC_REF=${{ github.sha }} so the image bakes the exact built commit.

Validation (local, real built image)

  • /opt/agentic-orchestrator has the source, no .env/orchestrator.env, owned vscode:vscode, node_modules absent (installed on first use).
  • A non-vendoring project (.devcontainer/ + config only) resolves afk/opt/agentic-orchestrator/run.sh.
  • 108 tests pass; typecheck clean.

Note / follow-up

First run does one npm install into /opt (not fully offline-from-boot). If that matters, bake node_modules per-arch via a second FROM <devcontainer-image> build stage — deferred (adds multi-arch build cost); noted in ADR-0016.

🤖 Generated with Claude Code

…install)

The published outer image carried only the runtime; the orchestrator (.sandcastle/*.ts)
still had to be vendored into every adopting repo, and run.sh ran `npm install` on
every launch. Bake the orchestrator SOURCE into /opt/agentic-orchestrator so adopters
run without vendoring, and install deps once per container instead of per run (ADR-0016).

Key constraints handled:
- The workspace bind mount shadows anything baked at the workspace path → bake at
  the non-mounted /opt.
- The image is public → clone the COMMITTED code at build time (Dockerfile, git
  fetch AGENTIC_REF) rather than COPY the build context, so gitignored secrets
  (.sandcastle/.env, orchestrator.env) can never be baked. Verified: secrets absent
  from the built image.
- node comes from a devcontainer feature (after the Dockerfile), so npm ci can't run
  at build time → ship source only; run.sh installs into /opt (chowned vscode) on
  first use. (Confirmed `devcontainer build` does NOT bake onCreateCommand.)

run.sh / afk resolve the orchestrator: prefer the workspace copy when it has the
source (dogfood / vendored adopters → local edits win), else fall back to the baked
/opt (override via AGENTIC_ORCHESTRATOR_HOME). afk also locates a project by its
.devcontainer/ so a non-vendoring adopter is found. The orchestrator always runs with
cwd = the project, so config/worktrees/identity resolve against the target repo.

The bake is build-arg-gated (BAKE_ORCHESTRATOR), so the compose/runtime build stays
lean and the dogfood is untouched. CI passes AGENTIC_REF=${github.sha} via
devcontainer.build.json so the image bakes the exact built commit.

Validated locally: built the dist image; /opt has the source, no secrets, owned by
vscode; a non-vendoring project resolves afk → baked run.sh. 108 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lsfera
lsfera merged commit 273b527 into main Jun 26, 2026
2 checks passed
@lsfera
lsfera deleted the feat/bake-orchestrator-into-image branch June 26, 2026 09:03
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