instar 1.3.175 → 1.3.177
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/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +31 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
- package/dist/messaging/TelegramAdapter.js +8 -1
- package/dist/messaging/TelegramAdapter.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +18 -18
- package/upgrades/1.3.176.md +97 -0
- package/upgrades/1.3.177.md +70 -0
- package/upgrades/side-effects/stop-gate-stated-continuation.md +41 -0
- package/upgrades/side-effects/tokenless-standby-relay-token-check.md +33 -0
- package/upgrades/1.3.175.md +0 -46
package/package.json
CHANGED
|
@@ -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-31T20:20:49.223Z",
|
|
5
|
+
"instarVersion": "1.3.177",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
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": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
141
141
|
"since": "2025-01-01"
|
|
142
142
|
},
|
|
143
143
|
"job:health-check": {
|
|
@@ -1489,7 +1489,7 @@
|
|
|
1489
1489
|
"type": "subsystem",
|
|
1490
1490
|
"domain": "updates",
|
|
1491
1491
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
1492
|
-
"contentHash": "
|
|
1492
|
+
"contentHash": "6785feccb0b5dab73704c9002fb025222445da09255a2d124978b6a395c65c3d",
|
|
1493
1493
|
"since": "2025-01-01"
|
|
1494
1494
|
},
|
|
1495
1495
|
"subsystem:scheduler": {
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
**The stop gate now catches the "I'll do it now" silent stall — even in shadow
|
|
9
|
+
mode.** A recurring failure: an agent's final message tells the user it is about
|
|
10
|
+
to act this turn ("I'll build that now", "starting now", "Next phase: ship the
|
|
11
|
+
fix") and then the turn simply ends, leaving the user staring at silence after
|
|
12
|
+
being told work was continuing.
|
|
13
|
+
|
|
14
|
+
The existing `stop-gate-router.js` hook delegated the continue/stop decision to
|
|
15
|
+
the server-side Unjustified Stop Gate, which only blocks in `enforce` mode — but
|
|
16
|
+
the gate ships in `shadow` (telemetry-only) mode on most agents, so the exact
|
|
17
|
+
moment a stall happened, nothing intervened.
|
|
18
|
+
|
|
19
|
+
This adds a small, always-on guard at the top of the hook. When the final message
|
|
20
|
+
states an imminent this-turn action together with an imminence marker (now / right
|
|
21
|
+
now / this turn / next phase / on it), the hook blocks once and re-feeds the
|
|
22
|
+
agent: either actually do the work, or send the user one honest sentence that it
|
|
23
|
+
is stopping and why. The guard is mode-independent (works even when the gate is in
|
|
24
|
+
shadow mode or the server is unreachable) and fires at most once — the existing
|
|
25
|
+
loop guard prevents any continuation trap. "Report-back-later" intent (no
|
|
26
|
+
imminence marker) is not caught; that stays with the commitment tracker.
|
|
27
|
+
|
|
28
|
+
The Framework-Onboarding Mentor System's "lessons for the next framework"
|
|
29
|
+
playbook now actually populates. Generalizable framework issues (the portable
|
|
30
|
+
lessons — `framework-limitation` and `instar-integration-gap`) are promoted from
|
|
31
|
+
`none` to `candidate` the moment they're terminally resolved (fixed or won't-fix),
|
|
32
|
+
which is the auto-suggestion step the spec (§13.6) defined but that had never been
|
|
33
|
+
implemented. A one-time, idempotent backfill on ledger startup seeds lessons that
|
|
34
|
+
were resolved before this existed. Without this, the onboarding playbook returned
|
|
35
|
+
an empty list even with a full ledger of hard-won lessons — they were logged but
|
|
36
|
+
never reached the next framework's onboarding.
|
|
37
|
+
|
|
38
|
+
The `candidate → extracted` step (canonizing a lesson into the reusable onboarding
|
|
39
|
+
checklist) is unchanged: it still requires a non-Echo attestation, so an agent
|
|
40
|
+
cannot canonize its own lessons.
|
|
41
|
+
|
|
42
|
+
## What to Tell Your User
|
|
43
|
+
|
|
44
|
+
Nothing to configure. Your agent can no longer tell you "I'll do that now" and
|
|
45
|
+
then quietly stop without doing it — if it tries, it gets nudged once to either
|
|
46
|
+
actually do the work or tell you plainly that it is stopping and why. The result
|
|
47
|
+
is fewer confusing silences after an agent says it is continuing.
|
|
48
|
+
|
|
49
|
+
Nothing required — this is internal mentor-system robustness. If asked: the
|
|
50
|
+
lessons learned onboarding one agent framework now actually carry forward to the
|
|
51
|
+
next one, instead of sitting unused in the ledger.
|
|
52
|
+
|
|
53
|
+
## Summary of New Capabilities
|
|
54
|
+
|
|
55
|
+
- Local, mode-independent stated-continuation guard in the stop-gate-router hook
|
|
56
|
+
(`PostUpdateMigrator.getStopGateRouterHook()`); deploys to every agent on update
|
|
57
|
+
via the always-overwrite built-in hook path.
|
|
58
|
+
|
|
59
|
+
- `GET /framework-issues/playbook?targetFramework=X` now returns the generalizable,
|
|
60
|
+
terminally-resolved lessons from prior frameworks (previously always empty because
|
|
61
|
+
nothing ever moved an issue off `playbook_status='none'`).
|
|
62
|
+
- `FrameworkIssueLedger.backfillPlaybookCandidates()` seeds pre-existing eligible
|
|
63
|
+
lessons; runs automatically and idempotently on ledger construction.
|
|
64
|
+
|
|
65
|
+
## Evidence
|
|
66
|
+
|
|
67
|
+
Reproduction (live, topic 13481, 2026-05-31): the agent posted "I'm going to
|
|
68
|
+
build that now ... then deploy and finish the round-trip proof" at 16:56 UTC,
|
|
69
|
+
then ended the turn and went silent for ~90 minutes without starting the work.
|
|
70
|
+
Operator response: "your session has stalled again ... this is incoherent."
|
|
71
|
+
|
|
72
|
+
Root cause observed: a direct probe of the running gate returned
|
|
73
|
+
GET /internal/stop-gate/hot-path -> {"mode":"shadow",...}. In shadow mode the
|
|
74
|
+
stop-gate-router records telemetry but never blocks, so the stall passed through
|
|
75
|
+
unchallenged — the safety net was off at the exact moment it was needed.
|
|
76
|
+
|
|
77
|
+
Before: rendering the prior hook and feeding it the exact stall message
|
|
78
|
+
("Next phase: build the reverse reply-relay, then ship the fix") exits 0 — the
|
|
79
|
+
agent is allowed to stop silently.
|
|
80
|
+
|
|
81
|
+
After: the same rendered hook fed the same message exits 2 and writes
|
|
82
|
+
{"decision":"block", reason:"STOP-GATE (stated-continuation): ..."}, regardless
|
|
83
|
+
of the server's shadow/enforce mode and even with no server reachable. A benign
|
|
84
|
+
completion ("Done — all tests passed ...") still exits 0, and stop_hook_active=true
|
|
85
|
+
exits 0 (loop guard intact). Confirmed by executing the rendered hook as a
|
|
86
|
+
subprocess against each payload (tests/unit/stop-gate-stated-continuation.test.ts,
|
|
87
|
+
5/5 green).
|
|
88
|
+
|
|
89
|
+
- Root cause: §13.6's `none→candidate` auto-suggestion was specified but never
|
|
90
|
+
implemented — the only writer of `candidate` was the manual promote route, so a
|
|
91
|
+
live ledger with 18 generalizable codex lessons (11 terminal) served `playbook: []`.
|
|
92
|
+
- Fix: deterministic auto-bump in `updateIssue` on terminal resolution + an
|
|
93
|
+
idempotent constructor backfill; the `candidate→extracted` non-Echo attestation
|
|
94
|
+
guard is untouched.
|
|
95
|
+
- Tests: +10 unit, +1 integration end-to-end; 192 ledger/mentor/route/E2E tests pass.
|
|
96
|
+
`npm run lint` clean.
|
|
97
|
+
- Spec: docs/specs/PLAYBOOK-CANDIDATE-AUTOSEED-SPEC.md (+ ELI16 companion).
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
**A conversation moved to a second machine can now reply to you.** When you move
|
|
9
|
+
a conversation to another machine (e.g. "move this to the Mac Mini"), that machine
|
|
10
|
+
serves the session but deliberately holds NO Telegram bot token — only one machine
|
|
11
|
+
may hold it, or Telegram throws a 409 poller conflict. The reply path already had
|
|
12
|
+
the fix for this: a tokenless standby relays its reply through the token-owning
|
|
13
|
+
machine (bug #7, `outboundRelay`).
|
|
14
|
+
|
|
15
|
+
But the "am I tokenless?" check was `!this.config.token`. On a standby the bot
|
|
16
|
+
token is *externalized* and arrives unresolved as a placeholder object
|
|
17
|
+
(`{ secret: true }`), not `null` — and an object is truthy, so the check concluded
|
|
18
|
+
"I have a token", skipped the relay, and attempted a doomed direct API call with
|
|
19
|
+
the placeholder. The moved session's reply returned 200 internally but never
|
|
20
|
+
reached Telegram.
|
|
21
|
+
|
|
22
|
+
The fix treats only a non-empty STRING as a usable bot token. The placeholder,
|
|
23
|
+
`null`, `undefined`, and `''` all now correctly mean "no usable token" → relay
|
|
24
|
+
through the token-owning machine. Token-holding machines (the normal case) are
|
|
25
|
+
completely unaffected — they still send directly.
|
|
26
|
+
|
|
27
|
+
## What to Tell Your User
|
|
28
|
+
|
|
29
|
+
Nothing to configure. If you run on more than one machine and move a conversation
|
|
30
|
+
to another one, that machine can now actually reply to you — previously a moved
|
|
31
|
+
session would go silent because its reply couldn't reach Telegram.
|
|
32
|
+
|
|
33
|
+
## Summary of New Capabilities
|
|
34
|
+
|
|
35
|
+
- `TelegramAdapter.sendToTopic` correctly detects a tokenless pool standby when
|
|
36
|
+
the bot token is an unresolved (non-string) externalized placeholder, and routes
|
|
37
|
+
the reply through `outboundRelay` instead of a doomed direct send.
|
|
38
|
+
|
|
39
|
+
## Evidence
|
|
40
|
+
|
|
41
|
+
**Reproduction (live, topic 8882, 2026-05-31 16:46 UTC):** POSTed a reply to the
|
|
42
|
+
Mac Mini standby's `/telegram/reply/8882`. Response was `{"ok":true}` (HTTP 200)
|
|
43
|
+
but the message never appeared in Telegram; the mini's `logs/server.log` showed NO
|
|
44
|
+
outbound-relay attempt and the laptop showed NO inbound relay. The mini's
|
|
45
|
+
`.instar/config.json` carried `botToken: { secret: true }` (externalized, never
|
|
46
|
+
resolved on the tokenless standby).
|
|
47
|
+
|
|
48
|
+
**Observed before/after (the relay decision, run in dev against the real
|
|
49
|
+
placeholder value):**
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
token value: {"secret":true}
|
|
53
|
+
BEFORE (!token): HAS-TOKEN -> direct API send (DOOMED: placeholder is not a real token)
|
|
54
|
+
AFTER (typeof string): TOKENLESS -> relay (FIXED)
|
|
55
|
+
real string AFTER: HAS-TOKEN -> direct API send (unchanged)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The truthy placeholder object flips the decision from "doomed direct send" to
|
|
59
|
+
"relay" — exactly the path the moved session needed. A real string token is
|
|
60
|
+
unchanged (still direct), so token-holding machines see no behavior change.
|
|
61
|
+
|
|
62
|
+
**Behavioral test:** `tests/unit/telegram-tokenless-relay.test.ts` constructs a
|
|
63
|
+
real `TelegramAdapter` with the `{ secret: true }` placeholder + spy `outboundRelay`
|
|
64
|
+
+ spy `fetch`, calls the REAL `sendToTopic`, and observes `outboundRelay` invoked
|
|
65
|
+
once with `fetch` never called (before this fix that path called `fetch` with the
|
|
66
|
+
bad token). 3/3 green.
|
|
67
|
+
|
|
68
|
+
**Live round-trip confirmation:** the full "move via Telegram → mini serves →
|
|
69
|
+
reply lands in 8882" round trip is confirmed against the deployed release on the
|
|
70
|
+
two-machine setup.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Side effects — stated-continuation stop guard
|
|
2
|
+
|
|
3
|
+
## What changes at runtime
|
|
4
|
+
|
|
5
|
+
The built-in `stop-gate-router.js` Stop hook gains a local, mode-independent
|
|
6
|
+
guard. On every Stop, if the agent's final message states an imminent this-turn
|
|
7
|
+
action ("I'll build X now", "starting now", "next phase: ...", "on it ... now")
|
|
8
|
+
the hook returns `{decision:'block'}` (exit 2) ONCE, re-feeding the agent to
|
|
9
|
+
either do the work or tell the user plainly it is stopping and why.
|
|
10
|
+
|
|
11
|
+
## Who is affected
|
|
12
|
+
|
|
13
|
+
- **Every Instar agent on update.** Built-in `instar/` hooks are always
|
|
14
|
+
overwritten on migration, so the guard deploys automatically — no opt-in,
|
|
15
|
+
no per-agent migration. New agents get it via `init`.
|
|
16
|
+
|
|
17
|
+
## Behavioral side effects (intended)
|
|
18
|
+
|
|
19
|
+
- An agent that ends a turn right after saying "I'll do X now" will be blocked
|
|
20
|
+
once and pushed to either act or send an explicit stop message. This is the
|
|
21
|
+
intended fix; it converts silent stalls into either real work or an honest
|
|
22
|
+
"I'm stopping because…" message.
|
|
23
|
+
- Borderline matches (e.g. a summary heading "Next phase: …") cost exactly one
|
|
24
|
+
extra nudge and force an explicit sign-off — acceptable and desirable.
|
|
25
|
+
|
|
26
|
+
## What is NOT affected
|
|
27
|
+
|
|
28
|
+
- The server-side Unjustified Stop Gate, its mode (shadow/enforce), its telemetry,
|
|
29
|
+
and its circuit breaker are all untouched.
|
|
30
|
+
- The autonomous-stop-hook and hook-event-reporter Stop hooks are untouched.
|
|
31
|
+
- The loop-prevention contract is preserved: the existing `stop_hook_active` guard
|
|
32
|
+
still short-circuits on the re-fire, so the guard fires at most once per stop —
|
|
33
|
+
no infinite continuation loop is possible.
|
|
34
|
+
- "Report-back-later" / scheduled commitments (no imminence marker) are NOT
|
|
35
|
+
caught — those remain the commitment tracker's domain.
|
|
36
|
+
|
|
37
|
+
## Rollback
|
|
38
|
+
|
|
39
|
+
Revert the `getStopGateRouterHook()` change; the next migration overwrites the
|
|
40
|
+
installed hook back to the prior content. No state, config, or schema changes are
|
|
41
|
+
involved.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Side effects — tokenless-standby relay token check
|
|
2
|
+
|
|
3
|
+
## What this changes at runtime
|
|
4
|
+
|
|
5
|
+
`TelegramAdapter.sendToTopic` now decides "tokenless → relay" by checking that
|
|
6
|
+
the bot token is a non-empty STRING, instead of the old truthy check
|
|
7
|
+
(`!this.config.token`). The change is confined to the relay-vs-direct branch.
|
|
8
|
+
|
|
9
|
+
## Who is affected
|
|
10
|
+
|
|
11
|
+
- **Token-holding adapters (the normal case — laptop, single-machine agents):**
|
|
12
|
+
NO behavior change. Their `config.token` is a real string, so
|
|
13
|
+
`hasUsableBotToken` is `true` and they continue to send directly via the
|
|
14
|
+
Telegram API exactly as before. Verified by the "sends DIRECTLY" unit test.
|
|
15
|
+
- **Tokenless pool standbys (a moved session on a machine without the token):**
|
|
16
|
+
Their externalized token (`{ secret: true }` / `null`) is now correctly seen
|
|
17
|
+
as "no usable token", so their replies route through `outboundRelay` to the
|
|
18
|
+
lease holder instead of silently failing a direct send.
|
|
19
|
+
|
|
20
|
+
## Blast radius
|
|
21
|
+
|
|
22
|
+
- Single file (`src/messaging/TelegramAdapter.ts`), one branch condition.
|
|
23
|
+
- No config keys added or changed. No migration required (the change is in
|
|
24
|
+
compiled source, not in any agent-installed file/hook/skill).
|
|
25
|
+
- The relay target (`outboundRelay`, wired in `server.ts`) is unchanged.
|
|
26
|
+
|
|
27
|
+
## Failure modes considered
|
|
28
|
+
|
|
29
|
+
- If a standby has no usable token AND `outboundRelay` is not wired, behavior is
|
|
30
|
+
unchanged from before (it falls through to the direct-send branch and fails the
|
|
31
|
+
same way) — no new failure introduced.
|
|
32
|
+
- The relay still surfaces a hard error if the lease holder is unreachable
|
|
33
|
+
(`telegram outbound relay failed`), so a lost reply is loud, not silent.
|
package/upgrades/1.3.175.md
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# Upgrade Guide — vNEXT
|
|
2
|
-
|
|
3
|
-
<!-- assembled-by: assemble-next-md -->
|
|
4
|
-
<!-- bump: patch -->
|
|
5
|
-
|
|
6
|
-
## What Changed
|
|
7
|
-
|
|
8
|
-
The Framework-Onboarding Mentor System's "lessons for the next framework"
|
|
9
|
-
playbook now actually populates. Generalizable framework issues (the portable
|
|
10
|
-
lessons — `framework-limitation` and `instar-integration-gap`) are promoted from
|
|
11
|
-
`none` to `candidate` the moment they're terminally resolved (fixed or won't-fix),
|
|
12
|
-
which is the auto-suggestion step the spec (§13.6) defined but that had never been
|
|
13
|
-
implemented. A one-time, idempotent backfill on ledger startup seeds lessons that
|
|
14
|
-
were resolved before this existed. Without this, the onboarding playbook returned
|
|
15
|
-
an empty list even with a full ledger of hard-won lessons — they were logged but
|
|
16
|
-
never reached the next framework's onboarding.
|
|
17
|
-
|
|
18
|
-
The `candidate → extracted` step (canonizing a lesson into the reusable onboarding
|
|
19
|
-
checklist) is unchanged: it still requires a non-Echo attestation, so an agent
|
|
20
|
-
cannot canonize its own lessons.
|
|
21
|
-
|
|
22
|
-
## What to Tell Your User
|
|
23
|
-
|
|
24
|
-
Nothing required — this is internal mentor-system robustness. If asked: the
|
|
25
|
-
lessons learned onboarding one agent framework now actually carry forward to the
|
|
26
|
-
next one, instead of sitting unused in the ledger.
|
|
27
|
-
|
|
28
|
-
## Summary of New Capabilities
|
|
29
|
-
|
|
30
|
-
- `GET /framework-issues/playbook?targetFramework=X` now returns the generalizable,
|
|
31
|
-
terminally-resolved lessons from prior frameworks (previously always empty because
|
|
32
|
-
nothing ever moved an issue off `playbook_status='none'`).
|
|
33
|
-
- `FrameworkIssueLedger.backfillPlaybookCandidates()` seeds pre-existing eligible
|
|
34
|
-
lessons; runs automatically and idempotently on ledger construction.
|
|
35
|
-
|
|
36
|
-
## Evidence
|
|
37
|
-
|
|
38
|
-
- Root cause: §13.6's `none→candidate` auto-suggestion was specified but never
|
|
39
|
-
implemented — the only writer of `candidate` was the manual promote route, so a
|
|
40
|
-
live ledger with 18 generalizable codex lessons (11 terminal) served `playbook: []`.
|
|
41
|
-
- Fix: deterministic auto-bump in `updateIssue` on terminal resolution + an
|
|
42
|
-
idempotent constructor backfill; the `candidate→extracted` non-Echo attestation
|
|
43
|
-
guard is untouched.
|
|
44
|
-
- Tests: +10 unit, +1 integration end-to-end; 192 ledger/mentor/route/E2E tests pass.
|
|
45
|
-
`npm run lint` clean.
|
|
46
|
-
- Spec: docs/specs/PLAYBOOK-CANDIDATE-AUTOSEED-SPEC.md (+ ELI16 companion).
|