instar 1.3.1649 → 1.3.1650

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 (451) 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/reflect.d.ts.map +1 -1
  24. package/dist/commands/reflect.js +2 -0
  25. package/dist/commands/reflect.js.map +1 -1
  26. package/dist/commands/route.d.ts.map +1 -1
  27. package/dist/commands/route.js +2 -0
  28. package/dist/commands/route.js.map +1 -1
  29. package/dist/commands/server.d.ts.map +1 -1
  30. package/dist/commands/server.js +315 -14
  31. package/dist/commands/server.js.map +1 -1
  32. package/dist/commands/setClaudeKey.d.ts +8 -0
  33. package/dist/commands/setClaudeKey.d.ts.map +1 -0
  34. package/dist/commands/setClaudeKey.js +35 -0
  35. package/dist/commands/setClaudeKey.js.map +1 -0
  36. package/dist/core/AccountFollowMeOrchestrator.d.ts.map +1 -1
  37. package/dist/core/AccountFollowMeOrchestrator.js +4 -0
  38. package/dist/core/AccountFollowMeOrchestrator.js.map +1 -1
  39. package/dist/core/AppMediaStore.d.ts.map +1 -1
  40. package/dist/core/AppMediaStore.js +3 -0
  41. package/dist/core/AppMediaStore.js.map +1 -1
  42. package/dist/core/BackupManager.d.ts.map +1 -1
  43. package/dist/core/BackupManager.js +2 -0
  44. package/dist/core/BackupManager.js.map +1 -1
  45. package/dist/core/ClaudeCliIntelligenceProvider.d.ts.map +1 -1
  46. package/dist/core/ClaudeCliIntelligenceProvider.js +11 -3
  47. package/dist/core/ClaudeCliIntelligenceProvider.js.map +1 -1
  48. package/dist/core/ClaudeKeyHealth.d.ts +141 -0
  49. package/dist/core/ClaudeKeyHealth.d.ts.map +1 -0
  50. package/dist/core/ClaudeKeyHealth.js +467 -0
  51. package/dist/core/ClaudeKeyHealth.js.map +1 -0
  52. package/dist/core/CodexTaskContinuationStore.d.ts.map +1 -1
  53. package/dist/core/CodexTaskContinuationStore.js +7 -0
  54. package/dist/core/CodexTaskContinuationStore.js.map +1 -1
  55. package/dist/core/CoherenceJournal.d.ts +1 -1
  56. package/dist/core/CoherenceJournal.d.ts.map +1 -1
  57. package/dist/core/CoherenceJournal.js +11 -2
  58. package/dist/core/CoherenceJournal.js.map +1 -1
  59. package/dist/core/Config.d.ts +8 -0
  60. package/dist/core/Config.d.ts.map +1 -1
  61. package/dist/core/Config.js +26 -0
  62. package/dist/core/Config.js.map +1 -1
  63. package/dist/core/CredentialSwapExecutor.d.ts.map +1 -1
  64. package/dist/core/CredentialSwapExecutor.js +10 -0
  65. package/dist/core/CredentialSwapExecutor.js.map +1 -1
  66. package/dist/core/DecisionQualityRecorderImpl.d.ts.map +1 -1
  67. package/dist/core/DecisionQualityRecorderImpl.js +6 -0
  68. package/dist/core/DecisionQualityRecorderImpl.js.map +1 -1
  69. package/dist/core/DiscoveryEvaluator.d.ts.map +1 -1
  70. package/dist/core/DiscoveryEvaluator.js +4 -0
  71. package/dist/core/DiscoveryEvaluator.js.map +1 -1
  72. package/dist/core/IdentityReannounceClaimant.d.ts.map +1 -1
  73. package/dist/core/IdentityReannounceClaimant.js +4 -0
  74. package/dist/core/IdentityReannounceClaimant.js.map +1 -1
  75. package/dist/core/IntelligenceRouter.d.ts.map +1 -1
  76. package/dist/core/IntelligenceRouter.js +9 -0
  77. package/dist/core/IntelligenceRouter.js.map +1 -1
  78. package/dist/core/JournalSyncApplier.d.ts +1 -0
  79. package/dist/core/JournalSyncApplier.d.ts.map +1 -1
  80. package/dist/core/JournalSyncApplier.js +48 -0
  81. package/dist/core/JournalSyncApplier.js.map +1 -1
  82. package/dist/core/LeaseCoordinator.d.ts +4 -0
  83. package/dist/core/LeaseCoordinator.d.ts.map +1 -1
  84. package/dist/core/LeaseCoordinator.js +64 -1
  85. package/dist/core/LeaseCoordinator.js.map +1 -1
  86. package/dist/core/MessagingToneGate.d.ts +11 -7
  87. package/dist/core/MessagingToneGate.d.ts.map +1 -1
  88. package/dist/core/MessagingToneGate.js +15 -1
  89. package/dist/core/MessagingToneGate.js.map +1 -1
  90. package/dist/core/MobileDeviceKeys.d.ts +10 -0
  91. package/dist/core/MobileDeviceKeys.d.ts.map +1 -1
  92. package/dist/core/MobileDeviceKeys.js +17 -0
  93. package/dist/core/MobileDeviceKeys.js.map +1 -1
  94. package/dist/core/MultiMachineCoordinator.d.ts +12 -0
  95. package/dist/core/MultiMachineCoordinator.d.ts.map +1 -1
  96. package/dist/core/MultiMachineCoordinator.js +115 -3
  97. package/dist/core/MultiMachineCoordinator.js.map +1 -1
  98. package/dist/core/MutualSshRuntime.d.ts +1 -0
  99. package/dist/core/MutualSshRuntime.d.ts.map +1 -1
  100. package/dist/core/MutualSshRuntime.js +17 -1
  101. package/dist/core/MutualSshRuntime.js.map +1 -1
  102. package/dist/core/ObservedEndpointTracker.d.ts +1 -0
  103. package/dist/core/ObservedEndpointTracker.d.ts.map +1 -1
  104. package/dist/core/ObservedEndpointTracker.js +17 -0
  105. package/dist/core/ObservedEndpointTracker.js.map +1 -1
  106. package/dist/core/OverloadShedPlanner.d.ts.map +1 -1
  107. package/dist/core/OverloadShedPlanner.js +9 -0
  108. package/dist/core/OverloadShedPlanner.js.map +1 -1
  109. package/dist/core/OwnershipApplier.d.ts.map +1 -1
  110. package/dist/core/OwnershipApplier.js +7 -0
  111. package/dist/core/OwnershipApplier.js.map +1 -1
  112. package/dist/core/OwnershipReconciler.d.ts.map +1 -1
  113. package/dist/core/OwnershipReconciler.js +5 -0
  114. package/dist/core/OwnershipReconciler.js.map +1 -1
  115. package/dist/core/PostUpdateMigrator.d.ts +8 -0
  116. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  117. package/dist/core/PostUpdateMigrator.js +76 -2
  118. package/dist/core/PostUpdateMigrator.js.map +1 -1
  119. package/dist/core/PrHandLease.d.ts.map +1 -1
  120. package/dist/core/PrHandLease.js +2 -0
  121. package/dist/core/PrHandLease.js.map +1 -1
  122. package/dist/core/ProactiveSwapMonitor.d.ts.map +1 -1
  123. package/dist/core/ProactiveSwapMonitor.js +7 -0
  124. package/dist/core/ProactiveSwapMonitor.js.map +1 -1
  125. package/dist/core/ProjectRoundExecution.d.ts.map +1 -1
  126. package/dist/core/ProjectRoundExecution.js +3 -2
  127. package/dist/core/ProjectRoundExecution.js.map +1 -1
  128. package/dist/core/QueueDrainLoop.d.ts +7 -0
  129. package/dist/core/QueueDrainLoop.d.ts.map +1 -1
  130. package/dist/core/QueueDrainLoop.js +37 -1
  131. package/dist/core/QueueDrainLoop.js.map +1 -1
  132. package/dist/core/RemoteAckStore.d.ts.map +1 -1
  133. package/dist/core/RemoteAckStore.js +4 -0
  134. package/dist/core/RemoteAckStore.js.map +1 -1
  135. package/dist/core/ReplicatedStoreReconcilerWiring.d.ts.map +1 -1
  136. package/dist/core/ReplicatedStoreReconcilerWiring.js +1 -0
  137. package/dist/core/ReplicatedStoreReconcilerWiring.js.map +1 -1
  138. package/dist/core/SecretSync.d.ts +1 -0
  139. package/dist/core/SecretSync.d.ts.map +1 -1
  140. package/dist/core/SecretSync.js +16 -0
  141. package/dist/core/SecretSync.js.map +1 -1
  142. package/dist/core/SessionManager.d.ts +11 -0
  143. package/dist/core/SessionManager.d.ts.map +1 -1
  144. package/dist/core/SessionManager.js +125 -14
  145. package/dist/core/SessionManager.js.map +1 -1
  146. package/dist/core/SessionPoolFailoverRunner.d.ts.map +1 -1
  147. package/dist/core/SessionPoolFailoverRunner.js +4 -0
  148. package/dist/core/SessionPoolFailoverRunner.js.map +1 -1
  149. package/dist/core/SleepWakeDetector.d.ts.map +1 -1
  150. package/dist/core/SleepWakeDetector.js +10 -0
  151. package/dist/core/SleepWakeDetector.js.map +1 -1
  152. package/dist/core/SubscriptionReloginStore.d.ts.map +1 -1
  153. package/dist/core/SubscriptionReloginStore.js +10 -1
  154. package/dist/core/SubscriptionReloginStore.js.map +1 -1
  155. package/dist/core/TopicPinMutation.d.ts.map +1 -1
  156. package/dist/core/TopicPinMutation.js +5 -0
  157. package/dist/core/TopicPinMutation.js.map +1 -1
  158. package/dist/core/UnjustifiedStopGate.d.ts.map +1 -1
  159. package/dist/core/UnjustifiedStopGate.js +22 -0
  160. package/dist/core/UnjustifiedStopGate.js.map +1 -1
  161. package/dist/core/WindowRunCadenceExecutor.d.ts.map +1 -1
  162. package/dist/core/WindowRunCadenceExecutor.js +20 -0
  163. package/dist/core/WindowRunCadenceExecutor.js.map +1 -1
  164. package/dist/core/claudeChildAuth.d.ts +68 -0
  165. package/dist/core/claudeChildAuth.d.ts.map +1 -0
  166. package/dist/core/claudeChildAuth.js +173 -0
  167. package/dist/core/claudeChildAuth.js.map +1 -0
  168. package/dist/core/claudeKeyProbe.d.ts +23 -0
  169. package/dist/core/claudeKeyProbe.d.ts.map +1 -0
  170. package/dist/core/claudeKeyProbe.js +68 -0
  171. package/dist/core/claudeKeyProbe.js.map +1 -0
  172. package/dist/core/codexDeviceLimitWiring.d.ts.map +1 -1
  173. package/dist/core/codexDeviceLimitWiring.js +12 -0
  174. package/dist/core/codexDeviceLimitWiring.js.map +1 -1
  175. package/dist/core/deliverToConversation.d.ts.map +1 -1
  176. package/dist/core/deliverToConversation.js +11 -0
  177. package/dist/core/deliverToConversation.js.map +1 -1
  178. package/dist/core/meteredCallEntry.d.ts.map +1 -1
  179. package/dist/core/meteredCallEntry.js +21 -0
  180. package/dist/core/meteredCallEntry.js.map +1 -1
  181. package/dist/core/nobodyPollingActuator.d.ts.map +1 -1
  182. package/dist/core/nobodyPollingActuator.js +5 -0
  183. package/dist/core/nobodyPollingActuator.js.map +1 -1
  184. package/dist/core/operatorSurfaceReferral.d.ts +18 -0
  185. package/dist/core/operatorSurfaceReferral.d.ts.map +1 -0
  186. package/dist/core/operatorSurfaceReferral.js +32 -0
  187. package/dist/core/operatorSurfaceReferral.js.map +1 -0
  188. package/dist/core/ownershipFollowsLiveWork.d.ts.map +1 -1
  189. package/dist/core/ownershipFollowsLiveWork.js +10 -1
  190. package/dist/core/ownershipFollowsLiveWork.js.map +1 -1
  191. package/dist/core/types.d.ts +15 -0
  192. package/dist/core/types.d.ts.map +1 -1
  193. package/dist/core/types.js.map +1 -1
  194. package/dist/core/worktreeDirtyCheck.d.ts.map +1 -1
  195. package/dist/core/worktreeDirtyCheck.js +2 -0
  196. package/dist/core/worktreeDirtyCheck.js.map +1 -1
  197. package/dist/data/stageBCertifiedSet.d.ts +9 -0
  198. package/dist/data/stageBCertifiedSet.d.ts.map +1 -1
  199. package/dist/data/stageBCertifiedSet.js +12 -0
  200. package/dist/data/stageBCertifiedSet.js.map +1 -1
  201. package/dist/data/standards-guard-index.json +1 -1
  202. package/dist/data/standards-guard-index.meta.json +2 -2
  203. package/dist/data/standards-registry.meta.json +1 -1
  204. package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
  205. package/dist/lifeline/TelegramLifeline.js +17 -3
  206. package/dist/lifeline/TelegramLifeline.js.map +1 -1
  207. package/dist/messaging/attentionHubPolicy.d.ts.map +1 -1
  208. package/dist/messaging/attentionHubPolicy.js +1 -0
  209. package/dist/messaging/attentionHubPolicy.js.map +1 -1
  210. package/dist/monitoring/AgentWorktreeReaper.d.ts.map +1 -1
  211. package/dist/monitoring/AgentWorktreeReaper.js +15 -0
  212. package/dist/monitoring/AgentWorktreeReaper.js.map +1 -1
  213. package/dist/monitoring/ApprenticeshipCycleSlaMonitor.d.ts.map +1 -1
  214. package/dist/monitoring/ApprenticeshipCycleSlaMonitor.js +18 -9
  215. package/dist/monitoring/ApprenticeshipCycleSlaMonitor.js.map +1 -1
  216. package/dist/monitoring/CodexArmSessionSweeper.d.ts.map +1 -1
  217. package/dist/monitoring/CodexArmSessionSweeper.js +11 -0
  218. package/dist/monitoring/CodexArmSessionSweeper.js.map +1 -1
  219. package/dist/monitoring/CrashLoopPauser.d.ts.map +1 -1
  220. package/dist/monitoring/CrashLoopPauser.js +8 -0
  221. package/dist/monitoring/CrashLoopPauser.js.map +1 -1
  222. package/dist/monitoring/DegradationReporter.d.ts.map +1 -1
  223. package/dist/monitoring/DegradationReporter.js +7 -1
  224. package/dist/monitoring/DegradationReporter.js.map +1 -1
  225. package/dist/monitoring/DegradedTmuxGuard.d.ts +2 -0
  226. package/dist/monitoring/DegradedTmuxGuard.d.ts.map +1 -1
  227. package/dist/monitoring/DegradedTmuxGuard.js +14 -0
  228. package/dist/monitoring/DegradedTmuxGuard.js.map +1 -1
  229. package/dist/monitoring/DurableOutputScrubber.d.ts.map +1 -1
  230. package/dist/monitoring/DurableOutputScrubber.js +7 -0
  231. package/dist/monitoring/DurableOutputScrubber.js.map +1 -1
  232. package/dist/monitoring/DurableVaultSession.d.ts.map +1 -1
  233. package/dist/monitoring/DurableVaultSession.js +15 -0
  234. package/dist/monitoring/DurableVaultSession.js.map +1 -1
  235. package/dist/monitoring/ExternalHogSentinel.d.ts +2 -0
  236. package/dist/monitoring/ExternalHogSentinel.d.ts.map +1 -1
  237. package/dist/monitoring/ExternalHogSentinel.js +27 -1
  238. package/dist/monitoring/ExternalHogSentinel.js.map +1 -1
  239. package/dist/monitoring/FailureLedger.d.ts.map +1 -1
  240. package/dist/monitoring/FailureLedger.js +38 -1
  241. package/dist/monitoring/FailureLedger.js.map +1 -1
  242. package/dist/monitoring/FeatureEvidenceLog.d.ts +5 -0
  243. package/dist/monitoring/FeatureEvidenceLog.d.ts.map +1 -1
  244. package/dist/monitoring/FeatureEvidenceLog.js +25 -0
  245. package/dist/monitoring/FeatureEvidenceLog.js.map +1 -1
  246. package/dist/monitoring/GeminiCapacityEscalationMonitor.d.ts.map +1 -1
  247. package/dist/monitoring/GeminiCapacityEscalationMonitor.js +20 -2
  248. package/dist/monitoring/GeminiCapacityEscalationMonitor.js.map +1 -1
  249. package/dist/monitoring/GeminiLoopRunner.d.ts.map +1 -1
  250. package/dist/monitoring/GeminiLoopRunner.js +11 -1
  251. package/dist/monitoring/GeminiLoopRunner.js.map +1 -1
  252. package/dist/monitoring/GreenPrAutoMerger.d.ts.map +1 -1
  253. package/dist/monitoring/GreenPrAutoMerger.js +11 -0
  254. package/dist/monitoring/GreenPrAutoMerger.js.map +1 -1
  255. package/dist/monitoring/GrowthDigestPublisher.d.ts.map +1 -1
  256. package/dist/monitoring/GrowthDigestPublisher.js +16 -0
  257. package/dist/monitoring/GrowthDigestPublisher.js.map +1 -1
  258. package/dist/monitoring/GrowthMilestoneAnalyst.d.ts +3 -0
  259. package/dist/monitoring/GrowthMilestoneAnalyst.d.ts.map +1 -1
  260. package/dist/monitoring/GrowthMilestoneAnalyst.js +45 -1
  261. package/dist/monitoring/GrowthMilestoneAnalyst.js.map +1 -1
  262. package/dist/monitoring/McpProcessReaper.d.ts +2 -0
  263. package/dist/monitoring/McpProcessReaper.d.ts.map +1 -1
  264. package/dist/monitoring/McpProcessReaper.js +32 -0
  265. package/dist/monitoring/McpProcessReaper.js.map +1 -1
  266. package/dist/monitoring/MissingLoginSessionDetector.d.ts +2 -1
  267. package/dist/monitoring/MissingLoginSessionDetector.d.ts.map +1 -1
  268. package/dist/monitoring/MissingLoginSessionDetector.js +23 -0
  269. package/dist/monitoring/MissingLoginSessionDetector.js.map +1 -1
  270. package/dist/monitoring/OrchestratorPoller.d.ts +1 -0
  271. package/dist/monitoring/OrchestratorPoller.d.ts.map +1 -1
  272. package/dist/monitoring/OrchestratorPoller.js +13 -0
  273. package/dist/monitoring/OrchestratorPoller.js.map +1 -1
  274. package/dist/monitoring/OrphanedWorkSentinel.d.ts.map +1 -1
  275. package/dist/monitoring/OrphanedWorkSentinel.js +7 -0
  276. package/dist/monitoring/OrphanedWorkSentinel.js.map +1 -1
  277. package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
  278. package/dist/monitoring/PresenceProxy.js +9 -1
  279. package/dist/monitoring/PresenceProxy.js.map +1 -1
  280. package/dist/monitoring/ProcessFootprintMonitor.d.ts.map +1 -1
  281. package/dist/monitoring/ProcessFootprintMonitor.js +20 -2
  282. package/dist/monitoring/ProcessFootprintMonitor.js.map +1 -1
  283. package/dist/monitoring/PromiseBeacon.d.ts.map +1 -1
  284. package/dist/monitoring/PromiseBeacon.js +20 -0
  285. package/dist/monitoring/PromiseBeacon.js.map +1 -1
  286. package/dist/monitoring/ReleaseReadinessSentinel.d.ts +2 -0
  287. package/dist/monitoring/ReleaseReadinessSentinel.d.ts.map +1 -1
  288. package/dist/monitoring/ReleaseReadinessSentinel.js +26 -0
  289. package/dist/monitoring/ReleaseReadinessSentinel.js.map +1 -1
  290. package/dist/monitoring/RopeHealthMonitor.d.ts.map +1 -1
  291. package/dist/monitoring/RopeHealthMonitor.js +35 -1
  292. package/dist/monitoring/RopeHealthMonitor.js.map +1 -1
  293. package/dist/monitoring/SentinelNotifier.d.ts.map +1 -1
  294. package/dist/monitoring/SentinelNotifier.js +16 -0
  295. package/dist/monitoring/SentinelNotifier.js.map +1 -1
  296. package/dist/monitoring/SessionReaper.d.ts.map +1 -1
  297. package/dist/monitoring/SessionReaper.js +11 -2
  298. package/dist/monitoring/SessionReaper.js.map +1 -1
  299. package/dist/monitoring/SingleMachineFailoverGapDetector.d.ts +2 -0
  300. package/dist/monitoring/SingleMachineFailoverGapDetector.d.ts.map +1 -1
  301. package/dist/monitoring/SingleMachineFailoverGapDetector.js +20 -0
  302. package/dist/monitoring/SingleMachineFailoverGapDetector.js.map +1 -1
  303. package/dist/monitoring/SpeakerElection.d.ts.map +1 -1
  304. package/dist/monitoring/SpeakerElection.js +8 -0
  305. package/dist/monitoring/SpeakerElection.js.map +1 -1
  306. package/dist/monitoring/StrandedTopicSentinel.d.ts +3 -0
  307. package/dist/monitoring/StrandedTopicSentinel.d.ts.map +1 -1
  308. package/dist/monitoring/StrandedTopicSentinel.js +33 -0
  309. package/dist/monitoring/StrandedTopicSentinel.js.map +1 -1
  310. package/dist/native/InstarWedgeCanary.app/Contents/MacOS/InstarWedgeCanary +0 -0
  311. package/dist/native/instar-desktop-host +0 -0
  312. package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.d.ts.map +1 -1
  313. package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.js +5 -2
  314. package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.js.map +1 -1
  315. package/dist/recommended/RecommendedServicesLedger.d.ts +91 -0
  316. package/dist/recommended/RecommendedServicesLedger.d.ts.map +1 -0
  317. package/dist/recommended/RecommendedServicesLedger.js +193 -0
  318. package/dist/recommended/RecommendedServicesLedger.js.map +1 -0
  319. package/dist/recommended/RecommendedServicesReplicatedStore.d.ts +14 -0
  320. package/dist/recommended/RecommendedServicesReplicatedStore.d.ts.map +1 -0
  321. package/dist/recommended/RecommendedServicesReplicatedStore.js +34 -0
  322. package/dist/recommended/RecommendedServicesReplicatedStore.js.map +1 -0
  323. package/dist/recommended/legacyDeclines.d.ts +11 -0
  324. package/dist/recommended/legacyDeclines.d.ts.map +1 -0
  325. package/dist/recommended/legacyDeclines.js +17 -0
  326. package/dist/recommended/legacyDeclines.js.map +1 -0
  327. package/dist/recommended/serviceIds.d.ts +3 -0
  328. package/dist/recommended/serviceIds.d.ts.map +1 -0
  329. package/dist/recommended/serviceIds.js +6 -0
  330. package/dist/recommended/serviceIds.js.map +1 -0
  331. package/dist/scaffold/templates.d.ts +2 -0
  332. package/dist/scaffold/templates.d.ts.map +1 -1
  333. package/dist/scaffold/templates.js +8 -0
  334. package/dist/scaffold/templates.js.map +1 -1
  335. package/dist/scheduler/JobResultTriage.d.ts.map +1 -1
  336. package/dist/scheduler/JobResultTriage.js +10 -0
  337. package/dist/scheduler/JobResultTriage.js.map +1 -1
  338. package/dist/scheduler/JobScheduler.d.ts.map +1 -1
  339. package/dist/scheduler/JobScheduler.js +12 -0
  340. package/dist/scheduler/JobScheduler.js.map +1 -1
  341. package/dist/scheduler/MentorOnboardingRunner.d.ts +3 -0
  342. package/dist/scheduler/MentorOnboardingRunner.d.ts.map +1 -1
  343. package/dist/scheduler/MentorOnboardingRunner.js +24 -2
  344. package/dist/scheduler/MentorOnboardingRunner.js.map +1 -1
  345. package/dist/server/AgentServer.d.ts +2 -0
  346. package/dist/server/AgentServer.d.ts.map +1 -1
  347. package/dist/server/AgentServer.js +76 -15
  348. package/dist/server/AgentServer.js.map +1 -1
  349. package/dist/server/BootHealthBeacon.d.ts +3 -0
  350. package/dist/server/BootHealthBeacon.d.ts.map +1 -1
  351. package/dist/server/BootHealthBeacon.js +9 -0
  352. package/dist/server/BootHealthBeacon.js.map +1 -1
  353. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  354. package/dist/server/CapabilityIndex.js +10 -1
  355. package/dist/server/CapabilityIndex.js.map +1 -1
  356. package/dist/server/LifelineIngressGuard.d.ts.map +1 -1
  357. package/dist/server/LifelineIngressGuard.js +11 -0
  358. package/dist/server/LifelineIngressGuard.js.map +1 -1
  359. package/dist/server/PoolPollCache.d.ts +4 -0
  360. package/dist/server/PoolPollCache.d.ts.map +1 -1
  361. package/dist/server/PoolPollCache.js +33 -0
  362. package/dist/server/PoolPollCache.js.map +1 -1
  363. package/dist/server/machineRoutes.d.ts.map +1 -1
  364. package/dist/server/machineRoutes.js +6 -0
  365. package/dist/server/machineRoutes.js.map +1 -1
  366. package/dist/server/middleware.d.ts.map +1 -1
  367. package/dist/server/middleware.js +6 -0
  368. package/dist/server/middleware.js.map +1 -1
  369. package/dist/server/mobileConsoleTicket.d.ts +113 -0
  370. package/dist/server/mobileConsoleTicket.d.ts.map +1 -0
  371. package/dist/server/mobileConsoleTicket.js +405 -0
  372. package/dist/server/mobileConsoleTicket.js.map +1 -0
  373. package/dist/server/mobileConversationRoutes.d.ts.map +1 -1
  374. package/dist/server/mobileConversationRoutes.js +20 -1
  375. package/dist/server/mobileConversationRoutes.js.map +1 -1
  376. package/dist/server/mobileMediaRoutes.d.ts.map +1 -1
  377. package/dist/server/mobileMediaRoutes.js +3 -0
  378. package/dist/server/mobileMediaRoutes.js.map +1 -1
  379. package/dist/server/mobilePairingRoutes.d.ts +8 -2
  380. package/dist/server/mobilePairingRoutes.d.ts.map +1 -1
  381. package/dist/server/mobilePairingRoutes.js +67 -6
  382. package/dist/server/mobilePairingRoutes.js.map +1 -1
  383. package/dist/server/mobileSessionTerminalRoutes.d.ts +128 -0
  384. package/dist/server/mobileSessionTerminalRoutes.d.ts.map +1 -0
  385. package/dist/server/mobileSessionTerminalRoutes.js +389 -0
  386. package/dist/server/mobileSessionTerminalRoutes.js.map +1 -0
  387. package/dist/server/recommendedServiceRoutes.d.ts +13 -0
  388. package/dist/server/recommendedServiceRoutes.d.ts.map +1 -0
  389. package/dist/server/recommendedServiceRoutes.js +49 -0
  390. package/dist/server/recommendedServiceRoutes.js.map +1 -0
  391. package/dist/server/routes.d.ts +2 -0
  392. package/dist/server/routes.d.ts.map +1 -1
  393. package/dist/server/routes.js +170 -4
  394. package/dist/server/routes.js.map +1 -1
  395. package/dist/testing/selfActionRegistry.d.ts.map +1 -1
  396. package/dist/testing/selfActionRegistry.js +36 -0
  397. package/dist/testing/selfActionRegistry.js.map +1 -1
  398. package/dist/threadline/A2ACheckInProxy.d.ts.map +1 -1
  399. package/dist/threadline/A2ACheckInProxy.js +26 -15
  400. package/dist/threadline/A2ACheckInProxy.js.map +1 -1
  401. package/dist/threadline/AgentTrustManager.d.ts.map +1 -1
  402. package/dist/threadline/AgentTrustManager.js +3 -0
  403. package/dist/threadline/AgentTrustManager.js.map +1 -1
  404. package/dist/threadline/InboundIdLedger.d.ts.map +1 -1
  405. package/dist/threadline/InboundIdLedger.js +18 -1
  406. package/dist/threadline/InboundIdLedger.js.map +1 -1
  407. package/dist/threadline/NegotiatorGate.d.ts.map +1 -1
  408. package/dist/threadline/NegotiatorGate.js +11 -0
  409. package/dist/threadline/NegotiatorGate.js.map +1 -1
  410. package/dist/threadline/PipeSessionSpawner.d.ts.map +1 -1
  411. package/dist/threadline/PipeSessionSpawner.js +8 -0
  412. package/dist/threadline/PipeSessionSpawner.js.map +1 -1
  413. package/dist/threadline/ThreadlineRouter.d.ts.map +1 -1
  414. package/dist/threadline/ThreadlineRouter.js +13 -0
  415. package/dist/threadline/ThreadlineRouter.js.map +1 -1
  416. package/dist/threadline/pairingReplicationWiring.d.ts.map +1 -1
  417. package/dist/threadline/pairingReplicationWiring.js +9 -0
  418. package/dist/threadline/pairingReplicationWiring.js.map +1 -1
  419. package/dist/threadline/relayForward.d.ts.map +1 -1
  420. package/dist/threadline/relayForward.js +13 -2
  421. package/dist/threadline/relayForward.js.map +1 -1
  422. package/dist/threadline/relayUnknownSenderTrust.d.ts +0 -9
  423. package/dist/threadline/relayUnknownSenderTrust.d.ts.map +1 -1
  424. package/dist/threadline/relayUnknownSenderTrust.js +16 -0
  425. package/dist/threadline/relayUnknownSenderTrust.js.map +1 -1
  426. package/package.json +1 -1
  427. package/scripts/check-constitution-pairing.mjs +273 -0
  428. package/scripts/safe-merge.mjs +9 -0
  429. package/src/data/builtin-manifest.json +103 -103
  430. package/src/data/feature-ladders.json +113 -113
  431. package/src/data/stageBCertifiedSet.ts +12 -0
  432. package/src/data/standards-guard-index.json +1 -1
  433. package/src/data/standards-guard-index.meta.json +2 -2
  434. package/src/data/standards-registry.meta.json +1 -1
  435. package/src/data/state-coherence-registry.json +18 -0
  436. package/src/scaffold/templates.ts +9 -0
  437. package/upgrades/1.3.1650.md +105 -0
  438. package/upgrades/mobile-console-device-signin.eli16.md +5 -0
  439. package/upgrades/side-effects/cloud-key-internal-calls.md +116 -0
  440. package/upgrades/side-effects/constitution-alignment.eli16.md +11 -0
  441. package/upgrades/side-effects/constitution-alignment.md +69 -0
  442. package/upgrades/side-effects/feature-evidence-recording.eli16.md +3 -0
  443. package/upgrades/side-effects/feature-evidence-recording.md +66 -0
  444. package/upgrades/side-effects/feedback-reroute-admission-parity.md +77 -0
  445. package/upgrades/side-effects/mobile-console-device-signin.md +102 -0
  446. package/upgrades/side-effects/mobile-native-session-screen.md +88 -0
  447. package/upgrades/side-effects/operator-needs-first-screen.md +87 -0
  448. package/upgrades/side-effects/recommended-services-choices.md +50 -0
  449. package/upgrades/side-effects/rerouted-lifetime-active-process.md +63 -0
  450. package/upgrades/side-effects/undated-resurfacer-e2e-wait.eli16.md +5 -0
  451. package/upgrades/side-effects/undated-resurfacer-e2e-wait.md +9 -0
@@ -1,4 +1,7 @@
1
1
  import { registerEcosystemIdeaRoutes } from './ecosystemIdeaRoutes.js';
2
+ import { registerRecommendedServiceRoutes } from './recommendedServiceRoutes.js';
3
+ import { isRetiredLegacyOffer } from '../recommended/legacyDeclines.js';
4
+ import { featureEvidence } from '../monitoring/FeatureEvidenceLog.js';
2
5
  import { ISSUES_TOPIC_OFFSET } from '../messaging/telegramTopicSpace.js';
3
6
  import { SlackOriginLedger, SlackOriginRecordingError } from '../messaging/slack/SlackOriginLedger.js';
4
7
  import { slackOriginFooter, currentAgentDisplay, deviceOriginRow, effectiveDisplay, originEvidenceFromProducer, validateDeviceOriginRow, validateMessageOriginEvidence } from '../messaging/messageOrigin.js';
@@ -39,6 +42,7 @@ import { telegramFetch } from '../messaging/telegram-egress.js';
39
42
  import { emergencyStopUserMessage } from '../messaging/shared/emergencyStopUserMessage.js';
40
43
  import { isVerifiedChannelName, verifiedEntityName } from '../messaging/shared/channelIdentity.js';
41
44
  import { execFileSync } from 'node:child_process';
45
+ import { activeClaudeKeyHealth } from '../core/ClaudeKeyHealth.js';
42
46
  import { createHash, createHmac, timingSafeEqual, randomBytes, randomUUID } from 'node:crypto';
43
47
  import { governor as selfActionGovernorSurface } from '../monitoring/selfaction/governor.js';
44
48
  import { classifyActionClaim, classifyApprovalRequest, excerptAround } from '../core/action-claim.js';
@@ -390,6 +394,7 @@ import { credentialGuardMessage, detectOutboundCredential } from '../messaging/o
390
394
  import { detectJargon } from '../core/JargonDetector.js';
391
395
  import { detectRawFilePath } from '../core/raw-file-path.js';
392
396
  import { detectParkedOnUser } from '../core/parked-on-user.js';
397
+ import { detectSurfaceReferral } from '../core/operatorSurfaceReferral.js';
393
398
  import { detectAskWhenAuthorized } from '../core/ask-when-authorized.js';
394
399
  import { detectInternalIdLeak } from '../core/internal-id-leak.js';
395
400
  import { OutboundAdvisoryAudit, composeAdvisories, composeTimeClaimAdvisories, PREFLIGHT_TEXT_CAP, } from '../messaging/OutboundAdvisory.js';
@@ -3081,6 +3086,11 @@ export function createRoutes(ctx) {
3081
3086
  // over. A guard that walls a credential in the message body while storing
3082
3087
  // one from the reason field would be theatre.
3083
3088
  const note = input.reason ? scrubForStore(input.reason).text.slice(0, 500) : undefined;
3089
+ featureEvidence.record('toneGate.advisoryMigration', {
3090
+ kind: 'fired',
3091
+ reason: `self-report-${reaction}`,
3092
+ context: { reaction, rule: rule.slice(0, 64), derivation: derivation ?? null, grade: reaction === 'override' ? 'wrong' : 'right', hasReason: !!note },
3093
+ });
3084
3094
  // ── Off the send path ────────────────────────────────────────────────
3085
3095
  // `upsertOutcome` is a synchronous better-sqlite3 transaction that
3086
3096
  // recomputes the whole (decision_point, day) rollup twice over a window-
@@ -3285,6 +3295,25 @@ export function createRoutes(ctx) {
3285
3295
  catch {
3286
3296
  // @silent-fallback-ok — detector errors never override the authority; skip the signal (outbound-jargon-filepath-gap §2.3).
3287
3297
  }
3298
+ // operator-needs-first-screen §6 — surface referral (B22). SIGNAL ONLY, and only for a
3299
+ // sender that can react to a nudge: a caller that treats any hold as final never sees it.
3300
+ // Fail-OPEN: a detector throw skips the signal, never withholds.
3301
+ if (options.liveArtefactSignals === true && kindForSignals === 'reply' && options.noReactionPossible !== true) {
3302
+ try {
3303
+ const sr = detectSurfaceReferral(text);
3304
+ if (sr.referral) {
3305
+ signals.surfaceReferral = {
3306
+ ...(sr.phrase ? { phrase: sr.phrase } : {}),
3307
+ hasLink: sr.hasLink,
3308
+ hasOnScreenWords: sr.hasOnScreenWords,
3309
+ renderConfirmed: options.toneAdvisoryComplied === 'B22_SURFACE_REFERRAL',
3310
+ };
3311
+ }
3312
+ }
3313
+ catch {
3314
+ // @silent-fallback-ok — detector errors never override the authority; skip the signal.
3315
+ }
3316
+ }
3288
3317
  // C1+C2 §4.3 — parked-on-user (B19) + internal-id-leak (B20) signals.
3289
3318
  // SIGNAL ONLY: the authority (B19/B20 rules) decides with carve-outs +
3290
3319
  // fail-toward-sending. Fail-OPEN: a detector throw skips the signal.
@@ -4265,7 +4294,8 @@ export function createRoutes(ctx) {
4265
4294
  let isDegraded = sessionExhausted
4266
4295
  || totalFailures >= 5
4267
4296
  || degradations.length > 0
4268
- || (llmReliability !== null && llmReliability.status !== 'ok');
4297
+ || (llmReliability !== null && llmReliability.status !== 'ok')
4298
+ || activeClaudeKeyHealth()?.status()?.status === 'dead';
4269
4299
  const base = {
4270
4300
  status: isDegraded ? 'degraded' : 'ok',
4271
4301
  uptime: uptimeMs,
@@ -4286,6 +4316,9 @@ export function createRoutes(ctx) {
4286
4316
  // (`bearerMatches`): byte-identical to the inline check it replaced.
4287
4317
  const isAuthed = bearerMatches(req, ctx.config.authToken);
4288
4318
  if (isAuthed) {
4319
+ const claudeKey = activeClaudeKeyHealth()?.status();
4320
+ if (claudeKey)
4321
+ base.claudeKey = claudeKey;
4289
4322
  // job-cost-reduction §5.3: the stable feature ids behind degradationSummary.
4290
4323
  // The narrative strings carry per-occurrence values, so they are evidence
4291
4324
  // only; health-check keys its `degradation:<feature>` reasons on these.
@@ -7658,6 +7691,19 @@ export function createRoutes(ctx) {
7658
7691
  : condition.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 80) || 'autonomous-goal';
7659
7692
  const userFacing = typeof body.userFacing === 'boolean' ? body.userFacing : undefined;
7660
7693
  const gate = ctx.liveTestGate.evaluate({ featureId, userFacing, goalText: condition, mode: ctx.liveTestGateMode });
7694
+ featureEvidence.record('monitoring.liveTestGate', {
7695
+ kind: gate.outcome !== 'allow' ? 'fired' : 'held',
7696
+ reason: gate.blocks ? `veto:${gate.outcome}` : gate.wouldBlock ? `would-veto:${gate.outcome}` : 'allowed',
7697
+ context: {
7698
+ outcome: gate.outcome,
7699
+ mode: gate.mode,
7700
+ wouldBlock: gate.wouldBlock,
7701
+ blocks: gate.blocks,
7702
+ // The fallback id is built from the goal text, so only a declared id is kept.
7703
+ declaredFeatureId: typeof body.featureId === 'string' && body.featureId ? body.featureId : null,
7704
+ userFacingDeclared: userFacing ?? null,
7705
+ },
7706
+ });
7661
7707
  if (gate.outcome !== 'allow') {
7662
7708
  if (gate.blocks) {
7663
7709
  res.json({ met: false, reason: `live-test gate: ${gate.reason}`, liveTestGate: { outcome: gate.outcome, mode: gate.mode, overrode: true } });
@@ -7670,7 +7716,8 @@ export function createRoutes(ctx) {
7670
7716
  return;
7671
7717
  }
7672
7718
  }
7673
- catch {
7719
+ catch (gateErr) {
7720
+ featureEvidence.record('monitoring.liveTestGate', { kind: 'error', reason: 'gate-evaluate-failed', context: { mode: ctx.liveTestGateMode, errorName: gateErr instanceof Error ? gateErr.name : 'unknown' } });
7674
7721
  // @silent-fallback-ok — a gate error must never trap a genuine completion
7675
7722
  // (the completion judge is the primary authority); fall through to the verdict.
7676
7723
  }
@@ -12309,6 +12356,7 @@ export function createRoutes(ctx) {
12309
12356
  browserNonce: req.body?.browserNonce, videoCodec: req.body?.videoCodec,
12310
12357
  client: req.body?.client === 'app' ? 'app' : 'browser', controlRecords: req.body?.controlRecords === true,
12311
12358
  });
12359
+ featureEvidence.record('remoteDesktop', { kind: 'fired', reason: 'session-started-via-mesh', context: { route: 'mesh', machineId: String(req.body?.machineId ?? '').slice(0, 64), client: req.body?.client === 'app' ? 'app' : 'browser', controlRecords: req.body?.controlRecords === true } });
12312
12360
  res.status(201).json(result);
12313
12361
  return;
12314
12362
  }
@@ -12321,9 +12369,11 @@ export function createRoutes(ctx) {
12321
12369
  scopeConfirmed: req.body?.scopeConfirmed,
12322
12370
  client: req.body?.client === 'app' ? 'app' : 'browser', controlRecords: req.body?.controlRecords === true,
12323
12371
  });
12372
+ featureEvidence.record('remoteDesktop', { kind: 'fired', reason: 'session-started-direct', context: { route: 'direct', machineId: String(req.body?.machineId ?? '').slice(0, 64), client: req.body?.client === 'app' ? 'app' : 'browser', controlRecords: req.body?.controlRecords === true, telegramStepUp } });
12324
12373
  res.status(201).json(result);
12325
12374
  }
12326
12375
  catch (error) {
12376
+ featureEvidence.record('remoteDesktop', { kind: 'error', reason: 'session-start-refused', context: { machineId: String(req.body?.machineId ?? '').slice(0, 64), telegramStepUp, errorName: error?.name ?? 'unknown' } });
12327
12377
  res.status(403).json({ error: error.message });
12328
12378
  }
12329
12379
  });
@@ -13867,6 +13917,7 @@ export function createRoutes(ctx) {
13867
13917
  if (typeof proposedUid === 'string' && proposedUid) {
13868
13918
  const principal = ar.resolvePrincipal(proposedUid);
13869
13919
  if (!principal || !principal.registered) {
13920
+ featureEvidence.record('monitoring.authorizationRequests', { kind: 'held', reason: 'create refused: unknown-user', context: { status: 400 } });
13870
13921
  res.status(400).json({ error: 'unknown-user — the grantee must be a registered Slack user' });
13871
13922
  return;
13872
13923
  }
@@ -13878,9 +13929,11 @@ export function createRoutes(ctx) {
13878
13929
  reason: typeof b.reason === 'string' ? b.reason : undefined,
13879
13930
  });
13880
13931
  if (!result.ok) {
13932
+ featureEvidence.record('monitoring.authorizationRequests', { kind: 'held', reason: `create refused: ${result.error}`, context: { status: result.status } });
13881
13933
  res.status(result.status).json({ error: result.error });
13882
13934
  return;
13883
13935
  }
13936
+ featureEvidence.record('monitoring.authorizationRequests', { kind: 'fired', reason: result.deduped ? 'create deduped' : 'created', context: { requestId: result.request.id, requestKind: result.request.kind, floorAction: result.request.proposal.floorAction, durationMs: result.request.proposal.durationMs, deduped: result.deduped ?? false } });
13884
13937
  res.status(201).json({ id: result.request.id, deduped: result.deduped ?? false, request: decorateAuthReq(result.request) });
13885
13938
  });
13886
13939
  // List requests (filter ?status=pending). Each row carries the server-rendered card. Bearer.
@@ -13913,8 +13966,10 @@ export function createRoutes(ctx) {
13913
13966
  res.status(503).json({ error: 'coordination mandate engine unavailable' });
13914
13967
  return;
13915
13968
  }
13916
- if (!checkMandatePin(req, res))
13969
+ if (!checkMandatePin(req, res)) {
13970
+ featureEvidence.record('monitoring.authorizationRequests', { kind: 'held', reason: 'approve refused: PIN gate', context: { requestId: req.params.id } });
13917
13971
  return;
13972
+ }
13918
13973
  const ar = ctx.authorizationRequests;
13919
13974
  const result = ar.store.approve(req.params.id, {
13920
13975
  execute: (proposal) => {
@@ -13953,9 +14008,11 @@ export function createRoutes(ctx) {
13953
14008
  },
13954
14009
  });
13955
14010
  if (!result.ok) {
14011
+ featureEvidence.record('monitoring.authorizationRequests', { kind: result.status === 409 ? 'error' : 'held', reason: `approve refused: ${result.error}`, context: { requestId: req.params.id, status: result.status } });
13956
14012
  res.status(result.status).json({ error: result.error });
13957
14013
  return;
13958
14014
  }
14015
+ featureEvidence.record('monitoring.authorizationRequests', { kind: 'fired', reason: result.alreadyApproved ? 'already approved' : 'approved', context: { requestId: result.request.id, floorAction: result.request.proposal.floorAction, durationMs: result.request.proposal.durationMs, alreadyApproved: result.alreadyApproved ?? false } });
13959
14016
  res.status(result.alreadyApproved ? 200 : 201).json({
13960
14017
  approved: true, alreadyApproved: result.alreadyApproved ?? false, request: decorateAuthReq(result.request),
13961
14018
  });
@@ -13969,9 +14026,11 @@ export function createRoutes(ctx) {
13969
14026
  const reason = typeof (req.body ?? {}).denyReason === 'string' ? req.body.denyReason : '';
13970
14027
  const result = ctx.authorizationRequests.store.deny(req.params.id, reason);
13971
14028
  if (!result.ok) {
14029
+ featureEvidence.record('monitoring.authorizationRequests', { kind: 'held', reason: `deny refused: ${result.error}`, context: { requestId: req.params.id, status: result.status } });
13972
14030
  res.status(result.status).json({ error: result.error });
13973
14031
  return;
13974
14032
  }
14033
+ featureEvidence.record('monitoring.authorizationRequests', { kind: 'fired', reason: 'denied', context: { requestId: result.request.id, floorAction: result.request.proposal.floorAction } });
13975
14034
  res.json({ denied: true, request: decorateAuthReq(result.request) });
13976
14035
  });
13977
14036
  // Proposing agent WITHDRAWS its own still-pending request (Bearer).
@@ -13982,9 +14041,11 @@ export function createRoutes(ctx) {
13982
14041
  const agentName = (typeof b.createdByAgent === 'string' && b.createdByAgent) ? b.createdByAgent : 'agent';
13983
14042
  const result = ctx.authorizationRequests.store.withdraw(req.params.id, agentName);
13984
14043
  if (!result.ok) {
14044
+ featureEvidence.record('monitoring.authorizationRequests', { kind: 'held', reason: `withdraw refused: ${result.error}`, context: { requestId: req.params.id, status: result.status } });
13985
14045
  res.status(result.status).json({ error: result.error });
13986
14046
  return;
13987
14047
  }
14048
+ featureEvidence.record('monitoring.authorizationRequests', { kind: 'fired', reason: 'withdrawn', context: { requestId: result.request.id, floorAction: result.request.proposal.floorAction } });
13988
14049
  res.json({ withdrawn: true, request: decorateAuthReq(result.request) });
13989
14050
  });
13990
14051
  // ── ReviewExchange — autonomous code-review protocol (coordination-mandate spec §7 G2.3) ──
@@ -14867,6 +14928,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
14867
14928
  const plan = ctx.feedbackTriage.store.createPlan({ action: 'ignore-live', payload: { enabled }, renderedText });
14868
14929
  res.json({ action: 'ignore-live', ...plan });
14869
14930
  });
14931
+ registerRecommendedServiceRoutes(router, { ledger: () => ctx.recommendedServicesLedger ?? null, checkPin: (req, res) => checkMandatePin(req, res) });
14870
14932
  registerEcosystemIdeaRoutes(router, { ecosystem: () => ctx.ecosystemIdeas?.() ?? null, checkPin: (req, res) => checkMandatePin(req, res) });
14871
14933
  router.post('/feedback-factory/triage/commit', (req, res) => {
14872
14934
  if (triageUnavailable(res))
@@ -18143,6 +18205,10 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
18143
18205
  const advisories = kind === 'automated'
18144
18206
  ? composeAdvisories(capped, { sessionClocks: activeClocks })
18145
18207
  : composeTimeClaimAdvisories(capped, activeClocks);
18208
+ const timeClaimAdvisories = advisories.filter((a) => a.code === 'TIME_CLAIM').length;
18209
+ if (timeClaimAdvisories > 0) {
18210
+ featureEvidence.record('messaging.outboundAdvisory.timeClaim', { kind: 'fired', reason: 'TIME_CLAIM: claim contradicts the live session clock', context: { topicId: Number.isFinite(topic) ? topic : 0, senderKind: kind, jobSlug: typeof jobSlug === 'string' ? jobSlug : null, timeClaimAdvisories, activeClocks: activeClocks.length, chars: capped.length } });
18211
+ }
18146
18212
  outboundAdvisoryAudit.recordPreflight({
18147
18213
  topicId: Number.isFinite(topic) ? topic : 0,
18148
18214
  // Non-automated (conversational-session) preflights carry no job slug —
@@ -18416,6 +18482,9 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
18416
18482
  toneAdvisoryComplied,
18417
18483
  // jev-signal-live: this reply path carries the acknowledge-and-override fields.
18418
18484
  liveArtefactSignals: true,
18485
+ // A sentinel redrive has nobody to react to a nudge, and the recovery policy treats any 422
18486
+ // as final, so B22 must not hold it. A fabricated header does not buy this: it must match a queue row.
18487
+ noReactionPossible: typeof deliveryId === 'string' && /^[0-9a-f-]{16,64}$/i.test(deliveryId) && ctx.pendingRelayLookup?.(deliveryId) === true,
18419
18488
  }))
18420
18489
  return false;
18421
18490
  ctx.telegramOrigin?.service.markCurrentSendPolicyReviewed();
@@ -19967,9 +20036,11 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
19967
20036
  if (body.match === false) {
19968
20037
  const ok = trustManager.markVerificationFailed(peerFp, 'Operator-asserted SAS mismatch (POST /threadline/pairing/:peerFp/verify)');
19969
20038
  if (!ok) {
20039
+ featureEvidence.record('threadline.verifiedPairing', { kind: 'error', reason: 'could-not-mark-verification-failed', context: { peerFp } });
19970
20040
  res.status(409).json({ error: 'could not mark verification-failed for this pairing' });
19971
20041
  return;
19972
20042
  }
20043
+ featureEvidence.record('threadline.verifiedPairing', { kind: 'error', reason: 'verification-failed: sas-mismatch', context: { peerFp, typedWords: Array.isArray(body.words) } });
19973
20044
  // §3.2 / §3.7 — an operator-asserted SAS mismatch is a potential MITM and must
19974
20045
  // raise ONE HIGH attention item, deduped per (peerFp) episode, NEVER coalesced
19975
20046
  // (a re-attempt LOOP — repeated handshake-then-mismatch — collapses onto the SAME
@@ -20003,6 +20074,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
20003
20074
  peerAcked: profile.peerAcked,
20004
20075
  });
20005
20076
  if (!ok) {
20077
+ featureEvidence.record('threadline.verifiedPairing', { kind: 'error', reason: 'confirm-refused: state-or-epoch', context: { peerFp, pairingState: profile.pairingState ?? null } });
20006
20078
  res.status(409).json({ error: 'could not confirm pairing (state/epoch mismatch or not pending) — re-handshake required' });
20007
20079
  return;
20008
20080
  }
@@ -20874,16 +20946,19 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
20874
20946
  let dropped = 0;
20875
20947
  for (const intent of remoteAckStore.list()) {
20876
20948
  if (intent.attempts >= REMOTE_ACK_GIVE_UP_ATTEMPTS) {
20949
+ featureEvidence.record('multiMachine.seamlessness.ws41DurableAck', { kind: 'error', reason: 'ack intent given up after the attempt limit', context: { itemId: intent.itemId, targetMachineId: intent.targetMachineId, attempts: intent.attempts, lastOutcome: intent.lastOutcome ?? null } });
20877
20950
  remoteAckStore.resolve(intent.itemId, intent.targetMachineId);
20878
20951
  dropped += 1;
20879
20952
  continue;
20880
20953
  }
20881
20954
  const disposition = await deliverRemoteAck(intent);
20882
20955
  if (disposition === 'delivered') {
20956
+ featureEvidence.record('multiMachine.seamlessness.ws41DurableAck', { kind: 'fired', reason: 'queued ack applied on the owner', context: { itemId: intent.itemId, targetMachineId: intent.targetMachineId, attempts: intent.attempts } });
20883
20957
  remoteAckStore.resolve(intent.itemId, intent.targetMachineId);
20884
20958
  delivered += 1;
20885
20959
  }
20886
20960
  else if (disposition === 'stale-superseded') {
20961
+ featureEvidence.record('multiMachine.seamlessness.ws41DurableAck', { kind: 'held', reason: 'queued ack superseded on the owner', context: { itemId: intent.itemId, targetMachineId: intent.targetMachineId, attempts: intent.attempts } });
20887
20962
  remoteAckStore.resolve(intent.itemId, intent.targetMachineId);
20888
20963
  dropped += 1;
20889
20964
  }
@@ -25530,7 +25605,13 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
25530
25605
  // bound, single-use, mesh-signed assertion of THAT user-authentication —
25531
25606
  // never the raw credential (each machine's PIN secret never crosses).
25532
25607
  if (ctx.poolLink) {
25533
- await proxyViewToHolder(req, res, req.params.id);
25608
+ try {
25609
+ await proxyViewToHolder(req, res, req.params.id);
25610
+ }
25611
+ catch (err) {
25612
+ featureEvidence.record('multiMachine.seamlessness.ws44PoolLinks', { kind: 'error', reason: 'view proxy to the holder failed', context: { error: (err instanceof Error ? err.message : String(err)).slice(0, 80) } });
25613
+ throw err;
25614
+ }
25534
25615
  return;
25535
25616
  }
25536
25617
  res.status(404).json({ error: 'View not found' });
@@ -25595,12 +25676,14 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
25595
25676
  // labeled), never a fabricated/stale body. (The broader pool-cache
25596
25677
  // unification is the tracked follow-up CMT-1416; this in-scope posture is
25597
25678
  // the staleness-tag on the holder-resolution caching surface.)
25679
+ featureEvidence.record('multiMachine.seamlessness.ws44PoolLinks', { kind: 'held', reason: 'declined: fronting machine load-shedding with no cached holder', context: { resolution: resolution.kind } });
25598
25680
  res.status(503).setHeader('Retry-After', '5');
25599
25681
  res.json({ error: 'Fronting machine busy (load-shed) — retry shortly' });
25600
25682
  return;
25601
25683
  }
25602
25684
  if (resolution.kind === 'holder-offline') {
25603
25685
  // §WS4.4 d: honest unavailable — NEVER a bare 404, never stale content.
25686
+ featureEvidence.record('multiMachine.seamlessness.ws44PoolLinks', { kind: 'held', reason: 'holder offline: answered unavailable', context: { resolution: resolution.kind, stale: tagged.stale } });
25604
25687
  tagStale();
25605
25688
  res.status(503).setHeader('Content-Type', 'text/html; charset=utf-8');
25606
25689
  res.send('<!doctype html><meta charset="utf-8"><title>Temporarily unavailable</title>'
@@ -25620,17 +25703,24 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
25620
25703
  const slot = await pl.proxy.withSlot(async () => pl.fetchFromHolder({ machineId: resolution.machineId, url: resolution.url }, viewId, method, assertion));
25621
25704
  if (!slot.ok) {
25622
25705
  // §WS4.4 c: over the in-flight cap — honest 503, never an unbounded queue.
25706
+ featureEvidence.record('multiMachine.seamlessness.ws44PoolLinks', { kind: 'held', reason: 'over the in-flight proxy cap', context: { holder: resolution.machineId, method } });
25623
25707
  res.status(503).json({ error: 'Too many in-flight remote view requests — retry shortly' });
25624
25708
  return;
25625
25709
  }
25626
25710
  const holderRes = slot.value;
25627
25711
  if (holderRes.status === 404) {
25712
+ featureEvidence.record('multiMachine.seamlessness.ws44PoolLinks', { kind: 'error', reason: 'resolved holder no longer has the view', context: { holder: resolution.machineId, status: 404, stale: tagged.stale, method } });
25628
25713
  // The memo may name a stale holder (view moved). Invalidate so the next
25629
25714
  // request re-fans-out, and surface not-found honestly.
25630
25715
  pl.proxy.invalidate(viewId);
25631
25716
  res.status(404).json({ error: 'View not found' });
25632
25717
  return;
25633
25718
  }
25719
+ featureEvidence.recordAtMostEvery('multiMachine.seamlessness.ws44PoolLinks', `proxied|${holderRes.status}`, 10 * 60 * 1000, {
25720
+ kind: holderRes.status >= 500 || holderRes.status === 401 || holderRes.status === 403 ? 'error' : 'fired',
25721
+ reason: holderRes.status === 401 || holderRes.status === 403 ? 'holder refused the assertion' : `proxied view to the holder: ${holderRes.status}`,
25722
+ context: { holder: resolution.machineId, status: holderRes.status, stale: tagged.stale, method, userAuth },
25723
+ });
25634
25724
  // §WS4.4 b: the HOLDER makes the authorization decision — relay its
25635
25725
  // 401/403 (or any status) UNCHANGED. The fronting machine never substitutes
25636
25726
  // its own decision. Stream the body straight through; never cache it.
@@ -28658,6 +28748,11 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
28658
28748
  const full = String(req.query.full ?? '') === '1';
28659
28749
  const bsk = new BootSelfKnowledge({ stateDir: ctx.config.stateDir, configPath });
28660
28750
  const result = bsk.sessionContext(maxBytes, { full });
28751
+ featureEvidence.record('selfKnowledge.sessionContext', {
28752
+ kind: result.vaultState === 'decrypt-failed' ? 'error' : 'fired',
28753
+ reason: result.vaultState === 'decrypt-failed' ? 'vault-decrypt-failed' : result.present ? 'block-served' : 'nothing-to-serve',
28754
+ context: { present: result.present, nameCount: result.names.length, factCount: result.factCount, vaultState: result.vaultState, blockBytes: Buffer.byteLength(result.block, 'utf8'), maxBytes, full },
28755
+ });
28661
28756
  console.log(`[boot-self-knowledge] served names=${result.names.length} facts=${result.factCount} vaultState=${result.vaultState} bytes=${Buffer.byteLength(result.block, 'utf8')}`);
28662
28757
  if (result.vaultState === 'decrypt-failed') {
28663
28758
  console.warn('[boot-self-knowledge] vault DECRYPT-FAILED — served hands-off warning block (not an empty vault)');
@@ -28665,6 +28760,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
28665
28760
  res.json(result);
28666
28761
  }
28667
28762
  catch (err) {
28763
+ featureEvidence.record('selfKnowledge.sessionContext', { kind: 'error', reason: 'build-failed', context: { errorName: err instanceof Error ? err.name : 'unknown' } });
28668
28764
  res.status(500).json({ error: err instanceof Error ? err.message : 'Failed to build boot self-knowledge' });
28669
28765
  }
28670
28766
  });
@@ -29397,6 +29493,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
29397
29493
  const entry = outbox.enqueue({ canonicalEmail: canonical, targetMachineId, principal, portable,
29398
29494
  cutoffSeq: Number.isSafeInteger(args.revokesGrantSeq) ? args.revokesGrantSeq : null });
29399
29495
  const after = await outbox.attemptNow(entry.key);
29496
+ featureEvidence.record('passkeys', { kind: after?.state === 'applied' ? 'fired' : 'held', reason: after?.state === 'applied' ? 'peer-revoke-applied' : 'peer-revoke-queued', context: { op, target: targetMachineId, outboxState: after?.state ?? 'pending' } });
29400
29497
  appendPlaywrightAudit('passkey-revoke', 'passkeys', { target: targetMachineId, email: canonical ? 'set' : 'none', delivered: after?.state === 'applied', outbox: after?.state ?? 'pending', reason: after?.lastResult ?? null, dryRun: false });
29401
29498
  res.status(after?.state === 'applied' ? 200 : 202).json({ op, target: targetMachineId, delivered: after?.state === 'applied', outbox: after ? { key: after.key, state: after.state, attempts: after.attempts, nextAttemptAt: after.nextAttemptAt, lastResult: after.lastResult ?? null } : null,
29402
29499
  note: after?.state === 'applied' ? undefined : 'queued in the durable revoke outbox; re-delivered unchanged on backoff (1h, 6h, then daily) until the peer applies it' });
@@ -29408,12 +29505,14 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
29408
29505
  auth.grants.recordIssuedPeerGrant({ canonicalEmail: canonical, targetMachineId, issuedAt: new Date().toISOString(), nonce: out.portable?.body.nonce ?? '',
29409
29506
  ...(Number.isSafeInteger(peerSeq) ? { targetLocalSeq: peerSeq } : {}) });
29410
29507
  }
29508
+ featureEvidence.record('passkeys', { kind: out.ok ? 'fired' : 'error', reason: out.ok ? `peer-${op}-delivered` : `peer-${op}-failed: ${out.reason ?? 'unknown'}`, context: { op, target: targetMachineId, status: out.status ?? null } });
29411
29509
  appendPlaywrightAudit(`passkey-${op}`, 'passkeys', { target: targetMachineId, email: canonical ? 'set' : 'none', delivered: out.ok, reason: out.reason ?? null, dryRun: false });
29412
29510
  res.status(out.ok ? 200 : 502).json({ op, target: targetMachineId, delivered: out.ok, status: out.status, reason: out.reason ?? null, result: out.result ?? null });
29413
29511
  return;
29414
29512
  }
29415
29513
  const body = mintPasskeyCellBody({ principal, canonicalEmail: canonical, targetMachineId, op, args });
29416
29514
  const outcome = await applyLocalPasskeyCellAction(auth.deps, body);
29515
+ featureEvidence.record('passkeys', { kind: outcome.applied ? 'fired' : 'error', reason: outcome.applied ? `local-${op}-applied` : `local-${op}-refused: ${outcome.reason}`, context: { op, target: 'local' } });
29417
29516
  appendPlaywrightAudit(`passkey-${op}`, 'passkeys', { target: 'local', email: canonical ? 'set' : 'none', applied: outcome.applied, reason: outcome.applied ? null : outcome.reason, dryRun: false });
29418
29517
  res.status(outcome.applied ? 200 : (outcome.reason === 'issuer-bootstrap-required' ? 409 : 400)).json({ ...outcome, target: targetMachineId });
29419
29518
  };
@@ -29968,6 +30067,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
29968
30067
  return;
29969
30068
  }
29970
30069
  const r = buildPasskeyHealth(auth).recordOutcome({ canonicalEmail: email, outcome: outcome, origin: origin, reenrolled });
30070
+ featureEvidence.record('passkeys', { kind: outcome === 'ready' ? 'fired' : outcome === 'unknown' ? 'held' : 'error', reason: `proof-outcome: ${outcome}`, context: { outcome, origin, transition: r.transition ? `${r.transition.from}->${r.transition.to}` : null } });
29971
30071
  appendPlaywrightAudit('passkey-health-outcome', 'passkeys', { outcome, origin, transition: r.transition ? `${r.transition.from}->${r.transition.to}` : null, dryRun: false });
29972
30072
  res.json({ cell: r.cell, transition: r.transition, scheduleConfirmAt: r.scheduleConfirmAt });
29973
30073
  }
@@ -30089,6 +30189,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
30089
30189
  pauses.push('account-throttled-24h', 'machine-throttled-1h');
30090
30190
  }
30091
30191
  const recorded = health.recordOutcome({ canonicalEmail: canonical, outcome: result.outcome, origin: 'operator' });
30192
+ featureEvidence.record('passkeys', { kind: result.outcome === 'ready' ? 'fired' : result.outcome === 'unknown' ? 'held' : 'error', reason: `sign-in-proof: ${result.outcome}`, context: { outcome: result.outcome, reasonCode: result.reason ?? null, finalPageClass: result.finalPageClass ?? null, steps: result.steps.length, riskPage: !!result.riskPage, throttled: !!result.throttled } });
30092
30193
  appendPlaywrightAudit('passkey-prove', 'passkeys', { outcome: result.outcome, reason: result.reason, page: result.finalPageClass, steps: result.steps.length, pauses: pauses.join(',') || null, transition: recorded.transition ? `${recorded.transition.from}->${recorded.transition.to}` : null, dryRun: false });
30093
30194
  res.json({ outcome: result.outcome, reason: result.reason, finalPageClass: result.finalPageClass, observedAssertion: result.observedAssertion, singleCredential: result.singleCredential, signedInIdentity: result.signedInIdentity, riskPage: result.riskPage, throttled: result.throttled, steps: result.steps, teardown: result.teardown, pauses, cell: recorded.cell, transition: recorded.transition,
30094
30195
  // Honest about the admission inputs this build does not publish yet (same wording as GET /passkeys/admission).
@@ -30113,10 +30214,12 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
30113
30214
  try {
30114
30215
  const auth = await buildPasskeyAuthorityAndSweep();
30115
30216
  const outcome = await receivePasskeyCellMandate({ ...auth.deps, verify: { issuerPublicKeyPem: passkeyIssuerPublicKeyPem } }, portable);
30217
+ featureEvidence.record('passkeys', { kind: outcome.applied ? 'fired' : 'error', reason: outcome.applied ? `mandate-applied: ${outcome.op}` : `mandate-refused: ${outcome.reason}`, context: { op: outcome.op ?? null, applied: outcome.applied } });
30116
30218
  appendPlaywrightAudit('passkey-cell-action', 'passkeys', { op: outcome.op, applied: outcome.applied, reason: outcome.applied ? null : outcome.reason, dryRun: false });
30117
30219
  res.status(outcome.applied ? 200 : 403).json(outcome);
30118
30220
  }
30119
30221
  catch (err) {
30222
+ featureEvidence.record('passkeys', { kind: 'error', reason: 'mandate-authority-unreadable', context: { errorName: err instanceof Error ? err.name : 'unknown' } });
30120
30223
  res.status(500).json({ applied: false, reason: 'authority-unreadable', detail: err instanceof Error ? err.message : String(err) });
30121
30224
  }
30122
30225
  });
@@ -34296,6 +34399,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
34296
34399
  const { command, cwd, topicId, sessionName, intent, prNumber } = req.body ?? {};
34297
34400
  if (typeof command !== 'string' || typeof cwd !== 'string' || typeof topicId !== 'number' || typeof sessionName !== 'string') {
34298
34401
  // Malformed → fail-open (never block on a bad request).
34402
+ featureEvidence.record('monitoring.prHandLease', { kind: 'error', reason: 'bad-request-failopen', context: { dryRun } });
34299
34403
  res.json({ decision: 'allow', reason: 'bad-request-failopen' });
34300
34404
  return;
34301
34405
  }
@@ -34308,6 +34412,19 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
34308
34412
  return;
34309
34413
  }
34310
34414
  const evalResult = ctx.prHandLease.evaluate(key, topicId, sessionName);
34415
+ const leaseRefuses = evalResult.decision === 'deny' || evalResult.decision === 'escalate';
34416
+ featureEvidence.record('monitoring.prHandLease', {
34417
+ kind: evalResult.reason === 'eval-error-failopen' ? 'error' : leaseRefuses ? 'fired' : 'held',
34418
+ reason: `${leaseRefuses && dryRun ? 'would-' : ''}${evalResult.decision}:${evalResult.reason}`,
34419
+ context: {
34420
+ decision: evalResult.decision,
34421
+ leaseReason: evalResult.reason,
34422
+ dryRun,
34423
+ topicId,
34424
+ holderTopicId: evalResult.holder?.holderTopicId ?? null,
34425
+ holderPr: evalResult.holder?.prNumber ?? null,
34426
+ },
34427
+ });
34311
34428
  // Always (re)acquire/renew MY lease on the allow-because-mine / no-lease paths,
34312
34429
  // and take over on a stale path — so a peer can see I hold it.
34313
34430
  if (evalResult.decision === 'allow' && (evalResult.reason === 'own-topic' || evalResult.reason === 'no-lease')) {
@@ -34328,6 +34445,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
34328
34445
  }
34329
34446
  catch (err) {
34330
34447
  // Inner fail-open — never block a push on an internal error.
34448
+ featureEvidence.record('monitoring.prHandLease', { kind: 'error', reason: 'eval-error-failopen', context: { dryRun, errorName: err instanceof Error ? err.name : 'unknown' } });
34331
34449
  res.json({ decision: 'allow', reason: 'eval-error-failopen' });
34332
34450
  }
34333
34451
  });
@@ -34607,6 +34725,8 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
34607
34725
  attention: ctx.telegram,
34608
34726
  });
34609
34727
  if (!verdict.ok) {
34728
+ if (isMinted)
34729
+ featureEvidence.record('messaging.actionClaim.slack', { kind: 'held', reason: 'refused: conversation-bind-not-authorized', context: { topicId, lane, dryRun: slackDryRun } });
34610
34730
  res.status(403).json({ error: 'conversation-bind-not-authorized', detail: verdict.detail });
34611
34731
  return;
34612
34732
  }
@@ -34622,6 +34742,8 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
34622
34742
  (c.externalKey.startsWith('actionclaim:') || c.externalKey.startsWith('timepromise:')));
34623
34743
  const alreadyOpen = openForTopic.some((c) => c.externalKey === externalKey);
34624
34744
  if (!alreadyOpen && openForTopic.length >= cap) {
34745
+ if (isMinted)
34746
+ featureEvidence.record('messaging.actionClaim.slack', { kind: 'held', reason: 'refused: per-topic-cap', context: { topicId, lane, dryRun: slackDryRun, openForTopic: openForTopic.length, cap } });
34625
34747
  res.json({ observed: true, registered: false, reason: 'per-topic-cap', lane, ...(verb ? { verb } : {}), cap, activityNote });
34626
34748
  return;
34627
34749
  }
@@ -34648,6 +34770,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
34648
34770
  catch {
34649
34771
  /* audit is observability */
34650
34772
  }
34773
+ featureEvidence.record('messaging.actionClaim.slack', { kind: 'fired', reason: 'would register (dry run)', context: { topicId, lane, verb: verb ?? null, externalKey, bindVerdict: boundBy ?? 'legacy-open', dryRun: true, openForTopic: openForTopic.length, alreadyOpen } });
34651
34774
  res.json({ observed: true, registered: false, dryRun: true, wouldRegister: true, lane, ...(verb ? { verb } : {}), externalKey, activityNote });
34652
34775
  return;
34653
34776
  }
@@ -34666,6 +34789,8 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
34666
34789
  // Lane B passes NO beacon fields — record()'s internal auto-arm sets
34667
34790
  // beaconEnabled + cadence from the SAME detectTimePromise (§4.2 fold).
34668
34791
  });
34792
+ if (isMinted)
34793
+ featureEvidence.record('messaging.actionClaim.slack', { kind: 'fired', reason: 'registered', context: { topicId, lane, verb: verb ?? null, commitmentId: commitment.id, bindVerdict: boundBy ?? 'legacy-open', dryRun: false, beaconEnabled: commitment.beaconEnabled ?? false, alreadyOpen } });
34669
34794
  res.json({
34670
34795
  observed: true,
34671
34796
  registered: true,
@@ -34679,6 +34804,8 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
34679
34804
  }
34680
34805
  catch (err) {
34681
34806
  // Signal-only: never surface a failure as a block. Audit via the 500-free path.
34807
+ if (isMinted)
34808
+ featureEvidence.record('messaging.actionClaim.slack', { kind: 'error', reason: 'record-failed', context: { topicId, lane, verb: verb ?? null, errorName: err instanceof Error ? err.name : 'unknown' } });
34682
34809
  res.json({ observed: true, registered: false, reason: 'record-failed', detail: err instanceof Error ? err.message : String(err) });
34683
34810
  }
34684
34811
  });
@@ -37622,6 +37749,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
37622
37749
  // No trust manager (relay off, relay standby, or trust init failed):
37623
37750
  // there is no authority to consult, so today's handling stands. Counted.
37624
37751
  localRouteTrustCounters.noTrustManager++;
37752
+ featureEvidence.recordAtMostEvery('threadline.localRouteTrust', 'no-trust-manager', 60 * 60 * 1000, { kind: 'held', reason: 'no-trust-manager', context: { dryRun: trustMode.dryRun } });
37625
37753
  }
37626
37754
  else {
37627
37755
  let verdict = null;
@@ -37636,6 +37764,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
37636
37764
  }
37637
37765
  catch (trustErr) {
37638
37766
  localRouteTrustCounters.lookupErrors++;
37767
+ featureEvidence.record('threadline.localRouteTrust', { kind: 'error', reason: 'trust-lookup-failed', context: { dryRun: trustMode.dryRun, senderRegistered: !!senderRegistryFp } });
37639
37768
  console.warn(`[relay-agent-trust] lookup failed: ${trustErr instanceof Error ? trustErr.message : String(trustErr)}`);
37640
37769
  if (!trustMode.dryRun) {
37641
37770
  // Enforcing and the authority cannot answer: refuse, retryable —
@@ -37646,6 +37775,15 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
37646
37775
  }
37647
37776
  if (verdict) {
37648
37777
  localRouteTrustCounters.evaluated++;
37778
+ // Per message, so one row per sender, operation and verdict per hour. A refusal of
37779
+ // a registry-known same-machine agent is the failure this rollout watches for.
37780
+ const localTrustEvidenceVerdict = verdict.allowed ? 'allowed' : trustMode.dryRun ? 'would-refuse' : 'refuse';
37781
+ const localTrustEvidenceFailure = !verdict.allowed && verdict.identitySource === 'registry';
37782
+ featureEvidence.recordAtMostEvery('threadline.localRouteTrust', `${verdict.fingerprint ?? 'no-fp'}|${verdict.identitySource}|${verdict.operation.slice(0, 48)}|${localTrustEvidenceVerdict}`, 60 * 60 * 1000, {
37783
+ kind: localTrustEvidenceFailure ? 'error' : 'fired',
37784
+ reason: localTrustEvidenceFailure ? `${localTrustEvidenceVerdict}-registered-sender` : localTrustEvidenceVerdict,
37785
+ context: { level: verdict.level, operation: verdict.operation.slice(0, 48), identitySource: verdict.identitySource, fingerprint: verdict.fingerprint, dryRun: trustMode.dryRun },
37786
+ });
37649
37787
  if (verdict.allowed) {
37650
37788
  localRouteTrustCounters.allowed++;
37651
37789
  // Enforcing: the router is told the resolved level instead of the
@@ -39747,6 +39885,11 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
39747
39885
  backupRouteCounters.fingerprintLocal++;
39748
39886
  fingerprintRouteCounted = true;
39749
39887
  console.log(backupLogLine('fingerprint-local', msgId, localPostPeerFp, outcome));
39888
+ featureEvidence.recordAtMostEvery('threadline.backupRoutes', `fingerprint-local|${localPostPeerFp}|${accepted}`, 5 * 60 * 1000, {
39889
+ kind: accepted ? 'fired' : 'error',
39890
+ reason: accepted ? 'fingerprint-local-delivered' : 'fingerprint-local-not-accepted',
39891
+ context: { path: 'fingerprint-local', peerFp: localPostPeerFp, messageId: msgId, status: localResp.status },
39892
+ });
39750
39893
  }
39751
39894
  // Persist our OWN outbound leg into the thread history so
39752
39895
  // getThread()/threadline_history return BOTH halves of the
@@ -40037,9 +40180,11 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
40037
40180
  if (fallthrough.marked) {
40038
40181
  backupRouteCounters.markedFallthrough++;
40039
40182
  console.log(backupLogLine('marked-fallthrough', msgId, localPostPeerFp || resolvedId, fallthrough.outcome));
40183
+ featureEvidence.recordAtMostEvery('threadline.backupRoutes', `marked-fallthrough|${fallthrough.outcome}`, 10 * 60 * 1000, { kind: 'fired', reason: `marked-fallthrough: ${fallthrough.outcome}`, context: { path: 'marked-fallthrough', peerFp: localPostPeerFp || resolvedId, messageId: msgId, outcome: fallthrough.outcome } });
40040
40184
  }
40041
40185
  else {
40042
40186
  backupRouteCounters.unmarkedFallthroughAfterPost++;
40187
+ featureEvidence.recordAtMostEvery('threadline.backupRoutes', `unmarked-fallthrough|${fallthrough.outcome}`, 10 * 60 * 1000, { kind: 'held', reason: `unmarked-fallthrough: ${fallthrough.outcome}`, context: { path: 'unmarked-fallthrough', peerFp: localPostPeerFp || resolvedId, messageId: msgId, outcome: fallthrough.outcome } });
40043
40188
  }
40044
40189
  }
40045
40190
  const relayLegResend = Boolean(fallthrough?.marked || (forwardedRequest && req.body?.resend === true));
@@ -41062,6 +41207,10 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
41062
41207
  });
41063
41208
  // ── Phase 2: State Machine, Consent, Events ─────────────────────
41064
41209
  router.post('/features/:id/surface', (req, res) => {
41210
+ if (isRetiredLegacyOffer(req.params.id)) {
41211
+ res.status(409).json({ error: { code: 'OFFER_RETIRED', message: 'This offer now goes through recommended services.' } });
41212
+ return;
41213
+ }
41065
41214
  if (!ctx.featureRegistry) {
41066
41215
  res.status(501).json({ error: 'FeatureRegistry not initialized' });
41067
41216
  return;
@@ -42773,6 +42922,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
42773
42922
  // enforces (a non-move is a recorded 200 'aborted', never a misleading PASS).
42774
42923
  const t = await transfer(telegramTopicId, targetMachine);
42775
42924
  if (!t.seatMoved) {
42925
+ featureEvidence.record('monitoring.liveTestRunner', { kind: 'held', reason: 'capstone-aborted-seat-did-not-move', context: { targetMachine, blockedSurfaces: blockedSurfaces.length, hasSlack: Boolean(slackChannelId) } });
42776
42926
  res.status(200).json({ ok: true, seatMoved: false, capstone: 'aborted', reason: t.detail ?? 'seat did not move', blockedSurfaces });
42777
42927
  return;
42778
42928
  }
@@ -42781,9 +42931,25 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
42781
42931
  const matrix = buildMultiMachineCapstoneMatrix({ featureId, targetMachine, telegramTopicId, slackChannelId, message, timeoutMs });
42782
42932
  const harness = ctx.liveTestRunnerCtx.makeHarness(driver);
42783
42933
  const result = await harness.run(matrix, runId ? { runId } : {});
42934
+ const scenarioVerdict = (v) => result.artifact.scenarios.filter((s) => s.verdict === v).length;
42935
+ featureEvidence.record('monitoring.liveTestRunner', {
42936
+ kind: 'fired',
42937
+ reason: 'capstone-ran',
42938
+ context: {
42939
+ targetMachine,
42940
+ runId: result.artifact.runId,
42941
+ scenarios: result.artifact.scenarios.length,
42942
+ passed: scenarioVerdict('PASS'),
42943
+ failed: scenarioVerdict('FAIL'),
42944
+ blocked: scenarioVerdict('BLOCKED'),
42945
+ blockedSurfaces: blockedSurfaces.length,
42946
+ surfaces: result.artifact.surfaces.join(','),
42947
+ },
42948
+ });
42784
42949
  res.json({ ok: true, seatMoved: true, capstone: 'ran', artifact: result.artifact, entry: result.entry, blockedSurfaces });
42785
42950
  }
42786
42951
  catch (err) {
42952
+ featureEvidence.record('monitoring.liveTestRunner', { kind: 'error', reason: 'capstone-run-failed', context: { targetMachine, errorName: err instanceof Error ? err.name : 'unknown' } });
42787
42953
  // A genuine internal error surfaces LOUDLY as a 500 with the reason — never a
42788
42954
  // fabricated PASS, never a swallowed run. This is the honest error path.
42789
42955
  res.status(500).json({ error: `capstone run failed: ${err instanceof Error ? err.message : String(err)}` });