instar 1.3.1662 → 1.3.1663

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.
Files changed (41) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +6 -3
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/core/ClaudeKeyHealth.d.ts +6 -3
  5. package/dist/core/ClaudeKeyHealth.d.ts.map +1 -1
  6. package/dist/core/ClaudeKeyHealth.js +17 -3
  7. package/dist/core/ClaudeKeyHealth.js.map +1 -1
  8. package/dist/core/SessionManager.d.ts.map +1 -1
  9. package/dist/core/SessionManager.js +4 -5
  10. package/dist/core/SessionManager.js.map +1 -1
  11. package/dist/core/StateManager.d.ts +8 -0
  12. package/dist/core/StateManager.d.ts.map +1 -1
  13. package/dist/core/StateManager.js +11 -0
  14. package/dist/core/StateManager.js.map +1 -1
  15. package/dist/core/claudeKeyRecovery.d.ts +1 -1
  16. package/dist/core/claudeKeyRecovery.js +1 -1
  17. package/dist/core/pickSessionByTmux.d.ts +11 -0
  18. package/dist/core/pickSessionByTmux.d.ts.map +1 -0
  19. package/dist/core/pickSessionByTmux.js +11 -0
  20. package/dist/core/pickSessionByTmux.js.map +1 -0
  21. package/dist/data/standards-guard-index.json +1 -1
  22. package/dist/data/standards-guard-index.meta.json +2 -2
  23. package/dist/data/standards-registry.meta.json +1 -1
  24. package/dist/native/InstarWedgeCanary.app/Contents/MacOS/InstarWedgeCanary +0 -0
  25. package/dist/native/instar-desktop-host +0 -0
  26. package/dist/server/routes.js +3 -3
  27. package/dist/server/routes.js.map +1 -1
  28. package/dist/threadline/ThreadlineMcpHttpService.d.ts.map +1 -1
  29. package/dist/threadline/ThreadlineMcpHttpService.js +2 -1
  30. package/dist/threadline/ThreadlineMcpHttpService.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/data/builtin-manifest.json +47 -47
  33. package/src/data/feature-ladders.json +2 -1
  34. package/src/data/standards-guard-index.json +1 -1
  35. package/src/data/standards-guard-index.meta.json +2 -2
  36. package/src/data/standards-registry.meta.json +1 -1
  37. package/upgrades/{1.3.1662.md → 1.3.1663.md} +14 -2
  38. package/upgrades/cloud-key-recovery-reply.eli16.md +1 -1
  39. package/upgrades/side-effects/cloud-key-recovery-reply.md +9 -1
  40. package/upgrades/side-effects/memory-privacy-ladder-off-by-default.md +100 -0
  41. package/upgrades/side-effects/session-by-tmux.md +48 -0
@@ -2,5 +2,5 @@
2
2
  "sha256": "f91273af3f6f22eb6bb3161c35b109469d8457f1f93b2ec90eec9e58f62ead53",
3
3
  "articleCount": 95,
4
4
  "generatedFrom": "docs/STANDARDS-REGISTRY.md",
5
- "packageVersion": "1.3.1662"
5
+ "packageVersion": "1.3.1663"
6
6
  }
@@ -11,24 +11,30 @@ These receipts go only to an agent that has said it understands them, and an old
11
11
 
12
12
  Routine Agent Health reports now stay in the attention record without sending Telegram messages. A report explicitly marked as needing the person can still reach the Agent Health topic. HTML formatting now survives a standby machine's relay to the Telegram holder.
13
13
 
14
- After a rejected Claude sign-in key is fixed, every conversation that was waiting now gets a real answer. Each restarted conversation is given the messages that arrived during the outage and the exact command to reply. A restart counts as done only once a reply shows up; if none does within 15 minutes, the person is asked to send again and the miss is reported. `slack-reply.sh` in a bound Slack session now ignores a channel id passed out of habit. Before, it posted that id as the message and dropped the real reply. The operator warning counts as delivered only when a person can read it: if the Slack alert channel has none of the agent's people in it, each of them gets a direct message.
14
+ After a rejected Claude sign-in key is fixed, every conversation that was waiting now gets a real answer. Each restarted conversation is given the messages that arrived during the outage and the exact command to reply. When messages were held, a restart counts as done only once a reply shows up; if none does within 15 minutes, the person is asked to send again and the miss is reported. With nothing held, nobody is asked. The check is per conversation: it confirms a reply, not that each held message got its own answer. Telegram is covered by tests; only Slack has been proven live so far. `slack-reply.sh` in a bound Slack session now ignores a channel id passed out of habit. Before, it posted that id as the message and dropped the real reply. The operator warning counts as delivered only when a person can read it: if the Slack alert channel has none of the agent's people in it, each of them gets a direct message.
15
15
 
16
16
  Feedback executor change sets may now contain up to 5 MiB of valid UTF-8 text, enough to modify the current `server.ts` and `routes.ts` pair with focused tests. Binary or invalid UTF-8 content keeps the former 4 MiB aggregate limit. The 200-file ceiling, credential scan, confined workspace, independent review, and test/CI gates remain.
17
17
 
18
+ The memory-privacy spec and the maturation board now say what has shipped since 1.3.1657: memory privacy is off by default and on only when an owner turns it on. The board gains a memory-privacy entry whose last rung is "off by owner preference", decided by Justin on 2026-11-04, with a development-agent rung that still has to earn its evidence. No runtime behaviour changes.
19
+
18
20
  With memory privacy turned on, a Linux agent saved memory correctly but could not answer anyone: the sandboxed session has its own network, so its reply scripts could not reach the agent's server (curl exit 7). Each scoped session on Linux now gets a small curl setting in its own folder that sends requests for the agent's server through the sandbox's own proxy, which already allows it. The session reaches nothing it could not reach on macOS. macOS is unchanged, and so is every agent with memory privacy off (the default).
19
21
 
22
+ A session's tmux name is reused when a conversation returns to a machine, and lookups by name could pick an old finished record instead of the live session. When a conversation moved away, that could leave the live session running on the machine it had left. Every lookup by name now picks the live session.
23
+
20
24
  ## What to Tell Your User
21
25
 
22
26
  When you ask me to reach out to another agent, I can now tell you what really happened instead of "they still haven't replied": whether their server is holding it, whether a session has read it and what that session understood, or that it was lost. This needs both agents to be on this version, so an older agent still shows as unknown.
23
27
 
24
28
  Agent Health is quieter: I keep my own machine and session reports in the record, and message you only when I need you to act.
25
29
 
26
- If my sign-in key stops working and you fix it, I'll answer everything you sent while I was down. If I miss something, I'll ask you to send it again. Warnings about my key now reach you directly, even if you never joined my alert channel.
30
+ If my sign-in key stops working and you fix it, I'll answer what you sent while I was down. If no answer comes, I'll ask you to send it again. Warnings about my key now reach you directly, even if you never joined my alert channel.
27
31
 
28
32
  The executor can now submit a small fix that touches two large Instar integration files for review. This removes one measured size blocker; a fresh fix still has to pass review and tests before it reaches users.
29
33
 
30
34
  Nothing changes unless you turned on memory privacy on a Linux machine. If you did, people now get replies again; their facts stay as separate as before.
31
35
 
36
+ Nothing to do. On an agent with several machines, a conversation that moves back and forth no longer leaves a stray copy behind.
37
+
32
38
  ## Summary of New Capabilities
33
39
 
34
40
  | Capability | How to Use |
@@ -52,6 +58,10 @@ No new commands. Key-outage recovery now answers held messages, checks that it d
52
58
  |---|---|
53
59
  | Replies work from privacy sessions on Linux | automatic when memoryPrivacy.enabled is true |
54
60
 
61
+ | Capability | How to Use |
62
+ |---|---|
63
+ | Lookups by session name find the live session | automatic |
64
+
55
65
  ## Evidence
56
66
 
57
67
  `tests/unit/a2a-required-ack.test.ts`, `tests/unit/SpawnRequestManager-required-ack.test.ts`, `tests/unit/PostUpdateMigrator-a2aRequiredAck.test.ts`, `tests/integration/threadline/required-ack.test.ts`, `tests/e2e/threadline/required-ack-alive.test.ts`. Live proof on throwaway agents, then Echo and Scout, is still to come.
@@ -62,4 +72,6 @@ Found in the 2026-11-04 nimbus bad-key drill: two restarted sessions posted thei
62
72
 
63
73
  On main `0aa1391f`, the two affected source files total 4,356,054 bytes, exceeding the previous 4 MiB ceiling. Boundary tests exercise the measured pair, exact 5 MiB and 5 MiB plus one byte, 201 files, and binary/invalid UTF-8 at the former 4 MiB boundary. The independent review record is `docs/specs/reports/feedback-changeset-byte-cap-calibration-review.md`.
64
74
 
75
+ `tests/unit/feature-ladders-coverage.test.ts` and `tests/unit/MaturationLadder.test.ts`: 45 passed with the new entry. The maturation-plan gate (`findMaturationPlanGaps` with the ladder required) passes on the edited spec.
76
+
65
77
  Claude Code 2.1.318 on Ubuntu 24.04 with the real session settings, slack-reply.sh and telegram-reply.sh, against a stand-in server on port 4040: without the change, curl exit 7 and no reply; with it, both replies arrived carrying the session's limited token, outside hosts still reachable, and the agent home's files still unreadable. Unit: memory-session-policy. Integration: memory-privacy-spawn (Linux and macOS spawn flags).
@@ -10,7 +10,7 @@ We broke an agent's key on purpose and then fixed it. The agent noticed, told pe
10
10
 
11
11
  - The Slack reply script now ignores a channel code typed out of habit, so it can never be sent as the reply.
12
12
  - Each restarted conversation gets a copy of the messages that were waiting, plus the exact command to reply.
13
- - A restart only counts once a real reply shows up (the agent's automatic "still working on it" notes don't count). If none shows up within 15 minutes, the person is asked to send again, and the miss is reported.
13
+ - If messages were waiting, a restart only counts once a real reply shows up (the agent's automatic "still working on it" notes don't count). If none shows up within 15 minutes, the person is asked to send again, and the miss is reported. If nothing was waiting, nobody is asked anything. The check looks for a reply in the conversation; it can't tell whether every single message got its own answer.
14
14
  - The operator warning counts only if a person can see it. If the alert channel has none of the agent's people in it, each of them gets a direct message.
15
15
 
16
16
  ## What stays the same
@@ -12,7 +12,7 @@ Follow-up to `cloud-key-internal-calls` (#2695), from the 2026-11-04 nimbus bad-
12
12
  Three fixes:
13
13
 
14
14
  1. `slack-reply.sh` in a bound Slack session drops a leading channel id (and thread id) instead of sending it as the message. This was the direct cause: the sessions ran `cat <<EOF | slack-reply.sh C0…`, and in session mode any argument became the text, so the channel id was posted and the piped reply was thrown away. The old template's hash is added to `PRIOR_SHIPPED_SLACK_RELAY_SHA256`, so existing agents get the new copy on update.
15
- 2. `ClaudeKeyHealth` restarts each stuck conversation with its own prompt (`claudeKeyRecovery.buildKeyRecoveryPrompt`): the held messages quoted (people's messages after the agent's last real reply; the server's own key notices and a bare channel id don't count as replies), and the exact reply command. A Slack prompt carries the `[slack:<channel>]` tag. Then a restart counts as done only when a real reply appears in the conversation. If none appears within 15 minutes, the person is asked once to send again and the miss is reported. The waiting list is persisted, so it survives a server restart.
15
+ 2. `ClaudeKeyHealth` restarts each stuck conversation with its own prompt (`claudeKeyRecovery.buildKeyRecoveryPrompt`): the held messages quoted (people's messages after the agent's last real reply; the server's own key notices and a bare channel id don't count as replies), and the exact reply command. A Slack prompt carries the `[slack:<channel>]` tag. Then, when messages were held, a restart counts as done only once a real reply appears in the conversation. If none appears within 15 minutes, the person is asked once to send again and the miss is reported. When nothing was held, nothing is awaited, so nobody is asked to resend. When the held messages can't be read, the conversation restarts with the general prompt, the gap is reported, and no resend request is guessed. The waiting list is persisted, so it survives a server restart.
16
16
  3. The operator notice counts as delivered only when a person can read it: the Telegram attention topic, a Slack alert channel with an operator in it, or a direct message. On Slack the operators are the authorized people whose user profile is an owner or admin. With no ranked profile, an authorized list of three or fewer stands in. A larger unranked list gets no direct messages, so a team workspace is never mass-messaged. When the alert channel has no operator in it, it is skipped (a post there reaches nobody, and retries would repeat it) and each operator gets a direct message. When its members can't be read, it gets the post and the operators get direct messages too. `deliverOperatorNotice` is a pure function; the SlackAdapter gains `authorizedMembersOf`, `sendDirectMessage`, `getAuthorizedUserIds` and `recentConversationMessages`.
17
17
 
18
18
  ## Decision-point inventory
@@ -32,6 +32,8 @@ Nothing is blocked. The script change only affects bound sessions whose first ar
32
32
 
33
33
  ## 2. Under-block
34
34
 
35
+ The answer check is per conversation, not per message. It confirms that the agent replied after the restart, not that each held message got its own answer. The prompt quotes every held message and asks for each to be answered, and one reply may rightly cover several, but a reply that skips one is not caught. Matching replies to messages would need a model judgment. That is not added here.
36
+
35
37
  A conversation that answers late (more than 15 minutes) still gets the resend request. That costs one extra line, and nothing is lost. A conversation respawned a second time within the 15 minutes (a new session name) can't be checked under its old name: it is reported as unchecked, and the resend request may not reach the person. Held messages read straight from Slack in a mention-only channel can include an authorized person's message that didn't mention the agent (the ring buffer marks those, Slack's own history doesn't), so the agent may answer one message too many. A Telegram row with no provenance (legacy) is treated as the agent's reply. The answer check reads the latest 50 messages, so a very busy channel could push the reply out of view and cause a needless resend request.
36
38
 
37
39
  ---
@@ -113,6 +115,12 @@ Replaying the drill's message order showed that the server's standby note (":tel
113
115
 
114
116
  ---
115
117
 
118
+ ## Live proof scope
119
+
120
+ The live rerun is on nimbus, which is Slack only. The Telegram side (the reply command naming the topic, the answer check reading Telegram log rows by provenance) is covered by unit tests only. No key-only test agent with Telegram exists today (Cirrus has no Slack and runs on the exhausted key). The Telegram live proof is owed and is listed as open in the coordination ledger, not claimed here.
121
+
122
+ ---
123
+
116
124
  ## Evidence pointers
117
125
 
118
126
  - `tests/unit/slack-reply-session-channel-arg.test.ts`: the real script under bash. Fails on main's script (reproduces the drill), passes now.
@@ -0,0 +1,100 @@
1
+ # Side-Effects Review — memory privacy: spec and maturation board match off-by-default
2
+
3
+ **Version / slug:** `memory-privacy-ladder-off-by-default`
4
+ **Date:** `2026-11-04`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required — Tier 1: documentation and board data only; no runtime decision changes`
7
+
8
+ ## Summary of the change
9
+
10
+ Tier 1, 4 files, about 20 lines. `docs/specs/memory-privacy.md` still said "on by default", "fleet: default on" and "dark-window: none", but since PR 2744 (1.3.1657) the feature has shipped off by default, by Justin's decision on 2026-11-04. The spec now says off by default in section 8, adds a `ladder:` line, and rewrites the maturation plan: development rung by owner opt-in (nimbus first), fleet final off by recorded preference, criterion and dark window dated. `src/data/feature-ladders.json` gains a `memoryPrivacy` entry: `final: default-off-by-preference`, the recorded decision (decider, reason, date, reference), risk sensitive, a dev rung with `advance: code`, and tracking `needed`, since the feature logs no evidence yet. The ELI16 line that read as if it turns on by itself is reworded. Effort: one commit attempt, no review rounds.
11
+
12
+ ## Decision-point inventory
13
+
14
+ No runtime decision point changes. The board reads the new entry; with `advance: code`, nothing will flip the setting on its own.
15
+
16
+ ---
17
+
18
+ ## 1. Over-block
19
+
20
+ No block/allow surface — over-block not applicable.
21
+
22
+ ---
23
+
24
+ ## 2. Under-block
25
+
26
+ No block/allow surface — under-block not applicable.
27
+
28
+ ---
29
+
30
+ ## 3. Level-of-abstraction fit
31
+
32
+ The ladder registry is the single home for graduation decisions (Maturation Path clause d), so the preference final belongs there, not only in prose.
33
+
34
+ ---
35
+
36
+ ## 4. Signal vs authority compliance
37
+
38
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
39
+
40
+ - [x] No — this change has no block/allow surface.
41
+
42
+ ---
43
+
44
+ ## 4b. Judgment-point check (Judgment Within Floors standard)
45
+
46
+ No new static heuristic at a competing-signals decision point.
47
+
48
+ ---
49
+
50
+ ## 5. Interactions
51
+
52
+ The maturation service will list the entry. Its dev rung reads `logs/feature-evidence.jsonl`, where nothing is written yet, so it reads as not started; the tracking plan says so. `advance: code` keeps any automatic move from turning on a restricting setting.
53
+
54
+ ---
55
+
56
+ ## 6. External surfaces
57
+
58
+ The maturation board shows one new entry. No agent behaviour or user-facing message changes.
59
+
60
+ ---
61
+
62
+ ## 6b. Operator-surface quality (Operator-Surface Quality standard)
63
+
64
+ No operator surface — not applicable.
65
+
66
+ ---
67
+
68
+ ## 7. Multi-machine posture (Cross-Machine Coherence)
69
+
70
+ The ladder data ships with the package, identical on every machine. No state, notices or URLs.
71
+
72
+ ---
73
+
74
+ ## 8. Rollback cost
75
+
76
+ Revert the commit. No persistent state.
77
+
78
+ ---
79
+
80
+ ## Conclusion
81
+
82
+ Brings the document and the board in line with what ships. Clear to ship.
83
+
84
+ ---
85
+
86
+ ## Second-pass review (if required)
87
+
88
+ Not required.
89
+
90
+ ---
91
+
92
+ ## Evidence pointers
93
+
94
+ Ladder tests 45/45; `findMaturationPlanGaps(spec, { requireLadder: true })` → ok. Follow-up for the boot check is tracked as ACT-047.
95
+
96
+ ---
97
+
98
+ ## Class-Closure Declaration (display-only mirror)
99
+
100
+ No agent-authored-artifact defect — not applicable.
@@ -0,0 +1,48 @@
1
+ # Side-Effects Review — lookups by tmux name find the live session
2
+
3
+ **Version / slug:** `session-by-tmux`
4
+ **Date:** `2026-11-04`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** gpt-6-astra via codex, outside review, two rounds. Round one objected: `ThreadlineMcpHttpService.noteCallFailure` still took the first record by name. Fixed through the shared `pickSessionByTmux`. Round two concurred.
7
+
8
+ ## Summary of the change
9
+
10
+ `state.listSessions().find(s => s.tmuxSession === name)` returns whichever record the directory lists first, and a name is reused when a conversation comes back to a machine. A drain closed a finished record, was told `already-completed`, and left the running session on the machine the conversation had left (signed red, Studio to Mini, 2026-11-04). `StateManager.findSessionByTmux` prefers a running record, then the newest, at all nine lookups, and a test keeps the pattern out of `src`.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - Session lookup by name — modify — nine call sites read `StateManager.findSessionByTmux`, and the Threadline failure report reads the same `pickSessionByTmux` rule. No decision rule changes; each now reads the right record.
15
+
16
+ ---
17
+
18
+ ## 1. Over-block
19
+
20
+ The drain now closes a session it used to miss. That is the intent: the record says the conversation lives elsewhere. Closing still goes through `terminateWithAuthority`.
21
+
22
+ ## 2. Under-block
23
+
24
+ Only records with a shared name change outcome. If a name has no running record the newest wins, which is the closest fact available.
25
+
26
+ ## 3. Level-of-abstraction fit
27
+
28
+ One pure rule, `pickSessionByTmux`, exposed on `StateManager`, the owner of session records, rather than a fix at the drain alone, because ten sites had the same fault. The Threadline service gets its records from an injected list, so it calls the rule directly.
29
+
30
+ ## 4. Signal vs authority compliance
31
+
32
+ No new authority. Readers get a truer record.
33
+
34
+ ## 5. Interactions
35
+
36
+ Each site meant "the session this name means now": framework resolution, the output route, bound-session reads, delivery incarnation checks and the drain. The Threadline failure report no longer stays silent for a live HTTP session that shares a name with a finished stdio record. `DeviceLimitSessionMover` keeps its injected list and is exempt in the guard. The result is a copy, as before.
37
+
38
+ ## 6. External surfaces
39
+
40
+ None. No route shape, config or message changes.
41
+
42
+ ## 7. Multi-machine posture
43
+
44
+ Machine-local records. It fixes a multi-machine symptom: one conversation running in two places after a return trip.
45
+
46
+ ## 8. Rollback cost
47
+
48
+ Revert the commit. No state depends on it.