Skip to content

Harness Contract v1 — the ADR (A2) #621

Description

@aarontrowbridge

Important

Problem — The product promises switchable harnesses ("opencode (open) — the default; telaio (subscription) — arriving") but nothing in the repo defines what a harness must BE. Telaio.jl's serve daemon (the first proprietary harness) and any third-party harness need a written, testable contract to implement; without one, "harness-agnostic" is marketing.
Approach — A decision record: Harness Contract v1 IS the fixture-pinned subset of the canonical opencode server API and serving behavior the product actually consumes (lifecycle, auth, event bus, session/turn API, web app at origin, injection channels). Compat-first: no new neutral protocol for v1. The tool surface is product-owned with an MCP floor. One adapter seam owns harness selection.
Approaches considered — (a) Neutral protocol first: rejected — it strands the app bundle/SDK investment, re-plumbs every consumer, and delays telaio behind a protocol-design project while the fixture-pinned subset buys the same guarantee. (b) Adapter seam only, no written contract: rejected — an interface without a pinned behavioral contract drifts silently; the golden-fixture technique (just proven by the #451 route port) is the enforcement mechanism we already trust.
Scope — in: docs/adr/0011-harness-contract.md (the decision + the contract surface matrix by consumer) · out: any code change, the MCP server itself (A3, seeded), Telaio.jl serve (T4, queued in the harness-agnostic campaign).
Assumptions — The consumed-subset framing survives the second harness (if not, v2 may revisit the neutral-protocol question — recorded as a consequence, not a blocker).

Acceptance Criteria

  • The ADR lands at docs/adr/0011-harness-contract.md in house style (thesis title, Status, prose, Why, Consequence, Implementation link).
  • The contract surface is enumerated as a consumer × surface × evidence matrix: process lifecycle + health + auth, the ?auth_token= web-app bootstrap, the /event SSE envelopes, the session/turn API (SDK paths the app bundle uses), the injection channels (AGENTS.md/instructions, skills as files; config authorship), and the amicode_* tool surface with the MCP-floor decision.
  • The three decisions are recorded with rationale: compat-first (vs neutral protocol), product-owned tools with an MCP floor (vs harness-owned tools), and the adapter seam (harness identity in settings, never in wire protocol — the blocklist constraint).
  • Non-goals are explicit: the full opencode API is not contract; the fork's server-coupled app features (the 35-file inventory) are a recorded worklist, not contract; the TUI stays an opencode-harness property (ADR-0010).
  • Enforcement is stated: golden fixtures recorded against canonical pins + drift gates; a harness passes the contract by passing the fixtures; fixture refresh = contract version bump.
  • Docs-only change; no code touched; CI green.

Testing Decisions

No test surface — the ADR is the deliverable. CI rides the existing docs path (fast build + app-bundle-gate must stay green; they are unaffected by a docs-only diff).

Key Decisions

  1. Compat-first: the contract is the consumed subset of the incumbent's API, pinned by evidence, versioned by fixture refresh.
  2. Product-owned tools: the amicode_* tool surface belongs to the studio, carried portably by an MCP server (A3) with native harness implementations allowed to exceed it; the opencode plugin remains until A3 lands.
  3. The adapter seam: one extension-side seam owns harness selection (descriptor: launcher, health probe, capabilities); harness names live in settings and product copy, never in wire protocol strings.

Constraints & Invariants

  • The proprietary-strings blocklist (protocol-blocklist.json) governs wire-protocol naming — the ADR must record this constraint for future harness code.
  • The ADR must not contradict ADR-0010 (XDG paths) or the migration manifest (docs/migration-canonical-opencode.md) — it builds on both.
  • The M2 manifest's server_coupled_port_inventory is referenced as the recorded worklist for server-coupled app features, not silently absorbed into the contract.

Prior Art

  • docs/migration-canonical-opencode.md — the route × consumer inventory and the golden-fixture technique this ADR generalizes.
  • docs/adr/0010-install-path-contract.md — the boundary this ADR complements (engine state vs product state).
  • The extension source: server lifecycle/auth, the SSE client, the deck/chat iframe bootstrap, the config author, the opencode plugin.

Source

  • Campaign ledger sessions/session-20260827-harness-agnostic.md (personal vault), queue item A2, hypothesis P15.

Notes

  • This ADR does not schedule Telaio.jl's serve work; it defines what that work must implement. T4 (serve) is queued in the campaign.

Metadata

Metadata

Assignees

No one assigned

    Labels

    afkImplementable without human interaction

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions