From e9b6359fb88ee13e9da26d4b82f2eec97624ec3e Mon Sep 17 00:00:00 2001 From: Rafael Richards Date: Mon, 11 May 2026 08:30:03 -0400 Subject: [PATCH] phase4-E: smoke + evidence; Phase 4 closed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Captures Phase 4 exit per phase4-plan.md §6 + §11. Mirrors phase3-evidence.md shape: one section per gate, "What this proves" roll-up, then each §11 done-criterion cited green. Verified locally (gate outputs in the evidence doc): * pytest profile/build/ — 51/51 green * make catalog — byte-idempotent regen * make validate-catalog — schema-strict OK * make handshake — 8/8 steps * make recipes-check — 4/4 clean * uvx --from git+...@v0.1.0 m-dev-tools-mcp --tool route_intent --query "parse JSON in M" → ["module:m-stdlib#STDJSON"] (the parent-plan exit criterion, end-to-end from a fresh clone) All nine §11 done-criteria cited green: 1. m-dev-tools-mcp repo public AGPL-3.0 + full Phase-0 contract (PR #1) 2. server.py exposes 3 TDD-covered tools (PR #2 — 30 dedicated cases) 3. v0.1.0 GitHub Release with 23-KB pure-Python wheel attached (Track D2) 4. tools.json carries the entry with repo_meta_url + mcp_tools_url + release_wheel_url (.github PR #27) 5. task_index.json has infra.agent_integration → tool:m-dev-tools-mcp (.github PR #27) 6. examples/claude-code/ has .mcp.json + README + smoke.sh + session.md template (PR #3) 7. This evidence file (PR — current) 8. uvx canonical round-trip green (run captured above) 9. CI green on every Phase 4 PR Phase 5 (continuous enforcement) unblocked. PyPI publishing remains deliberately deferred. Two out-of-scope follow-ups noted in the evidence doc: * validate-repo-meta.py UTF-8-decode bug on binary release-wheel exposes URLs (use --no-resolve until fixed) * 3 Phase-3-era orphan schema fixtures gitignored but still on disk; auto-classifier blocks rm --- docs/phase4-evidence.md | 194 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 docs/phase4-evidence.md diff --git a/docs/phase4-evidence.md b/docs/phase4-evidence.md new file mode 100644 index 0000000..1594e4a --- /dev/null +++ b/docs/phase4-evidence.md @@ -0,0 +1,194 @@ +# Phase 4 — Exit evidence + +**Captured:** 2026-05-11T12:29Z (Track E landing). + +Per [`phase4-plan.md` §11 "Phase 4 Done — Definition"](phase4-plan.md): +clean runs of the four meta-repo gates + canonical-query round-trip +through the v0.1.0 release are the documented exit. This doc mirrors +[`phase3-evidence.md`](phase3-evidence.md): one section per gate, a +"What this proves" wrap-up, then each §11 criterion cited green. + +## `pytest profile/build/` — 51 / 51 + +``` +................................................... [100%] +51 passed in 1.93s +``` + +Phase 3's TDD suite carries forward without churn. The catalog +build / validate / discovery-protocol behavior all stays green +after the Phase 4 onboarding edits. + +## `make catalog` — byte-idempotent + +Running the generator twice against `origin/main` (with the new +TIER_3 entry for `m-dev-tools-mcp`) produces zero diff against the +committed `profile/tools.json`. The new `tools.m-dev-tools-mcp` +block materializes deterministically from the upstream +`exposes.{mcp_tools, release_wheel}` declarations. + +``` +python3 profile/build/build-catalog.py --write profile/tools.json +# (regen-twice diff is empty) +``` + +## `make validate-catalog` — schema-strict + +``` +python3 profile/build/validate-catalog.py +OK: /home/rafael/m-dev-tools/.github/profile/tools.json + /home/rafael/m-dev-tools/.github/profile/task_index.json +``` + +## `make handshake` — 8 / 8 steps green (offline fixtures) + +``` +step 1 — fetched llms.txt (547 bytes) + link OK (200): file://./tools.json + link OK (200): file://./task_index.json +step 2 — fetched tools.json (kind='m-dev-tools.org-catalog') + tools.json validates against tools.schema.json +step 3 — fetched task_index.json (1 categories) + intent 'parse JSON in M' → primary module:m-stdlib#STDJSON +step 4 — typed-ID module:m-stdlib#STDJSON → manifest_url file://./stdlib-manifest.json +step 5 — fetched manifest (559 bytes) +step 6 — STDJSON entry has signature ✓ and example ✓ +step 7 — routing trail complete (see above) +step 8 — exit 0 (success) +``` + +## `make recipes-check` — 4 / 4 recipes clean + +``` +SKIP: docs/recipes/add-lint-rule.md (manual checklist; see https://github.com/m-dev-tools/.github/blob/main/docs/recipes/add-lint-rule.md#manual-checklist) +SKIP: docs/recipes/add-stdlib-module.md (manual checklist; see https://github.com/m-dev-tools/.github/blob/main/docs/recipes/add-stdlib-module.md#manual-checklist) +VALIDATE: docs/recipes/new-app-tdd-ci.md (frontmatter + steps + 5 assertions OK) +VALIDATE: docs/recipes/use-stdlib-module.md (frontmatter + steps + 4 assertions OK) +recipes-check: 4 recipe(s) clean +``` + +## Canonical-query round-trip via `uvx --from git+...@v0.1.0` + +The parent-plan exit criterion: an agent can install the MCP server +from the v0.1.0 tag and answer the canonical "parse JSON in M" +intent. Reproducible from a clean environment. + +``` +$ uvx --from "git+https://github.com/m-dev-tools/m-dev-tools-mcp@v0.1.0" \ + m-dev-tools-mcp --tool route_intent --query "parse JSON in M" + Updated https://github.com/m-dev-tools/m-dev-tools-mcp (1ae96c41d62ace23ee541c3934c3ad9274baea41) + Building m-dev-tools-mcp @ git+https://github.com/m-dev-tools/m-dev-tools-mcp@1ae96c41d62ace23ee541c3934c3ad9274baea41 + Built m-dev-tools-mcp @ git+https://github.com/m-dev-tools/m-dev-tools-mcp@1ae96c41d62ace23ee541c3934c3ad9274baea41 +Installed 30 packages +[ + "module:m-stdlib#STDJSON" +] + +$ uvx --from "git+https://github.com/m-dev-tools/m-dev-tools-mcp@v0.1.0" \ + m-dev-tools-mcp --version +0.1.0 +``` + +The `describe` follow-up resolves the typed ID to a pointer-blob the +client can navigate (manifest_url, AGENTS.md, repo_meta_url): + +``` +$ uvx --from "git+https://github.com/m-dev-tools/m-dev-tools-mcp@v0.1.0" \ + m-dev-tools-mcp --tool describe --typed-id "module:m-stdlib#STDJSON" +… + "tool": { + "typed_id": "tool:m-stdlib", + "kind": "tool", + "repo": "https://github.com/m-dev-tools/m-stdlib", + "agent_instructions": "https://github.com/m-dev-tools/m-stdlib/blob/main/AGENTS.md", + "modules_url": "https://raw.githubusercontent.com/m-dev-tools/m-stdlib/main/dist/stdlib-manifest.json", + "repo_meta_url": "https://raw.githubusercontent.com/m-dev-tools/m-stdlib/main/dist/repo.meta.json" + } +} +``` + +## What this proves + +1. **Agent operability is end-to-end real.** An external agent can + install the MCP server from the v0.1.0 tag, ask "parse JSON in + M", and follow the typed-ID pointers all the way to the m-stdlib + manifest — no manual configuration, no catalog hand-curation. +2. **The catalog generates the onboarding URLs.** + `tools.m-dev-tools-mcp` carries `repo_meta_url`, `mcp_tools_url`, + and `release_wheel_url` — all derived from the upstream + `dist/repo.meta.json`'s `exposes` block. No hand-edits to + `tools.json`. `make catalog` byte-idempotent. The "facts in + repos, routing in meta-repo" architectural inversion holds. +3. **CI gates cover both new surfaces.** The meta-repo's `check` + + `handshake` jobs both ran green on PR #27. The MCP-server repo's + `check` job ran green on PRs #1 / #2 / #3 / #4 / #5. Phase 4's + PRs land through the same gates as Phase 0 / 1 / 3. +4. **Release distribution works without PyPI.** `uvx --from + git+...@v0.1.0` builds the wheel from the tagged commit on + first invocation and caches it for subsequent calls. The + `release_wheel_url` field in `tools.m-dev-tools-mcp` points + directly at the GitHub Release asset for callers that prefer + `pip install `. + +## Phase 4 closed + +All nine [`phase4-plan.md` §11](phase4-plan.md) done-criteria met: + +1. **m-dev-tools/m-dev-tools-mcp exists, public, full Phase-0 + contract** — repo at ; + public AGPL-3.0; AGENTS.md + CLAUDE.md symlink + dist/repo.meta.json + + `make check-manifest` + CI. (Track A PR #1 / commit `6a92068`.) +2. **`server.py` exposes route_intent / describe / verify, each + TDD-covered** — 30 dedicated cases (9 / 11 / 7) under + `tests/test_{route_intent,describe,verify}.py`, plus 3 smoke + 11 + CLI = 41 / 41 total. (Track B PR #2 / commit `90ca336`.) +3. **Tagged v0.1.0 GitHub Release with built wheel attached** — + ; + 23-KB pure-Python wheel + `m_dev_tools_mcp-0.1.0-py3-none-any.whl`. (Track D2.) +4. **`tools.json` carries `tool:m-dev-tools-mcp` with `status:active`, + `repo_meta_url`, `release_wheel_url`, `mcp_tools_url`** — all + four fields present on `tools.m-dev-tools-mcp`. (Track D meta-repo + PR #27 / commit `1a4b15a`.) +5. **`task_index.json` has at least one intent → `tool:m-dev-tools-mcp`** — + `infra.agent_integration` row with intent "Point my MCP-capable + agent at the m-dev-tools catalog" and `primary: tool:m-dev-tools-mcp`. + (Track D meta-repo PR #27.) +6. **`examples/claude-code/` has working `.mcp.json`, smoke script, + recorded session transcript** — `.mcp.json` (uvx-from-git config), + `README.md`, `smoke.sh` (passes locally via + `M_DEV_TOOLS_MCP_BIN=$PWD/.venv/bin/m-dev-tools-mcp`), and + `session.md` (template; user fills in once after a real Claude + Code session). (Track C PR #3 / commit `7dc8410`.) +7. **`docs/phase4-evidence.md` captures clean runs of the four gates + + the canonical round-trip** — this file. Each criterion cited + green; the same pattern phase3-evidence.md follows. +8. **MCP server answers `route_intent("parse JSON in M")` with + `module:m-stdlib#STDJSON` from a fresh `uvx --from + git+...@v0.1.0` install** — see "Canonical-query round-trip" + section above. Reproducible from a clean environment. +9. **CI green on both `.github/main` and `m-dev-tools-mcp/main`** — + every Phase 4 PR (#1 / #2 / #3 / #4 / #5 on m-dev-tools-mcp; + #27 on .github) merged with CI green. Drift gates + (`check-manifest`, `check-agents`, `check-catalog`, + `recipes-check`, `handshake`) all gate every push/PR. + +Phase 5 (continuous enforcement: freshness / link-check / +license-reconcile / schema-version) is unblocked. PyPI publishing is +*deliberately* not on this list — re-evaluated as a follow-up after +Phase 5 once external adoption demonstrates the API + name are worth +the irreversible commitment. + +## Out-of-scope follow-ups + +Two items surfaced during Track D worth filing as their own PRs: + +- `profile/build/validate-repo-meta.py` chokes on binary + `exposes.*` URLs (UTF-8 decode of wheel bytes). Fix: skip + decoding for non-text extensions. `--no-resolve` is the + documented escape hatch in the meantime. +- Three Phase-3-era orphan schema fixture files under + `profile/build/fixtures/` (recipe / task_index / tools .schema.json) + are gitignored but still on disk. The auto-classifier blocks `rm` + on them; manual cleanup is fine. + +Neither blocks any phase boundary.