Adopt eva.consumption.v1 in petrova-hq
Date: 2026-05-08 Status: open Supersedes: docs/decisions/2026-05-06-sub-project-g-rocky-eva-surface-ratification.md (G.2 stance), docs/decisions/2026-05-06-sub-project-g-closure.md (G.2 outcome only — G.1 + G.3 unaffected) Superseded-by: none — current
Context
Section titled “Context”Sub-project G closed on 2026-05-06 with G.2 ratifying that “eva-hq has no consumption surface; consumer-side eva is permanently not_applicable for every governed repo.” That stance held for two days.
On 2026-05-08, eva-hq ratified
eva.consumption.v1:
a per-surface consumption contract with three declared surfaces
(events, control, prompts) and a producer-controlled
evidence_consumer mirror. The schema lives at
eva-hq:contracts/consumption.v1.json; helpers at
eva-hq:bin/eva_consumption.py.
That ratification reverses G.2 — eva-hq now does have a consumption
surface, and consumers that POST run events, call the control API, or
pull pinned prompts can declare wired truthfully. Petrova’s upstream
schema, probe, status verb, and verify-round mirror logic must be
updated to accept the v1 shape. Until they are, every consumer is
schema-locked into the legacy not_applicable envelope.
Decision
Section titled “Decision”petrova-hq adopts eva.consumption.v1 as the canonical EVA
integration shape. Specifically:
- Schema.
contracts/contract.schema.json$defs.integration_evabecomes aoneOfdiscriminated by the presence ofsurfaces:- Legacy branch (
integration_eva_legacy) — accepts the pre-v1 envelope, retained for backward compat for slugs not yet migrated. Forbidssurfaces. - v1 branch —
$reftoeva-hq:contracts/consumption.v1.json, vendored atpetrova-hq:contracts/vendor/eva-consumption.v1.json.
- Legacy branch (
- Vendoring. The v1 schema is vendored, not cross-repo
$ref’d at validate time. Refresh procedure documented incontracts/vendor/README.md. Vendoring keepspetrova doctorhermetic — the cli does not need a sibling checkout to validate. - Probe.
cli/src/probes/eva.tsrewritten:- Legacy block →
unreachablewith a migration pointer to this ADR. - v1 block → per-surface freshness check against
verification_ttl_days(default 7). Eachwiredsurface that passes contributes a fingerprint; aggregateevidence_shais the 12-char hash of sorted fingerprints.
- Legacy block →
- Status verb.
cli/src/verbs/eva_status.tsrewritten to surface per-surface state, evidence summaries, and theevidence_consumermirror, replacing thebail_reason: not_implementedstub. - Mirror.
cli/src/eva-mirror.tsportseva_consumption.py::compute_mirror + apply_mirrorto TypeScript.sweepAndWriteStatecallsapplyMirrorafter writing per-slug state whenEVA_HQ_ROOTresolves to a git tree. Mirror writes are idempotent (semantic equality modulomirrored_at).
Consequences
Section titled “Consequences”For code:
- New file:
contracts/vendor/eva-consumption.v1.json(vendored fromeva-hqHEADbb5a8e0). - New file:
contracts/vendor/README.md. - Edited:
contracts/contract.schema.json(integration_eva→oneOf). - Edited:
cli/src/contract.ts(AjvaddSchemafor vendored ref). - Edited:
cli/src/types.ts(EvaIntegration=EvaIntegrationLegacy | EvaConsumptionV1). - Rewritten:
cli/src/probes/eva.ts,cli/src/verbs/eva_status.ts. - New:
cli/src/eva-mirror.ts, called fromcli/src/verbs/doctor.ts::sweepAndWriteState.
For tests:
cli/tests/contract.test.ts— added 5 cases covering v1 valid, v1 fixture-on-disk, v1-wired-without-evidence, legacy-with-surfaces (discriminator), legacy not_applicable still valid.- New:
cli/tests/probes/eva.test.ts— 8 cases (legacy reject, ok with no wired surfaces, fresh events, stale events, missing fields, stale control, prompts manifest missing, prompts unverified fallback). - New:
cli/tests/eva-mirror.test.ts— 7 cases covering compute, idempotent apply, SHA drift, legacy-skip. - New fixtures:
valid/eva-v1-all-surfaces-wired.yaml,invalid/eva-v1-wired-no-surface-evidence.yaml,invalid/eva-legacy-with-surfaces.yaml. - Existing fixture
valid/all-wired.yamlupdated to use the v1 shape for its eva block (the canonical “all-wired” example reflects the new normal).
For docs:
- This ADR.
- The G.2 closure doc (
docs/decisions/2026-05-06-sub-project-g-closure.md) getsSuperseded-byupdated to point at this ADR for its G.2 section. G.1 and G.3 outcomes are unaffected.
For governance:
- Existing registered slugs (ARES, Traceo, Rocky, devarno-cloud,
STRATT, Choco, Grace, KAHN, Skyflow) keep their legacy
eva: not_applicableblocks until a follow-up sweep migrates each to v1. The mirror writer skips legacy blocks, so the sweep is a no-op for them. Migration is one PR per consumer. - New consumers (smo1-io and onward) declare v1 directly.
Alternatives considered
Section titled “Alternatives considered”- Cross-repo
$reftoeva-hq:contracts/consumption.v1.json— rejected. Ajv would have to walk the sibling checkout at validate time, breaking hermetic doctor runs in CI environments that don’t clone eva-hq. Vendoring + a documented refresh procedure is the same guarantee with less coupling. - Replace legacy schema entirely (no
oneOf) — rejected. ~9 registered slugs currently carry legacyeva: not_applicableblocks; a hard cutover would invalidate all of them in one PR and force a coordinated registry-wide migration. TheoneOflets each slug migrate independently. - Shell out to
eva consumption mirrorfor theevidence_consumerwrite — rejected. Adds a Python runtime dependency to the cli and couples petrova-hq’s CI to eva-hq’s pip env. The TS port is ~30 lines (file-system +git rev-parse) and the vendored schema + tests catch shape drift if the upstream impl evolves. - Wait for upstream to publish a stable producer-side contract.schema.json patch and consume it directly — rejected. No such patch is in flight on eva-hq, and the producer ADR is explicit that the schema lives in eva-hq for the producer side and in petrova-hq for the consumer-discovery side. Each repo owns its half.
References
Section titled “References”eva-hq/docs/decisions/2026-05-08-eva-consumption-contract.md— upstream ratification.eva-hq/docs/decisions/2026-05-07-eva-evidence-shape.md— the producer-side ADR that this is the consumer-side complement of.eva-hq/contracts/consumption.v1.json— canonical schema (vendored copy atcontracts/vendor/eva-consumption.v1.json, source SHAbb5a8e0).eva-hq/bin/eva_consumption.py— reference impl forcompute_mirror/apply_mirror.core/prompts/10-eva-wire.md— already rewritten for v1 on brancheva-consumption-alignment(commit1b57f59).
Sign-off
Section titled “Sign-off”- subagent: human:cli (this PR)
- triggering: eva-hq#? — eva.consumption.v1 ratification