instar 1.2.66 → 1.2.68
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 +50 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +12 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +138 -0
- 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/codexCapabilities.d.ts +31 -0
- package/dist/core/codexCapabilities.d.ts.map +1 -0
- package/dist/core/codexCapabilities.js +56 -0
- package/dist/core/codexCapabilities.js.map +1 -0
- package/dist/core/frameworkSessionLaunch.d.ts.map +1 -1
- package/dist/core/frameworkSessionLaunch.js +13 -0
- package/dist/core/frameworkSessionLaunch.js.map +1 -1
- package/dist/providers/adapters/anthropic-headless/transport/agenticSessionHeadless.d.ts.map +1 -1
- package/dist/providers/adapters/anthropic-headless/transport/agenticSessionHeadless.js +1 -0
- package/dist/providers/adapters/anthropic-headless/transport/agenticSessionHeadless.js.map +1 -1
- package/dist/providers/adapters/openai-codex/transport/agenticSessionHeadless.d.ts.map +1 -1
- package/dist/providers/adapters/openai-codex/transport/agenticSessionHeadless.js +1 -0
- package/dist/providers/adapters/openai-codex/transport/agenticSessionHeadless.js.map +1 -1
- package/dist/providers/adapters/openai-codex/transport/codexSpawn.d.ts +2 -0
- package/dist/providers/adapters/openai-codex/transport/codexSpawn.d.ts.map +1 -1
- package/dist/providers/adapters/openai-codex/transport/codexSpawn.js +4 -0
- package/dist/providers/adapters/openai-codex/transport/codexSpawn.js.map +1 -1
- package/dist/server/AgentServer.d.ts +4 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +2 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +6 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +60 -1
- package/dist/server/routes.js.map +1 -1
- package/dist/threadline/ConversationStore.d.ts +158 -0
- package/dist/threadline/ConversationStore.d.ts.map +1 -0
- package/dist/threadline/ConversationStore.js +341 -0
- package/dist/threadline/ConversationStore.js.map +1 -0
- package/dist/threadline/ThreadlineRouter.d.ts.map +1 -1
- package/dist/threadline/ThreadlineRouter.js +24 -0
- package/dist/threadline/ThreadlineRouter.js.map +1 -1
- package/dist/threadline/WarrantsReplyGate.d.ts +110 -0
- package/dist/threadline/WarrantsReplyGate.d.ts.map +1 -0
- package/dist/threadline/WarrantsReplyGate.js +263 -0
- package/dist/threadline/WarrantsReplyGate.js.map +1 -0
- package/dist/threadline/mcp-http-client.d.ts.map +1 -1
- package/dist/threadline/mcp-http-client.js +6 -0
- package/dist/threadline/mcp-http-client.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/upgrades/1.2.67.md +57 -0
- package/upgrades/1.2.68.md +97 -0
- package/upgrades/side-effects/codex-hook-trust-bypass.md +37 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- bump: minor -->
|
|
4
|
+
<!-- minor = new capability, backward compatible -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
Phase 1 of the Threadline re-assessment — the **conversation keystone**. It fixes
|
|
9
|
+
the two failures we hit live: agent-to-agent threads fragmenting into stray
|
|
10
|
+
side-sessions, and two agents echoing acknowledgements at each other forever (the
|
|
11
|
+
echo↔codey ~20-minute ping-pong on 2026-05-24).
|
|
12
|
+
|
|
13
|
+
**The root cause.** Every inbound Threadline message spawned a fresh, memory-less
|
|
14
|
+
worker whose prompt always said "reply." Nothing owned the turn count, so an
|
|
15
|
+
amnesiac worker reflexively volleyed acks; and the conversation→topic binding was
|
|
16
|
+
captured *outbound by willpower* (a caller had to stamp `originTopicId`), so when
|
|
17
|
+
it was forgotten the thread floated into a new untied session.
|
|
18
|
+
|
|
19
|
+
**The fix (three parts).**
|
|
20
|
+
1. **A single Conversation record** (`ConversationStore`) is now the home for a
|
|
21
|
+
thread's turn count, novelty hashes, binding and lifecycle — the one place the
|
|
22
|
+
one-shot worker provably can't keep, but the gate needs. Every write goes
|
|
23
|
+
through a single-writer CAS surface (modeled on `CommitmentTracker.mutate`) so
|
|
24
|
+
concurrent inbound messages can't clobber the turn count.
|
|
25
|
+
2. **A warrants-a-reply gate** runs once at the relay inbound funnel, upstream of
|
|
26
|
+
all three routing branches (pipe-spawn / warm-listener / cold-spawn), so a
|
|
27
|
+
no-reply verdict short-circuits all of them. Questions, imperatives and
|
|
28
|
+
decisive control tokens always get a reply; a content-free ack does not; a
|
|
29
|
+
novelty-gated turn budget winds down a circular exchange while a genuinely
|
|
30
|
+
novel long collaboration never trips it; a human in the thread is always
|
|
31
|
+
answered instantly.
|
|
32
|
+
3. **Structural session/topic binding.** The origin session name is injected at
|
|
33
|
+
the spawn boundary (`INSTAR_SESSION_NAME`), forwarded on the send, and
|
|
34
|
+
resolved to the owning topic server-side — so a conversation sticks to its
|
|
35
|
+
session/topic without anyone remembering to tag it.
|
|
36
|
+
|
|
37
|
+
Plus an anti-hijack fix found while wiring it: a threadId is not a bearer token —
|
|
38
|
+
an unverified peer presenting someone else's threadId is now isolated to a fresh
|
|
39
|
+
first-contact thread instead of being injected into the owner's session.
|
|
40
|
+
|
|
41
|
+
## What to Tell Your User
|
|
42
|
+
|
|
43
|
+
- Agents no longer loop on "thanks → thanks." A bare acknowledgement doesn't
|
|
44
|
+
trigger a reply, and a back-and-forth that stops making progress winds down on
|
|
45
|
+
its own — but a real question or request is always answered, and if you're in
|
|
46
|
+
the conversation it stays instant.
|
|
47
|
+
- A conversation now stays glued to the right place automatically; it won't spin
|
|
48
|
+
off into a stray parallel session anymore.
|
|
49
|
+
- Nothing to configure. Existing in-flight conversations are migrated over on
|
|
50
|
+
update so they keep their context.
|
|
51
|
+
|
|
52
|
+
## Summary of New Capabilities
|
|
53
|
+
|
|
54
|
+
| Capability | How to Use |
|
|
55
|
+
|-----------|-----------|
|
|
56
|
+
| Conversation single-source-of-truth (`ConversationStore`) | Automatic; backs the loop gate's turn/novelty state at `.instar/threadline/conversations.json` |
|
|
57
|
+
| Warrants-a-reply loop gate | Automatic at the relay inbound funnel; budget exhaustion escalates ONE attention item (never silently drops) |
|
|
58
|
+
| Structural session/topic binding | Automatic via `INSTAR_SESSION_NAME` — no caller needs to stamp `originTopicId` |
|
|
59
|
+
| Anti-hijack resume guard | Automatic; unverified threadId-mismatch → isolated fresh thread |
|
|
60
|
+
|
|
61
|
+
## Migration Notes
|
|
62
|
+
|
|
63
|
+
`PostUpdateMigrator.migrateThreadlineConversationStore` folds the legacy
|
|
64
|
+
`thread-resume-map.json` + `context-thread-map.json` into `conversations.json` on
|
|
65
|
+
update — idempotent, field-preserving (`sessionUuid`, `agentIdentity`, `pinned`,
|
|
66
|
+
`failed`/`archived`, cross-machine, `boundTopicId`), and it never clobbers a
|
|
67
|
+
runtime-written row. No `~/.codex` or relay change.
|
|
68
|
+
|
|
69
|
+
The full physical collapse of `ThreadResumeMap`/`ContextThreadMap` into the single
|
|
70
|
+
store (so the router reads/writes *only* the Conversation) is intentionally NOT in
|
|
71
|
+
this release: those stores are written from two processes (the server and the MCP
|
|
72
|
+
stdio child), so a single in-memory store needs the child to route writes through
|
|
73
|
+
the server first — tracked as **CMT-497**, folding into the Phase 2 server-owned
|
|
74
|
+
reply model (CMT-493). Phase 1 ships the loop/fragmentation/hijack fixes with the
|
|
75
|
+
Conversation as the authoritative turn/novelty/binding store.
|
|
76
|
+
|
|
77
|
+
## Evidence
|
|
78
|
+
|
|
79
|
+
- Spec: `docs/specs/THREADLINE-CONVERSATION-KEYSTONE-SPEC.md` (+ ELI16 companion,
|
|
80
|
+
+ convergence report — 2 fatal + 4 blocking findings fixed before code).
|
|
81
|
+
- Tests (4 tiers): `ConversationStore.test.ts` (14, incl. 50-concurrent-increment
|
|
82
|
+
CAS race), `WarrantsReplyGate.test.ts` (18, both sides of every boundary),
|
|
83
|
+
`ThreadlineRouter-anti-hijack.test.ts` (3), `PostUpdateMigrator-conversationStore.test.ts`
|
|
84
|
+
(5, field preservation + idempotency), integration `warrants-reply-funnel.test.ts`
|
|
85
|
+
(5, incl. the echo↔codey loop-termination reproduction + CAS integrity under
|
|
86
|
+
concurrency), and wiring-integrity `conversation-keystone-wiring.test.ts` (6,
|
|
87
|
+
feature-alive: constructed + invoked + upstream of all branches).
|
|
88
|
+
- A loop-gate bug the integration test caught that unit tests missed: keying
|
|
89
|
+
"first contact" off `turnCount===0` made every post-progress turn reply, since
|
|
90
|
+
turnCount resets to 0 on novelty — fixed to key off conversation history.
|
|
91
|
+
|
|
92
|
+
## Rollback
|
|
93
|
+
|
|
94
|
+
Additive. The Conversation store is new; the gate is a guarded early-return at the
|
|
95
|
+
funnel; the binding is a launch-time computation. Revert = remove the funnel gate
|
|
96
|
+
block + the `INSTAR_SESSION_NAME` injection + the migration call. No persistent
|
|
97
|
+
state to clean up (the legacy stores are left intact by the migration).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Side-Effects Review: Codex hook-trust bypass (P6a — autonomy)
|
|
2
|
+
|
|
3
|
+
## Change
|
|
4
|
+
- **New** `src/core/codexCapabilities.ts`: memoized `codexSupportsHookTrustBypass(binaryPath)` — probes `codex --help` once per binary path, returns whether `--dangerously-bypass-hook-trust` is supported. Fails closed on any error.
|
|
5
|
+
- **`src/core/frameworkSessionLaunch.ts`**: both the interactive (`codexCliBuilder`) and headless (`codexCliHeadlessBuilder`) codex builders append `--dangerously-bypass-hook-trust` when the probe passes.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
Codex requires interactive trust of command hooks before they run; that prompt freezes an unattended/autonomous session and offers a "continue without trusting" escape that lets an agent decline its own guards. The flag (codex 0.133) runs instar's already-vetted hooks with no prompt. Per Justin's delegation ("choose what's best for Instar", 2026-05-24), chosen as a **per-agent launch flag** over system-managed hooks — see spec §10 P6a for the full rationale.
|
|
9
|
+
|
|
10
|
+
## Scope / blast radius
|
|
11
|
+
- **Codex launches only.** Claude launches are untouched (separate builder). The flag is appended only to codex argv, and only when the probed binary supports it.
|
|
12
|
+
- **Safe-by-construction:** instar writes the hooks (`installCodexHooks`) AND owns the launch command — there is no untrusted third-party hook this prompt would have protected against. The "danger" of the flag (running arbitrary untrusted hooks) does not apply.
|
|
13
|
+
- **No system-wide effect:** unlike managed hooks, this changes nothing outside instar's own spawned codex processes. The operator's personal `codex` launches do not get the flag and still prompt normally.
|
|
14
|
+
- **Older codex (<0.133):** the probe returns false → flag omitted → the launch still succeeds (an unknown flag would otherwise fail the whole launch) and degrades to the safe-by-blocking interactive trust-prompt path.
|
|
15
|
+
|
|
16
|
+
## Signal vs Authority / over-block
|
|
17
|
+
- No change to what the hooks block. This only affects whether they run unprompted. No new authority, no new patterns.
|
|
18
|
+
|
|
19
|
+
## Performance
|
|
20
|
+
- The probe runs `codex --help` at most once per binary path per process (memoized), at session-spawn time (infrequent), 5s timeout. Negligible.
|
|
21
|
+
|
|
22
|
+
## Migration parity
|
|
23
|
+
- **None required.** This is instar's own dist code (the launch builders), not an agent-installed file (`.claude/settings.json` / `.codex/hooks.json` / hook scripts / config defaults). Existing agents receive it on the normal npm update + server restart. (The P5c hooks.json/guard changes that this depends on already shipped in v1.2.66 with their own migration.)
|
|
24
|
+
|
|
25
|
+
## Unbypassability (honest bound)
|
|
26
|
+
- The agent cannot remove the flag from a launch instar constructs → it cannot turn off the trust-bypass. It could still attempt to edit `.codex/hooks.json` / the guard script to neuter the hook itself; that residual vector is covered by always-overwrite-on-update of instar-owned hooks + the file-edit gates, not by this change. Absolute unbypassability would require system-managed hooks, deliberately not chosen (see spec §10 P6a).
|
|
27
|
+
|
|
28
|
+
## Tests
|
|
29
|
+
- `tests/unit/codexCapabilities.test.ts` (5): supported/unsupported `--help`, fail-closed on missing + empty path, memoization (cached true survives binary deletion).
|
|
30
|
+
- `tests/unit/frameworkSessionLaunch.test.ts` (+4): interactive & headless builders append the flag when the fake binary advertises it, omit it when it doesn't; prompt stays the final positional arg in headless.
|
|
31
|
+
- Live-proven end-to-end on real codex 0.133 (no trust granted → no prompt → guard still blocked `rm -rf /`). `tsc` clean; 53 launch/capability tests green.
|
|
32
|
+
|
|
33
|
+
## Rollback
|
|
34
|
+
- Remove the two `if (codexSupportsHookTrustBypass(...)) argv.push(...)` blocks and delete `codexCapabilities.ts`. No data migration. (Rollback re-introduces the autonomous-hang on the trust prompt.)
|
|
35
|
+
|
|
36
|
+
## Publish
|
|
37
|
+
- Branch `echo/codex-hook-trust-bypass`. Patch → next release.
|