instar 1.3.607 → 1.3.608

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 (39) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +297 -31
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +22 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  8. package/dist/core/PostUpdateMigrator.js +18 -0
  9. package/dist/core/PostUpdateMigrator.js.map +1 -1
  10. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  11. package/dist/core/devGatedFeatures.js +6 -0
  12. package/dist/core/devGatedFeatures.js.map +1 -1
  13. package/dist/core/types.d.ts +37 -0
  14. package/dist/core/types.d.ts.map +1 -1
  15. package/dist/core/types.js.map +1 -1
  16. package/dist/monitoring/AutonomousLivenessReconciler.d.ts +278 -0
  17. package/dist/monitoring/AutonomousLivenessReconciler.d.ts.map +1 -0
  18. package/dist/monitoring/AutonomousLivenessReconciler.js +660 -0
  19. package/dist/monitoring/AutonomousLivenessReconciler.js.map +1 -0
  20. package/dist/monitoring/ResumeQueue.d.ts +10 -0
  21. package/dist/monitoring/ResumeQueue.d.ts.map +1 -1
  22. package/dist/monitoring/ResumeQueue.js +12 -0
  23. package/dist/monitoring/ResumeQueue.js.map +1 -1
  24. package/dist/scaffold/templates.d.ts.map +1 -1
  25. package/dist/scaffold/templates.js +4 -0
  26. package/dist/scaffold/templates.js.map +1 -1
  27. package/dist/server/AgentServer.d.ts +1 -0
  28. package/dist/server/AgentServer.d.ts.map +1 -1
  29. package/dist/server/AgentServer.js +6 -0
  30. package/dist/server/AgentServer.js.map +1 -1
  31. package/dist/server/routes.d.ts +4 -0
  32. package/dist/server/routes.d.ts.map +1 -1
  33. package/dist/server/routes.js +10 -0
  34. package/dist/server/routes.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/data/builtin-manifest.json +64 -64
  37. package/src/scaffold/templates.ts +4 -0
  38. package/upgrades/1.3.608.md +29 -0
  39. package/upgrades/side-effects/autonomous-liveness-reconciler.md +39 -0
@@ -0,0 +1,39 @@
1
+ # Side-Effects Review — AutonomousLivenessReconciler (self-heal a run marked active but with no live session)
2
+
3
+ **Spec:** docs/specs/autonomous-liveness-reconciler.md. **Constitutional principle served:** Structure > Willpower + "An autonomous run must outlive its session" — a level-triggered control loop replaces an edge-triggered heuristic that had a single-instant failure window.
4
+ **Ships DARK on the fleet** behind `monitoring.autonomousLivenessReconciler.enabled` (OMITTED in defaults → the dev-agent gate resolves it live-on-dev / dark-on-fleet) **and dryRun-first** (the component code-defaults `dryRun:true`). On the fleet the routes 503 and the loop never constructs/acts. On a dev agent the loop + route are live but only LOG "would respawn" until a deliberate `dryRun:false` flip.
5
+ **Files:** src/monitoring/AutonomousLivenessReconciler.ts (new), src/core/devGatedFeatures.ts, plus (pending in this branch) src/commands/server.ts, src/server/routes.ts, src/server/AgentServer.ts, src/config/ConfigDefaults.ts, src/core/PostUpdateMigrator.ts, src/scaffold/templates.ts, and the integration/e2e tests.
6
+
7
+ ## What changed
8
+
9
+ 1. **AutonomousLivenessReconciler.ts (new):** the level-triggered reconcile loop. Per tick it reads the active autonomous runs (reusing `activeAutonomousJobs` + `autonomousRunRemainingForTopic`), and for each evaluates 7 candidate criteria — active+remaining, NOT paused, NOT operator-stopped, NOT mid-machine-move, owned by THIS machine, NO live session, NOT already in the resume queue. A candidate must persist N consecutive ticks across a debounce window before action. Action = a respawn through the SAME spawn-with-resume primitive the ResumeQueueDrainer uses, bounded by a per-topic rolling-window cap (P19 loop brake) that gives up LOUDLY (one coalesced attention item) and posts one honest self-heal line.
10
+ 2. **devGatedFeatures.ts:** registers `autonomousLivenessReconciler` (configPath `monitoring.autonomousLivenessReconciler.enabled`) so the dev-agent gate resolves it live-on-dev / dark-fleet.
11
+ 3. **(pending) server.ts / AgentServer / routes.ts / ConfigDefaults / migrator / templates:** construct the loop behind the gate reusing the drainer's in-scope dep closures (`liveSessionForTopic`, `topicOwnerElsewhere`, `operatorStopSince`, quota), the `GET /autonomous/liveness` status route, the config block, and the migration + CLAUDE.md awareness.
12
+
13
+ ## Blast radius
14
+
15
+ - **Config-gated + dryRun-first.** Fleet: `enabled` resolves false → the loop is never constructed, the route 503s, zero behavior change. Dev: `enabled` resolves true but `dryRun:true` → the loop runs and LOGS "would respawn" without spawning anything. Only a deliberate `dryRun:false` makes it actuate.
16
+ - **No new outbound path of its own.** A respawn reuses the existing spawn-with-resume primitive; the self-heal notice + the give-up attention item reuse the existing send/aggregated-attention plumbing.
17
+ - **Coordinates with, never races, the ResumeQueue.** Criterion 7 (not-already-queued) + the multi-machine ownership criterion ensure the edge-triggered queue stays first responder; the reconciler only catches what the queue missed, and only on the owning machine.
18
+ - **Cost is O(active runs) per tick** (reads run-state files + a tmux-liveness check), same class as the reaper. No whole-tree walk.
19
+
20
+ ## Risk + mitigation
21
+
22
+ - **Risk:** the reconciler fights the reaper (respawns what was just deliberately killed). **Mitigation:** it acts ONLY when the run-state file still says active+remaining AND no operator-stop/pause is in effect — a deliberate stop sets those, excluding the run. Proven by the operator-stopped / paused unit cases.
23
+ - **Risk:** an infinite respawn loop on a run that keeps dying. **Mitigation:** the per-topic rolling-window cap (default 3/6h, durable across restarts) stops auto-respawn and raises ONE attention item. Proven by the loop-brake unit case.
24
+ - **Risk:** two machines both respawn the same run. **Mitigation:** the ownership criterion (only the owner reconciles) + the debounce window absorbing lease-move lag + the post-transfer closeout. Proven by the owner-elsewhere unit case.
25
+ - **Risk:** a transient gap (mid-recycle) triggers a needless respawn. **Mitigation:** the N-tick debounce across a window + criterion 7 (queue already handling it). Proven by the debounce-reset unit case.
26
+ - **Risk:** spawning under quota pressure. **Mitigation:** a per-respawn quota gate (skip + retry next tick). Proven by the quota unit case.
27
+ - **Direction of failure:** every dep read fails toward NOT acting (err toward "alive" / "owned elsewhere" / "stopped" / "queued"), so an uncertain read suppresses a respawn — the strictly-safe direction (a missed respawn is the status quo; a false respawn is bounded by the cap).
28
+
29
+ ## Migration parity
30
+
31
+ - (pending) `migrateConfig` adds the `monitoring.autonomousLivenessReconciler` block (existence-checked); the CLAUDE.md template gains the awareness section + proactive trigger ("user asks why a run died / didn't come back"). devGatedFeatures registration is in. No hook/skill/settings change.
32
+
33
+ ## Dark-gate line-map
34
+
35
+ - (pending) `ConfigDefaults.ts` adds the `monitoring.autonomousLivenessReconciler` block with `enabled` OMITTED (resolved by the dev-agent gate). `node scripts/lint-dev-agent-dark-gate.js` must stay clean (no hardcoded `enabled:false`); the golden-map drift-canary test will be updated for the new `enabled:`-free block's line shift.
36
+
37
+ ## Rollback
38
+
39
+ - Revert the PR, or set `monitoring.autonomousLivenessReconciler.enabled:false` (or leave dryRun:true). The loop never constructs / never actuates; the durable cap-state file is inert. Byte-identical to pre-PR behavior when off.