@noopolis/daimon 0.2.0 → 0.2.1

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 (255) hide show
  1. package/README.md +6 -0
  2. package/dist/contracts/attentionContract.d.ts +25 -0
  3. package/dist/contracts/attentionContract.d.ts.map +1 -1
  4. package/dist/contracts/attentionContract.js +8 -1
  5. package/dist/contracts/grokBrokerTaskClock.d.ts +18 -0
  6. package/dist/contracts/grokBrokerTaskClock.d.ts.map +1 -0
  7. package/dist/contracts/grokBrokerTaskClock.js +16 -0
  8. package/dist/contracts/organizationRuntimeContract.d.ts +76 -0
  9. package/dist/contracts/organizationRuntimeContract.d.ts.map +1 -1
  10. package/dist/contracts/organizationRuntimeContract.js +2 -0
  11. package/dist/contracts/runtimeContractManifest.d.ts +222 -15
  12. package/dist/contracts/runtimeContractManifest.d.ts.map +1 -1
  13. package/dist/contracts/runtimeContractManifest.js +35 -10
  14. package/dist/contracts/shellEnvironmentPolicy.d.ts +3 -0
  15. package/dist/contracts/shellEnvironmentPolicy.d.ts.map +1 -0
  16. package/dist/contracts/shellEnvironmentPolicy.js +5 -0
  17. package/dist/contracts/wakeMomentContract.d.ts +61 -0
  18. package/dist/contracts/wakeMomentContract.d.ts.map +1 -0
  19. package/dist/contracts/wakeMomentContract.js +27 -0
  20. package/dist/core/types.d.ts +2 -0
  21. package/dist/core/types.d.ts.map +1 -1
  22. package/dist/examples/jungianPlayAgent.d.ts +1 -0
  23. package/dist/examples/jungianPlayAgent.d.ts.map +1 -1
  24. package/dist/examples/jungianPlayAgent.js +6 -2
  25. package/dist/observability/causalEvents.d.ts +3 -3
  26. package/dist/observability/causalEvents.d.ts.map +1 -1
  27. package/dist/observability/causalEvents.js +4 -4
  28. package/dist/pi/cliEngineSpawn.d.ts +2 -2
  29. package/dist/pi/cliEngineSpawn.d.ts.map +1 -1
  30. package/dist/pi/cliEngineSpawn.js +7 -2
  31. package/dist/pi/cliEnvironment.d.ts.map +1 -1
  32. package/dist/pi/cliEnvironment.js +2 -0
  33. package/dist/pi/cliMcpRegistration.d.ts +1 -1
  34. package/dist/pi/cliMcpRegistration.d.ts.map +1 -1
  35. package/dist/pi/cliMcpRegistration.js +1 -1
  36. package/dist/pi/cliSession.d.ts +2 -0
  37. package/dist/pi/cliSession.d.ts.map +1 -1
  38. package/dist/pi/cliSession.js +3 -80
  39. package/dist/pi/cliSessionMcp.d.ts +9 -0
  40. package/dist/pi/cliSessionMcp.d.ts.map +1 -0
  41. package/dist/pi/cliSessionMcp.js +80 -0
  42. package/dist/pi/engineTaskClock.d.ts +9 -0
  43. package/dist/pi/engineTaskClock.d.ts.map +1 -0
  44. package/dist/pi/engineTaskClock.js +28 -0
  45. package/dist/pi/grokHomeMcpRegistration.d.ts.map +1 -1
  46. package/dist/pi/grokHomeMcpRegistration.js +2 -1
  47. package/dist/pi/grokSandbox.js +1 -1
  48. package/dist/pi/memoryClock.d.ts +25 -0
  49. package/dist/pi/memoryClock.d.ts.map +1 -0
  50. package/dist/pi/memoryClock.js +18 -0
  51. package/dist/pi/piAgentHandle.d.ts +3 -1
  52. package/dist/pi/piAgentHandle.d.ts.map +1 -1
  53. package/dist/pi/piAgentHandle.js +5 -2
  54. package/dist/pi/piHarness.d.ts +8 -2
  55. package/dist/pi/piHarness.d.ts.map +1 -1
  56. package/dist/pi/piHarness.js +28 -12
  57. package/dist/pi/taskClockProcess.d.ts +6 -0
  58. package/dist/pi/taskClockProcess.d.ts.map +1 -0
  59. package/dist/pi/taskClockProcess.js +8 -0
  60. package/dist/pi/turnCausal.d.ts +4 -2
  61. package/dist/pi/turnCausal.d.ts.map +1 -1
  62. package/dist/pi/turnCausal.js +4 -4
  63. package/dist/pi/wakeAcceptance.d.ts +1 -1
  64. package/dist/pi/wakeAcceptance.d.ts.map +1 -1
  65. package/dist/pi/wakeAcceptance.js +2 -2
  66. package/dist/runtime/agySubscriptionBootstrap.js +1 -1
  67. package/dist/runtime/agySubscriptionRealm.js +1 -1
  68. package/dist/runtime/attention.d.ts +5 -0
  69. package/dist/runtime/attention.d.ts.map +1 -1
  70. package/dist/runtime/attention.js +14 -1
  71. package/dist/runtime/attentionDispatcher.d.ts +14 -2
  72. package/dist/runtime/attentionDispatcher.d.ts.map +1 -1
  73. package/dist/runtime/attentionDispatcher.js +127 -33
  74. package/dist/runtime/cli.js +5 -0
  75. package/dist/runtime/contract-manifest.json +1 -1
  76. package/dist/runtime/contract-manifest.sha256 +1 -1
  77. package/dist/runtime/engineBrokerCapabilities.d.ts +10 -0
  78. package/dist/runtime/engineBrokerCapabilities.d.ts.map +1 -1
  79. package/dist/runtime/engineBrokerCapabilities.js +10 -0
  80. package/dist/runtime/engineBrokerControlClient.d.ts +12 -1
  81. package/dist/runtime/engineBrokerControlClient.d.ts.map +1 -1
  82. package/dist/runtime/engineBrokerControlClient.js +139 -43
  83. package/dist/runtime/engineBrokerCredentialJournal.d.ts +2 -0
  84. package/dist/runtime/engineBrokerCredentialJournal.d.ts.map +1 -1
  85. package/dist/runtime/engineBrokerCredentialJournal.js +9 -0
  86. package/dist/runtime/engineBrokerInferenceProtocol.d.ts +3 -2
  87. package/dist/runtime/engineBrokerInferenceProtocol.d.ts.map +1 -1
  88. package/dist/runtime/engineBrokerInferenceProtocol.js +4 -4
  89. package/dist/runtime/engineBrokerMcpCallLog.d.ts +11 -0
  90. package/dist/runtime/engineBrokerMcpCallLog.d.ts.map +1 -1
  91. package/dist/runtime/engineBrokerMcpCallLog.js +13 -1
  92. package/dist/runtime/engineBrokerMcpFacade.d.ts +5 -2
  93. package/dist/runtime/engineBrokerMcpFacade.d.ts.map +1 -1
  94. package/dist/runtime/engineBrokerMcpFacade.js +5 -2
  95. package/dist/runtime/engineBrokerNativeClient.js +2 -2
  96. package/dist/runtime/engineBrokerProtocol.d.ts +42 -10
  97. package/dist/runtime/engineBrokerProtocol.d.ts.map +1 -1
  98. package/dist/runtime/engineBrokerProtocol.js +97 -14
  99. package/dist/runtime/engineBrokerSealLedger.d.ts.map +1 -1
  100. package/dist/runtime/engineBrokerSealLedger.js +9 -0
  101. package/dist/runtime/engineBrokerService.d.ts +8 -2
  102. package/dist/runtime/engineBrokerService.d.ts.map +1 -1
  103. package/dist/runtime/engineBrokerService.js +95 -37
  104. package/dist/runtime/engineBrokerServiceCli.js +1 -1
  105. package/dist/runtime/engineBrokerServiceConfig.d.ts +5 -0
  106. package/dist/runtime/engineBrokerServiceConfig.d.ts.map +1 -1
  107. package/dist/runtime/engineBrokerServiceConfig.js +47 -9
  108. package/dist/runtime/engineBrokerTurnRegistry.d.ts +1 -1
  109. package/dist/runtime/engineBrokerTurnRegistry.d.ts.map +1 -1
  110. package/dist/runtime/engineBrokerTurnRegistry.js +7 -6
  111. package/dist/runtime/engineDispatcher.d.ts +2 -0
  112. package/dist/runtime/engineDispatcher.d.ts.map +1 -1
  113. package/dist/runtime/engineDispatcher.js +14 -2
  114. package/dist/runtime/engineReadiness.js +1 -1
  115. package/dist/runtime/grokBrokerCredentialAuthority.d.ts +1 -0
  116. package/dist/runtime/grokBrokerCredentialAuthority.d.ts.map +1 -1
  117. package/dist/runtime/grokBrokerCredentialAuthority.js +48 -22
  118. package/dist/runtime/grokBrokerCredentialReader.d.ts +1 -0
  119. package/dist/runtime/grokBrokerCredentialReader.d.ts.map +1 -1
  120. package/dist/runtime/grokBrokerCredentialReader.js +2 -1
  121. package/dist/runtime/grokBrokerProjection.d.ts +9 -1
  122. package/dist/runtime/grokBrokerProjection.d.ts.map +1 -1
  123. package/dist/runtime/grokBrokerProjection.js +11 -4
  124. package/dist/runtime/grokBrokerProviderClock.d.ts +26 -0
  125. package/dist/runtime/grokBrokerProviderClock.d.ts.map +1 -0
  126. package/dist/runtime/grokBrokerProviderClock.js +133 -0
  127. package/dist/runtime/grokBrokerProxy.d.ts +17 -3
  128. package/dist/runtime/grokBrokerProxy.d.ts.map +1 -1
  129. package/dist/runtime/grokBrokerProxy.js +73 -9
  130. package/dist/runtime/grokBrokerProxyJson.d.ts +10 -0
  131. package/dist/runtime/grokBrokerProxyJson.d.ts.map +1 -0
  132. package/dist/runtime/grokBrokerProxyJson.js +31 -0
  133. package/dist/runtime/grokBrokerProxyRequest.d.ts.map +1 -1
  134. package/dist/runtime/grokBrokerProxyRequest.js +17 -6
  135. package/dist/runtime/grokBrokerRealmLease.js +1 -1
  136. package/dist/runtime/grokBrokerRefresh.js +1 -1
  137. package/dist/runtime/grokBrokerRunBudget.d.ts +20 -0
  138. package/dist/runtime/grokBrokerRunBudget.d.ts.map +1 -0
  139. package/dist/runtime/grokBrokerRunBudget.js +85 -0
  140. package/dist/runtime/grokBrokerSlot.d.ts +6 -0
  141. package/dist/runtime/grokBrokerSlot.d.ts.map +1 -0
  142. package/dist/runtime/grokBrokerSlot.js +21 -0
  143. package/dist/runtime/grokBrokerTaskClock.d.ts +32 -0
  144. package/dist/runtime/grokBrokerTaskClock.d.ts.map +1 -0
  145. package/dist/runtime/grokBrokerTaskClock.js +120 -0
  146. package/dist/runtime/grokBrokerTurnMeter.d.ts +55 -3
  147. package/dist/runtime/grokBrokerTurnMeter.d.ts.map +1 -1
  148. package/dist/runtime/grokBrokerTurnMeter.js +90 -4
  149. package/dist/runtime/grokBrokerWorkerConfig.d.ts +5 -2
  150. package/dist/runtime/grokBrokerWorkerConfig.d.ts.map +1 -1
  151. package/dist/runtime/grokBrokerWorkerConfig.js +22 -3
  152. package/dist/runtime/grokEngineBroker.d.ts +43 -3
  153. package/dist/runtime/grokEngineBroker.d.ts.map +1 -1
  154. package/dist/runtime/grokEngineBroker.js +159 -71
  155. package/dist/runtime/grokEngineBrokerTurn.d.ts +32 -8
  156. package/dist/runtime/grokEngineBrokerTurn.d.ts.map +1 -1
  157. package/dist/runtime/grokEngineBrokerTurn.js +204 -21
  158. package/dist/runtime/grokEngineBrokerTurnEnd.d.ts +88 -0
  159. package/dist/runtime/grokEngineBrokerTurnEnd.d.ts.map +1 -0
  160. package/dist/runtime/grokEngineBrokerTurnEnd.js +148 -0
  161. package/dist/runtime/grokInferenceProxy.d.ts.map +1 -1
  162. package/dist/runtime/grokInferenceProxy.js +3 -0
  163. package/dist/runtime/grokSubscriptionRealm.js +1 -1
  164. package/dist/runtime/grokWorkerAttestation.d.ts +9 -4
  165. package/dist/runtime/grokWorkerAttestation.d.ts.map +1 -1
  166. package/dist/runtime/grokWorkerAttestation.js +2 -2
  167. package/dist/runtime/grokWorkerHomeAttestation.d.ts +4 -2
  168. package/dist/runtime/grokWorkerHomeAttestation.d.ts.map +1 -1
  169. package/dist/runtime/grokWorkerHomeAttestation.js +10 -4
  170. package/dist/runtime/index.d.ts +7 -2
  171. package/dist/runtime/index.d.ts.map +1 -1
  172. package/dist/runtime/index.js +5 -1
  173. package/dist/runtime/native/daimon-engine-broker +0 -0
  174. package/dist/runtime/organizationRuntime.d.ts +3 -0
  175. package/dist/runtime/organizationRuntime.d.ts.map +1 -1
  176. package/dist/runtime/organizationRuntimeAdmission.d.ts +6 -0
  177. package/dist/runtime/organizationRuntimeAdmission.d.ts.map +1 -0
  178. package/dist/runtime/organizationRuntimeAdmission.js +22 -0
  179. package/dist/runtime/organizationRuntimeControl.d.ts +9 -0
  180. package/dist/runtime/organizationRuntimeControl.d.ts.map +1 -1
  181. package/dist/runtime/organizationRuntimeControl.js +72 -24
  182. package/dist/runtime/organizationRuntimeHost.d.ts.map +1 -1
  183. package/dist/runtime/organizationRuntimeHost.js +13 -4
  184. package/dist/runtime/organizationRuntimeParsing.d.ts.map +1 -1
  185. package/dist/runtime/organizationRuntimeParsing.js +4 -1
  186. package/dist/runtime/organizationRuntimeReadiness.d.ts.map +1 -1
  187. package/dist/runtime/organizationRuntimeReadiness.js +8 -0
  188. package/dist/runtime/organizationRuntimeRecording.d.ts +7 -0
  189. package/dist/runtime/organizationRuntimeRecording.d.ts.map +1 -0
  190. package/dist/runtime/organizationRuntimeRecording.js +58 -0
  191. package/dist/runtime/physicalReadiness.d.ts +12 -0
  192. package/dist/runtime/physicalReadiness.d.ts.map +1 -1
  193. package/dist/runtime/physicalReadiness.js +43 -9
  194. package/dist/runtime/productionAgentTools.d.ts.map +1 -1
  195. package/dist/runtime/productionAgentTools.js +13 -5
  196. package/dist/runtime/relocateRuntimeConfig.d.ts +14 -0
  197. package/dist/runtime/relocateRuntimeConfig.d.ts.map +1 -0
  198. package/dist/runtime/relocateRuntimeConfig.js +38 -0
  199. package/dist/runtime/schedule.d.ts.map +1 -1
  200. package/dist/runtime/schedule.js +12 -7
  201. package/dist/runtime/storeCoordination.d.ts +10 -0
  202. package/dist/runtime/storeCoordination.d.ts.map +1 -1
  203. package/dist/runtime/storeCoordination.js +23 -0
  204. package/dist/runtime/taskClock.d.ts +42 -0
  205. package/dist/runtime/taskClock.d.ts.map +1 -0
  206. package/dist/runtime/taskClock.js +102 -0
  207. package/dist/runtime/taskClockProcess.d.ts +17 -0
  208. package/dist/runtime/taskClockProcess.d.ts.map +1 -0
  209. package/dist/runtime/taskClockProcess.js +58 -0
  210. package/dist/runtime/turnRequestLedger.d.ts +0 -5
  211. package/dist/runtime/turnRequestLedger.d.ts.map +1 -1
  212. package/dist/runtime/turnRequestLedger.js +23 -21
  213. package/dist/runtime/wakeAcceptanceClaimDiagnostics.d.ts +34 -0
  214. package/dist/runtime/wakeAcceptanceClaimDiagnostics.d.ts.map +1 -0
  215. package/dist/runtime/wakeAcceptanceClaimDiagnostics.js +79 -0
  216. package/dist/runtime/wakeAcceptanceIndex.d.ts +55 -0
  217. package/dist/runtime/wakeAcceptanceIndex.d.ts.map +1 -0
  218. package/dist/runtime/wakeAcceptanceIndex.js +158 -0
  219. package/dist/runtime/wakeAcceptanceProcessIdentity.d.ts +9 -1
  220. package/dist/runtime/wakeAcceptanceProcessIdentity.d.ts.map +1 -1
  221. package/dist/runtime/wakeAcceptanceProcessIdentity.js +5 -1
  222. package/dist/runtime/wakeAcceptanceRecord.d.ts +2 -0
  223. package/dist/runtime/wakeAcceptanceRecord.d.ts.map +1 -1
  224. package/dist/runtime/wakeAcceptanceRecord.js +4 -2
  225. package/dist/runtime/wakeAcceptanceRetention.d.ts +25 -1
  226. package/dist/runtime/wakeAcceptanceRetention.d.ts.map +1 -1
  227. package/dist/runtime/wakeAcceptanceRetention.js +28 -2
  228. package/dist/runtime/wakeAcceptanceStore.d.ts +8 -8
  229. package/dist/runtime/wakeAcceptanceStore.d.ts.map +1 -1
  230. package/dist/runtime/wakeAcceptanceStore.js +66 -63
  231. package/dist/runtime/wakeFuse.d.ts +58 -3
  232. package/dist/runtime/wakeFuse.d.ts.map +1 -1
  233. package/dist/runtime/wakeFuse.js +106 -7
  234. package/dist/runtime/wakeMomentFs.d.ts +27 -0
  235. package/dist/runtime/wakeMomentFs.d.ts.map +1 -0
  236. package/dist/runtime/wakeMomentFs.js +223 -0
  237. package/dist/runtime/wakeMomentHistory.d.ts +26 -0
  238. package/dist/runtime/wakeMomentHistory.d.ts.map +1 -0
  239. package/dist/runtime/wakeMomentHistory.js +109 -0
  240. package/dist/runtime/wakeMomentIo.d.ts +22 -0
  241. package/dist/runtime/wakeMomentIo.d.ts.map +1 -0
  242. package/dist/runtime/wakeMomentIo.js +114 -0
  243. package/dist/runtime/wakeMomentRecorder.d.ts +33 -0
  244. package/dist/runtime/wakeMomentRecorder.d.ts.map +1 -0
  245. package/dist/runtime/wakeMomentRecorder.js +81 -0
  246. package/dist/runtime/wakeMomentRetention.d.ts +7 -0
  247. package/dist/runtime/wakeMomentRetention.d.ts.map +1 -0
  248. package/dist/runtime/wakeMomentRetention.js +143 -0
  249. package/dist/runtime/wakeMomentRows.d.ts +8 -0
  250. package/dist/runtime/wakeMomentRows.d.ts.map +1 -0
  251. package/dist/runtime/wakeMomentRows.js +66 -0
  252. package/dist/runtime/wakeMomentSnapshot.d.ts +56 -0
  253. package/dist/runtime/wakeMomentSnapshot.d.ts.map +1 -0
  254. package/dist/runtime/wakeMomentSnapshot.js +248 -0
  255. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"wakeAcceptanceProcessIdentity.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeAcceptanceProcessIdentity.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAC3L,qBAAa,8BAA+B,SAAQ,KAAK;IAAG,QAAQ,CAAC,IAAI,EAAG,iCAAiC,CAAU;;CAAmF;AAC1M,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,mBAAmB,GAAG,mBAAmB,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,mBAAmB,GAAG,mBAAmB,CAAC,GAAG,OAAO,CAAqH;AAC1S,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,YAAY,CAAC,CAAC,CAKvG;AACD,wBAAsB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3E"}
1
+ {"version":3,"file":"wakeAcceptanceProcessIdentity.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeAcceptanceProcessIdentity.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAC3L,KAAK,iBAAiB,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,YAAY,CAAC,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC,CAAC;AAC/J,qBAAa,8BAA+B,SAAQ,KAAK;IAE3C,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB;IAD/C,QAAQ,CAAC,IAAI,EAAG,iCAAiC,CAAU;gBACtC,MAAM,CAAC,EAAE,iBAAiB,YAAA;CAChD;AACD,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,mBAAmB,GAAG,mBAAmB,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,mBAAmB,GAAG,mBAAmB,CAAC,GAAG,OAAO,CAAqH;AAC1S,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,YAAY,CAAC,CAAC,CAKvG;AACD,wBAAsB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3E"}
@@ -1,7 +1,11 @@
1
1
  import { readFile, stat } from "node:fs/promises";
2
2
  export class WakeTransitionLockBlockedError extends Error {
3
+ detail;
3
4
  code = "offline_reconciliation_required";
4
- constructor() { super("wake transition lock requires offline reconciliation"); }
5
+ constructor(detail) {
6
+ super(`wake transition lock requires offline reconciliation${detail === undefined ? "" : `: step=${detail.step} assertion=transition_lock_namespace ${JSON.stringify(detail)}`}`);
7
+ this.detail = detail;
8
+ }
5
9
  }
6
10
  export function sameNamespace(left, right) { return left.pid_namespace_dev === right.pid_namespace_dev && left.pid_namespace_ino === right.pid_namespace_ino; }
7
11
  export async function currentProcessIdentity() {
@@ -6,6 +6,8 @@ export type StoredWakeAcceptanceRecord = Readonly<{
6
6
  request_digest: string;
7
7
  event: OrganizationRuntimeWakeAcceptanceRequest["event"];
8
8
  state: WakeReceiptState;
9
+ /** Set only through native scheduler acceptance; absent means a real delivery instant. */
10
+ native_schedule?: true;
9
11
  accepted_at: string;
10
12
  updated_at: string;
11
13
  claim_generation?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"wakeAcceptanceRecord.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeAcceptanceRecord.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,iCAAiC,EACtC,KAAK,wCAAwC,EAC7C,KAAK,oCAAoC,EACzC,KAAK,eAAe,EACpB,KAAK,gBAAgB,EAEtB,MAAM,0BAA0B,CAAC;AAElC,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IACrF,KAAK,EAAE,wCAAwC,CAAC,OAAO,CAAC,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAC;IAClF,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,eAAe,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CAChL,CAAC,CAAC;AAEH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,0BAA0B,GAAG,iCAAiC,CAEtG;AACD,wBAAgB,YAAY,CAAC,MAAM,EAAE,0BAA0B,GAAG,oCAAoC,CAErG;AACD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,0BAA0B,CA0BpF;AAMD,oFAAoF;AACpF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5D"}
1
+ {"version":3,"file":"wakeAcceptanceRecord.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeAcceptanceRecord.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,iCAAiC,EACtC,KAAK,wCAAwC,EAC7C,KAAK,oCAAoC,EACzC,KAAK,eAAe,EACpB,KAAK,gBAAgB,EAEtB,MAAM,0BAA0B,CAAC;AAElC,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IACrF,KAAK,EAAE,wCAAwC,CAAC,OAAO,CAAC,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAC;IAClF,0FAA0F;IAC1F,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,eAAe,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CAChL,CAAC,CAAC;AAEH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,0BAA0B,GAAG,iCAAiC,CAEtG;AACD,wBAAgB,YAAY,CAAC,MAAM,EAAE,0BAA0B,GAAG,oCAAoC,CAErG;AACD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,0BAA0B,CA2BpF;AAMD,oFAAoF;AACpF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5D"}
@@ -10,10 +10,12 @@ export function parseStoredWakeAcceptance(value) {
10
10
  if (value === null || typeof value !== "object" || Array.isArray(value))
11
11
  throw new Error("wake acceptance record is invalid");
12
12
  const record = value;
13
- const keys = ["acceptance_id", "agent_id", "delivery_id", "request_digest", "event", "state", "accepted_at", "updated_at", "claim_generation", "execution_id", "deferred", "execution_error", "code", "text"];
13
+ const keys = ["acceptance_id", "agent_id", "delivery_id", "request_digest", "event", "state", "accepted_at", "updated_at", "claim_generation", "execution_id", "deferred", "execution_error", "code", "text", "native_schedule"];
14
14
  if (Object.keys(record).some((key) => !keys.includes(key)))
15
15
  throw new Error("wake acceptance record is invalid");
16
16
  const parsed = parseWakeAcceptanceRequest({ token: undefined, agent_id: string(record.agent_id), delivery_id: string(record.delivery_id), event: record.event });
17
+ if (record.native_schedule !== undefined && (record.native_schedule !== true || parsed.event.kind !== "schedule"))
18
+ throw new Error("wake acceptance schedule provenance is invalid");
17
19
  const state = string(record.state);
18
20
  if (!["accepted", "running", "completed", "failed", "stopped"].includes(state))
19
21
  throw new Error("wake acceptance record is invalid");
@@ -42,7 +44,7 @@ export function parseStoredWakeAcceptance(value) {
42
44
  throw new Error("wake acceptance record is invalid");
43
45
  if (string(record.request_digest) !== wakeAcceptanceDigest(parsed) || !uuid(string(record.acceptance_id)))
44
46
  throw new Error("wake acceptance record is invalid");
45
- return { acceptance_id: string(record.acceptance_id), agent_id: parsed.agent_id, delivery_id: parsed.delivery_id, request_digest: string(record.request_digest), event: parsed.event, state, accepted_at: timestamp(record.accepted_at), updated_at: timestamp(record.updated_at), ...(claimGeneration === undefined ? {} : { claim_generation: claimGeneration }), ...(executionId === undefined ? {} : { execution_id: executionId }), ...(record.deferred === undefined ? {} : { deferred: record.deferred }), ...(code === undefined ? {} : { code }), ...(completionText === undefined ? {} : { text: completionText }), ...(executionError === undefined ? {} : { execution_error: executionError }) };
47
+ return { acceptance_id: string(record.acceptance_id), agent_id: parsed.agent_id, delivery_id: parsed.delivery_id, request_digest: string(record.request_digest), event: parsed.event, state, accepted_at: timestamp(record.accepted_at), updated_at: timestamp(record.updated_at), ...(record.native_schedule === true ? { native_schedule: true } : {}), ...(claimGeneration === undefined ? {} : { claim_generation: claimGeneration }), ...(executionId === undefined ? {} : { execution_id: executionId }), ...(record.deferred === undefined ? {} : { deferred: record.deferred }), ...(code === undefined ? {} : { code }), ...(completionText === undefined ? {} : { text: completionText }), ...(executionError === undefined ? {} : { execution_error: executionError }) };
46
48
  }
47
49
  function string(value) { if (typeof value !== "string")
48
50
  throw new Error("wake acceptance record is invalid"); return value; }
@@ -1,12 +1,36 @@
1
1
  export declare const TERMINAL_RECEIPT_IDEMPOTENCY_HORIZON = 2048;
2
2
  export declare const WAKE_ACCEPTANCE_COMPACTION_THRESHOLD = 2112;
3
3
  export declare const MAX_WAKE_ACCEPTANCE_RECORDS = 2176;
4
+ /**
5
+ * How long a delivery may sit in `accepted` before the store stops it.
6
+ *
7
+ * Inbox agents return every delivery they did not dispose of to `accepted`
8
+ * (deferred), and a failed execution keeps its batch for retry. Nothing ever
9
+ * ended either, so by 2026-10-05 213 deliveries up to two weeks old sat in the
10
+ * queue, were re-offered on every wake, and kept the store at its bound. A
11
+ * day is longer than any delivery stays actionable in a daily organization: at
12
+ * two days, deliveries from 2026-10-05 were still being retried — and failing —
13
+ * through 10-07's edition. The dispatcher stops an expired delivery
14
+ * `queued_wake_stopped` the first time it meets one and says so on stderr
15
+ * (`attentionDispatcher.ts`), rather than leaving it hidden until compaction.
16
+ */
17
+ export declare const STALE_QUEUED_DELIVERY_MS: number;
4
18
  export type RetentionCandidate = Readonly<{
5
19
  file: string;
6
20
  state: "accepted" | "running" | "completed" | "failed" | "stopped";
7
21
  updatedAt: string;
22
+ acceptedAt?: string;
8
23
  acceptanceId: string;
9
24
  }>;
10
- /** Active work is never eligible; the newest terminal receipt horizon survives. */
25
+ /** Queued, unclaimed deliveries accepted before the staleness horizon. Running or claimed work never qualifies. */
26
+ export declare function staleQueuedFilesToStop(records: readonly (RetentionCandidate & Readonly<{
27
+ claimed: boolean;
28
+ }>)[], nowMs: number): readonly string[];
29
+ /**
30
+ * Active work is never eligible. The newest terminal receipts survive up to the
31
+ * idempotency horizon, but never so many that active work plus kept receipts
32
+ * still sits at the compaction threshold: a horizon that ignores active work
33
+ * lets parked deliveries hold the store at its bound with nothing to compact.
34
+ */
11
35
  export declare function terminalFilesToCompact(records: readonly RetentionCandidate[]): readonly string[];
12
36
  //# sourceMappingURL=wakeAcceptanceRetention.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"wakeAcceptanceRetention.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeAcceptanceRetention.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oCAAoC,OAAQ,CAAC;AAC1D,eAAO,MAAM,oCAAoC,OAAQ,CAAC;AAC1D,eAAO,MAAM,2BAA2B,OAAQ,CAAC;AAEjD,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC;AAEH,mFAAmF;AACnF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,GAAG,SAAS,MAAM,EAAE,CAMhG"}
1
+ {"version":3,"file":"wakeAcceptanceRetention.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeAcceptanceRetention.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oCAAoC,OAAQ,CAAC;AAC1D,eAAO,MAAM,oCAAoC,OAAQ,CAAC;AAC1D,eAAO,MAAM,2BAA2B,OAAQ,CAAC;AACjD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,QAAmB,CAAC;AAEzD,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC;AAEH,mHAAmH;AACnH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,SAAS,CAAC,kBAAkB,GAAG,QAAQ,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAIlJ;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,GAAG,SAAS,MAAM,EAAE,CAOhG"}
@@ -1,12 +1,38 @@
1
1
  export const TERMINAL_RECEIPT_IDEMPOTENCY_HORIZON = 2_048;
2
2
  export const WAKE_ACCEPTANCE_COMPACTION_THRESHOLD = 2_112;
3
3
  export const MAX_WAKE_ACCEPTANCE_RECORDS = 2_176;
4
- /** Active work is never eligible; the newest terminal receipt horizon survives. */
4
+ /**
5
+ * How long a delivery may sit in `accepted` before the store stops it.
6
+ *
7
+ * Inbox agents return every delivery they did not dispose of to `accepted`
8
+ * (deferred), and a failed execution keeps its batch for retry. Nothing ever
9
+ * ended either, so by 2026-10-05 213 deliveries up to two weeks old sat in the
10
+ * queue, were re-offered on every wake, and kept the store at its bound. A
11
+ * day is longer than any delivery stays actionable in a daily organization: at
12
+ * two days, deliveries from 2026-10-05 were still being retried — and failing —
13
+ * through 10-07's edition. The dispatcher stops an expired delivery
14
+ * `queued_wake_stopped` the first time it meets one and says so on stderr
15
+ * (`attentionDispatcher.ts`), rather than leaving it hidden until compaction.
16
+ */
17
+ export const STALE_QUEUED_DELIVERY_MS = 24 * 60 * 60_000;
18
+ /** Queued, unclaimed deliveries accepted before the staleness horizon. Running or claimed work never qualifies. */
19
+ export function staleQueuedFilesToStop(records, nowMs) {
20
+ return records
21
+ .filter((record) => record.state === "accepted" && !record.claimed && record.acceptedAt !== undefined && Date.parse(record.acceptedAt) <= nowMs - STALE_QUEUED_DELIVERY_MS)
22
+ .map((record) => record.file);
23
+ }
24
+ /**
25
+ * Active work is never eligible. The newest terminal receipts survive up to the
26
+ * idempotency horizon, but never so many that active work plus kept receipts
27
+ * still sits at the compaction threshold: a horizon that ignores active work
28
+ * lets parked deliveries hold the store at its bound with nothing to compact.
29
+ */
5
30
  export function terminalFilesToCompact(records) {
6
31
  if (records.length < WAKE_ACCEPTANCE_COMPACTION_THRESHOLD)
7
32
  return [];
8
33
  const terminal = records
9
34
  .filter((record) => record.state === "completed" || record.state === "failed" || record.state === "stopped")
10
35
  .sort((left, right) => right.updatedAt.localeCompare(left.updatedAt) || right.acceptanceId.localeCompare(left.acceptanceId));
11
- return terminal.slice(TERMINAL_RECEIPT_IDEMPOTENCY_HORIZON).map((record) => record.file);
36
+ const keep = Math.max(0, Math.min(TERMINAL_RECEIPT_IDEMPOTENCY_HORIZON, WAKE_ACCEPTANCE_COMPACTION_THRESHOLD - 1 - (records.length - terminal.length)));
37
+ return terminal.slice(keep).map((record) => record.file);
12
38
  }
@@ -43,10 +43,12 @@ export declare class WakeAcceptanceStore {
43
43
  private readonly ownerLiveness;
44
44
  private readonly afterFinalLockAssertion?;
45
45
  private mutations;
46
- private readonly acceptanceFiles;
46
+ private readonly index;
47
+ private onRecordRead?;
48
+ private claimTransitionLockTiming?;
47
49
  private constructor();
48
50
  static open(root: string, options?: WakeAcceptanceStoreTestOptions): Promise<WakeAcceptanceStore>;
49
- accept(request: OrganizationRuntimeWakeAcceptanceRequest): Promise<{
51
+ accept(request: OrganizationRuntimeWakeAcceptanceRequest, nativeSchedule?: boolean): Promise<{
50
52
  readonly record: Stored;
51
53
  readonly created: boolean;
52
54
  }>;
@@ -56,10 +58,10 @@ export declare class WakeAcceptanceStore {
56
58
  /** Internal availability view; diagnostics never enter the public receipt wire. */
57
59
  activityWithExecutionErrors(): Promise<readonly ActivityRow[]>;
58
60
  private activityRows;
59
- recoverable(agentIds: ReadonlySet<string>): Promise<readonly Stored[]>;
61
+ recoverable(agentIds: ReadonlySet<string>, onStale?: (record: Stored) => void): Promise<readonly Stored[]>;
60
62
  transition(acceptanceId: string, state: WakeReceiptState, code?: WakeReceiptCode): Promise<Stored>;
61
63
  /** Fuse race seam: never stops a record that was claimed after enumeration. */
62
- transitionAcceptedToStopped(acceptanceId: string): Promise<Stored>;
64
+ transitionAcceptedToStopped(acceptanceId: string, code?: "host_stopping" | "queued_wake_stopped"): Promise<Stored>;
63
65
  acquireClaim(acceptanceId: string, ownerId: string, acceptanceIds?: readonly string[], executionId?: string): Promise<WakeExecutionClaimResult>;
64
66
  claimHeartbeatIntervalMs(): number;
65
67
  renewClaim(acceptanceId: string, claim: WakeExecutionClaim): Promise<WakeExecutionClaim>;
@@ -99,14 +101,12 @@ export declare class WakeAcceptanceStore {
99
101
  private verify;
100
102
  }
101
103
  export declare class WakeInboxFullError extends Error {
102
- constructor();
104
+ constructor(message?: string);
103
105
  }
104
106
  export declare class WakeAcceptanceConflictError extends Error {
105
107
  constructor();
106
108
  }
107
- export declare class WakeExecutionClaimLostError extends Error {
108
- constructor();
109
- }
109
+ export { WakeExecutionClaimLostError, WakeTransitionLockContentionError } from "./wakeAcceptanceClaimDiagnostics.js";
110
110
  /** A container boundary requires deployment-authorized offline reconciliation. */
111
111
  export { WakeTransitionLockBlockedError } from "./wakeAcceptanceProcessIdentity.js";
112
112
  export { publicAcceptance } from "./wakeAcceptanceRecord.js";
@@ -1 +1 @@
1
- {"version":3,"file":"wakeAcceptanceStore.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeAcceptanceStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyF,KAAK,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAKhK,OAAO,EAIL,KAAK,wCAAwC,EAC7C,KAAK,oCAAoC,EACzC,KAAK,eAAe,EACpB,KAAK,gBAAgB,EAEtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAqF,KAAK,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAI/J,KAAK,MAAM,GAAG,0BAA0B,CAAC;AACzC,KAAK,WAAW,GAAG,oCAAoC,GAAG,QAAQ,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAC3I,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAC1L,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,CAAC,GAAG,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,QAAQ,CAAC;IAAE,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AAEpL,MAAM,MAAM,8BAA8B,GAAG,QAAQ,CAAC;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,uBAAuB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,YAAY,CAAC,CAAC,CAAA;CAAE,CAAC,CAAC;AAIvS,qFAAqF;AACrF,qBAAa,mBAAmB;IAGV,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAU,OAAO,CAAC,QAAQ,CAAC,SAAS;IAAoC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAAqB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAAyB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAAU,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAgB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAAmD,OAAO,CAAC,QAAQ,CAAC,aAAa;IAA8C,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IAF5d,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA6B;IAC7D,OAAO;WACM,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,8BAAmC,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAsB3G,MAAM,CAAC,OAAO,EAAE,wCAAwC,GAAG,OAAO,CAAC;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;YAG5G,SAAS;IA6BjB,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,oCAAoC,GAAG,SAAS,CAAC;IAIvF,QAAQ,IAAI,OAAO,CAAC,SAAS,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,CAAC;IAC1E,mFAAmF;IAC7E,2BAA2B,IAAI,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC;YACtD,YAAY;IAcpB,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC;IAY5E,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAGlG,+EAA+E;IAC/E,2BAA2B,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUlE,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IA8B/I,wBAAwB,IAAI,MAAM;IAClC,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAexF,+FAA+F;IAC/F,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,eAAe,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,eAAe,CAAC,EAAE,OAAO,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAmCnR,YAAY,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAatD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAS/B,aAAa;IAQrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAC5B,OAAO,CAAC,SAAS;YAKH,kBAAkB;YAWlB,mBAAmB;IAKjC,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;YACD,qBAAqB;YAerB,oBAAoB;YAIpB,qBAAqB;IAKnC,OAAO,CAAC,OAAO;YAGD,KAAK;YAOL,UAAU;YACV,YAAY;YACZ,IAAI;YAOJ,iBAAiB;YACjB,SAAS;YAcT,gBAAgB;YAChB,QAAQ;YAWR,oBAAoB;YAOpB,sBAAsB;YAWtB,QAAQ;YAIR,OAAO;YACP,YAAY;YAIZ,MAAM;CAMrB;AACD,qBAAa,kBAAmB,SAAQ,KAAK;;CAAmG;AAChJ,qBAAa,2BAA4B,SAAQ,KAAK;;CAAoF;AAC1I,qBAAa,2BAA4B,SAAQ,KAAK;;CAA8D;AACpH,kFAAkF;AAClF,OAAO,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"wakeAcceptanceStore.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeAcceptanceStore.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { WakeExecutionClaimLostError, readExpectedClaim, waitForClaimTransitionLock } from "./wakeAcceptanceClaimDiagnostics.js";
1
2
  import { sameNamespace, currentProcessIdentity, processIsAlive, WakeTransitionLockBlockedError } from "./wakeAcceptanceProcessIdentity.js";
2
3
  import { constants } from "node:fs";
3
4
  import { link, lstat, open, readFile, readdir, realpath, rename, unlink } from "node:fs/promises";
@@ -6,8 +7,9 @@ import { createHash, randomUUID } from "node:crypto";
6
7
  import { MAX_WAKE_ACCEPTANCE_RECORD_BYTES, sanitizeWakeCompletionText, wakeAcceptanceDigest } from "./wakeAcceptanceTypes.js";
7
8
  import { sanitizeExecutionError, parseStoredWakeAcceptance, publicStatus } from "./wakeAcceptanceRecord.js";
8
9
  import { assertOfflineReconciliationLeaseAvailable } from "./wakeAcceptanceReconciliation.js";
9
- import { acquireHostRegistration, releaseHostRegistration } from "./storeCoordination.js";
10
- import { MAX_WAKE_ACCEPTANCE_RECORDS, terminalFilesToCompact } from "./wakeAcceptanceRetention.js";
10
+ import { acquireHostRegistration, pruneDeadHostRegistrations, releaseHostRegistration } from "./storeCoordination.js";
11
+ import { WakeAcceptanceIndex } from "./wakeAcceptanceIndex.js";
12
+ import { MAX_WAKE_ACCEPTANCE_RECORDS, WAKE_ACCEPTANCE_COMPACTION_THRESHOLD, staleQueuedFilesToStop, terminalFilesToCompact } from "./wakeAcceptanceRetention.js";
11
13
  const DEFAULT_CLAIM_TTL_MS = 240_000;
12
14
  /** Durable, private idempotency authority; callers must pre-create its 0700 root. */
13
15
  export class WakeAcceptanceStore {
@@ -21,7 +23,9 @@ export class WakeAcceptanceStore {
21
23
  ownerLiveness;
22
24
  afterFinalLockAssertion;
23
25
  mutations = Promise.resolve();
24
- acceptanceFiles = new Map();
26
+ index;
27
+ onRecordRead;
28
+ claimTransitionLockTiming;
25
29
  constructor(root, directory, identity, registration, claimTtlMs, now, owner, ownerLiveness, afterFinalLockAssertion) {
26
30
  this.root = root;
27
31
  this.directory = directory;
@@ -32,6 +36,8 @@ export class WakeAcceptanceStore {
32
36
  this.owner = owner;
33
37
  this.ownerLiveness = ownerLiveness;
34
38
  this.afterFinalLockAssertion = afterFinalLockAssertion;
39
+ this.index = new WakeAcceptanceIndex(root, { directoryStat: async () => await this.directory.stat({ bigint: true }), files: async () => await this.files(), readId: async (file) => (await this.read(file)).acceptance_id, fileStat: async (file) => await lstat(file, { bigint: true }).catch((error) => { if (error.code === "ENOENT")
40
+ return undefined; throw error; }) }, () => BigInt(this.now()) * 1000000n);
35
41
  }
36
42
  static async open(root, options = {}) {
37
43
  const claimTtlMs = options.claimTtlMs ?? DEFAULT_CLAIM_TTL_MS;
@@ -53,23 +59,27 @@ export class WakeAcceptanceStore {
53
59
  if (!same(identity(before), identity(after)))
54
60
  throw new Error("wake acceptance store changed during validation");
55
61
  const registration = await acquireHostRegistration(real, directory, owner);
56
- return new WakeAcceptanceStore(real, directory, identity(before), registration, claimTtlMs, options.nowForTest ?? Date.now, owner, options.ownerLiveness ?? processIsAlive, options.afterFinalLockAssertion);
62
+ await pruneDeadHostRegistrations(real, directory, registration, options.ownerLiveness ?? processIsAlive);
63
+ const store = new WakeAcceptanceStore(real, directory, identity(before), registration, claimTtlMs, options.nowForTest ?? Date.now, owner, options.ownerLiveness ?? processIsAlive, options.afterFinalLockAssertion);
64
+ store.claimTransitionLockTiming = options.claimTransitionLockTimingForTest;
65
+ store.onRecordRead = options.onRecordReadForTest;
66
+ return store;
57
67
  }
58
68
  catch (error) {
59
69
  await directory.close().catch(() => undefined);
60
70
  throw error;
61
71
  }
62
72
  }
63
- accept(request) {
64
- return this.serialize(async () => await this.acceptNow(request));
73
+ accept(request, nativeSchedule = false) {
74
+ return this.serialize(async () => await this.acceptNow(request, nativeSchedule));
65
75
  }
66
- async acceptNow(request) {
76
+ async acceptNow(request, nativeSchedule) {
67
77
  await this.verify();
68
78
  const request_digest = wakeAcceptanceDigest(request);
69
79
  const target = this.fileFor(request.agent_id, request.delivery_id);
70
80
  const existing = await this.readOptional(target);
71
81
  if (existing !== undefined) {
72
- if (existing.request_digest !== request_digest)
82
+ if (existing.request_digest !== request_digest || existing.native_schedule !== (nativeSchedule ? true : undefined))
73
83
  throw new WakeAcceptanceConflictError();
74
84
  return { record: existing, created: false };
75
85
  }
@@ -77,7 +87,7 @@ export class WakeAcceptanceStore {
77
87
  if ((await this.files()).length >= MAX_WAKE_ACCEPTANCE_RECORDS)
78
88
  throw new WakeInboxFullError();
79
89
  const now = new Date().toISOString();
80
- const record = { acceptance_id: randomUUID(), agent_id: request.agent_id, delivery_id: request.delivery_id, request_digest, event: request.event, state: "accepted", accepted_at: now, updated_at: now };
90
+ const record = { acceptance_id: randomUUID(), agent_id: request.agent_id, delivery_id: request.delivery_id, request_digest, event: request.event, state: "accepted", accepted_at: now, updated_at: now, ...(nativeSchedule ? { native_schedule: true } : {}) };
81
91
  const temporary = path.join(this.root, `.pending-${randomUUID()}`);
82
92
  try {
83
93
  await this.writeNew(temporary, record);
@@ -88,12 +98,12 @@ export class WakeAcceptanceStore {
88
98
  if (error.code !== "EEXIST")
89
99
  throw error;
90
100
  const winner = await this.read(target);
91
- if (winner.request_digest !== request_digest)
101
+ if (winner.request_digest !== request_digest || winner.native_schedule !== (nativeSchedule ? true : undefined))
92
102
  throw new WakeAcceptanceConflictError();
93
103
  return { record: winner, created: false };
94
104
  }
95
105
  await this.directory.sync();
96
- this.acceptanceFiles.set(record.acceptance_id, target);
106
+ this.index.set(record.acceptance_id, target);
97
107
  return { record, created: true };
98
108
  }
99
109
  finally {
@@ -123,7 +133,7 @@ export class WakeAcceptanceStore {
123
133
  ...(includeExecutionErrors && record.execution_error !== undefined ? { execution_error: record.execution_error } : {}) };
124
134
  });
125
135
  }
126
- async recoverable(agentIds) {
136
+ async recoverable(agentIds, onStale) {
127
137
  const result = [];
128
138
  for (const file of await this.files()) {
129
139
  const record = await this.read(path.join(this.root, file));
@@ -131,7 +141,12 @@ export class WakeAcceptanceStore {
131
141
  throw new Error("wake acceptance store contains an unknown agent authority");
132
142
  if (record.state === "accepted" || record.state === "running") {
133
143
  const claim = await this.readClaimOptional(this.claimFor(record));
134
- result.push(!record.deferred && record.execution_id === undefined && claim?.acceptance_ids?.includes(record.acceptance_id) && claim.execution_id !== undefined ? { ...record, execution_id: claim.execution_id } : record);
144
+ // A long-parked delivery is no longer offered: it would head every batch ahead of today's mail. Compaction stops it.
145
+ if (staleQueuedFilesToStop([{ file, state: record.state, updatedAt: record.updated_at, acceptedAt: record.accepted_at, acceptanceId: record.acceptance_id, claimed: claim !== undefined && !expired(claim, this.now()) }], this.now()).length) {
146
+ onStale?.(record);
147
+ continue;
148
+ }
149
+ result.push(!record.deferred && record.execution_id === undefined && record.execution_error === undefined && claim?.acceptance_ids?.includes(record.acceptance_id) && claim.execution_id !== undefined ? { ...record, execution_id: claim.execution_id } : record);
135
150
  }
136
151
  }
137
152
  return result.sort((left, right) => left.accepted_at.localeCompare(right.accepted_at) || left.acceptance_id.localeCompare(right.acceptance_id));
@@ -140,13 +155,14 @@ export class WakeAcceptanceStore {
140
155
  return this.serialize(async () => await this.transitionNow(acceptanceId, state, code));
141
156
  }
142
157
  /** Fuse race seam: never stops a record that was claimed after enumeration. */
143
- transitionAcceptedToStopped(acceptanceId) {
158
+ transitionAcceptedToStopped(acceptanceId, code = "host_stopping") {
144
159
  return this.serialize(async () => {
145
160
  const target = await this.pathForAcceptanceId(acceptanceId);
146
161
  const prior = await this.read(target);
147
- if (prior.state !== "accepted")
162
+ const claim = prior.state === "accepted" ? await this.readClaimOptional(this.claimFor(prior)) : undefined;
163
+ if (prior.state !== "accepted" || (claim !== undefined && !expired(claim, this.now())))
148
164
  return prior;
149
- const record = { ...prior, state: "stopped", code: "host_stopping", updated_at: new Date().toISOString() };
165
+ const record = { ...prior, state: "stopped", code, updated_at: new Date().toISOString() };
150
166
  await this.replace(target, record);
151
167
  return record;
152
168
  });
@@ -216,13 +232,9 @@ export class WakeAcceptanceStore {
216
232
  const record = await this.findByAcceptanceId(acceptanceId);
217
233
  if (record === undefined)
218
234
  throw new Error("wake acceptance receipt is unavailable");
219
- const lock = await this.acquireTransitionLock(record, claim.owner_id);
220
- if (lock === undefined)
221
- throw new WakeExecutionClaimLostError();
235
+ const lock = await waitForClaimTransitionLock(() => this.acquireTransitionLock(record, claim.owner_id), () => this.readLockOptional(this.lockFor(record)), acceptanceId, claim, "renew", this.claimTransitionLockTiming);
222
236
  try {
223
- const current = await this.readClaim(this.claimFor(record));
224
- if (!(current.acceptance_id === acceptanceId || current.acceptance_ids?.includes(acceptanceId)) || current.acceptance_id !== claim.acceptance_id || current.owner_id !== claim.owner_id || current.generation !== claim.generation || current.expires_at !== claim.expires_at || expired(current, this.now()))
225
- throw new WakeExecutionClaimLostError();
237
+ const current = await readExpectedClaim(() => this.readClaim(this.claimFor(record)), acceptanceId, claim, "renew", this.now, lock);
226
238
  const renewed = { ...current, expires_at: new Date(this.now() + this.claimTtlMs).toISOString() };
227
239
  await this.replaceValue(this.claimFor(record), renewed);
228
240
  return renewed;
@@ -240,24 +252,22 @@ export class WakeAcceptanceStore {
240
252
  const initial = await this.findByAcceptanceId(acceptanceId);
241
253
  if (initial === undefined)
242
254
  throw new Error("wake acceptance receipt is unavailable");
243
- const lock = await this.acquireTransitionLock(initial, claim.owner_id);
244
- if (lock === undefined)
245
- throw new WakeExecutionClaimLostError();
255
+ const lock = await waitForClaimTransitionLock(() => this.acquireTransitionLock(initial, claim.owner_id), () => this.readLockOptional(this.lockFor(initial)), acceptanceId, claim, `transition:${state}`, this.claimTransitionLockTiming);
246
256
  try {
247
- let record = await this.transitionNowClaimed(acceptanceId, claim);
257
+ let record = await this.transitionNowClaimed(acceptanceId, claim, `transition:${state}:initial`, lock);
248
258
  if (isTerminal(record.state))
249
259
  return record;
250
260
  if (state !== "running" && record.claim_generation !== claim.generation)
251
- throw new WakeExecutionClaimLostError();
252
- await this.assertTransitionLock(record, lock);
253
- record = await this.transitionNowClaimed(acceptanceId, claim);
261
+ throw new WakeExecutionClaimLostError({ step: `transition:${state}`, assertion: "record_claim_generation", acceptance_id: acceptanceId, expected: claim.generation, current: record.claim_generation ?? null, lock });
262
+ await this.assertTransitionLock(record, lock, `transition:${state}`);
263
+ record = await this.transitionNowClaimed(acceptanceId, claim, `transition:${state}:final`, lock);
254
264
  if (isTerminal(record.state))
255
265
  return record;
256
266
  if (state !== "running" && record.claim_generation !== claim.generation)
257
- throw new WakeExecutionClaimLostError();
258
- await this.assertTransitionLock(record, lock);
267
+ throw new WakeExecutionClaimLostError({ step: `transition:${state}`, assertion: "record_claim_generation", acceptance_id: acceptanceId, expected: claim.generation, current: record.claim_generation ?? null, lock });
268
+ await this.assertTransitionLock(record, lock, `transition:${state}`);
259
269
  await this.afterFinalLockAssertion?.();
260
- await this.assertTransitionLock(record, lock);
270
+ await this.assertTransitionLock(record, lock, `transition:${state}:before_write`);
261
271
  const target = this.fileFor(record.agent_id, record.delivery_id);
262
272
  // The code explains the transition that produced the CURRENT state, so a
263
273
  // transition that names none clears it. While codes existed only on terminal
@@ -285,14 +295,12 @@ export class WakeAcceptanceStore {
285
295
  return this.serialize(async () => {
286
296
  const record = await this.findByAcceptanceId(claim.acceptance_id);
287
297
  if (!record)
288
- throw new WakeExecutionClaimLostError();
289
- const lock = await this.acquireTransitionLock(record, claim.owner_id);
290
- if (!lock)
291
- throw new WakeExecutionClaimLostError();
298
+ throw new WakeExecutionClaimLostError({ step: "release", assertion: "record_missing", acceptance_id: claim.acceptance_id, expected: claim, current: null });
299
+ const lock = await waitForClaimTransitionLock(() => this.acquireTransitionLock(record, claim.owner_id), () => this.readLockOptional(this.lockFor(record)), claim.acceptance_id, claim, "release", this.claimTransitionLockTiming);
292
300
  try {
293
301
  const current = await this.readClaimOptional(this.claimFor(record));
294
302
  if (current?.generation !== claim.generation || current.owner_id !== claim.owner_id)
295
- throw new WakeExecutionClaimLostError();
303
+ throw new WakeExecutionClaimLostError({ step: "release", assertion: "claim_identity", acceptance_id: claim.acceptance_id, expected: claim, current: current ?? null, lock });
296
304
  await unlink(this.claimFor(record));
297
305
  await this.directory.sync();
298
306
  }
@@ -329,16 +337,8 @@ export class WakeAcceptanceStore {
329
337
  async findByAcceptanceId(acceptanceId) {
330
338
  if (!uuid(acceptanceId))
331
339
  return undefined;
332
- const known = this.acceptanceFiles.get(acceptanceId);
333
- if (known !== undefined)
334
- return await this.readOptional(known);
335
- for (const file of await this.files()) {
336
- const record = await this.read(path.join(this.root, file));
337
- this.acceptanceFiles.set(record.acceptance_id, path.join(this.root, file));
338
- if (record.acceptance_id === acceptanceId)
339
- return record;
340
- }
341
- return undefined;
340
+ await this.verify();
341
+ return await this.index.find(acceptanceId, async (file) => await this.readOptional(file));
342
342
  }
343
343
  async pathForAcceptanceId(acceptanceId) {
344
344
  const record = await this.findByAcceptanceId(acceptanceId);
@@ -352,7 +352,7 @@ export class WakeAcceptanceStore {
352
352
  const target = this.lockFor(record);
353
353
  const current = await this.readLockOptional(target);
354
354
  if (current !== undefined && !sameNamespace(current, this.owner))
355
- throw new WakeTransitionLockBlockedError();
355
+ throw new WakeTransitionLockBlockedError({ step: "acquire_transition_lock", acceptance_id: record.acceptance_id, expected: this.owner, current });
356
356
  if (current !== undefined && await this.ownerLiveness(current))
357
357
  return undefined;
358
358
  if (current !== undefined) {
@@ -378,10 +378,10 @@ export class WakeAcceptanceStore {
378
378
  await unlink(temporary).catch(() => undefined);
379
379
  }
380
380
  }
381
- async assertTransitionLock(record, lock) {
382
- const current = await this.readLock(this.lockFor(record)).catch(() => { throw new WakeExecutionClaimLostError(); });
381
+ async assertTransitionLock(record, lock, step) {
382
+ const current = await this.readLock(this.lockFor(record)).catch((cause) => { throw new WakeExecutionClaimLostError({ step, assertion: "transition_lock_read", acceptance_id: record.acceptance_id, expected: lock, current: null }, cause); });
383
383
  if (current.owner_id !== lock.owner_id || current.generation !== lock.generation || current.pid !== lock.pid || current.process_start !== lock.process_start || current.boot_id !== lock.boot_id || !sameNamespace(current, lock))
384
- throw new WakeExecutionClaimLostError();
384
+ throw new WakeExecutionClaimLostError({ step, assertion: "transition_lock_identity", acceptance_id: record.acceptance_id, expected: lock, current });
385
385
  }
386
386
  async releaseTransitionLock(record, lock) {
387
387
  const target = this.lockFor(record);
@@ -399,7 +399,7 @@ export class WakeAcceptanceStore {
399
399
  const entries = await readdir(this.root);
400
400
  const files = entries.filter((entry) => /^[a-f0-9]{64}\.json$/.test(entry));
401
401
  if (files.length > MAX_WAKE_ACCEPTANCE_RECORDS || entries.length > MAX_WAKE_ACCEPTANCE_RECORDS + 128)
402
- throw new Error("wake acceptance store exceeds its bounded record limit");
402
+ throw new WakeInboxFullError("wake acceptance store exceeds its bounded record limit");
403
403
  return files;
404
404
  }
405
405
  async claimFiles() { return (await readdir(this.root)).filter((entry) => /^[a-f0-9]{64}\.agent-claim$/.test(entry)); }
@@ -415,6 +415,7 @@ export class WakeAcceptanceStore {
415
415
  const entry = await lstat(file);
416
416
  if (!entry.isFile() || entry.isSymbolicLink() || entry.uid !== process.getuid?.() || (entry.mode & 0o777) !== 0o600 || entry.size > MAX_WAKE_ACCEPTANCE_RECORD_BYTES)
417
417
  throw new Error("wake acceptance record is unsafe");
418
+ this.onRecordRead?.(file);
418
419
  const bytes = await readFile(file);
419
420
  if (bytes.length > MAX_WAKE_ACCEPTANCE_RECORD_BYTES)
420
421
  throw new Error("wake acceptance record exceeds its bound");
@@ -471,25 +472,29 @@ export class WakeAcceptanceStore {
471
472
  throw new Error("wake transition lock is invalid");
472
473
  return result;
473
474
  }
474
- async transitionNowClaimed(acceptanceId, claim) {
475
+ async transitionNowClaimed(acceptanceId, claim, step, lock) {
475
476
  const record = await this.findByAcceptanceId(acceptanceId);
476
477
  if (record === undefined)
477
478
  throw new Error("wake acceptance receipt is unavailable");
478
- const current = await this.readClaim(this.claimFor(record));
479
- if (!(current.acceptance_id === acceptanceId || current.acceptance_ids?.includes(acceptanceId)) || current.acceptance_id !== claim.acceptance_id || current.owner_id !== claim.owner_id || current.generation !== claim.generation || current.expires_at !== claim.expires_at || expired(current, this.now()))
480
- throw new WakeExecutionClaimLostError();
479
+ await readExpectedClaim(() => this.readClaim(this.claimFor(record)), acceptanceId, claim, step, this.now, lock);
481
480
  return record;
482
481
  }
483
482
  async compactTerminalRecords() {
484
483
  const files = await this.files();
485
- if (files.length < 2_112)
484
+ if (files.length < WAKE_ACCEPTANCE_COMPACTION_THRESHOLD)
486
485
  return;
487
486
  const records = await Promise.all(files.map(async (file) => ({ file, record: await this.read(path.join(this.root, file)) })));
487
+ const candidates = await Promise.all(records.map(async ({ file, record }) => ({ file, state: record.state, updatedAt: record.updated_at, acceptedAt: record.accepted_at, acceptanceId: record.acceptance_id, claimed: await this.readClaimOptional(this.claimFor(record)).then((claim) => claim !== undefined && !expired(claim, this.now())) })));
488
+ for (const file of staleQueuedFilesToStop(candidates, this.now())) {
489
+ const entry = records.find((candidate) => candidate.file === file);
490
+ entry.record = { ...entry.record, state: "stopped", code: "queued_wake_stopped", updated_at: new Date(this.now()).toISOString() };
491
+ await this.replace(path.join(this.root, file), entry.record);
492
+ }
488
493
  for (const file of terminalFilesToCompact(records.map(({ file, record }) => ({ file, state: record.state, updatedAt: record.updated_at, acceptanceId: record.acceptance_id })))) {
489
494
  const record = records.find((candidate) => candidate.file === file)?.record;
490
- if (record !== undefined)
491
- this.acceptanceFiles.delete(record.acceptance_id);
492
495
  await unlink(path.join(this.root, file));
496
+ if (record !== undefined)
497
+ this.index.forget(path.join(this.root, file));
493
498
  }
494
499
  await this.directory.sync();
495
500
  }
@@ -524,14 +529,12 @@ export class WakeAcceptanceStore {
524
529
  }
525
530
  }
526
531
  export class WakeInboxFullError extends Error {
527
- constructor() { super("wake acceptance store has no capacity without deleting active work"); }
532
+ constructor(message = "wake acceptance store has no capacity without deleting active work") { super(message); }
528
533
  }
529
534
  export class WakeAcceptanceConflictError extends Error {
530
535
  constructor() { super("delivery id is already bound to a different request"); }
531
536
  }
532
- export class WakeExecutionClaimLostError extends Error {
533
- constructor() { super("wake execution claim was lost"); }
534
- }
537
+ export { WakeExecutionClaimLostError, WakeTransitionLockContentionError } from "./wakeAcceptanceClaimDiagnostics.js";
535
538
  /** A container boundary requires deployment-authorized offline reconciliation. */
536
539
  export { WakeTransitionLockBlockedError } from "./wakeAcceptanceProcessIdentity.js";
537
540
  export { publicAcceptance } from "./wakeAcceptanceRecord.js";
@@ -1,5 +1,6 @@
1
1
  export declare const WAKE_FUSE_VERSION: "noopolis.daimon.wake-fuse.v1";
2
2
  export declare const WAKE_FUSE_DIRECTORY_ENV: "DAIMON_WAKE_FUSE_DIRECTORY";
3
+ export declare const WAKE_FUSE_EPOCH_ZONE_ENV: "DAIMON_WAKE_FUSE_EPOCH_ZONE";
3
4
  export declare const DEFAULT_WAKE_FUSE_MAX_WAKES = 100;
4
5
  export declare const DEFAULT_WAKE_FUSE_MAX_TOKENS = 5000000;
5
6
  export type WakeFuseTripReason = "wake_ceiling" | "token_ceiling" | "operator_stop" | "ledger_unavailable";
@@ -30,6 +31,26 @@ export type WakeFuseVerdict = Readonly<{
30
31
  state: "paused";
31
32
  reason: "agent_execution_ceiling" | "agent_token_ceiling";
32
33
  }>;
34
+ /**
35
+ * The counting window, when the operator has not named one.
36
+ *
37
+ * WHY THIS IS DERIVED AND NOT CONFIGURED
38
+ * --------------------------------------
39
+ * `DAIMON_WAKE_FUSE_EPOCH` is read from the container's env file, and an env
40
+ * file is applied at container CREATION only. So an operator who wants a daily
41
+ * budget has to rewrite that file and RECREATE THE CONTAINER every day, and
42
+ * the only thing that ever did that was a daily rebuild. The budget was
43
+ * therefore coupled to a deploy: stop deploying daily and the wake ceiling
44
+ * never resets, and the organization stops admitting wakes for good.
45
+ *
46
+ * A date-derived epoch removes the coupling instead of moving it. There is no
47
+ * file to rewrite, no deploy, no restart, and no clock for anybody to forget.
48
+ *
49
+ * An explicitly configured epoch still wins, unchanged: an operator pinning one
50
+ * window is doing it deliberately, and this must not roll it out from under
51
+ * them.
52
+ */
53
+ export declare function derivedEpoch(organizationKey: string, at: Date, zone: string): string;
33
54
  export type WakeFuseOptions = Readonly<{
34
55
  organizationKey: string;
35
56
  environment?: NodeJS.ProcessEnv;
@@ -45,23 +66,57 @@ export type WakeFuseOptions = Readonly<{
45
66
  export declare class WakeFuse {
46
67
  private readonly armed;
47
68
  private readonly directory;
48
- private readonly epoch;
49
- private readonly epochStartedAt;
69
+ private epoch;
70
+ private epochStartedAt;
50
71
  private readonly maxWakes;
51
72
  private readonly maxTokens;
52
- private readonly admissions;
73
+ private admissions;
53
74
  private readonly usageLedgerPath;
54
75
  private readonly now;
76
+ private readonly nextEpoch;
55
77
  private serial;
56
78
  private reason;
57
79
  private tripMarkerMissing;
58
80
  private constructor();
59
81
  static open(options: WakeFuseOptions): Promise<WakeFuse>;
60
82
  admit(agentId: string, deliveryId: string, limits?: WakeBudgetLimits): Promise<WakeFuseVerdict>;
83
+ /**
84
+ * The budget as the caller should act on it NOW — which means after the day
85
+ * has been allowed to roll.
86
+ *
87
+ * This is the gate the scheduler actually consults: `AttentionDispatcher.drain()`
88
+ * returns at `snapshot().state !== "available"` before it ever reaches
89
+ * `admit()`. Rolling only inside `admitNow` therefore never fired for an
90
+ * organization that had hit its ceiling — it stayed paused across midnight
91
+ * and only a process restart could renew the budget. The roll is serialized
92
+ * with admissions so a snapshot and an admission never see two windows.
93
+ */
61
94
  snapshot(agentId: string, limits?: WakeBudgetLimits): Promise<WakeBudgetSnapshot>;
95
+ private snapshotNow;
62
96
  pollOperatorStop(): Promise<WakeFuseTripReason | undefined>;
63
97
  tripped(): WakeFuseTripReason | undefined;
64
98
  close(): Promise<void>;
99
+ /**
100
+ * Moves the counting window when the derived day has changed.
101
+ *
102
+ * Called at admission, which is the only moment the answer can matter: the
103
+ * organization runtime is a long-lived process, so an epoch computed once at
104
+ * open() would be the same epoch a week later.
105
+ *
106
+ * WHAT ROLLS AND WHAT DOES NOT
107
+ * ----------------------------
108
+ * A new window clears a CEILING trip, exactly as selecting a new epoch by
109
+ * hand always did: `readTripMarker` only honours a marker belonging to the
110
+ * current epoch. It does NOT clear an operator stop. `fuse.stop` is checked
111
+ * by existence and is deliberately not epoch-scoped, so a parked newsroom
112
+ * stays parked across midnight. That asymmetry is the whole point: a budget
113
+ * is a thing that renews, an operator stop is a decision that does not.
114
+ *
115
+ * Admissions are rebuilt from the ledger rather than emptied, so a clock that
116
+ * steps BACKWARD into a window that already spent wakes does not hand the
117
+ * organization a fresh budget.
118
+ */
119
+ private rollEpochIfDue;
65
120
  private admitNow;
66
121
  private trip;
67
122
  }