Implementation Plan: Loop-reliability + CI-red burndown remediation
Branch: fix/loop-reliability-ci-red-burndown | Date: 2026-07-19 | Spec: spec.md Input: Land the ready product fixes for two implement-review-loop P0s (#2534, #2573b) and burn down the tracked 3.2.x CI reds (#2807, #2809, #2812), grounded by a pre-plan squad (research.md).
Summary
Two lanes of small, fully-rooted remediation. Lane A (product): land the ready consumer-repo calm-degrade fix (#2534, a rebase) and teach the sync daemon to honor SPEC_KITTY_SYNC_DISABLE (#2573b, ~4 lines). Lane B (CI hygiene): isolate a leaked-toggle test (#2809), fix a schema-drift crash that reds three charter tests at once (#2807), seed a stale fixture + skip an auth-env test (#2807), and root-fix a warnings flake + a CI filter-guard mismatch (#2812). All items are S except #2534 (M — the rebase over churned files is the only real risk). Behavior-preserving except the intended env-honoring and consumer-repo calm-degrade.
Technical Context
Language/Version: Python 3.11+ Primary Dependencies: src/specify_cli/review/ (pre-review gate), src/specify_cli/sync/ (daemon), src/charter/evidence/ (dry-run evidence), src/specify_cli/runtime/resolver.py, .github/workflows/ci-quality.yml Testing: pytest; ATDD red-first through the pre-existing repros (test_daemon_sync_disable_env, the fix/2534 red-first tests, the charter reds); the reliable lane invocation is uv run --extra test pytest Constraints: exclude deferred-by-design work (C-001); #2534 is land-not-redesign (C-002); every xfail is strict + carries a tracking-issue ref (NFR-002); ruff + mypy --strict clean Scale/Scope: ~6 WPs / 2 lanes; ~5 S fixes + one M rebase; net small
Charter Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
tests, the charter/urn reds); no new entry points where one exists. PASS.
(test_upgrade_updates_templates) uses a skip-when-logged-out env-guard, not a blanket xfail. PASS.
env) change only the intended surfaces; spec-kitty-repo gate behavior + daemon-on-unset are unchanged. PASS.
later. PASS.
re-wire to its own issue; do not split the (well-rooted) loader anomaly. PASS.
- ATDD-First (C-011) — every fix flips a pre-existing red-first repro red→green (daemon repro, the fix/2534
- No unjustified suppression (NFR-002 / Sonar) — prefer real fixes; the only xfail-candidate
- Behavior-preserving except intent — #2534 (consumer-repo calm-degrade) + #2573b (daemon honors disable
- Land-not-redesign (C-002) — #2534 ships by rebasing the ready branch; #2598 (epic-blocked) supersedes
- Scope fences (C-001/C-005) — exclude #2795/#2367-A, #2573a-deep, #2598; defer the
url_list→charter.yaml
No violations → Complexity Tracking intentionally empty.
Project Structure
Documentation (this mission)
kitty-specs/loop-reliability-ci-red-burndown-01KXWWD6/
├── plan.md, research.md, data-model.md, contracts/, traces/, issue-matrix.md, tasks.md (later)
Source Code (repository root)
src/specify_cli/review/pre_review_gate.py # WP01 (#2534) — is_consumer_repo seam
src/specify_cli/cli/commands/agent/tasks_move_task.py # WP01 (#2534) — calm reason (3way)
src/specify_cli/sync/daemon.py # WP02 (#2573b) — _daemon_start_skip_reason honors disable env
src/charter/evidence/orchestrator.py # WP04 (#2807) — isinstance guard (clears 3 reds)
.github/workflows/ci-quality.yml # WP06 (#2812) — add `platform` to the loader-coverage if-guard
tests/review/test_pre_review_gate_engine.py # WP01 — red-first unit (from fix branch)
tests/review/test_pre_review_gate_integration.py # WP01 — red-first integration (from fix branch)
tests/sync/test_daemon_sync_disable_env.py # WP02 — repro (flip green)
tests/sync/conftest.py # WP03 (#2809) — hoist the #2794 env-reset fixture
tests/charter/test_bundle_contract.py # WP05 (#2807) — seed charter.yaml in _init_fixture
tests/adversarial/test_distribution.py # WP05 (#2807) — skip-when-logged-out
tests/runtime/test_resolve_by_urn.py # WP06 (#2812) — clear resolver.__warningregistry__
Structure Decision: single-project. Two lanes (product vs CI-hygiene), disjoint owned_files per WP.
Complexity Tracking
No Charter Check violations — table intentionally empty.
Implementation Concern Map
> Concerns are NOT work packages. /spec-kitty.tasks maps these to executable WPs.
IC-01 — Land the consumer-repo pre-review-gate calm-degrade (#2534)
"gate authorities unavailable" internal-module message — calm-degrade to a non-blocking no_coverage warn.
_is_spec_kitty_source_repo), tasks_move_task.py (_PRE_REVIEW_CONSUMER_REPO_REASON; needs git apply --3way — positional drift only), tests/review/test_pre_review_gate_{engine,integration}.py (red-first).
fights, port-the-intent (research §1). Do NOT re-derive (C-002).
- Purpose: A consumer repo's
move-task --to for_reviewno longer surfaces the alarming - Relevant requirements: FR-002; NFR-003; C-002, C-003.
- Affected surfaces: rebase commit
0153934f9onto main —pre_review_gate.py(is_consumer_reposeam + - Sequencing/depends-on: none.
- Risks: the rebase (LM-1) — verify the repro still fires on main + the two hunks land by 3-way; if it
IC-02 — Sync daemon honors the disable env (#2573b)
is_truthy-guarded disable-env check mirroring the pre-review-gate grammar; flip tests/sync/test_daemon_sync_disable_env.py green.
- Purpose:
SPEC_KITTY_SYNC_DISABLE/MINIMAL_IMPORTactually prevents daemon spawn. - Relevant requirements: FR-003; NFR-003; C-003.
- Affected surfaces:
src/specify_cli/sync/daemon.py_daemon_start_skip_reason(:1038) — add an early - Sequencing/depends-on: none (independent of the fixture; the repro sets the env itself).
- Risks: precedence placement (any position returns non-None → skip); zero blast radius on the unset path.
IC-03 — Isolate the strict-JSON test from the leaked sync toggle (#2809)
agent/conftest.py:51) into tests/sync/conftest.py.
- Purpose:
test_strict_json_stdoutis deterministic in CI regardless of a leakedSPEC_KITTY_SYNC_*toggle. - Relevant requirements: FR-005; NFR-001.
- Affected surfaces: copy the existing autouse
_isolate_pre_review_gate_sync_togglesfixture (#2794, - Sequencing/depends-on: none.
- Risks: scope the fixture to
tests/sync/(minimal blast radius); don't hoist repo-wide unless needed.
IC-04 — Fix the schema-drift crash in dry-run evidence (#2807, clears 3 reds)
AND test_charter_epic_golden_path.
string post-#2773 (if not isinstance(charter_cfg, dict): charter_cfg = {}) + fix the stale docstring (:82).
the red; the feature has no live config home post-#2773.
- Purpose: one
isinstanceguard clearstest_phase3_dry_run_evidence_smoke, the orchestrator dry-run test, - Relevant requirements: FR-004; NFR-001.
- Affected surfaces:
src/charter/evidence/orchestrator.py:95-96— guardconfig["charter"]being a path - Sequencing/depends-on: none.
- Risks: defer the
url_list→charter.yaml re-wire to a separate issue (C-005) — NOT required to clear
IC-05 — Charter CI-fixture hygiene (#2807)
charter.yaml alongside charter.md); tests/adversarial/test_distribution.py:237 (skip-when-logged-out env-guard, mirroring the charter-mission auth-skip — real fix over blanket xfail).
(existence + git-tracked is the load-bearing assertion).
- Purpose: green
test_bundle_contract(stale fixture) + de-noisetest_upgrade_updates_templates(auth-env). - Relevant requirements: FR-004; NFR-001, NFR-002.
- Affected surfaces:
tests/charter/test_bundle_contract.py_init_fixture(seed + commit a minimal - Sequencing/depends-on: none.
- Risks: bundle_contract may need schema-plausible
charter.yamlcontent ifis_stalehashing runs
IC-06 — CI flake + workflow filter-guard (#2812)
block); .github/workflows/ci-quality.yml (add || needs.changes.outputs.platform == 'true' to the mission-loader-coverage job if:, :1290-1293).
- Purpose: root-fix the urn-lane warnings flake and the mission-loader-coverage skip anomaly.
- Relevant requirements: FR-006; NFR-001, NFR-002.
- Affected surfaces:
tests/runtime/test_resolve_by_urn.py(clearresolver.__warningregistry__in the - Sequencing/depends-on: none.
- Risks:
platformoutput feeds other jobs — the 1-line guard change is low blast radius; don't split.
Mission hygiene (not an IC)
issue-matrix.md(already authored) references #2534/#2573/#2807/#2809/#2812. Tracer files seeded at planning.
Lanes
Lane A (product): IC-01, IC-02. Lane B (CI hygiene): IC-03, IC-04, IC-05, IC-06. All ICs independent (disjoint owned_files) → ~6 WPs, highly parallel. finalize-tasks computes lanes.