This commit is contained in:
John Lancaster
2026-06-20 13:39:25 -05:00
parent adaa4177fe
commit fa4498cb78
+169
View File
@@ -0,0 +1,169 @@
**Phase 3 Results: Packaging Contract and Surface Decoupling (Wheel/sdist Resources + Docs-Only Authoring)**
This section finalizes Phase 3 by defining how authored docs are packaged as runtime resources, how runtime loading avoids filesystem assumptions, and how website and MCP distribution surfaces are decoupled while sharing one authored source.
### Greenfield Framing (Normative)
This Phase 3 design assumes a full refactor with intentional break-and-replace behavior:
1. No compatibility shims, aliases, adapter layers, or dual-read runtime paths.
2. No runtime dependency on repository checkout layout.
3. Runtime docs access is package-resource-only.
4. Canonical authoring remains in `docs/` in source control.
### Research Baseline (Packaging + Runtime)
Authoritative references used for this phase:
1. Python `importlib.resources` docs (`files`, `Traversable`, and zip-safe behavior)
2. Python packaging guidance for wheel/sdist data inclusion
3. Hatchling build target configuration guidance for including non-code files
4. Existing repository constraints from Steps 4-5 (registry-first, deterministic startup, resource-first discovery)
Best-practice conclusions applied to this design:
1. Package docs as build artifacts so runtime reads work from installed wheels.
2. Keep docs source-of-truth in one place (`docs/`) and project into package resource space at build time.
3. Avoid `Path(__file__)`/repo-root probing in runtime paths.
4. Enforce parity across wheel and sdist so local/dev/prod behavior does not drift.
### Phase 3 Responsibilities (Normative)
Phase 3 MUST:
1. Ensure authored markdown under `docs/` is included in wheel and sdist artifacts.
2. Ensure runtime docs registry/document reads use `importlib.resources` only.
3. Ensure MCP runtime behavior is independent of current working directory or checkout structure.
4. Ensure website docs build continues to consume source `docs/` directly.
5. Remove materialization/path-probing coupling from runtime loader code.
6. Preserve deterministic packaged docs layout for registry/resource URI generation.
### Packaging Contract (Wheel + sdist)
Canonical packaging behavior:
1. Source-authored docs remain at repository root: `docs/`.
2. Build projects docs into package resource space under `personal_mcp/docs/` inside artifacts.
3. Runtime anchor for docs loading is `importlib.resources.files("personal_mcp").joinpath("docs")`.
4. Build artifacts MUST include:
- top-level docs pages used by discovery/overview
- `docs/skills/<skill-id>/SKILL.md`
- `docs/skills/<skill-id>/references/**`
Parity requirements:
1. Wheel and sdist contain equivalent docs content for runtime use.
2. Missing docs resources in either artifact is a hard validation failure.
### Build-System Plan (pyproject + build)
Primary target file:
1. `pyproject.toml`
Configuration goals:
1. Add explicit build inclusion rules so docs resources are shipped in wheel artifacts.
2. Add explicit sdist inclusion rules so docs are present for source builds.
3. Keep inclusion deterministic and auditable (no implicit glob side effects beyond intended docs content).
4. Ensure packaged destination path matches runtime anchor (`personal_mcp/docs`).
Implementation note:
1. Use Hatchling-native inclusion mapping (for example force-include or equivalent target-level include mapping) to project `docs/` into package resource space.
2. Prefer one clear packaging path over multiple fallback packaging mechanisms.
### Runtime Loader Contract (No Filesystem Assumptions)
Primary target file:
1. `src/personal_mcp/skills/document_loader.py`
Required runtime behavior:
1. Remove repository-root discovery helpers and path-probing candidates.
2. Remove metadata-based document path overrides that bypass canonical skill layout.
3. Resolve SKILL and reference documents via package-resource-relative paths only.
4. Keep reads UTF-8 and deterministic.
5. Raise explicit errors for missing packaged resources; no fallback probing.
Prohibited runtime behavior:
1. No `Path(__file__).resolve().parents[...]` lookup for docs.
2. No implicit fallback to source-tree `docs/` during runtime reads.
3. No slug-guessing or namespace substitution for path recovery.
### Surface Decoupling Contract (Website vs MCP)
Website surface:
1. Website build pipeline consumes source `docs/` directly (`uv run zensical build`).
2. Static output (`site/`) remains a build artifact served by web mounting logic.
MCP surface:
1. MCP runtime serves docs from packaged resources loaded by registry/resource handlers.
2. MCP does not read `site/` and does not depend on website build artifacts.
Decoupling guarantees:
1. One authored source (`docs/`), two distribution surfaces (website + MCP runtime).
2. Changes to website serving do not alter MCP resource loading semantics.
3. Changes to MCP runtime loader do not require website materialization logic.
### Integration Plan for Existing Modules
Primary integration targets:
1. `pyproject.toml`: add wheel/sdist docs inclusion mapping.
2. `src/personal_mcp/skills/document_loader.py`: replace filesystem probing with package-resource loading.
3. `src/personal_mcp/main.py`: keep startup composition deterministic once registry/resource registration is in place.
4. `src/personal_mcp/mcp.py`: maintain registry-driven resource composition as canonical runtime surface.
5. `src/personal_mcp/web/docs_mount.py`: continue static-site mount behavior without coupling to MCP runtime docs loading.
Cleanup targets:
1. Remove obsolete references to materialization-only modules if no longer present/used.
2. Remove dead code paths that attempt source-tree fallback loading.
### Validation and Test Plan (Phase 3 Scope)
Build/package validation:
1. Build wheel and sdist in CI/local.
2. Inspect artifacts to confirm `personal_mcp/docs/**` exists and includes representative skill/reference files.
3. Install built wheel in isolated environment and verify resource reads via `importlib.resources.files(...)`.
Runtime validation:
1. Run MCP in an environment where repo-root docs paths are unavailable and confirm reads still succeed.
2. Verify representative URIs resolve (skill document and reference document).
3. Confirm startup fails clearly if required packaged docs resources are missing.
Decoupling validation:
1. Run `uv run zensical build` to verify website pipeline still consumes source `docs/`.
2. Confirm MCP runtime does not require `site/` presence.
3. Confirm web static serving behavior is unchanged when docs are built.
Expected command path in this repo:
1. `uv run pytest -q`
2. `uv run zensical build`
### Acceptance Criteria for Phase 3 Completion
Phase 3 is complete when all are true:
1. Wheel and sdist include docs resources in deterministic package paths.
2. Runtime docs loading works from installed artifacts using `importlib.resources` only.
3. Runtime docs loading has no checkout-path dependency and no fallback probing.
4. Website docs build remains source-docs-driven and independent of MCP runtime loading.
5. No compatibility shims, aliases, or dual runtime loader paths exist.
### Non-goals for Phase 3
1. No Step 6 discovery-tool fallback implementation details.
2. No URI aliasing or backward-compat transition mechanics.
3. No redesign of skill frontmatter/schema contracts already finalized in earlier steps.
4. No web UI visual redesign or docs IA overhaul.