instar 1.3.642 → 1.3.643
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 +160 -6
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +29 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/InFlightSyncOpMarker.d.ts +29 -0
- package/dist/core/InFlightSyncOpMarker.d.ts.map +1 -0
- package/dist/core/InFlightSyncOpMarker.js +149 -0
- package/dist/core/InFlightSyncOpMarker.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts +16 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +56 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionManager.d.ts +146 -1
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +498 -144
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/SleepWakeDetector.d.ts +33 -0
- package/dist/core/SleepWakeDetector.d.ts.map +1 -1
- package/dist/core/SleepWakeDetector.js +53 -0
- package/dist/core/SleepWakeDetector.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +23 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/types.d.ts +52 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/lifeline/ServerSupervisor.d.ts +42 -0
- package/dist/lifeline/ServerSupervisor.d.ts.map +1 -1
- package/dist/lifeline/ServerSupervisor.js +79 -4
- package/dist/lifeline/ServerSupervisor.js.map +1 -1
- package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
- package/dist/lifeline/TelegramLifeline.js +8 -0
- package/dist/lifeline/TelegramLifeline.js.map +1 -1
- package/dist/monitoring/DegradedTmuxGuard.d.ts +161 -0
- package/dist/monitoring/DegradedTmuxGuard.d.ts.map +1 -0
- package/dist/monitoring/DegradedTmuxGuard.js +277 -0
- package/dist/monitoring/DegradedTmuxGuard.js.map +1 -0
- package/dist/monitoring/guardManifest.d.ts.map +1 -1
- package/dist/monitoring/guardManifest.js +18 -0
- package/dist/monitoring/guardManifest.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +13 -5
- package/dist/server/routes.js.map +1 -1
- package/package.json +2 -2
- package/scripts/lint-no-direct-destructive.js +14 -0
- package/scripts/lint-sync-subprocess-chokepoint.js +208 -0
- package/scripts/sync-subprocess-chokepoint-baseline.json +148 -0
- package/src/data/builtin-manifest.json +65 -65
- package/upgrades/1.3.643.md +66 -0
- package/upgrades/side-effects/tmux-event-loop-resilience.md +86 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Side-Effects Review — tmux Event-Loop Resilience (Increment 1)
|
|
2
|
+
|
|
3
|
+
**Slug:** `tmux-event-loop-resilience` · **Tier:** 2 (converged + approved spec
|
|
4
|
+
`docs/specs/tmux-event-loop-resilience.md`). Touches `PostUpdateMigrator` (a
|
|
5
|
+
config-strip migration), so the tier signal flags `belowFloor` — accepted: the
|
|
6
|
+
PostUpdateMigrator touch is a dev-gate cleanup strip (removes a stale persisted
|
|
7
|
+
`enabled:false` so the dev-gate resolves live-on-dev), fully reversible, no
|
|
8
|
+
external surface.
|
|
9
|
+
|
|
10
|
+
## Summary of the change
|
|
11
|
+
|
|
12
|
+
The server's frequent synchronous `tmux` calls blocked the single event loop; a
|
|
13
|
+
slow shared tmux server froze the loop ~15s, dropping the dashboard websocket and
|
|
14
|
+
getting misread as host sleep. Increment 1: (A) an async, timeout-bounded tmux
|
|
15
|
+
hot path with cache-served dashboard/session reads; (B) an in-flight-sync-op
|
|
16
|
+
marker as the block-vs-sleep discriminator (in-process for SleepWakeDetector,
|
|
17
|
+
cross-process via a mirror file for ServerSupervisor); (C) a signal-only
|
|
18
|
+
`DegradedTmuxGuard` that surfaces a persistently slow tmux without ever killing
|
|
19
|
+
it. All three are dev-gated: LIVE on a development agent, DARK on the fleet.
|
|
20
|
+
|
|
21
|
+
## 1. Over-block / false signal
|
|
22
|
+
|
|
23
|
+
`DegradedTmuxGuard` is signal-only — it raises ONE deduped attention item and
|
|
24
|
+
never kills, restarts, or reaps anything, so a false degradation signal costs at
|
|
25
|
+
most one surfaced notice. It is load-gated (suppressed when per-core load is high
|
|
26
|
+
— that is expected slowness, not a tmux fault) and requires N-cycle corroboration
|
|
27
|
+
(a single hiccup never raises an episode), with episode dedup + age-escalation.
|
|
28
|
+
The in-flight marker can only SUPPRESS a wake / DEFER a restart when affirmatively
|
|
29
|
+
present, in-flight, and non-stale — a false positive there fails toward the SAFE
|
|
30
|
+
direction (keep the session alive / let a genuinely-dead server restart).
|
|
31
|
+
|
|
32
|
+
## 2. Under-block / missed signal
|
|
33
|
+
|
|
34
|
+
A real freeze the marker doesn't cover is still caught: SleepWakeDetector's
|
|
35
|
+
existing cpuBlockBusyRatio path (CPU-spin blocks) is unchanged, and the marker
|
|
36
|
+
adds the ~0-CPU I/O-wait case #1240 couldn't see. The marker self-heals via a
|
|
37
|
+
2×timeout TTL so a leaked depth can never permanently blind sleep detection. The
|
|
38
|
+
supervisor defer is hard-capped (`starvationRestartThreshold`) so a stuck
|
|
39
|
+
in-flight marker can never wedge the restart path forever — it gives up loudly.
|
|
40
|
+
|
|
41
|
+
## 3. Blast radius / fail-open
|
|
42
|
+
|
|
43
|
+
Every failure path fails toward SAFE and is non-silent (no-silent-fallbacks
|
|
44
|
+
ratchet enforced): a tmux call that times out maps to INDETERMINATE, never to
|
|
45
|
+
"absent" — `isSessionAliveAsync` returns `'indeterminate'` (never `false`) on a
|
|
46
|
+
timeout, so a slow tmux can NEVER cause a live session to be reaped (the
|
|
47
|
+
line-2352 regression the tri-state guards). The cross-process marker reader is
|
|
48
|
+
fail-OPEN: an absent/unparseable mirror ⇒ null ⇒ the supervisor proceeds to
|
|
49
|
+
restart a genuinely dead server. The mirror writer is best-effort: an unwritable
|
|
50
|
+
mirror never breaks a tmux call. `DegradedTmuxGuard` uses a fixed-capacity
|
|
51
|
+
modulo-write ring (Bounded Accumulation — 10,000-sample burst-invariant test
|
|
52
|
+
proves the ring length never exceeds windowSize), so it cannot grow memory under
|
|
53
|
+
a flood.
|
|
54
|
+
|
|
55
|
+
## 4. Signal vs authority
|
|
56
|
+
|
|
57
|
+
The only blocking authority introduced is the supervisor restart-DEFER, and it is
|
|
58
|
+
bounded (hard cap + TTL + fail-open) and additive to the existing
|
|
59
|
+
`deferRestartForCpuStarvation` (the `||` keeps the CPU side-effect — verified by
|
|
60
|
+
test). The wake-handler amplifier guard short-circuits a marker-covered wake and
|
|
61
|
+
bounds the cascade's tmux re-validation (async 9000+SIGKILL); it never silences a
|
|
62
|
+
genuine recovery. `DegradedTmuxGuard` holds zero authority — it observes and
|
|
63
|
+
surfaces only.
|
|
64
|
+
|
|
65
|
+
## 5. Interactions
|
|
66
|
+
|
|
67
|
+
Reuses the existing `'event-loop-block'` WakeSuppressionReason + StallEvent (no
|
|
68
|
+
new telemetry shape). The async hot-path twins coexist with the legacy sync
|
|
69
|
+
methods behind `tmuxAsyncEnabled` (off ⇒ byte-identical legacy behavior — the e2e
|
|
70
|
+
observable-equivalence test). `getCachedRunningSessions()` is the cache the
|
|
71
|
+
request routes (GET /status et al.) now read; the non-request consumers
|
|
72
|
+
(JobScheduler, WebSocketManager, AutoUpdater) intentionally keep the live read
|
|
73
|
+
(documented residual, Increment 2 territory). Per-agent socket isolation is
|
|
74
|
+
explicitly OUT of Increment 1 (Increment 2).
|
|
75
|
+
|
|
76
|
+
## 6. Rollback
|
|
77
|
+
|
|
78
|
+
Each of the three flags is independently disable-able in `.instar/config.json`
|
|
79
|
+
(`monitoring.tmuxResilience.asyncHotPath.enabled`,
|
|
80
|
+
`monitoring.tmuxResilience.inFlightMarker.enabled`,
|
|
81
|
+
`monitoring.degradedTmuxGuard.enabled`) — set to `false` to revert that layer to
|
|
82
|
+
the pre-change behavior. The async hot path falls back to the sync path; the
|
|
83
|
+
marker branch goes inert; the guard stops observing. The migration strips only a
|
|
84
|
+
default-shaped persisted `false`, never an explicit operator `true`/`false`.
|
|
85
|
+
Config defaults OMIT `enabled` so the dev-gate (resolveDevAgentGate) governs:
|
|
86
|
+
fleet = dark, dev = live.
|