refactor: extract the CLI-independent describe seam and scaffold mcp/sdk#9
Merged
Conversation
…dent seam The composition of the `version` and `spec schema` payloads lived inside cobra `RunE` closures, so the only way to obtain either was to invoke the CLI. Any second surface would have had to either import the cobra-carrying `cli` package or rebuild the payloads itself, and a rebuilt payload is a second contract that drifts. Move both into `internal/describe`, which holds no CLI, transport, or presentation concerns. Error mapping stays in the CLI, where the distinction between an unsupported specification version and a corrupt bundled artifact is already expressed as distinct exit classes and diagnostic codes. `WrittenTo` deliberately does not move: it records what a caller did, not what the artifact is, and a test asserts the package never populates it. Pure refactor. Verified by capturing `version`, `spec schema`, `spec validate`, and `spec test-conformance` output in both human and JSON form before and after: all six are byte-identical. Also pins the machine contract in tests -- `outputVersion`, `tool.name`, the six exit classes, and the four envelope members every payload carries. These were enforced only by convention, so a rename or an accidental version bump passed silently. `internal/result` had no test file at all before this. Removes `stringFrom`, now dead in `cli`, and three imports it was the last user of. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Brian Jin <35789537+kikashy@users.noreply.github.com>
Reserve two package homes as documented, empty Go packages so the planned adapter and composition seams have obvious locations before any code lands: - internal/mcp: a transport adapter that will expose this runtime over the Model Context Protocol as an "mcp" subcommand of the single binary, delegating to the existing core and adding no judgment behavior. - sdk: a public, experimental in-process Go composition API for embedding the runtime without invoking the binary. Each holds only a doc.go carrying a package clause and an intent comment, so both build clean and add no behavior. No public interface changes: internal/mcp is unimportable outside this module, and sdk exports nothing and is marked pre-1.0 unstable. Other-language clients are out of scope here by design; they reach the runtime over a wire protocol or the binary, not by importing sdk. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Brian Jin <35789537+kikashy@users.noreply.github.com>
Contributor
Author
|
Added |
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.
Pure refactor, no behavior change. Prepares the seam the MCP skeleton needs.
Why
The composition of the
versionandspec schemapayloads lived inside cobraRunEclosures (app.go:124-131,:279-290). The only way to obtain either was to invoke the CLI, so a second surface would have to import the cobra-carryingclipackage or rebuild the payloads itself — and a rebuilt payload is a second contract that drifts from the first.What
New
internal/describe, holding no CLI, transport, or presentation concerns:Error mapping stays in the CLI, where the distinction between an unsupported specification version (
ExitUnsupported/JPS-CAPABILITY-SPEC-VERSION) and a corrupt bundled artifact (ExitInternal/JPS-ARTIFACT-SCHEMA) is already expressed. Collapsing those into one error return would have lost a distinction the CLI contract makes.WrittenTodeliberately does not move — it records what a caller did, not what the artifact is. A test asserts the package never populates it.Also removes
stringFrom, now dead incli, and the three imports it was the last user of.The gate for a pure refactor
Captured every output in both formats before and after:
version --format jsonversion(human)spec schema 0.1.0-draft --format jsonspec schema 0.1.0-draft(human)spec validate - --format jsonspec test-conformance --format jsonByte-identical, via
cmp, not eyeballed.Contract pinning
internal/resulthad no test file at all. The machine contract —outputVersion,tool.name, the six exit classes, and the four envelope members every payload carries — was enforced only by convention, so a rename or an accidental version bump passed silently. Now pinned by literal, with the reasoning in a comment so the next person knows the failure is the point.The envelope test marshals to JSON and asserts on the emitted members rather than the struct fields, since a
json:tag rename is invisible to the type checker but breaks every consumer.Verified
gofmt -lempty ·go vetclean · 11 packages ok (was 10) ·check-release --tag v0.1.0verified · conformance 47/47 exit 0Next
internal/mcpcalls these two functions plusvalidation.Engine.Validateandconformance.Runner.Run— all four now reachable without cobra.🤖 Generated with Claude Code