feat: adopt the @effected front-end kit in cli, mcp and the silk carrier - #698
Conversation
- Spread ToolFailure.fields into every tagged tool error and compose messages with ToolFailure.message and truncate - Drop Remediation, composeRemediatedMessage and truncateEchoed from the barrel; the kit owns them now Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
- Build ServerLayer on McpStdio.layer and accept a distribution that is rendered into serverInfo.version - Resolve the project directory with LaunchContext.projectDir and run under McpStdio.launch and teardown - Delete the hand-rolled project-root resolver and the e2e process helper in favour of the kit's testing module Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
- Pass the carrier distribution from the savvy-mcp shim so the server reports its version via @savvy-web/silk - Hold the mcp process boundary with a SourceBoundary scan: only bin, main and version touch process Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
- Hand the program to CliRuntime.main with the Node platform at the edge and CliLogger dropping the timestamp prefix - Exit 64 on a usage error instead of 1 - Name the carrier in savvy --version, and pass it from the silk savvy shim Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
- Replace every process.exitCode write in the repos and changeset commands with CliExit.set - Pin the boundary with SourceBoundary: no exitCode or exit writes in src, and process reads ratcheted to today's files Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
- Write savvy lint check and init results through Output on stdout, with glyphs coloured only on a terminal - Add Output.skip for items that are absent or not applicable Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
- Write repos results through Output on stdout and send each failure's explanation to stderr - Keep repos status --json stdout a single JSON document on the config-error path, reporting error and clean false Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
- Write changeset check, validate, transform, deps, version, init and clean results through Output on stdout - Keep a file read failure and the git-remote placeholder notice on stderr as diagnostics Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
- Run savvy under the kit-default CliLogger so stdout carries only command output, JSON and hook envelopes - Separate the savvy check sections with a blank line Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
- Move layers.json into silk on the kit's policy schema, with required edges as the non-vacuity guard - Check the live graph with WorkspaceLayering and the cli/mcp non-import invariant with SourceBoundary - Delete the e2e/workspace harness and its hand-rolled graph walk Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
- Add a draft Decision for the front ends adopting @Effected engine, mcp and cli, and the stdout contract - Point the layering concepts and CLAUDE.md files at silk's layers.json and tests now that e2e/workspace is gone Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
…lures - Print the error document under --json when status or the drift check fails with a git error, not just a config error - Render a propagated failure by its message or its tag and fields instead of a bare tag - Pin the usage-error contract (help on stdout, error on stderr, exit 64) and correct two doc claims Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
- Drop the markdown transcript: content[0].text is now the structuredContent object as JSON, the only channel Claude Code forwards - Replace the registerSilkToolkit port with McpToolkit.layer in annotated-strict mode so every tool stays lenient - Re-pin the lifecycle e2e: a declared failure answers isError and leaves stderr empty Closes #688 Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
- Record McpToolkit registration, the structuredContent contract and the content-reading client trade-off in the okf concepts and mcp CLAUDE.md - Tell the changeset and dependencies skills to read structuredContent fields instead of a transcript Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
The staged sync wrote the conventions and decisions indexes at the repo root instead of under okf/. Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
|
This run was cancelled 🛑 The workflow was cancelled before completion. Please check the link below for details. |
|
Important Review skippedToo many files! This PR contains 135 files, which is 35 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Advanced Run ID: ⛔ Files ignored due to path filters (9)
📒 Files selected for processing (135)
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code ReviewCurrent Commit: SummaryThis PR moves
I reviewed the substantive source changes rather than the generated churn (lockfile, changelogs, okf indexes). What holds up well
Notes (non-blocking)The deferred follow-ups you list match what I'd flag — the no-op Nice work — the stdout contract, the JSON error documents, and the layering/source-boundary tests are the load-bearing parts and they're all solid. Approving. 🤖 Generated with Claude Code |

Summary
@savvy-web/cli,@savvy-web/mcpand silk's carrier shims now run on the@effectedfront-end kit (@effected/engine0.1.0,@effected/mcp0.1.1,@effected/cli0.8.0), replacing hand-rolled process-boundary code. Three things behave differently for people using the tools:savvyoutput. Every log line now goes to stderr without the[12:00:00.000] INFO (#N):prefix. stdout carries only a command's result (✓ ⚠ ✗ • lines, coloured only on a TTY withoutNO_COLOR), JSON output and hook envelopes. Usage errors exit 64 instead of 1: the help text goes to stdout and the error to stderr, which is coreeffect/unstable/clibehaviour.structuredContent, andcontent[0].textis the same object as JSON. Claude Code forwards onlystructuredContentto the model, so the transcript reached no model there. Clients that showcontent(Cursor, Copilot, MCP Apps hosts) now see JSON.@savvy-web/silk,savvy --versionprintssavvy v3.2.8 via @savvy-web/silk 4.2.8, and savvy-mcp'sserverInfo.versiongets the same suffix. This is guaranteed under pnpm only: npm's flat.bincan link the cli or mcp package's own bin instead of silk's shim.What changed
mcp
main.tsresolves the project directory withLaunchContext.projectDir, which skips empty values and unsubstituted${VAR}values, and then runsMcpStdio.launch/teardown. The crash guards and dynamic imports stay, since the kit doesn't package them yet (effected#835).ServerLayeris built onMcpStdio.layer. The layer answers a non-JSON stdin line with-32700and keeps logs off the wire.McpToolkit.layer(SilkToolkit, { strict: "annotated" }). No tool is annotated, so every tool still accepts the extra arguments Claude Code sends.registerSilkToolkitport of core'sregisterToolkitis deleted, along withSilkMarkdownand all per-tool markdown renderers.ToolFailure.fields. The barrel dropsRemediation,composeRemediatedMessage,truncateEchoedandSilkMarkdown(a minor bump, per the mcp semver-surface convention).cli
main.tsrunsCliRuntime.mainwith Node as the platform and the kit-defaultCliLogger, and passes arenderthat prints a failure's message, or its tag and fields. The kit default would print a bare tag, so a failingsavvy cleanshowedCleanErrorwith no reason.process.exitCode = 1writes becameCliExit.set(1).Outputhelper on stdout. Progress and failure explanations stay asEffect.log*and go to stderr.repos status --jsonnow always prints one JSON document, including{ "error": …, "clean": false }on a config error or a git failure. The gitmodules-drift monitor runsJSON.parseon it.savvy checkseparates its three sections with a blank line.silk and layering
{ distribution: { name: "@savvy-web/silk", version } }.packages/silk/layers.jsonon the kit'sLayerPolicyschema.unconstrainedreplacesharnessand also covers the private root.requiredEdgesguards against a check that passes on an empty graph.WorkspaceLayering.checkWorkspacechecks the policy in silk's own tests, ande2e/workspaceis deleted.SourceBoundarytests pin three rules at source:src/binshims import cli or mcp);bin/main/versiontouchprocess" in mcp;process.exitCode/process.exit" in cli, plus a ratchet on the files that readprocess.Things a reviewer should check
savvy commit hook *still prints its JSON envelope.changeset validate-filestill printsfile:line:col rule messagelines, which the plugin hook greps forCSHnnnafter merging stderr into stdout.repos status --drift --jsonis always JSON.repos syncis read by exit code only.@effected/clihas no switch to move it. The bin e2e pins the contract: exit 64, the error only on stderr, only help on stdout.optional:flags inpnpm-lock.yamlalongside the new@effectededges.Verification
All run on the final tree in the worktree:
pnpm test: 3226/3228 passed, 2 skipped (both pre-existing), and all coverage thresholds met.pnpm build: green, and API Extractor reports zero errors and zero warnings for cli, mcp and silk.pnpm typecheck,pnpm lint,pnpm lint:md,pnpm peers check: clean. The two lint warnings are__PACKAGE_VERSION__notes on silk's shims; it is a build-time define, not a turbo env var.pnpm test:hooks: 473/473 passed.okfit validate: 0 errors.--jsonerror path and the lint init stdout test were checked by temporarily breaking the code and watching the test fail.savvy check: stderr empty.savvy repos status --drift --json: parses as JSON.savvy --version: prints the carrier suffix through silk.savvy lint --bogus: exits 64.Follow-ups
effect-v4-cliskill).CliExit.setbefore a propagated failure inconfig-gate.ts;CurrentDistributionis provided but never read;Output.summaryis unused;cleanprints a ✓ summary after ⚠ failures.okfit verifypass.okfit sync --stagedstaged the regenerated conventions and decisions indexes at the repo root instead of underokf/. Commitd1472281corrects it.Closes #695
Closes #688
Signed-off-by: C. Spencer Beggs spencer@savvyweb.systems