instar 1.3.327 → 1.3.329

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-06-06T02:41:41.619Z",
5
- "instarVersion": "1.3.327",
4
+ "generatedAt": "2026-06-06T03:08:49.643Z",
5
+ "instarVersion": "1.3.329",
6
6
  "entryCount": 199,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -778,7 +778,7 @@
778
778
  "type": "cli-command",
779
779
  "domain": "setup",
780
780
  "sourcePath": "src/cli.ts",
781
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
781
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
782
782
  "since": "2025-01-01"
783
783
  },
784
784
  "cli:setup": {
@@ -786,7 +786,7 @@
786
786
  "type": "cli-command",
787
787
  "domain": "setup",
788
788
  "sourcePath": "src/cli.ts",
789
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
789
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
790
790
  "since": "2025-01-01"
791
791
  },
792
792
  "cli:add": {
@@ -794,7 +794,7 @@
794
794
  "type": "cli-command",
795
795
  "domain": "setup",
796
796
  "sourcePath": "src/cli.ts",
797
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
797
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
798
798
  "since": "2025-01-01"
799
799
  },
800
800
  "cli:backup": {
@@ -802,7 +802,7 @@
802
802
  "type": "cli-command",
803
803
  "domain": "operations",
804
804
  "sourcePath": "src/cli.ts",
805
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
805
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
806
806
  "since": "2025-01-01"
807
807
  },
808
808
  "cli:git": {
@@ -810,7 +810,7 @@
810
810
  "type": "cli-command",
811
811
  "domain": "coordination",
812
812
  "sourcePath": "src/cli.ts",
813
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
813
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
814
814
  "since": "2025-01-01"
815
815
  },
816
816
  "cli:memory": {
@@ -818,7 +818,7 @@
818
818
  "type": "cli-command",
819
819
  "domain": "memory",
820
820
  "sourcePath": "src/cli.ts",
821
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
821
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
822
822
  "since": "2025-01-01"
823
823
  },
824
824
  "cli:knowledge": {
@@ -826,7 +826,7 @@
826
826
  "type": "cli-command",
827
827
  "domain": "memory",
828
828
  "sourcePath": "src/cli.ts",
829
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
829
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
830
830
  "since": "2025-01-01"
831
831
  },
832
832
  "cli:semantic": {
@@ -834,7 +834,7 @@
834
834
  "type": "cli-command",
835
835
  "domain": "memory",
836
836
  "sourcePath": "src/cli.ts",
837
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
837
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
838
838
  "since": "2025-01-01"
839
839
  },
840
840
  "cli:intent": {
@@ -842,7 +842,7 @@
842
842
  "type": "cli-command",
843
843
  "domain": "intent",
844
844
  "sourcePath": "src/cli.ts",
845
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
845
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
846
846
  "since": "2025-01-01"
847
847
  },
848
848
  "cli:feedback": {
@@ -850,7 +850,7 @@
850
850
  "type": "cli-command",
851
851
  "domain": "feedback",
852
852
  "sourcePath": "src/cli.ts",
853
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
853
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
854
854
  "since": "2025-01-01"
855
855
  },
856
856
  "cli:server": {
@@ -858,7 +858,7 @@
858
858
  "type": "cli-command",
859
859
  "domain": "server",
860
860
  "sourcePath": "src/cli.ts",
861
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
861
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
862
862
  "since": "2025-01-01"
863
863
  },
864
864
  "cli:status": {
@@ -866,7 +866,7 @@
866
866
  "type": "cli-command",
867
867
  "domain": "monitoring",
868
868
  "sourcePath": "src/cli.ts",
869
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
869
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
870
870
  "since": "2025-01-01"
871
871
  },
872
872
  "cli:user": {
@@ -874,7 +874,7 @@
874
874
  "type": "cli-command",
875
875
  "domain": "users",
876
876
  "sourcePath": "src/cli.ts",
877
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
877
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
878
878
  "since": "2025-01-01"
879
879
  },
880
880
  "cli:relationship": {
@@ -882,7 +882,7 @@
882
882
  "type": "cli-command",
883
883
  "domain": "relationships",
884
884
  "sourcePath": "src/cli.ts",
885
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
885
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
886
886
  "since": "2025-01-01"
887
887
  },
888
888
  "cli:job": {
@@ -890,7 +890,7 @@
890
890
  "type": "cli-command",
891
891
  "domain": "scheduling",
892
892
  "sourcePath": "src/cli.ts",
893
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
893
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
894
894
  "since": "2025-01-01"
895
895
  },
896
896
  "cli:lifeline": {
@@ -898,7 +898,7 @@
898
898
  "type": "cli-command",
899
899
  "domain": "communication",
900
900
  "sourcePath": "src/cli.ts",
901
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
901
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
902
902
  "since": "2025-01-01"
903
903
  },
904
904
  "cli:list": {
@@ -906,7 +906,7 @@
906
906
  "type": "cli-command",
907
907
  "domain": "monitoring",
908
908
  "sourcePath": "src/cli.ts",
909
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
909
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
910
910
  "since": "2025-01-01"
911
911
  },
912
912
  "cli:autostart": {
@@ -914,7 +914,7 @@
914
914
  "type": "cli-command",
915
915
  "domain": "operations",
916
916
  "sourcePath": "src/cli.ts",
917
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
917
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
918
918
  "since": "2025-01-01"
919
919
  },
920
920
  "cli:migrate": {
@@ -922,7 +922,7 @@
922
922
  "type": "cli-command",
923
923
  "domain": "updates",
924
924
  "sourcePath": "src/cli.ts",
925
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
925
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
926
926
  "since": "2025-01-01"
927
927
  },
928
928
  "cli:machines": {
@@ -930,7 +930,7 @@
930
930
  "type": "cli-command",
931
931
  "domain": "coordination",
932
932
  "sourcePath": "src/cli.ts",
933
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
933
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
934
934
  "since": "2025-01-01"
935
935
  },
936
936
  "cli:whoami": {
@@ -938,7 +938,7 @@
938
938
  "type": "cli-command",
939
939
  "domain": "identity",
940
940
  "sourcePath": "src/cli.ts",
941
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
941
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
942
942
  "since": "2025-01-01"
943
943
  },
944
944
  "cli:pair": {
@@ -946,7 +946,7 @@
946
946
  "type": "cli-command",
947
947
  "domain": "coordination",
948
948
  "sourcePath": "src/cli.ts",
949
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
949
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
950
950
  "since": "2025-01-01"
951
951
  },
952
952
  "cli:join": {
@@ -954,7 +954,7 @@
954
954
  "type": "cli-command",
955
955
  "domain": "coordination",
956
956
  "sourcePath": "src/cli.ts",
957
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
957
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
958
958
  "since": "2025-01-01"
959
959
  },
960
960
  "cli:wakeup": {
@@ -962,7 +962,7 @@
962
962
  "type": "cli-command",
963
963
  "domain": "coordination",
964
964
  "sourcePath": "src/cli.ts",
965
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
965
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
966
966
  "since": "2025-01-01"
967
967
  },
968
968
  "cli:leave": {
@@ -970,7 +970,7 @@
970
970
  "type": "cli-command",
971
971
  "domain": "coordination",
972
972
  "sourcePath": "src/cli.ts",
973
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
973
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
974
974
  "since": "2025-01-01"
975
975
  },
976
976
  "cli:doctor": {
@@ -978,7 +978,7 @@
978
978
  "type": "cli-command",
979
979
  "domain": "monitoring",
980
980
  "sourcePath": "src/cli.ts",
981
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
981
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
982
982
  "since": "2025-01-01"
983
983
  },
984
984
  "cli:review": {
@@ -986,7 +986,7 @@
986
986
  "type": "cli-command",
987
987
  "domain": "monitoring",
988
988
  "sourcePath": "src/cli.ts",
989
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
989
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
990
990
  "since": "2025-01-01"
991
991
  },
992
992
  "cli:nuke": {
@@ -994,7 +994,7 @@
994
994
  "type": "cli-command",
995
995
  "domain": "operations",
996
996
  "sourcePath": "src/cli.ts",
997
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
997
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
998
998
  "since": "2025-01-01"
999
999
  },
1000
1000
  "cli:playbook": {
@@ -1002,7 +1002,7 @@
1002
1002
  "type": "cli-command",
1003
1003
  "domain": "context",
1004
1004
  "sourcePath": "src/cli.ts",
1005
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
1005
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
1006
1006
  "since": "2025-01-01"
1007
1007
  },
1008
1008
  "cli:dev-preflight": {
@@ -1010,7 +1010,7 @@
1010
1010
  "type": "cli-command",
1011
1011
  "domain": "development",
1012
1012
  "sourcePath": "src/cli.ts",
1013
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
1013
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
1014
1014
  "since": "2025-01-01"
1015
1015
  },
1016
1016
  "cli:dev-ci-failures": {
@@ -1018,7 +1018,7 @@
1018
1018
  "type": "cli-command",
1019
1019
  "domain": "development",
1020
1020
  "sourcePath": "src/cli.ts",
1021
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
1021
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
1022
1022
  "since": "2025-01-01"
1023
1023
  },
1024
1024
  "cli:dev-profile-node": {
@@ -1026,7 +1026,7 @@
1026
1026
  "type": "cli-command",
1027
1027
  "domain": "development",
1028
1028
  "sourcePath": "src/cli.ts",
1029
- "contentHash": "e513a3a7f1cae3970a8a34bf51ae622ba47fa8026f85e6d2f3fed4581e9ec8e7",
1029
+ "contentHash": "bfa434d670d4a07e78522422cffe333026479f9c3c4a8afea35d1a1203e4fe29",
1030
1030
  "since": "2025-01-01"
1031
1031
  },
1032
1032
  "template:build-stop-hook.sh": {
@@ -1570,7 +1570,7 @@
1570
1570
  "type": "subsystem",
1571
1571
  "domain": "communication",
1572
1572
  "sourcePath": "src/lifeline/TelegramLifeline.ts",
1573
- "contentHash": "3446974605736d653bf08f9c315c95b5cc42c0998867e4e1b60cb86144a3b975",
1573
+ "contentHash": "524266bb64da7168ab8577b173a0126bf018bc5ffc8b7923dd2ea6b0f5df6b3e",
1574
1574
  "since": "2025-01-01"
1575
1575
  },
1576
1576
  "subsystem:orphan-process-reaper": {
@@ -0,0 +1,58 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ The Instar CLI now rejects unknown top-level commands before the bare setup flow can run. A typo such as `instar dev:claim-checkk` prints a clear unknown-command error and exits with status 1 instead of falling into the interactive setup wizard.
9
+
10
+ Bare `instar` remains unchanged: it still opens the setup flow for new or interrupted setup sessions. `instar help` now prints CLI help instead of entering setup.
11
+
12
+ The ServerSupervisor's slow-retry mode (respawn a dead server every 2h, forever)
13
+ is a sanctioned Eternal Sentinel under the new "No Unbounded Loops" standard —
14
+ but it violated condition 4: it never told anyone. A multi-day crash-revive loop
15
+ was indistinguishable from silence. Now a pure one-shot latch
16
+ (`SlowRetrySentinelEscalation`, the AgeKillBackoff suppressor shape) fires
17
+ exactly once per outage episode after a sustained-failure threshold (default
18
+ 12h ≈ 6 failed cycles): the supervisor emits `sentinelStalled` and the lifeline
19
+ sends ONE operator message with the two useful levers (`/lifeline doctor`,
20
+ `/lifeline reset`), then the sentinel keeps quietly retrying. The message goes
21
+ directly to the Telegram Bot API from the lifeline process — no dependency on
22
+ the (down) agent server. Recovery re-arms the latch via the single
23
+ `resetCircuitBreaker()` funnel; retry/kill/spawn decisions are unchanged.
24
+
25
+ ## What to Tell Your User
26
+
27
+ - **Clearer command typos**: "When I mistype an Instar command, I now fail fast with a clear message instead of opening setup and looking stuck."
28
+
29
+ If your agent's server ever gets stuck in a crash loop, you'll now get one
30
+ clear heads-up after ~12 hours — "still down, here's how to diagnose or force a
31
+ retry, I'll keep trying" — instead of discovering the outage by noticing your
32
+ agent went quiet for days. One message per outage, never a stream.
33
+
34
+ ## Summary of New Capabilities
35
+
36
+ | Capability | How to Use |
37
+ |-----------|-----------|
38
+ | Unknown command rejection | Automatic for mistyped top-level Instar commands |
39
+ | Bare setup preservation | Automatic when running Instar without a command |
40
+ | Help command preservation | Automatic when asking Instar for help |
41
+
42
+ - Slow-retry escalation: a sustained server outage (default 12h in slow-retry)
43
+ produces exactly one operator notification per episode; the never-give-up
44
+ revival behavior is unchanged. In-code default; no config required.
45
+
46
+ ## Evidence
47
+
48
+ Reproduced the typo path locally with the built CLI. Before this change, a typoed command could enter the interactive setup path and hang an agent shell. After the change, `node dist/cli.js dev:claim-checkk` exits 1 with `error: unknown command 'dev:claim-checkk'` and the help hint. A separate `node dist/cli.js help` probe exits 0 and prints CLI help. A separate bare invocation probe, `timeout 3 node dist/cli.js`, still enters setup and times out at status 124, confirming the default setup behavior remains intact.
49
+
50
+ Loop-safety audit finding (CMT-1109), verified at source: the slow-retry block
51
+ in `src/lifeline/ServerSupervisor.ts` was annotated "never truly give up" with
52
+ no operator signal. Fix is the first PR under constitution P19 ("No Unbounded
53
+ Loops", incl. Justin's Eternal Sentinel caveat — this loop is its namesake
54
+ case). Tests: 10 green in `tests/unit/SlowRetrySentinelEscalation.test.ts`
55
+ including the P19 sustained-failure bound (week-long never-recovering episode →
56
+ exactly 1 escalation) and source-shape wiring pins. Independent adversarial
57
+ second-pass: CONCUR (all probes safe — per-tick reachability, no double-fire,
58
+ server-independent delivery, emit-before-spawn ordering). tsc clean.
@@ -0,0 +1,31 @@
1
+ # Side-Effects Review - CLI unknown-command trap
2
+
3
+ **Version / slug:** `cli-unknown-command-trap`
4
+ **Date:** `2026-06-06`
5
+ **Author:** `instar-codey`
6
+
7
+ ## Summary
8
+
9
+ This change adds a top-level command guard before Commander parses the CLI. Unknown first-position command tokens now print a clear error and exit 1. The existing no-argument setup path is preserved, and Commander’s implicit `help` command remains allowed.
10
+
11
+ ## Decision Points
12
+
13
+ - Add `rejectUnknownTopLevelCommand` in `src/cli.ts`.
14
+ - Call it after all commands are registered and before `program.parse()`.
15
+ - Add e2e regression tests for `dist/cli.js dev:claim-checkk` and `dist/cli.js help`.
16
+
17
+ ## Over-Block
18
+
19
+ Risk: rejecting a legitimate command before Commander sees it. Mitigation: the guard builds its allowlist from `program.commands` and command aliases after registration, and explicitly handles Commander’s implicit `help` command because Commander does not list it in `program.commands` and otherwise sends it into the default setup action. Options and the no-argument path bypass the guard.
20
+
21
+ ## Under-Block
22
+
23
+ Nested unknown subcommands remain Commander-owned. This fix targets the incident class: unknown top-level command tokens falling into the default setup action.
24
+
25
+ ## Interactions
26
+
27
+ No server routes, persistent state, messaging, or external APIs change. The behavior changes are limited to process exit behavior for unknown top-level CLI commands and restoring the intended `instar help` help output.
28
+
29
+ ## Rollback
30
+
31
+ Rollback is a normal revert of the helper, call site, test, and notes. No data migration is involved.
@@ -0,0 +1,61 @@
1
+ # Side-Effects Review — Slow-Retry Sentinel Escalation
2
+
3
+ **Version / slug:** `supervisor-sentinel-escalation`
4
+ **Date:** `2026-06-05`
5
+ **Author:** `Echo (instar-dev agent)`
6
+ **Second-pass reviewer:** `independent adversarial reviewer subagent — CONCUR (all four probes safe; no blocking defects; non-blocking notes recorded below)`
7
+
8
+ ## Summary of the change
9
+
10
+ The ServerSupervisor's slow-retry mode (2h respawn cadence, deliberately forever) gains the Eternal Sentinel's condition-4 observability: a pure one-shot latch (`src/lifeline/SlowRetrySentinelEscalation.ts`) fires once per outage episode after `escalateAfterMs` (default 12h), the supervisor emits `'sentinelStalled'`, and `TelegramLifeline.notifySentinelStalled` delivers ONE operator message (doctor/reset levers), after which the sentinel keeps retrying unchanged. `resetCircuitBreaker()` — the single episode-ending funnel — re-arms the latch in lockstep with zeroing `slowRetryStartedAt`. Files: `SlowRetrySentinelEscalation.ts` (new, pure), `ServerSupervisor.ts` (declaration comment + per-tick check + emit + reset hook + one constructor option), `TelegramLifeline.ts` (listener + notify method), one test file.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - `ServerSupervisor` slow-retry block — **modify (additive)** — gains a read-only latch check + event emit; the retry decision, cadence, kill, and spawn are untouched.
15
+ - `SlowRetrySentinelEscalation` — **add** — a pure signal producer with no authority of any kind.
16
+ - `TelegramLifeline` event wiring — **add** — delivery only; mirrors the existing `circuitBroken` handler shape (fire-and-forget, catch-swallowed).
17
+
18
+ ## 1. Over-block
19
+
20
+ Nothing is blocked — this change cannot suppress, delay, or alter any retry or recovery action. The only "cost" added is one Telegram message per ≥12h outage episode.
21
+
22
+ ## 2. Under-block
23
+
24
+ (a) A lifeline PROCESS restart zeroes the in-memory latch with all breaker state; after ~13.5h of freshly rebuilt sustained failure it would notify again. Reviewer-assessed as correct-by-design ("still broken after a bounce" is a legitimate re-notification), and persisting the latch was explicitly rejected — a stale on-disk latch could suppress a legitimate notification, the worse failure. (b) The threshold is time-based, not attempt-based: a machine asleep for 12h would escalate on wake even though few attempts ran — acceptable; the operator-facing claim ("down ~N hours") remains true. (c) Other eternal-sentinel-shaped loops (lease pull) are NOT covered here — next audit PR <!-- tracked: CMT-1109 -->.
25
+
26
+ ## 3. Level-of-abstraction fit
27
+
28
+ Yes. The latch lives beside the loop it observes (lifeline package), as a pure helper in the established suppressor shape (`AgeKillBackoff`: injectable clock, bounded state, unit-testable). Delivery rides the existing supervisor→lifeline event channel (`circuitBroken` precedent) rather than inventing a new notification path — and deliberately does NOT use the agent server's attention queue, which is definitionally down when this fires.
29
+
30
+ ## 4. Signal vs authority compliance
31
+
32
+ **Required reference:** `docs/signal-vs-authority.md`
33
+
34
+ - [x] No — pure signal. The latch can only cause one message; it holds no authority over retries, kills, spawns, or the circuit breaker. The healer's behavior is byte-identical with the latch removed.
35
+
36
+ ## 5. Interactions
37
+
38
+ - **Double-fire:** impossible within a process — the episode key (`slowRetryStartedAt`) is written only at episode start (when 0) and zeroed only inside `resetCircuitBreaker()`, which re-arms the latch in the same method; key and latch cannot desync (reviewer traced every write).
39
+ - **Starvation:** the slow-retry block runs every 10s health-check tick while broken (the branch returns without resetting `consecutiveFailures`), so the latch check cannot be starved (reviewer traced `evaluateUnhealthyServer` → `handleUnhealthy` reachability).
40
+ - **Ordering:** the emit's listener is fire-and-forget and catch-swallowed; it cannot block or throw into the same tick's kill/spawn (mirrors `circuitBroken`).
41
+ - **Feedback loops:** none — a message cannot change health-check outcomes.
42
+
43
+ ## 6. External surfaces
44
+
45
+ - **User-visible:** one new Telegram message class, bounded at one per episode (Bounded Notification Surface-compatible: no topic creation — it posts to the existing lifeline topic).
46
+ - **Delivery independence:** `sendToTopic` → Telegram Bot API directly over HTTPS from the lifeline process; zero dependency on the down agent server (reviewer-verified at `apiCall`).
47
+ - **Persistent state / config / schema:** none. In-code default; `slowRetryEscalateAfterMs` is a constructor option for tests only. No migration (Migration Parity: nothing installed changes).
48
+
49
+ ## 7. Rollback cost
50
+
51
+ Revert the commit. No state to clean, no config to unwind. The only observable regression of rollback is the silence returning.
52
+
53
+ ## Conclusion
54
+
55
+ Signal-only observability for the constitution's namesake Eternal Sentinel: persistence preserved, silence eliminated, volume bounded at one message per episode and proven by the P19 sustained-failure test (week-long never-recovering episode → exactly 1). Second-pass reviewer CONCUR with zero blocking findings; both non-blocking notes (restart re-fire window, no Tier-2/3 for a route-less signal change) are recorded in §2/§6 with their rationale.
56
+
57
+ ---
58
+
59
+ ## Phase 5 — Second-pass review (server-lifecycle-adjacent → performed)
60
+
61
+ An independent adversarial reviewer audited the diff and final files at line level against four probes: (1) any >1-fire-per-outage path — traced every `slowRetryStartedAt`/`circuitBroken` write; none desync the episode key from the latch; lifeline-restart re-fire requires ~13.5h of rebuilt failure and is a correct re-notification; (2) any never-fire path — the slow-retry branch is reached every 10s tick while broken (per-tick reachability traced through `evaluateUnhealthyServer`/`handleUnhealthy`); (3) delivery dependence on the down server — none: the lifeline posts straight to the Telegram Bot API; (4) emit-vs-spawn ordering — fire-and-forget listener, cannot block or throw into the spawn. Ran the 10-test suite (green) and `tsc --noEmit` (clean). **Verdict: CONCUR.**