Repository navigation
Expand file tree
/
Copy patherrors.json
More file actions
181 lines (181 loc) · 20 KB
/
Copy patherrors.json
File metadata and controls
181 lines (181 loc) · 20 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"schema_version": "0.1",
"name": "agents-shipgate-errors",
"description": "Machine-readable enumeration of error kinds emitted by `agents-shipgate` when `AGENTS_SHIPGATE_AGENT_MODE=1` is set. Coding agents fetch this file to pre-load the recovery vocabulary instead of pattern-matching on prose. The catalog is stable for `0.x`: error-kind ids will not change in minor versions, and additions are pinned by the public-surface contract test against AGENTS.md and the codebase.",
"agent_mode_env_var": "AGENTS_SHIPGATE_AGENT_MODE",
"agent_mode_truthy_values": [
"1",
"true",
"yes",
"on"
],
"stderr_format": "Single JSON line, one object per emitted error. Always carries an `error` field naming the kind plus `next_action` (single-string back-compat) and `next_actions` (ranked array). Additional fields per kind are command-dependent and may be absent when they are not relevant. `message`, `next_action`, and `next_actions[]` are written for a person to act on and name files, symbols, and manifest keys rather than internal identity fields; a `details` object, where a kind emits one, carries those identifiers for routing and bug reports. An error line from `detect`, `init`, or `doctor` also carries `control` \u2014 the same `shipgate.agent_control/v1` envelope those commands publish on `--json`, so one routing rule covers both streams (contract v27). Every such envelope reports `decision_source: \"setup\"`, a `decision` from the setup vocabulary, every `permissions` field false, and never `control_state: \"complete\"`. `execution` is NOT a marker for \"this is an error\" \u2014 the `error` field is: it reports `\"failed\"` when the command could not reach an answer about the workspace, and `\"succeeded\"` beside a non-zero `exit_code` when it reached one and the answer is a refusal it can route past (`config_already_exists`, the unresolved-scope `config_error`). Two lines carry no `control` by design: the shared `--workspace` refusal, which fires before a workspace exists, and `environment_error`, which is emitted before Agents Shipgate is running.",
"exit_codes": {
"0": "success; the gate did not fail (with no fail_on in effect, advisory mode exits 0 on every decision, blocked included)",
"2": "configuration, catalog lookup, or patch-payload error (config_error, config_already_exists, unknown_check_id, unknown_fingerprint, malformed_patch), or a partial clone missing the objects `diff` needs (objects_missing)",
"3": "input parse error (input_parse_error)",
"4": "other agents-shipgate error (other_error, internal_error), or an environment that cannot start Agents Shipgate at all (environment_error)",
"5": "apply-patches containment violation (covered by other_error in agent mode)",
"6": "baseline integrity failure: baseline verify --strict reported SHIP-BASELINE-INTEGRITY-MISMATCH (the baseline is not backed by its audit log); no other command exits 6",
"20": "gate failure: scan/verify in either mode when a release_decision blocker or an active finding has a severity in the resolved fail_on (verify with a base and without --fail-on adds the base manifest's ci.fail_on); in strict mode also on a blocked or insufficient_evidence decision, a semantic, binding or policy evidence gap, or an active blocks_release finding, with or without a fail_on match. fixture run returns the code of the scan or verify it runs. Elsewhere: skill lint/security/review when an unsuppressed finding has a severity in their fail_on; fixture verify when a fixture's summary differs from its expected/summary.json; org status when it reports a governance violation; or an opt-in gate flag (baseline status --require-owner/--require-expiry/--max-age-days on violations; audit --host --drift --fail-on-drift on host-grant drift; registry report --fail-on-bypass on a bypass row; registry verify --fail-on-issue on a registry issue), without which its command is advisory and exits 0."
},
"errors": [
{
"id": "config_error",
"description": "A command's configuration or request shape is missing, invalid, inconsistent, or unsafe to apply. This includes manifest loading failures as well as incompatible CLI flags, invalid preflight inputs, and host-audit baseline/control errors.",
"exit_code": 2,
"typical_cause": "The manifest is missing or rejected; mutually exclusive or dependent CLI flags were combined; a preflight request is invalid; or a host-grants baseline request cannot be completed or acknowledged safely.",
"additional_fields": [
"message",
"next_action",
"next_actions",
"agent_scope",
"agent_scope_truncated",
"python_parse_truncated",
"project_root_count",
"agent_project_candidates"
],
"recovery_hint": "Follow the emitted ranked `next_actions[]`; do not assume every config_error is a manifest problem. For manifests, distinguish missing vs. invalid via the diagnostic id: `SHIP-DIAG-MISSING-MANIFEST` → run the emitted preview/setup route; `SHIP-DIAG-INVALID-MANIFEST` → edit the existing manifest and do NOT re-run `init`. When `agent_scope` is `ambiguous` or `unknown`, `init --write` refused because the manifest scope was not settled — agents in several self-contained projects, or discovery capped before it could tell — and wrote nothing at all; re-run it with `--workspace` pointed at one of `agent_project_candidates[].path` instead of retrying the same command. When `agent_scope_truncated` is `true` that list is a lower bound, not an enumeration — discovery stopped at its Python-file cap — so if the project you are changing is not in it, re-run `detect --max-python-files <n> --json` rather than concluding it is absent — the emitted `next_actions[]` carries that command already, with a bound that covers every Python file. For flag, preflight, and host-audit errors, preserve the original workspace and request context, and stop for review whenever no exact safe command is emitted."
},
{
"id": "config_already_exists",
"description": "`init --write` refused to overwrite an existing `shipgate.yaml`.",
"exit_code": 2,
"typical_cause": "The repo already has a manifest. Initializing fresh would clobber it.",
"additional_fields": [
"path",
"next_action",
"next_actions",
"control"
],
"recovery_hint": "Follow `next_actions[0]` — this line carries an authoritative route (contract v27), and which one it is depends on what the run asked for. When the manifest already satisfies this invocation the route is `doctor` on it, which reports what that manifest still owes. When the run asked for a `--control-pack` the manifest does not select, the route names `policies.control_pack` and the exact value — a coding-agent `edit` when the change only tightens the gate, and a human `review` when it would require less of any effect, because command-line arguments are not a human approval for loosening one. An unresolved human-owned declaration outranks both, and that route names the field and the line. `init --write` is intentionally write-once: deleting the manifest to get a fresh template discards the declarations in it, which is a decision for a person rather than a recovery."
},
{
"id": "input_parse_error",
"description": "A referenced input file or output path could not be read, parsed, validated, or safely resolved.",
"exit_code": 3,
"typical_cause": "scan/doctor found a bad tool_sources[].path, explain-finding/scenario was pointed at a missing or incompatible report, or scenario --out was not a writable file path.",
"additional_fields": [
"message",
"source_report",
"details",
"next_action",
"next_actions"
],
"recovery_hint": "Follow `next_actions[]`. For scan/doctor tool-source failures, run `agents-shipgate doctor -c shipgate.yaml --json` to inspect `unresolved_sources[]`. For report-consuming commands, inspect `source_report` when present (or the `--from` path in the message) and regenerate a current `report.json` if needed. `message` and `next_actions[]` name files, symbols, and manifest keys only; when a failure has internal identifiers behind it they are in `details`, which is for routing and bug reports and is never required to act on the error. **Open only `next_actions[].path`.** It is the one field resolved for the caller — against the manifest the run actually read, and omitted entirely when the failure belongs to a ref that is not checked out. `details` is for routing and bug reports and is never required to act on the error; its paths are recorded as the loader saw them and are not verbatim-openable. Route on `details.failure` rather than pattern-matching the prose: `duplicate_tool_in_source` means one tool source produced the same tool twice, and `details.cause` says which repair applies — `repeated_source_entry` (the manifest names one artifact twice, so the action edits the manifest), `duplicate_in_source_artifact` (one artifact defines the tool twice, so the action is a review naming it), or `duplicate_across_artifacts` (two different files declare one capability under one name, named in `details.source_file` and `details.other_source_file`; either declaration may be renamed, or both files brought under a single `tool_sources` entry, so the action is a review naming both). `details.manifest_placeholders` lists the manifest fields still holding `CHANGE_ME`; `details.evaluated_ref` appears when the failure was evaluated against a ref rather than the working tree."
},
{
"id": "unknown_check_id",
"description": "`explain <CHECK_ID>` was called with an id that doesn't exist in the loaded catalog.",
"exit_code": 2,
"typical_cause": "Typo, a check id from a plugin that isn't loaded, or a check id that was renamed/removed.",
"additional_fields": [
"check_id",
"suggestion",
"next_action",
"next_actions"
],
"recovery_hint": "Use `suggestion` (close-match from `difflib`) when present. Otherwise run `agents-shipgate list-checks --json` to enumerate the loaded catalog."
},
{
"id": "unknown_fingerprint",
"description": "`explain-finding <FINGERPRINT>` was called with a fingerprint that doesn't match any entry in the supplied report.",
"exit_code": 2,
"typical_cause": "Stale fingerprint from an older scan, typo, or the report was generated from a different workspace.",
"additional_fields": [
"fingerprint",
"suggestion",
"source_report",
"next_action",
"next_actions"
],
"recovery_hint": "Use `suggestion` (close-match from `difflib`) when present. Otherwise read `findings[].fingerprint` in `source_report` to find the right id; fingerprints are stable across scans for the same `(check_id, tool_name, evidence)` tuple."
},
{
"id": "malformed_patch",
"description": "`apply-patches --from <report>` was called with a report that cannot be read, parsed as JSON, or validated against the Patch schema.",
"exit_code": 2,
"typical_cause": "`--from` points at a missing/non-JSON file, the report is too old (pre-v0.6), the scan omitted `--suggest-patches`, or the report was hand-edited.",
"additional_fields": [
"message",
"next_action",
"next_actions"
],
"recovery_hint": "Verify `--from` points at a readable report.json, then re-run the scan with `--suggest-patches` to regenerate a valid patch payload."
},
{
"id": "other_error",
"description": "Catch-all for application-layer errors that aren't config / input / unknown-id failures.",
"exit_code": 4,
"typical_cause": "Filesystem permission, output-directory not writable, scenario-input failure, or an apply-patches containment violation (which exits 5 in some paths).",
"additional_fields": [
"message",
"next_action",
"next_actions"
],
"recovery_hint": "Read the `next_action` / `next_actions` fields. If the cause is unclear, re-run with `--verbose` to surface the underlying exception."
},
{
"id": "internal_error",
"description": "Unexpected exception in the scanner itself. Should be reported as a bug.",
"exit_code": 4,
"typical_cause": "A bug in the scanner; the loader, check engine, or reporter raised an uncaught exception.",
"additional_fields": [
"message",
"next_action",
"next_actions",
"details"
],
"recovery_hint": "File an issue at https://github.com/ThreeMoonsLab/agents-shipgate/issues with the message and a minimal reproduction. Re-run with `--verbose` to capture the traceback. For init generation failures, details.failure is manifest_generation_failed and details.origin is agents_shipgate. The sole route is to report the product defect; it carries no repository edit or fallback command. No manifest, CI workflow or instruction kit is written. --minimal remains an explicit user choice, not a remedy for generated output that failed validation."
},
{
"id": "environment_error",
"description": "The environment cannot run Agents Shipgate: the interpreter is older than `requires-python`, or it cannot import the package or its dependencies. Emitted by the repository launcher (`./shipgate`) before any Shipgate code is running, so it is the one kind that carries no `control` envelope.",
"exit_code": 4,
"typical_cause": "A source checkout whose dependencies are not installed in the selected interpreter, an unsupported Python, or AGENTS_SHIPGATE_PYTHON pointing at something that is not an interpreter.",
"additional_fields": [
"message",
"next_action",
"next_actions",
"environment"
],
"recovery_hint": "Run the emitted `next_actions[0]`: it installs the checkout into the interpreter that was actually selected, named by absolute path. Read `environment` for which interpreter that was, which checkout was selected, and what disagrees. When no next action is emitted, no working interpreter is known and the message names the one that was tried."
},
{
"id": "objects_missing",
"description": "`diff` could not read its base side: this checkout is a partial clone (`git clone --filter=...`) that never fetched the Git objects the base tree needs. Shipgate runs Git with `GIT_NO_LAZY_FETCH=1` and never fetches them itself, so it refuses rather than compare. The id is the `diff_status.reason` `verify` reports for the same condition, and the message ends with the same remediation sentence.",
"exit_code": 2,
"typical_cause": "A `--filter=blob:none` or `--filter=tree:0` clone whose checkout fetched only the head, compared against a base that differs from it.",
"additional_fields": [
"message",
"next_action",
"next_actions"
],
"recovery_hint": "Run `next_actions[0]`, then rerun the same `diff`. It is `git -C <workspace> fetch --refetch --no-filter <remote>`; `next_actions` holds one such command per promisor remote the clone's configuration names, in configuration order, so try the next when a remote cannot supply the objects. A remote is named only when Git accepts its name as a remote name, it has a URL, and it does not start with `-`; no other name, `origin` included, is put in its place, so when none qualifies the one next action is a `review` and the example ends in a `<remote>` placeholder for the operator to fill. The command downloads the repository's full object set, which is why Shipgate names it instead of running it. `--no-filter` is required: `git fetch --refetch <remote>` alone applies the clone's configured filter again and fetches no blob. Cloning without `--filter` works too. A shallow checkout is refused first, as `config_error` with `git fetch --unshallow`; after that fetch a partial clone can still report `objects_missing`."
}
],
"next_action_kinds": {
"command": "Concrete CLI invocation the agent can run as-is.",
"edit": "Open and edit a specific file (path field carries the target).",
"review": "Read a file or output and decide; no machine-applicable change.",
"stop": "Negative-control action: stop this flow because the workspace or input is intentionally out of scope."
},
"invocation_policy": {
"contract_version": "24",
"description": "Every emitted `command` names the entry point that started the running process, so a recovery command is runnable in the environment that produced it. A console-script run emits `agents-shipgate ...` or `shipgate ...` unchanged; a `python -m agents_shipgate` run emits `<sys.executable> -P -m agents_shipgate ...`, spelled by interpreter path because a bare `python` resolves through PATH, and with `-P` because the command is run from the repository under review, where plain `python -m` would import a committed package of the same name first. `command` never contains `__main__.py`.",
"override_env_var": "AGENTS_SHIPGATE_CLI",
"override_precedence": "Highest. An explicit entry point is always used, including one whose program name matches a console script (`/private/venv/bin/agents-shipgate`) — the operator named that wrapper, not whichever one PATH resolves.",
"structured_fields": "Actions with `kind=\"command\"` in `next_actions[]` also carry `executable` (entry-point argv tokens) and `args` (the rest). Run them as `[*executable, *args]` with no shell. The pair is computed from `command` and ignored on input, and it is recomputed on every read so it cannot describe a command the action no longer holds. Both keys are OMITTED, never null, when the command has no faithful argv form: a leading NAME=VALUE assignment, or any unquoted shell metacharacter (operators, redirection including `<placeholder>` syntax, substitution, globs). Only single quotes make those inert — double quotes still expand `$VAR` and `$(...)`, so those are withheld too.",
"scope": "Executable fields only, and applied at the emission boundary so a route built as a plain dict cannot opt out. Durable evidence artifacts (`report.json`, `report.md`, `packet.*`) stay canonical: `docs/architecture.md` makes 'same inputs -> same report' a non-negotiable invariant and process entry is not an input. Published contract vocabulary (`primary_commands`, `.well-known/agents-shipgate.json`) and prose remediation text also name the canonical installed CLI.",
"command_quoting": "`command` is quoted with POSIX rules on every platform and is NOT a host-shell promise. One renderer and one parser must agree or a value changes in transit: rendering with subprocess.list2cmdline (MS C-runtime argv quoting, not shell escaping) and parsing with POSIX shlex turned `C:\\repo` into `C:repo` — a runnable command against the wrong workspace. Uniform POSIX quoting round-trips Windows paths exactly. Do not paste `command` into cmd.exe or PowerShell, where single quotes are not quoting; use the structured pair.",
"legacy_next_action": "When the rank-1 action is a command, `next_action` is that command verbatim and spelled for the same invocation, so the back-compat string can never route a caller to a different program than `next_actions[0]`. For other kinds it is a human-readable sentence describing the same action.",
"argv_recovery": "The pair is carried on `next_actions[]` only. The operational control contracts (`control.next_action`, `allowed_next_commands`, verifier repairs, `fix_task.verification_command`) publish the command string alone. Every command Shipgate emits is POSIX-rendered on every platform, so `shlex.split(command)` reproduces the exact argv on any surface and any host: use `subprocess.run(shlex.split(command))`, never `shell=True`."
},
"see_also": {
"agent_instructions": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/AGENTS.md",
"agent_contract": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/agent-contract-current.md",
"diagnostics": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/docs/diagnostics.md",
"stability_contract": "https://raw.githubusercontent.com/ThreeMoonsLab/agents-shipgate/main/STABILITY.md"
}
}