diff --git a/README.md b/README.md index a4fa5d3..124234e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ detector — as a DeepSeek Harness bundle. Slopo finds non-obvious duplicated logic: similar implementations of the same problem that are not copy-paste, and that a human reviewer, a coding agent and a clone detector all miss. This bundle gives you three user-triggered skills and -one configuration-aware tool, so you can run it against whichever workspace you +one configuration-aware tool, and a settings card. Run it against whichever workspace you are in without remembering flags. ## What it adds @@ -17,8 +17,8 @@ are in without remembering flags. | `/slopo-analyze-ignore` | Triages the whole codebase's clusters, writing the obvious false positives into the ignore file. | | `/slopo-analyze-one` | Reports one cluster at a time — optionally by hash — and judges whether it is worth acting on. | | the `slopo` tool | Resolves the CLI, materialises the config, runs the work, and turns slopo's terse failures into something actionable. | -| the `dsh-slopo` settings namespace | The embedding backend and per-workspace state, editable at runtime. | - +| the `dsh-slopo` settings namespace | The embedding backend and per-workspace state, registered on the Host. | +| the settings card | A form for all of it, in Settings → Plugins → Plugin configuration. | All three skills are **user-invocable and deliberately not model-invocable**, matching slopo's own agent configs. Typing `/slopo-review` anywhere in a message injects that skill; the model will not reach for one on its own. Every one of @@ -30,13 +30,30 @@ these commands can spend minutes embedding, so the human decides when. dsh plugin --profile web add git+https://git.notexpectedyet.com/Not-Expected-Yet/dsh-slopo.git ``` -Then restart the profile — a new bundle's modules are resolved at startup. +Then restart the profile. A new bundle's modules are resolved at startup, and a +client half's bytes are snapshotted at activation — so the settings card only +appears after that restart. Plain ESM, no build step, and therefore no `prepare` script and no `allowBuilds` entry to authorise. That is deliberate: `dsh plugin add git+…` fetches the source tree rather than build output, so a `prepare` script would make every user allowlist a build before the first install can succeed. +## Settings + +The plugin contributes a card to **Settings → Plugins → Plugin configuration**, +keyed on the `dsh-slopo` settings namespace the Host registers. Every setting in +the table below is editable there, overridden fields are marked, and Reset +returns a field to the deployment default rather than to empty. + +The card is the bundle's second half — the browser half. It needs no build step +and ships as plain ESM in the module-loader wrapper, but the platform snapshots +client bundles at activation, so **a client half only appears after the profile +restarts.** Without it the namespace still works — it is editable in +`$DSH_HOME/settings.yaml` and through the tool's `configure` action — there is +simply no form drawn for it, because the tab renders the intersection of served +namespaces and registered cards. + ## Configure it Nothing is defaulted. Slopo itself requires a source directory, an embedding @@ -118,7 +135,7 @@ Or drive the tool directly: | Action | What it does | | --- | --- | -| `status` | Resolved settings, index state, binary, and what is still missing. | +| `status` | Everything: resolved settings, index state, the binary and its version, plus a live pre-flight against the embedding endpoint. | | `configure` | Patch the settings namespace. | | `prepare` | `slopo index` then `slopo embed` — the slow, possibly costly phase. | | `review` | Similar code involving Git changes (`base` defaults to `HEAD`). | @@ -228,6 +245,14 @@ that silently does nothing. Two real bugs were caught this way: a config renderer that would write the API key to disk if handed one, and `--config-version` placed before the subcommand, which slopo rejects with a usage error. +The browser half has no browser to run in, so its tests evaluate the bundle the +way the real module loader does — inside `window.__ModuleLoader__.load` — with a +fake `require` that answers `react` and throws on anything else. That last part is +deliberate: it checks the card stays inside the platform's seed table, which is +the constraint a hand-written client half is most likely to break. The card is +then rendered and its handlers driven, which is not a substitute for looking at +it but does cover the wiring it cannot work without. + `node_modules/@deepseek-ai` is a local symlink to the installed harness so the `@deepseek-ai/*` imports resolve during tests. It is gitignored and is not a declared dependency — an out-of-tree bundle that depended on an in-box package