Contracts¶
The contracts are the source of truth every HarnessWeaver implementation is tested against: the Python core, the TypeScript core and the harnessd sidecar (RULES R11). They live in contracts/, versioned as harnessweaver/v1. Read them when you build a client in another language, an integration, or a plugin that crosses process boundaries.
contracts/
schemas/ JSON Schemas (draft 2020-12) of every wire contract
openapi/ harnessd's HTTP/JSON API, generated and drift-tested
proto/harnessweaver/v1/ harnessd's services, mirroring the OpenAPI routes for gRPC later
fixtures/conformance/ language-neutral behavior fixtures, one folder per suite
Schemas¶
The schemas are generated from the Pydantic contract models in the Python core and checked in, so reviewers and other languages read the contract directly. A test fails if a checked-in schema drifts from its model. Every schema has the $id urn:harnessweaver:v1:<name>.
| Schema | Contract |
|---|---|
harness, profile |
The harness.yaml app spec and profile documents (complete documents; profiles and overlays may be partial) |
envelope |
The immutable run context every hook event carries |
hook-event |
The 13 hook event payloads, discriminated by hook |
outcome |
What middleware returns: continue, retry, escalate, suspend, block |
decision-request, decision |
Routing questions and answers |
guard-result |
A guardrail's verdict and its seven actions |
model-request, model-response, tool-call |
The neutral model-call contracts (R7) |
tool-info, tool-result |
Tool facts policies decide on, and tool output |
tool-manifest, tool-verdict |
A kind: Tool manifest, and the governor's decision about one call |
policy-request, policy-decision |
What a PolicyEngine is asked and answers |
sandbox-result |
What a Sandbox returns for code it ran |
context-item |
A retrieved item with its ACL |
approval-request, approval-decision |
Human-in-the-loop approvals |
trace-event |
One entry in a run's trace |
run-result, run-event |
A run's status, output or error, usage, cost and trace; and the progress events harness.stream yields |
error-info |
The serializable error taxonomy |
eval-dataset, eval-sample, grade, suite-result, baseline, online-sample |
Eval datasets, what a grader sees and says, a suite's results, its stored baseline, and a graded production sample |
policy-tests |
A harnessweaver policy test table |
recorded-call, replay-report |
What a recorded run got from outside, and what replaying it found |
tool-allow-list |
The tools a gateway may let through, and the ones only the harness may run |
make schemas # regenerate after changing a contract model (also the OpenAPI document)
make schemas-check # report drift
uv run harnessweaver contracts export DIR [--check]
The sidecar's API¶
openapi/harnessd.openapi.json describes every /v1 route of harnessd. It is generated from the routes and the request models in harnessweaver.core.sidecar, so make schemas writes it and make schemas-check reports drift. proto/harnessweaver/v1/harnessd.proto mirrors the same routes in its google.api.http options for gRPC serving later; a test fails if a route is in one and not the other. Generate a client from the OpenAPI document for any language; see harnessd.
Conformance fixtures¶
Behavior that is part of the contract is pinned by JSON fixtures that every implementation must pass. Each suite folder holds files of this shape:
{
"suite": "expr",
"description": "What this file covers.",
"cases": [
{ "name": "unique within the file", "expr": "args.amount_usd > 100",
"vars": { "args": { "amount_usd": 250 } }, "expect": { "value": true } }
]
}
| Suite | Pins down |
|---|---|
durations |
Duration parsing and canonical text |
semver |
Versions, comparisons and npm-style ranges |
outcomes |
Severity and combining outcomes |
hook_order |
Hook directions and middleware order by band |
bus |
Running middleware: outcomes, modifications, fail modes, timeouts, the trace |
expr |
cel-lite: literals, access, operators, functions, macros, logic, errors |
merge |
Layer merging, keyed lists, locks, bounds, provenance, per-run budgets |
levels |
Adoption levels and requirement codes |
budgets |
Budget checks at each hook, and cost resolution |
plugins |
Namespaces, qualified names, ownership, allow-lists |
guards |
The built-in guards, and the guard pipeline (actions, modes, parallel groups, approvals) |
governor |
Definition digests, rate limits, the schema subset, policy combination, the governor's steps, output sanitizing |
routing |
Tokens, lexical similarity, the hashing embedder, stages and cascades |
evals |
Graders, dataset validation, summaries, baselines and regressions, sampling, the shadow-guard report |
Expected values are written by hand from the design, never copied from an implementation's output. A new suite needs a runner in every language: the Python runners live in python/harnessweaver/tests/conformance/ and the TypeScript runners in typescript/packages/core/test/, and both fail when a suite folder has no runner. The full case format per suite is in contracts/README.md.
Changing a contract¶
Within harnessweaver/v1, changes are additive only: new optional fields, new hook points, new actions (RULES V2). Anything else needs an ADR and a new major apiVersion, with the previous major supported for 12 months. A contract change starts in the model, then make schemas, then fixtures, and isn't released until Python, TypeScript and the sidecar all pass (R11). See Versioning.