Replies: 2 comments
|
Checked your Confirmed: But: on Windows specifically, So if Your third question (surfacing unsatisfied injections at boot) seems worth pursuing regardless of which explanation is right — "config-valid but silently inert forever" is a real diagnosability gap either way. |
|
Verified against the current checkout (master @ Q1 — Q2 — your
Q3 — surfacing unsatisfied injections at boot: agreed, and the gap is worse than you thought — but only in one place.
What I think is actually happening — two silent candidates, discriminated by one command:
One command discriminates: Family note. This is the 6th loader-entry-lifecycle report (with #1377/#1404/#1610/#2854/#2889): an entry that resolves and validates but is inert, with no observable channel to say why. The |
Uh oh!
There was an error while loading. Please reload this page.
Found while wiring an external governance tool to the Claude Code hook bridge. Posting here rather than as an issue per
CONTRIBUTING.md.Short version: a plugin inserted through a
--patchoverlay is resolved, applied and config-validated, and then appears never to activate — no handler ever runs. I could not find the reason from the outside becausectx.loggerhas no sink in either shipped profile, so the warning that would explain it is unobservable.This is not the PowerShell exit-code fail-open in #2485. There the hook runs and its exit code is mangled; here the hook command never executes at all — a marker command that only appends to a file leaves no file.
Environment
dsh0.1.0-rc.7 (npmnext),@deepseek-ai/dsh-hooks-claude-code0.1.0-rc.6headlessandweb, both freshly materialisedReproduce
hooks.json— the command deliberately involves no third-party tool, so nothing but the bridge is on trial:{ "hooks": { "PreToolUse": [ { "matcher": ".*", "hooks": [ { "type": "command", "timeout": 60, "command": "node -e \"require('fs').appendFileSync('C:/tmp/proj/marker.txt','fired\\n')\"" } ] } ] } }patch.yml:dsh --profile headless --patch patch.yml "create a file named hello.txt containing hi"Observed: the agent creates
hello.txtand exits normally.marker.txtis never created. No warning, no error, on stdout or stderr.Expected: either the hook runs, or something says why it did not.
The mount is fine — that part is verifiable
Both ways an entry can be wrong fail loudly, so a valid entry really is resolved, applied and validated:
Ruled out along the way: package not installed; version skew (rc.5 → rc.6 against runtime rc.7); the patch not composing (
--dump-configshows the entry); absolute vs relativeconfigPath; spaces in the path (the 8.3 short form behaves identically); and the config file shape —parseClaudeCodeConfigaccepts a barehooksevent map ofcommandhooks, which is what is being fed.No diagnostic channel in either shipped profile
packages/hooks/hooks-claude-codecatches a config-load failure, callsctx.logger.warn(... — no hooks registered)and returns, and theexamples/acp-agent/cordis.ymlcomment notes warnings "usectx.logger, never stdout". That is reasonable, but neither shipped profile appears to mount a sink:dsh --profile headless --dump-configand--profile web --dump-configcontain no logger entry.webwith aconfigPathpointing at a file that does not exist produced no warning at all.@deepseek-ai/cordis-plugin-logger-console(as inexamples/headless-agent/tests/fixtures/session-telemetry-otel.cordis.yml) through the same--patchproduced zero output, including from the logger itself — which may be the same activation problem, one level down.So a mount that silently does nothing is also a mount that cannot be debugged from a released install.
Guess, offered only as a starting point
lib/index.jsdeclaresinject = ["shell"]. If activation is gated on service availability while config validation happens earlier at apply, that would explain the whole pattern at once: a config error is visible, an unsatisfied injection is not, and an inactive plugin registers nothing. I could not confirm whetherheadlessprovides ashellservice — it composesdsh-bash-sandbox,dsh-shell-env,dsh-subprocess-localanddsh-tool-bash.Questions
--patchinsertexpected to activate plugins the same way a bundle layer does, or is there an additional step for out-of-tree packages that declare nodsh.bundle?headlesssatisfyinject: ["shell"]? If not, is that the intended reason the bridge is inert there, and is there a supported profile for running it?Happy to test a patch or supply fuller logs.
All reactions