refactor(archon): wire CLAUDE_BIN_PATH for live-workflow agent work orders (#2217) - #2359
Conversation
…rders Issue #2217 (2026-08-03): the archon service in `pmoves/docker-compose.yml` already wires the bulk of the live-workflow auth (CLAUDE_API_KEY, CLAUDE_CODE_OAUTH_TOKEN, CLAUDE_USE_GLOBAL_AUTH, GH_TOKEN). One last token from the issue's "Auth for live workflows" section is still missing: `CLAUDE_BIN_PATH` — the path to the Claude CLI binary inside the container. The TS archon server uses this when spawning Claude Code as a subprocess for the Agent Work Orders feature. This is a 1-token, 1-PR change — the lane is small because the upstream `PMOVES-Archon/.env.example` mapping was mostly already done in earlier PRs. The only thing this commit adds: - `pmoves/docker-compose.yml`: add `CLAUDE_BIN_PATH=${CLAUDE_BIN_PATH:-}` to the `archon` service env, with a 4-line comment explaining the default behavior ($PATH) and the upstream's standard install path (/usr/local/bin/claude). - `pmoves/docker-compose.agents.yml`: regenerated by `make -C pmoves compose-split` to reflect the new env var on the agents-profile split. All other splits are unchanged (they don't include archon). - `pmoves/env.tier-agent.example`: new "Archon — Claude / gh live-workflow auth (Issue #2217)" section that documents the full set of live-workflow tokens (CLAUDE_API_KEY, CLAUDE_CODE_OAUTH_TOKEN, CLAUDE_USE_GLOBAL_AUTH, CLAUDE_BIN_PATH, GH_TOKEN) with comments on each. This makes the operator's `env.shared` setup explicit; previously these were scattered or undocumented. Validation: `yaml.safe_load` parses the main compose; `make -C pmoves compose-split` reports 102/102 services across overlays, all YAML syntactically valid. What does NOT change (intentionally, out of scope for this lane): - The Makefile archon targets (`up-archon-submodule`, `up-archon-native`, `archon-smoke`, etc.) — they don't reference CLAUDE_BIN_PATH. - The upstream `PMOVES-Archon/.env.example` has additional env vars (`ENABLE_AGENT_WORK_ORDERS`, `STATE_STORAGE_TYPE`, `SERVICE_DISCOVERY_MODE`, etc.) that aren't relevant to PMOVES' single-service deployment. We can wire them in a follow-up lane if Agent Work Orders is ever added as a separate PMOVES service. - The `archon-data` / `archon-user-home` / `archon-pg-data` volumes — those are persistent state, not auth. Refs: #2217
#2217) Lane 2217 (2026-08-03): closes the lane. The CLAIM goes on the AGNOTE; the cold-read spec captures the full design for a fresh local model picking this work up next session. What lands: - pmoves/docs/AGENTS/AGNOTE4482PHI.t1.md: new section "Issue #2217 — Archon 0.6.0 env wiring (2026-08-03)" with the full CLAIM text. Ends with the GRAPHITI_MARK HTML comment so a future graphiti loader can index it. - pmoves/docs/specs/archon-env-wiring-2026-08-03.md (new, ~5KB): cold-read spec covering TL;DR + why now + what shipped (P1 only, since the lane is small enough for 1 commit) + validation + out of scope + what's left for Issue #2217 + three-body + CHIT trail. The functional commit is already pushed. The PR is ready to push after this commit lands: YAML parses, compose-split regenerates cleanly (102/102 services), 1 env var + 5 lines of comments in env.tier-agent.example. Refs: #2217
Docker Hardening ValidationHardening Validation ReportValidated: Mon Aug 3 15:46:33 UTC 2026Services CheckedPMOVES.AI Docker Hardening Validation[INFO] Checking: pmoves/docker-compose.hardened.yml [INFO] Validating: hi-rag-gateway-v2 [INFO] Validating: extract-worker [INFO] Validating: langextract [INFO] Validating: presign [INFO] Validating: render-webhook [INFO] Validating: retrieval-eval [INFO] Validating: pdf-ingest [INFO] Validating: jellyfin-bridge [INFO] Validating: invidious-companion-proxy [INFO] Validating: ffmpeg-whisper [INFO] Validating: media-video [INFO] Validating: media-audio [INFO] Validating: hi-rag-gateway-v2-gpu [INFO] Validating: hi-rag-gateway-gpu [INFO] Validating: deepresearch [INFO] Validating: supaserch [INFO] Validating: publisher-discord [INFO] Validating: mesh-agent [INFO] Validating: nats-echo-req [INFO] Validating: nats-echo-res [INFO] Validating: comfy-watcher [INFO] Validating: grayjay-plugin-host [INFO] Validating: agent-zero [INFO] Validating: p7-room-orchestrator [INFO] Validating: archon [INFO] Validating: channel-monitor [INFO] Validating: pmoves-yt [INFO] Validating: notebook-sync [INFO] Validating: supabase_service_role_key [INFO] Validating: supabase_jwt_secret [INFO] Validating: p7_control_token ====================================== |
📝 WalkthroughWalkthroughArchon now supports configurable Claude CLI paths in both compose definitions. The agent-tier environment template documents Claude and GitHub authentication variables. An AGNOTE and specification record the wiring, validation, and Issue ChangesArchon environment wiring
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20bcd46e51
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # Default empty (uses $PATH). The upstream Archon Dockerfile installs | ||
| # Claude at /usr/local/bin/claude; set this only if the image builds | ||
| # Claude at a non-standard path or you want to pin a specific binary. | ||
| - CLAUDE_BIN_PATH=${CLAUDE_BIN_PATH:-} |
There was a problem hiding this comment.
Let env.tier-agent supply the custom Claude binary path
When an operator follows the new template and sets CLAUDE_BIN_PATH only in env.tier-agent, the documented raw docker compose --profile agents ... invocation in pmoves/README.md:112 does not use that file for Compose interpolation. This expression therefore resolves to an empty string, and the explicit environment entry overrides the value that the service's env_file would otherwise inject. Custom Archon images consequently fall back to $PATH and cannot launch Claude; the repository already identifies this exact empty-default shadowing pattern in pmoves/docs/operations/CREDENTIAL_AND_DRIFT_SITREP.md:85. Omit the explicit entry or ensure every supported invocation supplies the tier file with --env-file.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
pmoves/env.tier-agent.example (1)
77-78: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winDocument least-privilege GitHub permissions.
The template prescribes
repo, workflowwithout identifying the Archon operations that require them. Verify the minimum permissions for Archon 0.6.0. Prefer a fine-grained, repository-scoped token where possible instead of making broad classic-PAT access the default guidance.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pmoves/env.tier-agent.example` around lines 77 - 78, Update the GH_TOKEN documentation near the env.tier-agent example to verify and describe the minimum GitHub permissions required by Archon 0.6.0, mapping each permission to the specific Archon operation that uses it. Prefer guidance for a fine-grained, repository-scoped token and present broad classic-PAT scopes only when unavoidable.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pmoves/env.tier-agent.example`:
- Around line 65-70: Update the Archon authentication comment near the Claude/gh
live-workflow section to explicitly identify Archon live workflows as the
exception to the TensorZero-only policy, and state that CLAUDE_API_KEY and
CLAUDE_CODE_OAUTH_TOKEN must not be copied or provided to other agent-tier
services.
---
Nitpick comments:
In `@pmoves/env.tier-agent.example`:
- Around line 77-78: Update the GH_TOKEN documentation near the env.tier-agent
example to verify and describe the minimum GitHub permissions required by Archon
0.6.0, mapping each permission to the specific Archon operation that uses it.
Prefer guidance for a fine-grained, repository-scoped token and present broad
classic-PAT scopes only when unavoidable.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 07bea862-f186-4fd7-8505-cda5669d2748
📒 Files selected for processing (5)
pmoves/docker-compose.agents.ymlpmoves/docker-compose.ymlpmoves/docs/AGENTS/AGNOTE4482PHI.t1.mdpmoves/docs/specs/archon-env-wiring-2026-08-03.mdpmoves/env.tier-agent.example
| # --------------------------------------------------------------------------- | ||
| # Archon — Claude / gh live-workflow auth (Issue #2217) | ||
| # --------------------------------------------------------------------------- | ||
| # The TS server exits(1) at boot if no Claude auth is present. The compose | ||
| # file wires the following tokens to the `archon` service env. Set at least | ||
| # one of CLAUDE_API_KEY or CLAUDE_CODE_OAUTH_TOKEN; leave the others empty. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
State the Archon exception to the TensorZero-only policy.
The file says agent-tier services must not receive direct external LLM API keys, but this section instructs operators to set CLAUDE_API_KEY. State that Archon live workflows are the exception and that these credentials must not be copied to other agent services.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pmoves/env.tier-agent.example` around lines 65 - 70, Update the Archon
authentication comment near the Claude/gh live-workflow section to explicitly
identify Archon live workflows as the exception to the TensorZero-only policy,
and state that CLAUDE_API_KEY and CLAUDE_CODE_OAUTH_TOKEN must not be copied or
provided to other agent-tier services.
archon boots healthy, passes its health check, and dies on the first workflow with `billing_error: Credit balance is too low`. The cause is not a missing value, it is a missing slot. env.tier-agent.example has declared CLAUDE_CODE_OAUTH_TOKEN since PR #2359, and both compose files wire `${CLAUDE_CODE_OAUTH_TOKEN:-}` into the archon service. But the label was never in the CHIT registry, so the funnel had no route for it and the live env.tier-agent carries none of the five Claude auth vars the example promises. Meanwhile ANTHROPIC_API_KEY is a registered slot, is set fleet-wide from env.shared, and the Claude CLI PREFERS it over the OAuth token. archon says so in its own source: "the CLI prefers ANTHROPIC_API_KEY over the OAuth token, so injecting the install key alongside it would silently rebill the run". So the metered key wins and the coding plan never gets a chance. MODEL_FABRIC_CONTRACT.md:44 already lists `Claude Code Max` in the approved coding-plan inventory. This is a missing slot, not a new policy decision. Registered via the sanctioned path only -- registry entry, then chit-manifest-register, then chit-manifest-sync. No manifest was hand-edited. NECESSARY BUT NOT SUFFICIENT. This routes the label; it does not conjure a value. secrets_sync.py skips an entry entirely when no source value exists (`if source_key is None: continue`), so until a token is provisioned into the CGP source the key is emitted NOT AT ALL -- not emitted empty. That is the same blank-is-not-absent rule #2688 established: an empty secret is not a secret, so absent stays absent. archon therefore behaves exactly as it does today until the value lands. No regression, and no fix yet either. SECOND FIX, unavoidable and deliberate: the same sync emits `min_length: 64` onto secret_key_base in the v1 manifest. PR #2688 added that constraint to the registry, to v2, and to the sync logic, but never re-ran the sync -- and secrets_sync.py reads v1 (tools/secrets_sync.py:336). So the min-length gate shipped in #2688 has been INERT on main: the constraint lived in v2 and in the tooling while the file the enforcer reads never carried it. It could not be excluded here without hand-editing a machine-emitted file, which the pipeline forbids, so it ships with this change rather than silently. Gates: - chit-manifest-register --check: manifest complete, no constraint drift - negative-tested: an unregistered label fails the check with Error 1 - secrets-funnel run end to end: 0 errors, env.tier-agent regenerated Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X9mpK1ZFjexjthZbvcb94f
…ugh (#2700) * fix(secrets): the Claude coding-plan token had no slot to arrive through archon boots healthy, passes its health check, and dies on the first workflow with `billing_error: Credit balance is too low`. The cause is not a missing value, it is a missing slot. env.tier-agent.example has declared CLAUDE_CODE_OAUTH_TOKEN since PR #2359, and both compose files wire `${CLAUDE_CODE_OAUTH_TOKEN:-}` into the archon service. But the label was never in the CHIT registry, so the funnel had no route for it and the live env.tier-agent carries none of the five Claude auth vars the example promises. Meanwhile ANTHROPIC_API_KEY is a registered slot, is set fleet-wide from env.shared, and the Claude CLI PREFERS it over the OAuth token. archon says so in its own source: "the CLI prefers ANTHROPIC_API_KEY over the OAuth token, so injecting the install key alongside it would silently rebill the run". So the metered key wins and the coding plan never gets a chance. MODEL_FABRIC_CONTRACT.md:44 already lists `Claude Code Max` in the approved coding-plan inventory. This is a missing slot, not a new policy decision. Registered via the sanctioned path only -- registry entry, then chit-manifest-register, then chit-manifest-sync. No manifest was hand-edited. NECESSARY BUT NOT SUFFICIENT. This routes the label; it does not conjure a value. secrets_sync.py skips an entry entirely when no source value exists (`if source_key is None: continue`), so until a token is provisioned into the CGP source the key is emitted NOT AT ALL -- not emitted empty. That is the same blank-is-not-absent rule #2688 established: an empty secret is not a secret, so absent stays absent. archon therefore behaves exactly as it does today until the value lands. No regression, and no fix yet either. SECOND FIX, unavoidable and deliberate: the same sync emits `min_length: 64` onto secret_key_base in the v1 manifest. PR #2688 added that constraint to the registry, to v2, and to the sync logic, but never re-ran the sync -- and secrets_sync.py reads v1 (tools/secrets_sync.py:336). So the min-length gate shipped in #2688 has been INERT on main: the constraint lived in v2 and in the tooling while the file the enforcer reads never carried it. It could not be excluded here without hand-editing a machine-emitted file, which the pipeline forbids, so it ships with this change rather than silently. Gates: - chit-manifest-register --check: manifest complete, no constraint drift - negative-tested: an unregistered label fails the check with Error 1 - secrets-funnel run end to end: 0 errors, env.tier-agent regenerated Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X9mpK1ZFjexjthZbvcb94f * fix(secrets): route the OAuth token into the runner bundle too Review on #2700 caught that the manifest slot alone does not reach production or self-hosted nodes. sync-secrets-local.yml builds the CGP bundle solely from its explicit env: map, and the v1 sync discards github_secret targets -- so a registered label with no row in that map funnels nothing on any node hydrated from the bundle. Archon would keep the metered-key behaviour this change set exists to fix. The workflow says so in its own comment, two lines above where the key was missing: "Absent from this map = never delivered." Adds CLAUDE_CODE_OAUTH_TOKEN beside the other prod-environment-scoped coding-plan keys (ALIBABA_PRO_CODING_PLAN, KIMI_CODING_API, KILOCODE_API_KEY), which is where it belongs -- it is the same class of credential and resolves the same way under environment: prod. This is the third routing layer the token has to cross: the registry entry so the manifest emits it, this map so the bundle carries it, and the GitHub prod secret so there is a value at all. Declaring a value and routing a value are separate acts, and only the last one is load-bearing. YAML re-parsed clean after the edit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X9mpK1ZFjexjthZbvcb94f --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
refactor(archon): wire CLAUDE_BIN_PATH for live-workflow agent work orders (Issue #2217)
Issue #2217's "Auth for live workflows" section listed three things:
CLAUDE_USE_GLOBAL_AUTH, thetoken(ambiguous; either API key or OAuth token), andCLAUDE_BIN_PATH. The first two are already wired;CLAUDE_BIN_PATHis the only remaining piece. The TS archon server usesCLAUDE_BIN_PATHwhen spawning the Claude CLI as a subprocess for the Agent Work Orders feature.2 stacked commits
f4f6cfe2ee20bcd46e51What ships
P1 — the env wiring:
pmoves/docker-compose.yml— addCLAUDE_BIN_PATH=${CLAUDE_BIN_PATH:-}to thearchonservice env, with a 4-line comment explaining the default (uses$PATH) and the upstream's standard install path (/usr/local/bin/claude).pmoves/docker-compose.agents.yml— regenerated bymake -C pmoves compose-splitto reflect the new env var on theagents-profile split. All other split overlays are unchanged.pmoves/env.tier-agent.example— new "Archon — Claude / gh live-workflow auth (Issue Archon 0.6.0 integration: first-class main-compose service + fabric wiring + Claude/gh auth #2217)" section that documents the full set of live-workflow tokens (CLAUDE_API_KEY, CLAUDE_CODE_OAUTH_TOKEN, CLAUDE_USE_GLOBAL_AUTH, CLAUDE_BIN_PATH, GH_TOKEN) with comments on each. This makes the operator'senv.sharedsetup explicit.Docs:
pmoves/docs/specs/archon-env-wiring-2026-08-03.md.Validation
yaml.safe_loadparses the main compose cleanlymake -C pmoves compose-splitreports 102/102 services across overlays, all YAML syntactically validWhat does NOT change (intentionally)
up-archon-submodule,up-archon-native,archon-smoke, etc.) — they don't referenceCLAUDE_BIN_PATH.archon-data/archon-user-home/archon-pg-datavolumes — those are persistent state, not auth.PMOVES-Archon/.env.exampleadditional env vars (ENABLE_AGENT_WORK_ORDERS,STATE_STORAGE_TYPE,SERVICE_DISCOVERY_MODE,ENABLE_DOCKER_SOCKET_MONITORING,MCP_HEALTH_CHECK_TIMEOUT,LOGFIRE_TOKEN,LOG_LEVEL) — not relevant to PMOVES's single-service deployment. We can wire them in a follow-up lane if Agent Work Orders is ever added as a separate PMOVES service.What this means for Issue #2217
Items #1 (first-class main-compose service), #2 (fabric wiring), #3 (DB decision), and #5 (retire the dead Python wrapper) were all already done in earlier PRs. Item #4 (auth for live workflows) is now complete with this commit. The issue is effectively closed at the wiring level.
Three-body
CLAUDE_BIN_PATHinenv.sharedif needed; verifies the archon service still boots)env.tier-agent.exampleRefs: #2217
Summary by CodeRabbit