Contracts
pre-review-gate-output.md
Contract: Public Pre-Review Gate Output
Human mode
Running
- announce gate start within 1 second;
- receive a typed
scope_assessedevent and, if classification is unknown, state before launch that it will run under the existing timeout; - while the process remains active, emit elapsed liveness at least every 30 seconds;
- emit exactly one final outcome.
Oversized refusal
The final output must state:
- validation did not start because the scope is explicitly oversized;
- the normalized target(s) and effective budget;
- the work package remains in its prior lane;
- recovery choices: bounded
pre_review_test_scopeor explicit--skip-pre-review-gate.
Unknown timeout
The final output must state:
- timeout and unknown classification;
- normalized scope identity and targets;
- configured effective budget and monotonic-clock observed elapsed time;
- unchanged lane;
- evidence is a candidate for a reviewed metadata update, not an automatic classification.
Structured mode
Stdout contains exactly one final JSON document. There are no progress JSON objects and no human heartbeat text mixed into stdout.
The existing pre_review_gate object is extended additively:
{
"outcome": "timed_out",
"reason": "...",
"test_targets": ["tests/example"],
"run_state": "timed_out",
"budget_classification": "unknown",
"scope_identity": "...",
"effective_budget_seconds": 300,
"matched_budget_rule": null,
"classification_candidate": true,
"observed_elapsed_seconds": 300.0,
"classification_guidance": "Propose a reviewed metadata update if evidence shows structural oversize"
}
The final envelope carries authoritative top-level transition_applied: false. Oversized refusal uses nested outcome: "scope_oversized", run_state: "not_started", classification_candidate: false, and both recovery choices. Existing skip, disable, warning, block, success, timeout, and cancellation fields remain compatible.
The existing top-level transition_applied field is authoritative. Whenever a nested mirror is present inside pre_review_gate, tests require equality with the top-level value.
Precedence
1. explicit per-invocation skip; 2. first truthy canonical disable variable; 3. scope-budget assessment; 4. gate execution and terminal/block/warn aggregation; 5. transition application.
No refusal or timeout may report a successful transition.
scope-budget-policy.md
Contract: Deterministic Pre-Review Scope Budget Policy
Purpose
Decide, before subprocess launch, whether a resolved test scope is explicitly suitable, explicitly oversized, or not yet classified for the interactive pre-review gate.
Input
ScopeResult.test_targets;- positive effective head-run timeout in seconds.
Output
One immutable ScopeBudgetAssessment:
classification: bounded | oversized | unknown
scope_identity: stable string
normalized_targets: ordered unique tuple
effective_budget_seconds: positive number
matched_rule_id: string | null
evidence: string | null
guidance: string
Normative behavior
1. Normalize a copy of targets; never rewrite executed argv. 2. Derive identity using namespace spec-kitty.pre-review-budget/v1 and canonical UTF-8 JSON {"namespace":...,"targets":[...]} (sort_keys=True, ensure_ascii=True, separators (",", ":")), then SHA-256; emit budget-v1:sha256:<lowercase hex>. Do not use Python hash()/repr() or reuse post-run scope_source_identity(). 3. Match source-controlled exact target atoms by membership. 4. Return unknown when no rule matches. 5. Refuse execution only for oversized. 6. Warn and execute for unknown under the existing timeout. 7. Expose no runtime write, learning, or promotion API. 8. A new classification requires a reviewed source change with evidence. 9. The pinned vector for ("tests/architectural",) MUST equal budget-v1:sha256:10c1e7475c72e48b83e4910e24437646d6ecd55052ca9a3a4f413b17153946fe, including in a fresh process with a different PYTHONHASHSEED.
Initial rule
Any normalized target set containing the exact atom tests/architectural is oversized, based on #2573 dogfood evidence of roughly 26 minutes for that full-directory target. Descendant file targets do not match this rule. A suite encoded only inside a declared command remains unknown; arbitrary command parsing is outside 3.2.6.
Non-goals
- CI runtime prediction;
- workflow scheduling or shard changes;
- log ingestion/backfill;
- per-machine caches;
- automatic classification after timeout;
- refusal of an unknown scope.