From 674c739d71c31fa02af3598f44e934afeb5fbbe5 Mon Sep 17 00:00:00 2001 From: Pengfei Hu Date: Tue, 2 Jun 2026 18:04:25 -0700 Subject: [PATCH 1/2] Pin bundled install snippets to zero-install uvx/pipx run The bundled adoption-kit/skill install steps recommended a bare `pipx install agents-shipgate`, which is a no-op when an older build is already on PATH. A coding agent could then silently run a stale release (we have seen 0.8.0) that has no `verify` subcommand and writes no verifier.json, breaking the merge gate. Lead the install/quickstart steps with a pinned, zero-install runner (`uvx agents-shipgate@0.11.0` / `pipx run agents-shipgate==0.11.0`) that fetches the exact version regardless of any global install, and make the remaining pip/pipx install fallback assert `>=0.11.0` and fail loudly. Applied across the 3 byte-identical copies of add-shipgate-to-repo.md and decide-shipgate-relevance.md (prompts/, skills/, adoption-kits/); render-hash snapshot bumped and outgoing hashes appended to prior_render_sha256 (bootstrap_legacy untouched). Pin literals equal the pyproject version (0.11.0). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../.agents-shipgate-kit-metadata.json | 6 +++++- .../prompts/add-shipgate-to-repo.md | 14 ++++++++++---- .../prompts/decide-shipgate-relevance.md | 10 ++++++---- prompts/add-shipgate-to-repo.md | 14 ++++++++++---- prompts/decide-shipgate-relevance.md | 10 ++++++---- .../prompts/add-shipgate-to-repo.md | 14 ++++++++++---- .../prompts/decide-shipgate-relevance.md | 10 ++++++---- tests/test_agent_instructions_renderers.py | 4 ++-- 8 files changed, 55 insertions(+), 27 deletions(-) diff --git a/adoption-kits/claude-code-skill/.agents-shipgate-kit-metadata.json b/adoption-kits/claude-code-skill/.agents-shipgate-kit-metadata.json index ca3744e..ef0465f 100644 --- a/adoption-kits/claude-code-skill/.agents-shipgate-kit-metadata.json +++ b/adoption-kits/claude-code-skill/.agents-shipgate-kit-metadata.json @@ -10,7 +10,11 @@ "bd4755e06715c839608c09da302ed844c764fd3e4047d7bdf495d68dc559c2a5" ], "prompts/add-shipgate-to-repo.md": [ - "c67aa56813d76ddafd4091b2120d914fab6e0590b46e3598d856b7c4e6443fb1" + "c67aa56813d76ddafd4091b2120d914fab6e0590b46e3598d856b7c4e6443fb1", + "ea3c37cfbbd42c40d164abfe21d468a3a5550d5384125f94a53c947dea6b4b2a" + ], + "prompts/decide-shipgate-relevance.md": [ + "9cf6fdf60f45032635482ff96c64684af5f84ef9c10977e6d36e7d1c856d07e9" ], "prompts/stabilize-strict-mode.md": [ "ac9a176738ab2538d725c29ba302637bac6b287588e07d952aae352f85ab98cc" diff --git a/adoption-kits/claude-code-skill/prompts/add-shipgate-to-repo.md b/adoption-kits/claude-code-skill/prompts/add-shipgate-to-repo.md index e1f5c65..8cd6105 100644 --- a/adoption-kits/claude-code-skill/prompts/add-shipgate-to-repo.md +++ b/adoption-kits/claude-code-skill/prompts/add-shipgate-to-repo.md @@ -9,12 +9,18 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. ## Your task -1. **Install the tool** — you need `>=0.11.0`, since the `agents-shipgate verify` step this prompt relies on only ships in 0.11.0+: +1. **Install the tool — pin the version so a stale build can't shadow it.** This flow drives `agents-shipgate verify`, which only ships in **`>=0.11.0`**; an older copy lingering on `PATH` (we have seen `0.8.0`) has no `verify` subcommand and writes no `verifier.json`, so it silently breaks the gate. Prefer a **pinned, zero-install** runner that fetches the exact version every time instead of trusting whatever is already on `PATH`: ```bash - pipx install agents-shipgate - pipx upgrade agents-shipgate + uvx agents-shipgate@0.11.0 --version # uv: ephemeral, always the pinned build + pipx run agents-shipgate==0.11.0 --version # pipx equivalent + ``` + Run every `agents-shipgate …` step below through that same runner (`uvx agents-shipgate@0.11.0 …` / `pipx run agents-shipgate==0.11.0 …`) so no stale global install can shadow it. + + If you instead install onto `PATH`, pin the floor and **fail loudly when it resolves older** — a plain `pipx install agents-shipgate` is a no-op when an older build already exists: + ```bash + python -m pip install -U "agents-shipgate>=0.11.0" # or: pipx install "agents-shipgate>=0.11.0" + agents-shipgate --version # STOP if this prints < 0.11.0 — re-run pinned via uvx agents-shipgate@0.11.0 ``` - A plain `pipx install` is a no-op when an older build is already installed, so the follow-up `pipx upgrade` brings a stale copy current. If `pipx` is unavailable, use `python -m pip install -U "agents-shipgate>=0.11"` and verify with `agents-shipgate --version`. 2. **Sanity-check the install** before touching the user's code: ```bash diff --git a/adoption-kits/claude-code-skill/prompts/decide-shipgate-relevance.md b/adoption-kits/claude-code-skill/prompts/decide-shipgate-relevance.md index 87991ec..a36662f 100644 --- a/adoption-kits/claude-code-skill/prompts/decide-shipgate-relevance.md +++ b/adoption-kits/claude-code-skill/prompts/decide-shipgate-relevance.md @@ -75,10 +75,12 @@ the rules to the changed file list. ``` Then follow [`prompts/add-shipgate-to-repo.md`](https://github.com/ThreeMoonsLab/agents-shipgate/blob/main/prompts/add-shipgate-to-repo.md) for the first-adoption helper flow. - - If `run_shipgate: true` and Shipgate is **not** installed: install - it (`pipx install agents-shipgate`) and run `detect`. If the user - prefers a zero-install first step, point them at the GitHub Action - (`ThreeMoonsLab/agents-shipgate@v0.11.0`) instead. + - If `run_shipgate: true` and Shipgate is **not** installed: run it + version-pinned and zero-install so a stale global build can't shadow + it — `uvx agents-shipgate@0.11.0 detect --workspace . --json` (or + `pipx run agents-shipgate==0.11.0 …`). If the user prefers CI, point + them at the GitHub Action (`ThreeMoonsLab/agents-shipgate@v0.11.0`) + instead. - If `run_shipgate: false` and `dry_run_recommended: true`: propose a non-mutating scan only — never propose `init --write` based on a dry-run match alone. Phrase it as "X may have shifted the tool diff --git a/prompts/add-shipgate-to-repo.md b/prompts/add-shipgate-to-repo.md index e1f5c65..8cd6105 100644 --- a/prompts/add-shipgate-to-repo.md +++ b/prompts/add-shipgate-to-repo.md @@ -9,12 +9,18 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. ## Your task -1. **Install the tool** — you need `>=0.11.0`, since the `agents-shipgate verify` step this prompt relies on only ships in 0.11.0+: +1. **Install the tool — pin the version so a stale build can't shadow it.** This flow drives `agents-shipgate verify`, which only ships in **`>=0.11.0`**; an older copy lingering on `PATH` (we have seen `0.8.0`) has no `verify` subcommand and writes no `verifier.json`, so it silently breaks the gate. Prefer a **pinned, zero-install** runner that fetches the exact version every time instead of trusting whatever is already on `PATH`: ```bash - pipx install agents-shipgate - pipx upgrade agents-shipgate + uvx agents-shipgate@0.11.0 --version # uv: ephemeral, always the pinned build + pipx run agents-shipgate==0.11.0 --version # pipx equivalent + ``` + Run every `agents-shipgate …` step below through that same runner (`uvx agents-shipgate@0.11.0 …` / `pipx run agents-shipgate==0.11.0 …`) so no stale global install can shadow it. + + If you instead install onto `PATH`, pin the floor and **fail loudly when it resolves older** — a plain `pipx install agents-shipgate` is a no-op when an older build already exists: + ```bash + python -m pip install -U "agents-shipgate>=0.11.0" # or: pipx install "agents-shipgate>=0.11.0" + agents-shipgate --version # STOP if this prints < 0.11.0 — re-run pinned via uvx agents-shipgate@0.11.0 ``` - A plain `pipx install` is a no-op when an older build is already installed, so the follow-up `pipx upgrade` brings a stale copy current. If `pipx` is unavailable, use `python -m pip install -U "agents-shipgate>=0.11"` and verify with `agents-shipgate --version`. 2. **Sanity-check the install** before touching the user's code: ```bash diff --git a/prompts/decide-shipgate-relevance.md b/prompts/decide-shipgate-relevance.md index 87991ec..a36662f 100644 --- a/prompts/decide-shipgate-relevance.md +++ b/prompts/decide-shipgate-relevance.md @@ -75,10 +75,12 @@ the rules to the changed file list. ``` Then follow [`prompts/add-shipgate-to-repo.md`](https://github.com/ThreeMoonsLab/agents-shipgate/blob/main/prompts/add-shipgate-to-repo.md) for the first-adoption helper flow. - - If `run_shipgate: true` and Shipgate is **not** installed: install - it (`pipx install agents-shipgate`) and run `detect`. If the user - prefers a zero-install first step, point them at the GitHub Action - (`ThreeMoonsLab/agents-shipgate@v0.11.0`) instead. + - If `run_shipgate: true` and Shipgate is **not** installed: run it + version-pinned and zero-install so a stale global build can't shadow + it — `uvx agents-shipgate@0.11.0 detect --workspace . --json` (or + `pipx run agents-shipgate==0.11.0 …`). If the user prefers CI, point + them at the GitHub Action (`ThreeMoonsLab/agents-shipgate@v0.11.0`) + instead. - If `run_shipgate: false` and `dry_run_recommended: true`: propose a non-mutating scan only — never propose `init --write` based on a dry-run match alone. Phrase it as "X may have shifted the tool diff --git a/skills/agents-shipgate/prompts/add-shipgate-to-repo.md b/skills/agents-shipgate/prompts/add-shipgate-to-repo.md index e1f5c65..8cd6105 100644 --- a/skills/agents-shipgate/prompts/add-shipgate-to-repo.md +++ b/skills/agents-shipgate/prompts/add-shipgate-to-repo.md @@ -9,12 +9,18 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. ## Your task -1. **Install the tool** — you need `>=0.11.0`, since the `agents-shipgate verify` step this prompt relies on only ships in 0.11.0+: +1. **Install the tool — pin the version so a stale build can't shadow it.** This flow drives `agents-shipgate verify`, which only ships in **`>=0.11.0`**; an older copy lingering on `PATH` (we have seen `0.8.0`) has no `verify` subcommand and writes no `verifier.json`, so it silently breaks the gate. Prefer a **pinned, zero-install** runner that fetches the exact version every time instead of trusting whatever is already on `PATH`: ```bash - pipx install agents-shipgate - pipx upgrade agents-shipgate + uvx agents-shipgate@0.11.0 --version # uv: ephemeral, always the pinned build + pipx run agents-shipgate==0.11.0 --version # pipx equivalent + ``` + Run every `agents-shipgate …` step below through that same runner (`uvx agents-shipgate@0.11.0 …` / `pipx run agents-shipgate==0.11.0 …`) so no stale global install can shadow it. + + If you instead install onto `PATH`, pin the floor and **fail loudly when it resolves older** — a plain `pipx install agents-shipgate` is a no-op when an older build already exists: + ```bash + python -m pip install -U "agents-shipgate>=0.11.0" # or: pipx install "agents-shipgate>=0.11.0" + agents-shipgate --version # STOP if this prints < 0.11.0 — re-run pinned via uvx agents-shipgate@0.11.0 ``` - A plain `pipx install` is a no-op when an older build is already installed, so the follow-up `pipx upgrade` brings a stale copy current. If `pipx` is unavailable, use `python -m pip install -U "agents-shipgate>=0.11"` and verify with `agents-shipgate --version`. 2. **Sanity-check the install** before touching the user's code: ```bash diff --git a/skills/agents-shipgate/prompts/decide-shipgate-relevance.md b/skills/agents-shipgate/prompts/decide-shipgate-relevance.md index 87991ec..a36662f 100644 --- a/skills/agents-shipgate/prompts/decide-shipgate-relevance.md +++ b/skills/agents-shipgate/prompts/decide-shipgate-relevance.md @@ -75,10 +75,12 @@ the rules to the changed file list. ``` Then follow [`prompts/add-shipgate-to-repo.md`](https://github.com/ThreeMoonsLab/agents-shipgate/blob/main/prompts/add-shipgate-to-repo.md) for the first-adoption helper flow. - - If `run_shipgate: true` and Shipgate is **not** installed: install - it (`pipx install agents-shipgate`) and run `detect`. If the user - prefers a zero-install first step, point them at the GitHub Action - (`ThreeMoonsLab/agents-shipgate@v0.11.0`) instead. + - If `run_shipgate: true` and Shipgate is **not** installed: run it + version-pinned and zero-install so a stale global build can't shadow + it — `uvx agents-shipgate@0.11.0 detect --workspace . --json` (or + `pipx run agents-shipgate==0.11.0 …`). If the user prefers CI, point + them at the GitHub Action (`ThreeMoonsLab/agents-shipgate@v0.11.0`) + instead. - If `run_shipgate: false` and `dry_run_recommended: true`: propose a non-mutating scan only — never propose `init --write` based on a dry-run match alone. Phrase it as "X may have shifted the tool diff --git a/tests/test_agent_instructions_renderers.py b/tests/test_agent_instructions_renderers.py index 03e77cd..6581842 100644 --- a/tests/test_agent_instructions_renderers.py +++ b/tests/test_agent_instructions_renderers.py @@ -43,10 +43,10 @@ "b442316b7bbdb4b2a84b8543f3589e1bb1d8d2bfd968637db99bd07835c406fd" ), ".claude/skills/agents-shipgate/prompts/add-shipgate-to-repo.md": ( - "ea3c37cfbbd42c40d164abfe21d468a3a5550d5384125f94a53c947dea6b4b2a" + "d6b9944dc7849aa7827fd8138e72b0720674944a313c9351e9afe94aa3bfc794" ), ".claude/skills/agents-shipgate/prompts/decide-shipgate-relevance.md": ( - "9cf6fdf60f45032635482ff96c64684af5f84ef9c10977e6d36e7d1c856d07e9" + "7d92c6e1466825a4550c6b1259efccfbeb4dd35eb9e27b1d29de5421515bac2c" ), ".claude/skills/agents-shipgate/prompts/explain-finding-to-user.md": ( "18031ed870b3c937a2996173820639ef441afe0a45e8171f16468826cd389829" From 61cde78b74344b0b01340c78ec0f3720d0d12b31 Mon Sep 17 00:00:00 2001 From: Pengfei Hu Date: Tue, 2 Jun 2026 21:09:44 -0700 Subject: [PATCH 2/2] Use the pinned runner for every command, not just --version Address PR review feedback: - add-shipgate-to-repo.md: define one pinned runner variable in step 1 (SG="uvx agents-shipgate@0.11.0" / "pipx run agents-shipgate==0.11.0") and route every command block through $SG, so copying the prompt verbatim can't fall through to a stale PATH binary. The install-onto- PATH fallback sets SG=agents-shipgate only after the version floor is confirmed. - decide-shipgate-relevance.md: the decision flow now always runs detect through the pinned runner; a bare `agents-shipgate detect` is gated on `agents-shipgate --version` confirming >=0.11.0, closing the path where a stale installed 0.8.0 answered unguarded. - test_public_surface_contract.py: add UVX_PIN_PATTERN + test_uvx_pins_match_pyproject_version so `uvx agents-shipgate@X.Y.Z` literals can't go stale on a pyproject bump, and add decide-shipgate-relevance.md (prompts/ + skills/) to ACTION_PIN_FILES. Re-synced all 3 byte-identical copies and bumped the render-hash snapshot. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../prompts/add-shipgate-to-repo.md | 32 ++++++++++--------- .../prompts/decide-shipgate-relevance.md | 21 ++++++------ prompts/add-shipgate-to-repo.md | 32 ++++++++++--------- prompts/decide-shipgate-relevance.md | 21 ++++++------ .../prompts/add-shipgate-to-repo.md | 32 ++++++++++--------- .../prompts/decide-shipgate-relevance.md | 21 ++++++------ tests/test_agent_instructions_renderers.py | 4 +-- tests/test_public_surface_contract.py | 29 +++++++++++++++++ 8 files changed, 109 insertions(+), 83 deletions(-) diff --git a/adoption-kits/claude-code-skill/prompts/add-shipgate-to-repo.md b/adoption-kits/claude-code-skill/prompts/add-shipgate-to-repo.md index 8cd6105..1202507 100644 --- a/adoption-kits/claude-code-skill/prompts/add-shipgate-to-repo.md +++ b/adoption-kits/claude-code-skill/prompts/add-shipgate-to-repo.md @@ -9,28 +9,30 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. ## Your task -1. **Install the tool — pin the version so a stale build can't shadow it.** This flow drives `agents-shipgate verify`, which only ships in **`>=0.11.0`**; an older copy lingering on `PATH` (we have seen `0.8.0`) has no `verify` subcommand and writes no `verifier.json`, so it silently breaks the gate. Prefer a **pinned, zero-install** runner that fetches the exact version every time instead of trusting whatever is already on `PATH`: +1. **Install the tool — pin the version so a stale build can't shadow it.** This flow drives `agents-shipgate verify`, which only ships in **`>=0.11.0`**; an older copy lingering on `PATH` (we have seen `0.8.0`) has no `verify` subcommand and writes no `verifier.json`, so it silently breaks the gate. Prefer a **pinned, zero-install** runner that fetches the exact version every time instead of trusting whatever is already on `PATH`. **Pin it into one variable and use that for every step below**, so no single command can fall through to a stale binary: ```bash - uvx agents-shipgate@0.11.0 --version # uv: ephemeral, always the pinned build - pipx run agents-shipgate==0.11.0 --version # pipx equivalent + SG="uvx agents-shipgate@0.11.0" # uv: ephemeral, always the pinned build + # or: SG="pipx run agents-shipgate==0.11.0" + $SG --version # confirm the pinned runner resolves ``` - Run every `agents-shipgate …` step below through that same runner (`uvx agents-shipgate@0.11.0 …` / `pipx run agents-shipgate==0.11.0 …`) so no stale global install can shadow it. + Every step below calls `$SG …`; e.g. `$SG detect …` runs `agents-shipgate detect` through the pinned runner, never a `PATH` copy. - If you instead install onto `PATH`, pin the floor and **fail loudly when it resolves older** — a plain `pipx install agents-shipgate` is a no-op when an older build already exists: + If you would rather install onto `PATH`, pin the floor and **fail loudly when it resolves older** — a plain `pipx install agents-shipgate` is a no-op when an older build already exists — then set `SG=agents-shipgate`: ```bash python -m pip install -U "agents-shipgate>=0.11.0" # or: pipx install "agents-shipgate>=0.11.0" agents-shipgate --version # STOP if this prints < 0.11.0 — re-run pinned via uvx agents-shipgate@0.11.0 + SG=agents-shipgate # only after the line above confirms >=0.11.0 ``` 2. **Sanity-check the install** before touching the user's code: ```bash - agents-shipgate self-check --json + $SG self-check --json ``` Confirm `"ready": true`. If not, surface the failure to the user. When available, verify the installed CLI contract locally: ```bash - agents-shipgate contract --json + $SG contract --json ``` Read `report_schema_version`, `packet_schema_version`, `gating_signal`, and `manual_review_signals[]`; prefer these local values over stale docs. If the @@ -40,7 +42,7 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. 3. **Detect:** ```bash - agents-shipgate detect --workspace . --json + $SG detect --workspace . --json ``` Read the response: `is_agent_project`, `frameworks[]` (per-framework score + evidence + candidate files), `agent_name_candidates[]`, `suggested_sources[]` (MCP/OpenAPI files matched by glob). @@ -48,7 +50,7 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. 4. **Generate a starter manifest + GitHub Actions workflow:** ```bash - agents-shipgate init --workspace . --write --ci --json + $SG init --workspace . --write --ci --json ``` The `--json` form returns: - `manifest_status`: `"written"` | `"skipped_existing"` | `"not_attempted"` @@ -66,7 +68,7 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. 6. **Run the scan with patch suggestions:** ```bash - agents-shipgate scan -c shipgate.yaml --suggest-patches --format json --ci-mode advisory + $SG scan -c shipgate.yaml --suggest-patches --format json --ci-mode advisory ``` The report lands at `agents-shipgate-reports/report.json`. The Release Evidence Packet lands at `agents-shipgate-reports/packet.{md,json,html}`. Parse `report.json`; Codex plugin facts, when present, live under `codex_plugin_surface`. @@ -86,7 +88,7 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. 7. **Apply the safe patches:** ```bash - agents-shipgate apply-patches --from agents-shipgate-reports/report.json --confidence high --apply --json + $SG apply-patches --from agents-shipgate-reports/report.json --confidence high --apply --json ``` Default `--confidence high` only mutates patches whose `confidence` field is `"high"`. Today that's the 3 stale-manifest removals. Scope-coverage appends ship at `medium` and require explicit `--confidence medium` to apply. ManualPatches are never auto-applied. @@ -112,17 +114,17 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. - The path to the Release Evidence Packet (`agents-shipgate-reports/packet.md`) for reviewer-shaped output - The top 3 active critical/high findings (use `report.json`, not stdout) - Which patches were applied (count from `apply-patches --json` output's `files`) - - Any check IDs the user should investigate first — link to `docs_url` from the finding for full rationale, or use `agents-shipgate explain --json` for the same content via CLI + - Any check IDs the user should investigate first — link to `docs_url` from the finding for full rationale, or use `$SG explain --json` for the same content via CLI ## What to do if the scan errors out -Set `AGENTS_SHIPGATE_AGENT_MODE=1` and re-run. The CLI will append a JSON line to stderr with `{error, message, next_action}`. Follow the `next_action`. +Re-run the failing `$SG …` command with `AGENTS_SHIPGATE_AGENT_MODE=1` set. The CLI will append a JSON line to stderr with `{error, message, next_action}`. Follow the `next_action`. Common errors and fixes: | Error | Fix | |---|---| -| `Config file not found: shipgate.yaml` | Run `agents-shipgate init --workspace . --write` first | +| `Config file not found: shipgate.yaml` | Run `$SG init --workspace . --write` first | | `Input path '...' resolves outside manifest directory` | The declared `tool_sources[].path` is outside the manifest dir. Move the spec inside the tree, symlink it, or copy it | | `Invalid shipgate.yaml: ... Did you mean X?` | A field is at the wrong nesting level; move it as suggested | | `Containment violation` (apply-patches exit 5) | A patch's `target_file` resolved outside `report.manifest_dir`. Re-run scan to refresh; never patch arbitrary system files | @@ -130,7 +132,7 @@ Common errors and fixes: ## What NOT to do - Do **not** commit `agents-shipgate-reports/` — it's regenerated each run. -- Do **not** run `agents-shipgate baseline save` until the user has reviewed the initial findings. Baselining ratchets in noise that strict CI will silently ignore. The right time to baseline is **after** the user has decided which findings they accept. +- Do **not** run `$SG baseline save` until the user has reviewed the initial findings. Baselining ratchets in noise that strict CI will silently ignore. The right time to baseline is **after** the user has decided which findings they accept. - Do **not** suppress findings without a real `reason` — the manifest validator rejects empty reasons, and the `reason` field is the audit trail when someone asks "why is this OK?" - Do **not** use `risk_overrides.tools.{tool}.remove_tags` to silence a finding without checking whether the heuristic is actually wrong. Prefer `checks.ignore` with a reason. - Do **not** edit a trace recording to flip `approved` or `confirmed` — implement the runtime gate instead. diff --git a/adoption-kits/claude-code-skill/prompts/decide-shipgate-relevance.md b/adoption-kits/claude-code-skill/prompts/decide-shipgate-relevance.md index a36662f..a1ea9bc 100644 --- a/adoption-kits/claude-code-skill/prompts/decide-shipgate-relevance.md +++ b/adoption-kits/claude-code-skill/prompts/decide-shipgate-relevance.md @@ -69,18 +69,15 @@ the rules to the changed file list. ``` 5. **Then act.** - - If `run_shipgate: true` and Shipgate is installed: - ```bash - agents-shipgate detect --workspace . --json - ``` - Then follow [`prompts/add-shipgate-to-repo.md`](https://github.com/ThreeMoonsLab/agents-shipgate/blob/main/prompts/add-shipgate-to-repo.md) - for the first-adoption helper flow. - - If `run_shipgate: true` and Shipgate is **not** installed: run it - version-pinned and zero-install so a stale global build can't shadow - it — `uvx agents-shipgate@0.11.0 detect --workspace . --json` (or - `pipx run agents-shipgate==0.11.0 …`). If the user prefers CI, point - them at the GitHub Action (`ThreeMoonsLab/agents-shipgate@v0.11.0`) - instead. + - If `run_shipgate: true`: run `detect` through a **version-pinned, + zero-install** runner so a stale copy already on `PATH` can't answer — + `uvx agents-shipgate@0.11.0 detect --workspace . --json` (or + `pipx run agents-shipgate==0.11.0 …`). Only fall back to a bare + `agents-shipgate detect` once `agents-shipgate --version` confirms + `>=0.11.0`. Then follow + [`prompts/add-shipgate-to-repo.md`](https://github.com/ThreeMoonsLab/agents-shipgate/blob/main/prompts/add-shipgate-to-repo.md) + for the first-adoption helper flow, or point the user at the GitHub + Action (`ThreeMoonsLab/agents-shipgate@v0.11.0`) if they prefer CI. - If `run_shipgate: false` and `dry_run_recommended: true`: propose a non-mutating scan only — never propose `init --write` based on a dry-run match alone. Phrase it as "X may have shifted the tool diff --git a/prompts/add-shipgate-to-repo.md b/prompts/add-shipgate-to-repo.md index 8cd6105..1202507 100644 --- a/prompts/add-shipgate-to-repo.md +++ b/prompts/add-shipgate-to-repo.md @@ -9,28 +9,30 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. ## Your task -1. **Install the tool — pin the version so a stale build can't shadow it.** This flow drives `agents-shipgate verify`, which only ships in **`>=0.11.0`**; an older copy lingering on `PATH` (we have seen `0.8.0`) has no `verify` subcommand and writes no `verifier.json`, so it silently breaks the gate. Prefer a **pinned, zero-install** runner that fetches the exact version every time instead of trusting whatever is already on `PATH`: +1. **Install the tool — pin the version so a stale build can't shadow it.** This flow drives `agents-shipgate verify`, which only ships in **`>=0.11.0`**; an older copy lingering on `PATH` (we have seen `0.8.0`) has no `verify` subcommand and writes no `verifier.json`, so it silently breaks the gate. Prefer a **pinned, zero-install** runner that fetches the exact version every time instead of trusting whatever is already on `PATH`. **Pin it into one variable and use that for every step below**, so no single command can fall through to a stale binary: ```bash - uvx agents-shipgate@0.11.0 --version # uv: ephemeral, always the pinned build - pipx run agents-shipgate==0.11.0 --version # pipx equivalent + SG="uvx agents-shipgate@0.11.0" # uv: ephemeral, always the pinned build + # or: SG="pipx run agents-shipgate==0.11.0" + $SG --version # confirm the pinned runner resolves ``` - Run every `agents-shipgate …` step below through that same runner (`uvx agents-shipgate@0.11.0 …` / `pipx run agents-shipgate==0.11.0 …`) so no stale global install can shadow it. + Every step below calls `$SG …`; e.g. `$SG detect …` runs `agents-shipgate detect` through the pinned runner, never a `PATH` copy. - If you instead install onto `PATH`, pin the floor and **fail loudly when it resolves older** — a plain `pipx install agents-shipgate` is a no-op when an older build already exists: + If you would rather install onto `PATH`, pin the floor and **fail loudly when it resolves older** — a plain `pipx install agents-shipgate` is a no-op when an older build already exists — then set `SG=agents-shipgate`: ```bash python -m pip install -U "agents-shipgate>=0.11.0" # or: pipx install "agents-shipgate>=0.11.0" agents-shipgate --version # STOP if this prints < 0.11.0 — re-run pinned via uvx agents-shipgate@0.11.0 + SG=agents-shipgate # only after the line above confirms >=0.11.0 ``` 2. **Sanity-check the install** before touching the user's code: ```bash - agents-shipgate self-check --json + $SG self-check --json ``` Confirm `"ready": true`. If not, surface the failure to the user. When available, verify the installed CLI contract locally: ```bash - agents-shipgate contract --json + $SG contract --json ``` Read `report_schema_version`, `packet_schema_version`, `gating_signal`, and `manual_review_signals[]`; prefer these local values over stale docs. If the @@ -40,7 +42,7 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. 3. **Detect:** ```bash - agents-shipgate detect --workspace . --json + $SG detect --workspace . --json ``` Read the response: `is_agent_project`, `frameworks[]` (per-framework score + evidence + candidate files), `agent_name_candidates[]`, `suggested_sources[]` (MCP/OpenAPI files matched by glob). @@ -48,7 +50,7 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. 4. **Generate a starter manifest + GitHub Actions workflow:** ```bash - agents-shipgate init --workspace . --write --ci --json + $SG init --workspace . --write --ci --json ``` The `--json` form returns: - `manifest_status`: `"written"` | `"skipped_existing"` | `"not_attempted"` @@ -66,7 +68,7 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. 6. **Run the scan with patch suggestions:** ```bash - agents-shipgate scan -c shipgate.yaml --suggest-patches --format json --ci-mode advisory + $SG scan -c shipgate.yaml --suggest-patches --format json --ci-mode advisory ``` The report lands at `agents-shipgate-reports/report.json`. The Release Evidence Packet lands at `agents-shipgate-reports/packet.{md,json,html}`. Parse `report.json`; Codex plugin facts, when present, live under `codex_plugin_surface`. @@ -86,7 +88,7 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. 7. **Apply the safe patches:** ```bash - agents-shipgate apply-patches --from agents-shipgate-reports/report.json --confidence high --apply --json + $SG apply-patches --from agents-shipgate-reports/report.json --confidence high --apply --json ``` Default `--confidence high` only mutates patches whose `confidence` field is `"high"`. Today that's the 3 stale-manifest removals. Scope-coverage appends ship at `medium` and require explicit `--confidence medium` to apply. ManualPatches are never auto-applied. @@ -112,17 +114,17 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. - The path to the Release Evidence Packet (`agents-shipgate-reports/packet.md`) for reviewer-shaped output - The top 3 active critical/high findings (use `report.json`, not stdout) - Which patches were applied (count from `apply-patches --json` output's `files`) - - Any check IDs the user should investigate first — link to `docs_url` from the finding for full rationale, or use `agents-shipgate explain --json` for the same content via CLI + - Any check IDs the user should investigate first — link to `docs_url` from the finding for full rationale, or use `$SG explain --json` for the same content via CLI ## What to do if the scan errors out -Set `AGENTS_SHIPGATE_AGENT_MODE=1` and re-run. The CLI will append a JSON line to stderr with `{error, message, next_action}`. Follow the `next_action`. +Re-run the failing `$SG …` command with `AGENTS_SHIPGATE_AGENT_MODE=1` set. The CLI will append a JSON line to stderr with `{error, message, next_action}`. Follow the `next_action`. Common errors and fixes: | Error | Fix | |---|---| -| `Config file not found: shipgate.yaml` | Run `agents-shipgate init --workspace . --write` first | +| `Config file not found: shipgate.yaml` | Run `$SG init --workspace . --write` first | | `Input path '...' resolves outside manifest directory` | The declared `tool_sources[].path` is outside the manifest dir. Move the spec inside the tree, symlink it, or copy it | | `Invalid shipgate.yaml: ... Did you mean X?` | A field is at the wrong nesting level; move it as suggested | | `Containment violation` (apply-patches exit 5) | A patch's `target_file` resolved outside `report.manifest_dir`. Re-run scan to refresh; never patch arbitrary system files | @@ -130,7 +132,7 @@ Common errors and fixes: ## What NOT to do - Do **not** commit `agents-shipgate-reports/` — it's regenerated each run. -- Do **not** run `agents-shipgate baseline save` until the user has reviewed the initial findings. Baselining ratchets in noise that strict CI will silently ignore. The right time to baseline is **after** the user has decided which findings they accept. +- Do **not** run `$SG baseline save` until the user has reviewed the initial findings. Baselining ratchets in noise that strict CI will silently ignore. The right time to baseline is **after** the user has decided which findings they accept. - Do **not** suppress findings without a real `reason` — the manifest validator rejects empty reasons, and the `reason` field is the audit trail when someone asks "why is this OK?" - Do **not** use `risk_overrides.tools.{tool}.remove_tags` to silence a finding without checking whether the heuristic is actually wrong. Prefer `checks.ignore` with a reason. - Do **not** edit a trace recording to flip `approved` or `confirmed` — implement the runtime gate instead. diff --git a/prompts/decide-shipgate-relevance.md b/prompts/decide-shipgate-relevance.md index a36662f..a1ea9bc 100644 --- a/prompts/decide-shipgate-relevance.md +++ b/prompts/decide-shipgate-relevance.md @@ -69,18 +69,15 @@ the rules to the changed file list. ``` 5. **Then act.** - - If `run_shipgate: true` and Shipgate is installed: - ```bash - agents-shipgate detect --workspace . --json - ``` - Then follow [`prompts/add-shipgate-to-repo.md`](https://github.com/ThreeMoonsLab/agents-shipgate/blob/main/prompts/add-shipgate-to-repo.md) - for the first-adoption helper flow. - - If `run_shipgate: true` and Shipgate is **not** installed: run it - version-pinned and zero-install so a stale global build can't shadow - it — `uvx agents-shipgate@0.11.0 detect --workspace . --json` (or - `pipx run agents-shipgate==0.11.0 …`). If the user prefers CI, point - them at the GitHub Action (`ThreeMoonsLab/agents-shipgate@v0.11.0`) - instead. + - If `run_shipgate: true`: run `detect` through a **version-pinned, + zero-install** runner so a stale copy already on `PATH` can't answer — + `uvx agents-shipgate@0.11.0 detect --workspace . --json` (or + `pipx run agents-shipgate==0.11.0 …`). Only fall back to a bare + `agents-shipgate detect` once `agents-shipgate --version` confirms + `>=0.11.0`. Then follow + [`prompts/add-shipgate-to-repo.md`](https://github.com/ThreeMoonsLab/agents-shipgate/blob/main/prompts/add-shipgate-to-repo.md) + for the first-adoption helper flow, or point the user at the GitHub + Action (`ThreeMoonsLab/agents-shipgate@v0.11.0`) if they prefer CI. - If `run_shipgate: false` and `dry_run_recommended: true`: propose a non-mutating scan only — never propose `init --write` based on a dry-run match alone. Phrase it as "X may have shifted the tool diff --git a/skills/agents-shipgate/prompts/add-shipgate-to-repo.md b/skills/agents-shipgate/prompts/add-shipgate-to-repo.md index 8cd6105..1202507 100644 --- a/skills/agents-shipgate/prompts/add-shipgate-to-repo.md +++ b/skills/agents-shipgate/prompts/add-shipgate-to-repo.md @@ -9,28 +9,30 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. ## Your task -1. **Install the tool — pin the version so a stale build can't shadow it.** This flow drives `agents-shipgate verify`, which only ships in **`>=0.11.0`**; an older copy lingering on `PATH` (we have seen `0.8.0`) has no `verify` subcommand and writes no `verifier.json`, so it silently breaks the gate. Prefer a **pinned, zero-install** runner that fetches the exact version every time instead of trusting whatever is already on `PATH`: +1. **Install the tool — pin the version so a stale build can't shadow it.** This flow drives `agents-shipgate verify`, which only ships in **`>=0.11.0`**; an older copy lingering on `PATH` (we have seen `0.8.0`) has no `verify` subcommand and writes no `verifier.json`, so it silently breaks the gate. Prefer a **pinned, zero-install** runner that fetches the exact version every time instead of trusting whatever is already on `PATH`. **Pin it into one variable and use that for every step below**, so no single command can fall through to a stale binary: ```bash - uvx agents-shipgate@0.11.0 --version # uv: ephemeral, always the pinned build - pipx run agents-shipgate==0.11.0 --version # pipx equivalent + SG="uvx agents-shipgate@0.11.0" # uv: ephemeral, always the pinned build + # or: SG="pipx run agents-shipgate==0.11.0" + $SG --version # confirm the pinned runner resolves ``` - Run every `agents-shipgate …` step below through that same runner (`uvx agents-shipgate@0.11.0 …` / `pipx run agents-shipgate==0.11.0 …`) so no stale global install can shadow it. + Every step below calls `$SG …`; e.g. `$SG detect …` runs `agents-shipgate detect` through the pinned runner, never a `PATH` copy. - If you instead install onto `PATH`, pin the floor and **fail loudly when it resolves older** — a plain `pipx install agents-shipgate` is a no-op when an older build already exists: + If you would rather install onto `PATH`, pin the floor and **fail loudly when it resolves older** — a plain `pipx install agents-shipgate` is a no-op when an older build already exists — then set `SG=agents-shipgate`: ```bash python -m pip install -U "agents-shipgate>=0.11.0" # or: pipx install "agents-shipgate>=0.11.0" agents-shipgate --version # STOP if this prints < 0.11.0 — re-run pinned via uvx agents-shipgate@0.11.0 + SG=agents-shipgate # only after the line above confirms >=0.11.0 ``` 2. **Sanity-check the install** before touching the user's code: ```bash - agents-shipgate self-check --json + $SG self-check --json ``` Confirm `"ready": true`. If not, surface the failure to the user. When available, verify the installed CLI contract locally: ```bash - agents-shipgate contract --json + $SG contract --json ``` Read `report_schema_version`, `packet_schema_version`, `gating_signal`, and `manual_review_signals[]`; prefer these local values over stale docs. If the @@ -40,7 +42,7 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. 3. **Detect:** ```bash - agents-shipgate detect --workspace . --json + $SG detect --workspace . --json ``` Read the response: `is_agent_project`, `frameworks[]` (per-framework score + evidence + candidate files), `agent_name_candidates[]`, `suggested_sources[]` (MCP/OpenAPI files matched by glob). @@ -48,7 +50,7 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. 4. **Generate a starter manifest + GitHub Actions workflow:** ```bash - agents-shipgate init --workspace . --write --ci --json + $SG init --workspace . --write --ci --json ``` The `--json` form returns: - `manifest_status`: `"written"` | `"skipped_existing"` | `"not_attempted"` @@ -66,7 +68,7 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. 6. **Run the scan with patch suggestions:** ```bash - agents-shipgate scan -c shipgate.yaml --suggest-patches --format json --ci-mode advisory + $SG scan -c shipgate.yaml --suggest-patches --format json --ci-mode advisory ``` The report lands at `agents-shipgate-reports/report.json`. The Release Evidence Packet lands at `agents-shipgate-reports/packet.{md,json,html}`. Parse `report.json`; Codex plugin facts, when present, live under `codex_plugin_surface`. @@ -86,7 +88,7 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. 7. **Apply the safe patches:** ```bash - agents-shipgate apply-patches --from agents-shipgate-reports/report.json --confidence high --apply --json + $SG apply-patches --from agents-shipgate-reports/report.json --confidence high --apply --json ``` Default `--confidence high` only mutates patches whose `confidence` field is `"high"`. Today that's the 3 stale-manifest removals. Scope-coverage appends ship at `medium` and require explicit `--confidence medium` to apply. ManualPatches are never auto-applied. @@ -112,17 +114,17 @@ agent-related PRs should use `agents-shipgate verify` after this adoption step. - The path to the Release Evidence Packet (`agents-shipgate-reports/packet.md`) for reviewer-shaped output - The top 3 active critical/high findings (use `report.json`, not stdout) - Which patches were applied (count from `apply-patches --json` output's `files`) - - Any check IDs the user should investigate first — link to `docs_url` from the finding for full rationale, or use `agents-shipgate explain --json` for the same content via CLI + - Any check IDs the user should investigate first — link to `docs_url` from the finding for full rationale, or use `$SG explain --json` for the same content via CLI ## What to do if the scan errors out -Set `AGENTS_SHIPGATE_AGENT_MODE=1` and re-run. The CLI will append a JSON line to stderr with `{error, message, next_action}`. Follow the `next_action`. +Re-run the failing `$SG …` command with `AGENTS_SHIPGATE_AGENT_MODE=1` set. The CLI will append a JSON line to stderr with `{error, message, next_action}`. Follow the `next_action`. Common errors and fixes: | Error | Fix | |---|---| -| `Config file not found: shipgate.yaml` | Run `agents-shipgate init --workspace . --write` first | +| `Config file not found: shipgate.yaml` | Run `$SG init --workspace . --write` first | | `Input path '...' resolves outside manifest directory` | The declared `tool_sources[].path` is outside the manifest dir. Move the spec inside the tree, symlink it, or copy it | | `Invalid shipgate.yaml: ... Did you mean X?` | A field is at the wrong nesting level; move it as suggested | | `Containment violation` (apply-patches exit 5) | A patch's `target_file` resolved outside `report.manifest_dir`. Re-run scan to refresh; never patch arbitrary system files | @@ -130,7 +132,7 @@ Common errors and fixes: ## What NOT to do - Do **not** commit `agents-shipgate-reports/` — it's regenerated each run. -- Do **not** run `agents-shipgate baseline save` until the user has reviewed the initial findings. Baselining ratchets in noise that strict CI will silently ignore. The right time to baseline is **after** the user has decided which findings they accept. +- Do **not** run `$SG baseline save` until the user has reviewed the initial findings. Baselining ratchets in noise that strict CI will silently ignore. The right time to baseline is **after** the user has decided which findings they accept. - Do **not** suppress findings without a real `reason` — the manifest validator rejects empty reasons, and the `reason` field is the audit trail when someone asks "why is this OK?" - Do **not** use `risk_overrides.tools.{tool}.remove_tags` to silence a finding without checking whether the heuristic is actually wrong. Prefer `checks.ignore` with a reason. - Do **not** edit a trace recording to flip `approved` or `confirmed` — implement the runtime gate instead. diff --git a/skills/agents-shipgate/prompts/decide-shipgate-relevance.md b/skills/agents-shipgate/prompts/decide-shipgate-relevance.md index a36662f..a1ea9bc 100644 --- a/skills/agents-shipgate/prompts/decide-shipgate-relevance.md +++ b/skills/agents-shipgate/prompts/decide-shipgate-relevance.md @@ -69,18 +69,15 @@ the rules to the changed file list. ``` 5. **Then act.** - - If `run_shipgate: true` and Shipgate is installed: - ```bash - agents-shipgate detect --workspace . --json - ``` - Then follow [`prompts/add-shipgate-to-repo.md`](https://github.com/ThreeMoonsLab/agents-shipgate/blob/main/prompts/add-shipgate-to-repo.md) - for the first-adoption helper flow. - - If `run_shipgate: true` and Shipgate is **not** installed: run it - version-pinned and zero-install so a stale global build can't shadow - it — `uvx agents-shipgate@0.11.0 detect --workspace . --json` (or - `pipx run agents-shipgate==0.11.0 …`). If the user prefers CI, point - them at the GitHub Action (`ThreeMoonsLab/agents-shipgate@v0.11.0`) - instead. + - If `run_shipgate: true`: run `detect` through a **version-pinned, + zero-install** runner so a stale copy already on `PATH` can't answer — + `uvx agents-shipgate@0.11.0 detect --workspace . --json` (or + `pipx run agents-shipgate==0.11.0 …`). Only fall back to a bare + `agents-shipgate detect` once `agents-shipgate --version` confirms + `>=0.11.0`. Then follow + [`prompts/add-shipgate-to-repo.md`](https://github.com/ThreeMoonsLab/agents-shipgate/blob/main/prompts/add-shipgate-to-repo.md) + for the first-adoption helper flow, or point the user at the GitHub + Action (`ThreeMoonsLab/agents-shipgate@v0.11.0`) if they prefer CI. - If `run_shipgate: false` and `dry_run_recommended: true`: propose a non-mutating scan only — never propose `init --write` based on a dry-run match alone. Phrase it as "X may have shifted the tool diff --git a/tests/test_agent_instructions_renderers.py b/tests/test_agent_instructions_renderers.py index 6581842..d9b8096 100644 --- a/tests/test_agent_instructions_renderers.py +++ b/tests/test_agent_instructions_renderers.py @@ -43,10 +43,10 @@ "b442316b7bbdb4b2a84b8543f3589e1bb1d8d2bfd968637db99bd07835c406fd" ), ".claude/skills/agents-shipgate/prompts/add-shipgate-to-repo.md": ( - "d6b9944dc7849aa7827fd8138e72b0720674944a313c9351e9afe94aa3bfc794" + "cbe776960a7b18a92b9608e5a9852486d3744ca25c823a44cb69a7eb167a7994" ), ".claude/skills/agents-shipgate/prompts/decide-shipgate-relevance.md": ( - "7d92c6e1466825a4550c6b1259efccfbeb4dd35eb9e27b1d29de5421515bac2c" + "5bb45a71a44c2350e94d6197e6225c92b7cd00521e668c9e36358e4136852f0f" ), ".claude/skills/agents-shipgate/prompts/explain-finding-to-user.md": ( "18031ed870b3c937a2996173820639ef441afe0a45e8171f16468826cd389829" diff --git a/tests/test_public_surface_contract.py b/tests/test_public_surface_contract.py index 7228f2d..047c716 100644 --- a/tests/test_public_surface_contract.py +++ b/tests/test_public_surface_contract.py @@ -77,6 +77,11 @@ r"ThreeMoonsLab/agents-shipgate@v(\d+\.\d+\.\d+)" ) PIP_PIN_PATTERN = re.compile(r"agents-shipgate==(\d+\.\d+\.\d+)") +# Zero-install runner pin recommended by the agent-facing install +# snippets: ``uvx agents-shipgate@X.Y.Z``. The ``@v`` GitHub Action form +# is NOT matched (a digit must follow ``@``), nor is the ``==`` pip form, +# so this guards the uvx literal specifically. +UVX_PIN_PATTERN = re.compile(r"agents-shipgate@(\d+\.\d+\.\d+)") SHIPGATE_VERSION_INPUT_PATTERN = re.compile( r"shipgate_version:\s*['\"](\d+\.\d+\.\d+)['\"]" ) @@ -217,6 +222,8 @@ "examples/gitlab-ci/03-sarif-or-artifact.yml", "examples/gitlab-ci/04-multi-config-workspace.yml", "examples/gitlab-ci/05-on-tool-source-changes.yml", + "prompts/decide-shipgate-relevance.md", + "skills/agents-shipgate/prompts/decide-shipgate-relevance.md", "prompts/stabilize-strict-mode.md", "skills/agents-shipgate/prompts/stabilize-strict-mode.md", "skills/agents-shipgate/ci-recipes/advisory-pr-comment.yml", @@ -624,6 +631,28 @@ def test_pip_pins_match_pyproject_version(relpath): ) +@pytest.mark.parametrize("relpath", ACTION_PIN_FILES) +def test_uvx_pins_match_pyproject_version(relpath): + """Every ``uvx agents-shipgate@X.Y.Z`` zero-install pin in a public + surface must equal the package version. The agent-facing install + snippets recommend this pinned runner so a coding agent never shells + out to a stale ``PATH`` build; without this guard a pyproject bump + could leave a stale ``uvx agents-shipgate@…`` literal in a bundled + prompt. The ``pipx run agents-shipgate==X.Y.Z`` form is already + covered by ``PIP_PIN_PATTERN`` and the ``@v`` Action form by + ``ACTION_PIN_PATTERN``.""" + expected = _load_pyproject_version() + for line_number, line, found in _file_lines_with_pin( + relpath, UVX_PIN_PATTERN + ): + assert found == expected, ( + f"{relpath}:{line_number} pins uvx agents-shipgate@{found}; " + f"pyproject.toml says {expected}. Update the pin to " + f"@{expected} or bump pyproject.toml.\n line: " + f"{line.strip()!r}" + ) + + @pytest.mark.parametrize("relpath", ACTION_PIN_FILES) def test_shipgate_version_inputs_match_pyproject_version(relpath): """The `shipgate_version: ''` Action input in workflow