Contracts
packaging-parity.md
Contract: Packaging parity (wheel + sdist)
Requirement
packs/built-in/ ships completely in BOTH the monolith wheel and the sdist; the moved content's src/doctrine/** package-data globs are removed (no duplication).
Root pyproject.toml changes
src/doctrine/** artifacts.
excludes a top-level packs/).
[tool.hatch.build.targets.wheel]:force-include = { "packs" = "packs" }; drop moved-content[tool.hatch.build.targets.sdist]:includegains"packs/"(today it issrc/, which
Acceptance (NFR-002 — non-fakeable)
1. Build wheel + sdist. For each, the set of relative paths under packs/built-in/ equals the pre-move file manifest (exact set-equality — ≥ would pass on duplication; a partial move fails). 2. Install the wheel into a clean venv (declared deps only, no repo src/ on path); import doctrine, load_built_in_graph() (identity fixture), and spec-kitty doctor doctrine all succeed with 0 missing-file errors. 3. The moved content is absent under src/doctrine/** (FR-009) — no dual-home duplication.
Rationale
Pre-spec squad proved a build can succeed while shipping an empty/partial artifact; gate on the built artifacts' contents and a live import, never on "build exited 0."
resolve-pack-root.md
Contract: resolve_pack_root(tier)
Module: src/doctrine/pack_paths.py (doctrine layer — must not import charter/specify_cli, C-004).
Signature
def resolve_pack_root(tier: Literal["built-in", "org", "project"], *, org_root: Path | None = None,
project_root: Path | None = None) -> Path: ...
Resolution order (built-in)
1. SPEC_KITTY_PACKS_ROOT env → <env>/built-in if it exists. 2. Editable: nearest ancestor of __file__ containing packs/built-in/. 3. Installed: files("doctrine").parent / packs / built-in if it exists. 4. Else raise PackRootNotFound("built-in").
org/project: return the caller-supplied org_root / project_root (unchanged semantics — the seam is shared, the tier inputs differ).
Guarantees (tested — FR-006 two-layout matrix)
packs/built-in/.
- Editable: from a repo checkout, returns repo-root
packs/built-in/. - Installed: from a clean-venv wheel install (no repo
src/on path), returns the site-packages - Fail-closed: never returns a path inside
src/doctrine/; never falls open to an arbitrary tree. - Idempotent / pure: no mutation; same inputs → same path.
Consumers repointed (FR-003/FR-004)
built_in_graph_source()→resolve_pack_root("built-in").- each repository
built_in_dirdefault →resolve_pack_root("built-in") / <kind>. - the enumerated moved-tree readers + the
specify_clihardcoded string path.
Non-goals (C-002)
stays OrgDRGFragment). This contract unifies the path, not the load mechanism.
- Does not unify the loader or schema (built-in stays a
DRGGraph/14-fragment reader; org