archctx-contracts 0.5.9 → 0.5.11

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": "archcontext.capabilities/v1",
3
- "package": { "name": "archctx", "version": "0.5.9" },
3
+ "package": { "name": "archctx", "version": "0.5.11" },
4
4
  "protocols": {
5
5
  "projectionRequest": "archcontext.projection-request/v1",
6
6
  "projectionResult": "archcontext.projection-result/v2",
@@ -10,5 +10,5 @@
10
10
  "architectureDocs": "archcontext.docs-renderer/v4",
11
11
  "agentContext": "archcontext.agent-context-renderer/v1"
12
12
  },
13
- "features": ["architecture-docs-renderer-v2", "architecture-refresh-signal-v1", "module-statistics-v1", "projection-apply-receipt-v1", "projection-apply-recovery-v1", "projection-prior-committed-applies-v1", "projection-protocol-v2", "recommendation-v3", "refactor-assessment-v1", "refactor-resolution-v1"]
13
+ "features": ["architecture-docs-renderer-v2", "architecture-refresh-signal-v1", "module-statistics-v1", "projection-apply-readback-v1", "projection-apply-receipt-v1", "projection-apply-recovery-v1", "projection-prior-committed-applies-v1", "projection-protocol-v2", "recommendation-v3", "refactor-assessment-v1", "refactor-resolution-v1"]
14
14
  }
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": "archcontext.product-version-manifest/v1",
3
3
  "product": {
4
4
  "name": "archctx",
5
- "version": "0.5.9",
5
+ "version": "0.5.11",
6
6
  "distribution": "one-package"
7
7
  },
8
8
  "packageManager": "bun@1.4.0",
@@ -12,25 +12,25 @@
12
12
  "surfaces": {
13
13
  "cli": {
14
14
  "packageName": "@archcontext/surfaces",
15
- "version": "0.5.9",
15
+ "version": "0.5.11",
16
16
  "entrypoint": "archctx"
17
17
  },
18
18
  "daemon": {
19
19
  "packageName": "@archcontext/local-runtime",
20
- "version": "0.5.9",
20
+ "version": "0.5.11",
21
21
  "entrypoint": "archctx daemon start",
22
22
  "rpcSchemaVersion": "archcontext.runtime-rpc/v1"
23
23
  },
24
24
  "mcp": {
25
25
  "packageName": "@archcontext/surfaces",
26
- "version": "0.5.9",
26
+ "version": "0.5.11",
27
27
  "entrypoint": "archctx mcp",
28
28
  "transport": "stdio"
29
29
  }
30
30
  },
31
31
  "schemas": {
32
32
  "schemaSetVersion": "2026-06-25.al0-ledger",
33
- "contractsPackageVersion": "0.5.9",
33
+ "contractsPackageVersion": "0.5.11",
34
34
  "reviewChallenge": "archcontext.review-challenge/v2",
35
35
  "attestation": "archcontext.attestation/v2",
36
36
  "deviceIdentity": "archcontext.device-identity/v1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archctx-contracts",
3
- "version": "0.5.9",
3
+ "version": "0.5.11",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -39,7 +39,7 @@
39
39
  "type": "array",
40
40
  "minItems": 3,
41
41
  "uniqueItems": true,
42
- "items": { "enum": ["architecture-docs-renderer-v2", "architecture-refresh-signal-v1", "module-statistics-v1", "projection-apply-receipt-v1", "projection-apply-recovery-v1", "projection-prior-committed-applies-v1", "projection-protocol-v2", "recommendation-v3", "refactor-assessment-v1", "refactor-resolution-v1"] }
42
+ "items": { "enum": ["architecture-docs-renderer-v2", "architecture-refresh-signal-v1", "module-statistics-v1", "projection-apply-readback-v1", "projection-apply-receipt-v1", "projection-apply-recovery-v1", "projection-prior-committed-applies-v1", "projection-protocol-v2", "recommendation-v3", "refactor-assessment-v1", "refactor-resolution-v1"] }
43
43
  }
44
44
  }
45
45
  }
@@ -0,0 +1,1064 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://archcontext.dev/schemas/runtime/projection-apply-readback.schema.json",
4
+ "title": "ProjectionApplyReadbackV1",
5
+ "oneOf": [
6
+ {
7
+ "$ref": "#/$defs/readbackResult"
8
+ },
9
+ {
10
+ "$ref": "#/$defs/absence"
11
+ }
12
+ ],
13
+ "$defs": {
14
+ "digest": {
15
+ "type": "string",
16
+ "pattern": "^sha256:[a-f0-9]{64}$"
17
+ },
18
+ "nullableDigest": {
19
+ "type": [
20
+ "string",
21
+ "null"
22
+ ],
23
+ "pattern": "^sha256:[a-f0-9]{64}$"
24
+ },
25
+ "snapshot": {
26
+ "type": "object",
27
+ "additionalProperties": false,
28
+ "required": [
29
+ "repositoryId",
30
+ "workspaceId",
31
+ "headSha",
32
+ "baseHeadSha",
33
+ "worktreeDigest",
34
+ "sourceTreeDigest",
35
+ "modelDigest",
36
+ "codeGraphDigest",
37
+ "indexedWorktreeDigest",
38
+ "projectionInputDigest",
39
+ "rendererVersion",
40
+ "layoutVersion",
41
+ "generatedFrom"
42
+ ],
43
+ "properties": {
44
+ "repositoryId": {
45
+ "type": "string",
46
+ "minLength": 1
47
+ },
48
+ "workspaceId": {
49
+ "type": "string",
50
+ "minLength": 1
51
+ },
52
+ "headSha": {
53
+ "type": "string",
54
+ "pattern": "^[a-f0-9]{40}$"
55
+ },
56
+ "baseHeadSha": {
57
+ "type": "string",
58
+ "pattern": "^[a-f0-9]{40}$"
59
+ },
60
+ "worktreeDigest": {
61
+ "$ref": "#/$defs/digest"
62
+ },
63
+ "sourceTreeDigest": {
64
+ "$ref": "#/$defs/digest"
65
+ },
66
+ "modelDigest": {
67
+ "$ref": "#/$defs/digest"
68
+ },
69
+ "codeGraphDigest": {
70
+ "$ref": "#/$defs/digest"
71
+ },
72
+ "indexedWorktreeDigest": {
73
+ "$ref": "#/$defs/nullableDigest"
74
+ },
75
+ "projectionInputDigest": {
76
+ "$ref": "#/$defs/digest"
77
+ },
78
+ "rendererVersion": {
79
+ "const": "archcontext.docs-renderer/v4"
80
+ },
81
+ "layoutVersion": {
82
+ "const": "archcontext.docs-layout/v1"
83
+ },
84
+ "generatedFrom": {
85
+ "type": "object",
86
+ "additionalProperties": false,
87
+ "required": [
88
+ "codeGraphPackage",
89
+ "codeGraphVersion",
90
+ "codeGraphBinaryDigest",
91
+ "codeGraphStatus"
92
+ ],
93
+ "properties": {
94
+ "codeGraphPackage": {
95
+ "const": "@colbymchenry/codegraph"
96
+ },
97
+ "codeGraphVersion": {
98
+ "const": "1.5.0"
99
+ },
100
+ "codeGraphBinaryDigest": {
101
+ "$ref": "#/$defs/digest"
102
+ },
103
+ "codeGraphStatus": {
104
+ "enum": [
105
+ "ready",
106
+ "unavailable"
107
+ ]
108
+ }
109
+ }
110
+ }
111
+ }
112
+ },
113
+ "file": {
114
+ "type": "object",
115
+ "additionalProperties": false,
116
+ "required": [
117
+ "path",
118
+ "action",
119
+ "preimageDigest",
120
+ "outputDigest"
121
+ ],
122
+ "properties": {
123
+ "path": {
124
+ "type": "string",
125
+ "minLength": 1,
126
+ "not": {
127
+ "anyOf": [
128
+ {
129
+ "pattern": "^/"
130
+ },
131
+ {
132
+ "pattern": "\\\\"
133
+ },
134
+ {
135
+ "pattern": "(^|/)\\.\\.(/|$)"
136
+ }
137
+ ]
138
+ }
139
+ },
140
+ "action": {
141
+ "enum": [
142
+ "create",
143
+ "delete",
144
+ "unchanged",
145
+ "update"
146
+ ]
147
+ },
148
+ "preimageDigest": {
149
+ "$ref": "#/$defs/nullableDigest"
150
+ },
151
+ "outputDigest": {
152
+ "$ref": "#/$defs/nullableDigest"
153
+ }
154
+ },
155
+ "allOf": [
156
+ {
157
+ "if": {
158
+ "properties": {
159
+ "action": {
160
+ "const": "create"
161
+ }
162
+ },
163
+ "required": [
164
+ "action"
165
+ ]
166
+ },
167
+ "then": {
168
+ "properties": {
169
+ "preimageDigest": {
170
+ "const": null
171
+ },
172
+ "outputDigest": {
173
+ "$ref": "#/$defs/digest"
174
+ }
175
+ }
176
+ }
177
+ },
178
+ {
179
+ "if": {
180
+ "properties": {
181
+ "action": {
182
+ "const": "delete"
183
+ }
184
+ },
185
+ "required": [
186
+ "action"
187
+ ]
188
+ },
189
+ "then": {
190
+ "properties": {
191
+ "preimageDigest": {
192
+ "$ref": "#/$defs/digest"
193
+ },
194
+ "outputDigest": {
195
+ "const": null
196
+ }
197
+ }
198
+ }
199
+ },
200
+ {
201
+ "if": {
202
+ "properties": {
203
+ "action": {
204
+ "enum": [
205
+ "unchanged",
206
+ "update"
207
+ ]
208
+ }
209
+ },
210
+ "required": [
211
+ "action"
212
+ ]
213
+ },
214
+ "then": {
215
+ "properties": {
216
+ "preimageDigest": {
217
+ "$ref": "#/$defs/digest"
218
+ },
219
+ "outputDigest": {
220
+ "$ref": "#/$defs/digest"
221
+ }
222
+ }
223
+ }
224
+ }
225
+ ]
226
+ },
227
+ "humanAction": {
228
+ "type": "object",
229
+ "additionalProperties": false,
230
+ "required": [
231
+ "reasonCode",
232
+ "affectedNodeIds",
233
+ "requestPayloadDigest"
234
+ ],
235
+ "properties": {
236
+ "reasonCode": {
237
+ "enum": [
238
+ "adoption-required",
239
+ "manual-region-conflict",
240
+ "target-collision",
241
+ "unprovable-required-flow",
242
+ "unresolved-major-change"
243
+ ]
244
+ },
245
+ "affectedNodeIds": {
246
+ "type": "array",
247
+ "uniqueItems": true,
248
+ "items": {
249
+ "type": "string",
250
+ "minLength": 1
251
+ }
252
+ },
253
+ "requestPayloadDigest": {
254
+ "$ref": "#/$defs/digest"
255
+ }
256
+ }
257
+ },
258
+ "digestSet": {
259
+ "type": "object",
260
+ "additionalProperties": false,
261
+ "required": [
262
+ "modelDigest",
263
+ "sourceTreeDigest",
264
+ "flowProofDigest",
265
+ "projectionDigest"
266
+ ],
267
+ "properties": {
268
+ "modelDigest": {
269
+ "$ref": "#/$defs/digest"
270
+ },
271
+ "sourceTreeDigest": {
272
+ "$ref": "#/$defs/digest"
273
+ },
274
+ "flowProofDigest": {
275
+ "$ref": "#/$defs/digest"
276
+ },
277
+ "projectionDigest": {
278
+ "$ref": "#/$defs/digest"
279
+ }
280
+ }
281
+ },
282
+ "reasonCode": {
283
+ "enum": [
284
+ "constraint-changed",
285
+ "entrypoint-changed",
286
+ "interface-changed",
287
+ "lifecycle-changed",
288
+ "node-added",
289
+ "node-moved",
290
+ "node-removed",
291
+ "node-renamed",
292
+ "ownership-changed",
293
+ "relation-changed",
294
+ "responsibility-changed",
295
+ "risk-boundary-changed",
296
+ "verified-flow-proof-changed"
297
+ ]
298
+ },
299
+ "refreshSignal": {
300
+ "type": "object",
301
+ "additionalProperties": false,
302
+ "required": [
303
+ "schemaVersion",
304
+ "signalId",
305
+ "idempotencyKey",
306
+ "mode",
307
+ "repository",
308
+ "worktree",
309
+ "cause",
310
+ "reasonCodes",
311
+ "affectedNodeIds",
312
+ "refreshTargets",
313
+ "baseDigests",
314
+ "resultingDigests",
315
+ "projectionReceiptDigest"
316
+ ],
317
+ "properties": {
318
+ "schemaVersion": {
319
+ "const": "archcontext.architecture-refresh-signal/v1"
320
+ },
321
+ "signalId": {
322
+ "$ref": "#/$defs/digest"
323
+ },
324
+ "idempotencyKey": {
325
+ "$ref": "#/$defs/digest"
326
+ },
327
+ "mode": {
328
+ "enum": [
329
+ "human-action-required",
330
+ "refresh-required"
331
+ ]
332
+ },
333
+ "repository": {
334
+ "type": "object",
335
+ "additionalProperties": false,
336
+ "required": [
337
+ "repositoryId"
338
+ ],
339
+ "properties": {
340
+ "repositoryId": {
341
+ "type": "string",
342
+ "minLength": 1
343
+ }
344
+ }
345
+ },
346
+ "worktree": {
347
+ "type": "object",
348
+ "additionalProperties": false,
349
+ "required": [
350
+ "workspaceId",
351
+ "headSha",
352
+ "worktreeDigest"
353
+ ],
354
+ "properties": {
355
+ "workspaceId": {
356
+ "type": "string",
357
+ "minLength": 1
358
+ },
359
+ "headSha": {
360
+ "type": "string",
361
+ "pattern": "^[a-f0-9]{40}$"
362
+ },
363
+ "worktreeDigest": {
364
+ "$ref": "#/$defs/digest"
365
+ }
366
+ }
367
+ },
368
+ "cause": {
369
+ "enum": [
370
+ "accepted-semantic-delta",
371
+ "unresolved-major-candidate",
372
+ "verified-flow-proof-delta"
373
+ ]
374
+ },
375
+ "acceptedChange": {
376
+ "$ref": "#/$defs/acceptedChange"
377
+ },
378
+ "reasonCodes": {
379
+ "type": "array",
380
+ "minItems": 1,
381
+ "uniqueItems": true,
382
+ "items": {
383
+ "$ref": "#/$defs/reasonCode"
384
+ }
385
+ },
386
+ "affectedNodeIds": {
387
+ "type": "array",
388
+ "minItems": 1,
389
+ "uniqueItems": true,
390
+ "items": {
391
+ "type": "string",
392
+ "minLength": 1
393
+ }
394
+ },
395
+ "refreshTargets": {
396
+ "type": "array",
397
+ "minItems": 1,
398
+ "uniqueItems": true,
399
+ "items": {
400
+ "enum": [
401
+ "architecture-contract-context",
402
+ "architecture-readiness",
403
+ "architecture-request-index",
404
+ "capability-context",
405
+ "capability-index"
406
+ ]
407
+ }
408
+ },
409
+ "baseDigests": {
410
+ "$ref": "#/$defs/digestSet"
411
+ },
412
+ "resultingDigests": {
413
+ "$ref": "#/$defs/digestSet"
414
+ },
415
+ "projectionReceiptDigest": {
416
+ "$ref": "#/$defs/digest"
417
+ }
418
+ },
419
+ "allOf": [
420
+ {
421
+ "if": {
422
+ "properties": {
423
+ "cause": {
424
+ "const": "unresolved-major-candidate"
425
+ }
426
+ },
427
+ "required": [
428
+ "cause"
429
+ ]
430
+ },
431
+ "then": {
432
+ "properties": {
433
+ "mode": {
434
+ "const": "human-action-required"
435
+ }
436
+ },
437
+ "not": {
438
+ "required": [
439
+ "acceptedChange"
440
+ ]
441
+ }
442
+ },
443
+ "else": {
444
+ "properties": {
445
+ "mode": {
446
+ "const": "refresh-required"
447
+ }
448
+ },
449
+ "required": [
450
+ "acceptedChange"
451
+ ]
452
+ }
453
+ }
454
+ ]
455
+ },
456
+ "acceptedChange": {
457
+ "type": "object",
458
+ "additionalProperties": false,
459
+ "required": [
460
+ "changeSetId",
461
+ "eventId",
462
+ "reasonCodes",
463
+ "affectedNodeIds"
464
+ ],
465
+ "properties": {
466
+ "changeSetId": {
467
+ "type": "string",
468
+ "minLength": 1
469
+ },
470
+ "eventId": {
471
+ "type": "string",
472
+ "minLength": 1
473
+ },
474
+ "reasonCodes": {
475
+ "type": "array",
476
+ "minItems": 1,
477
+ "uniqueItems": true,
478
+ "items": {
479
+ "$ref": "#/$defs/reasonCode"
480
+ }
481
+ },
482
+ "affectedNodeIds": {
483
+ "type": "array",
484
+ "minItems": 1,
485
+ "uniqueItems": true,
486
+ "items": {
487
+ "type": "string",
488
+ "minLength": 1
489
+ }
490
+ }
491
+ }
492
+ },
493
+ "priorCommittedApply": {
494
+ "type": "object",
495
+ "additionalProperties": false,
496
+ "required": [
497
+ "requestId",
498
+ "changeSetId",
499
+ "committedAt",
500
+ "files"
501
+ ],
502
+ "properties": {
503
+ "applyId": {
504
+ "$ref": "#/$defs/digest"
505
+ },
506
+ "lookupKey": {
507
+ "$ref": "#/$defs/digest"
508
+ },
509
+ "requestId": {
510
+ "type": "string",
511
+ "pattern": "^[a-zA-Z0-9_.:-]+$",
512
+ "minLength": 1
513
+ },
514
+ "changeSetId": {
515
+ "type": "string",
516
+ "minLength": 1
517
+ },
518
+ "committedAt": {
519
+ "type": "string",
520
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{1,3})?Z$"
521
+ },
522
+ "files": {
523
+ "type": "array",
524
+ "minItems": 1,
525
+ "description": "Canonical wire order is by path and is enforced by projectionResultInvariantIssues.",
526
+ "items": {
527
+ "type": "object",
528
+ "additionalProperties": false,
529
+ "required": [
530
+ "path",
531
+ "operation",
532
+ "hash"
533
+ ],
534
+ "properties": {
535
+ "path": {
536
+ "type": "string",
537
+ "minLength": 1,
538
+ "not": {
539
+ "anyOf": [
540
+ {
541
+ "pattern": "^/"
542
+ },
543
+ {
544
+ "pattern": "\\\\"
545
+ },
546
+ {
547
+ "pattern": "(^|/)\\.\\.(/|$)"
548
+ }
549
+ ]
550
+ }
551
+ },
552
+ "operation": {
553
+ "enum": [
554
+ "delete",
555
+ "write"
556
+ ]
557
+ },
558
+ "hash": {
559
+ "type": "string",
560
+ "pattern": "^(?:sha256:[a-f0-9]{64}|missing)$"
561
+ }
562
+ },
563
+ "allOf": [
564
+ {
565
+ "if": {
566
+ "properties": {
567
+ "operation": {
568
+ "const": "delete"
569
+ }
570
+ },
571
+ "required": [
572
+ "operation"
573
+ ]
574
+ },
575
+ "then": {
576
+ "properties": {
577
+ "hash": {
578
+ "const": "missing"
579
+ }
580
+ }
581
+ },
582
+ "else": {
583
+ "properties": {
584
+ "hash": {
585
+ "$ref": "#/$defs/digest"
586
+ }
587
+ }
588
+ }
589
+ }
590
+ ]
591
+ }
592
+ }
593
+ },
594
+ "dependentRequired": {
595
+ "applyId": [
596
+ "lookupKey"
597
+ ],
598
+ "lookupKey": [
599
+ "applyId"
600
+ ]
601
+ }
602
+ },
603
+ "applyIdentity": {
604
+ "type": "object",
605
+ "additionalProperties": false,
606
+ "required": [
607
+ "schemaVersion",
608
+ "applyId",
609
+ "lookupKey",
610
+ "repositoryId",
611
+ "workspaceId",
612
+ "acceptedChange",
613
+ "semanticCommit",
614
+ "ownedFilesDigest",
615
+ "refreshSignalsDigest"
616
+ ],
617
+ "properties": {
618
+ "schemaVersion": {
619
+ "const": "archcontext.projection-apply-identity/v1"
620
+ },
621
+ "applyId": {
622
+ "$ref": "#/$defs/digest"
623
+ },
624
+ "lookupKey": {
625
+ "$ref": "#/$defs/digest"
626
+ },
627
+ "repositoryId": {
628
+ "type": "string",
629
+ "minLength": 1
630
+ },
631
+ "workspaceId": {
632
+ "type": "string",
633
+ "minLength": 1
634
+ },
635
+ "acceptedChange": {
636
+ "$ref": "#/$defs/acceptedChange"
637
+ },
638
+ "semanticCommit": {
639
+ "type": "object",
640
+ "additionalProperties": false,
641
+ "required": [
642
+ "changeSetId",
643
+ "idempotencyKey"
644
+ ],
645
+ "properties": {
646
+ "changeSetId": {
647
+ "type": "string",
648
+ "minLength": 1
649
+ },
650
+ "idempotencyKey": {
651
+ "type": "string",
652
+ "minLength": 1
653
+ }
654
+ }
655
+ },
656
+ "ownedFilesDigest": {
657
+ "$ref": "#/$defs/digest"
658
+ },
659
+ "refreshSignalsDigest": {
660
+ "$ref": "#/$defs/digest"
661
+ }
662
+ }
663
+ },
664
+ "projectionResult": {
665
+ "type": "object",
666
+ "additionalProperties": false,
667
+ "required": [
668
+ "schemaVersion",
669
+ "requestId",
670
+ "status",
671
+ "inputSnapshot",
672
+ "outputSnapshot",
673
+ "affectedNodeIds",
674
+ "files",
675
+ "humanActions",
676
+ "refreshSignals",
677
+ "receiptDigest"
678
+ ],
679
+ "properties": {
680
+ "schemaVersion": {
681
+ "const": "archcontext.projection-result/v2"
682
+ },
683
+ "requestId": {
684
+ "type": "string",
685
+ "pattern": "^[a-zA-Z0-9_.:-]+$",
686
+ "minLength": 1
687
+ },
688
+ "status": {
689
+ "enum": [
690
+ "adoption-required",
691
+ "applied",
692
+ "applied-reconcile-required",
693
+ "blocked",
694
+ "human-action-required",
695
+ "noop",
696
+ "permanent-failure",
697
+ "planned",
698
+ "retryable-failure"
699
+ ]
700
+ },
701
+ "inputSnapshot": {
702
+ "$ref": "#/$defs/snapshot"
703
+ },
704
+ "outputSnapshot": {
705
+ "$ref": "#/$defs/snapshot"
706
+ },
707
+ "affectedNodeIds": {
708
+ "type": "array",
709
+ "uniqueItems": true,
710
+ "description": "Canonical wire order is lexicographic and is enforced by projectionResultInvariantIssues.",
711
+ "items": {
712
+ "type": "string",
713
+ "minLength": 1
714
+ }
715
+ },
716
+ "files": {
717
+ "type": "array",
718
+ "description": "Canonical wire order is by path and is enforced by projectionResultInvariantIssues.",
719
+ "items": {
720
+ "$ref": "#/$defs/file"
721
+ }
722
+ },
723
+ "humanActions": {
724
+ "type": "array",
725
+ "items": {
726
+ "$ref": "#/$defs/humanAction"
727
+ }
728
+ },
729
+ "refreshSignals": {
730
+ "type": "array",
731
+ "description": "Canonical wire order is by signalId and cross-object receipt/snapshot bindings are enforced by projectionResultInvariantIssues.",
732
+ "items": {
733
+ "$ref": "#/$defs/refreshSignal"
734
+ }
735
+ },
736
+ "applyReceipt": {
737
+ "$ref": "#/$defs/applyIdentity"
738
+ },
739
+ "priorCommittedApplies": {
740
+ "type": "array",
741
+ "minItems": 1,
742
+ "description": "Omitted, never empty. Canonical wire order is by changeSetId and is enforced by projectionResultInvariantIssues.",
743
+ "items": {
744
+ "$ref": "#/$defs/priorCommittedApply"
745
+ }
746
+ },
747
+ "receiptDigest": {
748
+ "$ref": "#/$defs/digest"
749
+ }
750
+ },
751
+ "allOf": [
752
+ {
753
+ "if": {
754
+ "properties": {
755
+ "status": {
756
+ "enum": [
757
+ "adoption-required",
758
+ "human-action-required"
759
+ ]
760
+ }
761
+ },
762
+ "required": [
763
+ "status"
764
+ ]
765
+ },
766
+ "then": {
767
+ "properties": {
768
+ "humanActions": {
769
+ "minItems": 1
770
+ }
771
+ }
772
+ },
773
+ "else": {
774
+ "properties": {
775
+ "humanActions": {
776
+ "maxItems": 0
777
+ }
778
+ }
779
+ }
780
+ },
781
+ {
782
+ "if": {
783
+ "properties": {
784
+ "status": {
785
+ "const": "applied-reconcile-required"
786
+ }
787
+ },
788
+ "required": [
789
+ "status"
790
+ ]
791
+ },
792
+ "then": {
793
+ "required": [
794
+ "applyReceipt"
795
+ ],
796
+ "properties": {
797
+ "refreshSignals": {
798
+ "maxItems": 0
799
+ }
800
+ }
801
+ }
802
+ }
803
+ ]
804
+ },
805
+ "expectedSnapshot": {
806
+ "type": "object",
807
+ "additionalProperties": false,
808
+ "required": [
809
+ "repositoryId",
810
+ "workspaceId",
811
+ "headSha",
812
+ "worktreeDigest"
813
+ ],
814
+ "properties": {
815
+ "repositoryId": {
816
+ "type": "string",
817
+ "minLength": 1
818
+ },
819
+ "workspaceId": {
820
+ "type": "string",
821
+ "minLength": 1
822
+ },
823
+ "headSha": {
824
+ "type": "string",
825
+ "pattern": "^[a-f0-9]{40}$"
826
+ },
827
+ "worktreeDigest": {
828
+ "$ref": "#/$defs/digest"
829
+ }
830
+ }
831
+ },
832
+ "repoPath": {
833
+ "type": "string",
834
+ "minLength": 1,
835
+ "not": {
836
+ "anyOf": [
837
+ {
838
+ "pattern": "^/"
839
+ },
840
+ {
841
+ "pattern": "\\\\"
842
+ },
843
+ {
844
+ "pattern": "(^|/)\\.\\.(/|$)"
845
+ }
846
+ ]
847
+ }
848
+ },
849
+ "recoveryBinding": {
850
+ "type": "object",
851
+ "additionalProperties": false,
852
+ "required": [
853
+ "schemaVersion",
854
+ "targets",
855
+ "changedPaths",
856
+ "originalExpectedSnapshot",
857
+ "expectedResultingDigests",
858
+ "rendererVersion",
859
+ "layoutVersion",
860
+ "generatedFrom",
861
+ "ownedOutputDigest",
862
+ "receiptDigest"
863
+ ],
864
+ "properties": {
865
+ "schemaVersion": {
866
+ "const": "archcontext.projection-apply-recovery-binding/v1"
867
+ },
868
+ "targets": {
869
+ "type": "array",
870
+ "minItems": 1,
871
+ "uniqueItems": true,
872
+ "description": "Canonical wire order is lexicographic and is enforced by projectionRequestInvariantIssues.",
873
+ "items": {
874
+ "enum": [
875
+ "agent-context",
876
+ "architecture-docs"
877
+ ]
878
+ }
879
+ },
880
+ "changedPaths": {
881
+ "type": "array",
882
+ "uniqueItems": true,
883
+ "description": "Canonical wire order is lexicographic and is enforced by projectionRequestInvariantIssues.",
884
+ "items": {
885
+ "$ref": "#/$defs/repoPath"
886
+ }
887
+ },
888
+ "originalExpectedSnapshot": {
889
+ "$ref": "#/$defs/expectedSnapshot"
890
+ },
891
+ "expectedResultingDigests": {
892
+ "$ref": "#/$defs/digestSet"
893
+ },
894
+ "rendererVersion": {
895
+ "const": "archcontext.docs-renderer/v4"
896
+ },
897
+ "layoutVersion": {
898
+ "const": "archcontext.docs-layout/v1"
899
+ },
900
+ "generatedFrom": {
901
+ "type": "object",
902
+ "additionalProperties": false,
903
+ "required": [
904
+ "codeGraphPackage",
905
+ "codeGraphVersion",
906
+ "codeGraphBinaryDigest",
907
+ "codeGraphStatus"
908
+ ],
909
+ "properties": {
910
+ "codeGraphPackage": {
911
+ "const": "@colbymchenry/codegraph"
912
+ },
913
+ "codeGraphVersion": {
914
+ "const": "1.5.0"
915
+ },
916
+ "codeGraphBinaryDigest": {
917
+ "$ref": "#/$defs/digest"
918
+ },
919
+ "codeGraphStatus": {
920
+ "enum": [
921
+ "ready",
922
+ "unavailable"
923
+ ]
924
+ }
925
+ }
926
+ },
927
+ "ownedOutputDigest": {
928
+ "$ref": "#/$defs/digest"
929
+ },
930
+ "receiptDigest": {
931
+ "$ref": "#/$defs/digest"
932
+ }
933
+ }
934
+ },
935
+ "receipt": {
936
+ "type": "object",
937
+ "additionalProperties": false,
938
+ "required": [
939
+ "schemaVersion",
940
+ "identity",
941
+ "result",
942
+ "recovery"
943
+ ],
944
+ "properties": {
945
+ "schemaVersion": {
946
+ "const": "archcontext.projection-apply-receipt/v1"
947
+ },
948
+ "identity": {
949
+ "$ref": "#/$defs/applyIdentity"
950
+ },
951
+ "result": {
952
+ "$ref": "#/$defs/projectionResult"
953
+ },
954
+ "recovery": {
955
+ "$ref": "#/$defs/recoveryBinding"
956
+ }
957
+ }
958
+ },
959
+ "readbackResult": {
960
+ "type": "object",
961
+ "additionalProperties": false,
962
+ "required": [
963
+ "schemaVersion",
964
+ "requestId",
965
+ "requestDigest",
966
+ "receipt",
967
+ "current",
968
+ "readbackDigest"
969
+ ],
970
+ "properties": {
971
+ "schemaVersion": {
972
+ "const": "archcontext.projection-apply-readback-result/v1"
973
+ },
974
+ "requestId": {
975
+ "type": "string",
976
+ "pattern": "^[a-zA-Z0-9_.:-]+$",
977
+ "minLength": 1
978
+ },
979
+ "requestDigest": {
980
+ "$ref": "#/$defs/digest"
981
+ },
982
+ "receipt": {
983
+ "$ref": "#/$defs/receipt"
984
+ },
985
+ "current": {
986
+ "type": "object",
987
+ "additionalProperties": false,
988
+ "required": [
989
+ "snapshot",
990
+ "resultingDigests",
991
+ "ownedOutputDigest",
992
+ "fixedPointDigest"
993
+ ],
994
+ "properties": {
995
+ "snapshot": {
996
+ "allOf": [
997
+ {
998
+ "$ref": "#/$defs/snapshot"
999
+ },
1000
+ {
1001
+ "properties": {
1002
+ "generatedFrom": {
1003
+ "properties": {
1004
+ "codeGraphStatus": {
1005
+ "const": "ready"
1006
+ }
1007
+ }
1008
+ }
1009
+ }
1010
+ }
1011
+ ]
1012
+ },
1013
+ "resultingDigests": {
1014
+ "$ref": "#/$defs/digestSet"
1015
+ },
1016
+ "ownedOutputDigest": {
1017
+ "$ref": "#/$defs/digest"
1018
+ },
1019
+ "fixedPointDigest": {
1020
+ "$ref": "#/$defs/digest"
1021
+ }
1022
+ }
1023
+ },
1024
+ "readbackDigest": {
1025
+ "$ref": "#/$defs/digest"
1026
+ }
1027
+ }
1028
+ },
1029
+ "absence": {
1030
+ "type": "object",
1031
+ "additionalProperties": false,
1032
+ "required": [
1033
+ "schemaVersion",
1034
+ "requestId",
1035
+ "requestDigest",
1036
+ "lookupKey",
1037
+ "current",
1038
+ "absenceDigest"
1039
+ ],
1040
+ "properties": {
1041
+ "schemaVersion": {
1042
+ "const": "archcontext.projection-apply-absence/v1"
1043
+ },
1044
+ "requestId": {
1045
+ "type": "string",
1046
+ "pattern": "^[a-zA-Z0-9_.:-]+$",
1047
+ "minLength": 1
1048
+ },
1049
+ "requestDigest": {
1050
+ "$ref": "#/$defs/digest"
1051
+ },
1052
+ "lookupKey": {
1053
+ "$ref": "#/$defs/digest"
1054
+ },
1055
+ "current": {
1056
+ "$ref": "#/$defs/expectedSnapshot"
1057
+ },
1058
+ "absenceDigest": {
1059
+ "$ref": "#/$defs/digest"
1060
+ }
1061
+ }
1062
+ }
1063
+ }
1064
+ }
@@ -1,5 +1,5 @@
1
1
  export const ARCHCONTEXT_PRODUCT_NAME = "archctx";
2
- export const ARCHCONTEXT_PRODUCT_VERSION = "0.5.9";
2
+ export const ARCHCONTEXT_PRODUCT_VERSION = "0.5.11";
3
3
  export const ARCHCONTEXT_PACKAGE_MANAGER = "bun@1.4.0";
4
4
  export const ARCHCONTEXT_NODE_RANGE = ">=22.22 <26";
5
5
  export const LOCAL_RUNTIME_RPC_SCHEMA_VERSION = "archcontext.runtime-rpc/v1";
package/src/projection.ts CHANGED
@@ -8,6 +8,7 @@ export const PROJECTION_APPLY_RECOVERY_BINDING_SCHEMA_VERSION = "archcontext.pro
8
8
  export const PROJECTION_APPLY_RECOVERY_INTENT_SCHEMA_VERSION = "archcontext.projection-apply-recovery-intent/v1" as const;
9
9
  export const PROJECTION_APPLY_RECOVERY_PROOF_SCHEMA_VERSION = "archcontext.projection-apply-recovery-proof/v1" as const;
10
10
  export const PROJECTION_APPLY_RECOVERY_RESULT_SCHEMA_VERSION = "archcontext.projection-apply-recovery-result/v1" as const;
11
+ export const PROJECTION_APPLY_READBACK_RESULT_SCHEMA_VERSION = "archcontext.projection-apply-readback-result/v1" as const;
11
12
  export const ARCHITECTURE_REFRESH_SIGNAL_SCHEMA_VERSION = "archcontext.architecture-refresh-signal/v1" as const;
12
13
  export const ARCHCTX_CAPABILITIES_SCHEMA_VERSION = "archcontext.capabilities/v1" as const;
13
14
  export const ARCHITECTURE_DOCS_RENDERER_VERSION = "archcontext.docs-renderer/v4" as const;
@@ -60,6 +61,7 @@ export const ARCHCTX_FEATURES = [
60
61
  "architecture-docs-renderer-v2",
61
62
  "architecture-refresh-signal-v1",
62
63
  "module-statistics-v1",
64
+ "projection-apply-readback-v1",
63
65
  "projection-apply-receipt-v1",
64
66
  "projection-apply-recovery-v1",
65
67
  "projection-prior-committed-applies-v1",
@@ -291,6 +293,28 @@ export interface ProjectionApplyRecoveryResultV1 {
291
293
  refreshSignals: ArchitectureRefreshSignalV1[];
292
294
  }
293
295
 
296
+ /** Non-consuming receipt retrieval; current state is rebuilt for every response. */
297
+ export interface ProjectionApplyReadbackResultV1 {
298
+ schemaVersion: typeof PROJECTION_APPLY_READBACK_RESULT_SCHEMA_VERSION;
299
+ requestId: string;
300
+ requestDigest: Sha256Digest;
301
+ receipt: ProjectionApplyReceiptV1;
302
+ current: ProjectionApplyRecoveryProofV1["current"];
303
+ readbackDigest: Sha256Digest;
304
+ }
305
+
306
+ /** Exact-request absence observed under the same writer boundary used by apply. */
307
+ export interface ProjectionApplyAbsenceV1 {
308
+ schemaVersion: "archcontext.projection-apply-absence/v1";
309
+ requestId: string;
310
+ requestDigest: Sha256Digest;
311
+ lookupKey: Sha256Digest;
312
+ current: ProjectionExpectedSnapshotV1;
313
+ absenceDigest: Sha256Digest;
314
+ }
315
+
316
+ export type ProjectionApplyReadbackV1 = ProjectionApplyReadbackResultV1 | ProjectionApplyAbsenceV1;
317
+
294
318
  export interface ArchctxCapabilitiesV1 {
295
319
  schemaVersion: typeof ARCHCTX_CAPABILITIES_SCHEMA_VERSION;
296
320
  package: {
@@ -550,6 +574,89 @@ export function projectionApplyRecoveryBindingInvariantIssues(
550
574
  return issues;
551
575
  }
552
576
 
577
+ /** Readback carries the original accepted apply request, never caller-authored receipt data. */
578
+ export function projectionApplyReadbackRequestInvariantIssues(request: ProjectionRequestV1): string[] {
579
+ const issues = projectionRequestInvariantIssues(request);
580
+ const allowed = new Set(["schemaVersion", "requestId", "profile", "mode", "targets", "changedPaths", "expected", "acceptedChange"]);
581
+ if (Object.keys(request).some((key) => !allowed.has(key))) issues.push("readback request contains unsupported fields");
582
+ if (request.mode !== "apply" || !request.acceptedChange) issues.push("readback requires an accepted apply request");
583
+ if (request.schemaVersion !== PROJECTION_REQUEST_SCHEMA_VERSION || request.profile !== "repo-harness/v1") issues.push("readback request protocol is invalid");
584
+ if (typeof request.requestId !== "string"
585
+ || request.targets.some((target) => !(PROJECTION_TARGETS as readonly string[]).includes(target))
586
+ || request.changedPaths.some((path) => typeof path !== "string" || !isRepoRelativePosixPath(path))) issues.push("readback request fields are invalid");
587
+ const expectedKeys = ["repositoryId", "workspaceId", "headSha", "worktreeDigest"];
588
+ if (Object.keys(request.expected).some((key) => !expectedKeys.includes(key))
589
+ || expectedKeys.some((key) => typeof request.expected[key as keyof ProjectionExpectedSnapshotV1] !== "string")
590
+ || !request.expected.repositoryId || !request.expected.workspaceId
591
+ || !/^[a-f0-9]{40}$/.test(request.expected.headSha)
592
+ || !SHA256_DIGEST.test(request.expected.worktreeDigest)) issues.push("readback expected snapshot is invalid");
593
+ if (request.acceptedChange && Object.keys(request.acceptedChange).some((key) => !["changeSetId", "eventId", "reasonCodes", "affectedNodeIds"].includes(key))) {
594
+ issues.push("readback accepted change contains unsupported fields");
595
+ }
596
+ return issues;
597
+ }
598
+
599
+ export function projectionApplyAbsenceInvariantIssues(input: ProjectionApplyAbsenceV1, request: ProjectionRequestV1): string[] {
600
+ const issues = projectionApplyReadbackRequestInvariantIssues(request);
601
+ if (input.schemaVersion !== "archcontext.projection-apply-absence/v1") issues.push("absence schemaVersion is invalid");
602
+ if (Object.keys(input).some((key) => !["schemaVersion", "requestId", "requestDigest", "lookupKey", "current", "absenceDigest"].includes(key))) issues.push("absence contains unsupported fields");
603
+ const { absenceDigest, ...body } = input;
604
+ if (absenceDigest !== digestJson(body as unknown as Json)) issues.push("absenceDigest must bind the complete absence result");
605
+ if (input.requestId !== request.requestId || input.requestDigest !== digestJson(request as unknown as Json)) issues.push("absence request identity mismatch");
606
+ if (digestJson(input.current as unknown as Json) !== digestJson(request.expected as unknown as Json)) issues.push("absence current snapshot differs from request");
607
+ if (!request.acceptedChange || input.lookupKey !== projectionApplyLookupKey({
608
+ repositoryId: request.expected.repositoryId, workspaceId: request.expected.workspaceId, acceptedChange: request.acceptedChange
609
+ })) issues.push("absence lookup identity mismatch");
610
+ return issues;
611
+ }
612
+
613
+ export function projectionApplyReadbackResultDigest(input: Omit<ProjectionApplyReadbackResultV1, "readbackDigest">): Sha256Digest {
614
+ return digestJson(input as unknown as Json) as Sha256Digest;
615
+ }
616
+
617
+ export function projectionApplyReadbackResultInvariantIssues(
618
+ input: ProjectionApplyReadbackResultV1,
619
+ request?: ProjectionRequestV1
620
+ ): string[] {
621
+ const issues = projectionApplyReceiptInvariantIssues(input.receipt);
622
+ const { readbackDigest, ...body } = input;
623
+ if (input.schemaVersion !== PROJECTION_APPLY_READBACK_RESULT_SCHEMA_VERSION) issues.push("readback schemaVersion is invalid");
624
+ if (projectionApplyReadbackResultDigest(body) !== readbackDigest) issues.push("readbackDigest must bind the complete readback result");
625
+ if (!/^[a-zA-Z0-9_.:-]+$/.test(input.requestId)) issues.push("readback requestId is invalid");
626
+ for (const value of [input.requestDigest, input.current.ownedOutputDigest, input.current.fixedPointDigest]) {
627
+ if (!/^sha256:[a-f0-9]{64}$/.test(value)) issues.push("readback digest is invalid");
628
+ }
629
+ const receipt = input.receipt;
630
+ if (receipt.schemaVersion !== PROJECTION_APPLY_RECEIPT_SCHEMA_VERSION) issues.push("readback receipt schemaVersion is invalid");
631
+ const binding = receipt.recovery;
632
+ if (!binding) return [...issues, "committed receipt lacks its original recovery binding"];
633
+ for (const field of ["repositoryId", "workspaceId", "headSha", "worktreeDigest"] as const) {
634
+ if (input.current.snapshot[field] !== binding.originalExpectedSnapshot[field]) issues.push(`readback current ${field} differs from approval`);
635
+ }
636
+ if (input.current.snapshot.generatedFrom.codeGraphStatus !== "ready"
637
+ || input.current.snapshot.rendererVersion !== binding.rendererVersion
638
+ || input.current.snapshot.layoutVersion !== binding.layoutVersion
639
+ || input.current.snapshot.projectionInputDigest !== receipt.result.outputSnapshot.projectionInputDigest
640
+ || input.current.snapshot.codeGraphDigest !== receipt.result.outputSnapshot.codeGraphDigest
641
+ || digestJson(input.current.snapshot.generatedFrom as unknown as Json) !== digestJson(binding.generatedFrom as unknown as Json)
642
+ || digestJson(input.current.resultingDigests as unknown as Json) !== digestJson(binding.expectedResultingDigests as unknown as Json)
643
+ || input.current.ownedOutputDigest !== binding.ownedOutputDigest) {
644
+ issues.push("readback current state differs from committed recovery binding");
645
+ }
646
+ if (input.requestId !== receipt.result.requestId) issues.push("readback requestId differs from committed request");
647
+ if (request) {
648
+ issues.push(...projectionApplyReadbackRequestInvariantIssues(request));
649
+ if (input.requestDigest !== digestJson(request as unknown as Json) || input.requestId !== request.requestId) issues.push("readback request identity mismatch");
650
+ if (digestJson(request.expected as unknown as Json) !== digestJson(binding.originalExpectedSnapshot as unknown as Json)
651
+ || digestJson(request.acceptedChange as unknown as Json) !== digestJson(receipt.identity.acceptedChange as unknown as Json)
652
+ || digestJson(request.targets as unknown as Json) !== digestJson(binding.targets as unknown as Json)
653
+ || digestJson(request.changedPaths as unknown as Json) !== digestJson(binding.changedPaths as unknown as Json)) {
654
+ issues.push("readback request differs from committed approval binding");
655
+ }
656
+ }
657
+ return issues;
658
+ }
659
+
553
660
  export function projectionApplyRecoveryIntentInvariantIssues(input: ProjectionApplyRecoveryIntentV1): string[] {
554
661
  const issues: string[] = [];
555
662
  if (input.schemaVersion !== PROJECTION_APPLY_RECOVERY_INTENT_SCHEMA_VERSION) issues.push("recovery intent schemaVersion is invalid");