Mission Specification: Restore green main: stale test premises after the requirement-grammar scoping and the events 10.4.6 bump

Mission Branch: issue-6240-main-red-test-premise-repair Created: 2026-10-14 Status: Draft Input: Issues #6240 and #6238 (folded together by operator steer), plus an operator scope ruling on dependency-bump shard selection.

Intent Summary (confirmed)

  • Primary actor: a Spec Kitty maintainer or contributor whose PR, or the nightly run, depends on an honest test signal from main.
  • Trigger: the nightly run and every PR that selects the upgrade module shards go red on two tests whose premises lagged shipped changes. Neither failure is a product defect.
  • Desired outcome: both tests pass on main against the shipped contract, the audit they exercise stays as strict as it is today, and a future reducer-dependency bump that lands through the lock file runs the shards that would have caught this.
  • Invariant: no test, audit or classifier is loosened to reach green. Corrections reach the fixture only through the existing operator-sanctioned corrections list.
  • Boundary: an edit to the project manifest alone (for example a rename or a non-version edit) must not trigger the upgrade shards. Only the lock file does.

User Scenarios & Testing (mandatory)

User Story 1 - The requirement-ID lint test matches the shipped grammar (Priority: P1)

A maintainer runs the requirement-ID lint tests. They pass, and they cover the behaviour the grammar now has: requirement kinds are scoped by Mission type, and template placeholders are rejected.

Why this priority: it reds the nightly on two jobs today (#6240).

Independent Test: run the lint test file in isolation. All cases pass, and a case for each Mission-type branch exists.

Acceptance Scenarios:

1. Given the five existing well-formedness cases, When they are checked under the software-dev Mission type, Then each gives its existing expected verdict. 2. Given a research-only requirement kind (for example DR-001), When it is checked under the research Mission type, Then it is well-formed; and when it is checked under software-dev, Then it is not. 3. Given a template placeholder in a declared position (for example FR-00N), When it is checked under either Mission type, Then it is not well-formed.

User Story 2 - The full-corpus recovery audit passes on the pinned historical corpus (Priority: P1)

A maintainer runs the full-corpus recovery audit tests. The healthy baseline audit reports no teamspace blocker, because the fixture carries the same operator-sanctioned correction the live corpus already carries.

Why this priority: it reds main for every PR that selects the upgrade shards, and fail-fast then cancels most other module shards (#6238).

Independent Test: run the full-corpus recovery test in isolation under the pinned reducer version. All three variants pass.

Acceptance Scenarios:

1. Given the full historical corpus exported from its pinned commit, When the fixture is built, Then every path in the operator-sanctioned corrections list that exists in the export carries its sanctioned bytes, applied as a separate, labelled fixture commit. 2. Given that fixture, When the strict mission-state audit runs, Then it reports zero teamspace blockers. The scanner-membership fault variants still reject their injected faults. 3. Given a sanctioned path that does not exist in the historical export, When the fixture is built, Then it is skipped, not created.

User Story 3 - A lock-file reducer bump runs the shards that reduce status events (Priority: P2)

A maintainer opens a PR that changes the lock file (for example, a reducer-package bump). CI selects the upgrade and status module shards for that PR. A PR that changes only the project manifest does not select the upgrade shards through this route.

Why this priority: it closes the gap that let #6238 merge unseen. It is secondary to restoring green.

Independent Test: call the shard-selection authority with a changed-path set containing only the lock file, then with only the project manifest, and compare the selected modules.

Acceptance Scenarios:

1. Given a diff that touches only uv.lock, When the module selection is computed, Then it includes upgrade and status. 2. Given a diff that touches only pyproject.toml, When the module selection is computed, Then this mission's routing does not add upgrade.

Edge Cases

  • A sanctioned correction path that is absent from the pinned export is skipped.
  • A sanctioned correction whose current bytes would make another fixture-based assertion fail is surfaced, not silently applied. The overlay is limited to paths present in the export, and the existing recovery and byte-identity tests are run to confirm.
  • The routing change must keep the group non-src, so it never masks an unmapped src/** change.

Requirements (mandatory)

Functional Requirements

IDTitleUser StoryPriorityStatusDeliveryNo-op passable?
FR-001Lint test re-pinned to the Mission-type-aware signatureAs a maintainer, I want the well-formedness test to call the helper with an explicit Mission type so that it exercises the shipped contract (#6240).HighOpen[ratchet]no — the test is red at the base commit and must be green after
FR-002Research-scoped kinds and placeholder rejection coveredAs a maintainer, I want cases proving a research-only kind is valid only under research, and a placeholder is never well-formed, so that the c0f455d06 behaviour is pinned (#6240).HighOpen[ratchet]no — paired positive/negative verdicts on the same token
FR-003Full-corpus fixture carries the sanctioned correctionsAs a maintainer, I want the full-corpus recovery fixture to apply the operator-sanctioned corrections, read from the single existing list, so that the strict audit agrees with the live corpus (#6238).HighOpen[ratchet]no — the audit exits 1 at the base commit and 0 after
FR-004Lock-file change selects the upgrade and status shardsAs a maintainer, I want a uv.lock change to select the upgrade and status module shards, and a pyproject.toml-only change not to select upgrade through this route, so that a lock-file reducer bump is tested before merge (#6238).MediumOpen[build]no — paired lock-only vs manifest-only selection

Non-Functional Requirements

IDTitleRequirementCategoryPriorityStatus
NFR-001Audit strictness preservedZero new classifier tolerances, allowlist entries or skipped assertions in the audit and recovery tests. The count of _OPERATOR_SANCTIONED_CORRECTIONS entries is unchanged.ReliabilityHighOpen
NFR-002Bounded CI costThe routing change adds shard selection for exactly one path (uv.lock) and at most two modules (upgrade, status).PerformanceMediumOpen

Constraints

IDTitleConstraintCategoryPriorityStatus
C-001No product code changeChanges are confined to tests, test fixtures and CI routing configuration. No src/ behaviour changes.TechnicalHighOpen
C-002Single authority for sanctioned correctionsThe fixture reads the existing sanctioned-corrections list. It must not keep its own copy of the paths.TechnicalHighOpen
C-003Project manifest excluded from the new routepyproject.toml is not added to the new fan-out group (operator ruling, decision 01M4XV6HM7WHEB2B8QG67N29HT).BusinessHighOpen

Key Entities

  • Operator-sanctioned corrections list: the reviewed set of corpus files whose bytes an operator deliberately changed after the byte-freeze. It is the only authority for which historical bytes may differ.
  • Full-corpus recovery fixture: a throwaway repository built from a pinned historical commit, used to prove the recovery path and the strict audit.
  • Module fan-out group: a non-src path group that adds named module shards to CI selection.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: The requirement-ID lint test file passes in full (0 failures, up from 5), under both the software-dev and research Mission types — [ratchet] · no-op passable: no
  • SC-002: All 3 variants of the full-corpus recovery audit test pass under the pinned reducer version (0 failures, up from 3) — [ratchet] · no-op passable: no
  • SC-003: The nightly jobs that failed on these tests ("specify_cli out-of-matrix trees", "Interpreter matrix shard 5") pass on their next run after merge — [ratchet] · no-op passable: no
  • SC-004: A lock-file-only change selects 2 additional module shards (upgrade, status); a manifest-only change selects 0 additional upgrade shards through the new route — [build] · no-op passable: no

Out of Scope (follow-ups, named in the PR)

  • The shared subprocess test virtualenv (tests/conftest.py) installs the newest allowed reducer package rather than the locked one, so subprocess CLI tests can run a reducer version other than the pin.
  • A broader per-PR lane for the specify_cli out-of-matrix tree. Follow-up: #4732.