instar 1.3.1649 → 1.3.1651

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 (498) hide show
  1. package/dashboard/console/accounts.js +2 -1
  2. package/dashboard/console/agents-model.js +3 -3
  3. package/dashboard/console/agents.js +7 -4
  4. package/dashboard/console/console.css +1 -0
  5. package/dashboard/console/console.js +35 -4
  6. package/dashboard/console/costs-model.js +12 -0
  7. package/dashboard/console/costs.js +6 -3
  8. package/dashboard/console/development-model.js +9 -3
  9. package/dashboard/console/development.js +7 -4
  10. package/dashboard/console/home-model.js +30 -14
  11. package/dashboard/console/mandates.js +3 -3
  12. package/dashboard/console/needs-model.js +105 -0
  13. package/dashboard/console/plans.js +2 -1
  14. package/dashboard/console/secrets.js +2 -2
  15. package/dashboard/console/ticket-model.js +36 -0
  16. package/dashboard/console/ui.js +3 -0
  17. package/dist/cli.js +8 -0
  18. package/dist/cli.js.map +1 -1
  19. package/dist/commands/install.d.ts +9 -7
  20. package/dist/commands/install.d.ts.map +1 -1
  21. package/dist/commands/install.js +2 -19
  22. package/dist/commands/install.js.map +1 -1
  23. package/dist/commands/machine.d.ts +2 -0
  24. package/dist/commands/machine.d.ts.map +1 -1
  25. package/dist/commands/machine.js +19 -0
  26. package/dist/commands/machine.js.map +1 -1
  27. package/dist/commands/reflect.d.ts.map +1 -1
  28. package/dist/commands/reflect.js +2 -0
  29. package/dist/commands/reflect.js.map +1 -1
  30. package/dist/commands/route.d.ts.map +1 -1
  31. package/dist/commands/route.js +2 -0
  32. package/dist/commands/route.js.map +1 -1
  33. package/dist/commands/server.d.ts.map +1 -1
  34. package/dist/commands/server.js +537 -21
  35. package/dist/commands/server.js.map +1 -1
  36. package/dist/commands/setClaudeKey.d.ts +8 -0
  37. package/dist/commands/setClaudeKey.d.ts.map +1 -0
  38. package/dist/commands/setClaudeKey.js +35 -0
  39. package/dist/commands/setClaudeKey.js.map +1 -0
  40. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  41. package/dist/config/ConfigDefaults.js +2 -0
  42. package/dist/config/ConfigDefaults.js.map +1 -1
  43. package/dist/core/AccountFollowMeOrchestrator.d.ts.map +1 -1
  44. package/dist/core/AccountFollowMeOrchestrator.js +4 -0
  45. package/dist/core/AccountFollowMeOrchestrator.js.map +1 -1
  46. package/dist/core/AppMediaStore.d.ts.map +1 -1
  47. package/dist/core/AppMediaStore.js +3 -0
  48. package/dist/core/AppMediaStore.js.map +1 -1
  49. package/dist/core/BackupManager.d.ts.map +1 -1
  50. package/dist/core/BackupManager.js +2 -0
  51. package/dist/core/BackupManager.js.map +1 -1
  52. package/dist/core/ClaudeCliIntelligenceProvider.d.ts.map +1 -1
  53. package/dist/core/ClaudeCliIntelligenceProvider.js +11 -3
  54. package/dist/core/ClaudeCliIntelligenceProvider.js.map +1 -1
  55. package/dist/core/ClaudeKeyHealth.d.ts +141 -0
  56. package/dist/core/ClaudeKeyHealth.d.ts.map +1 -0
  57. package/dist/core/ClaudeKeyHealth.js +467 -0
  58. package/dist/core/ClaudeKeyHealth.js.map +1 -0
  59. package/dist/core/CodexTaskContinuationStore.d.ts.map +1 -1
  60. package/dist/core/CodexTaskContinuationStore.js +7 -0
  61. package/dist/core/CodexTaskContinuationStore.js.map +1 -1
  62. package/dist/core/CoherenceJournal.d.ts +1 -1
  63. package/dist/core/CoherenceJournal.d.ts.map +1 -1
  64. package/dist/core/CoherenceJournal.js +11 -2
  65. package/dist/core/CoherenceJournal.js.map +1 -1
  66. package/dist/core/Config.d.ts +8 -0
  67. package/dist/core/Config.d.ts.map +1 -1
  68. package/dist/core/Config.js +26 -0
  69. package/dist/core/Config.js.map +1 -1
  70. package/dist/core/CredentialSwapExecutor.d.ts.map +1 -1
  71. package/dist/core/CredentialSwapExecutor.js +10 -0
  72. package/dist/core/CredentialSwapExecutor.js.map +1 -1
  73. package/dist/core/DecisionQualityRecorderImpl.d.ts.map +1 -1
  74. package/dist/core/DecisionQualityRecorderImpl.js +6 -0
  75. package/dist/core/DecisionQualityRecorderImpl.js.map +1 -1
  76. package/dist/core/DiscoveryEvaluator.d.ts.map +1 -1
  77. package/dist/core/DiscoveryEvaluator.js +4 -0
  78. package/dist/core/DiscoveryEvaluator.js.map +1 -1
  79. package/dist/core/IdentityReannounceClaimant.d.ts.map +1 -1
  80. package/dist/core/IdentityReannounceClaimant.js +4 -0
  81. package/dist/core/IdentityReannounceClaimant.js.map +1 -1
  82. package/dist/core/IntelligenceRouter.d.ts.map +1 -1
  83. package/dist/core/IntelligenceRouter.js +9 -0
  84. package/dist/core/IntelligenceRouter.js.map +1 -1
  85. package/dist/core/JournalSyncApplier.d.ts +1 -0
  86. package/dist/core/JournalSyncApplier.d.ts.map +1 -1
  87. package/dist/core/JournalSyncApplier.js +48 -0
  88. package/dist/core/JournalSyncApplier.js.map +1 -1
  89. package/dist/core/LeaseCoordinator.d.ts +4 -0
  90. package/dist/core/LeaseCoordinator.d.ts.map +1 -1
  91. package/dist/core/LeaseCoordinator.js +64 -1
  92. package/dist/core/LeaseCoordinator.js.map +1 -1
  93. package/dist/core/MachinePoolRegistry.d.ts +8 -0
  94. package/dist/core/MachinePoolRegistry.d.ts.map +1 -1
  95. package/dist/core/MachinePoolRegistry.js +25 -2
  96. package/dist/core/MachinePoolRegistry.js.map +1 -1
  97. package/dist/core/MessagingToneGate.d.ts +11 -7
  98. package/dist/core/MessagingToneGate.d.ts.map +1 -1
  99. package/dist/core/MessagingToneGate.js +15 -1
  100. package/dist/core/MessagingToneGate.js.map +1 -1
  101. package/dist/core/MobileDeviceKeys.d.ts +10 -0
  102. package/dist/core/MobileDeviceKeys.d.ts.map +1 -1
  103. package/dist/core/MobileDeviceKeys.js +17 -0
  104. package/dist/core/MobileDeviceKeys.js.map +1 -1
  105. package/dist/core/MultiMachineCoordinator.d.ts +12 -0
  106. package/dist/core/MultiMachineCoordinator.d.ts.map +1 -1
  107. package/dist/core/MultiMachineCoordinator.js +115 -3
  108. package/dist/core/MultiMachineCoordinator.js.map +1 -1
  109. package/dist/core/MutualSshRuntime.d.ts +1 -0
  110. package/dist/core/MutualSshRuntime.d.ts.map +1 -1
  111. package/dist/core/MutualSshRuntime.js +17 -1
  112. package/dist/core/MutualSshRuntime.js.map +1 -1
  113. package/dist/core/ObservedEndpointTracker.d.ts +1 -0
  114. package/dist/core/ObservedEndpointTracker.d.ts.map +1 -1
  115. package/dist/core/ObservedEndpointTracker.js +17 -0
  116. package/dist/core/ObservedEndpointTracker.js.map +1 -1
  117. package/dist/core/OverloadShedPlanner.d.ts +63 -7
  118. package/dist/core/OverloadShedPlanner.d.ts.map +1 -1
  119. package/dist/core/OverloadShedPlanner.js +177 -38
  120. package/dist/core/OverloadShedPlanner.js.map +1 -1
  121. package/dist/core/OwnershipApplier.d.ts.map +1 -1
  122. package/dist/core/OwnershipApplier.js +7 -0
  123. package/dist/core/OwnershipApplier.js.map +1 -1
  124. package/dist/core/OwnershipReconciler.d.ts +11 -0
  125. package/dist/core/OwnershipReconciler.d.ts.map +1 -1
  126. package/dist/core/OwnershipReconciler.js +32 -9
  127. package/dist/core/OwnershipReconciler.js.map +1 -1
  128. package/dist/core/PostUpdateMigrator.d.ts +12 -0
  129. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  130. package/dist/core/PostUpdateMigrator.js +97 -5
  131. package/dist/core/PostUpdateMigrator.js.map +1 -1
  132. package/dist/core/PrHandLease.d.ts.map +1 -1
  133. package/dist/core/PrHandLease.js +2 -0
  134. package/dist/core/PrHandLease.js.map +1 -1
  135. package/dist/core/ProactiveSwapMonitor.d.ts.map +1 -1
  136. package/dist/core/ProactiveSwapMonitor.js +7 -0
  137. package/dist/core/ProactiveSwapMonitor.js.map +1 -1
  138. package/dist/core/ProjectRoundExecution.d.ts.map +1 -1
  139. package/dist/core/ProjectRoundExecution.js +3 -2
  140. package/dist/core/ProjectRoundExecution.js.map +1 -1
  141. package/dist/core/QueueDrainLoop.d.ts +7 -0
  142. package/dist/core/QueueDrainLoop.d.ts.map +1 -1
  143. package/dist/core/QueueDrainLoop.js +37 -1
  144. package/dist/core/QueueDrainLoop.js.map +1 -1
  145. package/dist/core/RebalancePlanner.d.ts +1 -0
  146. package/dist/core/RebalancePlanner.d.ts.map +1 -1
  147. package/dist/core/RebalancePlanner.js +1 -1
  148. package/dist/core/RebalancePlanner.js.map +1 -1
  149. package/dist/core/RemoteAckStore.d.ts.map +1 -1
  150. package/dist/core/RemoteAckStore.js +4 -0
  151. package/dist/core/RemoteAckStore.js.map +1 -1
  152. package/dist/core/ReplicatedStoreReconcilerWiring.d.ts.map +1 -1
  153. package/dist/core/ReplicatedStoreReconcilerWiring.js +1 -0
  154. package/dist/core/ReplicatedStoreReconcilerWiring.js.map +1 -1
  155. package/dist/core/SecretSync.d.ts +1 -0
  156. package/dist/core/SecretSync.d.ts.map +1 -1
  157. package/dist/core/SecretSync.js +16 -0
  158. package/dist/core/SecretSync.js.map +1 -1
  159. package/dist/core/SessionDrainRunner.d.ts +10 -1
  160. package/dist/core/SessionDrainRunner.d.ts.map +1 -1
  161. package/dist/core/SessionDrainRunner.js +60 -3
  162. package/dist/core/SessionDrainRunner.js.map +1 -1
  163. package/dist/core/SessionManager.d.ts +11 -0
  164. package/dist/core/SessionManager.d.ts.map +1 -1
  165. package/dist/core/SessionManager.js +125 -14
  166. package/dist/core/SessionManager.js.map +1 -1
  167. package/dist/core/SessionPoolFailoverRunner.d.ts.map +1 -1
  168. package/dist/core/SessionPoolFailoverRunner.js +4 -0
  169. package/dist/core/SessionPoolFailoverRunner.js.map +1 -1
  170. package/dist/core/SleepWakeDetector.d.ts.map +1 -1
  171. package/dist/core/SleepWakeDetector.js +10 -0
  172. package/dist/core/SleepWakeDetector.js.map +1 -1
  173. package/dist/core/StageAdvancer.d.ts +19 -0
  174. package/dist/core/StageAdvancer.d.ts.map +1 -1
  175. package/dist/core/StageAdvancer.js +51 -1
  176. package/dist/core/StageAdvancer.js.map +1 -1
  177. package/dist/core/SubscriptionReloginStore.d.ts.map +1 -1
  178. package/dist/core/SubscriptionReloginStore.js +10 -1
  179. package/dist/core/SubscriptionReloginStore.js.map +1 -1
  180. package/dist/core/TopicPinMutation.d.ts.map +1 -1
  181. package/dist/core/TopicPinMutation.js +5 -0
  182. package/dist/core/TopicPinMutation.js.map +1 -1
  183. package/dist/core/UnjustifiedStopGate.d.ts.map +1 -1
  184. package/dist/core/UnjustifiedStopGate.js +22 -0
  185. package/dist/core/UnjustifiedStopGate.js.map +1 -1
  186. package/dist/core/WindowRunCadenceExecutor.d.ts.map +1 -1
  187. package/dist/core/WindowRunCadenceExecutor.js +20 -0
  188. package/dist/core/WindowRunCadenceExecutor.js.map +1 -1
  189. package/dist/core/WriteDomainRegistry.d.ts.map +1 -1
  190. package/dist/core/WriteDomainRegistry.js +12 -0
  191. package/dist/core/WriteDomainRegistry.js.map +1 -1
  192. package/dist/core/claudeChildAuth.d.ts +68 -0
  193. package/dist/core/claudeChildAuth.d.ts.map +1 -0
  194. package/dist/core/claudeChildAuth.js +173 -0
  195. package/dist/core/claudeChildAuth.js.map +1 -0
  196. package/dist/core/claudeKeyProbe.d.ts +23 -0
  197. package/dist/core/claudeKeyProbe.d.ts.map +1 -0
  198. package/dist/core/claudeKeyProbe.js +68 -0
  199. package/dist/core/claudeKeyProbe.js.map +1 -0
  200. package/dist/core/codexDeviceLimitWiring.d.ts.map +1 -1
  201. package/dist/core/codexDeviceLimitWiring.js +12 -0
  202. package/dist/core/codexDeviceLimitWiring.js.map +1 -1
  203. package/dist/core/deliverToConversation.d.ts.map +1 -1
  204. package/dist/core/deliverToConversation.js +11 -0
  205. package/dist/core/deliverToConversation.js.map +1 -1
  206. package/dist/core/leaseMediumSelection.d.ts +8 -0
  207. package/dist/core/leaseMediumSelection.d.ts.map +1 -1
  208. package/dist/core/leaseMediumSelection.js +17 -0
  209. package/dist/core/leaseMediumSelection.js.map +1 -1
  210. package/dist/core/meteredCallEntry.d.ts.map +1 -1
  211. package/dist/core/meteredCallEntry.js +21 -0
  212. package/dist/core/meteredCallEntry.js.map +1 -1
  213. package/dist/core/nobodyPollingActuator.d.ts.map +1 -1
  214. package/dist/core/nobodyPollingActuator.js +5 -0
  215. package/dist/core/nobodyPollingActuator.js.map +1 -1
  216. package/dist/core/operatorSurfaceReferral.d.ts +18 -0
  217. package/dist/core/operatorSurfaceReferral.d.ts.map +1 -0
  218. package/dist/core/operatorSurfaceReferral.js +32 -0
  219. package/dist/core/operatorSurfaceReferral.js.map +1 -0
  220. package/dist/core/ownershipFollowsLiveWork.d.ts.map +1 -1
  221. package/dist/core/ownershipFollowsLiveWork.js +10 -1
  222. package/dist/core/ownershipFollowsLiveWork.js.map +1 -1
  223. package/dist/core/poolReadiness.d.ts +67 -0
  224. package/dist/core/poolReadiness.d.ts.map +1 -0
  225. package/dist/core/poolReadiness.js +156 -0
  226. package/dist/core/poolReadiness.js.map +1 -0
  227. package/dist/core/quietTopicScanner.d.ts +39 -0
  228. package/dist/core/quietTopicScanner.d.ts.map +1 -0
  229. package/dist/core/quietTopicScanner.js +57 -0
  230. package/dist/core/quietTopicScanner.js.map +1 -0
  231. package/dist/core/rebalanceProof.d.ts +114 -0
  232. package/dist/core/rebalanceProof.d.ts.map +1 -0
  233. package/dist/core/rebalanceProof.js +192 -0
  234. package/dist/core/rebalanceProof.js.map +1 -0
  235. package/dist/core/types.d.ts +23 -1
  236. package/dist/core/types.d.ts.map +1 -1
  237. package/dist/core/types.js.map +1 -1
  238. package/dist/core/worktreeDirtyCheck.d.ts.map +1 -1
  239. package/dist/core/worktreeDirtyCheck.js +2 -0
  240. package/dist/core/worktreeDirtyCheck.js.map +1 -1
  241. package/dist/data/stageBCertifiedSet.d.ts +9 -0
  242. package/dist/data/stageBCertifiedSet.d.ts.map +1 -1
  243. package/dist/data/stageBCertifiedSet.js +12 -0
  244. package/dist/data/stageBCertifiedSet.js.map +1 -1
  245. package/dist/data/standards-guard-index.json +1 -1
  246. package/dist/data/standards-guard-index.meta.json +2 -2
  247. package/dist/data/standards-registry.meta.json +1 -1
  248. package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
  249. package/dist/lifeline/TelegramLifeline.js +17 -3
  250. package/dist/lifeline/TelegramLifeline.js.map +1 -1
  251. package/dist/messaging/attentionHubPolicy.d.ts.map +1 -1
  252. package/dist/messaging/attentionHubPolicy.js +1 -0
  253. package/dist/messaging/attentionHubPolicy.js.map +1 -1
  254. package/dist/monitoring/AgentWorktreeReaper.d.ts.map +1 -1
  255. package/dist/monitoring/AgentWorktreeReaper.js +15 -0
  256. package/dist/monitoring/AgentWorktreeReaper.js.map +1 -1
  257. package/dist/monitoring/ApprenticeshipCycleSlaMonitor.d.ts.map +1 -1
  258. package/dist/monitoring/ApprenticeshipCycleSlaMonitor.js +18 -9
  259. package/dist/monitoring/ApprenticeshipCycleSlaMonitor.js.map +1 -1
  260. package/dist/monitoring/CodexArmSessionSweeper.d.ts.map +1 -1
  261. package/dist/monitoring/CodexArmSessionSweeper.js +11 -0
  262. package/dist/monitoring/CodexArmSessionSweeper.js.map +1 -1
  263. package/dist/monitoring/CrashLoopPauser.d.ts.map +1 -1
  264. package/dist/monitoring/CrashLoopPauser.js +8 -0
  265. package/dist/monitoring/CrashLoopPauser.js.map +1 -1
  266. package/dist/monitoring/DegradationReporter.d.ts.map +1 -1
  267. package/dist/monitoring/DegradationReporter.js +7 -1
  268. package/dist/monitoring/DegradationReporter.js.map +1 -1
  269. package/dist/monitoring/DegradedTmuxGuard.d.ts +2 -0
  270. package/dist/monitoring/DegradedTmuxGuard.d.ts.map +1 -1
  271. package/dist/monitoring/DegradedTmuxGuard.js +14 -0
  272. package/dist/monitoring/DegradedTmuxGuard.js.map +1 -1
  273. package/dist/monitoring/DurableOutputScrubber.d.ts.map +1 -1
  274. package/dist/monitoring/DurableOutputScrubber.js +7 -0
  275. package/dist/monitoring/DurableOutputScrubber.js.map +1 -1
  276. package/dist/monitoring/DurableVaultSession.d.ts.map +1 -1
  277. package/dist/monitoring/DurableVaultSession.js +15 -0
  278. package/dist/monitoring/DurableVaultSession.js.map +1 -1
  279. package/dist/monitoring/ExternalHogSentinel.d.ts +2 -0
  280. package/dist/monitoring/ExternalHogSentinel.d.ts.map +1 -1
  281. package/dist/monitoring/ExternalHogSentinel.js +27 -1
  282. package/dist/monitoring/ExternalHogSentinel.js.map +1 -1
  283. package/dist/monitoring/FailureLedger.d.ts.map +1 -1
  284. package/dist/monitoring/FailureLedger.js +38 -1
  285. package/dist/monitoring/FailureLedger.js.map +1 -1
  286. package/dist/monitoring/FeatureEvidenceLog.d.ts +5 -0
  287. package/dist/monitoring/FeatureEvidenceLog.d.ts.map +1 -1
  288. package/dist/monitoring/FeatureEvidenceLog.js +25 -0
  289. package/dist/monitoring/FeatureEvidenceLog.js.map +1 -1
  290. package/dist/monitoring/GeminiCapacityEscalationMonitor.d.ts.map +1 -1
  291. package/dist/monitoring/GeminiCapacityEscalationMonitor.js +20 -2
  292. package/dist/monitoring/GeminiCapacityEscalationMonitor.js.map +1 -1
  293. package/dist/monitoring/GeminiLoopRunner.d.ts.map +1 -1
  294. package/dist/monitoring/GeminiLoopRunner.js +11 -1
  295. package/dist/monitoring/GeminiLoopRunner.js.map +1 -1
  296. package/dist/monitoring/GreenPrAutoMerger.d.ts.map +1 -1
  297. package/dist/monitoring/GreenPrAutoMerger.js +11 -0
  298. package/dist/monitoring/GreenPrAutoMerger.js.map +1 -1
  299. package/dist/monitoring/GrowthDigestPublisher.d.ts.map +1 -1
  300. package/dist/monitoring/GrowthDigestPublisher.js +16 -0
  301. package/dist/monitoring/GrowthDigestPublisher.js.map +1 -1
  302. package/dist/monitoring/GrowthMilestoneAnalyst.d.ts +3 -0
  303. package/dist/monitoring/GrowthMilestoneAnalyst.d.ts.map +1 -1
  304. package/dist/monitoring/GrowthMilestoneAnalyst.js +45 -1
  305. package/dist/monitoring/GrowthMilestoneAnalyst.js.map +1 -1
  306. package/dist/monitoring/McpProcessReaper.d.ts +2 -0
  307. package/dist/monitoring/McpProcessReaper.d.ts.map +1 -1
  308. package/dist/monitoring/McpProcessReaper.js +32 -0
  309. package/dist/monitoring/McpProcessReaper.js.map +1 -1
  310. package/dist/monitoring/MissingLoginSessionDetector.d.ts +2 -1
  311. package/dist/monitoring/MissingLoginSessionDetector.d.ts.map +1 -1
  312. package/dist/monitoring/MissingLoginSessionDetector.js +23 -0
  313. package/dist/monitoring/MissingLoginSessionDetector.js.map +1 -1
  314. package/dist/monitoring/OrchestratorPoller.d.ts +1 -0
  315. package/dist/monitoring/OrchestratorPoller.d.ts.map +1 -1
  316. package/dist/monitoring/OrchestratorPoller.js +13 -0
  317. package/dist/monitoring/OrchestratorPoller.js.map +1 -1
  318. package/dist/monitoring/OrphanedWorkSentinel.d.ts.map +1 -1
  319. package/dist/monitoring/OrphanedWorkSentinel.js +7 -0
  320. package/dist/monitoring/OrphanedWorkSentinel.js.map +1 -1
  321. package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
  322. package/dist/monitoring/PresenceProxy.js +9 -1
  323. package/dist/monitoring/PresenceProxy.js.map +1 -1
  324. package/dist/monitoring/ProcessFootprintMonitor.d.ts.map +1 -1
  325. package/dist/monitoring/ProcessFootprintMonitor.js +20 -2
  326. package/dist/monitoring/ProcessFootprintMonitor.js.map +1 -1
  327. package/dist/monitoring/PromiseBeacon.d.ts.map +1 -1
  328. package/dist/monitoring/PromiseBeacon.js +20 -0
  329. package/dist/monitoring/PromiseBeacon.js.map +1 -1
  330. package/dist/monitoring/ReleaseReadinessSentinel.d.ts +2 -0
  331. package/dist/monitoring/ReleaseReadinessSentinel.d.ts.map +1 -1
  332. package/dist/monitoring/ReleaseReadinessSentinel.js +26 -0
  333. package/dist/monitoring/ReleaseReadinessSentinel.js.map +1 -1
  334. package/dist/monitoring/RopeHealthMonitor.d.ts.map +1 -1
  335. package/dist/monitoring/RopeHealthMonitor.js +35 -1
  336. package/dist/monitoring/RopeHealthMonitor.js.map +1 -1
  337. package/dist/monitoring/SentinelNotifier.d.ts.map +1 -1
  338. package/dist/monitoring/SentinelNotifier.js +16 -0
  339. package/dist/monitoring/SentinelNotifier.js.map +1 -1
  340. package/dist/monitoring/SessionReaper.d.ts.map +1 -1
  341. package/dist/monitoring/SessionReaper.js +11 -2
  342. package/dist/monitoring/SessionReaper.js.map +1 -1
  343. package/dist/monitoring/SingleMachineFailoverGapDetector.d.ts +2 -0
  344. package/dist/monitoring/SingleMachineFailoverGapDetector.d.ts.map +1 -1
  345. package/dist/monitoring/SingleMachineFailoverGapDetector.js +20 -0
  346. package/dist/monitoring/SingleMachineFailoverGapDetector.js.map +1 -1
  347. package/dist/monitoring/SpeakerElection.d.ts.map +1 -1
  348. package/dist/monitoring/SpeakerElection.js +8 -0
  349. package/dist/monitoring/SpeakerElection.js.map +1 -1
  350. package/dist/monitoring/StrandedTopicSentinel.d.ts +3 -0
  351. package/dist/monitoring/StrandedTopicSentinel.d.ts.map +1 -1
  352. package/dist/monitoring/StrandedTopicSentinel.js +33 -0
  353. package/dist/monitoring/StrandedTopicSentinel.js.map +1 -1
  354. package/dist/native/InstarWedgeCanary.app/Contents/MacOS/InstarWedgeCanary +0 -0
  355. package/dist/native/instar-desktop-host +0 -0
  356. package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.d.ts.map +1 -1
  357. package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.js +5 -2
  358. package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.js.map +1 -1
  359. package/dist/recommended/RecommendedServicesLedger.d.ts +91 -0
  360. package/dist/recommended/RecommendedServicesLedger.d.ts.map +1 -0
  361. package/dist/recommended/RecommendedServicesLedger.js +193 -0
  362. package/dist/recommended/RecommendedServicesLedger.js.map +1 -0
  363. package/dist/recommended/RecommendedServicesReplicatedStore.d.ts +14 -0
  364. package/dist/recommended/RecommendedServicesReplicatedStore.d.ts.map +1 -0
  365. package/dist/recommended/RecommendedServicesReplicatedStore.js +34 -0
  366. package/dist/recommended/RecommendedServicesReplicatedStore.js.map +1 -0
  367. package/dist/recommended/legacyDeclines.d.ts +11 -0
  368. package/dist/recommended/legacyDeclines.d.ts.map +1 -0
  369. package/dist/recommended/legacyDeclines.js +17 -0
  370. package/dist/recommended/legacyDeclines.js.map +1 -0
  371. package/dist/recommended/serviceIds.d.ts +3 -0
  372. package/dist/recommended/serviceIds.d.ts.map +1 -0
  373. package/dist/recommended/serviceIds.js +6 -0
  374. package/dist/recommended/serviceIds.js.map +1 -0
  375. package/dist/scaffold/templates.d.ts +2 -0
  376. package/dist/scaffold/templates.d.ts.map +1 -1
  377. package/dist/scaffold/templates.js +11 -1
  378. package/dist/scaffold/templates.js.map +1 -1
  379. package/dist/scheduler/JobResultTriage.d.ts.map +1 -1
  380. package/dist/scheduler/JobResultTriage.js +10 -0
  381. package/dist/scheduler/JobResultTriage.js.map +1 -1
  382. package/dist/scheduler/JobScheduler.d.ts.map +1 -1
  383. package/dist/scheduler/JobScheduler.js +12 -0
  384. package/dist/scheduler/JobScheduler.js.map +1 -1
  385. package/dist/scheduler/MentorOnboardingRunner.d.ts +3 -0
  386. package/dist/scheduler/MentorOnboardingRunner.d.ts.map +1 -1
  387. package/dist/scheduler/MentorOnboardingRunner.js +24 -2
  388. package/dist/scheduler/MentorOnboardingRunner.js.map +1 -1
  389. package/dist/server/AgentServer.d.ts +2 -0
  390. package/dist/server/AgentServer.d.ts.map +1 -1
  391. package/dist/server/AgentServer.js +78 -15
  392. package/dist/server/AgentServer.js.map +1 -1
  393. package/dist/server/BootHealthBeacon.d.ts +3 -0
  394. package/dist/server/BootHealthBeacon.d.ts.map +1 -1
  395. package/dist/server/BootHealthBeacon.js +9 -0
  396. package/dist/server/BootHealthBeacon.js.map +1 -1
  397. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  398. package/dist/server/CapabilityIndex.js +12 -3
  399. package/dist/server/CapabilityIndex.js.map +1 -1
  400. package/dist/server/LifelineIngressGuard.d.ts.map +1 -1
  401. package/dist/server/LifelineIngressGuard.js +11 -0
  402. package/dist/server/LifelineIngressGuard.js.map +1 -1
  403. package/dist/server/PoolPollCache.d.ts +4 -0
  404. package/dist/server/PoolPollCache.d.ts.map +1 -1
  405. package/dist/server/PoolPollCache.js +33 -0
  406. package/dist/server/PoolPollCache.js.map +1 -1
  407. package/dist/server/machineRoutes.d.ts.map +1 -1
  408. package/dist/server/machineRoutes.js +6 -0
  409. package/dist/server/machineRoutes.js.map +1 -1
  410. package/dist/server/middleware.d.ts.map +1 -1
  411. package/dist/server/middleware.js +6 -0
  412. package/dist/server/middleware.js.map +1 -1
  413. package/dist/server/mobileConsoleTicket.d.ts +113 -0
  414. package/dist/server/mobileConsoleTicket.d.ts.map +1 -0
  415. package/dist/server/mobileConsoleTicket.js +405 -0
  416. package/dist/server/mobileConsoleTicket.js.map +1 -0
  417. package/dist/server/mobileConversationRoutes.d.ts.map +1 -1
  418. package/dist/server/mobileConversationRoutes.js +20 -1
  419. package/dist/server/mobileConversationRoutes.js.map +1 -1
  420. package/dist/server/mobileMediaRoutes.d.ts.map +1 -1
  421. package/dist/server/mobileMediaRoutes.js +3 -0
  422. package/dist/server/mobileMediaRoutes.js.map +1 -1
  423. package/dist/server/mobilePairingRoutes.d.ts +8 -2
  424. package/dist/server/mobilePairingRoutes.d.ts.map +1 -1
  425. package/dist/server/mobilePairingRoutes.js +67 -6
  426. package/dist/server/mobilePairingRoutes.js.map +1 -1
  427. package/dist/server/mobileSessionTerminalRoutes.d.ts +128 -0
  428. package/dist/server/mobileSessionTerminalRoutes.d.ts.map +1 -0
  429. package/dist/server/mobileSessionTerminalRoutes.js +389 -0
  430. package/dist/server/mobileSessionTerminalRoutes.js.map +1 -0
  431. package/dist/server/recommendedServiceRoutes.d.ts +13 -0
  432. package/dist/server/recommendedServiceRoutes.d.ts.map +1 -0
  433. package/dist/server/recommendedServiceRoutes.js +49 -0
  434. package/dist/server/recommendedServiceRoutes.js.map +1 -0
  435. package/dist/server/routes.d.ts +2 -0
  436. package/dist/server/routes.d.ts.map +1 -1
  437. package/dist/server/routes.js +215 -5
  438. package/dist/server/routes.js.map +1 -1
  439. package/dist/testing/selfActionRegistry.d.ts.map +1 -1
  440. package/dist/testing/selfActionRegistry.js +44 -3
  441. package/dist/testing/selfActionRegistry.js.map +1 -1
  442. package/dist/threadline/A2ACheckInProxy.d.ts.map +1 -1
  443. package/dist/threadline/A2ACheckInProxy.js +26 -15
  444. package/dist/threadline/A2ACheckInProxy.js.map +1 -1
  445. package/dist/threadline/AgentTrustManager.d.ts.map +1 -1
  446. package/dist/threadline/AgentTrustManager.js +3 -0
  447. package/dist/threadline/AgentTrustManager.js.map +1 -1
  448. package/dist/threadline/InboundIdLedger.d.ts.map +1 -1
  449. package/dist/threadline/InboundIdLedger.js +18 -1
  450. package/dist/threadline/InboundIdLedger.js.map +1 -1
  451. package/dist/threadline/NegotiatorGate.d.ts.map +1 -1
  452. package/dist/threadline/NegotiatorGate.js +11 -0
  453. package/dist/threadline/NegotiatorGate.js.map +1 -1
  454. package/dist/threadline/PipeSessionSpawner.d.ts.map +1 -1
  455. package/dist/threadline/PipeSessionSpawner.js +8 -0
  456. package/dist/threadline/PipeSessionSpawner.js.map +1 -1
  457. package/dist/threadline/ThreadlineRouter.d.ts.map +1 -1
  458. package/dist/threadline/ThreadlineRouter.js +13 -0
  459. package/dist/threadline/ThreadlineRouter.js.map +1 -1
  460. package/dist/threadline/pairingReplicationWiring.d.ts.map +1 -1
  461. package/dist/threadline/pairingReplicationWiring.js +9 -0
  462. package/dist/threadline/pairingReplicationWiring.js.map +1 -1
  463. package/dist/threadline/relayForward.d.ts.map +1 -1
  464. package/dist/threadline/relayForward.js +13 -2
  465. package/dist/threadline/relayForward.js.map +1 -1
  466. package/dist/threadline/relayUnknownSenderTrust.d.ts +0 -9
  467. package/dist/threadline/relayUnknownSenderTrust.d.ts.map +1 -1
  468. package/dist/threadline/relayUnknownSenderTrust.js +16 -0
  469. package/dist/threadline/relayUnknownSenderTrust.js.map +1 -1
  470. package/package.json +1 -1
  471. package/scripts/check-constitution-pairing.mjs +273 -0
  472. package/scripts/safe-merge.mjs +9 -0
  473. package/src/data/builtin-manifest.json +103 -103
  474. package/src/data/feature-ladders.json +113 -113
  475. package/src/data/stageBCertifiedSet.ts +12 -0
  476. package/src/data/standards-guard-index.json +1 -1
  477. package/src/data/standards-guard-index.meta.json +2 -2
  478. package/src/data/standards-registry.meta.json +1 -1
  479. package/src/data/state-coherence-registry.json +18 -0
  480. package/src/scaffold/templates.ts +12 -1
  481. package/upgrades/1.3.1650.md +105 -0
  482. package/upgrades/1.3.1651.md +30 -0
  483. package/upgrades/mobile-console-device-signin.eli16.md +5 -0
  484. package/upgrades/side-effects/cloud-key-internal-calls.md +116 -0
  485. package/upgrades/side-effects/constitution-alignment.eli16.md +11 -0
  486. package/upgrades/side-effects/constitution-alignment.md +69 -0
  487. package/upgrades/side-effects/feature-evidence-recording.eli16.md +3 -0
  488. package/upgrades/side-effects/feature-evidence-recording.md +66 -0
  489. package/upgrades/side-effects/feedback-reroute-admission-parity.md +77 -0
  490. package/upgrades/side-effects/mobile-console-device-signin.md +102 -0
  491. package/upgrades/side-effects/mobile-native-session-screen.md +88 -0
  492. package/upgrades/side-effects/operator-needs-first-screen.md +87 -0
  493. package/upgrades/side-effects/recommended-services-choices.md +50 -0
  494. package/upgrades/side-effects/rerouted-lifetime-active-process.md +63 -0
  495. package/upgrades/side-effects/session-pool-default-on.md +53 -0
  496. package/upgrades/side-effects/session-pool-rebalancing-finish.md +151 -0
  497. package/upgrades/side-effects/undated-resurfacer-e2e-wait.eli16.md +5 -0
  498. package/upgrades/side-effects/undated-resurfacer-e2e-wait.md +9 -0
@@ -23,6 +23,18 @@ export const STAGE_B_CERTIFIED_SET = {
23
23
  "src/core/StageBStartupReadiness.ts"
24
24
  ],
25
25
  "excluded": [
26
+ {
27
+ "file": "src/core/claudeChildAuth.ts",
28
+ "reason": "Claude-only helper that passes the sign-in key to claude children; a Codex launch never reads it, so it cannot change the behaviour the Stage-B evidence certifies."
29
+ },
30
+ {
31
+ "file": "src/monitoring/FeatureEvidenceLog.ts",
32
+ "reason": "Write-only evidence log reached through DegradationReporter; its calls never throw, return nothing the caller reads, and do not alter the certified Codex Stage-B delivery path."
33
+ },
34
+ {
35
+ "file": "src/utils/jsonl-rotation.ts",
36
+ "reason": "Size-based log rotation used only by the evidence log in this closure; it never throws and does not alter the certified Codex Stage-B delivery path."
37
+ },
26
38
  {
27
39
  "file": "src/scheduler/jobScriptProtocol.ts",
28
40
  "reason": "Shared deterministic script-job output parser reached through scheduler imports; it does not alter the certified Codex Stage-B delivery path and has separate script protocol unit and lifecycle coverage"
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "generatedFrom": "source-tree",
4
4
  "registrySha256": "e9eb5bb7f56ce6f81c5f80210c1ec7999d4b8c7d2ff1ab5cfd97a269172ce2ac",
5
- "packageVersion": "1.3.1649",
5
+ "packageVersion": "1.3.1651",
6
6
  "guards": [
7
7
  {
8
8
  "ref": "docs/audits/phase-b/f10-triage.md",
@@ -1,5 +1,5 @@
1
1
  {
2
- "sha256": "925a6e27d3abc6b957a8e865a9623c9a4a607cc43ddbf9bbe70cc8193b2f0e0e",
2
+ "sha256": "eae2d0da679c49a33c433ae8c4a70b386075115535f1bb0785025e914bd65db0",
3
3
  "registrySha256": "e9eb5bb7f56ce6f81c5f80210c1ec7999d4b8c7d2ff1ab5cfd97a269172ce2ac",
4
- "packageVersion": "1.3.1649"
4
+ "packageVersion": "1.3.1651"
5
5
  }
@@ -2,5 +2,5 @@
2
2
  "sha256": "e9eb5bb7f56ce6f81c5f80210c1ec7999d4b8c7d2ff1ab5cfd97a269172ce2ac",
3
3
  "articleCount": 93,
4
4
  "generatedFrom": "docs/STANDARDS-REGISTRY.md",
5
- "packageVersion": "1.3.1649"
5
+ "packageVersion": "1.3.1651"
6
6
  }
@@ -2155,6 +2155,24 @@
2155
2155
  "note": "Never pruned by design: a message signed by a key must stay checkable after the key is revoked. One activation and at most one revocation row per paired phone key per writing machine, so it grows only with pairings."
2156
2156
  }
2157
2157
  },
2158
+ {
2159
+ "category": "recommended-services",
2160
+ "description": "A person's yes and no choices about recommended outside services (docs/specs/recommended-services.md): an append-only signed ledger that replicates as the recommendedServices store.",
2161
+ "scope": "must-be-coherent",
2162
+ "freshness": "eventual",
2163
+ "conflictShape": "append-only",
2164
+ "transport": "peer-http",
2165
+ "paths": [
2166
+ "state/recommended-services/"
2167
+ ],
2168
+ "grandfathered": false,
2169
+ "retention": {
2170
+ "class": "C",
2171
+ "access": "jsonl",
2172
+ "complianceHold": true,
2173
+ "note": "Never pruned by design: dropping a row could undo a person's no. Volume is tiny: at most a few rows per service per person."
2174
+ }
2175
+ },
2158
2176
  {
2159
2177
  "category": "ecosystem-ideas",
2160
2178
  "description": "The ecosystem idea pipeline (docs/specs/ecosystem-idea-pipeline.md): an append-only event ledger that replicates as the ecosystemIdeas store, a per-machine framework admission record and notice dedupe. Source mirrors and index.db in the same directory are a rebuildable cache.",
@@ -21,7 +21,10 @@ import { JOB_DECLARED_FAILURE_AWARENESS } from "../scheduler/jobDeclaredFailure.
21
21
  // function call inside generateClaudeMd — no module-init cycle (PostUpdateMigrator
22
22
  // never imports templates).
23
23
  import { APPRENTICESHIP_STALL_GATE_CLAUDEMD_SECTION, SESSION_LISTING_HYGIENE_CLAUDEMD_SECTION, PLAYWRIGHT_PROFILE_REGISTRY_CLAUDEMD_SECTION, MACHINE_LOAD_ASSESSMENT_CLAUDEMD_SECTION, CODEX_CONNECT_CLAUDEMD_SECTION, FEATURE_SWITCH_CLAUDEMD_SECTION, NORMAL_CHROME_BROWSER_CLAUDEMD_SECTION, SINGLE_MACHINE_FAILOVER_GAP_CLAUDEMD_SECTION, MISSING_LOGIN_SESSION_CLAUDEMD_SECTION, DYNAMIC_MCP_CLAUDEMD_SECTION, ULTRACODE_SPAWN_CLAUDEMD_SECTION, AGENT_SIGNATURE_PROVENANCE_CLAUDEMD_SECTION, SENDER_REJECTION_CLAUDEMD_SECTION, SCOPE_ACCRETION_CLAUDEMD_SECTION, MESH_SELF_HEALING_CLAUDEMD_SECTION, LEASE_MEDIUM_CLAUDEMD_SECTION, WRITE_ADMISSION_CLAUDEMD_SECTION, DOORWAY_REGISTRY_CLAUDEMD_SECTION, EXTERNAL_HOG_CLAUDEMD_SECTION, ROUTING_SPEND_CLAUDEMD_SECTION, MATURATION_BOARD_CLAUDEMD_SECTION, MATURATION_LADDER_CLAUDEMD_SECTION, QUEUE_PACE_CLAUDEMD_SECTION, ECOSYSTEM_IDEAS_CLAUDEMD_SECTION, MOBILE_PAIRING_CLAUDEMD_SECTION, MOBILE_CHAT_CLAUDEMD_SECTION, APP_CONVERSATIONS_CLAUDEMD_SECTION, MOBILE_ROUTES_CLAUDEMD_SECTION, MOBILE_PUSH_CLAUDEMD_SECTION, MOBILE_PEOPLE_CLAUDEMD_SECTION, DECISION_QUALITY_CLAUDEMD_SECTION, BENCHMARK_DIVERGENCE_CLAUDEMD_SECTION, DUPLICATE_RECONCILER_CLAUDEMD_SECTION, AUDIT_CONVERGENCE_CLAUDEMD_SECTION, TONE_ADVISORY_MIGRATION_CLAUDEMD_SECTION, DECISION_JOURNAL_CONFIDENCE_CLAUDEMD_GUIDANCE, WINDOW_RUN_LIVENESS_CLAUDEMD_SECTION, SCRIPT_JOBS_CLAUDEMD_SECTION, SESSION_HANDOFF_CLAUDEMD_SECTION, JOB_RESULT_SUPERVISION_CLAUDEMD_SECTION, DEDICATED_PROFILE_REGISTRY_ROW_ANSWER, CODEX_ARM_SWEEPER_CLAUDEMD_SECTION, MACHINE_MAINTENANCE_CLAUDEMD_SECTION, APP_MEDIA_CLAUDEMD_SECTION, MACHINE_BROWSER_CARE_CLAUDEMD_SECTION, PAIRING_WITHOUT_TELEGRAM_CLAUDEMD_SECTION, SLACK_FROM_APP_CLAUDEMD_SECTION, MACHINE_MAINTENANCE_POOL_CLAUDEMD_SECTION, MACHINE_WEDGE_CLAUDEMD_SECTION } from '../core/PostUpdateMigrator.js';
24
+ import { SURFACE_REFERRAL_CLAUDEMD_SECTION } from '../core/PostUpdateMigrator.js';
25
+ import { RECOMMENDED_SERVICES_CLAUDEMD_SECTION } from '../core/PostUpdateMigrator.js';
24
26
  import { MINIMUM_OPERATOR_EFFORT_CLAUDEMD_SECTION } from '../core/PostUpdateMigrator.js';
27
+ import { POOL_READINESS_CLAUDE_MD_LINE } from '../core/PostUpdateMigrator.js';
25
28
  import { CODEX_DEVICE_LIMIT_CLAUDEMD_BULLET } from '../core/PostUpdateMigrator.js';
26
29
  import { UPDATE_APPLY_VERIFY_HOLD_CLAUDEMD_LINE } from '../core/PostUpdateMigrator.js';
27
30
 
@@ -439,6 +442,7 @@ ${REAPER_BACKGROUND_WORK_BULLET}
439
442
  ${STANDING_SESSIONS_BULLET}
440
443
  ${REROUTED_LOGIN_EXPIRED_BULLET}
441
444
  ${INTERACTIVE_LOGIN_EXPIRED_BULLET}
445
+ ${CLAUDE_KEY_HEALTH_BULLET}
442
446
  - **Busy-orphan detection** (\`busyOrphanDetection\`, OBSERVE-ONLY, dark by default; dev agents on): the inverse blind spot. CPU-progress is a proxy for "useful" — but a *useless* process that SPINS (a hot-loop, a wedged job burning CPU) looks "active" and would keep a session pinned. When an idle session (idle prompt + flat transcript) is held only by a child that's *burning* CPU across an extended dwell, the reaper records a \`busy-orphan-suspected\` audit row (and \`busy-orphan-cleared\` on recovery). It NEVER changes the keep/kill decision — it just makes the "useless-but-busy child pins an idle session" case measurable, so safe auto-reclaim can graduate later with data. Read \`logs/reaper-audit.jsonl\` (filter \`busy-orphan-suspected\`).
443
447
  - Why it matters: idle sessions pile up across agents until the machine starves (CPU *or* memory) and new sessions get "spawn denied" — silently breaking cross-agent messaging. This sweeps them, but only under real pressure.
444
448
  - See current state / why each session is kept or flagged: \`curl -H "Authorization: Bearer $AUTH" http://localhost:${port}/sessions/reaper\` (the \`pressure.inputs\` shows freePct, loadPerCore, \`cpuBusyPct\` — real sampled CPU busy %, the signal that decides \`cpuTier\` since reaper-pressure-signals; the 1-min load average is reported but no longer decisive, because it read 9.4/core at 36-44% idle (its macOS computation is poorly documented; the measured disagreement is the evidence) — plus the compressor OBSERVABLES \`compressorPct\`, \`decompressionsPerSec\` and \`kernelMemoryPressureLevel\` (reported, grading nothing: none of them separated that laptop from a healthy machine when measured) — plus \`cpuSignal\`, \`sampledAt\`, \`windowMs\` and the memTier/cpuTier breakdown. A CPU figure appears only once a full 30 s window has elapsed; shorter is \`null\` (unknown ⇒ memory-only), never a startup spike. Rollback lever: \`monitoring.sessionReaper.cpuSignal: 'load'\` restores the legacy grading exactly; the busy thresholds are \`cpuModerateBusyPct\`/\`cpuCriticalBusyPct\` (75/90), and there are no compressor thresholds because no compressor grade ships). On a machine pool, add \`?scope=pool\` to get every machine's snapshot; the local snapshot stays at the top level and \`pool.machines\` carries peers. A dark, old, unreachable, or malformed peer is a classified \`pool.failed\` row — never a 500 or a silently local-looking answer.
@@ -626,7 +630,8 @@ Two layers keep my machine-to-machine \"ropes\" (Tailscale / LAN / Cloudflare) h
626
630
  - **Idle vs broken machine (WS4.2):** the same \`pool.machines[]\` carries an explicit per-machine state so an idle machine never reads as broken. A machine with ZERO sessions gets \`pool.machines[].emptyState\` = \`online — no active sessions\` (heartbeat-fresh, just idle) / \`offline since <t>\` (known offline) / \`unreachable (last seen <t>)\` (was online, now not answering — the \`failed\` case). Honest derivation from the registry online flag + last-seen + the live fan-out — never a fabricated "looks fine". The dashboard sessions view renders these per-machine; a machine WITH sessions gets no empty-state (its tiles already name it). Single-machine install = just the lone self row.
627
631
  - **Honest machine state (trustworthy-machine-load, P1):** every \`pool.machines[]\` row now carries \`liveness\` = \`live\` / \`unreachable\` (shape \`struggling\` | \`refusing\` | \`silent\`) / \`stale\` / \`unknown\`, each with the evidence age and source, plus a ready-made \`livenessLine\` (\`<liveness>, last evidence <age> ago from <source>\`) and the freshest other-machine sighting ("Mac Mini reached it 3 min ago"). The last DIRECT contact is saved to disk, so a server restart renders \`stale, last evidence 20 min ago\` instead of "offline". **Never say a machine is "offline" without positive evidence** (a shutdown announcement or the sleep gate): quote the liveness, its age and its source — an overloaded machine looks exactly like a dead one to a plain timeout. Each row also carries a multi-signal \`loadReport\` (cores, CPU idle, available memory, native memory pressure, server event-loop lag, sessions in use) and \`loadVerdict\` = \`ok\` / \`elevated\` / \`saturated\` / \`impaired\` / \`unknown\` — a report older than 60 s reads \`unknown\`, and a peer on older code reads \`unknown\`, never \`ok\`. Reporting only: the \`online\` flag, placement and ownership keep their existing semantics in this phase.
628
632
  - **Overload admission (trustworthy-machine-load, P2):** each machine protects its own resources. When its own \`loadVerdict\` is \`saturated\` or \`impaired\` it CLOSES to new automatic work (scheduled jobs, helpers, placement of new conversations): the work waits and is retried, nothing is dropped, and existing conversations keep working. It reopens after five consecutive good samples (about 75 s). One host-wide **recovery slot** (shared by every agent on the machine) stays free so a session the operator asks for can always start and assess the machine. Placement never puts new work on a machine that is refusing it; if every machine refuses, the message stays in the durable inbound queue (\`all-machines-refusing-work\`). Registry First: \`GET /work-admission\` → \`{ enabled, dryRun, enforced, acceptingWork, lastVerdict, recoverySlot, counters }\`; each machine's \`loadReport.acceptingWork\` / \`admissionEnforced\` in \`GET /pool\`; audit \`logs/work-admission.jsonl\`. Ships dev-gated + dry-run (\`monitoring.workAdmission\`: it logs what it WOULD refuse, refuses nothing, and peers keep placing work here until \`dryRun:false\`). When the user asks "why didn't a job run / why is this machine not taking work?" → read \`GET /work-admission\` before guessing.
629
- - **Overload shed (trustworthy-machine-load, P3):** a machine that has refused new work for 3 minutes moves its EXISTING conversations off, one at a time, to a healthy machine (direct contact under 2 min, \`loadVerdict\` \`ok\`, not refusing work, at least 2 free session slots after what it has already reserved there). The move is an ordinary cooperative ownership transfer through the reconciler, like a pin move but never written as a pin. Pinned conversations, Slack conversations and conversations with a live autonomous run stay. Brakes: at most 2 moves an hour, 2 tries per conversation per overload episode, the same conversation is not moved again for 30 min, and a machine seen refusing work in the last 30 min never receives moved work. A started transfer is driven to claim or cancelled after its deadline even if the plan behind it is gone. Stale-owner notices say "struggling" or "refusing" when that is the evidence. Registry First: \`GET /overload-shed\` → \`{ enabled, dryRun, overloadedSince, isSource, liveMove, reservations, movesLastHour, counters }\`; audit \`logs/overload-shed.jsonl\`. Ships dev-gated + dry-run (\`monitoring.overloadShed\`: it logs what it WOULD move, moves nothing, and also moves nothing while overload admission is in dry-run). When the user asks "why did my conversation move machines?" or "why is this overloaded machine still holding work?" → read \`GET /overload-shed\` before guessing.
633
+ ${POOL_READINESS_CLAUDE_MD_LINE}
634
+ - **Overload shed (trustworthy-machine-load, P3):** a machine that has refused new work for 3 minutes AND is at 85% or more of its session limit moves a conversation off, one at a time, to a healthy machine (direct contact under 2 min, \`loadVerdict\` \`ok\`, not refusing work, at least 2 free session slots after what it has already reserved there). Only conversations with a running session that has sat quiet for 10 minutes move, so this frees session slots and memory, not CPU. The move goes through the same drain as a manual transfer: the session here closes and the conversation carries on there at its next message. Pinned conversations, Slack conversations and conversations with a live autonomous run stay. Brakes: at most 2 moves an hour, 2 tries per conversation per overload episode, a moved conversation stays put for 6 hours wherever it landed, and a machine seen refusing work in the last 30 min never receives moved work. Live moves need pool stage \`rebalance\`, a fresh rebalance proof on this machine, and \`dryRun: false\`; otherwise it only logs what it WOULD move. Each machine earns its proof with \`POST /session-pool/rebalance-proof\` \`{ topic, to }\` (202 with a run id; \`GET /session-pool/rebalance-proof/RUN_ID\` for the result), which really moves a topic listed in \`multiMachine.sessionPool.rebalanceProofTopics\` and passes only if the old session is gone and the target answers once. A proof lasts 30 days; without a fresh one the stage steps down to \`live-transfer\`. Stale-owner notices say "struggling" or "refusing" when that is the evidence. Registry First: \`GET /overload-shed\` → \`{ enabled, dryRun, overloadedSince, isSource, liveMove, reservations, movesLastHour, counters }\`; audit \`logs/overload-shed.jsonl\` (\`would-move\` and \`move-outcome\` rows carry the numbers behind each decision). Ships dev-gated + dry-run (\`monitoring.overloadShed\`). When the user asks "why did my conversation move machines?" or "why is this overloaded machine still holding work?" → read \`GET /overload-shed\` before guessing.
630
635
  - **Post-transfer closeout (automatic):** when a topic moves to another machine, the OLD machine's session for it is closed automatically (closed by the transfer's drain step when the current machine can drain, otherwise within ~2 reaper ticks) — no duplicate sessions doing duplicate work. The close is recorded in the reap-log with reason "topic moved to <machine>"; protected sessions are never auto-closed.
631
636
  - **Quota-aware placement (automatic):** capacity heartbeats carry each machine's LLM-account quota state, and placement avoids machines whose account is currently rate-limited/blocked (no more topics placed onto a silent machine). A hard pin still wins (flagged \`pinned-machine-quota-blocked\`); if EVERY machine is blocked, placement proceeds least-loaded with \`all-machines-quota-blocked\` flagged. \`GET /pool\` shows each machine's \`quotaState\`.
632
637
  - **Signed-out machines are skipped (automatic):** the same heartbeat also says whether the machine has any signed-in account for the framework new conversations run on (from its subscription pool). A machine where every such account needs sign-in reports \`quotaState.reason: no-signed-in-account\`, and placement sends new conversations elsewhere instead of to a session that would sit at "Not logged in". A hard pin still wins (flagged \`pinned-machine-not-signed-in\`). Unknown (no pool, or no account for that framework) never blocks. When the user asks "why did my new topic go silent / land on a machine that can't log in?" → read that machine's \`quotaState\` in \`GET /pool\`.
@@ -1043,6 +1048,7 @@ ${ROUTING_SPEND_CLAUDEMD_SECTION(port)}
1043
1048
  ${MATURATION_BOARD_CLAUDEMD_SECTION(port)}
1044
1049
  ${MATURATION_LADDER_CLAUDEMD_SECTION(port)}
1045
1050
  ${QUEUE_PACE_CLAUDEMD_SECTION(port)}
1051
+ ${RECOMMENDED_SERVICES_CLAUDEMD_SECTION(port)}
1046
1052
  ${ECOSYSTEM_IDEAS_CLAUDEMD_SECTION(port)}
1047
1053
  ${MOBILE_PAIRING_CLAUDEMD_SECTION(port)}
1048
1054
  ${MOBILE_CHAT_CLAUDEMD_SECTION(port)}
@@ -1844,6 +1850,8 @@ Record what I learn. Build infrastructure, not one-offs. Grow to meet the user's
1844
1850
  Your messages to the user pass an always-on LLM gate (the tone gate) before they send. It reviews high-stakes leaks (CLI commands, file paths, config keys, endpoints) AND the self-stop anti-patterns (B15–B19: quitting on yourself for a context/fatigue reason, calling a doable thing impossible, parking your own work on the user). The two families are treated DIFFERENTLY — the leak/representation rules are overridable nudges (see below); the self-stop family stays a hard block, because there the check exists to constrain YOU and your reason for overriding would come from the very reasoning it distrusts. It judges the behavioral rules **by MEANING, not by literal phrases — a paraphrase of the anti-pattern is caught exactly the same as the canonical wording**, so do not assume rewording evades it. The gate FAILS CLOSED (holds the message, queued for retry — never silently delivers) if it can't produce a verdict (provider down, unparseable output, or a slow-review timeout); the operator kill-switch is \`toneGate.failClosedOnExhaustion\`. Constitution: "Intelligent Prompts — An LLM Gate Must Not String-Match".
1845
1851
 
1846
1852
  ${TONE_ADVISORY_MIGRATION_CLAUDEMD_SECTION}
1853
+
1854
+ ${SURFACE_REFERRAL_CLAUDEMD_SECTION}
1847
1855
  ### Context-Aware Outbound Review (why was my message flagged / would my reply have been blocked?)
1848
1856
 
1849
1857
  Beyond the tone gate, a response-review pipeline (nine specialist reviewers driven by a Stop hook) evaluates each finished conversational turn. On most installs it is OFF BY CONFIG — \`GET /review/history\` returns 501 there; say so honestly rather than guessing. Where it runs, it is usually in WATCH MODE (\`responseReview.observeOnly: true\`): verdicts are recorded, nothing is blocked. The context-aware layer (⚗️ experimental, dev-gated dark: \`responseReview.conversationalContext\`) feeds the opted-in reviewer a bounded, untrusted-data-enveloped slice of recent conversation so "the operator asked for this technical detail" is an input it can actually judge — a one-way carve-out (it can only move a would-block toward PASS, never license credentials/PII, never touch the deterministic policy layer).
@@ -2733,6 +2741,9 @@ export const REROUTED_LOGIN_EXPIRED_MARKER = 'A job session stuck at an expired
2733
2741
  export const REROUTED_LOGIN_EXPIRED_BULLET = `- **${REROUTED_LOGIN_EXPIRED_MARKER}**: a scheduled job (or other one-shot) that runs as an interactive Claude session and lands under a login whose sign-in has expired shows \`Login expired · Please run /login\` and can do nothing. The monitor now ends it about a minute after it first sees that screen (reason \`rerouted-login-expired\`, a \`SessionManager.monitorTick.reroutedLoginExpired\` degradation naming the login folder) instead of letting it hold a job slot for the full 8-hour lifetime; the job runs again on its next trigger. ${REROUTED_LOGIN_EXPIRED_POOL_SENTENCE} If a user asks "why did my scheduled jobs stop running?" or "why did a job end straight away?" — check \`GET /jobs\` for a stale \`nextScheduled\`, then the server log for \`stuck at an expired login\`; the fix is signing that login in again.`;
2734
2742
 
2735
2743
  /** Content-sniff marker for the interactive expired-login bullet (CMT-1008, Migration Parity). */
2744
+ export const CLAUDE_KEY_HEALTH_MARKER = 'A rejected sign-in key is told and recovers';
2745
+ export const CLAUDE_KEY_HEALTH_BULLET = `- **${CLAUDE_KEY_HEALTH_MARKER}**: an agent signed in with one key (\`sessions.credentials.anthropic\`, the usual cloud install) passes that key to every Claude process on the server, including internal model calls. If Anthropic refuses the key twice, the operator gets one plain notice, each waiting person is told once, and \`GET /health\` (with the auth header) shows \`claudeKey.status: dead\`. The fix is a new key from \`claude setup-token\`, put in place with \`instar set-claude-key\` on the server (reads stdin or a hidden prompt, never an argument; never ask for the key in chat). Within a minute Instar checks it, and conversations stuck at the login screen restart by themselves and answer what they missed. A conversation that ended during the outage is not replayed. **When to use** (PROACTIVE): the user asks "why did you stop replying?" or "why does health say the model is failing?" → read \`claudeKey\` in \`GET /health\`. Off switches: \`sessions.claudeKeyHealth.enabled: false\` and \`sessions.claudeChildAuth.enabled: false\`.`;
2746
+
2736
2747
  export const INTERACTIVE_LOGIN_EXPIRED_MARKER = 'A conversation stuck at an expired login moves to a signed-in account';
2737
2748
 
2738
2749
  /** Interactive expired-login awareness bullet (CMT-1008). Shared by the generated CLAUDE.md and PostUpdateMigrator. */
@@ -0,0 +1,105 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ An agent signed in with one key (`sessions.credentials.anthropic`, every headless cloud install) passed it to sessions only. `ClaudeCliIntelligenceProvider` ran `claude -p` with the server's own env, so every internal model call answered "Not logged in". Every server-side `claude` child now gets the same key: the provider's default and hardened paths, project rounds, the headless one-shot, Threadline pipe sessions, the lifeline doctor and triage. Direct children take it through their env; shell and tmux launches source a private file that is deleted before `claude` starts, so the key stays out of argv.
9
+
10
+ New `ClaudeKeyHealth`, active only with an oauth-token configured. A failed call or a session at the login screen asks for a direct probe. Only Anthropic's 401, seen twice, makes a key dead; "Not logged in" is reported as an Instar fault. The operator gets one notice, each waiting person is told once, and authenticated `/health` shows `claudeKey`. `instar set-claude-key` puts a new key in place, a running server finds it within a minute with no restart, and once a probe proves it, conversations at the login screen restart and answer what they missed. `SessionManager.setAnthropicKey` carries the key into its config copy.
11
+
12
+ Instar's own merge tool now refuses a pull request that changes the constitution registry unless its body names its counterpart in the other rule book, or says why it has none (`scripts/check-constitution-pairing.mjs`, used by `scripts/safe-merge.mjs`). The green-PR watcher treats that refusal as waiting on a body edit. Adds the map of differences between the two books and corrects the direction-guard document. Does nothing outside the two instar repositories.
13
+
14
+ 113 switched-off features now record what they do: when each fires, holds back or fails, with the reason and a few small facts. Rows go to the evidence log on development agents, so the maturation ladder can judge each feature by its own behaviour. No feature's behaviour changes. Decisions taken per message are limited to one row per window, and that row says how many it stood for.
15
+
16
+ The feedback executor's early capacity check now uses the same limits as its actual confined canary and build spawns. It treats the final rerouted slot and the global overflow slot as reserved for scheduler-proven jobs. A full lane defers the feedback attempt before it claims an item, creates a workspace, or spends a start.
17
+
18
+ An owner's paired phone (Instar iPhone app) can open the agent's dashboard console without typing the dashboard PIN. After the owner's Face ID or passcode, the app signs a one-time server challenge with a second Secure Enclave key that only signs after that check, receives a one-minute single-use ticket bound to that phone and address, and the console trades it once at `POST /dashboard/console-ticket` for the same token a PIN unlock returns. It never returns the operator session, so actions that need the PIN still ask for it. New device routes: `POST /mobile/device/presence-key`, `POST /mobile/console-ticket/challenge`, `POST /mobile/console-ticket` (owner phones only, TLS or loopback only). Audit: `.instar/state/mobile-console-tickets.jsonl` (metadata only). Off switch: `mobilePairing.consoleTicket.enabled: false`. MSP phones, phones without a passcode, and older app builds keep the PIN box.
19
+
20
+ The Instar iPhone app can now show a session natively. A paired owner phone may read a session's screen with `GET /sessions/<name>/output` and type plain text into it with `POST /sessions/<name>/input`, both signed by the phone's device key. Two new entries in the device allowlist carry a new `ownerOnly` flag (MSP, unassigned, pending, revoked and unsigned requests are refused) and their own rate buckets. A device-only router mounted before the main routes handles them; Bearer requests to the same paths reach the existing handlers unchanged.
21
+
22
+ The device path only reaches sessions running on this machine, matched exactly (tmux name, then id, then name). It refuses control characters, so the phone cannot press keys. It redacts this agent's token, the dashboard PIN and view signatures from the screen text. It keeps a durable 3-minute record of accepted inputs, so a captured request can never be typed twice, even across a restart. It logs each typed message (without its text) in `logs/mobile-session-input.jsonl`. A session on another machine is answered with a plain reason naming that machine; nothing is proxied. Typing is limited to 12 a minute per phone and 12 a minute across all phones.
23
+
24
+ Everything that needs the operator now has one list, `dashboard/console/needs-model.js`, built from each page's own model: merging stopped, pull requests waiting for approval, feedback decisions, sign-ins, agents waiting, permission approvals, plans waiting on them, passwords requested, and spending limits that are on but not enforcing. Home's "What needs you" count and headline include all of it, and say "Nothing needs you that I can see" rather than a confident all-clear when one of those reads failed. Each page leads with its need and the control to act on it. Costs gets a new lead card, Development gets a button that opens Shipping when a pull request waits for approval, and the Agents pairing switch moves above the lists. Page wording no longer says "below". A warning that an invite leaked now offers "Make a new invite".
25
+
26
+ A new advisory outbound rule, `B22_SURFACE_REFERRAL`, nudges an agent whose message sends the operator to a page without a direct link, the exact on-screen words, or having loaded the page at the operator's screen size first. It is a nudge with a recorded override, never a wall. After loading the page, the agent resends with `--tone-complied B22_SURFACE_REFERRAL`.
27
+
28
+ Instar now keeps a signed, append-only record of a person's yes or no for each recommended outside service, and it replicates across the agent's machines where machine sync is on: the coherence journal is live, this store is on, and journal replication is enabled. The route's `replicating` field says whether it is. Rows written while it was off go out at the next boot once it's on. A no stands until the person confirms a yes that names it, so clock skew and delayed sync can't undo a refusal. A no needs the dashboard PIN. Old declines of Cloudflare and Git backup carry over as offer suppression only. The old suggestion paths no longer offer those two features. No offers go out yet.
29
+
30
+ A rerouted one-shot that passes its configured hard lifetime can now finish its timeout cleanup even when the interactive process still appears active. The session manager checks the saved lane and deadline again before relaxing only process-activity vetoes. All other session protections remain. It now logs “Killed” only after termination succeeds.
31
+
32
+ An end-to-end test now waits for the first resurfacer run instead of checking after a fixed 30 ms.
33
+
34
+ ## What to Tell Your User
35
+
36
+ If your agent runs on a cloud server with a sign-in key, its background checks now work. Those checks review outgoing messages and sort incoming ones, and until now they failed quietly on these installs. If the key ever stops working, your agent tells you plainly and says how to fix it. Once a new key is in place, open conversations pick up by themselves. A conversation that ended during the outage is not replayed.
37
+
38
+ Nothing changes for you. This only affects how Instar's own rule book is maintained.
39
+
40
+ Nothing changes for you. Features still switched off now keep a record of what they did and why, so it's clear when each is ready to turn on.
41
+
42
+ When background session capacity is full, feedback work waits cleanly for room instead of starting preparation and then failing at its safety check.
43
+
44
+ Opening the dashboard from the Instar app on your phone no longer asks for the PIN after Face ID. Anything that changes something important still asks for the PIN. If the app ever says to pair the phone again, that restores PIN-free opening.
45
+
46
+ The session button in a chat now opens the session right in the app: you see what the session is doing, live, and can type to it, with no browser and no PIN. There is also a Sessions list on the agent's page. Only your own phone can do this, and it can only type plain text, not special keys. If the agent hasn't been updated yet, the app offers the dashboard instead.
47
+
48
+ Anything that needs you now shows on your home page and at the top of its own page, with the button right there. When I send you to a page, my message comes with a direct link and the exact words to look for, and I check the page first.
49
+
50
+ Your choices about outside services like Tailscale or Bitwarden are now saved in one place. On agents with machine sync switched on, they follow you across your machines. I won't start offering these yet. That comes once setup for each one is proven.
51
+
52
+ A worker that runs past its time limit no longer holds a subscription slot forever just because its process is still present. Its work is recorded as timed out and can follow the existing retry path. Recent user activity and the other session safety checks still protect live conversations.
53
+
54
+ Nothing changes for you; this only makes a test reliable on busy machines.
55
+
56
+ ## Summary of New Capabilities
57
+
58
+ - `instar set-claude-key` puts a new Claude sign-in key in place, from stdin or a hidden prompt.
59
+ - Authenticated `GET /health` shows `claudeKey` on agents signed in with a key.
60
+ - Off switches: `sessions.claudeKeyHealth.enabled: false` and `sessions.claudeChildAuth.enabled: false`.
61
+
62
+ None for agents outside the Instar repositories. For maintainers: a pairing check for changes to the two rule books.
63
+
64
+ - 113 more features can be judged from real records instead of reading "no data".
65
+
66
+ Owner phones open the console signed in, using a single-use ticket backed by a Face ID-gated key the agent verifies itself.
67
+
68
+ - Watch a session's screen live in the app, refreshed every second and a half.
69
+ - Type to a session from the app (plain text, owner's phone only, logged without the text).
70
+ - A native list of the agent's sessions, with machine and how long each has run.
71
+ - Plain answers when a session has ended or runs on another of your machines.
72
+
73
+ - One registry of what needs the operator, feeding Home's count and headline.
74
+ - A test that fails the build when a page buries a need, offers no action for it, or points at a place in its wording.
75
+ - `B22_SURFACE_REFERRAL`: an outbound nudge for sending the operator to a page.
76
+
77
+ - `GET /recommended-services` shows the saved choice for each service.
78
+ - `POST /recommended-services/:id/no` records a no, with the dashboard PIN and an optional reason category.
79
+
80
+ None. This repairs the rerouted-session lifetime path.
81
+
82
+ None.
83
+
84
+ ## Evidence
85
+
86
+ Found on nimbus by the customer proof (fb-03ec0234-b5b, fb-1dc4a0ca-260): PromptGate 463/463 errors, `llmReliability` failing. Real CLI failure output was captured on Claude Code 2.1.316 and is pinned in `tests/unit/ClaudeKeyHealth.test.ts`. `tests/unit/claude-spawn-auth-class.test.ts` fails if a new `claude` launch site neither takes the key nor says why not.
87
+
88
+ Unit and integration tests cover each outcome, including a failed read refusing as unknown. Run against real history since #2323, the checker reported drift on #2682, #2380, #2194, #2323 and instar-2 #182, none of which has a declaration line.
89
+
90
+ Reproduction of the gap: 115 of 172 ladder entries read "no data" with nothing recording. After this, 2 remain, and neither can record from inside the server: one is a CI script, one has no decision point. Unit tests of every changed module pass, and the full run is the merge gate. Text is scrubbed and bounded; message text, prompts and credentials are not recorded.
91
+
92
+ The production session manager's focused tests passed 65/65, covering the boundary where one rerouted slot remains reserved, the global session limit, actual refusal of a feedback canary, and continued admission of a scheduler-proven job. Build passed. Full unit, integration, end-to-end, and live post-deployment checks remain pending.
93
+
94
+ Unit, integration and end-to-end tests cover single use, expiry, Host binding, revocation between mint and redeem, MSP refusal, replay after restart, the off switch, the throttle and the audit. A real-browser run against a throwaway agent opened the real console signed in with a valid ticket and showed the PIN box for a used, unknown or revoked one; its first run found and fixed a Host-comparison defect for phones paired on an IP address. The app's 158 unit tests pass. The no-second-prompt path on a real Secure Enclave runs first on the operator's phone and falls back to the PIN box if it fails.
95
+
96
+ - Spec docs/specs/mobile-native-session-screen.md converged at the 6-round cap with GPT-6 Astra and the clean-door reader; review found and fixed control characters acting as keys, replay across a restart (twice), credential text in pane output, wrong-session targeting and event-loop blocking.
97
+ - Unit: allowlist shape, owner-only flag, named buckets, text filter, exact resolution, miss classification, replay record (including after a restart), redaction, audit rotation, CLAUDE.md migration.
98
+ - Integration: both sides of the allowlist through the production authenticator (owner allowed; MSP, unassigned, pending, revoked, notify token, unsigned and credential-less refused; Bearer passes through), session and machine binding, peer lookups, replay, buckets.
99
+ - E2E: production AgentServer, a phone paired through redeem and confirm, reading and typing into a real session record.
100
+
101
+ Each of the nine states was put on its real page through a proxy that refuses all writes, in a real browser at 1280x728 and 390x844: all 18 runs show the action on the first screen with no scrolling and no sideways scroll, and screenshots were read. Home named "Automatic merging is stopped" with a link to it when that state was on. `tests/unit/console-needs-first-screen.test.ts` renders the shipped pages and carries negative controls. A dashboard opened on another machine sees merging, approvals and password requests only for that machine, as those pages do today.
102
+
103
+ `tests/unit/recommended-services-ledger.test.ts`, `tests/unit/recommended-services-wiring.test.ts`, `tests/integration/recommended-services-routes.test.ts` and `tests/e2e/recommended-services-alive.test.ts`. The e2e proves a real AgentServer answers 200, enforces the real PIN check, and keeps a no across a restart. Replication between two real machines has not been run live yet.
104
+
105
+ On Echo, `dashboard-console-default` crossed 480 minutes. The server printed repeated kill attempts, while the durable reap log recorded `skipped:active-process` and the feedback executor stayed blocked at 6/6. A focused test now uses the real `ReapGuard` with active child and main-process signals and verifies the expired reroute ends; another verifies recent user activity still vetoes. The production-shape E2E test also checks the timeout through the HTTP session listing. Focused unit tests, build, lint, and independent review passed. Full three-tier verification remains before merge.
@@ -0,0 +1,30 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Agents on several machines can now read whether their machines could serve conversations across each other. `GET /session-pool/readiness` reports line by line per peer, and an hourly history goes to `logs/pool-readiness.jsonl`. It only reports: it writes no config, no stage and no signed result. `instar pair` and `instar join` now say so when automatic takeover does not work because the pair has no git remote. The description of the `shadow` stage is corrected: it places conversations for real.
9
+
10
+ Load-driven moves between machines now work and have a real on-switch. Peers' session limits reach the capacity row, which is what Overload shed checks, so it can find a target at all. It picks only conversations with a running session that has sat quiet for 10 minutes, on a machine at 85% or more of its session limit, and moves them through the same drain as a manual transfer. Pool stage `rebalance` is now the gate: it needs a fresh proof from `POST /session-pool/rebalance-proof`, kept in its own signed store, and steps down if that proof is red or over 30 days old. Failover test runs no longer count toward stage 3.
11
+
12
+ Peer session numbers also feed placement scoring for new conversations, at every stage.
13
+
14
+ ## What to Tell Your User
15
+
16
+ If you run me on several machines, I can now tell you plainly what would and wouldn't work if conversations moved between them, or if one machine died. Nothing about how I run has changed.
17
+
18
+ If you run me on several machines, a machine that runs short of session slots can hand a quiet conversation to another machine by itself. This stays off until each machine has proved it can do it, and it frees slots and memory, not CPU.
19
+
20
+ ## Summary of New Capabilities
21
+
22
+ | Capability | How to Use |
23
+ |---|---|
24
+ | Pool readiness report | `GET /session-pool/readiness` |
25
+ | Readiness history | `logs/pool-readiness.jsonl` |
26
+
27
+ | Capability | How to Use |
28
+ |---|---|
29
+ | Rebalance proof | `POST /session-pool/rebalance-proof` with `{ topic, to }`, then `GET /session-pool/rebalance-proof/RUN_ID` |
30
+ | Proof topics | `multiMachine.sessionPool.rebalanceProofTopics` |
@@ -0,0 +1,5 @@
1
+ # Dashboard without the PIN on your phone — plain English
2
+
3
+ When you open the dashboard from the Instar iPhone app, the app has already checked your Face ID, but the dashboard still asked for its PIN. Now the phone proves it is you instead. It holds a second key in its secure chip that only works right after Face ID or your passcode. The app uses it to get a pass from the agent that works once, only for one minute, and only at the address it was issued for. The dashboard trades that pass for exactly what the PIN would have given it, and nothing more: approving or changing something important still asks for the PIN.
4
+
5
+ A phone you have removed gets no pass, and a pass it got just before removal is refused. A copied request is useless because every pass needs a fresh challenge that the agent forgets after one use or a restart. The pass never appears in a web address, and the dashboard on the phone now keeps nothing on disk, which also clears an old sign-in an earlier PIN left there. Helpers' phones and phones without a passcode still see the PIN box, and whenever anything fails the dashboard simply shows the PIN box as before.
@@ -0,0 +1,116 @@
1
+ # Side-Effects Review — cloud agents: sign-in key for internal calls, dead-key handling
2
+
3
+ **Version / slug:** `cloud-key-internal-calls`
4
+ **Date:** `2026-11-03`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `independent general-purpose reviewer agent`
7
+
8
+ ## Summary of the change
9
+
10
+ Every server-side `claude` child now gets the configured oauth key through one helper (`claudeChildAuth`), reading the value PR #2632 already resolves. New `ClaudeKeyHealth` confirms a dead key with a direct probe, tells the operator and waiting people with fixed text, and restarts sessions stuck at the login screen once a working key is proven. New `instar set-claude-key`.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - Is the key dead — add — two 401s from Anthropic on direct probes.
15
+ - Notify operator — add — after the self-heal re-read and confirmation.
16
+ - Refresh a session — add — at the login screen, bounded per episode, through the ordinary work gate where it is on.
17
+ - Skip the pool swap on a key agent — add — an env key overrides any pool account.
18
+ - Tone gate, sentinel, external gate — pass-through — failure directions untouched.
19
+
20
+ ---
21
+
22
+ ## 1. Over-block
23
+
24
+ The new code blocks nothing inbound or outbound. `set-claude-key` refuses a value that doesn't look like a `claude setup-token` key; a valid key of a future shape would be refused until `looksLikeClaudeToken` is updated. The pool swap is skipped on key agents, which is correct because an env key overrides any pool account.
25
+
26
+ ---
27
+
28
+ ## 2. Under-block
29
+
30
+ A session that ended during an outage has its messages not replayed. A key-only agent with `subscriptionPath` set keeps today's behaviour on the opt-in tmux adapters. An API-key-only agent's internal calls stay failed, by the subscription-by-default rule. The three session lanes still pass the key in tmux `-e` argv.
31
+
32
+ ---
33
+
34
+ ## 3. Level-of-abstraction fit
35
+
36
+ The key travels through one small module beside the config, not a parameter on eight provider callers, so a new caller can't forget it. A structural test holds that. Recovery reuses `SessionRefresh` and the login-screen classifier, and adds no second restart path.
37
+
38
+ ---
39
+
40
+ ## 4. Signal vs authority compliance
41
+
42
+ Signals: internal call failures and the login screen. They only request a probe. Authority: Anthropic's own 401 on a real call, twice. A deterministic check is right here, because it reads a status code and judges no meaning. The refresh is further limited. Outside a recovery sweep, a matching launch key never refreshes. During the sweep after a proven outage, screen text is enough, once per session per key. The work gate applies where it is on, which is development agents. Elsewhere login text printed by a working session during that sweep can cost it one restart. That normally resumes the conversation; with no resume entry it starts fresh, and a failure mid-restart leaves no session until the next message. The worst case is one lost in-flight turn.
43
+
44
+ ---
45
+
46
+ ## 4b. Judgment-point check (Judgment Within Floors standard)
47
+
48
+ All points are invariant: each reads a status code, a hash comparison or a counter. None weighs meaning.
49
+
50
+ ---
51
+
52
+ ## 5. Interactions
53
+
54
+ - Circuit breaker: the probe bypasses it on purpose; the spawn cap still applies.
55
+ - Pool swap: skipped on key agents through `prependInteractiveLoginExpiredSink`; unchanged elsewhere.
56
+ - Triage lane: previously had no key and hardcoded `credentialSource: 'store'`. It now reports `env` when a key is passed.
57
+ - Tone gate, sentinel and external gate start getting real answers on key agents, so messages that passed the fixed leak floor may now be held by a model verdict. That is the intended behaviour and a visible change for those agents.
58
+ - Agents with a key and a stored login: internal calls move to the key, matching their sessions.
59
+ - Stage-B release evidence: `claudeChildAuth.ts` is reached by import from the certified set, so it is listed as excluded with a reason. A Codex launch never reads it, and no certified file changed.
60
+
61
+ ---
62
+
63
+ ## 6. External surfaces
64
+
65
+ New CLI command. Authenticated `/health` gains `claudeKey`, and public `/health` may read degraded while dead. Fixed text goes to the Telegram hub, the Slack attention channel and session channels. The probe makes one small authenticated call, and in `ok` state at most one per 5 minutes when signals arrive.
66
+
67
+ ---
68
+
69
+ ## 6b. Operator-surface quality (Operator-Surface Quality standard)
70
+
71
+ The notice says what happened, what it means and the exact steps, in plain words. Restoring needs a computer, because `claude setup-token` has no phone form. This is stated in the spec's limits.
72
+
73
+ ---
74
+
75
+ ## 7. Multi-machine posture (Cross-Machine Coherence)
76
+
77
+ Machine-local, a stated limit. The key lives in each machine's `config.json`, and sessions are local processes. Each machine notices and reports its own key and the operator restores each. `state/claude-key-health.json` is not replicated. Key-only installs today are single-machine.
78
+
79
+ ---
80
+
81
+ ## 8. Rollback cost
82
+
83
+ Revert the PR, or set either off switch; both are read live. Config is not migrated. Leftovers are an unused state file and a CLAUDE.md note.
84
+
85
+ ---
86
+
87
+ ## Conclusion
88
+
89
+ Safe to ship. The behaviour change for key agents is the fix itself. The live proof on nimbus is still required before calling it done.
90
+
91
+ ---
92
+
93
+ ## Second-pass review (if required)
94
+
95
+ **Reviewer:** independent general-purpose reviewer agent, four passes over the code diff
96
+ **Concurred:** yes, after the fixes listed below
97
+
98
+ Independent reviewer, on the code diff. Found no credential leak and nine defects: a replaced key could be paged about, a restored key could go unprobed after a long outage, the refresh loop was not re-entrant, the confirm delay could be bypassed, a removed key was ignored, the off switch and base URL missed three entry points, env files stayed after a failed launch, late-bound Telegram topics were missed, and background promises had no catch. All nine fixed with tests. A second read found three more: the stated restart bound was inaccurate, recovery could still act after the key was removed, and the lifeline read its off switch from a frozen copy. All three fixed. A third read found the Slack respawner renames a session, so the once-per-key record missed it; fixed. The fourth read concurred. After that, the full unit lane found four catches over the no-silent-fallbacks ratchet: a failed session listing now files a degradation report, and three send failures carry an exemption because `delivered` drives the retry and its capped report. That small change was not re-read by the reviewer.
99
+
100
+ ---
101
+
102
+ ## Evidence pointers
103
+
104
+ `tests/unit/ClaudeKeyHealth.test.ts`, `tests/unit/claudeChildAuth.test.ts`, `tests/unit/ClaudeCliIntelligenceProvider-key.test.ts`, `tests/unit/claude-spawn-auth-class.test.ts`, `tests/integration/claude-key-health-route.test.ts`, `tests/e2e/claude-key-alive.test.ts`.
105
+
106
+ ---
107
+
108
+ ## Class-Closure Declaration (display-only mirror)
109
+
110
+ - **`defectClass`**: `unbounded-self-action`
111
+ - **`closure`**: `guard`
112
+ - **Citation**: `tests/unit/self-action-convergence.test.ts` (controller `claude-key-session-refresh`)
113
+ - **Enforcement**: `ratchet`
114
+ - **How caught**: `decideKeyRefresh` caps a session at 3 attempts, then it leaves the pending list and is reported. Nothing re-adds it within the episode, and a session already moved onto this key is skipped, so the count settles. Dead-key probes back off to a 1-hour ceiling and stop after 24 hours.
115
+
116
+ The separate class this change closes, a server-side child that needs a credential but inherits only the server's own env, is held by `tests/unit/claude-spawn-auth-class.test.ts`.
@@ -0,0 +1,11 @@
1
+ # Pairing check for the two rule books, in plain words
2
+
3
+ Instar 1.x and 2.0 each have a written copy of the rules, and changes to one often never reached the other. This adds the first working part of the requirement Justin asked for.
4
+
5
+ Any pull request that changes the 1.x rule book now has to carry one line: which matching change it pairs with in 2.0, or why it has none. My merge tool checks that the line is there and that the named change really exists and really touches the other book. If not, it refuses and says exactly what to add. Adding the line doesn't cancel an approval.
6
+
7
+ It only checks that a pair exists. Whether the two say the same thing, or whether "no pair needed" is honest, stays with the independent review.
8
+
9
+ Nothing here changes the rule books themselves. Those wordings still need Justin's own approval, and come separately. This also adds a map of how the two books differ today, and corrects one document that wrongly said no rule change could land at all.
10
+
11
+ Other agents are unaffected: the check does nothing outside these two repositories. To undo it, revert this change. No data needs fixing.
@@ -0,0 +1,69 @@
1
+ # Side-Effects Review — constitution pairing check and merge-tool wiring
2
+
3
+ **Version / slug:** `constitution-alignment`
4
+ **Date:** `2026-11-03`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `independent subagent, appended below`
7
+
8
+ ## Summary of the change
9
+
10
+ Step 1 of `docs/specs/constitution-alignment.md`. Adds `scripts/check-constitution-pairing.mjs`: every PR touching a constitution book must name its counterpart in the other repository, or say why it has none. `scripts/safe-merge.mjs` refuses a registry PR that doesn't. `GreenPrAutoMerger` treats that refusal as waiting on a body edit. Also adds the map of existing differences and corrects `docs/STANDARDS-DIRECTION-GUARD.md`. No constitution text changes here. Tier 2; 5 spec review rounds of a cap of 6; about 6 files and 450 lines, most of it tests.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - safe-merge refusal on a missing or unreal declaration: **add**, invariant. Existence only.
15
+ - `none:` honesty and same-obligation: judgment-candidate, held by the independent review of each change. No code here decides it.
16
+
17
+ ## 1. Over-block
18
+
19
+ A PR touching the registry with no line is refused until one line is added. That includes a typo fix; the requirement says all updates. Clearing it takes one body edit and dismisses no approval. A failed read of a named counterpart refuses a registry PR with state `unknown`. A failed read of the PR's own file list refuses *any* PR on this repository with state `unread`, because whether it touches a book isn't known; its message says to retry and the watcher re-reads in 15 minutes. safe-merge already stops on any failed `gh` read a moment earlier or later, so this adds no new class of outage, only one more read that can hit it.
20
+
21
+ ## 2. Under-block
22
+
23
+ - A dishonest `none:`, or a pair that changes something else in the other book. Not visible to a script. The independent review and the operator's review hold it.
24
+ - A merge not going through safe-merge, and every merge in instar-2. Caught by the daily run, within a day.
25
+ - A PR body edited after merge can mislead the daily read. Accepted.
26
+
27
+ ## 3. Level-of-abstraction fit
28
+
29
+ The merge funnel is the right layer in instar: the base-branch refusal lives at the same point. A GitHub required status check would be stronger but needs the operator's admin action on two repositories, and the daily run backs it up.
30
+
31
+ ## 4. Signal vs authority
32
+
33
+ Compliant, per `docs/signal-vs-authority.md`: the blocking authority covers a closed existence question, in the shape of the Maturation Path plan gate, over inputs no model is needed to read. All judgment of meaning stays with a mind. The refusal is cheap to clear and says exactly how.
34
+
35
+ ## 5. Interactions
36
+
37
+ - Sits immediately after `nonMainBaseRefusal`, before every floor. Base refusal still wins for a stacked PR.
38
+ - `GreenPrAutoMerger`: new branch, no ladder attempt, re-read every 15 minutes, since the fix moves no head. Without it, the default ladder would give up. A body edit therefore takes up to 15 minutes to be seen. An approved registry PR with no line waits on audit only, with no attention item: the author is me, and the reader of that item would be the operator, who can't fix it.
39
+ - Adds two `gh` reads per safe-merge run on `JKHeadley/instar`. A registry PR adds a read of the counterpart. Negligible.
40
+ - `scripts/safe-merge.mjs` now imports a sibling file, the same way it imports its existing siblings.
41
+
42
+ ## 6. External surfaces
43
+
44
+ Instar's own PR process only. `scripts/` ships to the fleet, where this is inert: any repository but the two named no-ops. No user-facing change, no message, no route.
45
+
46
+ ## 7. Multi-machine posture
47
+
48
+ Unified. No local state: GitHub is the only record. The same script behaves identically on every machine.
49
+
50
+ ## 8. Rollback
51
+
52
+ Revert. Removes the refusal and the watcher branch. No data migration. The daily job, added at landing on Echo, is disabled in one edit.
53
+
54
+ ## Evidence
55
+
56
+ - Unit: `tests/unit/check-constitution-pairing.test.ts`. Integration: `tests/integration/safe-merge-constitution-counterpart.test.ts` runs the real script with a fake `gh`, including the refusal path, the unreadable-counterpart path, and a PR touching no book.
57
+ - Live positive control, against real history since #2323: `paired=0 declared-none=0 waiting=0 overdue=0 drift=5 no-pr=0`, naming #2682, #2380, #2194, #2323 and instar-2 #182. All five lack a line, so this proves the no-line class only; fixtures cover the rest. A real TLS failure on an earlier run printed `unknown` and did not read as clean.
58
+
59
+ ## Ladder line
60
+
61
+ This spec has no flag, so its plan says `ladder: not applicable: no flag.` The ladder's coverage test now accepts that form, with a reason, and still refuses a name that matches no entry.
62
+
63
+ ## Second-pass review
64
+
65
+ **Reviewer:** independent general-purpose subagent, on claude-opus-5-5
66
+
67
+ Independent subagent, 2026-11-03. Concern raised: a failed first read refused every PR on the repository, labelled as a constitution change. Verified live with a 404. Resolved: a separate `unread` state with its own message, this artifact and the spec corrected, tests added. It also found that a line naming a nonexistent PR made the whole daily run `unknown`; now one row of drift, tested. Everything else it checked held: standalone run from a temp directory, real page shapes, state mapping, `nextEligibleAt`. Recorded after fixing; the concern is resolved by these changes rather than concurred with as first written.
68
+
69
+ **Second-pass re-check of the fix:** Concur with the review.
@@ -0,0 +1,3 @@
1
+ # Recording what switched-off features do, in plain words
2
+
3
+ To judge a switched-off feature, you need a record of what it actually did. Most of them kept none, so the maturation ladder could only say "no data". This adds one line at the point where each of 113 features makes its decision: it fired, it held back, or it failed, with the reason and a few small facts. It changes nothing about what the feature does, and a failure to record can never break the feature. It never records message text, prompts or credentials. It's off on the fleet for now, like the ladder itself. Two features can't record this way, because they don't run inside the server, and they stay marked as needing it.
@@ -0,0 +1,66 @@
1
+ # Side-Effects Review — Evidence recording in switched-off features
2
+
3
+ **Version / slug:** `feature-evidence-recording`
4
+ **Date:** `2026-11-03`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `independent subagent, appended below`
7
+
8
+ ## Summary of the change
9
+
10
+ Adds `featureEvidence.record` (and `recordAtMostEvery` for per-message paths) at the decision points of 113 features across 85 files, and marks them measured in the registry. Spec: `docs/specs/feature-maturation-ladder.md` §4 and §13. Tier 2 by spread; each call is additive and cannot change behaviour.
11
+
12
+ ## Decision-point inventory
13
+
14
+ No decision point is added or changed. Each call observes a decision that already happened.
15
+
16
+ ---
17
+
18
+ ## 1. Over-block
19
+
20
+ No block/allow surface — over-block not applicable.
21
+
22
+ ## 2. Under-block
23
+
24
+ No block/allow surface. Recording misses what a feature cannot see about itself: a wrong decision reads like a right one until graded. Agents flagged double replies, wrongly refused holders and spurious reaps as undetectable from inside; the review's grading covers those.
25
+
26
+ ## 3. Level-of-abstraction fit
27
+
28
+ One thin call at each feature's decision point, through one log. Hook scripts and CI scripts cannot call it and are listed as not covered.
29
+
30
+ ## 4. Signal vs authority compliance
31
+
32
+ Signals only; no call's result is read. Reference: `docs/signal-vs-authority.md`.
33
+
34
+ ## 5. Interactions
35
+
36
+ The call appends synchronously, so it stays off per-tick paths; per-message paths use `recordAtMostEvery`. `catch` blocks that gained a recording call stay non-throwing. The log is wired only when the ladder is on, so on the fleet every call is a no-op, and rows from before the log is wired at boot are lost. A source-order test on `/messages/relay-agent` used a 30 KB window that the added lines outgrew; widened to 40 KB.
37
+
38
+ ## 6. External surfaces
39
+
40
+ None. Rows stay on the machine; only numbers leave. `context` holds reason codes, counts and non-secret ids, and text passes `scrubForStore`.
41
+
42
+ ## 7. Multi-machine posture
43
+
44
+ Per-machine facts read through each machine's route and the board, as the spec states.
45
+
46
+ ## 8. Rollback cost
47
+
48
+ Revert, or set `maturation.ladder.enabled` false, which makes every call a no-op.
49
+
50
+ ## Evidence
51
+
52
+ `tsc` clean; unit tests of each changed module; `tests/unit/FeatureEvidenceLog.test.ts`; the full run is the merge gate.
53
+
54
+ ## Second-pass review
55
+
56
+ **Reviewer:** independent general-purpose subagent, on claude-opus-5-5
57
+
58
+ Independent subagent, first read: "Concern raised". `allPeersPresumedGone()` in a record's arguments could throw on a corrupt registry just before the lease self-suspend, so the self-fence would be skipped; three per-message or per-request paths recorded without the limiter; one `.message.slice` could throw on a non-Error. All fixed: those facts came out of the lease context, the three paths use `recordAtMostEvery`, and the error read is guarded. A wider grep of added arguments found no other call that can throw on a load-bearing path. It found no message text or credentials in the sampled context, and every feature id in the registry. It sampled by risk, not all 85 files. Concur after fixes.
59
+
60
+ ## Class-Closure Declaration
61
+
62
+ `unbounded-self-action`: closure `n/a`. These calls observe decisions other code already made; none triggers an action or a retry. Row volume is bounded by rotation and, on per-message paths, by `recordAtMostEvery`.
63
+
64
+ ## Stage-B certified set
65
+
66
+ `src/monitoring/DegradationReporter.ts` sits in the certified Codex delivery closure and gained a recording call, so the evidence log and its rotation helper entered the closure. Both are listed as excluded, with reasons: write-only, never throwing, and off the delivery path. The certified fingerprint is unchanged.