Repository navigation
Provider protocol
Protocol 1.0.0. Every command accepts --json and answers with an envelope on
stdout. Failures go to stderr with exit code 2.
The normative version of this page is
docs/provider-protocol.md.
This page adds the full payloads and the consumer checklist.
protocolVersion describes the envelope and the capability names.
contractVersion, inside result, describes the payload shape for that
command. They move independently: a new command can ship without touching the
protocol major, and a report can gain a field without renaming any capability.
Both are majors you must check. providerVersion is informational.
mestre-yoda handshake --json{
"protocolVersion": "1.0.0",
"provider": "mestre-yoda",
"providerVersion": "0.1.0",
"command": "handshake",
"status": "success",
"result": {
"protocolVersion": "1.0.0",
"provider": "mestre-yoda",
"providerVersion": "0.1.0",
"mode": "read-only",
"capabilities": [
"profiles.list",
"profiles.describe",
"project.inspect",
"project.recommend",
"project.check",
"project.plan",
"catalog.validate"
],
"mutations": false
}
}A consumer should call this first, reject an unknown protocol major, and then only invoke commands whose capability appears in the list. Feature detection through the capability array is what lets a consumer work across provider versions without a compatibility table.
| Command | Capability | Result |
|---|---|---|
profiles |
profiles.list |
Identity, version, and digest of each profile |
describe <id> |
profiles.describe |
The complete public manifest |
inspect --root <dir> |
project.inspect |
Inventory and detected signals |
recommend --root <dir> |
project.recommend |
Profiles ranked by confidence and conformity |
check <id> --root <dir> |
project.check |
Compliance report |
plan <id> --root <dir> |
project.plan |
Ordered tasks, without effects |
validate |
catalog.validate |
Internal integrity of the catalog |
Every successful response has the same five fields around a command-specific
result:
{
"protocolVersion": "1.0.0",
"provider": "mestre-yoda",
"providerVersion": "0.1.0",
"command": "check",
"status": "success",
"result": {}
}{
"protocolVersion": "1.0.0",
"provider": "mestre-yoda",
"providerVersion": "0.1.0",
"command": "describe",
"status": "failure",
"error": {
"code": "INVALID_REQUEST",
"summary": "Unknown Golden Path profile: missing-profile."
}
}This goes to stderr, with exit code 2. Read both streams if you want to
handle failures programmatically.
Failure summaries never carry local paths, stack traces, or content from the analyzed project. A test asserts the summary contains no stack frame.
{
"contractVersion": "1.0.0",
"root": "/absolute/path/to/project",
"inventory": {
"files": 8,
"inspectedTextFiles": 8,
"inspectedBytes": 565,
"skippedSymlinks": []
},
"signals": {
"apiVersioning": false,
"applicationLayer": true,
"architectureTests": false,
"...": "21 keys in total, alphabetically ordered"
}
}root is the resolved absolute path, so it is the one field in a success
payload that reveals the local filesystem. Strip it before storing a report
somewhere less trusted than the machine that produced it.
{
"contractVersion": "1.0.0",
"recommended": {
"id": "dotnet-modular-react-postgresql",
"version": "1.0.0",
"digest": "sha256:89963b03fac95b7af4972176a46b92143948ddf280b3bc627d53539af797b56f",
"confidence": 100,
"conformity": 77
},
"candidates": [
{
"id": "dotnet-modular-react-postgresql",
"version": "1.0.0",
"digest": "sha256:89963b03fac95b7af4972176a46b92143948ddf280b3bc627d53539af797b56f",
"confidence": 100,
"conformity": 77
}
]
}recommended is null when the catalog is empty. It is otherwise the first
element of candidates.
{
"contractVersion": "1.0.0",
"profile": {
"id": "dotnet-modular-react-postgresql",
"version": "1.0.0",
"digest": "sha256:89963b03fac95b7af4972176a46b92143948ddf280b3bc627d53539af797b56f"
},
"compliant": false,
"score": 77,
"summary": { "passed": 16, "failed": 5, "blocking": 2, "total": 21 },
"rules": [
{
"id": "stack.no-nestjs",
"severity": "blocking",
"description": "The backend does not use NestJS.",
"passed": true,
"signal": "forbiddenNestAbsent",
"expected": true,
"observed": true,
"remediation": "Remove NestJS dependencies and keep the backend on ASP.NET Core."
}
]
}rules contains every rule, passing and failing, in manifest order. Both
expected and observed are present so a consumer can render why a rule failed
without re-deriving it.
{
"contractVersion": "1.0.0",
"planId": "sha256:e58b0438750d3f3a8be336f57f383f24d36c7b67c3028912428be06f53f7aa84",
"profile": {
"id": "dotnet-modular-react-postgresql",
"version": "1.0.0",
"digest": "sha256:89963b03fac95b7af4972176a46b92143948ddf280b3bc627d53539af797b56f"
},
"readOnly": true,
"effects": [],
"tasks": [
{
"order": 1,
"ruleId": "api.version-v1",
"severity": "blocking",
"action": "Version public routes under /api/v1 and document the evolution policy.",
"requiresHumanDecision": true
}
],
"summary": { "taskCount": 5, "blockingDecisions": 2 }
}planId is a SHA-256 over the profile digest, the serialized signals, and the
serialized tasks. Two plans with the same id were produced from the same
standard against the same observed state.
In protocol 1.0.0, handshake.result.mutations is false, plan.readOnly is
true, and plan.effects is always empty.
Consumers must not infer operations from the text of tasks. Those strings are
guidance for a human reviewer. Parsing "Add versioned migrations" into a
filesystem operation is exactly the failure this boundary exists to prevent, and
a future protocol version will declare typed operations explicitly rather than
leaving them to be inferred from prose.
Four schemas ship in
schemas/:
| Schema | Describes |
|---|---|
golden-path-manifest.v1.schema.json |
A profile manifest |
golden-path-report.v1.schema.json |
The check result |
golden-path-plan.v1.schema.json |
The plan result |
provider-result.v1.schema.json |
The envelope itself |
They are published as https://mestre-yoda.dev/schemas/... $id values.
Resolve them from the repository rather than over the network.
- an incompatible change requires a new major of
protocolVersion; - an incompatible change to a manifest, a report, or a plan requires a new major
of
contractVersionand a new schema; - changing the content of a profile changes its version and its digest;
- consumers should reject unknown majors and digests they have not approved;
- local paths, error stacks, and project content are never part of a failure envelope.
Before trusting a result in an automated flow:
- Call
handshakeand reject an unknownprotocolVersionmajor. - Confirm the capability you need is in
capabilities. - Confirm
mutationsisfalseif you expect a read-only provider. - Check
contractVersioninside the payload you consume. - Compare the profile
digestagainst the one you approved, not justversion. - Read
stderrand the exit code, not onlystdout. - Treat
tasks[].actionas text for humans.
Repository · Releases · Issues · MIT license
Normative contracts live in
docs/. Where
this wiki disagrees with the repository, the repository is correct.
Getting started
Reference
The catalog
Using it
Project