Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/skills/agents-shipgate/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
---
name: agents-shipgate
description: Use when the user wants to run the prominent Agents Shipgate flows — `shipgate check`, `agents-shipgate verify`, or `shipgate audit --host` — for AI agent capability changes, PR release readiness, or coding-agent host grants.
Expand All @@ -20,7 +20,7 @@
5. Default first-time CI to advisory mode. Do not enable release-blocking CI or save a baseline until a human has reviewed current findings.
6. For local agent control, run `shipgate check --agent codex --workspace . --format agent-boundary-json` and read the stdout `shipgate.agent_boundary_result/v1` object. Switch on `control.state`; follow only `control.next_action`, `control.allowed_next_commands`, and `control.human_review`. Treat `decision` as diagnostic context only.
7. Before editing `shipgate.yaml`, Shipgate CI, AGENTS/CLAUDE/Cursor rules, policy packs, baselines, waivers, suppressions, Codex hooks/config, Codex plugin manifests, `.mcp.json`, `.app.json`, or `SKILL.md`, plan to run `agents-shipgate verify` before completion and route trust-root review to a human when the verifier requires it.
8. For full PR verification, validate `agents-shipgate-reports/verification-receipt.json` first, then read `agent-handoff.json` and switch on `control.state`; read `verifier.json` for detailed control state, `verify-run.json` for the request graph, and `report.json` for reviewer detail. `report.json.release_decision.decision` remains the release gate.
8. For full PR verification, validate `agents-shipgate-reports/verification-receipt.json` first, then read `agent-handoff.json` and switch on `control.state`; read `verifier.json` for detailed control state, `verify-run.json` for the request graph, and `report.json` for reviewer detail. `report.json.release_decision.decision` remains the release gate. Refresh `agents-shipgate-reports/current-control.json` with `agents-shipgate agent control --workspace .` — which refuses the read when HEAD, the tree, or the working tree has moved since the decision — before you act on any of that, and again before enforcing a cached `must_stop`, before commit/push/PR update, before merge, and before declaring the task complete. A non-zero exit means no control identity is current and you hold no authority; if `current_control_id` changed, discard every cached control state and restart from the new identity. A result remembered from earlier in the conversation never outranks the current pointer, in either direction.
9. Auto-apply only high-confidence safe patches. Do not auto-assert action effect, action authority, agent bindings, approval, confirmation, idempotency, broad-scope, prohibited-action, or runtime-trace evidence.
10. Ensure `.gitignore` covers `agents-shipgate-reports/` before committing.

Expand Down
9 changes: 7 additions & 2 deletions .agents/skills/agents-shipgate/references/report-reading.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
# Reading Agents Shipgate Reports

For verify runs, validate `agents-shipgate-reports/verification-receipt.json`
first. Then read `agents-shipgate-reports/agent-handoff.json`. After that,
For verify runs, read `agents-shipgate-reports/current-control.json` first —
via `agents-shipgate agent control --workspace .` — because it names which run
is current, checks it against the repository as it stands right now, and a
non-zero exit means none is. Then validate the
`agents-shipgate-reports/verification-receipt.json` it binds. Then read
`agents-shipgate-reports/agent-handoff.json`. After that,
read `agents-shipgate-reports/verifier.json` for detailed control context
and `agents-shipgate-reports/report.json` for findings. Do not scrape Markdown.

## Order

0. `current-control.json.current_control_id` / `lifecycle_state` / `control.state`: which run is current, and whether any decision is. Re-read this before enforcing a cached `must_stop`, before commit/push/PR update, before merge, and before declaring the task complete; if the id changed, discard cached control state and start again from the new identity.
1. `agent-handoff.json.control.state`: `complete`, `agent_action_required`, or `human_review_required`.
2. `agent-handoff.json.capability_review.top_changes[]`: the highest-signal tool/action or trust-root changes.
3. `agent-handoff.json.next_action` / `control.next_action` / `fix_task`: who acts next and whether a coding agent may safely attempt the fix.
Expand Down
6 changes: 4 additions & 2 deletions .claude/commands/shipgate.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
---
description: "Run the prominent Agents Shipgate flows: check, verify, or audit --host"
---
Expand Down Expand Up @@ -48,7 +48,8 @@

1. Set `AGENTS_SHIPGATE_AGENT_MODE=1` for every CLI call so errors emit a `next_action` JSON line on stderr.
2. Run `agents-shipgate contract --json` when available and use it to verify the installed CLI's schema versions and gating signal.
3. For verifier runs, validate `agents-shipgate-reports/verification-receipt.json` first,
3. For verifier runs, read `agents-shipgate-reports/current-control.json` first,
then validate the `agents-shipgate-reports/verification-receipt.json` it binds,
then parse `agents-shipgate-reports/agent-handoff.json`,
then `verifier.json`, `verify-run.json`, and
`report.json.release_decision.decision` as the release gate.
Expand Down Expand Up @@ -78,7 +79,8 @@
agents-shipgate verify --base origin/main --head HEAD --json
```

Validate `agents-shipgate-reports/verification-receipt.json` first, then read
Read `agents-shipgate-reports/current-control.json` first, then validate the
`agents-shipgate-reports/verification-receipt.json` it binds, then read
`agents-shipgate-reports/agent-handoff.json` and lead with
`gate.merge_verdict` (a deterministic projection of `release_decision.decision`,
which remains the gate in `report.json`), then the authoritative substrate
Expand Down
13 changes: 13 additions & 0 deletions .cursor/rules/agents-shipgate.mdc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
---
description: Run Agents Shipgate as the deterministic merge gate for AI-generated agent capability changes.
globs:
Expand Down Expand Up @@ -68,6 +68,19 @@
Legacy `agent-result.json` surfaces, where present, are supporting/provisional
projections and not the CI gate.

`agents-shipgate-reports/current-control.json` is the one entry point that
says which control identity is current. Read it with `agents-shipgate agent
control --workspace .`, which checks the pointer against the repository as it
stands right now — a moved HEAD, a changed tree, or an edited working file
refuses the read. A non-zero exit means nothing is current here and you hold no
authority. Re-read it after any human or external-tool action, after commit,
rebase, checkout, pull, or any worktree change, after any agents-shipgate
command returns, before enforcing a cached `must_stop`, before commit/push/PR
update, before merge or release, and before declaring the task complete. If
`current_control_id` changed, discard every cached control state and restart
from the new identity. A result you remember from earlier in this conversation
never outranks the current pointer — in either direction.

For coding-agent host grants, run:

shipgate audit --host --json --out agents-shipgate-reports/host-grants.json
Expand Down
30 changes: 29 additions & 1 deletion .well-known/agents-shipgate.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@
"verification_unit_result_schema_version": "shipgate.verification_unit_result/v1",
"verification_artifact_manifest_schema_version": "shipgate.verification_artifact_manifest/v1",
"verification_receipt_schema_version": "shipgate.verification_receipt/v1",
"current_control_schema_version": "shipgate.current_control/v1",
"current_control_schema_path": "docs/current-control-schema.v1.json",
"current_control_artifact": "agents-shipgate-reports/current-control.json",
"human_authorization_request_schema_version": "shipgate.human_authorization_request/v1",
"human_authorization_schema_version": "shipgate.human_authorization/v1",
"human_authorization_evaluation_schema_version": "shipgate.human_authorization_evaluation/v1",
Expand All @@ -195,7 +198,7 @@
"agent_handoff_schema_version": "shipgate.agent_handoff/v6",
"agent_handoff_schema_path": "docs/agent-handoff-schema.v6.json",
"agent_handoff_artifact": "agents-shipgate-reports/agent-handoff.json",
"contract_version": "19",
"contract_version": "20",
"minimum_control_contract_version": "14",
"local_agent_contract_schema_version": "7",
"inputs": [
Expand All @@ -213,6 +216,7 @@
"conductor"
],
"outputs": [
"current_control_json",
"markdown",
"json",
"sarif",
Expand Down Expand Up @@ -243,6 +247,7 @@
"governance_benchmark_result_json"
],
"artifacts": {
"current_control": "agents-shipgate-reports/current-control.json",
"verifier": "agents-shipgate-reports/verifier.json",
"verify_run": "agents-shipgate-reports/verify-run.json",
"agent_handoff": "agents-shipgate-reports/agent-handoff.json",
Expand Down Expand Up @@ -295,6 +300,7 @@
"skill_review"
],
"external_integration_surfaces": [
"current_control",
"agent_handoff",
"preflight",
"capability_lock",
Expand Down Expand Up @@ -404,6 +410,10 @@
"decision_id"
],
"agent_read_order": [
"current-control.json",
"current-control.json.current_control_id",
"current-control.json.lifecycle_state",
"current-control.json.control.state",
"verification-receipt.json",
"verification-receipt.json.request_id",
"verification-receipt.json.receipt_id",
Expand All @@ -414,6 +424,23 @@
"verify-run.json",
"report.json.release_decision.decision"
],
"agent_refresh_triggers": [
"after any human action or external tool action",
"after commit, rebase, checkout, pull, or any other worktree mutation",
"after any agents-shipgate command returns",
"before enforcing a cached must_stop",
"before commit, push, or PR update when permission depends on Shipgate",
"before merge or release",
"before declaring the task complete",
"whenever the observed request_id, HEAD, worktree identity, or current_control_id changes"
],
"current_control_fallback_read_order": [
"current-control.json",
"verification-receipt.json",
"agent-handoff.json",
"verifier.json",
"report.json"
],
"do_not_auto_assert": [
"action_effect",
"action_authority",
Expand All @@ -436,6 +463,7 @@
"runtime_behavior_verified": false,
"static_verdict_disclaimer": "This verdict covers deterministic static evidence only. Agents Shipgate did not execute the agent or prove runtime behavior, tool routing, credential enforcement, or safety.",
"schemas": {
"current_control": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/current-control-schema.v1.json",
"manifest": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/manifest-v0.1.json",
"report": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/report-schema.v0.34.json",
"agent_result": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/agent-result-schema.v2.json",
Expand Down
28 changes: 26 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# 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.
Expand Down Expand Up @@ -130,8 +130,10 @@
```

For local uncommitted verifier work, omit `--base`/`--head` so the working tree
is scanned. Validate `agents-shipgate-reports/verification-receipt.json`
first, then read `agents-shipgate-reports/agent-handoff.json` and lead
is scanned. Read `agents-shipgate-reports/current-control.json`
first — it names which run is current — then validate the
`verification-receipt.json` it binds, then read
`agents-shipgate-reports/agent-handoff.json` and lead
with `control.state`, then `gate.merge_verdict`
(`mergeable | human_review_required | insufficient_evidence | blocked |
unknown`), `gate.can_merge_without_human`, `next_action`,
Expand All @@ -145,6 +147,28 @@
changes the control state; conversation-level acceptance is not a gate
override.

Read the pointer with:

```bash
agents-shipgate agent control --workspace . --reports-dir agents-shipgate-reports
```

A zero exit means the printed pointer was validated against every artifact it
binds, still describes the repository as it stands right now, and did not move
while it was read. Byte consistency is not generation consistency: one commit
is enough to make an intact artifact set describe a workspace that has moved,
so the read compares the pointer's HEAD, tree, and worktree overlay against the
live repository and refuses on drift. A non-zero exit means no control identity
is current here — you hold no authority, and a remembered result does
not substitute for one. Re-read it after any human or external-tool action,
after commit, rebase, checkout, pull, or any worktree change, after any
agents-shipgate command returns, before enforcing a cached `must_stop`, before
commit/push/PR update, before merge or release, and before declaring the task
complete. If `current_control_id` changed, discard every cached control state
and restart from the new identity. This runs in both directions: a cached stop
must not survive a newer complete run, and a cached completion must not survive
a changed workspace.

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
Expand Down
60 changes: 60 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,66 @@

## Unreleased

- **A coding agent can no longer enforce a verifier result the workspace has
outgrown.** The reported failure ran forward: a worktree verify returned
`human_review_required`, a human committed the reviewed change, a fresh
committed-ref run produced a `complete` receipt for the same request — and the
agent kept enforcing the older `must_stop`, asking for the commit that had
already happened. It runs backward just as easily: a `complete` remembered
from earlier in a conversation is not evidence about a workspace that has
since been rebased, checked out, or reconfigured. The content-addressed
receipt already prevented an old decision from *authorizing a different
request*; what was missing was one atomic place to ask "what is current now?",
and any obligation to ask it. Both are now present.
`agents-shipgate-reports/current-control.json`
(`shipgate.current_control/v1`) is that entry point. It is a pointer, not a
second decision engine: it binds identities and hashes of the receipt,
handoff, verifier, and report those commands already publish. Its lifecycle is
what makes it trustworthy. `verify`, `verify --preview`, `scan`, and
`verification prepare` each replace it with a non-terminal `unavailable`
marker *before* touching any other artifact, so a run that crashes leaves a
directory that denies cached control instead of one that still advertises the
previous verdict for a workspace that has moved; the terminal pointer is
written last, after every artifact it references exists and has been hashed,
and published by same-directory `os.replace` so no reader can observe a
half-written one. Readers use the generation-safe protocol in `agents-shipgate
agent control`: validate the pointer, validate every artifact hash it binds,
re-read the pointer, and continue only if `current_control_id` is unchanged —
a run that republishes mid-read makes the read fail rather than return one
generation's pointer beside another's artifacts. And because byte consistency
is not generation consistency — every bound artifact still hashes correctly
one unrelated commit later — the read also compares the pointer's
`workspace_identity` against the live repository: repository, HEAD commit, and
HEAD tree, plus the base revision when the decision named one — advancing a
base until `base...HEAD` is empty changes the evidence completely while
leaving HEAD and the working tree untouched. Uncommitted work is checked
against what the decision actually covered: a worktree decision must still
hash to the overlay it committed to *and* see no live change outside the set
it recorded, while a committed-tree decision, whose evidence stops at HEAD, is
invalidated by any uncommitted change that appeared afterwards. Overlay rows
bind entry kind and the executable bit alongside content, so a `100755` →
`100644` flip or a regular-file-to-symlink swap with identical bytes cannot
pass as unchanged. Completion authority is never returned without that
comparison. Two invariants are structural rather than
advisory: only an `operation: "verify"` pointer can carry
`control.state: "complete"`, and only when it also binds a
`verification_receipt` whose request and decision are the ones the pointer
records — the assembler accepts any `--out` name under its artifacts root, so
an older canonical receipt cannot be mistaken for the one a run just closed.
A scan or a preview cannot represent completion authority at all, and each
pointer binds only the artifacts its own run wrote: a `scan --format markdown`
after a verify no longer claims that verifier's `report.json`.
Supporting scans stay isolated —
`verify`'s internal head scan does not take over the PR's control identity,
and `baseline save` already scanned into a temporary directory. Contract
`19 → 20` adds `current_control_schema_version`, `current_control_artifact`,
the `agent_refresh_triggers[]` list of boundaries at which a cached control
state expires, and `current_control_fallback_read_order[]` for consumers built
before the pointer existed; `agent_read_order[]` now starts at the pointer,
and the local downstream contract moves `7 → 8`. Generated agent instructions
and both adoption kits now require the refresh. No report, packet, verifier,
handoff, or receipt schema changed. ([#339](https://github.com/ThreeMoonsLab/agents-shipgate/issues/339))

- **An unreadable PR diff is no longer reported as "nothing here is
agent-related."** `verify --preview` collapsed every diff-acquisition failure
into one message, then evaluated the trigger catalog against the empty inputs
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,11 @@ The release gate is `agents-shipgate-reports/report.json` →
The PR/control surface is `agents-shipgate-reports/verifier.json` →
`merge_verdict` (`mergeable | human_review_required | insufficient_evidence |
blocked | unknown`), a deterministic projection of the release decision.
Validate `verification-receipt.json` first; then read `agent-handoff.json`
Read `agents-shipgate-reports/current-control.json` first — it names which run
is current, and `agents-shipgate agent control --workspace .` validates it
against every artifact it binds and against the live repository, refusing the
read when HEAD or the working tree has moved since the decision. Then validate the `verification-receipt.json` it binds; then
read `agent-handoff.json`
(`control.state`, then `gate.merge_verdict`), followed by the
authoritative control substrate `verifier.json` for `control`, `merge_verdict`,
`applicability`, `can_merge_without_human`,
Expand Down
12 changes: 12 additions & 0 deletions STABILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,19 @@ Stable JSON fields:
- `agent_handoff_artifact` — default emitted handoff artifact path.
- `codex_boundary_result_schema_version` — schema version emitted by
`shipgate check --format codex-boundary-json`.
- `current_control_schema_version` / `current_control_schema_path` /
`current_control_artifact` — schema version, checked-in JSON Schema path, and
default artifact path for `agents-shipgate-reports/current-control.json`, the
one atomic entry point naming the control identity that is current.
- `agent_refresh_triggers[]` — the boundaries at which a consumer must re-read
`current_control_artifact` before acting. A control state cached across any of
them is not authority.
- `current_control_fallback_read_order[]` — documented read order for consumers
built before the pointer existed. Its absence is evidence of an older
producer, never permission to act on a cached decision.
- `agent_read_order[]` — cross-artifact machine read order for coding agents:
`current-control.json` first (`current_control_id`, `lifecycle_state`,
`control.state`), then `verification-receipt.json`,
`agent-handoff.json.control.state`, then `verifier.json.control.state`,
`verify-run.json`, then
`report.json.release_decision.decision`.
Expand Down
Loading