Repository navigation
Replies: 1 comment
Confirmed on both counts — but direction 2 would break the layer it aims to fixThank you for measuring rather than inferring; the chain reproduces from the source on Your chain is right. But the two paths are not two spellings of one check — they are two layers, and the So What that means for your three directions:
Your last section is the most valuable part, and I would underline it: reusing the host's One adjacent note, honestly scoped: the "mounted but silently inert" shape has a partial relative in the ecosystem — a plugin that is installed but never reaches the loaded set is what the activation-doctor style check watches ( |
Uh oh!
There was an error while loading. Please reload this page.
Summary
A plugin whose tool
outputschema is invalid mounts successfully, registers zero tools, and prints nothing. Two separate behaviours combine into that dead end:register()surfaces a contract violation only through the cordis logger, so on a normal deployment there is no visible error — measuredconsole.warninvocations: 0.output: { schema: { type: 'json' } }— is not in the output whitelist (SCHEMA_TYPES,dsh-tools/lib/index.js:50-58), while the same'json'sentinel is accepted on thevalueSchemaSpecpath thatdefineTooluses (:688-691, compiled to{}at:849). An author who hand-rollsregister(instead ofdefineTool) therefore walks into it with no feedback at all.Reproduction (measured on 0.2.0-rc.2, not inferred)
Running the same plugin under a real cordis
Context+ realToolRuntime+SystemPrompt:ctx.tools.schemas()console.warncalls{ type: 'json' }output){}Direct calls against the exported validators:
Call chain in the current tree:
SCHEMA_TYPEShas nojson(:50-58) → the violation is recorded (:236-237) →assertSupportedJsonSchemathrows (:323-327) →register()calls it at:2882, after forcing anoutputwith bothschemaandrender(:2881) → the throw is caught and logged, never rethrown.Why I think this is worth a change on the host side
The failure mode is silent by construction. The plugin appears in the loaded set, the tool list is simply empty, and there is nothing to grep for. In our case it survived a package with 282 passing tests — because those tests use a lenient hand-rolled
registerstub that never validatesoutput.schema. So neither the author's logs nor the author's CI can see it.From reading the code, the try/catch in
register()looks intended to tolerate things like duplicate tool names. A schema-contract violation is a different class of problem and currently disappears into the same path.Possible directions (author's opinion only — you know the design intent better)
'json'on the output path too, for parity with thevalueSchemaSpecpath — or, if that is deliberately not wanted, make the thrown message name the working alternative (output: { schema: jsonValueOutputSchema(), render }) explicitly, so the error teaches the fix.register()must produce a whitelist-compliantoutput.schema, and that a violation yields a silently tool-less plugin.A note that helped us on the plugin side
Reusing the host's exported
assertSupportedJsonSchemainside plugin tests catches this in CI in one line. A stubregisterthat accepts anything makes a whole suite blind to the host contract — that is how the 282 green tests happened.Happy to file a minimal reproduction repo if that is useful. Everything above was measured on
0.2.0-rc.2with a real (not stubbed) runtime.Context: found while integrating a third-party plugin bundle (ERD/data-modelling tools) from a scaffold into a web profile; four of its tools were silently absent until the output schemas were fixed. The same pattern was then checked across the other plugins in that bundle.
All reactions