instar 1.3.769 → 1.3.771
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/server.d.ts.map +1 -1
- package/dist/commands/server.js +18 -0
- package/dist/commands/server.js.map +1 -1
- package/dist/core/IntelligenceRouter.d.ts +23 -0
- package/dist/core/IntelligenceRouter.d.ts.map +1 -1
- package/dist/core/IntelligenceRouter.js +67 -1
- package/dist/core/IntelligenceRouter.js.map +1 -1
- package/dist/core/slackRefreshBinding.d.ts +20 -0
- package/dist/core/slackRefreshBinding.d.ts.map +1 -1
- package/dist/core/slackRefreshBinding.js +31 -0
- package/dist/core/slackRefreshBinding.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.3.770.md +40 -0
- package/upgrades/1.3.771.md +53 -0
- package/upgrades/la4-degrade-clamp-a1.eli16.md +42 -0
- package/upgrades/side-effects/la4-degrade-clamp-a1.md +77 -0
- package/upgrades/side-effects/slack-respawn-bind-token.eli16.md +46 -0
- package/upgrades/side-effects/slack-respawn-bind-token.md +121 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Side-Effects Review — Slack session respawn re-mints the conversation bind token
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `slack-respawn-bind-token`
|
|
4
|
+
**Date:** `2026-07-04`
|
|
5
|
+
**Author:** `Echo`
|
|
6
|
+
**Second-pass reviewer:** `not required (Tier-1)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
A FRESH Slack channel spawn passes `bootstrapConversationIds: [conversationId]` to
|
|
11
|
+
`spawnInteractiveSession`, so the session mints `INSTAR_BIND_TOKEN` + `INSTAR_CONVERSATION_ID`
|
|
12
|
+
(durable-conversation-identity §7) and can open durable state — a commitment bound to its minted
|
|
13
|
+
(negative) conversation id. The Slack session **respawn** closure (`slackRespawner` in
|
|
14
|
+
`src/commands/server.ts`, used by `/sessions/refresh`, quota-swap, restart, and restart-all — all
|
|
15
|
+
funnel through `SessionRefresh` → `slackRespawner`) **omitted** `bootstrapConversationIds`. So a
|
|
16
|
+
refreshed/quota-swapped Slack session came up **token-less** (and without `INSTAR_CONVERSATION_ID`),
|
|
17
|
+
its durable commitment binds were **refused fail-closed**, and the follow-through fell back to a
|
|
18
|
+
fragile session-local timer that dies on the next restart. This is the live-proven S7 gap (Round-1 of
|
|
19
|
+
the 2026-07-04 test-as-self proof: an already-running/refreshed Slack session couldn't register a
|
|
20
|
+
durable commitment; a fresh spawn — Round-2 — could, registering `CMT-1922` bound to `-1734007126`).
|
|
21
|
+
Telegram's respawn is unaffected because it passes `telegramTopicId`, which the bind-token env
|
|
22
|
+
resolver uses as a fallback; Slack has no such fallback. Fix: the respawn closure resolves the
|
|
23
|
+
conversation id from the routing key (`conversationRegistry.mintForInbound(routingKey).id`, idempotent
|
|
24
|
+
get-or-create → the SAME id the fresh dispatch resolves) via a new unit-tested helper
|
|
25
|
+
`slackRespawnBootstrapIds` and passes it as `bootstrapConversationIds` — restoring parity with the
|
|
26
|
+
fresh spawn. Files: `src/commands/server.ts` (closure + import), `src/core/slackRefreshBinding.ts`
|
|
27
|
+
(helper), + test.
|
|
28
|
+
|
|
29
|
+
## Decision-point inventory
|
|
30
|
+
|
|
31
|
+
- `slackRespawner` closure spawn options (`src/commands/server.ts`) — **modify** — now passes
|
|
32
|
+
`bootstrapConversationIds` resolved from the routing key.
|
|
33
|
+
- `slackRespawnBootstrapIds` (`src/core/slackRefreshBinding.ts`) — **add** — the pure, tested resolver.
|
|
34
|
+
|
|
35
|
+
## 1. Over-block / 2. Under-block
|
|
36
|
+
|
|
37
|
+
No block/allow surface. This RESTORES a capability (durable bind on a respawned Slack session) that was
|
|
38
|
+
mistakenly dropped. Over/under-block not applicable.
|
|
39
|
+
|
|
40
|
+
## 3. Level-of-abstraction fit
|
|
41
|
+
|
|
42
|
+
Right layer — the fix is a one-option addition at the respawn spawn site, mirroring the fresh-spawn
|
|
43
|
+
site exactly; the resolution is a tiny pure helper in the existing `slackRefreshBinding` module. No new
|
|
44
|
+
machinery, no new authority.
|
|
45
|
+
|
|
46
|
+
## 4. Signal vs authority compliance
|
|
47
|
+
|
|
48
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
49
|
+
|
|
50
|
+
- [x] No — no runtime block/allow surface. The bind token it restores is enforced by the EXISTING §7
|
|
51
|
+
`conversationBindGate` (unchanged); this change only ensures the legitimately-authorized session
|
|
52
|
+
actually receives its own token on respawn.
|
|
53
|
+
|
|
54
|
+
## 5. Interactions
|
|
55
|
+
|
|
56
|
+
- **Shadowing:** none — additive spawn option, mirroring the fresh path.
|
|
57
|
+
- **Double-fire:** none. `mintForInbound` is idempotent (get-or-create), so re-resolving on respawn
|
|
58
|
+
returns the same id the fresh dispatch used; no duplicate conversation is minted.
|
|
59
|
+
- **Races:** none new — the respawn already spawned a session; this only adds one option to that call.
|
|
60
|
+
- **Feedback loops:** none.
|
|
61
|
+
- **Fail posture:** `slackRespawnBootstrapIds` FAILS TOWARD RESPAWN — any resolution error → `undefined`
|
|
62
|
+
(the prior token-less behavior), never throws, so a refresh can never be blocked by id resolution.
|
|
63
|
+
|
|
64
|
+
## 6. External surfaces
|
|
65
|
+
|
|
66
|
+
- **Install base / agents:** ships with the server; a refreshed Slack session now carries its bind
|
|
67
|
+
token. No config migration. No behavior change for a session that already had the token (fresh
|
|
68
|
+
spawns) or for Telegram (unaffected — separate fallback).
|
|
69
|
+
- **External systems:** Slack unchanged (same channel session, same delivery). No new API.
|
|
70
|
+
- **Persistent state:** none — `INSTAR_BIND_TOKEN` lives only in the tmux `-e` env at spawn (stateless,
|
|
71
|
+
self-authenticating). This change sets it correctly on respawn; nothing is persisted.
|
|
72
|
+
|
|
73
|
+
## 6b. Operator-surface quality
|
|
74
|
+
|
|
75
|
+
No operator surface — not applicable.
|
|
76
|
+
|
|
77
|
+
## 7. Multi-machine posture (Cross-Machine Coherence)
|
|
78
|
+
|
|
79
|
+
**machine-local BY DESIGN** — `machine-local-justification: physical-credential-locality`. A Slack
|
|
80
|
+
session is a tmux process on the machine that owns the Slack connection; its bind token is minted into
|
|
81
|
+
that process's env at spawn on that machine (the token is a per-session, per-machine credential — the
|
|
82
|
+
§7 secret is machine-local plaintext, same posture as authToken). The respawn happens on the owning
|
|
83
|
+
machine. There is no cross-machine state, notice, durable record, or URL introduced; the fix only
|
|
84
|
+
corrects a spawn-option omission on the local respawn path.
|
|
85
|
+
|
|
86
|
+
## 8. Rollback cost
|
|
87
|
+
|
|
88
|
+
Pure code change — revert the closure option, the helper, the import, and the test. No persistent
|
|
89
|
+
state; a rollback returns to the (buggy) token-less respawn. Zero-cost back-out.
|
|
90
|
+
|
|
91
|
+
## Conclusion
|
|
92
|
+
|
|
93
|
+
Closes the final live-proven S7 gap: a refreshed/quota-swapped Slack session now re-mints its
|
|
94
|
+
conversation bind token, so durable, restart-surviving follow-through works even after a session
|
|
95
|
+
churn — matching the fresh-spawn path that the 2026-07-04 test-as-self proof showed already works.
|
|
96
|
+
Minimal, parity-restoring, fail-open, unit-tested. Clear to ship.
|
|
97
|
+
|
|
98
|
+
## Second-pass review (if required)
|
|
99
|
+
|
|
100
|
+
**Reviewer:** not required (Tier-1)
|
|
101
|
+
|
|
102
|
+
## Evidence pointers
|
|
103
|
+
|
|
104
|
+
- `tests/unit/slack-respawn-bootstrap-ids.test.ts` — 4 cases: resolves id → `[id]`, passes the full
|
|
105
|
+
`channel:thread` routing key, `null` id → `undefined`, throwing registry → `undefined` (fails toward
|
|
106
|
+
respawn).
|
|
107
|
+
- Existing `tests/unit/sessionRefresh-slack.test.ts` (22) stay green; `tsc` clean.
|
|
108
|
+
- Live proof: `docs/investigations/s7-slack-delivery-repro-2026-07-04.md` §9 (Round-1 refused vs
|
|
109
|
+
Round-2 durable `CMT-1922`).
|
|
110
|
+
|
|
111
|
+
## Class-Closure Declaration (display-only mirror)
|
|
112
|
+
|
|
113
|
+
- **`defectClass`** — `spawn-option-asymmetry` (`novel`; nearestExistingClass: `feature-un-enablable`;
|
|
114
|
+
includes: a spawn/respawn path that omits an option the parallel fresh-spawn path passes, silently
|
|
115
|
+
degrading a capability; excludes: an intentionally-different respawn option). Enters
|
|
116
|
+
`status:"unconfirmed"`, so this fix carries `closure: gap`.
|
|
117
|
+
- **`closure`** — `gap` — a class-level guard (a lint/test asserting respawn spawn-option parity with
|
|
118
|
+
the fresh-spawn site) is out of scope for this fix.
|
|
119
|
+
- **`guardEvidence`** — n/a for `closure: gap`.
|
|
120
|
+
- **`gap`** — tracked follow-up: "respawn/fresh-spawn option-parity guard — assert the Slack (and other
|
|
121
|
+
platform) respawn paths pass the same identity/bind options as their fresh-spawn counterparts."
|