ReadonlyharnessPillar 2 — deterministic harness tests + evals: the binary can be spawned
and pointed at a mock model. Requires runtime + modelMock +
harnessTestDriver. false for closed harnesses that route through a fixed
backend (no BYOM): Cursor, Devin, Amp, Amazon Q — pillar-1-only adapters.
ReadonlyshellHooks are shell processes speaking the exit-code/env block protocol —
Claude Code, Codex, Crush. Requires hookProtocol. false when hooks are
in-process code modules (OpenCode's TS plugins), so the run-hook unit
tier and the HookProtocol port do not apply.
ReadonlysubagentsThe harness has subagents — a named, model-dispatched delegate with its
own tool contract and frontmatter (Claude Code's agents/*.md, OpenCode's
agent surface). Gates the subagent-surface lint rules (subagent-tool-contract,
subagent-frontmatter, untested-subagent, mcp-tool-resolves): where this
is false those rules report n/a rather than running. false for Codex,
whose [agents] TOML is a concurrency table, not a tool-contract file — a
wholly different concept that deliberately shares the word.
No port sits behind it, so it stays a plain flag on the base rather than becoming a discriminant of a union with nothing in its arms.
Which vigiles pillars/tiers a harness can drive — the capability matrix made executable (see
docs/harnesses.md).🔴 KEPT AS A TYPE, NOT AS A FIELD. The flags used to sit in a nested
capabilitiesobject on the adapter, and that nesting is precisely what made the illegal state below expressible: TypeScript narrows a union by a discriminant on the object ITSELF, never bya.capabilities.x, so no shape of this interface could have tiedharnessTesting: trueto the presence of a driver. The flags are now discriminants onHarnessAdapterdirectly; this interface remains as the documented projection of them.referenceVerificationis gone. It wastrueon every adapter and its type was the literaltrue— a field that can hold one value carries no information, and the conformance check for it could not fail.