Known Current Friction Points
This page is deliberately time-sensitive and drifts fast. It captures repo and tooling friction that a maintainer — or an agent acting in a maintainer capacity — is likely to hit while running a mission today. It is not durable doctrine: specific issue numbers, version gates, and toggles change as the codebase moves. Always re-verify against the authoritative sources before trusting a specific number:
CLAUDE.md(its "Test-run baseline-red gotcha" note), ADR 2026-07-17-1, and the issue tracker.
Snapshot date: 2026-09-30 · Spec Kitty 4.0.0rc5 (4.x cycle). Proof that this list drifts:
#2772 was a known-red P0 when this note was first drafted and has since been
closed — so the "known reds" below are already a different set than a month ago.
The friction points
mainmay be legitimately RED. Honest P0 reproductions are left red on purpose (in the nightlyp0-reprolane, not per PR) (ADR 2026-07-17-1); currently open examples: #2736, #1834. Before "fixing" any red, attribute it — reproduce onupstream/main/ the merge-base. Never green-wash a@pytest.mark.p0_reprored (it shows only in the nightly); that erases a deliberate release-blocker signal.- CI-environment false reds that pass locally: auth
(
logged_out_on_connected_teamspace) and the pre-review gate opt-out (SPEC_KITTY_SKIP_PRE_REVIEW_GATE, its own name since #3980). Config, not your diff. - Stale-install false reds. Commands that shell out to
spec-kitty(e.g. themerge-driver-*commands) only reflect your working tree afterpip install -e ./uv pip install -e .. Re-install after every rebase. - Stale-venv false reds. A
ModuleNotFoundErrorfor a package that is declared and pinned usually means the.venvwas never (re)synced, not a real regression — runuv sync --frozen --all-extrasbefore recording it as pre-existing (#648). - The
pr:deferred/pr:skip-cilabels skip some PR workflows — a green check can mean "not run," not "passed." Jobs inci-windows.yml,check-spec-kitty-events-alignment.ymlandrelease-readiness.ymlcarryif: !contains(github.event.pull_request.labels.*.name, 'pr:deferred') && !contains(..., 'pr:skip-ci'), so either label makes them report skipped. Check the PR's label list before treating an all-green run as evidence the change is safe; a skipped job is unverified, not clean. (See pr-landing.md §4 for how to classify checks once you do have real CI results to read.) charter lint's project-DRG input (.kittify/charter-packs/graph.yaml) looks gitignored but is deliberately un-ignored — confirm it is tracked and in-diff before filing a lint finding..gitignoreblanket-excludes.kittify/charter-packs/**and then re-includes specific subpaths, including!.kittify/charter-packs/graph.yaml; the file is meant to be committed and is the first candidatecharter_runtime/lint/_drg.py::_load_project_drgreads (ahead ofmerged_drg.json/drg.json/compiled_drg.json). If it is stale or absent,charter lintsilently falls back toGraphState.BUILT_IN_ONLY(orMISSING) and skips project-layer checks rather than failing loudly — so before treating acharter lintresult as authoritative, confirmgit ls-files .kittify/charter-packs/graph.yamlshows it tracked and thatspec-kitty charter synthesizeregenerated it in your diff if doctrine artifacts changed.- In a lane or clone, a bare
python/pytestimports the PRIMARYsrc, not your lane. Alwaysuv run <cmd>. - CI gates that pass locally, then fail on the PR: the terminology guard
(
terminologyjob inci-router.yml), the architectural battery (the always-onarchitectural-fastgate, which runs on every PR shape, plus the two code-scopedarchitectural-heavylegs), the canonical-producer lint (CP001 fires on a hand-rolled event dict withevent_type+payloadkeys — build viaspec_kitty_events.lifecycle.*instead;scripts/lint_canonical_producers.py), and the docs tests (tests-docsjob). On the rebased tip, run the terminology guard, the specifictests/architectural/gate files your diff implicates (not the whole directory — seeNO_FULL_HEAVY_SUITES_IN_MISSION; CI owns the full sweep), andPYTHONPATH=. python scripts/docs/check_docs_freshness.py --cifor docs changes before declaring a branch green. - An always-on
tests/architectural/test_lifted_*.pygate re-runs an out-of-matrix suite's invariant, so share its code; never copy it. The source suite runs only in the nightly and its lift runs on every PR, so a copied predicate keeps enforcing the old rule after the source changes (#5008). Since #5015, the code a lift shares with its source lives once, intests/architectural/_lifted_<topic>.py, and both files import it. That includes tests:from <home> import test_x as test_xis what makes pytest collecttest_xin the importing module. The lift's docstring names its source in double backticks.tests/architectural/test_lift_single_source.pyfails a lift that defines a name its source, or a shared home, also defines, or that copies a body under a new name. The name rule is strict: even an unrelatedREPO_ROOTdefined in one file and bound in the other fails, so import it or rename it. To change a lifted invariant, edit the shared home: both suites pick it up. - No
git stashin lane worktrees — the stash stack is shared across worktrees, so apopcan steal a sibling lane's work-in-progress. move-taskcan hang on fan-out. Background it and setSPEC_KITTY_NO_MOMENT_HANDLERS=1(the oldSPEC_KITTY_SYNC_MINIMAL_IMPORT=1spelling is still accepted as an alias, #3980).- After
finalize-tasks, verify the issue-matrix / coordination state. 3.2.6 made the PRIMARY scaffolder idempotent; the coordination/consolidate reset path is not fully verified (not re-checked on 4.0.0rc5). - Docs scripts need
PYTHONPATH=., andbuild_cli_reference.pydefaults to the wrong output path — pass--output docs/api/cli-commands.md --agent-output docs/api/agent-subcommands.mdexplicitly. - Shared-package boundary: anchor new runtime code in
src/runtime/next/_internal_runtime/; the oldsrc/specify_cli/next/shim was removed on 2026-07-03 — do not recreate it. Consume events / tracker only viaspec_kitty_events.*/spec_kitty_tracker.*. - A pyenv-scoped editable
spec-kitty-cliinstall shadows a pipx install. Recurring: ifpyenvmanages the Python version active for this repo (a.python-versionfile, orpyenv local), an editable install left in that pyenv version'ssite-packages(an_editable_impl_spec_kitty_cli.pthpointing at some checkout'ssrc/) resolves ahead of the pipx-installedspec-kittyonPATH, so the CLI silently runs a stale or unrelated checkout instead of the one you are working in. Detect:which spec-kitty(a pyenv shim, e.g.~/.pyenv/shims/spec-kitty, instead of the pipx shim under~/.local/bin) andpip show -f spec-kitty-cliin that pyenv version (an_editable_impl_spec_kitty_cli.pth/ editable project-location entry is the tell). Fix:pip uninstall spec-kitty-cliinside the offending pyenv version, or reorderPATHso the pipx shim wins. .git/hooks/pre-commitpins an absolute python interpreter. The commit-guard hook Spec Kitty installs (specify_cli.policy.hook_installer) capturessys.executableat install time and hardcodes it into the hook — by design, so the hook does not depend onPATH(FR-009). Moving, deleting, or rebuilding.venvat a different location (a renamed clone, a relocated checkout) leaves the pinned path dangling. Symptom:git commitfails because the hook's interpreter path no longer exists. Fix: if only the interpreter binary vanished,uv sync --frozen --all-extrasrebuilds.venvat the same path and the existing hook resolves again; if the checkout itself moved, delete.git/hooks/pre-commitand re-runspec-kitty implement <any-WP>(or any path that allocates a lane worktree) to regenerate the hook pinned to the new location.
Maintaining this page
When you hit a new mid-mission friction point — or when one above stops being true (a known-red P0 closes, a toggle is retired, a version gate passes) — update this page and bump the snapshot date and the version tag in the same change. Keep entries short and actionable; deep rationale belongs in the linked runbooks, not here.
See also
- Landing contributor PRs — the maintainer landing runbook.
- Onboarding run — the mission-run priming prompt that points here.
- Test-flakiness handling policy — the never-retry-to-green rule.
- Red main and release readiness.