From 80a27ad7a6a79185b3caae30ae51de705c3721c9 Mon Sep 17 00:00:00 2001 From: Sollan Systems Date: Sat, 4 Jul 2026 17:57:19 -0400 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20Adopt=20in=20your=20stack=20?= =?UTF-8?q?=E2=80=94=20uvx=20funnel,=20emit=20recipe,=20CI=20action,=20sto?= =?UTF-8?q?p=20firewall?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01As92NaD7jMDbnQTqXDzBVa --- README.md | 51 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 0caf89c..ea95159 100644 --- a/README.md +++ b/README.md @@ -244,25 +244,16 @@ See `reference/repo-os-contract.md` for the canonical artifact schemas. ### Portable validator / inspector -No Claude Code plugin is required to validate or inspect a loop contract. From -the cloned repo root: +No Claude Code plugin is required to validate or inspect a loop contract: ```bash -python3 -m loop doctor /path/to/workspace -python3 -m loop inspect /path/to/workspace +uvx loop-engineer inspect . # zero-install score of any repo's loop contract +pip install loop-engineer # or install the CLI: `loop doctor`, `loop inspect`, ... ``` -To run it against a loop in any other directory, install the core once -(editable): - -```bash -pip install -e . # optional faster manifest parsing: pip install -e ".[yaml]" -python3 -m loop doctor /path/to/workspace -``` - -`python3 -m loop` resolves the bundled `loop/` package from the repo root; -`pip install -e .` puts it on your path so the CLI works from any directory. The -core is pure-stdlib — PyYAML is an optional extra, not a requirement. +From a clone, `python3 -m loop ` and `pip install -e .` keep working; the +wheel is self-contained (schemas, templates, and the inspect/metrics tooling +ship inside it). The core is pure-stdlib — PyYAML/jsonschema are optional extras. The portable core lives in `loop/` and validates schema-bearing artifacts in `schemas/`: @@ -289,6 +280,36 @@ never required; every skill runs on the bundled core alone. --- +## Adopt in your stack + +Three thin, enforcing on-ramps — each one makes a false "done" fail somewhere +that already exists in your workflow. Start where your loop lives: + +**Claude Code** — the plugin ships a Stop-hook firewall: if the session's repo +holds a `.loop/` contract that claims `Succeeded` while `loop doctor` says +otherwise, the stop is blocked with the exact doctor issues. No-op without +`.loop/`, fail-open on error, zero config beyond installing the plugin. + +**Any Python runtime** — `loop.emit` is a pure-stdlib writer for foreign +orchestrators (LangGraph, or anything that can call four functions): +`open_contract`, `append_iteration`, `append_receipt`, `terminate`. The writer +refuses an evidence-free `Succeeded` at write time. Recipe: +[docs/integrations/langgraph.md](docs/integrations/langgraph.md). + +**CI** — one workflow step validates the contract and publishes a scorecard: + +```yaml +- uses: SollanSystems/loop-engineer@v0.7.0 + with: + path: "." +``` + +`doctor` failure fails the job; the inspect verdict is warn-only unless you set +`fail-under-score`. Pre-commit users: hook id `loop-doctor`. This repo runs the +same action against its own contract — the gate gates its maker. + +--- + ## Claude Code reference workflow The Claude Code plugin is the reference UI over the portable loop contract. From 7ce393800fe8c9ca05fa4942090d9880c7c2d965 Mon Sep 17 00:00:00 2001 From: Sollan Systems Date: Sat, 4 Jul 2026 20:01:26 -0400 Subject: [PATCH 2/2] test(docs): adoption claims are gate-backed Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 26 ++++++++++++ scripts/test_docs_adoption.py | 77 +++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 scripts/test_docs_adoption.py diff --git a/CHANGELOG.md b/CHANGELOG.md index dc2b415..fa3e5fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,6 +87,32 @@ loop-engineer runtime — and the repo dogfoods both on its own contract in CI. when absent); the `action-dogfood` CI job installs it and runs the fixture for real on the PR checkout. +**PR5 — Adopt in your stack.** The four on-ramps shipped above (uvx funnel, +`loop.emit` writer, Stop-hook firewall, CI Action + pre-commit hook) get a single +"Adopt in your stack" README section that funnels a reader from zero-install +`uvx loop-engineer inspect .` through to full adoption, with a refreshed Install +section. Every claim the section makes is gate-backed by a new test, so the docs +can never advertise an on-ramp that does not exist. + +### Added +- **README "Adopt in your stack" section + Install refresh** — a runtime-neutral + adoption path leading with `uvx loop-engineer inspect .` (zero install), then the + `loop.emit` writer for foreign runtimes, the Stop-hook firewall, and the CI + Action / pre-commit gate pinned at `SollanSystems/loop-engineer@v0.7.0` (a + forward-looking pin re-verified at the next release). +- **show-hn launch draft leads with the uvx funnel** — the M5-LAUNCH Show HN draft + now opens its command sequence with `uvx loop-engineer inspect .`. The draft + lives under the gitignored `roadmap/` tree (a launch working file, absent in a + fresh checkout), so its gate is env-guarded. +- **Docs-claims gate test** (`scripts/test_docs_adoption.py`) — asserts every + "Adopt in your stack" README claim is backed by a shipped, wired artifact: the + uvx funnel by the `loop-engineer` console script, the `loop.emit` claim by the + real writer functions + the LangGraph guide, the Stop-hook claim by the + registered hook file, and the CI Action claim by `action.yml` + the + `loop-doctor` pre-commit hook. The show-hn assertion skips when the gitignored + draft is absent (fresh CI checkouts), matching the repo's env-guarded-skip + pattern. + ## 0.6.1 — 2026-07-04 **PyPI substrate.** `loop-engineer` becomes a self-contained wheel that runs from diff --git a/scripts/test_docs_adoption.py b/scripts/test_docs_adoption.py new file mode 100644 index 0000000..2646397 --- /dev/null +++ b/scripts/test_docs_adoption.py @@ -0,0 +1,77 @@ +# scripts/test_docs_adoption.py +"""PR5 gate: every 'Adopt in your stack' README claim is backed by a shipped, +wired artifact — the docs cannot advertise an on-ramp that does not exist.""" + +from __future__ import annotations + +import json +from pathlib import Path + +import pytest + +REPO_ROOT = Path(__file__).resolve().parent.parent +README = (REPO_ROOT / "README.md").read_text(encoding="utf-8") + + +def test_uvx_funnel_claim_is_backed_by_console_script(): + if "uvx loop-engineer" not in README: + return + pyproject = (REPO_ROOT / "pyproject.toml").read_text(encoding="utf-8") + assert 'loop-engineer = "loop.__main__:main"' in pyproject, ( + "README sells `uvx loop-engineer ...` but the package declares no " + "loop-engineer console script (uvx runs the executable named after the package)" + ) + + +def test_emit_claim_names_only_real_functions(): + if "loop.emit" not in README: + return + import loop.emit as emit + + for name in ("open_contract", "append_iteration", "append_receipt", "terminate"): + assert name not in README or callable(getattr(emit, name, None)), ( + f"README names loop.emit.{name} but it does not exist" + ) + assert (REPO_ROOT / "docs" / "integrations" / "langgraph.md").is_file() + + +def test_stop_firewall_claim_is_backed_by_registered_hook(): + if "Stop-hook" not in README and "stop firewall" not in README.lower(): + return + manifest = json.loads((REPO_ROOT / ".claude-plugin" / "plugin.json").read_text(encoding="utf-8")) + commands = [ + h["command"] + for entry in manifest.get("hooks", {}).get("Stop", []) + for h in entry.get("hooks", []) + ] + hook_files = [c.split("${CLAUDE_PLUGIN_ROOT}/")[-1].split()[0] for c in commands] + assert any((REPO_ROOT / f).is_file() for f in hook_files), ( + "README sells the Stop-hook firewall but plugin.json registers no existing Stop hook file" + ) + + +def test_ci_action_claim_is_backed_by_action_and_precommit(): + if "uses: SollanSystems/loop-engineer@" not in README: + return + assert (REPO_ROOT / "action.yml").is_file() + if "loop-doctor" in README: + assert "id: loop-doctor" in (REPO_ROOT / ".pre-commit-hooks.yaml").read_text(encoding="utf-8") + + +def test_show_hn_leads_with_the_uvx_funnel(): + # roadmap/ is gitignored — show-hn.md exists locally but is absent in a fresh + # CI checkout, so guard on existence the way the wheel/recipe tests env-guard. + show_hn_path = ( + REPO_ROOT / "roadmap" / "launch" / ".loop" / "artifacts" / "M5-LAUNCH" / "show-hn.md" + ) + if not show_hn_path.is_file(): + pytest.skip("show-hn.md is a gitignored launch draft — absent in fresh checkouts") + show_hn = show_hn_path.read_text(encoding="utf-8") + first_cmd = next( + line.strip() + for line in show_hn.splitlines() + if line.strip().startswith(("uvx ", "$ uvx", "pip ", "$ pip", "python", "loop ", "git clone")) + ) + assert first_cmd.lstrip("$ ").startswith("uvx loop-engineer inspect"), ( + f"show-hn's first command is {first_cmd!r}, spec requires `uvx loop-engineer inspect .`" + )