Orchestrata Ultimate › Plans › briefs › p-rul040-stage1-codetools-verb

P-RUL040 Stage 1 — codetools side: the select-affected verb with a frozen JSON contract

Source: plans/briefs/p-rul040-stage1-codetools-verb.md at 8a2cb42ad · last changed 2026-10-20 · first committed 2026-10-20 · 88 lines.

Prose pending.

Plan text

P-RUL040 Stage 1 — codetools side: the select-affected verb with a frozen JSON contract

Status: DISPATCH-READY · Repo: /home/mohamed/workspace/orchestrata.codetools (branch master) Authority: RUL-040 (Mohamed, verbatim, injected in plans/briefs/p-rul040-fail-closed-blast-radius.md §RULING) + the Stage 0 adjudication in reports/p-rul040-stage0.md (seam = option (b): the codetools select-affected verb consumed as a subprocess JSON contract from the DEPLOYED CLI). This packet is the codetools half; the orchestrata consumption half is a SEPARATE packet on a separate fence.

Context (measured, verify each)

The contract (coordinator-defined; implement exactly, freeze in the docstring + a contract test)

Command: codetools deploy select-affected --repo-root R --json reading one JSON document on stdin:

{
  "changed_files": ["src/a.py", "tests/b/x.py"],
  "facts": {
    "sym_hash": [["sym.path", "hexhash"], ...],
    "file_hash": [["relpath", "hexhash"], ...],
    "defines": [["relpath", "sym.path"], ...],
    "calls": [["caller.sym.path", "callee.sym.path"], ...],
    "is_test": [["node.id"], ...],
    "safety_escape": [["relpath"], ...]
  }
}

stdout is exactly one JSON line; stderr is for progress/errors:

Facts mapping (the ladder's inputs from the facts — measure each and REPORT the exact mapping table): symbol diff = sym_hash pairs vs the baseline hashes the facts carry (old hashes come from file_hash+history if present; if the facts cannot express a baseline, that missing fact is a REFUSAL, not a guess); defines/calls drive rung 1; is_test/rung-3 rules; rung 4 triggers on the changed_files names (pyproject.toml, uv.lock, env/*.env, pytest config names); rung 5 whenever a rung needs data the facts lack. Do NOT require a codetools coverage baseline — the contract's baseline is the facts' hash pairs; if any rung is IMPOSSIBLE without a real coverage baseline, say so explicitly in the report with the mechanism (it is either a fact-schema extension for the orchestrata side or a documented contract limit — the coordinator rules it).

Deliverables

Fence

ALLOWED: src/codetools/deploy/cli.py, new files under src/codetools/deploy/, new/existing tests under tests/deploy/ that test the verb. FORBIDDEN (named): pyproject.toml, uv.lock, deploy/**, src/codetools/review/** (REV-3 lane ACTIVE), anything else — including /tmp and any absolute path (the fence wins every time; the previous packet was refused on a /tmp write). FOREIGN DIRT — untouched: src/codetools/review/gates.py, tests/review/test_review_ruff_lookup.py, plans/ast-*.json, kimi-export-*.md, plans/*.warmcache.

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 (the coordinator commits). Do not run a test twice against the same code state. Final report ends with: git status of the allowlist files, the rung×facts mapping table, the three contract-case outputs verbatim, the D4 lane output.