The integration tests load the real plugin module against a thin mock Cordis
context and drive the tool through a real shell into the real slopo binary. The
mock implements only the seams the plugin touches, so a wrong assumption about a
dsh service fails a test instead of producing a plugin that silently does
nothing at runtime.
Two real bugs were caught this way and are now pinned:
* renderSlopoConfig would write the embedding API key to disk if it were
handed one. It cannot now.
* --config-version was placed before the subcommand, which slopo rejects with
exit code 2. It is declared on the command, not the callback.
The end-to-end test is opt-in (DSH_SLOPO_E2E=1) because it needs a reachable
embedding backend; it indexes a real repository, embeds it, and asserts a real
duplicate cluster comes back.
The three SKILL.md files are ports of the configs slopo 0.8.0 ships for
Claude Code, not new prose. What changed is the mechanics:
* name + description frontmatter, both required by dsh
* disable-model-invocation: true kept verbatim -- dsh has the same key,
and slopo makes that choice for a reason (every one of these commands
can spend minutes embedding)
* allowed-tools / argument-hint / arguments dropped, not dsh keys
* the !`slopo ...` shell-injection directive replaced with an
instruction to call the slopo tool plus an explicit failure check,
because dsh skill bodies do not execute commands
The guidance prose is quoted from slopo; NOTICE.md records the mapping and
the licence obligation that follows from it (AGPL-3.0-or-later, matching
upstream and the LICENSE file fetched from it).