Drive an implementation
These specs are packaged for consumption. An implementation proves it satisfies them; it never redefines them. Agents do the building; the specs supply their context and their gates. The same loop applies to every service; each service overview carries its own current pin.
The loop below is carried end-to-end by the implement-service skill (and consume-servicefor UIs and clients building against the mocks). Install the plugin ( /plugin marketplace add hungovercoders/sysspec, then /plugin install) and ask to implement a service; the skill runs everything on this page, from interview to verified definition of done. What follows is the shape of that loop, so you can recognise it, review it, or run it by hand.
flowchart TD
subgraph specs["Spec repo (the specs of record)"]
tag["merge to main cuts<br/><service>/vX.Y.Z"]
end
subgraph impl["Implementation repo"]
lock["contracts.lock<br/>pins the tag + its commit sha"]
fetch["task contracts:fetch<br/>read-only .contracts/ (specs + mocks + cli)"]
build["build<br/>bind the feature files, strict"]
verify{"task contracts:verify"}
done(["implementation satisfies<br/>the pinned surface"])
end
tag -->|"pin the newest tag"| lock
lock --> fetch --> build --> verify
verify -->|green| done
verify -->|red| build
tag -.->|"each new tag: Renovate re-pins"| lock1. Pin the released surface
A merge to the spec repo's main publishes each changed service as a lightweight git tag <service>/v<version>. The implementation records which surface it satisfies in a contracts.lock at its root:
# contract pin - version is the specs release tag, sha its commit
version: <service>/v<version>
sha: <commit sha of that tag>2. Fetch read-only, never vendor
A contracts:fetch task sparse-checks-out specs/<service> at the pinned sha into a write-protected .contracts/ directory, along with the spec repo's mocks/ and cli/, so the whole toolchain is versioned by the pin. Every run re-fetches, so a local edit cannot survive, and the sha rather than the tag is what gets checked out, so a re-cut tag cannot silently change what you build against. The Microcks mock stack then runs straight from the pin: task -d .contracts mocks:load, nothing copied or installed.
3. Build with the specs in context, over MCP
The agent implementing the service reads these specs as it works, never from a remembered or vendored copy. Interactive sessions use the sysspec MCP server:
claude mcp add sysspec --scope project \
--env SPECS_DIR=/path/to/checkout/specs \
-- npx -y sysspec-mcpThen list_services() → get_service(name) → narrow reads (get_acceptance_criteria, get_message_schema, get_artifact); trace_channel(address) shows who a change would break. CI and anything needing reproducible file paths read the same surface from .contracts/, which is one source with two access routes. The implement-service and consume-service skills (hungovercoders/sysspec) carry the deeper process the agent follows, written to be read as documentation and executed as agent process.
4. Bind the acceptance criteria, strict
The feature files run from .contracts/ as-is, so the specs keep the sentences and the implementation owns the step definitions. Strict mode is mandatory, because an unbound or pending scenario fails the build and an unbound scenario is a spec obligation silently dropped. Strict mode has one blind spot, a bound-but-empty step that passes, which is exactly what the negative control in the next section exists to catch.
5. Verify (the definition of done)
One task, contracts:verify, run with the implementation up. It chains four checks:
- Contract tests.
task -d .contracts contract:test SERVICE=<name> REST_ENDPOINT=… ASYNC_ENDPOINT=…has Microcks replay every spec operation against the running implementation and validates the real responses and emitted events against the schemas. - The bound scenario suite against the running implementation.
- The negative control.
task -d .contracts null:run …replays the same suite against a null service the CLI serves, answering200 {}to every request and emitting no events; red unless zero scenarios pass. Strict mode catches unbound steps, this catches bound-but-empty ones: a suite is only trustworthy if it is fully red against a service that does nothing. The fake answer is deliberately a plausible 200 rather than an error, so scenarios that assert nothing beyond a status code get flagged too. - Schema fuzz.
uvx schemathesis run .contracts/specs/<name>/openapi/*.yaml --url …for declared-but-unexampled paths.
One trap worth knowing: the endpoint overrides in check 1 resolve frominside the Microcks containers, so an implementation on your host is host.docker.internal rather thanlocalhost, while checks 2 and 3 run on the host and use the local URL. Two views of the same running service.
These gates are deterministic and live with the specs rather than the implementation, so they cannot be softened to make failing code pass. Mocking is deliberately not on this page: the mocks:*tasks serve consumers and the spec repo's own conformance checks, and have their own loop, covered in Build a consumer.
6. Stay converged
The specs never push work at implementations; they pull. When a new release tag lands, Renovate opens a pin-bump PR on the implementation and the gates above run against the new surface. A green run, typical for additive minors, auto-merges with no human and no agent. A red run, or a major bump, means the gates have proven code changes are needed, and only then does an agent wake to converge the implementation, with the failing checks as its scope.