Research — CI Pipeline Reinstatement (Phase 0)
No open [NEEDS CLARIFICATION]. This records the load-bearing design decisions and the supply-chain / adversarial evidence for the dependency additions (DIR-051, advisory).
Decisions
D1 — Change router: dorny/paths-filter, two-authority model
filter block = path→group; job if: = group→job), fail-closed unmatched(src/**)→run-all.
full run" (NFR-002) is exactly this engine. Alternatives: hand-rolled path globs per job (drifts, no completeness oracle) — rejected.
it is rewritten in lockstep when filters return (Topology T1).
- Decision: revive the pre-fork
dorny/paths-filterrouter with the two-authority invariant (dorny - Rationale: proven at
e8cc2f444f^; canonical (SO#6); the mission's "docs/packs-only PR skips the - Guard: the
test_ci_quality_path_filters.pyassertion currently pins no filter on the husk;
D2 — Warmup env: cache, pinned-PR / latest-nightly
spec_kitty_events rev, nightly/full pulls latest mainline**; publish via actions/cache keyed on uv.lock + the resolved events rev (not a bare upload-artifact, which architect flagged conflates cache semantics).
pinned-rev policy (operator decision B); nightly still catches upstream drift. Alternatives: always latest (non-deterministic, charter tension) / always pinned (misses drift) — rejected in favor of the split.
- Decision: a warmup composite resolves + builds the editable env once; **PR mode pins a recorded
- Rationale: kills #3283 venv-lock cascade; deterministic PR builds satisfy the charter Shared-Package
D3 — Dual-mode failure behavior
dependents); full mode (nightly + workflow_dispatch "run full") = fail-fast: false + if: always() so every job runs. A mode input threads through reusable workflows. Merge-eligibility: a successor skipped by short-circuit is NOT green — the required-check set treats "skipped-due-to-upstream" distinctly (SC-009). Alternatives: single mode (either churns or hides signal) — rejected.
- Decision: PR mode = fail-fast (matrix
fail-fast: true, tieredneeds:so a red tier short-circuits
D4 — Governance-map introduced disposition (BLOCKER fix)
restore|defer|never-restore set to add introduced (net-new workflows with no pre-fork ancestor: Sonar, new module-*.yml, router, aggregate, nightly, packs). The enforcer asserts the introduced set as data, keeping stock-runner + no-SK_CI_TOKEN invariants.
(architect BLOCKER). Alternatives: shoehorn net-new as restore (lies about provenance) — rejected.
- Decision: extend
interim-ci-producer.md+test_release_ci_ownership.pyfrom the closed - Rationale: the enforcer asserts an exact closed set; "append a row" is not representable
D5 — P1 dead-code census as machine oracle
artifact* that (a) authorizes each base-red drop + each shard exclusion, (b) excludes the coverage denominator, (c) is cross-checked by a non-vacuity floor + a planted dead-code/retired-import negative test. The enforcement allowlists (test_no_dead_, test_no_retired_subsystems) stay always-on.
closes the "mislabel a live regression as dead-code test" loophole. Alternatives: reviewer scrub (fakeable) — rejected.
- Decision: promote the dead-code census (grounding
25-dead-code-census) into an **in-repo machine - Rationale: post-spec squad convergence — P1 must be machine-enforced, not prose+reviewer scrub;
D6 — Sonar: SonarCloud, nightly, fork-safe
the spec-kitty repo, nightly/dispatch, aggregating per-shard coverage-*.xml; skip-green without SONAR_TOKEN. Verify the Priivacy-ai_spec-kitty project identity before wiring (client-inversion). Promotable to per-PR without re-architecting the artefact flow. Alternatives: self-hosted SonarQube (no instance today) / PR-blocking now (backlog risk) — deferred.
- Decision: net-new
sonar.ymlrunsSonarSource/sonarqube-scan-action+ quality-gate action from
D7 — Full-tree modularization, phased
FOUNDATION→TOPOLOGY→LEAN-SUITE cluster gates. Rationale: operator's explicit scope, ROI concern reconciled by phasing (planner). Alternatives: hybrid (kernel/doctrine/packs only) — offered, operator chose phased full-tree.
- Decision: every per-module test group → its own
workflow_callmodule-*.yml, delivered in the
Supply-chain & adversarial evidence (DIR-051, advisory)
Dependencies added/pinned by this plan: dorny/paths-filter, SonarSource/sonarqube-scan-action + sonarqube-quality-gate-action, actions/* (checkout/setup-uv/upload-artifact/download-artifact/cache), astral-sh/setup-uv; pytest plugins (pytest-cov, diff-cover, pytest-xdist) already in pyproject.
tag); versions recorded and periodically reviewed. First-party actions/* + astral-sh + SonarSource are the canonical publishers.
composite executes only pinned, reviewed steps.
echoed (DIR-050).
all contested findings dispositioned — governance-map schema changed (D4); P1 machine-oracle changed (D5); warmup pinned-PR changed (D2); full-tree ROI deferred_with_rationale (phased, D7); #3189 claim changed (downgraded to follow-up). None silently dropped.
- Authenticity + freshness: all third-party actions pinned to a full commit SHA (not a moving
- Lifecycle-script discipline: CI installs run under
uvwith no arbitrarypostinstall; the warmup - Secrets:
SONAR_TOKENonly on the canonical repo; neverSK_CI_TOKENon public jobs; tokens never - Adversarial disposition (post-spec squad,
contracts/adversarial-evidence-contract.mdposture):