instar 1.3.656 → 1.3.658
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 +4 -0
- package/dist/commands/server.js.map +1 -1
- package/dist/core/LiveTestHarness.d.ts +25 -0
- package/dist/core/LiveTestHarness.d.ts.map +1 -1
- package/dist/core/LiveTestHarness.js +40 -4
- package/dist/core/LiveTestHarness.js.map +1 -1
- package/dist/core/RealChannelDriver.d.ts +15 -0
- package/dist/core/RealChannelDriver.d.ts.map +1 -1
- package/dist/core/RealChannelDriver.js +16 -0
- package/dist/core/RealChannelDriver.js.map +1 -1
- package/dist/core/SessionManager.d.ts +12 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +45 -2
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/SlackLiveSender.d.ts +29 -0
- package/dist/core/SlackLiveSender.d.ts.map +1 -1
- package/dist/core/SlackLiveSender.js +68 -3
- package/dist/core/SlackLiveSender.js.map +1 -1
- package/dist/core/TelegramLiveSender.d.ts +18 -0
- package/dist/core/TelegramLiveSender.d.ts.map +1 -1
- package/dist/core/TelegramLiveSender.js +60 -0
- package/dist/core/TelegramLiveSender.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +6 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/types.d.ts +10 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/rateLimitDetection.d.ts +29 -0
- package/dist/monitoring/rateLimitDetection.d.ts.map +1 -1
- package/dist/monitoring/rateLimitDetection.js +29 -0
- package/dist/monitoring/rateLimitDetection.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +3 -3
- package/upgrades/1.3.657.md +32 -0
- package/upgrades/1.3.658.md +24 -0
- package/upgrades/side-effects/idle-throttle-settle-gate.md +37 -0
- package/upgrades/side-effects/real-channel-absence-collect.md +73 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Side-Effects Review — Idle-monitor throttle settle-gate
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `idle-throttle-settle-gate`
|
|
4
|
+
**Date:** `2026-06-24`
|
|
5
|
+
**Author:** Echo (autonomous, 8-hour run)
|
|
6
|
+
**Spec:** `docs/specs/idle-throttle-settle-gate.md` (review-convergence + approved)
|
|
7
|
+
**Second-pass reviewer:** REQUIRED (touches the SessionManager idle/recovery path) — verdict appended below.
|
|
8
|
+
|
|
9
|
+
## Summary of the change
|
|
10
|
+
|
|
11
|
+
The safe slice of the false-rate-limit F3 residual (CMT-1785). The SessionManager idle-monitor emitted `rateLimitedAtIdle` (handing to RateLimitSentinel recovery) the instant `detectRateLimited(last-30-lines)` matched — a single glance, which false-fires on a stale/transient throttle line. Behind a DARK flag, the idle-monitor now gates that hand-off behind the SAME settle discipline the SessionWatchdog already uses (`evaluateThrottleSettle`: throttle present AND pane byte-identical across polls = the turn genuinely ended on the throttle). Strictly more conservative — it can only ever emit `rateLimitedAtIdle` LESS often, never more.
|
|
12
|
+
|
|
13
|
+
Files modified:
|
|
14
|
+
- `src/monitoring/rateLimitDetection.ts` — new pure `nextIdleThrottleAction` (a thin wrapper over the existing `evaluateThrottleSettle`; returns `'emit'`/`'wait'`/`'fall-through'`). No change to `evaluateThrottleSettle` or `detectRateLimited`.
|
|
15
|
+
- `src/core/SessionManager.ts` — (a) new dark-flagged per-tick settle check inside `if (isActuallyIdle)` AHEAD of the first-idle-tick gate, so the pane is re-sampled every tick (load-bearing — see F1 below); (b) the first-tick legacy emit fenced to `detectRateLimited(recentOutput) && !this.idleThrottleSettleGate` (flag-off only); (c) per-session `idleThrottleSettle` Map + `idleThrottleSettleGate` field from new opt; (d) unconditional cleanup of the Map on `sessionComplete` (constructor) + on session-active.
|
|
16
|
+
- `src/core/devGatedFeatures.ts` — new `idleThrottleSettleGate` DEV_GATED_FEATURES entry (`monitoring.idleThrottleSettleGate.enabled`, omitted ⇒ dev-live/dark-fleet).
|
|
17
|
+
- `src/core/types.ts` — `MonitoringConfig.idleThrottleSettleGate?: { enabled?: boolean }`.
|
|
18
|
+
- `src/commands/server.ts` — resolves the flag via `resolveDevAgentGate(...)` and threads it into the SessionManager opts.
|
|
19
|
+
|
|
20
|
+
Files added:
|
|
21
|
+
- `tests/unit/idle-throttle-settle-gate.test.ts` — 6 unit tests for `nextIdleThrottleAction` (every decision boundary: no-throttle→fall-through, first-sighting→wait, unchanged≥settleMs→emit, unchanged<settleMs→wait, pane-changed→wait+restart, transient-clears→fall-through).
|
|
22
|
+
- `docs/specs/idle-throttle-settle-gate.md` (+ `.eli16.md`, convergence report).
|
|
23
|
+
|
|
24
|
+
## Blast radius
|
|
25
|
+
|
|
26
|
+
- **Flag OFF (the FLEET, by default):** byte-identical to legacy. The per-tick block is skipped entirely (`if (this.idleThrottleSettleGate)` false); the first-tick emit fires exactly as before; the `idleThrottleSettle` Map is never written (cleanup deletes are no-ops on an empty map). Confirmed by the adversarial reviewer + the existing watcher/quota suites unchanged.
|
|
27
|
+
- **Flag ON (dev only):** the idle-path rate-limit hand-off is settle-gated. It only WITHHOLDS a spurious `rateLimitedAtIdle`; it never adds a kill/send/authority. RateLimitSentinel stays the recovery authority. The SessionWatchdog independently settle-gates the same class (the two emits are deduped by `RateLimitSentinel.report()`), so no double-recovery and no coverage gap.
|
|
28
|
+
- **Multi-machine:** machine-local-by-design — per-process state about locally-running sessions; no replicated/proxied state.
|
|
29
|
+
- **Migration parity:** dev-gated flag, `enabled` omitted from ConfigDefaults (no user default written) ⇒ no migration surface. No hooks/CLAUDE.md/skill/dashboard changes.
|
|
30
|
+
|
|
31
|
+
## Rollback
|
|
32
|
+
|
|
33
|
+
Flip `monitoring.idleThrottleSettleGate.enabled` false (or revert the commit) ⇒ legacy immediate emit. Fully additive and reversible; nothing irreversible ships.
|
|
34
|
+
|
|
35
|
+
## Second-pass reviewer verdict
|
|
36
|
+
|
|
37
|
+
Multi-angle spec-converge (adversarial + decision-completeness + lessons/integration internal lenses, + codex-cli:gpt-5.5 + gemini-2.5-pro external) over 2 rounds. Round 1 caught a CRITICAL functional defect (F1: the settle check ran only on the first idle tick → `'settled'` unreachable → flag-ON would emit recovery never, silently delegating to the watchdog) and a LOW map-cleanup leak (F2). Both fixed (per-tick re-sample; unconditional constructor cleanup) and verified RESOLVED + CONVERGED in round 2, with new adversarial checks (idle-kill starvation, flag-off regression, decision boundaries) clean. External minors (overstated safety claim; polling redundancy) folded into the spec. 130 unit tests green, no regression, clean typecheck. The one non-blocking note (per-tick wider capture cost when flag ON) is documented + deferred to the CMT-1785 unification. Verdict: APPROVED.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Side-Effects Review — Real-channel collectMessages (absence proof over a live channel)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `real-channel-absence-collect`
|
|
4
|
+
**Date:** `2026-06-24`
|
|
5
|
+
**Author:** Echo (autonomous, 8-hour run)
|
|
6
|
+
**Spec:** `docs/specs/real-channel-absence-collect.md` (review-convergence + approved)
|
|
7
|
+
**Second-pass reviewer:** REQUIRED (touches the LiveTestHarness verdict path) — verdict appended below.
|
|
8
|
+
|
|
9
|
+
## Summary of the change
|
|
10
|
+
|
|
11
|
+
The `LiveTestHarness` absence assertion (PR #1262) could only run against a fake driver,
|
|
12
|
+
because the production `RealChannelDriver` had no `collectMessages`. This adds it, so the
|
|
13
|
+
"no spurious background message" proof runs over a REAL Telegram/Slack channel. The whole
|
|
14
|
+
risk of an absence proof is a silent **false PASS** (reporting "no spurious message" over
|
|
15
|
+
an incomplete read), so every under-collection path is forced to BLOCK, never PASS.
|
|
16
|
+
|
|
17
|
+
Files modified:
|
|
18
|
+
- `src/core/LiveTestHarness.ts` — new `AbsenceUnverifiableError` (a sender's
|
|
19
|
+
read-incompleteness signal) + the absence-path catch now maps BOTH it and
|
|
20
|
+
`DriverCapabilityError` to **BLOCKED**; a plain `Error` stays a FAIL. The §5.3
|
|
21
|
+
pre-flight now treats any `absenceWindowMs != null` scenario as demo-only regardless of
|
|
22
|
+
its `safe` tag (a whole-history read must never touch a live channel).
|
|
23
|
+
- `src/core/RealChannelDriver.ts` — new `collectMessages(surface, channelId, opts)`
|
|
24
|
+
delegating to the surface sender; raises `DriverCapabilityError` for a surface whose
|
|
25
|
+
sender has no collector; new optional `SurfaceSender.collectMessages`.
|
|
26
|
+
- `src/core/TelegramLiveSender.ts` — `collectMessages`: polls `getHistory` across the
|
|
27
|
+
window, keeps ALL text versions per messageId (anti edit-laundering), skips non-finite
|
|
28
|
+
ids, clamps the window to 300s, and BLOCKS (AbsenceUnverifiableError) on a
|
|
29
|
+
marker-bounded full-page truncation (full page whose oldest entry is still after the
|
|
30
|
+
marker — so a reused demo topic is not wrongly blocked).
|
|
31
|
+
- `src/core/SlackLiveSender.ts` — `collectMessages` (mirror): `oldest`-bounded read,
|
|
32
|
+
BLOCKS on `ok:false` (failed read) or `next_cursor`/full-page (truncation); new
|
|
33
|
+
`isAgentAuthored` helper matches `user` OR an injected `agentBotId` (a background nudge
|
|
34
|
+
may carry only `bot_id`) — applied to `collectMessages` AND `awaitReply` for parity;
|
|
35
|
+
optional `agentBotId` dep.
|
|
36
|
+
|
|
37
|
+
Files added:
|
|
38
|
+
- `tests/unit/realchannel-collect-messages.test.ts` — 22 unit tests: collect semantics,
|
|
39
|
+
late-nudge polling, anti-laundering, truncation→BLOCK (marker-bounded), reused-topic
|
|
40
|
+
no-mis-fire, Slack bot_id / ok:false / next_cursor, §5.3 absence-demo guard, and the
|
|
41
|
+
end-to-end harness PASS/FAIL/BLOCKED over a RealChannelDriver.
|
|
42
|
+
- `docs/specs/real-channel-absence-collect.md` (+ `.eli16.md`, convergence report).
|
|
43
|
+
|
|
44
|
+
## Blast radius
|
|
45
|
+
|
|
46
|
+
- **Production runtime:** none. `collectMessages` is reachable ONLY via
|
|
47
|
+
`LiveTestHarness.run` → `RealChannelDriver`, constructed per-request in the live-test
|
|
48
|
+
route and the `instar dev` runner. No sentinel, gate, scheduler, or request path calls
|
|
49
|
+
it (verified by the scalability + integration reviewers).
|
|
50
|
+
- **Existing callers:** unchanged. `RealChannelDriver`'s constructor signature is
|
|
51
|
+
untouched; `collectMessages` is a new instance method. The harness's `!driver.collectMessages`
|
|
52
|
+
BLOCKED path still fires for FAKE drivers (RealChannelDriver now routes per-surface
|
|
53
|
+
"unsupported" through the typed error instead). `awaitReply`'s new `bot_id` matching is
|
|
54
|
+
additive — unset `agentBotId` → byte-identical prior behavior (existing tests green).
|
|
55
|
+
- **Multi-machine:** machine-local-by-design — a live channel read happens on the serving
|
|
56
|
+
machine against that channel's live history; no replicated/proxied state.
|
|
57
|
+
|
|
58
|
+
## Rollback
|
|
59
|
+
|
|
60
|
+
Fully additive and revertible: drop the three `collectMessages` method bodies, the
|
|
61
|
+
`AbsenceUnverifiableError` class + its catch clause, the §5.3 `absenceWindowMs` predicate,
|
|
62
|
+
and the `agentBotId` dep. No config defaults, hooks, CLAUDE.md template, migration, or
|
|
63
|
+
dashboard surface touched, so no Migration Parity obligation. Reverting the commit is
|
|
64
|
+
sufficient; nothing ships dark or irreversible.
|
|
65
|
+
|
|
66
|
+
## Second-pass reviewer verdict
|
|
67
|
+
|
|
68
|
+
Multi-angle spec-converge (6 internal lenses + codex-cli:gpt-5.5 + gemini-2.5-pro across
|
|
69
|
+
3 rounds) converged with zero material findings in the final round. Round 1 surfaced 5
|
|
70
|
+
material false-PASS holes (truncation, edit-laundering, Slack `bot_id`, Slack `ok:false`,
|
|
71
|
+
§5.3 safe-bypass) — all fixed + tested. Round 2 surfaced 1 material (Telegram full-page
|
|
72
|
+
guard mis-firing on a reused demo topic) — fixed marker-bounded + tested. Round 3
|
|
73
|
+
verified resolution. Standards-Conformance Gate: 0 flags all rounds. Verdict: APPROVED.
|