instar 0.28.82 → 0.28.83

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,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-05-06T18:40:12.418Z",
5
- "instarVersion": "0.28.82",
4
+ "generatedAt": "2026-05-09T09:58:35.024Z",
5
+ "instarVersion": "0.28.83",
6
6
  "entryCount": 187,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -384,7 +384,7 @@
384
384
  "type": "route-group",
385
385
  "domain": "monitoring",
386
386
  "sourcePath": "src/server/routes.ts",
387
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
387
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
388
388
  "since": "2025-01-01"
389
389
  },
390
390
  "route-group:agents": {
@@ -392,7 +392,7 @@
392
392
  "type": "route-group",
393
393
  "domain": "sessions",
394
394
  "sourcePath": "src/server/routes.ts",
395
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
395
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
396
396
  "since": "2025-01-01"
397
397
  },
398
398
  "route-group:backups": {
@@ -400,7 +400,7 @@
400
400
  "type": "route-group",
401
401
  "domain": "operations",
402
402
  "sourcePath": "src/server/routes.ts",
403
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
403
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
404
404
  "since": "2025-01-01"
405
405
  },
406
406
  "route-group:git": {
@@ -408,7 +408,7 @@
408
408
  "type": "route-group",
409
409
  "domain": "coordination",
410
410
  "sourcePath": "src/server/routes.ts",
411
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
411
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
412
412
  "since": "2025-01-01"
413
413
  },
414
414
  "route-group:memory": {
@@ -416,7 +416,7 @@
416
416
  "type": "route-group",
417
417
  "domain": "memory",
418
418
  "sourcePath": "src/server/routes.ts",
419
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
419
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
420
420
  "since": "2025-01-01"
421
421
  },
422
422
  "route-group:semantic": {
@@ -424,7 +424,7 @@
424
424
  "type": "route-group",
425
425
  "domain": "memory",
426
426
  "sourcePath": "src/server/routes.ts",
427
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
427
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
428
428
  "since": "2025-01-01"
429
429
  },
430
430
  "route-group:status": {
@@ -432,7 +432,7 @@
432
432
  "type": "route-group",
433
433
  "domain": "monitoring",
434
434
  "sourcePath": "src/server/routes.ts",
435
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
435
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
436
436
  "since": "2025-01-01"
437
437
  },
438
438
  "route-group:capabilities": {
@@ -440,7 +440,7 @@
440
440
  "type": "route-group",
441
441
  "domain": "mapping",
442
442
  "sourcePath": "src/server/routes.ts",
443
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
443
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
444
444
  "since": "2025-01-01"
445
445
  },
446
446
  "route-group:project-map": {
@@ -448,7 +448,7 @@
448
448
  "type": "route-group",
449
449
  "domain": "mapping",
450
450
  "sourcePath": "src/server/routes.ts",
451
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
451
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
452
452
  "since": "2025-01-01"
453
453
  },
454
454
  "route-group:coherence": {
@@ -456,7 +456,7 @@
456
456
  "type": "route-group",
457
457
  "domain": "coherence",
458
458
  "sourcePath": "src/server/routes.ts",
459
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
459
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
460
460
  "since": "2025-01-01"
461
461
  },
462
462
  "route-group:topic-bindings": {
@@ -464,7 +464,7 @@
464
464
  "type": "route-group",
465
465
  "domain": "sessions",
466
466
  "sourcePath": "src/server/routes.ts",
467
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
467
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
468
468
  "since": "2025-01-01"
469
469
  },
470
470
  "route-group:context": {
@@ -472,7 +472,7 @@
472
472
  "type": "route-group",
473
473
  "domain": "context",
474
474
  "sourcePath": "src/server/routes.ts",
475
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
475
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
476
476
  "since": "2025-01-01"
477
477
  },
478
478
  "route-group:scope-coherence": {
@@ -480,7 +480,7 @@
480
480
  "type": "route-group",
481
481
  "domain": "coherence",
482
482
  "sourcePath": "src/server/routes.ts",
483
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
483
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
484
484
  "since": "2025-01-01"
485
485
  },
486
486
  "route-group:canonical-state": {
@@ -488,7 +488,7 @@
488
488
  "type": "route-group",
489
489
  "domain": "state",
490
490
  "sourcePath": "src/server/routes.ts",
491
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
491
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
492
492
  "since": "2025-01-01"
493
493
  },
494
494
  "route-group:ci": {
@@ -496,7 +496,7 @@
496
496
  "type": "route-group",
497
497
  "domain": "monitoring",
498
498
  "sourcePath": "src/server/routes.ts",
499
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
499
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
500
500
  "since": "2025-01-01"
501
501
  },
502
502
  "route-group:sessions": {
@@ -504,7 +504,7 @@
504
504
  "type": "route-group",
505
505
  "domain": "sessions",
506
506
  "sourcePath": "src/server/routes.ts",
507
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
507
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
508
508
  "since": "2025-01-01"
509
509
  },
510
510
  "route-group:jobs": {
@@ -512,7 +512,7 @@
512
512
  "type": "route-group",
513
513
  "domain": "scheduling",
514
514
  "sourcePath": "src/server/routes.ts",
515
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
515
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
516
516
  "since": "2025-01-01"
517
517
  },
518
518
  "route-group:skip-ledger": {
@@ -520,7 +520,7 @@
520
520
  "type": "route-group",
521
521
  "domain": "scheduling",
522
522
  "sourcePath": "src/server/routes.ts",
523
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
523
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
524
524
  "since": "2025-01-01"
525
525
  },
526
526
  "route-group:telegram": {
@@ -528,7 +528,7 @@
528
528
  "type": "route-group",
529
529
  "domain": "communication",
530
530
  "sourcePath": "src/server/routes.ts",
531
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
531
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
532
532
  "since": "2025-01-01"
533
533
  },
534
534
  "route-group:attention": {
@@ -536,7 +536,7 @@
536
536
  "type": "route-group",
537
537
  "domain": "communication",
538
538
  "sourcePath": "src/server/routes.ts",
539
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
539
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
540
540
  "since": "2025-01-01"
541
541
  },
542
542
  "route-group:relationships": {
@@ -544,7 +544,7 @@
544
544
  "type": "route-group",
545
545
  "domain": "relationships",
546
546
  "sourcePath": "src/server/routes.ts",
547
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
547
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
548
548
  "since": "2025-01-01"
549
549
  },
550
550
  "route-group:feedback": {
@@ -552,7 +552,7 @@
552
552
  "type": "route-group",
553
553
  "domain": "feedback",
554
554
  "sourcePath": "src/server/routes.ts",
555
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
555
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
556
556
  "since": "2025-01-01"
557
557
  },
558
558
  "route-group:updates": {
@@ -560,7 +560,7 @@
560
560
  "type": "route-group",
561
561
  "domain": "updates",
562
562
  "sourcePath": "src/server/routes.ts",
563
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
563
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
564
564
  "since": "2025-01-01"
565
565
  },
566
566
  "route-group:dispatches": {
@@ -568,7 +568,7 @@
568
568
  "type": "route-group",
569
569
  "domain": "dispatches",
570
570
  "sourcePath": "src/server/routes.ts",
571
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
571
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
572
572
  "since": "2025-01-01"
573
573
  },
574
574
  "route-group:quota": {
@@ -576,7 +576,7 @@
576
576
  "type": "route-group",
577
577
  "domain": "monitoring",
578
578
  "sourcePath": "src/server/routes.ts",
579
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
579
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
580
580
  "since": "2025-01-01"
581
581
  },
582
582
  "route-group:publishing": {
@@ -584,7 +584,7 @@
584
584
  "type": "route-group",
585
585
  "domain": "publishing",
586
586
  "sourcePath": "src/server/routes.ts",
587
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
587
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
588
588
  "since": "2025-01-01"
589
589
  },
590
590
  "route-group:private-views": {
@@ -592,7 +592,7 @@
592
592
  "type": "route-group",
593
593
  "domain": "publishing",
594
594
  "sourcePath": "src/server/routes.ts",
595
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
595
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
596
596
  "since": "2025-01-01"
597
597
  },
598
598
  "route-group:tunnel": {
@@ -600,7 +600,7 @@
600
600
  "type": "route-group",
601
601
  "domain": "networking",
602
602
  "sourcePath": "src/server/routes.ts",
603
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
603
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
604
604
  "since": "2025-01-01"
605
605
  },
606
606
  "route-group:events": {
@@ -608,7 +608,7 @@
608
608
  "type": "route-group",
609
609
  "domain": "networking",
610
610
  "sourcePath": "src/server/routes.ts",
611
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
611
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
612
612
  "since": "2025-01-01"
613
613
  },
614
614
  "route-group:evolution": {
@@ -616,7 +616,7 @@
616
616
  "type": "route-group",
617
617
  "domain": "evolution",
618
618
  "sourcePath": "src/server/routes.ts",
619
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
619
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
620
620
  "since": "2025-01-01"
621
621
  },
622
622
  "route-group:watchdog": {
@@ -624,7 +624,7 @@
624
624
  "type": "route-group",
625
625
  "domain": "monitoring",
626
626
  "sourcePath": "src/server/routes.ts",
627
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
627
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
628
628
  "since": "2025-01-01"
629
629
  },
630
630
  "route-group:topic-memory": {
@@ -632,7 +632,7 @@
632
632
  "type": "route-group",
633
633
  "domain": "memory",
634
634
  "sourcePath": "src/server/routes.ts",
635
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
635
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
636
636
  "since": "2025-01-01"
637
637
  },
638
638
  "route-group:state-sync": {
@@ -640,7 +640,7 @@
640
640
  "type": "route-group",
641
641
  "domain": "coordination",
642
642
  "sourcePath": "src/server/routes.ts",
643
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
643
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
644
644
  "since": "2025-01-01"
645
645
  },
646
646
  "route-group:intent": {
@@ -648,7 +648,7 @@
648
648
  "type": "route-group",
649
649
  "domain": "intent",
650
650
  "sourcePath": "src/server/routes.ts",
651
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
651
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
652
652
  "since": "2025-01-01"
653
653
  },
654
654
  "route-group:triage": {
@@ -656,7 +656,7 @@
656
656
  "type": "route-group",
657
657
  "domain": "safety",
658
658
  "sourcePath": "src/server/routes.ts",
659
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
659
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
660
660
  "since": "2025-01-01"
661
661
  },
662
662
  "route-group:operations": {
@@ -664,7 +664,7 @@
664
664
  "type": "route-group",
665
665
  "domain": "safety",
666
666
  "sourcePath": "src/server/routes.ts",
667
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
667
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
668
668
  "since": "2025-01-01"
669
669
  },
670
670
  "route-group:sentinel": {
@@ -672,7 +672,7 @@
672
672
  "type": "route-group",
673
673
  "domain": "safety",
674
674
  "sourcePath": "src/server/routes.ts",
675
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
675
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
676
676
  "since": "2025-01-01"
677
677
  },
678
678
  "route-group:trust": {
@@ -680,7 +680,7 @@
680
680
  "type": "route-group",
681
681
  "domain": "safety",
682
682
  "sourcePath": "src/server/routes.ts",
683
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
683
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
684
684
  "since": "2025-01-01"
685
685
  },
686
686
  "route-group:monitoring": {
@@ -688,7 +688,7 @@
688
688
  "type": "route-group",
689
689
  "domain": "monitoring",
690
690
  "sourcePath": "src/server/routes.ts",
691
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
691
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
692
692
  "since": "2025-01-01"
693
693
  },
694
694
  "route-group:commitments": {
@@ -696,7 +696,7 @@
696
696
  "type": "route-group",
697
697
  "domain": "commitments",
698
698
  "sourcePath": "src/server/routes.ts",
699
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
699
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
700
700
  "since": "2025-01-01"
701
701
  },
702
702
  "route-group:episodes": {
@@ -704,7 +704,7 @@
704
704
  "type": "route-group",
705
705
  "domain": "memory",
706
706
  "sourcePath": "src/server/routes.ts",
707
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
707
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
708
708
  "since": "2025-01-01"
709
709
  },
710
710
  "route-group:messages": {
@@ -712,7 +712,7 @@
712
712
  "type": "route-group",
713
713
  "domain": "coordination",
714
714
  "sourcePath": "src/server/routes.ts",
715
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
715
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
716
716
  "since": "2025-01-01"
717
717
  },
718
718
  "route-group:system-reviews": {
@@ -720,7 +720,7 @@
720
720
  "type": "route-group",
721
721
  "domain": "monitoring",
722
722
  "sourcePath": "src/server/routes.ts",
723
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
723
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
724
724
  "since": "2025-01-01"
725
725
  },
726
726
  "route-group:machine-mesh": {
@@ -736,7 +736,7 @@
736
736
  "type": "route-group",
737
737
  "domain": "security",
738
738
  "sourcePath": "src/server/routes.ts",
739
- "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
739
+ "contentHash": "50dd7ce0b9b9918de65ee2729e804505a9120456d2f0db1ed06b4afe2528df50",
740
740
  "since": "2025-01-01"
741
741
  },
742
742
  "cli:init": {
@@ -0,0 +1,45 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- bump: patch -->
4
+ <!-- Valid values: patch, minor, major -->
5
+ <!-- patch = bug fixes, refactors, test additions, doc updates -->
6
+ <!-- minor = new features, new APIs, new capabilities (backwards-compatible) -->
7
+ <!-- major = breaking changes to existing APIs or behavior -->
8
+
9
+ ## What Changed
10
+
11
+ `POST /threadline/relay-send` now consults the local nickname store at `.instar/threadline/nicknames.json` BEFORE asking the relay's discovery cache to resolve a name → fingerprint. User-curated nicknames are now the highest-authority mapping for outbound sends; relay discovery is a signal that the resolver only consults when no nickname matches.
12
+
13
+ When a nickname does resolve, the route uses the nickname's fingerprint directly for both the local-delivery match (fingerprint compare against `known-agents.json`) and the relay-delivery `sendAuto` call. If relay discovery happens to also know the same name but maps it to a different fingerprint, the route logs a `[relay-send] Nickname/discovery mismatch …` warning and honors the nickname (signal-vs-authority — the user's mapping wins).
14
+
15
+ `ThreadlineNicknames` (originally implemented on `feat/dashboard-grouped-nav` for the dashboard surface) is now landed on `main` with one new method — `resolveByName(name)` — and three convergence-review hardenings:
16
+
17
+ - **Canonicalized matching** (`canonicalizeName(name)` static helper applies NFC + trim + internal-whitespace-collapse + lowercase): a hand-edited entry like `"Dawn Q "` resolves the same as `"dawn q"`, including for combining-character Unicode forms. Stored strings preserve user casing/spacing for dashboard display; canonicalization happens at compare time only.
18
+ - **Atomic writes** via temp+rename in `persist()`: a concurrent reader can no longer observe a half-written file (which would parse-fail and silently drop the user's authority). POSIX rename(2) atomicity holds because `.instar/threadline/` is a single filesystem.
19
+ - **Corrupt-file observability**: `load()` catches JSON parse errors and emits a one-shot rate-limited warn (one log per 30s cache cycle) so a corrupted `nicknames.json` is visible in operator logs without spamming. Sends still flow via the relay-discovery fallback.
20
+
21
+ Sends to inputs that look like a raw fingerprint skip the nickname check. The `name:fpPrefix` qualifier syntax now consults the nickname store and uses the prefix to disambiguate among candidates: 1 candidate matches the prefix → use it; 0 → 409 with the candidate list; multiple → 409 asking for a longer prefix. (Previously the route skipped the nickname check whenever `:fpPrefix` was present, which made the documented disambiguation remedy a dead end. Convergence review caught this; now corrected.)
22
+
23
+ ## What to Tell Your User
24
+
25
+ - **Outbound messages now reach the right agent**: "When I send a message to someone you've named — like 'Dawn' — I now use the fingerprint you wrote in nicknames.json instead of asking the relay's directory, which can return a stale or imposter entry. If the relay disagrees with your mapping, your mapping wins and I log the conflict so you can see it."
26
+
27
+ ## Summary of New Capabilities
28
+
29
+ | Capability | How to Use |
30
+ |-----------|-----------|
31
+ | Nickname-first send-path resolver | automatic — applies to every `/threadline/relay-send` call (which the MCP `threadline_send` tool also uses) |
32
+ | Nickname-vs-discovery mismatch warning | automatic — logged at `[relay-send] Nickname/discovery mismatch …` when the relay's resolved fingerprint differs from a user-curated nickname for the same name |
33
+ | `name:fpPrefix` disambiguation honors nickname store | use `name:fpPrefix` when two of your nicknamed fingerprints share a name; the route filters candidates by the prefix you supply |
34
+ | Corrupt `nicknames.json` warn | logged at `[ThreadlineNicknames] nicknames.json parse failed …` (rate-limited to once per 30s cache cycle) |
35
+ | `ThreadlineNicknames.resolveByName()` and `.canonicalizeName()` | imported from `'../threadline/ThreadlineNicknames.js'` for any future caller that needs name → fingerprint reverse lookup or canonical-form comparison |
36
+
37
+ ## Evidence
38
+
39
+ Reproduction (real bug): on 2026-05-08, Echo (this agent) sent two follow-up messages to Dawn over Threadline thread `thread-2ebce60b`. The MCP `threadline_send` resolver returned fingerprint `5c338c63cd2ecebc8f52483d5bba6486` for the name "Dawn" — but Dawn's real fingerprint per Echo's `.instar/threadline/nicknames.json` (and per every prior message in that thread) was `8c7928aa9f04fbda947172a2f9b2d81a`. The messages were silently delivered to a wrong/stale recipient. Dawn never received the question. Bug surfaced when Justin asked "check again for Dawn's reply"; diagnosis traced to `ThreadlineClient.resolveAgent` consulting only the discovery cache and bypassing the user-curated nickname mapping (no source-tree code read `nicknames.json` at all on `main`).
40
+
41
+ Verified-after: `tests/integration/threadline-relay-send-nickname.test.ts` reproduces the exact failure conditions — a stub relay client whose `resolveAgent('Dawn')` returns `5c338c63…` (the wrong fingerprint), with `nicknames.json` curating `Dawn` → `8c7928aa…`. The test asserts that the route sends to `8c7928aa…` (NOT the relay's wrong answer) and that `resolvedAgent` in the response body is `8c7928aa…`. The mismatch warning fires and is observable in the test output. Unit-level coverage at `tests/unit/ThreadlineNicknames.test.ts` exercises the new `resolveByName` method including the corrupt-file-tolerance, ambiguous-mapping, and canonicalization (NFC + whitespace) cases — 8 unit tests + 3 integration tests, all green. The full threadline-area subtree (1493 tests) remains green.
42
+
43
+ Spec converged in 3 iterations through `/spec-converge` (multi-angle internal reviewers + GPT/Gemini/Grok cross-model reviewers). Convergence report at `docs/specs/reports/threadline-nickname-resolver-authority-convergence.md`. The convergence review caught and corrected: cache-honesty wording, atomic-write spec-vs-code mismatch, normalization weakness (added canonicalization), corrupt-file silent fail, the `name:fpPrefix` disambiguation dead-end, and one stale acceptance criterion.
44
+
45
+ The `ThreadlineNicknames` class is derived from `feat/dashboard-grouped-nav` commit `16c605ce`. The convergence-review hardenings (atomic writes, canonicalization, observability warn) are additive; when that feature branch lands, the merge delta is the new methods/improvements. The `resolveByName` method is additive (new method, no existing-method signature changes) so no existing caller is affected.
@@ -0,0 +1,81 @@
1
+ # Side-Effects Review — Threadline name-resolver honors user-curated nicknames
2
+
3
+ **Version / slug:** `threadline-nickname-resolver-authority`
4
+ **Date:** `2026-05-08`
5
+ **Author:** Echo
6
+ **Second-pass reviewer:** required (touches Threadline send-path delivery correctness)
7
+
8
+ ## Summary of the change
9
+
10
+ `POST /threadline/relay-send` now consults `.instar/threadline/nicknames.json` BEFORE asking the relay's discovery cache to map a name → fingerprint. User-curated nicknames are highest-authority; relay discovery is a signal the resolver only consults when no nickname matches.
11
+
12
+ The `ThreadlineNicknames` class (already on `feat/dashboard-grouped-nav`, commit `16c605ce`) is cherry-picked onto `main` byte-identical, plus one additive method: `resolveByName(name)` for case-insensitive name → fingerprint reverse lookup. The route handler wires nickname resolution at the top of the request, then propagates a single `nicknameResolvedFp` through the local-delivery match (now by-fingerprint instead of by-name when set) and the relay branch (skipping `relayClient.resolveAgent` when set).
13
+
14
+ When relay discovery and nicknames disagree on a name's fingerprint, the route logs a `[relay-send] Nickname/discovery mismatch …` warning and uses the nickname's fingerprint. The mismatch is not silently swallowed.
15
+
16
+ Files touched:
17
+ - `src/threadline/ThreadlineNicknames.ts` — cherry-picked from `16c605ce`; added `resolveByName(name)` method (single match | ambiguous | null).
18
+ - `src/server/routes.ts` — added import; added nickname-first resolution block at the top of `/threadline/relay-send`; switched local-delivery name-match to fingerprint-match when nickname resolved; replaced bare `relayClient.resolveAgent(targetAgent)` with the nickname-aware version.
19
+ - `tests/unit/ThreadlineNicknames.test.ts` — new, 7 cases covering `resolveByName`: null on missing/empty/whitespace, single match (case-insensitive), ambiguous detection, on-disk file read, corrupt-file tolerance, no-match.
20
+ - `tests/integration/threadline-relay-send-nickname.test.ts` — new, 3 cases reproducing the production bug (relay returns wrong fingerprint, nickname authority overrides), plus the no-nickname and raw-fingerprint pass-through cases.
21
+ - `upgrades/NEXT.md` — release note with reproduction + verified-after evidence.
22
+
23
+ ## Decision-point inventory
24
+
25
+ - Top of `/threadline/relay-send` — **add** — new nickname-resolution block.
26
+ - Local-delivery `nameMatches` filter — **modify** — by-fingerprint when nickname resolved, otherwise existing by-name.
27
+ - Relay-delivery `resolveAgent` call — **modify** — uses `nicknameResolvedFp` directly when set; relay discovery only as a probe for the mismatch warning.
28
+ - `ThreadlineNicknames.resolveByName` — **add** — additive method on existing class.
29
+
30
+ ---
31
+
32
+ ## 1. Over-block
33
+
34
+ **What legitimate inputs does this change reject that it shouldn't?**
35
+
36
+ The nickname-first path overrides relay discovery whenever the user has an exact (case-insensitive) name match in their nicknames file. Concrete over-block surfaces:
37
+
38
+ - **User has a stale nickname mapping**: `.instar/threadline/nicknames.json` says "Dawn" → `8c79…`, but Dawn re-keyed to `9911…`. We'd route to `8c79…` (a dead fingerprint). Mitigation: the mismatch warning surfaces in operator logs (`[relay-send] Nickname/discovery mismatch …`). User can clear the mapping via the existing `DELETE /threadline/nicknames/:fingerprint` route once the dashboard PR (`feat/dashboard-grouped-nav`) lands, or by editing the JSON file directly. The previous behavior — silently routing to whatever the relay cached — is strictly worse: it masks the staleness instead of letting the user see and fix it.
39
+ - **User has nicknamed a remote agent with the same name as a local one**: e.g., user nicknames remote `fp_X` as "echo" and there's also a local agent literally named "echo". The route now routes to the remote one. The previous behavior would have routed locally. The user explicitly chose this nickname; honoring it is correct, and the tradeoff is documented (see Interactions §4 below).
40
+
41
+ For inputs that look like raw fingerprints (`/^[0-9a-f]{16,64}$/i`) or use the `name:fpPrefix` qualifier syntax, the nickname check is skipped — caller is being explicit about a fingerprint, no over-block possible.
42
+
43
+ ## 2. Under-block
44
+
45
+ **What does this change fail to catch that the user expects it to catch?**
46
+
47
+ Names with NO nickname mapping fall through to the existing `relayClient.resolveAgent(targetAgent)` flow. The original silent-wrong-fingerprint bug can still manifest for un-nicknamed names — e.g., if the relay's discovery cache holds a stale entry for "Stranger" and the user has not nicknamed "Stranger", a send to "Stranger" will go to whatever the relay says. This fix defends the user-curated path; the underlying relay-discovery-can-be-wrong problem remains for un-nicknamed names. Acceptable scope: the user's authority lever is the nickname store; if they care about delivery correctness for an agent, they nickname it.
48
+
49
+ Names with `name:fpPrefix` syntax also bypass nicknames — the caller is overriding by being explicit; if their explicit choice is wrong, that's not the resolver's job to second-guess.
50
+
51
+ ## 3. Level-of-abstraction fit
52
+
53
+ The wiring lives in the route handler (instar-specific code) rather than in `ThreadlineClient` (generic library code). This keeps `ThreadlineClient.resolveAgent` agnostic of instar's `.instar/` state directory and nicknames file. `ThreadlineNicknames` itself is reused — no new abstraction invented; the new `resolveByName` method is the single sensible reverse-lookup primitive on a class that already exposes `get` (forward), `set`, `delete`, `all`, `invalidate`.
54
+
55
+ The handler reads the nickname store inline rather than caching a long-lived instance — `ThreadlineNicknames` already has its own 30-second internal cache, so per-request construction is cheap and the cache-invalidation story stays simple (file edits visible within 30 s).
56
+
57
+ ## 4. Signal-vs-authority compliance
58
+
59
+ This change is the canonical signal-vs-authority move:
60
+
61
+ - **Signal (low-context, can be wrong)**: `relayClient.resolveAgent(name)` — the relay's discovery cache is built from gossip, can hold stale presence, can hold imposter entries.
62
+ - **Authority (full-context, user-curated)**: `nicknames.json` — set explicitly by the user (via the dashboard ✎ pencil, the `PUT /threadline/nicknames/:fingerprint` route on the feature branch, or by hand-editing the JSON).
63
+
64
+ Authority wins. Signal is consulted only when authority is silent. When the two disagree, the conflict is observable (warning log) but the route still honors authority. This matches the existing patterns in `feedback_signal_vs_authority.md` and `feedback_side_effects_review.md` from agent memory.
65
+
66
+ ## 5. Interactions
67
+
68
+ - **Local-delivery path (same-machine agents in `known-agents.json`)**: When a nickname resolves, the local-delivery loop now matches by fingerprint instead of by name. Same-name collisions (Dawn-the-remote vs. dawn-the-local) resolve to whichever fingerprint the user nicknamed. If the user nicknamed Dawn-the-remote, sends bypass the local "dawn" agent. This is intentional — the user curated the mapping. If they wanted the local one, they wouldn't have nicknamed the remote.
69
+ - **Self-guard (don't deliver to self)**: Unaffected. The fingerprint comparison against `identity.json` still runs on the resolved local target.
70
+ - **`name:fpPrefix` syntax**: Unaffected. The check happens before nickname resolution and short-circuits it. Callers who use the explicit qualifier retain their existing semantics.
71
+ - **MCP `threadline_send` tool**: Unaffected directly — the MCP server forwards `agentId` to `/threadline/relay-send` over HTTP, so the nickname-first resolution applies transparently to every MCP-initiated send. This is the path Echo's outbound messages to Dawn travel; the original bug was on this exact path.
72
+ - **Existing tests**: The local-delivery `nameMatches` filter was wrapped in `nicknameResolvedFp ? (...) : (...)`. When no nickname store exists (the case for every existing test that doesn't write `nicknames.json`), `nicknameResolvedFp` is null and the existing by-name filter runs unchanged. No regression risk for existing test fixtures.
73
+ - **`feat/dashboard-grouped-nav` merge conflict**: `ThreadlineNicknames.ts` is cherry-picked byte-identical from commit `16c605ce`, so when that feature branch lands, the file content already matches and only the additive `resolveByName` method is the merge delta. Trivial conflict resolution.
74
+
75
+ ## 6. Rollback cost
76
+
77
+ Trivial. Single-commit revert. Three files changed plus one cherry-picked file plus two test files. No data-migration, no schema change, no deployment ordering. The nickname JSON file format is read-only here (no writes from the route), so even a partial rollback (revert routes.ts only, keep ThreadlineNicknames.ts) leaves the system in a consistent state.
78
+
79
+ ## Sign-off
80
+
81
+ Change is self-contained, defends the user-curated authority lever, exposes mismatches via warning logs, leaves un-nicknamed paths unchanged, and is fully covered by integration test that reproduces the original Dawn-routing failure.