deepdebug-local-agent 1.3.0 → 1.4.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 (108) hide show
  1. package/.github/workflows/deploy-gcp.yml +58 -26
  2. package/CHANGELOG.md +6 -0
  3. package/docs/la-protocol-v2.md +68 -0
  4. package/package.json +2 -1
  5. package/scripts/sync-la-protocol-v2-contract.mjs +58 -0
  6. package/src/la-protocol-v2/chunks.js +45 -0
  7. package/src/la-protocol-v2/config.js +27 -0
  8. package/src/la-protocol-v2/content.js +57 -0
  9. package/src/la-protocol-v2/contract/CONTRACT_SOURCE.json +81 -0
  10. package/src/la-protocol-v2/contract/README.md +103 -0
  11. package/src/la-protocol-v2/contract/ack.schema.json +51 -0
  12. package/src/la-protocol-v2/contract/alert.schema.json +62 -0
  13. package/src/la-protocol-v2/contract/approval.decision.schema.json +57 -0
  14. package/src/la-protocol-v2/contract/audit.event.schema.json +86 -0
  15. package/src/la-protocol-v2/contract/config.update.schema.json +73 -0
  16. package/src/la-protocol-v2/contract/content.request.schema.json +110 -0
  17. package/src/la-protocol-v2/contract/content.response.schema.json +90 -0
  18. package/src/la-protocol-v2/contract/defs.schema.json +191 -0
  19. package/src/la-protocol-v2/contract/envelope.schema.json +89 -0
  20. package/src/la-protocol-v2/contract/error.schema.json +59 -0
  21. package/src/la-protocol-v2/contract/heartbeat.schema.json +100 -0
  22. package/src/la-protocol-v2/contract/hello.schema.json +111 -0
  23. package/src/la-protocol-v2/contract/incident.candidate.schema.json +102 -0
  24. package/src/la-protocol-v2/contract/index.json +166 -0
  25. package/src/la-protocol-v2/contract/job.assign.schema.json +212 -0
  26. package/src/la-protocol-v2/contract/job.cancel.schema.json +52 -0
  27. package/src/la-protocol-v2/contract/job.event.schema.json +115 -0
  28. package/src/la-protocol-v2/contract/job.result.schema.json +100 -0
  29. package/src/la-protocol-v2/contract/log.stats.schema.json +79 -0
  30. package/src/la-protocol-v2/contract/ready.schema.json +106 -0
  31. package/src/la-protocol-v2/contract/register.schema.json +92 -0
  32. package/src/la-protocol-v2/contract/scan.upload.schema.json +59 -0
  33. package/src/la-protocol-v2/contract/scan.uploaded.schema.json +51 -0
  34. package/src/la-protocol-v2/contract/webhook.forward.schema.json +69 -0
  35. package/src/la-protocol-v2/contract.js +90 -0
  36. package/src/la-protocol-v2/errors.js +34 -0
  37. package/src/la-protocol-v2/index.js +8 -0
  38. package/src/la-protocol-v2/link.js +93 -0
  39. package/src/la-protocol-v2/runtime.js +72 -0
  40. package/src/la-protocol-v2/session.js +650 -0
  41. package/src/la-protocol-v2/strict-json.js +47 -0
  42. package/src/server.js +22 -4
  43. package/test/contract/la-protocol-v2/vectors/ack.vectors.json +149 -0
  44. package/test/contract/la-protocol-v2/vectors/alert.vectors.json +101 -0
  45. package/test/contract/la-protocol-v2/vectors/approval.decision.vectors.json +165 -0
  46. package/test/contract/la-protocol-v2/vectors/audit.event.vectors.json +156 -0
  47. package/test/contract/la-protocol-v2/vectors/config.update.vectors.json +189 -0
  48. package/test/contract/la-protocol-v2/vectors/content.request.vectors.json +325 -0
  49. package/test/contract/la-protocol-v2/vectors/content.response.vectors.json +413 -0
  50. package/test/contract/la-protocol-v2/vectors/cross-type.vectors.json +260 -0
  51. package/test/contract/la-protocol-v2/vectors/error.vectors.json +179 -0
  52. package/test/contract/la-protocol-v2/vectors/heartbeat.vectors.json +109 -0
  53. package/test/contract/la-protocol-v2/vectors/hello.vectors.json +224 -0
  54. package/test/contract/la-protocol-v2/vectors/incident.candidate.vectors.json +186 -0
  55. package/test/contract/la-protocol-v2/vectors/job.assign.vectors.json +631 -0
  56. package/test/contract/la-protocol-v2/vectors/job.cancel.vectors.json +133 -0
  57. package/test/contract/la-protocol-v2/vectors/job.event.vectors.json +233 -0
  58. package/test/contract/la-protocol-v2/vectors/job.result.vectors.json +137 -0
  59. package/test/contract/la-protocol-v2/vectors/log.stats.vectors.json +137 -0
  60. package/test/contract/la-protocol-v2/vectors/ready.vectors.json +177 -0
  61. package/test/contract/la-protocol-v2/vectors/register.vectors.json +399 -0
  62. package/test/contract/la-protocol-v2/vectors/scan.upload.vectors.json +137 -0
  63. package/test/contract/la-protocol-v2/vectors/scan.uploaded.vectors.json +101 -0
  64. package/test/contract/la-protocol-v2/vectors/traces/invalid-agent-mismatch.json +140 -0
  65. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-after-last.json +200 -0
  66. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-byte-length-mismatch.json +174 -0
  67. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-last-flag.json +200 -0
  68. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-out-of-order.json +200 -0
  69. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-total-changes.json +200 -0
  70. package/test/contract/la-protocol-v2/vectors/traces/invalid-clock-skew.json +46 -0
  71. package/test/contract/la-protocol-v2/vectors/traces/invalid-event-before-ready.json +72 -0
  72. package/test/contract/la-protocol-v2/vectors/traces/invalid-first-frame-not-register.json +48 -0
  73. package/test/contract/la-protocol-v2/vectors/traces/invalid-frame-over-48kib.json +141 -0
  74. package/test/contract/la-protocol-v2/vectors/traces/invalid-la-sends-job-assign.json +173 -0
  75. package/test/contract/la-protocol-v2/vectors/traces/invalid-params-raw-differs-from-payload.json +172 -0
  76. package/test/contract/la-protocol-v2/vectors/traces/invalid-payload-above-limit.json +174 -0
  77. package/test/contract/la-protocol-v2/vectors/traces/invalid-resume-restarts-seq.json +144 -0
  78. package/test/contract/la-protocol-v2/vectors/traces/invalid-seq-gap.json +166 -0
  79. package/test/contract/la-protocol-v2/vectors/traces/invalid-seq-repeated.json +166 -0
  80. package/test/contract/la-protocol-v2/vectors/traces/invalid-sig-tenant-mismatch.json +172 -0
  81. package/test/contract/la-protocol-v2/vectors/traces/invalid-signature-warn-with-enforce-required.json +77 -0
  82. package/test/contract/la-protocol-v2/vectors/traces/invalid-tenant-mismatch.json +140 -0
  83. package/test/contract/la-protocol-v2/vectors/traces/invalid-type-outside-allowlist.json +140 -0
  84. package/test/contract/la-protocol-v2/vectors/traces/valid-content-chunks-in-order.json +224 -0
  85. package/test/contract/la-protocol-v2/vectors/traces/valid-handshake-and-job.json +266 -0
  86. package/test/contract/la-protocol-v2/vectors/traces/valid-resume-continues-seq.json +168 -0
  87. package/test/contract/la-protocol-v2/vectors/traces/valid-retransmit-is-idempotent.json +193 -0
  88. package/test/contract/la-protocol-v2/vectors/webhook.forward.vectors.json +170 -0
  89. package/test/la-protocol-v2/contract.test.js +131 -0
  90. package/test/la-protocol-v2/helpers/la-rig.js +83 -0
  91. package/test/la-protocol-v2/helpers/reference-cp.js +349 -0
  92. package/test/la-protocol-v2/helpers/spawn-agent.js +35 -0
  93. package/test/la-protocol-v2/link.test.js +141 -0
  94. package/test/la-protocol-v2/session-inbound.test.js +279 -0
  95. package/test/la-protocol-v2/session-outbound.test.js +382 -0
  96. package/test/la-protocol-v2/traces.test.js +270 -0
  97. package/test/la-protocol-v2/tunnel-e2e.test.js +124 -0
  98. package/tools/graphify-validation/extras/README.md +19 -0
  99. package/tools/graphify-validation/extras/bymethod.py +35 -0
  100. package/tools/graphify-validation/extras/docker/Dockerfile +16 -0
  101. package/tools/graphify-validation/extras/docker/inner.sh +7 -0
  102. package/tools/graphify-validation/extras/g10.py +59 -0
  103. package/tools/graphify-validation/extras/g3aug.py +49 -0
  104. package/tools/graphify-validation/extras/hybrid.py +34 -0
  105. package/tools/graphify-validation/extras/truth2.py +44 -0
  106. package/tools/interop/LaV2NodeInteropTest.java +266 -0
  107. package/tools/interop/README.md +21 -0
  108. package/tools/interop/la-interop-client.mjs +97 -0
@@ -0,0 +1,260 @@
1
+ {
2
+ "type": "*",
3
+ "schema": "envelope.schema.json",
4
+ "vectors": [
5
+ {
6
+ "name": "type-outside-allowlist",
7
+ "why": "type must be one of the 21 allowlisted types (no arbitrary commands from the CP)",
8
+ "expect": {
9
+ "valid": false,
10
+ "code": "unknown_type",
11
+ "keyword": "enum"
12
+ },
13
+ "message": {
14
+ "schemaVersion": 2,
15
+ "type": "shell.exec",
16
+ "msgId": "00000000-0000-4000-8000-000000000001",
17
+ "seq": 1,
18
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
19
+ "workspaceId": "ws-1",
20
+ "ts": "2026-10-29T10:00:00Z",
21
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
22
+ "payload": {
23
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
24
+ "state": "running",
25
+ "phase": "edit",
26
+ "iteration": 2,
27
+ "filesRead": 14,
28
+ "filesChanged": 1,
29
+ "tokensIn": 8200,
30
+ "tokensOut": 1300,
31
+ "costUsd": 0.042,
32
+ "durationMs": 61000,
33
+ "errorCode": "none"
34
+ }
35
+ }
36
+ },
37
+ {
38
+ "name": "legacy-v1-command-as-type",
39
+ "why": "v1 commands (mcp.execute-command, ...) are not v2 types",
40
+ "expect": {
41
+ "valid": false,
42
+ "code": "unknown_type",
43
+ "keyword": "enum"
44
+ },
45
+ "message": {
46
+ "schemaVersion": 2,
47
+ "type": "mcp.execute-command",
48
+ "msgId": "00000000-0000-4000-8000-000000000001",
49
+ "seq": 1,
50
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
51
+ "workspaceId": "ws-1",
52
+ "ts": "2026-10-29T10:00:00Z",
53
+ "paramsRaw": "{\"jobId\":\"c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f\",\"kind\":\"fix\",\"incidentRef\":{\"id\":\"inc-8c8deab3\",\"fingerprint\":\"5a1f09c2d7e8b3a4\"},\"repoRef\":{\"provider\":\"github\",\"org\":\"acme\",\"repo\":\"billing\",\"branch\":\"main\"},\"policy\":{\"operationMode\":\"assist\",\"automationLevel\":2,\"ceiling\":\"autonomous\"},\"budget\":{\"tokens\":200000,\"seconds\":900},\"llm\":{\"alias\":\"vh-coder\",\"keyRef\":\"key-la-1\"},\"inputs\":[{\"ref\":\"incident:inc-8c8deab3\"},{\"inline\":\"Fix the NPE in PaymentService\",\"transient\":true}]}",
54
+ "sig": {
55
+ "keyId": "vh-cp-2026-10",
56
+ "timestamp": "1793268000",
57
+ "nonce": "Zm9vYmFyYmF6cXV4MTIzNDU2",
58
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
59
+ "workspaceId": "ws-1",
60
+ "signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
61
+ },
62
+ "requestId": "d4e5f6a7-b8c9-4d0e-9f1a-3b4c5d6e7f80",
63
+ "payload": {
64
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
65
+ "kind": "fix",
66
+ "incidentRef": {
67
+ "id": "inc-8c8deab3",
68
+ "fingerprint": "5a1f09c2d7e8b3a4"
69
+ },
70
+ "repoRef": {
71
+ "provider": "github",
72
+ "org": "acme",
73
+ "repo": "billing",
74
+ "branch": "main"
75
+ },
76
+ "policy": {
77
+ "operationMode": "assist",
78
+ "automationLevel": 2,
79
+ "ceiling": "autonomous"
80
+ },
81
+ "budget": {
82
+ "tokens": 200000,
83
+ "seconds": 900
84
+ },
85
+ "llm": {
86
+ "alias": "vh-coder",
87
+ "keyRef": "key-la-1"
88
+ },
89
+ "inputs": [
90
+ {
91
+ "ref": "incident:inc-8c8deab3"
92
+ },
93
+ {
94
+ "inline": "Fix the NPE in PaymentService",
95
+ "transient": true
96
+ }
97
+ ]
98
+ }
99
+ }
100
+ },
101
+ {
102
+ "name": "schema-version-1",
103
+ "why": "schemaVersion is the const 2",
104
+ "expect": {
105
+ "valid": false,
106
+ "code": "schema_violation",
107
+ "keyword": "const"
108
+ },
109
+ "message": {
110
+ "schemaVersion": 1,
111
+ "type": "job.event",
112
+ "msgId": "00000000-0000-4000-8000-000000000001",
113
+ "seq": 1,
114
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
115
+ "workspaceId": "ws-1",
116
+ "ts": "2026-10-29T10:00:00Z",
117
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
118
+ "payload": {
119
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
120
+ "state": "running",
121
+ "phase": "edit",
122
+ "iteration": 2,
123
+ "filesRead": 14,
124
+ "filesChanged": 1,
125
+ "tokensIn": 8200,
126
+ "tokensOut": 1300,
127
+ "costUsd": 0.042,
128
+ "durationMs": 61000,
129
+ "errorCode": "none"
130
+ }
131
+ }
132
+ },
133
+ {
134
+ "name": "missing-tenant-id",
135
+ "why": "tenantId is required on every frame",
136
+ "expect": {
137
+ "valid": false,
138
+ "code": "schema_violation",
139
+ "keyword": "required"
140
+ },
141
+ "message": {
142
+ "schemaVersion": 2,
143
+ "type": "job.event",
144
+ "msgId": "00000000-0000-4000-8000-000000000001",
145
+ "seq": 1,
146
+ "workspaceId": "ws-1",
147
+ "ts": "2026-10-29T10:00:00Z",
148
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
149
+ "payload": {
150
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
151
+ "state": "running",
152
+ "phase": "edit",
153
+ "iteration": 2,
154
+ "filesRead": 14,
155
+ "filesChanged": 1,
156
+ "tokensIn": 8200,
157
+ "tokensOut": 1300,
158
+ "costUsd": 0.042,
159
+ "durationMs": 61000,
160
+ "errorCode": "none"
161
+ }
162
+ }
163
+ },
164
+ {
165
+ "name": "v1-legacy-command-frame",
166
+ "why": "a v1 command envelope is not a v2 frame",
167
+ "expect": {
168
+ "valid": false,
169
+ "code": "schema_violation",
170
+ "keyword": "required"
171
+ },
172
+ "message": {
173
+ "requestId": "d4e5f6a7-b8c9-4d0e-9f1a-3b4c5d6e7f80",
174
+ "command": "mcp.execute-command",
175
+ "params": {
176
+ "command": "ls"
177
+ }
178
+ }
179
+ },
180
+ {
181
+ "name": "legacy-register",
182
+ "why": "the v1 register frame is not v2 (v1 path, no schemaVersion)",
183
+ "expect": {
184
+ "valid": false,
185
+ "code": "schema_violation",
186
+ "keyword": "required"
187
+ },
188
+ "message": {
189
+ "type": "register",
190
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
191
+ "port": 5055,
192
+ "workspacePath": "/home/user/code"
193
+ }
194
+ },
195
+ {
196
+ "name": "ts-not-rfc3339-utc",
197
+ "why": "ts is RFC 3339 UTC",
198
+ "expect": {
199
+ "valid": false,
200
+ "code": "schema_violation",
201
+ "keyword": "pattern"
202
+ },
203
+ "message": {
204
+ "schemaVersion": 2,
205
+ "type": "job.event",
206
+ "msgId": "00000000-0000-4000-8000-000000000001",
207
+ "seq": 1,
208
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
209
+ "workspaceId": "ws-1",
210
+ "ts": "2026-10-29 10:00:00",
211
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
212
+ "payload": {
213
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
214
+ "state": "running",
215
+ "phase": "edit",
216
+ "iteration": 2,
217
+ "filesRead": 14,
218
+ "filesChanged": 1,
219
+ "tokensIn": 8200,
220
+ "tokensOut": 1300,
221
+ "costUsd": 0.042,
222
+ "durationMs": 61000,
223
+ "errorCode": "none"
224
+ }
225
+ }
226
+ },
227
+ {
228
+ "name": "negative-seq",
229
+ "why": "seq >= 0",
230
+ "expect": {
231
+ "valid": false,
232
+ "code": "schema_violation",
233
+ "keyword": "minimum"
234
+ },
235
+ "message": {
236
+ "schemaVersion": 2,
237
+ "type": "job.event",
238
+ "msgId": "00000000-0000-4000-8000-000000000001",
239
+ "seq": -1,
240
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
241
+ "workspaceId": "ws-1",
242
+ "ts": "2026-10-29T10:00:00Z",
243
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
244
+ "payload": {
245
+ "jobId": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
246
+ "state": "running",
247
+ "phase": "edit",
248
+ "iteration": 2,
249
+ "filesRead": 14,
250
+ "filesChanged": 1,
251
+ "tokensIn": 8200,
252
+ "tokensOut": 1300,
253
+ "costUsd": 0.042,
254
+ "durationMs": 61000,
255
+ "errorCode": "none"
256
+ }
257
+ }
258
+ }
259
+ ]
260
+ }
@@ -0,0 +1,179 @@
1
+ {
2
+ "type": "error",
3
+ "schema": "error.schema.json",
4
+ "vectors": [
5
+ {
6
+ "name": "minimal-valid",
7
+ "expect": {
8
+ "valid": true
9
+ },
10
+ "message": {
11
+ "schemaVersion": 2,
12
+ "type": "error",
13
+ "msgId": "00000000-0000-4000-8000-000000000001",
14
+ "seq": 0,
15
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
16
+ "workspaceId": "ws-1",
17
+ "ts": "2026-10-29T10:00:00Z",
18
+ "payload": {
19
+ "code": "seq_gap",
20
+ "retryable": true,
21
+ "refSeq": 7,
22
+ "detail": "expected seq 5"
23
+ },
24
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
25
+ }
26
+ },
27
+ {
28
+ "name": "extra-top-level-field",
29
+ "why": "envelope is closed (additionalProperties:false)",
30
+ "expect": {
31
+ "valid": false,
32
+ "code": "schema_violation",
33
+ "keyword": "additionalProperties"
34
+ },
35
+ "message": {
36
+ "schemaVersion": 2,
37
+ "type": "error",
38
+ "msgId": "00000000-0000-4000-8000-000000000001",
39
+ "seq": 0,
40
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
41
+ "workspaceId": "ws-1",
42
+ "ts": "2026-10-29T10:00:00Z",
43
+ "payload": {
44
+ "code": "seq_gap",
45
+ "retryable": true,
46
+ "refSeq": 7,
47
+ "detail": "expected seq 5"
48
+ },
49
+ "extra": "x",
50
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
51
+ }
52
+ },
53
+ {
54
+ "name": "extra-payload-field",
55
+ "why": "payload is closed: no free-form fields",
56
+ "expect": {
57
+ "valid": false,
58
+ "code": "schema_violation",
59
+ "keyword": "additionalProperties"
60
+ },
61
+ "message": {
62
+ "schemaVersion": 2,
63
+ "type": "error",
64
+ "msgId": "00000000-0000-4000-8000-000000000001",
65
+ "seq": 0,
66
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
67
+ "workspaceId": "ws-1",
68
+ "ts": "2026-10-29T10:00:00Z",
69
+ "payload": {
70
+ "code": "seq_gap",
71
+ "retryable": true,
72
+ "refSeq": 7,
73
+ "detail": "expected seq 5",
74
+ "freeText": "client text"
75
+ },
76
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
77
+ }
78
+ },
79
+ {
80
+ "name": "tenant-id-not-uuid",
81
+ "why": "tenantId must be a UUID",
82
+ "expect": {
83
+ "valid": false,
84
+ "code": "schema_violation",
85
+ "keyword": "pattern"
86
+ },
87
+ "message": {
88
+ "schemaVersion": 2,
89
+ "type": "error",
90
+ "msgId": "00000000-0000-4000-8000-000000000001",
91
+ "seq": 0,
92
+ "tenantId": "tenant-1",
93
+ "workspaceId": "ws-1",
94
+ "ts": "2026-10-29T10:00:00Z",
95
+ "payload": {
96
+ "code": "seq_gap",
97
+ "retryable": true,
98
+ "refSeq": 7,
99
+ "detail": "expected seq 5"
100
+ },
101
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
102
+ }
103
+ },
104
+ {
105
+ "name": "detail-above-200",
106
+ "why": "error.detail is bounded; never carries content",
107
+ "expect": {
108
+ "valid": false,
109
+ "code": "schema_violation",
110
+ "keyword": "maxLength"
111
+ },
112
+ "message": {
113
+ "schemaVersion": 2,
114
+ "type": "error",
115
+ "msgId": "00000000-0000-4000-8000-000000000001",
116
+ "seq": 0,
117
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
118
+ "workspaceId": "ws-1",
119
+ "ts": "2026-10-29T10:00:00Z",
120
+ "payload": {
121
+ "code": "seq_gap",
122
+ "retryable": true,
123
+ "refSeq": 7,
124
+ "detail": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
125
+ },
126
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
127
+ }
128
+ },
129
+ {
130
+ "name": "error-code-outside-enum",
131
+ "why": "error codes are an enum",
132
+ "expect": {
133
+ "valid": false,
134
+ "code": "schema_violation",
135
+ "keyword": "enum"
136
+ },
137
+ "message": {
138
+ "schemaVersion": 2,
139
+ "type": "error",
140
+ "msgId": "00000000-0000-4000-8000-000000000001",
141
+ "seq": 0,
142
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
143
+ "workspaceId": "ws-1",
144
+ "ts": "2026-10-29T10:00:00Z",
145
+ "payload": {
146
+ "code": "file_not_found_in_PaymentService",
147
+ "retryable": true,
148
+ "refSeq": 7,
149
+ "detail": "expected seq 5"
150
+ },
151
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
152
+ }
153
+ },
154
+ {
155
+ "name": "missing-agent-id",
156
+ "expect": {
157
+ "valid": false,
158
+ "code": "schema_violation",
159
+ "keyword": "required"
160
+ },
161
+ "message": {
162
+ "schemaVersion": 2,
163
+ "type": "error",
164
+ "msgId": "00000000-0000-4000-8000-000000000001",
165
+ "seq": 0,
166
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
167
+ "workspaceId": "ws-1",
168
+ "ts": "2026-10-29T10:00:00Z",
169
+ "payload": {
170
+ "code": "seq_gap",
171
+ "retryable": true,
172
+ "refSeq": 7,
173
+ "detail": "expected seq 5"
174
+ }
175
+ },
176
+ "why": "agentId is required on ack/error (the gateway refuses a frame without it: agent_mismatch)"
177
+ }
178
+ ]
179
+ }
@@ -0,0 +1,109 @@
1
+ {
2
+ "type": "heartbeat",
3
+ "schema": "heartbeat.schema.json",
4
+ "vectors": [
5
+ {
6
+ "name": "minimal-valid",
7
+ "expect": {
8
+ "valid": true
9
+ },
10
+ "message": {
11
+ "schemaVersion": 2,
12
+ "type": "heartbeat",
13
+ "msgId": "00000000-0000-4000-8000-000000000001",
14
+ "seq": 1,
15
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
16
+ "workspaceId": "ws-1",
17
+ "ts": "2026-10-29T10:00:00Z",
18
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
19
+ "payload": {
20
+ "signatureMode": "enforce",
21
+ "diskFreeBytes": 52428800000,
22
+ "queueDepth": 1,
23
+ "clockEpochMs": 1793268030000,
24
+ "inflight": 1
25
+ }
26
+ }
27
+ },
28
+ {
29
+ "name": "extra-top-level-field",
30
+ "why": "envelope is closed (additionalProperties:false)",
31
+ "expect": {
32
+ "valid": false,
33
+ "code": "schema_violation",
34
+ "keyword": "additionalProperties"
35
+ },
36
+ "message": {
37
+ "schemaVersion": 2,
38
+ "type": "heartbeat",
39
+ "msgId": "00000000-0000-4000-8000-000000000001",
40
+ "seq": 1,
41
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
42
+ "workspaceId": "ws-1",
43
+ "ts": "2026-10-29T10:00:00Z",
44
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
45
+ "payload": {
46
+ "signatureMode": "enforce",
47
+ "diskFreeBytes": 52428800000,
48
+ "queueDepth": 1,
49
+ "clockEpochMs": 1793268030000,
50
+ "inflight": 1
51
+ },
52
+ "extra": "x"
53
+ }
54
+ },
55
+ {
56
+ "name": "extra-payload-field",
57
+ "why": "payload is closed: no free-form fields",
58
+ "expect": {
59
+ "valid": false,
60
+ "code": "schema_violation",
61
+ "keyword": "additionalProperties"
62
+ },
63
+ "message": {
64
+ "schemaVersion": 2,
65
+ "type": "heartbeat",
66
+ "msgId": "00000000-0000-4000-8000-000000000001",
67
+ "seq": 1,
68
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
69
+ "workspaceId": "ws-1",
70
+ "ts": "2026-10-29T10:00:00Z",
71
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
72
+ "payload": {
73
+ "signatureMode": "enforce",
74
+ "diskFreeBytes": 52428800000,
75
+ "queueDepth": 1,
76
+ "clockEpochMs": 1793268030000,
77
+ "inflight": 1,
78
+ "freeText": "client text"
79
+ }
80
+ }
81
+ },
82
+ {
83
+ "name": "tenant-id-not-uuid",
84
+ "why": "tenantId must be a UUID",
85
+ "expect": {
86
+ "valid": false,
87
+ "code": "schema_violation",
88
+ "keyword": "pattern"
89
+ },
90
+ "message": {
91
+ "schemaVersion": 2,
92
+ "type": "heartbeat",
93
+ "msgId": "00000000-0000-4000-8000-000000000001",
94
+ "seq": 1,
95
+ "tenantId": "tenant-1",
96
+ "workspaceId": "ws-1",
97
+ "ts": "2026-10-29T10:00:00Z",
98
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
99
+ "payload": {
100
+ "signatureMode": "enforce",
101
+ "diskFreeBytes": 52428800000,
102
+ "queueDepth": 1,
103
+ "clockEpochMs": 1793268030000,
104
+ "inflight": 1
105
+ }
106
+ }
107
+ }
108
+ ]
109
+ }