instar 1.3.102 → 1.3.104
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/dist/commands/gate.d.ts.map +1 -1
- package/dist/commands/gate.js +8 -1
- package/dist/commands/gate.js.map +1 -1
- package/dist/commands/nuke.d.ts.map +1 -1
- package/dist/commands/nuke.js +19 -10
- package/dist/commands/nuke.js.map +1 -1
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +81 -0
- package/dist/commands/server.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +33 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +155 -20
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/TopicPlacementPinStore.d.ts +37 -0
- package/dist/core/TopicPlacementPinStore.d.ts.map +1 -0
- package/dist/core/TopicPlacementPinStore.js +95 -0
- package/dist/core/TopicPlacementPinStore.js.map +1 -0
- package/dist/server/middleware.d.ts.map +1 -1
- package/dist/server/middleware.js +13 -0
- package/dist/server/middleware.js.map +1 -1
- package/dist/threadline/listener-daemon.d.ts.map +1 -1
- package/dist/threadline/listener-daemon.js +18 -8
- package/dist/threadline/listener-daemon.js.map +1 -1
- package/dist/threadline/mcp-stdio-entry.js +8 -3
- package/dist/threadline/mcp-stdio-entry.js.map +1 -1
- package/package.json +1 -1
- package/scripts/threadline-bridge-backfill.mjs +7 -1
- package/src/data/builtin-manifest.json +29 -29
- package/src/templates/hooks/compaction-recovery.sh +24 -9
- package/src/templates/hooks/session-start.sh +9 -2
- package/src/templates/hooks/slack-channel-context.sh +8 -1
- package/src/templates/hooks/telegram-topic-context.sh +14 -2
- package/src/templates/scripts/imessage-reply.sh +7 -3
- package/src/templates/scripts/instar-watchdog.sh +14 -5
- package/src/templates/scripts/secret-drop-retrieve.mjs +12 -4
- package/src/templates/scripts/serendipity-capture.sh +15 -9
- package/src/templates/scripts/slack-reply.sh +8 -1
- package/src/templates/scripts/telegram-reply.sh +11 -5
- package/src/templates/scripts/whatsapp-reply.sh +7 -4
- package/upgrades/1.3.103.md +77 -0
- package/upgrades/1.3.104.md +58 -0
- package/upgrades/NEXT.eli16.md +71 -0
- package/upgrades/side-effects/mesh-rpc-auth-and-transfer-activation.md +72 -0
- package/upgrades/side-effects/secret-externalization-hook-resolver-audit.md +48 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-05-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-05-30T00:17:16.098Z",
|
|
5
|
+
"instarVersion": "1.3.104",
|
|
6
6
|
"entryCount": 193,
|
|
7
7
|
"entries": {
|
|
8
8
|
"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": "
|
|
14
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
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": "
|
|
23
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
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": "
|
|
32
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
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": "
|
|
41
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
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": "
|
|
50
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
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": "
|
|
59
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
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": "
|
|
68
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
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": "
|
|
77
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
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": "
|
|
86
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
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": "
|
|
95
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
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": "
|
|
104
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
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": "
|
|
113
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
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": "
|
|
122
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
123
123
|
"since": "2025-01-01"
|
|
124
124
|
},
|
|
125
125
|
"hook:stop-gate-router": {
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"domain": "safety",
|
|
129
129
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
130
130
|
"installedPath": ".instar/hooks/instar/stop-gate-router.js",
|
|
131
|
-
"contentHash": "
|
|
131
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
132
132
|
"since": "2025-01-01"
|
|
133
133
|
},
|
|
134
134
|
"hook:auto-approve-permissions": {
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"domain": "safety",
|
|
138
138
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
139
139
|
"installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
|
|
140
|
-
"contentHash": "
|
|
140
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
141
141
|
"since": "2025-01-01"
|
|
142
142
|
},
|
|
143
143
|
"job:health-check": {
|
|
@@ -1009,7 +1009,7 @@
|
|
|
1009
1009
|
"type": "template",
|
|
1010
1010
|
"domain": "safety",
|
|
1011
1011
|
"sourcePath": "src/templates/hooks/compaction-recovery.sh",
|
|
1012
|
-
"contentHash": "
|
|
1012
|
+
"contentHash": "f65f4731a5142981cf021e948afa5b064dcc35ceadf6efd5354d749f2d85569f",
|
|
1013
1013
|
"since": "2025-01-01"
|
|
1014
1014
|
},
|
|
1015
1015
|
"template:dangerous-command-guard.sh": {
|
|
@@ -1049,7 +1049,7 @@
|
|
|
1049
1049
|
"type": "template",
|
|
1050
1050
|
"domain": "safety",
|
|
1051
1051
|
"sourcePath": "src/templates/hooks/session-start.sh",
|
|
1052
|
-
"contentHash": "
|
|
1052
|
+
"contentHash": "d8b20ab9e46aecc400171bde09a5a64f5a1eeb53e09017564cebc65e67fca062",
|
|
1053
1053
|
"since": "2025-01-01"
|
|
1054
1054
|
},
|
|
1055
1055
|
"template:settings-template.json": {
|
|
@@ -1073,7 +1073,7 @@
|
|
|
1073
1073
|
"type": "template",
|
|
1074
1074
|
"domain": "safety",
|
|
1075
1075
|
"sourcePath": "src/templates/hooks/slack-channel-context.sh",
|
|
1076
|
-
"contentHash": "
|
|
1076
|
+
"contentHash": "ebb2a74ce3819a148b1cfaace3d3467d317ed8cccd98db5cd7ffe0df3a2e9784",
|
|
1077
1077
|
"since": "2025-01-01"
|
|
1078
1078
|
},
|
|
1079
1079
|
"template:telegram-topic-context.sh": {
|
|
@@ -1081,7 +1081,7 @@
|
|
|
1081
1081
|
"type": "template",
|
|
1082
1082
|
"domain": "safety",
|
|
1083
1083
|
"sourcePath": "src/templates/hooks/telegram-topic-context.sh",
|
|
1084
|
-
"contentHash": "
|
|
1084
|
+
"contentHash": "317b11084547271dab3f333be8bdf5e536a5af7239f50d51030c62990b4b7e59",
|
|
1085
1085
|
"since": "2025-01-01"
|
|
1086
1086
|
},
|
|
1087
1087
|
"template:convergence-check.sh": {
|
|
@@ -1113,7 +1113,7 @@
|
|
|
1113
1113
|
"type": "template",
|
|
1114
1114
|
"domain": "operations",
|
|
1115
1115
|
"sourcePath": "src/templates/scripts/imessage-reply.sh",
|
|
1116
|
-
"contentHash": "
|
|
1116
|
+
"contentHash": "e4ecc66feaaea92c5f65f008e5b82b1022c7fd61ee9e4f1ed1346106b4a63d6c",
|
|
1117
1117
|
"since": "2025-01-01"
|
|
1118
1118
|
},
|
|
1119
1119
|
"template:instar-watchdog.sh": {
|
|
@@ -1121,7 +1121,7 @@
|
|
|
1121
1121
|
"type": "template",
|
|
1122
1122
|
"domain": "operations",
|
|
1123
1123
|
"sourcePath": "src/templates/scripts/instar-watchdog.sh",
|
|
1124
|
-
"contentHash": "
|
|
1124
|
+
"contentHash": "1f462b267e6724bea21692e617bd61a6b7cd4def7187321871cdc1fc178d1d1b",
|
|
1125
1125
|
"since": "2025-01-01"
|
|
1126
1126
|
},
|
|
1127
1127
|
"template:instar-worktree-create.sh": {
|
|
@@ -1137,7 +1137,7 @@
|
|
|
1137
1137
|
"type": "template",
|
|
1138
1138
|
"domain": "operations",
|
|
1139
1139
|
"sourcePath": "src/templates/scripts/secret-drop-retrieve.mjs",
|
|
1140
|
-
"contentHash": "
|
|
1140
|
+
"contentHash": "3c99a8d8898868e31e88c4b729b57968c14cb723c9ffb6f903d36a1e18841156",
|
|
1141
1141
|
"since": "2025-01-01"
|
|
1142
1142
|
},
|
|
1143
1143
|
"template:serendipity-capture.sh": {
|
|
@@ -1145,7 +1145,7 @@
|
|
|
1145
1145
|
"type": "template",
|
|
1146
1146
|
"domain": "operations",
|
|
1147
1147
|
"sourcePath": "src/templates/scripts/serendipity-capture.sh",
|
|
1148
|
-
"contentHash": "
|
|
1148
|
+
"contentHash": "317bc0bbb09bf03c9755ab25ca0b8da940eccb8a74886fac60045163c6bdd091",
|
|
1149
1149
|
"since": "2025-01-01"
|
|
1150
1150
|
},
|
|
1151
1151
|
"template:slack-reply.sh": {
|
|
@@ -1153,7 +1153,7 @@
|
|
|
1153
1153
|
"type": "template",
|
|
1154
1154
|
"domain": "operations",
|
|
1155
1155
|
"sourcePath": "src/templates/scripts/slack-reply.sh",
|
|
1156
|
-
"contentHash": "
|
|
1156
|
+
"contentHash": "ea698ef54e0e48233d82225c6cfcf886f58c7939101d966cfafc5e85edcac6a4",
|
|
1157
1157
|
"since": "2025-01-01"
|
|
1158
1158
|
},
|
|
1159
1159
|
"template:smart-fetch.py": {
|
|
@@ -1169,7 +1169,7 @@
|
|
|
1169
1169
|
"type": "template",
|
|
1170
1170
|
"domain": "operations",
|
|
1171
1171
|
"sourcePath": "src/templates/scripts/telegram-reply.sh",
|
|
1172
|
-
"contentHash": "
|
|
1172
|
+
"contentHash": "0f6d27a522b123551871e6081774f8c89d1ad0ce248597af7dd60d8522871069",
|
|
1173
1173
|
"since": "2025-01-01"
|
|
1174
1174
|
},
|
|
1175
1175
|
"template:whatsapp-reply.sh": {
|
|
@@ -1177,7 +1177,7 @@
|
|
|
1177
1177
|
"type": "template",
|
|
1178
1178
|
"domain": "operations",
|
|
1179
1179
|
"sourcePath": "src/templates/scripts/whatsapp-reply.sh",
|
|
1180
|
-
"contentHash": "
|
|
1180
|
+
"contentHash": "942712aa272235bca9f14ab6baa23bbe5ae0a8bf20f76edf87c963b181a7764c",
|
|
1181
1181
|
"since": "2025-01-01"
|
|
1182
1182
|
},
|
|
1183
1183
|
"playbook-script:atomic_write.py": {
|
|
@@ -1489,7 +1489,7 @@
|
|
|
1489
1489
|
"type": "subsystem",
|
|
1490
1490
|
"domain": "updates",
|
|
1491
1491
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
1492
|
-
"contentHash": "
|
|
1492
|
+
"contentHash": "a2f7941039c9bb8bfe6777412d3fee869077eb9a3d6e359c8f5efe52b3a693bb",
|
|
1493
1493
|
"since": "2025-01-01"
|
|
1494
1494
|
},
|
|
1495
1495
|
"subsystem:scheduler": {
|
|
@@ -174,9 +174,12 @@ echo ""
|
|
|
174
174
|
# Resolves Open Question #5 from the Consent & Discovery Framework spec:
|
|
175
175
|
# lastSurfacedAt timestamps persist in SQLite regardless of context state.
|
|
176
176
|
if [ -f "$CONFIG_FILE" ]; then
|
|
177
|
-
PORT=$(grep -
|
|
177
|
+
PORT=$(grep -oE '"port"[[:space:]]*:[[:space:]]*[0-9]+' "$CONFIG_FILE" | head -1 | grep -oE '[0-9]+' | head -1)
|
|
178
178
|
if [ -n "$PORT" ]; then
|
|
179
|
-
AUTH_TOKEN
|
|
179
|
+
AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
180
|
+
if [ -z "$AUTH_TOKEN" ]; then
|
|
181
|
+
AUTH_TOKEN=$(python3 -c "import json; v=json.load(open('$CONFIG_FILE')).get('authToken',''); print(v if isinstance(v, str) else '')" 2>/dev/null)
|
|
182
|
+
fi
|
|
180
183
|
FEATURES_JSON=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
181
184
|
"http://localhost:${PORT}/features/summary" 2>/dev/null)
|
|
182
185
|
if [ -n "$FEATURES_JSON" ]; then
|
|
@@ -235,7 +238,7 @@ fi
|
|
|
235
238
|
# Server health reminder + recent Telegram context
|
|
236
239
|
CONFIG_FILE="$INSTAR_DIR/config.json"
|
|
237
240
|
if [ -f "$CONFIG_FILE" ]; then
|
|
238
|
-
PORT=$(grep -
|
|
241
|
+
PORT=$(grep -oE '"port"[[:space:]]*:[[:space:]]*[0-9]+' "$CONFIG_FILE" | head -1 | grep -oE '[0-9]+' | head -1)
|
|
239
242
|
if [ -n "$PORT" ]; then
|
|
240
243
|
echo "Server: curl http://localhost:${PORT}/health | Capabilities: curl http://localhost:${PORT}/capabilities"
|
|
241
244
|
|
|
@@ -247,7 +250,10 @@ if [ -f "$CONFIG_FILE" ]; then
|
|
|
247
250
|
# Slack channel context — if INSTAR_SLACK_CHANNEL is set, this is a Slack session
|
|
248
251
|
SLACK_CHANNEL="${INSTAR_SLACK_CHANNEL:-}"
|
|
249
252
|
if [ -n "$SLACK_CHANNEL" ]; then
|
|
250
|
-
AUTH_TOKEN
|
|
253
|
+
AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
254
|
+
if [ -z "$AUTH_TOKEN" ]; then
|
|
255
|
+
AUTH_TOKEN=$(python3 -c "import json; v=json.load(open('$CONFIG_FILE')).get('authToken',''); print(v if isinstance(v, str) else '')" 2>/dev/null)
|
|
256
|
+
fi
|
|
251
257
|
SLACK_MSGS=$(curl -s \
|
|
252
258
|
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
253
259
|
"http://localhost:${PORT}/slack/channels/${SLACK_CHANNEL}/messages?limit=20" 2>/dev/null)
|
|
@@ -346,7 +352,10 @@ except Exception:
|
|
|
346
352
|
fi
|
|
347
353
|
|
|
348
354
|
if [ -n "$TOPIC_FOR_CONTEXT" ]; then
|
|
349
|
-
AUTH_TOKEN
|
|
355
|
+
AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
356
|
+
if [ -z "$AUTH_TOKEN" ]; then
|
|
357
|
+
AUTH_TOKEN=$(python3 -c "import json; v=json.load(open('$CONFIG_FILE')).get('authToken',''); print(v if isinstance(v, str) else '')" 2>/dev/null)
|
|
358
|
+
fi
|
|
350
359
|
if [ -n "$AUTH_TOKEN" ]; then
|
|
351
360
|
RECENT_MSGS=$(curl -s \
|
|
352
361
|
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
@@ -418,9 +427,12 @@ fi
|
|
|
418
427
|
# This surfaces what you already know that's relevant to the current context,
|
|
419
428
|
# preventing you from re-deriving knowledge you've already accumulated.
|
|
420
429
|
if [ -f "$CONFIG_FILE" ]; then
|
|
421
|
-
PORT=$(grep -
|
|
430
|
+
PORT=$(grep -oE '"port"[[:space:]]*:[[:space:]]*[0-9]+' "$CONFIG_FILE" | head -1 | grep -oE '[0-9]+' | head -1)
|
|
422
431
|
if [ -n "$PORT" ]; then
|
|
423
|
-
AUTH_TOKEN
|
|
432
|
+
AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
433
|
+
if [ -z "$AUTH_TOKEN" ]; then
|
|
434
|
+
AUTH_TOKEN=$(python3 -c "import json; v=json.load(open('$CONFIG_FILE')).get('authToken',''); print(v if isinstance(v, str) else '')" 2>/dev/null)
|
|
435
|
+
fi
|
|
424
436
|
WORKING_MEM=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
425
437
|
"http://localhost:${PORT}/context/working-memory?prompt=compaction-recovery&limit=5" 2>/dev/null)
|
|
426
438
|
if [ -n "$WORKING_MEM" ]; then
|
|
@@ -452,10 +464,13 @@ fi
|
|
|
452
464
|
# so it gives us a guaranteed signal. The server will check for unanswered user
|
|
453
465
|
# messages and re-inject them shortly after this hook completes.
|
|
454
466
|
if [ -f "$CONFIG_FILE" ] && command -v tmux >/dev/null 2>&1; then
|
|
455
|
-
PORT=$(grep -
|
|
467
|
+
PORT=$(grep -oE '"port"[[:space:]]*:[[:space:]]*[0-9]+' "$CONFIG_FILE" | head -1 | grep -oE '[0-9]+' | head -1)
|
|
456
468
|
TMUX_SESSION=$(tmux display-message -p '#S' 2>/dev/null)
|
|
457
469
|
if [ -n "$PORT" ] && [ -n "$TMUX_SESSION" ]; then
|
|
458
|
-
AUTH_TOKEN
|
|
470
|
+
AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
471
|
+
if [ -z "$AUTH_TOKEN" ]; then
|
|
472
|
+
AUTH_TOKEN=$(python3 -c "import json; v=json.load(open('$CONFIG_FILE')).get('authToken',''); print(v if isinstance(v, str) else '')" 2>/dev/null)
|
|
473
|
+
fi
|
|
459
474
|
curl -s -m 2 -X POST \
|
|
460
475
|
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
461
476
|
-H "Content-Type: application/json" \
|
|
@@ -21,12 +21,19 @@ if [ ! -f "$CONFIG_FILE" ]; then
|
|
|
21
21
|
exit 0
|
|
22
22
|
fi
|
|
23
23
|
|
|
24
|
-
PORT=$(grep -
|
|
24
|
+
PORT=$(grep -oE '"port"[[:space:]]*:[[:space:]]*[0-9]+' "$CONFIG_FILE" | head -1 | grep -oE '[0-9]+' | head -1)
|
|
25
25
|
if [ -z "$PORT" ]; then
|
|
26
26
|
exit 0
|
|
27
27
|
fi
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
# Resolve auth token: INSTAR_AUTH_TOKEN env first (SessionManager injects it per
|
|
30
|
+
# spawned session — survives secret-externalization), legacy plaintext-config
|
|
31
|
+
# fallback with string-type guard so the { "secret": true } placeholder produced
|
|
32
|
+
# by SecretMigrator cannot leak through as a bogus Bearer.
|
|
33
|
+
AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
34
|
+
if [ -z "$AUTH_TOKEN" ]; then
|
|
35
|
+
AUTH_TOKEN=$(python3 -c "import json; v=json.load(open('$CONFIG_FILE')).get('authToken',''); print(v if isinstance(v, str) else '')" 2>/dev/null)
|
|
36
|
+
fi
|
|
30
37
|
|
|
31
38
|
# Check if server is alive
|
|
32
39
|
HEALTH=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
@@ -29,7 +29,14 @@ if [ -f ".instar/config.json" ]; then
|
|
|
29
29
|
CONFIG_PORT=$(python3 -c "import json; print(json.load(open('.instar/config.json')).get('port',''))" 2>/dev/null)
|
|
30
30
|
[ -n "$CONFIG_PORT" ] && PORT="$CONFIG_PORT"
|
|
31
31
|
fi
|
|
32
|
-
|
|
32
|
+
# Auth resolution: INSTAR_AUTH_TOKEN env first (SessionManager injects it per
|
|
33
|
+
# spawned session — survives secret-externalization), legacy plaintext-config
|
|
34
|
+
# fallback with string-type guard so the { "secret": true } placeholder
|
|
35
|
+
# produced by SecretMigrator cannot leak through as a bogus Bearer.
|
|
36
|
+
AUTH="${INSTAR_AUTH_TOKEN:-}"
|
|
37
|
+
if [ -z "$AUTH" ]; then
|
|
38
|
+
AUTH=$(python3 -c "import json; v=json.load(open('.instar/config.json')).get('authToken',''); print(v if isinstance(v, str) else '')" 2>/dev/null)
|
|
39
|
+
fi
|
|
33
40
|
fi
|
|
34
41
|
|
|
35
42
|
PORT="${PORT:-4042}"
|
|
@@ -43,7 +43,7 @@ if [ ! -f "$CONFIG_FILE" ]; then
|
|
|
43
43
|
exit 0
|
|
44
44
|
fi
|
|
45
45
|
|
|
46
|
-
PORT=$(grep -
|
|
46
|
+
PORT=$(grep -oE '"port"[[:space:]]*:[[:space:]]*[0-9]+' "$CONFIG_FILE" | head -1 | grep -oE '[0-9]+' | head -1)
|
|
47
47
|
if [ -z "$PORT" ]; then
|
|
48
48
|
exit 0
|
|
49
49
|
fi
|
|
@@ -54,8 +54,20 @@ if [ "$HEALTH" != "200" ]; then
|
|
|
54
54
|
exit 0
|
|
55
55
|
fi
|
|
56
56
|
|
|
57
|
+
# Resolve the auth token. INSTAR_AUTH_TOKEN env first — SessionManager injects
|
|
58
|
+
# this into every spawned Claude Code session, so hooks running inside a session
|
|
59
|
+
# always have it; survives the secret-externalization refactor that moved authToken
|
|
60
|
+
# out of config.json into the encrypted store. Legacy fallback reads config.json
|
|
61
|
+
# with a string-type guard: after externalization the value is the literal
|
|
62
|
+
# placeholder { "secret": true } — the guard rejects it and yields empty so we
|
|
63
|
+
# never send the placeholder as a Bearer token (which the server rejects with 403,
|
|
64
|
+
# silently breaking history injection — the 2026-05-29 incident this fix is for).
|
|
65
|
+
AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
66
|
+
if [ -z "$AUTH_TOKEN" ] && [ -f "$CONFIG_FILE" ]; then
|
|
67
|
+
AUTH_TOKEN=$(python3 -c "import json; v=json.load(open('$CONFIG_FILE')).get('authToken',''); print(v if isinstance(v, str) else '')" 2>/dev/null)
|
|
68
|
+
fi
|
|
69
|
+
|
|
57
70
|
# Fetch recent messages for this topic
|
|
58
|
-
AUTH_TOKEN=$(python3 -c "import json; print(json.load(open('$CONFIG_FILE')).get('authToken',''))" 2>/dev/null)
|
|
59
71
|
if [ -n "$AUTH_TOKEN" ]; then
|
|
60
72
|
RECENT_MSGS=$(curl -s \
|
|
61
73
|
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
@@ -42,9 +42,13 @@ fi
|
|
|
42
42
|
|
|
43
43
|
PORT="${INSTAR_PORT:-4042}"
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
# Auth: env first (SessionManager injects it per spawned session and it
|
|
46
|
+
# survives secret-externalization), legacy plaintext-config fallback with
|
|
47
|
+
# string-type guard so the { "secret": true } placeholder produced by
|
|
48
|
+
# SecretMigrator cannot leak through as a bogus Bearer.
|
|
49
|
+
AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
50
|
+
if [ -z "$AUTH_TOKEN" ] && [ -f ".instar/config.json" ]; then
|
|
51
|
+
AUTH_TOKEN=$(python3 -c "import json; v=json.load(open('.instar/config.json')).get('authToken',''); print(v if isinstance(v, str) else '')" 2>/dev/null)
|
|
48
52
|
fi
|
|
49
53
|
|
|
50
54
|
# Escape message for JSON
|
|
@@ -324,7 +324,11 @@ escalate_via_peer() {
|
|
|
324
324
|
node_bin=$(resolve_node || true)
|
|
325
325
|
[ -z "$node_bin" ] && continue
|
|
326
326
|
local peer_meta
|
|
327
|
-
|
|
327
|
+
# The string-type guard on authToken protects against the { secret: true }
|
|
328
|
+
# placeholder that SecretMigrator writes after externalizing the auth token:
|
|
329
|
+
# `c.authToken || ''` would otherwise return the object itself (truthy)
|
|
330
|
+
# which serializes to "[object Object]" — never a valid Bearer.
|
|
331
|
+
peer_meta=$("$node_bin" -e "const c=JSON.parse(require('fs').readFileSync(process.argv[1],'utf8'));const t=typeof c.authToken==='string'?c.authToken:'';process.stdout.write((c.port||'')+'\t'+t)" "$peer_dir/.instar/config.json" 2>/dev/null || true)
|
|
328
332
|
peer_port="${peer_meta%% *}"
|
|
329
333
|
peer_auth="${peer_meta##* }"
|
|
330
334
|
[ -z "$peer_port" ] && continue
|
|
@@ -434,11 +438,16 @@ probe_server_identity() {
|
|
|
434
438
|
node_bin=$(resolve_node || true)
|
|
435
439
|
[ -z "$node_bin" ] && return 0
|
|
436
440
|
|
|
437
|
-
# Read port + authToken in one node invocation. The authToken is
|
|
438
|
-
# because /health gates the `project` field behind authentication
|
|
439
|
-
# it the probe can
|
|
441
|
+
# Read port + authToken in one node invocation. The authToken is needed
|
|
442
|
+
# because /health gates the `project` field behind authentication; without
|
|
443
|
+
# it the probe can still hit /health for a basic alive check but loses the
|
|
444
|
+
# identity disambiguation. INSTAR_AUTH_TOKEN env is preferred when set
|
|
445
|
+
# (preserves cross-version compatibility). The string-type guard rejects the
|
|
446
|
+
# { secret: true } placeholder SecretMigrator writes after externalizing the
|
|
447
|
+
# auth token — `String(c.authToken || '')` would otherwise yield
|
|
448
|
+
# "[object Object]" and the Bearer would be invalid.
|
|
440
449
|
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'+
|
|
450
|
+
meta=$("$node_bin" -e "const c=JSON.parse(require('fs').readFileSync(process.argv[1],'utf8'));const t=process.env.INSTAR_AUTH_TOKEN||(typeof c.authToken==='string'?c.authToken:'');process.stdout.write(String(c.port||'')+'\t'+t)" "$config_file" 2>/dev/null || true)
|
|
442
451
|
port="${meta%% *}"
|
|
443
452
|
auth_token="${meta##* }"
|
|
444
453
|
# Lifeline-only agents have no port; treat as healthy from probe POV.
|
|
@@ -47,15 +47,23 @@ if (!token || !mode || mode === '--consume') {
|
|
|
47
47
|
process.exit(2);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
// Auth-token resolution: INSTAR_AUTH_TOKEN env first (SessionManager and
|
|
51
|
+
// JobScheduler inject it for every spawned context; survives the
|
|
52
|
+
// secret-externalization refactor that moved authToken out of config.json into
|
|
53
|
+
// the encrypted store), legacy plaintext-config fallback with a string-type
|
|
54
|
+
// guard so the { "secret": true } placeholder produced by SecretMigrator
|
|
55
|
+
// cannot leak through as a bogus Bearer.
|
|
56
|
+
let authToken = process.env.INSTAR_AUTH_TOKEN || '';
|
|
51
57
|
let port;
|
|
52
58
|
try {
|
|
53
59
|
const config = JSON.parse(fs.readFileSync('.instar/config.json', 'utf-8'));
|
|
54
|
-
authToken = config.authToken;
|
|
60
|
+
if (!authToken && typeof config.authToken === 'string') authToken = config.authToken;
|
|
55
61
|
port = config.port;
|
|
56
62
|
} catch (e) {
|
|
57
|
-
|
|
58
|
-
|
|
63
|
+
if (!authToken) {
|
|
64
|
+
process.stderr.write('cannot read .instar/config.json: ' + e.message + '\n');
|
|
65
|
+
process.exit(2);
|
|
66
|
+
}
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
// Port resolution: env > config. Mirrors the telegram-reply.sh precedence
|
|
@@ -294,15 +294,21 @@ if patch_file or artifact_type:
|
|
|
294
294
|
# Key derivation: HMAC-SHA256(authToken, "serendipity-v1:" + sessionId)
|
|
295
295
|
signing_key = os.environ.get("SERENDIPITY_SIGNING_KEY", "")
|
|
296
296
|
if not signing_key:
|
|
297
|
-
# Derive from auth token + session
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
297
|
+
# Derive from auth token + session. Token: INSTAR_AUTH_TOKEN env first
|
|
298
|
+
# (SessionManager injects it; survives secret-externalization), legacy
|
|
299
|
+
# plaintext-config fallback with a string-type guard so the
|
|
300
|
+
# { "secret": true } placeholder produced by SecretMigrator cannot leak.
|
|
301
|
+
auth_token = os.environ.get("INSTAR_AUTH_TOKEN", "")
|
|
302
|
+
if not auth_token:
|
|
303
|
+
config_path = os.environ.get("CONFIG_FILE", "")
|
|
304
|
+
if config_path and os.path.exists(config_path):
|
|
305
|
+
try:
|
|
306
|
+
cfg = json.load(open(config_path))
|
|
307
|
+
v = cfg.get("authToken", "")
|
|
308
|
+
if isinstance(v, str):
|
|
309
|
+
auth_token = v
|
|
310
|
+
except:
|
|
311
|
+
pass
|
|
306
312
|
session_id = finding["source"]["sessionId"]
|
|
307
313
|
key_material = f"serendipity-v1:{session_id}"
|
|
308
314
|
signing_key = hmac.new(
|
|
@@ -44,7 +44,14 @@ if [ -f ".instar/config.json" ]; then
|
|
|
44
44
|
CONFIG_PORT=$(python3 -c "import json; print(json.load(open('.instar/config.json')).get('port',''))" 2>/dev/null)
|
|
45
45
|
[ -n "$CONFIG_PORT" ] && PORT="$CONFIG_PORT"
|
|
46
46
|
fi
|
|
47
|
-
|
|
47
|
+
# Auth: env first (SessionManager injects it into spawned sessions; survives
|
|
48
|
+
# secret-externalization), legacy plaintext-config fallback with string-type
|
|
49
|
+
# guard so the { "secret": true } placeholder produced by SecretMigrator
|
|
50
|
+
# cannot leak as a bogus Bearer.
|
|
51
|
+
AUTH="${INSTAR_AUTH_TOKEN:-}"
|
|
52
|
+
if [ -z "$AUTH" ]; then
|
|
53
|
+
AUTH=$(python3 -c "import json; v=json.load(open('.instar/config.json')).get('authToken',''); print(v if isinstance(v, str) else '')" 2>/dev/null)
|
|
54
|
+
fi
|
|
48
55
|
fi
|
|
49
56
|
|
|
50
57
|
PORT="${PORT:-4042}"
|
|
@@ -75,9 +75,13 @@ if [ -z "$MSG" ]; then
|
|
|
75
75
|
fi
|
|
76
76
|
|
|
77
77
|
# Resolve config-derived values from .instar/config.json (single python3
|
|
78
|
-
# invocation). Env > config > 4040-warn for port
|
|
79
|
-
#
|
|
80
|
-
|
|
78
|
+
# invocation). Env > config > 4040-warn for port. Auth: INSTAR_AUTH_TOKEN env
|
|
79
|
+
# first (SessionManager injects it per spawned session; survives the
|
|
80
|
+
# secret-externalization refactor that moved authToken out of config.json into
|
|
81
|
+
# the encrypted store), legacy plaintext-config fallback with a string-type
|
|
82
|
+
# guard so the { "secret": true } placeholder produced by SecretMigrator
|
|
83
|
+
# cannot leak through as a bogus Bearer.
|
|
84
|
+
AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
81
85
|
AGENT_ID=""
|
|
82
86
|
CONFIG_PORT=""
|
|
83
87
|
if [ -f ".instar/config.json" ]; then
|
|
@@ -87,11 +91,13 @@ try:
|
|
|
87
91
|
c = json.load(open('.instar/config.json'))
|
|
88
92
|
except Exception:
|
|
89
93
|
sys.exit(0)
|
|
90
|
-
|
|
94
|
+
v = c.get('authToken', '')
|
|
95
|
+
print(v if isinstance(v, str) else '')
|
|
91
96
|
print(c.get('projectName', ''))
|
|
92
97
|
print(c.get('port', ''))
|
|
93
98
|
" 2>/dev/null)
|
|
94
|
-
|
|
99
|
+
CONFIG_AUTH=$(printf '%s\n' "$CONFIG_VALUES" | sed -n '1p')
|
|
100
|
+
[ -z "$AUTH_TOKEN" ] && AUTH_TOKEN="$CONFIG_AUTH"
|
|
95
101
|
AGENT_ID=$(printf '%s\n' "$CONFIG_VALUES" | sed -n '2p')
|
|
96
102
|
CONFIG_PORT=$(printf '%s\n' "$CONFIG_VALUES" | sed -n '3p')
|
|
97
103
|
fi
|
|
@@ -33,10 +33,13 @@ fi
|
|
|
33
33
|
|
|
34
34
|
PORT="${INSTAR_PORT:-4040}"
|
|
35
35
|
|
|
36
|
-
# Read auth token
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
# Read auth token: env first (SessionManager injects it per spawned session and
|
|
37
|
+
# it survives secret-externalization), legacy plaintext-config fallback with
|
|
38
|
+
# string-type guard so the { "secret": true } placeholder produced by
|
|
39
|
+
# SecretMigrator cannot leak through as a bogus Bearer.
|
|
40
|
+
AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
41
|
+
if [ -z "$AUTH_TOKEN" ] && [ -f ".instar/config.json" ]; then
|
|
42
|
+
AUTH_TOKEN=$(python3 -c "import json; v=json.load(open('.instar/config.json')).get('authToken',''); print(v if isinstance(v, str) else '')" 2>/dev/null)
|
|
40
43
|
fi
|
|
41
44
|
|
|
42
45
|
# Escape for JSON
|