Skip to content

dm-agent-sync.ts: user-override detection only fires when agents.length === 1, leaving multi-agent installs unsynced #113

@chubes4

Description

@chubes4

Summary

dm-agent-sync.ts only injects DM agent prompts into config.agent.build / config.agent.plan when exactly one DM agent exists (line 129). Multi-agent installs (this VPS has 10 agents) skip the injection branch entirely. Combined with #112 (orphaned empty build/plan blocks), the agent runtime launches without AGENTS.md, SOUL.md, MEMORY.md, etc.

Repro

  1. Site with 2+ active DM agents.
  2. opencode.json contains an agent.build / agent.plan block with no prompt (typical post-fix(opencode): use instructions array, not agent.build.prompt #60 state — see repair-opencode-json.py: orphaned empty agent.build/plan blocks survive #60 prompt migration and silently break dm-agent-sync #112).
  3. Start a Kimaki/OpenCode session.
  4. Inspect system prompt: no AGENTS.md, no agent identity files. dm-agent-sync registered the agents under their slug names (config.agent[slug]), but the default build / plan agents — which is what almost every session actually uses — were not touched.

Root cause

In /opt/kimaki-config/plugins/dm-agent-sync.ts lines 127–139:

// Check if this agent is already defined in the config (user override).
// Don't overwrite explicit user config — only fill in missing agents.
if (config.agent.build && config.agent.plan && agents.length === 1) {
  // Single agent + build/plan already defined = user has configured it.
  // Still update the prompt to ensure file paths are current.
  if (!isUserOverride(config.agent.build)) {
    config.agent.build.prompt = prompt;
  }
  if (!isUserOverride(config.agent.plan)) {
    config.agent.plan.prompt = prompt;
  }
  continue;
}

// For multi-agent setups, register each agent by slug.
// First active agent also populates build/plan defaults if not set.
if (!config.agent.build) {
  config.agent.build = { ...buildEntry };
}

Two interacting problems:

  1. The single-agent gate (agents.length === 1) is overly narrow. The intent of the comment ("don't overwrite explicit user config") is correctly captured by isUserOverride() — but only inside the gate. For multi-agent installs, the override check never runs.
  2. The fallback at line 143 (if (!config.agent.build)) is short-circuited by the empty post-fix(opencode): use instructions array, not agent.build.prompt #60 agent.build shells, so even the multi-agent path does not write a prompt.

Net effect: on multi-agent installs the build and plan agents never receive a DM prompt at all, regardless of whether the user explicitly configured them.

Proposed fix

Restructure the override logic so it runs uniformly for any agents.length:

// Pick the "primary" DM agent for build/plan defaults — typically the first
// active agent, or one matching some channel/owner heuristic. For now: first.
const primary = agents[0];

// For build/plan: inject DM prompt unless the user explicitly customized them.
for (const slot of ['build', 'plan'] as const) {
  const existing = config.agent[slot];
  if (!existing || !isUserOverride(existing)) {
    config.agent[slot] = {
      ...(existing ?? {}),  // preserve mode/model/tools if present
      prompt: primaryPrompt,
    };
  }
}

// Always register every agent under its slug for the agent switcher.
for (const agent of agents) { ... }

Treat isUserOverride as the single source of truth for "leave it alone" — independent of agent count.

Why it matters

This is the runtime half of #112. Even after #112's repair removes orphaned shells, multi-agent installs still need this plugin path to work correctly so the next session inherits a usable build/plan agent.

Together they explain why this VPS has been launching sessions without AGENTS.md for weeks: #112 leaves the empty shells, and this bug means even a clean shell wouldn't help on a multi-agent install.

Test plan

  • Single-agent install with user-customized build → not touched.
  • Single-agent install with default build → DM prompt injected.
  • Multi-agent install with empty build shell → DM prompt injected (currently broken).
  • Multi-agent install with no agent block → build/plan created with DM prompt.
  • Multi-agent install with user-customized build.tools → tools preserved, prompt injected.

Verification gap

Both wp datamachine memory compose and wp datamachine agents list are called with .quiet().nothrow(). If either fails (DB down, --allow-root rejected, plugin not installed), the plugin exits silently with no registration and no error surfaces. Worth a follow-up issue: surface plugin failures to OpenCode logs with a clear marker so silent context-loss like this is detectable from logs alone.

Related

Environment

  • wp-coding-agents 0.8.1 (commit b7e5acb)
  • Plugin: /opt/kimaki-config/plugins/dm-agent-sync.ts
  • VPS: /var/www/extrachill.com, 10 DM agents, Kimaki bridge

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions