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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
certify readiness.
- Added four `SHIP-EVIDENCE-*` checks. Existing baselines may surface these as
new findings after upgrade when a manifest opts into `validation:`.
- Add `agents-shipgate scenario suggest` (target: `0.9.1`), a YAML export that
fans out `report.json.suggested_scenarios[]` into concrete
per-finding/per-tool dynamic validation steps.

## 0.8.0 - 2026-05-05

Expand Down
18 changes: 18 additions & 0 deletions STABILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ These commands and flags are stable across all `0.x.y` releases. They will only
|---|---|
| `agents-shipgate scan` | `-c`, `--config`, `--out`, `--format`, `--ci-mode`, `--fail-on`, `--baseline`, `--no-plugins`, `--verbose`, `--workspace`, `--packet`/`--no-packet`, `--packet-format` |
| `agents-shipgate evidence-packet` | `--from`, `--out`, `--format`, `--json` |
| `agents-shipgate scenario suggest` | `--from`, `--out` |
| `agents-shipgate init` | `--workspace`, `--write`, `--json` |
| `agents-shipgate doctor` | `-c`, `--config`, `--workspace`, `--json`, `--verbose` |
| `agents-shipgate explain` | `<check_id>`, `--no-plugins`, `--json` |
Expand Down Expand Up @@ -58,6 +59,23 @@ In `agents-shipgate-reports/report.json`, the following are guaranteed:
- `tool_inventory[].{name, source_type, source_ref, risk_tags, auth_scopes, owner, confidence}`
- `loaded_plugins[].{name, value, distribution, version, check_id}`

### Scenario Suggestion YAML

`agents-shipgate scenario suggest --from agents-shipgate-reports/report.json`
projects `report.json.suggested_scenarios[]` into
`suggested-scenarios.yaml`. It is a concrete fan-out of the JSON report's
scenario contract, not a separate scenario engine.

Stable YAML fields:

- `scenarios[].{id, scenario_type, derived_from, finding_id, source_scenario_id, source_misalignment_id, tool, adversarial_goal, expected_control}`

Suppressed findings are omitted. Baseline-matched findings are included because
they represent accepted debt, not resolved risk. `adversarial_goal` text may
evolve in minor releases; the field itself remains stable. Rows follow the
source `suggested_scenarios[]` order, then sort within each source scenario by
severity, check ID, tool, finding ID, and misalignment ID.

#### `release_decision.decision` vs `summary.status`

These are **intentionally different signals**, kept apart for backwards compatibility:
Expand Down
13 changes: 13 additions & 0 deletions docs/agent-recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,19 @@ has at least one patch. Manual-only findings (e.g. trace approval
flips, per-check policy decisions) carry a single `ManualPatch` with
`instructions` instead of a machine-applicable patch.

Optional dynamic-validation handoff:

```bash
agents-shipgate scenario suggest \
--from agents-shipgate-reports/report.json \
--out agents-shipgate-reports/suggested-scenarios.yaml
```

This YAML is a concrete per-finding/per-tool fan-out of
`report.json.suggested_scenarios[]`, not a separate scenario engine.
Suppressed findings are omitted; baseline-matched findings remain because
they are accepted debt, not resolved risk.

### Step 4 · `apply-patches --confidence high --apply`

Default `--confidence high` only auto-applies patches whose `confidence`
Expand Down
8 changes: 8 additions & 0 deletions docs/integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,16 @@ For source-only testing in this repository:
agents-shipgate init --workspace . --write
agents-shipgate doctor --config shipgate.yaml
AGENTS_SHIPGATE_LOG_FORMAT=json agents-shipgate scan --config shipgate.yaml --verbose
agents-shipgate scenario suggest \
--from agents-shipgate-reports/report.json \
--out agents-shipgate-reports/suggested-scenarios.yaml
```

The scenario YAML is derived from `report.json.suggested_scenarios[]` and
fans static findings out into concrete sandbox/adversarial validation steps.
Baseline-matched findings remain in this export because they are accepted
debt, not resolved risk.

## GitLab CI

First-class GitLab CI recipes live in [`../examples/gitlab-ci/`](../examples/gitlab-ci/):
Expand Down
19 changes: 19 additions & 0 deletions src/agents_shipgate/cli/agent_mode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from __future__ import annotations

import json
import os
import sys


def emit_agent_mode_error(error_kind: str, **fields: object) -> None:
"""Emit a structured one-line error for coding-agent callers."""
if os.environ.get("AGENTS_SHIPGATE_AGENT_MODE", "").lower() not in {
"1",
"true",
"yes",
"on",
}:
return
payload = {"error": error_kind, **fields}
print(json.dumps(payload, default=str), file=sys.stderr)

14 changes: 3 additions & 11 deletions src/agents_shipgate/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import glob
import json
import logging
import os
import re
import sys
from difflib import get_close_matches
Expand All @@ -13,6 +12,7 @@

from agents_shipgate import __version__
from agents_shipgate.checks.registry import check_catalog
from agents_shipgate.cli.agent_mode import emit_agent_mode_error as _emit_agent_mode_error
from agents_shipgate.cli.apply_patches import apply_patches as _apply_patches_command
from agents_shipgate.cli.detect import detect as _detect_command
from agents_shipgate.cli.discovery import (
Expand All @@ -25,22 +25,13 @@
from agents_shipgate.cli.evidence_packet import evidence_packet as _evidence_packet_command
from agents_shipgate.cli.fixture import fixture_app
from agents_shipgate.cli.scan import inspect_sources, run_scan
from agents_shipgate.cli.scenario import scenario_app
from agents_shipgate.cli.self_check import self_check
from agents_shipgate.core.baseline import write_baseline
from agents_shipgate.core.errors import AgentsShipgateError, ConfigError, InputParseError
from agents_shipgate.core.findings import SEVERITY_ORDER
from agents_shipgate.core.logging import configure_logging


def _emit_agent_mode_error(error_kind: str, **fields: object) -> None:
"""When AGENTS_SHIPGATE_AGENT_MODE=1, emit a structured one-line JSON
record on stderr after the human-readable error so coding agents can
parse the next action without scraping prose."""
if os.environ.get("AGENTS_SHIPGATE_AGENT_MODE", "").lower() not in {"1", "true", "yes", "on"}:
return
payload = {"error": error_kind, **fields}
print(json.dumps(payload, default=str), file=sys.stderr)

app = typer.Typer(
name="agents-shipgate",
help="Manifest-first release readiness scanner for agent tool surfaces.",
Expand All @@ -50,6 +41,7 @@ def _emit_agent_mode_error(error_kind: str, **fields: object) -> None:
baseline_app = typer.Typer(help="Manage local finding baselines.")
app.add_typer(baseline_app, name="baseline")
app.add_typer(fixture_app, name="fixture")
app.add_typer(scenario_app, name="scenario")
app.command(
"self-check",
help="Verify install and bundled fixtures. Run this first in a fresh environment.",
Expand Down
Loading