Remove the ACP release-matrix admission path

80e61fbb21f9 · Devin AI · · parent 46ed5df7e51e

Remove the ACP release-matrix admission path

Keep protocol conformance, hermetic artifact checks, and diagnostic peer probes while removing release-matrix validation, candidate runners, and release evidence. Grok and Cursor remain experimental because no release-evidence path can promote either peer.

Co-Authored-By: Christopher David <chris@openagents.com>
Co-Authored-By
Christopher David <chris@openagents.com>

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

Not deployed through the forge lane

No push, promotion, build, or deploy receipt references this commit (receipts are scanned over a bounded recent window). Changes shipped by full node replacement carry their proof in the release gate receipt instead.

Changed files

  • modified README.md
  • modified docs/assure-repo/false-green-candidates.v1.json
  • modified docs/assure-repo/surface-inventory.v1.json
  • modified package.json
  • modified packages/agent-client-protocol-conformance/README.md
  • deleted packages/agent-client-protocol-conformance/compatibility/live/desktop-cursor-release-run-2026-07-16-darwin-arm64.json
  • deleted packages/agent-client-protocol-conformance/compatibility/live/desktop-grok-release-run-2026-07-16-darwin-arm64.json
  • deleted packages/agent-client-protocol-conformance/compatibility/live/release-run-2026-07-16-darwin-arm64.json
  • deleted packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-auth-2026-07-16-darwin-arm64.json
  • deleted packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-current-2026-07-17-darwin-arm64.json
  • deleted packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-extensions-2026-07-16-darwin-arm64.json
  • deleted packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-auth-cancel-2026-07-16-darwin-arm64.json
  • deleted packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-current-2026-07-17-darwin-arm64.json
  • deleted packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-mcp-2026-07-16-darwin-arm64.json
  • deleted packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-metadata-2026-07-16-darwin-arm64.json
  • deleted packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-reverse-2026-07-16-darwin-arm64.json
  • deleted packages/agent-client-protocol-conformance/compatibility/release-matrix.json
  • modified packages/agent-client-protocol-conformance/package.json
  • deleted packages/agent-client-protocol-conformance/scripts/check-release-matrix.ts
  • deleted packages/agent-client-protocol-conformance/scripts/live-release-suite.ts
  • modified packages/agent-client-protocol-conformance/src/conformance.test.ts
  • modified packages/agent-client-protocol-conformance/src/index.ts
  • deleted packages/agent-client-protocol-conformance/src/live-release.ts
  • deleted packages/agent-client-protocol-conformance/src/release-evidence.test.ts
  • deleted packages/agent-client-protocol-conformance/src/release-evidence.ts
  • deleted packages/agent-client-protocol-conformance/src/release.ts

Diff

26 files changed, +15 -4549

README.md modified +7 -8

@@ -127,14 +127,13 @@ and digest-bound feature gates. Cursor's composer launches only a resolved

127 127
flat installation closure, negotiates `cursor_login`, and
128 128
keeps model discovery behind its versioned extension decoder. Diagnostic live
129 129
probes and source-derived fixtures remain explicitly non-release evidence. A
130
checked opt-in production runner now reproduces a redacted Grok/Cursor candidate
131
receipt in disposable repositories. It has no claim authority. The checked
132
[pinned live-binary matrix](packages/agent-client-protocol-conformance/compatibility/release-matrix.json)
133
and [human proof ledger](docs/qa/2026-07-16-acp10-release-proof/README.md) now
134
independently gate the two peers. Their current verdict is experimental because
135
the complete checked evidence has not yet been bound into shipped admission.
136
All code-owned required scenarios are now satisfied on tested Darwin arm64.
137
other platforms remain explicitly untested. Execution is tracked in
130
checked opt-in production runner is no longer part of the support path. The
131
[human proof ledger](docs/qa/2026-07-16-acp10-release-proof/README.md) remains a
132
historical record, and no release-evidence path can promote either peer above
133
`experimental`. ACP peer support remains experimental because it has no
134
release-evidence path.
135
Hermetic conformance checks cover the required scenario catalog. Other
136
platforms remain explicitly untested. Execution is tracked in
138 137
[#8887 — Full Agent Client Protocol integration for Grok and Cursor](https://github.com/OpenAgentsInc/openagents/issues/8887).
139 138
the wider reference set remains indexed in
140 139
[Product Teardowns](docs/teardowns/README.md).
docs/assure-repo/false-green-candidates.v1.json modified +1 -1

@@ -4,7 +4,7 @@

4 4
  "note": "Heuristic false-green LEADS, not findings. A finding requires a demonstrated reproduction (surviving mutation via mutation-runner). Do not treat a candidate as a confirmed false green. Coverage-theater leads may include tests that delegate their assertion to a custom helper the classifier does not recognise; verify before acting.",
5 5
  "sourceDigest": "sha256:dd810dd48c5bdbc9becd7fcc01dd41a4ca2abf0b2d6f6a545907247f6e3e8361",
6 6
  "summary": {
7
    "filesScanned": 2417,
7
    "filesScanned": 2421,
8 8
    "candidateCount": 16,
9 9
    "byMode": {
10 10
      "false_green_coverage_theater": 15,
docs/assure-repo/surface-inventory.v1.json modified +2 -2

@@ -1,7 +1,7 @@

1 1
{
2 2
  "schemaVersion": "1",
3 3
  "repository": "OpenAgentsInc/openagents",
4
  "sourceDigest": "sha256:89eece9db1d575b6b3f6b051835dee8e1e0cb211444b5ba390c36a92a4add904",
4
  "sourceDigest": "sha256:7c585930cb375e3359bfd928c7e78f38deb2cb8f84eaf0e16a8e2ade809a0795",
5 5
  "surfaces": [
6 6
    {
7 7
      "id": "app:@openagentsinc/acceptance-runner",

@@ -1876,7 +1876,7 @@

1876 1876
      "oracles": [
1877 1877
        {
1878 1878
          "type": "test",
1879
          "ref": "packages/openagents-cli (16 tracked test files)"
1879
          "ref": "packages/openagents-cli (20 tracked test files)"
1880 1880
        },
1881 1881
        {
1882 1882
          "type": "behavior-contract",
package.json modified +2 -2

@@ -6,7 +6,7 @@

6 6
  "scripts": {
7 7
    "check:vp2-node-runtime": "node scripts/vp2-node-runtime-guard.mjs",
8 8
    "check:agent-client-protocol": "pnpm --dir packages/agent-client-protocol run check:generated",
9
    "check:agent-client-protocol-conformance": "pnpm --dir packages/agent-client-protocol-conformance run check:artifacts && pnpm --dir packages/agent-client-protocol-conformance run check:release",
9
    "check:agent-client-protocol-conformance": "pnpm --dir packages/agent-client-protocol-conformance run check:artifacts",
10 10
    "check:all-work-contract": "pnpm --dir packages/all-work-contract run check:generated && cargo test -p openagents-all-work-contract",
11 11
    "check:codex-app-server-protocol": "pnpm --dir packages/codex-app-server-protocol run check:generated",
12 12
    "test:vp2-node": "node --test packages/runtime-platform/src/runtime-platform.node-suite.ts packages/sqlite-runtime/src/node-database.node-suite.ts scripts/public-cli-artifacts.node.test.mjs scripts/vp2-node-runtime-guard.test.mjs scripts/vp2-retained-service.node.test.mjs",

@@ -120,7 +120,7 @@

120 120
    "check:ste-control-semantics": "pnpm run check:ste-public-semantics",
121 121
    "check:node-vp-freeze": "node scripts/node-vp-cutover-inventory.mjs --check",
122 122
    "check:vp1-retirement": "node scripts/vp1-retired-money-surface-guard.mjs .",
123
    "check:deploy": "pnpm run check:google-cloud-authority && pnpm run check:ste:public && pnpm run check:ste-public-semantics && pnpm run test:ste && pnpm run check:sol-docs && pnpm run test:sol-docs && pnpm --dir packages/agent-client-protocol-conformance run check:release:freshness && pnpm --dir apps/openagents.com run check:deploy",
123
    "check:deploy": "pnpm run check:google-cloud-authority && pnpm run check:ste:public && pnpm run check:ste-public-semantics && pnpm run test:ste && pnpm run check:sol-docs && pnpm run test:sol-docs && pnpm --dir apps/openagents.com run check:deploy",
124 124
    "typecheck": "vp run --concurrency-limit 2 --filter './**' --filter '!./packages/probe' --filter '!./packages/probe/**' typecheck",
125 125
    "lint": "vp lint --report-unused-disable-directives",
126 126
    "fmt": "vp fmt",
packages/agent-client-protocol-conformance/README.md modified +2 -74

@@ -44,26 +44,10 @@ pnpm --dir packages/agent-client-protocol-conformance run typecheck

44 44
pnpm --dir packages/agent-client-protocol-conformance run test
45 45
pnpm --dir packages/agent-client-protocol-conformance run check:artifacts
46 46
pnpm --dir packages/agent-client-protocol-conformance run report
47
pnpm --dir packages/agent-client-protocol-conformance run check:release
48
pnpm --dir packages/agent-client-protocol-conformance run check:release:freshness
49 47
```
50 48
51
`compatibility/release-matrix.json` is the release-defining named-peer ledger.
52
It uses a closed claim vocabulary (`supported`, `experimental`, `incompatible`,
53
`not-installed`, `auth-required`, `degraded`) and distinguishes `live-pass`
54
from fixture-only, blocked, untested, unsupported, and failed scenarios. The
55
validator enforces the exact release/schema/platform/profile/binary identities,
56
the complete 47-scenario catalog, and repository-local evidence references
57
before recomputing release eligibility. The push-path `check:release` gate
58
blocks content errors and prints a warning when the freshness window expires.
59
The release-path `check:release:freshness` gate also blocks an expired window.
60
Requiredness and evidence class are code-owned: required live peer and packaged
61
Desktop rows require live proof, optional peer alternatives do not gate the
62
default path, and only explicitly hermetic production-transport rows may be
63
satisfied by executed fixture proof. Matrix flags cannot self-exempt a provider,
64
and one provider can never mask the other. The current checked verdict is `supported`
65
for the exact pinned Grok 0.2.101 and Cursor 2026.06.24 Darwin arm64 identities
66
only. Other versions and platforms remain experimental or not tested.
49
ACP peer support remains experimental. This package has no release-evidence
50
path and cannot promote Grok or Cursor above `experimental`.
67 51
68 52
Live probes are inert unless explicitly armed and never run in ordinary CI:
69 53

@@ -72,62 +56,6 @@ GROK_ACP_LIVE=1 pnpm --dir packages/agent-client-protocol-conformance run live:g

72 56
CURSOR_ACP_LIVE=1 pnpm --dir packages/agent-client-protocol-conformance run live:cursor
73 57
```
74 58
75
The deeper candidate runner launches the production Grok and Cursor runtimes in
76
separate disposable Git repositories, authenticates through the peers' normal
77
local login, performs sequential prompts, and attempts session listing, mode
78
changes, streaming cancellation, and bounded shutdown where advertised. Its
79
Grok lane also sends a random canary only through broker-materialized stdio MCP
80
environment, proves the disposable server received it by digest, shuts Grok
81
down, and scans the exact session/configuration persistence surfaces for the
82
unredacted value:
83
84
```bash
85
ACP_RELEASE_LIVE=1 ACP_RELEASE_PEER=both \
86
  pnpm --dir packages/agent-client-protocol-conformance run live:release
87
```
88
89
Set `ACP_RELEASE_OUTPUT` to an absolute `.json` path beneath
90
`compatibility/live/` to retain its closed-schema, redacted receipt. The runner
91
does not retain prompts, responses, session IDs, auth material, or absolute
92
paths. Its artifact is deliberately marked `candidate-live` and has no power to
93
change the release matrix or promote either peer. A human-reviewed matrix edit
94
and the fail-closed `check:release` gate remain mandatory. The Cursor lane also
95
proves client-side `cursor_login` cancellation using the ordinary HOME and
96
stopping before `authenticate`. It never creates an empty HOME or changes login
97
or keychain state. Its exact-binary extension qualification registers only the
98
four allowlisted Cursor methods and retains aggregate observation counts. An
99
unobserved extension remains blocked rather than inferred from a prompt. The
100
same rule applies to permission qualification: only an option actually offered
101
by the peer may be selected, and zero reverse calls remain zero live evidence.
102
Cursor approval and refusal run in separate pinned processes with an empty
103
allow/deny policy stored only in the disposable repository's `.cursor/cli.json`.
104
the runner never changes the user's global Cursor configuration.
105
The Grok qualification additionally enables bounded filesystem and simulated
106
terminal handlers only inside the disposable repository, forces only its new
107
disposable sessions out of inherited YOLO/auto mode through session metadata,
108
and retains method counts rather than file, command, terminal, or response
109
content. It never changes global Grok configuration.
110
The shared runtime also preserves notification and prompt-completion `_meta` as
111
private native evidence. Candidate receipts expose only metadata-presence and
112
usage-presence counts. They never export token values, model/session IDs, or
113
other metadata contents.
114
115
After packaging Desktop, the separately armed peer journey proves real app
116
workspace refusal, interruption, restart settlement, re-enable, completion,
117
disable, and shutdown without changing HOME or credential/keychain state:
118
119
```bash
120
ACP_DESKTOP_RELEASE_LIVE=1 ACP_DESKTOP_RELEASE_PEER=<grok-or-cursor> \
121
  ACP_DESKTOP_RELEASE_OUTPUT=<absolute compatibility/live JSON path> \
122
  pnpm --dir apps/openagents-desktop run smoke:acp-release
123
```
124
125
The checked live records beneath `compatibility/live/` pin the installed
126
commands, full reported builds, executable/installation-closure digests, wire
127
version, advertised auth methods, and capability keys. The release matrix adds
128
the deeper redacted peer runs described in the human ledger. Every unexercised
129
required scenario remains an explicit blocker to a `supported` claim.
130
131 59
Each probe emits one machine-readable diagnostic result with command, binary
132 60
version, schema identity, and initialize outcome. It does not authenticate,
133 61
print secrets, or establish a release claim.
packages/agent-client-protocol-conformance/compatibility/live/desktop-cursor-release-run-2026-07-16-darwin-arm64.json deleted -39

@@ -1,39 +0,0 @@

1
{
2
  "format": "openagents-acp-desktop-release-run-v1",
3
  "protocol": "Agent Client Protocol",
4
  "protocolExclusions": [
5
    "Agent Communication Protocol",
6
    "A2A"
7
  ],
8
  "proofClass": "candidate-packaged-desktop-live",
9
  "claimAuthority": "none-release-matrix-only",
10
  "recordedAt": "2026-07-16T16:46:36.674Z",
11
  "openAgentsRevision": "661c1b3c7f74ac396026ec6aa1a0c6ea8845dcd1",
12
  "platform": "darwin-arm64-node-24.13.1",
13
  "provider": "cursor",
14
  "lane": "acp:cursor-agent",
15
  "packaged": true,
16
  "interruption": {
17
    "mismatchedWorkspaceRefused": true,
18
    "laneConfigured": true,
19
    "laneAdmitted": true,
20
    "exitedDuringRunningTurn": true
21
  },
22
  "recovery": {
23
    "reusedDesktopState": true,
24
    "explicitlyReenabledSameThread": true,
25
    "recoveredSameThread": true,
26
    "freshThreadRetryAfterFailure": false,
27
    "laneConfigured": true,
28
    "interruptedTurnSettled": true,
29
    "durableCompletedTurn": true,
30
    "disabled": true
31
  },
32
  "redaction": {
33
    "promptTextRetained": false,
34
    "responseTextRetained": false,
35
    "threadIdentifiersRetained": false,
36
    "authMaterialRetained": false,
37
    "absolutePathsRetained": false
38
  }
39
}
packages/agent-client-protocol-conformance/compatibility/live/desktop-grok-release-run-2026-07-16-darwin-arm64.json deleted -40

@@ -1,40 +0,0 @@

1
{
2
  "format": "openagents-acp-desktop-release-run-v1",
3
  "protocol": "Agent Client Protocol",
4
  "protocolExclusions": [
5
    "Agent Communication Protocol",
6
    "A2A"
7
  ],
8
  "proofClass": "candidate-packaged-desktop-live",
9
  "claimAuthority": "none-release-matrix-only",
10
  "recordedAt": "2026-07-16T16:56:36.589Z",
11
  "openAgentsRevision": "4bb214739f4bd41732e96a12514223f9cc57982e",
12
  "platform": "darwin-arm64-node-24.13.1",
13
  "provider": "grok",
14
  "lane": "acp:grok-cli",
15
  "packaged": true,
16
  "interruption": {
17
    "mismatchedWorkspaceRefused": true,
18
    "laneConfigured": true,
19
    "laneAdmitted": true,
20
    "exitedDuringRunningTurn": true
21
  },
22
  "recovery": {
23
    "reusedDesktopState": true,
24
    "explicitlyReenabledSameThread": true,
25
    "recoveredSameThread": true,
26
    "freshThreadRetryAfterFailure": false,
27
    "additionalProcessRestartAfterFailedRetry": true,
28
    "laneConfigured": true,
29
    "interruptedTurnSettled": true,
30
    "durableCompletedTurn": true,
31
    "disabled": true
32
  },
33
  "redaction": {
34
    "promptTextRetained": false,
35
    "responseTextRetained": false,
36
    "threadIdentifiersRetained": false,
37
    "authMaterialRetained": false,
38
    "absolutePathsRetained": false
39
  }
40
}
packages/agent-client-protocol-conformance/compatibility/live/release-run-2026-07-16-darwin-arm64.json deleted -182

@@ -1,182 +0,0 @@

1
{
2
  "format": "openagents-acp-live-release-run-v1",
3
  "protocol": "Agent Client Protocol",
4
  "protocolExclusions": [
5
    "Agent Communication Protocol",
6
    "A2A"
7
  ],
8
  "proofClass": "candidate-live",
9
  "claimAuthority": "none-release-matrix-only",
10
  "recordedAt": "2026-07-16T16:49:32.334Z",
11
  "openAgentsRevision": "661c1b3c7f74ac396026ec6aa1a0c6ea8845dcd1",
12
  "schemaRelease": "schema-v1.19.0",
13
  "platform": "darwin-arm64-node-24.13.1",
14
  "peers": [
15
    {
16
      "peer": "grok",
17
      "result": "partial",
18
      "binary": {
19
        "reportedVersion": "grok 0.2.101 (5bc4b5dfadcf) [stable]",
20
        "executableSha256": "8431538dbd99379240f558b48b779c651d668b06d793c87311ad532c4395a4e2"
21
      },
22
      "negotiation": {
23
        "wireVersion": 1,
24
        "authMethodIds": [
25
          "cached_token",
26
          "grok.com"
27
        ],
28
        "capabilityKeys": [
29
          "load"
30
        ]
31
      },
32
      "scenarios": [
33
        {
34
          "id": "identity-version",
35
          "result": "live-pass",
36
          "safeDetail": "Exact Grok version and executable digest probed"
37
        },
38
        {
39
          "id": "initialize",
40
          "result": "live-pass",
41
          "safeDetail": "Wire version 1 initialize completed"
42
        },
43
        {
44
          "id": "auth-primary",
45
          "result": "live-pass",
46
          "safeDetail": "Advertised cached authentication completed"
47
        },
48
        {
49
          "id": "session-new",
50
          "result": "live-pass",
51
          "safeDetail": "Disposable repository session created"
52
        },
53
        {
54
          "id": "real-repo-text",
55
          "result": "live-pass",
56
          "safeDetail": "Real disposable repository produced assistant text"
57
        },
58
        {
59
          "id": "sequential-turns",
60
          "result": "live-pass",
61
          "safeDetail": "Two sequential prompts completed"
62
        },
63
        {
64
          "id": "session-list",
65
          "result": "not-observed",
66
          "safeDetail": "Peer did not advertise session list"
67
        },
68
        {
69
          "id": "stream-cancel",
70
          "result": "live-pass",
71
          "safeDetail": "Streaming prompt cancelled after 1 updates"
72
        },
73
        {
74
          "id": "cleanup-bounds",
75
          "result": "not-observed",
76
          "safeDetail": "Shutdown ran in finally; this runner does not retain process leak counters"
77
        }
78
      ],
79
      "counters": {
80
        "updateCount": 106,
81
        "updateKinds": [
82
          "agent_message_chunk",
83
          "agent_thought_chunk",
84
          "available_commands_update",
85
          "tool_call",
86
          "tool_call_update",
87
          "user_message_chunk"
88
        ],
89
        "promptCount": 3
90
      }
91
    },
92
    {
93
      "peer": "cursor",
94
      "result": "partial",
95
      "binary": {
96
        "reportedVersion": "2026.06.24-00-45-58-9f61de7",
97
        "executableSha256": "b7babf47d8b1eee28ac27a74affa02a559bb38103a6e71fbb1f120805d51fedf",
98
        "installationClosureSha256": "69d078daa4db8cbb4163ce2f010207553efb06d652c1e1ea421d739795532faa"
99
      },
100
      "negotiation": {
101
        "wireVersion": 1,
102
        "authMethodIds": [
103
          "cursor_login"
104
        ],
105
        "capabilityKeys": [
106
          "list",
107
          "load"
108
        ]
109
      },
110
      "scenarios": [
111
        {
112
          "id": "identity-version",
113
          "result": "live-pass",
114
          "safeDetail": "Exact Cursor version and installation closure probed"
115
        },
116
        {
117
          "id": "initialize",
118
          "result": "live-pass",
119
          "safeDetail": "Wire version 1 initialize completed"
120
        },
121
        {
122
          "id": "auth-primary",
123
          "result": "live-pass",
124
          "safeDetail": "Advertised Cursor login completed"
125
        },
126
        {
127
          "id": "session-new",
128
          "result": "live-pass",
129
          "safeDetail": "Disposable repository session created"
130
        },
131
        {
132
          "id": "real-repo-text",
133
          "result": "live-pass",
134
          "safeDetail": "Real disposable repository produced assistant text"
135
        },
136
        {
137
          "id": "sequential-turns",
138
          "result": "live-pass",
139
          "safeDetail": "Two sequential prompts completed"
140
        },
141
        {
142
          "id": "session-list",
143
          "result": "live-pass",
144
          "safeDetail": "Advertised session list completed"
145
        },
146
        {
147
          "id": "model-mode-config",
148
          "result": "live-pass",
149
          "safeDetail": "Advertised mode change completed"
150
        },
151
        {
152
          "id": "stream-cancel",
153
          "result": "live-pass",
154
          "safeDetail": "Streaming prompt cancelled after 0 updates"
155
        },
156
        {
157
          "id": "cleanup-bounds",
158
          "result": "not-observed",
159
          "safeDetail": "Shutdown ran in finally; this runner does not retain process leak counters"
160
        }
161
      ],
162
      "counters": {
163
        "updateCount": 17,
164
        "updateKinds": [
165
          "agent_message_chunk",
166
          "agent_thought_chunk",
167
          "available_commands_update",
168
          "current_mode_update",
169
          "session_info_update"
170
        ],
171
        "promptCount": 3
172
      }
173
    }
174
  ],
175
  "redaction": {
176
    "promptTextRetained": false,
177
    "responseTextRetained": false,
178
    "sessionIdentifiersRetained": false,
179
    "authMaterialRetained": false,
180
    "absolutePathsRetained": false
181
  }
182
}
packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-auth-2026-07-16-darwin-arm64.json deleted -102

@@ -1,102 +0,0 @@

1
{
2
  "format": "openagents-acp-live-release-run-v1",
3
  "protocol": "Agent Client Protocol",
4
  "protocolExclusions": ["Agent Communication Protocol", "A2A"],
5
  "proofClass": "candidate-live",
6
  "claimAuthority": "none-release-matrix-only",
7
  "recordedAt": "2026-07-16T17:12:04.946Z",
8
  "openAgentsRevision": "29fe5ad3e750a0ab79048e234d509316a6c0a821",
9
  "schemaRelease": "schema-v1.19.0",
10
  "platform": "darwin-arm64-node-24.13.1",
11
  "peers": [
12
    {
13
      "peer": "cursor",
14
      "result": "partial",
15
      "binary": {
16
        "reportedVersion": "2026.06.24-00-45-58-9f61de7",
17
        "executableSha256": "b7babf47d8b1eee28ac27a74affa02a559bb38103a6e71fbb1f120805d51fedf",
18
        "installationClosureSha256": "69d078daa4db8cbb4163ce2f010207553efb06d652c1e1ea421d739795532faa"
19
      },
20
      "negotiation": {
21
        "wireVersion": 1,
22
        "authMethodIds": ["cursor_login"],
23
        "capabilityKeys": ["list", "load"]
24
      },
25
      "scenarios": [
26
        {
27
          "id": "identity-version",
28
          "result": "live-pass",
29
          "safeDetail": "Exact Cursor version and installation closure probed"
30
        },
31
        {
32
          "id": "initialize",
33
          "result": "live-pass",
34
          "safeDetail": "Wire version 1 initialize completed"
35
        },
36
        {
37
          "id": "auth-primary",
38
          "result": "live-pass",
39
          "safeDetail": "Advertised Cursor login completed"
40
        },
41
        {
42
          "id": "auth-cancel",
43
          "result": "live-pass",
44
          "safeDetail": "Client cancelled advertised login before authenticate and received auth required"
45
        },
46
        {
47
          "id": "session-new",
48
          "result": "live-pass",
49
          "safeDetail": "Disposable repository session created"
50
        },
51
        {
52
          "id": "real-repo-text",
53
          "result": "live-pass",
54
          "safeDetail": "Real disposable repository produced assistant text"
55
        },
56
        {
57
          "id": "sequential-turns",
58
          "result": "live-pass",
59
          "safeDetail": "Two sequential prompts completed"
60
        },
61
        {
62
          "id": "session-list",
63
          "result": "live-pass",
64
          "safeDetail": "Advertised session list completed"
65
        },
66
        {
67
          "id": "model-mode-config",
68
          "result": "live-pass",
69
          "safeDetail": "Advertised mode change completed"
70
        },
71
        {
72
          "id": "stream-cancel",
73
          "result": "live-pass",
74
          "safeDetail": "Streaming prompt cancelled after 0 updates"
75
        },
76
        {
77
          "id": "cleanup-bounds",
78
          "result": "not-observed",
79
          "safeDetail": "Shutdown ran in finally; this runner does not retain process leak counters"
80
        }
81
      ],
82
      "counters": {
83
        "updateCount": 18,
84
        "updateKinds": [
85
          "agent_message_chunk",
86
          "agent_thought_chunk",
87
          "available_commands_update",
88
          "current_mode_update",
89
          "session_info_update"
90
        ],
91
        "promptCount": 3
92
      }
93
    }
94
  ],
95
  "redaction": {
96
    "promptTextRetained": false,
97
    "responseTextRetained": false,
98
    "sessionIdentifiersRetained": false,
99
    "authMaterialRetained": false,
100
    "absolutePathsRetained": false
101
  }
102
}
packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-current-2026-07-17-darwin-arm64.json deleted -128

@@ -1,128 +0,0 @@

1
{
2
  "format": "openagents-acp-live-release-run-v1",
3
  "protocol": "Agent Client Protocol",
4
  "protocolExclusions": [
5
    "Agent Communication Protocol",
6
    "A2A"
7
  ],
8
  "proofClass": "candidate-live",
9
  "claimAuthority": "none-release-matrix-only",
10
  "recordedAt": "2026-07-17T12:16:40.076Z",
11
  "openAgentsRevision": "6a26feb82244247b1d591c26aa5ff614b00b8b50",
12
  "schemaRelease": "schema-v1.19.0",
13
  "platform": "darwin-arm64-node-24.13.1",
14
  "peers": [
15
    {
16
      "peer": "cursor",
17
      "result": "partial",
18
      "binary": {
19
        "reportedVersion": "2026.06.24-00-45-58-9f61de7",
20
        "executableSha256": "b7babf47d8b1eee28ac27a74affa02a559bb38103a6e71fbb1f120805d51fedf",
21
        "installationClosureSha256": "69d078daa4db8cbb4163ce2f010207553efb06d652c1e1ea421d739795532faa"
22
      },
23
      "negotiation": {
24
        "wireVersion": 1,
25
        "authMethodIds": [
26
          "cursor_login"
27
        ],
28
        "capabilityKeys": [
29
          "list",
30
          "load"
31
        ]
32
      },
33
      "scenarios": [
34
        {
35
          "id": "identity-version",
36
          "result": "live-pass",
37
          "safeDetail": "Exact Cursor version and installation closure probed"
38
        },
39
        {
40
          "id": "initialize",
41
          "result": "live-pass",
42
          "safeDetail": "Wire version 1 initialize completed"
43
        },
44
        {
45
          "id": "auth-primary",
46
          "result": "live-pass",
47
          "safeDetail": "Advertised Cursor login completed"
48
        },
49
        {
50
          "id": "auth-cancel",
51
          "result": "live-pass",
52
          "safeDetail": "Client cancelled advertised login before authenticate and received auth required"
53
        },
54
        {
55
          "id": "session-new",
56
          "result": "live-pass",
57
          "safeDetail": "Disposable repository session created"
58
        },
59
        {
60
          "id": "real-repo-text",
61
          "result": "live-pass",
62
          "safeDetail": "Real disposable repository produced assistant text"
63
        },
64
        {
65
          "id": "sequential-turns",
66
          "result": "live-pass",
67
          "safeDetail": "Two sequential prompts completed"
68
        },
69
        {
70
          "id": "session-list",
71
          "result": "live-pass",
72
          "safeDetail": "Advertised session list completed"
73
        },
74
        {
75
          "id": "model-mode-config",
76
          "result": "live-pass",
77
          "safeDetail": "Advertised mode change completed"
78
        },
79
        {
80
          "id": "stream-cancel",
81
          "result": "live-pass",
82
          "safeDetail": "Streaming prompt cancelled after 0 updates"
83
        },
84
        {
85
          "id": "cleanup-bounds",
86
          "result": "not-observed",
87
          "safeDetail": "Shutdown ran in finally; this runner does not retain process leak counters"
88
        },
89
        {
90
          "id": "cursor-extensions-models",
91
          "result": "not-observed",
92
          "safeDetail": "Pinned extension counts: questions 0, plans 0, todos 0, models 33"
93
        },
94
        {
95
          "id": "permission-approval",
96
          "result": "live-pass",
97
          "safeDetail": "Pinned permission approval selections: 1"
98
        },
99
        {
100
          "id": "permission-refusal",
101
          "result": "live-pass",
102
          "safeDetail": "Pinned permission refusal selections: 1"
103
        }
104
      ],
105
      "counters": {
106
        "updateCount": 19,
107
        "updateKinds": [
108
          "agent_message_chunk",
109
          "agent_thought_chunk",
110
          "available_commands_update",
111
          "current_mode_update",
112
          "session_info_update"
113
        ],
114
        "promptCount": 3,
115
        "updateMetadataCount": 0,
116
        "completionMetadataCount": 0,
117
        "usageMetadataCount": 0
118
      }
119
    }
120
  ],
121
  "redaction": {
122
    "promptTextRetained": false,
123
    "responseTextRetained": false,
124
    "sessionIdentifiersRetained": false,
125
    "authMaterialRetained": false,
126
    "absolutePathsRetained": false
127
  }
128
}
packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-extensions-2026-07-16-darwin-arm64.json deleted -124

@@ -1,124 +0,0 @@

1
{
2
  "format": "openagents-acp-live-release-run-v1",
3
  "protocol": "Agent Client Protocol",
4
  "protocolExclusions": [
5
    "Agent Communication Protocol",
6
    "A2A"
7
  ],
8
  "proofClass": "candidate-live",
9
  "claimAuthority": "none-release-matrix-only",
10
  "recordedAt": "2026-07-16T17:57:59.006Z",
11
  "openAgentsRevision": "8677fec5a5c4267cdfb8181fd649e140f82300d0",
12
  "schemaRelease": "schema-v1.19.0",
13
  "platform": "darwin-arm64-node-24.13.1",
14
  "peers": [
15
    {
16
      "peer": "cursor",
17
      "result": "partial",
18
      "binary": {
19
        "reportedVersion": "2026.06.24-00-45-58-9f61de7",
20
        "executableSha256": "b7babf47d8b1eee28ac27a74affa02a559bb38103a6e71fbb1f120805d51fedf",
21
        "installationClosureSha256": "69d078daa4db8cbb4163ce2f010207553efb06d652c1e1ea421d739795532faa"
22
      },
23
      "negotiation": {
24
        "wireVersion": 1,
25
        "authMethodIds": [
26
          "cursor_login"
27
        ],
28
        "capabilityKeys": [
29
          "list",
30
          "load"
31
        ]
32
      },
33
      "scenarios": [
34
        {
35
          "id": "identity-version",
36
          "result": "live-pass",
37
          "safeDetail": "Exact Cursor version and installation closure probed"
38
        },
39
        {
40
          "id": "initialize",
41
          "result": "live-pass",
42
          "safeDetail": "Wire version 1 initialize completed"
43
        },
44
        {
45
          "id": "auth-primary",
46
          "result": "live-pass",
47
          "safeDetail": "Advertised Cursor login completed"
48
        },
49
        {
50
          "id": "auth-cancel",
51
          "result": "live-pass",
52
          "safeDetail": "Client cancelled advertised login before authenticate and received auth required"
53
        },
54
        {
55
          "id": "session-new",
56
          "result": "live-pass",
57
          "safeDetail": "Disposable repository session created"
58
        },
59
        {
60
          "id": "real-repo-text",
61
          "result": "live-pass",
62
          "safeDetail": "Real disposable repository produced assistant text"
63
        },
64
        {
65
          "id": "sequential-turns",
66
          "result": "live-pass",
67
          "safeDetail": "Two sequential prompts completed"
68
        },
69
        {
70
          "id": "session-list",
71
          "result": "live-pass",
72
          "safeDetail": "Advertised session list completed"
73
        },
74
        {
75
          "id": "model-mode-config",
76
          "result": "live-pass",
77
          "safeDetail": "Advertised mode change completed"
78
        },
79
        {
80
          "id": "stream-cancel",
81
          "result": "live-pass",
82
          "safeDetail": "Streaming prompt cancelled after 0 updates"
83
        },
84
        {
85
          "id": "cleanup-bounds",
86
          "result": "not-observed",
87
          "safeDetail": "Shutdown ran in finally; this runner does not retain process leak counters"
88
        },
89
        {
90
          "id": "cursor-extensions-models",
91
          "result": "not-observed",
92
          "safeDetail": "Pinned extension counts: questions 0, plans 1, todos 0, models 33"
93
        },
94
        {
95
          "id": "permission-approval",
96
          "result": "live-pass",
97
          "safeDetail": "Pinned permission approval selections: 1"
98
        },
99
        {
100
          "id": "permission-refusal",
101
          "result": "live-pass",
102
          "safeDetail": "Pinned permission refusal selections: 1"
103
        }
104
      ],
105
      "counters": {
106
        "updateCount": 12,
107
        "updateKinds": [
108
          "agent_message_chunk",
109
          "agent_thought_chunk",
110
          "available_commands_update",
111
          "current_mode_update"
112
        ],
113
        "promptCount": 3
114
      }
115
    }
116
  ],
117
  "redaction": {
118
    "promptTextRetained": false,
119
    "responseTextRetained": false,
120
    "sessionIdentifiersRetained": false,
121
    "authMaterialRetained": false,
122
    "absolutePathsRetained": false
123
  }
124
}
packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-auth-cancel-2026-07-16-darwin-arm64.json deleted -136

@@ -1,136 +0,0 @@

1
{
2
  "format": "openagents-acp-live-release-run-v1",
3
  "protocol": "Agent Client Protocol",
4
  "protocolExclusions": [
5
    "Agent Communication Protocol",
6
    "A2A"
7
  ],
8
  "proofClass": "candidate-live",
9
  "claimAuthority": "none-release-matrix-only",
10
  "recordedAt": "2026-07-16T18:12:12.590Z",
11
  "openAgentsRevision": "b0a397edd0fa91599bde5dd089b053adc3268da0",
12
  "schemaRelease": "schema-v1.19.0",
13
  "platform": "darwin-arm64-node-24.13.1",
14
  "peers": [
15
    {
16
      "peer": "grok",
17
      "result": "partial",
18
      "binary": {
19
        "reportedVersion": "grok 0.2.101 (5bc4b5dfadcf) [stable]",
20
        "executableSha256": "8431538dbd99379240f558b48b779c651d668b06d793c87311ad532c4395a4e2"
21
      },
22
      "negotiation": {
23
        "wireVersion": 1,
24
        "authMethodIds": [
25
          "cached_token",
26
          "grok.com"
27
        ],
28
        "capabilityKeys": [
29
          "load"
30
        ]
31
      },
32
      "scenarios": [
33
        {
34
          "id": "identity-version",
35
          "result": "live-pass",
36
          "safeDetail": "Exact Grok version and executable digest probed"
37
        },
38
        {
39
          "id": "initialize",
40
          "result": "live-pass",
41
          "safeDetail": "Wire version 1 initialize completed"
42
        },
43
        {
44
          "id": "auth-primary",
45
          "result": "live-pass",
46
          "safeDetail": "Advertised cached authentication completed"
47
        },
48
        {
49
          "id": "auth-cancel",
50
          "result": "live-pass",
51
          "safeDetail": "Client cancelled explicitly requested Grok login before authenticate"
52
        },
53
        {
54
          "id": "session-new",
55
          "result": "live-pass",
56
          "safeDetail": "Disposable repository session created"
57
        },
58
        {
59
          "id": "real-repo-text",
60
          "result": "live-pass",
61
          "safeDetail": "Real disposable repository produced assistant text"
62
        },
63
        {
64
          "id": "sequential-turns",
65
          "result": "live-pass",
66
          "safeDetail": "Two sequential prompts completed"
67
        },
68
        {
69
          "id": "session-list",
70
          "result": "not-observed",
71
          "safeDetail": "Peer did not advertise session list"
72
        },
73
        {
74
          "id": "stream-cancel",
75
          "result": "live-pass",
76
          "safeDetail": "Streaming prompt cancelled after 1 updates"
77
        },
78
        {
79
          "id": "mcp-authorized",
80
          "result": "live-pass",
81
          "safeDetail": "Brokered MCP canary reached only the disposable stdio server"
82
        },
83
        {
84
          "id": "mcp-no-durable-secret",
85
          "result": "live-pass",
86
          "safeDetail": "Bounded post-shutdown scan found zero canary matches in 23 files"
87
        },
88
        {
89
          "id": "cleanup-bounds",
90
          "result": "live-pass",
91
          "safeDetail": "Runtime completed bounded shutdown before scanning"
92
        },
93
        {
94
          "id": "grok-question-extensions",
95
          "result": "not-observed",
96
          "safeDetail": "Pinned question methods observed: 1"
97
        },
98
        {
99
          "id": "permission-approval",
100
          "result": "live-pass",
101
          "safeDetail": "Pinned permission approval selections: 5"
102
        },
103
        {
104
          "id": "permission-refusal",
105
          "result": "live-pass",
106
          "safeDetail": "Pinned permission refusal selections: 1"
107
        },
108
        {
109
          "id": "fs-terminal-enabled",
110
          "result": "live-pass",
111
          "safeDetail": "Pinned reverse calls: filesystem 4, terminal 16"
112
        }
113
      ],
114
      "counters": {
115
        "updateCount": 63,
116
        "updateKinds": [
117
          "agent_message_chunk",
118
          "agent_thought_chunk",
119
          "available_commands_update",
120
          "user_message_chunk"
121
        ],
122
        "promptCount": 3,
123
        "updateMetadataCount": 63,
124
        "completionMetadataCount": 2,
125
        "usageMetadataCount": 62
126
      }
127
    }
128
  ],
129
  "redaction": {
130
    "promptTextRetained": false,
131
    "responseTextRetained": false,
132
    "sessionIdentifiersRetained": false,
133
    "authMaterialRetained": false,
134
    "absolutePathsRetained": false
135
  }
136
}
packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-current-2026-07-17-darwin-arm64.json deleted -136

@@ -1,136 +0,0 @@

1
{
2
  "format": "openagents-acp-live-release-run-v1",
3
  "protocol": "Agent Client Protocol",
4
  "protocolExclusions": [
5
    "Agent Communication Protocol",
6
    "A2A"
7
  ],
8
  "proofClass": "candidate-live",
9
  "claimAuthority": "none-release-matrix-only",
10
  "recordedAt": "2026-07-17T12:15:58.619Z",
11
  "openAgentsRevision": "6a26feb82244247b1d591c26aa5ff614b00b8b50",
12
  "schemaRelease": "schema-v1.19.0",
13
  "platform": "darwin-arm64-node-24.13.1",
14
  "peers": [
15
    {
16
      "peer": "grok",
17
      "result": "partial",
18
      "binary": {
19
        "reportedVersion": "grok 0.2.101 (5bc4b5dfadcf) [stable]",
20
        "executableSha256": "8431538dbd99379240f558b48b779c651d668b06d793c87311ad532c4395a4e2"
21
      },
22
      "negotiation": {
23
        "wireVersion": 1,
24
        "authMethodIds": [
25
          "cached_token",
26
          "grok.com"
27
        ],
28
        "capabilityKeys": [
29
          "load"
30
        ]
31
      },
32
      "scenarios": [
33
        {
34
          "id": "identity-version",
35
          "result": "live-pass",
36
          "safeDetail": "Exact Grok version and executable digest probed"
37
        },
38
        {
39
          "id": "initialize",
40
          "result": "live-pass",
41
          "safeDetail": "Wire version 1 initialize completed"
42
        },
43
        {
44
          "id": "auth-primary",
45
          "result": "live-pass",
46
          "safeDetail": "Advertised cached authentication completed"
47
        },
48
        {
49
          "id": "auth-cancel",
50
          "result": "live-pass",
51
          "safeDetail": "Client cancelled explicitly requested Grok login before authenticate"
52
        },
53
        {
54
          "id": "session-new",
55
          "result": "live-pass",
56
          "safeDetail": "Disposable repository session created"
57
        },
58
        {
59
          "id": "real-repo-text",
60
          "result": "live-pass",
61
          "safeDetail": "Real disposable repository produced assistant text"
62
        },
63
        {
64
          "id": "sequential-turns",
65
          "result": "live-pass",
66
          "safeDetail": "Two sequential prompts completed"
67
        },
68
        {
69
          "id": "session-list",
70
          "result": "not-observed",
71
          "safeDetail": "Peer did not advertise session list"
72
        },
73
        {
74
          "id": "stream-cancel",
75
          "result": "live-pass",
76
          "safeDetail": "Streaming prompt cancelled after 1 updates"
77
        },
78
        {
79
          "id": "mcp-authorized",
80
          "result": "live-pass",
81
          "safeDetail": "Brokered MCP canary reached only the disposable stdio server"
82
        },
83
        {
84
          "id": "mcp-no-durable-secret",
85
          "result": "live-pass",
86
          "safeDetail": "Bounded post-shutdown scan found zero canary matches in 23 files"
87
        },
88
        {
89
          "id": "cleanup-bounds",
90
          "result": "live-pass",
91
          "safeDetail": "Runtime completed bounded shutdown before scanning"
92
        },
93
        {
94
          "id": "grok-question-extensions",
95
          "result": "not-observed",
96
          "safeDetail": "Pinned question methods observed: 1"
97
        },
98
        {
99
          "id": "permission-approval",
100
          "result": "live-pass",
101
          "safeDetail": "Pinned permission approval selections: 4"
102
        },
103
        {
104
          "id": "permission-refusal",
105
          "result": "live-pass",
106
          "safeDetail": "Pinned permission refusal selections: 1"
107
        },
108
        {
109
          "id": "fs-terminal-enabled",
110
          "result": "live-pass",
111
          "safeDetail": "Pinned reverse calls: filesystem 4, terminal 12"
112
        }
113
      ],
114
      "counters": {
115
        "updateCount": 66,
116
        "updateKinds": [
117
          "agent_message_chunk",
118
          "agent_thought_chunk",
119
          "available_commands_update",
120
          "user_message_chunk"
121
        ],
122
        "promptCount": 3,
123
        "updateMetadataCount": 66,
124
        "completionMetadataCount": 2,
125
        "usageMetadataCount": 65
126
      }
127
    }
128
  ],
129
  "redaction": {
130
    "promptTextRetained": false,
131
    "responseTextRetained": false,
132
    "sessionIdentifiersRetained": false,
133
    "authMaterialRetained": false,
134
    "absolutePathsRetained": false
135
  }
136
}
packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-mcp-2026-07-16-darwin-arm64.json deleted -102

@@ -1,102 +0,0 @@

1
{
2
  "format": "openagents-acp-live-release-run-v1",
3
  "protocol": "Agent Client Protocol",
4
  "protocolExclusions": ["Agent Communication Protocol", "A2A"],
5
  "proofClass": "candidate-live",
6
  "claimAuthority": "none-release-matrix-only",
7
  "recordedAt": "2026-07-16T17:09:00.256Z",
8
  "openAgentsRevision": "ce4fe714f05a9f4ca0530e71d4a66b5602d987e4",
9
  "schemaRelease": "schema-v1.19.0",
10
  "platform": "darwin-arm64-node-24.13.1",
11
  "peers": [
12
    {
13
      "peer": "grok",
14
      "result": "partial",
15
      "binary": {
16
        "reportedVersion": "grok 0.2.101 (5bc4b5dfadcf) [stable]",
17
        "executableSha256": "8431538dbd99379240f558b48b779c651d668b06d793c87311ad532c4395a4e2"
18
      },
19
      "negotiation": {
20
        "wireVersion": 1,
21
        "authMethodIds": ["cached_token", "grok.com"],
22
        "capabilityKeys": ["load"]
23
      },
24
      "scenarios": [
25
        {
26
          "id": "identity-version",
27
          "result": "live-pass",
28
          "safeDetail": "Exact Grok version and executable digest probed"
29
        },
30
        {
31
          "id": "initialize",
32
          "result": "live-pass",
33
          "safeDetail": "Wire version 1 initialize completed"
34
        },
35
        {
36
          "id": "auth-primary",
37
          "result": "live-pass",
38
          "safeDetail": "Advertised cached authentication completed"
39
        },
40
        {
41
          "id": "session-new",
42
          "result": "live-pass",
43
          "safeDetail": "Disposable repository session created"
44
        },
45
        {
46
          "id": "real-repo-text",
47
          "result": "live-pass",
48
          "safeDetail": "Real disposable repository produced assistant text"
49
        },
50
        {
51
          "id": "sequential-turns",
52
          "result": "live-pass",
53
          "safeDetail": "Two sequential prompts completed"
54
        },
55
        {
56
          "id": "session-list",
57
          "result": "not-observed",
58
          "safeDetail": "Peer did not advertise session list"
59
        },
60
        {
61
          "id": "stream-cancel",
62
          "result": "live-pass",
63
          "safeDetail": "Streaming prompt cancelled after 1 updates"
64
        },
65
        {
66
          "id": "mcp-authorized",
67
          "result": "live-pass",
68
          "safeDetail": "Brokered MCP canary reached only the disposable stdio server"
69
        },
70
        {
71
          "id": "mcp-no-durable-secret",
72
          "result": "live-pass",
73
          "safeDetail": "Bounded post-shutdown scan found zero canary matches in 23 files"
74
        },
75
        {
76
          "id": "cleanup-bounds",
77
          "result": "live-pass",
78
          "safeDetail": "Runtime completed bounded shutdown before scanning"
79
        }
80
      ],
81
      "counters": {
82
        "updateCount": 110,
83
        "updateKinds": [
84
          "agent_message_chunk",
85
          "agent_thought_chunk",
86
          "available_commands_update",
87
          "tool_call",
88
          "tool_call_update",
89
          "user_message_chunk"
90
        ],
91
        "promptCount": 3
92
      }
93
    }
94
  ],
95
  "redaction": {
96
    "promptTextRetained": false,
97
    "responseTextRetained": false,
98
    "sessionIdentifiersRetained": false,
99
    "authMaterialRetained": false,
100
    "absolutePathsRetained": false
101
  }
102
}
packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-metadata-2026-07-16-darwin-arm64.json deleted -123

@@ -1,123 +0,0 @@

1
{
2
  "format": "openagents-acp-live-release-run-v1",
3
  "protocol": "Agent Client Protocol",
4
  "protocolExclusions": ["Agent Communication Protocol", "A2A"],
5
  "proofClass": "candidate-live",
6
  "claimAuthority": "none-release-matrix-only",
7
  "recordedAt": "2026-07-16T18:07:25.480Z",
8
  "openAgentsRevision": "d242b3bf08c83010fb5e80a0f8a7c0593c6db063",
9
  "schemaRelease": "schema-v1.19.0",
10
  "platform": "darwin-arm64-node-24.13.1",
11
  "peers": [
12
    {
13
      "peer": "grok",
14
      "result": "partial",
15
      "binary": {
16
        "reportedVersion": "grok 0.2.101 (5bc4b5dfadcf) [stable]",
17
        "executableSha256": "8431538dbd99379240f558b48b779c651d668b06d793c87311ad532c4395a4e2"
18
      },
19
      "negotiation": {
20
        "wireVersion": 1,
21
        "authMethodIds": ["cached_token", "grok.com"],
22
        "capabilityKeys": ["load"]
23
      },
24
      "scenarios": [
25
        {
26
          "id": "identity-version",
27
          "result": "live-pass",
28
          "safeDetail": "Exact Grok version and executable digest probed"
29
        },
30
        {
31
          "id": "initialize",
32
          "result": "live-pass",
33
          "safeDetail": "Wire version 1 initialize completed"
34
        },
35
        {
36
          "id": "auth-primary",
37
          "result": "live-pass",
38
          "safeDetail": "Advertised cached authentication completed"
39
        },
40
        {
41
          "id": "session-new",
42
          "result": "live-pass",
43
          "safeDetail": "Disposable repository session created"
44
        },
45
        {
46
          "id": "real-repo-text",
47
          "result": "live-pass",
48
          "safeDetail": "Real disposable repository produced assistant text"
49
        },
50
        {
51
          "id": "sequential-turns",
52
          "result": "live-pass",
53
          "safeDetail": "Two sequential prompts completed"
54
        },
55
        {
56
          "id": "session-list",
57
          "result": "not-observed",
58
          "safeDetail": "Peer did not advertise session list"
59
        },
60
        {
61
          "id": "stream-cancel",
62
          "result": "live-pass",
63
          "safeDetail": "Streaming prompt cancelled after 1 updates"
64
        },
65
        {
66
          "id": "mcp-authorized",
67
          "result": "live-pass",
68
          "safeDetail": "Brokered MCP canary reached only the disposable stdio server"
69
        },
70
        {
71
          "id": "mcp-no-durable-secret",
72
          "result": "live-pass",
73
          "safeDetail": "Bounded post-shutdown scan found zero canary matches in 23 files"
74
        },
75
        {
76
          "id": "cleanup-bounds",
77
          "result": "live-pass",
78
          "safeDetail": "Runtime completed bounded shutdown before scanning"
79
        },
80
        {
81
          "id": "grok-question-extensions",
82
          "result": "not-observed",
83
          "safeDetail": "Pinned question methods observed: 1"
84
        },
85
        {
86
          "id": "permission-approval",
87
          "result": "live-pass",
88
          "safeDetail": "Pinned permission approval selections: 4"
89
        },
90
        {
91
          "id": "permission-refusal",
92
          "result": "live-pass",
93
          "safeDetail": "Pinned permission refusal selections: 1"
94
        },
95
        {
96
          "id": "fs-terminal-enabled",
97
          "result": "live-pass",
98
          "safeDetail": "Pinned reverse calls: filesystem 4, terminal 20"
99
        }
100
      ],
101
      "counters": {
102
        "updateCount": 63,
103
        "updateKinds": [
104
          "agent_message_chunk",
105
          "agent_thought_chunk",
106
          "available_commands_update",
107
          "user_message_chunk"
108
        ],
109
        "promptCount": 3,
110
        "updateMetadataCount": 63,
111
        "completionMetadataCount": 2,
112
        "usageMetadataCount": 62
113
      }
114
    }
115
  ],
116
  "redaction": {
117
    "promptTextRetained": false,
118
    "responseTextRetained": false,
119
    "sessionIdentifiersRetained": false,
120
    "authMaterialRetained": false,
121
    "absolutePathsRetained": false
122
  }
123
}
packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-reverse-2026-07-16-darwin-arm64.json deleted -128

@@ -1,128 +0,0 @@

1
{
2
  "format": "openagents-acp-live-release-run-v1",
3
  "protocol": "Agent Client Protocol",
4
  "protocolExclusions": [
5
    "Agent Communication Protocol",
6
    "A2A"
7
  ],
8
  "proofClass": "candidate-live",
9
  "claimAuthority": "none-release-matrix-only",
10
  "recordedAt": "2026-07-16T17:40:55.849Z",
11
  "openAgentsRevision": "b20fe2427629fe9233fcfb7b3abc407e87c921d5",
12
  "schemaRelease": "schema-v1.19.0",
13
  "platform": "darwin-arm64-node-24.13.1",
14
  "peers": [
15
    {
16
      "peer": "grok",
17
      "result": "partial",
18
      "binary": {
19
        "reportedVersion": "grok 0.2.101 (5bc4b5dfadcf) [stable]",
20
        "executableSha256": "8431538dbd99379240f558b48b779c651d668b06d793c87311ad532c4395a4e2"
21
      },
22
      "negotiation": {
23
        "wireVersion": 1,
24
        "authMethodIds": [
25
          "cached_token",
26
          "grok.com"
27
        ],
28
        "capabilityKeys": [
29
          "load"
30
        ]
31
      },
32
      "scenarios": [
33
        {
34
          "id": "identity-version",
35
          "result": "live-pass",
36
          "safeDetail": "Exact Grok version and executable digest probed"
37
        },
38
        {
39
          "id": "initialize",
40
          "result": "live-pass",
41
          "safeDetail": "Wire version 1 initialize completed"
42
        },
43
        {
44
          "id": "auth-primary",
45
          "result": "live-pass",
46
          "safeDetail": "Advertised cached authentication completed"
47
        },
48
        {
49
          "id": "session-new",
50
          "result": "live-pass",
51
          "safeDetail": "Disposable repository session created"
52
        },
53
        {
54
          "id": "real-repo-text",
55
          "result": "live-pass",
56
          "safeDetail": "Real disposable repository produced assistant text"
57
        },
58
        {
59
          "id": "sequential-turns",
60
          "result": "live-pass",
61
          "safeDetail": "Two sequential prompts completed"
62
        },
63
        {
64
          "id": "session-list",
65
          "result": "not-observed",
66
          "safeDetail": "Peer did not advertise session list"
67
        },
68
        {
69
          "id": "stream-cancel",
70
          "result": "live-pass",
71
          "safeDetail": "Streaming prompt cancelled after 1 updates"
72
        },
73
        {
74
          "id": "mcp-authorized",
75
          "result": "live-pass",
76
          "safeDetail": "Brokered MCP canary reached only the disposable stdio server"
77
        },
78
        {
79
          "id": "mcp-no-durable-secret",
80
          "result": "live-pass",
81
          "safeDetail": "Bounded post-shutdown scan found zero canary matches in 23 files"
82
        },
83
        {
84
          "id": "cleanup-bounds",
85
          "result": "live-pass",
86
          "safeDetail": "Runtime completed bounded shutdown before scanning"
87
        },
88
        {
89
          "id": "grok-question-extensions",
90
          "result": "not-observed",
91
          "safeDetail": "Pinned question methods observed: 1"
92
        },
93
        {
94
          "id": "permission-approval",
95
          "result": "live-pass",
96
          "safeDetail": "Pinned permission approval selections: 5"
97
        },
98
        {
99
          "id": "permission-refusal",
100
          "result": "live-pass",
101
          "safeDetail": "Pinned permission refusal selections: 1"
102
        },
103
        {
104
          "id": "fs-terminal-enabled",
105
          "result": "live-pass",
106
          "safeDetail": "Pinned reverse calls: filesystem 4, terminal 16"
107
        }
108
      ],
109
      "counters": {
110
        "updateCount": 61,
111
        "updateKinds": [
112
          "agent_message_chunk",
113
          "agent_thought_chunk",
114
          "available_commands_update",
115
          "user_message_chunk"
116
        ],
117
        "promptCount": 3
118
      }
119
    }
120
  ],
121
  "redaction": {
122
    "promptTextRetained": false,
123
    "responseTextRetained": false,
124
    "sessionIdentifiersRetained": false,
125
    "authMaterialRetained": false,
126
    "absolutePathsRetained": false
127
  }
128
}
packages/agent-client-protocol-conformance/compatibility/release-matrix.json deleted -910

@@ -1,910 +0,0 @@

1
{
2
  "format": "openagents-acp-release-matrix-v1",
3
  "protocol": "Agent Client Protocol",
4
  "protocolExclusions": ["Agent Communication Protocol", "A2A"],
5
  "recordedAt": "2026-07-17T12:16:40Z",
6
  "freshnessDays": 30,
7
  "openAgents": {
8
    "revision": "6a26feb82244247b1d591c26aa5ff614b00b8b50",
9
    "desktopIntegrationRevision": "6a26feb82244247b1d591c26aa5ff614b00b8b50",
10
    "build": "source-built Desktop admission integration plus retained packaged Desktop journeys; packaging refresh excluded from the current work order",
11
    "protocolPackageRevision": "workspace@6a26feb82244247b1d591c26aa5ff614b00b8b50",
12
    "schemaRelease": "schema-v1.19.0",
13
    "schemaSha256": "92c1dfcda10dd47e99127500a3763da2b471f9ac61e12b9bf0430c32cf953796"
14
  },
15
  "platform": {
16
    "tested": "darwin-arm64",
17
    "osVersion": "26.4",
18
    "nodeVersion": "24.13.1",
19
    "notTested": ["darwin-x64", "linux-arm64", "linux-x64"]
20
  },
21
  "statusVocabulary": {
22
    "claim": [
23
      "supported",
24
      "experimental",
25
      "incompatible",
26
      "not-installed",
27
      "auth-required",
28
      "degraded"
29
    ],
30
    "scenario": ["live-pass", "fixture-pass", "blocked", "not-tested", "unsupported", "fail"],
31
    "evidenceClass": [
32
      "live-peer",
33
      "packaged-desktop-live",
34
      "hermetic-production",
35
      "not-applicable"
36
    ],
37
    "rule": "Code owns scenario requiredness and evidence class. Live-peer and packaged-desktop-live require live-pass; hermetic-production accepts an executed fixture-pass; matrix flags cannot self-exempt a peer."
38
  },
39
  "peers": [
40
    {
41
      "peer": "grok",
42
      "profile": { "id": "grok-cli", "revision": 1 },
43
      "binary": {
44
        "command": ["grok", "agent", "stdio"],
45
        "reportedVersion": "grok 0.2.101 (5bc4b5dfadcf)",
46
        "resolvedExecutableName": "grok-0.2.101",
47
        "sha256": "8431538dbd99379240f558b48b779c651d668b06d793c87311ad532c4395a4e2",
48
        "installationSource": "detected external installation; installer provenance not proven"
49
      },
50
      "negotiation": {
51
        "wireVersion": 1,
52
        "peerIdentity": { "name": "grok", "version": "0.2.101" },
53
        "authMethodIds": ["cached_token", "grok.com"],
54
        "advertisedCapabilityKeys": [
55
          "auth",
56
          "loadSession",
57
          "mcpCapabilities",
58
          "promptCapabilities",
59
          "sessionCapabilities"
60
        ]
61
      },
62
      "claimState": "supported",
63
      "releaseEligible": true,
64
      "scenarios": [
65
        {
66
          "id": "identity-version",
67
          "requiredForSupported": true,
68
          "result": "live-pass",
69
          "evidenceRefs": [
70
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json",
71
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-current-2026-07-17-darwin-arm64.json"
72
          ],
73
          "safeDetail": "Exact installed version and executable digest passed."
74
        },
75
        {
76
          "id": "incompatible-version-rejection",
77
          "requiredForSupported": true,
78
          "result": "fixture-pass",
79
          "evidenceRefs": ["packages/agent-client-protocol/src/profiles/profiles.test.ts"],
80
          "safeDetail": "Admission rejection is hermetic; no alternate real binary was installed."
81
        },
82
        {
83
          "id": "initialize",
84
          "requiredForSupported": true,
85
          "result": "live-pass",
86
          "evidenceRefs": [
87
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
88
          ],
89
          "safeDetail": "Wire v1 initialize passed with sanitized capability identifiers."
90
        },
91
        {
92
          "id": "auth-primary",
93
          "requiredForSupported": true,
94
          "result": "live-pass",
95
          "evidenceRefs": [
96
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
97
          ],
98
          "safeDetail": "Cached-token authentication passed without retaining auth material."
99
        },
100
        {
101
          "id": "auth-secondary",
102
          "requiredForSupported": false,
103
          "result": "not-tested",
104
          "evidenceRefs": [],
105
          "safeDetail": "Optional xai.api_key authentication was not configured. Existing local cached_token authentication is the supported headless default and requires no API key."
106
        },
107
        {
108
          "id": "auth-cancel",
109
          "requiredForSupported": true,
110
          "result": "live-pass",
111
          "evidenceRefs": [
112
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-auth-cancel-2026-07-16-darwin-arm64.json"
113
          ],
114
          "safeDetail": "With ordinary HOME and cached login intact, the client explicitly selected advertised grok.com, cancelled once before authenticate, and returned typed auth_required without opening a browser or changing credentials."
115
        },
116
        {
117
          "id": "auth-expiry-failure",
118
          "requiredForSupported": true,
119
          "result": "live-pass",
120
          "evidenceRefs": [
121
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
122
          ],
123
          "safeDetail": "The required failure branch passed with an intentionally invalid API key, followed by recovery in a fresh cached-token process; no stored credential was changed."
124
        },
125
        {
126
          "id": "auth-logout-reauth",
127
          "requiredForSupported": false,
128
          "result": "unsupported",
129
          "evidenceRefs": [
130
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
131
          ],
132
          "safeDetail": "The exact Grok initialize response advertised no auth.logout capability; fresh-process cached-token authentication is covered independently."
133
        },
134
        {
135
          "id": "session-new",
136
          "requiredForSupported": true,
137
          "result": "live-pass",
138
          "evidenceRefs": [
139
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
140
          ],
141
          "safeDetail": "A disposable-repository session was created."
142
        },
143
        {
144
          "id": "session-list",
145
          "requiredForSupported": true,
146
          "result": "live-pass",
147
          "evidenceRefs": [
148
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-2026-07-16-darwin-arm64.json"
149
          ],
150
          "safeDetail": "The pinned peer did not advertise session/list; the production runner retained the exact capability-false outcome and did not call an absent method."
151
        },
152
        {
153
          "id": "session-load",
154
          "requiredForSupported": true,
155
          "result": "live-pass",
156
          "evidenceRefs": [
157
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
158
          ],
159
          "safeDetail": "A new peer process loaded the prior session and completed another prompt."
160
        },
161
        {
162
          "id": "session-resume-close-delete",
163
          "requiredForSupported": false,
164
          "result": "unsupported",
165
          "evidenceRefs": ["packages/agent-client-protocol/src/profiles/grok.ts"],
166
          "safeDetail": "The pinned profile does not claim these lifecycle methods."
167
        },
168
        {
169
          "id": "real-repo-text",
170
          "requiredForSupported": true,
171
          "result": "live-pass",
172
          "evidenceRefs": [
173
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
174
          ],
175
          "safeDetail": "A real disposable Git repository produced text updates and end_turn."
176
        },
177
        {
178
          "id": "real-repo-tool-plan-config-usage",
179
          "requiredForSupported": true,
180
          "result": "live-pass",
181
          "evidenceRefs": [
182
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json",
183
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-metadata-2026-07-16-darwin-arm64.json"
184
          ],
185
          "safeDetail": "A disposable-file tool call emitted three updates and created the file; 63 live updates and two completions retained private metadata, with 62 usage-bearing observations. Grok advertises no mode/config surface."
186
        },
187
        {
188
          "id": "permission-approval",
189
          "requiredForSupported": true,
190
          "result": "live-pass",
191
          "evidenceRefs": [
192
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-reverse-2026-07-16-darwin-arm64.json"
193
          ],
194
          "safeDetail": "A disposable ask-mode session selected five peer-offered allow-once permission options."
195
        },
196
        {
197
          "id": "permission-refusal",
198
          "requiredForSupported": true,
199
          "result": "live-pass",
200
          "evidenceRefs": [
201
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-reverse-2026-07-16-darwin-arm64.json"
202
          ],
203
          "safeDetail": "A separate disposable ask-mode session selected one peer-offered reject option before command execution."
204
        },
205
        {
206
          "id": "permission-timeout-stale-policy",
207
          "requiredForSupported": true,
208
          "result": "fixture-pass",
209
          "evidenceRefs": ["packages/agent-client-protocol-conformance/src/conformance.test.ts"],
210
          "safeDetail": "Production host timeout, stale-response fencing, and policy-denial paths pass hermetically; these are host authority semantics rather than peer behavior."
211
        },
212
        {
213
          "id": "fs-terminal-enabled",
214
          "requiredForSupported": true,
215
          "result": "live-pass",
216
          "evidenceRefs": [
217
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-reverse-2026-07-16-darwin-arm64.json"
218
          ],
219
          "safeDetail": "The pinned Grok peer made four filesystem and sixteen terminal reverse calls through explicitly enabled bounded qualification handlers in a disposable repository."
220
        },
221
        {
222
          "id": "fs-terminal-disabled",
223
          "requiredForSupported": true,
224
          "result": "fixture-pass",
225
          "evidenceRefs": ["packages/agent-client-protocol-conformance/src/conformance.test.ts"],
226
          "safeDetail": "Capability-false refusal is hermetic only."
227
        },
228
        {
229
          "id": "mcp-authorized",
230
          "requiredForSupported": true,
231
          "result": "live-pass",
232
          "evidenceRefs": [
233
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
234
          ],
235
          "safeDetail": "A broker-materialized authorization canary reached only the local MCP server; initialize, tools/list, and tools/call completed in the intended live session."
236
        },
237
        {
238
          "id": "mcp-expired-refusal",
239
          "requiredForSupported": true,
240
          "result": "fixture-pass",
241
          "evidenceRefs": [
242
            "packages/agent-client-protocol-conformance/fixtures/mcp/expired-ref/input.json"
243
          ],
244
          "safeDetail": "Expired reference refusal passed before peer launch."
245
        },
246
        {
247
          "id": "mcp-no-durable-secret",
248
          "requiredForSupported": true,
249
          "result": "live-pass",
250
          "evidenceRefs": [
251
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-grok-mcp-2026-07-16-darwin-arm64.json"
252
          ],
253
          "safeDetail": "A broker-only canary reached the disposable MCP server, then a complete bounded scan of the exact disposable session tree, MCP logs, and Grok configuration/state surfaces found zero durable matches."
254
        },
255
        {
256
          "id": "model-mode-config",
257
          "requiredForSupported": false,
258
          "result": "unsupported",
259
          "evidenceRefs": ["packages/agent-client-protocol/src/profiles/grok.ts"],
260
          "safeDetail": "The pinned Grok profile claims no mode or model configuration surface."
261
        },
262
        {
263
          "id": "stream-cancel",
264
          "requiredForSupported": true,
265
          "result": "live-pass",
266
          "evidenceRefs": [
267
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
268
          ],
269
          "safeDetail": "session/cancel during a live stream returned cancelled after three updates."
270
        },
271
        {
272
          "id": "reverse-cancel",
273
          "requiredForSupported": true,
274
          "result": "live-pass",
275
          "evidenceRefs": [
276
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
277
          ],
278
          "safeDetail": "An underscore question reverse request was session-bound, its AbortSignal fired, and the turn returned cancelled."
279
        },
280
        {
281
          "id": "crash-kill-restart",
282
          "requiredForSupported": true,
283
          "result": "live-pass",
284
          "evidenceRefs": [
285
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
286
          ],
287
          "safeDetail": "The pinned process was SIGKILLed, reported crash, restarted in a new process, loaded the session, and completed the post-repair prompt."
288
        },
289
        {
290
          "id": "malformed-unknown-output",
291
          "requiredForSupported": true,
292
          "result": "fixture-pass",
293
          "evidenceRefs": [
294
            "packages/agent-client-protocol-conformance/compatibility/fault-matrix.json"
295
          ],
296
          "safeDetail": "Malformed and unknown output handling is hermetic only."
297
        },
298
        {
299
          "id": "attachment-repair",
300
          "requiredForSupported": true,
301
          "result": "live-pass",
302
          "evidenceRefs": [
303
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
304
          ],
305
          "safeDetail": "After orderly process restart, session/load repaired the attachment and the next prompt completed."
306
        },
307
        {
308
          "id": "sequential-turns",
309
          "requiredForSupported": true,
310
          "result": "live-pass",
311
          "evidenceRefs": [
312
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
313
          ],
314
          "safeDetail": "Two turns completed before restart and one after load."
315
        },
316
        {
317
          "id": "multiple-sessions",
318
          "requiredForSupported": true,
319
          "result": "live-pass",
320
          "evidenceRefs": [
321
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
322
          ],
323
          "safeDetail": "Two independent live peer processes completed sessions concurrently, matching the single-root-session-per-process policy."
324
        },
325
        {
326
          "id": "cleanup-bounds",
327
          "requiredForSupported": true,
328
          "result": "live-pass",
329
          "evidenceRefs": [
330
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
331
          ],
332
          "safeDetail": "Single live process shutdown passed; repeated leak proof remains separate."
333
        },
334
        {
335
          "id": "fragmented-oversized",
336
          "requiredForSupported": true,
337
          "result": "fixture-pass",
338
          "evidenceRefs": [
339
            "packages/agent-client-protocol-conformance/compatibility/fault-matrix.json"
340
          ],
341
          "safeDetail": "Frame bounds are production-transport fixture proof."
342
        },
343
        {
344
          "id": "stderr-update-flood",
345
          "requiredForSupported": true,
346
          "result": "fixture-pass",
347
          "evidenceRefs": ["packages/agent-client-protocol-conformance/src/conformance.test.ts"],
348
          "safeDetail": "Redacted stderr and bounded update handling are hermetic only."
349
        },
350
        {
351
          "id": "queue-stall-timeout-race",
352
          "requiredForSupported": true,
353
          "result": "fixture-pass",
354
          "evidenceRefs": [
355
            "packages/agent-client-protocol-conformance/compatibility/fault-matrix.json"
356
          ],
357
          "safeDetail": "Queue, stall, timeout, late response, and cancellation races are hermetic only."
358
        },
359
        {
360
          "id": "crash-loop-repeat",
361
          "requiredForSupported": true,
362
          "result": "live-pass",
363
          "evidenceRefs": [
364
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
365
          ],
366
          "safeDetail": "Five crash cycles plus five clean cycles completed with zero exit-listener delta and zero pending request counters after clean shutdown."
367
        },
368
        {
369
          "id": "secret-scan",
370
          "requiredForSupported": true,
371
          "result": "live-pass",
372
          "evidenceRefs": [
373
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
374
          ],
375
          "safeDetail": "The serialized production-host support bundle had zero matches for prompt, private path, authorization, cached-provider-auth, or provider-secret canaries."
376
        },
377
        {
378
          "id": "trust-controls",
379
          "requiredForSupported": true,
380
          "result": "fixture-pass",
381
          "evidenceRefs": ["packages/agent-client-protocol/src/profiles/profiles.test.ts"],
382
          "safeDetail": "Executable, argv, environment, and profile admission controls pass hermetically."
383
        },
384
        {
385
          "id": "grok-wire-launch",
386
          "requiredForSupported": true,
387
          "result": "live-pass",
388
          "evidenceRefs": [
389
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
390
          ],
391
          "safeDetail": "grok agent stdio negotiated wire v1."
392
        },
393
        {
394
          "id": "grok-rich-stream",
395
          "requiredForSupported": true,
396
          "result": "live-pass",
397
          "evidenceRefs": [
398
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
399
          ],
400
          "safeDetail": "Live message, thought, available-command, and user-message update kinds were observed; tool/plan variants remain unproven."
401
        },
402
        {
403
          "id": "grok-load-replay",
404
          "requiredForSupported": true,
405
          "result": "live-pass",
406
          "evidenceRefs": [
407
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json"
408
          ],
409
          "safeDetail": "A fresh peer process loaded the existing session and completed a post-load prompt."
410
        },
411
        {
412
          "id": "grok-question-extensions",
413
          "requiredForSupported": true,
414
          "result": "live-pass",
415
          "evidenceRefs": [
416
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json",
417
            "packages/agent-client-runtime-bridge/src/vendor-handlers.test.ts"
418
          ],
419
          "safeDetail": "Pinned Grok 0.2.101 emitted _x.ai/ask_user_question live; the same allowlisted production handler also accepts the historical x.ai/ask_user_question spelling, which this exact build did not emit."
420
        },
421
        {
422
          "id": "cursor-wire-launch",
423
          "requiredForSupported": false,
424
          "result": "unsupported",
425
          "evidenceRefs": [],
426
          "safeDetail": "Cursor-only scenario."
427
        },
428
        {
429
          "id": "cursor-login-lifecycle",
430
          "requiredForSupported": false,
431
          "result": "unsupported",
432
          "evidenceRefs": [],
433
          "safeDetail": "Cursor-only scenario."
434
        },
435
        {
436
          "id": "cursor-extensions-models",
437
          "requiredForSupported": false,
438
          "result": "unsupported",
439
          "evidenceRefs": [],
440
          "safeDetail": "Cursor-only scenario."
441
        },
442
        {
443
          "id": "cursor-load-unsupported",
444
          "requiredForSupported": false,
445
          "result": "unsupported",
446
          "evidenceRefs": [],
447
          "safeDetail": "Cursor-only scenario."
448
        },
449
        {
450
          "id": "desktop-clean-machine",
451
          "requiredForSupported": true,
452
          "result": "live-pass",
453
          "evidenceRefs": [
454
            "packages/agent-client-protocol-conformance/compatibility/live/desktop-grok-release-run-2026-07-16-darwin-arm64.json"
455
          ],
456
          "safeDetail": "The packaged Grok lane refused a mismatched workspace, interrupted a running turn across app exit, settled the old turn on restart, preserved its one-session-per-process admission rule, restarted cleanly, completed the original durable thread, disabled, and shut down."
457
        },
458
        {
459
          "id": "support-bundle",
460
          "requiredForSupported": true,
461
          "result": "live-pass",
462
          "evidenceRefs": [
463
            "packages/agent-client-protocol-conformance/compatibility/live/grok-0.2.101-darwin-arm64.json",
464
            "docs/qa/2026-07-16-acp-provider-lanes/README.md"
465
          ],
466
          "safeDetail": "The production main-owned host ran both pinned drivers and exported its closed support schema; the serialized bundle contained zero forbidden prompt, path, auth, or provider-secret matches."
467
        }
468
      ]
469
    },
470
    {
471
      "peer": "cursor",
472
      "profile": { "id": "cursor-agent", "revision": 3 },
473
      "binary": {
474
        "command": ["agent", "acp"],
475
        "reportedVersion": "2026.06.24-00-45-58-9f61de7",
476
        "classifiedVersion": "2026.6.24",
477
        "resolvedExecutableName": "cursor-agent",
478
        "sha256": "b7babf47d8b1eee28ac27a74affa02a559bb38103a6e71fbb1f120805d51fedf",
479
        "installationClosureSha256": "69d078daa4db8cbb4163ce2f010207553efb06d652c1e1ea421d739795532faa",
480
        "installationSource": "detected external installation; installer provenance not proven"
481
      },
482
      "negotiation": {
483
        "wireVersion": 1,
484
        "peerIdentity": { "name": "cursor-agent", "version": "2026.06.24" },
485
        "authMethodIds": ["cursor_login"],
486
        "advertisedCapabilityKeys": [
487
          "loadSession",
488
          "mcpCapabilities",
489
          "promptCapabilities",
490
          "sessionCapabilities"
491
        ],
492
        "advertisedSessionCapabilityKeys": ["list"]
493
      },
494
      "claimState": "supported",
495
      "releaseEligible": true,
496
      "scenarios": [
497
        {
498
          "id": "identity-version",
499
          "requiredForSupported": true,
500
          "result": "live-pass",
501
          "evidenceRefs": [
502
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json",
503
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-current-2026-07-17-darwin-arm64.json"
504
          ],
505
          "safeDetail": "Exact installed version, launcher digest, and installation closure passed."
506
        },
507
        {
508
          "id": "incompatible-version-rejection",
509
          "requiredForSupported": true,
510
          "result": "fixture-pass",
511
          "evidenceRefs": ["packages/agent-client-protocol/src/profiles/profiles.test.ts"],
512
          "safeDetail": "Admission rejection is hermetic; no alternate real binary was installed."
513
        },
514
        {
515
          "id": "initialize",
516
          "requiredForSupported": true,
517
          "result": "live-pass",
518
          "evidenceRefs": [
519
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
520
          ],
521
          "safeDetail": "Wire v1 initialize passed with sanitized capability identifiers."
522
        },
523
        {
524
          "id": "auth-primary",
525
          "requiredForSupported": true,
526
          "result": "live-pass",
527
          "evidenceRefs": [
528
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
529
          ],
530
          "safeDetail": "cursor_login authenticated an existing signed-in session without retained auth material."
531
        },
532
        {
533
          "id": "auth-secondary",
534
          "requiredForSupported": false,
535
          "result": "unsupported",
536
          "evidenceRefs": ["packages/agent-client-protocol/src/profiles/cursor.ts"],
537
          "safeDetail": "The pinned profile advertises no second auth path."
538
        },
539
        {
540
          "id": "auth-cancel",
541
          "requiredForSupported": true,
542
          "result": "live-pass",
543
          "evidenceRefs": [
544
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-auth-2026-07-16-darwin-arm64.json"
545
          ],
546
          "safeDetail": "Using the ordinary signed-in HOME, the client cancelled the advertised cursor_login decision before authenticate; exactly one decision callback ran and the runtime returned typed auth_required without altering login or keychain state."
547
        },
548
        {
549
          "id": "auth-expiry-failure",
550
          "requiredForSupported": true,
551
          "result": "fixture-pass",
552
          "evidenceRefs": [
553
            "packages/cursor-agent-runtime/src/cursor-peer-runtime.test.ts",
554
            "packages/agent-client-runtime-bridge/src/session-runtime.ts"
555
          ],
556
          "safeDetail": "The production runtime returns typed auth_lost, disposes the failed process, and permits a fresh-process cursor_login retry. Deliberate expiry of the user's stored credential was not required or performed."
557
        },
558
        {
559
          "id": "auth-logout-reauth",
560
          "requiredForSupported": false,
561
          "result": "unsupported",
562
          "evidenceRefs": [
563
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
564
          ],
565
          "safeDetail": "The exact Cursor initialize response advertised no auth.logout capability; fresh-process cursor_login authentication is covered independently."
566
        },
567
        {
568
          "id": "session-new",
569
          "requiredForSupported": true,
570
          "result": "live-pass",
571
          "evidenceRefs": [
572
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
573
          ],
574
          "safeDetail": "A disposable-repository session was created."
575
        },
576
        {
577
          "id": "session-list",
578
          "requiredForSupported": true,
579
          "result": "live-pass",
580
          "evidenceRefs": [
581
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
582
          ],
583
          "safeDetail": "Advertised session/list completed successfully and returned an empty result for the disposable workspace."
584
        },
585
        {
586
          "id": "session-load",
587
          "requiredForSupported": true,
588
          "result": "live-pass",
589
          "evidenceRefs": [
590
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
591
          ],
592
          "safeDetail": "A new peer process loaded the prior session and completed another prompt."
593
        },
594
        {
595
          "id": "session-resume-close-delete",
596
          "requiredForSupported": false,
597
          "result": "unsupported",
598
          "evidenceRefs": [
599
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
600
          ],
601
          "safeDetail": "Resume, close, and delete were not advertised by this build."
602
        },
603
        {
604
          "id": "real-repo-text",
605
          "requiredForSupported": true,
606
          "result": "live-pass",
607
          "evidenceRefs": [
608
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
609
          ],
610
          "safeDetail": "A real disposable Git repository produced text/thought updates and end_turn."
611
        },
612
        {
613
          "id": "real-repo-tool-plan-config-usage",
614
          "requiredForSupported": true,
615
          "result": "live-pass",
616
          "evidenceRefs": [
617
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json",
618
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-extensions-2026-07-16-darwin-arm64.json"
619
          ],
620
          "safeDetail": "A disposable-file tool call emitted three tool updates and created the file; live plan, model listing, mode, and configuration paths passed. The exact adapter returned stopReason without a usage payload, so no unsupported usage variant is claimed."
621
        },
622
        {
623
          "id": "permission-approval",
624
          "requiredForSupported": true,
625
          "result": "live-pass",
626
          "evidenceRefs": [
627
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-extensions-2026-07-16-darwin-arm64.json"
628
          ],
629
          "safeDetail": "A disposable project-local deny-by-default policy induced one peer-offered approval selection in an isolated process."
630
        },
631
        {
632
          "id": "permission-refusal",
633
          "requiredForSupported": true,
634
          "result": "live-pass",
635
          "evidenceRefs": [
636
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-extensions-2026-07-16-darwin-arm64.json"
637
          ],
638
          "safeDetail": "A separate pinned process selected one peer-offered refusal before command execution."
639
        },
640
        {
641
          "id": "permission-timeout-stale-policy",
642
          "requiredForSupported": true,
643
          "result": "fixture-pass",
644
          "evidenceRefs": ["packages/agent-client-protocol-conformance/src/conformance.test.ts"],
645
          "safeDetail": "Production host timeout, stale-response fencing, and policy-denial paths pass hermetically; these are host authority semantics rather than peer behavior."
646
        },
647
        {
648
          "id": "fs-terminal-enabled",
649
          "requiredForSupported": false,
650
          "result": "unsupported",
651
          "evidenceRefs": ["packages/agent-client-protocol/src/profiles/cursor.ts"],
652
          "safeDetail": "The pinned Cursor profile deliberately withholds reverse filesystem and terminal."
653
        },
654
        {
655
          "id": "fs-terminal-disabled",
656
          "requiredForSupported": true,
657
          "result": "fixture-pass",
658
          "evidenceRefs": ["packages/agent-client-protocol-conformance/src/conformance.test.ts"],
659
          "safeDetail": "Capability-false refusal is hermetic only."
660
        },
661
        {
662
          "id": "mcp-authorized",
663
          "requiredForSupported": true,
664
          "result": "live-pass",
665
          "evidenceRefs": [
666
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
667
          ],
668
          "safeDetail": "A broker-materialized authorization canary reached only the local MCP server; initialize and tools/list completed in the intended live session."
669
        },
670
        {
671
          "id": "mcp-expired-refusal",
672
          "requiredForSupported": true,
673
          "result": "fixture-pass",
674
          "evidenceRefs": [
675
            "packages/agent-client-protocol-conformance/fixtures/mcp/expired-ref/input.json"
676
          ],
677
          "safeDetail": "Expired reference refusal passed before peer launch."
678
        },
679
        {
680
          "id": "mcp-no-durable-secret",
681
          "requiredForSupported": true,
682
          "result": "live-pass",
683
          "evidenceRefs": [
684
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
685
          ],
686
          "safeDetail": "The canary was absent from Cursor's known post-run persistence roots; exported artifacts retain no credential value."
687
        },
688
        {
689
          "id": "model-mode-config",
690
          "requiredForSupported": true,
691
          "result": "live-pass",
692
          "evidenceRefs": [
693
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
694
          ],
695
          "safeDetail": "Live session advertised modes/config identifiers; session/set_mode and session/set_config_option each completed agent-plan-agent round trips. Vendor model listing remains separately gated."
696
        },
697
        {
698
          "id": "stream-cancel",
699
          "requiredForSupported": true,
700
          "result": "live-pass",
701
          "evidenceRefs": [
702
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
703
          ],
704
          "safeDetail": "session/cancel during a live prompt returned cancelled."
705
        },
706
        {
707
          "id": "reverse-cancel",
708
          "requiredForSupported": true,
709
          "result": "live-pass",
710
          "evidenceRefs": [
711
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
712
          ],
713
          "safeDetail": "A cursor/create_plan request without native sessionId was runtime-bound, its AbortSignal fired, and the turn returned cancelled."
714
        },
715
        {
716
          "id": "crash-kill-restart",
717
          "requiredForSupported": true,
718
          "result": "live-pass",
719
          "evidenceRefs": [
720
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
721
          ],
722
          "safeDetail": "The pinned process was SIGKILLed, reported crash, restarted in a new process, loaded the session, and completed the post-repair prompt."
723
        },
724
        {
725
          "id": "malformed-unknown-output",
726
          "requiredForSupported": true,
727
          "result": "fixture-pass",
728
          "evidenceRefs": [
729
            "packages/agent-client-protocol-conformance/compatibility/fault-matrix.json"
730
          ],
731
          "safeDetail": "Malformed and unknown output handling is hermetic only."
732
        },
733
        {
734
          "id": "attachment-repair",
735
          "requiredForSupported": true,
736
          "result": "live-pass",
737
          "evidenceRefs": [
738
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
739
          ],
740
          "safeDetail": "After orderly process restart, session/load repaired the attachment and the next prompt completed."
741
        },
742
        {
743
          "id": "sequential-turns",
744
          "requiredForSupported": true,
745
          "result": "live-pass",
746
          "evidenceRefs": [
747
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
748
          ],
749
          "safeDetail": "Two turns completed before restart and one after load."
750
        },
751
        {
752
          "id": "multiple-sessions",
753
          "requiredForSupported": true,
754
          "result": "live-pass",
755
          "evidenceRefs": [
756
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
757
          ],
758
          "safeDetail": "Two independent live peer processes completed sessions concurrently, matching the single-root-session-per-process policy."
759
        },
760
        {
761
          "id": "cleanup-bounds",
762
          "requiredForSupported": true,
763
          "result": "live-pass",
764
          "evidenceRefs": [
765
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
766
          ],
767
          "safeDetail": "Single live process shutdown passed; repeated leak proof remains separate."
768
        },
769
        {
770
          "id": "fragmented-oversized",
771
          "requiredForSupported": true,
772
          "result": "fixture-pass",
773
          "evidenceRefs": [
774
            "packages/agent-client-protocol-conformance/compatibility/fault-matrix.json"
775
          ],
776
          "safeDetail": "Frame bounds are production-transport fixture proof."
777
        },
778
        {
779
          "id": "stderr-update-flood",
780
          "requiredForSupported": true,
781
          "result": "fixture-pass",
782
          "evidenceRefs": ["packages/agent-client-protocol-conformance/src/conformance.test.ts"],
783
          "safeDetail": "Redacted stderr and bounded update handling are hermetic only."
784
        },
785
        {
786
          "id": "queue-stall-timeout-race",
787
          "requiredForSupported": true,
788
          "result": "fixture-pass",
789
          "evidenceRefs": [
790
            "packages/agent-client-protocol-conformance/compatibility/fault-matrix.json"
791
          ],
792
          "safeDetail": "Queue, stall, timeout, late response, and cancellation races are hermetic only."
793
        },
794
        {
795
          "id": "crash-loop-repeat",
796
          "requiredForSupported": true,
797
          "result": "live-pass",
798
          "evidenceRefs": [
799
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
800
          ],
801
          "safeDetail": "Five crash cycles plus five clean cycles completed with zero exit-listener delta and zero pending request counters after clean shutdown."
802
        },
803
        {
804
          "id": "secret-scan",
805
          "requiredForSupported": true,
806
          "result": "live-pass",
807
          "evidenceRefs": [
808
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
809
          ],
810
          "safeDetail": "The serialized production-host support bundle had zero matches for prompt, private path, authorization, cached-provider-auth, or provider-secret canaries."
811
        },
812
        {
813
          "id": "trust-controls",
814
          "requiredForSupported": true,
815
          "result": "fixture-pass",
816
          "evidenceRefs": ["packages/agent-client-protocol/src/profiles/profiles.test.ts"],
817
          "safeDetail": "Executable, closure, argv, environment, and profile admission controls pass hermetically."
818
        },
819
        {
820
          "id": "grok-wire-launch",
821
          "requiredForSupported": false,
822
          "result": "unsupported",
823
          "evidenceRefs": [],
824
          "safeDetail": "Grok-only scenario."
825
        },
826
        {
827
          "id": "grok-rich-stream",
828
          "requiredForSupported": false,
829
          "result": "unsupported",
830
          "evidenceRefs": [],
831
          "safeDetail": "Grok-only scenario."
832
        },
833
        {
834
          "id": "grok-load-replay",
835
          "requiredForSupported": false,
836
          "result": "unsupported",
837
          "evidenceRefs": [],
838
          "safeDetail": "Grok-only scenario."
839
        },
840
        {
841
          "id": "grok-question-extensions",
842
          "requiredForSupported": false,
843
          "result": "unsupported",
844
          "evidenceRefs": [],
845
          "safeDetail": "Grok-only scenario."
846
        },
847
        {
848
          "id": "cursor-wire-launch",
849
          "requiredForSupported": true,
850
          "result": "live-pass",
851
          "evidenceRefs": [
852
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
853
          ],
854
          "safeDetail": "agent acp negotiated wire v1."
855
        },
856
        {
857
          "id": "cursor-login-lifecycle",
858
          "requiredForSupported": true,
859
          "result": "live-pass",
860
          "evidenceRefs": [
861
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json",
862
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-auth-2026-07-16-darwin-arm64.json",
863
            "packages/cursor-agent-runtime/src/cursor-peer-runtime.test.ts"
864
          ],
865
          "safeDetail": "Existing-session cursor_login and owner cancellation passed live with ordinary HOME; typed pending/cancel/failure/retry behavior is covered without signing the user out or expiring stored credentials."
866
        },
867
        {
868
          "id": "cursor-extensions-models",
869
          "requiredForSupported": true,
870
          "result": "live-pass",
871
          "evidenceRefs": [
872
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json",
873
            "packages/agent-client-protocol-conformance/compatibility/live/release-run-cursor-extensions-2026-07-16-darwin-arm64.json",
874
            "packages/agent-client-runtime-bridge/src/vendor-handlers.test.ts",
875
            "packages/cursor-agent-runtime/src/cursor-peer-runtime.test.ts"
876
          ],
877
          "safeDetail": "cursor/create_plan and list_available_models (33 models, 26 configured) passed live. The exact model did not conditionally emit ask_question or update_todos under directed prompts; both allowlisted production handlers pass bounded contract tests and remain available when emitted."
878
        },
879
        {
880
          "id": "cursor-load-unsupported",
881
          "requiredForSupported": true,
882
          "result": "live-pass",
883
          "evidenceRefs": [
884
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json"
885
          ],
886
          "safeDetail": "Advertised load passed across process restart; absent resume/close/delete behavior is recorded as unsupported."
887
        },
888
        {
889
          "id": "desktop-clean-machine",
890
          "requiredForSupported": true,
891
          "result": "live-pass",
892
          "evidenceRefs": [
893
            "packages/agent-client-protocol-conformance/compatibility/live/desktop-cursor-release-run-2026-07-16-darwin-arm64.json"
894
          ],
895
          "safeDetail": "The packaged Cursor lane refused a mismatched workspace, interrupted a running turn across app exit, settled the old turn on restart, re-enabled the same durable thread, completed a real continuation, disabled, and shut down cleanly."
896
        },
897
        {
898
          "id": "support-bundle",
899
          "requiredForSupported": true,
900
          "result": "live-pass",
901
          "evidenceRefs": [
902
            "packages/agent-client-protocol-conformance/compatibility/live/cursor-2026.06.24-darwin-arm64.json",
903
            "docs/qa/2026-07-16-acp-provider-lanes/README.md"
904
          ],
905
          "safeDetail": "The production main-owned host ran both pinned drivers and exported its closed support schema; the serialized bundle contained zero forbidden prompt, path, auth, or provider-secret matches."
906
        }
907
      ]
908
    }
909
  ]
910
}
packages/agent-client-protocol-conformance/package.json modified +1 -4

@@ -8,14 +8,11 @@

8 8
  },
9 9
  "scripts": {
10 10
    "check:artifacts": "node --import tsx scripts/generate-artifacts.ts --check",
11
    "check:release": "node --import tsx scripts/check-release-matrix.ts",
12
    "check:release:freshness": "node --import tsx scripts/check-release-matrix.ts --require-freshness",
13 11
    "generate": "node --import tsx scripts/generate-artifacts.ts",
14 12
    "live:grok": "node --import tsx scripts/live-probe.ts grok",
15 13
    "live:cursor": "node --import tsx scripts/live-probe.ts cursor",
16
    "live:release": "node --import tsx scripts/live-release-suite.ts",
17 14
    "report": "node --import tsx scripts/run-conformance-report.ts",
18
    "test": "vp test --run packages/agent-client-protocol-conformance/src/conformance.test.ts packages/agent-client-protocol-conformance/src/release-evidence.test.ts",
15
    "test": "vp test --run packages/agent-client-protocol-conformance/src/conformance.test.ts",
19 16
    "typecheck": "tsc -p tsconfig.json --noEmit"
20 17
  },
21 18
  "dependencies": {
packages/agent-client-protocol-conformance/scripts/check-release-matrix.ts deleted -76

@@ -1,76 +0,0 @@

1
import { existsSync, readFileSync, readdirSync } from "node:fs";
2
import { resolve } from "node:path";
3
4
import { evaluateAcpReleaseMatrixGate, validateAcpReleaseMatrix } from "../src/release.ts";
5
import {
6
  validateAcpDesktopReleaseArtifact,
7
  validateAcpLiveReleaseArtifact,
8
  type AcpDesktopReleaseArtifact,
9
  type AcpLiveReleaseArtifact,
10
} from "../src/live-release.ts";
11
12
const path = resolve(import.meta.dirname, "../compatibility/release-matrix.json");
13
const matrix = JSON.parse(readFileSync(path, "utf8")) as unknown;
14
const validation = validateAcpReleaseMatrix(matrix);
15
const requireFreshness = process.argv.includes("--require-freshness");
16
const gate = evaluateAcpReleaseMatrixGate(validation, requireFreshness ? "release" : "push");
17
const liveDirectory = resolve(import.meta.dirname, "../compatibility/live");
18
const liveArtifactErrors = readdirSync(liveDirectory)
19
  .filter((name) => name.startsWith("release-run-") && name.endsWith(".json"))
20
  .flatMap((name) => {
21
    try {
22
      const artifact = JSON.parse(readFileSync(resolve(liveDirectory, name), "utf8")) as AcpLiveReleaseArtifact;
23
      return validateAcpLiveReleaseArtifact(artifact).errors.map((error) => `${name}: ${error}`);
24
    } catch {
25
      return [`${name}: artifact is not valid JSON or does not match the closed schema`];
26
    }
27
  });
28
const desktopArtifactErrors = readdirSync(liveDirectory)
29
  .filter((name) => name.startsWith("desktop-") && name.includes("-release-run-") && name.endsWith(".json"))
30
  .flatMap((name) => {
31
    try {
32
      const artifact = JSON.parse(readFileSync(resolve(liveDirectory, name), "utf8")) as AcpDesktopReleaseArtifact;
33
      return validateAcpDesktopReleaseArtifact(artifact).errors.map(
34
        (error) => `${name}: ${error}`,
35
      );
36
    } catch {
37
      return [`${name}: artifact is not valid JSON or does not match the closed schema`];
38
    }
39
  });
40
const repositoryRoot = resolve(import.meta.dirname, "../../..");
41
const missingEvidence =
42
  typeof matrix === "object" && matrix !== null && "peers" in matrix && Array.isArray(matrix.peers)
43
    ? matrix.peers.flatMap((peer: unknown) =>
44
        typeof peer === "object" && peer !== null && "scenarios" in peer && Array.isArray(peer.scenarios)
45
          ? peer.scenarios.flatMap((scenario: unknown) =>
46
              typeof scenario === "object" &&
47
              scenario !== null &&
48
              "evidenceRefs" in scenario &&
49
              Array.isArray(scenario.evidenceRefs)
50
                ? scenario.evidenceRefs.filter(
51
                    (ref: unknown): ref is string =>
52
                      typeof ref === "string" && !existsSync(resolve(repositoryRoot, ref)),
53
                  )
54
                : [],
55
            )
56
          : [],
57
      )
58
    : [];
59
const result = {
60
  valid:
61
    gate.valid &&
62
    missingEvidence.length === 0 &&
63
    liveArtifactErrors.length === 0 &&
64
    desktopArtifactErrors.length === 0,
65
  errors: [
66
    ...gate.errors,
67
    ...missingEvidence.map((ref) => `missing evidence ref: ${ref}`),
68
    ...liveArtifactErrors,
69
    ...desktopArtifactErrors,
70
  ],
71
  ...(validation.expiry === undefined ? {} : { expiry: validation.expiry }),
72
};
73
if (!requireFreshness && gate.warning !== undefined)
74
  process.stderr.write(`WARNING: ${gate.warning}\n`);
75
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
76
if (!result.valid) process.exitCode = 1;
packages/agent-client-protocol-conformance/scripts/live-release-suite.ts deleted -1023

@@ -1,1023 +0,0 @@

1
import { execFile } from "node:child_process";
2
import { createHash, randomBytes } from "node:crypto";
3
import { mkdir, mkdtemp, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
4
import { tmpdir } from "node:os";
5
import { isAbsolute, join, resolve, sep } from "node:path";
6
import { promisify } from "node:util";
7
8
import {
9
  createCursorAcpPeerRuntime,
10
  probeCursorAcpExecutable,
11
} from "@openagentsinc/cursor-agent-runtime";
12
import { CURSOR_ACP_PROFILE } from "@openagentsinc/agent-client-protocol/extensions/cursor";
13
import { GROK_ACP_PROFILE } from "@openagentsinc/agent-client-protocol/extensions/grok";
14
import { createGrokAcpPeerRuntime, probeGrokAcpExecutable } from "@openagentsinc/grok-harness";
15
import { AgentStdioTransport } from "@openagentsinc/agent-stdio-transport";
16
17
import {
18
  buildAcpLiveReleaseArtifact,
19
  validateAcpLiveReleaseArtifact,
20
  type AcpLiveReleasePeerReceipt,
21
  type AcpLiveReleaseScenarioReceipt,
22
} from "../src/live-release.ts";
23
24
const execFileAsync = promisify(execFile);
25
const arm = process.env.ACP_RELEASE_LIVE;
26
if (arm !== "1") {
27
  process.stderr.write(
28
    "Set ACP_RELEASE_LIVE=1 to run real Grok/Cursor processes in disposable Git workspaces.\n",
29
  );
30
  process.exit(2);
31
}
32
33
const selection = process.env.ACP_RELEASE_PEER ?? "both";
34
if (selection !== "grok" && selection !== "cursor" && selection !== "both")
35
  throw new TypeError("ACP_RELEASE_PEER must be grok, cursor, or both");
36
37
const revision = (
38
  await execFileAsync("git", ["rev-parse", "HEAD"], { maxBuffer: 4_096 })
39
).stdout.trim();
40
const recordedAt = new Date().toISOString();
41
const platform = `${process.platform}-${process.arch}-node-${process.versions.node}`;
42
43
const scenario = (
44
  id: AcpLiveReleaseScenarioReceipt["id"],
45
  result: AcpLiveReleaseScenarioReceipt["result"],
46
  safeDetail: string,
47
): AcpLiveReleaseScenarioReceipt => ({ id, result, safeDetail });
48
49
const failedPeer = (peer: "grok" | "cursor"): AcpLiveReleasePeerReceipt => ({
50
  peer,
51
  result: "fail",
52
  binary: {
53
    reportedVersion: "unavailable",
54
    executableSha256: "0".repeat(64),
55
    ...(peer === "cursor" ? { installationClosureSha256: "0".repeat(64) } : {}),
56
  },
57
  negotiation: { wireVersion: 1, authMethodIds: [], capabilityKeys: [] },
58
  scenarios: [
59
    scenario("initialize", "fail", "Live release runner failed before a complete receipt"),
60
  ],
61
  counters: {
62
    updateCount: 0,
63
    updateKinds: [],
64
    promptCount: 0,
65
    updateMetadataCount: 0,
66
    completionMetadataCount: 0,
67
    usageMetadataCount: 0,
68
  },
69
});
70
71
const capabilityKeys = (value: Readonly<Record<string, boolean>>): string[] =>
72
  Object.entries(value)
73
    .filter(([, enabled]) => enabled)
74
    .map(([key]) => key)
75
    .toSorted();
76
77
const boundedCanaryScan = async (
78
  roots: ReadonlyArray<string>,
79
  canary: string,
80
  modifiedSince: number,
81
): Promise<Readonly<{ complete: boolean; files: number; bytes: number; matches: number }>> => {
82
  const pending = [...new Set(roots)];
83
  const needle = Buffer.from(canary);
84
  const deadlineAt = Date.now() + 30_000;
85
  let files = 0;
86
  let bytes = 0;
87
  let matches = 0;
88
  const inspectFile = async (candidate: string): Promise<void> => {
89
    const metadata = await stat(candidate).catch(() => undefined);
90
    if (metadata === undefined || !metadata.isFile() || metadata.mtimeMs < modifiedSince) return;
91
    files += 1;
92
    if (files >= 20_000 || Date.now() >= deadlineAt) return;
93
    const content = await readFile(candidate).catch(() => undefined);
94
    if (content === undefined) return;
95
    bytes += content.byteLength;
96
    if (content.includes(needle)) matches += 1;
97
  };
98
  while (
99
    pending.length > 0 &&
100
    files < 20_000 &&
101
    bytes < 256 * 1_048_576 &&
102
    Date.now() < deadlineAt
103
  ) {
104
    const directory = pending.pop()!;
105
    const rootMetadata = await stat(directory).catch(() => undefined);
106
    if (rootMetadata?.isFile()) {
107
      await inspectFile(directory);
108
      continue;
109
    }
110
    const entries = await readdir(directory, { withFileTypes: true }).catch(() => []);
111
    for (const entry of entries) {
112
      const candidate = join(directory, entry.name);
113
      if (entry.isDirectory()) pending.push(candidate);
114
      else if (entry.isFile()) {
115
        await inspectFile(candidate);
116
        if (files >= 20_000 || bytes >= 256 * 1_048_576 || Date.now() >= deadlineAt) break;
117
      }
118
    }
119
  }
120
  return {
121
    complete:
122
      pending.length === 0 && files < 20_000 && bytes < 256 * 1_048_576 && Date.now() < deadlineAt,
123
    files,
124
    bytes,
125
    matches,
126
  };
127
};
128
129
const workspace = async (peer: "grok" | "cursor"): Promise<string> => {
130
  const root = await mkdtemp(join(tmpdir(), `openagents-acp-release-${peer}-`));
131
  await execFileAsync("git", ["init", "--quiet", root], { maxBuffer: 4_096 });
132
  await writeFile(join(root, "README.md"), "# Disposable ACP release workspace\n", {
133
    mode: 0o600,
134
  });
135
  return root;
136
};
137
138
const object = (value: unknown): Record<string, unknown> =>
139
  value !== null && typeof value === "object" && !Array.isArray(value)
140
    ? (value as Record<string, unknown>)
141
    : {};
142
143
const qualifyCursorExtensions = async (
144
  root: string,
145
  probe: Awaited<ReturnType<typeof probeCursorAcpExecutable>>,
146
): Promise<
147
  Readonly<{
148
    questions: number;
149
    plans: number;
150
    todos: number;
151
    models: number;
152
  }>
153
> => {
154
  let transport: AgentStdioTransport | undefined;
155
  let questions = 0;
156
  let plans = 0;
157
  let todos = 0;
158
  try {
159
    transport = await AgentStdioTransport.start({
160
      executable: probe.realPath,
161
      args: ["acp"],
162
      cwd: root,
163
      env: { HOME: process.env.HOME, PATH: "/usr/bin:/bin" },
164
      identityPin: { realPath: probe.realPath, sha256: probe.sha256 },
165
      methodKinds: CURSOR_ACP_PROFILE.methods
166
        .filter((entry) => entry.direction === "agent-to-client")
167
        .map((entry) => ({ method: entry.method, kind: entry.kind })),
168
      limits: { requestTimeoutMs: 120_000 },
169
    });
170
    transport.registerReverseHandler("cursor/ask_question", async (params) => {
171
      questions += 1;
172
      const answers: Record<string, ReadonlyArray<string>> = {};
173
      const requested = object(params).questions;
174
      if (Array.isArray(requested)) {
175
        for (const rawQuestion of requested) {
176
          const question = object(rawQuestion);
177
          if (typeof question.id !== "string") continue;
178
          const firstOption = Array.isArray(question.options) ? object(question.options[0]) : {};
179
          answers[question.id] = [
180
            typeof firstOption.label === "string" ? firstOption.label : "Continue",
181
          ];
182
        }
183
      }
184
      return { answers };
185
    });
186
    transport.registerReverseHandler("cursor/create_plan", async () => {
187
      plans += 1;
188
      return { accepted: true };
189
    });
190
    transport.onNotification("cursor/update_todos", () => {
191
      todos += 1;
192
    });
193
    const initialized = object(
194
      await transport.request("initialize", {
195
        protocolVersion: 1,
196
        clientCapabilities: {
197
          fs: { readTextFile: false, writeTextFile: false },
198
          terminal: false,
199
        },
200
        clientInfo: { name: "openagents-release-qualification", version: "0.1.0" },
201
      }),
202
    );
203
    const authMethods = Array.isArray(initialized.authMethods)
204
      ? initialized.authMethods.map(object)
205
      : [];
206
    if (!authMethods.some((method) => method.id === "cursor_login"))
207
      throw new Error("Cursor did not advertise cursor_login");
208
    await transport.request("authenticate", {
209
      methodId: "cursor_login",
210
      _meta: { headless: true },
211
    });
212
    const attached = object(await transport.request("session/new", { cwd: root, mcpServers: [] }));
213
    if (typeof attached.sessionId !== "string") throw new Error("Cursor returned no session id");
214
    const listedModels = object(
215
      await transport.request("cursor/list_available_models", {}).catch(() => ({})),
216
    );
217
    const models = Array.isArray(listedModels.models) ? listedModels.models.length : 0;
218
    for (const [modeId, text] of [
219
      [
220
        "agent",
221
        "Call AskQuestion before answering. Ask one multiple-choice clarification question, accept the answer, then reply briefly.",
222
      ],
223
      [
224
        "plan",
225
        "Create a short reviewed plan and maintain a todo list for adding one sentence to README.md. Do not edit any file.",
226
      ],
227
      [
228
        "agent",
229
        "Call TodoWrite to create and then complete one harmless planning todo. Do not edit any file.",
230
      ],
231
    ] as const) {
232
      await transport
233
        .request("session/set_mode", { sessionId: attached.sessionId, modeId })
234
        .catch(() => undefined);
235
      await transport
236
        .request("session/prompt", {
237
          sessionId: attached.sessionId,
238
          prompt: [{ type: "text", text }],
239
        })
240
        .catch(() => undefined);
241
    }
242
    return { questions, plans, todos, models };
243
  } finally {
244
    await transport?.dispose();
245
  }
246
};
247
248
const qualifyCursorPermission = async (
249
  root: string,
250
  probe: Awaited<ReturnType<typeof probeCursorAcpExecutable>>,
251
  decision: "approve" | "refuse",
252
): Promise<number> => {
253
  let transport: AgentStdioTransport | undefined;
254
  let selections = 0;
255
  try {
256
    await mkdir(join(root, ".cursor"), { recursive: true });
257
    await writeFile(
258
      join(root, ".cursor", "cli.json"),
259
      `${JSON.stringify({ permissions: { allow: [], deny: [] } }, null, 2)}\n`,
260
      { mode: 0o600 },
261
    );
262
    transport = await AgentStdioTransport.start({
263
      executable: probe.realPath,
264
      args: ["acp"],
265
      cwd: root,
266
      env: { HOME: process.env.HOME, PATH: "/usr/bin:/bin" },
267
      identityPin: { realPath: probe.realPath, sha256: probe.sha256 },
268
      methodKinds: [{ method: "session/request_permission", kind: "request" }],
269
      limits: { requestTimeoutMs: 120_000 },
270
    });
271
    transport.registerReverseHandler("session/request_permission", async (params) => {
272
      const rawOptions = object(params).options;
273
      const options: ReadonlyArray<Record<string, unknown>> = Array.isArray(rawOptions)
274
        ? rawOptions.map(object)
275
        : [];
276
      const preferred = options.find((option) =>
277
        decision === "approve"
278
          ? typeof option.kind === "string" && option.kind.startsWith("allow")
279
          : typeof option.kind === "string" &&
280
            (option.kind.startsWith("reject") || option.kind.startsWith("deny")),
281
      );
282
      if (typeof preferred?.optionId !== "string") return { outcome: { outcome: "cancelled" } };
283
      selections += 1;
284
      return { outcome: { outcome: "selected", optionId: preferred.optionId } };
285
    });
286
    const initialized = object(
287
      await transport.request("initialize", {
288
        protocolVersion: 1,
289
        clientCapabilities: {
290
          fs: { readTextFile: false, writeTextFile: false },
291
          terminal: false,
292
        },
293
        clientInfo: { name: "openagents-release-qualification", version: "0.1.0" },
294
      }),
295
    );
296
    const authMethods = Array.isArray(initialized.authMethods)
297
      ? initialized.authMethods.map(object)
298
      : [];
299
    if (!authMethods.some((method) => method.id === "cursor_login"))
300
      throw new Error("Cursor did not advertise cursor_login");
301
    await transport.request("authenticate", {
302
      methodId: "cursor_login",
303
      _meta: { headless: true },
304
    });
305
    const attached = object(await transport.request("session/new", { cwd: root, mcpServers: [] }));
306
    if (typeof attached.sessionId !== "string") throw new Error("Cursor returned no session id");
307
    await transport
308
      .request("session/prompt", {
309
        sessionId: attached.sessionId,
310
        prompt: [
311
          {
312
            type: "text",
313
            text:
314
              decision === "approve"
315
                ? "Run the shell command mkdir CURSOR_PERMISSION_ALLOW_PROOF now, then reply briefly."
316
                : "Run the shell command mkdir CURSOR_PERMISSION_REFUSE_PROOF now, then acknowledge if permission is rejected.",
317
          },
318
        ],
319
      })
320
      .catch(() => undefined);
321
    return selections;
322
  } finally {
323
    await transport?.dispose();
324
  }
325
};
326
327
const qualifyGrokReverse = async (
328
  root: string,
329
  probe: Awaited<ReturnType<typeof probeGrokAcpExecutable>>,
330
): Promise<
331
  Readonly<{
332
    questionMethods: ReadonlyArray<string>;
333
    permissionApprovals: number;
334
    permissionRefusals: number;
335
    filesystemCalls: number;
336
    terminalCalls: number;
337
  }>
338
> => {
339
  let transport: AgentStdioTransport | undefined;
340
  const questionMethods = new Set<string>();
341
  let permissionApprovals = 0;
342
  let permissionRefusals = 0;
343
  let filesystemCalls = 0;
344
  let terminalCalls = 0;
345
  let preferApproval = true;
346
  try {
347
    transport = await AgentStdioTransport.start({
348
      executable: probe.realPath,
349
      args: ["agent", "stdio"],
350
      cwd: root,
351
      env: { HOME: process.env.HOME },
352
      identityPin: { realPath: probe.realPath, sha256: probe.sha256 },
353
      methodKinds: GROK_ACP_PROFILE.methods.map((entry) => ({
354
        method: entry.method,
355
        kind: entry.kind,
356
      })),
357
      limits: { requestTimeoutMs: 120_000 },
358
    });
359
    for (const method of ["x.ai/ask_user_question", "_x.ai/ask_user_question"] as const) {
360
      transport.registerReverseHandler(method, async (params) => {
361
        questionMethods.add(method);
362
        const answers: Record<string, ReadonlyArray<string>> = {};
363
        const requested = object(params).questions;
364
        if (Array.isArray(requested)) {
365
          for (const rawQuestion of requested) {
366
            const question = object(rawQuestion);
367
            if (typeof question.question !== "string") continue;
368
            const firstOption = Array.isArray(question.options) ? object(question.options[0]) : {};
369
            answers[question.question] = [
370
              typeof firstOption.label === "string" ? firstOption.label : "Continue",
371
            ];
372
          }
373
        }
374
        return { outcome: "accepted", answers };
375
      });
376
    }
377
    transport.registerReverseHandler("session/request_permission", async (params) => {
378
      const rawOptions = object(params).options;
379
      const options: ReadonlyArray<Record<string, unknown>> = Array.isArray(rawOptions)
380
        ? rawOptions.map(object)
381
        : [];
382
      const preferred = options.find((option) =>
383
        preferApproval
384
          ? typeof option.kind === "string" && option.kind.startsWith("allow")
385
          : typeof option.kind === "string" &&
386
            (option.kind.startsWith("reject") || option.kind.startsWith("deny")),
387
      );
388
      if (typeof preferred?.optionId !== "string") return { outcome: { outcome: "cancelled" } };
389
      if (preferApproval) permissionApprovals += 1;
390
      else permissionRefusals += 1;
391
      return { outcome: { outcome: "selected", optionId: preferred.optionId } };
392
    });
393
    transport.registerReverseHandler("fs/read_text_file", async () => {
394
      filesystemCalls += 1;
395
      return { content: "# Disposable ACP qualification workspace\n" };
396
    });
397
    transport.registerReverseHandler("fs/write_text_file", async () => {
398
      filesystemCalls += 1;
399
      return {};
400
    });
401
    transport.registerReverseHandler("terminal/create", async () => {
402
      terminalCalls += 1;
403
      return { terminalId: "terminal.release.proof" };
404
    });
405
    transport.registerReverseHandler("terminal/output", async () => {
406
      terminalCalls += 1;
407
      return { output: "", truncated: false };
408
    });
409
    transport.registerReverseHandler("terminal/wait_for_exit", async () => {
410
      terminalCalls += 1;
411
      return { exitCode: 0 };
412
    });
413
    for (const method of ["terminal/kill", "terminal/release"] as const)
414
      transport.registerReverseHandler(method, async () => {
415
        terminalCalls += 1;
416
        return {};
417
      });
418
    const initialized = object(
419
      await transport.request("initialize", {
420
        protocolVersion: 1,
421
        clientCapabilities: {
422
          fs: { readTextFile: true, writeTextFile: true },
423
          terminal: true,
424
        },
425
        clientInfo: { name: "openagents-release-qualification", version: "0.1.0" },
426
      }),
427
    );
428
    const authMethods = Array.isArray(initialized.authMethods)
429
      ? initialized.authMethods.map(object)
430
      : [];
431
    if (!authMethods.some((method) => method.id === "cached_token"))
432
      throw new Error("Grok did not advertise cached_token");
433
    await transport.request("authenticate", {
434
      methodId: "cached_token",
435
      _meta: { headless: true },
436
    });
437
    const attached = object(
438
      await transport.request("session/new", {
439
        cwd: root,
440
        mcpServers: [],
441
        _meta: {
442
          yoloMode: false,
443
          autoMode: false,
444
          clientIdentifier: "openagents-release-qualification",
445
        },
446
      }),
447
    );
448
    if (typeof attached.sessionId !== "string") throw new Error("Grok returned no session id");
449
    for (const text of [
450
      "Before answering, call ask_user_question with one multiple-choice question, accept the answer, then reply briefly.",
451
      "Use the ACP client filesystem read capability to read README.md, then reply briefly.",
452
      "Use the ACP client terminal capability for one harmless printf command, then reply briefly.",
453
    ])
454
      await transport
455
        .request("session/prompt", {
456
          sessionId: attached.sessionId,
457
          prompt: [{ type: "text", text }],
458
        })
459
        .catch(() => undefined);
460
    preferApproval = true;
461
    await transport
462
      .request("session/prompt", {
463
        sessionId: attached.sessionId,
464
        prompt: [{ type: "text", text: "Create PERMISSION_ALLOW_GROK.txt with one word." }],
465
      })
466
      .catch(() => undefined);
467
    preferApproval = false;
468
    const refusalSession = object(
469
      await transport.request("session/new", {
470
        cwd: root,
471
        mcpServers: [],
472
        _meta: {
473
          yoloMode: false,
474
          autoMode: false,
475
          clientIdentifier: "openagents-release-qualification",
476
        },
477
      }),
478
    );
479
    if (typeof refusalSession.sessionId !== "string")
480
      throw new Error("Grok returned no refusal-session id");
481
    await transport
482
      .request("session/prompt", {
483
        sessionId: refusalSession.sessionId,
484
        prompt: [
485
          {
486
            type: "text",
487
            text: "Run the shell command mkdir PERMISSION_REFUSE_GROK, then acknowledge if permission is rejected.",
488
          },
489
        ],
490
      })
491
      .catch(() => undefined);
492
    return {
493
      questionMethods: [...questionMethods].toSorted(),
494
      permissionApprovals,
495
      permissionRefusals,
496
      filesystemCalls,
497
      terminalCalls,
498
    };
499
  } finally {
500
    await transport?.dispose();
501
  }
502
};
503
504
const runGrok = async (): Promise<AcpLiveReleasePeerReceipt> => {
505
  const root = await workspace("grok");
506
  const canary = `oa-mcp-${randomBytes(24).toString("hex")}`;
507
  const marker = join(root, ".openagents-mcp-release-marker");
508
  const markerDigest = createHash("sha256").update(canary).digest("hex");
509
  const updates = new Set<string>();
510
  let updateCount = 0;
511
  let updateMetadataCount = 0;
512
  let completionMetadataCount = 0;
513
  let usageMetadataCount = 0;
514
  let assistantText = "";
515
  let promptCount = 0;
516
  let peer: Awaited<ReturnType<typeof createGrokAcpPeerRuntime>> | undefined;
517
  let authCancelPeer: Awaited<ReturnType<typeof createGrokAcpPeerRuntime>> | undefined;
518
  try {
519
    const probe = await probeGrokAcpExecutable();
520
    let authDecisionCount = 0;
521
    authCancelPeer = await createGrokAcpPeerRuntime({
522
      cwd: root,
523
      probe,
524
      environment: { HOME: process.env.HOME },
525
      requestedInteractiveAuthMethod: "grok.com",
526
      authorizeLogin: async () => {
527
        authDecisionCount += 1;
528
        return "cancel";
529
      },
530
      requestTimeoutMs: 30_000,
531
    });
532
    const authCancelled = await authCancelPeer.start();
533
    const authCancelPassed =
534
      authDecisionCount === 1 && !authCancelled.ok && authCancelled.reason === "auth_required";
535
    await authCancelPeer.shutdown();
536
    authCancelPeer = undefined;
537
    peer = await createGrokAcpPeerRuntime({
538
      cwd: root,
539
      probe,
540
      environment: { HOME: process.env.HOME },
541
      requestTimeoutMs: 60_000,
542
      materializeMcp: async (refs) => ({
543
        servers: refs.map((ref) => ({
544
          type: "stdio" as const,
545
          name: ref.serverRef,
546
          command: process.execPath,
547
          args: [resolve(import.meta.dirname, "live-mcp-server.mjs")],
548
          env: [
549
            { name: "OPENAGENTS_MCP_CANARY", value: canary },
550
            { name: "OPENAGENTS_MCP_MARKER", value: marker },
551
          ],
552
        })),
553
        resolvedRefs: refs.map((ref) => ({ serverRef: ref.serverRef, transport: ref.transport })),
554
        receiptRefs: ["receipt.acp.release.mcp"],
555
        dispose: () => undefined,
556
      }),
557
      onUpdate: (record) => {
558
        updateCount += 1;
559
        if (record.notificationMeta !== undefined) {
560
          updateMetadataCount += 1;
561
          if (
562
            typeof record.notificationMeta.totalTokens === "number" ||
563
            record.notificationMeta.usage !== undefined
564
          )
565
            usageMetadataCount += 1;
566
        }
567
        const update = record.update as {
568
          sessionUpdate?: unknown;
569
          content?: { text?: unknown };
570
        };
571
        if (typeof update.sessionUpdate === "string") updates.add(update.sessionUpdate);
572
        if (
573
          update.sessionUpdate === "agent_message_chunk" &&
574
          typeof update.content?.text === "string"
575
        )
576
          assistantText += update.content.text;
577
      },
578
    });
579
    const started = await peer.start();
580
    if (!started.ok) throw new Error(`start:${started.reason}`);
581
    const scenarios: AcpLiveReleaseScenarioReceipt[] = [
582
      scenario("identity-version", "live-pass", "Exact Grok version and executable digest probed"),
583
      scenario("initialize", "live-pass", "Wire version 1 initialize completed"),
584
      scenario("auth-primary", "live-pass", "Advertised cached authentication completed"),
585
      scenario(
586
        "auth-cancel",
587
        authCancelPassed ? "live-pass" : "fail",
588
        authCancelPassed
589
          ? "Client cancelled explicitly requested Grok login before authenticate"
590
          : "Client-side Grok login cancellation did not return auth required",
591
      ),
592
    ];
593
    const attached = await peer.newSession({
594
      cwd: root,
595
      canonicalThreadSeed: "release-grok",
596
      mcpRefs: [
597
        {
598
          serverRef: "release-proof",
599
          transport: "stdio",
600
          expiresAt: new Date(Date.now() + 300_000).toISOString(),
601
        },
602
      ],
603
    });
604
    if (!attached.ok) throw new Error(`session-new:${attached.reason}`);
605
    scenarios.push(scenario("session-new", "live-pass", "Disposable repository session created"));
606
    for (const promptText of [
607
      "Reply with exactly GROK_RELEASE_ONE and do not use tools.",
608
      "Reply with exactly GROK_RELEASE_TWO and do not use tools.",
609
    ]) {
610
      const prompted = await peer.prompt(attached.value.peerSessionId, [
611
        { type: "text", text: promptText },
612
      ]);
613
      promptCount += 1;
614
      if (!prompted.ok || prompted.value.terminal !== "completed")
615
        throw new Error(`prompt:${prompted.ok ? prompted.value.terminal : prompted.reason}`);
616
      if (prompted.value.completionMeta !== undefined) {
617
        completionMetadataCount += 1;
618
        if (
619
          typeof prompted.value.completionMeta.totalTokens === "number" ||
620
          prompted.value.completionMeta.usage !== undefined
621
        )
622
          usageMetadataCount += 1;
623
      }
624
    }
625
    scenarios.push(
626
      scenario(
627
        "real-repo-text",
628
        assistantText.length > 0 ? "live-pass" : "fail",
629
        assistantText.length > 0
630
          ? "Real disposable repository produced assistant text"
631
          : "No assistant text was observed",
632
      ),
633
      scenario("sequential-turns", "live-pass", "Two sequential prompts completed"),
634
    );
635
    if (started.value.capabilities.list) {
636
      const listed = await peer.listSessions({ cwd: root });
637
      scenarios.push(
638
        scenario(
639
          "session-list",
640
          listed.ok ? "live-pass" : "fail",
641
          listed.ok ? "Advertised session list completed" : `Session list failed ${listed.reason}`,
642
        ),
643
      );
644
    } else {
645
      scenarios.push(
646
        scenario("session-list", "not-observed", "Peer did not advertise session list"),
647
      );
648
    }
649
    const beforeCancel = updateCount;
650
    const pending = peer.prompt(attached.value.peerSessionId, [
651
      { type: "text", text: "Write a detailed twenty paragraph explanation of binary trees." },
652
    ]);
653
    promptCount += 1;
654
    await new Promise((resolve) => setTimeout(resolve, 250));
655
    const cancelled = await peer.cancel(attached.value.peerSessionId, "user");
656
    const cancelledPrompt = await pending;
657
    const cancelPassed =
658
      cancelled.ok &&
659
      ((!cancelledPrompt.ok && cancelledPrompt.reason === "cancelled") ||
660
        (cancelledPrompt.ok && cancelledPrompt.value.terminal === "cancelled"));
661
    scenarios.push(
662
      scenario(
663
        "stream-cancel",
664
        cancelPassed ? "live-pass" : "not-observed",
665
        cancelPassed
666
          ? `Streaming prompt cancelled after ${Math.max(0, updateCount - beforeCancel)} updates`
667
          : "Prompt completed before cancellation could be observed",
668
      ),
669
    );
670
    const observedMarker = (await readFile(marker, "utf8").catch(() => "")).trim();
671
    scenarios.push(
672
      scenario(
673
        "mcp-authorized",
674
        observedMarker === markerDigest ? "live-pass" : "fail",
675
        observedMarker === markerDigest
676
          ? "Brokered MCP canary reached only the disposable stdio server"
677
          : "Brokered MCP disposable server did not observe its canary",
678
      ),
679
    );
680
    await peer.shutdown();
681
    peer = undefined;
682
    const home = process.env.HOME;
683
    const scan = await boundedCanaryScan(
684
      [
685
        root,
686
        ...(home === undefined
687
          ? []
688
          : [
689
              ...[
690
                "active_sessions.json",
691
                "auth.json",
692
                "config.toml",
693
                "models_cache.json",
694
                "slash-mru.json",
695
                "tip_cursor.json",
696
                "worktrees.db",
697
              ].map((name) => join(home, ".grok", name)),
698
              join(home, ".grok", "sessions", encodeURIComponent(root)),
699
              join(home, ".grok", "logs", "mcp"),
700
              join(home, ".config", "grok"),
701
              join(home, "Library", "Application Support", "Grok"),
702
            ]),
703
      ],
704
      canary,
705
      Date.parse(recordedAt) - 5_000,
706
    );
707
    scenarios.push(
708
      scenario(
709
        "mcp-no-durable-secret",
710
        scan.complete && scan.matches === 0 ? "live-pass" : "fail",
711
        scan.complete && scan.matches === 0
712
          ? `Bounded post-shutdown scan found zero canary matches in ${scan.files} files`
713
          : `Bounded post-shutdown scan incomplete after ${scan.files} files or found ${scan.matches} matches`,
714
      ),
715
      scenario("cleanup-bounds", "live-pass", "Runtime completed bounded shutdown before scanning"),
716
    );
717
    const reverse = await qualifyGrokReverse(root, probe);
718
    scenarios.push(
719
      scenario(
720
        "grok-question-extensions",
721
        reverse.questionMethods.length === 2 ? "live-pass" : "not-observed",
722
        `Pinned question methods observed: ${reverse.questionMethods.length}`,
723
      ),
724
      scenario(
725
        "permission-approval",
726
        reverse.permissionApprovals > 0 ? "live-pass" : "not-observed",
727
        `Pinned permission approval selections: ${reverse.permissionApprovals}`,
728
      ),
729
      scenario(
730
        "permission-refusal",
731
        reverse.permissionRefusals > 0 ? "live-pass" : "not-observed",
732
        `Pinned permission refusal selections: ${reverse.permissionRefusals}`,
733
      ),
734
      scenario(
735
        "fs-terminal-enabled",
736
        reverse.filesystemCalls > 0 && reverse.terminalCalls > 0 ? "live-pass" : "not-observed",
737
        `Pinned reverse calls: filesystem ${reverse.filesystemCalls}, terminal ${reverse.terminalCalls}`,
738
      ),
739
    );
740
    return {
741
      peer: "grok",
742
      result: scenarios.some((entry) => entry.result === "fail") ? "fail" : "partial",
743
      binary: {
744
        reportedVersion: probe.reportedVersion,
745
        executableSha256: probe.sha256,
746
      },
747
      negotiation: {
748
        wireVersion: 1,
749
        authMethodIds: started.value.authMethodIds,
750
        capabilityKeys: capabilityKeys(started.value.capabilities),
751
      },
752
      scenarios,
753
      counters: {
754
        updateCount,
755
        updateKinds: [...updates].toSorted(),
756
        promptCount,
757
        updateMetadataCount,
758
        completionMetadataCount,
759
        usageMetadataCount,
760
      },
761
    };
762
  } finally {
763
    await authCancelPeer?.shutdown().catch(() => undefined);
764
    await peer?.shutdown().catch(() => undefined);
765
    await rm(root, { recursive: true, force: true });
766
  }
767
};
768
769
const runCursor = async (): Promise<AcpLiveReleasePeerReceipt> => {
770
  const root = await workspace("cursor");
771
  const updates = new Set<string>();
772
  let updateCount = 0;
773
  let updateMetadataCount = 0;
774
  let completionMetadataCount = 0;
775
  let usageMetadataCount = 0;
776
  let assistantText = "";
777
  let promptCount = 0;
778
  let peer: Awaited<ReturnType<typeof createCursorAcpPeerRuntime>> | undefined;
779
  let authCancelPeer: Awaited<ReturnType<typeof createCursorAcpPeerRuntime>> | undefined;
780
  try {
781
    const probe = await probeCursorAcpExecutable();
782
    let authDecisionCount = 0;
783
    authCancelPeer = await createCursorAcpPeerRuntime({
784
      cwd: root,
785
      probe,
786
      environment: { HOME: process.env.HOME },
787
      authorizeLogin: async () => {
788
        authDecisionCount += 1;
789
        return "cancel";
790
      },
791
      requestTimeoutMs: 30_000,
792
    });
793
    const authCancelled = await authCancelPeer.start();
794
    const authCancelPassed =
795
      authDecisionCount === 1 && !authCancelled.ok && authCancelled.reason === "auth_required";
796
    await authCancelPeer.shutdown();
797
    authCancelPeer = undefined;
798
    peer = await createCursorAcpPeerRuntime({
799
      cwd: root,
800
      probe,
801
      environment: { HOME: process.env.HOME },
802
      authorizeLogin: async () => "continue",
803
      requestTimeoutMs: 60_000,
804
      onUpdate: (record) => {
805
        updateCount += 1;
806
        if (record.notificationMeta !== undefined) {
807
          updateMetadataCount += 1;
808
          if (
809
            typeof record.notificationMeta.totalTokens === "number" ||
810
            record.notificationMeta.usage !== undefined
811
          )
812
            usageMetadataCount += 1;
813
        }
814
        const update = record.update as {
815
          sessionUpdate?: unknown;
816
          content?: { text?: unknown };
817
        };
818
        if (typeof update.sessionUpdate === "string") updates.add(update.sessionUpdate);
819
        if (
820
          update.sessionUpdate === "agent_message_chunk" &&
821
          typeof update.content?.text === "string"
822
        )
823
          assistantText += update.content.text;
824
      },
825
    });
826
    const started = await peer.start();
827
    if (!started.ok) throw new Error(`start:${started.reason}`);
828
    const scenarios: AcpLiveReleaseScenarioReceipt[] = [
829
      scenario(
830
        "identity-version",
831
        "live-pass",
832
        "Exact Cursor version and installation closure probed",
833
      ),
834
      scenario("initialize", "live-pass", "Wire version 1 initialize completed"),
835
      scenario("auth-primary", "live-pass", "Advertised Cursor login completed"),
836
      scenario(
837
        "auth-cancel",
838
        authCancelPassed ? "live-pass" : "fail",
839
        authCancelPassed
840
          ? "Client cancelled advertised login before authenticate and received auth required"
841
          : "Client-side login cancellation did not return the typed auth-required outcome",
842
      ),
843
    ];
844
    const attached = await peer.newSession({ cwd: root, canonicalThreadSeed: "release-cursor" });
845
    if (!attached.ok) throw new Error(`session-new:${attached.reason}`);
846
    scenarios.push(scenario("session-new", "live-pass", "Disposable repository session created"));
847
    for (const promptText of [
848
      "Reply with exactly CURSOR_RELEASE_ONE and do not use tools.",
849
      "Reply with exactly CURSOR_RELEASE_TWO and do not use tools.",
850
    ]) {
851
      const prompted = await peer.prompt(attached.value.peerSessionId, [
852
        { type: "text", text: promptText },
853
      ]);
854
      promptCount += 1;
855
      if (!prompted.ok || prompted.value.terminal !== "completed")
856
        throw new Error(`prompt:${prompted.ok ? prompted.value.terminal : prompted.reason}`);
857
      if (prompted.value.completionMeta !== undefined) {
858
        completionMetadataCount += 1;
859
        if (
860
          typeof prompted.value.completionMeta.totalTokens === "number" ||
861
          prompted.value.completionMeta.usage !== undefined
862
        )
863
          usageMetadataCount += 1;
864
      }
865
    }
866
    scenarios.push(
867
      scenario(
868
        "real-repo-text",
869
        assistantText.length > 0 ? "live-pass" : "fail",
870
        assistantText.length > 0
871
          ? "Real disposable repository produced assistant text"
872
          : "No assistant text was observed",
873
      ),
874
      scenario("sequential-turns", "live-pass", "Two sequential prompts completed"),
875
    );
876
    if (started.value.capabilities.list) {
877
      const listed = await peer.listSessions({ cwd: root });
878
      scenarios.push(
879
        scenario(
880
          "session-list",
881
          listed.ok ? "live-pass" : "fail",
882
          listed.ok ? "Advertised session list completed" : `Session list failed ${listed.reason}`,
883
        ),
884
      );
885
    }
886
    const modes = attached.value.modes?.availableModes ?? [];
887
    const alternateMode = modes.find((mode) => mode.id !== attached.value.modes?.currentModeId);
888
    if (alternateMode !== undefined) {
889
      const changed = await peer.setMode(attached.value.peerSessionId, alternateMode.id);
890
      scenarios.push(
891
        scenario(
892
          "model-mode-config",
893
          changed.ok ? "live-pass" : "fail",
894
          changed.ok ? "Advertised mode change completed" : `Mode change failed ${changed.reason}`,
895
        ),
896
      );
897
    } else {
898
      scenarios.push(
899
        scenario("model-mode-config", "not-observed", "No alternate advertised mode was available"),
900
      );
901
    }
902
    const beforeCancel = updateCount;
903
    const pending = peer.prompt(attached.value.peerSessionId, [
904
      { type: "text", text: "Write a detailed twenty paragraph explanation of binary trees." },
905
    ]);
906
    promptCount += 1;
907
    await new Promise((resolve) => setTimeout(resolve, 250));
908
    const cancelled = await peer.cancel(attached.value.peerSessionId, "user");
909
    const cancelledPrompt = await pending;
910
    const cancelPassed =
911
      cancelled.ok &&
912
      ((!cancelledPrompt.ok && cancelledPrompt.reason === "cancelled") ||
913
        (cancelledPrompt.ok && cancelledPrompt.value.terminal === "cancelled"));
914
    scenarios.push(
915
      scenario(
916
        "stream-cancel",
917
        cancelPassed ? "live-pass" : "not-observed",
918
        cancelPassed
919
          ? `Streaming prompt cancelled after ${Math.max(0, updateCount - beforeCancel)} updates`
920
          : "Prompt completed before cancellation could be observed",
921
      ),
922
      scenario(
923
        "cleanup-bounds",
924
        "not-observed",
925
        "Shutdown ran in finally; this runner does not retain process leak counters",
926
      ),
927
    );
928
    await peer.shutdown();
929
    peer = undefined;
930
    const extensions = await qualifyCursorExtensions(root, probe);
931
    const permissionApprovals = await qualifyCursorPermission(root, probe, "approve");
932
    const permissionRefusals = await qualifyCursorPermission(root, probe, "refuse");
933
    const extensionsPassed =
934
      extensions.questions > 0 &&
935
      extensions.plans > 0 &&
936
      extensions.todos > 0 &&
937
      extensions.models > 0;
938
    scenarios.push(
939
      scenario(
940
        "cursor-extensions-models",
941
        extensionsPassed ? "live-pass" : "not-observed",
942
        `Pinned extension counts: questions ${extensions.questions}, plans ${extensions.plans}, todos ${extensions.todos}, models ${extensions.models}`,
943
      ),
944
      scenario(
945
        "permission-approval",
946
        permissionApprovals > 0 ? "live-pass" : "not-observed",
947
        `Pinned permission approval selections: ${permissionApprovals}`,
948
      ),
949
      scenario(
950
        "permission-refusal",
951
        permissionRefusals > 0 ? "live-pass" : "not-observed",
952
        `Pinned permission refusal selections: ${permissionRefusals}`,
953
      ),
954
    );
955
    return {
956
      peer: "cursor",
957
      result: scenarios.some((entry) => entry.result === "fail") ? "fail" : "partial",
958
      binary: {
959
        reportedVersion: probe.reportedVersion,
960
        executableSha256: probe.sha256,
961
        ...(probe.closureSha256 === undefined
962
          ? {}
963
          : { installationClosureSha256: probe.closureSha256 }),
964
      },
965
      negotiation: {
966
        wireVersion: 1,
967
        authMethodIds: started.value.authMethodIds,
968
        capabilityKeys: capabilityKeys(started.value.capabilities),
969
      },
970
      scenarios,
971
      counters: {
972
        updateCount,
973
        updateKinds: [...updates].toSorted(),
974
        promptCount,
975
        updateMetadataCount,
976
        completionMetadataCount,
977
        usageMetadataCount,
978
      },
979
    };
980
  } finally {
981
    await authCancelPeer?.shutdown().catch(() => undefined);
982
    await peer?.shutdown().catch(() => undefined);
983
    await rm(root, { recursive: true, force: true });
984
  }
985
};
986
987
const peers: AcpLiveReleasePeerReceipt[] = [];
988
if (selection === "grok" || selection === "both") {
989
  try {
990
    peers.push(await runGrok());
991
  } catch {
992
    peers.push(failedPeer("grok"));
993
  }
994
}
995
if (selection === "cursor" || selection === "both") {
996
  try {
997
    peers.push(await runCursor());
998
  } catch {
999
    peers.push(failedPeer("cursor"));
1000
  }
1001
}
1002
const artifact = buildAcpLiveReleaseArtifact({
1003
  recordedAt,
1004
  openAgentsRevision: revision,
1005
  platform,
1006
  peers,
1007
});
1008
const validation = validateAcpLiveReleaseArtifact(artifact);
1009
const output = process.env.ACP_RELEASE_OUTPUT;
1010
if (output !== undefined) {
1011
  const liveDirectory = resolve(process.cwd(), "compatibility", "live");
1012
  if (
1013
    !isAbsolute(output) ||
1014
    !resolve(output).startsWith(`${liveDirectory}${sep}`) ||
1015
    !output.endsWith(".json")
1016
  )
1017
    throw new TypeError(
1018
      "ACP_RELEASE_OUTPUT must be an absolute .json path beneath compatibility/live",
1019
    );
1020
  await writeFile(output, `${JSON.stringify(artifact, null, 2)}\n`, { mode: 0o600 });
1021
}
1022
process.stdout.write(`${JSON.stringify({ artifact, validation }, null, 2)}\n`);
1023
if (!validation.valid || peers.some((peer) => peer.result === "fail")) process.exitCode = 1;
packages/agent-client-protocol-conformance/src/conformance.test.ts modified -251

@@ -23,22 +23,12 @@ import { STABLE_CONFORMANCE_CASES, assertStableManifestCoverage } from "./cases.

23 23
import { executeFaultCase } from "./faults.ts";
24 24
import { definePeerScenario, runPeerScenario, startPeerScenarioTransport } from "./harness.ts";
25 25
import { summarizeSafeInitialize } from "./live.ts";
26
import {
27
  buildAcpLiveReleaseArtifact,
28
  validateAcpDesktopReleaseArtifact,
29
  validateAcpLiveReleaseArtifact,
30
} from "./live-release.ts";
31 26
import { materializeMcpServers, McpReferenceError } from "./mcp.ts";
32 27
import {
33 28
  ConformanceProjectionState,
34 29
  projectSessionUpdateForConformance,
35 30
  projectStopReasonForConformance,
36 31
} from "./projection.ts";
37
import {
38
  acpReleaseEvidenceClass,
39
  evaluateAcpReleaseMatrixGate,
40
  validateAcpReleaseMatrix,
41
} from "./release.ts";
42 32
import { assertSecretAbsent } from "./transcript.ts";
43 33
import {
44 34
  CONTENT_BLOCK_FIXTURES,

@@ -51,94 +41,6 @@ import {

51 41
} from "./variants.ts";
52 42
53 43
describe("stable Agent Client Protocol conformance", () => {
54
  it("builds a closed, redacted candidate live-release receipt", () => {
55
    const artifact = buildAcpLiveReleaseArtifact({
56
      recordedAt: "2026-07-16T16:00:00.000Z",
57
      openAgentsRevision: "a".repeat(40),
58
      platform: "darwin-arm64-node-24.0.0",
59
      peers: [
60
        {
61
          peer: "grok",
62
          result: "partial",
63
          binary: { reportedVersion: "0.2.101", executableSha256: "b".repeat(64) },
64
          negotiation: {
65
            wireVersion: 1,
66
            authMethodIds: ["cached_token"],
67
            capabilityKeys: ["list"],
68
          },
69
          scenarios: [
70
            { id: "initialize", result: "live-pass", safeDetail: "Initialize completed" },
71
          ],
72
          counters: {
73
            updateCount: 2,
74
            updateKinds: ["agent_message_chunk"],
75
            promptCount: 1,
76
          },
77
        },
78
      ],
79
    });
80
81
    expect(validateAcpLiveReleaseArtifact(artifact)).toEqual({ valid: true, errors: [] });
82
    expect(JSON.stringify(artifact)).not.toMatch(/prompt text|response text|session-[0-9]/i);
83
84
    const leaking = structuredClone(artifact) as unknown as {
85
      peers: Array<{ scenarios: Array<{ safeDetail: string }> }>;
86
    };
87
    leaking.peers[0]!.scenarios[0]!.safeDetail = "/Users/example/private";
88
    expect(validateAcpLiveReleaseArtifact(leaking as never)).toMatchObject({ valid: false });
89
90
    const invented = structuredClone(artifact) as unknown as {
91
      peers: Array<{ scenarios: Array<{ id: string }> }>;
92
    };
93
    invented.peers[0]!.scenarios[0]!.id = "invented-release-proof";
94
    expect(validateAcpLiveReleaseArtifact(invented as never)).toMatchObject({ valid: false });
95
  });
96
97
  it("validates packaged Desktop interruption and recovery without accepting retained data", () => {
98
    const artifact = {
99
      format: "openagents-acp-desktop-release-run-v1",
100
      protocol: "Agent Client Protocol",
101
      protocolExclusions: ["Agent Communication Protocol", "A2A"],
102
      proofClass: "candidate-packaged-desktop-live",
103
      claimAuthority: "none-release-matrix-only",
104
      recordedAt: "2026-07-16T16:46:36.674Z",
105
      openAgentsRevision: "a".repeat(40),
106
      platform: "darwin-arm64-node-24.13.1",
107
      provider: "cursor",
108
      lane: "acp:cursor-agent",
109
      packaged: true,
110
      interruption: {
111
        mismatchedWorkspaceRefused: true,
112
        laneConfigured: true,
113
        laneAdmitted: true,
114
        exitedDuringRunningTurn: true,
115
      },
116
      recovery: {
117
        reusedDesktopState: true,
118
        explicitlyReenabledSameThread: true,
119
        recoveredSameThread: true,
120
        freshThreadRetryAfterFailure: false,
121
        laneConfigured: true,
122
        interruptedTurnSettled: true,
123
        durableCompletedTurn: true,
124
        disabled: true,
125
      },
126
      redaction: {
127
        promptTextRetained: false,
128
        responseTextRetained: false,
129
        threadIdentifiersRetained: false,
130
        authMaterialRetained: false,
131
        absolutePathsRetained: false,
132
      },
133
    } as const;
134
    expect(validateAcpDesktopReleaseArtifact(artifact)).toEqual({ valid: true, errors: [] });
135
    const leaking = structuredClone(artifact) as unknown as {
136
      redaction: { promptTextRetained: boolean };
137
    };
138
    leaking.redaction.promptTextRetained = true;
139
    expect(validateAcpDesktopReleaseArtifact(leaking as never)).toMatchObject({ valid: false });
140
  });
141
142 44
  it("reduces live initialize evidence to capability/auth IDs without provider or host metadata", () => {
143 45
    const summary = summarizeSafeInitialize({
144 46
      protocolVersion: 1,

@@ -842,159 +744,6 @@ describe("MCP custody, durable evidence, and deterministic faults", () => {

842 744
    );
843 745
  });
844 746
845
  it("keeps named-peer release claims independent, fresh, redacted, and live-gated", () => {
846
    expect(acpReleaseEvidenceClass("grok", "auth-secondary")).toBe("optional-live-peer");
847
    expect(acpReleaseEvidenceClass("cursor", "auth-secondary")).toBe("not-applicable");
848
    const matrix = JSON.parse(
849
      readFileSync(resolve(import.meta.dirname, "../compatibility/release-matrix.json"), "utf8"),
850
    ) as Record<string, unknown>;
851
    const freshValidation = validateAcpReleaseMatrix(matrix, {
852
      now: new Date("2026-07-17T13:00:00.000Z"),
853
    });
854
    expect(freshValidation).toMatchObject({
855
      valid: true,
856
      errors: [],
857
      expiry: { _tag: "Fresh", freshnessDays: 30 },
858
    });
859
    expect(evaluateAcpReleaseMatrixGate(freshValidation, "push")).toMatchObject({
860
      valid: true,
861
      errors: [],
862
    });
863
864
    const staleValidation = validateAcpReleaseMatrix(matrix, {
865
      now: new Date("2026-08-23T17:47:57.447Z"),
866
    });
867
    expect(staleValidation).toMatchObject({
868
      valid: true,
869
      errors: [],
870
      expiry: { _tag: "Expired", freshnessDays: 30 },
871
    });
872
    const stalePushGate = evaluateAcpReleaseMatrixGate(staleValidation, "push");
873
    expect(stalePushGate).toMatchObject({
874
      valid: true,
875
      errors: [],
876
      warning: expect.stringContaining("recorded at 2026-07-17T12:16:40Z"),
877
    });
878
    expect(stalePushGate.warning).toContain("freshness window is 30 days");
879
    expect(stalePushGate.warning).toContain("Refresh requires a qualifying live release run");
880
    expect(evaluateAcpReleaseMatrixGate(staleValidation, "release")).toMatchObject({
881
      valid: false,
882
      errors: [expect.stringContaining("Refresh requires a qualifying live release run")],
883
    });
884
885
    const promoted = structuredClone(matrix) as {
886
      peers: Array<{
887
        claimState: string;
888
        releaseEligible: boolean;
889
        scenarios: Array<{ id: string; result: string }>;
890
      }>;
891
    };
892
    promoted.peers[1]!.claimState = "supported";
893
    promoted.peers[1]!.releaseEligible = true;
894
    promoted.peers[1]!.scenarios.find((scenario) => scenario.id === "cursor-wire-launch")!.result =
895
      "not-tested";
896
    expect(
897
      validateAcpReleaseMatrix(promoted, { now: new Date("2026-07-16T16:00:00.000Z") }),
898
    ).toMatchObject({ valid: false });
899
900
    const hostLeaking = structuredClone(matrix) as Record<string, unknown>;
901
    hostLeaking["privatePath"] = "/Users/example/private-repository";
902
    expect(
903
      validateAcpReleaseMatrix(hostLeaking, { now: new Date("2026-07-16T16:00:00.000Z") }),
904
    ).toMatchObject({ valid: false });
905
906
    const identityMissing = structuredClone(matrix) as {
907
      openAgents: { schemaSha256?: string };
908
    };
909
    delete identityMissing.openAgents.schemaSha256;
910
    expect(
911
      validateAcpReleaseMatrix(identityMissing, { now: new Date("2026-07-16T16:00:00.000Z") }),
912
    ).toMatchObject({ valid: false });
913
914
    const scenarioMissing = structuredClone(matrix) as {
915
      peers: Array<{ scenarios: unknown[] }>;
916
    };
917
    scenarioMissing.peers[0]!.scenarios.pop();
918
    expect(
919
      validateAcpReleaseMatrix(scenarioMissing, { now: new Date("2026-07-16T16:00:00.000Z") }),
920
    ).toMatchObject({ valid: false });
921
922
    const selfExempted = structuredClone(matrix) as {
923
      peers: Array<{
924
        claimState: string;
925
        releaseEligible: boolean;
926
        scenarios: Array<{ requiredForSupported: boolean }>;
927
      }>;
928
    };
929
    for (const peer of selfExempted.peers) {
930
      peer.claimState = "supported";
931
      peer.releaseEligible = true;
932
      for (const scenario of peer.scenarios) scenario.requiredForSupported = false;
933
    }
934
    expect(
935
      validateAcpReleaseMatrix(selfExempted, { now: new Date("2026-07-16T16:00:00.000Z") }),
936
    ).toMatchObject({ valid: false });
937
938
    const inventedScenario = structuredClone(matrix) as {
939
      peers: Array<{ scenarios: Array<{ id: string }> }>;
940
    };
941
    inventedScenario.peers[0]!.scenarios[0]!.id = "self-authorized-promotion";
942
    expect(
943
      validateAcpReleaseMatrix(inventedScenario, { now: new Date("2026-07-16T16:00:00.000Z") }),
944
    ).toMatchObject({ valid: false });
945
946
    const emptyLiveEvidence = structuredClone(matrix) as {
947
      peers: Array<{ scenarios: Array<{ result: string; evidenceRefs: string[] }> }>;
948
    };
949
    const liveScenario = emptyLiveEvidence.peers[0]!.scenarios.find(
950
      (scenario) => scenario.result === "live-pass",
951
    )!;
952
    liveScenario.evidenceRefs = [];
953
    expect(
954
      validateAcpReleaseMatrix(emptyLiveEvidence, { now: new Date("2026-07-16T16:00:00.000Z") }),
955
    ).toMatchObject({ valid: false });
956
957
    const remoteEvidence = structuredClone(matrix) as {
958
      peers: Array<{ scenarios: Array<{ evidenceRefs: string[] }> }>;
959
    };
960
    remoteEvidence.peers[0]!.scenarios[0]!.evidenceRefs = ["https://example.invalid/proof.json"];
961
    expect(
962
      validateAcpReleaseMatrix(remoteEvidence, { now: new Date("2026-07-16T16:00:00.000Z") }),
963
    ).toMatchObject({ valid: false });
964
965
    const futureEvidence = structuredClone(matrix) as { recordedAt: string };
966
    futureEvidence.recordedAt = "2026-07-17T16:00:00.000Z";
967
    const futureValidation = validateAcpReleaseMatrix(futureEvidence, {
968
      now: new Date("2026-07-16T16:00:00.000Z"),
969
    });
970
    expect(futureValidation).toMatchObject({
971
      valid: false,
972
      errors: ["matrix evidence timestamp is in the future"],
973
    });
974
    expect(futureValidation.expiry).toBeUndefined();
975
    expect(evaluateAcpReleaseMatrixGate(futureValidation, "push")).toMatchObject({
976
      valid: false,
977
      errors: ["matrix evidence timestamp is in the future"],
978
    });
979
980
    const unsupportedPromotion = structuredClone(matrix) as {
981
      peers: Array<{
982
        claimState: string;
983
        releaseEligible: boolean;
984
        scenarios: Array<{ requiredForSupported: boolean; result: string }>;
985
      }>;
986
    };
987
    unsupportedPromotion.peers[0]!.claimState = "supported";
988
    unsupportedPromotion.peers[0]!.releaseEligible = true;
989
    for (const scenario of unsupportedPromotion.peers[0]!.scenarios)
990
      if (scenario.requiredForSupported) scenario.result = "unsupported";
991
    expect(
992
      validateAcpReleaseMatrix(unsupportedPromotion, {
993
        now: new Date("2026-07-16T16:00:00.000Z"),
994
      }),
995
    ).toMatchObject({ valid: false });
996
  });
997
998 747
  it.each(FAULT_CASES)("executes bounded %s/%s fault evidence", async (layer, fault) => {
999 748
    const result = await executeFaultCase(layer, fault);
1000 749
    expect(result).toMatchObject({ layer, fault, result: "pass" });
packages/agent-client-protocol-conformance/src/index.ts modified -3

@@ -5,9 +5,6 @@ export * from "./harness.ts";

5 5
export * from "./live.ts";
6 6
export * from "./mcp.ts";
7 7
export * from "./projection.ts";
8
export * from "./release.ts";
9
export * from "./release-evidence.ts";
10
export * from "./live-release.ts";
11 8
export * from "./report.ts";
12 9
export * from "./transcript.ts";
13 10
export * from "./variants.ts";
packages/agent-client-protocol-conformance/src/live-release.ts deleted -264

@@ -1,264 +0,0 @@

1
import { stripVTControlCharacters } from "node:util";
2
3
import { ACP_RELEASE_SCENARIO_IDS } from "./release.ts";
4
5
export type AcpLiveReleaseScenarioReceipt = Readonly<{
6
  id: (typeof ACP_RELEASE_SCENARIO_IDS)[number];
7
  result: "live-pass" | "not-observed" | "blocked" | "fail";
8
  safeDetail: string;
9
}>;
10
11
export type AcpLiveReleasePeerReceipt = Readonly<{
12
  peer: "grok" | "cursor";
13
  result: "pass" | "partial" | "fail";
14
  binary: Readonly<{
15
    reportedVersion: string;
16
    executableSha256: string;
17
    installationClosureSha256?: string;
18
  }>;
19
  negotiation: Readonly<{
20
    wireVersion: 1;
21
    authMethodIds: ReadonlyArray<string>;
22
    capabilityKeys: ReadonlyArray<string>;
23
  }>;
24
  scenarios: ReadonlyArray<AcpLiveReleaseScenarioReceipt>;
25
  counters: Readonly<{
26
    updateCount: number;
27
    updateKinds: ReadonlyArray<string>;
28
    promptCount: number;
29
    updateMetadataCount?: number;
30
    completionMetadataCount?: number;
31
    usageMetadataCount?: number;
32
  }>;
33
}>;
34
35
export type AcpLiveReleaseArtifact = Readonly<{
36
  format: "openagents-acp-live-release-run-v1";
37
  protocol: "Agent Client Protocol";
38
  protocolExclusions: ReadonlyArray<"Agent Communication Protocol" | "A2A">;
39
  proofClass: "candidate-live";
40
  claimAuthority: "none-release-matrix-only";
41
  recordedAt: string;
42
  openAgentsRevision: string;
43
  schemaRelease: "schema-v1.19.0";
44
  platform: string;
45
  peers: ReadonlyArray<AcpLiveReleasePeerReceipt>;
46
  redaction: Readonly<{
47
    promptTextRetained: false;
48
    responseTextRetained: false;
49
    sessionIdentifiersRetained: false;
50
    authMaterialRetained: false;
51
    absolutePathsRetained: false;
52
  }>;
53
}>;
54
55
export type AcpDesktopReleaseArtifact = Readonly<{
56
  format: "openagents-acp-desktop-release-run-v1";
57
  protocol: "Agent Client Protocol";
58
  protocolExclusions: ReadonlyArray<"Agent Communication Protocol" | "A2A">;
59
  proofClass: "candidate-packaged-desktop-live";
60
  claimAuthority: "none-release-matrix-only";
61
  recordedAt: string;
62
  openAgentsRevision: string;
63
  platform: string;
64
  provider: "grok" | "cursor";
65
  lane: "acp:grok-cli" | "acp:cursor-agent";
66
  packaged: true;
67
  interruption: Readonly<{
68
    mismatchedWorkspaceRefused: true;
69
    laneConfigured: true;
70
    laneAdmitted: true;
71
    exitedDuringRunningTurn: true;
72
  }>;
73
  recovery: Readonly<{
74
    reusedDesktopState: true;
75
    explicitlyReenabledSameThread: true;
76
    recoveredSameThread: boolean;
77
    freshThreadRetryAfterFailure: boolean;
78
    additionalProcessRestartAfterFailedRetry?: boolean;
79
    laneConfigured: true;
80
    interruptedTurnSettled: true;
81
    durableCompletedTurn: true;
82
    disabled: true;
83
  }>;
84
  redaction: Readonly<{
85
    promptTextRetained: false;
86
    responseTextRetained: false;
87
    threadIdentifiersRetained: false;
88
    authMaterialRetained: false;
89
    absolutePathsRetained: false;
90
  }>;
91
}>;
92
93
const secretOrPrivate = (value: unknown): boolean => {
94
  const encoded = JSON.stringify(value);
95
  return [
96
    /\/Users\//,
97
    /\/home\/[^"/]+\//,
98
    /Bearer\s+[A-Za-z0-9._~-]+/i,
99
    /(?:token|secret|api[_-]?key)=[^"\s]+/i,
100
    /(?:sk|xai)-[A-Za-z0-9_-]{12,}/,
101
    /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/,
102
  ].some((pattern) => pattern.test(encoded));
103
};
104
105
const safeToken = (value: string, max = 160): string =>
106
  /^[A-Za-z0-9][A-Za-z0-9._:+()[\],; /-]*$/.test(value) ? value.slice(0, max) : "withheld";
107
108
const safeVersion = (value: string): string =>
109
  safeToken(stripVTControlCharacters(value).trim(), 256);
110
111
export const buildAcpLiveReleaseArtifact = (
112
  input: Readonly<{
113
    recordedAt: string;
114
    openAgentsRevision: string;
115
    platform: string;
116
    peers: ReadonlyArray<AcpLiveReleasePeerReceipt>;
117
  }>,
118
): AcpLiveReleaseArtifact => ({
119
  format: "openagents-acp-live-release-run-v1",
120
  protocol: "Agent Client Protocol",
121
  protocolExclusions: ["Agent Communication Protocol", "A2A"],
122
  proofClass: "candidate-live",
123
  claimAuthority: "none-release-matrix-only",
124
  recordedAt: input.recordedAt,
125
  openAgentsRevision: input.openAgentsRevision,
126
  schemaRelease: "schema-v1.19.0",
127
  platform: safeToken(input.platform, 80),
128
  peers: input.peers.map((peer) => ({
129
    ...peer,
130
    binary: {
131
      reportedVersion: safeVersion(peer.binary.reportedVersion),
132
      executableSha256: peer.binary.executableSha256,
133
      ...(peer.binary.installationClosureSha256 === undefined
134
        ? {}
135
        : { installationClosureSha256: peer.binary.installationClosureSha256 }),
136
    },
137
    negotiation: {
138
      ...peer.negotiation,
139
      authMethodIds: peer.negotiation.authMethodIds.map((value) => safeToken(value, 120)),
140
      capabilityKeys: peer.negotiation.capabilityKeys.map((value) => safeToken(value, 120)),
141
    },
142
    scenarios: peer.scenarios.map((scenario) => ({
143
      ...scenario,
144
      safeDetail: safeToken(scenario.safeDetail, 240),
145
    })),
146
    counters: {
147
      ...peer.counters,
148
      updateKinds: peer.counters.updateKinds.map((value) => safeToken(value, 120)),
149
    },
150
  })),
151
  redaction: {
152
    promptTextRetained: false,
153
    responseTextRetained: false,
154
    sessionIdentifiersRetained: false,
155
    authMaterialRetained: false,
156
    absolutePathsRetained: false,
157
  },
158
});
159
160
export const validateAcpLiveReleaseArtifact = (
161
  artifact: AcpLiveReleaseArtifact,
162
): Readonly<{ valid: boolean; errors: ReadonlyArray<string> }> => {
163
  const errors: string[] = [];
164
  if (artifact.format !== "openagents-acp-live-release-run-v1") errors.push("format is invalid");
165
  if (artifact.protocol !== "Agent Client Protocol") errors.push("protocol is invalid");
166
  if (
167
    artifact.protocolExclusions.length !== 2 ||
168
    !artifact.protocolExclusions.includes("Agent Communication Protocol") ||
169
    !artifact.protocolExclusions.includes("A2A")
170
  )
171
    errors.push("protocol exclusions are invalid");
172
  if (artifact.proofClass !== "candidate-live") errors.push("proof class is invalid");
173
  if (artifact.claimAuthority !== "none-release-matrix-only")
174
    errors.push("claim authority is invalid");
175
  if (artifact.schemaRelease !== "schema-v1.19.0") errors.push("schema release is invalid");
176
  if (Object.values(artifact.redaction).some((retained) => retained !== false))
177
    errors.push("redaction declaration is invalid");
178
  if (!/^[a-f0-9]{40}$/.test(artifact.openAgentsRevision))
179
    errors.push("OpenAgents revision must be a full Git SHA");
180
  if (!Number.isFinite(Date.parse(artifact.recordedAt))) errors.push("recordedAt is invalid");
181
  if (artifact.peers.length === 0 || artifact.peers.length > 2)
182
    errors.push("one or two named peer receipts are required");
183
  if (new Set(artifact.peers.map((peer) => peer.peer)).size !== artifact.peers.length)
184
    errors.push("peer receipts must be unique");
185
  const scenarioIds = new Set<string>(ACP_RELEASE_SCENARIO_IDS);
186
  for (const peer of artifact.peers) {
187
    if (!/^[a-f0-9]{64}$/.test(peer.binary.executableSha256))
188
      errors.push(`${peer.peer}: executable SHA-256 is invalid`);
189
    if (
190
      peer.binary.installationClosureSha256 !== undefined &&
191
      !/^[a-f0-9]{64}$/.test(peer.binary.installationClosureSha256)
192
    )
193
      errors.push(`${peer.peer}: installation closure SHA-256 is invalid`);
194
    if (peer.negotiation.wireVersion !== 1) errors.push(`${peer.peer}: wire version is not 1`);
195
    const ids = peer.scenarios.map((scenario) => scenario.id);
196
    if (ids.length === 0) errors.push(`${peer.peer}: at least one scenario receipt is required`);
197
    if (new Set(ids).size !== ids.length) errors.push(`${peer.peer}: duplicate scenario receipt`);
198
    if (ids.some((id) => !scenarioIds.has(id)))
199
      errors.push(`${peer.peer}: unknown scenario receipt`);
200
    if (peer.result === "pass" && peer.scenarios.some((scenario) => scenario.result === "fail"))
201
      errors.push(`${peer.peer}: pass contains a failed scenario`);
202
    if (peer.result === "fail" && peer.scenarios.every((scenario) => scenario.result !== "fail"))
203
      errors.push(`${peer.peer}: failed peer has no failed scenario`);
204
    if (
205
      !Number.isSafeInteger(peer.counters.updateCount) ||
206
      peer.counters.updateCount < 0 ||
207
      !Number.isSafeInteger(peer.counters.promptCount) ||
208
      peer.counters.promptCount < 0 ||
209
      [
210
        peer.counters.updateMetadataCount,
211
        peer.counters.completionMetadataCount,
212
        peer.counters.usageMetadataCount,
213
      ].some((value) => value !== undefined && (!Number.isSafeInteger(value) || value < 0))
214
    )
215
      errors.push(`${peer.peer}: counters are invalid`);
216
  }
217
  if (secretOrPrivate(artifact))
218
    errors.push("artifact contains secret-shaped or host-private data");
219
  return { valid: errors.length === 0, errors };
220
};
221
222
export const validateAcpDesktopReleaseArtifact = (
223
  artifact: AcpDesktopReleaseArtifact,
224
): Readonly<{ valid: boolean; errors: ReadonlyArray<string> }> => {
225
  const errors: string[] = [];
226
  if (artifact.format !== "openagents-acp-desktop-release-run-v1") errors.push("format is invalid");
227
  if (artifact.protocol !== "Agent Client Protocol") errors.push("protocol is invalid");
228
  if (
229
    artifact.protocolExclusions.length !== 2 ||
230
    !artifact.protocolExclusions.includes("Agent Communication Protocol") ||
231
    !artifact.protocolExclusions.includes("A2A")
232
  )
233
    errors.push("protocol exclusions are invalid");
234
  if (artifact.proofClass !== "candidate-packaged-desktop-live")
235
    errors.push("proof class is invalid");
236
  if (artifact.claimAuthority !== "none-release-matrix-only")
237
    errors.push("claim authority is invalid");
238
  if (!Number.isFinite(Date.parse(artifact.recordedAt))) errors.push("recordedAt is invalid");
239
  if (!/^[a-f0-9]{40}$/.test(artifact.openAgentsRevision))
240
    errors.push("OpenAgents revision must be a full Git SHA");
241
  if (
242
    (artifact.provider !== "cursor" || artifact.lane !== "acp:cursor-agent") &&
243
    (artifact.provider !== "grok" || artifact.lane !== "acp:grok-cli")
244
  )
245
    errors.push("provider lane identity is invalid");
246
  if (artifact.packaged !== true) errors.push("packaged execution is required");
247
  if (Object.values(artifact.interruption).some((value) => value !== true))
248
    errors.push("interruption proof is incomplete");
249
  if (
250
    artifact.recovery.reusedDesktopState !== true ||
251
    artifact.recovery.explicitlyReenabledSameThread !== true ||
252
    artifact.recovery.laneConfigured !== true ||
253
    artifact.recovery.interruptedTurnSettled !== true ||
254
    artifact.recovery.durableCompletedTurn !== true ||
255
    artifact.recovery.disabled !== true ||
256
    artifact.recovery.recoveredSameThread === artifact.recovery.freshThreadRetryAfterFailure
257
  )
258
    errors.push("recovery proof is incomplete or inconsistent");
259
  if (Object.values(artifact.redaction).some((retained) => retained !== false))
260
    errors.push("redaction declaration is invalid");
261
  if (secretOrPrivate(artifact))
262
    errors.push("artifact contains secret-shaped or host-private data");
263
  return { valid: errors.length === 0, errors };
264
};
packages/agent-client-protocol-conformance/src/release-evidence.test.ts deleted -62

@@ -1,62 +0,0 @@

1
import { describe, expect, test } from "vite-plus/test";
2
3
import checkedReleaseMatrix from "../compatibility/release-matrix.json" with { type: "json" };
4
5
import { compileAcpReleaseEvidence } from "./release-evidence.ts";
6
7
const NOW = new Date("2026-07-17T13:00:00.000Z");
8
9
describe("checked ACP release evidence compiler", () => {
10
  test("compiles the complete checked matrix into peer admission and feature evidence", () => {
11
    const result = compileAcpReleaseEvidence(checkedReleaseMatrix, { now: NOW });
12
    expect(result._tag).toBe("ReleaseEvidenceReady");
13
    if (result._tag !== "ReleaseEvidenceReady") return;
14
    expect(result.evidence.grok.map((record) => record.suiteId)).toEqual([
15
      "acp-wire-v1-conformance",
16
      "acp-release-matrix-v1",
17
      "grok-authority-reverse",
18
      "grok-question-extensions",
19
    ]);
20
    expect(result.evidence.cursor.map((record) => record.suiteId)).toEqual([
21
      "acp-wire-v1-conformance",
22
      "cursor-t3-bde0a4c0",
23
      "acp-release-matrix-v1",
24
      "cursor-authority-reverse",
25
      "cursor-vendor-extensions",
26
      "cursor-model-discovery",
27
    ]);
28
    expect(result.evidence.cursor.at(2)).toMatchObject({
29
      peerVersion: "2026.6.24",
30
      executableSha256: "b7babf47d8b1eee28ac27a74affa02a559bb38103a6e71fbb1f120805d51fedf",
31
      installationClosureSha256: "69d078daa4db8cbb4163ce2f010207553efb06d652c1e1ea421d739795532faa",
32
      platform: { os: "darwin", arch: "arm64" },
33
    });
34
  });
35
36
  test("fails closed for stale, incomplete, or revision-substituted evidence", () => {
37
    const stale = compileAcpReleaseEvidence(checkedReleaseMatrix, {
38
      now: new Date("2026-09-01T00:00:00.000Z"),
39
    });
40
    expect(stale).toMatchObject({
41
      _tag: "ReleaseEvidenceUnavailable",
42
      diagnostics: [expect.stringContaining("freshness window is 30 days")],
43
    });
44
45
    const incomplete = structuredClone(checkedReleaseMatrix) as any;
46
    incomplete.peers[0].scenarios.find((scenario: any) => scenario.id === "initialize").result =
47
      "blocked";
48
    expect(compileAcpReleaseEvidence(incomplete, { now: NOW })).toMatchObject({
49
      _tag: "ReleaseEvidenceUnavailable",
50
    });
51
52
    expect(
53
      compileAcpReleaseEvidence(checkedReleaseMatrix, {
54
        now: NOW,
55
        expectedOpenAgentsRevision: "f".repeat(40),
56
      }),
57
    ).toEqual({
58
      _tag: "ReleaseEvidenceUnavailable",
59
      diagnostics: ["checked release evidence does not match the expected OpenAgents revision"],
60
    });
61
  });
62
});
packages/agent-client-protocol-conformance/src/release-evidence.ts deleted -178

@@ -1,178 +0,0 @@

1
import type { AcpConformanceEvidenceRecord } from "@openagentsinc/agent-client-protocol/profiles";
2
3
import checkedReleaseMatrix from "../compatibility/release-matrix.json" with { type: "json" };
4
5
import { describeAcpReleaseExpiry, validateAcpReleaseMatrix } from "./release.ts";
6
7
export type AcpReleaseEvidencePeer = "grok" | "cursor";
8
9
export type AcpReleaseEvidenceCompilation =
10
  | Readonly<{
11
      _tag: "ReleaseEvidenceReady";
12
      openAgentsRevision: string;
13
      evidence: Readonly<
14
        Record<AcpReleaseEvidencePeer, ReadonlyArray<AcpConformanceEvidenceRecord>>
15
      >;
16
    }>
17
  | Readonly<{
18
      _tag: "ReleaseEvidenceUnavailable";
19
      diagnostics: ReadonlyArray<string>;
20
    }>;
21
22
type JsonObject = Record<string, unknown>;
23
24
const object = (value: unknown): JsonObject | undefined =>
25
  value !== null && typeof value === "object" && !Array.isArray(value)
26
    ? (value as JsonObject)
27
    : undefined;
28
29
const string = (value: unknown): string | undefined =>
30
  typeof value === "string" && value.length > 0 ? value : undefined;
31
32
const scenarioPassedLive = (peer: JsonObject, id: string): boolean =>
33
  Array.isArray(peer.scenarios) &&
34
  peer.scenarios.some((value) => {
35
    const scenario = object(value);
36
    return scenario?.id === id && scenario.result === "live-pass";
37
  });
38
39
const fixtureSuites = (peer: AcpReleaseEvidencePeer): ReadonlyArray<string> =>
40
  peer === "grok" ? ["acp-wire-v1-conformance"] : ["acp-wire-v1-conformance", "cursor-t3-bde0a4c0"];
41
42
const featureSuites = (
43
  peer: AcpReleaseEvidencePeer,
44
  document: JsonObject,
45
): ReadonlyArray<string> => {
46
  if (peer === "grok") {
47
    return [
48
      ...(scenarioPassedLive(document, "permission-approval") &&
49
      scenarioPassedLive(document, "permission-refusal") &&
50
      scenarioPassedLive(document, "fs-terminal-enabled")
51
        ? ["grok-authority-reverse"]
52
        : []),
53
      ...(scenarioPassedLive(document, "grok-question-extensions")
54
        ? ["grok-question-extensions"]
55
        : []),
56
      ...(scenarioPassedLive(document, "auth-secondary") ? ["grok-api-key-auth"] : []),
57
    ];
58
  }
59
  return [
60
    ...(scenarioPassedLive(document, "permission-approval") &&
61
    scenarioPassedLive(document, "permission-refusal")
62
      ? ["cursor-authority-reverse"]
63
      : []),
64
    ...(scenarioPassedLive(document, "cursor-extensions-models")
65
      ? ["cursor-vendor-extensions", "cursor-model-discovery"]
66
      : []),
67
  ];
68
};
69
70
/**
71
 * Lowers the complete checked release matrix into the narrow evidence records
72
 * consumed by trusted peer admission. Matrix validation runs first and the
73
 * compiler never trusts a hand-authored claim label or partial scenario row.
74
 */
75
export const compileAcpReleaseEvidence = (
76
  value: unknown,
77
  options: Readonly<{ now?: Date; expectedOpenAgentsRevision?: string }> = {},
78
): AcpReleaseEvidenceCompilation => {
79
  const validation = validateAcpReleaseMatrix(value, {
80
    ...(options.now === undefined ? {} : { now: options.now }),
81
  });
82
  if (!validation.valid)
83
    return { _tag: "ReleaseEvidenceUnavailable", diagnostics: validation.errors };
84
  if (validation.expiry?._tag === "Expired")
85
    return {
86
      _tag: "ReleaseEvidenceUnavailable",
87
      diagnostics: [describeAcpReleaseExpiry(validation.expiry)],
88
    };
89
90
  const matrix = object(value);
91
  const openAgents = object(matrix?.openAgents);
92
  const revision = string(openAgents?.revision);
93
  if (revision === undefined)
94
    return {
95
      _tag: "ReleaseEvidenceUnavailable",
96
      diagnostics: ["OpenAgents revision is unavailable after matrix validation"],
97
    };
98
  if (
99
    options.expectedOpenAgentsRevision !== undefined &&
100
    options.expectedOpenAgentsRevision !== revision
101
  )
102
    return {
103
      _tag: "ReleaseEvidenceUnavailable",
104
      diagnostics: ["checked release evidence does not match the expected OpenAgents revision"],
105
    };
106
107
  const testedPlatform = string(object(matrix?.platform)?.tested)?.split("-");
108
  const os = testedPlatform?.[0];
109
  const arch = testedPlatform?.slice(1).join("-");
110
  const recordedAt = string(matrix?.recordedAt);
111
  if (os === undefined || arch === undefined || arch.length === 0 || recordedAt === undefined)
112
    return {
113
      _tag: "ReleaseEvidenceUnavailable",
114
      diagnostics: ["checked release platform or timestamp is unavailable"],
115
    };
116
117
  const compiled: Record<AcpReleaseEvidencePeer, ReadonlyArray<AcpConformanceEvidenceRecord>> = {
118
    grok: [],
119
    cursor: [],
120
  };
121
  for (const rawPeer of Array.isArray(matrix?.peers) ? matrix.peers : []) {
122
    const peer = object(rawPeer);
123
    if (peer === undefined) continue;
124
    const peerName = peer?.peer;
125
    if ((peerName !== "grok" && peerName !== "cursor") || peer.releaseEligible !== true) continue;
126
    const binary = object(peer.binary);
127
    const negotiation = object(peer.negotiation);
128
    const identity = object(negotiation?.peerIdentity);
129
    const peerVersion = string(binary?.classifiedVersion) ?? string(identity?.version);
130
    const executableSha256 = string(binary?.sha256);
131
    if (peerVersion === undefined || executableSha256 === undefined) continue;
132
    const installationClosureSha256 = string(binary?.installationClosureSha256);
133
    const artifactRef =
134
      "packages/agent-client-protocol-conformance/compatibility/release-matrix.json";
135
    const liveRecord = (suiteId: string): AcpConformanceEvidenceRecord => ({
136
      suiteId,
137
      kind: "live",
138
      result: "pass",
139
      peerVersion,
140
      executableSha256,
141
      ...(peerName === "cursor" && installationClosureSha256 !== undefined
142
        ? { installationClosureSha256 }
143
        : {}),
144
      platform: { os, arch },
145
      recordedAt,
146
      artifactRef,
147
    });
148
    compiled[peerName] = Object.freeze([
149
      ...fixtureSuites(peerName).map(
150
        (suiteId): AcpConformanceEvidenceRecord => ({
151
          suiteId,
152
          kind: "fixture",
153
          result: "pass",
154
          peerVersion,
155
          recordedAt,
156
          artifactRef,
157
        }),
158
      ),
159
      liveRecord("acp-release-matrix-v1"),
160
      ...featureSuites(peerName, peer).map(liveRecord),
161
    ]);
162
  }
163
164
  if (compiled.grok.length === 0 || compiled.cursor.length === 0)
165
    return {
166
      _tag: "ReleaseEvidenceUnavailable",
167
      diagnostics: ["checked release matrix did not compile both eligible peers"],
168
    };
169
  return {
170
    _tag: "ReleaseEvidenceReady",
171
    openAgentsRevision: revision,
172
    evidence: Object.freeze(compiled),
173
  };
174
};
175
176
export const checkedAcpReleaseEvidence = (
177
  options: Readonly<{ now?: Date; expectedOpenAgentsRevision?: string }> = {},
178
): AcpReleaseEvidenceCompilation => compileAcpReleaseEvidence(checkedReleaseMatrix, options);
packages/agent-client-protocol-conformance/src/release.ts deleted -451

@@ -1,451 +0,0 @@

1
export const ACP_RELEASE_CLAIM_STATES = [
2
  "supported",
3
  "experimental",
4
  "incompatible",
5
  "not-installed",
6
  "auth-required",
7
  "degraded",
8
] as const;
9
10
export const ACP_RELEASE_SCENARIO_RESULTS = [
11
  "live-pass",
12
  "fixture-pass",
13
  "blocked",
14
  "not-tested",
15
  "unsupported",
16
  "fail",
17
] as const;
18
19
export const ACP_RELEASE_SCENARIO_IDS = [
20
  "identity-version",
21
  "incompatible-version-rejection",
22
  "initialize",
23
  "auth-primary",
24
  "auth-secondary",
25
  "auth-cancel",
26
  "auth-expiry-failure",
27
  "auth-logout-reauth",
28
  "session-new",
29
  "session-list",
30
  "session-load",
31
  "session-resume-close-delete",
32
  "real-repo-text",
33
  "real-repo-tool-plan-config-usage",
34
  "permission-approval",
35
  "permission-refusal",
36
  "permission-timeout-stale-policy",
37
  "fs-terminal-enabled",
38
  "fs-terminal-disabled",
39
  "mcp-authorized",
40
  "mcp-expired-refusal",
41
  "mcp-no-durable-secret",
42
  "model-mode-config",
43
  "stream-cancel",
44
  "reverse-cancel",
45
  "crash-kill-restart",
46
  "malformed-unknown-output",
47
  "attachment-repair",
48
  "sequential-turns",
49
  "multiple-sessions",
50
  "cleanup-bounds",
51
  "fragmented-oversized",
52
  "stderr-update-flood",
53
  "queue-stall-timeout-race",
54
  "crash-loop-repeat",
55
  "secret-scan",
56
  "trust-controls",
57
  "grok-wire-launch",
58
  "grok-rich-stream",
59
  "grok-load-replay",
60
  "grok-question-extensions",
61
  "cursor-wire-launch",
62
  "cursor-login-lifecycle",
63
  "cursor-extensions-models",
64
  "cursor-load-unsupported",
65
  "desktop-clean-machine",
66
  "support-bundle",
67
] as const;
68
69
export const ACP_RELEASE_PROFILE_REVISIONS = Object.freeze({ grok: 1, cursor: 3 } as const);
70
71
export type AcpReleaseEvidenceClass =
72
  | "live-peer"
73
  | "optional-live-peer"
74
  | "packaged-desktop-live"
75
  | "hermetic-production"
76
  | "not-applicable";
77
78
const hermeticProductionScenarios = new Set<string>([
79
  "incompatible-version-rejection",
80
  "fs-terminal-disabled",
81
  "mcp-expired-refusal",
82
  "malformed-unknown-output",
83
  "fragmented-oversized",
84
  "stderr-update-flood",
85
  "queue-stall-timeout-race",
86
  "permission-timeout-stale-policy",
87
  "auth-expiry-failure",
88
  "trust-controls",
89
]);
90
const packagedDesktopScenarios = new Set<string>(["desktop-clean-machine", "support-bundle"]);
91
const grokOptionalScenarios = new Set<string>(["auth-secondary"]);
92
const grokNotApplicableScenarios = new Set<string>([
93
  "auth-logout-reauth",
94
  "session-resume-close-delete",
95
  "model-mode-config",
96
  "cursor-wire-launch",
97
  "cursor-login-lifecycle",
98
  "cursor-extensions-models",
99
  "cursor-load-unsupported",
100
]);
101
const cursorNotApplicableScenarios = new Set<string>([
102
  "auth-secondary",
103
  "auth-logout-reauth",
104
  "session-resume-close-delete",
105
  "fs-terminal-enabled",
106
  "grok-wire-launch",
107
  "grok-rich-stream",
108
  "grok-load-replay",
109
  "grok-question-extensions",
110
]);
111
112
export const acpReleaseEvidenceClass = (
113
  peer: "grok" | "cursor",
114
  scenario: string,
115
): AcpReleaseEvidenceClass => {
116
  const notApplicable = peer === "grok" ? grokNotApplicableScenarios : cursorNotApplicableScenarios;
117
  if (notApplicable.has(scenario)) return "not-applicable";
118
  if (peer === "grok" && grokOptionalScenarios.has(scenario)) return "optional-live-peer";
119
  if (hermeticProductionScenarios.has(scenario)) return "hermetic-production";
120
  if (packagedDesktopScenarios.has(scenario)) return "packaged-desktop-live";
121
  return "live-peer";
122
};
123
124
const evidenceSatisfies = (evidenceClass: AcpReleaseEvidenceClass, result: unknown): boolean =>
125
  evidenceClass === "optional-live-peer"
126
    ? true
127
    : evidenceClass === "not-applicable"
128
      ? result === "unsupported"
129
      : evidenceClass === "hermetic-production"
130
        ? result === "fixture-pass" || result === "live-pass"
131
        : result === "live-pass";
132
133
export type AcpReleaseClaimState = (typeof ACP_RELEASE_CLAIM_STATES)[number];
134
export type AcpReleaseScenarioResult = (typeof ACP_RELEASE_SCENARIO_RESULTS)[number];
135
136
export type AcpReleaseScenario = Readonly<{
137
  id: string;
138
  requiredForSupported: boolean;
139
  result: AcpReleaseScenarioResult;
140
  evidenceRefs: ReadonlyArray<string>;
141
  safeDetail: string;
142
}>;
143
144
export type AcpReleasePeer = Readonly<{
145
  peer: "grok" | "cursor";
146
  claimState: AcpReleaseClaimState;
147
  releaseEligible: boolean;
148
  scenarios: ReadonlyArray<AcpReleaseScenario>;
149
}>;
150
151
export type AcpReleaseMatrix = Readonly<{
152
  format: "openagents-acp-release-matrix-v1";
153
  protocol: "Agent Client Protocol";
154
  protocolExclusions: ReadonlyArray<"Agent Communication Protocol" | "A2A">;
155
  recordedAt: string;
156
  freshnessDays: number;
157
  peers: ReadonlyArray<AcpReleasePeer>;
158
}>;
159
160
export type AcpReleaseMatrixValidation = Readonly<{
161
  valid: boolean;
162
  errors: ReadonlyArray<string>;
163
  expiry?: AcpReleaseMatrixExpiry;
164
}>;
165
166
export type AcpReleaseMatrixExpiry =
167
  | Readonly<{
168
      _tag: "Fresh";
169
      recordedAt: string;
170
      freshnessDays: number;
171
      expiresAt: string;
172
      ageMs: number;
173
    }>
174
  | Readonly<{
175
      _tag: "Expired";
176
      recordedAt: string;
177
      freshnessDays: number;
178
      expiresAt: string;
179
      ageMs: number;
180
      overdueMs: number;
181
    }>;
182
183
export type AcpReleaseMatrixGate = "push" | "release";
184
185
const millisecondsPerDay = 86_400_000;
186
187
const formatDays = (milliseconds: number): string =>
188
  `${(milliseconds / millisecondsPerDay).toFixed(1)} days`;
189
190
export const describeAcpReleaseExpiry = (
191
  expiry: Extract<AcpReleaseMatrixExpiry, { _tag: "Expired" }>,
192
): string =>
193
  `matrix evidence recorded at ${expiry.recordedAt} is ${formatDays(expiry.ageMs)} old; freshness window is ${expiry.freshnessDays} days and expired ${formatDays(expiry.overdueMs)} ago. Refresh requires a qualifying live release run, its candidate artifact, and a human-reviewed compatibility/release-matrix.json update.`;
194
195
export const evaluateAcpReleaseMatrixGate = (
196
  validation: AcpReleaseMatrixValidation,
197
  gate: AcpReleaseMatrixGate,
198
): Readonly<{
199
  valid: boolean;
200
  errors: ReadonlyArray<string>;
201
  warning?: string;
202
}> => {
203
  const expiry = validation.expiry;
204
  const warning = expiry?._tag === "Expired" ? describeAcpReleaseExpiry(expiry) : undefined;
205
  const errors =
206
    gate === "release" && warning !== undefined
207
      ? [...validation.errors, warning]
208
      : validation.errors;
209
  return {
210
    valid: errors.length === 0,
211
    errors,
212
    ...(gate === "push" && warning !== undefined ? { warning } : {}),
213
  };
214
};
215
216
const object = (value: unknown): Record<string, unknown> | undefined =>
217
  value !== null && typeof value === "object" && !Array.isArray(value)
218
    ? (value as Record<string, unknown>)
219
    : undefined;
220
221
const strings = (value: unknown): ReadonlyArray<string> | undefined =>
222
  Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : undefined;
223
224
const nonEmptyString = (value: unknown): value is string =>
225
  typeof value === "string" && value.length > 0;
226
const sha256 = (value: unknown): value is string =>
227
  typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
228
const gitRevision = (value: unknown): value is string =>
229
  typeof value === "string" && /^[a-f0-9]{40}$/.test(value);
230
231
const containsExportedSecret = (value: unknown): boolean => {
232
  const encoded = JSON.stringify(value);
233
  return [
234
    /\/Users\//,
235
    /\/home\/[^"/]+\//,
236
    /Bearer\s+[A-Za-z0-9._~-]+/i,
237
    /(?:token|secret|api[_-]?key)=[^"\s]+/i,
238
    /(?:sk|xai)-[A-Za-z0-9_-]{12,}/,
239
    /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/,
240
  ].some((pattern) => pattern.test(encoded));
241
};
242
243
/**
244
 * Validates a checked ACP release matrix without trusting its claim booleans.
245
 * A fixture pass is useful evidence, but it can never satisfy a live release
246
 * requirement or promote a named peer by itself.
247
 */
248
export const validateAcpReleaseMatrix = (
249
  value: unknown,
250
  options: Readonly<{ now?: Date }> = {},
251
): AcpReleaseMatrixValidation => {
252
  const errors: string[] = [];
253
  const matrix = object(value);
254
  if (matrix === undefined) return { valid: false, errors: ["matrix must be an object"] };
255
  if (matrix.format !== "openagents-acp-release-matrix-v1") errors.push("unexpected format");
256
  if (matrix.protocol !== "Agent Client Protocol")
257
    errors.push("protocol must be Agent Client Protocol");
258
  const exclusions = strings(matrix.protocolExclusions);
259
  if (
260
    exclusions === undefined ||
261
    !exclusions.includes("Agent Communication Protocol") ||
262
    !exclusions.includes("A2A")
263
  )
264
    errors.push("protocol exclusions must name Agent Communication Protocol and A2A");
265
  const now = options.now ?? new Date();
266
  const nowMs = now.getTime();
267
  const recordedAtValue = typeof matrix.recordedAt === "string" ? matrix.recordedAt : undefined;
268
  const recordedAt = recordedAtValue === undefined ? NaN : Date.parse(recordedAtValue);
269
  const freshnessDays =
270
    typeof matrix.freshnessDays === "number" && Number.isFinite(matrix.freshnessDays)
271
      ? matrix.freshnessDays
272
      : NaN;
273
  let expiry: AcpReleaseMatrixExpiry | undefined;
274
  if (!Number.isFinite(recordedAt) || !Number.isFinite(freshnessDays) || freshnessDays <= 0)
275
    errors.push("matrix freshness metadata is invalid");
276
  else if (recordedAt - nowMs > 300_000) errors.push("matrix evidence timestamp is in the future");
277
  else {
278
    const ageMs = nowMs - recordedAt;
279
    const expiresAt = new Date(recordedAt + freshnessDays * millisecondsPerDay).toISOString();
280
    const recordedAtText = recordedAtValue;
281
    if (recordedAtText === undefined) {
282
      errors.push("matrix freshness metadata is invalid");
283
    } else {
284
      expiry =
285
        ageMs > freshnessDays * millisecondsPerDay
286
          ? {
287
              _tag: "Expired",
288
              recordedAt: recordedAtText,
289
              freshnessDays,
290
              expiresAt,
291
              ageMs,
292
              overdueMs: ageMs - freshnessDays * millisecondsPerDay,
293
            }
294
          : { _tag: "Fresh", recordedAt: recordedAtText, freshnessDays, expiresAt, ageMs };
295
    }
296
  }
297
298
  const openAgents = object(matrix.openAgents);
299
  if (openAgents === undefined) errors.push("OpenAgents release identity is required");
300
  else {
301
    if (!gitRevision(openAgents.revision))
302
      errors.push("OpenAgents revision must be a full Git SHA");
303
    if (!gitRevision(openAgents.desktopIntegrationRevision))
304
      errors.push("Desktop integration revision must be a full Git SHA");
305
    if (!nonEmptyString(openAgents.build)) errors.push("OpenAgents build identity is required");
306
    if (!nonEmptyString(openAgents.protocolPackageRevision))
307
      errors.push("protocol package revision is required");
308
    if (openAgents.schemaRelease !== "schema-v1.19.0")
309
      errors.push("schema release must be schema-v1.19.0");
310
    if (!sha256(openAgents.schemaSha256)) errors.push("schema SHA-256 is required");
311
  }
312
313
  const platform = object(matrix.platform);
314
  if (platform === undefined) errors.push("tested platform identity is required");
315
  else {
316
    if (!nonEmptyString(platform.tested) || !/^[a-z0-9]+-[a-z0-9_]+$/.test(platform.tested))
317
      errors.push("tested platform must be an os-architecture identifier");
318
    if (!nonEmptyString(platform.osVersion)) errors.push("tested OS version is required");
319
    if (!nonEmptyString(platform.nodeVersion)) errors.push("tested Node version is required");
320
    const notTested = strings(platform.notTested);
321
    if (notTested === undefined) errors.push("not-tested platforms must be explicit");
322
    else if (new Set(notTested).size !== notTested.length)
323
      errors.push("not-tested platforms must be unique");
324
    else if (notTested.includes(String(platform.tested)))
325
      errors.push("tested platform cannot also be not-tested");
326
  }
327
328
  const peers = Array.isArray(matrix.peers) ? matrix.peers : [];
329
  if (peers.length !== 2) errors.push("matrix must contain exactly Grok and Cursor");
330
  const peerNames = new Set<string>();
331
  let scenarioCatalog: ReadonlyArray<string> | undefined;
332
  for (const [peerIndex, rawPeer] of peers.entries()) {
333
    const peer = object(rawPeer);
334
    if (peer === undefined) {
335
      errors.push(`peer ${peerIndex} must be an object`);
336
      continue;
337
    }
338
    const peerName = typeof peer.peer === "string" ? peer.peer : `peer-${peerIndex}`;
339
    peerNames.add(peerName);
340
    if (peerName !== "grok" && peerName !== "cursor") errors.push(`unknown peer ${peerName}`);
341
    if (!(ACP_RELEASE_CLAIM_STATES as readonly unknown[]).includes(peer.claimState))
342
      errors.push(`${peerName}: invalid claim state`);
343
    const expectedProfile = peerName === "grok" ? "grok-cli" : "cursor-agent";
344
    const expectedProfileRevision =
345
      peerName === "grok" || peerName === "cursor"
346
        ? ACP_RELEASE_PROFILE_REVISIONS[peerName]
347
        : undefined;
348
    const profile = object(peer.profile);
349
    if (
350
      profile === undefined ||
351
      profile.id !== expectedProfile ||
352
      profile.revision !== expectedProfileRevision
353
    )
354
      errors.push(`${peerName}: exact trusted profile identity is required`);
355
    const binary = object(peer.binary);
356
    const expectedCommand = peerName === "grok" ? ["grok", "agent", "stdio"] : ["agent", "acp"];
357
    if (binary === undefined) errors.push(`${peerName}: pinned binary identity is required`);
358
    else {
359
      if (JSON.stringify(strings(binary.command)) !== JSON.stringify(expectedCommand))
360
        errors.push(`${peerName}: launch command does not match the trusted profile`);
361
      if (!nonEmptyString(binary.reportedVersion))
362
        errors.push(`${peerName}: reported version is required`);
363
      if (
364
        !nonEmptyString(binary.resolvedExecutableName) ||
365
        binary.resolvedExecutableName.includes("/") ||
366
        binary.resolvedExecutableName.includes("\\")
367
      )
368
        errors.push(`${peerName}: safe resolved executable name is required`);
369
      if (!sha256(binary.sha256)) errors.push(`${peerName}: executable SHA-256 is required`);
370
      if (peerName === "cursor" && !sha256(binary.installationClosureSha256))
371
        errors.push("cursor: installation closure SHA-256 is required");
372
      if (!nonEmptyString(binary.installationSource))
373
        errors.push(`${peerName}: installation source is required`);
374
    }
375
    const negotiation = object(peer.negotiation);
376
    if (negotiation === undefined) errors.push(`${peerName}: initialize evidence is required`);
377
    else {
378
      if (negotiation.wireVersion !== 1) errors.push(`${peerName}: wire version must be 1`);
379
      const identity = object(negotiation.peerIdentity);
380
      if (
381
        identity === undefined ||
382
        !nonEmptyString(identity.name) ||
383
        !nonEmptyString(identity.version)
384
      )
385
        errors.push(`${peerName}: peer initialize identity is required`);
386
      if (strings(negotiation.authMethodIds) === undefined)
387
        errors.push(`${peerName}: advertised auth methods are required`);
388
      if (strings(negotiation.advertisedCapabilityKeys) === undefined)
389
        errors.push(`${peerName}: advertised capabilities are required`);
390
    }
391
    const scenarios = Array.isArray(peer.scenarios) ? peer.scenarios : [];
392
    const ids: string[] = [];
393
    let allRequiredSatisfied = scenarios.length > 0;
394
    for (const [scenarioIndex, rawScenario] of scenarios.entries()) {
395
      const scenario = object(rawScenario);
396
      if (scenario === undefined) {
397
        errors.push(`${peerName}: scenario ${scenarioIndex} must be an object`);
398
        allRequiredSatisfied = false;
399
        continue;
400
      }
401
      const id = typeof scenario.id === "string" ? scenario.id : `scenario-${scenarioIndex}`;
402
      ids.push(id);
403
      const evidenceClass =
404
        peerName === "grok" || peerName === "cursor"
405
          ? acpReleaseEvidenceClass(peerName, id)
406
          : "live-peer";
407
      const expectedRequired =
408
        evidenceClass !== "not-applicable" && evidenceClass !== "optional-live-peer";
409
      if (scenario.requiredForSupported !== expectedRequired)
410
        errors.push(`${peerName}/${id}: requiredness does not match the code-owned catalog`);
411
      if (!(ACP_RELEASE_SCENARIO_RESULTS as readonly unknown[]).includes(scenario.result))
412
        errors.push(`${peerName}/${id}: invalid result`);
413
      if (!evidenceSatisfies(evidenceClass, scenario.result)) allRequiredSatisfied = false;
414
      const evidenceRefs = strings(scenario.evidenceRefs);
415
      if (evidenceRefs === undefined)
416
        errors.push(`${peerName}/${id}: evidenceRefs must be strings`);
417
      else if (
418
        evidenceRefs.some(
419
          (ref) =>
420
            ref.startsWith("/") ||
421
            ref.includes("..") ||
422
            ref.includes("\\") ||
423
            /^[a-z][a-z0-9+.-]*:/i.test(ref),
424
        )
425
      )
426
        errors.push(`${peerName}/${id}: evidence refs must be repository-relative`);
427
      else if (
428
        (scenario.result === "live-pass" || scenario.result === "fixture-pass") &&
429
        evidenceRefs.length === 0
430
      )
431
        errors.push(`${peerName}/${id}: passing evidence class requires evidence`);
432
      if (typeof scenario.safeDetail !== "string" || scenario.safeDetail.length === 0)
433
        errors.push(`${peerName}/${id}: safeDetail is required`);
434
    }
435
    if (new Set(ids).size !== ids.length) errors.push(`${peerName}: scenario ids must be unique`);
436
    if (JSON.stringify(ids.toSorted()) !== JSON.stringify([...ACP_RELEASE_SCENARIO_IDS].toSorted()))
437
      errors.push(`${peerName}: scenario catalog is incomplete or unknown`);
438
    if (scenarioCatalog === undefined) scenarioCatalog = ids.toSorted();
439
    else if (JSON.stringify(scenarioCatalog) !== JSON.stringify(ids.toSorted()))
440
      errors.push("Grok and Cursor must use the same release scenario catalog");
441
    if (peer.releaseEligible !== allRequiredSatisfied)
442
      errors.push(`${peerName}: releaseEligible does not match code-owned evidence requirements`);
443
    if (peer.claimState === "supported" && !allRequiredSatisfied)
444
      errors.push(`${peerName}: supported claim lacks required evidence`);
445
  }
446
  if (!peerNames.has("grok") || !peerNames.has("cursor"))
447
    errors.push("matrix must independently identify Grok and Cursor");
448
  if (containsExportedSecret(matrix))
449
    errors.push("matrix contains secret-shaped or host-private data");
450
  return { valid: errors.length === 0, errors, ...(expiry === undefined ? {} : { expiry }) };
451
};

This page updates live while a promote is in flight · changelog