# Agents Shipgate · Agent Instructions
Authoritative instructions for AI coding agents (Claude Code, Codex, Cursor, Aider, Cline, Windsurf, Devin, or any other harness — see [`docs/agents/any-coding-agent.md`](docs/agents/any-coding-agent.md)) working **with** this repository or a project that uses Agents Shipgate.
> If you are a human, the README and the [wiki](https://github.com/ThreeMoonsLab/agents-shipgate/wiki) are the right places to start. This file is optimized for agent ingest: short, copy-pasteable, machine-friendly.
---
## What this project is
The deterministic merge gate for AI-generated agent capability changes. Reads `shipgate.yaml` plus tool sources (MCP exports, OpenAPI specs, OpenAI Agents SDK Python files, Anthropic Messages API tool/prompt artifacts, Google ADK Python/config files, LangChain/LangGraph Python files, CrewAI Python files, OpenAI API artifacts, Codex repo config, Codex plugin packages and marketplaces, n8n workflow JSON/stubs) and produces deterministic findings. Local-first and static by default — no agent execution, tool calls, LLM calls, or network access.
- **Inputs:** MCP · OpenAPI · OpenAI Agents SDK · Anthropic Messages API · Google ADK · LangChain/LangGraph · CrewAI · OpenAI API · Codex config · Codex plugin · n8n
- **Outputs:** Markdown · JSON · SARIF
- **Trust:** Static-by-default. No agent execution, tool calls, LLM calls, or network access.
- **Marketing site:** [threemoonslab.com](https://threemoonslab.com/) — human-readable companion pages. **If you are an agent working inside this repo, use the in-tree [`.well-known/agents-shipgate.json`](.well-known/agents-shipgate.json) (current `main` contract, may be ahead of the site's released copy) for schema-version and gating-signal decisions.**
---
## Naming (canonical)
Use exactly one form depending on context. Mixing them in user-visible copy is an adoption cost.
| Form | When to use |
|---|---|
| **Agents Shipgate** | Display name. Prose, headings, marketing copy, social cards, slide titles, blog posts. |
| **`agents-shipgate`** | Package, CLI binary, repo, GitHub Action, PyPI distribution name, env-var prefix (`AGENTS_SHIPGATE_*`), import path (`agents_shipgate`). Always lowercase, kebab-case. |
| **`shipgate`** | Short alias for the CLI binary only. Acceptable in shell snippets where brevity helps; never as the project name. |
Do **not** use any of: `Agent Shipgate` (singular), `Agent Shipcheck`, `agents shipgate` (display lowercase), `Agents-Shipgate` (display kebab). When in doubt: prose → `Agents Shipgate`; code → `agents-shipgate`.
The canonical tagline is:
> The deterministic merge gate for AI-generated agent capability changes.
This single sentence is the source of truth for the GitHub repo description, [README.md](README.md), the [wiki Home page](https://github.com/ThreeMoonsLab/agents-shipgate/wiki/Home), and the [marketing site](https://threemoonslab.com/) ``. Keep them in sync; the website's `.well-known` discovery file is pinned to the latest released tag and refreshes at each release.
Use **Tool-Use Readiness** in Title Case when naming the product/category or
the **Tool-Use Readiness Report** artifact. Use **tool-use readiness** in
sentence case when describing the general concept.
---
## Install (canonical)
```bash
pipx install agents-shipgate
```
Alternatives if `pipx` is unavailable:
```bash
python -m pip install agents-shipgate # global pip
uv tool install agents-shipgate # via uv
python -m agents_shipgate --help # run from a pip install without PATH
```
The CLI binary is `agents-shipgate`. A short alias `shipgate` is also installed.
---
## Run (canonical)
Handling a capability change right now? Start with **Local control** below —
run First-time setup only when the repo has no `shipgate.yaml` yet.
**First-time setup** — in a repo that contains an agent and its tools:
```bash
agents-shipgate init --workspace . --write
agents-shipgate scan -c shipgate.yaml
```
Reports land at `agents-shipgate-reports/report.{md,json}`.
**Local control for coding agents** — before reporting an agent-capability
change complete, run the local control loop and parse stdout JSON:
```bash
shipgate check --agent codex --workspace . --format codex-boundary-json
shipgate check --agent claude-code --workspace . --format codex-boundary-json
shipgate check --agent cursor --workspace . --format codex-boundary-json
```
Read the single stdout object as `shipgate.codex_boundary_result/v1`. Switch on
`decision`, `completion_allowed`, `must_stop`, `first_next_action`,
`human_review`, `repair`, `policy`, and `verify_required`; never infer a local-control decision
from Markdown, PR comments, or prose. If `decision=allow` or `warn`, continue
and summarize the result. If `first_next_action.kind=repair` and
`repair.safe_to_attempt` is `true`, apply only that repair and rerun the
command. If `human_review.required=true` or `must_stop=true`, stop and surface the JSON
result to a human.
**Before editing a protected release surface** — ask the proactive static
planner first:
```bash
agents-shipgate preflight --workspace . --plan - --json
agents-shipgate preflight --changed-files changed.txt --json
agents-shipgate preflight --capability-request request.json --json
```
If `requires_human_review` is `true` or `first_next_action.actor` is `human`,
stop and route the change to a human. The plan form accepts `changed_files[]`,
`diff_text`, `capability_requests[]`, `host_permission_requests[]`, and
`context.{agent,task}`; prefer it whenever the agent can describe the planned
change as one JSON object. Protected surfaces include
`shipgate.yaml`, `.github/workflows/agents-shipgate.yml`,
`AGENTS.md`/`CLAUDE.md`/Cursor rules, policy packs, baselines, waivers,
suppressions, Codex hooks/config, Codex plugin manifests, `.mcp.json`,
`.app.json`, and `SKILL.md`. Preflight is a routing/projection surface only;
`release_decision.decision` remains the release gate.
**PR / reviewer evidence** — for committed PR/CI refs, run the deterministic
verifier on the diff. Make the base ref available first because `verify` never
fetches:
```bash
agents-shipgate verify --workspace . --config shipgate.yaml \
--base origin/main --head HEAD --ci-mode advisory --format json
```
For local uncommitted verifier work, omit `--base`/`--head` so the working tree
is scanned. Read `agents-shipgate-reports/agent-handoff.json` first and lead
with `gate.merge_verdict`
(`mergeable | human_review_required | insufficient_evidence | blocked |
unknown`), `gate.can_merge_without_human`, `controller`, `next_action`,
`fix_task`, and `capability_review.top_changes[]`. Fall back to
`agents-shipgate-reports/verifier.json` only when the installed CLI contract is
older than v6. Then read
`agents-shipgate-reports/report.json.release_decision.decision`
(`blocked | review_required | insufficient_evidence | passed`), which remains
the release gate. Do not report completion while `merge_verdict` is `blocked`,
`insufficient_evidence`, or `human_review_required` unless the user explicitly
accepts human review.
Do not bypass the verifier by suppressing findings, lowering severity,
expanding baselines or waivers, removing Shipgate CI, or weakening agent
instructions. Verify-mode `SHIP-VERIFY-*` checks make those trust-root edits
release-visible and route them to human review.
To reproduce the verify-native blocked refund PR demo without writing YAML:
```bash
agents-shipgate fixture run ai_generated_refund_pr
```
To verify your install on the older static scan fixture:
```bash
agents-shipgate fixture run support_refund_agent
```
---
## First-adoption helper flow (v0.6+)
For coding agents adopting Shipgate end-to-end in one turn:
```bash
agents-shipgate detect --json
agents-shipgate init --write --ci --json
agents-shipgate scan -c shipgate.yaml --suggest-patches --format json
agents-shipgate apply-patches --from agents-shipgate-reports/report.json \
--confidence high --apply
```
Or chain all four in one call:
```bash
agents-shipgate bootstrap --json
```
`bootstrap` runs `detect → init --write --ci → scan --suggest-patches → apply-patches --confidence high` against the current workspace, stopping on the first non-recoverable error and emitting a structured per-step summary. Use it for first-time adoption; for ongoing CI keep using the GitHub Action. Flags: `--workspace`, `--confidence`, `--no-ci`, `--no-apply`, `--json`.
- **`detect`** — read-only; classifies the workspace. `is_agent_project: false`
means stop early.
- **`init`** — auto-detects by default. `--ci` writes
`.github/workflows/agents-shipgate.yml`; orthogonal to `--write`. Use
`--minimal` for the pre-v0.6 CHANGE_ME-heavy template.
`--agent-instructions=default` renders the recommended downstream kit
(`AGENTS.md`, `CLAUDE.md`, `.cursor/rules/agents-shipgate.mdc`,
`.claude/commands/shipgate.md`, and `.shipgate/agent-contract.json`).
Use `--ci` to write advisory CI. `--agent-instructions=all` means every
supported target. A comma-separated subset can name any target:
`agents-md,claude-md,cursor,claude-command,local-contract,codex-skill,claude-code-skill,pr-template`.
Combined with `--write`, managed-block hosts are idempotently updated and
full-file / skill-bundle targets use safe-update checks. The `codex-skill` and
`claude-code-skill` targets remain explicit opt-ins and write multi-file skill
bundles under `.agents/skills/agents-shipgate/` and
`.claude/skills/agents-shipgate/` respectively. Strict CI and baselines remain
opt-in human decisions; generated CI stays advisory by default.
- **`scan --suggest-patches`** — attaches Patch objects to every active
finding. `Finding.patches` is absent without the flag.
- **`apply-patches`** — file-grouped, dry-run by default. Containment-
checked against `report.manifest_dir`. v0.6 default `--confidence high`
applies only manifest stale-removals; scope-coverage appends require
`--confidence medium`. Trace approval/confirmation findings are
always `ManualPatch` — never auto-applied (flipping the trace patches
the evidence, not the agent's runtime gate).
---
## Agent mode
Every command supports JSON output for programmatic consumption:
```bash
agents-shipgate detect --workspace . --json
agents-shipgate preflight --workspace . --plan - --json
agents-shipgate init --workspace . --write --json
agents-shipgate scan -c shipgate.yaml # already produces report.json
agents-shipgate apply-patches --from agents-shipgate-reports/report.json --json
agents-shipgate doctor --json
agents-shipgate contract --json
agents-shipgate explain SHIP-POLICY-APPROVAL-MISSING --json
agents-shipgate list-checks --json
agents-shipgate self-check --json
agents-shipgate fixture list --json
```
Errors carry a structured `next_action` (single string, back-compat) and `next_actions` (ranked list) when agent mode is active. Agent mode auto-enables inside a known coding-agent harness (Claude Code exports `CLAUDECODE=1`, Cursor `CURSOR_TRACE_ID`); set `AGENTS_SHIPGATE_AGENT_MODE=1` to force it on elsewhere, or `=0` to force it off:
```bash
$ AGENTS_SHIPGATE_AGENT_MODE=1 agents-shipgate scan -c missing.yaml
Config error: Config file not found: missing.yaml
{"error": "config_error", "message": "...", "next_action": "agents-shipgate detect --workspace . --json", "next_actions": [{"kind": "command", "command": "agents-shipgate detect --workspace . --json", "why": "..."}, {"kind": "command", "command": "agents-shipgate init --workspace . --write", "why": "..."}]}
```
The full set of error kinds emitted in agent mode: `config_error`, `config_already_exists`, `input_parse_error`, `unknown_check_id`, `unknown_fingerprint`, `other_error`, `internal_error`, `malformed_patch`. `unknown_fingerprint` is emitted by `explain-finding` when the fingerprint doesn't match any entry in the supplied report; the payload includes `suggestion` (a close-match fingerprint, when one exists) and `source_report`.
The machine-readable catalog of error kinds — exit codes, typical causes, additional fields per kind, recovery hints — lives at [`docs/errors.json`](docs/errors.json). Pre-fetch it once and pattern-match the `error` field instead of re-deriving the recovery vocabulary from this prose.
`detect --json` and each `doctor --json` payload also carry `diagnostics: [...]` and `next_actions: [...]` fields. `next_action` (single string) remains the rank-1 action projected to a string; `next_actions` is the ranked list with `kind`, `command|path`, `why`, and `expects` fields. See [docs/diagnostics.md](docs/diagnostics.md) for the full catalog and schema.
### Doctor behavior change for unresolved tool_sources
When a required `tool_sources[].path` does not resolve under the manifest directory (file missing OR resolves outside the manifest dir):
- `agents-shipgate doctor --json` exits **0** with a `SHIP-DIAG-MISSING-SOURCE-FILE` diagnostic and an `unresolved_sources: [{id, declared_path, line, reason}]` field in the payload, so an agent can route to a fix without parsing the error message. `reason` is `"missing"` or `"outside_manifest_dir"`.
- `agents-shipgate doctor` (no `--json`) prints the same `unresolved_sources` + diagnostic block in human-readable form and **exits 3**, preserving the pre-feature loud failure for interactive users.
- `agents-shipgate scan` is unchanged — it still raises `InputParseError(3)` regardless of `--json`. Once you're past doctor, missing sources are real scan failures.
### Missing vs invalid manifests
`config_error` covers two distinct shapes — agent-mode emits a different rank-1 action for each:
- **Missing**: file does not exist → `SHIP-DIAG-MISSING-MANIFEST`, rank-1 is `agents-shipgate detect --workspace
--json` (then `init --write`).
- **Invalid**: file exists but the loader rejected it (invalid YAML, schema validation, unsupported version) → `SHIP-DIAG-INVALID-MANIFEST`, rank-1 is `edit ` with the loader error in `why`. Do **not** re-run `init` — it refuses to overwrite an existing file.
---
## When to use this tool
Use it when the user is:
- Writing or modifying an AI agent that calls tools (MCP servers, OpenAPI APIs, `@function_tool`-decorated Python, Google ADK, LangChain/LangGraph, CrewAI, n8n)
- Publishing or modifying a Codex plugin package or marketplace entry that declares skills, apps, MCP servers, or hooks
- Adding a new tool, scope, or policy to an existing agent
- Preparing an agent for production promotion
- Wiring a release gate into PR CI
Do NOT use it for:
- General code linting (ruff, eslint, etc.)
- Runtime monitoring (use observability/tracing)
- Behavior testing (use evals)
- Stopping a tool call in flight (use a gateway or guardrail)
### Should I run Shipgate on this PR?
| Trigger in this PR | Run Shipgate? |
|---|---|
| Adds/changes MCP exports, OpenAPI specs, or `tools/*openai*tools*.json` | Yes |
| Adds/changes Codex repo config, hooks, or permission profiles | Yes |
| Adds/changes Codex plugin manifests, marketplace files, `.app.json`, `.mcp.json`, or `SKILL.md` files | Yes |
| Adds/changes `@function_tool`/`@tool` decorators (LangChain, CrewAI, OpenAI Agents SDK) | Yes |
| Adds/changes n8n workflow JSON, credential stubs, or n8n tool inventories | Yes |
| Edits `prompts/`, `policies/`, or `permissions.scopes` in `shipgate.yaml` | Yes |
| Adds/edits `.github/workflows/agents-shipgate.yml` or related CI | Yes |
| Pure read-only doc/test changes with no manifest impact | Skip |
| Refactor with no behavior change to tools or policies | Skip (or dry-run only) |
Two implicit triggers also fire even when no row above matches:
- **Repo already opted in (shipgate.yaml present in the workspace)** — run on every PR; the manifest's existence is the opt-in.
- **(Optional) Refactor or framework upgrade that may shift the extracted tool surface** — dry-run only; bumping `openai-agents`, `langchain`, `crewai`, or `google-adk` can change AST extraction even without app-code edits.
A machine-readable mirror of these triggers lives at [`docs/triggers.json`](docs/triggers.json). Coding agents that have not yet adopted Shipgate can fetch the file (raw URL: `https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/triggers.json`), apply the rules to a PR diff, and decide whether to propose `agents-shipgate detect`. The catalog is stable for `0.x` and pinned by the public-surface contract test against this prose table — if you change a row above, update `triggers.json` in the same commit. To evaluate a diff locally, use the first-class `trigger` subcommand:
```bash
# From a list of changed paths (and optional diff body for diff_contains rules):
agents-shipgate trigger --changed-files changed.txt --diff pr.diff --json
# Or straight from git (the ONLY mode that shells out to git):
agents-shipgate trigger --base origin/main --head HEAD --json
agents-shipgate trigger --list-rules --json
```
The command emits a stable JSON verdict: `should_run` (alias of `run_shipgate`), `force_run`, `dry_run_recommended`, `skip_reason`, `matched_rules`, `changed_files`, and `diff_tokens`. The developer entry point `python -m agents_shipgate.triggers shipgate.yaml prompts/refund.md` is preserved.
**Stop conditions.** Stop and do not run `init` only when **all** of these hold:
- `agents-shipgate detect --json` returns `is_agent_project: false`, AND
- `suggested_sources` is empty (no MCP/OpenAPI hits flowing in as `mcp` or `openapi`), AND
- `codex_plugin_candidates` is empty (no Codex plugin package or marketplace hits), AND
- no `shipgate.yaml` already exists in the workspace, AND
- the user did not explicitly request a scan.
Otherwise proceed to `init`. MCP/OpenAPI tool-surface repos and Codex plugin package repos register as `is_agent_project: false` because they have no Python framework imports — but they are valid Shipgate targets. MCP/OpenAPI hits surface as `suggested_sources`; Codex plugin hits surface as `codex_plugin_candidates`. The trigger table above is the authoritative go/no-go.
---
## Five common agent tasks
### Task 1 · Add the gate to an existing repo
```bash
pipx install agents-shipgate
agents-shipgate init --workspace . --write
# edit shipgate.yaml to replace any CHANGE_ME values
agents-shipgate scan -c shipgate.yaml
```
`init` writes a manifest with `CHANGE_ME` placeholders for `agent.name` and `agent.declared_purpose`. Replace them by reading the agent's prompt or main file.
### Task 2 · Read findings programmatically
Always parse `agents-shipgate-reports/report.json`, not the markdown.
The canonical field list — `release_decision`, `capability_facts` / `declared_intentions` / `misalignments` / `release_consequence` / `suggested_scenarios`, `tool_surface_facts` / `tool_surface_diff`, and `action_surface_facts` / `action_surface_diff` — lives in [`docs/agent-contract-current.md`](docs/agent-contract-current.md#read-these-first-for-release-gating). It updates first when the contract bumps; this file links to it instead of restating the field set.
Other stable top-level fields (full history and semantics live in
[`docs/agent-contract-current.md`](docs/agent-contract-current.md); never
restate version archaeology here):
- `summary.{critical_count, high_count, medium_count, status}` (legacy,
baseline-blind — do not gate on it)
- `findings[].{id, fingerprint, check_id, severity, tool_name, evidence, recommendation, suppressed}`
- `findings[].{autofix_safe, requires_human_review, suggested_patch_kind, docs_url, provenance_kind, blocks_release}`
- `findings[].policy_routing` (policy-pack owner/reviewer/approval routing metadata only; non-enforcing and not part of `evidence`)
- `findings[].patches[]` (only when scan ran with `--suggest-patches`)
- `baseline.{matched_count, new_count, resolved_count}` · `tool_inventory[]` · `codex_plugin_surface`
- `action_surface_facts` / `action_surface_diff`
- Audit envelopes: `release_decision.contribution_rules[]`, `policy_audit`,
`privacy_audit`, `heuristics_filter` — explanatory, never a second gate
The full schema is at [`docs/report-schema.v0.28.json`](docs/report-schema.v0.28.json) (current; emitted reports carry `report_schema_version: "0.28"`, moving policy-pack owner/reviewer/approval routing metadata to `findings[].policy_routing` so `Finding.evidence` remains deterministic match/gating evidence). v0.27 (frozen at [`docs/report-schema.v0.27.json`](docs/report-schema.v0.27.json)) added policy-pack distribution metadata — `loaded_policy_packs[].{source,sha256,sha256_status,owner}` — while preserving findings, fingerprints, policy-pack behavior, capability locks, and the release gate. v0.26 (frozen at [`docs/report-schema.v0.26.json`](docs/report-schema.v0.26.json)) added structured evidence gaps — `release_decision.evidence_coverage.evidence_gaps[]`, one actionable remediation row per low-confidence tool or source warning — plus the advisory `suggested-inventory.json` skeleton written next to `report.json`; gate behavior is unchanged. v0.25 (frozen at [`docs/report-schema.v0.25.json`](docs/report-schema.v0.25.json)) added opt-in capability-linked local trace/provenance evidence while preserving existing findings, fingerprints, policy-pack behavior, capability locks, and the release gate. v0.24 (frozen at [`docs/report-schema.v0.24.json`](docs/report-schema.v0.24.json)) added capability-native policy evidence. v0.23 (frozen at [`docs/report-schema.v0.23.json`](docs/report-schema.v0.23.json)) added semantic metadata to `capability_change` members while preserving the existing capability-change buckets and release gate. v0.22 (frozen at [`docs/report-schema.v0.22.json`](docs/report-schema.v0.22.json)) added the verifier-cycle top-level blocks `capability_change`, `protected_surface_changes`, `effective_policy`, `human_ack`, and `verifier_summary` — reviewer-facing projections that never gate independently — alongside v0.21's `heuristics_filter` audit envelope. v0.21 (frozen at [`docs/report-schema.v0.21.json`](docs/report-schema.v0.21.json)) added the `heuristics_filter` envelope on top of v0.20's `reviewer_summary` deterministic projection of reviewer-lens surfaces and audit envelopes. v0.19 added `Finding.policy_evidence_source` and `ReleaseDecisionItem.{source, policy_evidence_source}` for reviewer-grade dual-source provenance on top of v0.18's `privacy_audit`, v0.17's `policy_audit`, and `release_decision.contribution_rules[]` audit fields. What's-stable is documented in [STABILITY.md](STABILITY.md).
**Release gating signal**: prefer `release_decision.decision` (`"blocked" | "review_required" | "insufficient_evidence" | "passed"`) over `summary.status`. The new field is **baseline-aware** — a baseline-matched critical surfaces in `release_decision.review_items` (accepted debt), not `release_decision.blockers`. `summary.status` stays baseline-blind for v0.7 compatibility, so a baseline-matched-only critical produces both `summary.status = "release_blockers_detected"` AND `release_decision.decision = "review_required"` (intentional divergence — see [STABILITY.md](STABILITY.md#release_decisiondecision-vs-summarystatus)). `insufficient_evidence` (added v0.14) signals that the scan saw too many low-confidence tools or source-loader warnings to be trustworthy; consumers that switch on the enum must fall back to `review_required` for unknown future values.
For a step-by-step reader's primer with anti-patterns and concrete code rewrites, see [`docs/report-reading-for-agents.md`](docs/report-reading-for-agents.md).
### Task 3 · Suppress a finding with a reason
```yaml
# shipgate.yaml
checks:
ignore:
- check_id: SHIP-DOC-MISSING-DESCRIPTION
tool: legacy_search
reason: tool deprecated 2026-Q2
```
`reason` is required and non-empty; the manifest fails validation otherwise.
### Task 4 · Save a baseline before enabling strict CI
```bash
agents-shipgate baseline save -c shipgate.yaml --out .agents-shipgate/baseline.json \
--owner --reason "" --expires
```
`--owner`/`--reason`/`--expires` (v0.13+) record who accepted the debt, why,
and the review-by date on newly-accepted entries. They are human-declared
values: an agent must ask the user, never invent them, and blank values are
rejected. `--apply-to-existing` fills the fields into existing entries that
lack them without overwriting previously-set values.
Then in CI:
```bash
agents-shipgate scan -c shipgate.yaml \
--baseline .agents-shipgate/baseline.json \
--ci-mode strict --fail-on critical,high
```
Strict mode fails CI only on **new** findings (those not in the baseline).
`agents-shipgate baseline status --json` reports accepted-debt aging
(owner, age, expiry); with `--require-owner` / `--require-expiry` /
`--max-age-days N` it exits `20` on violations (advisory exit `0` without
gate flags) — parse `violations[]` from the JSON, then route to a human:
acknowledging debt is a human decision.
### Task 5 · Explain a check or a specific finding
For static catalog metadata about a check ID (rationale, fires-when, recommendation):
```bash
agents-shipgate explain SHIP-POLICY-APPROVAL-MISSING --json
```
Returns the full `CheckMetadata` with `id`, `category`, `default_severity`, `description`, `rationale`, `fires_when`, `evidence_fields`, `recommendation`.
For a contextual explanation tied to a specific finding from a real scan (catalog metadata + the finding's evidence + a 3–5 sentence templated prose summary):
```bash
agents-shipgate explain-finding fp_ \
--from agents-shipgate-reports/report.json --json
```
Returns the canonical Finding fields plus `metadata` (CheckMetadata for the check_id) and `explanation` — a deterministic prose summary suitable for direct quotation in a PR comment or chat reply. The companion prompt is [`prompts/explain-finding-to-user.md`](prompts/explain-finding-to-user.md).
---
## Agent FAQ
### Where is the manifest schema?
Use [`docs/manifest-v0.1.json`](docs/manifest-v0.1.json) for machine
validation and [`docs/manifest-v0.1.md`](docs/manifest-v0.1.md) for prose.
### Where is the report schema?
Parse `agents-shipgate-reports/report.json` and validate against
[`docs/report-schema.v0.28.json`](docs/report-schema.v0.28.json) (current).
Older reports (`report_schema_version: "0.10"`) validate against the
frozen [`docs/report-schema.v0.10.json`](docs/report-schema.v0.10.json).
Do not scrape Markdown when JSON is available.
### How do I add a new check?
Follow [`docs/architecture.md`](docs/architecture.md) and update the check
registry, tests, [`docs/checks.md`](docs/checks.md), and
[`docs/checks.json`](docs/checks.json). Check IDs must not change after
publication.
### How do I add a new framework adapter?
Start with [`docs/framework-adapter-checklist.md`](docs/framework-adapter-checklist.md).
Adapters must be static by default: no user-code import, no network access, no
agent execution.
### Where are runnable examples?
Use [`samples/README.md`](samples/README.md) for sample agents and
[`docs/examples.md`](docs/examples.md) for a narrative overview. The fastest
fixture is `agents-shipgate fixture run support_refund_agent`.
### What vocabulary should I use in user-facing copy?
Use the [canonical names](#canonical-names) table above and the website
glossary: https://threemoonslab.com/glossary/.
---
## Schemas
For the short, current statement of "which fields to read", see [`docs/agent-contract-current.md`](docs/agent-contract-current.md). It is the single file that updates first when the contract bumps; the table below lists the underlying schemas.
| What | Path | Stable |
|---|---|---|
| Manifest schema | [`docs/manifest-v0.1.json`](docs/manifest-v0.1.json) | `0.1` |
| Report schema (current) | [`docs/report-schema.v0.28.json`](docs/report-schema.v0.28.json) | `0.28` |
| Report schema (v0.27 frozen reference) | [`docs/report-schema.v0.27.json`](docs/report-schema.v0.27.json) | `0.27` |
| Report schema (v0.26 frozen reference) | [`docs/report-schema.v0.26.json`](docs/report-schema.v0.26.json) | `0.26` |
| Report schema (v0.25 frozen reference) | [`docs/report-schema.v0.25.json`](docs/report-schema.v0.25.json) | `0.25` |
| Verify-run schema | [`docs/verify-run-schema.v1.json`](docs/verify-run-schema.v1.json) | `shipgate.verify_run/v1` |
| Agent handoff schema | [`docs/agent-handoff-schema.v1.json`](docs/agent-handoff-schema.v1.json) | `shipgate.agent_handoff/v1` |
| Codex boundary result schema | [`docs/codex-boundary-result-schema.v1.json`](docs/codex-boundary-result-schema.v1.json) | `shipgate.codex_boundary_result/v1` |
| Report schema (v0.24 frozen reference) | [`docs/report-schema.v0.24.json`](docs/report-schema.v0.24.json) | `0.24` |
| Report schema (v0.23 frozen reference) | [`docs/report-schema.v0.23.json`](docs/report-schema.v0.23.json) | `0.23` |
| Report schema (v0.22 frozen reference) | [`docs/report-schema.v0.22.json`](docs/report-schema.v0.22.json) | `0.22` |
| Report schema (v0.21 frozen reference) | [`docs/report-schema.v0.21.json`](docs/report-schema.v0.21.json) | `0.21` |
| Report schema (v0.20 frozen reference) | [`docs/report-schema.v0.20.json`](docs/report-schema.v0.20.json) | `0.20` |
| Report schema (v0.19 frozen reference) | [`docs/report-schema.v0.19.json`](docs/report-schema.v0.19.json) | `0.19` |
| Report schema (v0.18 frozen reference) | [`docs/report-schema.v0.18.json`](docs/report-schema.v0.18.json) | `0.18` |
| Report schema (v0.17 frozen reference) | [`docs/report-schema.v0.17.json`](docs/report-schema.v0.17.json) | `0.17` |
| Report schema (v0.16 frozen reference) | [`docs/report-schema.v0.16.json`](docs/report-schema.v0.16.json) | `0.16` |
| Report schema (v0.15 frozen reference) | [`docs/report-schema.v0.15.json`](docs/report-schema.v0.15.json) | `0.15` |
| Report schema (v0.14 frozen reference) | [`docs/report-schema.v0.14.json`](docs/report-schema.v0.14.json) | `0.14` |
| Report schema (v0.13 frozen reference) | [`docs/report-schema.v0.13.json`](docs/report-schema.v0.13.json) | `0.13` |
| Report schema (v0.12 frozen reference) | [`docs/report-schema.v0.12.json`](docs/report-schema.v0.12.json) | `0.12` |
| Report schema (v0.11 frozen reference) | [`docs/report-schema.v0.11.json`](docs/report-schema.v0.11.json) | `0.11` |
| Report schema (v0.10 frozen reference) | [`docs/report-schema.v0.10.json`](docs/report-schema.v0.10.json) | `0.10` |
| Report schema (v0.9 frozen reference) | [`docs/report-schema.v0.9.json`](docs/report-schema.v0.9.json) | `0.9` |
| Report schema (v0.8 frozen reference) | [`docs/report-schema.v0.8.json`](docs/report-schema.v0.8.json) | `0.8` |
| Report schema (v0.7 frozen reference) | [`docs/report-schema.v0.7.json`](docs/report-schema.v0.7.json) | `0.7` |
| Report schema (v0.6 frozen reference) | [`docs/report-schema.v0.6.json`](docs/report-schema.v0.6.json) | `0.6` |
| Packet schema (Release Evidence Packet, latest) | [`docs/packet-schema.v0.7.json`](docs/packet-schema.v0.7.json) | `0.7` |
| Capability standard | [`docs/capability-standard.md`](docs/capability-standard.md) | `0.1` |
| Capability lock schema | [`docs/capability-lock-schema.v0.2.json`](docs/capability-lock-schema.v0.2.json) | `0.2` |
| Capability lock diff schema | [`docs/capability-lock-diff-schema.v0.3.json`](docs/capability-lock-diff-schema.v0.3.json) | `0.3` |
| Governance benchmark catalog schema | [`docs/governance-benchmark-catalog-schema.v0.2.json`](docs/governance-benchmark-catalog-schema.v0.2.json) | `0.2` |
| Governance benchmark result schema | [`docs/governance-benchmark-result-schema.v0.2.json`](docs/governance-benchmark-result-schema.v0.2.json) | `0.2` |
| Check catalog | [`docs/checks.json`](docs/checks.json) | regenerated each release |
| Anti-patterns (what NOT to write) | [`samples/_anti_patterns/`](samples/_anti_patterns/) | reference |
| Minimal manifest example | [`docs/manifest-v0.1.example.minimal.yaml`](docs/manifest-v0.1.example.minimal.yaml) | reference |
For VS Code / Cursor live YAML validation, every manifest produced by `init` includes:
```yaml
# yaml-language-server: $schema=https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/manifest-v0.1.json
```
---
## Stable command surface
Promised to not break in `0.x` minor versions. See [STABILITY.md](STABILITY.md) for the full contract.
| Command | Stable flags |
|---|---|
| `agents-shipgate scan` | `-c`, `--out`, `--format`, `--ci-mode`, `--fail-on`, `--baseline`, `--diff-from`, `--changed-files`, `--no-plugins`, `--no-heuristics`, `--verbose`, `--packet`/`--no-packet`, `--packet-format` |
| `agents-shipgate evidence-packet` | `--from`, `--out`, `--format`, `--json` |
| `agents-shipgate init` | `--workspace`, `--write`, `--json` |
| `agents-shipgate doctor` | `-c`, `--workspace`, `--json`, `--verbose` |
| `agents-shipgate contract` | `--json` |
| `agents-shipgate explain` | ``, `--no-plugins`, `--json` |
| `agents-shipgate explain-finding` | ``, `--from`, `--no-plugins`, `--json` |
| `agents-shipgate findings` | `--from`, `--provenance-kind`, `--include-suppressed`, `--json` |
| `agents-shipgate trigger` | `--workspace`, `--changed-files`, `--diff`, `--base`, `--head`, `--manifest-present`/`--no-manifest-present`, `--user-requested`, `--list-rules`, `--json` |
| `agents-shipgate bootstrap` | `--workspace`, `--confidence`, `--no-ci`, `--no-apply`, `--json` |
| `agents-shipgate list-checks` | `--json`, `--no-plugins` |
| `agents-shipgate baseline save` | `-c`, `--out`, `--owner`, `--reason`, `--expires`, `--apply-to-existing` |
| `agents-shipgate baseline status` | `--baseline`, `--as-of`, `--require-owner`, `--require-expiry`, `--max-age-days`, `--json` (gate flags exit `20` on violations) |
| `agents-shipgate fixture` | `list`, `run`, `copy`, `verify` |
| `agents-shipgate self-check` | `--json` |
| `agents-shipgate agent handoff` | `--from`, `--report`, `--verify-run`, `--out`, `--json` |
Newer commands (stable intent, flags may still evolve):
| Command | Purpose |
|---|---|
| `shipgate audit --host` | Zero-config, read-only inventory of coding-agent host grants (MCP servers, permission rules, hooks, workflow scopes); `--json` available. Works without `shipgate.yaml`. |
| `agents-shipgate mcp-serve` | Local read-only stdio MCP server (`[mcp]` extra) exposing `shipgate.check`, `shipgate.preflight`, `shipgate.explain`, `shipgate.capabilities`, and `shipgate.handoff`. See [`docs/mcp-server.md`](docs/mcp-server.md). |
| `agents-shipgate org status` | Local organization governance projection over exception hygiene, policy-pack pins, host-grant drift, and registry readiness; `--json` available and governance violations exit `20`. |
| `agents-shipgate registry` | `ingest --attestation ` / `query` / `report --bypass` — local capability-release ledger over attestations. |
| `agents-shipgate install-hooks` | Claude Code hooks: PreToolUse trust-root boundary (`ask`/`deny`), PostToolUse trigger nudge, Stop verify. |
### Release Evidence Packet (v0.7)
`scan` emits a reviewer-shaped Release Evidence Packet alongside
`report.{md,json}` by default; outputs land at
`agents-shipgate-reports/packet.{md,json,html}` (and `packet.pdf` with the
`[pdf]` extras). The packet is derived from the report JSON, is a local
artifact only, and never gates — §1's verdict derives from
`release_decision.decision` alone, and §10 always lists what the packet did
NOT prove. Use `--no-packet` / `--packet-format` on `scan`, and
`agents-shipgate evidence-packet --from ` to
re-render. The full packet contract (fixed sections, disclaimers,
`evidence_matrix` rules) lives in
[STABILITY.md §Release Evidence Packet](STABILITY.md#release-evidence-packet-v07)
and [`docs/agent-contract-current.md`](docs/agent-contract-current.md#read-these-for-release-review).
Exit codes (stable):
| Code | Meaning |
|---|---|
| `0` | Pass (advisory or strict-no-blockers) |
| `2` | Manifest config error |
| `3` | Input parse error (file missing, malformed, path traversal blocked, file too large) |
| `4` | Other Agents Shipgate error |
| `20` | Strict-mode gate failure |
---
## What you can't do (intentionally)
This section is the **CLI's** invariants. For the **agent's** behavioral boundary — what an agent driving Shipgate may assert in PR comments and review summaries — see [`docs/agent-autofix-boundary.md`](docs/agent-autofix-boundary.md).
- The CLI does not modify user code; it only reads.
- The CLI does not connect to MCP servers; it reads exported JSON only.
- Tool sources outside the manifest directory are rejected (path traversal containment).
- Files larger than 10 MB are rejected.
- Plugins are off by default (`AGENTS_SHIPGATE_ENABLE_PLUGINS=1` to enable; `--no-plugins` to force off).
---
## When you make changes to this repo
- Run `python -m ruff check .` and `python -m pytest` before committing.
- Bumping a check's behavior requires updating the test suite and any golden fixtures under `samples/*/expected/`.
- New checks must include: code in `src/agents_shipgate/checks/.py` plus a `BUILTIN_CHECKS` entry in `checks/registry.py`, metadata in `docs/checks/.yaml` (loaded into `CHECK_METADATA` at registry import time by `agents_shipgate.checks._metadata_loader`), a test in `tests/`, and a row in `docs/checks.md`. After editing YAML, regenerate `docs/checks.json` with `python scripts/generate_schemas.py`.
- Do not change check IDs in published versions; always add new ones.
- If you regenerate the JSON schemas, run `python scripts/generate_schemas.py` and commit every changed file under `docs/`.
---
## Reusable prompts
Prebuilt prompts for common workflows live in [`prompts/`](prompts/):
- [`decide-shipgate-relevance.md`](prompts/decide-shipgate-relevance.md) — apply [`docs/triggers.json`](docs/triggers.json) to decide whether Shipgate should run at all
- [`add-shipgate-to-repo.md`](prompts/add-shipgate-to-repo.md) — bootstrap a repo
- [`fix-top-finding.md`](prompts/fix-top-finding.md) — iterate on a single finding
- [`recommend-fixes.md`](prompts/recommend-fixes.md) — walk all active findings and surface targeted fix recommendations across the four autofix-policy classes
- [`explain-finding-to-user.md`](prompts/explain-finding-to-user.md) — translate one finding into 3–5 sentences of user-facing prose; companion to `agents-shipgate explain-finding`
- [`stabilize-strict-mode.md`](prompts/stabilize-strict-mode.md) — tune → baseline → promote
- [`triage-false-positive.md`](prompts/triage-false-positive.md) — override vs suppress decision
- [`upgrade-shipgate-version.md`](prompts/upgrade-shipgate-version.md) — bump agents-shipgate version safely (regenerate baseline if needed)
For downstream repos, use [`docs/target-repo-agent-snippets.md`](docs/target-repo-agent-snippets.md)
to copy Shipgate trigger rules into `AGENTS.md`, `CLAUDE.md`, Cursor rules,
PR templates, and advisory CI. Use
[`docs/agent-adoption-harness.md`](docs/agent-adoption-harness.md) to evaluate
whether coding agents discover and use Shipgate without being prompted by name.
### Editor / agent integrations
Per-agent install guides for dropping Shipgate into your own agent project:
- [`docs/agents/use-with-claude-code.md`](docs/agents/use-with-claude-code.md) — install the `/shipgate` slash command and `agents-shipgate` auto-discoverable skill. Source surfaces ship at [`.claude/commands/shipgate.md`](.claude/commands/shipgate.md) and [`skills/agents-shipgate/`](skills/agents-shipgate/) (named `agents-shipgate` to avoid colliding with the slash command — Claude Code lets a same-named skill preempt a command). The skill bundles the recipes in [`skills/agents-shipgate/prompts/`](skills/agents-shipgate/prompts/) and a starter advisory CI workflow at [`skills/agents-shipgate/ci-recipes/advisory-pr-comment.yml`](skills/agents-shipgate/ci-recipes/advisory-pr-comment.yml); when you change anything in [`prompts/`](prompts/) or `examples/github-actions/01-advisory-pr-comment.yml`, sync the bundled copy.
- [`docs/agents/use-with-codex.md`](docs/agents/use-with-codex.md) — install the canonical `AGENTS.md` snippet plus repo-scoped Codex skill. Source surfaces ship at [`.agents/skills/agents-shipgate/`](.agents/skills/agents-shipgate/) and are generated into downstream repos with `agents-shipgate init --write --agent-instructions=agents-md,codex-skill`. The default `all` kit does not install skill bundles. The skill is Codex-optimized: concise `SKILL.md`, on-demand references, and an advisory CI template.
- [`docs/agents/use-with-cursor.md`](docs/agents/use-with-cursor.md) — drop the canonical `.cursor/rules/agents-shipgate.mdc` auto-attach rule (from [`docs/target-repo-agent-snippets.md`](docs/target-repo-agent-snippets.md)) into your repo. The rule fires whenever a chat touches `shipgate.yaml`, an MCP/OpenAPI spec, a tool JSON, or a `.py` file.
---
## Verification
After you (the agent) complete a task involving Agents Shipgate, verify:
1. `agents-shipgate self-check --json` returns `"ready": true`.
2. `agents-shipgate contract --json` matches the installed CLI contract you expect.
3. The user's `shipgate.yaml` has no `CHANGE_ME` placeholders.
4. A scan completes with exit code 0 (advisory mode) and writes `report.json`.
5. The user's repo `.gitignore` includes `agents-shipgate-reports/` (do not commit reports).