petrova.cupel.trace_status — read-only tool scope
Date: 2026-09-10 Status: open Supersedes: none Superseded-by: none — current
Context
Section titled “Context”stratt-hq/stratt-run PR #334 (docs/decisions/2026-09-10-cupel-petrova-integration-points.md, that repo) scopes CUPEL↔PETROVA to three additive extension points, all petrova-codes-side, none implemented. Item 1 (mr_grounding.kind += cupel_ticket/cupel_trace) shipped here as #419. This doc scopes item 3: a new read-only verb/MCP tool letting a petrova caller query traces/TR-*.yaml and handoffs/HO-*.yaml state for a target repo — no existing petrova.* tool touches these paths.
Read from the stratt-run source directly this session: scripts/check-cupel-trace-lint.ts (TR-.yaml shape, T1-T6/T8-T10), scripts/check-cupel-handoff.ts (HO-.yaml shape, state_assertions re-derivation), scripts/check-cupel-trailer.ts (Cupel-Red/Cupel-Green/Cupel-Criterion commit trailer format). Neither traces/ nor handoffs/ exist yet in that repo (one handoff, HO-smo1-census-1.yaml, landed same PR) — this tool has no live fixture beyond that one file today.
Decision
Section titled “Decision”Add petrova.cupel.trace_status (read-only, mutating: false) to host/src/registry.ts, backed by a new host/src/sources/cupel.ts source, following the existing remote-repo-read pattern used by acts.ts/audit.ts (makeOctokitForOwner(owner) + octo.repos.getContent({owner, repo, path, ref}) resolved from registry.yaml by slug) rather than local filesystem (eva.ts’s pattern only works for repos checked out as siblings, which stratt-hq is but the tool must not assume that for every fleet member).
Schema (schemas: { type: "object", required: ["slug"], properties: { slug: {type:"string"}, criterion: {type:"string"}, ticket: {type:"string"} } }):
slug(required) — registry slug, resolved to owner/repo the same wayacts.getdoes.criterion(optional) — filter traces to onecriterion.id(e.g.C1).ticket(optional) — filter handoffs to oneticket.
Behavior:
- List
traces/*.yamlandhandoffs/*.yamlviagetContenton the directory path (404 on either → treat as empty list, not an error — both check scripts already model “no dir yet” as a pass-0 state, this tool should match that posture). - Parse each YAML (js-yaml, already a host dependency via
eva.ts). - For each trace record, surface:
criterion.id,invariant, whetherred/greenblocks are both present,red.at < green.at(T3), whethermerge.commitis set and itscitesincludes both run-ids (T6) — i.e. report the same violationscheck-cupel-trace-lint.tscomputes, but as read-only status fields, not a pass/fail gate. Do not reimplement T1-T10 exhaustively; surface the subset a caller needs to know “is this criterion green and merged” (T3, T6, presence of red/green) and flaglint_clean: nullwith a note that full T1-T10 requires running the actual script, rather than silently claiming a clean bill this tool didn’t fully check. - For each handoff record, surface:
handoff_id,ticket,phase, count ofstate_assertions, andreproduced: null(this tool must NOT re-runderivecommands against a remote repo it doesn’t have checked out — re-derivation requires local execution, which ischeck-cupel-handoff.ts’s job, not a read-only MCP tool’s). Report structure only, never claim reproduction. - Degrade-never-throw contract, matching
ralph.run/ralph.runs: auth or rate-limit failure returns{ ok:false, degraded:true, detail }, not an exception.
Explicitly out of scope for this tool (mirrors the parent decision’s altitude split):
- No
derivere-execution (that requires a local checkout + shell exec against a repo this MCP server doesn’t own). - No admissibility/criteria-count judgment (CUPEL’s own scripts own that).
- No write path — this is query-only, symmetric with
petrova.ralph.runandpetrova.decisions.get.
Alternatives considered
Section titled “Alternatives considered”- Reimplement full T1-T10 trace-lint inside the tool — rejected: duplicates
check-cupel-trace-lint.tslogic in a second language-adjacent surface that will drift; the parent decision doc already rejected merging CUPEL discipline into petrova at a finer grain than citation/status. - Local filesystem read via
EvaSource-style root path — rejected: only works for repos already checked out as workspace siblings; the tool must work for any registered fleet slug, same constraintacts.ts/audit.tssolve viamakeOctokitForOwner. - Fold into
petrova.acts.recent/diagnose— rejected per the parent decision’s “diagnose is not being merged with census” ruling; this is a distinct namespace (petrova.cupel.*) for a distinct, optional-adoption substrate.
Consequences
Section titled “Consequences”For code:
- New file
host/src/sources/cupel.ts. - New registry entry in
host/src/registry.ts(read-only surface — nospec/verbs/*.schema.jsonfile needed; existing read-only tools likepetrova.decisions.getdon’t have one either, only the 18 mutating/CLI verbs underspec/verbs/do). - No schema changes beyond #419 (already shipped).
For docs:
- This doc. No CLAUDE.md changes — tool count in the top-of-file “43 tools” line will need bumping to 44 once implemented (currently unimplemented).
For in-flight phases: none.
For invariants: none changed.
References
Section titled “References”- stratt-hq/stratt-run PR #334,
docs/decisions/2026-09-10-cupel-petrova-integration-points.md - stratt-hq/stratt-run
scripts/check-cupel-trace-lint.ts,check-cupel-handoff.ts,check-cupel-trailer.ts host/src/sources/acts.ts,host/src/sources/audit.ts(remote-repo-read pattern to follow)host/src/registry.ts(registration point)- petrova-codes #419 (
feat(spec): add cupel_ticket/cupel_trace grounding kinds)
Sign-off
Section titled “Sign-off”- Subagent: agent (Claude Sonnet 5), composed 2026-09-10
- Human countersign: alex@devarno.com — scope agreed, implementation cleared to start
Countersigned by human:alex@devarno.com on 2026-09-10 — commit 909ecf52
(this file’s creation commit) is authored by the human directly, per
docs/decisions/2026-09-05-proxy-countersign-retired.md’s post-retirement
definition. Line added retroactively by the agent as scribe.