instar 1.3.1339 → 1.3.1340

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 (58) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +119 -13
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +15 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  8. package/dist/core/PostUpdateMigrator.js +14 -0
  9. package/dist/core/PostUpdateMigrator.js.map +1 -1
  10. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  11. package/dist/core/devGatedFeatures.js +6 -0
  12. package/dist/core/devGatedFeatures.js.map +1 -1
  13. package/dist/core/types.d.ts +20 -0
  14. package/dist/core/types.d.ts.map +1 -1
  15. package/dist/core/types.js.map +1 -1
  16. package/dist/data/standards-guard-index.json +1 -1
  17. package/dist/data/standards-guard-index.meta.json +2 -2
  18. package/dist/data/standards-registry.meta.json +1 -1
  19. package/dist/monitoring/A2ARedeliverySentinel.d.ts +145 -6
  20. package/dist/monitoring/A2ARedeliverySentinel.d.ts.map +1 -1
  21. package/dist/monitoring/A2ARedeliverySentinel.js +451 -11
  22. package/dist/monitoring/A2ARedeliverySentinel.js.map +1 -1
  23. package/dist/scaffold/templates.d.ts.map +1 -1
  24. package/dist/scaffold/templates.js +4 -0
  25. package/dist/scaffold/templates.js.map +1 -1
  26. package/dist/server/routes.d.ts.map +1 -1
  27. package/dist/server/routes.js +65 -4
  28. package/dist/server/routes.js.map +1 -1
  29. package/dist/testing/selfActionRegistry.d.ts.map +1 -1
  30. package/dist/testing/selfActionRegistry.js +71 -0
  31. package/dist/testing/selfActionRegistry.js.map +1 -1
  32. package/dist/threadline/A2ADeliveryTracker.d.ts +55 -1
  33. package/dist/threadline/A2ADeliveryTracker.d.ts.map +1 -1
  34. package/dist/threadline/A2ADeliveryTracker.js +97 -5
  35. package/dist/threadline/A2ADeliveryTracker.js.map +1 -1
  36. package/dist/threadline/ThreadlineMCPServer.d.ts +15 -0
  37. package/dist/threadline/ThreadlineMCPServer.d.ts.map +1 -1
  38. package/dist/threadline/ThreadlineMCPServer.js +3 -0
  39. package/dist/threadline/ThreadlineMCPServer.js.map +1 -1
  40. package/dist/threadline/client/ThreadlineClient.d.ts +47 -0
  41. package/dist/threadline/client/ThreadlineClient.d.ts.map +1 -1
  42. package/dist/threadline/client/ThreadlineClient.js +93 -0
  43. package/dist/threadline/client/ThreadlineClient.js.map +1 -1
  44. package/dist/threadline/mcp-http-client.d.ts.map +1 -1
  45. package/dist/threadline/mcp-http-client.js +2 -0
  46. package/dist/threadline/mcp-http-client.js.map +1 -1
  47. package/dist/threadline/peerDark.d.ts +165 -0
  48. package/dist/threadline/peerDark.d.ts.map +1 -0
  49. package/dist/threadline/peerDark.js +204 -0
  50. package/dist/threadline/peerDark.js.map +1 -0
  51. package/package.json +1 -1
  52. package/src/data/builtin-manifest.json +63 -63
  53. package/src/data/standards-guard-index.json +1 -1
  54. package/src/data/standards-guard-index.meta.json +2 -2
  55. package/src/data/standards-registry.meta.json +1 -1
  56. package/src/scaffold/templates.ts +4 -0
  57. package/upgrades/1.3.1340.md +32 -0
  58. package/upgrades/side-effects/a2a-peer-dark-reporting.md +149 -0
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-10-11T00:18:12.887Z",
5
- "instarVersion": "1.3.1339",
4
+ "generatedAt": "2026-10-11T00:47:41.474Z",
5
+ "instarVersion": "1.3.1340",
6
6
  "entryCount": 203,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -11,7 +11,7 @@
11
11
  "domain": "identity",
12
12
  "sourcePath": "src/core/PostUpdateMigrator.ts",
13
13
  "installedPath": ".instar/hooks/instar/session-start.sh",
14
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
14
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
15
15
  "since": "2025-01-01"
16
16
  },
17
17
  "hook:dangerous-command-guard": {
@@ -20,7 +20,7 @@
20
20
  "domain": "safety",
21
21
  "sourcePath": "src/core/PostUpdateMigrator.ts",
22
22
  "installedPath": ".instar/hooks/instar/dangerous-command-guard.sh",
23
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
23
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
24
24
  "since": "2025-01-01"
25
25
  },
26
26
  "hook:grounding-before-messaging": {
@@ -29,7 +29,7 @@
29
29
  "domain": "safety",
30
30
  "sourcePath": "src/core/PostUpdateMigrator.ts",
31
31
  "installedPath": ".instar/hooks/instar/grounding-before-messaging.sh",
32
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
32
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
33
33
  "since": "2025-01-01"
34
34
  },
35
35
  "hook:compaction-recovery": {
@@ -38,7 +38,7 @@
38
38
  "domain": "identity",
39
39
  "sourcePath": "src/core/PostUpdateMigrator.ts",
40
40
  "installedPath": ".instar/hooks/instar/compaction-recovery.sh",
41
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
41
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
42
42
  "since": "2025-01-01"
43
43
  },
44
44
  "hook:external-operation-gate": {
@@ -47,7 +47,7 @@
47
47
  "domain": "safety",
48
48
  "sourcePath": "src/core/PostUpdateMigrator.ts",
49
49
  "installedPath": ".instar/hooks/instar/external-operation-gate.js",
50
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
50
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
51
51
  "since": "2025-01-01"
52
52
  },
53
53
  "hook:deferral-detector": {
@@ -56,7 +56,7 @@
56
56
  "domain": "safety",
57
57
  "sourcePath": "src/core/PostUpdateMigrator.ts",
58
58
  "installedPath": ".instar/hooks/instar/deferral-detector.js",
59
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
59
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
60
60
  "since": "2025-01-01"
61
61
  },
62
62
  "hook:self-stop-guard": {
@@ -65,7 +65,7 @@
65
65
  "domain": "coherence",
66
66
  "sourcePath": "src/core/PostUpdateMigrator.ts",
67
67
  "installedPath": ".instar/hooks/instar/self-stop-guard.js",
68
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
68
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
69
69
  "since": "2025-01-01"
70
70
  },
71
71
  "hook:post-action-reflection": {
@@ -74,7 +74,7 @@
74
74
  "domain": "evolution",
75
75
  "sourcePath": "src/core/PostUpdateMigrator.ts",
76
76
  "installedPath": ".instar/hooks/instar/post-action-reflection.js",
77
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
77
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
78
78
  "since": "2025-01-01"
79
79
  },
80
80
  "hook:external-communication-guard": {
@@ -83,7 +83,7 @@
83
83
  "domain": "safety",
84
84
  "sourcePath": "src/core/PostUpdateMigrator.ts",
85
85
  "installedPath": ".instar/hooks/instar/external-communication-guard.js",
86
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
86
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
87
87
  "since": "2025-01-01"
88
88
  },
89
89
  "hook:telegram-origin-guard": {
@@ -101,7 +101,7 @@
101
101
  "domain": "coherence",
102
102
  "sourcePath": "src/core/PostUpdateMigrator.ts",
103
103
  "installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
104
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
104
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
105
105
  "since": "2025-01-01"
106
106
  },
107
107
  "hook:scope-coherence-checkpoint": {
@@ -110,7 +110,7 @@
110
110
  "domain": "coherence",
111
111
  "sourcePath": "src/core/PostUpdateMigrator.ts",
112
112
  "installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
113
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
113
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
114
114
  "since": "2025-01-01"
115
115
  },
116
116
  "hook:free-text-guard": {
@@ -119,7 +119,7 @@
119
119
  "domain": "safety",
120
120
  "sourcePath": "src/core/PostUpdateMigrator.ts",
121
121
  "installedPath": ".instar/hooks/instar/free-text-guard.sh",
122
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
122
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
123
123
  "since": "2025-01-01"
124
124
  },
125
125
  "hook:claim-intercept": {
@@ -128,7 +128,7 @@
128
128
  "domain": "coherence",
129
129
  "sourcePath": "src/core/PostUpdateMigrator.ts",
130
130
  "installedPath": ".instar/hooks/instar/claim-intercept.js",
131
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
131
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
132
132
  "since": "2025-01-01"
133
133
  },
134
134
  "hook:claim-intercept-response": {
@@ -137,7 +137,7 @@
137
137
  "domain": "coherence",
138
138
  "sourcePath": "src/core/PostUpdateMigrator.ts",
139
139
  "installedPath": ".instar/hooks/instar/claim-intercept-response.js",
140
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
140
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
141
141
  "since": "2025-01-01"
142
142
  },
143
143
  "hook:stop-gate-router": {
@@ -146,7 +146,7 @@
146
146
  "domain": "safety",
147
147
  "sourcePath": "src/core/PostUpdateMigrator.ts",
148
148
  "installedPath": ".instar/hooks/instar/stop-gate-router.js",
149
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
149
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
150
150
  "since": "2025-01-01"
151
151
  },
152
152
  "hook:auto-approve-permissions": {
@@ -155,7 +155,7 @@
155
155
  "domain": "safety",
156
156
  "sourcePath": "src/core/PostUpdateMigrator.ts",
157
157
  "installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
158
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
158
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
159
159
  "since": "2025-01-01"
160
160
  },
161
161
  "job:health-check": {
@@ -427,7 +427,7 @@
427
427
  "type": "route-group",
428
428
  "domain": "monitoring",
429
429
  "sourcePath": "src/server/routes.ts",
430
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
430
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
431
431
  "since": "2025-01-01"
432
432
  },
433
433
  "route-group:agents": {
@@ -435,7 +435,7 @@
435
435
  "type": "route-group",
436
436
  "domain": "sessions",
437
437
  "sourcePath": "src/server/routes.ts",
438
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
438
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
439
439
  "since": "2025-01-01"
440
440
  },
441
441
  "route-group:backups": {
@@ -443,7 +443,7 @@
443
443
  "type": "route-group",
444
444
  "domain": "operations",
445
445
  "sourcePath": "src/server/routes.ts",
446
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
446
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
447
447
  "since": "2025-01-01"
448
448
  },
449
449
  "route-group:git": {
@@ -451,7 +451,7 @@
451
451
  "type": "route-group",
452
452
  "domain": "coordination",
453
453
  "sourcePath": "src/server/routes.ts",
454
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
454
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
455
455
  "since": "2025-01-01"
456
456
  },
457
457
  "route-group:memory": {
@@ -459,7 +459,7 @@
459
459
  "type": "route-group",
460
460
  "domain": "memory",
461
461
  "sourcePath": "src/server/routes.ts",
462
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
462
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
463
463
  "since": "2025-01-01"
464
464
  },
465
465
  "route-group:semantic": {
@@ -467,7 +467,7 @@
467
467
  "type": "route-group",
468
468
  "domain": "memory",
469
469
  "sourcePath": "src/server/routes.ts",
470
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
470
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
471
471
  "since": "2025-01-01"
472
472
  },
473
473
  "route-group:status": {
@@ -475,7 +475,7 @@
475
475
  "type": "route-group",
476
476
  "domain": "monitoring",
477
477
  "sourcePath": "src/server/routes.ts",
478
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
478
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
479
479
  "since": "2025-01-01"
480
480
  },
481
481
  "route-group:capabilities": {
@@ -483,7 +483,7 @@
483
483
  "type": "route-group",
484
484
  "domain": "mapping",
485
485
  "sourcePath": "src/server/routes.ts",
486
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
486
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
487
487
  "since": "2025-01-01"
488
488
  },
489
489
  "route-group:project-map": {
@@ -491,7 +491,7 @@
491
491
  "type": "route-group",
492
492
  "domain": "mapping",
493
493
  "sourcePath": "src/server/routes.ts",
494
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
494
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
495
495
  "since": "2025-01-01"
496
496
  },
497
497
  "route-group:coherence": {
@@ -499,7 +499,7 @@
499
499
  "type": "route-group",
500
500
  "domain": "coherence",
501
501
  "sourcePath": "src/server/routes.ts",
502
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
502
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
503
503
  "since": "2025-01-01"
504
504
  },
505
505
  "route-group:topic-bindings": {
@@ -507,7 +507,7 @@
507
507
  "type": "route-group",
508
508
  "domain": "sessions",
509
509
  "sourcePath": "src/server/routes.ts",
510
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
510
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
511
511
  "since": "2025-01-01"
512
512
  },
513
513
  "route-group:context": {
@@ -515,7 +515,7 @@
515
515
  "type": "route-group",
516
516
  "domain": "context",
517
517
  "sourcePath": "src/server/routes.ts",
518
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
518
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
519
519
  "since": "2025-01-01"
520
520
  },
521
521
  "route-group:scope-coherence": {
@@ -523,7 +523,7 @@
523
523
  "type": "route-group",
524
524
  "domain": "coherence",
525
525
  "sourcePath": "src/server/routes.ts",
526
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
526
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
527
527
  "since": "2025-01-01"
528
528
  },
529
529
  "route-group:canonical-state": {
@@ -531,7 +531,7 @@
531
531
  "type": "route-group",
532
532
  "domain": "state",
533
533
  "sourcePath": "src/server/routes.ts",
534
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
534
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
535
535
  "since": "2025-01-01"
536
536
  },
537
537
  "route-group:ci": {
@@ -539,7 +539,7 @@
539
539
  "type": "route-group",
540
540
  "domain": "monitoring",
541
541
  "sourcePath": "src/server/routes.ts",
542
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
542
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
543
543
  "since": "2025-01-01"
544
544
  },
545
545
  "route-group:sessions": {
@@ -547,7 +547,7 @@
547
547
  "type": "route-group",
548
548
  "domain": "sessions",
549
549
  "sourcePath": "src/server/routes.ts",
550
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
550
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
551
551
  "since": "2025-01-01"
552
552
  },
553
553
  "route-group:jobs": {
@@ -555,7 +555,7 @@
555
555
  "type": "route-group",
556
556
  "domain": "scheduling",
557
557
  "sourcePath": "src/server/routes.ts",
558
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
558
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
559
559
  "since": "2025-01-01"
560
560
  },
561
561
  "route-group:skip-ledger": {
@@ -563,7 +563,7 @@
563
563
  "type": "route-group",
564
564
  "domain": "scheduling",
565
565
  "sourcePath": "src/server/routes.ts",
566
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
566
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
567
567
  "since": "2025-01-01"
568
568
  },
569
569
  "route-group:telegram": {
@@ -571,7 +571,7 @@
571
571
  "type": "route-group",
572
572
  "domain": "communication",
573
573
  "sourcePath": "src/server/routes.ts",
574
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
574
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
575
575
  "since": "2025-01-01"
576
576
  },
577
577
  "route-group:attention": {
@@ -579,7 +579,7 @@
579
579
  "type": "route-group",
580
580
  "domain": "communication",
581
581
  "sourcePath": "src/server/routes.ts",
582
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
582
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
583
583
  "since": "2025-01-01"
584
584
  },
585
585
  "route-group:relationships": {
@@ -587,7 +587,7 @@
587
587
  "type": "route-group",
588
588
  "domain": "relationships",
589
589
  "sourcePath": "src/server/routes.ts",
590
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
590
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
591
591
  "since": "2025-01-01"
592
592
  },
593
593
  "route-group:feedback": {
@@ -595,7 +595,7 @@
595
595
  "type": "route-group",
596
596
  "domain": "feedback",
597
597
  "sourcePath": "src/server/routes.ts",
598
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
598
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
599
599
  "since": "2025-01-01"
600
600
  },
601
601
  "route-group:updates": {
@@ -603,7 +603,7 @@
603
603
  "type": "route-group",
604
604
  "domain": "updates",
605
605
  "sourcePath": "src/server/routes.ts",
606
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
606
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
607
607
  "since": "2025-01-01"
608
608
  },
609
609
  "route-group:dispatches": {
@@ -611,7 +611,7 @@
611
611
  "type": "route-group",
612
612
  "domain": "dispatches",
613
613
  "sourcePath": "src/server/routes.ts",
614
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
614
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
615
615
  "since": "2025-01-01"
616
616
  },
617
617
  "route-group:quota": {
@@ -619,7 +619,7 @@
619
619
  "type": "route-group",
620
620
  "domain": "monitoring",
621
621
  "sourcePath": "src/server/routes.ts",
622
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
622
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
623
623
  "since": "2025-01-01"
624
624
  },
625
625
  "route-group:publishing": {
@@ -627,7 +627,7 @@
627
627
  "type": "route-group",
628
628
  "domain": "publishing",
629
629
  "sourcePath": "src/server/routes.ts",
630
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
630
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
631
631
  "since": "2025-01-01"
632
632
  },
633
633
  "route-group:private-views": {
@@ -635,7 +635,7 @@
635
635
  "type": "route-group",
636
636
  "domain": "publishing",
637
637
  "sourcePath": "src/server/routes.ts",
638
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
638
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
639
639
  "since": "2025-01-01"
640
640
  },
641
641
  "route-group:tunnel": {
@@ -643,7 +643,7 @@
643
643
  "type": "route-group",
644
644
  "domain": "networking",
645
645
  "sourcePath": "src/server/routes.ts",
646
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
646
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
647
647
  "since": "2025-01-01"
648
648
  },
649
649
  "route-group:events": {
@@ -651,7 +651,7 @@
651
651
  "type": "route-group",
652
652
  "domain": "networking",
653
653
  "sourcePath": "src/server/routes.ts",
654
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
654
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
655
655
  "since": "2025-01-01"
656
656
  },
657
657
  "route-group:evolution": {
@@ -659,7 +659,7 @@
659
659
  "type": "route-group",
660
660
  "domain": "evolution",
661
661
  "sourcePath": "src/server/routes.ts",
662
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
662
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
663
663
  "since": "2025-01-01"
664
664
  },
665
665
  "route-group:watchdog": {
@@ -667,7 +667,7 @@
667
667
  "type": "route-group",
668
668
  "domain": "monitoring",
669
669
  "sourcePath": "src/server/routes.ts",
670
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
670
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
671
671
  "since": "2025-01-01"
672
672
  },
673
673
  "route-group:topic-memory": {
@@ -675,7 +675,7 @@
675
675
  "type": "route-group",
676
676
  "domain": "memory",
677
677
  "sourcePath": "src/server/routes.ts",
678
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
678
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
679
679
  "since": "2025-01-01"
680
680
  },
681
681
  "route-group:state-sync": {
@@ -683,7 +683,7 @@
683
683
  "type": "route-group",
684
684
  "domain": "coordination",
685
685
  "sourcePath": "src/server/routes.ts",
686
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
686
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
687
687
  "since": "2025-01-01"
688
688
  },
689
689
  "route-group:intent": {
@@ -691,7 +691,7 @@
691
691
  "type": "route-group",
692
692
  "domain": "intent",
693
693
  "sourcePath": "src/server/routes.ts",
694
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
694
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
695
695
  "since": "2025-01-01"
696
696
  },
697
697
  "route-group:triage": {
@@ -699,7 +699,7 @@
699
699
  "type": "route-group",
700
700
  "domain": "safety",
701
701
  "sourcePath": "src/server/routes.ts",
702
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
702
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
703
703
  "since": "2025-01-01"
704
704
  },
705
705
  "route-group:operations": {
@@ -707,7 +707,7 @@
707
707
  "type": "route-group",
708
708
  "domain": "safety",
709
709
  "sourcePath": "src/server/routes.ts",
710
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
710
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
711
711
  "since": "2025-01-01"
712
712
  },
713
713
  "route-group:sentinel": {
@@ -715,7 +715,7 @@
715
715
  "type": "route-group",
716
716
  "domain": "safety",
717
717
  "sourcePath": "src/server/routes.ts",
718
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
718
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
719
719
  "since": "2025-01-01"
720
720
  },
721
721
  "route-group:trust": {
@@ -723,7 +723,7 @@
723
723
  "type": "route-group",
724
724
  "domain": "safety",
725
725
  "sourcePath": "src/server/routes.ts",
726
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
726
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
727
727
  "since": "2025-01-01"
728
728
  },
729
729
  "route-group:monitoring": {
@@ -731,7 +731,7 @@
731
731
  "type": "route-group",
732
732
  "domain": "monitoring",
733
733
  "sourcePath": "src/server/routes.ts",
734
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
734
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
735
735
  "since": "2025-01-01"
736
736
  },
737
737
  "route-group:commitments": {
@@ -739,7 +739,7 @@
739
739
  "type": "route-group",
740
740
  "domain": "commitments",
741
741
  "sourcePath": "src/server/routes.ts",
742
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
742
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
743
743
  "since": "2025-01-01"
744
744
  },
745
745
  "route-group:episodes": {
@@ -747,7 +747,7 @@
747
747
  "type": "route-group",
748
748
  "domain": "memory",
749
749
  "sourcePath": "src/server/routes.ts",
750
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
750
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
751
751
  "since": "2025-01-01"
752
752
  },
753
753
  "route-group:messages": {
@@ -755,7 +755,7 @@
755
755
  "type": "route-group",
756
756
  "domain": "coordination",
757
757
  "sourcePath": "src/server/routes.ts",
758
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
758
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
759
759
  "since": "2025-01-01"
760
760
  },
761
761
  "route-group:system-reviews": {
@@ -763,7 +763,7 @@
763
763
  "type": "route-group",
764
764
  "domain": "monitoring",
765
765
  "sourcePath": "src/server/routes.ts",
766
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
766
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
767
767
  "since": "2025-01-01"
768
768
  },
769
769
  "route-group:machine-mesh": {
@@ -779,7 +779,7 @@
779
779
  "type": "route-group",
780
780
  "domain": "security",
781
781
  "sourcePath": "src/server/routes.ts",
782
- "contentHash": "4063a5c83ca8f3149333c4090d815bfc4af2a3db56e08101dfab9d72ca88629e",
782
+ "contentHash": "99c66cd1ab74871e51eb610179f95098575154c6bfa82d8fbe2f03db76758397",
783
783
  "since": "2025-01-01"
784
784
  },
785
785
  "cli:init": {
@@ -1571,7 +1571,7 @@
1571
1571
  "type": "subsystem",
1572
1572
  "domain": "updates",
1573
1573
  "sourcePath": "src/core/PostUpdateMigrator.ts",
1574
- "contentHash": "56f7cf7a747b462c74e8e2a6818682f58b4c6acbf0adad8f7d05d8ac15e0ad1d",
1574
+ "contentHash": "28702ce618a021184ca95a7f3a9f07721eed81e6f57633b884b353e5fbc28843",
1575
1575
  "since": "2025-01-01"
1576
1576
  },
1577
1577
  "subsystem:scheduler": {
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "generatedFrom": "source-tree",
4
4
  "registrySha256": "35448db940d659661ebdfb09761439033f93a15157540ee2f6eecf825488e1e6",
5
- "packageVersion": "1.3.1339",
5
+ "packageVersion": "1.3.1340",
6
6
  "guards": [
7
7
  {
8
8
  "ref": "docs/audits/phase-b/f10-triage.md",
@@ -1,5 +1,5 @@
1
1
  {
2
- "sha256": "c095cc2f04124b77c960da745e9fb02cacf4036692174b7d95780c5f5691c5cc",
2
+ "sha256": "ceb93c9320fa5f3c072e65c141e046c666cd5f87b3d86a088d18504bf1e9f732",
3
3
  "registrySha256": "35448db940d659661ebdfb09761439033f93a15157540ee2f6eecf825488e1e6",
4
- "packageVersion": "1.3.1339"
4
+ "packageVersion": "1.3.1340"
5
5
  }
@@ -2,5 +2,5 @@
2
2
  "sha256": "35448db940d659661ebdfb09761439033f93a15157540ee2f6eecf825488e1e6",
3
3
  "articleCount": 92,
4
4
  "generatedFrom": "docs/STANDARDS-REGISTRY.md",
5
- "packageVersion": "1.3.1339"
5
+ "packageVersion": "1.3.1340"
6
6
  }
@@ -2038,6 +2038,10 @@ When a direct send to an agent on this machine may have reached it before I fell
2038
2038
 
2039
2039
  When this machine is a standby and another of my machines holds my relay connection, my sends go out through that machine. \`deliveryPath: 'forwarded'\` and \`forwardedTo\` say so; \`relayStatus\` is the real relay verdict, and \`unconfirmed\` means unknown: I do not resend. \`reply\` is null. A reply to a send made from a topic arrives in that topic's session; a reply to a send with no topic arrives on the machine named in \`forwardedTo\`, in its Threadline hub. **When to use** (PROACTIVE): a user asks which machine carried a message, or where a reply went → read \`forwardedTo\`, \`replyArrivesIn\` and \`GET /threadline/peers/health?scope=pool\`.
2040
2040
 
2041
+ ### A2A dark peers (did my message arrive?)
2042
+
2043
+ A peer is \`dark\` when my own delivery ledger shows messages to it queued at the relay, unconfirmed, or expired for hours with nothing back — no acknowledgement and no inbound since. A relay \`delivered\` verdict alone does NOT clear it: it shows only that something holding the peer's address took the message, not that the peer read it. Messages the relay queued and later handed over stay counted until the peer acknowledges or replies (\`handedUnackedCount\`). It is a proxy read from my ledger: it means "nothing from this peer for N h" and cannot by itself tell offline from a wrong address. A send to a dark peer answers with \`peerDark\` (\`since\`, \`queuedCount\`, \`expiresAt\`, \`connectedNow\`, \`connectedNowReason\`, \`connectedAsOf\`) beside \`relayStatus\`; \`connectedNow\` is the presence map's answer (\`true\` / \`false\` / \`null\` = unknown — never a fresh discover on the send path). When it is \`null\`, \`connectedNowReason\` says why: \`no-row\` (the relay gave me no record of this peer), \`relay-down\` (my own relay is not connected — my side, not theirs) or \`stale\` (my record is too old to trust). \`connectedAsOf\` is when that record was written, so "connected" always means "as of N minutes ago", never "right now". \`GET /threadline/peers/health\` and the per-peer route (\`?scope=pool\` across my machines) carry \`dark\`, \`darkSince\`, \`queuedCount\`, \`connectedNow\`, \`connectedNowReason\`, \`connectedAsOf\`. The wait before a peer counts as dark is 2 h by default and can be set for one peer by its fingerprint (\`threadline.peerDarkNotice.perPeer\`, e.g. 30 min for a peer that normally answers in minutes). Before blaming the peer I read my own \`relay.state\` first: a disconnected sender makes every peer look queued. The operator hears about it ONCE per peer (item \`a2a-peer-dark:<agent>:<peer>\`, 12 h cooldown) only after the awake machine reconnected its relay, refreshed the presence map and re-checked; a peer that answered on any of my machines is not dark, and the item resolves naming the messages that expired unacknowledged. Ships dry-run (\`threadline.peerDarkNotice\`): the fields are live, the worded sentence and the item wait for \`dryRun: false\`. **When to use** (PROACTIVE): a user asks "did <peer> get my message?" → read the send's \`relayStatus\` AND \`peerDark\`; "is <peer> there?" → \`GET /threadline/peers/<fingerprint>/health\` → \`dark\`, \`darkSince\`, \`queuedCount\`, \`connectedNow\`. It may be offline, or listening under a different address — I say which evidence I have, never "nothing will arrive".
2044
+
2041
2045
  ### A2A local-route trust
2042
2046
 
2043
2047
  Messages from another agent on this machine arrive on a direct route that used to treat every sender as \`verified\`, while the same sender over the relay is \`untrusted\` unless I hold a trust profile for it. With \`threadline.localRouteTrust\` on, the direct route looks the sender up in the same trust profiles and applies the same rule: a sender with no profile may only ping. It starts in watch-only mode (\`dryRun\`, the default): every message is delivered as before, and each one that would be refused is logged (\`[relay-agent-trust] would-refuse\`) and counted. With \`dryRun: false\` such a message is refused before it is recorded, with HTTP 403 \`{ error: 'insufficient-trust', refused: true }\`; the sender then falls back to the relay, which judges the message again under its own rules and may accept it. Live on a development agent, dark on the fleet (omitted \`enabled\`). With no trust manager (relay off, or a relay standby) it does nothing and counts that. Counters and the current mode: authed \`/health\` → \`threadline.localRouteTrust\`. **When to use** (PROACTIVE): before turning \`dryRun\` off, read \`wouldRefuse\` — each count is a working same-machine conversation that would stop; grant those senders trust first (\`threadline_trust\`). A same-machine agent says its message was refused with \`insufficient-trust\` → grant it trust, or check the mode.
@@ -0,0 +1,32 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Part §3 of `docs/specs/a2a-single-agent-identity.md` (CMT-706, approved 2026-10-09): when messages to another agent sit queued at the relay for hours with nothing back, the sender now knows — on the send itself, on the health read, and (once the notice is switched on) as one operator item per peer.
9
+
10
+ - **`dark` on the delivery ledger.** `GET /threadline/peers/health` and `/threadline/peers/:fp/health` (and `?scope=pool`) carry `dark`, `darkSince`, `queuedCount`, `queuedExpiresAt`, `lastDeliveredAt`, `connectedNow`, `connectedNowReason`, `connectedAsOf`; the list carries `darkCount`. A peer is dark when its oldest message that is queued, unconfirmed or expired — sent after the last ack or inbound from it — is older than `threadline.peerDarkNotice.queuedDarkAfterMs` (2 h), or than that peer's own entry in `threadline.peerDarkNotice.perPeer` (by fingerprint; e.g. 30 min for a pair that answers in minutes). Relay expiry never clears it. A relay `delivered` verdict alone never clears it either — it shows only that something holding the peer's address took the message. An acknowledgement or an inbound message does. Messages the relay queued and later handed to a connection stay counted until then (`handedUnackedCount`), and the wording names them rather than calling them queued.
11
+ - **`peerDark` on the send.** `POST /threadline/relay-send` and the `threadline_send` tool answer a send to a dark peer with `peerDark: { since, queuedCount, expiresAt, connectedNow, connectedNowReason, connectedAsOf }`. `connectedNow` is the relay presence map's answer (`presence_change` frames now update it; `null` when unknown — never a fresh discover on the send path). When it is `null`, `connectedNowReason` says why (`no-row`, `relay-down` = my own side, `stale`); `connectedAsOf` is when the record was written, and the sentence states that age ("as of 3 min ago"). With `dryRun: false` the `deliveryOutcome` becomes "no acknowledgement from <peer> for N h; this and K other messages are still queued (oldest expires T); <peer> is not connected to the relay right now — it may be offline, or listening under a different address" (or the connected / unknown variant) — worded to the evidence, never "nothing will arrive".
12
+ - **One item per peer through the reworked `A2ARedeliverySentinel`.** It is now constructed under EITHER `monitoring.a2aRedelivery.enabled` OR `threadline.peerDarkNotice` (escalate-only under the latter). Trigger: dark, with queued rows, after the awake machine healed its own side (reconnect a dropped relay, one presence refresh, the identity self-check; two passes 40 s apart). Deterministic id `a2a-peer-dark:<agent>:<peerFp>`, raise and resolve both read pool-scope evidence (a peer that answered on another of my machines is not dark), the resolve line names how many messages expired unacknowledged, 12 h cooldown per peer. My own relay down → one aggregated item instead. A standby heals nothing and raises nothing.
13
+ - **Bounded ledger.** The silence sweep deletes rows older than 30 days in every state; `findOverdue` reads the oldest 500.
14
+ - **Dev-gated, dry-run first.** `threadline.peerDarkNotice: { dryRun: true, queuedDarkAfterMs: 7200000, cooldownMs: 43200000 }` (plus an optional `perPeer` map) with `enabled` omitted (live on a development agent, dark on the fleet; registered as `a2aPeerDarkNotice`). Dry-run writes would-raise / would-sentence rows to `logs/a2a-peer-dark.jsonl`; the health fields are live everywhere. CLAUDE.md section "A2A dark peers (did my message arrive?)" for new and existing agents.
15
+
16
+ ## What to Tell Your User
17
+
18
+ When I message another agent and the relay has to hold the message because that agent is not connected, I used to say "queued" and nothing more — and if the message quietly expired a day later, nobody heard. Now I keep count: if messages to an agent have been waiting for hours with nothing back, I say so on the spot, with how many are waiting, when the oldest expires, and whether the relay saw that agent connected, with how many minutes old that reading is. If I cannot tell, I say whether that is because my own connection is down or because I have no fresh reading for them. A message the relay merely handed to that agent's address does not count as an answer; only a reply or an acknowledgement does. For an agent that normally answers within minutes, the wait before I speak up can be set shorter than the two-hour default. I cannot always tell "offline" from "listening under a different address", so I say which it might be rather than guessing. Once the notice is switched on, you also get a single heads-up per agent — after I have first checked and repaired my own connection — and a note when that agent is back saying how many messages expired unanswered so you can resend what still matters.
19
+
20
+ ## Summary of New Capabilities
21
+
22
+ - `peerHealth()` / `GET /threadline/peers/health`: `dark`, `darkSince`, `queuedCount`, `queuedExpiresAt`, `lastDeliveredAt`, `connectedNow`, `connectedNowReason`, `connectedAsOf`, `handedUnackedCount`, `darkCount`.
23
+ - `POST /threadline/relay-send` + `threadline_send`: `peerDark` object; evidence-worded `deliveryOutcome` when live.
24
+ - `ThreadlineClient.peerConnectedNow()` / `peerPresence()` / `refreshPresence()`; `presence_change` frames feed the presence map.
25
+ - `A2ARedeliverySentinel`: per-peer dark path (deterministic item id, pool-scope raise/resolve, cooldown, local-relay aggregate, awake-only self-heal), constructed under either gate.
26
+ - `threadline.peerDarkNotice` config block (dev-gated, dry-run) with per-peer thresholds (`perPeer`), `logs/a2a-peer-dark.jsonl`.
27
+
28
+ ## Evidence
29
+
30
+ - `tests/unit/a2a-peer-dark.test.ts` (51): the classification (threshold, per-peer threshold, every clearing event, a `delivered` verdict alone NOT clearing, expiry never clears, `escalated` never suppresses, counts, expiry, retention in every state, `findOverdue` bound, bounded `allPeerHealth`); the presence map (`presence_change`, stale frame → null, rejected refresh → false/null, relay down → null, and the reason + age for each unknown); the sentinel (gate-alone construction, one item after the heal, dry-run rows, pool-cleared raise, pool-life resolve with the expired count, cooldown + reopen, restart rebuild, local-relay aggregate, standby, split supersede, cleared-during-heal, legacy loop coexistence, failing pool read); helpers (resolver + floors, every sentence variant, HTML-escaped label, audit writer); migration parity (template = migrator wording, deep-merged defaults with `enabled` omitted, dev-gate entry).
31
+ - `tests/integration/threadline/a2a-peer-dark-route.test.ts` (8): a real `ThreadlineClient` against the in-repo `RelayServer` — `peerDark` + would-sentence in dry-run, the worded sentence when live, the MCP client passthrough, the live-read threshold, a per-peer threshold, `relay-down` vs `no-row`, dark NOT clearing on a reconnect's `delivered` verdict and clearing on the first inbound, the health fields.
32
+ - `tests/e2e/a2a-peer-dark-alive.test.ts` (5): the real `AgentServer` on the production init path — the routes answer 200 with the §3 fields, a row in the real on-disk ledger reads dark, the construction rule under the gate alone, migration E2E (defaults twice + CLAUDE.md once).