arcane-cli 1.17.2 → 1.18.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.
@@ -0,0 +1,586 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://arcaneai.net/schemas/presence/v0",
4
+ "title": "Arcane presence session record",
5
+ "description": "One session of the local presence channel (`spell presence`, ARC-060): one checkout plus the agent it reports as. Held in the service's memory only, reconstructable from `spell state --json` and never authoritative. The document root is a session record; $defs hold the request and response bodies of the /v0/ loopback contract and the event feed. Every route requires `Authorization: Bearer <token>`. The contract is /v0/; from its first stable version the schema is additive-only.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "session",
10
+ "agent",
11
+ "harness",
12
+ "repository",
13
+ "checkout",
14
+ "spell",
15
+ "task",
16
+ "message",
17
+ "status",
18
+ "needs_you",
19
+ "started_at",
20
+ "reported_at",
21
+ "ended_at",
22
+ "stale"
23
+ ],
24
+ "properties": {
25
+ "session": {
26
+ "type": "string",
27
+ "pattern": "^arcane:session:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
28
+ "description": "Minted by the service on the first report from a checkout (ARC-060 decision 4). Opaque."
29
+ },
30
+ "agent": {
31
+ "$ref": "#/$defs/agent"
32
+ },
33
+ "harness": {
34
+ "$ref": "#/$defs/harness"
35
+ },
36
+ "repository": {
37
+ "$ref": "#/$defs/repository"
38
+ },
39
+ "checkout": {
40
+ "$ref": "#/$defs/checkout"
41
+ },
42
+ "spell": {
43
+ "type": [
44
+ "string",
45
+ "null"
46
+ ],
47
+ "maxLength": 256,
48
+ "description": "The spell running, when reported."
49
+ },
50
+ "task": {
51
+ "type": [
52
+ "string",
53
+ "null"
54
+ ],
55
+ "maxLength": 256,
56
+ "description": "What the session is doing, in one line."
57
+ },
58
+ "message": {
59
+ "type": [
60
+ "string",
61
+ "null"
62
+ ],
63
+ "maxLength": 256,
64
+ "description": "A free one-line note."
65
+ },
66
+ "status": {
67
+ "enum": [
68
+ "working",
69
+ "waiting",
70
+ "blocked",
71
+ "idle",
72
+ "done"
73
+ ],
74
+ "description": "working: a spell is running; waiting: the session asked the operator for something; blocked: cannot proceed for an external reason; idle: open, no spell running; done: ended (set by end only)."
75
+ },
76
+ "needs_you": {
77
+ "type": "array",
78
+ "maxItems": 20,
79
+ "items": {
80
+ "$ref": "#/$defs/needsYou"
81
+ }
82
+ },
83
+ "started_at": {
84
+ "type": "string",
85
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?Z$",
86
+ "description": "When this session's reference was minted."
87
+ },
88
+ "reported_at": {
89
+ "type": "string",
90
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?Z$",
91
+ "description": "The last accepted report. The stale and expiry clocks run from it."
92
+ },
93
+ "ended_at": {
94
+ "oneOf": [
95
+ {
96
+ "type": "string",
97
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?Z$"
98
+ },
99
+ {
100
+ "type": "null"
101
+ }
102
+ ],
103
+ "description": "Set by end; otherwise null."
104
+ },
105
+ "stale": {
106
+ "type": "boolean",
107
+ "description": "Set by the service alone: no report for 90 s. status stays as last reported; a client renders a stale session as unknown, never as working. Expired and dropped after 24 h."
108
+ }
109
+ },
110
+ "$defs": {
111
+ "capabilities": {
112
+ "description": "The capability descriptor (ARC-059 decision 10). The presence service declares { observe: true, actions: [] } on /v0/health, in server.hello, in the snapshot envelope and as the MCP capabilities resource.",
113
+ "type": "object",
114
+ "additionalProperties": false,
115
+ "required": [
116
+ "observe",
117
+ "actions"
118
+ ],
119
+ "properties": {
120
+ "observe": {
121
+ "type": "boolean",
122
+ "description": "The source reports state or presence."
123
+ },
124
+ "actions": {
125
+ "type": "array",
126
+ "uniqueItems": true,
127
+ "items": {
128
+ "enum": [
129
+ "open",
130
+ "resume",
131
+ "instruct"
132
+ ]
133
+ },
134
+ "description": "Action identifiers the source accepts, from ARC-059 decision 10's vocabulary, extended only by a decision record (ARC-060 decision 8). Empty in v0: observation only, by contract. A client renders a control only for a declared action."
135
+ }
136
+ }
137
+ },
138
+ "alias": {
139
+ "type": "object",
140
+ "additionalProperties": false,
141
+ "required": [
142
+ "value",
143
+ "context"
144
+ ],
145
+ "properties": {
146
+ "value": {
147
+ "type": "string",
148
+ "minLength": 1
149
+ },
150
+ "context": {
151
+ "enum": [
152
+ "openclaw",
153
+ "slug"
154
+ ],
155
+ "description": "openclaw: a harness id; slug: a former slug (ARC-059 decision 4)."
156
+ }
157
+ }
158
+ },
159
+ "agent": {
160
+ "description": "Always all six keys (architecture D7). Filled from the resolved roster entry; on a v2 roster ref is null and aliases is [] (ARC-060 decision 13); with no roster, an unloadable one or an unmatched --agent, every field is null and aliases is [].",
161
+ "type": "object",
162
+ "additionalProperties": false,
163
+ "required": [
164
+ "ref",
165
+ "slug",
166
+ "name",
167
+ "origin",
168
+ "definition_revision",
169
+ "aliases"
170
+ ],
171
+ "properties": {
172
+ "ref": {
173
+ "type": [
174
+ "string",
175
+ "null"
176
+ ],
177
+ "pattern": "^arcane:agent:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
178
+ "description": "The agent's opaque reference (ARC-059). null on a v2 roster: a reader never mints."
179
+ },
180
+ "slug": {
181
+ "type": [
182
+ "string",
183
+ "null"
184
+ ],
185
+ "description": "On a v3 roster the entry's slug; on a v2 roster the entry's id (ARC-060 decision 13), so the orchestrator is 'main' until the roster is migrated. Match a consumer's seat on slug or on an alias, never on slug alone."
186
+ },
187
+ "name": {
188
+ "type": [
189
+ "string",
190
+ "null"
191
+ ],
192
+ "description": "Display name; null while unnamed."
193
+ },
194
+ "origin": {
195
+ "enum": [
196
+ "repo",
197
+ "user",
198
+ null
199
+ ],
200
+ "description": "Which roster won the precedence (ARC-059 decision 8)."
201
+ },
202
+ "definition_revision": {
203
+ "type": [
204
+ "string",
205
+ "null"
206
+ ],
207
+ "pattern": "^sha256:[0-9a-f]{64}$",
208
+ "description": "sha256 of the role definition file at resolution; null when it is missing."
209
+ },
210
+ "aliases": {
211
+ "type": "array",
212
+ "items": {
213
+ "$ref": "#/$defs/alias"
214
+ },
215
+ "maxItems": 32
216
+ }
217
+ }
218
+ },
219
+ "needsYou": {
220
+ "type": "object",
221
+ "additionalProperties": false,
222
+ "required": [
223
+ "action",
224
+ "reason"
225
+ ],
226
+ "properties": {
227
+ "action": {
228
+ "type": "string",
229
+ "maxLength": 256,
230
+ "description": "Exactly what the operator must do: one line of a '## ⚠ Needs you' block.",
231
+ "minLength": 1
232
+ },
233
+ "reason": {
234
+ "type": [
235
+ "string",
236
+ "null"
237
+ ],
238
+ "maxLength": 256,
239
+ "description": "Why the agent cannot do it itself; null when the line carried no reason."
240
+ }
241
+ }
242
+ },
243
+ "remote": {
244
+ "type": "object",
245
+ "additionalProperties": false,
246
+ "required": [
247
+ "provider",
248
+ "url"
249
+ ],
250
+ "properties": {
251
+ "provider": {
252
+ "enum": [
253
+ "github",
254
+ "ado",
255
+ "other"
256
+ ]
257
+ },
258
+ "url": {
259
+ "type": "string",
260
+ "description": "origin's URL with userinfo stripped (the state export's git.remote shape)."
261
+ }
262
+ }
263
+ },
264
+ "repository": {
265
+ "type": "object",
266
+ "additionalProperties": false,
267
+ "required": [
268
+ "root",
269
+ "name",
270
+ "remote"
271
+ ],
272
+ "properties": {
273
+ "root": {
274
+ "type": "string",
275
+ "minLength": 1,
276
+ "description": "Absolute real path of the repository's main working tree. A label: the service never opens it."
277
+ },
278
+ "name": {
279
+ "type": "string",
280
+ "maxLength": 256,
281
+ "description": "The root folder's name.",
282
+ "minLength": 1
283
+ },
284
+ "remote": {
285
+ "oneOf": [
286
+ {
287
+ "$ref": "#/$defs/remote"
288
+ },
289
+ {
290
+ "type": "null"
291
+ }
292
+ ]
293
+ }
294
+ }
295
+ },
296
+ "checkout": {
297
+ "type": "object",
298
+ "additionalProperties": false,
299
+ "required": [
300
+ "path",
301
+ "branch",
302
+ "linked_worktree"
303
+ ],
304
+ "properties": {
305
+ "path": {
306
+ "type": "string",
307
+ "minLength": 1,
308
+ "description": "Absolute real path of this worktree: the session key (ARC-060 decision 4). A linked worktree is its own session."
309
+ },
310
+ "branch": {
311
+ "type": [
312
+ "string",
313
+ "null"
314
+ ],
315
+ "maxLength": 256,
316
+ "description": "Branch name, the short commit id when detached, or null."
317
+ },
318
+ "linked_worktree": {
319
+ "type": "boolean"
320
+ }
321
+ }
322
+ },
323
+ "harness": {
324
+ "enum": [
325
+ "claude-code",
326
+ "copilot",
327
+ "codex",
328
+ "openclaw",
329
+ "cron",
330
+ "other"
331
+ ],
332
+ "description": "Where the session runs. 'other' when the reporter cannot tell; never null (architecture D8)."
333
+ },
334
+ "reportStatus": {
335
+ "enum": [
336
+ "working",
337
+ "waiting",
338
+ "blocked",
339
+ "idle"
340
+ ]
341
+ },
342
+ "report": {
343
+ "description": "The body of POST /v0/sessions/report: a patch on the record of the checkout it names (architecture D4). 'done' is not a report status: end a session with POST /v0/sessions/end.",
344
+ "type": "object",
345
+ "additionalProperties": false,
346
+ "required": [
347
+ "status",
348
+ "harness",
349
+ "agent",
350
+ "repository",
351
+ "checkout"
352
+ ],
353
+ "properties": {
354
+ "status": {
355
+ "$ref": "#/$defs/reportStatus"
356
+ },
357
+ "harness": {
358
+ "$ref": "#/$defs/harness"
359
+ },
360
+ "agent": {
361
+ "$ref": "#/$defs/agent"
362
+ },
363
+ "repository": {
364
+ "$ref": "#/$defs/repository"
365
+ },
366
+ "checkout": {
367
+ "$ref": "#/$defs/checkout"
368
+ },
369
+ "spell": {
370
+ "type": [
371
+ "string",
372
+ "null"
373
+ ],
374
+ "maxLength": 256,
375
+ "description": "Absent keeps the stored value; null clears it."
376
+ },
377
+ "task": {
378
+ "type": [
379
+ "string",
380
+ "null"
381
+ ],
382
+ "maxLength": 256,
383
+ "description": "Absent keeps the stored value; null clears it."
384
+ },
385
+ "message": {
386
+ "type": [
387
+ "string",
388
+ "null"
389
+ ],
390
+ "maxLength": 256,
391
+ "description": "Absent keeps the stored value; null clears it."
392
+ },
393
+ "needs_you": {
394
+ "type": "array",
395
+ "maxItems": 20,
396
+ "items": {
397
+ "$ref": "#/$defs/needsYou"
398
+ },
399
+ "description": "Replaces the stored list on every report; absent means []. More than 20 entries is refused with 400, never cut."
400
+ }
401
+ }
402
+ },
403
+ "end": {
404
+ "description": "The body of POST /v0/sessions/end.",
405
+ "type": "object",
406
+ "additionalProperties": false,
407
+ "required": [
408
+ "checkout"
409
+ ],
410
+ "properties": {
411
+ "checkout": {
412
+ "type": "object",
413
+ "additionalProperties": false,
414
+ "required": [
415
+ "path"
416
+ ],
417
+ "properties": {
418
+ "path": {
419
+ "type": "string",
420
+ "minLength": 1
421
+ }
422
+ }
423
+ }
424
+ }
425
+ },
426
+ "generator": {
427
+ "type": "object",
428
+ "additionalProperties": false,
429
+ "required": [
430
+ "name",
431
+ "version"
432
+ ],
433
+ "properties": {
434
+ "name": {
435
+ "const": "arcane-cli"
436
+ },
437
+ "version": {
438
+ "type": "string"
439
+ }
440
+ }
441
+ },
442
+ "health": {
443
+ "description": "GET /v0/health.",
444
+ "type": "object",
445
+ "additionalProperties": false,
446
+ "required": [
447
+ "ok",
448
+ "generator",
449
+ "contract",
450
+ "capabilities",
451
+ "sessions",
452
+ "started_at"
453
+ ],
454
+ "properties": {
455
+ "ok": {
456
+ "const": true
457
+ },
458
+ "generator": {
459
+ "$ref": "#/$defs/generator"
460
+ },
461
+ "contract": {
462
+ "const": "v0"
463
+ },
464
+ "capabilities": {
465
+ "$ref": "#/$defs/capabilities"
466
+ },
467
+ "sessions": {
468
+ "type": "integer",
469
+ "minimum": 0,
470
+ "description": "Active and stale sessions."
471
+ },
472
+ "started_at": {
473
+ "type": "string",
474
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?Z$",
475
+ "description": "When this service started."
476
+ }
477
+ }
478
+ },
479
+ "snapshot": {
480
+ "description": "GET /v0/sessions, and the arcane://presence/sessions MCP resource.",
481
+ "type": "object",
482
+ "additionalProperties": false,
483
+ "required": [
484
+ "capabilities",
485
+ "generated_at",
486
+ "sessions"
487
+ ],
488
+ "properties": {
489
+ "capabilities": {
490
+ "$ref": "#/$defs/capabilities"
491
+ },
492
+ "generated_at": {
493
+ "type": "string",
494
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?Z$",
495
+ "description": "When the snapshot was taken."
496
+ },
497
+ "sessions": {
498
+ "type": "array",
499
+ "items": {
500
+ "$ref": "#"
501
+ },
502
+ "description": "Active and stale sessions, never expired or ended, by started_at then session."
503
+ }
504
+ }
505
+ },
506
+ "hello": {
507
+ "description": "The data of the first event on GET /v0/events, server.hello: the current state, so a subscriber, or a reconnecting one, starts from it. There is no replay.",
508
+ "type": "object",
509
+ "additionalProperties": false,
510
+ "required": [
511
+ "contract",
512
+ "capabilities",
513
+ "sessions"
514
+ ],
515
+ "properties": {
516
+ "contract": {
517
+ "const": "v0"
518
+ },
519
+ "capabilities": {
520
+ "$ref": "#/$defs/capabilities"
521
+ },
522
+ "sessions": {
523
+ "type": "array",
524
+ "items": {
525
+ "$ref": "#"
526
+ }
527
+ }
528
+ }
529
+ },
530
+ "event": {
531
+ "description": "One change on GET /v0/events: the event name and the full record after the change. Exactly one event per accepted report, by the precedence started > resumed > needs_you > updated (architecture D5). The record is the truth and the event name is why it was sent: a consumer that alerts on 'needs you' reads the record's needs_you, because a first or a resumed report can carry lines under another event name.",
532
+ "type": "object",
533
+ "additionalProperties": false,
534
+ "required": [
535
+ "event",
536
+ "data"
537
+ ],
538
+ "properties": {
539
+ "event": {
540
+ "enum": [
541
+ "session.started",
542
+ "session.updated",
543
+ "session.needs_you",
544
+ "session.stale",
545
+ "session.resumed",
546
+ "session.ended",
547
+ "session.expired"
548
+ ]
549
+ },
550
+ "data": {
551
+ "$ref": "#"
552
+ }
553
+ }
554
+ },
555
+ "error": {
556
+ "description": "Every 4xx answer except 401, which has an empty body.",
557
+ "type": "object",
558
+ "additionalProperties": false,
559
+ "required": [
560
+ "error"
561
+ ],
562
+ "properties": {
563
+ "error": {
564
+ "type": "object",
565
+ "additionalProperties": false,
566
+ "required": [
567
+ "code",
568
+ "message"
569
+ ],
570
+ "properties": {
571
+ "code": {
572
+ "type": "string",
573
+ "minLength": 1
574
+ },
575
+ "field": {
576
+ "type": "string"
577
+ },
578
+ "message": {
579
+ "type": "string"
580
+ }
581
+ }
582
+ }
583
+ }
584
+ }
585
+ }
586
+ }