overlord-cli 0.2607301714.0 → 0.2608011442.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/dist/connectors/AGENTS.md +201 -9
  2. package/dist/connectors/HARNESS-MATRIX.md +67 -0
  3. package/dist/connectors/README.md +26 -12
  4. package/dist/connectors/VERSION +1 -1
  5. package/dist/connectors/adapters/antigravity/CAPABILITIES.md +84 -0
  6. package/dist/connectors/adapters/antigravity/README.md +8 -2
  7. package/dist/connectors/adapters/antigravity/conformance-manifest.yaml +14 -3
  8. package/dist/connectors/adapters/antigravity/fixtures/unbound-session.json +24 -0
  9. package/dist/connectors/adapters/antigravity/harness-capabilities.yaml +130 -0
  10. package/dist/connectors/adapters/antigravity/plugin.json +1 -1
  11. package/dist/connectors/adapters/claude/.claude-plugin/plugin.json +1 -1
  12. package/dist/connectors/adapters/claude/CAPABILITIES.md +109 -0
  13. package/dist/connectors/adapters/claude/README.md +3 -1
  14. package/dist/connectors/adapters/claude/codec/claude.codec.yaml +52 -0
  15. package/dist/connectors/adapters/claude/codec/claude.decision-codec.yaml +23 -0
  16. package/dist/connectors/adapters/claude/conformance-manifest.yaml +17 -1
  17. package/dist/connectors/adapters/claude/fixtures/agent-session-hook-unbound.json +26 -0
  18. package/dist/connectors/adapters/claude/fixtures/agent-session-inbox-unbound.json +23 -0
  19. package/dist/connectors/adapters/claude/fixtures/decision-codec.json +39 -0
  20. package/dist/connectors/adapters/claude/fixtures/inject-async-rewake.json +13 -0
  21. package/dist/connectors/adapters/claude/fixtures/inject-stop-block.json +9 -0
  22. package/dist/connectors/adapters/claude/fixtures/normalize-post-tool-use-shell.json +51 -0
  23. package/dist/connectors/adapters/claude/fixtures/normalize-post-tool-use-write.json +49 -0
  24. package/dist/connectors/adapters/claude/fixtures/normalize-session-start.json +35 -0
  25. package/dist/connectors/adapters/claude/fixtures/normalize-user-prompt-submit.json +36 -0
  26. package/dist/connectors/adapters/claude/fixtures/permission-request.json +17 -0
  27. package/dist/connectors/adapters/claude/fixtures/post-tool-use-parity.json +13 -0
  28. package/dist/connectors/adapters/claude/fixtures/unbound-session.json +26 -0
  29. package/dist/connectors/adapters/claude/harness-capabilities.yaml +247 -0
  30. package/dist/connectors/adapters/claude/hooks/hooks.json +59 -2
  31. package/dist/connectors/adapters/codex/.codex-plugin/hooks.json +55 -1
  32. package/dist/connectors/adapters/codex/.codex-plugin/plugin.json +1 -1
  33. package/dist/connectors/adapters/codex/CAPABILITIES.md +99 -0
  34. package/dist/connectors/adapters/codex/README.md +9 -2
  35. package/dist/connectors/adapters/codex/codec/codex.codec.yaml +42 -0
  36. package/dist/connectors/adapters/codex/codec/codex.decision-codec.yaml +23 -0
  37. package/dist/connectors/adapters/codex/conformance-manifest.yaml +17 -1
  38. package/dist/connectors/adapters/codex/fixtures/agent-session-hooks.json +20 -0
  39. package/dist/connectors/adapters/codex/fixtures/decision-codec.json +39 -0
  40. package/dist/connectors/adapters/codex/fixtures/normalize-post-tool-use.json +34 -0
  41. package/dist/connectors/adapters/codex/fixtures/normalize-pre-tool-use.json +40 -0
  42. package/dist/connectors/adapters/codex/fixtures/normalize-session-start.json +30 -0
  43. package/dist/connectors/adapters/codex/fixtures/normalize-user-prompt.json +31 -0
  44. package/dist/connectors/adapters/codex/fixtures/permission-request.json +18 -0
  45. package/dist/connectors/adapters/codex/fixtures/unbound-session.json +26 -0
  46. package/dist/connectors/adapters/codex/harness-capabilities.yaml +180 -0
  47. package/dist/connectors/adapters/cursor/.cursor-plugin/plugin.json +1 -1
  48. package/dist/connectors/adapters/cursor/CAPABILITIES.md +106 -0
  49. package/dist/connectors/adapters/cursor/README.md +4 -1
  50. package/dist/connectors/adapters/cursor/codec/cursor.decision-codec.yaml +28 -0
  51. package/dist/connectors/adapters/cursor/conformance-manifest.yaml +14 -3
  52. package/dist/connectors/adapters/cursor/fixtures/decision-codec.json +38 -0
  53. package/dist/connectors/adapters/cursor/fixtures/fail-closed-unset.json +10 -0
  54. package/dist/connectors/adapters/cursor/fixtures/inject-followup-message.json +16 -0
  55. package/dist/connectors/adapters/cursor/fixtures/no-permission-request-hook.json +10 -0
  56. package/dist/connectors/adapters/cursor/fixtures/permission-request.json +17 -0
  57. package/dist/connectors/adapters/cursor/fixtures/post-tool-use-log-dir.json +9 -0
  58. package/dist/connectors/adapters/cursor/fixtures/stop-calls-inbox.json +13 -0
  59. package/dist/connectors/adapters/cursor/fixtures/unbound-session.json +26 -0
  60. package/dist/connectors/adapters/cursor/harness-capabilities.yaml +213 -0
  61. package/dist/connectors/adapters/cursor/hooks/overlord-permission-request.sh +5 -24
  62. package/dist/connectors/adapters/cursor/hooks/overlord-post-tool-use.sh +8 -0
  63. package/dist/connectors/adapters/cursor/hooks/overlord-stop.sh +16 -2
  64. package/dist/connectors/adapters/cursor/skills/overlord-mission/SKILL.md +3 -1
  65. package/dist/connectors/adapters/opencode/CAPABILITIES.md +96 -0
  66. package/dist/connectors/adapters/opencode/README.md +30 -0
  67. package/dist/connectors/adapters/opencode/codec/opencode.codec.yaml +41 -0
  68. package/dist/connectors/adapters/opencode/conformance-manifest.yaml +26 -0
  69. package/dist/connectors/adapters/opencode/fixtures/normalize-session-idle.json +30 -0
  70. package/dist/connectors/adapters/opencode/fixtures/normalize-tool-completed.json +56 -0
  71. package/dist/connectors/adapters/opencode/fixtures/permission-reply-path.json +14 -0
  72. package/dist/connectors/adapters/opencode/fixtures/prompt-async-path.json +10 -0
  73. package/dist/connectors/adapters/opencode/fixtures/sidecar-loopback-only.json +10 -0
  74. package/dist/connectors/adapters/opencode/fixtures/unbound-session.json +10 -0
  75. package/dist/connectors/adapters/opencode/harness-capabilities.yaml +190 -0
  76. package/dist/connectors/adapters/pi/CAPABILITIES.md +100 -0
  77. package/dist/connectors/adapters/pi/README.md +25 -8
  78. package/dist/connectors/adapters/pi/codec/pi.codec.yaml +30 -0
  79. package/dist/connectors/adapters/pi/codec/pi.decision-codec.yaml +18 -0
  80. package/dist/connectors/adapters/pi/conformance-manifest.yaml +14 -1
  81. package/dist/connectors/adapters/pi/extensions/overlord.ts +188 -1
  82. package/dist/connectors/adapters/pi/fixtures/agent-session-runtime.json +21 -0
  83. package/dist/connectors/adapters/pi/fixtures/decision-codec.json +39 -0
  84. package/dist/connectors/adapters/pi/fixtures/extension-holds-no-credentials.json +10 -0
  85. package/dist/connectors/adapters/pi/fixtures/inject-send-user-message.json +15 -0
  86. package/dist/connectors/adapters/pi/fixtures/normalize-tool-call.json +37 -0
  87. package/dist/connectors/adapters/pi/harness-capabilities.yaml +190 -0
  88. package/dist/connectors/core/overlord-mission/SKILL.md +2 -10
  89. package/dist/connectors/core/overlord-mission/reference/cli.md +1 -10
  90. package/dist/connectors/core/overlord-mission/reference/context.md +7 -1
  91. package/dist/connectors/core/overlord-mission/reference/mcp.md +2 -1
  92. package/dist/connectors/core/scripts/agent-session-hook.sh +37 -0
  93. package/dist/connectors/core/scripts/overlord-mcp.mjs +37 -1
  94. package/dist/contract/conformance-manifest.schema.yaml +60 -2
  95. package/dist/index.js +5035 -1052
  96. package/dist/index.js.map +4 -4
  97. package/package.json +1 -1
@@ -8,12 +8,12 @@ This file tells agents how to extend the Connectors module to add new agent harn
8
8
 
9
9
  A connector lets an AI coding harness (Claude Code, Codex, Cursor, etc.) speak the `ovld protocol` and inherit mission context. Extensions in this module fall into four categories:
10
10
 
11
- | Extension type | Example user request |
12
- | --- | --- |
13
- | New agent connector | "Add a connector for OpenCode / Windsurf / Zed" |
14
- | New hook type | "Add a Stop hook for pending-delivery checks" |
15
- | Extend connector core | "Add a new canonical instruction to all connectors" |
16
- | New capability flag | "Connectors can now declare `supports-multi-session`" |
11
+ | Extension type | Example user request |
12
+ | --------------------- | ----------------------------------------------------- |
13
+ | New agent connector | "Add a connector for OpenCode / Windsurf / Zed" |
14
+ | New hook type | "Add a Stop hook for pending-delivery checks" |
15
+ | Extend connector core | "Add a new canonical instruction to all connectors" |
16
+ | New capability flag | "Connectors can now declare `supports-multi-session`" |
17
17
 
18
18
  Each type has a different procedure below.
19
19
 
@@ -29,6 +29,185 @@ Each type has a different procedure below.
29
29
 
30
30
  ---
31
31
 
32
+ ## Harness capability descriptors
33
+
34
+ **Before writing any code for a harness, read
35
+ `connectors/adapters/<agent>/harness-capabilities.yaml`, or run
36
+ `ovld agent-session capabilities <agent>`. It is authoritative and fixture-backed.**
37
+
38
+ - `unsupported` means the harness cannot do it. **Do not attempt it.** If you believe the cited
39
+ evidence is now wrong, replace `evidenceRef` and add the executable fixture in the same change
40
+ that flips the status.
41
+ - `not-implemented` means it is buildable and unbuilt. **This is your work.**
42
+ - `unverified` means find out first. Write the fixture, then flip the status.
43
+ - `supported` without passing fixtures is a CI failure, not a claim.
44
+
45
+ Two states (`yes`/`no`) would be a trap: an agent reading "no" could not tell whether to give up
46
+ or to start building, and both errors are expensive — one wastes a day on something structurally
47
+ impossible, the other leaves a capability unbuilt for a year because someone assumed it was
48
+ refused.
49
+
50
+ ### What is generated from the descriptor
51
+
52
+ The descriptor is the **only hand-authored capability source**. Everything below is generated by
53
+ `yarn connectors:capabilities` and must never be hand-edited:
54
+
55
+ | Artifact | Purpose |
56
+ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
57
+ | `connectors/adapters/<agent>/CAPABILITIES.md` | Per-adapter page with a do-not-edit banner |
58
+ | `connectors/HARNESS-MATRIX.md` | Cross-adapter matrix |
59
+ | `cli/src/agent-session/catalog.generated.ts` | Compiled catalog the CLI runtime reads |
60
+ | The `connector:` block's `capabilities`, `hookTypes`, `integrationShape`, `capabilityTier`, and `harnessCapabilities` fields in `conformance-manifest.yaml` | The deprecated hook-named legacy projection plus the descriptor digest |
61
+
62
+ `yarn connectors:capabilities:check` is the CI drift check: it validates every descriptor,
63
+ executes every referenced fixture, re-derives each tier, and fails if any generated artifact is
64
+ stale. `yarn connectors:check` runs it alongside the connector version check.
65
+
66
+ ### Rules that keep it honest
67
+
68
+ 1. **A capability is proven by fixture, not by inspection.** CI runs the fixture. Checking only
69
+ that a named file exists would let an empty fixture claim a capability into existence.
70
+ 2. **The tier is derived, never authored.** `capabilityTier` comes from what the fixtures prove.
71
+ Claimed-but-unproven is worse than absent, because the UI renders controls that do nothing.
72
+ 3. **Every adapter ships the unbound-session negative fixture.** An unbound session in an
73
+ unrelated directory must be untouched and unblocked by every registered integration. A side
74
+ effect the fixture records must be declared as a hazard with a tracker — recording the truth
75
+ is required; claiming silence you do not have is not.
76
+ 4. **A native session id binds nothing on its own.** It is a correlation alias. The verified
77
+ channel/session credential is the authorization and mission scope, and the working directory
78
+ is never a binding authority.
79
+ 5. **Adapters make no network call.** Translate, hand off to `ovld agent-session`, return.
80
+
81
+ ### The rendered agent-session hook
82
+
83
+ Do not write a per-adapter shell script for agent-session traffic. One core script,
84
+ `connectors/core/scripts/agent-session-hook.sh`, is rendered per adapter at `ovld agent-setup`
85
+ time — declare the managed file as `scripts/agent-session-<action>.sh` in the manifest, and the
86
+ installer substitutes both your adapter key and that **fixed action**:
87
+
88
+ ```bash
89
+ [ -n "${OVERLORD_SESSION_CHANNEL_ID:-}" ] || exit 0
90
+ command -v ovld >/dev/null 2>&1 || exit 0
91
+ exec ovld agent-session event --agent claude --payload-file -
92
+ ```
93
+
94
+ The first line is the scope gate, and it is in bash rather than in the CLI on purpose. An
95
+ unbound session — someone's own agent in an unrelated directory on a machine that happens to
96
+ have Overlord installed — must cost no process, no log line, and no measurable delay. A gate
97
+ inside the CLI cannot deliver that, because reaching it already cost a process launch. The CLI
98
+ applies the same gate again, since a check that can be skipped by invoking `ovld` directly is
99
+ not a gate.
100
+
101
+ The action being fixed at install time is the point, not a simplification. A single script that
102
+ dispatched on `$1` would let whatever wrote the hook registration choose which CLI operation
103
+ runs, and hook registrations are the least-reviewed configuration on a developer's machine. A
104
+ `PostToolUse` registration renders an `event` script; a permission registration renders a
105
+ `request` script; an inject registration renders an `inbox` script; none can become another.
106
+ `event`, `request`, and `inbox` are the only three actions a managed path may name.
107
+
108
+ The payload streams on stdin — not through a shell variable, which caps size and mangles NUL
109
+ bytes, and not through argv, which is world-readable. For `request` and `inbox`, stdout and exit
110
+ status pass through unchanged so the native decision or injection reaches the harness in its
111
+ exact expected shape.
112
+
113
+ Silence is the failure mode. A missing `ovld` exits `0` with no output, which for a decision
114
+ hook means _no decision_ and therefore the harness's own prompt. No failure path may ever
115
+ manufacture an approval.
116
+
117
+ ### The event codec
118
+
119
+ Native event shapes belong to the connector, so they live here as
120
+ `connectors/adapters/<agent>/codec/<agent>.codec.yaml`, referenced from the descriptor's
121
+ `codecSpec` field and compiled by `yarn connectors:capabilities` into
122
+ `cli/src/agent-session/codec-registry.generated.ts`. The CLI executes harness dialects; it is
123
+ never their source of truth.
124
+
125
+ A codec is a **declaration**, not a function, and that is the whole design:
126
+
127
+ ```yaml
128
+ codecVersion: 1
129
+ adapter: claude
130
+ eventNamePath: hook_event_name # where the native event name lives (omit for a bus transport)
131
+ nativeSessionPaths: [session_id] # correlation alias only, never an authority
132
+ projectRootPaths: [cwd] # used ONLY to relativize file paths
133
+ events:
134
+ - native: PostToolUse
135
+ kind: tool.completed # from the closed normalized event vocabulary
136
+ origin: agent
137
+ toolPath: tool_name
138
+ inputPath: tool_input
139
+ fileEditKind: file.edited # a file-mutating tool becomes this kind instead
140
+ ```
141
+
142
+ A codec can only say **where** native values live. It cannot name a destination the core
143
+ interpreter (`packages/core/service/agent-session/pure/codec.ts`) does not implement, an unknown
144
+ key is a generation error rather than a silently ignored field, and the normalized payload type
145
+ has no index signature to smuggle anything through. So "does this codec forward a raw payload?"
146
+ is a question you answer by looking, not by reading code — which matters on the sixth adapter far
147
+ more than on the first.
148
+
149
+ What each field feeds:
150
+
151
+ - `toolPath` is normalized to the **nine-value tool vocabulary**, and the description formatter
152
+ is keyed by that normalized name in core. Adapters own the mapping; core owns the formatter.
153
+ `Bash`, `bash`, `Shell`, and `shell_command` are one thing with one card.
154
+ - `inputPath` is never transmitted. It is reduced on the machine into an action, a subject, a
155
+ bounded detail, and machine-derived risk markers. A tool with no formatter emits its name and
156
+ the top-level **key names** of its input and nothing else.
157
+ - `promptPath` is the single deliberate exception: prompt text is persisted in full for bound
158
+ sessions, because the activity feed exists to show it. Secret redaction still runs over it.
159
+
160
+ Control-plane adapters (Shape C) write the same kind of codec and omit `eventNamePath`, because
161
+ the transport rather than the payload names the event. There is no separate control-plane
162
+ codec format, and that is the evidence the waist is in the right place.
163
+
164
+ ### The decision codec
165
+
166
+ Callback and extension adapters with fixture-proven `decide.*` capabilities declare
167
+ `codec/<agent>.decision-codec.yaml` and reference it as `decisionCodecSpec`. The declaration
168
+ names native event/request paths and literal allow/deny/defer response bodies; the shared pure
169
+ interpreter owns validation, bounded redacted card construction, and JSON-line emission. Do not
170
+ add an `if (agent === ...)` branch to `cli/src/agent-session/request.ts`.
171
+
172
+ Every supported callback/extension decision capability must reference a `decision-codec`
173
+ fixture. That fixture executes the shipped interpreter, asserts the complete reduced request
174
+ card, rejects named secret/raw values, and pins exact allow/deny/defer bytes. A
175
+ `native-payload` fixture proves only that upstream fields exist; it cannot prove what the CLI
176
+ emits back to the harness.
177
+
178
+ ### Where the session channel comes from
179
+
180
+ The credential your adapter's CLI call presents is not something the adapter finds or derives:
181
+
182
+ | Launch | Channel created at | Credential reaches the process via |
183
+ | ---------------------- | ---------------------------------------- | --------------------------------------------------- |
184
+ | Queued (runner) | the `launching` transition | owner-only local cache, keyed by channel id |
185
+ | Manual (`ovld launch`) | `POST /api/missions/:id/session-channel` | owner-only local cache, keyed by channel id |
186
+ | Virtual gateway | the same preparation service | `OVERLORD_SESSION_CHANNEL_TOKEN` in the environment |
187
+
188
+ Only `OVERLORD_SESSION_CHANNEL_ID` is exported into the launch environment and the terminal
189
+ launch script. The script lives in `<checkout>/.overlord/tmp`, so nothing secret may enter it —
190
+ a checkout-local secret is one that can be committed, copied into a worktree, or backed up.
191
+
192
+ `ovld protocol attach` binds the channel to the session and backfills every event published
193
+ before the agent attached. If your adapter learns the harness's session id later, report it with
194
+ `ovld agent-session bind --agent <key> --native-session-id <id>`; it is recorded as an alias and
195
+ grants nothing on its own.
196
+
197
+ ### Fixture kinds
198
+
199
+ | Kind | What it does |
200
+ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
201
+ | `native-payload` | Asserts the shape of a recorded native harness payload (pure; no process started) |
202
+ | `script-io` | Runs a shipped adapter script in an isolated sandbox — own `HOME`, `TMPDIR`, cwd, and a `PATH` whose only `ovld` is a recording spy — and asserts exit status, stdout, stderr, every sandbox write, and every CLI invocation attempted |
203
+ | `source-guard` | Asserts a repo file does or does not contain declared markers (how "this dangerous harness flag must stay unset" is enforced) |
204
+ | `normalized-event` | Runs the shipped codec and the real core interpreter against a recorded native payload, asserts the exact normalized envelope, and asserts that named raw content (file bodies, transcript paths, credentials) appears nowhere in it. This is how an `observe.*` capability becomes provable rather than claimed |
205
+ | `decision-codec` | Runs the connector-owned request/decision declaration through the real pure interpreter, asserts the bounded redacted request card, and pins exact allow/deny/defer bytes. Required for supported callback/extension `decide.*` capabilities |
206
+
207
+ Fixtures never reach the network.
208
+
209
+ ---
210
+
32
211
  ## Adding a New Agent Connector
33
212
 
34
213
  A new connector is the primary sanctioned extension point for this module. It requires a conformance manifest but does not require a contract version bump unless it introduces new capability flags or hook types.
@@ -54,13 +233,26 @@ A new connector is the primary sanctioned extension point for this module. It re
54
233
  - Not clobber existing user settings
55
234
  - Be detectable by `ovld doctor` as stale, missing, or partially installed
56
235
 
57
- 4. **List managed files** in the adapter's manifest so `ovld doctor` can verify them.
236
+ 4. **List managed files** in the adapter's manifest so `ovld doctor` can verify them. Include
237
+ `harness-capabilities.yaml` and `CAPABILITIES.md` so the installed descriptor digest can be
238
+ compared with the compiled catalog.
239
+
240
+ 4b. **Write the harness capability descriptor** (`harness-capabilities.yaml`) and its fixtures,
241
+ then run `yarn connectors:capabilities`. Declare every capability id — an omission reads as a
242
+ claim. Start honest: a harness that can do something Overlord has not built yet is
243
+ `not-implemented` with a tracker, never `supported`.
244
+
245
+ 4c. **Write the event codec** (`codec/<agent>.codec.yaml`) and a `normalized-event` fixture per
246
+ capability you intend to grade `supported`. You should not need to write any TypeScript to
247
+ add a push path for a new harness — if you find yourself wanting to, the abstraction is
248
+ wrong and that is worth raising rather than working around.
58
249
 
59
250
  5. **Write a prompt wrapper** if the agent needs mission context prepended at launch time. The wrapper receives a context file path and emits the final prompt text.
60
251
 
61
252
  6. **Create `connectors/adapters/<agent-name>/conformance-manifest.yaml`** declaring:
253
+
62
254
  ```yaml
63
- contractVersion: "0"
255
+ contractVersion: '0'
64
256
  componentType: connector
65
257
  componentKey: <agent-name>
66
258
  capabilities:
@@ -105,7 +297,7 @@ The connector core is the set of canonical Markdown workflow instructions every
105
297
 
106
298
  ## Adding a New Capability Flag
107
299
 
108
- Capability flags (e.g. `supports-checkpointing`, `supports-multi-session`) are listed in `contract/extension-points.yaml` under `approvedConnectorCapabilities`. New flags require a contract update.
300
+ Capability flags (e.g. `sessionEventStream`, `nativeSessionBinding`) are listed in `contract/extension-points.yaml` under `approvedConnectorCapabilities`. New flags require a contract update.
109
301
 
110
302
  **Steps:**
111
303
 
@@ -0,0 +1,67 @@
1
+ <!-- GENERATED FILE — DO NOT EDIT. Source: harness-capabilities.yaml. Regenerate with `yarn connectors:capabilities`. -->
2
+
3
+ # Harness capability matrix
4
+
5
+ Generated from each adapter's `harness-capabilities.yaml`. This file replaces the
6
+ hand-written capability table that used to live in `connectors/README.md`: prose maintained
7
+ by hand alongside code drifts, and a matrix that is 60% accurate is worse than none because
8
+ it is trusted.
9
+
10
+ Legend: ✅ supported (fixture-proven) · ⛔ unsupported (harness cannot) · 🚧 not-implemented
11
+ (buildable, unbuilt) · ❓ unverified (find out first).
12
+
13
+ ## Adapters
14
+
15
+ | Adapter | Harness | Verified version | Shape | Tier | Binding | Decision hold |
16
+ | --- | --- | --- | --- | --- | --- | --- |
17
+ | [`antigravity`](adapters/antigravity/CAPABILITIES.md) | Antigravity CLI | — | `callback` | 0 (Unsupported) | ❓ unverified | ❓ unverified |
18
+ | [`claude`](adapters/claude/CAPABILITIES.md) | Claude Code | `2.1.220` | `callback` | 3 (Conversational) | ✅ supported | ✅ supported |
19
+ | [`codex`](adapters/codex/CAPABILITIES.md) | Codex CLI | `0.146.0` | `callback` | 3 (Conversational) | ✅ supported | ✅ supported |
20
+ | [`cursor`](adapters/cursor/CAPABILITIES.md) | Cursor Agent CLI | `2026.07.23-e383d2b` | `callback` | 0 (Unsupported) | ❓ unverified | ✅ supported |
21
+ | [`opencode`](adapters/opencode/CAPABILITIES.md) | OpenCode | — | `controlPlane` | 3 (Conversational) | ✅ supported | ✅ supported |
22
+ | [`pi`](adapters/pi/CAPABILITIES.md) | Pi Coding Agent | `0.83.0` | `extension` | 3 (Conversational) | ✅ supported | ✅ supported |
23
+
24
+ ## Capabilities
25
+
26
+ | Capability | `antigravity` | `claude` | `codex` | `cursor` | `opencode` | `pi` |
27
+ | --- | --- | --- | --- | --- | --- | --- |
28
+ | `observe.prompt` | ❓ unverified | ✅ supported | ✅ supported | 🚧 not-implemented | 🚧 not-implemented | ✅ supported |
29
+ | `observe.toolCall` | ❓ unverified | 🚧 not-implemented | ✅ supported | 🚧 not-implemented | 🚧 not-implemented | ✅ supported |
30
+ | `observe.toolResult` | ❓ unverified | ✅ supported | ✅ supported | 🚧 not-implemented | ✅ supported | 🚧 not-implemented |
31
+ | `observe.fileEdit` | ❓ unverified | ✅ supported | ✅ supported | 🚧 not-implemented | ✅ supported | 🚧 not-implemented |
32
+ | `observe.sessionLifecycle` | ❓ unverified | ✅ supported | ✅ supported | 🚧 not-implemented | ✅ supported | ✅ supported |
33
+ | `decide.shell` | ❓ unverified | ✅ supported | ✅ supported | ✅ supported | ✅ supported | ✅ supported |
34
+ | `decide.mcp` | ❓ unverified | ✅ supported | ✅ supported | ✅ supported | ✅ supported | ✅ supported |
35
+ | `decide.fileWrite` | ❓ unverified | ✅ supported | ✅ supported | 🚧 not-implemented | 🚧 not-implemented | ✅ supported |
36
+ | `decide.anyTool` | ❓ unverified | 🚧 not-implemented | 🚧 not-implemented | ✅ supported | ✅ supported | ✅ supported |
37
+ | `decide.universal` | ❓ unverified | ✅ supported | ✅ supported | ⛔ unsupported | 🚧 not-implemented | ✅ supported |
38
+ | `answer.structuredQuestion` | ❓ unverified | ❓ unverified | ❓ unverified | ⛔ unsupported | 🚧 not-implemented | 🚧 not-implemented |
39
+ | `answer.persistentAllow` | ❓ unverified | 🚧 not-implemented | ❓ unverified | ⛔ unsupported | 🚧 not-implemented | ⛔ unsupported |
40
+ | `inject.midTurn` | ❓ unverified | ✅ supported | ❓ unverified | ⛔ unsupported | ✅ supported | ✅ supported |
41
+ | `inject.turnBoundary` | ❓ unverified | ✅ supported | ✅ supported | ✅ supported | ✅ supported | ✅ supported |
42
+ | `inject.nextTurn` | ❓ unverified | 🚧 not-implemented | 🚧 not-implemented | ✅ supported | ✅ supported | 🚧 not-implemented |
43
+ | `terminal.concurrentAnswer` | ❓ unverified | ⛔ unsupported | ⛔ unsupported | ⛔ unsupported | ✅ supported | ⛔ unsupported |
44
+ | `terminal.statusSurface` | ❓ unverified | 🚧 not-implemented | ❓ unverified | ❓ unverified | 🚧 not-implemented | 🚧 not-implemented |
45
+
46
+ ## Open hazards
47
+
48
+ | Adapter | Hazard | Severity | Verification | Mitigation | Tracked as |
49
+ | --- | --- | --- | --- | --- | --- |
50
+ | `antigravity` | `outside-verification-survey` | medium | unverified | required | `agent-session-verify-antigravity` |
51
+ | `antigravity` | `pre-tool-use-always-allows` | medium | verified | required | `agent-session-verify-antigravity` |
52
+ | `claude` | `shipped-stop-hook-inert` | medium | verified | required | `agent-session-phase-3` |
53
+ | `claude` | `unbound-session-side-effects` | medium | verified | required | `agent-session-phase-4` |
54
+ | `claude` | `fork-and-subagent-identity-unknown` | medium | unverified | required | `taxonomy-7.6` |
55
+ | `codex` | `hooks-version-and-platform-gate` | medium | verified | required | `agent-session-phase-4` |
56
+ | `cursor` | `reads-claude-hook-config` | high | unverified | required | `taxonomy-7.1` |
57
+ | `cursor` | `allowlist-precedence` | medium | unverified | required | `taxonomy-7.8` |
58
+ | `opencode` | `harness-version-unverified` | medium | unverified | required | `agent-session-verify-opencode-frames` |
59
+ | `pi` | `typed-api-version-coupling` | medium | unverified | required | `taxonomy-7.10` |
60
+
61
+ ## Reading this table
62
+
63
+ Before writing any code for a harness, read its descriptor or run
64
+ `ovld agent-session capabilities <agent>`. Do not attempt an `unsupported` capability. If you
65
+ believe the cited evidence is now wrong, replace `evidenceRef` and add the executable fixture
66
+ in the same change that flips the status.
67
+
@@ -70,26 +70,40 @@ or the harness extension catalog (→ Extension System, see [Database module](..
70
70
 
71
71
  ### Adapter capability matrix
72
72
 
73
- Adapters deliberately differ. This table records what each one ships and, where a
74
- mechanism is absent, whether the gap is a decision or simply unported work — so a
73
+ > **Agent-session interaction capabilities are not documented here.** What a harness can
74
+ > observe, decide, and inject — and whether a gap is a hard limit, unbuilt work, or simply
75
+ > unknown — lives in the generated, fixture-backed [harness capability
76
+ > matrix](HARNESS-MATRIX.md) and each adapter's `CAPABILITIES.md`. Prose maintained by hand
77
+ > alongside code drifts, and a matrix that is 60% accurate is worse than none because it is
78
+ > trusted. Run `ovld agent-session capabilities <agent>` for the same answer in a terminal.
79
+
80
+ The table below is about **packaging**, not interaction: which files each adapter ships and,
81
+ where a mechanism is absent, whether the gap is a decision or simply unported work — so a
75
82
  contributor adding an adapter can tell signal from neglect. Source of truth for the
76
83
  "ships" columns is each adapter's `conformance-manifest.yaml`.
77
84
 
78
- | Adapter | Commands | Hooks | Local MCP shim | MCP config | Rules | Native resume |
79
- |---|---|---|---|---|---|---|
80
- | `claude` | `commands/` | `hooks/hooks.json` (4 types) | — | — | — | — |
81
- | `codex` | — | `.codex-plugin/hooks.json` + `scripts/*.sh` (2 types) | rendered | `.mcp.json` | — | yes |
82
- | `cursor` | `commands/` | `hooks/*.sh` (4 types) | rendered | `mcp.json` | `rules/` | — |
83
- | `antigravity` | `skills/*.md` | `hooks.json` + `scripts/*.sh` (2 types) | rendered | `mcp_config.json` | — | — |
84
- | `pi` | — | `extensions/overlord.ts` (`input` event) | — | — | — | yes |
85
+ | Adapter | Commands | Hooks | Local MCP shim | MCP config | Rules | Native resume |
86
+ | ------------- | ------------- | ----------------------------------------------------- | -------------- | ----------------- | -------- | ------------- |
87
+ | `claude` | `commands/` | `hooks/hooks.json` (5 types) | — | — | — | — |
88
+ | `codex` | — | `.codex-plugin/hooks.json` + `scripts/*.sh` (2 types) | rendered | `.mcp.json` | — | yes |
89
+ | `cursor` | `commands/` | `hooks/*.sh` (4 types) | rendered | `mcp.json` | `rules/` | — |
90
+ | `antigravity` | `skills/*.md` | `hooks.json` + `scripts/*.sh` (2 types) | rendered | `mcp_config.json` | — | — |
91
+ | `pi` | — | `extensions/overlord.ts` (input/tool/session events) | — | — | — | yes |
92
+ | `opencode` | — | none — control plane, see below | — | — | — | — |
85
93
 
86
94
  Intentional omissions:
87
95
 
96
+ - **`opencode` ships no hooks, and never will.** It is a control-plane harness (Shape C): it
97
+ runs a local HTTP server and publishes an event stream, so integration means subscribing
98
+ rather than being invoked. Overlord drives it with `ovld agent-session sidecar`, started
99
+ alongside the harness. The sidecar implements event reconciliation, concurrent permission
100
+ observation, and `prompt_async` instruction delivery, but the bundled agent catalog does not
101
+ yet start it automatically. A supervised execution target must supply that launch integration.
88
102
  - **`claude` ships no local MCP shim.** The Claude plugin reaches Overlord's hosted
89
103
  MCP server, so a local stdio bridge would duplicate it.
90
- - **`pi` ships no shim, hooks directory, or commands.** PI integrates through a
91
- single TypeScript extension, and it has no native permission-request hook — its
92
- `input` event carries follow-up capture only.
104
+ - **`pi` ships no shim, hooks directory, or commands.** PI integrates through one TypeScript
105
+ extension. It has no native permission dialog; its optional `tool_call` decision interceptor
106
+ is fail-open and requires explicit workspace and project opt-in.
93
107
  - **`antigravity` passes no model or effort flag.** Antigravity selects the model
94
108
  internally; see [05 — Connectors and Agent Plugins](docs/05-connectors-and-agent-plugins.md#antigravity-connector).
95
109
  - **`cursor` passes no effort/thinking flag.** Deferred, not declined — recorded in
@@ -1 +1 @@
1
- 0.3.10
1
+ 0.3.17
@@ -0,0 +1,84 @@
1
+ <!-- GENERATED FILE — DO NOT EDIT. Source: harness-capabilities.yaml. Regenerate with `yarn connectors:capabilities`. -->
2
+
3
+ # Antigravity CLI — Overlord agent-session capabilities
4
+
5
+ **Adapter** `antigravity` · **Codec** `antigravity` · **Integration shape** `callback` · **Capability tier** 0 (Unsupported)
6
+
7
+ **Harness version verified** _not verified_ · **scheme** `opaque`
8
+
9
+ **Descriptor digest** `c021926c384a72bdaa62ac5f0eab57e80822c5d2996db75ea3c30c6bf5d09ce8`
10
+
11
+ > The tier is derived from passing fixtures, never authored. `unsupported` means the harness
12
+ > cannot do it — do not attempt it. `not-implemented` means it is buildable and unbuilt: that is
13
+ > your work. `unverified` means find out first. `supported` without a passing fixture is a CI
14
+ > failure, not a claim.
15
+
16
+ ## Session binding
17
+
18
+ | Field | Value |
19
+ | --- | --- |
20
+ | Status | ❓ unverified |
21
+ | Source | `payload` |
22
+ | Evidence | tracked as `agent-session-verify-antigravity` |
23
+
24
+ No native session identifier has been established for Antigravity hook payloads. Until one is, this connector cannot bind, and therefore cannot reach any interaction tier.
25
+
26
+ The native session id is a **correlation alias only**. Authorization and mission scope come
27
+ from the verified channel/session credential; neither the working directory nor an unverified
28
+ native id is a binding authority.
29
+
30
+ ## Decision hold
31
+
32
+ | Field | Value |
33
+ | --- | --- |
34
+ | Status | ❓ unverified |
35
+ | Harness ceiling | none documented |
36
+ | Evidence | tracked as `agent-session-verify-antigravity` |
37
+
38
+ The shipped hooks declare a 10-second timeout, but whether a held PreToolUse response actually gates execution — and what the harness does when the hook exceeds that timeout — was not verified.
39
+
40
+ ## Capabilities
41
+
42
+ | Capability | Status | Native | Evidence |
43
+ | --- | --- | --- | --- |
44
+ | `observe.prompt` | ❓ unverified | `PreInvocation` | tracked as `agent-session-verify-antigravity` |
45
+ | `observe.toolCall` | ❓ unverified | `PreToolUse` | tracked as `agent-session-verify-antigravity` |
46
+ | `observe.toolResult` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
47
+ | `observe.fileEdit` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
48
+ | `observe.sessionLifecycle` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
49
+ | `decide.shell` | ❓ unverified | `PreToolUse` | tracked as `agent-session-verify-antigravity` |
50
+ | `decide.mcp` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
51
+ | `decide.fileWrite` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
52
+ | `decide.anyTool` | ❓ unverified | `PreToolUse` | tracked as `agent-session-verify-antigravity` |
53
+ | `decide.universal` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
54
+ | `answer.structuredQuestion` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
55
+ | `answer.persistentAllow` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
56
+ | `inject.midTurn` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
57
+ | `inject.turnBoundary` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
58
+ | `inject.nextTurn` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
59
+ | `terminal.concurrentAnswer` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
60
+ | `terminal.statusSurface` | ❓ unverified | — | tracked as `agent-session-verify-antigravity` |
61
+
62
+ ## Hazards
63
+
64
+ | Hazard | Severity | Verification | Mitigation | Tracked as |
65
+ | --- | --- | --- | --- | --- |
66
+ | `outside-verification-survey` | medium | unverified | required | `agent-session-verify-antigravity` |
67
+ | `pre-tool-use-always-allows` | medium | verified | required | `agent-session-verify-antigravity` |
68
+
69
+ **`outside-verification-survey`** — Antigravity was not part of the harness verification survey. Every row above is unverified rather than inferred, and this connector must stay at its fixture-proven tier until a dedicated verification objective upgrades it.
70
+
71
+ **`pre-tool-use-always-allows`** — The shipped PreToolUse hook always answers `{"allow_tool":true}` and records the request through a detached `ovld protocol permission-request` call to a subcommand that does not exist. It therefore neither gates nor records anything, while its conformance manifest declared the permissionHook capability.
72
+
73
+ ## Native decision shape
74
+
75
+ - **Codec** `antigravity`
76
+ - **Never send** `hookSpecificOutput`, `permissionDecision`, `permission`
77
+
78
+ The observed response shape is a flat `{"allow_tool": boolean}`. No deny or defer shape has been verified, so no decision codec may be written for this adapter yet.
79
+
80
+ ## Unbound-session negative test
81
+
82
+ Fixture: `fixtures/unbound-session.json` — proves what this adapter's registered
83
+ integrations do in a session with no Overlord binding, in an unrelated directory.
84
+
@@ -72,7 +72,9 @@ This connector is intentionally reviewable against the four connector layers in
72
72
  - `plugin.json` — Antigravity plugin manifest (name, description, metadata).
73
73
  - `skills/overlord-mission/SKILL.md` — Antigravity adapter template with a `<!-- @connector-core -->` marker; setup interpolates shared core content at install time.
74
74
  - `skills/attach.md`, `skills/connect.md`, `skills/load.md`, `skills/create.md`, `skills/prompt.md`, `skills/discuss-objective.md`, `skills/add-objectives.md`, `skills/record-work.md`, `skills/spawn.md` — one skill per protocol operation; Antigravity auto-registers each as a `/<name>` slash command.
75
- - `hooks.json` + `scripts/pre-invocation-hook.sh` + `scripts/pre-tool-use-hook.sh` — follow-up and permission activity capture through `ovld protocol` (see mapping notes below).
75
+ - `hooks.json` + `scripts/pre-invocation-hook.sh` + `scripts/pre-tool-use-hook.sh` — legacy
76
+ follow-up and pre-tool compatibility hooks (see the limitations below). These are not a
77
+ fixture-proven agent-session decision path.
76
78
  - `mcp_config.json` + `scripts/overlord-mcp.mjs` — MCP bridge to common `ovld protocol` operations. The shim is **generated**: it is rendered from `connectors/core/scripts/overlord-mcp.mjs` at setup time with the adapter key substituted, and there is no copy in this directory to edit.
77
79
  - `conformance-manifest.yaml` — connector conformance declaration for the Overlord contract.
78
80
  - `prompt-wrapper.md` — Antigravity launch guidance.
@@ -92,7 +94,11 @@ See the [adapter capability matrix](../../README.md#adapter-capability-matrix) f
92
94
  Antigravity's native hook events are `PreToolUse`, `PostToolUse`, `PreInvocation`, `PostInvocation`, and `Stop` — it has no event literally named `UserPromptSubmit` or `PermissionRequest` the way Claude Code and Codex do. This adapter maps Antigravity's native events onto Overlord's canonical hook-type vocabulary the same way the Cursor adapter maps `beforeSubmitPrompt` onto `UserPromptSubmit`:
93
95
 
94
96
  - `PreInvocation` (fires before each agent turn) → recorded as the canonical `UserPromptSubmit` follow-up-capture hook.
95
- - `PreToolUse` (fires before each tool call) → recorded as the canonical `PermissionRequest` hook. It always responds `{"allow_tool":true}`; it never gates a tool call, it only logs the request through `ovld protocol permission-request`.
97
+ - `PreToolUse` (fires before each tool call) → the legacy script always responds
98
+ `{"allow_tool":true}`. Its detached `ovld protocol permission-request` target is not a current
99
+ protocol command, so it neither gates nor reliably records the request. The generated
100
+ capability descriptor keeps Antigravity at tier 0 until a native fixture-backed path replaces
101
+ this compatibility hook.
96
102
 
97
103
  Both hook scripts are defensive: they no-op on any missing `MISSION_ID`, missing `ovld` binary, or unexpected payload shape, and they always return a well-formed allow response so a hook failure never blocks the Antigravity session. Antigravity's public docs do not yet pin an exact `PreInvocation` payload shape the way they do for `PreToolUse` (`toolCall.args`), so `pre-invocation-hook.sh` probes a few plausible field names (`prompt`, `message`, `text`, `input`) for the human turn text; adjust this once the official schema is confirmed.
98
104
 
@@ -1,4 +1,4 @@
1
- contractVersion: "37"
1
+ contractVersion: "52"
2
2
  componentType: connector
3
3
  componentKey: antigravity
4
4
  label: "Antigravity Connector"
@@ -6,16 +6,27 @@ description: "Antigravity plugin adapter for the Overlord mission protocol workf
6
6
 
7
7
  connector:
8
8
  agentIdentifier: antigravity
9
+ # ── GENERATED: do not edit by hand ───────────────────────────────────────────
10
+ # Projected from connectors/adapters/antigravity/harness-capabilities.yaml by `yarn connectors:capabilities`.
11
+ # `capabilities` and `hookTypes` are the DEPRECATED hook-named projection, retained for
12
+ # one release. `harnessCapabilities` is the authoritative source.
13
+ integrationShape: callback
14
+ capabilityTier: 0
15
+ harnessCapabilities:
16
+ path: connectors/adapters/antigravity/harness-capabilities.yaml
17
+ schemaVersion: 1
18
+ digest: "c021926c384a72bdaa62ac5f0eab57e80822c5d2996db75ea3c30c6bf5d09ce8"
9
19
  capabilities:
10
20
  - followUpHook
11
- - permissionHook
12
21
  - contextFilePrompt
13
22
  - slashCommands
14
23
  hookTypes:
15
24
  - UserPromptSubmit
16
- - PermissionRequest
25
+ # ── END GENERATED ────────────────────────────────────────────────────────────
17
26
  installPath: "~/.gemini/antigravity-cli/plugins/overlord"
18
27
  managedFiles:
28
+ - "harness-capabilities.yaml"
29
+ - "CAPABILITIES.md"
19
30
  - "plugin.json"
20
31
  - "mcp_config.json"
21
32
  - "hooks.json"
@@ -0,0 +1,24 @@
1
+ {
2
+ "fixtureVersion": 1,
3
+ "kind": "script-io",
4
+ "description": "Mandatory negative test: Antigravity's PreToolUse hook in a session with no Overlord binding, in an unrelated directory. It must make no write, no CLI invocation, and no delay. Its stdout is the harness's required allow response, which is the correct fail-toward-the-harness behavior for an unbound session.",
5
+ "script": "connectors/adapters/antigravity/scripts/pre-tool-use-hook.sh",
6
+ "stdin": {
7
+ "hook_event_name": "PreToolUse",
8
+ "tool_name": "run_command",
9
+ "tool_input": { "command": "rm -rf ./build" }
10
+ },
11
+ "env": {
12
+ "MISSION_ID": null,
13
+ "SESSION_KEY": null,
14
+ "OVERLORD_SESSION_CHANNEL_ID": null,
15
+ "OVERLORD_SESSION_CHANNEL_TOKEN": null
16
+ },
17
+ "expect": {
18
+ "exitCode": 0,
19
+ "stdout": "{\"allow_tool\":true}",
20
+ "stderr": "",
21
+ "cliInvocations": [],
22
+ "sandboxWrites": []
23
+ }
24
+ }