Orchestrata Ultimate › Plans › briefs › p-rul040-native-refusal-seam
P-RUL040 native refusal seam (this repo only) — the escalate arm dies; named reasons are the verdict
Source: plans/briefs/p-rul040-native-refusal-seam.md at 8a2cb42ad · last changed 2026-10-20 · first committed 2026-10-20 · 85 lines.
Prose pending.
Plan text
P-RUL040 native refusal seam (this repo only) — the escalate arm dies; named reasons are the verdict
Status: DISPATCH-READY · Repo: /home/mohamed/workspace/wt-COMPONENTS (branch components)
Authority: RUL-040 (Mohamed, verbatim: "never escalate=true is meaningless, it must be measured never
the whole suite that is a huge bug") + his 2026-10-20 directive "focus on this repo only for now".
SEAM NOTE (coordinator, superseding the Stage 0 option-(b) codetools-verb seam FOR NOW): the
codetools select-affected verb remains a later precision upgrade (its packet exists); this packet
implements the refusal seam NATIVELY with this repo's own machinery — scripts/affected_tests.py's
already-measured reasons + scripts/rts.py symbol-precise selection where edges exist. The codetools
verb packet is NOT required, NOT a fence, NOT in scope.
The founding incident (measured, 2026-10-20)
The pre-push gate ran run_tests.py --affected origin/master...HEAD; the oracle answered
"escalate": true with NAMED reasons (docs "certified inert, smoke floor only", .envrc → resolved
edge tests/deploy/test_envrc_toolchain.py, .gitlab-ci.yml → manifest-declared coverage, ...), and
run_tests.py's elif resolved.get("escalate"): arm THREW THE REASONS AWAY and selected the full
39,102-test suite — which then collapsed into ~1.8k killed batches (the cap's session budget).
Four push attempts died on that arm. RUL-040: the measured reasons ARE the verdict; the full run
must never be the fallback.
Deliverables
- D1 —
scripts/affected_tests.py: kill theescalate: trueboolean in the output schema. Its replacement: every output carries"verdict": "bounded" | "named_full" | "refused"plus the resolved per-reason rows (reason → resolved test set, or"certified inert: smoke floor"for zero-edge docs, or"named_full: dependency-or-environment-change:<path>"for pyproject/uv.lock/ env/pytest-config names, or"refused: <missing fact>"when a reason has NO resolution at all). The existing module-level selection machinery stays the resolver; rts.py (select) is used for symbol-precise narrowing where the oracle HAS reference edges (measure its invocation shape and paste it — if rts' swipl dependency makes it unfit for the gate path, say so with the measured cost and leave module-level as the resolver for now). - D2 —
scripts/run_tests.py: DELETE theelif resolved.get("escalate"):full-run arm (cite by symbol; lines drift). New behavior, fail-closed in every arm:bounded→ run the selection (existing path);named_full→ run the selection that the oracle DID resolve PLUS record each named-full verdict with its path in the report — a named-full verdict is an HONEST full justification for those paths, never an implicit 39k (the gate operator sees the name and decides);refused→ ABORT naming the missing fact + the changed set, and require the explicit-decision mechanism:--affected-decision <citation>(recorded in the report and the refusal row); without it the run aborts. NEVER a silent full run, in any arm.
- D2b —
scripts/hooks/pre-push(measured 2026-10-20): the hook has its OWN full-suite arm —BASE not found → "cannot bound the blast radius; running the FULL suite" → exec run_tests.py. Replace it with an ABORT naming the missing base (fail-closed; the pusher re-runs with a base that exists or supplies the decision), and update the hook's echo text ("escalates to the FULL suite only when the honest blast radius IS the whole suite") to the new semantics: named verdicts only, never a silent full run. - D3 — the ledger interaction: measure what a refused/named-full selection records today (paste); a refusal must record a named-refusal row (never a green, never a silent nothing). A named-full run records its verdict names. Keep the reuse machinery untouched otherwise.
- D4 — prove the founding case: the REAL branch diff (
git diff --name-only origin/master...HEAD) throughrun_tests.py --affected(dry path or the actual selection output — do NOT launch the full run): paste the output showing named reasons, noescalateboolean, and either a bounded selection or a named refusal. Then prove the gate's decision path: the same command with--affected-decision "<measured justification citation>"selects exactly the resolved set. - D5 — tests (real, no mocks): repoint
tests/scripts/test_affected_tests.py(measure the exact module name first) to the three verdicts; add the run_tests.py arm tests (refused-aborts, named-full-records, bounded-runs). Run them via the sanctioned runner with explicit paths +--skip-gates(the runner is the file you edit — never a full 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/T17-D7 machinery),
scripts/hooks/pre-push (the D2b arm ONLY), reports/run-tests-latest.json (the sanctioned
runner's OWN report — running any lane writes it; it is allowlisted so the fence does not trip on
the runner's artifact, never edited by hand), the test files under tests/scripts/ that pin these
(name them in the report). FORBIDDEN: everything else — scripts/rts.py (read-only measurement
unless D1's measurement proves a REQUIRED minimal change, then STOP and report the change for
coordinator sign-off), tests/plugins/** (§5.2 landed — do not touch), pyproject.toml, uv.lock,
plans/, reports/ (except the one allowlisted file), /tmp and any absolute path. FOREIGN DIRT —
untouched: context.json, context.md, context.history.md, docs/CODEBASE_MAP*.md,
plans/ast-*.json, .claude/skills/**, .deepchat/**.
INFRA NOTE (measured 2026-10-20): the test-fleet Graph service (10.53.2.10:7687) answers the port
but refuses bolt queries — the runner's preflight fails on it. For FUNCTIONAL lanes add
--skip-services graph (named, functional-only); do NOT skip other services and do NOT use
--skip-infra. If an integration lane needs the graph, STOP and report instead of skipping.
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 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, the D1 schema sample, the three-arm outputs verbatim, the real-branch-diff proof
verbatim, the D5 lane outputs.