surfaces: every daemon route has a verb and a provider method - #94
Merged
Conversation
Both extractors already carried the normalisation the OpenAPI templates
need — `${id}` -> `{}` in provider-methods.mjs, `{id}` -> `{}` in
cli-routes.sh, and a `split("?")` for query strings — but neither regex
could ever match a literal carrying one, so every interpolated or
query-bearing call read as an uncovered route.
Widen both to accept `?`/`&`/`=` and `${...}` holes, strip the query
before comparing, and treat a hole as a path segment only when a `/`
introduces it (so `/executions${queryString(f)}` is `/executions`, not
`/executions/{}`). Also read the `web/api/*.ts` modules the provider
delegates to: those calls are the provider's calls.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018M415coMKAv5V2xJQsaSf8
…ve one
61 routes had no command-line verb. Adds them as new families (auth,
drift, execution, onboarding, workspace, send) and as verbs on the
families already there (agent states/step-autonomy, bot status/
formations/memory, canvas --connections, config connector/heartbeat,
ten connector verbs, cooperation utterances/recent, five formation
verbs, eleven recipe verbs, five rule verbs, safety disguise-profile,
healthcheck --ready). Every one goes through `Client` and prints
through `output::emit`.
Three routes needed a body the JSON client does not speak, so they use
`Client::request` directly: `/recipes/import` (text/plain TOML),
`/recipes/{id}/export` and `/render` (text/plain out), and
`/connectors/install-wasm` (a two-part multipart body built by hand
rather than pulling in reqwest's multipart feature). `/workspaces/
onboard` answers SSE over POST, so `Client::post_stream` hands back the
undecoded response.
Under /formations the drum rule holds: intents, members/eligible,
propose-intent, votes and run-command are composition, intent,
constraints, intervention and inspection. No assign verb.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018M415coMKAv5V2xJQsaSf8
…b methods The gap ledger had 76 CLI entries and 56 provider entries. Most were real; a handful were routes that should never have a verb or a method and were sitting in a file that reads as a to-do list. - `scripts/surface-not-surfaced.txt` is the new list for those, with a reason on every line: the SPA asset routes, the inbound webhook, the two process probes, the SSE half of chat, and the six offline-first CLI paths (doctor, fix, panic, travel) that must work when the daemon is the thing that is broken. - `check-surface.sh` reads both files and still fails on a stale entry in either, so neither can grow quietly. - 17 provider methods for the routes the web surface could not reach: session/token management, the three bot views, heartbeat config, both connector installs, recent utterances, data import/purge, rule drift, execution vacuum, formation propose-intent and votes, and sessions. The desktop provider spreads the web provider, so both apps get them. - Two doc steps called verbs that do not exist: the deleted project scaffolder (now recipes) and `springtale api token print` (now the login flow plus `auth tokens`/`auth revoke`). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018M415coMKAv5V2xJQsaSf8
…groups `reassign` tripped the drum-rule test that bans an assign verb anywhere in the clap tree. A rule is re-homed onto another connector, never handed to a named member, so `move` is both the honest name and the one that keeps the ban absolute. The route is unchanged. The formation group test gains the five new verbs with their groups: `intents`/`eligible` are inspection and composition, `propose-intent` and `vote` are the intent group, and `run` is the execution half of `commands` — the same split check-surface.sh already enforces on the routes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018M415coMKAv5V2xJQsaSf8
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018M415coMKAv5V2xJQsaSf8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The contract work measured how far the project is from its own stated shape, where the daemon owns all state and each surface is a thin client: 76 routes had no command-line verb and 56 had no web provider method. This closes that to two entries, both a product decision rather than plumbing.
The first finding was that both extractors were undercounting. Each already normalised interpolated paths and stripped query strings, but neither pattern could match a call that carried one, and the provider extractor skipped the modules the provider delegates to. Fixing that closed about 29 phantom gaps before any feature code was written, which is a reminder that a check is only as good as what it can see.
What is left in the ledger is the author registry. Registering a signing identity happens before a daemon exists, so routing it through the daemon would make first-run signing depend on one, while leaving it as it is keeps a second writer against a registry the API owns. That needs a decision, and it is written down as one.
One rename: a rule verb called reassign tripped the test that bans an assign verb anywhere in the command tree, so it is now called move. The route is unchanged.
Documentation: a tutorial step that scaffolded from the deleted template system now applies a recipe, and the formations guide now shows the login flow and token commands instead of a command that printed a derived token. Two stale claims about the old token scheme remain in the reference pages and are worth a follow-up.
Verification: builds and clippy
-D warningsclean; 95 tests across 14 binaries;cargo fmtclean; the surface check reports 123 routes against 111 command-line paths and 118 provider paths and passes; frontend typecheck, lint and build pass.🤖 Generated with Claude Code
https://claude.ai/code/session_018M415coMKAv5V2xJQsaSf8