instar 1.3.121 → 1.3.122

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 (28) hide show
  1. package/dist/core/TopicResumeMap.d.ts.map +1 -1
  2. package/dist/core/TopicResumeMap.js +18 -2
  3. package/dist/core/TopicResumeMap.js.map +1 -1
  4. package/dist/messaging/relayContentDedup.d.ts +51 -0
  5. package/dist/messaging/relayContentDedup.d.ts.map +1 -0
  6. package/dist/messaging/relayContentDedup.js +0 -0
  7. package/dist/messaging/relayContentDedup.js.map +1 -0
  8. package/dist/monitoring/frameworkActivitySignals.d.ts.map +1 -1
  9. package/dist/monitoring/frameworkActivitySignals.js +12 -1
  10. package/dist/monitoring/frameworkActivitySignals.js.map +1 -1
  11. package/dist/providers/adapters/openai-codex/observability/sessionPaths.d.ts +10 -0
  12. package/dist/providers/adapters/openai-codex/observability/sessionPaths.d.ts.map +1 -1
  13. package/dist/providers/adapters/openai-codex/observability/sessionPaths.js +44 -1
  14. package/dist/providers/adapters/openai-codex/observability/sessionPaths.js.map +1 -1
  15. package/dist/server/routes.d.ts.map +1 -1
  16. package/dist/server/routes.js +27 -0
  17. package/dist/server/routes.js.map +1 -1
  18. package/dist/threadline/ThreadResumeMap.d.ts.map +1 -1
  19. package/dist/threadline/ThreadResumeMap.js +19 -7
  20. package/dist/threadline/ThreadResumeMap.js.map +1 -1
  21. package/package.json +1 -1
  22. package/scripts/instar-dev-precommit.js +10 -1
  23. package/src/data/builtin-manifest.json +46 -46
  24. package/upgrades/1.3.122.md +86 -0
  25. package/upgrades/side-effects/codex-exec-json-silence-signal.md +64 -0
  26. package/upgrades/side-effects/codex-resume-jsonl-exists.md +68 -0
  27. package/upgrades/side-effects/ship-gate-sha-mismatch-error.md +54 -0
  28. package/upgrades/side-effects/threadline-relay-content-dedup.md +93 -0
@@ -0,0 +1,64 @@
1
+ # Side-Effects Review — silence sentinel recognizes codex exec --json sessions
2
+
3
+ **Version / slug:** `codex-exec-json-silence-signal`
4
+ **Date:** `2026-05-30`
5
+ **Author:** `instar-echo`
6
+ **Second-pass reviewer:** `instar-echo second-pass checklist`
7
+
8
+ ## Summary of the change
9
+
10
+ The ActiveWorkSilenceSentinel only watches sessions that `looksActivelyWorking`;
11
+ an idle frame is marked `paused` and skipped. The codex activity signatures in
12
+ `frameworkActivitySignals.ts` matched only the interactive TUI. Codex job and
13
+ autonomous-spawn sessions run `codex exec --json`, which emits a JSON event
14
+ stream (`{"type":"thread.started"}`, `{"type":"turn.started"}`,
15
+ `{"type":"item.completed"}`, ...) that matched nothing — so a working exec-json
16
+ session read as not-active, was marked paused, and the silence watchdog never
17
+ considered it. A wedged exec-json job (frozen mid-turn ~8.5h, 2026-05-30) was
18
+ invisible.
19
+
20
+ The change adds the event-stream namespaces to
21
+ `CODEX_CLI_SIGNAL.toolCallOrSpinner` (`"type":"thread."`/`"turn."`/`"item."`),
22
+ keeping every existing TUI pattern. A working exec-json session is now active and
23
+ silence-eligible; when it freezes the sentinel detects the output gap.
24
+
25
+ ## Decision-point inventory
26
+
27
+ - `CODEX_CLI_SIGNAL.toolCallOrSpinner` — modify — extends the "is codex actively
28
+ working" signature to cover the exec-json event stream, not just the TUI.
29
+
30
+ ---
31
+
32
+ ## 1. Over-block
33
+
34
+ "Over-block" here would mean flagging a session as frozen when it is fine. The
35
+ change cannot cause that: it only makes a session ELIGIBLE for silence checking
36
+ (by counting it as active). The actual freeze decision is still the
37
+ output-silence threshold plus the tracker's observed-change requirement — both
38
+ unchanged. A live, still-streaming exec-json session keeps advancing
39
+ `lastChangeAt` and is never flagged.
40
+
41
+ ## 2. Under-block
42
+
43
+ A truly-idle exec-json pane that happens to contain a stale event marker could
44
+ read as active. This does not cause a false alarm (the tracker requires an
45
+ observed active→silent transition; a pane frozen before first sighting stays
46
+ `lastOutputAt: 0` and is skipped). The critical 2026-05-23 guard — never match
47
+ the idle model-name status line — is preserved and explicitly tested.
48
+
49
+ ## 3. Level-of-abstraction fit
50
+
51
+ The codex event-stream signature belongs in `frameworkActivitySignals.ts`, the
52
+ single module that owns per-framework activity patterns. The framework-agnostic
53
+ detection in `sentinelWiring`/`ActiveWorkSilenceSentinel` is untouched — only the
54
+ codex signature it consumes is extended, so every framework's detection path
55
+ stays uniform.
56
+
57
+ ## 4. Signal vs authority compliance
58
+
59
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
60
+
61
+ - [x] This is a detector signature, not authority. It feeds the existing silence
62
+ detector; it issues no kill and no block. Its only effect is to let the
63
+ detector SEE codex exec-json sessions it was previously blind to. The
64
+ downstream nudge/escalation policy is unchanged and already tone-gated.
@@ -0,0 +1,68 @@
1
+ # Side-Effects Review — jsonlExists resolves codex rollout files
2
+
3
+ **Version / slug:** `codex-resume-jsonl-exists`
4
+ **Date:** `2026-05-30`
5
+ **Author:** `instar-echo`
6
+ **Second-pass reviewer:** `instar-echo second-pass checklist`
7
+
8
+ ## Summary of the change
9
+
10
+ `ThreadResumeMap.jsonlExists` and `TopicResumeMap.jsonlExists` decided a saved
11
+ session UUID was missing unless a Claude flat-layout transcript
12
+ (`~/.claude/projects/<encoded>/<uuid>.jsonl`) existed. Codex writes rollout files
13
+ at `$CODEX_HOME/sessions/YYYY/MM/DD/rollout-<ts>-<uuid>.jsonl`, so both
14
+ predicates returned `false` for every codex session — `get()` returned null and
15
+ resume broke fleet-wide for codex agents (~9 consumers).
16
+
17
+ The change adds `findRolloutFileSync` to the openai-codex `sessionPaths` helper
18
+ (a synchronous sibling of the existing async `findRolloutFile`, since the resume
19
+ guards are synchronous) and makes both `jsonlExists` predicates check the Claude
20
+ layout first (unchanged, early-return on hit) then fall back to the codex layout.
21
+ Returns true if either exists. Reuses the codex session-path seam `TokenLedger`
22
+ already uses.
23
+
24
+ ## Decision-point inventory
25
+
26
+ - `findRolloutFileSync` — add — sync codex rollout lookup; chooses whether a
27
+ codex thread has an on-disk rollout.
28
+ - `ThreadResumeMap.jsonlExists` — modify — now resolves codex rollouts in
29
+ addition to the Claude layout.
30
+ - `TopicResumeMap.jsonlExists` — modify — same codex fallback.
31
+
32
+ ---
33
+
34
+ ## 1. Over-block
35
+
36
+ A false "missing" would now require BOTH the Claude layout and the codex layout
37
+ to lack the uuid. The change can only make `jsonlExists` return true in MORE
38
+ cases than before (it adds a second place to look, never removes the first), so
39
+ it cannot newly over-block a session that previously resolved. The only residual
40
+ over-block is the pre-existing one: a genuinely-deleted transcript correctly
41
+ reads as missing in both layouts.
42
+
43
+ ## 2. Under-block
44
+
45
+ The codex fallback could in principle resolve a uuid collision — a rollout file
46
+ whose name contains the uuid substring but belongs to a different session. This
47
+ mirrors the existing async `findRolloutFile` matching (`rollout-*-<uuid>.jsonl`)
48
+ and uuids are effectively unique, so the risk is the same as the established
49
+ codex path. The match also requires the `rollout-` prefix and `.jsonl` suffix, so
50
+ an unrelated file merely containing the uuid is not matched (covered by test).
51
+
52
+ ## 3. Level-of-abstraction fit
53
+
54
+ The sync lookup lives in the openai-codex `sessionPaths` module, alongside the
55
+ async `findRolloutFile` it mirrors — the one place that owns the codex on-disk
56
+ session layout. The resume predicates consume it rather than reimplementing the
57
+ walk, so the codex layout knowledge stays in exactly one module. No framework
58
+ state is threaded into the predicate; it simply consults both layouts.
59
+
60
+ ## 4. Signal vs authority compliance
61
+
62
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
63
+
64
+ - [x] No LLM judgment. This is a deterministic filesystem existence check feeding
65
+ an existing guard. It exercises no new authority — it only makes the existing
66
+ "does this transcript exist" predicate correct for codex agents. Its single
67
+ effect is to let a codex session resume that previously could not; it never
68
+ blocks, kills, or messages.
@@ -0,0 +1,54 @@
1
+ # Side-Effects Review — ship-gate sha-mismatch error becomes self-service
2
+
3
+ **Version / slug:** `ship-gate-sha-mismatch-error`
4
+ **Date:** `2026-05-30`
5
+ **Author:** `instar-echo`
6
+ **Second-pass reviewer:** `instar-echo second-pass checklist`
7
+
8
+ ## Summary of the change
9
+
10
+ `scripts/instar-dev-precommit.js` blocks a commit when the staged side-effects
11
+ artifact's sha256 differs from the sha recorded in the trace. The old message
12
+ ("artifact content has changed ... sha mismatch") never printed the correct sha,
13
+ so authors regenerated the artifact — whose volatile `Date:` field changed the
14
+ bytes and thus the sha — and chased the hash forever (a ~2h grind 2026-05-30,
15
+ worst for codex agents). The hook already computes the correct sha to do the
16
+ comparison; it just was not showing it. The change prints the recorded sha
17
+ (truncated), the EXACT computed sha to write, and the freeze/re-stage/no-amend
18
+ recipe. Failure-path text only; pass/fail logic unchanged.
19
+
20
+ ## Decision-point inventory
21
+
22
+ - sha-mismatch error string in `instar-dev-precommit.js` — modify — turns a dead
23
+ end into an actionable self-service fix; does not change which commits block.
24
+
25
+ ---
26
+
27
+ ## 1. Over-block
28
+
29
+ None changed. The gate blocks exactly the same set of commits (a mismatching
30
+ sha). No commit that passed before now fails, and none that failed now passes —
31
+ the comparison is byte-identical. Only the message emitted on an existing block
32
+ changes.
33
+
34
+ ## 2. Under-block
35
+
36
+ None changed. The change cannot let a genuinely-mismatched artifact through; the
37
+ `continue` on mismatch is unchanged, so a bad bundle still fails to produce a
38
+ valid trace and the commit is still blocked. Printing the computed sha does not
39
+ weaken the check — the author still has to actually set it and re-stage.
40
+
41
+ ## 3. Level-of-abstraction fit
42
+
43
+ The message lives exactly where the mismatch is detected, in the pre-commit
44
+ validator, beside the sha computation it already performs. No new module, no new
45
+ data flow — the fix uses a value the function already holds.
46
+
47
+ ## 4. Signal vs authority compliance
48
+
49
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
50
+
51
+ - [x] No LLM, no new authority. This is a developer-experience improvement to an
52
+ existing deterministic gate's error output. The gate's blocking authority is
53
+ unchanged; the change only makes its existing refusal explainable and fixable.
54
+ The printed sha is a checksum of a public review artifact (not sensitive).
@@ -0,0 +1,93 @@
1
+ # Side-Effects Review — Content-hash dedup for the relay-agent ingress
2
+
3
+ **Version / slug:** `threadline-relay-content-dedup`
4
+ **Date:** `2026-05-30`
5
+ **Author:** `instar-echo`
6
+ **Second-pass reviewer:** `instar-echo second-pass checklist`
7
+
8
+ ## Summary of the change
9
+
10
+ This change stops duplicate agent-to-agent replies. The handler at
11
+ `POST /messages/relay-agent` accepts an inbound message, then spawns or resumes
12
+ the receiving agent's session before responding. When that spawn is slow (a
13
+ loaded box), the sender times out and retries the same message with a fresh
14
+ `message.id`. The existing dedup in `MessageRouter.relay` keys on `message.id`,
15
+ so the retry slips through and the receiver spawns/replies twice (observed six
16
+ times in one evening, 2026-05-30).
17
+
18
+ A new module `src/messaging/relayContentDedup.ts` (`RelayContentDedup`) provides
19
+ a bounded, in-memory, fixed-window dedup keyed on the stable triple
20
+ `(senderAgent, threadId, normalized content)`. `src/server/routes.ts` creates
21
+ one instance per server inside `createRoutes` and checks it in the relay-agent
22
+ handler, after envelope validation and before the relay accept. A duplicate
23
+ within the window short-circuits with an idempotent `200`
24
+ (`{ ok: true, deduped: true }`) and no spawn. Tests cover the unit logic (both
25
+ sides of every boundary) and the real HTTP route on a booted `AgentServer`.
26
+
27
+ This ships the dedup alone. The accept-boundary change (respond on inbox-accept
28
+ rather than after the spawn) is the root fix but touches response semantics and
29
+ the warrants-reply gate in the same handler, so it is a separately-reviewed
30
+ follow-up.
31
+
32
+ ## Decision-point inventory
33
+
34
+ - `RelayContentDedup` — add — the dedup engine; chooses whether an inbound relay
35
+ message is a fresh send or a duplicate retry.
36
+ - `relayContentDedup` instance in `createRoutes` — add — per-server-process
37
+ dedup state, scoped to one server instance for test isolation.
38
+ - relay-agent handler guard — add — runs the dedup check on the ingress path and
39
+ short-circuits duplicates before the relay accept and the session spawn.
40
+
41
+ ---
42
+
43
+ ## 1. Over-block
44
+
45
+ The guard drops an inbound only when the exact same sender, thread, and content
46
+ recur within the window (default 60 s). The realistic over-block is a legitimate
47
+ rapid identical resend — an agent sending the same short text (for example a bare
48
+ acknowledgement) twice in the same thread within a minute would have the second
49
+ collapsed. The window is intentionally short and the match is exact, so this is
50
+ narrow; identical back-to-back content on one thread is far more likely a retry
51
+ than two distinct intents.
52
+
53
+ A subtler case: the guard records a key when it passes the check, before the
54
+ downstream spawn outcome is known. If the first attempt's spawn genuinely failed
55
+ and the sender resent identical content to retry it, that resend would be
56
+ dropped. In practice the retry trigger is a sender timeout while the original
57
+ spawn is still in flight (so the retry is genuinely redundant), not a spawn
58
+ failure — a failed spawn already returns `200` today, so it does not provoke a
59
+ retry. The limitation is documented rather than papered over.
60
+
61
+ ## 2. Under-block
62
+
63
+ A retry whose content was modified (for example the sender appends text) hashes
64
+ differently and is not collapsed — correct, it is a different message. Messages
65
+ missing a `threadId` or body content are passed through unchanged, because there
66
+ is no stable key for them and they are not part of the observed failure.
67
+
68
+ The dedup is per-server-process in-memory state. Across a multi-machine failover
69
+ the new holder starts with an empty window, so a duplicate that straddles the
70
+ handoff could slip through. This is acceptable: the durable per-message ledger
71
+ and the `message.id` relay dedup still apply, and the straddle window is seconds
72
+ wide.
73
+
74
+ ## 3. Level-of-abstraction fit
75
+
76
+ The dedup lives at the relay-agent ingress as a small local module, not inside
77
+ `MessageRouter.relay`. The relay funnel's dedup is the `message.id` identity
78
+ layer with redelivery semantics; the content-hash layer is a distinct identity
79
+ (what the message *is*, not its id) for the specific retry-with-fresh-id failure.
80
+ Keeping it a separate module checked at the route keeps the change local to where
81
+ the failure manifests and leaves the relay funnel's contract unchanged.
82
+
83
+ ## 4. Signal vs authority compliance
84
+
85
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
86
+
87
+ - [x] No LLM judgment is involved. This is a deterministic mechanical guard — an
88
+ exact content-hash match within a fixed time window — exercising the same kind
89
+ of narrow, idempotent authority the existing `message.id` relay dedup already
90
+ holds. It never interprets meaning; it only recognizes an exact repeat. A
91
+ false match requires identical sender, thread, and bytes within seconds, and
92
+ its only effect is to withhold a second spawn (no data is lost; the message is
93
+ still acknowledged with `200`).