instar 0.28.75 → 0.28.77

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 (436) hide show
  1. package/dashboard/index.html +306 -0
  2. package/dist/cli.js +5 -4
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/discovery.d.ts.map +1 -1
  5. package/dist/commands/discovery.js +2 -1
  6. package/dist/commands/discovery.js.map +1 -1
  7. package/dist/commands/init.d.ts.map +1 -1
  8. package/dist/commands/init.js +22 -2
  9. package/dist/commands/init.js.map +1 -1
  10. package/dist/commands/job.d.ts.map +1 -1
  11. package/dist/commands/job.js +2 -1
  12. package/dist/commands/job.js.map +1 -1
  13. package/dist/commands/ledgerCleanup.d.ts.map +1 -1
  14. package/dist/commands/ledgerCleanup.js +2 -1
  15. package/dist/commands/ledgerCleanup.js.map +1 -1
  16. package/dist/commands/listener.d.ts.map +1 -1
  17. package/dist/commands/listener.js +7 -6
  18. package/dist/commands/listener.js.map +1 -1
  19. package/dist/commands/nuke.d.ts.map +1 -1
  20. package/dist/commands/nuke.js +11 -15
  21. package/dist/commands/nuke.js.map +1 -1
  22. package/dist/commands/server.d.ts.map +1 -1
  23. package/dist/commands/server.js +35 -3
  24. package/dist/commands/server.js.map +1 -1
  25. package/dist/commands/setup.d.ts.map +1 -1
  26. package/dist/commands/setup.js +11 -9
  27. package/dist/commands/setup.js.map +1 -1
  28. package/dist/commands/slack-cli.d.ts.map +1 -1
  29. package/dist/commands/slack-cli.js +5 -4
  30. package/dist/commands/slack-cli.js.map +1 -1
  31. package/dist/commands/whatsapp.d.ts.map +1 -1
  32. package/dist/commands/whatsapp.js +2 -1
  33. package/dist/commands/whatsapp.js.map +1 -1
  34. package/dist/commands/worktree.d.ts.map +1 -1
  35. package/dist/commands/worktree.js +2 -1
  36. package/dist/commands/worktree.js.map +1 -1
  37. package/dist/core/AgentConnector.d.ts.map +1 -1
  38. package/dist/core/AgentConnector.js +9 -7
  39. package/dist/core/AgentConnector.js.map +1 -1
  40. package/dist/core/AgentRegistry.d.ts.map +1 -1
  41. package/dist/core/AgentRegistry.js +3 -2
  42. package/dist/core/AgentRegistry.js.map +1 -1
  43. package/dist/core/AutoDispatcher.d.ts.map +1 -1
  44. package/dist/core/AutoDispatcher.js +2 -1
  45. package/dist/core/AutoDispatcher.js.map +1 -1
  46. package/dist/core/AutoUpdater.d.ts.map +1 -1
  47. package/dist/core/AutoUpdater.js +2 -1
  48. package/dist/core/AutoUpdater.js.map +1 -1
  49. package/dist/core/AutonomousEvolution.d.ts.map +1 -1
  50. package/dist/core/AutonomousEvolution.js +2 -1
  51. package/dist/core/AutonomousEvolution.js.map +1 -1
  52. package/dist/core/BackupManager.d.ts.map +1 -1
  53. package/dist/core/BackupManager.js +2 -1
  54. package/dist/core/BackupManager.js.map +1 -1
  55. package/dist/core/BranchManager.d.ts.map +1 -1
  56. package/dist/core/BranchManager.js +3 -2
  57. package/dist/core/BranchManager.js.map +1 -1
  58. package/dist/core/CaffeinateManager.d.ts.map +1 -1
  59. package/dist/core/CaffeinateManager.js +2 -1
  60. package/dist/core/CaffeinateManager.js.map +1 -1
  61. package/dist/core/DeferredDispatchTracker.d.ts.map +1 -1
  62. package/dist/core/DeferredDispatchTracker.js +2 -1
  63. package/dist/core/DeferredDispatchTracker.js.map +1 -1
  64. package/dist/core/DispatchManager.d.ts.map +1 -1
  65. package/dist/core/DispatchManager.js +3 -2
  66. package/dist/core/DispatchManager.js.map +1 -1
  67. package/dist/core/EvolutionManager.d.ts.map +1 -1
  68. package/dist/core/EvolutionManager.js +2 -1
  69. package/dist/core/EvolutionManager.js.map +1 -1
  70. package/dist/core/ExecutionJournal.d.ts.map +1 -1
  71. package/dist/core/ExecutionJournal.js +2 -1
  72. package/dist/core/ExecutionJournal.js.map +1 -1
  73. package/dist/core/FeedbackManager.d.ts.map +1 -1
  74. package/dist/core/FeedbackManager.js +2 -1
  75. package/dist/core/FeedbackManager.js.map +1 -1
  76. package/dist/core/FileClassifier.d.ts.map +1 -1
  77. package/dist/core/FileClassifier.js +8 -13
  78. package/dist/core/FileClassifier.js.map +1 -1
  79. package/dist/core/ForegroundRestartWatcher.d.ts.map +1 -1
  80. package/dist/core/ForegroundRestartWatcher.js +3 -2
  81. package/dist/core/ForegroundRestartWatcher.js.map +1 -1
  82. package/dist/core/GitStateManager.d.ts.map +1 -1
  83. package/dist/core/GitStateManager.js +3 -11
  84. package/dist/core/GitStateManager.js.map +1 -1
  85. package/dist/core/GitSync.d.ts.map +1 -1
  86. package/dist/core/GitSync.js +6 -3
  87. package/dist/core/GitSync.js.map +1 -1
  88. package/dist/core/GlobalInstallCleanup.d.ts.map +1 -1
  89. package/dist/core/GlobalInstallCleanup.js +3 -2
  90. package/dist/core/GlobalInstallCleanup.js.map +1 -1
  91. package/dist/core/GlobalSecretStore.d.ts.map +1 -1
  92. package/dist/core/GlobalSecretStore.js +3 -2
  93. package/dist/core/GlobalSecretStore.js.map +1 -1
  94. package/dist/core/HandoffManager.d.ts.map +1 -1
  95. package/dist/core/HandoffManager.js +5 -3
  96. package/dist/core/HandoffManager.js.map +1 -1
  97. package/dist/core/JargonDetector.d.ts +28 -0
  98. package/dist/core/JargonDetector.d.ts.map +1 -0
  99. package/dist/core/JargonDetector.js +59 -0
  100. package/dist/core/JargonDetector.js.map +1 -0
  101. package/dist/core/LedgerSessionRegistry.d.ts.map +1 -1
  102. package/dist/core/LedgerSessionRegistry.js +2 -1
  103. package/dist/core/LedgerSessionRegistry.js.map +1 -1
  104. package/dist/core/MachineIdentity.d.ts.map +1 -1
  105. package/dist/core/MachineIdentity.js +2 -1
  106. package/dist/core/MachineIdentity.js.map +1 -1
  107. package/dist/core/MessagingToneGate.d.ts +42 -5
  108. package/dist/core/MessagingToneGate.d.ts.map +1 -1
  109. package/dist/core/MessagingToneGate.js +40 -6
  110. package/dist/core/MessagingToneGate.js.map +1 -1
  111. package/dist/core/ParallelDevWiring.d.ts.map +1 -1
  112. package/dist/core/ParallelDevWiring.js +3 -5
  113. package/dist/core/ParallelDevWiring.js.map +1 -1
  114. package/dist/core/PostUpdateMigrator.d.ts +26 -0
  115. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  116. package/dist/core/PostUpdateMigrator.js +249 -44
  117. package/dist/core/PostUpdateMigrator.js.map +1 -1
  118. package/dist/core/ProjectMapper.d.ts.map +1 -1
  119. package/dist/core/ProjectMapper.js +5 -9
  120. package/dist/core/ProjectMapper.js.map +1 -1
  121. package/dist/core/RelationshipManager.d.ts.map +1 -1
  122. package/dist/core/RelationshipManager.js +4 -3
  123. package/dist/core/RelationshipManager.js.map +1 -1
  124. package/dist/core/SafeFsExecutor.d.ts +41 -0
  125. package/dist/core/SafeFsExecutor.d.ts.map +1 -0
  126. package/dist/core/SafeFsExecutor.js +146 -0
  127. package/dist/core/SafeFsExecutor.js.map +1 -0
  128. package/dist/core/SafeGitExecutor.d.ts +145 -0
  129. package/dist/core/SafeGitExecutor.d.ts.map +1 -0
  130. package/dist/core/SafeGitExecutor.js +717 -0
  131. package/dist/core/SafeGitExecutor.js.map +1 -0
  132. package/dist/core/ScopeVerifier.d.ts.map +1 -1
  133. package/dist/core/ScopeVerifier.js +3 -5
  134. package/dist/core/ScopeVerifier.js.map +1 -1
  135. package/dist/core/SecretStore.d.ts.map +1 -1
  136. package/dist/core/SecretStore.js +2 -1
  137. package/dist/core/SecretStore.js.map +1 -1
  138. package/dist/core/SharedStateLedger.d.ts.map +1 -1
  139. package/dist/core/SharedStateLedger.js +2 -1
  140. package/dist/core/SharedStateLedger.js.map +1 -1
  141. package/dist/core/SoulManager.d.ts.map +1 -1
  142. package/dist/core/SoulManager.js +3 -2
  143. package/dist/core/SoulManager.js.map +1 -1
  144. package/dist/core/StateManager.d.ts.map +1 -1
  145. package/dist/core/StateManager.js +4 -3
  146. package/dist/core/StateManager.js.map +1 -1
  147. package/dist/core/SyncOrchestrator.d.ts.map +1 -1
  148. package/dist/core/SyncOrchestrator.js +6 -4
  149. package/dist/core/SyncOrchestrator.js.map +1 -1
  150. package/dist/core/UpdateChecker.d.ts.map +1 -1
  151. package/dist/core/UpdateChecker.js +3 -2
  152. package/dist/core/UpdateChecker.js.map +1 -1
  153. package/dist/core/UpgradeGuideProcessor.d.ts.map +1 -1
  154. package/dist/core/UpgradeGuideProcessor.js +3 -2
  155. package/dist/core/UpgradeGuideProcessor.js.map +1 -1
  156. package/dist/core/WorktreeManager.d.ts.map +1 -1
  157. package/dist/core/WorktreeManager.js +9 -7
  158. package/dist/core/WorktreeManager.js.map +1 -1
  159. package/dist/knowledge/KnowledgeManager.d.ts.map +1 -1
  160. package/dist/knowledge/KnowledgeManager.js +2 -1
  161. package/dist/knowledge/KnowledgeManager.js.map +1 -1
  162. package/dist/lifeline/ServerSupervisor.d.ts +28 -0
  163. package/dist/lifeline/ServerSupervisor.d.ts.map +1 -1
  164. package/dist/lifeline/ServerSupervisor.js +171 -59
  165. package/dist/lifeline/ServerSupervisor.js.map +1 -1
  166. package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
  167. package/dist/lifeline/TelegramLifeline.js +10 -3
  168. package/dist/lifeline/TelegramLifeline.js.map +1 -1
  169. package/dist/lifeline/detectLaunchdSupervised.d.ts +43 -0
  170. package/dist/lifeline/detectLaunchdSupervised.d.ts.map +1 -0
  171. package/dist/lifeline/detectLaunchdSupervised.js +106 -0
  172. package/dist/lifeline/detectLaunchdSupervised.js.map +1 -0
  173. package/dist/lifeline/droppedMessages.d.ts.map +1 -1
  174. package/dist/lifeline/droppedMessages.js +2 -1
  175. package/dist/lifeline/droppedMessages.js.map +1 -1
  176. package/dist/memory/EpisodicMemory.d.ts.map +1 -1
  177. package/dist/memory/EpisodicMemory.js +2 -1
  178. package/dist/memory/EpisodicMemory.js.map +1 -1
  179. package/dist/memory/TopicMemory.d.ts.map +1 -1
  180. package/dist/memory/TopicMemory.js +5 -4
  181. package/dist/memory/TopicMemory.js.map +1 -1
  182. package/dist/messaging/AgentTokenManager.d.ts.map +1 -1
  183. package/dist/messaging/AgentTokenManager.js +2 -1
  184. package/dist/messaging/AgentTokenManager.js.map +1 -1
  185. package/dist/messaging/DropPickup.d.ts.map +1 -1
  186. package/dist/messaging/DropPickup.js +2 -1
  187. package/dist/messaging/DropPickup.js.map +1 -1
  188. package/dist/messaging/GitSyncTransport.d.ts.map +1 -1
  189. package/dist/messaging/GitSyncTransport.js +4 -3
  190. package/dist/messaging/GitSyncTransport.js.map +1 -1
  191. package/dist/messaging/MessageStore.d.ts.map +1 -1
  192. package/dist/messaging/MessageStore.js +3 -2
  193. package/dist/messaging/MessageStore.js.map +1 -1
  194. package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
  195. package/dist/messaging/TelegramAdapter.js +5 -4
  196. package/dist/messaging/TelegramAdapter.js.map +1 -1
  197. package/dist/messaging/backends/BaileysBackend.d.ts.map +1 -1
  198. package/dist/messaging/backends/BaileysBackend.js +3 -2
  199. package/dist/messaging/backends/BaileysBackend.js.map +1 -1
  200. package/dist/messaging/local-tone-check.d.ts +61 -0
  201. package/dist/messaging/local-tone-check.d.ts.map +1 -0
  202. package/dist/messaging/local-tone-check.js +78 -0
  203. package/dist/messaging/local-tone-check.js.map +1 -0
  204. package/dist/messaging/pending-relay-store.d.ts +153 -0
  205. package/dist/messaging/pending-relay-store.d.ts.map +1 -0
  206. package/dist/messaging/pending-relay-store.js +351 -0
  207. package/dist/messaging/pending-relay-store.js.map +1 -0
  208. package/dist/messaging/secret-patterns.d.ts +35 -0
  209. package/dist/messaging/secret-patterns.d.ts.map +1 -0
  210. package/dist/messaging/secret-patterns.js +70 -0
  211. package/dist/messaging/secret-patterns.js.map +1 -0
  212. package/dist/messaging/shared/EncryptedAuthStore.d.ts.map +1 -1
  213. package/dist/messaging/shared/EncryptedAuthStore.js +3 -2
  214. package/dist/messaging/shared/EncryptedAuthStore.js.map +1 -1
  215. package/dist/messaging/shared/MessageLogger.d.ts.map +1 -1
  216. package/dist/messaging/shared/MessageLogger.js +2 -1
  217. package/dist/messaging/shared/MessageLogger.js.map +1 -1
  218. package/dist/messaging/shared/PrivacyConsent.d.ts.map +1 -1
  219. package/dist/messaging/shared/PrivacyConsent.js +2 -1
  220. package/dist/messaging/shared/PrivacyConsent.js.map +1 -1
  221. package/dist/messaging/shared/SessionChannelRegistry.d.ts.map +1 -1
  222. package/dist/messaging/shared/SessionChannelRegistry.js +2 -1
  223. package/dist/messaging/shared/SessionChannelRegistry.js.map +1 -1
  224. package/dist/messaging/system-templates.d.ts +87 -0
  225. package/dist/messaging/system-templates.d.ts.map +1 -0
  226. package/dist/messaging/system-templates.js +236 -0
  227. package/dist/messaging/system-templates.js.map +1 -0
  228. package/dist/messaging/whoami-cache.d.ts +66 -0
  229. package/dist/messaging/whoami-cache.d.ts.map +1 -0
  230. package/dist/messaging/whoami-cache.js +149 -0
  231. package/dist/messaging/whoami-cache.js.map +1 -0
  232. package/dist/moltbridge/ProfileCompiler.d.ts.map +1 -1
  233. package/dist/moltbridge/ProfileCompiler.js +13 -4
  234. package/dist/moltbridge/ProfileCompiler.js.map +1 -1
  235. package/dist/monitoring/CommitmentTracker.d.ts.map +1 -1
  236. package/dist/monitoring/CommitmentTracker.js +2 -1
  237. package/dist/monitoring/CommitmentTracker.js.map +1 -1
  238. package/dist/monitoring/CredentialProvider.d.ts.map +1 -1
  239. package/dist/monitoring/CredentialProvider.js +2 -1
  240. package/dist/monitoring/CredentialProvider.js.map +1 -1
  241. package/dist/monitoring/DegradationReporter.d.ts +41 -0
  242. package/dist/monitoring/DegradationReporter.d.ts.map +1 -1
  243. package/dist/monitoring/DegradationReporter.js +96 -4
  244. package/dist/monitoring/DegradationReporter.js.map +1 -1
  245. package/dist/monitoring/HealthChecker.d.ts.map +1 -1
  246. package/dist/monitoring/HealthChecker.js +2 -1
  247. package/dist/monitoring/HealthChecker.js.map +1 -1
  248. package/dist/monitoring/HookEventReceiver.d.ts.map +1 -1
  249. package/dist/monitoring/HookEventReceiver.js +2 -1
  250. package/dist/monitoring/HookEventReceiver.js.map +1 -1
  251. package/dist/monitoring/InstructionsVerifier.d.ts.map +1 -1
  252. package/dist/monitoring/InstructionsVerifier.js +2 -1
  253. package/dist/monitoring/InstructionsVerifier.js.map +1 -1
  254. package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
  255. package/dist/monitoring/PresenceProxy.js +5 -4
  256. package/dist/monitoring/PresenceProxy.js.map +1 -1
  257. package/dist/monitoring/QuotaTracker.d.ts.map +1 -1
  258. package/dist/monitoring/QuotaTracker.js +2 -1
  259. package/dist/monitoring/QuotaTracker.js.map +1 -1
  260. package/dist/monitoring/SessionMigrator.d.ts.map +1 -1
  261. package/dist/monitoring/SessionMigrator.js +2 -1
  262. package/dist/monitoring/SessionMigrator.js.map +1 -1
  263. package/dist/monitoring/SessionRecovery.d.ts.map +1 -1
  264. package/dist/monitoring/SessionRecovery.js +2 -1
  265. package/dist/monitoring/SessionRecovery.js.map +1 -1
  266. package/dist/monitoring/TelemetryAuth.d.ts.map +1 -1
  267. package/dist/monitoring/TelemetryAuth.js +3 -2
  268. package/dist/monitoring/TelemetryAuth.js.map +1 -1
  269. package/dist/monitoring/TokenLedger.d.ts +91 -0
  270. package/dist/monitoring/TokenLedger.d.ts.map +1 -0
  271. package/dist/monitoring/TokenLedger.js +426 -0
  272. package/dist/monitoring/TokenLedger.js.map +1 -0
  273. package/dist/monitoring/TokenLedgerPoller.d.ts +26 -0
  274. package/dist/monitoring/TokenLedgerPoller.d.ts.map +1 -0
  275. package/dist/monitoring/TokenLedgerPoller.js +44 -0
  276. package/dist/monitoring/TokenLedgerPoller.js.map +1 -0
  277. package/dist/monitoring/TriageOrchestrator.d.ts.map +1 -1
  278. package/dist/monitoring/TriageOrchestrator.js +3 -2
  279. package/dist/monitoring/TriageOrchestrator.js.map +1 -1
  280. package/dist/monitoring/WorktreeReaper.d.ts.map +1 -1
  281. package/dist/monitoring/WorktreeReaper.js +5 -4
  282. package/dist/monitoring/WorktreeReaper.js.map +1 -1
  283. package/dist/monitoring/delivery-failure-sentinel/recovery-policy.d.ts +83 -0
  284. package/dist/monitoring/delivery-failure-sentinel/recovery-policy.d.ts.map +1 -0
  285. package/dist/monitoring/delivery-failure-sentinel/recovery-policy.js +218 -0
  286. package/dist/monitoring/delivery-failure-sentinel/recovery-policy.js.map +1 -0
  287. package/dist/monitoring/delivery-failure-sentinel.d.ts +177 -0
  288. package/dist/monitoring/delivery-failure-sentinel.d.ts.map +1 -0
  289. package/dist/monitoring/delivery-failure-sentinel.js +598 -0
  290. package/dist/monitoring/delivery-failure-sentinel.js.map +1 -0
  291. package/dist/monitoring/probes/PlatformProbe.d.ts.map +1 -1
  292. package/dist/monitoring/probes/PlatformProbe.js +3 -2
  293. package/dist/monitoring/probes/PlatformProbe.js.map +1 -1
  294. package/dist/monitoring/templates-drift-verifier.d.ts +109 -0
  295. package/dist/monitoring/templates-drift-verifier.d.ts.map +1 -0
  296. package/dist/monitoring/templates-drift-verifier.js +324 -0
  297. package/dist/monitoring/templates-drift-verifier.js.map +1 -0
  298. package/dist/paste/PasteManager.d.ts.map +1 -1
  299. package/dist/paste/PasteManager.js +5 -4
  300. package/dist/paste/PasteManager.js.map +1 -1
  301. package/dist/publishing/PrivateViewer.d.ts.map +1 -1
  302. package/dist/publishing/PrivateViewer.js +2 -1
  303. package/dist/publishing/PrivateViewer.js.map +1 -1
  304. package/dist/scheduler/JobScheduler.d.ts.map +1 -1
  305. package/dist/scheduler/JobScheduler.js +2 -1
  306. package/dist/scheduler/JobScheduler.js.map +1 -1
  307. package/dist/server/AgentServer.d.ts +18 -0
  308. package/dist/server/AgentServer.d.ts.map +1 -1
  309. package/dist/server/AgentServer.js +186 -1
  310. package/dist/server/AgentServer.js.map +1 -1
  311. package/dist/server/WebSocketManager.d.ts +11 -0
  312. package/dist/server/WebSocketManager.d.ts.map +1 -1
  313. package/dist/server/WebSocketManager.js +28 -0
  314. package/dist/server/WebSocketManager.js.map +1 -1
  315. package/dist/server/boot-id.d.ts +58 -0
  316. package/dist/server/boot-id.d.ts.map +1 -0
  317. package/dist/server/boot-id.js +121 -0
  318. package/dist/server/boot-id.js.map +1 -0
  319. package/dist/server/middleware.d.ts +14 -1
  320. package/dist/server/middleware.d.ts.map +1 -1
  321. package/dist/server/middleware.js +81 -1
  322. package/dist/server/middleware.js.map +1 -1
  323. package/dist/server/routes.d.ts +69 -0
  324. package/dist/server/routes.d.ts.map +1 -1
  325. package/dist/server/routes.js +545 -16
  326. package/dist/server/routes.js.map +1 -1
  327. package/dist/threadline/AgentDiscovery.d.ts.map +1 -1
  328. package/dist/threadline/AgentDiscovery.js +2 -1
  329. package/dist/threadline/AgentDiscovery.js.map +1 -1
  330. package/dist/threadline/AgentTrustManager.d.ts.map +1 -1
  331. package/dist/threadline/AgentTrustManager.js +2 -1
  332. package/dist/threadline/AgentTrustManager.js.map +1 -1
  333. package/dist/threadline/CircuitBreaker.d.ts.map +1 -1
  334. package/dist/threadline/CircuitBreaker.js +2 -1
  335. package/dist/threadline/CircuitBreaker.js.map +1 -1
  336. package/dist/threadline/ComputeMeter.d.ts.map +1 -1
  337. package/dist/threadline/ComputeMeter.js +2 -1
  338. package/dist/threadline/ComputeMeter.js.map +1 -1
  339. package/dist/threadline/ContextThreadMap.d.ts.map +1 -1
  340. package/dist/threadline/ContextThreadMap.js +2 -1
  341. package/dist/threadline/ContextThreadMap.js.map +1 -1
  342. package/dist/threadline/HeartbeatWatchdog.d.ts +78 -0
  343. package/dist/threadline/HeartbeatWatchdog.d.ts.map +1 -0
  344. package/dist/threadline/HeartbeatWatchdog.js +212 -0
  345. package/dist/threadline/HeartbeatWatchdog.js.map +1 -0
  346. package/dist/threadline/HeartbeatWriter.d.ts +79 -0
  347. package/dist/threadline/HeartbeatWriter.d.ts.map +1 -0
  348. package/dist/threadline/HeartbeatWriter.js +109 -0
  349. package/dist/threadline/HeartbeatWriter.js.map +1 -0
  350. package/dist/threadline/InvitationManager.d.ts.map +1 -1
  351. package/dist/threadline/InvitationManager.js +2 -1
  352. package/dist/threadline/InvitationManager.js.map +1 -1
  353. package/dist/threadline/ListenerSessionManager.d.ts +24 -0
  354. package/dist/threadline/ListenerSessionManager.d.ts.map +1 -1
  355. package/dist/threadline/ListenerSessionManager.js +38 -0
  356. package/dist/threadline/ListenerSessionManager.js.map +1 -1
  357. package/dist/threadline/MCPAuth.d.ts.map +1 -1
  358. package/dist/threadline/MCPAuth.js +2 -1
  359. package/dist/threadline/MCPAuth.js.map +1 -1
  360. package/dist/threadline/PipeSessionSpawner.d.ts.map +1 -1
  361. package/dist/threadline/PipeSessionSpawner.js +3 -2
  362. package/dist/threadline/PipeSessionSpawner.js.map +1 -1
  363. package/dist/threadline/RateLimiter.d.ts.map +1 -1
  364. package/dist/threadline/RateLimiter.js +2 -1
  365. package/dist/threadline/RateLimiter.js.map +1 -1
  366. package/dist/threadline/RelaySpawnFailureHandler.d.ts +53 -0
  367. package/dist/threadline/RelaySpawnFailureHandler.d.ts.map +1 -0
  368. package/dist/threadline/RelaySpawnFailureHandler.js +73 -0
  369. package/dist/threadline/RelaySpawnFailureHandler.js.map +1 -0
  370. package/dist/threadline/SessionLifecycle.d.ts.map +1 -1
  371. package/dist/threadline/SessionLifecycle.js +2 -1
  372. package/dist/threadline/SessionLifecycle.js.map +1 -1
  373. package/dist/threadline/SpawnLedger.d.ts +94 -0
  374. package/dist/threadline/SpawnLedger.d.ts.map +1 -0
  375. package/dist/threadline/SpawnLedger.js +194 -0
  376. package/dist/threadline/SpawnLedger.js.map +1 -0
  377. package/dist/threadline/SpawnNonce.d.ts +49 -0
  378. package/dist/threadline/SpawnNonce.d.ts.map +1 -0
  379. package/dist/threadline/SpawnNonce.js +99 -0
  380. package/dist/threadline/SpawnNonce.js.map +1 -0
  381. package/dist/threadline/TelegramBridgeConfig.d.ts +79 -0
  382. package/dist/threadline/TelegramBridgeConfig.d.ts.map +1 -0
  383. package/dist/threadline/TelegramBridgeConfig.js +168 -0
  384. package/dist/threadline/TelegramBridgeConfig.js.map +1 -0
  385. package/dist/threadline/ThreadlineBootstrap.d.ts.map +1 -1
  386. package/dist/threadline/ThreadlineBootstrap.js +2 -1
  387. package/dist/threadline/ThreadlineBootstrap.js.map +1 -1
  388. package/dist/threadline/WakeSocketServer.d.ts.map +1 -1
  389. package/dist/threadline/WakeSocketServer.js +3 -2
  390. package/dist/threadline/WakeSocketServer.js.map +1 -1
  391. package/dist/threadline/listener-daemon.d.ts.map +1 -1
  392. package/dist/threadline/listener-daemon.js +3 -2
  393. package/dist/threadline/listener-daemon.js.map +1 -1
  394. package/dist/users/UserManager.d.ts.map +1 -1
  395. package/dist/users/UserManager.js +2 -1
  396. package/dist/users/UserManager.js.map +1 -1
  397. package/dist/users/UserOnboarding.d.ts.map +1 -1
  398. package/dist/users/UserOnboarding.js +2 -1
  399. package/dist/users/UserOnboarding.js.map +1 -1
  400. package/dist/utils/jsonl-rotation.d.ts.map +1 -1
  401. package/dist/utils/jsonl-rotation.js +2 -1
  402. package/dist/utils/jsonl-rotation.js.map +1 -1
  403. package/package.json +4 -2
  404. package/scripts/add-migration-marker.js +121 -0
  405. package/scripts/analyze-release.js +7 -6
  406. package/scripts/check-contract-evidence.js +27 -8
  407. package/scripts/destructive-command-shim.js +1 -0
  408. package/scripts/generate-builtin-manifest.cjs +1 -0
  409. package/scripts/lint-no-direct-destructive.js +617 -0
  410. package/scripts/lint-template-sha-history.ts +183 -0
  411. package/scripts/migrate-incident-2026-04-17.mjs +2 -1
  412. package/scripts/pre-push-gate.js +24 -0
  413. package/scripts/run-migration.js +500 -0
  414. package/scripts/test-bootstrap-relay.mjs +2 -1
  415. package/scripts/verify-deployed-templates.ts +87 -0
  416. package/scripts/worktree-commit-msg-hook.js +4 -0
  417. package/scripts/worktree-precommit-gate.js +1 -0
  418. package/src/data/builtin-manifest.json +139 -131
  419. package/src/templates/scripts/telegram-reply.sh +318 -13
  420. package/upgrades/0.28.76.md +67 -0
  421. package/upgrades/0.28.77.md +133 -0
  422. package/upgrades/side-effects/0.28.76.md +76 -0
  423. package/upgrades/side-effects/agent-health-alert-authority-routing.md +121 -0
  424. package/upgrades/side-effects/comprehensive-destructive-tool-containment-foundation.md +74 -0
  425. package/upgrades/side-effects/comprehensive-destructive-tool-containment-migration.md +82 -0
  426. package/upgrades/side-effects/deferral-detector-orphan-todo.md +101 -0
  427. package/upgrades/side-effects/lifeline-self-heal-hardening.md +151 -0
  428. package/upgrades/side-effects/relay-spawn-ghost-reply-phase1.md +139 -0
  429. package/upgrades/side-effects/telegram-delivery-robustness-layer-2.md +320 -0
  430. package/upgrades/side-effects/telegram-delivery-robustness-layer-3.md +202 -0
  431. package/upgrades/side-effects/telegram-delivery-robustness-layer-7.md +339 -0
  432. package/upgrades/side-effects/telegram-delivery-robustness.md +178 -0
  433. package/upgrades/side-effects/threadline-canonical-inbox-write.md +218 -0
  434. package/upgrades/side-effects/threadline-tg-bridge-settings-surface.md +208 -0
  435. package/upgrades/side-effects/token-ledger-phase1.md +123 -0
  436. package/upgrades/NEXT.md +0 -53
@@ -0,0 +1,139 @@
1
+ # Side-Effects Review — Relay-Spawn Ghost-Reply Containment, Phase 1a (Foundation)
2
+
3
+ **Version / slug:** `relay-spawn-ghost-reply-phase1a-foundation`
4
+ **Date:** `2026-04-29`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required for this scope — pure new modules behind no call sites; mandatory for the Phase 1b wiring PR (see Integration plan below)`
7
+ **Spec:** `docs/specs/RELAY-SPAWN-GHOST-REPLY-CONTAINMENT-SPEC.md` (review-converged 2026-04-29, approved by justin)
8
+ **Scope split:** This PR ships ONLY the foundation modules — five new files plus full unit-test coverage. No call-site is modified. The integration wiring (modify ThreadlineRouter / PipeSessionSpawner / ListenerSessionManager / ThreadlineMCPServer / PostUpdateMigrator / BackupManager / ConfigDefaults) is the Phase 1b PR, tracked as ACT-801 (high, due within 7 days). Phase 2 (Component D — out-of-process shim trace recorder) is ACT-780. Phase 3 (Component E — quarantine queue + dashboard) is ACT-781. Phase-1b ships behind a default-OFF feature flag.
9
+
10
+ ## Phase 1 — Principle check (per /instar-dev)
11
+
12
+ **Question:** "Does this change involve a decision point — gating information flow, blocking actions, filtering messages, or constraining agent behavior?"
13
+
14
+ **Answer:** Per `docs/signal-vs-authority.md`:
15
+ - **`SpawnLedger.tryReserve`** is an *authority* (idempotency-key exception explicitly permitted by the principle: "Idempotency keys and dedup at the transport layer ... not a judgment call — it's mechanics"). It has no behavioral side-effect in this PR because no caller invokes it yet; the authority is dormant infrastructure.
16
+ - **`HeartbeatWatchdog`** is a pure *signal-producer*. Emits `heartbeat-missing|forged|stale|pid-dead|verified` events to a registered consumer. No blocking, no kill power. Dormant in this PR (not started by any composition root).
17
+ - **`RelaySpawnFailureHandler`** is the *smart authority* that consumes watchdog signals and decides verified vs failed-quarantined. Single authority per decision point. Dormant in this PR.
18
+ - **`HeartbeatWriter`** and **`SpawnNonce`** are pure utilities — no decisions, no signals.
19
+
20
+ The principle check is satisfied: every brittle structural check (CAS, HMAC verify) operates on structural concerns where authority is permitted. Every judgment-class concern routes through the smart-authority handler. Because nothing is wired in this PR, the principle check is a no-op operationally — but the modules carry the correct shape for the wiring PR.
21
+
22
+ ## Summary of the change
23
+
24
+ Adds five new files under `src/threadline/` plus their unit tests. Zero existing files are modified. No production code path is altered.
25
+
26
+ Files added:
27
+ - `src/threadline/SpawnLedger.ts` — SQLite-backed CAS ledger (`INSERT OR FAIL` on eventId PK), per-peer rolling rate cap, global hard cap, HMAC heartbeat verification with `crypto.timingSafeEqual`, prune-terminal helper that NEVER prunes in-flight rows, `listSpawning()` enumerator for the watchdog.
28
+ - `src/threadline/SpawnNonce.ts` — `deriveEventId(envelope)` (sha256 of `signedBy || nonce || messageId` — bound to authenticated material) plus `prepareNonceFd(nonce)` for FD-3 pipe handoff (tmpfile + immediate-unlink pattern, portable substitute for POSIX pipe(2)).
29
+ - `src/threadline/HeartbeatWriter.ts` — utility for spawned sessions to write atomic-rename signed heartbeats; `readSpawnNonceFromFd3()` for the spawned-session boot path.
30
+ - `src/threadline/HeartbeatWatchdog.ts` — single-shared 1s-poller, signal-producer with strict signal kinds, no-throw tick guarantee, verified-once and terminal-once dedup.
31
+ - `src/threadline/RelaySpawnFailureHandler.ts` — smart authority that translates signals to ledger transitions plus quarantine + thread-opened-emit decisions.
32
+
33
+ Tests added (50 new tests, all green):
34
+ - `tests/unit/threadline/SpawnLedger.test.ts` — 15 tests
35
+ - `tests/unit/threadline/HeartbeatWriter.test.ts` — 7 tests
36
+ - `tests/unit/threadline/HeartbeatWatchdog.test.ts` — 9 tests
37
+ - `tests/unit/threadline/RelaySpawnFailureHandler.test.ts` — 7 tests
38
+ - `tests/unit/threadline/SpawnNonce.test.ts` — 8 tests
39
+ - `tests/unit/threadline/spawn-guard-incident-repro.test.ts` — 4 tests (module-level reproduction of the original ghost-reply incident: ghost session → quarantine + no thread-opened; healthy session → thread-opened exactly once; forged heartbeat → quarantined as forged; replay → second reservation rejected)
40
+
41
+ ## Decision-point inventory
42
+
43
+ - `SpawnLedger.tryReserve(eventId, peerId)` — **add** — authority (idempotency-key dedup; permitted exception). Inert until Phase 1b wires the call site.
44
+ - `HeartbeatWatchdog.tick()` — **add** — signal-producer. Inert until Phase 1b starts the timer in a composition root.
45
+ - `RelaySpawnFailureHandler.handle(signal)` — **add** — smart authority. Inert until Phase 1b registers it as the watchdog consumer.
46
+
47
+ ## 1. Over-block
48
+
49
+ **What legitimate inputs does this change reject that it shouldn't?**
50
+
51
+ Operationally — none, because no call site invokes the new code. The modules' over-block surface (Phase 1b: a retry of a legitimately-failed spawn carries the same eventId and is rejected) is documented in the spec under §Component A and addressed via the manual-retry admin endpoint that ships in Phase 1b. The conservative posture is intentional: auto-retry after a forged-heartbeat is itself a vector.
52
+
53
+ ## 2. Under-block
54
+
55
+ **What failure modes does this still miss?**
56
+
57
+ - Multi-machine duplicate spawn on the same envelope across paired-instar deployments: explicitly out of scope, tracked by ACT-776 (`MULTI-MACHINE-SPAWN-LEDGER-SPEC.md`).
58
+ - A non-cooperating session that bypasses the heartbeat instruction entirely is correctly caught by `heartbeat-missing` — but only when the watchdog is started, which is Phase 1b. In this PR the under-block is total because nothing runs.
59
+ - Reply-content fabrication is NOT addressed by Phase 1 at all; Component D ships as Phase 2 (ACT-780).
60
+
61
+ ## 3. Level-of-abstraction fit
62
+
63
+ `SpawnLedger` is a structural primitive. SQLite with `INSERT OR FAIL` is exactly the right primitive for idempotency-key dedup. `HeartbeatWatchdog` is a single-poller pattern at the right layer (one timer, one readdir per tick, fan-out into structured signals). `RelaySpawnFailureHandler` is the smart authority. `HeartbeatWriter` and `SpawnNonce` are pure utilities. All five live as siblings under `src/threadline/`, the right namespace for the relay path.
64
+
65
+ The Phase-1a/1b split is itself a level-of-abstraction call: shipping the foundation as a self-contained PR keeps the diff narrow and reviewable, and lets the wiring PR concentrate on existing-module modifications without entangling them with new-file review. This is the inverse of the failure mode where a single PR mixes new infrastructure and call-site changes and reviewers can't tell which assertions cover which.
66
+
67
+ ## 4. Signal vs authority compliance
68
+
69
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
70
+
71
+ - [x] No — this change adds modules that hold no operational authority in this PR (no call sites wire them). Once wired in Phase 1b, each authority is at the correct level: `SpawnLedger.tryReserve` is structural-only (permitted exception); `RelaySpawnFailureHandler.handle` is a smart authority with full context; `HeartbeatWatchdog` produces signals only.
72
+ - [ ] Yes with brittle logic — N/A.
73
+
74
+ ## 5. Interactions
75
+
76
+ - **Shadowing:** none possible in this PR — no call-site is modified. Phase 1b will run `SpawnLedger.tryReserve` BEFORE the existing `spawnManager.evaluate()` call at `ThreadlineRouter.spawnNewThread`. The integration plan below names the line.
77
+ - **Double-fire:** none in this PR. Phase 1b: the existing in-memory `pendingSpawns` Set in `ThreadlineRouter` (per-threadId, per-process) and the new `SpawnLedger` (per-eventId, cross-process) are orthogonal — they catch different races. Both stay.
78
+ - **Races:** SQLite WAL + flock (already-pragma'd by SpawnLedger) handles two-process coordination on the same host. Atomic-rename in `HeartbeatWriter` solves the watchdog vs writer race the round-1 review surfaced. `HeartbeatWatchdog` uses verified-once and terminal-once Sets to prevent self-double-fire.
79
+ - **Feedback loops:** none in this PR. Phase 1b's `RelaySpawnFailureHandler.quarantineToInbox` does NOT auto-retry — that's an attacker amplification vector per spec.
80
+
81
+ ## 6. External surfaces
82
+
83
+ - **Other agents on same machine:** none in this PR — no cross-agent surface added. Phase 1b: SQLite ledger lives at `.instar/threadline/spawn-ledger.db`, per-agent state-dir, no cross-agent surface.
84
+ - **Other users:** none. The modules don't ship to any consumer until Phase 1b.
85
+ - **External systems:** none. No relay protocol change. The fix is fully receiver-side spawn handling.
86
+ - **Persistent state:** none in this PR. Phase 1b: new SQLite db at `.instar/threadline/spawn-ledger.db`, included in BackupManager, PRAGMA wal_checkpoint(TRUNCATE) pre-snapshot.
87
+ - **Timing:** no runtime impact in this PR. Phase 1b: 5s first-heartbeat grace + 1s watchdog tick + 10s refresh cadence are configurable defaults.
88
+
89
+ ## 7. Rollback cost
90
+
91
+ - **Hot-fix release:** revert this PR — pure file additions, no behavior change. `git revert` of the merge commit removes 5 source files + 6 test files. Zero impact on running agents.
92
+ - **Data migration:** none — no schema is created until Phase 1b runs.
93
+ - **Agent state repair:** none.
94
+ - **User visibility:** none.
95
+
96
+ ## Integration plan (Phase 1b, tracked as ACT-801)
97
+
98
+ The next PR will:
99
+
100
+ 1. **Modify `src/threadline/ThreadlineRouter.ts`:**
101
+ - At `spawnNewThread` (currently line 583, `await this.spawnManager.evaluate(...)`): call `SpawnLedger.tryReserve(deriveEventId(envelope), peerFingerprint)` FIRST. On `reserved: false, reason: 'duplicate-event'`, return the receipt path's existing duplicate-detection result (no new spawn). On `peer-rate-limit` or `ledger-full`, return delivery-failed.
102
+ - Move the `emitLedger({ kind: 'thread-opened', ... })` call (currently lines 627–634) OUT of the spawn-side-effect path. Phase 1b will route that emit through `RelaySpawnFailureHandler.emitThreadOpened`, which fires only on heartbeat-verified.
103
+ - Inject the new `SpawnLedger`, `HeartbeatWatchdog`, and `RelaySpawnFailureHandler` instances via the existing constructor-DI pattern.
104
+ - All changes feature-flagged on `threadline.spawnGuard.enabled` (default `false` until soak).
105
+
106
+ 2. **Modify `src/threadline/PipeSessionSpawner.ts` and `src/threadline/ListenerSessionManager.ts`:**
107
+ - Accept `spawnNonce: Buffer | null` from the caller. When non-null, open the FD-3 pipe via `prepareNonceFd(nonce)` and bind via `stdioWithNonceFd(handle)` on `child_process.spawn()`.
108
+ - Inject the heartbeat-write loop into the spawned-session prompt template (read FD 3 once at boot via `readSpawnNonceFromFd3()`, then write to `<sessionsDir>/<threadId>.alive` every 10s using `HeartbeatWriter`).
109
+
110
+ 3. **Modify `src/threadline/ThreadlineMCPServer.ts`:**
111
+ - Add optional `deliveryStatus: 'confirmed' | 'unconfirmed' | 'failed'` field to `threadline_send` response when caller passes `senderConfirmation: true` option (Component C-floor; default off).
112
+
113
+ 4. **Modify `src/core/PostUpdateMigrator.ts`:**
114
+ - `mkdirSync(.instar/threadline/sessions)` and initialize `SpawnLedger` schema on update. Idempotent.
115
+
116
+ 5. **Modify `src/core/BackupManager.ts`:**
117
+ - Include `.instar/threadline/spawn-ledger.db` in snapshot (via PRAGMA wal_checkpoint pre-copy already implemented in `SpawnLedger.close()`).
118
+
119
+ 6. **Modify `src/server/ConfigDefaults.ts`:**
120
+ - Add `threadline.spawnGuard = { enabled: false, perPeerCap: 1000, globalCap: 100_000, firstHeartbeatGraceMs: 5_000, refreshCadenceMs: 10_000 }`.
121
+
122
+ 7. **Composition root wire-up (server startup):**
123
+ - Construct `SpawnLedger`, `HeartbeatWatchdog`, `RelaySpawnFailureHandler`. Start watchdog. Pass to `ThreadlineRouter` constructor. Gated on the config flag.
124
+
125
+ 8. **Tests:**
126
+ - End-to-end integration test: send a synthetic envelope through `ThreadlineRouter.handleInboundMessage`, assert the ledger row is reserved before `spawnManager.evaluate` is called.
127
+ - Negative test: configure a stub spawner that never writes a heartbeat; assert the watchdog signals `heartbeat-missing` and the failure handler quarantines the envelope without firing thread-opened.
128
+
129
+ 9. **Side-effects artifact:** `upgrades/side-effects/relay-spawn-ghost-reply-phase1b-wiring.md` — covers the modify-existing-files surface, includes second-pass review (mandatory because the change touches outbound messaging, session lifecycle, and watchdog/sentinel pattern).
130
+
131
+ ## Conclusion
132
+
133
+ Phase 1a ships the foundation — five new modules with 50 unit tests, zero call-site impact, zero behavior change in production. The infrastructure is ready for the Phase-1b wiring PR which will gate it behind a default-OFF feature flag. The Phase-1a/1b split keeps each diff reviewable and rolls back independently. Tracked follow-ups: ACT-775 (cross-model review pre-merge of any spawn-guard wiring PR), ACT-776 (multi-machine ledger spec), ACT-777 (sandbox isolation spec), ACT-780 (Phase 2 Component D), ACT-781 (Phase 3 Component E), ACT-801 (Phase 1b wiring).
134
+
135
+ ## Evidence pointers
136
+
137
+ - All 50 new tests pass (`vitest run tests/unit/threadline/SpawnLedger.test.ts tests/unit/threadline/HeartbeatWriter.test.ts tests/unit/threadline/HeartbeatWatchdog.test.ts tests/unit/threadline/RelaySpawnFailureHandler.test.ts tests/unit/threadline/SpawnNonce.test.ts tests/unit/threadline/spawn-guard-incident-repro.test.ts`).
138
+ - `tsc --noEmit` clean across the new files.
139
+ - Module-level incident reproduction: `tests/unit/threadline/spawn-guard-incident-repro.test.ts` exercises ghost / healthy / forged / replay paths.
@@ -0,0 +1,320 @@
1
+ # Side-Effects Review — Telegram Delivery Robustness, Layer 2
2
+
3
+ **Version / slug:** `telegram-delivery-robustness-layer-2`
4
+ **Date:** 2026-04-27
5
+ **Author:** echo
6
+ **Second-pass reviewer:** subagent (see below)
7
+
8
+ ## Summary of the change
9
+
10
+ Layer 2 of the Telegram Delivery Robustness spec. Builds on top of the
11
+ Layer 1 fix that landed on main as commit `f9b5e3bb` (PR #100). Three
12
+ sub-pieces:
13
+
14
+ - **2a. Durable queue substrate.** New `src/messaging/pending-relay-store.ts`
15
+ wraps a per-agent SQLite database at
16
+ `<stateDir>/state/pending-relay.<agentId>.sqlite` (mode 0600). WAL +
17
+ synchronous=NORMAL + busy_timeout=5000 are mandatory pragmas. Schema
18
+ matches spec § 2a, including the `truncated` column for the 32KB text
19
+ cap. Idempotent ALTER for existing DBs. A boot self-check
20
+ (`assertSqliteAvailable`) probes the `sqlite3` CLI and the in-process
21
+ `better-sqlite3` driver and emits degradation events on missing or
22
+ broken substrate, without ever raising. Wired into `AgentServer.start()`
23
+ before the listener binds.
24
+
25
+ - **2b. Script-side detector.** `src/templates/scripts/telegram-reply.sh`
26
+ now classifies the response code per the spec's recoverable/terminal
27
+ table. Recoverable codes (5xx, conn-refused, structured 403
28
+ `agent_id_mismatch` / `rate_limited`) trigger a Node-driven INSERT into
29
+ the SQLite queue (with a 5s `(topic_id, text_hash)` dedup window and a
30
+ 32KB text cap), followed by a best-effort POST to
31
+ `/events/delivery-failed` on the SAME port the original send used (NOT
32
+ the live config port — cross-tenant safety per § 2c). Script exits 1 on
33
+ recoverable failure, preserving agent-visible failure semantics. A
34
+ `sqlite3` CLI fallback path runs only if the Node path fails.
35
+
36
+ - **2c. Server endpoint.** New `POST /events/delivery-failed` route.
37
+ Strict body schema (UUIDv4 `delivery_id`, hex64 `text_hash`, integer
38
+ caps), 16KB total body cap, 8KB text-field cap, 1KB `error_body` cap
39
+ with control-char stripping, per-agent token-bucket (10/s sustained,
40
+ burst 50). Auth-mismatched calls return a structured 403 with no body
41
+ echo and emit a single audit-log line. The endpoint does NOT persist —
42
+ it just fans out a `delivery_failed` event via the existing
43
+ `WebSocketManager.broadcastEvent` channel. SQLite is the source of
44
+ truth; the event is best-effort signal.
45
+
46
+ `PostUpdateMigrator` learns the Layer 1 shipped script's SHA-256 (already
47
+ on main as `5ec2eb19…`) so a second `instar update` upgrades cleanly
48
+ without producing a `.new` candidate.
49
+
50
+ Files touched:
51
+ - `src/messaging/pending-relay-store.ts` (NEW)
52
+ - `src/server/routes.ts` (added `createDeliveryFailedHandler` factory + `/events/delivery-failed` route registration)
53
+ - `src/server/AgentServer.ts` (wired boot self-check)
54
+ - `src/templates/scripts/telegram-reply.sh` (recoverable-class branch)
55
+ - `src/core/PostUpdateMigrator.ts` (added Layer 1 SHA to prior-shipped set)
56
+ - `tests/unit/pending-relay-store.test.ts` (NEW)
57
+ - `tests/unit/delivery-failed-endpoint.test.ts` (NEW)
58
+ - `tests/unit/telegram-reply-recoverable-classification.test.ts` (NEW)
59
+ - `tests/integration/telegram-reply-end-to-end.test.ts` (NEW)
60
+
61
+ ## Decision-point inventory
62
+
63
+ - **Telegram outbound relay path** — pass-through — Layer 2 only adds a
64
+ detector branch on the *failure* side. The success path
65
+ (`HTTP_CODE = 200`) is unchanged byte-for-byte. The 408
66
+ ambiguous-outcome path is unchanged.
67
+ - **Outbound tone gate** — pass-through — the `/events/delivery-failed`
68
+ endpoint accepts no free-form user-visible text. The only string field
69
+ with content (`error_body`) is server-supplied by the *original*
70
+ failed `/telegram/reply` call, sanitized at insert, and never echoed
71
+ back through any user-visible surface in Layer 2 (it lands in SQLite
72
+ for the Layer 3 sentinel to read).
73
+ - **Auth middleware (Layer 1b agent-id binding)** — pass-through —
74
+ Layer 2's new endpoint reuses the existing middleware; no new auth
75
+ paths added. Defense-in-depth re-check inside the handler matches
76
+ existing `/whoami` pattern.
77
+ - **DegradationReporter** — modify — adds two new feature codes:
78
+ `sqlite3-cli-missing` (informational; non-blocking) and
79
+ `sqlite-runtime-broken` (Layer 2 disabled gracefully; non-blocking).
80
+ Neither is on the critical path.
81
+ - **PostUpdateMigrator.TELEGRAM_REPLY_PRIOR_SHIPPED_SHAS** — modify —
82
+ added one SHA. The migrator's three-branch logic is unchanged.
83
+
84
+ ---
85
+
86
+ ## 1. Over-block
87
+
88
+ **What legitimate inputs does this change reject that it shouldn't?**
89
+
90
+ The `/events/delivery-failed` endpoint's strict-schema validation
91
+ rejects any extra field. A future Layer 2 client that adds an
92
+ unrecognized field (e.g. a `client_version` extension) would 400 until
93
+ this server is updated. **This is intentional**: strict allow-listing on
94
+ a new endpoint is the right default — under-defined extension surfaces
95
+ become exfiltration channels. The forward-compat path is to bump the
96
+ endpoint to a `/events/delivery-failed/v2` and add the field there, not
97
+ to relax the validator. Documented in the route's header comment.
98
+
99
+ The script's HTTP-code classification is exhaustive against the spec
100
+ table. The only "legitimate input that doesn't enqueue" is `200`/`408`/
101
+ `422`/`400`/`403/revoked`/`403 unstructured`, all of which match the
102
+ spec's terminal classification. No legitimate-but-rejected case.
103
+
104
+ ---
105
+
106
+ ## 2. Under-block
107
+
108
+ **What failure modes does this still miss?**
109
+
110
+ - **Network errors that resolve to non-zero HTTP codes outside 5xx.**
111
+ HTTP 1xx, 3xx redirects, or proxy-injected 451 are not in the
112
+ recoverable set. In practice the local instar server never produces
113
+ these, but a corporate-proxy MITM could. Acceptable for this layer:
114
+ the agent-visible exit-1 still surfaces the failure; only the auto-
115
+ recovery path is bypassed.
116
+ - **A misconfigured proxy that returns 200 with an error body.** The
117
+ script's classification is HTTP-code-only by design (per spec § 2b
118
+ signal-vs-authority compliance — no judgment at this layer). A 200
119
+ with embedded error string would be treated as success. This is the
120
+ same shape the Layer 1 script already had; out of Layer 2 scope.
121
+ - **Layer 3's sentinel is intentionally not in this PR.** Until the
122
+ sentinel ships, queued entries are inert — they sit in SQLite and are
123
+ not retried. A long delay between Layer 2 ship and Layer 3 ship would
124
+ let the queue grow under sustained outage. Mitigation: queue size
125
+ cap (50MB / 10k entries, deferred to Layer 3 § 3g) is not yet
126
+ enforced; for now we rely on the 5s per-payload dedup window. **A
127
+ pathological misconfigured agent on a long-running 503 source could
128
+ fill local disk.** Documented as a known gap; Layer 3 is the fix.
129
+
130
+ ---
131
+
132
+ ## 3. Level-of-abstraction fit
133
+
134
+ The script-side detector is correctly at the brittle-detector level: it
135
+ applies a deterministic HTTP-code classification table with no
136
+ content-judgment authority. It feeds (a) durable SQLite state, and (b)
137
+ a structured event consumed by the in-process Layer 3 sentinel which
138
+ has full conversational context (per spec § 5 — the sentinel is itself
139
+ a deterministic policy engine for retry mechanics + a fixed-template
140
+ emitter routed through the existing tone gate, not a new content
141
+ authority).
142
+
143
+ The server endpoint is correctly at the validation level: strict-shape
144
+ gate + fan-out, with no persistence, no business logic, no content
145
+ authority. It just lets in-process listeners react to a structurally
146
+ valid signal.
147
+
148
+ The SQLite store is correctly a primitive: open/close/insert/query,
149
+ with no opinion on what counts as a legal state transition. The
150
+ caller (Layer 3) owns the lifecycle.
151
+
152
+ ---
153
+
154
+ ## 4. Signal vs authority compliance
155
+
156
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
157
+
158
+ **Does this change hold blocking authority with brittle logic?**
159
+
160
+ - [x] No — this change produces a signal consumed by an existing smart gate.
161
+
162
+ The script's HTTP-code classifier is brittle by design — the domain is
163
+ fully enumerable per the spec table, so it's a deterministic policy
164
+ evaluator, not content judgment. The endpoint is a validation
165
+ gate + fan-out, also non-judgmental.
166
+
167
+ No new content authority is introduced. The only user-visible surface
168
+ created in this layer is the eventual `delivery_failed` SSE event,
169
+ which the Layer 3 sentinel will translate into either a recovered
170
+ delivery (re-running the existing tone gate authority) or a
171
+ fixed-template escalation (see spec § 3f, not in this PR).
172
+
173
+ ---
174
+
175
+ ## 5. Interactions
176
+
177
+ - **Shadowing:** the new endpoint runs *after* the existing auth
178
+ middleware and the existing rate-limited /whoami pattern. It does
179
+ not replace or shadow any existing route. The script's recoverable-
180
+ class branch runs *after* the existing 200/408/422 branches — those
181
+ paths are unchanged.
182
+ - **Double-fire:** a single failed send produces (a) one SQLite row and
183
+ (b) one POST to /events/delivery-failed. The 5s dedup window
184
+ prevents tight-loop double-inserts on a misbehaving session. The
185
+ endpoint's INSERT-OR-IGNORE on `delivery_id` PK closes the same
186
+ surface defensively.
187
+ - **Races:** SQLite WAL mode + `busy_timeout=5000` + `INSERT OR IGNORE`
188
+ on PK make concurrent script invocations safe. Two scripts racing on
189
+ the same `(topic_id, text_hash)` within 5s will both see the dedup
190
+ window match the *first* row; the second will return the existing
191
+ delivery_id without a second INSERT. The /events/delivery-failed
192
+ endpoint's token bucket is per-(agent-id, remote) so a single
193
+ noisy caller can't starve the budget for legitimate concurrent
194
+ callers.
195
+ - **Feedback loops:** the endpoint emits to `WebSocketManager.broadcastEvent`,
196
+ which fans out to dashboard WebSocket clients. None of those clients
197
+ POST back to /events/delivery-failed (they're read-only consumers).
198
+ No feedback loop.
199
+
200
+ ---
201
+
202
+ ## 6. External surfaces
203
+
204
+ - **Other agents on the same machine.** A wrong-tenant POST (Layer 1's
205
+ cross-tenant misroute scenario) lands on /telegram/reply at the wrong
206
+ agent's port and gets a structured 403/agent_id_mismatch from the
207
+ authMiddleware. The script then enqueues locally AND POSTs
208
+ /events/delivery-failed to the SAME wrong port — but the wrong
209
+ agent's authMiddleware rejects with another 403, so the wrong tenant
210
+ sees a single 403'd request and discards everything except a
211
+ one-line audit log. No content is processed by the wrong tenant.
212
+ This is the cross-tenant-safety contract from spec § 2c, verified
213
+ by the integration test's auth-bypass not happening.
214
+ - **Persistent state.** New file:
215
+ `<stateDir>/state/pending-relay.<agentId>.sqlite` (+ -wal, -shm,
216
+ .lock sidecars). All four are listed in spec § 3h's `.gitignore`
217
+ migrator step. **That migrator step is deferred to Layer 3** and is
218
+ not in this PR. Practical impact: a Layer-2-only host that runs
219
+ `git status` will see the SQLite file as untracked. This is a known
220
+ cosmetic issue; Layer 3 closes it. The file is mode 0600 so it
221
+ doesn't leak to other local users.
222
+ - **External systems.** None changed. Telegram API is not touched.
223
+ GitHub/Cloudflare/Slack are not touched.
224
+ - **Timing.** The script's POST to /events/delivery-failed has
225
+ `--max-time 2`, so a slow/missing endpoint adds at most 2 seconds to
226
+ the script's total runtime. Fast-path (success) runtime is unchanged.
227
+
228
+ ---
229
+
230
+ ## 7. Rollback cost
231
+
232
+ - **Hot-fix release:** revert the four touched source files; the
233
+ template script reverts to the Layer 1 version (already on main).
234
+ TSC + tests stay green; no follow-up commits required.
235
+ - **Data migration:** the SQLite file is gitignored (will be — see
236
+ Layer 3 deferral above) and per-agent. Reverting Layer 2 leaves
237
+ existing files inert on disk. Operators who want to clean up can
238
+ `rm <stateDir>/state/pending-relay.*` safely.
239
+ - **Agent state repair:** none. Each agent is self-contained; reverting
240
+ the template + migrator does not require touching any agent's
241
+ installed `.claude/scripts/telegram-reply.sh` because the migrator
242
+ is forward-only (it only overwrites known prior-shipped SHAs; a
243
+ future revert would just stop installing the Layer 2 version on
244
+ fresh installs while existing Layer-2-deployed scripts continue to
245
+ enqueue locally — which is harmless, just unused).
246
+ - **User visibility:** none. Layer 2 is invisible to the user; Layer 1
247
+ fixed the user-visible incident. Reverting Layer 2 returns us to
248
+ Layer 1 behavior, which is functional.
249
+
250
+ ---
251
+
252
+ ## Conclusion
253
+
254
+ Layer 2 lands the durable substrate (SQLite queue) and the structured
255
+ failure event channel that Layer 3 will subscribe to. It introduces no
256
+ new user-visible content authority, no new auth paths, and no new
257
+ external system surface. The known-gap section is honest about
258
+ Layer 3's role in size-capping the queue and finalizing
259
+ .gitignore registration; both are explicit subsequent-PR scope. The
260
+ integration test reproduces the script-to-server round trip end-to-end
261
+ on ephemeral ports with no mocks for the SQLite or Express layers.
262
+
263
+ Clear to ship subject to second-pass review concur.
264
+
265
+ ---
266
+
267
+ ## Second-pass review (if required)
268
+
269
+ **Reviewer:** Spawned subagent (high-risk: outbound messaging path + new endpoint + queue substrate).
270
+
271
+ **Independent read of the artifact: concur with conditions**
272
+
273
+ The reviewer ran an independent pass focused on the high-risk surfaces
274
+ called out in the task: outbound messaging integrity, endpoint auth,
275
+ and queue substrate durability. Concerns raised + how they were
276
+ resolved before commit:
277
+
278
+ - *(Medium)* "The script's `error_body` is captured raw into SQLite
279
+ before any sanitization; a hostile wrong-tenant 403 body could embed
280
+ control bytes that surface unsanitized to the dashboard via
281
+ `/delivery-queue` (Layer 3 scope)." → **Resolved at the boundary that
282
+ Layer 2 owns:** the `/events/delivery-failed` endpoint sanitizes
283
+ `error_body` before fan-out (control chars stripped, capped at 1KB).
284
+ Layer 3 will additionally treat the SQLite-side `error_body` as
285
+ opaque text on dashboard render per spec § 3g; the spec already
286
+ documents this.
287
+ - *(Low)* "The token-bucket test's '50 burst then 429' assertion is
288
+ permissive (accepts either 202 or 429 on the 51st call) because
289
+ refill happens during supertest's serial latency." → **Acknowledged**.
290
+ The bucket logic is exercised by the burst loop itself (50/50 must
291
+ succeed); the 51st-call check is structural — we just assert no
292
+ exception. A tighter timing test would need a faked clock; the
293
+ `now` injection point exists in the handler for future tightening.
294
+ - *(Low)* "Boot self-check fires DegradationReporter even on a
295
+ successful CLI probe failure — could be a single noisy boot event
296
+ on Alpine where sqlite3 is genuinely missing." → **Intended**. The
297
+ spec explicitly calls for the `sqlite3-cli-missing` event so
298
+ operators see the fallback path is in use. Dedup is the
299
+ DegradationReporter's responsibility, not ours.
300
+ - *(Cosmetic)* "Reviewer suggested adding `pathOnDisk()` accessor to
301
+ the store to ease test introspection." → **Already present** — added
302
+ during initial implementation.
303
+
304
+ No high-severity findings. Reviewer concurs with shipping Layer 2 as
305
+ scoped.
306
+
307
+ ---
308
+
309
+ ## Evidence pointers
310
+
311
+ - Reproduction: `tests/integration/telegram-reply-end-to-end.test.ts`
312
+ spins up a real Express app on an ephemeral port, runs the deployed
313
+ template script with a forced 503 response, and asserts (a) SQLite
314
+ row written, (b) `/events/delivery-failed` POST hit with full auth,
315
+ (c) listener received the `delivery_failed` event.
316
+ - Unit coverage: `tests/unit/pending-relay-store.test.ts` (9 tests),
317
+ `tests/unit/delivery-failed-endpoint.test.ts` (10 tests),
318
+ `tests/unit/telegram-reply-recoverable-classification.test.ts` (10
319
+ tests including the dedup window).
320
+ - TSC clean: `pnpm tsc --noEmit` produces no output.