Research: Frozen lanes for started work packages

Phase 0 research for this mission is the pre-spec grounding squad (research/code-grounding.md) plus the post-specify squad (research/squad-post-specify.md). This file records the plan-level questions those reports left open, and how the plan answers them.

#QuestionDecisionRationaleAlternatives rejected
R1Where does the invariant live?A constraint input of the pure compute_lanes, re-checked at the compute_and_write_lanes chokepointOne decision site. The #5573 reproduction becomes a preserving success. Compute stays pure (C-002).A post-hoc diff in finalize: it would refuse the repro, and the heuristic would stay the authority. Freezing all lanes: it breaks supported amendments of unstarted WPs. Compute reading status/git: it breaks purity.
R2How is "started" decided?History-based: any event with to_lane ∉ {planned, blocked, canceled}, plus lane-work-tip fallback evidence for lanes with no history-started memberThe FSM resets (in_progress/in_review/approved → planned) and forced or blocked → in_progress moves would otherwise unfreeze committed workCurrent-state lane != planned (the planning-pin predicate): misses resets, and counts planned → canceled
R3How are lane tips read without N git calls?recorded_tip_branches(repo_root): one git for-each-ref --format=%(refname) refs/spec-kitty/lane-tip/NFR-001 (≤ 200 ms for 30 WPs)One read_tip call per lane
R4When does the refusal fire?A read-only preflight after the ownership gates and before _emit_tasks_started (the first status write)No status commit to undo (#5641). Finalize's write-scope restore covers frontmatter and tasks.md (SC-003). Validate-only gets the same check (FR-009).Inside the commit pipeline only: it fires after the status writes and relies on restore
R5Absent vs unreadable status logAbsent → no history-started WPs (proceed). Malformed (StoreError) or an unresolvable surface → refuse status_unreadableA legacy agent tasks finalize-tasks writes lanes.json before seeding status (tasks_finalize.py:308-330)Refuse whenever no log exists
R6Started lane-mates split by an amendmentPre-union them in the union-find with a frozen_lane_membership collapse eventBoth WPs' commits live on the same branch; preservation beats refusalRefuse the split
R7Which lane ids are reserved from minting?The recorded lane ids of every started WP, including started WPs excluded by the #3713 cancellation projectionAn orphaned id whose branch holds commits must not be handed to new work (FR-004)Reserve every previous id: it changes unstarted-only re-letter behaviour without need (SC-004)
R8Property testing without hypothesispytest.mark.parametrize over itertools.product / combinationsSupply-chain tactic, C-006; precedent tests/terminus/test_terminus_reconciliation_property.pyAdding hypothesis
R9Error-code shapeLaneMembershipFrozenError(LaneComputationError) with error_code: ClassVar = "LANE_MEMBERSHIP_FROZEN", structured conflicts, rendered by the existing terminal rendererMirrors LaneDependencyCycleError (compute.py:218) and its rendering branch (mission_finalize_commit.py:922-972)A StructuredError subclass (another family)

No dependency is added, removed or upgraded, so the supply-chain section does not apply (DIRECTIVE_051 not triggered).