Skip to content

fix: make upgrade cover the Claude Code runtime + single-agent scoping#244

Merged
chubes4 merged 1 commit into
mainfrom
fix/claude-code-runtime-upgrade-parity
Jun 28, 2026
Merged

fix: make upgrade cover the Claude Code runtime + single-agent scoping#244
chubes4 merged 1 commit into
mainfrom
fix/claude-code-runtime-upgrade-parity

Conversation

@chubes4

@chubes4 chubes4 commented Jun 27, 2026

Copy link
Copy Markdown
Member

Problem

On existing installs, the Claude Code runtime silently rotted while opencode kept working.

upgrade.sh upgrades opencode/kimaki (opencode.json drift, kimaki plugins, systemd units, AGENTS.md compose) but never re-syncs the Claude Code SessionStart hook (.claude/hooks/dm-agent-sync.sh) and won't regenerate CLAUDE.md (line: "don't clobber it"). So the claude-code runtime is installed once at setup and never updated.

The installed hook drifted to a broken version that exit 0s every session:

  • strict a.get('status') == 'active' filter — but Data Machine removed the status field, so every row fails the filter and ACTIVE_SLUGS is empty;
  • datamachine agent paths (a command that doesn't exist; it's memory paths);
  • missing the pre-compose refresh.

Result: CLAUDE.md never gets its <!-- DM_AGENT_SYNC_START --> memory block and degenerates to just @AGENTS.md. The agent boots with no SOUL.md/MEMORY.md — no personality, no memory. opencode was unaffected because its runtime injects the configured agent's files into opencode.json's instructions array directly.

Fix

  • upgrade.sh — new Phase 5b (sync_claude_code_runtime): re-copies the hook, writes the agent-scope sidecar, refreshes settings.json, and regenerates a degenerate CLAUDE.md from the template. Makes claude-code a first-class upgrade target alongside opencode. Resolves the install's agent slug via: explicit override → existing sidecar → domain- or directory-basename-derived candidate validated against the live DM agent list (Studio's siteurl is http://localhost:PORT, so the directory basename is the reliable signal there).
  • hooks/dm-agent-sync.sh — single-agent scoping (OpenCode parity): when dm-agent-sync.env sets DM_AGENT_SLUG, inject only that agent's files. Falls back to all-active-agents discovery when the sidecar is absent (backward compatible). Also carries the upstream status/memory paths/compose fixes.
  • runtimes/claude-code.sh: runtime_install_hooks writes the dm-agent-sync.env sidecar with the configured AGENT_SLUG.
  • lib/data-machine.sh: extract derive_agent_slug() shared by setup and upgrade.
  • tests/claude-code-hook-scope.sh + CI: regression coverage for both hook modes.

Verification

Applied to a live Studio install via ./upgrade.sh --runtime claude-code --agents-md-only:

  • slug resolved to the install's agent (single-agent parity);
  • CLAUDE.md regenerated with the agent's SOUL.md/MEMORY.md/USER.md/SITE.md/RULES.md and no other agents leaking in;
  • installed hook byte-identical to the fixed repo hook and runs clean/idempotent.

Full CI shell suite + .mjs tests pass locally, including the new test.

🤖 Generated with Claude Code

The Claude Code runtime silently rotted on existing installs: upgrade.sh
upgraded opencode/kimaki but never re-synced the SessionStart hook
(.claude/hooks/dm-agent-sync.sh) or regenerated CLAUDE.md. A stale hook
(strict status=='active' filter on an agents list that no longer carries a
status field, plus a `datamachine agent paths` typo) kept exit 0-ing, so
CLAUDE.md never got its Data Machine memory block — the agent booted with
no SOUL.md/MEMORY.md, just @AGENTS.md. opencode kept working because its
runtime injects the configured agent's files into opencode.json directly.

Changes:
- upgrade.sh: new Phase 5b (sync_claude_code_runtime) re-copies the hook,
  writes the agent-scope sidecar, refreshes settings.json, and regenerates
  a degenerate CLAUDE.md from the template. Resolves the install's agent
  slug from an explicit override -> existing sidecar -> domain- or
  directory-basename-derived candidate validated against the DM agent list
  (Studio's siteurl is http://localhost:PORT, so basename is the reliable
  signal there).
- hooks/dm-agent-sync.sh: when dm-agent-sync.env sets DM_AGENT_SLUG, inject
  only that agent's files — OpenCode parity (single configured agent).
  Falls back to all-active-agents discovery when the sidecar is absent.
- runtimes/claude-code.sh: runtime_install_hooks writes the
  dm-agent-sync.env sidecar with the configured AGENT_SLUG.
- lib/data-machine.sh: extract derive_agent_slug() shared by setup and
  upgrade.
- tests/claude-code-hook-scope.sh + CI: regression coverage for both hook
  modes (scoped vs all-agents).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chubes4 chubes4 merged commit 2ffdeba into main Jun 28, 2026
13 checks passed
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