instar 1.3.975 → 1.3.976

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": "1.3.975",
3
+ "version": "1.3.976",
4
4
  "description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
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-07-26T02:30:21.100Z",
5
- "instarVersion": "1.3.975",
4
+ "generatedAt": "2026-07-26T02:45:59.451Z",
5
+ "instarVersion": "1.3.976",
6
6
  "entryCount": 202,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -418,7 +418,7 @@
418
418
  "type": "route-group",
419
419
  "domain": "monitoring",
420
420
  "sourcePath": "src/server/routes.ts",
421
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
421
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
422
422
  "since": "2025-01-01"
423
423
  },
424
424
  "route-group:agents": {
@@ -426,7 +426,7 @@
426
426
  "type": "route-group",
427
427
  "domain": "sessions",
428
428
  "sourcePath": "src/server/routes.ts",
429
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
429
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
430
430
  "since": "2025-01-01"
431
431
  },
432
432
  "route-group:backups": {
@@ -434,7 +434,7 @@
434
434
  "type": "route-group",
435
435
  "domain": "operations",
436
436
  "sourcePath": "src/server/routes.ts",
437
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
437
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
438
438
  "since": "2025-01-01"
439
439
  },
440
440
  "route-group:git": {
@@ -442,7 +442,7 @@
442
442
  "type": "route-group",
443
443
  "domain": "coordination",
444
444
  "sourcePath": "src/server/routes.ts",
445
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
445
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
446
446
  "since": "2025-01-01"
447
447
  },
448
448
  "route-group:memory": {
@@ -450,7 +450,7 @@
450
450
  "type": "route-group",
451
451
  "domain": "memory",
452
452
  "sourcePath": "src/server/routes.ts",
453
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
453
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
454
454
  "since": "2025-01-01"
455
455
  },
456
456
  "route-group:semantic": {
@@ -458,7 +458,7 @@
458
458
  "type": "route-group",
459
459
  "domain": "memory",
460
460
  "sourcePath": "src/server/routes.ts",
461
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
461
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
462
462
  "since": "2025-01-01"
463
463
  },
464
464
  "route-group:status": {
@@ -466,7 +466,7 @@
466
466
  "type": "route-group",
467
467
  "domain": "monitoring",
468
468
  "sourcePath": "src/server/routes.ts",
469
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
469
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
470
470
  "since": "2025-01-01"
471
471
  },
472
472
  "route-group:capabilities": {
@@ -474,7 +474,7 @@
474
474
  "type": "route-group",
475
475
  "domain": "mapping",
476
476
  "sourcePath": "src/server/routes.ts",
477
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
477
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
478
478
  "since": "2025-01-01"
479
479
  },
480
480
  "route-group:project-map": {
@@ -482,7 +482,7 @@
482
482
  "type": "route-group",
483
483
  "domain": "mapping",
484
484
  "sourcePath": "src/server/routes.ts",
485
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
485
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
486
486
  "since": "2025-01-01"
487
487
  },
488
488
  "route-group:coherence": {
@@ -490,7 +490,7 @@
490
490
  "type": "route-group",
491
491
  "domain": "coherence",
492
492
  "sourcePath": "src/server/routes.ts",
493
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
493
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
494
494
  "since": "2025-01-01"
495
495
  },
496
496
  "route-group:topic-bindings": {
@@ -498,7 +498,7 @@
498
498
  "type": "route-group",
499
499
  "domain": "sessions",
500
500
  "sourcePath": "src/server/routes.ts",
501
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
501
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
502
502
  "since": "2025-01-01"
503
503
  },
504
504
  "route-group:context": {
@@ -506,7 +506,7 @@
506
506
  "type": "route-group",
507
507
  "domain": "context",
508
508
  "sourcePath": "src/server/routes.ts",
509
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
509
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
510
510
  "since": "2025-01-01"
511
511
  },
512
512
  "route-group:scope-coherence": {
@@ -514,7 +514,7 @@
514
514
  "type": "route-group",
515
515
  "domain": "coherence",
516
516
  "sourcePath": "src/server/routes.ts",
517
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
517
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
518
518
  "since": "2025-01-01"
519
519
  },
520
520
  "route-group:canonical-state": {
@@ -522,7 +522,7 @@
522
522
  "type": "route-group",
523
523
  "domain": "state",
524
524
  "sourcePath": "src/server/routes.ts",
525
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
525
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
526
526
  "since": "2025-01-01"
527
527
  },
528
528
  "route-group:ci": {
@@ -530,7 +530,7 @@
530
530
  "type": "route-group",
531
531
  "domain": "monitoring",
532
532
  "sourcePath": "src/server/routes.ts",
533
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
533
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
534
534
  "since": "2025-01-01"
535
535
  },
536
536
  "route-group:sessions": {
@@ -538,7 +538,7 @@
538
538
  "type": "route-group",
539
539
  "domain": "sessions",
540
540
  "sourcePath": "src/server/routes.ts",
541
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
541
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
542
542
  "since": "2025-01-01"
543
543
  },
544
544
  "route-group:jobs": {
@@ -546,7 +546,7 @@
546
546
  "type": "route-group",
547
547
  "domain": "scheduling",
548
548
  "sourcePath": "src/server/routes.ts",
549
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
549
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
550
550
  "since": "2025-01-01"
551
551
  },
552
552
  "route-group:skip-ledger": {
@@ -554,7 +554,7 @@
554
554
  "type": "route-group",
555
555
  "domain": "scheduling",
556
556
  "sourcePath": "src/server/routes.ts",
557
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
557
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
558
558
  "since": "2025-01-01"
559
559
  },
560
560
  "route-group:telegram": {
@@ -562,7 +562,7 @@
562
562
  "type": "route-group",
563
563
  "domain": "communication",
564
564
  "sourcePath": "src/server/routes.ts",
565
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
565
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
566
566
  "since": "2025-01-01"
567
567
  },
568
568
  "route-group:attention": {
@@ -570,7 +570,7 @@
570
570
  "type": "route-group",
571
571
  "domain": "communication",
572
572
  "sourcePath": "src/server/routes.ts",
573
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
573
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
574
574
  "since": "2025-01-01"
575
575
  },
576
576
  "route-group:relationships": {
@@ -578,7 +578,7 @@
578
578
  "type": "route-group",
579
579
  "domain": "relationships",
580
580
  "sourcePath": "src/server/routes.ts",
581
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
581
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
582
582
  "since": "2025-01-01"
583
583
  },
584
584
  "route-group:feedback": {
@@ -586,7 +586,7 @@
586
586
  "type": "route-group",
587
587
  "domain": "feedback",
588
588
  "sourcePath": "src/server/routes.ts",
589
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
589
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
590
590
  "since": "2025-01-01"
591
591
  },
592
592
  "route-group:updates": {
@@ -594,7 +594,7 @@
594
594
  "type": "route-group",
595
595
  "domain": "updates",
596
596
  "sourcePath": "src/server/routes.ts",
597
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
597
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
598
598
  "since": "2025-01-01"
599
599
  },
600
600
  "route-group:dispatches": {
@@ -602,7 +602,7 @@
602
602
  "type": "route-group",
603
603
  "domain": "dispatches",
604
604
  "sourcePath": "src/server/routes.ts",
605
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
605
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
606
606
  "since": "2025-01-01"
607
607
  },
608
608
  "route-group:quota": {
@@ -610,7 +610,7 @@
610
610
  "type": "route-group",
611
611
  "domain": "monitoring",
612
612
  "sourcePath": "src/server/routes.ts",
613
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
613
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
614
614
  "since": "2025-01-01"
615
615
  },
616
616
  "route-group:publishing": {
@@ -618,7 +618,7 @@
618
618
  "type": "route-group",
619
619
  "domain": "publishing",
620
620
  "sourcePath": "src/server/routes.ts",
621
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
621
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
622
622
  "since": "2025-01-01"
623
623
  },
624
624
  "route-group:private-views": {
@@ -626,7 +626,7 @@
626
626
  "type": "route-group",
627
627
  "domain": "publishing",
628
628
  "sourcePath": "src/server/routes.ts",
629
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
629
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
630
630
  "since": "2025-01-01"
631
631
  },
632
632
  "route-group:tunnel": {
@@ -634,7 +634,7 @@
634
634
  "type": "route-group",
635
635
  "domain": "networking",
636
636
  "sourcePath": "src/server/routes.ts",
637
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
637
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
638
638
  "since": "2025-01-01"
639
639
  },
640
640
  "route-group:events": {
@@ -642,7 +642,7 @@
642
642
  "type": "route-group",
643
643
  "domain": "networking",
644
644
  "sourcePath": "src/server/routes.ts",
645
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
645
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
646
646
  "since": "2025-01-01"
647
647
  },
648
648
  "route-group:evolution": {
@@ -650,7 +650,7 @@
650
650
  "type": "route-group",
651
651
  "domain": "evolution",
652
652
  "sourcePath": "src/server/routes.ts",
653
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
653
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
654
654
  "since": "2025-01-01"
655
655
  },
656
656
  "route-group:watchdog": {
@@ -658,7 +658,7 @@
658
658
  "type": "route-group",
659
659
  "domain": "monitoring",
660
660
  "sourcePath": "src/server/routes.ts",
661
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
661
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
662
662
  "since": "2025-01-01"
663
663
  },
664
664
  "route-group:topic-memory": {
@@ -666,7 +666,7 @@
666
666
  "type": "route-group",
667
667
  "domain": "memory",
668
668
  "sourcePath": "src/server/routes.ts",
669
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
669
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
670
670
  "since": "2025-01-01"
671
671
  },
672
672
  "route-group:state-sync": {
@@ -674,7 +674,7 @@
674
674
  "type": "route-group",
675
675
  "domain": "coordination",
676
676
  "sourcePath": "src/server/routes.ts",
677
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
677
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
678
678
  "since": "2025-01-01"
679
679
  },
680
680
  "route-group:intent": {
@@ -682,7 +682,7 @@
682
682
  "type": "route-group",
683
683
  "domain": "intent",
684
684
  "sourcePath": "src/server/routes.ts",
685
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
685
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
686
686
  "since": "2025-01-01"
687
687
  },
688
688
  "route-group:triage": {
@@ -690,7 +690,7 @@
690
690
  "type": "route-group",
691
691
  "domain": "safety",
692
692
  "sourcePath": "src/server/routes.ts",
693
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
693
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
694
694
  "since": "2025-01-01"
695
695
  },
696
696
  "route-group:operations": {
@@ -698,7 +698,7 @@
698
698
  "type": "route-group",
699
699
  "domain": "safety",
700
700
  "sourcePath": "src/server/routes.ts",
701
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
701
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
702
702
  "since": "2025-01-01"
703
703
  },
704
704
  "route-group:sentinel": {
@@ -706,7 +706,7 @@
706
706
  "type": "route-group",
707
707
  "domain": "safety",
708
708
  "sourcePath": "src/server/routes.ts",
709
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
709
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
710
710
  "since": "2025-01-01"
711
711
  },
712
712
  "route-group:trust": {
@@ -714,7 +714,7 @@
714
714
  "type": "route-group",
715
715
  "domain": "safety",
716
716
  "sourcePath": "src/server/routes.ts",
717
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
717
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
718
718
  "since": "2025-01-01"
719
719
  },
720
720
  "route-group:monitoring": {
@@ -722,7 +722,7 @@
722
722
  "type": "route-group",
723
723
  "domain": "monitoring",
724
724
  "sourcePath": "src/server/routes.ts",
725
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
725
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
726
726
  "since": "2025-01-01"
727
727
  },
728
728
  "route-group:commitments": {
@@ -730,7 +730,7 @@
730
730
  "type": "route-group",
731
731
  "domain": "commitments",
732
732
  "sourcePath": "src/server/routes.ts",
733
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
733
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
734
734
  "since": "2025-01-01"
735
735
  },
736
736
  "route-group:episodes": {
@@ -738,7 +738,7 @@
738
738
  "type": "route-group",
739
739
  "domain": "memory",
740
740
  "sourcePath": "src/server/routes.ts",
741
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
741
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
742
742
  "since": "2025-01-01"
743
743
  },
744
744
  "route-group:messages": {
@@ -746,7 +746,7 @@
746
746
  "type": "route-group",
747
747
  "domain": "coordination",
748
748
  "sourcePath": "src/server/routes.ts",
749
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
749
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
750
750
  "since": "2025-01-01"
751
751
  },
752
752
  "route-group:system-reviews": {
@@ -754,7 +754,7 @@
754
754
  "type": "route-group",
755
755
  "domain": "monitoring",
756
756
  "sourcePath": "src/server/routes.ts",
757
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
757
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
758
758
  "since": "2025-01-01"
759
759
  },
760
760
  "route-group:machine-mesh": {
@@ -770,7 +770,7 @@
770
770
  "type": "route-group",
771
771
  "domain": "security",
772
772
  "sourcePath": "src/server/routes.ts",
773
- "contentHash": "9cda21e349af7f9e1b0817a7a5aba7e54e0325a4c15ab3563ff87637aacb8515",
773
+ "contentHash": "c55d95e9a2af479f5ae1cbb258308581b4f272b7b7722c5e876f636089d5acce",
774
774
  "since": "2025-01-01"
775
775
  },
776
776
  "cli:init": {
@@ -0,0 +1,60 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ **The projects `/advance` merge-base check no longer reports "not on main" when it was simply not
9
+ allowed to look.** Found 2026-07-25 recording PR #1641 as merged — the step had never once
10
+ succeeded on a dogfooding agent.
11
+
12
+ - **The read now declares itself a read.** `gitMergeBaseIsAncestor` called
13
+ `SafeGitExecutor.readSync` without `sourceTreeReadOk: true`. A project's `targetRepoPath` IS an
14
+ instar source tree on a dogfooding agent, so `SourceTreeGuard` refused the query every time.
15
+ `merge-base` is already in `SOURCE_TREE_READ_TIER_VERBS` — the permission existed and was never
16
+ requested.
17
+ - **A refusal is no longer translated into a fact (the load-bearing half).** The old
18
+ `catch { return false }` turned a guard refusal, a missing binary, a bad revision (exit 128) and
19
+ a timeout into the same `false`, which the validator surfaced as `MERGE_COMMIT_UNREACHABLE` —
20
+ "this merge is not on main" — about a merge that demonstrably was. Now ONLY git's documented exit
21
+ status 1 means "not an ancestor"; every other failure is rethrown and
22
+ `StageTransitionValidator` returns a new distinct code **`MERGE_BASE_UNVERIFIABLE`** carrying the
23
+ underlying cause.
24
+
25
+ Nothing is loosened: a genuine non-ancestor still fails with `MERGE_COMMIT_UNREACHABLE` (asserted
26
+ in its own test so the boundary is not blurred in the other direction).
27
+
28
+ Reproduced under the server's exact environment before fixing: real merge SHA without the flag →
29
+ `SourceTreeGuardError`; with the flag → ancestor TRUE; a real commit not on main → status 1; a
30
+ nonexistent SHA → status 128 (unanswerable, which the old code also called a negative).
31
+
32
+ ## What to Tell Your User
33
+
34
+ If you use projects to track work, marking an item as merged should now succeed where it previously
35
+ failed with a confusing "merge commit is not reachable from main" — especially on an agent whose
36
+ target repository is the instar source tree. If the check genuinely cannot run, you now get "could
37
+ not verify" with the reason instead of a wrong factual claim.
38
+
39
+ ## Summary of New Capabilities
40
+
41
+ - `MERGE_BASE_UNVERIFIABLE` — a new stage-transition refusal code distinguishing "could not check"
42
+ from "checked and it is not there". The reason string carries the underlying cause.
43
+
44
+ ## Evidence
45
+
46
+ - `tests/unit/StageTransitionValidator.test.ts` — a throwing helper yields
47
+ `MERGE_BASE_UNVERIFIABLE`; a helper returning false still yields `MERGE_COMMIT_UNREACHABLE`.
48
+ - `tests/unit/projects-advance-mergebase-wiring.test.ts` — static wiring: the callsite carries
49
+ `sourceTreeReadOk: true`, the helper tests `status === 1` and rethrows otherwise, the bare
50
+ `catch { return false }` shape cannot reappear, and the new code comes from a `catch`. Static
51
+ rather than mocked because mocking `SafeGitExecutor` is how the existing tests masked this gap.
52
+
53
+ ## Known Gap (measured, tracked)
54
+
55
+ This is the SECOND instance of this bug class (the first, in May, hit failure-learning's git reads;
56
+ its ratchet was scoped to that subsystem only). Measured exposure: **34 of 46**
57
+ `SafeGitExecutor.readSync` callsites in `src/` do not pass `sourceTreeReadOk: true`. Most are
58
+ legitimate (targets that are not the instar source tree). They are deliberately NOT swept here —
59
+ flagging 34 callsites blind would relax a safety guard on evidence nobody has. The follow-up is a
60
+ per-callsite audit then a repo-wide default-plus-declared-exception ratchet. <!-- tracked: CMT-1035 -->
@@ -0,0 +1,132 @@
1
+ # Side-Effects Review — honest merge-base verification (a refusal is not a fact)
2
+
3
+ ## Summary of the change
4
+
5
+ Two defects in the projects `/advance` merge-base check, found 2026-07-25 while recording PR #1641
6
+ as merged (project `convergence-towards-coherence`, Tier 1 item 1).
7
+
8
+ **A. The read never declared itself a read.** `routes.ts`'s injected `gitMergeBaseIsAncestor`
9
+ called `SafeGitExecutor.readSync(['merge-base','--is-ancestor',…])` without
10
+ `sourceTreeReadOk: true`. A project's `targetRepoPath` IS an instar source tree on any dogfooding
11
+ agent, so `runSourceTreeChecks` refused the query every time with `SourceTreeGuardError`. Note
12
+ `merge-base` is ALREADY in `SOURCE_TREE_READ_TIER_VERBS` — the permission for exactly this read
13
+ existed and was never requested. Fix: pass the flag.
14
+
15
+ **B. (The load-bearing half.) The helper translated every failure into a factual negative.** The
16
+ old body was `catch { return false }` with a comment asserting that a non-zero exit "IS the
17
+ negative answer, not a degradation". That is true only for exit status 1. A guard refusal, a
18
+ missing binary, a bad revision (128) or a timeout all returned the same `false`, and the validator
19
+ turned it into `MERGE_COMMIT_UNREACHABLE` — "this merge is not on main" — about a merge that
20
+ demonstrably was. Fix: only `status === 1` returns false; every other failure is rethrown, and
21
+ `StageTransitionValidator` catches it and returns a NEW distinct code `MERGE_BASE_UNVERIFIABLE`
22
+ with the underlying cause in the reason.
23
+
24
+ Reproduced under the server's exact PATH/cwd BEFORE fixing, all four boundary cases:
25
+
26
+ | input | result | old code said |
27
+ |---|---|---|
28
+ | real merge SHA, no flag | `SourceTreeGuardError`, `status: undefined` | "not reachable" (false) |
29
+ | real merge SHA, with flag | returns → ancestor TRUE | — |
30
+ | real commit not on main | `status: 1` | "not reachable" (correct) |
31
+ | nonexistent SHA | `status: 128` | "not reachable" (wrong — unanswerable ≠ negative) |
32
+
33
+ ## Decision-point inventory
34
+
35
+ - `gitMergeBaseIsAncestor` — a helper feeding a GATE (the `building → merged` transition). Its
36
+ verdict decides whether a project item may be recorded merged. This change does not widen what
37
+ passes: a genuine non-ancestor still fails. It narrows what is *called* a non-ancestor.
38
+ - `validateStageTransition` `to === 'merged'` — the gate itself. Gains one new refusal code; loses
39
+ no existing refusal. `MERGE_COMMIT_UNREACHABLE` still fires for real non-ancestors
40
+ (asserted in a dedicated test so the boundary is not blurred in the other direction).
41
+ - No other decision point, hook, reaper, sentinel, scheduler or migration path is touched.
42
+
43
+ ## 1. Over-block
44
+
45
+ The gate becomes *more* likely to refuse in one respect: a case that previously produced
46
+ `MERGE_COMMIT_UNREACHABLE` may now produce `MERGE_BASE_UNVERIFIABLE`. Both are refusals, so nothing
47
+ that used to be blocked is now allowed — the transition is equally gated, with an honest reason.
48
+
49
+ The new `throw` path is bounded: it is caught inside `validateStageTransition` and converted to a
50
+ verdict. It cannot escape to a 500. (Asserted by the validator unit test, which passes a throwing
51
+ helper and expects `ok: false` with the new code, not an exception.)
52
+
53
+ ## 2. Under-block
54
+
55
+ **Nothing is loosened.** `status === 1` — git's documented "not an ancestor" — still returns false
56
+ and still yields `MERGE_COMMIT_UNREACHABLE`. The one behaviour change in the permissive direction
57
+ is that a read the guard was refusing now succeeds; that read is already sanctioned for source
58
+ trees by `SOURCE_TREE_READ_TIER_VERBS`, so this asks for a permission the design already grants
59
+ rather than creating one.
60
+
61
+ `sourceTreeReadOk: true` is scoped to this single call. It does not relax SourceTreeGuard for any
62
+ other operation, and it cannot: the flag is per-invocation and only bypasses the check for verbs in
63
+ the read-tier set.
64
+
65
+ ## 3. Blast radius
66
+
67
+ `src/server/routes.ts` (one helper), `src/core/StageTransitionValidator.ts` (one call wrapped, one
68
+ new code). Every consumer of the merged-transition verdict was checked:
69
+
70
+ - `grep -rn "MERGE_COMMIT_UNREACHABLE"` — the route surfaces `result.code` verbatim in a 409 body;
71
+ no consumer switches on the code value, so a new code string breaks no branch.
72
+ - `tests/unit/StageTransitionValidator.test.ts` — 41 tests, all pass, including the pre-existing
73
+ `MERGE_COMMIT_UNREACHABLE` case (deliberately kept and re-asserted).
74
+ - `tests/integration/projects-api.test.ts` — mocks the helper with plain booleans; unaffected,
75
+ because the boolean contract is unchanged for helpers that do not throw.
76
+
77
+ ## 4. Rollback plan
78
+
79
+ Single-commit revert; no state, no config key, no migration, no persisted artifact. Reverting
80
+ restores the previous (wrong) behaviour immediately with nothing to clean up.
81
+
82
+ ## 5. Test coverage (all tiers that apply)
83
+
84
+ - **Unit — behaviour** (`tests/unit/StageTransitionValidator.test.ts`, +2): a throwing helper
85
+ yields `MERGE_BASE_UNVERIFIABLE` with a `could not verify` reason carrying the cause; and — the
86
+ other side of the boundary — a helper returning `false` still yields
87
+ `MERGE_COMMIT_UNREACHABLE`. Both directions, because making refusals honest must not stop the
88
+ check refusing real negatives.
89
+ - **Unit — wiring** (`tests/unit/projects-advance-mergebase-wiring.test.ts`, new): static
90
+ introspection asserting the callsite carries `sourceTreeReadOk: true`, the helper tests
91
+ `status === 1` explicitly and rethrows otherwise, the bare `catch { return false }` shape cannot
92
+ reappear, and the validator produces the new code from a `catch`. Static rather than mocked
93
+ **because mocking SafeGitExecutor is exactly how the existing `/advance` tests masked this gap**
94
+ — a runtime mock never reaches the guard.
95
+ - **No new integration/e2e tier**: the route change is a two-line option + error-classification
96
+ fix with no new endpoint or response shape; the existing `projects-api` integration suite covers
97
+ the route, and the real end-to-end proof is the live advance succeeding after release (a
98
+ condition of autonomous run `run-ms13zzrz-78576404`).
99
+
100
+ ## 6. The bug CLASS, measured rather than guessed
101
+
102
+ **This is the second instance of the same bug.** In May the identical missing declaration made
103
+ failure-learning's git reads silently fail on dogfooding agents while `/failures/*` reported
104
+ health. It was fixed, and `tests/unit/failure-learning-source-tree-readok-wiring.test.ts` was
105
+ written to stop it recurring — **scoped to that subsystem's five files and its
106
+ `failure-learning:*` operations only.** So the class survived, moved one subsystem over, and
107
+ reproduced.
108
+
109
+ Exposure, measured (not estimated): **34 of 46** `SafeGitExecutor.readSync` callsites in `src/` do
110
+ not pass `sourceTreeReadOk: true`. Many are legitimate — `WorktreeManager` on a fresh clone,
111
+ `nuke.ts` on a shadow install, `commands/init.ts` on a user's own repo — where the target is not
112
+ the instar source tree and the guard should not be bypassed.
113
+
114
+ **Deliberately NOT swept in this change.** A blind flag-everything pass would touch 34 callsites
115
+ across subsystems whose target paths I have not verified, and would relax a safety guard on
116
+ evidence I do not have. That is precisely the confident over-reach this project exists to remove.
117
+ The honest form is a per-callsite audit answering "can this path ever be the instar source tree?",
118
+ which is real work with a known size.
119
+
120
+ Proposed follow-up, with the size stated so it cannot be mistaken for a quick fix: generalise the
121
+ May ratchet from one subsystem to a repo-wide default-plus-declared-exception check (each callsite
122
+ either carries the flag or an explicit `// source-tree-n/a: <reason>` marker), landing after the
123
+ 34-callsite audit. <!-- tracked: CMT-1035 -->
124
+
125
+ ## 7. One thing found while writing the test, recorded rather than tidied away
126
+
127
+ The assertion forbidding the old `catch { return false }` shape initially FAILED — because it
128
+ matched the helper's own comment, which quotes that shape while explaining its removal. A
129
+ text-matching check fooled by prose describing the thing it forbids. Fixed by stripping comments
130
+ before matching, and worth naming: our constitution says an LLM gate must not string-match, and
131
+ this is the static-check equivalent of the same trap. Cheap at test-writing time; the same mistake
132
+ inside a live gate is how you get a check that fires on nothing.