instar 1.0.13 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +52 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/init.d.ts +17 -0
  5. package/dist/commands/init.d.ts.map +1 -1
  6. package/dist/commands/init.js +156 -64
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/server.d.ts.map +1 -1
  9. package/dist/commands/server.js +68 -4
  10. package/dist/commands/server.js.map +1 -1
  11. package/dist/commands/setup.d.ts +3 -1
  12. package/dist/commands/setup.d.ts.map +1 -1
  13. package/dist/commands/setup.js +67 -28
  14. package/dist/commands/setup.js.map +1 -1
  15. package/dist/commands/worktree.d.ts +17 -4
  16. package/dist/commands/worktree.d.ts.map +1 -1
  17. package/dist/commands/worktree.js +28 -4
  18. package/dist/commands/worktree.js.map +1 -1
  19. package/dist/core/AgentWorktreeDetector.d.ts +63 -0
  20. package/dist/core/AgentWorktreeDetector.d.ts.map +1 -0
  21. package/dist/core/AgentWorktreeDetector.js +329 -0
  22. package/dist/core/AgentWorktreeDetector.js.map +1 -0
  23. package/dist/core/InstarWorktreeManager.d.ts +99 -0
  24. package/dist/core/InstarWorktreeManager.d.ts.map +1 -0
  25. package/dist/core/InstarWorktreeManager.js +447 -0
  26. package/dist/core/InstarWorktreeManager.js.map +1 -0
  27. package/dist/core/MachineIdentity.d.ts.map +1 -1
  28. package/dist/core/MachineIdentity.js +2 -0
  29. package/dist/core/MachineIdentity.js.map +1 -1
  30. package/dist/core/PostUpdateMigrator.d.ts +25 -0
  31. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  32. package/dist/core/PostUpdateMigrator.js +258 -0
  33. package/dist/core/PostUpdateMigrator.js.map +1 -1
  34. package/dist/monitoring/PromptGate.d.ts +12 -0
  35. package/dist/monitoring/PromptGate.d.ts.map +1 -1
  36. package/dist/monitoring/PromptGate.js +44 -0
  37. package/dist/monitoring/PromptGate.js.map +1 -1
  38. package/dist/scaffold/templates.d.ts.map +1 -1
  39. package/dist/scaffold/templates.js +17 -0
  40. package/dist/scaffold/templates.js.map +1 -1
  41. package/package.json +1 -1
  42. package/scripts/lint-no-direct-destructive.js +7 -0
  43. package/scripts/resolve-release-tier.mjs +192 -0
  44. package/src/data/builtin-manifest.json +56 -48
  45. package/src/scaffold/templates.ts +17 -0
  46. package/src/templates/scripts/instar-watchdog.sh +169 -6
  47. package/src/templates/scripts/instar-worktree-create.sh +79 -0
  48. package/upgrades/1.1.0.md +320 -0
  49. package/upgrades/side-effects/agent-worktree-convention-layer-1-2-5.md +280 -0
  50. package/upgrades/side-effects/agent-worktree-convention-layer-3-4.md +285 -0
  51. package/upgrades/side-effects/feat-fix-parent-framework-intercept.md +59 -0
  52. package/upgrades/side-effects/feat-install-claude-gating.md +67 -0
  53. package/upgrades/side-effects/feat-install-framework-flag.md +65 -0
  54. package/upgrades/side-effects/feat-portability-shadow-capabilities.md +63 -0
  55. package/upgrades/side-effects/feat-setup-framework-flag.md +65 -0
  56. package/upgrades/side-effects/lockdown-layer-2.md +123 -0
  57. package/upgrades/side-effects/watchdog-bind-failure-probe.md +174 -0
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-05-19T21:07:55.340Z",
5
- "instarVersion": "1.0.13",
6
- "entryCount": 189,
4
+ "generatedAt": "2026-05-20T16:51:39.613Z",
5
+ "instarVersion": "1.1.0",
6
+ "entryCount": 190,
7
7
  "entries": {
8
8
  "hook:session-start": {
9
9
  "id": "hook:session-start",
@@ -11,7 +11,7 @@
11
11
  "domain": "identity",
12
12
  "sourcePath": "src/core/PostUpdateMigrator.ts",
13
13
  "installedPath": ".instar/hooks/instar/session-start.sh",
14
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
14
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
15
15
  "since": "2025-01-01"
16
16
  },
17
17
  "hook:dangerous-command-guard": {
@@ -20,7 +20,7 @@
20
20
  "domain": "safety",
21
21
  "sourcePath": "src/core/PostUpdateMigrator.ts",
22
22
  "installedPath": ".instar/hooks/instar/dangerous-command-guard.sh",
23
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
23
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
24
24
  "since": "2025-01-01"
25
25
  },
26
26
  "hook:grounding-before-messaging": {
@@ -29,7 +29,7 @@
29
29
  "domain": "safety",
30
30
  "sourcePath": "src/core/PostUpdateMigrator.ts",
31
31
  "installedPath": ".instar/hooks/instar/grounding-before-messaging.sh",
32
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
32
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
33
33
  "since": "2025-01-01"
34
34
  },
35
35
  "hook:compaction-recovery": {
@@ -38,7 +38,7 @@
38
38
  "domain": "identity",
39
39
  "sourcePath": "src/core/PostUpdateMigrator.ts",
40
40
  "installedPath": ".instar/hooks/instar/compaction-recovery.sh",
41
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
41
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
42
42
  "since": "2025-01-01"
43
43
  },
44
44
  "hook:external-operation-gate": {
@@ -47,7 +47,7 @@
47
47
  "domain": "safety",
48
48
  "sourcePath": "src/core/PostUpdateMigrator.ts",
49
49
  "installedPath": ".instar/hooks/instar/external-operation-gate.js",
50
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
50
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
51
51
  "since": "2025-01-01"
52
52
  },
53
53
  "hook:deferral-detector": {
@@ -56,7 +56,7 @@
56
56
  "domain": "safety",
57
57
  "sourcePath": "src/core/PostUpdateMigrator.ts",
58
58
  "installedPath": ".instar/hooks/instar/deferral-detector.js",
59
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
59
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
60
60
  "since": "2025-01-01"
61
61
  },
62
62
  "hook:post-action-reflection": {
@@ -65,7 +65,7 @@
65
65
  "domain": "evolution",
66
66
  "sourcePath": "src/core/PostUpdateMigrator.ts",
67
67
  "installedPath": ".instar/hooks/instar/post-action-reflection.js",
68
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
68
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
69
69
  "since": "2025-01-01"
70
70
  },
71
71
  "hook:external-communication-guard": {
@@ -74,7 +74,7 @@
74
74
  "domain": "safety",
75
75
  "sourcePath": "src/core/PostUpdateMigrator.ts",
76
76
  "installedPath": ".instar/hooks/instar/external-communication-guard.js",
77
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
77
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
78
78
  "since": "2025-01-01"
79
79
  },
80
80
  "hook:scope-coherence-collector": {
@@ -83,7 +83,7 @@
83
83
  "domain": "coherence",
84
84
  "sourcePath": "src/core/PostUpdateMigrator.ts",
85
85
  "installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
86
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
86
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
87
87
  "since": "2025-01-01"
88
88
  },
89
89
  "hook:scope-coherence-checkpoint": {
@@ -92,7 +92,7 @@
92
92
  "domain": "coherence",
93
93
  "sourcePath": "src/core/PostUpdateMigrator.ts",
94
94
  "installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
95
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
95
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
96
96
  "since": "2025-01-01"
97
97
  },
98
98
  "hook:free-text-guard": {
@@ -101,7 +101,7 @@
101
101
  "domain": "safety",
102
102
  "sourcePath": "src/core/PostUpdateMigrator.ts",
103
103
  "installedPath": ".instar/hooks/instar/free-text-guard.sh",
104
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
104
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
105
105
  "since": "2025-01-01"
106
106
  },
107
107
  "hook:claim-intercept": {
@@ -110,7 +110,7 @@
110
110
  "domain": "coherence",
111
111
  "sourcePath": "src/core/PostUpdateMigrator.ts",
112
112
  "installedPath": ".instar/hooks/instar/claim-intercept.js",
113
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
113
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
114
114
  "since": "2025-01-01"
115
115
  },
116
116
  "hook:claim-intercept-response": {
@@ -119,7 +119,7 @@
119
119
  "domain": "coherence",
120
120
  "sourcePath": "src/core/PostUpdateMigrator.ts",
121
121
  "installedPath": ".instar/hooks/instar/claim-intercept-response.js",
122
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
122
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
123
123
  "since": "2025-01-01"
124
124
  },
125
125
  "hook:auto-approve-permissions": {
@@ -128,7 +128,7 @@
128
128
  "domain": "safety",
129
129
  "sourcePath": "src/core/PostUpdateMigrator.ts",
130
130
  "installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
131
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
131
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
132
132
  "since": "2025-01-01"
133
133
  },
134
134
  "job:health-check": {
@@ -752,7 +752,7 @@
752
752
  "type": "cli-command",
753
753
  "domain": "setup",
754
754
  "sourcePath": "src/cli.ts",
755
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
755
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
756
756
  "since": "2025-01-01"
757
757
  },
758
758
  "cli:setup": {
@@ -760,7 +760,7 @@
760
760
  "type": "cli-command",
761
761
  "domain": "setup",
762
762
  "sourcePath": "src/cli.ts",
763
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
763
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
764
764
  "since": "2025-01-01"
765
765
  },
766
766
  "cli:add": {
@@ -768,7 +768,7 @@
768
768
  "type": "cli-command",
769
769
  "domain": "setup",
770
770
  "sourcePath": "src/cli.ts",
771
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
771
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
772
772
  "since": "2025-01-01"
773
773
  },
774
774
  "cli:backup": {
@@ -776,7 +776,7 @@
776
776
  "type": "cli-command",
777
777
  "domain": "operations",
778
778
  "sourcePath": "src/cli.ts",
779
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
779
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
780
780
  "since": "2025-01-01"
781
781
  },
782
782
  "cli:git": {
@@ -784,7 +784,7 @@
784
784
  "type": "cli-command",
785
785
  "domain": "coordination",
786
786
  "sourcePath": "src/cli.ts",
787
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
787
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
788
788
  "since": "2025-01-01"
789
789
  },
790
790
  "cli:memory": {
@@ -792,7 +792,7 @@
792
792
  "type": "cli-command",
793
793
  "domain": "memory",
794
794
  "sourcePath": "src/cli.ts",
795
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
795
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
796
796
  "since": "2025-01-01"
797
797
  },
798
798
  "cli:knowledge": {
@@ -800,7 +800,7 @@
800
800
  "type": "cli-command",
801
801
  "domain": "memory",
802
802
  "sourcePath": "src/cli.ts",
803
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
803
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
804
804
  "since": "2025-01-01"
805
805
  },
806
806
  "cli:semantic": {
@@ -808,7 +808,7 @@
808
808
  "type": "cli-command",
809
809
  "domain": "memory",
810
810
  "sourcePath": "src/cli.ts",
811
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
811
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
812
812
  "since": "2025-01-01"
813
813
  },
814
814
  "cli:intent": {
@@ -816,7 +816,7 @@
816
816
  "type": "cli-command",
817
817
  "domain": "intent",
818
818
  "sourcePath": "src/cli.ts",
819
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
819
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
820
820
  "since": "2025-01-01"
821
821
  },
822
822
  "cli:feedback": {
@@ -824,7 +824,7 @@
824
824
  "type": "cli-command",
825
825
  "domain": "feedback",
826
826
  "sourcePath": "src/cli.ts",
827
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
827
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
828
828
  "since": "2025-01-01"
829
829
  },
830
830
  "cli:server": {
@@ -832,7 +832,7 @@
832
832
  "type": "cli-command",
833
833
  "domain": "server",
834
834
  "sourcePath": "src/cli.ts",
835
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
835
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
836
836
  "since": "2025-01-01"
837
837
  },
838
838
  "cli:status": {
@@ -840,7 +840,7 @@
840
840
  "type": "cli-command",
841
841
  "domain": "monitoring",
842
842
  "sourcePath": "src/cli.ts",
843
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
843
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
844
844
  "since": "2025-01-01"
845
845
  },
846
846
  "cli:user": {
@@ -848,7 +848,7 @@
848
848
  "type": "cli-command",
849
849
  "domain": "users",
850
850
  "sourcePath": "src/cli.ts",
851
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
851
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
852
852
  "since": "2025-01-01"
853
853
  },
854
854
  "cli:relationship": {
@@ -856,7 +856,7 @@
856
856
  "type": "cli-command",
857
857
  "domain": "relationships",
858
858
  "sourcePath": "src/cli.ts",
859
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
859
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
860
860
  "since": "2025-01-01"
861
861
  },
862
862
  "cli:job": {
@@ -864,7 +864,7 @@
864
864
  "type": "cli-command",
865
865
  "domain": "scheduling",
866
866
  "sourcePath": "src/cli.ts",
867
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
867
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
868
868
  "since": "2025-01-01"
869
869
  },
870
870
  "cli:lifeline": {
@@ -872,7 +872,7 @@
872
872
  "type": "cli-command",
873
873
  "domain": "communication",
874
874
  "sourcePath": "src/cli.ts",
875
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
875
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
876
876
  "since": "2025-01-01"
877
877
  },
878
878
  "cli:list": {
@@ -880,7 +880,7 @@
880
880
  "type": "cli-command",
881
881
  "domain": "monitoring",
882
882
  "sourcePath": "src/cli.ts",
883
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
883
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
884
884
  "since": "2025-01-01"
885
885
  },
886
886
  "cli:autostart": {
@@ -888,7 +888,7 @@
888
888
  "type": "cli-command",
889
889
  "domain": "operations",
890
890
  "sourcePath": "src/cli.ts",
891
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
891
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
892
892
  "since": "2025-01-01"
893
893
  },
894
894
  "cli:migrate": {
@@ -896,7 +896,7 @@
896
896
  "type": "cli-command",
897
897
  "domain": "updates",
898
898
  "sourcePath": "src/cli.ts",
899
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
899
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
900
900
  "since": "2025-01-01"
901
901
  },
902
902
  "cli:machines": {
@@ -904,7 +904,7 @@
904
904
  "type": "cli-command",
905
905
  "domain": "coordination",
906
906
  "sourcePath": "src/cli.ts",
907
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
907
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
908
908
  "since": "2025-01-01"
909
909
  },
910
910
  "cli:whoami": {
@@ -912,7 +912,7 @@
912
912
  "type": "cli-command",
913
913
  "domain": "identity",
914
914
  "sourcePath": "src/cli.ts",
915
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
915
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
916
916
  "since": "2025-01-01"
917
917
  },
918
918
  "cli:pair": {
@@ -920,7 +920,7 @@
920
920
  "type": "cli-command",
921
921
  "domain": "coordination",
922
922
  "sourcePath": "src/cli.ts",
923
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
923
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
924
924
  "since": "2025-01-01"
925
925
  },
926
926
  "cli:join": {
@@ -928,7 +928,7 @@
928
928
  "type": "cli-command",
929
929
  "domain": "coordination",
930
930
  "sourcePath": "src/cli.ts",
931
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
931
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
932
932
  "since": "2025-01-01"
933
933
  },
934
934
  "cli:wakeup": {
@@ -936,7 +936,7 @@
936
936
  "type": "cli-command",
937
937
  "domain": "coordination",
938
938
  "sourcePath": "src/cli.ts",
939
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
939
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
940
940
  "since": "2025-01-01"
941
941
  },
942
942
  "cli:leave": {
@@ -944,7 +944,7 @@
944
944
  "type": "cli-command",
945
945
  "domain": "coordination",
946
946
  "sourcePath": "src/cli.ts",
947
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
947
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
948
948
  "since": "2025-01-01"
949
949
  },
950
950
  "cli:doctor": {
@@ -952,7 +952,7 @@
952
952
  "type": "cli-command",
953
953
  "domain": "monitoring",
954
954
  "sourcePath": "src/cli.ts",
955
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
955
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
956
956
  "since": "2025-01-01"
957
957
  },
958
958
  "cli:review": {
@@ -960,7 +960,7 @@
960
960
  "type": "cli-command",
961
961
  "domain": "monitoring",
962
962
  "sourcePath": "src/cli.ts",
963
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
963
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
964
964
  "since": "2025-01-01"
965
965
  },
966
966
  "cli:nuke": {
@@ -968,7 +968,7 @@
968
968
  "type": "cli-command",
969
969
  "domain": "operations",
970
970
  "sourcePath": "src/cli.ts",
971
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
971
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
972
972
  "since": "2025-01-01"
973
973
  },
974
974
  "cli:playbook": {
@@ -976,7 +976,7 @@
976
976
  "type": "cli-command",
977
977
  "domain": "context",
978
978
  "sourcePath": "src/cli.ts",
979
- "contentHash": "300a4557e6ab4e7d0280493a445b10333e4b57f7ef3dea12767703e0fc001f41",
979
+ "contentHash": "a20f6fdbf151bdf22fb8f134fcb8bee872148b34e1f49d1fd962fb47e7200ba1",
980
980
  "since": "2025-01-01"
981
981
  },
982
982
  "template:build-stop-hook.sh": {
@@ -1104,7 +1104,15 @@
1104
1104
  "type": "template",
1105
1105
  "domain": "operations",
1106
1106
  "sourcePath": "src/templates/scripts/instar-watchdog.sh",
1107
- "contentHash": "14ec34c724149dd3df73c6296af39d09a95a74b3d471bea971aa2894c078aed3",
1107
+ "contentHash": "364033171d32f6458b0ebe6c757a55efd578260c3211b2bfe80c5cf56e0ce0ef",
1108
+ "since": "2025-01-01"
1109
+ },
1110
+ "template:instar-worktree-create.sh": {
1111
+ "id": "template:instar-worktree-create.sh",
1112
+ "type": "template",
1113
+ "domain": "operations",
1114
+ "sourcePath": "src/templates/scripts/instar-worktree-create.sh",
1115
+ "contentHash": "2e3f78d72a00a56a9bae9dfe0af0ecc48557e5af2cd59fc6435356784c8e6796",
1108
1116
  "since": "2025-01-01"
1109
1117
  },
1110
1118
  "template:serendipity-capture.sh": {
@@ -1456,7 +1464,7 @@
1456
1464
  "type": "subsystem",
1457
1465
  "domain": "updates",
1458
1466
  "sourcePath": "src/core/PostUpdateMigrator.ts",
1459
- "contentHash": "5ddc7a551c4e996307288ce70f6faf60337f8571a5e8f1825added7993cd48ce",
1467
+ "contentHash": "a5a854fd1aa35f15f48183ddf263d8a0cb2dc7f67e3c513a92b4acdc0c6d28f1",
1460
1468
  "since": "2025-01-01"
1461
1469
  },
1462
1470
  "subsystem:scheduler": {
@@ -235,6 +235,15 @@ export function generateMemoryMd(agentName: string): string {
235
235
 
236
236
  _Patterns and conventions discovered while working on this project._
237
237
 
238
+ - **Worktree convention.** Create worktrees for collaborator repos with
239
+ \`instar worktree create <branch>\` — never \`git worktree add\` directly
240
+ into a shared checkout, and never hardcode another agent's name into the
241
+ path. The CLI resolves your agent's home automatically and refuses
242
+ unsafe placements. Reason: the macOS sandbox can revoke filesystem
243
+ access mid-session to anything outside the agent home, with no
244
+ in-session recovery path. The agent home (\`~/.instar/agents/<agent>/\`)
245
+ is the one location the sandbox cannot revoke.
246
+
238
247
  ## Tools & Scripts
239
248
 
240
249
  _Custom scripts, jobs, and integrations that have been built._
@@ -1145,6 +1154,14 @@ instar playbook doctor # Verify everything is healthy
1145
1154
  ### Self-Evolution
1146
1155
 
1147
1156
  Record what I learn. Build infrastructure, not one-offs. Grow to meet the user's needs. Every session should leave things slightly better than I found them.
1157
+
1158
+ ## Worktree Convention
1159
+
1160
+ Create worktrees for collaborator repos with \`instar worktree create <branch>\` — it resolves your agent's home automatically. Never hardcode another agent's name or place worktrees inside the shared checkout.
1161
+
1162
+ **Why:** the macOS sandbox can revoke filesystem access to anything outside the agent home mid-session, with no in-session recovery path. The agent home (\`~/.instar/agents/<agent>/\`) is the one location the sandbox cannot revoke. \`instar worktree create\` places the worktree at \`~/.instar/agents/<agent>/.worktrees/<slug>/\` and refuses any other destination. Spec: \`docs/specs/AGENT-WORKTREE-CONVENTION-SPEC.md\`.
1163
+
1164
+ **Caveat — git identity env vars:** the CLI sets per-worktree \`user.name\` / \`user.email\` to \`Instar Agent (<name>)\` / \`<name>@instar.local\`. \`GIT_AUTHOR_NAME\` / \`GIT_COMMITTER_EMAIL\` in the calling environment override that local config. Agents that care about commit attribution must avoid exporting those vars.
1148
1165
  `;
1149
1166
 
1150
1167
  if (hasTelegram) {
@@ -270,6 +270,7 @@ bump_fail_counter() {
270
270
  reset_fail_counter() {
271
271
  local label="$1"
272
272
  rm -f "$HEAL_STATE_DIR/$label.consecutive-heal-fails" 2>/dev/null || true
273
+ rm -f "$HEAL_STATE_DIR/$label.bind-fail-conflict" 2>/dev/null || true
273
274
  }
274
275
 
275
276
  # Escalate via a healthy peer agent's /attention endpoint.
@@ -289,6 +290,20 @@ escalate_via_peer() {
289
290
  # Strip ai.instar. prefix for the user-facing name
290
291
  local dead_name="${dead_label#ai.instar.}"
291
292
 
293
+ # If the BIND-FAIL path stashed a conflicting-project hint, use it to build
294
+ # a more specific summary. Falls back to the generic "offline" copy.
295
+ local conflict_file="$HEAL_STATE_DIR/$dead_label.bind-fail-conflict"
296
+ local conflict_name=""
297
+ if [ -r "$conflict_file" ]; then
298
+ conflict_name=$(cat "$conflict_file" 2>/dev/null || true)
299
+ fi
300
+ local summary_text
301
+ if [ -n "$conflict_name" ] && [ "$conflict_name" != "$dead_name" ]; then
302
+ summary_text="${dead_name} hasn't been able to start its server because ${conflict_name} is using its port. My repair attempts haven't fixed it."
303
+ else
304
+ summary_text="${dead_name} has been offline for about ${minutes_down} minutes and my repair attempts aren't working."
305
+ fi
306
+
292
307
  # Find a healthy peer
293
308
  local peer_plist peer_label peer_dir peer_port peer_auth health_code
294
309
  for peer_plist in "$LAUNCH_AGENTS_DIR"/ai.instar.*.plist; do
@@ -327,7 +342,7 @@ escalate_via_peer() {
327
342
  {
328
343
  "id": "fleet-watchdog-heal-fail-${dead_label}-${fail_count}",
329
344
  "title": "${dead_name} is offline",
330
- "summary": "${dead_name} has been offline for about ${minutes_down} minutes and my repair attempts aren't working.",
345
+ "summary": "${summary_text}",
331
346
  "description": "Want me to dig in?",
332
347
  "category": "degradation",
333
348
  "priority": "HIGH"
@@ -389,6 +404,140 @@ JSONEOF
389
404
  return 1
390
405
  }
391
406
 
407
+ # Probe whether an agent's lifeline-managed server actually owns its configured
408
+ # port. Used to catch the failure mode where the lifeline (and launchd) report
409
+ # healthy but the server itself is locked out — e.g. by a port collision with
410
+ # another agent.
411
+ #
412
+ # Inputs:
413
+ # $1 = project_dir (e.g. /Users/x/Documents/Projects/ai-guy)
414
+ # $2 = label (e.g. ai.instar.ai-guy)
415
+ #
416
+ # Returns:
417
+ # 0 — server reachable and identifies as the expected project (or no port
418
+ # configured, treat as lifeline-only and skip).
419
+ # 2 — BIND-FAIL: port held by a different project.
420
+ # 3 — BIND-FAIL: port unreachable while lifeline alive.
421
+ #
422
+ # Side-effects: writes a log line on BIND-FAIL. Stdout (single line):
423
+ # "<kind>\t<conflicting-project-or-empty>" on BIND-FAIL.
424
+ # Empty otherwise.
425
+ probe_server_identity() {
426
+ local project_dir="$1"
427
+ local label="$2"
428
+
429
+ [ -z "$project_dir" ] || [ ! -d "$project_dir" ] && return 0
430
+ local config_file="$project_dir/.instar/config.json"
431
+ [ ! -r "$config_file" ] && return 0
432
+
433
+ local node_bin port auth_token
434
+ node_bin=$(resolve_node || true)
435
+ [ -z "$node_bin" ] && return 0
436
+
437
+ # Read port + authToken in one node invocation. The authToken is required
438
+ # because /health gates the `project` field behind authentication — without
439
+ # it the probe can't verify identity and would silently fail-open.
440
+ local meta
441
+ meta=$("$node_bin" -e "const c=JSON.parse(require('fs').readFileSync(process.argv[1],'utf8'));process.stdout.write(String(c.port||'')+'\t'+String(c.authToken||''))" "$config_file" 2>/dev/null || true)
442
+ port="${meta%% *}"
443
+ auth_token="${meta##* }"
444
+ # Lifeline-only agents have no port; treat as healthy from probe POV.
445
+ [ -z "$port" ] && return 0
446
+
447
+ # Probe /health with a short timeout. Short is critical — the watchdog runs
448
+ # every 5 minutes and must not stall on an unresponsive server.
449
+ # Authorization header included so the response carries the `project` field
450
+ # (gated server-side; see routes.ts /health handler).
451
+ local resp http_code body project_field auth_args
452
+ auth_args=()
453
+ if [ -n "$auth_token" ]; then
454
+ auth_args=(-H "Authorization: Bearer $auth_token")
455
+ fi
456
+ resp=$(curl -sS --max-time 5 -w '\n%{http_code}' "${auth_args[@]}" "http://localhost:${port}/health" 2>/dev/null || echo $'\n000')
457
+ http_code=$(echo "$resp" | tail -n1)
458
+ body=$(echo "$resp" | sed '$d')
459
+
460
+ if [ "$http_code" != "200" ]; then
461
+ log "BIND-FAIL: $label — port $port unreachable while lifeline alive (http=$http_code)"
462
+ printf 'unreachable\t\n'
463
+ return 3
464
+ fi
465
+
466
+ # Extract the project field from the JSON response.
467
+ project_field=$("$node_bin" -e "try{const j=JSON.parse(require('fs').readFileSync(0,'utf8'));process.stdout.write(String(j.project||''))}catch(_){}" <<<"$body" 2>/dev/null || true)
468
+
469
+ # Derive expected name: strip ai.instar. prefix from label.
470
+ local expected="${label#ai.instar.}"
471
+
472
+ if [ -z "$project_field" ]; then
473
+ # Server is responding but doesn't expose its project — can't verify.
474
+ # Treat as healthy (don't false-alarm); old instar versions don't return this field.
475
+ return 0
476
+ fi
477
+
478
+ if [ "$project_field" != "$expected" ]; then
479
+ log "BIND-FAIL: $label — port $port owned by $project_field (expected $expected)"
480
+ printf 'wrong-project\t%s\n' "$project_field"
481
+ return 2
482
+ fi
483
+
484
+ return 0
485
+ }
486
+
487
+ # Run the heal + escalate pipeline for a BIND-FAIL detection. Reuses the
488
+ # same machinery as crash-loop detection so we have ONE escalation path.
489
+ #
490
+ # Inputs:
491
+ # $1 = label
492
+ # $2 = project_dir
493
+ # $3 = plist
494
+ # $4 = probe stdout (kind\tconflicting-project)
495
+ handle_bind_fail() {
496
+ local label="$1"
497
+ local project_dir="$2"
498
+ local plist="$3"
499
+ local probe_out="$4"
500
+ local kind conflict
501
+ kind="${probe_out%% *}"
502
+ conflict="${probe_out#* }"
503
+ conflict="${conflict%$'\n'}"
504
+
505
+ if ! should_attempt_heal "$label"; then
506
+ $VERBOSE && log "BIND-FAIL: $label — heal attempted recently, waiting"
507
+ return 0
508
+ fi
509
+
510
+ if try_self_heal "$project_dir" "$label"; then
511
+ log "RECOVERING: $label — self-heal applied for bind-fail, reloading"
512
+ if ! $DRY_RUN; then
513
+ mark_heal_attempt "$label"
514
+ launchctl bootout "gui/$(id -u)" "$plist" 2>/dev/null || launchctl unload "$plist" 2>/dev/null || true
515
+ sleep 1
516
+ launchctl bootstrap "gui/$(id -u)" "$plist" 2>/dev/null || launchctl load "$plist" 2>/dev/null || true
517
+ reset_fail_counter "$label"
518
+ log "RELOADED: $label (after bind-fail self-heal)"
519
+ else
520
+ log "DRY-RUN: Would reload $label after bind-fail self-heal"
521
+ fi
522
+ return 0
523
+ fi
524
+
525
+ # Heal can't fix it. Bump counter; escalate at threshold.
526
+ log "BIND-FAIL: $label — no fixable issues found ($kind${conflict:+, conflict=$conflict})"
527
+ mark_heal_attempt "$label"
528
+ local fail_count
529
+ fail_count=$(bump_fail_counter "$label")
530
+ if [ "$fail_count" -ge "$ESCALATE_AFTER_FAILS" ]; then
531
+ # Stash the bind-fail context so escalate_via_peer can pick it up.
532
+ if [ -n "$conflict" ]; then
533
+ echo "$conflict" > "$HEAL_STATE_DIR/$label.bind-fail-conflict"
534
+ fi
535
+ escalate_via_peer "$label" "$fail_count" || true
536
+ else
537
+ $VERBOSE && log "FAIL-COUNT: $label — ${fail_count}/${ESCALATE_AFTER_FAILS}"
538
+ fi
539
+ }
540
+
392
541
  recovered=0
393
542
  checked=0
394
543
  for plist in "$LAUNCH_AGENTS_DIR"/ai.instar.*.plist; do
@@ -405,10 +554,21 @@ for plist in "$LAUNCH_AGENTS_DIR"/ai.instar.*.plist; do
405
554
  exit_status=$(launchctl list "$label" 2>/dev/null | grep '"LastExitStatus"' | grep -o '[0-9]*' || true)
406
555
 
407
556
  if [ -n "$pid" ] && [ "$pid" != "0" ]; then
408
- # Healthy — clear heal state
409
- rm -f "$HEAL_STATE_DIR/$label.last-heal" 2>/dev/null || true
410
- reset_fail_counter "$label"
411
- $VERBOSE && log "OK: $label (PID $pid)"
557
+ # Lifeline-level healthy. But the lifeline can be alive while the agent's
558
+ # server is locked out of its port (e.g. port collision with a peer).
559
+ # Run the bind-probe to catch that.
560
+ project_dir=$(get_project_dir "$plist")
561
+ probe_out=$(probe_server_identity "$project_dir" "$label")
562
+ probe_rc=$?
563
+ if [ "$probe_rc" -eq 0 ]; then
564
+ # Truly healthy — clear heal state
565
+ rm -f "$HEAL_STATE_DIR/$label.last-heal" 2>/dev/null || true
566
+ rm -f "$HEAL_STATE_DIR/$label.bind-fail-conflict" 2>/dev/null || true
567
+ reset_fail_counter "$label"
568
+ $VERBOSE && log "OK: $label (PID $pid)"
569
+ else
570
+ handle_bind_fail "$label" "$project_dir" "$plist" "$probe_out"
571
+ fi
412
572
  elif [ -n "$exit_status" ] && [ "$exit_status" != "0" ]; then
413
573
  log "CRASH-LOOP: $label (exit $exit_status, no PID)"
414
574
 
@@ -472,4 +632,7 @@ if [ -f "$LOG_FILE" ] && [ "$(wc -l < "$LOG_FILE")" -gt 1000 ]; then
472
632
  fi
473
633
 
474
634
  # Trim heal state files older than 24 hours
475
- find "$HEAL_STATE_DIR" -name "*.last-heal" -mmin +1440 -delete 2>/dev/null || true
635
+ # Trim heal-state files older than 24 hours. Covers all per-label markers:
636
+ # *.last-heal, *.consecutive-heal-fails, *.bind-fail-conflict — so state from
637
+ # uninstalled agents doesn't accumulate indefinitely.
638
+ find "$HEAL_STATE_DIR" \( -name "*.last-heal" -o -name "*.consecutive-heal-fails" -o -name "*.bind-fail-conflict" \) -mmin +1440 -delete 2>/dev/null || true