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
6 changes: 3 additions & 3 deletions .well-known/agents-shipgate.json
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@
"agent_handoff_schema_version": "shipgate.agent_handoff/v9",
"agent_handoff_schema_path": "docs/agent-handoff-schema.v9.json",
"agent_handoff_artifact": "agents-shipgate-reports/agent-handoff.json",
"contract_version": "41",
"contract_version": "42",
"minimum_control_contract_version": "21",
"local_agent_contract_schema_version": "10",
"inputs": [
Expand Down Expand Up @@ -305,7 +305,7 @@
"capability_delta_attestation_url": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/capability-delta-attestation.md",
"capability_delta_verifier_url": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/tools/verify-capability-delta.py",
"capability_delta_attestation_artifact": "agents-shipgate-reports/capability-delta-attestation.json",
"preflight_schema_version": "0.5",
"preflight_schema_version": "0.6",
"attestation_schema_version": "0.5",
"registry_schema_version": "0.4",
"org_evidence_bundle_schema_version": "shipgate.org_evidence_bundle/v2",
Expand Down Expand Up @@ -513,7 +513,7 @@
"human_authorization": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/human-authorization-schema.v1.json",
"agent_handoff": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/agent-handoff-schema.v9.json",
"packet": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/packet-schema.v0.18.json",
"preflight": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/preflight-schema.v0.5.json",
"preflight": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/preflight-schema.v0.6.json",
"capability_lock": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/capability-lock-schema.v0.8.json",
"capability_lock_diff": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/capability-lock-diff-schema.v0.9.json",
"capability_payload": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/capability-payload-schema.v1.json",
Expand Down
8 changes: 6 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,11 @@ agents-shipgate preflight --capability-request request.json --json

Switch on `control.state`. If it is `human_review_required`, stop and route the
change to a human. If it is `agent_action_required`, perform only the exact
coding-agent route in `control.next_action`. The plan form accepts `changed_files[]`,
coding-agent route in `control.next_action`. If it is `planning_only` (preflight
`0.6`, contract v42), the plan named nothing for preflight to route — an empty
plan, for example. Only planning completed: every `control.permissions` value
is `false`. Preflight never authorizes merge or completion, and never returns
`complete`. 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
Expand Down Expand Up @@ -831,7 +835,7 @@ For the short, current statement of "which fields to read", see [`docs/agent-con
| Agent result schema (current) | [`docs/agent-result-schema.v3.json`](docs/agent-result-schema.v3.json) | `agent_result_v3` |
| Verifier schema (current) | [`docs/verifier-schema.v0.21.json`](docs/verifier-schema.v0.21.json) | `0.21` |
| Agent handoff schema (current) | [`docs/agent-handoff-schema.v9.json`](docs/agent-handoff-schema.v9.json) | `shipgate.agent_handoff/v9` |
| Preflight schema (current) | [`docs/preflight-schema.v0.5.json`](docs/preflight-schema.v0.5.json) | `0.5` |
| Preflight schema (current) | [`docs/preflight-schema.v0.6.json`](docs/preflight-schema.v0.6.json) | `0.6` |
| Host-grants inventory schema | [`docs/host-grants-inventory-schema.v0.7.json`](docs/host-grants-inventory-schema.v0.7.json) | `0.7` |
| Host-grants baseline schema | [`docs/host-grants-baseline-schema.v0.7.json`](docs/host-grants-baseline-schema.v0.7.json) | `0.7` |
| Host-grants drift schema | [`docs/host-grants-drift-schema.v0.7.json`](docs/host-grants-drift-schema.v0.7.json) | `0.7` |
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Changes

- **An empty preflight plan no longer grants merge or completion.** A plan that named no changed file, capability request or host permission request returned the shared `complete` state, whose permissions include `merge` and `report_complete`, with no verifier run behind it. Preflight `0.6` answers it with the new `planning_only` state, which owes no action and authorizes nothing, and every preflight route now denies every permission in both the model and the published schema; `complete` and `review_publishable` cannot appear. Docs-only plans still route to `verify`, and protected surfaces and drift still stop for a human. `0.5` stays frozen and readable as a base preflight. Runtime contract 41 → 42; `minimum_control_contract_version` stays 21. Hooks written by `install-hooks` before this change accept only preflight `0.5`, so their instruction-structure check fails closed until `install-hooks --write` is re-run. See the `planning-only preflight` migration note in `STABILITY.md`. (#610)
- Move the published-release pins, examples and adoption prompts to `v1.2.0` (contract 41) now that it is published, re-capture the README and quickstart `diff` answers from the published `1.2.0`, and re-measure the pilot ledger's Route H dry run on it. No schema or contract change. (#778)

## 1.2.0 - 2026-09-30
Expand Down
3 changes: 2 additions & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ with bounded host reliability maintenance. Accountable owner: Pengfei Hu
[Days 1–5 evidence and ordered backlog](docs/research/application-days1-5/README.md)
records released/main reproductions and the #580/#655 comparison design.
Weeks 2–3 implement paired inputs, then per-agent wiring; deeper readers follow
reproduced gaps. #610 remains a reproduced contract defect; #787 is the selected
reproduced gaps. #610 was a reproduced contract defect until #925 (preflight
`0.6`, `planning_only`); #787 is the selected
recipe repair. #795/#812/#780/#369 retain their exact residual acceptance.

This selection supersedes the scheduling and recruitment instructions in the
Expand Down
80 changes: 78 additions & 2 deletions STABILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

What agents and CI integrations can rely on across versions of Agents Shipgate.

Unreleased, runtime contract v42: an empty preflight plan no longer mints
authority (#610). Through preflight `0.5`, a plan that named nothing to route
returned the shared `complete` state with every permission granted, `merge`
and `report_complete` included, and no verifier identity behind it. Preflight
`0.6` answers it with `planning_only`, which owes no action and authorizes
nothing, and on every preflight route every permission is now `false`.
Preflight never returns `complete` or `review_publishable`. `0.5` stays frozen
and readable. `minimum_control_contract_version` stays `21`. See
[the migration note](#planning-only-preflight-610).

New in 1.2.0, #829 adds a source-local residual-prefix explanation to the existing
host comparison row `why` text for supported Claude Code `git push` allows.
It reads all compared head deny rules in that source, including unchanged
Expand Down Expand Up @@ -312,6 +322,69 @@ the Action tag) for reproducible CI.

---

<a id="planning-only-preflight-610"></a>

## Migration Note: Unreleased — planning-only preflight (preflight `0.6`, contract v42, #610)

**What was wrong.** Preflight answers a question about a change that has not
been made yet, so it never has an evaluated change to stand behind. Yet a plan
that named no changed file, capability request or host permission request, with
no drift signal, returned the shared `complete` state, and that state's
`permissions` grant `edit`, `commit`, `push`, `update_pr`, `merge` and
`report_complete`. Leaving files out of a plan therefore read as merge
authority, with no verifier run and no current-control identity behind it. The
published `0.5` schema accepted that payload too: it pins `update_pr` to
`false` only while the state is not `complete`, so a schema-valid `0.5` answer
could carry merge authority. (`0.4` pinned it unconditionally and refused it.)

**What changes.** `preflight_schema_version` is `0.6`
([`docs/preflight-schema.v0.6.json`](docs/preflight-schema.v0.6.json)), and
`control` is preflight's own union:

- `planning_only` (new): nothing for preflight to route. `next_action` is
`null`, `allowed_next_commands` is empty, `completion_allowed`, `must_stop`
and `verify_required` are `false`, and `reason` says only planning finished.
The legacy `first_next_action` still projects `continue`, as it did.
- `agent_action_required`: unchanged; its `next_action` is the exact `verify`
command.
- `human_review_required`: unchanged.

`complete` and `review_publishable` cannot appear, and every permission is
`false` on every route. The model and the generated schema enforce both, and
both refuse a stored `0.6` control that does not state all six permissions. A
planning answer therefore never stands in for an evaluation of the change:
preflight never authorizes merge or completion.

**Who must act.**

- A reader that switched on preflight's `control.state == "complete"` now sees
`planning_only`. Treat it as "nothing to route, nothing authorized". A
reader that does not know the state must not read it as `complete`; the
vector beside it denies everything either way.
- A `.claude/hooks/agents-shipgate.py` written by `install-hooks` before this
change accepts only `preflight_schema_version: "0.5"`. Against a `0.6` CLI
its instruction-structure check fails closed: an instruction edit whose
structure is unchanged is prompted instead of allowed, and nothing is
allowed that was not before. Re-run `agents-shipgate install-hooks --write`;
the new script accepts `0.5` and `0.6`.

**What stays readable.** `0.5` and earlier stay frozen and published. A stored
`0.5` answer still reads as `0.5` through `--base-preflight` or
`shipgate.preflight`'s `base_preflight`, `complete` included, because that is
what it was; relabelled `0.6`, the same payload is refused. Both readers, the
CLI and the core builder, now parse a stored answer through one version ladder,
so a version cannot be readable in one and refused by the other.

**What does not change.** Routes for any plan that names something — a
docs-only plan still owes `verify`, and a protected surface still stops for a
human — and `signals[]`, `required_evidence[]`, `protected_surface_touches[]`,
the trust-root graph and its hash, the policy hash, host-grant drift, `verify`,
`check`, `current-control.json` and `release_decision.decision`. The shared
`AgentControl` union is byte-identical, so `minimum_control_contract_version`
stays `21`.

---

<a id="hook-script-dependencies-702"></a>

## Migration Note: 1.2.0 — selected hook script dependencies (#702)
Expand Down Expand Up @@ -3758,8 +3831,11 @@ or claim merge safety. `release_decision.decision` remains the only release gate

The stable top-level fields in the v0.3 preflight result are:

- `preflight_schema_version` — currently `"0.3"`.
- `control` — the shared `AgentControl` operational projection.
- `preflight_schema_version` — currently `"0.6"`.
- `control` — preflight's own operational projection: `planning_only`,
`agent_action_required` or `human_review_required`, with every permission
`false`. Through `0.5` it was the shared `AgentControl`; see
[the migration note](#planning-only-preflight-610).
- `workspace` and `config` — resolved workspace and manifest path context.
- `protected_surfaces[]` — canonical trust-root surfaces with `kind`, `pattern`,
`scope_type`, `present`, and `present_paths`.
Expand Down
5 changes: 3 additions & 2 deletions docs/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@ remain separate, pending work.
- [`codex-boundary-result-schema.v2.json`](codex-boundary-result-schema.v2.json) — frozen deprecated compatibility projection for `--format codex-boundary-json`
- [`codex-boundary-result-schema.v1.json`](codex-boundary-result-schema.v1.json) — frozen boundary v1 reference
- [`agent-result-schema.v1.json`](agent-result-schema.v1.json) — legacy JSON Schema retained for existing local-agent protocol and MCP surfaces; not emitted by `agents-shipgate verify`
- [`preflight-schema.v0.5.json`](preflight-schema.v0.5.json) — current proactive preflight control schema
- [`preflight-schema.v0.4.json`](preflight-schema.v0.4.json) — frozen prior reference; no inferred structural comparison
- [`preflight-schema.v0.6.json`](preflight-schema.v0.6.json) — current proactive preflight control schema; `planning_only`, and no permission on any route
- [`preflight-schema.v0.5.json`](preflight-schema.v0.5.json) — frozen prior reference; an empty plan returned the shared `complete`
- [`preflight-schema.v0.4.json`](preflight-schema.v0.4.json) — frozen reference; no inferred structural comparison
- [`policy-pack-schema.v0.4.json`](policy-pack-schema.v0.4.json) — JSON Schema for local policy-pack YAML files (current; selectors are evaluated against typed predicate evidence)
- [`policy-pack-schema.v0.3.json`](policy-pack-schema.v0.3.json) — frozen v0.3 policy-pack reference
- [`policy-pack-schema.v0.2.json`](policy-pack-schema.v0.2.json) — frozen v0.2 policy-pack reference
Expand Down
33 changes: 28 additions & 5 deletions docs/agent-contract-current.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Current Agent Contract

Runtime contract v42, unreleased, stops an empty preflight plan from minting
authority (#610). Through preflight `0.5` a plan that named nothing to route
returned the shared `complete` state, whose `permissions` grant `merge` and
`report_complete`, with no verifier identity behind it. Preflight `0.6` has its
own control union: `planning_only`, `agent_action_required` and
`human_review_required`. `planning_only` is new and means only that
planning finished, because the plan named no changed file, capability request
or host permission request and no drift signal fired; it has no `next_action`.
Preflight never returns `complete` or `review_publishable`, and every
permission is `false` on every route, in the model and in
[`docs/preflight-schema.v0.6.json`](preflight-schema.v0.6.json) alike, so
leaving files out of a plan can never stand in for an evaluation of the
change: preflight never authorizes merge or completion. `0.5` stays frozen
and readable as a
`--base-preflight`; `minimum_control_contract_version` stays `21`, because
the shared `AgentControl` union is unchanged and a reader that does not know
`planning_only` cannot mistake it for `complete`. See
[the migration note](../STABILITY.md#planning-only-preflight-610).

Runtime contract v41, new in 1.2.0, names the changed inputs a host comparison
does not read (#821). A zero-row comparison used to print "No static
host-grant changes detected" for a pull request that added a Cursor plugin's
Expand Down Expand Up @@ -235,7 +254,8 @@ schemas are unchanged; all setup permissions remain false.

Runtime contract v32 separates instruction prose from supported parsed permission
structure across verification, preflight, host drift and generated edit hooks.
It publishes verifier v0.17, handoff v9, preflight v0.5 and host evidence v0.3.
It publishes verifier v0.17, handoff v9, preflight v0.5 and host evidence v0.3;
preflight v0.6 (#610) keeps that structure and changes only its control.
Raw identity still changes on prose edits; legacy evidence is never upgraded to
a new permission claim. `conditional_file_edits` is a standing routing rule with
`grants_authority: false`, separate from unconditional `forbidden_file_edits`.
Expand Down Expand Up @@ -777,7 +797,7 @@ Downstream repos generated with

- Latest release: `v1.2.0`
- In-tree runtime: `1.2.0` — see [pyproject.toml](../pyproject.toml)
- Runtime contract: `41` (minimum control contract: `21`)
- Runtime contract: `42` (minimum control contract: `21`)
- Current report schema: `1.0`, frozen, superseding `0.43` — [`docs/report-schema.v1.0.json`](report-schema.v1.0.json); the `1.x` rules are in [`docs/report-1-0-contract.md`](report-1-0-contract.md)
- Current packet schema: `0.18` — [`docs/packet-schema.v0.18.json`](packet-schema.v0.18.json)
- Current shared agent result schema: `agent_result_v3` — [`docs/agent-result-schema.v3.json`](agent-result-schema.v3.json)
Expand All @@ -790,7 +810,7 @@ Downstream repos generated with
- Current agent handoff schema: `shipgate.agent_handoff/v9` — [`docs/agent-handoff-schema.v9.json`](agent-handoff-schema.v9.json)
- Current agent boundary result schema: `shipgate.agent_boundary_result/v3` — [`docs/agent-boundary-result-schema.v3.json`](agent-boundary-result-schema.v3.json)
- Frozen deprecated Codex projection: `shipgate.codex_boundary_result/v2` — [`docs/codex-boundary-result-schema.v2.json`](codex-boundary-result-schema.v2.json)
- Current preflight schema: `0.5` — [`docs/preflight-schema.v0.5.json`](preflight-schema.v0.5.json)
- Current preflight schema: `0.6` — [`docs/preflight-schema.v0.6.json`](preflight-schema.v0.6.json) (`0.5` and earlier stay frozen; `0.6` adds `planning_only` and denies every permission on every route)
- Current downstream local agent contract schema: `10`
- Current capability standard: `0.5` — [`docs/capability-standard.md`](capability-standard.md)
- Current capability lock schema: `0.8` — [`docs/capability-lock-schema.v0.8.json`](capability-lock-schema.v0.8.json)
Expand Down Expand Up @@ -1082,7 +1102,7 @@ they do not replace the gate above and must not introduce a second verdict.
proactive routing surface for coding agents before edits. It accepts a single
`PreflightPlanV1` object with `changed_files[]`, optional `diff_text`,
`capability_requests[]`, `host_permission_requests[]`, and
`context.{agent,task}`. The emitted `PreflightResultV5` reports protected
`context.{agent,task}`. The emitted `PreflightResultV6` reports protected
surfaces, forbidden shortcut actions, required evidence for proposed high-risk
capabilities, host-grant drift when a host baseline is present, deterministic
`signals[]`, `control`, `requires_verify`, `verification_command`,
Expand All @@ -1092,7 +1112,10 @@ only appends valid built-in `tool_sources` rows may mark that manifest touch
authorizes proposal authorship only: existing rows and all other manifest
values must be unchanged, authority-bearing fields and custom adapters are
excluded, and the resulting trust-root diff still requires human review. It is
not a second gate; it must never be read as passed or mergeable. The release
not a second gate; it must never be read as passed or mergeable. Its `control.state`
is `planning_only`, `agent_action_required` or `human_review_required`,
never `complete`, and every `control.permissions` value is `false` on all
three (#610). The release
gate remains `release_decision.decision`.

## Read these first for release gating
Expand Down
9 changes: 5 additions & 4 deletions docs/agent-recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ policy packs, baselines, waivers, suppressions, Codex hooks/config, Codex
plugin manifests, `.mcp.json`, `.app.json`, or `SKILL.md`, run
`agents-shipgate preflight --workspace . --plan - --json` with a
`PreflightPlanV1` object. Legacy `--changed-files` remains available. Switch on
`control.state`. If it is `review_publishable`, a human must approve the merge
and you may still commit, push, and update the PR; if it is
`human_review_required`, stop for a human; if it is
`control.state`. If it is `human_review_required`, stop for a human; if it is
`agent_action_required`, perform only the exact coding-agent action in
`control.next_action` — its `command` when it names one, and otherwise the
input its `expects` names, which is the shape a `fetch_base` route carries.
input its `expects` names, which is the shape a `fetch_base` route carries; if
it is `planning_only` (preflight `0.6`), the plan named nothing for
preflight to route and nothing is authorized: every `control.permissions`
value is `false`. Preflight never returns `complete` or `review_publishable`.

Do not claim completion unless `control.state` is `complete`. Conversation-level
acknowledgement never changes control state; only a newly generated verifier
Expand Down
Loading
Loading