instar 0.28.80 → 0.28.82

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "0.28.80",
3
+ "version": "0.28.82",
4
4
  "description": "Persistent autonomy infrastructure for AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-05-05T04:58:06.613Z",
5
- "instarVersion": "0.28.80",
4
+ "generatedAt": "2026-05-06T18:40:12.418Z",
5
+ "instarVersion": "0.28.82",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
387
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
395
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
403
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
411
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
419
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
427
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
435
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
443
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
451
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
459
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
467
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
475
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
483
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
491
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
499
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
507
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
515
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
523
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
531
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
539
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
547
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
555
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
563
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
571
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
579
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
587
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
595
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
603
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
611
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
619
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
627
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
635
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
643
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
651
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
659
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
667
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
675
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
683
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
691
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
699
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
707
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
715
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
723
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
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": "e05554b595d6a0b067ce8fa659f0cc2948c9428ad412163b5c13ae5e9e378337",
739
+ "contentHash": "6c6f6089f5b68c53ea212ae3ace1ceb6ca8d89437bb9079168585f234bd92dfa",
740
740
  "since": "2025-01-01"
741
741
  },
742
742
  "cli:init": {
@@ -0,0 +1,30 @@
1
+ # Upgrade Guide — v0.28.81
2
+
3
+ <!-- bump: patch -->
4
+
5
+ ## What Changed
6
+
7
+ The underscore-as-italic bug on outbound Telegram messages is fixed. Snake_case identifiers like `GITHUB_TOKEN`, `auto_triage_runs`, and any other word with an underscore inside it stop rendering as italics on Telegram. This was happening because instar was sending messages with `parse_mode: 'Markdown'`, and Telegram's legacy Markdown treats `_word_` as italic.
8
+
9
+ The fix flips the formatter default — the GFM-to-HTML formatter that PR1 + PR2 wired in (shipped disabled in v0.28.76) is now the shipped default. Outbound `sendMessage` and `editMessageText` now route GitHub-flavored markdown → Telegram HTML. Underscores stay literal because HTML doesn't treat them as anything special.
10
+
11
+ Two server-internal callsites (the attention-queue creator and the prompt-gate relay) already produced Telegram HTML directly. They migrate to a per-call `_formatMode: 'html'` opt-out so the markdown converter doesn't re-process their `<b>` tags. The override is reachable only from inside the adapter — HTTP routes cannot set it from the JSON body — which is the spec's "trusted internal callers list" enforced by the call graph rather than a runtime allowlist.
12
+
13
+ ## What to Tell Your User
14
+
15
+ Your Telegram messages from your agent now render correctly. Words with underscores in them — variable names, environment names, identifiers — will appear exactly as written instead of getting random italic styling halfway through. Bold and code blocks still work the way you'd expect. No action needed on your side; the fix lands automatically when your agent auto-updates.
16
+
17
+ If the rendering ever looks worse than before, your agent can flip a config switch back to the old behavior — just say "use the legacy Telegram rendering" and your agent will handle it.
18
+
19
+ ## Summary of New Capabilities
20
+
21
+ - **Markdown → HTML formatter (now default)** — GitHub-flavored markdown (`**bold**`, `` `code` ``, `# headings`, `- bullets`, `[text](url)`) is converted to Telegram HTML automatically on every outbound send. Underscores in identifiers stay literal.
22
+ - **Per-call HTML opt-out (`_formatMode: 'html'`)** — server-internal apiCall callers that already produce Telegram HTML can tag their send to bypass the markdown converter. Used by the attention-queue creator and the prompt-gate relay.
23
+ - **Rollback knob (`telegramFormatMode` in `.instar/config.json`)** — `'legacy-passthrough'` restores byte-for-byte pre-cutover behavior. Hot-reloadable accessor — picks up on next send after the config is saved.
24
+
25
+ ## Evidence
26
+
27
+ - Side-effects review: `docs/specs/side-effects/telegram-markdown-renderer-pr3.md`.
28
+ - Spec: `docs/specs/TELEGRAM-MARKDOWN-RENDERER-SPEC.md` — converged 2026-04-24, approved by Justin same day.
29
+ - Direct Bot API canary (snake_case + bold + code + URL) accepted by Telegram with `parse_mode='HTML'`, no parse error.
30
+ - Tests: 122 telegram formatter unit tests pass; 373 push-tier tests pass; type check clean.
@@ -0,0 +1,35 @@
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 /attention` is now gated by the existing `MessagingToneGate` authority — closing the one outbound user-message path that previously bypassed it. For health-class categories (`degradation`, `health`, `health-alert`, `alert`) the gate is invoked with `messageKind: 'health-alert'` so the existing B12 / B13 / B14 ruleset (jargon-laden internals, suppressed-by-self-heal, no call-to-action) fires before any Telegram topic is created. For other categories the standard ruleset (B1–B7, B11) still applies. When the gate blocks, the route returns 422 in the same shape the other outbound routes already use, and `createAttentionItem` is never invoked — no topic gets spawned, no item gets persisted.
12
+
13
+ `checkOutboundMessage` gained two additive options (`messageKind`, `jargon`) that are forwarded to the gate without changing existing-caller behavior. The `JargonDetector` is invoked as a signal-only detector when `jargon: true` is requested, matching the pattern `DegradationReporter.gateHealthAlert` already uses for its internal alert path.
14
+
15
+ The `guardian-pulse` skill template's recommended attention id is now `degradation:{FEATURE}` (no timestamp suffix). Repeated detections of the same feature collapse onto the existing attention item via `createAttentionItem`'s strict-id dedup instead of spawning a new Telegram topic per pulse.
16
+
17
+ ## What to Tell Your User
18
+
19
+ - **Cleaner attention queue**: "I now run every attention-queue alert through the same plain-English check as my other messages. If something is just background noise, doesn't need your input, or already healed itself, it won't reach you. And recurring versions of the same problem now stay in one topic instead of starting a new one each time."
20
+
21
+ ## Summary of New Capabilities
22
+
23
+ | Capability | How to Use |
24
+ |-----------|-----------|
25
+ | Attention queue gated by tone authority | automatic — applies to every POST to the attention queue |
26
+ | Health-alert ruleset on attention items | automatic when category is degradation / health / alert |
27
+ | Stable attention id for guardian-pulse | new agents pick this up automatically; existing agents keep using the old id, but the gate above catches their messages anyway |
28
+
29
+ ## Evidence
30
+
31
+ Reproduction: an instar agent ("Bob") created seven near-duplicate Telegram topics ("Server degraded | Priority: LOW Git conflicts may not auto-r...") in four days for one recurring degradation event — no call to action, jargon-laden header, nothing actionable. Reported 2026-05-05 by Justin in topic 8937 with screenshot showing the topic list.
32
+
33
+ Verified-after: with `POST /attention` wired through `MessagingToneGate`, identical candidate text returns 422 with `rule=B14_HEALTH_ALERT_NO_CTA` (covered by `tests/unit/attention-route-tone-gate.test.ts`). The route does not invoke `createAttentionItem` on block, so no Telegram topic spawns. The companion `tests/unit/guardian-pulse-skill-stable-id.test.ts` regression-guards the recipe. Pre-push gate ran the full suite (2069 unit tests passed) before push; CI confirmed green on PR #131 before merge.
34
+
35
+ Side-effects review and second-pass concur recorded in `upgrades/side-effects/attention-tone-gate-and-stable-id.md`.
@@ -0,0 +1,162 @@
1
+ # Side-Effects Review — Attention queue tone-gate wiring + guardian-pulse stable id
2
+
3
+ **Version / slug:** `attention-tone-gate-and-stable-id`
4
+ **Date:** `2026-05-06`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `pending — required (touches outbound-message block/allow surface)`
7
+
8
+ ## Summary of the change
9
+
10
+ A user-reported bug: an instar agent ("Bob") created 7+ near-duplicate Telegram topics for the same recurring "git conflict auto-resolution" degradation event over Sat–Tue. Two layered fixes:
11
+
12
+ 1. **Wire `POST /attention` through the existing `MessagingToneGate` authority.** Until now, `/attention` was the only outbound-message path that did NOT consult the gate — every other channel (telegram-reply, slack-reply, whatsapp, imessage) goes through `checkOutboundMessage`. Attention items reach the user as new Telegram topics with the title + summary as the body, so they are absolutely outbound user-facing messages and must pass the same authority. For `category=degradation|health|alert|health-alert` the route invokes the gate with `messageKind: 'health-alert'`, firing the existing B12 (jargon-laden internals), B13 (suppressed-by-self-heal), and B14 (no call-to-action) ruleset. For other categories the gate runs with `messageKind: 'reply'` — the standard ruleset still applies (B1–B7 prevent CLI/path/code leakage; B11 enforces target-style). When the gate blocks, the route returns 422 with the same shape `checkOutboundMessage` already returns elsewhere; `createAttentionItem` is not invoked, so no Telegram topic gets spawned.
13
+
14
+ 2. **Skill recipe fix in `src/commands/init.ts`.** The `guardian-pulse` skill template instructed agents to POST attention items with `id = "degradation:${FEATURE}:${TIMESTAMP}"`. The timestamp made the id unique per detection, so each pulse spawned a new topic for the SAME recurring feature. Changed to `id = "degradation:${FEATURE}"` so repeated detections collapse onto the existing attention item via `createAttentionItem`'s strict-id check.
15
+
16
+ Files touched:
17
+
18
+ - `src/server/routes.ts` — `checkOutboundMessage` accepts new `messageKind` + `jargon` options; `POST /attention` invokes it; `JargonDetector` import added.
19
+ - `src/commands/init.ts` — guardian-pulse skill template id changed to stable form; explanatory note added.
20
+ - `tests/unit/attention-route-tone-gate.test.ts` — new (4 tests): pass/block/non-health/alias coverage for `/attention` POST.
21
+ - `tests/unit/guardian-pulse-skill-stable-id.test.ts` — new (1 test): regression guard against the timestamp suffix returning.
22
+
23
+ ## Decision-point inventory
24
+
25
+ - `POST /attention` route handler (src/server/routes.ts) — **modify** — adds an outbound-message authority call before `createAttentionItem` so the existing tone-gate block/allow decision now applies to attention-queue topic creation.
26
+ - `checkOutboundMessage` helper (src/server/routes.ts) — **modify** — accepts `messageKind` + `jargon` options. Pass-through to existing `MessagingToneGate.review`, which is already an authority. No new decision power introduced — only a new entry point feeding the same authority.
27
+ - `installBuiltinSkills` → guardian-pulse template (src/commands/init.ts) — **modify** — changes the static instruction string the recipe gives agents. No runtime decision logic.
28
+
29
+ ---
30
+
31
+ ## 1. Over-block
32
+
33
+ **What legitimate inputs does this change reject that it shouldn't?**
34
+
35
+ The gate is the existing `MessagingToneGate`; its over-block surface is unchanged. The new entry point preserves the gate's "favor false-negatives over false-positives" disposition — when a candidate is borderline, the gate passes. Specific scenarios examined:
36
+
37
+ - **A genuinely actionable health-alert with a yes/no question and no jargon.** Passes — B12/B13/B14 all require concrete failure conditions to fire.
38
+ - **A non-health attention item that contains a literal path or CLI command.** B1/B2/B5 fire as they would on any other route — this is the intended behavior, not over-block.
39
+ - **An attention item whose summary mentions a feature name that overlaps a jargon term** (e.g., title = "Cron job stuck" with `category=general`). `messageKind` defaults to `reply` for non-health categories, so the jargon signal isn't even gathered — the health-alert ruleset doesn't fire. No over-block.
40
+ - **A deliberately verbose health-alert summary including a yes/no CTA**. Passes B14; `description` text is appended to the candidate so longer descriptions don't accidentally bury the CTA below the body the gate sees.
41
+
42
+ The candidate text the gate sees is `[title, summary, description]` joined with double newlines — this matches the user-visible body Telegram will post on topic creation. No legitimate-input pathway is rejected here that would not be rejected on `telegram-reply`.
43
+
44
+ ---
45
+
46
+ ## 2. Under-block
47
+
48
+ **What failure modes does this still miss?**
49
+
50
+ - **An agent that posts a long descriptive title that ITSELF is the jargon vehicle.** The gate sees the title; no special-casing required.
51
+ - **An agent that bypasses `/attention` entirely and calls `TelegramAdapter.createForumTopic` directly.** This was never gated and remains ungated — out of scope for this change. The Memory Rot Gates spec proposes a `MessageDispatch` boundary refactor that would close every direct call site; this fix is a targeted band-aid for the noisiest known path until that lands.
52
+ - **A genuinely new degradation event for a previously-known feature.** The skill recipe now produces the same id, so the second detection silently no-ops — the user does NOT get notified about the recurrence. Trade-off: chosen deliberately. The user's complaint was "none of these should have been created"; quiet recurrence is preferable to a new topic per recurrence. If recurrences need re-surfacing, that's a follow-up via an explicit `lastSeenAt` / occurrence counter on `AttentionItem` and an "append to existing topic" branch — not this fix.
53
+ - **`/attention` calls that supply `category` in mixed case or with whitespace.** The regex normalization is `^(degradation|health|health-alert|alert)$/i` — exact match (case-insensitive). Trailing whitespace, plurals, or aliases like "system-health" would default to `messageKind=reply`. Acceptable: the gate still runs the standard ruleset; only the health-alert-specific rules are skipped. If callers consistently use a non-matching alias we'll see it in the tone-gate-decision log and can extend the regex.
54
+ - **The gate fail-opens on LLM error/timeout.** Inherited from the existing gate behavior — not a regression. Fail-open is the existing system-wide policy and is documented in `MessagingToneGate.ts`.
55
+
56
+ ---
57
+
58
+ ## 3. Level-of-abstraction fit
59
+
60
+ **Is this at the right layer?**
61
+
62
+ Yes. The fix is at the route-handler layer where every other outbound-message gate already sits. The `MessagingToneGate` is the single existing authority for "should this user-facing text be sent" — feeding `/attention` into it is the layer-correct move. The alternative — putting the gate inside `TelegramAdapter.createAttentionItem` — would be lower-level, but `createAttentionItem` doesn't know about `messageKind` semantics or how to format a 422 response shape, and other adapters (Slack, WhatsApp) would need the same wiring. Doing it at the route handler keeps the authority single-locus.
63
+
64
+ The skill template fix is a documentation-layer change (the skill is a markdown recipe rendered to disk; agents read it). It belongs in `src/commands/init.ts` where the rest of the skill content already lives.
65
+
66
+ The fix does NOT preempt the planned `MessageDispatch` refactor in the Memory Rot Gates spec (`docs/specs/memory-rot-gates.md`) — that refactor would route ALL outbound message paths through one module, including `createAttentionItem` and the other direct-send paths. This fix is a route-level wiring that the future refactor will subsume cleanly: `MessageDispatch` will absorb the `checkOutboundMessage` call site without behavior change.
67
+
68
+ ---
69
+
70
+ ## 4. Signal vs authority compliance
71
+
72
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
73
+
74
+ **Does this change hold blocking authority with brittle logic?**
75
+
76
+ - [x] No — this change produces a signal consumed by an existing smart gate.
77
+ - [ ] No — this change has no block/allow surface.
78
+ - [ ] Yes — but the logic is a smart gate with full conversational context (LLM-backed with recent history or equivalent).
79
+ - [ ] ⚠️ Yes, with brittle logic — STOP.
80
+
81
+ The brittle pieces here are:
82
+ 1. The `category ∈ {degradation, health, alert, health-alert}` regex that decides whether to invoke `messageKind='health-alert'`. This is a routing hint, not a block decision — it just toggles which ruleset the gate considers. The gate is the only thing with blocking power.
83
+ 2. The `JargonDetector.detectJargon` call. `JargonDetector.ts` opens with "SIGNAL ONLY. This detector produces evidence; it does not block." Already-compliant; we're using it as designed — the detector populates `signals.jargon` and the gate decides.
84
+
85
+ Both pieces feed the existing `MessagingToneGate` as a SIGNAL. No new brittle authority is introduced. The 422 response that the route returns is sourced from `MessagingToneGate.review(...).pass === false` — i.e., the existing authority's decision, not a new one.
86
+
87
+ The skill recipe fix is a string change in a template — it has no decision logic at all and trivially complies.
88
+
89
+ ---
90
+
91
+ ## 5. Interactions
92
+
93
+ **Does this interact with existing checks, recovery paths, or infrastructure?**
94
+
95
+ - **Shadowing:** The new gate call runs BEFORE `createAttentionItem`. `createAttentionItem` already has a strict-id dedup (line 2845-2847) — that dedup is preserved unchanged. The two layer correctly: gate decides if the message is appropriate for the user; dedup decides if a same-id item is already known. They do not shadow each other.
96
+ - **Double-fire:** The gate is invoked on `/attention` POST and on the four direct messaging routes (telegram-reply, slack-reply, whatsapp, imessage). An attention item that gets created produces a Telegram message via `TelegramAdapter` internals — that downstream send does NOT re-invoke the gate (no double-fire). The DegradationReporter has its own `gateHealthAlert` for its DIRECT alert path (a different path that doesn't go through `/attention`). The new route-level gate does not interact with the reporter's internal gate.
97
+ - **Races:** The gate is a single LLM call before `createAttentionItem`. `createAttentionItem` is async and uses an in-memory `Map<id, AttentionItem>`. Two concurrent `/attention` POSTs with the same id could both pass the gate and both reach `createAttentionItem`; the second hits the strict-id check and returns the existing item without creating a duplicate topic. No new race; existing race-free behavior preserved.
98
+ - **Feedback loops:** The gate's decision log writes to stderr (existing behavior). The 422 response shape is unchanged from existing gate-blocked responses, so any caller-side retry logic that already handles 422 from telegram-reply will handle it the same way from /attention. No new feedback loop.
99
+
100
+ ---
101
+
102
+ ## 6. External surfaces
103
+
104
+ **Does this change anything visible outside the immediate code path?**
105
+
106
+ - **Other agents on the same machine:** Agents that POST to `/attention` may now receive 422 responses they didn't receive before. The 422 body shape (`{error, rule, issue, suggestion, latencyMs}`) matches the existing telegram-reply 422 shape, so any caller that already handles telegram-reply rejects can handle attention rejects identically. The guardian-pulse recipe in particular runs in a shell script that does not check HTTP status — it will silently swallow the 422, which is the desired behavior for noisy degradation events. Agents using `mark-reported` after `/attention` will still call mark-reported regardless of the attention POST status; the event stays out of the user's face whether the attention item created or got blocked.
107
+ - **Other users of the install base:** Behavioral change visible at the user's Telegram: fewer noise topics created. This IS the requested behavior. Existing topics created before this fix shipped are NOT cleaned up — that's a separate concern (the `/done` command per topic).
108
+ - **External systems:** No new Telegram API calls. Fewer `createForumTopic` calls when the gate blocks. No change to Slack/WhatsApp/iMessage paths.
109
+ - **Persistent state:** None. `attention-items.json` schema unchanged. The skill recipe fix only changes the rendered SKILL.md content for newly-installed agents (`migrateBuiltinSkills` is non-destructive and skips files that already exist) — existing agents will continue using the timestamped id until they reinstall the skill or get a destructive migration. The tone-gate at `/attention` is the primary defense and works regardless of skill version.
110
+ - **Timing / runtime:** Adds one Haiku-class LLM call per `/attention` POST (~500ms p50, ~3s p99). The existing `checkOutboundMessage` already absorbs this latency on every other outbound path; `/attention` is not user-facing latency-critical (agents calling it are background pulses, not interactive flows).
111
+
112
+ ---
113
+
114
+ ## 7. Rollback cost
115
+
116
+ **If this turns out wrong in production, what's the back-out?**
117
+
118
+ Pure code revert. No data migration. No agent state repair.
119
+
120
+ - The route changes (the gate call and the `messageKind`/`jargon` options on `checkOutboundMessage`) revert cleanly — no callers outside this PR depend on the new options.
121
+ - The skill template change reverts cleanly. New agents installed during the rollout will have the stable-id template; reverting the change does not invalidate their existing SKILL.md.
122
+ - `attention-items.json` unchanged in shape, so no DB-style migration concerns.
123
+ - During the rollback window, agents that received 422 responses they don't know how to handle would not have been retrying anyway (the recipe doesn't); rollback simply lets the previous noisy behavior return.
124
+
125
+ Estimated rollback time: hot-fix release, < 5 minutes from decision to ship.
126
+
127
+ ---
128
+
129
+ ## Conclusion
130
+
131
+ The change closes the one outbound-message path (`/attention`) that wasn't already gated, using the existing authority and existing rules. It is signal-vs-authority compliant: brittle bits are routing hints and signal producers, never blockers. The skill recipe fix is a one-line content change with a regression test guarding the regression. Both layered together give defense-in-depth: even if a future agent ignores the recipe and uses unstable IDs, the gate catches the message-quality failure (no CTA, jargon, suppressed-by-self-heal). And even if the gate fail-opens on an LLM error, the stable-id recipe prevents same-feature spam via `createAttentionItem`'s strict-id dedup.
132
+
133
+ Clear to ship pending second-pass review (required — touches outbound-message block/allow surface).
134
+
135
+ ---
136
+
137
+ ## Second-pass review (if required)
138
+
139
+ **Reviewer:** independent general-purpose subagent (instar-dev Phase 5 — outbound-message block/allow surface)
140
+ **Independent read of the artifact: CONCUR**
141
+
142
+ The reviewer independently read `signal-vs-authority.md`, the artifact, the source diff against main, and both new test files. Findings:
143
+
144
+ - **Signal vs authority audit clean.** `JargonDetector` is documented as signal-only and consumed via `signals.jargon`. The category regex is a routing hint that toggles which ruleset the gate considers, not a blocker. The only blocking decision is the LLM-backed `MessagingToneGate.review` call.
145
+ - **Tests genuinely exercise the claimed behavior.** Pass/block/non-health/alias paths each assert the recorded `messageKind` and verify `createAttentionItem` is NOT invoked on block.
146
+ - **Rollback claim verified.** `attention-items.json` schema unchanged. Skill template change is content-only.
147
+
148
+ Two minor observations the reviewer flagged but accepted:
149
+
150
+ 1. **In-memory dedup volatility across restarts.** `attentionItems` is a `Map` rebuilt on server start. Across server restarts a fresh map could let `degradation:foo` spawn a new topic. Mitigation: the file is persisted to `attention-items.json` and loaded on init (existing behavior — see `loadAttentionItems` at TelegramAdapter.ts:3001), so cross-restart dedup IS preserved. The reviewer's concern is satisfied by existing persistence; documenting here for completeness.
151
+ 2. **No topicId on attention POSTs → no recent-context history fed to the gate.** Acceptable: attention items create new topics, so there is no prior thread context applicable. The health-alert ruleset (B12/B13/B14) does not depend on per-thread history.
152
+
153
+ Conclusion: clear to ship.
154
+
155
+ ---
156
+
157
+ ## Evidence pointers
158
+
159
+ - New tests: `tests/unit/attention-route-tone-gate.test.ts` (4 tests), `tests/unit/guardian-pulse-skill-stable-id.test.ts` (1 test). All pass.
160
+ - Existing adjacent tests verified non-regressing: `tests/unit/MessagingToneGate.test.ts` (27), `tests/unit/messaging-tone-gate-health-alerts.test.ts` (8), `tests/unit/reply-scripts.test.ts` (15), `tests/unit/server.test.ts` (16) — all pass.
161
+ - Tone-gate decision log captured in test runs confirms `messageKind=health-alert` for `category=degradation` and `messageKind=reply` for `category=general`, with the correct rule fired (B14_HEALTH_ALERT_NO_CTA) when the mocked provider blocks a no-CTA degradation candidate.
162
+ - Original user report: Telegram screenshot showing 7+ duplicate "Server degraded / git conflict auto-resolution" topics from Bob agent over 2026-05-02 → 2026-05-05, all with no CTA and Priority: LOW headers — the exact pattern this fix structurally prevents.