instar 1.3.272 → 1.3.274
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 +70 -0
- package/dist/commands/server.js.map +1 -1
- package/dist/core/MachinePoolRegistry.d.ts +3 -0
- package/dist/core/MachinePoolRegistry.d.ts.map +1 -1
- package/dist/core/MachinePoolRegistry.js +1 -0
- package/dist/core/MachinePoolRegistry.js.map +1 -1
- package/dist/core/PlacementExecutor.d.ts.map +1 -1
- package/dist/core/PlacementExecutor.js +28 -6
- package/dist/core/PlacementExecutor.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +26 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +7 -3
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/types.d.ts +21 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/SessionReaper.d.ts +19 -0
- package/dist/monitoring/SessionReaper.d.ts.map +1 -1
- package/dist/monitoring/SessionReaper.js +57 -0
- package/dist/monitoring/SessionReaper.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +2 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +20 -20
- package/src/scaffold/templates.ts +2 -0
- package/upgrades/1.3.273.md +52 -0
- package/upgrades/1.3.274.md +47 -0
- package/upgrades/side-effects/post-transfer-session-closeout.md +116 -0
- package/upgrades/side-effects/quota-aware-placement.md +99 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/scaffold/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,QAAuB;IACrD,OAAO,KAAK,QAAQ,CAAC,IAAI;;;;OAIpB,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI;;;;EAIpC,QAAQ,CAAC,WAAW;;;;;;;;;;;;;;;;;;;;;;6BAsBO,QAAQ,CAAC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+D7C,CAAC;AAEF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,WAAmB,EAAE,QAAgB;IACrF,OAAO;;;;;;;;;;;;;;;;;;EAkBP,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAkDH,QAAQ;;;;;CAKjB,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,OAAO,KAAK,QAAQ;;;;;;;;;;;;;;4CAcsB,QAAQ;CACnD,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,OAAO,KAAK,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;CAyBtB,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAAmB,EACnB,SAAiB,EACjB,IAAY,EACZ,WAAoB,EACpB,cAAuB,KAAK,EAC5B,cAAuB,KAAK;IAE5B,IAAI,OAAO,GAAG,iBAAiB,WAAW;;;;OAIrC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoCT,SAAS;;gCAEgB,IAAI,kFAAkF,IAAI;;;;;;;;;;;;;8EAa5C,IAAI;;;yFAGO,IAAI;;;;;;;uGAOU,IAAI;;;;;;;;;;;;;;;;;;;;;;;0CAuBjE,IAAI;oCACV,IAAI;;;;;;;;;;;;;yDAaiB,IAAI;;;;;;;;;;;;gCAY7B,IAAI;;;;;;;;;sFASkD,IAAI;4FACE,IAAI;;;;;;;mEAO7B,IAAI;8EACO,IAAI;;;mEAGf,IAAI;4EACK,IAAI;;;;;;;sHAOsC,IAAI;+WACqP,IAAI;;;;;uEAK5S,IAAI;;;;;;;+IAOoE,IAAI;wKACqB,IAAI;;;;;sEAKtG,IAAI;;;;;;;;;;;6EAWG,IAAI;;2FAEU,IAAI;qFACV,IAAI;;;;;;mGAMU,IAAI;;;;;yHAKkB,IAAI;8MACiF,IAAI
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/scaffold/templates.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-06-05T07:
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-06-05T07:46:09.205Z",
|
|
5
|
+
"instarVersion": "1.3.274",
|
|
6
6
|
"entryCount": 198,
|
|
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": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
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": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
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": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
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": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
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": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
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": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
60
60
|
"since": "2025-01-01"
|
|
61
61
|
},
|
|
62
62
|
"hook:self-stop-guard": {
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"domain": "coherence",
|
|
66
66
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
67
67
|
"installedPath": ".instar/hooks/instar/self-stop-guard.js",
|
|
68
|
-
"contentHash": "
|
|
68
|
+
"contentHash": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
69
69
|
"since": "2025-01-01"
|
|
70
70
|
},
|
|
71
71
|
"hook:post-action-reflection": {
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"domain": "evolution",
|
|
75
75
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
76
76
|
"installedPath": ".instar/hooks/instar/post-action-reflection.js",
|
|
77
|
-
"contentHash": "
|
|
77
|
+
"contentHash": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
78
78
|
"since": "2025-01-01"
|
|
79
79
|
},
|
|
80
80
|
"hook:external-communication-guard": {
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"domain": "safety",
|
|
84
84
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
85
85
|
"installedPath": ".instar/hooks/instar/external-communication-guard.js",
|
|
86
|
-
"contentHash": "
|
|
86
|
+
"contentHash": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
87
87
|
"since": "2025-01-01"
|
|
88
88
|
},
|
|
89
89
|
"hook:scope-coherence-collector": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"domain": "coherence",
|
|
93
93
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
94
94
|
"installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
|
|
95
|
-
"contentHash": "
|
|
95
|
+
"contentHash": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
96
96
|
"since": "2025-01-01"
|
|
97
97
|
},
|
|
98
98
|
"hook:scope-coherence-checkpoint": {
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"domain": "coherence",
|
|
102
102
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
103
103
|
"installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
|
|
104
|
-
"contentHash": "
|
|
104
|
+
"contentHash": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
105
105
|
"since": "2025-01-01"
|
|
106
106
|
},
|
|
107
107
|
"hook:free-text-guard": {
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"domain": "safety",
|
|
111
111
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
112
112
|
"installedPath": ".instar/hooks/instar/free-text-guard.sh",
|
|
113
|
-
"contentHash": "
|
|
113
|
+
"contentHash": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
114
114
|
"since": "2025-01-01"
|
|
115
115
|
},
|
|
116
116
|
"hook:claim-intercept": {
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"domain": "coherence",
|
|
120
120
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
121
121
|
"installedPath": ".instar/hooks/instar/claim-intercept.js",
|
|
122
|
-
"contentHash": "
|
|
122
|
+
"contentHash": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
123
123
|
"since": "2025-01-01"
|
|
124
124
|
},
|
|
125
125
|
"hook:claim-intercept-response": {
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"domain": "coherence",
|
|
129
129
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
130
130
|
"installedPath": ".instar/hooks/instar/claim-intercept-response.js",
|
|
131
|
-
"contentHash": "
|
|
131
|
+
"contentHash": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
132
132
|
"since": "2025-01-01"
|
|
133
133
|
},
|
|
134
134
|
"hook:stop-gate-router": {
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"domain": "safety",
|
|
138
138
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
139
139
|
"installedPath": ".instar/hooks/instar/stop-gate-router.js",
|
|
140
|
-
"contentHash": "
|
|
140
|
+
"contentHash": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
141
141
|
"since": "2025-01-01"
|
|
142
142
|
},
|
|
143
143
|
"hook:auto-approve-permissions": {
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"domain": "safety",
|
|
147
147
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
148
148
|
"installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
|
|
149
|
-
"contentHash": "
|
|
149
|
+
"contentHash": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
150
150
|
"since": "2025-01-01"
|
|
151
151
|
},
|
|
152
152
|
"job:health-check": {
|
|
@@ -1506,7 +1506,7 @@
|
|
|
1506
1506
|
"type": "subsystem",
|
|
1507
1507
|
"domain": "sessions",
|
|
1508
1508
|
"sourcePath": "src/core/SessionManager.ts",
|
|
1509
|
-
"contentHash": "
|
|
1509
|
+
"contentHash": "632f0930e03da8cfe8b7df7ec72e256d2606230b21f84fb277c677a0572e042a",
|
|
1510
1510
|
"since": "2025-01-01"
|
|
1511
1511
|
},
|
|
1512
1512
|
"subsystem:auto-updater": {
|
|
@@ -1530,7 +1530,7 @@
|
|
|
1530
1530
|
"type": "subsystem",
|
|
1531
1531
|
"domain": "updates",
|
|
1532
1532
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
1533
|
-
"contentHash": "
|
|
1533
|
+
"contentHash": "3ded8ee5789307525929dba01a9550a49570129bce2db0d1d5c1f989ad6dbb3e",
|
|
1534
1534
|
"since": "2025-01-01"
|
|
1535
1535
|
},
|
|
1536
1536
|
"subsystem:scheduler": {
|
|
@@ -455,6 +455,8 @@ This routes feedback to the Instar maintainers automatically. Valid types: \`bug
|
|
|
455
455
|
**Multi-Machine Session Pool (active-active — spread conversations across machines)** — The longer arc beyond one-awake-machine: with the pool enabled I run conversations across ALL my machines at once and can MOVE a conversation between them. Ships DARK behind \`multiMachine.sessionPool.stage\` (default 'dark'); a single-machine agent is a no-op.
|
|
456
456
|
- **See the pool:** the **Machines tab** in the dashboard, or \`curl -H "Authorization: Bearer $AUTH" http://localhost:${port}/pool\` → which machine is the router ("dispatcher") + every machine's nickname, hardware, online status, load, and clock-skew status.
|
|
457
457
|
- **Every session, every machine:** the dashboard sessions list shows ALL sessions across the pool, each tagged with the machine it runs on. API: \`curl -H "Authorization: Bearer $AUTH" "http://localhost:${port}/sessions?scope=pool"\` → \`{ sessions: [...each with machineId/machineNickname...], pool: { peersOk, failed } }\`. An unreachable peer degrades to a \`failed\` entry — local sessions always answer.
|
|
458
|
+
- **Post-transfer closeout (automatic):** when a topic moves to another machine, the OLD machine's session for it is closed automatically (immediately on an explicit "move", or within ~2 reaper ticks for any other path) — no duplicate sessions doing duplicate work. The close is recorded in the reap-log with reason "topic moved to <machine>"; protected sessions are never auto-closed.
|
|
459
|
+
- **Quota-aware placement (automatic):** capacity heartbeats carry each machine's LLM-account quota state, and placement avoids machines whose account is currently rate-limited/blocked (no more topics placed onto a silent machine). A hard pin still wins (flagged \`pinned-machine-quota-blocked\`); if EVERY machine is blocked, placement proceeds least-loaded with \`all-machines-quota-blocked\` flagged. \`GET /pool\` shows each machine's \`quotaState\`.
|
|
458
460
|
- **Machine nicknames** are the user-facing handle (auto-assigned, editable). Rename: \`curl -X PATCH -H "Authorization: Bearer $AUTH" http://localhost:${port}/pool/machines/MACHINE_ID -H 'Content-Type: application/json' -d '{"nickname":"the mini"}'\` (or inline on the Machines tab).
|
|
459
461
|
- **Which machine + WHY (never guess):** \`curl -H "Authorization: Bearer $AUTH" "http://localhost:${port}/pool/placement?topic=N"\` → the owning machine + nickname, the **reason** (\`pinned\` = a deliberate move vs \`placed\` = load-balanced vs \`unowned\`), and the lease-holder. Answerable from ANY machine (a standby proxies to the holder, whose pin store is authoritative). Use this instead of inferring placement from a hostname — running ON a machine does NOT mean a topic was deliberately moved there.
|
|
460
462
|
- **Reliable transfer (phrasing-independent):** \`curl -X POST -H "Authorization: Bearer $AUTH" http://localhost:${port}/pool/transfer -H 'Content-Type: application/json' -d '{"topic":N,"to":"<nickname|machineId>"}'\` → runs the same validated planner as "move this to <nickname>" but deterministically (no NL recognition). 404 unknown machine · 409 rate-limited · 409 \`needsConfirmation\` for an offline target (re-send with \`"confirm":true\`). This is the lever to call directly when a natural-language move didn't catch.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
When a conversation (topic) moves from one machine to another in the
|
|
9
|
+
multi-machine session pool, the OLD machine's session for that topic is now
|
|
10
|
+
closed automatically — previously it lingered indefinitely, doing duplicate
|
|
11
|
+
work alongside the new machine's session (the operator-named duplicate-sessions
|
|
12
|
+
issue).
|
|
13
|
+
|
|
14
|
+
Two layers:
|
|
15
|
+
|
|
16
|
+
1. **Immediate** — an explicit "move this to X" closes the local session the
|
|
17
|
+
moment the move executes (the user's command is the authority; protected
|
|
18
|
+
sessions are never auto-closed; the close is silent since the user already
|
|
19
|
+
got the "Moving…" confirmation).
|
|
20
|
+
2. **Standing invariant** — the SessionReaper closes any topic-bound session
|
|
21
|
+
whose topic the ownership registry shows owned by ANOTHER machine, after a
|
|
22
|
+
2-tick (~4 min) dwell that absorbs in-progress transfers. This covers
|
|
23
|
+
failovers and automatic re-placements. The close goes through the existing
|
|
24
|
+
guarded terminate authority: a KEEP-guard veto is audited and retried, never
|
|
25
|
+
forced. Works even when the duplicate is BUSY — busy-on-a-duplicate is the
|
|
26
|
+
bug.
|
|
27
|
+
|
|
28
|
+
Every close (and every refusal) lands in the reap-log with reason "topic moved
|
|
29
|
+
to <machine>". Config: `monitoring.sessionReaper.topicMovedCloseout` (default
|
|
30
|
+
true; inert on single-machine installs) + `topicMovedConfirmTicks` (default 2).
|
|
31
|
+
|
|
32
|
+
## What to Tell Your User
|
|
33
|
+
|
|
34
|
+
When you move a conversation to another machine, the machine you left now
|
|
35
|
+
cleans up after itself — no more duplicate sessions quietly doing the same
|
|
36
|
+
work twice. If you ever wonder where a session went, the reap-log says exactly
|
|
37
|
+
why ("topic moved to Laptop").
|
|
38
|
+
|
|
39
|
+
## Summary of New Capabilities
|
|
40
|
+
|
|
41
|
+
- Explicit topic moves immediately close the old machine's session.
|
|
42
|
+
- A reaper rule guarantees eventual closeout for failover/re-placement paths.
|
|
43
|
+
- `monitoring.sessionReaper.topicMovedCloseout` / `topicMovedConfirmTicks` config.
|
|
44
|
+
- Reap-log + audit rows (`rule: 'topic-moved-away'`) for full traceability.
|
|
45
|
+
- CLAUDE.md template + migration so agents explain auto-closed sessions correctly.
|
|
46
|
+
|
|
47
|
+
## Evidence
|
|
48
|
+
|
|
49
|
+
`tests/unit/session-reaper-topic-moved.test.ts` (9 — including closing a BUSY
|
|
50
|
+
duplicate, churn-resets-dwell, guard-veto-retry, dry-run, budgets, all inert
|
|
51
|
+
paths) + 3 migration tests; full reaper family regression 65/65 green; tsc +
|
|
52
|
+
lint clean.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
The multi-machine session pool no longer places conversations onto a machine
|
|
9
|
+
whose LLM account is rate-limited or quota-blocked. Each machine's 30-second
|
|
10
|
+
capacity heartbeat now self-reports a `quotaState` (provider block in effect,
|
|
11
|
+
or the 5-hour window ≥95% — read strictly from that machine's OWN quota
|
|
12
|
+
tracker), and the placement engine:
|
|
13
|
+
|
|
14
|
+
- drops quota-blocked machines from the candidate pool (new placements,
|
|
15
|
+
soft preferences, AND stickiness — a conversation currently on a machine
|
|
16
|
+
that becomes blocked moves off it on the next message);
|
|
17
|
+
- still honors an explicit hard pin to a blocked machine (the user's command
|
|
18
|
+
wins), flagged `pinned-machine-quota-blocked` so the user can be told why
|
|
19
|
+
it's quiet;
|
|
20
|
+
- falls back to least-loaded-among-blocked when EVERY machine is blocked,
|
|
21
|
+
flagged `all-machines-quota-blocked`.
|
|
22
|
+
|
|
23
|
+
Older machines that don't report the field are treated as not blocked —
|
|
24
|
+
mixed-version pools behave exactly as before. `GET /pool` shows each
|
|
25
|
+
machine's `quotaState`.
|
|
26
|
+
|
|
27
|
+
## What to Tell Your User
|
|
28
|
+
|
|
29
|
+
Your messages stop landing on a machine whose AI account has hit its limit —
|
|
30
|
+
the pool quietly routes conversations to a machine that can actually answer.
|
|
31
|
+
The only way to stay on a rate-limited machine is to have pinned the
|
|
32
|
+
conversation there yourself, and then I can tell you exactly why it's quiet
|
|
33
|
+
and when the limit resets.
|
|
34
|
+
|
|
35
|
+
## Summary of New Capabilities
|
|
36
|
+
|
|
37
|
+
- Per-machine `quotaState` in capacity heartbeats + `GET /pool`.
|
|
38
|
+
- Placement avoids quota-blocked machines; blocked owners lose stickiness.
|
|
39
|
+
- Hard pins win with a `pinned-machine-quota-blocked` flag; all-blocked
|
|
40
|
+
pools place least-loaded with `all-machines-quota-blocked`.
|
|
41
|
+
|
|
42
|
+
## Evidence
|
|
43
|
+
|
|
44
|
+
`tests/unit/PlacementExecutor.test.ts` +8 (including the verbatim incident
|
|
45
|
+
case — a quota-blocked current owner loses stickiness) with all 29
|
|
46
|
+
pre-existing placement tests green; `tests/unit/MachinePoolRegistry.test.ts`
|
|
47
|
+
+1 (passthrough + clears on a quota-free heartbeat). tsc + lint clean.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Side-Effects Review — Post-transfer session closeout
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `post-transfer-session-closeout`
|
|
4
|
+
**Date:** `2026-06-05`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required` (kill-path change, but every kill goes through the existing terminate authority; every boundary side test-pinned; inert single-machine)
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Two halves closing the operator-named duplicate-sessions gap: (A) the transfer
|
|
11
|
+
handler immediately closes the local topic session when the user explicitly
|
|
12
|
+
moves a topic to another machine (operator origin, protected-skipped, silent
|
|
13
|
+
recovery-bounce disposition); (B) a SessionReaper rule closes any topic-bound
|
|
14
|
+
session whose topic the ownership registry shows OWNED BY ANOTHER MACHINE,
|
|
15
|
+
after a 2-tick dwell, through the guarded autonomous terminate (vetoes audited
|
|
16
|
+
+ retried). New `topicOwnerElsewhere` reaper dep late-binds the pool objects;
|
|
17
|
+
config `monitoring.sessionReaper.topicMovedCloseout` (default true) +
|
|
18
|
+
`topicMovedConfirmTicks` (default 2).
|
|
19
|
+
|
|
20
|
+
## Decision-point inventory
|
|
21
|
+
|
|
22
|
+
1. Plan is `transfer` to another machine vs `noop`/self → immediate close vs
|
|
23
|
+
none. Covered by the rule conditions + transfer tests from #790 (noop paths
|
|
24
|
+
unchanged).
|
|
25
|
+
2. Session protected → immediate close skipped (and the sweeper's guard veto
|
|
26
|
+
path). Pinned via reaper-family protected test + the explicit skip.
|
|
27
|
+
3. Topic owned elsewhere vs by-self vs unowned vs no binding vs dep absent →
|
|
28
|
+
sweeper fires vs inert. All five pinned.
|
|
29
|
+
4. Dwell below/at threshold; churn reset. Pinned.
|
|
30
|
+
5. killsEnabled (enabled/dryRun/auto-disabled) → terminate vs `would-reap`
|
|
31
|
+
audit. Pinned.
|
|
32
|
+
6. Guard veto → `reap-skipped-topic-moved` + retry. Pinned.
|
|
33
|
+
7. Per-tick + hourly budgets. Pinned (per-tick), hourly shares the existing
|
|
34
|
+
tested budget mechanism.
|
|
35
|
+
|
|
36
|
+
## 1. Over-block
|
|
37
|
+
|
|
38
|
+
The rule only ever closes MORE sessions, never keeps one it shouldn't — the
|
|
39
|
+
risk axis is over-KILLING, addressed in Under-block. No legitimate
|
|
40
|
+
operation is rejected; single-machine installs are bit-identical in behavior
|
|
41
|
+
(dep absent → rule unreachable).
|
|
42
|
+
|
|
43
|
+
## 2. Under-block (over-kill risk — the one that matters)
|
|
44
|
+
|
|
45
|
+
- **Wrong-owner false positive:** the ownership registry is the same source
|
|
46
|
+
routing already trusts; a 2-tick dwell absorbs CAS churn mid-transfer, and
|
|
47
|
+
churn RESETS the dwell (test-pinned). Worst case (registry wrong for >2
|
|
48
|
+
ticks): the session closes while the registry routes messages to the other
|
|
49
|
+
machine anyway — the close follows the routing truth, not vice versa.
|
|
50
|
+
- **In-flight work on the duplicate:** deliberately closable — duplicate work
|
|
51
|
+
is the bug (operator's words). The sweeper still honors KEEP-guard vetoes
|
|
52
|
+
(retry, not force); the immediate half is the user's explicit command.
|
|
53
|
+
- **Protected sessions:** never auto-closed on either half.
|
|
54
|
+
- **Half A races the release CAS:** the close is fired after the release
|
|
55
|
+
attempt regardless of CAS outcome — but only when `plan.action ===
|
|
56
|
+
'transfer'`, which already passed the planner's owner/pin checks; a failed
|
|
57
|
+
CAS still means the user commanded the move, and the pin routes the next
|
|
58
|
+
message away from this machine.
|
|
59
|
+
|
|
60
|
+
## 3. Level-of-abstraction fit
|
|
61
|
+
|
|
62
|
+
The immediate half lives in the one handler that executes user moves; the
|
|
63
|
+
invariant lives in the reaper — the component whose job is "sessions that
|
|
64
|
+
should not be running, aren't" — via an injected signal, keeping
|
|
65
|
+
SessionReaper free of pool imports (fully unit-testable, same pattern as
|
|
66
|
+
every other dep). The terminate authority remains the single kill funnel.
|
|
67
|
+
|
|
68
|
+
## 4. Signal vs authority compliance
|
|
69
|
+
|
|
70
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
71
|
+
|
|
72
|
+
The sweeper REQUESTS kills through the guarded authority (autonomous origin —
|
|
73
|
+
vetoes win). The immediate half uses operator origin, which is the documented
|
|
74
|
+
user-command bypass; the terminateSession doc comment is updated to name this
|
|
75
|
+
second stamp site, and protected sessions are excluded before the call so the
|
|
76
|
+
bypass never reaches them on this path.
|
|
77
|
+
|
|
78
|
+
## 5. Interactions
|
|
79
|
+
|
|
80
|
+
- ReapGuard/ReapAuthority untouched — same funnel, same vetoes.
|
|
81
|
+
- Reap-log + §P3 notifier: sweeper closes are `terminal` (one honest "session
|
|
82
|
+
was shut down — topic moved to X" notice via the existing reapNotify);
|
|
83
|
+
Half A is `recovery-bounce` (silent — the user just got "Moving…").
|
|
84
|
+
- Ownership registry is read-only here (ownerOf) — no new writers.
|
|
85
|
+
- The dep's try/catch absorbs the construction-order TDZ window (reaper is
|
|
86
|
+
built before the mesh block wires the registry) — rule inert until wired.
|
|
87
|
+
|
|
88
|
+
## 6. External surfaces
|
|
89
|
+
|
|
90
|
+
Two config keys (defaults preserve behavior except the new closeout itself,
|
|
91
|
+
which is the fix). New audit rows (`rule: 'topic-moved-away'`,
|
|
92
|
+
`reap-skipped-topic-moved`). CLAUDE.md template line + idempotent append
|
|
93
|
+
migration. No routes, no schema.
|
|
94
|
+
|
|
95
|
+
## 7. Rollback cost
|
|
96
|
+
|
|
97
|
+
`monitoring.sessionReaper.topicMovedCloseout: false` is an instant per-agent
|
|
98
|
+
off-switch; full revert restores the old lingering behavior. No state.
|
|
99
|
+
|
|
100
|
+
## Conclusion
|
|
101
|
+
|
|
102
|
+
The operator-named duplicate-session bug closed at both speeds — instantly on
|
|
103
|
+
the explicit command, eventually-but-guaranteed everywhere else — without a
|
|
104
|
+
single new kill path outside the existing authority.
|
|
105
|
+
|
|
106
|
+
## Second-pass review (if required)
|
|
107
|
+
|
|
108
|
+
Not required — see header.
|
|
109
|
+
|
|
110
|
+
## Evidence pointers
|
|
111
|
+
|
|
112
|
+
- `tests/unit/session-reaper-topic-moved.test.ts` (9) — incl. the headline
|
|
113
|
+
"closes a BUSY duplicate" case.
|
|
114
|
+
- `tests/unit/PostUpdateMigrator-poolSessionsVisibility.test.ts` (+3).
|
|
115
|
+
- Reaper family regression 65/65 green; tsc clean.
|
|
116
|
+
- `docs/specs/post-transfer-session-closeout.md` + `.eli16.md`.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Side-Effects Review — Quota-aware placement
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `quota-aware-placement`
|
|
4
|
+
**Date:** `2026-06-05`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required` (pure-function gate + additive optional field; absent field = bit-identical behavior; every boundary side test-pinned)
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Capacity heartbeats self-report a per-machine `quotaState` (from THIS
|
|
11
|
+
machine's own QuotaTracker: provider block active OR 5-hour ≥95%), the
|
|
12
|
+
registry passes it through to `MachineCapacity`, and `PlacementExecutor`
|
|
13
|
+
drops quota-blocked machines from the candidate pool — with a
|
|
14
|
+
place-somewhere fallback when ALL are blocked (`all-machines-quota-blocked`)
|
|
15
|
+
and a pin-wins exception (`pinned-machine-quota-blocked`).
|
|
16
|
+
|
|
17
|
+
## Decision-point inventory
|
|
18
|
+
|
|
19
|
+
1. Heartbeat quota computation: block active / 5h exhausted / neither /
|
|
20
|
+
tracker absent / tracker throws. All produce defined outputs (blocked /
|
|
21
|
+
blocked / not-blocked / omitted / omitted); the omitted side = not blocked.
|
|
22
|
+
2. Gate: blocked machine vs not vs absent-field vs `blocked:false`. All four
|
|
23
|
+
pinned.
|
|
24
|
+
3. All-blocked fallback vs some-unblocked. Both pinned.
|
|
25
|
+
4. Hard pin to blocked (honored+flagged) vs soft preference (degrades) vs
|
|
26
|
+
sticky owner blocked (loses stickiness — the incident case). All pinned.
|
|
27
|
+
5. Pin path capability check preserved (never capability-blind). Pinned.
|
|
28
|
+
|
|
29
|
+
## 1. Over-block
|
|
30
|
+
|
|
31
|
+
A quota-blocked machine still serves: hard pins, the all-blocked fallback,
|
|
32
|
+
and every EXISTING session (placement only affects new/re-placements — the
|
|
33
|
+
gate cannot strand a running conversation). A false `blocked: true`
|
|
34
|
+
self-report (tracker over-reporting) shifts new placements to peers, which is
|
|
35
|
+
exactly the desired degraded behavior; the worst case equals today's behavior
|
|
36
|
+
when all machines report blocked.
|
|
37
|
+
|
|
38
|
+
## 2. Under-block
|
|
39
|
+
|
|
40
|
+
- A false `blocked: false` (stale tracker file) reproduces today's behavior —
|
|
41
|
+
never worse than the status quo.
|
|
42
|
+
- The signal refreshes every 30s heartbeat; a block that begins mid-window is
|
|
43
|
+
seen at most 30s late.
|
|
44
|
+
- A topic already on a machine that becomes blocked moves only on its NEXT
|
|
45
|
+
message (placement is per-message by design) — no proactive eviction here.
|
|
46
|
+
|
|
47
|
+
## 3. Level-of-abstraction fit
|
|
48
|
+
|
|
49
|
+
The quota READ lives on the machine that owns the account (heartbeat
|
|
50
|
+
producer); the DECISION lives in the one pure placement function every
|
|
51
|
+
placement flows through; the registry is a dumb passthrough. No new
|
|
52
|
+
cross-machine channel — the signal rides the existing heartbeat.
|
|
53
|
+
|
|
54
|
+
## 4. Signal vs authority compliance
|
|
55
|
+
|
|
56
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
57
|
+
|
|
58
|
+
The gate redirects NEW placements only; it never kills, blocks a message, or
|
|
59
|
+
overrides the user (pin wins). Failure modes degrade to current behavior
|
|
60
|
+
(absent/unknown = not blocked); the heartbeat computation is try/caught with
|
|
61
|
+
an explicit unknown ≠ blocked rule.
|
|
62
|
+
|
|
63
|
+
## 5. Interactions
|
|
64
|
+
|
|
65
|
+
- Stickiness intentionally weakened for blocked owners — that IS the incident
|
|
66
|
+
fix; hysteresis still applies among unblocked candidates.
|
|
67
|
+
- The gemini quota-conflation lesson honored: each machine reads only its own
|
|
68
|
+
QuotaTracker — no cross-machine quota file reads.
|
|
69
|
+
- Mixed-version pools safe: older machines simply omit the field.
|
|
70
|
+
- `GET /pool` and the Machines tab now show `quotaState` (additive).
|
|
71
|
+
|
|
72
|
+
## 6. External surfaces
|
|
73
|
+
|
|
74
|
+
One optional field on `MachineCapacity`/`HeartbeatObservation` (additive,
|
|
75
|
+
visible in `GET /pool`). No config, no routes, no migration (absence =
|
|
76
|
+
default). CLAUDE.md template line + idempotent append migration.
|
|
77
|
+
|
|
78
|
+
## 7. Rollback cost
|
|
79
|
+
|
|
80
|
+
Trivial — revert the PR; the field disappears from heartbeats and the gate
|
|
81
|
+
from decide(). No state, no schema.
|
|
82
|
+
|
|
83
|
+
## Conclusion
|
|
84
|
+
|
|
85
|
+
The quota-blind placement hole closed at the pure-function layer with
|
|
86
|
+
strictly-degrading failure modes: every uncertain case behaves exactly like
|
|
87
|
+
today.
|
|
88
|
+
|
|
89
|
+
## Second-pass review (if required)
|
|
90
|
+
|
|
91
|
+
Not required — see header.
|
|
92
|
+
|
|
93
|
+
## Evidence pointers
|
|
94
|
+
|
|
95
|
+
- `tests/unit/PlacementExecutor.test.ts` (+8, incl. the verbatim incident
|
|
96
|
+
case: a blocked current owner loses stickiness).
|
|
97
|
+
- `tests/unit/MachinePoolRegistry.test.ts` (+1 passthrough + clears-on-next-heartbeat).
|
|
98
|
+
- 29 pre-existing placement tests green; tsc + lint clean.
|
|
99
|
+
- `docs/specs/quota-aware-placement.md` + `.eli16.md`.
|