instar 1.3.305 → 1.3.306
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/init.d.ts.map +1 -1
- package/dist/commands/init.js +32 -30
- package/dist/commands/init.js.map +1 -1
- package/dist/core/Config.d.ts.map +1 -1
- package/dist/core/Config.js +2 -0
- package/dist/core/Config.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +6 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +3 -0
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/types.d.ts +4 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/scheduler/JobScheduler.d.ts.map +1 -1
- package/dist/scheduler/JobScheduler.js +10 -6
- package/dist/scheduler/JobScheduler.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +58 -58
- package/src/scaffold/templates/jobs/instar/commitment-detection.md +2 -1
- package/src/scaffold/templates/jobs/instar/correction-analyzer.md +5 -1
- package/src/scaffold/templates/jobs/instar/evolution-overdue-check.md +1 -1
- package/src/scaffold/templates/jobs/instar/evolution-proposal-evaluate.md +1 -1
- package/src/scaffold/templates/jobs/instar/evolution-proposal-implement.md +1 -1
- package/src/scaffold/templates/jobs/instar/failure-analyzer.md +5 -1
- package/src/scaffold/templates/jobs/instar/identity-review.md +5 -4
- package/src/scaffold/templates/jobs/instar/initiative-digest-review.md +3 -1
- package/src/scaffold/templates/jobs/instar/insight-harvest.md +1 -1
- package/src/scaffold/templates/jobs/instar/mentor-onboarding.md +7 -4
- package/src/scaffold/templates/jobs/instar/org-intent-drift-audit.md +6 -4
- package/src/scaffold/templates/jobs/instar/overseer-development.md +4 -1
- package/src/scaffold/templates/jobs/instar/overseer-guardian.md +4 -1
- package/src/scaffold/templates/jobs/instar/overseer-infrastructure.md +4 -1
- package/src/scaffold/templates/jobs/instar/overseer-learning.md +4 -1
- package/src/scaffold/templates/jobs/instar/overseer-maintenance.md +4 -1
- package/src/scaffold/templates/jobs/instar/release-readiness-check.md +2 -1
- package/src/templates/hooks/compaction-recovery.sh +11 -6
- package/src/templates/hooks/session-start.sh +11 -3
- package/src/templates/hooks/slack-channel-context.sh +5 -0
- package/src/templates/hooks/telegram-topic-context.sh +6 -0
- package/src/templates/scripts/emit-session-clock.sh +3 -3
- package/src/templates/scripts/imessage-reply.sh +10 -0
- package/src/templates/scripts/instar-watchdog.sh +12 -6
- package/src/templates/scripts/secret-drop-retrieve.mjs +10 -2
- package/src/templates/scripts/slack-reply.sh +5 -0
- package/src/templates/scripts/whatsapp-reply.sh +5 -0
- package/upgrades/1.3.306.md +22 -0
- package/upgrades/side-effects/template-agent-id-header.md +48 -0
|
@@ -22,17 +22,20 @@ That keeps the structural two-hats enforcement in code, not in this prompt.
|
|
|
22
22
|
|
|
23
23
|
Do exactly this:
|
|
24
24
|
|
|
25
|
-
1.
|
|
26
|
-
`
|
|
25
|
+
1. Resolve auth context:
|
|
26
|
+
`AUTH="${INSTAR_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)}"; AGENT_ID="${INSTAR_AGENT_ID:-$(python3 -c "import json; print(json.load(open('.instar/config.json')).get('projectName',''))" 2>/dev/null)}"; PORT="${INSTAR_PORT:-4042}"`
|
|
27
27
|
|
|
28
|
-
2.
|
|
28
|
+
2. POST to `http://localhost:${PORT}/mentor/tick` with the bearer token:
|
|
29
|
+
`curl -s -X POST -H "Authorization: Bearer $AUTH" -H "X-Instar-AgentId: $AGENT_ID" http://localhost:${PORT}/mentor/tick`
|
|
30
|
+
|
|
31
|
+
3. Read the JSON result. It will be one of:
|
|
29
32
|
- `{"ran":false,"reason":"disabled"}` — the mentor is off (the default). Nothing to do; stop.
|
|
30
33
|
- `{"ran":false,"reason":"budget"|"unsafe-window"|"canary-failed"}` — it correctly skipped this
|
|
31
34
|
tick. Stop; the next heartbeat will try again.
|
|
32
35
|
- `{"ran":true,...}` — a mentor tick ran. Note `leakDetected` and `observationsWritten` briefly,
|
|
33
36
|
then stop.
|
|
34
37
|
|
|
35
|
-
|
|
38
|
+
4. Do NOT do any mentoring work yourself in this session, do NOT read the mentee's logs or code,
|
|
36
39
|
and do NOT send the mentee any message — the in-process tick owns all of that. You are only the
|
|
37
40
|
timer that pokes it. Then exit.
|
|
38
41
|
|
|
@@ -20,13 +20,15 @@ The job:
|
|
|
20
20
|
|
|
21
21
|
1. Verify the prerequisites. The drift audit only makes sense when `.instar/ORG-INTENT.md` is present AND the Coherence Gate has accumulated at least 5 review entries in the last 7 days. If either condition isn't met, send a short Telegram message saying so and exit — there's nothing to audit yet.
|
|
22
22
|
|
|
23
|
-
2.
|
|
23
|
+
2. Set auth context: `AUTH="${INSTAR_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)}"; AGENT_ID="${INSTAR_AGENT_ID:-$(python3 -c "import json; print(json.load(open('.instar/config.json')).get('projectName',''))" 2>/dev/null)}"; PORT="${INSTAR_PORT:-4042}"`
|
|
24
24
|
|
|
25
|
-
3.
|
|
25
|
+
3. Call the drift digest endpoint: `curl -H "Authorization: Bearer $AUTH" -H "X-Instar-AgentId: $AGENT_ID" "http://localhost:$PORT/intent/org/drift?lookbackDays=7"`. The response is a structured analysis: overall block rate, per-reviewer breakdown, half-window trend comparison (first half vs second half block rate), cross-reference against ORG-INTENT constraints / goals / values, and a single `trend` label (`stable` | `rising` | `concerning` | `insufficient-data` | `no-org-intent`).
|
|
26
26
|
|
|
27
|
-
4. If `trend === '
|
|
27
|
+
4. If `trend === 'stable'` or `trend === 'insufficient-data'` or `trend === 'no-org-intent'`, stay silent. Most weeks should be silent — that means the agent is staying aligned with the organizational intent. The `shouldSurface` field in the response will be `false` in these cases.
|
|
28
28
|
|
|
29
|
-
5.
|
|
29
|
+
5. If `trend === 'rising'` or `trend === 'concerning'`, surface the drift via Telegram. The response includes a `summary` field (plain-English one-paragraph framing) and a `suggestions` array (specific next actions). Compose a conversational message that leads with the trend and what changed: "Block rate climbed from 4% to 12% in the second half of the week — most flags came from value-alignment." Then list the most-flagged reviewer dimensions. Then surface the top 1-2 suggestions. Keep it under 600 characters. Plain English. No raw JSON.
|
|
30
|
+
|
|
31
|
+
6. After surfacing (or not), the audit is done. No state to persist — the gate's own review history is the canonical store.
|
|
30
32
|
|
|
31
33
|
IMPORTANT: This is a guardian job, not a doer. Surface the drift and where it might be coming from. Don't try to fix it autonomously. The fix work — if any — is a deliberate update to `.instar/ORG-INTENT.md` constraints, or a configuration change to the gate, or an operator-level decision about whether the agent's behavior is actually drifting or whether the constraints need updating. Surface; don't fix.
|
|
32
34
|
|
|
@@ -14,7 +14,10 @@ unrestrictedTools: true
|
|
|
14
14
|
---
|
|
15
15
|
You are a Category Overseer for the DEVELOPMENT category. Your job is to review development-focused jobs.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
AUTH="${INSTAR_AUTH_TOKEN:-}"
|
|
18
|
+
AGENT_ID="${INSTAR_AGENT_ID:-}"
|
|
19
|
+
|
|
20
|
+
1. Fetch the category report: curl -H "Authorization: Bearer $AUTH" -H "X-Instar-AgentId: $AGENT_ID" http://localhost:${INSTAR_PORT:-4042}/jobs/category-report/development?sinceHours=48
|
|
18
21
|
2. Analyze:
|
|
19
22
|
- Are development jobs consuming appropriate resources for their value?
|
|
20
23
|
- Are there CI/testing patterns that could be automated?
|
|
@@ -14,7 +14,10 @@ unrestrictedTools: true
|
|
|
14
14
|
---
|
|
15
15
|
You are a Category Overseer for the GUARDIAN category. Your job is to review all guardian/monitoring jobs and assess the health of the monitoring system itself.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
AUTH="${INSTAR_AUTH_TOKEN:-}"
|
|
18
|
+
AGENT_ID="${INSTAR_AGENT_ID:-}"
|
|
19
|
+
|
|
20
|
+
1. Fetch the category report: curl -H "Authorization: Bearer $AUTH" -H "X-Instar-AgentId: $AGENT_ID" http://localhost:${INSTAR_PORT:-4042}/jobs/category-report/guardian?sinceHours=24
|
|
18
21
|
2. Analyze the report for:
|
|
19
22
|
- Jobs with high failure rates or consecutive failures
|
|
20
23
|
- Jobs that are being skipped excessively (especially for quota reasons)
|
|
@@ -14,7 +14,10 @@ unrestrictedTools: true
|
|
|
14
14
|
---
|
|
15
15
|
You are a Category Overseer for the INFRASTRUCTURE category. Your job is to review infrastructure/plumbing jobs.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
AUTH="${INSTAR_AUTH_TOKEN:-}"
|
|
18
|
+
AGENT_ID="${INSTAR_AGENT_ID:-}"
|
|
19
|
+
|
|
20
|
+
1. Fetch the category report: curl -H "Authorization: Bearer $AUTH" -H "X-Instar-AgentId: $AGENT_ID" http://localhost:${INSTAR_PORT:-4042}/jobs/category-report/infrastructure?sinceHours=48
|
|
18
21
|
2. Analyze:
|
|
19
22
|
- Is git-sync succeeding? Any merge conflicts or divergence?
|
|
20
23
|
- Is dashboard-link-refresh keeping links current? Could it run less often?
|
|
@@ -14,7 +14,10 @@ unrestrictedTools: true
|
|
|
14
14
|
---
|
|
15
15
|
You are a Category Overseer for the LEARNING category. Your job is to review all evolution/learning jobs and assess whether the learning pipeline is producing genuine value.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
AUTH="${INSTAR_AUTH_TOKEN:-}"
|
|
18
|
+
AGENT_ID="${INSTAR_AGENT_ID:-}"
|
|
19
|
+
|
|
20
|
+
1. Fetch the category report: curl -H "Authorization: Bearer $AUTH" -H "X-Instar-AgentId: $AGENT_ID" http://localhost:${INSTAR_PORT:-4042}/jobs/category-report/learning?sinceHours=48
|
|
18
21
|
2. Analyze:
|
|
19
22
|
- Are evolution proposals being generated AND accepted? What's the accept/reject ratio?
|
|
20
23
|
- Is insight-harvest finding novel insights or recycling stale ones?
|
|
@@ -14,7 +14,10 @@ unrestrictedTools: true
|
|
|
14
14
|
---
|
|
15
15
|
You are a Category Overseer for the MAINTENANCE category. Your job is to review all housekeeping/maintenance jobs and ensure they're keeping the system clean.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
AUTH="${INSTAR_AUTH_TOKEN:-}"
|
|
18
|
+
AGENT_ID="${INSTAR_AGENT_ID:-}"
|
|
19
|
+
|
|
20
|
+
1. Fetch the category report: curl -H "Authorization: Bearer $AUTH" -H "X-Instar-AgentId: $AGENT_ID" http://localhost:${INSTAR_PORT:-4042}/jobs/category-report/maintenance?sinceHours=48
|
|
18
21
|
2. Analyze:
|
|
19
22
|
- Is memory-hygiene actually reducing stale entries, or finding nothing each run?
|
|
20
23
|
- Is project-map-refresh keeping the map accurate? How often does it find drift?
|
|
@@ -18,8 +18,9 @@ mcpAccess: none
|
|
|
18
18
|
Run the release-readiness check once. This is a mechanical, near-silent watchdog — do NOT message the user.
|
|
19
19
|
|
|
20
20
|
AUTH=$(python3 -c "import json; print(json.load(open('.instar/config.json')).get('authToken',''))" 2>/dev/null)
|
|
21
|
+
AGENT_ID="${INSTAR_AGENT_ID:-$(python3 -c "import json; print(json.load(open('.instar/config.json')).get('projectName',''))" 2>/dev/null)}"
|
|
21
22
|
|
|
22
23
|
1. Trigger one evaluation tick:
|
|
23
|
-
curl -s -X POST http://localhost:${INSTAR_PORT:-4042}/release-readiness/tick -H "Authorization: Bearer $AUTH"
|
|
24
|
+
curl -s -X POST http://localhost:${INSTAR_PORT:-4042}/release-readiness/tick -H "Authorization: Bearer $AUTH" -H "X-Instar-AgentId: $AGENT_ID"
|
|
24
25
|
2. That endpoint runs the ReleaseReadinessSentinel: it fetches canonical main, checks whether unreleased feature/fix work is piling up while publishing is blocked, and (only above the age threshold) raises a single deduped Attention item. All transitions are written to logs/sentinel-events.jsonl.
|
|
25
26
|
3. Exit silently. The sentinel owns all signalling (Attention queue) — this job is just the cadence. Do not relay anything to Telegram; do not summarize. If the curl fails, that is itself recorded by the server; do not retry-flood.
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
# matched on "compaction".
|
|
15
15
|
|
|
16
16
|
INSTAR_DIR="${CLAUDE_PROJECT_DIR:-.}/.instar"
|
|
17
|
+
CONFIG_FILE="$INSTAR_DIR/config.json"
|
|
18
|
+
AGENT_ID="${INSTAR_AGENT_ID:-}"
|
|
19
|
+
if [ -z "$AGENT_ID" ] && [ -f "$CONFIG_FILE" ]; then
|
|
20
|
+
AGENT_ID=$(python3 -c "import json; print(json.load(open('$CONFIG_FILE')).get('projectName',''))" 2>/dev/null)
|
|
21
|
+
fi
|
|
17
22
|
|
|
18
23
|
echo "=== COMPACTION RECOVERY — IDENTITY RESTORATION ==="
|
|
19
24
|
echo ""
|
|
@@ -36,7 +41,7 @@ if [ -f "$INSTAR_DIR/soul.md" ]; then
|
|
|
36
41
|
# Check integrity via server if available
|
|
37
42
|
SOUL_INTEGRITY="valid"
|
|
38
43
|
if [ -n "$PORT" ] && [ -n "$AUTH_TOKEN" ]; then
|
|
39
|
-
INTEGRITY_CHECK=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
44
|
+
INTEGRITY_CHECK=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" -H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
40
45
|
"http://localhost:${PORT}/identity/soul/integrity" 2>/dev/null)
|
|
41
46
|
SOUL_INTEGRITY=$(echo "$INTEGRITY_CHECK" | python3 -c "
|
|
42
47
|
import sys, json
|
|
@@ -180,7 +185,7 @@ if [ -f "$CONFIG_FILE" ]; then
|
|
|
180
185
|
if [ -z "$AUTH_TOKEN" ]; then
|
|
181
186
|
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
187
|
fi
|
|
183
|
-
FEATURES_JSON=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
188
|
+
FEATURES_JSON=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" -H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
184
189
|
"http://localhost:${PORT}/features/summary" 2>/dev/null)
|
|
185
190
|
if [ -n "$FEATURES_JSON" ]; then
|
|
186
191
|
DISCOVERY_STATE=$(echo "$FEATURES_JSON" | python3 -c "
|
|
@@ -255,7 +260,7 @@ if [ -f "$CONFIG_FILE" ]; then
|
|
|
255
260
|
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
261
|
fi
|
|
257
262
|
SLACK_MSGS=$(curl -s \
|
|
258
|
-
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
263
|
+
-H "Authorization: Bearer ${AUTH_TOKEN}" -H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
259
264
|
"http://localhost:${PORT}/slack/channels/${SLACK_CHANNEL}/messages?limit=20" 2>/dev/null)
|
|
260
265
|
|
|
261
266
|
echo "$SLACK_MSGS" | python3 -c "
|
|
@@ -358,7 +363,7 @@ except Exception:
|
|
|
358
363
|
fi
|
|
359
364
|
if [ -n "$AUTH_TOKEN" ]; then
|
|
360
365
|
RECENT_MSGS=$(curl -s \
|
|
361
|
-
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
366
|
+
-H "Authorization: Bearer ${AUTH_TOKEN}" -H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
362
367
|
"http://localhost:${PORT}/telegram/topics/${TOPIC_FOR_CONTEXT}/messages?limit=15" 2>/dev/null)
|
|
363
368
|
else
|
|
364
369
|
RECENT_MSGS=$(curl -s \
|
|
@@ -433,7 +438,7 @@ if [ -f "$CONFIG_FILE" ]; then
|
|
|
433
438
|
if [ -z "$AUTH_TOKEN" ]; then
|
|
434
439
|
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
440
|
fi
|
|
436
|
-
WORKING_MEM=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
441
|
+
WORKING_MEM=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" -H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
437
442
|
"http://localhost:${PORT}/context/working-memory?prompt=compaction-recovery&limit=5" 2>/dev/null)
|
|
438
443
|
if [ -n "$WORKING_MEM" ]; then
|
|
439
444
|
CONTEXT=$(echo "$WORKING_MEM" | python3 -c "
|
|
@@ -472,7 +477,7 @@ if [ -f "$CONFIG_FILE" ] && command -v tmux >/dev/null 2>&1; then
|
|
|
472
477
|
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
478
|
fi
|
|
474
479
|
curl -s -m 2 -X POST \
|
|
475
|
-
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
480
|
+
-H "Authorization: Bearer ${AUTH_TOKEN}" -H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
476
481
|
-H "Content-Type: application/json" \
|
|
477
482
|
-d "{\"sessionName\":\"${TMUX_SESSION}\"}" \
|
|
478
483
|
"http://localhost:${PORT}/internal/compaction-resume" >/dev/null 2>&1 &
|
|
@@ -34,10 +34,15 @@ AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
|
34
34
|
if [ -z "$AUTH_TOKEN" ]; then
|
|
35
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
36
|
fi
|
|
37
|
+
AGENT_ID="${INSTAR_AGENT_ID:-}"
|
|
38
|
+
if [ -z "$AGENT_ID" ]; then
|
|
39
|
+
AGENT_ID=$(python3 -c "import json; print(json.load(open('$CONFIG_FILE')).get('projectName',''))" 2>/dev/null)
|
|
40
|
+
fi
|
|
37
41
|
|
|
38
42
|
# Check if server is alive
|
|
39
43
|
HEALTH=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
40
44
|
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
45
|
+
-H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
41
46
|
"http://localhost:${PORT}/health" 2>/dev/null)
|
|
42
47
|
if [ "$HEALTH" != "200" ]; then
|
|
43
48
|
exit 0
|
|
@@ -50,15 +55,17 @@ curl -s -X POST "http://localhost:${PORT}/scope-coherence/reset" -o /dev/null 2>
|
|
|
50
55
|
# Record session start for reflection metrics (usage-based reflection trigger)
|
|
51
56
|
curl -s -X POST "http://localhost:${PORT}/reflection/session-start" \
|
|
52
57
|
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
58
|
+
-H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
53
59
|
-H "Content-Type: application/json" -o /dev/null 2>/dev/null || true
|
|
54
60
|
|
|
55
61
|
# Reset homeostasis state for new session (work-velocity awareness)
|
|
56
62
|
curl -s -X POST "http://localhost:${PORT}/homeostasis/reset" \
|
|
57
63
|
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
64
|
+
-H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
58
65
|
-H "Content-Type: application/json" -o /dev/null 2>/dev/null || true
|
|
59
66
|
|
|
60
67
|
# Check reflection metrics — usage-based reflection suggestion
|
|
61
|
-
REFLECTION_CHECK=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
68
|
+
REFLECTION_CHECK=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" -H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
62
69
|
"http://localhost:${PORT}/reflection/metrics" 2>/dev/null)
|
|
63
70
|
if [ -n "$REFLECTION_CHECK" ]; then
|
|
64
71
|
SUGGESTED=$(echo "$REFLECTION_CHECK" | python3 -c "import sys,json; print(json.load(sys.stdin).get('suggested',False))" 2>/dev/null)
|
|
@@ -166,7 +173,7 @@ if [ -n "$JOB_SLUG" ]; then
|
|
|
166
173
|
QUERY_URL="${QUERY_URL}&jobSlug=${JOB_SLUG_ENCODED}"
|
|
167
174
|
fi
|
|
168
175
|
|
|
169
|
-
WORKING_MEM=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" "$QUERY_URL" 2>/dev/null)
|
|
176
|
+
WORKING_MEM=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" -H "X-Instar-AgentId: ${AGENT_ID}" "$QUERY_URL" 2>/dev/null)
|
|
170
177
|
|
|
171
178
|
if [ -z "$WORKING_MEM" ]; then
|
|
172
179
|
exit 0
|
|
@@ -199,7 +206,7 @@ except Exception:
|
|
|
199
206
|
# Active commitments injection (PROMISE-BEACON-SPEC Round 3 #7).
|
|
200
207
|
# Surfaces beacon-watched pending commitments so the agent can self-regulate
|
|
201
208
|
# pacing across compaction. Capped server-side at 20 entries.
|
|
202
|
-
ACTIVE_COMMITMENTS=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
209
|
+
ACTIVE_COMMITMENTS=$(curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" -H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
203
210
|
"http://localhost:${PORT}/commitments/active-context" 2>/dev/null)
|
|
204
211
|
if [ -n "$ACTIVE_COMMITMENTS" ]; then
|
|
205
212
|
python3 -c "
|
|
@@ -326,6 +333,7 @@ if [ -n "$PORT" ] && [ -n "$AUTH_TOKEN" ]; then
|
|
|
326
333
|
|
|
327
334
|
EVAL_RESULT=$(curl -s --max-time 6 -X POST \
|
|
328
335
|
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
336
|
+
-H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
329
337
|
-H "Content-Type: application/json" \
|
|
330
338
|
"http://localhost:${PORT}/features/evaluate-context" \
|
|
331
339
|
-d "{\"topicCategory\":\"${TOPIC_LABEL}\",\"conversationIntent\":\"${INTENT}\",\"problemCategories\":[],\"autonomyProfile\":\"collaborative\",\"enabledFeatures\":[]}" \
|
|
@@ -23,6 +23,7 @@ fi
|
|
|
23
23
|
# Get port and auth from config
|
|
24
24
|
PORT="${INSTAR_PORT:-}"
|
|
25
25
|
AUTH=""
|
|
26
|
+
AGENT_ID="${INSTAR_AGENT_ID:-}"
|
|
26
27
|
|
|
27
28
|
if [ -f ".instar/config.json" ]; then
|
|
28
29
|
if [ -z "$PORT" ]; then
|
|
@@ -37,6 +38,9 @@ if [ -f ".instar/config.json" ]; then
|
|
|
37
38
|
if [ -z "$AUTH" ]; then
|
|
38
39
|
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
40
|
fi
|
|
41
|
+
if [ -z "$AGENT_ID" ]; then
|
|
42
|
+
AGENT_ID=$(python3 -c "import json; print(json.load(open('.instar/config.json')).get('projectName',''))" 2>/dev/null)
|
|
43
|
+
fi
|
|
40
44
|
fi
|
|
41
45
|
|
|
42
46
|
PORT="${PORT:-4042}"
|
|
@@ -49,6 +53,7 @@ fi
|
|
|
49
53
|
# Fetch channel history from ring buffer cache
|
|
50
54
|
MESSAGES=$(curl -sf \
|
|
51
55
|
${AUTH:+-H "Authorization: Bearer $AUTH"} \
|
|
56
|
+
${AGENT_ID:+-H "X-Instar-AgentId: $AGENT_ID"} \
|
|
52
57
|
"http://localhost:${PORT}/slack/channels/${CHANNEL_ID}/messages?limit=30" 2>/dev/null) || exit 0
|
|
53
58
|
|
|
54
59
|
# Format thread history for session context
|
|
@@ -66,11 +66,16 @@ AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
|
66
66
|
if [ -z "$AUTH_TOKEN" ] && [ -f "$CONFIG_FILE" ]; then
|
|
67
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
68
|
fi
|
|
69
|
+
AGENT_ID="${INSTAR_AGENT_ID:-}"
|
|
70
|
+
if [ -z "$AGENT_ID" ] && [ -f "$CONFIG_FILE" ]; then
|
|
71
|
+
AGENT_ID=$(python3 -c "import json; print(json.load(open('$CONFIG_FILE')).get('projectName',''))" 2>/dev/null)
|
|
72
|
+
fi
|
|
69
73
|
|
|
70
74
|
# Fetch recent messages for this topic
|
|
71
75
|
if [ -n "$AUTH_TOKEN" ]; then
|
|
72
76
|
RECENT_MSGS=$(curl -s \
|
|
73
77
|
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
78
|
+
-H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
74
79
|
"http://localhost:${PORT}/telegram/topics/${TOPIC_ID}/messages?limit=30" 2>/dev/null)
|
|
75
80
|
else
|
|
76
81
|
RECENT_MSGS=$(curl -s \
|
|
@@ -85,6 +90,7 @@ TOPIC_BRIEFING=""
|
|
|
85
90
|
if [ -n "$AUTH_TOKEN" ]; then
|
|
86
91
|
TOPIC_BRIEFING=$(curl -s --max-time 2 \
|
|
87
92
|
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
93
|
+
-H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
88
94
|
"http://localhost:${PORT}/topic-intent/${TOPIC_ID}/briefing" 2>/dev/null)
|
|
89
95
|
else
|
|
90
96
|
TOPIC_BRIEFING=$(curl -s --max-time 2 \
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# computed) values. The caller (autonomous-stop-hook) has already resolved
|
|
14
14
|
# the record + computed elapsed/remaining, so there is NO re-resolution —
|
|
15
15
|
# the injected clock can never disagree with the hook's expiry verdict.
|
|
16
|
-
# query <topic> <port> <auth>
|
|
16
|
+
# query <topic> <port> <auth> [agent-id]
|
|
17
17
|
# Curls GET /session/clock?topic=<topic> and prints the SESSION CLOCK line
|
|
18
18
|
# for the first active session (or nothing if none / server unreachable).
|
|
19
19
|
|
|
@@ -42,11 +42,11 @@ case "$MODE" in
|
|
|
42
42
|
render_line "${1:-}" "${2:-}" "${3:-0}" "${4:-}" "${5:-}"
|
|
43
43
|
;;
|
|
44
44
|
query)
|
|
45
|
-
TOPIC="${1:-}"; PORT="${2:-}"; AUTH="${3:-}"
|
|
45
|
+
TOPIC="${1:-}"; PORT="${2:-}"; AUTH="${3:-}"; AGENT_ID="${4:-${INSTAR_AGENT_ID:-}}"
|
|
46
46
|
[ -z "$PORT" ] && exit 0
|
|
47
47
|
URL="http://localhost:${PORT}/session/clock"
|
|
48
48
|
[ -n "$TOPIC" ] && URL="${URL}?topic=${TOPIC}"
|
|
49
|
-
RESP=$(curl -s --max-time 3 -H "Authorization: Bearer ${AUTH}" "$URL" 2>/dev/null)
|
|
49
|
+
RESP=$(curl -s --max-time 3 -H "Authorization: Bearer ${AUTH}" -H "X-Instar-AgentId: ${AGENT_ID}" "$URL" 2>/dev/null)
|
|
50
50
|
[ -z "$RESP" ] && exit 0
|
|
51
51
|
printf '%s' "$RESP" | python3 -c "
|
|
52
52
|
import sys, json
|
|
@@ -47,9 +47,13 @@ PORT="${INSTAR_PORT:-4042}"
|
|
|
47
47
|
# string-type guard so the { "secret": true } placeholder produced by
|
|
48
48
|
# SecretMigrator cannot leak through as a bogus Bearer.
|
|
49
49
|
AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
50
|
+
AGENT_ID="${INSTAR_AGENT_ID:-}"
|
|
50
51
|
if [ -z "$AUTH_TOKEN" ] && [ -f ".instar/config.json" ]; then
|
|
51
52
|
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)
|
|
52
53
|
fi
|
|
54
|
+
if [ -z "$AGENT_ID" ] && [ -f ".instar/config.json" ]; then
|
|
55
|
+
AGENT_ID=$(python3 -c "import json; print(json.load(open('.instar/config.json')).get('projectName',''))" 2>/dev/null)
|
|
56
|
+
fi
|
|
53
57
|
|
|
54
58
|
# Escape message for JSON
|
|
55
59
|
JSON_MSG=$(printf '%s' "$MSG" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))' 2>/dev/null)
|
|
@@ -67,12 +71,17 @@ AUTH_HEADER=""
|
|
|
67
71
|
if [ -n "$AUTH_TOKEN" ]; then
|
|
68
72
|
AUTH_HEADER="Authorization: Bearer ${AUTH_TOKEN}"
|
|
69
73
|
fi
|
|
74
|
+
AGENT_HEADER=""
|
|
75
|
+
if [ -n "$AGENT_ID" ]; then
|
|
76
|
+
AGENT_HEADER="X-Instar-AgentId: ${AGENT_ID}"
|
|
77
|
+
fi
|
|
70
78
|
|
|
71
79
|
# ── Step 1: Validate with server BEFORE sending (get single-use token) ──
|
|
72
80
|
|
|
73
81
|
VALIDATE_RESPONSE=$(curl -s -w "\n%{http_code}" \
|
|
74
82
|
-X POST "http://localhost:${PORT}/imessage/validate-send/${ENCODED_RECIPIENT}" \
|
|
75
83
|
${AUTH_HEADER:+-H "$AUTH_HEADER"} \
|
|
84
|
+
${AGENT_HEADER:+-H "$AGENT_HEADER"} \
|
|
76
85
|
-H 'Content-Type: application/json' \
|
|
77
86
|
-d "{\"text\":${JSON_MSG}}" 2>/dev/null)
|
|
78
87
|
|
|
@@ -140,6 +149,7 @@ fi
|
|
|
140
149
|
|
|
141
150
|
curl -s -o /dev/null -w "" -X POST "http://localhost:${PORT}/imessage/reply/${ENCODED_RECIPIENT}" \
|
|
142
151
|
${AUTH_HEADER:+-H "$AUTH_HEADER"} \
|
|
152
|
+
${AGENT_HEADER:+-H "$AGENT_HEADER"} \
|
|
143
153
|
-H 'Content-Type: application/json' \
|
|
144
154
|
-d "{\"text\":${JSON_MSG},\"sendToken\":\"${SEND_TOKEN}\"}" 2>/dev/null || \
|
|
145
155
|
echo "Warning: server confirmation failed (message was sent)" >&2
|
|
@@ -328,9 +328,11 @@ escalate_via_peer() {
|
|
|
328
328
|
# placeholder that SecretMigrator writes after externalizing the auth token:
|
|
329
329
|
# `c.authToken || ''` would otherwise return the object itself (truthy)
|
|
330
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)
|
|
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+'\t'+(c.projectName||''))" "$peer_dir/.instar/config.json" 2>/dev/null || true)
|
|
332
332
|
peer_port="${peer_meta%% *}"
|
|
333
|
-
|
|
333
|
+
peer_rest="${peer_meta#* }"
|
|
334
|
+
peer_auth="${peer_rest%% *}"
|
|
335
|
+
peer_agent_id="${peer_rest#* }"
|
|
334
336
|
[ -z "$peer_port" ] && continue
|
|
335
337
|
|
|
336
338
|
health_code=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:${peer_port}/health" 2>/dev/null || echo "000")
|
|
@@ -356,6 +358,7 @@ JSONEOF
|
|
|
356
358
|
resp_code=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
357
359
|
-X POST "http://localhost:${peer_port}/attention" \
|
|
358
360
|
-H "Authorization: Bearer $peer_auth" \
|
|
361
|
+
-H "X-Instar-AgentId: $peer_agent_id" \
|
|
359
362
|
-H "Content-Type: application/json" \
|
|
360
363
|
-H "X-Instar-Request: 1" \
|
|
361
364
|
-d "$payload" 2>/dev/null || echo "000")
|
|
@@ -385,6 +388,7 @@ JSONEOF
|
|
|
385
388
|
resp_code=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
386
389
|
-X POST "http://localhost:${peer_port}/attention" \
|
|
387
390
|
-H "Authorization: Bearer $peer_auth" \
|
|
391
|
+
-H "X-Instar-AgentId: $peer_agent_id" \
|
|
388
392
|
-H "Content-Type: application/json" \
|
|
389
393
|
-H "X-Instar-Request: 1" \
|
|
390
394
|
-d "$safe_payload" 2>/dev/null || echo "000")
|
|
@@ -434,7 +438,7 @@ probe_server_identity() {
|
|
|
434
438
|
local config_file="$project_dir/.instar/config.json"
|
|
435
439
|
[ ! -r "$config_file" ] && return 0
|
|
436
440
|
|
|
437
|
-
local node_bin port auth_token
|
|
441
|
+
local node_bin port auth_token agent_id
|
|
438
442
|
node_bin=$(resolve_node || true)
|
|
439
443
|
[ -z "$node_bin" ] && return 0
|
|
440
444
|
|
|
@@ -447,9 +451,11 @@ probe_server_identity() {
|
|
|
447
451
|
# auth token — `String(c.authToken || '')` would otherwise yield
|
|
448
452
|
# "[object Object]" and the Bearer would be invalid.
|
|
449
453
|
local meta
|
|
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)
|
|
454
|
+
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+'\t'+(c.projectName||''))" "$config_file" 2>/dev/null || true)
|
|
451
455
|
port="${meta%% *}"
|
|
452
|
-
|
|
456
|
+
rest="${meta#* }"
|
|
457
|
+
auth_token="${rest%% *}"
|
|
458
|
+
agent_id="${rest#* }"
|
|
453
459
|
# Lifeline-only agents have no port; treat as healthy from probe POV.
|
|
454
460
|
[ -z "$port" ] && return 0
|
|
455
461
|
|
|
@@ -460,7 +466,7 @@ probe_server_identity() {
|
|
|
460
466
|
local resp http_code body project_field auth_args
|
|
461
467
|
auth_args=()
|
|
462
468
|
if [ -n "$auth_token" ]; then
|
|
463
|
-
auth_args=(-H "Authorization: Bearer $auth_token")
|
|
469
|
+
auth_args=(-H "Authorization: Bearer $auth_token" -H "X-Instar-AgentId: $agent_id")
|
|
464
470
|
fi
|
|
465
471
|
resp=$(curl -sS --max-time 5 -w '\n%{http_code}' "${auth_args[@]}" "http://localhost:${port}/health" 2>/dev/null || echo $'\n000')
|
|
466
472
|
http_code=$(echo "$resp" | tail -n1)
|
|
@@ -81,10 +81,12 @@ if (runMode && runCmd.length === 0) {
|
|
|
81
81
|
// guard so the { "secret": true } placeholder produced by SecretMigrator
|
|
82
82
|
// cannot leak through as a bogus Bearer.
|
|
83
83
|
let authToken = process.env.INSTAR_AUTH_TOKEN || '';
|
|
84
|
+
let agentId = process.env.INSTAR_AGENT_ID || '';
|
|
84
85
|
let port;
|
|
85
86
|
try {
|
|
86
87
|
const config = JSON.parse(fs.readFileSync('.instar/config.json', 'utf-8'));
|
|
87
88
|
if (!authToken && typeof config.authToken === 'string') authToken = config.authToken;
|
|
89
|
+
if (!agentId && typeof config.projectName === 'string') agentId = config.projectName;
|
|
88
90
|
port = config.port;
|
|
89
91
|
} catch (e) {
|
|
90
92
|
if (!authToken) {
|
|
@@ -104,7 +106,10 @@ if (!resolvedPort) {
|
|
|
104
106
|
const url = `http://localhost:${resolvedPort}/secrets/retrieve/${token}${consume ? '?consume=true' : ''}`;
|
|
105
107
|
const res = await fetch(url, {
|
|
106
108
|
method: 'POST',
|
|
107
|
-
headers: {
|
|
109
|
+
headers: {
|
|
110
|
+
'Authorization': `Bearer ${authToken}`,
|
|
111
|
+
...(agentId ? { 'X-Instar-AgentId': agentId } : {}),
|
|
112
|
+
},
|
|
108
113
|
});
|
|
109
114
|
|
|
110
115
|
if (!res.ok) {
|
|
@@ -160,7 +165,10 @@ async function consumeSubmission() {
|
|
|
160
165
|
try {
|
|
161
166
|
await fetch(`http://localhost:${resolvedPort}/secrets/retrieve/${token}?consume=true`, {
|
|
162
167
|
method: 'POST',
|
|
163
|
-
headers: {
|
|
168
|
+
headers: {
|
|
169
|
+
'Authorization': `Bearer ${authToken}`,
|
|
170
|
+
...(agentId ? { 'X-Instar-AgentId': agentId } : {}),
|
|
171
|
+
},
|
|
164
172
|
});
|
|
165
173
|
} catch {
|
|
166
174
|
// Non-fatal — the sliding/absolute-cap cleanup will reclaim it regardless.
|
|
@@ -38,6 +38,7 @@ fi
|
|
|
38
38
|
# Get port from env or config
|
|
39
39
|
PORT="${INSTAR_PORT:-}"
|
|
40
40
|
AUTH=""
|
|
41
|
+
AGENT_ID="${INSTAR_AGENT_ID:-}"
|
|
41
42
|
|
|
42
43
|
if [ -f ".instar/config.json" ]; then
|
|
43
44
|
if [ -z "$PORT" ]; then
|
|
@@ -52,6 +53,9 @@ if [ -f ".instar/config.json" ]; then
|
|
|
52
53
|
if [ -z "$AUTH" ]; then
|
|
53
54
|
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
55
|
fi
|
|
56
|
+
if [ -z "$AGENT_ID" ]; then
|
|
57
|
+
AGENT_ID=$(python3 -c "import json; print(json.load(open('.instar/config.json')).get('projectName',''))" 2>/dev/null)
|
|
58
|
+
fi
|
|
55
59
|
fi
|
|
56
60
|
|
|
57
61
|
PORT="${PORT:-4042}"
|
|
@@ -68,6 +72,7 @@ RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \
|
|
|
68
72
|
"http://localhost:${PORT}/slack/reply/${CHANNEL_ID}" \
|
|
69
73
|
-H "Content-Type: application/json" \
|
|
70
74
|
${AUTH:+-H "Authorization: Bearer $AUTH"} \
|
|
75
|
+
${AGENT_ID:+-H "X-Instar-AgentId: $AGENT_ID"} \
|
|
71
76
|
-d "{\"text\": ${ESCAPED}}")
|
|
72
77
|
|
|
73
78
|
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
|
|
@@ -38,9 +38,13 @@ PORT="${INSTAR_PORT:-4040}"
|
|
|
38
38
|
# string-type guard so the { "secret": true } placeholder produced by
|
|
39
39
|
# SecretMigrator cannot leak through as a bogus Bearer.
|
|
40
40
|
AUTH_TOKEN="${INSTAR_AUTH_TOKEN:-}"
|
|
41
|
+
AGENT_ID="${INSTAR_AGENT_ID:-}"
|
|
41
42
|
if [ -z "$AUTH_TOKEN" ] && [ -f ".instar/config.json" ]; then
|
|
42
43
|
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)
|
|
43
44
|
fi
|
|
45
|
+
if [ -z "$AGENT_ID" ] && [ -f ".instar/config.json" ]; then
|
|
46
|
+
AGENT_ID=$(python3 -c "import json; print(json.load(open('.instar/config.json')).get('projectName',''))" 2>/dev/null)
|
|
47
|
+
fi
|
|
44
48
|
|
|
45
49
|
# Escape for JSON
|
|
46
50
|
JSON_MSG=$(printf '%s' "$MSG" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))' 2>/dev/null)
|
|
@@ -53,6 +57,7 @@ if [ -n "$AUTH_TOKEN" ]; then
|
|
|
53
57
|
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "http://localhost:${PORT}/whatsapp/send/${JID}" \
|
|
54
58
|
-H 'Content-Type: application/json' \
|
|
55
59
|
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
|
60
|
+
-H "X-Instar-AgentId: ${AGENT_ID}" \
|
|
56
61
|
-d "{\"text\":${JSON_MSG}}")
|
|
57
62
|
else
|
|
58
63
|
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "http://localhost:${PORT}/whatsapp/send/${JID}" \
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
Built-in job, hook, and helper-script templates now include the agent identity header on authenticated local API calls. The scheduler and session launcher expose `INSTAR_AGENT_ID` alongside the existing local auth token so installed templates do not need to guess their identity.
|
|
9
|
+
|
|
10
|
+
## What to Tell Your User
|
|
11
|
+
|
|
12
|
+
Nothing user-visible. This quiets internal auth deprecation warnings from built-in jobs and hooks and keeps installed templates aligned with the stricter local auth contract.
|
|
13
|
+
|
|
14
|
+
## Summary of New Capabilities
|
|
15
|
+
|
|
16
|
+
- Job gates, script jobs, and spawned sessions receive `INSTAR_AGENT_ID`.
|
|
17
|
+
- Built-in local API templates send `X-Instar-AgentId` with bearer auth.
|
|
18
|
+
- A regression test scans shipped templates for bearer-only local API calls.
|
|
19
|
+
|
|
20
|
+
## Evidence
|
|
21
|
+
|
|
22
|
+
Grounded against canonical `authMiddleware`: bearer-only local API calls are still accepted during the deprecation window but log a warning; `/whoami` already requires the header. Focused validation: `npx vitest run tests/unit/template-agent-id-header.test.ts tests/unit/JobScheduler.test.ts tests/unit/JobScheduler-script-job.test.ts tests/unit/telegram-topic-context-session-clock.test.ts` passed, 41/41 tests.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Side-Effects Review — Template Agent-ID Header
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `template-agent-id-header`
|
|
4
|
+
**Date:** `2026-06-05`
|
|
5
|
+
**Author:** `instar-codey`
|
|
6
|
+
**Second-pass reviewer:** `not required`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
This change updates the fleet-installed local API client surface so bearer-authenticated template calls also send `X-Instar-AgentId`. It adds `INSTAR_AGENT_ID` env propagation from `Config` -> `JobScheduler` and `SessionManager`, updates built-in job templates, hook/script templates, and selected migrator inline hook content, and adds a template scanner regression test.
|
|
11
|
+
|
|
12
|
+
## Decision-point inventory
|
|
13
|
+
|
|
14
|
+
No new decision point is added. Existing server auth remains the authority for missing/mismatched agent-id headers. This change only updates clients/templates to provide identity to that existing authority.
|
|
15
|
+
|
|
16
|
+
## 1. Over-block
|
|
17
|
+
|
|
18
|
+
No block/allow surface is added. A malformed or missing `projectName` could make a template send an empty or wrong `X-Instar-AgentId`, which the existing server auth would reject. The normal paths use `config.projectName`, and direct-run fallbacks read the same field.
|
|
19
|
+
|
|
20
|
+
## 2. Under-block
|
|
21
|
+
|
|
22
|
+
This does not remove the server's bearer-only compatibility window. A custom user-authored curl outside shipped templates can still be bearer-only and receive the deprecation warning until the server policy changes.
|
|
23
|
+
|
|
24
|
+
## 3. Level-of-abstraction fit
|
|
25
|
+
|
|
26
|
+
The fix sits at the client/template layer. The server already owns auth authority and should not be weakened to hide template warnings. Scheduler/session env propagation is the right shared primitive for jobs and hooks.
|
|
27
|
+
|
|
28
|
+
## 4. Signal vs authority compliance
|
|
29
|
+
|
|
30
|
+
Required reference: `docs/signal-vs-authority.md`
|
|
31
|
+
|
|
32
|
+
No brittle blocking authority is introduced. The change feeds identity into the existing deterministic auth authority; it does not add a new detector or gate.
|
|
33
|
+
|
|
34
|
+
## 5. Interactions
|
|
35
|
+
|
|
36
|
+
The scheduler now injects `INSTAR_AGENT_ID` alongside `INSTAR_AUTH_TOKEN` for gate and script job shells. `SessionManager` injects the same variable for spawned sessions, so hook and prompt-job examples have it. Fleet watchdog peer requests read the peer project name and bind the peer token to the peer identity.
|
|
37
|
+
|
|
38
|
+
## 6. External surfaces
|
|
39
|
+
|
|
40
|
+
Installed agents get quieter logs and future-compatible local API calls after template refresh/migration. No public API response shapes change. No persistent state is written.
|
|
41
|
+
|
|
42
|
+
## 7. Rollback cost
|
|
43
|
+
|
|
44
|
+
Rollback is a source/template revert and patch release. Existing agents would fall back to the current accepted-but-deprecated bearer-only behavior until a corrected template ships.
|
|
45
|
+
|
|
46
|
+
## Conclusion
|
|
47
|
+
|
|
48
|
+
Clear to ship as Tier 1. The change aligns installed templates with the existing auth contract and pins the class with a scanner test.
|