deepdebug-local-agent 1.9.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +5 -0
  3. package/CLAUDE.md +1 -1
  4. package/docs/examples/agent2-runner/docker-compose.yml +53 -0
  5. package/docs/la-agent2-runner.md +115 -0
  6. package/docs/la-jobs-and-llm.md +62 -0
  7. package/docs/la-protocol-v2.md +7 -5
  8. package/env.example +12 -0
  9. package/package.json +1 -1
  10. package/src/la-protocol-v2/content-handlers/install.js +27 -1
  11. package/src/la-protocol-v2/contract/CONTRACT_SOURCE.json +10 -6
  12. package/src/la-protocol-v2/contract/README.md +75 -2
  13. package/src/la-protocol-v2/contract/envelope.schema.json +3 -1
  14. package/src/la-protocol-v2/contract/index.json +18 -2
  15. package/src/la-protocol-v2/contract/job.assign.schema.json +31 -0
  16. package/src/la-protocol-v2/contract/policy.check.schema.json +97 -0
  17. package/src/la-protocol-v2/contract/policy.decision.schema.json +119 -0
  18. package/src/la-protocol-v2/jobs/agent2/api-client.js +150 -0
  19. package/src/la-protocol-v2/jobs/agent2/approvals.js +114 -0
  20. package/src/la-protocol-v2/jobs/agent2/bridge.js +299 -0
  21. package/src/la-protocol-v2/jobs/agent2/config.js +128 -0
  22. package/src/la-protocol-v2/jobs/agent2/frames.js +61 -0
  23. package/src/la-protocol-v2/jobs/agent2/policy-check.js +170 -0
  24. package/src/la-protocol-v2/jobs/agent2/runner.js +258 -0
  25. package/src/la-protocol-v2/jobs/agent2/supervisor.js +269 -0
  26. package/src/la-protocol-v2/jobs/config.js +60 -0
  27. package/src/la-protocol-v2/jobs/events.js +106 -0
  28. package/src/la-protocol-v2/jobs/install.js +43 -0
  29. package/src/la-protocol-v2/jobs/manager.js +281 -0
  30. package/src/la-protocol-v2/jobs/options.js +56 -0
  31. package/src/la-protocol-v2/jobs/smoke-runner.js +39 -0
  32. package/src/la-protocol-v2/llm/client.js +432 -0
  33. package/src/la-protocol-v2/llm/config.js +63 -0
  34. package/src/la-protocol-v2/llm/install.js +17 -0
  35. package/src/la-protocol-v2/llm-key/store.js +10 -0
  36. package/src/la-protocol-v2/runtime.js +69 -3
  37. package/src/server.js +4 -0
  38. package/src/utils/approval-token.js +3 -2
  39. package/test/contract/la-protocol-v2/vectors/job.assign.vectors.json +1538 -0
  40. package/test/contract/la-protocol-v2/vectors/policy.check.vectors.json +908 -0
  41. package/test/contract/la-protocol-v2/vectors/policy.decision.vectors.json +826 -0
  42. package/test/la-protocol-v2/agent2-approval-discovery.test.js +114 -0
  43. package/test/la-protocol-v2/agent2-config.test.js +103 -0
  44. package/test/la-protocol-v2/agent2-orphan.test.js +118 -0
  45. package/test/la-protocol-v2/agent2-policy-check.test.js +273 -0
  46. package/test/la-protocol-v2/agent2-real-e2e.test.js +89 -0
  47. package/test/la-protocol-v2/agent2-runner.test.js +510 -0
  48. package/test/la-protocol-v2/agent2-supervisor.test.js +185 -0
  49. package/test/la-protocol-v2/agent2-workspace-door.test.js +142 -0
  50. package/test/la-protocol-v2/agent2-workspace-real-server.test.js +137 -0
  51. package/test/la-protocol-v2/contract-v21.test.js +2 -2
  52. package/test/la-protocol-v2/contract.test.js +8 -7
  53. package/test/la-protocol-v2/helpers/agent2-rig.js +96 -0
  54. package/test/la-protocol-v2/helpers/fake-agent2-cli.js +22 -0
  55. package/test/la-protocol-v2/helpers/fake-agent2.js +280 -0
  56. package/test/la-protocol-v2/helpers/fake-la-api.js +29 -0
  57. package/test/la-protocol-v2/helpers/fake-llm.js +75 -0
  58. package/test/la-protocol-v2/helpers/reference-cp.js +6 -3
  59. package/test/la-protocol-v2/helpers/spawn-agent.js +4 -3
  60. package/test/la-protocol-v2/helpers/supervisor-exit-script.js +15 -0
  61. package/test/la-protocol-v2/jobs-e2e.test.js +405 -0
  62. package/test/la-protocol-v2/jobs-manager.test.js +370 -0
  63. package/test/la-protocol-v2/jobs-options.test.js +288 -0
  64. package/test/la-protocol-v2/llm-client.test.js +380 -0
  65. package/test/la-protocol-v2/llm-messages.test.js +132 -0
@@ -0,0 +1,908 @@
1
+ {
2
+ "type": "policy.check",
3
+ "schema": "policy.check.schema.json",
4
+ "vectors": [
5
+ {
6
+ "name": "full-valid",
7
+ "expect": {
8
+ "valid": true
9
+ },
10
+ "message": {
11
+ "schemaVersion": 2,
12
+ "type": "policy.check",
13
+ "msgId": "00000000-0000-4000-8000-000000000001",
14
+ "seq": 1,
15
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
16
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
17
+ "workspaceId": "ws-1",
18
+ "ts": "2026-11-04T10:00:00Z",
19
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
20
+ "payload": {
21
+ "actionType": "APPLY_PATCH",
22
+ "toolName": "mcp.apply-patch",
23
+ "requestHash": "abababababababababababababababababababababababababababababababab",
24
+ "repoRefs": [
25
+ {
26
+ "provider": "github",
27
+ "org": "acme",
28
+ "repo": "billing"
29
+ }
30
+ ],
31
+ "incidentId": "inc-8c8deab3",
32
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
33
+ "modelAlias": "vh-smart"
34
+ }
35
+ }
36
+ },
37
+ {
38
+ "name": "minimal-valid",
39
+ "why": "the two required fields only: no repo, no incident, no tool name",
40
+ "expect": {
41
+ "valid": true
42
+ },
43
+ "message": {
44
+ "schemaVersion": 2,
45
+ "type": "policy.check",
46
+ "msgId": "00000000-0000-4000-8000-000000000001",
47
+ "seq": 1,
48
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
49
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
50
+ "workspaceId": "ws-1",
51
+ "ts": "2026-11-04T10:00:00Z",
52
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
53
+ "payload": {
54
+ "actionType": "RUN_SHELL_SAFE",
55
+ "requestHash": "abababababababababababababababababababababababababababababababab"
56
+ }
57
+ }
58
+ },
59
+ {
60
+ "name": "several-repos-valid",
61
+ "why": "a multi-repo publish names every repository it touches",
62
+ "expect": {
63
+ "valid": true
64
+ },
65
+ "message": {
66
+ "schemaVersion": 2,
67
+ "type": "policy.check",
68
+ "msgId": "00000000-0000-4000-8000-000000000001",
69
+ "seq": 1,
70
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
71
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
72
+ "workspaceId": "ws-1",
73
+ "ts": "2026-11-04T10:00:00Z",
74
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
75
+ "payload": {
76
+ "actionType": "APPLY_PATCH",
77
+ "toolName": "mcp.apply-patch",
78
+ "requestHash": "abababababababababababababababababababababababababababababababab",
79
+ "repoRefs": [
80
+ {
81
+ "provider": "github",
82
+ "org": "acme",
83
+ "repo": "billing"
84
+ },
85
+ {
86
+ "provider": "gitlab",
87
+ "org": "acme",
88
+ "repo": "web"
89
+ },
90
+ {
91
+ "provider": "other",
92
+ "org": "acme",
93
+ "repo": "docs"
94
+ }
95
+ ],
96
+ "incidentId": "inc-8c8deab3",
97
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
98
+ "modelAlias": "vh-smart"
99
+ }
100
+ }
101
+ },
102
+ {
103
+ "name": "empty-workspace-valid",
104
+ "why": "workspaceId may be empty (envelope rule); the CP then denies it as workspace_unknown, the frame itself is valid",
105
+ "expect": {
106
+ "valid": true
107
+ },
108
+ "message": {
109
+ "schemaVersion": 2,
110
+ "type": "policy.check",
111
+ "msgId": "00000000-0000-4000-8000-000000000001",
112
+ "seq": 1,
113
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
114
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
115
+ "workspaceId": "",
116
+ "ts": "2026-11-04T10:00:00Z",
117
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
118
+ "payload": {
119
+ "actionType": "APPLY_PATCH",
120
+ "toolName": "mcp.apply-patch",
121
+ "requestHash": "abababababababababababababababababababababababababababababababab",
122
+ "repoRefs": [
123
+ {
124
+ "provider": "github",
125
+ "org": "acme",
126
+ "repo": "billing"
127
+ }
128
+ ],
129
+ "incidentId": "inc-8c8deab3",
130
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
131
+ "modelAlias": "vh-smart"
132
+ }
133
+ }
134
+ },
135
+ {
136
+ "name": "opaque-ids-valid",
137
+ "expect": {
138
+ "valid": true
139
+ },
140
+ "message": {
141
+ "schemaVersion": 2,
142
+ "type": "policy.check",
143
+ "msgId": "00000000-0000-4000-8000-000000000001",
144
+ "seq": 1,
145
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
146
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
147
+ "workspaceId": "ws-1",
148
+ "ts": "2026-11-04T10:00:00Z",
149
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
150
+ "payload": {
151
+ "actionType": "OPEN_PR",
152
+ "toolName": "github_open_pr",
153
+ "requestHash": "0000000000000000000000000000000000000000000000000000000000000000",
154
+ "incidentId": "8c8deab3",
155
+ "modelAlias": "vh-coder"
156
+ }
157
+ }
158
+ },
159
+ {
160
+ "name": "tenant-id-in-payload",
161
+ "why": "the tenant comes from the authenticated session, never from the payload",
162
+ "expect": {
163
+ "valid": false,
164
+ "code": "schema_violation",
165
+ "keyword": "additionalProperties"
166
+ },
167
+ "message": {
168
+ "schemaVersion": 2,
169
+ "type": "policy.check",
170
+ "msgId": "00000000-0000-4000-8000-000000000001",
171
+ "seq": 1,
172
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
173
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
174
+ "workspaceId": "ws-1",
175
+ "ts": "2026-11-04T10:00:00Z",
176
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
177
+ "payload": {
178
+ "actionType": "APPLY_PATCH",
179
+ "toolName": "mcp.apply-patch",
180
+ "requestHash": "abababababababababababababababababababababababababababababababab",
181
+ "repoRefs": [
182
+ {
183
+ "provider": "github",
184
+ "org": "acme",
185
+ "repo": "billing"
186
+ }
187
+ ],
188
+ "incidentId": "inc-8c8deab3",
189
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
190
+ "modelAlias": "vh-smart",
191
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f"
192
+ }
193
+ }
194
+ },
195
+ {
196
+ "name": "execution-origin-in-payload",
197
+ "why": "the execution origin is derived by the CP from the session; an LA cannot claim it",
198
+ "expect": {
199
+ "valid": false,
200
+ "code": "schema_violation",
201
+ "keyword": "additionalProperties"
202
+ },
203
+ "message": {
204
+ "schemaVersion": 2,
205
+ "type": "policy.check",
206
+ "msgId": "00000000-0000-4000-8000-000000000001",
207
+ "seq": 1,
208
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
209
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
210
+ "workspaceId": "ws-1",
211
+ "ts": "2026-11-04T10:00:00Z",
212
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
213
+ "payload": {
214
+ "actionType": "APPLY_PATCH",
215
+ "toolName": "mcp.apply-patch",
216
+ "requestHash": "abababababababababababababababababababababababababababababababab",
217
+ "repoRefs": [
218
+ {
219
+ "provider": "github",
220
+ "org": "acme",
221
+ "repo": "billing"
222
+ }
223
+ ],
224
+ "incidentId": "inc-8c8deab3",
225
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
226
+ "modelAlias": "vh-smart",
227
+ "executionOrigin": "local-agent"
228
+ }
229
+ }
230
+ },
231
+ {
232
+ "name": "agent-id-in-payload",
233
+ "why": "the agent comes from the session",
234
+ "expect": {
235
+ "valid": false,
236
+ "code": "schema_violation",
237
+ "keyword": "additionalProperties"
238
+ },
239
+ "message": {
240
+ "schemaVersion": 2,
241
+ "type": "policy.check",
242
+ "msgId": "00000000-0000-4000-8000-000000000001",
243
+ "seq": 1,
244
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
245
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
246
+ "workspaceId": "ws-1",
247
+ "ts": "2026-11-04T10:00:00Z",
248
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
249
+ "payload": {
250
+ "actionType": "APPLY_PATCH",
251
+ "toolName": "mcp.apply-patch",
252
+ "requestHash": "abababababababababababababababababababababababababababababababab",
253
+ "repoRefs": [
254
+ {
255
+ "provider": "github",
256
+ "org": "acme",
257
+ "repo": "billing"
258
+ }
259
+ ],
260
+ "incidentId": "inc-8c8deab3",
261
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
262
+ "modelAlias": "vh-smart",
263
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
264
+ }
265
+ }
266
+ },
267
+ {
268
+ "name": "file-paths-in-payload",
269
+ "why": "no paths and no content: the file scope never leaves the customer",
270
+ "expect": {
271
+ "valid": false,
272
+ "code": "schema_violation",
273
+ "keyword": "additionalProperties"
274
+ },
275
+ "message": {
276
+ "schemaVersion": 2,
277
+ "type": "policy.check",
278
+ "msgId": "00000000-0000-4000-8000-000000000001",
279
+ "seq": 1,
280
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
281
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
282
+ "workspaceId": "ws-1",
283
+ "ts": "2026-11-04T10:00:00Z",
284
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
285
+ "payload": {
286
+ "actionType": "APPLY_PATCH",
287
+ "toolName": "mcp.apply-patch",
288
+ "requestHash": "abababababababababababababababababababababababababababababababab",
289
+ "repoRefs": [
290
+ {
291
+ "provider": "github",
292
+ "org": "acme",
293
+ "repo": "billing"
294
+ }
295
+ ],
296
+ "incidentId": "inc-8c8deab3",
297
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
298
+ "modelAlias": "vh-smart",
299
+ "diffFiles": [
300
+ "src/main/App.java"
301
+ ]
302
+ }
303
+ }
304
+ },
305
+ {
306
+ "name": "diff-content-in-payload",
307
+ "why": "no diff, no command text, no content of any kind",
308
+ "expect": {
309
+ "valid": false,
310
+ "code": "schema_violation",
311
+ "keyword": "additionalProperties"
312
+ },
313
+ "message": {
314
+ "schemaVersion": 2,
315
+ "type": "policy.check",
316
+ "msgId": "00000000-0000-4000-8000-000000000001",
317
+ "seq": 1,
318
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
319
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
320
+ "workspaceId": "ws-1",
321
+ "ts": "2026-11-04T10:00:00Z",
322
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
323
+ "payload": {
324
+ "actionType": "APPLY_PATCH",
325
+ "toolName": "mcp.apply-patch",
326
+ "requestHash": "abababababababababababababababababababababababababababababababab",
327
+ "repoRefs": [
328
+ {
329
+ "provider": "github",
330
+ "org": "acme",
331
+ "repo": "billing"
332
+ }
333
+ ],
334
+ "incidentId": "inc-8c8deab3",
335
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
336
+ "modelAlias": "vh-smart",
337
+ "command": "rm -rf /"
338
+ }
339
+ }
340
+ },
341
+ {
342
+ "name": "repo-url-with-credentials",
343
+ "why": "a repository is {provider, org, repo}; a URL (which could carry a token) is not a field",
344
+ "expect": {
345
+ "valid": false,
346
+ "code": "schema_violation",
347
+ "keyword": "additionalProperties"
348
+ },
349
+ "message": {
350
+ "schemaVersion": 2,
351
+ "type": "policy.check",
352
+ "msgId": "00000000-0000-4000-8000-000000000001",
353
+ "seq": 1,
354
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
355
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
356
+ "workspaceId": "ws-1",
357
+ "ts": "2026-11-04T10:00:00Z",
358
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
359
+ "payload": {
360
+ "actionType": "APPLY_PATCH",
361
+ "toolName": "mcp.apply-patch",
362
+ "requestHash": "abababababababababababababababababababababababababababababababab",
363
+ "repoRefs": [
364
+ {
365
+ "provider": "github",
366
+ "org": "acme",
367
+ "repo": "billing",
368
+ "url": "https://x:tok@github.com/acme/billing.git"
369
+ }
370
+ ],
371
+ "incidentId": "inc-8c8deab3",
372
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
373
+ "modelAlias": "vh-smart"
374
+ }
375
+ }
376
+ },
377
+ {
378
+ "name": "repo-extra-branch",
379
+ "why": "the repo ref of a check has no branch (it is not needed to decide)",
380
+ "expect": {
381
+ "valid": false,
382
+ "code": "schema_violation",
383
+ "keyword": "additionalProperties"
384
+ },
385
+ "message": {
386
+ "schemaVersion": 2,
387
+ "type": "policy.check",
388
+ "msgId": "00000000-0000-4000-8000-000000000001",
389
+ "seq": 1,
390
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
391
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
392
+ "workspaceId": "ws-1",
393
+ "ts": "2026-11-04T10:00:00Z",
394
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
395
+ "payload": {
396
+ "actionType": "APPLY_PATCH",
397
+ "toolName": "mcp.apply-patch",
398
+ "requestHash": "abababababababababababababababababababababababababababababababab",
399
+ "repoRefs": [
400
+ {
401
+ "provider": "github",
402
+ "org": "acme",
403
+ "repo": "billing",
404
+ "branch": "main"
405
+ }
406
+ ],
407
+ "incidentId": "inc-8c8deab3",
408
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
409
+ "modelAlias": "vh-smart"
410
+ }
411
+ }
412
+ },
413
+ {
414
+ "name": "missing-request-hash",
415
+ "why": "the hash ties the decision (and a later approval) to this exact request",
416
+ "expect": {
417
+ "valid": false,
418
+ "code": "schema_violation",
419
+ "keyword": "required"
420
+ },
421
+ "message": {
422
+ "schemaVersion": 2,
423
+ "type": "policy.check",
424
+ "msgId": "00000000-0000-4000-8000-000000000001",
425
+ "seq": 1,
426
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
427
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
428
+ "workspaceId": "ws-1",
429
+ "ts": "2026-11-04T10:00:00Z",
430
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
431
+ "payload": {
432
+ "actionType": "APPLY_PATCH",
433
+ "toolName": "mcp.apply-patch",
434
+ "repoRefs": [
435
+ {
436
+ "provider": "github",
437
+ "org": "acme",
438
+ "repo": "billing"
439
+ }
440
+ ],
441
+ "incidentId": "inc-8c8deab3",
442
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
443
+ "modelAlias": "vh-smart"
444
+ }
445
+ }
446
+ },
447
+ {
448
+ "name": "request-hash-not-sha256",
449
+ "why": "requestHash is 64 lower-case hex",
450
+ "expect": {
451
+ "valid": false,
452
+ "code": "schema_violation",
453
+ "keyword": "pattern"
454
+ },
455
+ "message": {
456
+ "schemaVersion": 2,
457
+ "type": "policy.check",
458
+ "msgId": "00000000-0000-4000-8000-000000000001",
459
+ "seq": 1,
460
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
461
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
462
+ "workspaceId": "ws-1",
463
+ "ts": "2026-11-04T10:00:00Z",
464
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
465
+ "payload": {
466
+ "actionType": "APPLY_PATCH",
467
+ "toolName": "mcp.apply-patch",
468
+ "requestHash": "ABCDEF",
469
+ "repoRefs": [
470
+ {
471
+ "provider": "github",
472
+ "org": "acme",
473
+ "repo": "billing"
474
+ }
475
+ ],
476
+ "incidentId": "inc-8c8deab3",
477
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
478
+ "modelAlias": "vh-smart"
479
+ }
480
+ }
481
+ },
482
+ {
483
+ "name": "missing-action-type",
484
+ "why": "actionType is required",
485
+ "expect": {
486
+ "valid": false,
487
+ "code": "schema_violation",
488
+ "keyword": "required"
489
+ },
490
+ "message": {
491
+ "schemaVersion": 2,
492
+ "type": "policy.check",
493
+ "msgId": "00000000-0000-4000-8000-000000000001",
494
+ "seq": 1,
495
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
496
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
497
+ "workspaceId": "ws-1",
498
+ "ts": "2026-11-04T10:00:00Z",
499
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
500
+ "payload": {
501
+ "toolName": "mcp.apply-patch",
502
+ "requestHash": "abababababababababababababababababababababababababababababababab",
503
+ "repoRefs": [
504
+ {
505
+ "provider": "github",
506
+ "org": "acme",
507
+ "repo": "billing"
508
+ }
509
+ ],
510
+ "incidentId": "inc-8c8deab3",
511
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
512
+ "modelAlias": "vh-smart"
513
+ }
514
+ }
515
+ },
516
+ {
517
+ "name": "action-type-with-space",
518
+ "why": "actionType is a short id: no space, no shell character",
519
+ "expect": {
520
+ "valid": false,
521
+ "code": "schema_violation",
522
+ "keyword": "pattern"
523
+ },
524
+ "message": {
525
+ "schemaVersion": 2,
526
+ "type": "policy.check",
527
+ "msgId": "00000000-0000-4000-8000-000000000001",
528
+ "seq": 1,
529
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
530
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
531
+ "workspaceId": "ws-1",
532
+ "ts": "2026-11-04T10:00:00Z",
533
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
534
+ "payload": {
535
+ "actionType": "apply patch; rm",
536
+ "toolName": "mcp.apply-patch",
537
+ "requestHash": "abababababababababababababababababababababababababababababababab",
538
+ "repoRefs": [
539
+ {
540
+ "provider": "github",
541
+ "org": "acme",
542
+ "repo": "billing"
543
+ }
544
+ ],
545
+ "incidentId": "inc-8c8deab3",
546
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
547
+ "modelAlias": "vh-smart"
548
+ }
549
+ }
550
+ },
551
+ {
552
+ "name": "repo-refs-empty",
553
+ "why": "repoRefs, when present, names at least one repository",
554
+ "expect": {
555
+ "valid": false,
556
+ "code": "schema_violation",
557
+ "keyword": "minItems"
558
+ },
559
+ "message": {
560
+ "schemaVersion": 2,
561
+ "type": "policy.check",
562
+ "msgId": "00000000-0000-4000-8000-000000000001",
563
+ "seq": 1,
564
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
565
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
566
+ "workspaceId": "ws-1",
567
+ "ts": "2026-11-04T10:00:00Z",
568
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
569
+ "payload": {
570
+ "actionType": "APPLY_PATCH",
571
+ "toolName": "mcp.apply-patch",
572
+ "requestHash": "abababababababababababababababababababababababababababababababab",
573
+ "repoRefs": [],
574
+ "incidentId": "inc-8c8deab3",
575
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
576
+ "modelAlias": "vh-smart"
577
+ }
578
+ }
579
+ },
580
+ {
581
+ "name": "repo-refs-too-many",
582
+ "why": "at most 8 repositories",
583
+ "expect": {
584
+ "valid": false,
585
+ "code": "schema_violation",
586
+ "keyword": "maxItems"
587
+ },
588
+ "message": {
589
+ "schemaVersion": 2,
590
+ "type": "policy.check",
591
+ "msgId": "00000000-0000-4000-8000-000000000001",
592
+ "seq": 1,
593
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
594
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
595
+ "workspaceId": "ws-1",
596
+ "ts": "2026-11-04T10:00:00Z",
597
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
598
+ "payload": {
599
+ "actionType": "APPLY_PATCH",
600
+ "toolName": "mcp.apply-patch",
601
+ "requestHash": "abababababababababababababababababababababababababababababababab",
602
+ "repoRefs": [
603
+ {
604
+ "provider": "github",
605
+ "org": "acme",
606
+ "repo": "r0"
607
+ },
608
+ {
609
+ "provider": "github",
610
+ "org": "acme",
611
+ "repo": "r1"
612
+ },
613
+ {
614
+ "provider": "github",
615
+ "org": "acme",
616
+ "repo": "r2"
617
+ },
618
+ {
619
+ "provider": "github",
620
+ "org": "acme",
621
+ "repo": "r3"
622
+ },
623
+ {
624
+ "provider": "github",
625
+ "org": "acme",
626
+ "repo": "r4"
627
+ },
628
+ {
629
+ "provider": "github",
630
+ "org": "acme",
631
+ "repo": "r5"
632
+ },
633
+ {
634
+ "provider": "github",
635
+ "org": "acme",
636
+ "repo": "r6"
637
+ },
638
+ {
639
+ "provider": "github",
640
+ "org": "acme",
641
+ "repo": "r7"
642
+ },
643
+ {
644
+ "provider": "github",
645
+ "org": "acme",
646
+ "repo": "r8"
647
+ }
648
+ ],
649
+ "incidentId": "inc-8c8deab3",
650
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
651
+ "modelAlias": "vh-smart"
652
+ }
653
+ }
654
+ },
655
+ {
656
+ "name": "provider-unknown",
657
+ "why": "provider is a closed list",
658
+ "expect": {
659
+ "valid": false,
660
+ "code": "schema_violation",
661
+ "keyword": "enum"
662
+ },
663
+ "message": {
664
+ "schemaVersion": 2,
665
+ "type": "policy.check",
666
+ "msgId": "00000000-0000-4000-8000-000000000001",
667
+ "seq": 1,
668
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
669
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
670
+ "workspaceId": "ws-1",
671
+ "ts": "2026-11-04T10:00:00Z",
672
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
673
+ "payload": {
674
+ "actionType": "APPLY_PATCH",
675
+ "toolName": "mcp.apply-patch",
676
+ "requestHash": "abababababababababababababababababababababababababababababababab",
677
+ "repoRefs": [
678
+ {
679
+ "provider": "svn",
680
+ "org": "acme",
681
+ "repo": "billing"
682
+ }
683
+ ],
684
+ "incidentId": "inc-8c8deab3",
685
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
686
+ "modelAlias": "vh-smart"
687
+ }
688
+ }
689
+ },
690
+ {
691
+ "name": "job-id-not-uuid",
692
+ "why": "jobId is the UUID of the job",
693
+ "expect": {
694
+ "valid": false,
695
+ "code": "schema_violation",
696
+ "keyword": "pattern"
697
+ },
698
+ "message": {
699
+ "schemaVersion": 2,
700
+ "type": "policy.check",
701
+ "msgId": "00000000-0000-4000-8000-000000000001",
702
+ "seq": 1,
703
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
704
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
705
+ "workspaceId": "ws-1",
706
+ "ts": "2026-11-04T10:00:00Z",
707
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
708
+ "payload": {
709
+ "actionType": "APPLY_PATCH",
710
+ "toolName": "mcp.apply-patch",
711
+ "requestHash": "abababababababababababababababababababababababababababababababab",
712
+ "repoRefs": [
713
+ {
714
+ "provider": "github",
715
+ "org": "acme",
716
+ "repo": "billing"
717
+ }
718
+ ],
719
+ "incidentId": "inc-8c8deab3",
720
+ "jobId": "job-1",
721
+ "modelAlias": "vh-smart"
722
+ }
723
+ }
724
+ },
725
+ {
726
+ "name": "missing-request-id",
727
+ "why": "the envelope requestId correlates the decision",
728
+ "expect": {
729
+ "valid": false,
730
+ "code": "schema_violation",
731
+ "keyword": "required"
732
+ },
733
+ "message": {
734
+ "schemaVersion": 2,
735
+ "type": "policy.check",
736
+ "msgId": "00000000-0000-4000-8000-000000000001",
737
+ "seq": 1,
738
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
739
+ "workspaceId": "ws-1",
740
+ "ts": "2026-11-04T10:00:00Z",
741
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
742
+ "payload": {
743
+ "actionType": "APPLY_PATCH",
744
+ "toolName": "mcp.apply-patch",
745
+ "requestHash": "abababababababababababababababababababababababababababababababab",
746
+ "repoRefs": [
747
+ {
748
+ "provider": "github",
749
+ "org": "acme",
750
+ "repo": "billing"
751
+ }
752
+ ],
753
+ "incidentId": "inc-8c8deab3",
754
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
755
+ "modelAlias": "vh-smart"
756
+ }
757
+ }
758
+ },
759
+ {
760
+ "name": "request-id-not-uuid",
761
+ "why": "requestId is a UUID",
762
+ "expect": {
763
+ "valid": false,
764
+ "code": "schema_violation",
765
+ "keyword": "pattern"
766
+ },
767
+ "message": {
768
+ "schemaVersion": 2,
769
+ "type": "policy.check",
770
+ "msgId": "00000000-0000-4000-8000-000000000001",
771
+ "seq": 1,
772
+ "requestId": "req-1",
773
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
774
+ "workspaceId": "ws-1",
775
+ "ts": "2026-11-04T10:00:00Z",
776
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
777
+ "payload": {
778
+ "actionType": "APPLY_PATCH",
779
+ "toolName": "mcp.apply-patch",
780
+ "requestHash": "abababababababababababababababababababababababababababababababab",
781
+ "repoRefs": [
782
+ {
783
+ "provider": "github",
784
+ "org": "acme",
785
+ "repo": "billing"
786
+ }
787
+ ],
788
+ "incidentId": "inc-8c8deab3",
789
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
790
+ "modelAlias": "vh-smart"
791
+ }
792
+ }
793
+ },
794
+ {
795
+ "name": "missing-agent-id",
796
+ "why": "an LA->CP frame carries its agentId",
797
+ "expect": {
798
+ "valid": false,
799
+ "code": "schema_violation",
800
+ "keyword": "required"
801
+ },
802
+ "message": {
803
+ "schemaVersion": 2,
804
+ "type": "policy.check",
805
+ "msgId": "00000000-0000-4000-8000-000000000001",
806
+ "seq": 1,
807
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
808
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
809
+ "workspaceId": "ws-1",
810
+ "ts": "2026-11-04T10:00:00Z",
811
+ "payload": {
812
+ "actionType": "APPLY_PATCH",
813
+ "toolName": "mcp.apply-patch",
814
+ "requestHash": "abababababababababababababababababababababababababababababababab",
815
+ "repoRefs": [
816
+ {
817
+ "provider": "github",
818
+ "org": "acme",
819
+ "repo": "billing"
820
+ }
821
+ ],
822
+ "incidentId": "inc-8c8deab3",
823
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
824
+ "modelAlias": "vh-smart"
825
+ }
826
+ }
827
+ },
828
+ {
829
+ "name": "extra-top-level-field",
830
+ "why": "envelope is closed",
831
+ "expect": {
832
+ "valid": false,
833
+ "code": "schema_violation",
834
+ "keyword": "additionalProperties"
835
+ },
836
+ "message": {
837
+ "schemaVersion": 2,
838
+ "type": "policy.check",
839
+ "msgId": "00000000-0000-4000-8000-000000000001",
840
+ "seq": 1,
841
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
842
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
843
+ "workspaceId": "ws-1",
844
+ "ts": "2026-11-04T10:00:00Z",
845
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
846
+ "payload": {
847
+ "actionType": "APPLY_PATCH",
848
+ "toolName": "mcp.apply-patch",
849
+ "requestHash": "abababababababababababababababababababababababababababababababab",
850
+ "repoRefs": [
851
+ {
852
+ "provider": "github",
853
+ "org": "acme",
854
+ "repo": "billing"
855
+ }
856
+ ],
857
+ "incidentId": "inc-8c8deab3",
858
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
859
+ "modelAlias": "vh-smart"
860
+ },
861
+ "extra": "x"
862
+ }
863
+ },
864
+ {
865
+ "name": "signed-by-the-agent",
866
+ "why": "LA->CP frames are not signed (the session authenticates them): sig and paramsRaw are forbidden",
867
+ "expect": {
868
+ "valid": false,
869
+ "code": "schema_violation"
870
+ },
871
+ "message": {
872
+ "schemaVersion": 2,
873
+ "type": "policy.check",
874
+ "msgId": "00000000-0000-4000-8000-000000000001",
875
+ "seq": 1,
876
+ "requestId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
877
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
878
+ "workspaceId": "ws-1",
879
+ "ts": "2026-11-04T10:00:00Z",
880
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
881
+ "payload": {
882
+ "actionType": "APPLY_PATCH",
883
+ "toolName": "mcp.apply-patch",
884
+ "requestHash": "abababababababababababababababababababababababababababababababab",
885
+ "repoRefs": [
886
+ {
887
+ "provider": "github",
888
+ "org": "acme",
889
+ "repo": "billing"
890
+ }
891
+ ],
892
+ "incidentId": "inc-8c8deab3",
893
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
894
+ "modelAlias": "vh-smart"
895
+ },
896
+ "sig": {
897
+ "keyId": "vh-cp-2026-10",
898
+ "timestamp": "1793268000",
899
+ "nonce": "Zm9vYmFyYmF6cXV4MTIzNDU2",
900
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
901
+ "workspaceId": "ws-1",
902
+ "signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
903
+ },
904
+ "paramsRaw": "{}"
905
+ }
906
+ }
907
+ ]
908
+ }