Orchestrata Ultimate › Plans › briefs › p-rul040-stage1-orchestrata-consumption
P-RUL040 Stage 1 — orchestrata side: consume the deployed select-affected verb; the escalate arm dies
Source: plans/briefs/p-rul040-stage1-orchestrata-consumption.md at 8a2cb42ad · last changed 2026-10-20 · first committed 2026-10-20 · 78 lines.
Prose pending.
Plan text
P-RUL040 Stage 1 — orchestrata side: consume the deployed select-affected verb; the escalate arm dies
Status: DISPATCH-READY (dispatch ONLY after the coordinator confirms the codetools verb is DEPLOYED —
see Sequence) · Repo: /home/mohamed/workspace/wt-COMPONENTS (branch components)
Authority: RUL-040 (verbatim, injected in plans/briefs/p-rul040-fail-closed-blast-radius.md) + the
Stage 0 adjudication (reports/p-rul040-stage0.md): seam option (b) — the DEPLOYED codetools CLI's
select-affected verb, consumed as a subprocess JSON contract; rts.py extract's fact schema frozen as
the interop surface; rts select RETIRED at verb landing; refusal → abort with named set + an
explicit-decision citation mechanism; tool-missing → fail-closed naming the tooling state. NEVER a
silent full run.
Sequence (coordinator-enforced)
The codetools verb packet (plans/briefs/p-rul040-stage1-codetools-verb.md) lands and the coordinator
deploys it to /opt/codetools FIRST. Verify the deployed CLI answers before you write a line:
.venv/bin/codetools is NOT the target — the contract is consumed from the DEPLOYED surface the
coordinator names (it will be /opt/codetools/current/... or a bin/ shim). If the coordinator's
deployment note is absent from your task, STOP and report.
The contract (frozen in the codetools brief — do not renegotiate)
codetools deploy select-affected --repo-root R --json reads on stdin
{"changed_files": [...], "facts": {"sym_hash": [...], "file_hash": [...], "defines": [...], "calls": [...], "is_test": [...], "safety_escape": [...]}} and prints ONE JSON line on stdout:
{"verdict": "bounded", "selection": [...], "named_full": [...]} exit 0 ·
{"verdict": "refused", "missing": "...", "reason": "..."} exit 2 · tool error exit 1 (stderr).
Deliverables
- D1 —
scripts/affected_tests.py: replace the module-granularity selection with the verb call. Build the facts document fromscripts/rts.py extract's frozen fact schema via the <100 LOC JSON transform (measure rts' exact output shape FIRST and paste it; the transform maps its arities to the contract's fact arrays).--jsonoutput keeps its existing shape PLUS the new verdict fields (verdict,selection,named_full/missing+reason); the oldescalate: trueboolean is REMOVED from the output schema. A refused verdict is NOT an error — it is the bounded answer. - D2 —
scripts/run_tests.py: the affected-selection consumption arm. DELETE theelif resolved.get("escalate"):full-run arm (cite by symbol, lines drift). New behavior: bounded → run the selection; named_full verdicts → run the selection PLUS record each named-full verdict with its path in the report (adependency-or-environment-change:<path>verdict is a HONEST named full justification — it stays legal, but it must be NAMED in the report and the selection is what the verb returned, never an implicit 39k); refused → ABORT naming the missing fact + the changed set, and require the explicit-decision citation mechanism: a--affected-decision <citation>flag (recorded in the report and the refusal row) — without it the run aborts (fail-closed); tool-missing → fail-closed with the tooling state named (codetools CLI absent / too old — check its version output and name it). NEVER a silent full run, in any arm. - D3 —
scripts/rts.py: retire theselectverb at landing (extract stays and is the interop source); the fact schema is frozen — no shape changes; update the docstring to say select is retired per the Stage 0 adjudication and name the replacement. - D4 — ledger interaction: measure what a refused/bounded selection records today and report it (the M3 question); implement the adjudicated shape: a refusal records a named-refusal row (never a green, never a silent nothing) so the ledger never pretends a refused run passed.
- D5 — tests (real, no mocks): affected_tests.py's tests repointed to bounded/refused/tool-missing;
run_tests.py's affected-selection tests repointed to the three arms; rts' select-retirement test.
Prove the founding case: the REAL branch diff (
git diff --name-only origin/master...HEAD) must now yield a bounded selection or a NAMED refusal — paste the verbatim output. Prove the gate's worst case: a diff containing.envrcyieldsdependency-or-environment-change:.envrcas a NAMED verdict, neverescalate: true. - D6 — lanes via the sanctioned runner ONLY (the runner is the file you are editing — run it with
explicit test paths and
--skip-gates): the touched scripts' own test files (tests/scripts/test_affected_tests.pyand the run_tests affected tests — measure the exact names first). No full-suite run, by the very ruling this packet implements. Paste verbatim.
Fence
ALLOWED: scripts/affected_tests.py, scripts/run_tests.py (the affected-selection consumption
arm and its helpers ONLY — do not touch the batch/child-env/cap machinery), scripts/rts.py, the
test files under tests/scripts/ that pin these three (name them in the report). FORBIDDEN:
everything else — tests/plugins/** (the §5.2 worker's live fence), pyproject.toml, uv.lock,
plans/, reports/, /tmp and any absolute path. FOREIGN DIRT — untouched: context.json,
context.md, context.history.md, docs/CODEBASE_MAP*.md, plans/ast-*.json,
reports/run-tests-latest.json, .claude/skills/**, .deepchat/**.
Conduct
RUL-037 (no python -c/heredoc writes; file tools only; no codemod scripts). Measure before
editing; verbatim outputs; no false attribution. Do NOT commit. Never run a full-suite run. The
pre-push gate uses the file you edit — do not trigger it. Final report ends with: git status of the
allowlist files, rts' output shape + the transform, the three-arm outputs verbatim, the real-branch
diff verdict verbatim, the D6 lane outputs.