You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
dm-agent-sync.ts swallows every failure mode silently — no log, no error, no surface. Combined with #112 / #113 this is why context-loss bugs go undetected for weeks. Three independent silent-failure paths in 120 lines:
Every WP-CLI call uses .quiet().nothrow() — failures produce empty output that's parsed as "no agents".
The whole config() callback is wrapped in try { ... } catch { /* silent */ } (lines 46–166).
Break WP-CLI in any way (DB down, plugin error, missing --allow-root privileges, multisite --url required, even a deprecation notice that pollutes JSON output).
Start an OpenCode session.
wp datamachine memory compose and wp datamachine agents list both .nothrow() — no error reaches OpenCode logs.
The regex agentsRaw.match(/\[[\s\S]*\]/) returns null on empty output → plugin returns silently at line 63.
Session launches with zero DM context. No indication anything went wrong.
Path 2: Outer catch swallows everything else
Lines 163–166:
}catch{// If WP-CLI is unavailable or Data Machine isn't installed, silently skip.// The plugin is a no-op on systems without Data Machine.}
Any JS-level error — JSON parse failure, schema mismatch in DM output, OpenCode API change, plugin permission denied — is silently swallowed. The "no-op when DM not installed" intent could be detected explicitly (e.g. which wp first); blanket-catching is too coarse.
After #60's prompt migration, agent.build blocks contain { mode: "primary", model: "anthropic/claude-opus-4-7" } — same as the top-level model. isUserOverride returns true for these because typeof model === "string", even though the user never customized anything. This means even when #113's agents.length === 1 gate fires, the override check inside it skips the prompt write.
Why it matters
This is the silent-failure substrate that turned a one-line incompleteness in #60 into weeks of degraded context across the fleet. The user only discovered it by asking an agent in a Discord thread "do you have AGENTS.md?" — and even then it took manual log inspection to find that the plugin had been running but doing nothing useful.
Detect "Data Machine not installed" up front instead of catching everything:
constwpAvailable=(await$`command -v wp`.quiet().nothrow()).exitCode===0;if(!wpAvailable)return;// Genuine no-op case.// ... rest of plugin without an outer try/catch, so real bugs surface.
Fix isUserOverride to detect actual customization
Compare against config defaults instead of just checking key presence:
functionisUserOverride(agent: Record<string,unknown>,topLevelModel?: string): boolean{// A block is user-customized if it has fields beyond the safe defaults,// or if its model differs from the top-level model.constsafeKeys=newSet(["mode","model"]);constextraKeys=Object.keys(agent).filter((k)=>!safeKeys.has(k));if(extraKeys.length>0)returntrue;// tools, prompt, description, etc.if(agent.mode&&agent.mode!=="primary")returntrue;if(agent.model&&agent.model!==topLevelModel)returntrue;returnfalse;}
End-to-end verification at session start
Optional but ideal: after registering, dump a one-line summary to OpenCode logs:
[dm-agent-sync] registered 10 DM agents; build/plan now use slug=extra-chill-bot, prompt=AGENTS.md+4 files
Then a grep on kimaki.log answers "is the plugin doing anything?" without needing to inspect the next session's system prompt.
Test plan
WP-CLI exits non-zero → warning appears in OpenCode logs.
Data Machine not installed (no wp binary) → silent skip, no warning.
wp datamachine agents list returns malformed JSON → warning, no JS exception.
Summary
dm-agent-sync.tsswallows every failure mode silently — no log, no error, no surface. Combined with #112 / #113 this is why context-loss bugs go undetected for weeks. Three independent silent-failure paths in 120 lines:.quiet().nothrow()— failures produce empty output that's parsed as "no agents".config()callback is wrapped intry { ... } catch { /* silent */ }(lines 46–166).isUserOverride()(line 178) returns true if the agent block has anymodelstring — including the defaultanthropic/claude-opus-4-7value emitted into orphanedagent.buildshells (see repair-opencode-json.py: orphaned empty agent.build/plan blocks survive #60 prompt migration and silently break dm-agent-sync #112). This third path is the most surprising: it makes the override check fire for blocks the user never customized.Repro
Path 1: WP-CLI silently fails
--allow-rootprivileges, multisite--urlrequired, even a deprecation notice that pollutes JSON output).wp datamachine memory composeandwp datamachine agents listboth.nothrow()— no error reaches OpenCode logs.agentsRaw.match(/\[[\s\S]*\]/)returnsnullon empty output → plugin returns silently at line 63.Path 2: Outer catch swallows everything else
Lines 163–166:
Any JS-level error — JSON parse failure, schema mismatch in DM output, OpenCode API change, plugin permission denied — is silently swallowed. The "no-op when DM not installed" intent could be detected explicitly (e.g.
which wpfirst); blanket-catching is too coarse.Path 3:
isUserOverrideflags default-only blocksLine 178:
After #60's prompt migration,
agent.buildblocks contain{ mode: "primary", model: "anthropic/claude-opus-4-7" }— same as the top-levelmodel.isUserOverridereturns true for these becausetypeof model === "string", even though the user never customized anything. This means even when #113'sagents.length === 1gate fires, the override check inside it skips the prompt write.Why it matters
This is the silent-failure substrate that turned a one-line incompleteness in #60 into weeks of degraded context across the fleet. The user only discovered it by asking an agent in a Discord thread "do you have AGENTS.md?" — and even then it took manual log inspection to find that the plugin had been running but doing nothing useful.
Same family as:
This is a recurring pattern; the plugins need a uniform observability story.
Proposed fix
Surface failures to OpenCode logs
Replace
.nothrow()with explicit error handling that logs to OpenCode's logger so failures appear in the same stream as other plugin errors:Tighten the outer catch
Detect "Data Machine not installed" up front instead of catching everything:
Fix
isUserOverrideto detect actual customizationCompare against config defaults instead of just checking key presence:
End-to-end verification at session start
Optional but ideal: after registering, dump a one-line summary to OpenCode logs:
Then a grep on
kimaki.loganswers "is the plugin doing anything?" without needing to inspect the next session's system prompt.Test plan
wpbinary) → silent skip, no warning.wp datamachine agents listreturns malformed JSON → warning, no JS exception.agent.build = { mode: "primary", model: "<top-level model>" }(post-fix(opencode): use instructions array, not agent.build.prompt #60 orphan) →isUserOverridereturns false → prompt injected.agent.build = { tools: {...}, model: "..." }(genuine user override) →isUserOverridereturns true → preserved.Related
isUserOverrideworking correctly post-cleanupagent.build/agent.planshells thatisUserOverridemis-classifiesagents.length === 1gate preventing multi-agent override checksEnvironment
0.8.1(commitb7e5acb)/opt/kimaki-config/plugins/dm-agent-sync.tslines 46–166isUserOverridedefeats dm-agent-sync.ts: user-override detection only fires when agents.length === 1, leaving multi-agent installs unsynced #113's fix even after repair-opencode-json.py: orphaned empty agent.build/plan blocks survive #60 prompt migration and silently break dm-agent-sync #112's repair