@noopolis/daimon 0.1.2 → 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.
- package/README.md +275 -51
- package/dist/contracts/attentionContract.d.ts +142 -0
- package/dist/contracts/attentionContract.d.ts.map +1 -0
- package/dist/contracts/attentionContract.js +21 -0
- package/dist/contracts/canonicalJson.d.ts +3 -0
- package/dist/contracts/canonicalJson.d.ts.map +1 -0
- package/dist/contracts/canonicalJson.js +54 -0
- package/dist/contracts/grokBrokerTaskClock.d.ts +18 -0
- package/dist/contracts/grokBrokerTaskClock.d.ts.map +1 -0
- package/dist/contracts/grokBrokerTaskClock.js +16 -0
- package/dist/contracts/grokWorkerContract.d.ts +74 -0
- package/dist/contracts/grokWorkerContract.d.ts.map +1 -0
- package/dist/contracts/grokWorkerContract.js +88 -0
- package/dist/contracts/organizationRuntimeContract.d.ts +841 -0
- package/dist/contracts/organizationRuntimeContract.d.ts.map +1 -0
- package/dist/contracts/organizationRuntimeContract.js +123 -0
- package/dist/contracts/runtimeContractManifest.d.ts +1822 -0
- package/dist/contracts/runtimeContractManifest.d.ts.map +1 -0
- package/dist/contracts/runtimeContractManifest.js +206 -0
- package/dist/contracts/shellEnvironmentPolicy.d.ts +3 -0
- package/dist/contracts/shellEnvironmentPolicy.d.ts.map +1 -0
- package/dist/contracts/shellEnvironmentPolicy.js +5 -0
- package/dist/contracts/wakeMomentContract.d.ts +61 -0
- package/dist/contracts/wakeMomentContract.d.ts.map +1 -0
- package/dist/contracts/wakeMomentContract.js +27 -0
- package/dist/core/credentialRedaction.d.ts +4 -0
- package/dist/core/credentialRedaction.d.ts.map +1 -0
- package/dist/core/credentialRedaction.js +28 -0
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/examples/jungianPlayAgent.d.ts +1 -0
- package/dist/examples/jungianPlayAgent.d.ts.map +1 -1
- package/dist/examples/jungianPlayAgent.js +6 -2
- package/dist/mcp/toolServer.d.ts +19 -2
- package/dist/mcp/toolServer.d.ts.map +1 -1
- package/dist/mcp/toolServer.js +57 -17
- package/dist/observability/causalEvents.d.ts +6 -6
- package/dist/observability/causalEvents.d.ts.map +1 -1
- package/dist/observability/causalEvents.js +107 -19
- package/dist/observability/orgObserver.d.ts.map +1 -1
- package/dist/observability/orgObserver.js +3 -3
- package/dist/pi/agyHeadlessResult.d.ts +60 -0
- package/dist/pi/agyHeadlessResult.d.ts.map +1 -0
- package/dist/pi/agyHeadlessResult.js +95 -0
- package/dist/pi/cliChildOutput.d.ts +67 -0
- package/dist/pi/cliChildOutput.d.ts.map +1 -0
- package/dist/pi/cliChildOutput.js +269 -0
- package/dist/pi/cliEngineRun.d.ts +16 -0
- package/dist/pi/cliEngineRun.d.ts.map +1 -0
- package/dist/pi/cliEngineRun.js +27 -0
- package/dist/pi/cliEngineSpawn.d.ts +55 -0
- package/dist/pi/cliEngineSpawn.d.ts.map +1 -0
- package/dist/pi/cliEngineSpawn.js +169 -0
- package/dist/pi/cliEnvironment.d.ts +12 -0
- package/dist/pi/cliEnvironment.d.ts.map +1 -0
- package/dist/pi/cliEnvironment.js +34 -0
- package/dist/pi/cliMcpRegistration.d.ts +61 -0
- package/dist/pi/cliMcpRegistration.d.ts.map +1 -0
- package/dist/pi/cliMcpRegistration.js +75 -0
- package/dist/pi/cliProcess.d.ts +7 -0
- package/dist/pi/cliProcess.d.ts.map +1 -0
- package/dist/pi/cliProcess.js +132 -0
- package/dist/pi/cliSession.d.ts +86 -24
- package/dist/pi/cliSession.d.ts.map +1 -1
- package/dist/pi/cliSession.js +251 -173
- package/dist/pi/cliSessionMcp.d.ts +9 -0
- package/dist/pi/cliSessionMcp.d.ts.map +1 -0
- package/dist/pi/cliSessionMcp.js +80 -0
- package/dist/pi/cliTurnMetering.d.ts +60 -0
- package/dist/pi/cliTurnMetering.d.ts.map +1 -0
- package/dist/pi/cliTurnMetering.js +60 -0
- package/dist/pi/codexFilesystemRules.d.ts +3 -0
- package/dist/pi/codexFilesystemRules.d.ts.map +1 -0
- package/dist/pi/codexFilesystemRules.js +28 -0
- package/dist/pi/codexHeadlessResult.d.ts +68 -0
- package/dist/pi/codexHeadlessResult.d.ts.map +1 -0
- package/dist/pi/codexHeadlessResult.js +122 -0
- package/dist/pi/codexRolloutUsage.d.ts +95 -0
- package/dist/pi/codexRolloutUsage.d.ts.map +1 -0
- package/dist/pi/codexRolloutUsage.js +221 -0
- package/dist/pi/engineTaskClock.d.ts +9 -0
- package/dist/pi/engineTaskClock.d.ts.map +1 -0
- package/dist/pi/engineTaskClock.js +28 -0
- package/dist/pi/engineWakeLimits.d.ts +39 -0
- package/dist/pi/engineWakeLimits.d.ts.map +1 -0
- package/dist/pi/engineWakeLimits.js +55 -0
- package/dist/pi/grokHeadlessResult.d.ts +36 -0
- package/dist/pi/grokHeadlessResult.d.ts.map +1 -0
- package/dist/pi/grokHeadlessResult.js +118 -0
- package/dist/pi/grokHomeMcpRegistration.d.ts +21 -0
- package/dist/pi/grokHomeMcpRegistration.d.ts.map +1 -0
- package/dist/pi/grokHomeMcpRegistration.js +58 -0
- package/dist/pi/grokSandbox.d.ts +11 -0
- package/dist/pi/grokSandbox.d.ts.map +1 -0
- package/dist/pi/grokSandbox.js +216 -0
- package/dist/pi/grokStreamUsage.d.ts +31 -0
- package/dist/pi/grokStreamUsage.d.ts.map +1 -0
- package/dist/pi/grokStreamUsage.js +51 -0
- package/dist/pi/memoryClock.d.ts +25 -0
- package/dist/pi/memoryClock.d.ts.map +1 -0
- package/dist/pi/memoryClock.js +18 -0
- package/dist/pi/piAgentHandle.d.ts +6 -3
- package/dist/pi/piAgentHandle.d.ts.map +1 -1
- package/dist/pi/piAgentHandle.js +42 -12
- package/dist/pi/piAgentWakeSupport.d.ts +35 -0
- package/dist/pi/piAgentWakeSupport.d.ts.map +1 -1
- package/dist/pi/piAgentWakeSupport.js +4 -0
- package/dist/pi/piHarness.d.ts +18 -3
- package/dist/pi/piHarness.d.ts.map +1 -1
- package/dist/pi/piHarness.js +83 -14
- package/dist/pi/prompts.d.ts +1 -0
- package/dist/pi/prompts.d.ts.map +1 -1
- package/dist/pi/prompts.js +24 -0
- package/dist/pi/taskClockProcess.d.ts +6 -0
- package/dist/pi/taskClockProcess.d.ts.map +1 -0
- package/dist/pi/taskClockProcess.js +8 -0
- package/dist/pi/turnCausal.d.ts +4 -2
- package/dist/pi/turnCausal.d.ts.map +1 -1
- package/dist/pi/turnCausal.js +4 -4
- package/dist/pi/turnTrace.d.ts.map +1 -1
- package/dist/pi/turnTrace.js +5 -8
- package/dist/pi/wakeAcceptance.d.ts +1 -1
- package/dist/pi/wakeAcceptance.d.ts.map +1 -1
- package/dist/pi/wakeAcceptance.js +2 -2
- package/dist/pi/worldTrajectory.d.ts +1 -1
- package/dist/pi/worldTrajectory.d.ts.map +1 -1
- package/dist/pi/worldTrajectory.js +3 -3
- package/dist/runtime/agySubscriptionBootstrap.d.ts +16 -0
- package/dist/runtime/agySubscriptionBootstrap.d.ts.map +1 -0
- package/dist/runtime/agySubscriptionBootstrap.js +80 -0
- package/dist/runtime/agySubscriptionRealm.d.ts +38 -0
- package/dist/runtime/agySubscriptionRealm.d.ts.map +1 -0
- package/dist/runtime/agySubscriptionRealm.js +242 -0
- package/dist/runtime/attention.d.ts +26 -0
- package/dist/runtime/attention.d.ts.map +1 -0
- package/dist/runtime/attention.js +49 -0
- package/dist/runtime/attentionDispatcher.d.ts +78 -0
- package/dist/runtime/attentionDispatcher.d.ts.map +1 -0
- package/dist/runtime/attentionDispatcher.js +365 -0
- package/dist/runtime/cli.d.ts +7 -0
- package/dist/runtime/cli.d.ts.map +1 -0
- package/dist/runtime/cli.js +256 -0
- package/dist/runtime/codexSandboxProjection.d.ts +17 -0
- package/dist/runtime/codexSandboxProjection.d.ts.map +1 -0
- package/dist/runtime/codexSandboxProjection.js +40 -0
- package/dist/runtime/contract-manifest.json +1 -0
- package/dist/runtime/contract-manifest.sha256 +1 -0
- package/dist/runtime/contractManifest.d.ts +8 -0
- package/dist/runtime/contractManifest.d.ts.map +1 -0
- package/dist/runtime/contractManifest.js +4 -0
- package/dist/runtime/engineBrokerCapabilities.d.ts +40 -0
- package/dist/runtime/engineBrokerCapabilities.d.ts.map +1 -0
- package/dist/runtime/engineBrokerCapabilities.js +69 -0
- package/dist/runtime/engineBrokerControlClient.d.ts +55 -0
- package/dist/runtime/engineBrokerControlClient.d.ts.map +1 -0
- package/dist/runtime/engineBrokerControlClient.js +228 -0
- package/dist/runtime/engineBrokerCredentialJournal.d.ts +12 -0
- package/dist/runtime/engineBrokerCredentialJournal.d.ts.map +1 -0
- package/dist/runtime/engineBrokerCredentialJournal.js +26 -0
- package/dist/runtime/engineBrokerInferenceProtocol.d.ts +53 -0
- package/dist/runtime/engineBrokerInferenceProtocol.d.ts.map +1 -0
- package/dist/runtime/engineBrokerInferenceProtocol.js +65 -0
- package/dist/runtime/engineBrokerMcpCallLog.d.ts +171 -0
- package/dist/runtime/engineBrokerMcpCallLog.d.ts.map +1 -0
- package/dist/runtime/engineBrokerMcpCallLog.js +231 -0
- package/dist/runtime/engineBrokerMcpFacade.d.ts +59 -0
- package/dist/runtime/engineBrokerMcpFacade.d.ts.map +1 -0
- package/dist/runtime/engineBrokerMcpFacade.js +346 -0
- package/dist/runtime/engineBrokerNativeClient.d.ts +52 -0
- package/dist/runtime/engineBrokerNativeClient.d.ts.map +1 -0
- package/dist/runtime/engineBrokerNativeClient.js +151 -0
- package/dist/runtime/engineBrokerProtocol.d.ts +167 -0
- package/dist/runtime/engineBrokerProtocol.d.ts.map +1 -0
- package/dist/runtime/engineBrokerProtocol.js +357 -0
- package/dist/runtime/engineBrokerSealLedger.d.ts +70 -0
- package/dist/runtime/engineBrokerSealLedger.d.ts.map +1 -0
- package/dist/runtime/engineBrokerSealLedger.js +132 -0
- package/dist/runtime/engineBrokerService.d.ts +43 -0
- package/dist/runtime/engineBrokerService.d.ts.map +1 -0
- package/dist/runtime/engineBrokerService.js +196 -0
- package/dist/runtime/engineBrokerServiceCli.d.ts +5 -0
- package/dist/runtime/engineBrokerServiceCli.d.ts.map +1 -0
- package/dist/runtime/engineBrokerServiceCli.js +32 -0
- package/dist/runtime/engineBrokerServiceConfig.d.ts +55 -0
- package/dist/runtime/engineBrokerServiceConfig.d.ts.map +1 -0
- package/dist/runtime/engineBrokerServiceConfig.js +130 -0
- package/dist/runtime/engineBrokerSingleflight.d.ts +13 -0
- package/dist/runtime/engineBrokerSingleflight.d.ts.map +1 -0
- package/dist/runtime/engineBrokerSingleflight.js +24 -0
- package/dist/runtime/engineBrokerTurnAccounting.d.ts +76 -0
- package/dist/runtime/engineBrokerTurnAccounting.d.ts.map +1 -0
- package/dist/runtime/engineBrokerTurnAccounting.js +108 -0
- package/dist/runtime/engineBrokerTurnRegistry.d.ts +57 -0
- package/dist/runtime/engineBrokerTurnRegistry.d.ts.map +1 -0
- package/dist/runtime/engineBrokerTurnRegistry.js +159 -0
- package/dist/runtime/engineDispatcher.d.ts +38 -0
- package/dist/runtime/engineDispatcher.d.ts.map +1 -0
- package/dist/runtime/engineDispatcher.js +228 -0
- package/dist/runtime/engineReadiness.d.ts +23 -0
- package/dist/runtime/engineReadiness.d.ts.map +1 -0
- package/dist/runtime/engineReadiness.js +222 -0
- package/dist/runtime/grokAuthenticationError.d.ts +8 -0
- package/dist/runtime/grokAuthenticationError.d.ts.map +1 -0
- package/dist/runtime/grokAuthenticationError.js +20 -0
- package/dist/runtime/grokBrokerCredentialAuthority.d.ts +23 -0
- package/dist/runtime/grokBrokerCredentialAuthority.d.ts.map +1 -0
- package/dist/runtime/grokBrokerCredentialAuthority.js +150 -0
- package/dist/runtime/grokBrokerCredentialReader.d.ts +6 -0
- package/dist/runtime/grokBrokerCredentialReader.d.ts.map +1 -0
- package/dist/runtime/grokBrokerCredentialReader.js +38 -0
- package/dist/runtime/grokBrokerModelPolicy.d.ts +23 -0
- package/dist/runtime/grokBrokerModelPolicy.d.ts.map +1 -0
- package/dist/runtime/grokBrokerModelPolicy.js +28 -0
- package/dist/runtime/grokBrokerProjection.d.ts +114 -0
- package/dist/runtime/grokBrokerProjection.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProjection.js +101 -0
- package/dist/runtime/grokBrokerProviderClock.d.ts +26 -0
- package/dist/runtime/grokBrokerProviderClock.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProviderClock.js +133 -0
- package/dist/runtime/grokBrokerProxy.d.ts +69 -0
- package/dist/runtime/grokBrokerProxy.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProxy.js +326 -0
- package/dist/runtime/grokBrokerProxyJson.d.ts +10 -0
- package/dist/runtime/grokBrokerProxyJson.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProxyJson.js +31 -0
- package/dist/runtime/grokBrokerProxyRequest.d.ts +30 -0
- package/dist/runtime/grokBrokerProxyRequest.d.ts.map +1 -0
- package/dist/runtime/grokBrokerProxyRequest.js +85 -0
- package/dist/runtime/grokBrokerRealmLease.d.ts +4 -0
- package/dist/runtime/grokBrokerRealmLease.d.ts.map +1 -0
- package/dist/runtime/grokBrokerRealmLease.js +33 -0
- package/dist/runtime/grokBrokerRefresh.d.ts +2 -0
- package/dist/runtime/grokBrokerRefresh.d.ts.map +1 -0
- package/dist/runtime/grokBrokerRefresh.js +15 -0
- package/dist/runtime/grokBrokerRunBudget.d.ts +20 -0
- package/dist/runtime/grokBrokerRunBudget.d.ts.map +1 -0
- package/dist/runtime/grokBrokerRunBudget.js +85 -0
- package/dist/runtime/grokBrokerSlot.d.ts +6 -0
- package/dist/runtime/grokBrokerSlot.d.ts.map +1 -0
- package/dist/runtime/grokBrokerSlot.js +21 -0
- package/dist/runtime/grokBrokerTaskClock.d.ts +32 -0
- package/dist/runtime/grokBrokerTaskClock.d.ts.map +1 -0
- package/dist/runtime/grokBrokerTaskClock.js +120 -0
- package/dist/runtime/grokBrokerTurnMeter.d.ts +180 -0
- package/dist/runtime/grokBrokerTurnMeter.d.ts.map +1 -0
- package/dist/runtime/grokBrokerTurnMeter.js +337 -0
- package/dist/runtime/grokBrokerWorkerConfig.d.ts +89 -0
- package/dist/runtime/grokBrokerWorkerConfig.d.ts.map +1 -0
- package/dist/runtime/grokBrokerWorkerConfig.js +154 -0
- package/dist/runtime/grokEngineBroker.d.ts +88 -0
- package/dist/runtime/grokEngineBroker.d.ts.map +1 -0
- package/dist/runtime/grokEngineBroker.js +202 -0
- package/dist/runtime/grokEngineBrokerLedger.d.ts +52 -0
- package/dist/runtime/grokEngineBrokerLedger.d.ts.map +1 -0
- package/dist/runtime/grokEngineBrokerLedger.js +114 -0
- package/dist/runtime/grokEngineBrokerMetering.d.ts +51 -0
- package/dist/runtime/grokEngineBrokerMetering.d.ts.map +1 -0
- package/dist/runtime/grokEngineBrokerMetering.js +34 -0
- package/dist/runtime/grokEngineBrokerTurn.d.ts +82 -0
- package/dist/runtime/grokEngineBrokerTurn.d.ts.map +1 -0
- package/dist/runtime/grokEngineBrokerTurn.js +348 -0
- package/dist/runtime/grokEngineBrokerTurnEnd.d.ts +88 -0
- package/dist/runtime/grokEngineBrokerTurnEnd.d.ts.map +1 -0
- package/dist/runtime/grokEngineBrokerTurnEnd.js +148 -0
- package/dist/runtime/grokInferenceClientConfig.d.ts +41 -0
- package/dist/runtime/grokInferenceClientConfig.d.ts.map +1 -0
- package/dist/runtime/grokInferenceClientConfig.js +62 -0
- package/dist/runtime/grokInferenceGrants.d.ts +77 -0
- package/dist/runtime/grokInferenceGrants.d.ts.map +1 -0
- package/dist/runtime/grokInferenceGrants.js +116 -0
- package/dist/runtime/grokInferenceProxy.d.ts +29 -0
- package/dist/runtime/grokInferenceProxy.d.ts.map +1 -0
- package/dist/runtime/grokInferenceProxy.js +85 -0
- package/dist/runtime/grokInferenceProxyRequest.d.ts +23 -0
- package/dist/runtime/grokInferenceProxyRequest.d.ts.map +1 -0
- package/dist/runtime/grokInferenceProxyRequest.js +63 -0
- package/dist/runtime/grokSlotPreflightReceipt.d.ts +70 -0
- package/dist/runtime/grokSlotPreflightReceipt.d.ts.map +1 -0
- package/dist/runtime/grokSlotPreflightReceipt.js +101 -0
- package/dist/runtime/grokSubscriptionRealm.d.ts +4 -0
- package/dist/runtime/grokSubscriptionRealm.d.ts.map +1 -0
- package/dist/runtime/grokSubscriptionRealm.js +435 -0
- package/dist/runtime/grokSubscriptionRealmTypes.d.ts +26 -0
- package/dist/runtime/grokSubscriptionRealmTypes.d.ts.map +1 -0
- package/dist/runtime/grokSubscriptionRealmTypes.js +1 -0
- package/dist/runtime/grokWorkerAttestation.d.ts +175 -0
- package/dist/runtime/grokWorkerAttestation.d.ts.map +1 -0
- package/dist/runtime/grokWorkerAttestation.js +266 -0
- package/dist/runtime/grokWorkerDenyPlacement.d.ts +80 -0
- package/dist/runtime/grokWorkerDenyPlacement.d.ts.map +1 -0
- package/dist/runtime/grokWorkerDenyPlacement.js +128 -0
- package/dist/runtime/grokWorkerHomeAttestation.d.ts +32 -0
- package/dist/runtime/grokWorkerHomeAttestation.d.ts.map +1 -0
- package/dist/runtime/grokWorkerHomeAttestation.js +75 -0
- package/dist/runtime/grokWorkerSandboxProfile.d.ts +27 -0
- package/dist/runtime/grokWorkerSandboxProfile.d.ts.map +1 -0
- package/dist/runtime/grokWorkerSandboxProfile.js +44 -0
- package/dist/runtime/grokWorkerTmpAttestation.d.ts +55 -0
- package/dist/runtime/grokWorkerTmpAttestation.d.ts.map +1 -0
- package/dist/runtime/grokWorkerTmpAttestation.js +63 -0
- package/dist/runtime/index.d.ts +31 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +27 -0
- package/dist/runtime/inferenceUsageLedger.d.ts +38 -0
- package/dist/runtime/inferenceUsageLedger.d.ts.map +1 -0
- package/dist/runtime/inferenceUsageLedger.js +53 -0
- package/dist/runtime/mcpToolResult.d.ts +127 -0
- package/dist/runtime/mcpToolResult.d.ts.map +1 -0
- package/dist/runtime/mcpToolResult.js +214 -0
- package/dist/runtime/moltnetMachineRead.d.ts +97 -0
- package/dist/runtime/moltnetMachineRead.d.ts.map +1 -0
- package/dist/runtime/moltnetMachineRead.js +183 -0
- package/dist/runtime/native/daimon-engine-broker +0 -0
- package/dist/runtime/organizationRuntime.d.ts +168 -0
- package/dist/runtime/organizationRuntime.d.ts.map +1 -0
- package/dist/runtime/organizationRuntime.js +3 -0
- package/dist/runtime/organizationRuntimeAdmission.d.ts +6 -0
- package/dist/runtime/organizationRuntimeAdmission.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeAdmission.js +22 -0
- package/dist/runtime/organizationRuntimeControl.d.ts +51 -0
- package/dist/runtime/organizationRuntimeControl.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeControl.js +283 -0
- package/dist/runtime/organizationRuntimeHost.d.ts +19 -0
- package/dist/runtime/organizationRuntimeHost.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeHost.js +368 -0
- package/dist/runtime/organizationRuntimeParsing.d.ts +6 -0
- package/dist/runtime/organizationRuntimeParsing.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeParsing.js +373 -0
- package/dist/runtime/organizationRuntimeReadiness.d.ts +12 -0
- package/dist/runtime/organizationRuntimeReadiness.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeReadiness.js +67 -0
- package/dist/runtime/organizationRuntimeRecording.d.ts +7 -0
- package/dist/runtime/organizationRuntimeRecording.d.ts.map +1 -0
- package/dist/runtime/organizationRuntimeRecording.js +58 -0
- package/dist/runtime/physicalReadiness.d.ts +59 -0
- package/dist/runtime/physicalReadiness.d.ts.map +1 -0
- package/dist/runtime/physicalReadiness.js +176 -0
- package/dist/runtime/portableCredentialAuth.d.ts +6 -0
- package/dist/runtime/portableCredentialAuth.d.ts.map +1 -0
- package/dist/runtime/portableCredentialAuth.js +70 -0
- package/dist/runtime/portableCredentialMaterial.d.ts +8 -0
- package/dist/runtime/portableCredentialMaterial.d.ts.map +1 -0
- package/dist/runtime/portableCredentialMaterial.js +169 -0
- package/dist/runtime/productionAgentTools.d.ts +5 -0
- package/dist/runtime/productionAgentTools.d.ts.map +1 -0
- package/dist/runtime/productionAgentTools.js +336 -0
- package/dist/runtime/relocateRuntimeConfig.d.ts +14 -0
- package/dist/runtime/relocateRuntimeConfig.d.ts.map +1 -0
- package/dist/runtime/relocateRuntimeConfig.js +38 -0
- package/dist/runtime/runtimeHomeLayout.d.ts +48 -0
- package/dist/runtime/runtimeHomeLayout.d.ts.map +1 -0
- package/dist/runtime/runtimeHomeLayout.js +84 -0
- package/dist/runtime/schedule.d.ts +40 -0
- package/dist/runtime/schedule.d.ts.map +1 -0
- package/dist/runtime/schedule.js +376 -0
- package/dist/runtime/storeCoordination.d.ts +33 -0
- package/dist/runtime/storeCoordination.d.ts.map +1 -0
- package/dist/runtime/storeCoordination.js +117 -0
- package/dist/runtime/taskClock.d.ts +42 -0
- package/dist/runtime/taskClock.d.ts.map +1 -0
- package/dist/runtime/taskClock.js +102 -0
- package/dist/runtime/taskClockProcess.d.ts +17 -0
- package/dist/runtime/taskClockProcess.d.ts.map +1 -0
- package/dist/runtime/taskClockProcess.js +58 -0
- package/dist/runtime/toolResultSpill.d.ts +152 -0
- package/dist/runtime/toolResultSpill.d.ts.map +1 -0
- package/dist/runtime/toolResultSpill.js +351 -0
- package/dist/runtime/turnRequestLedger.d.ts +155 -0
- package/dist/runtime/turnRequestLedger.d.ts.map +1 -0
- package/dist/runtime/turnRequestLedger.js +251 -0
- package/dist/runtime/turnUsageLedger.d.ts +143 -0
- package/dist/runtime/turnUsageLedger.d.ts.map +1 -0
- package/dist/runtime/turnUsageLedger.js +203 -0
- package/dist/runtime/wakeAcceptanceClaimDiagnostics.d.ts +34 -0
- package/dist/runtime/wakeAcceptanceClaimDiagnostics.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceClaimDiagnostics.js +79 -0
- package/dist/runtime/wakeAcceptanceIndex.d.ts +55 -0
- package/dist/runtime/wakeAcceptanceIndex.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceIndex.js +158 -0
- package/dist/runtime/wakeAcceptanceProcessIdentity.d.ts +25 -0
- package/dist/runtime/wakeAcceptanceProcessIdentity.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceProcessIdentity.js +54 -0
- package/dist/runtime/wakeAcceptanceReconciliation.d.ts +211 -0
- package/dist/runtime/wakeAcceptanceReconciliation.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceReconciliation.js +289 -0
- package/dist/runtime/wakeAcceptanceRecord.d.ts +25 -0
- package/dist/runtime/wakeAcceptanceRecord.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceRecord.js +58 -0
- package/dist/runtime/wakeAcceptanceRetention.d.ts +36 -0
- package/dist/runtime/wakeAcceptanceRetention.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceRetention.js +38 -0
- package/dist/runtime/wakeAcceptanceStore.d.ts +113 -0
- package/dist/runtime/wakeAcceptanceStore.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceStore.js +561 -0
- package/dist/runtime/wakeAcceptanceTypes.d.ts +179 -0
- package/dist/runtime/wakeAcceptanceTypes.d.ts.map +1 -0
- package/dist/runtime/wakeAcceptanceTypes.js +95 -0
- package/dist/runtime/wakeFuse.d.ts +124 -0
- package/dist/runtime/wakeFuse.d.ts.map +1 -0
- package/dist/runtime/wakeFuse.js +466 -0
- package/dist/runtime/wakeMomentFs.d.ts +27 -0
- package/dist/runtime/wakeMomentFs.d.ts.map +1 -0
- package/dist/runtime/wakeMomentFs.js +223 -0
- package/dist/runtime/wakeMomentHistory.d.ts +26 -0
- package/dist/runtime/wakeMomentHistory.d.ts.map +1 -0
- package/dist/runtime/wakeMomentHistory.js +109 -0
- package/dist/runtime/wakeMomentIo.d.ts +22 -0
- package/dist/runtime/wakeMomentIo.d.ts.map +1 -0
- package/dist/runtime/wakeMomentIo.js +114 -0
- package/dist/runtime/wakeMomentRecorder.d.ts +33 -0
- package/dist/runtime/wakeMomentRecorder.d.ts.map +1 -0
- package/dist/runtime/wakeMomentRecorder.js +81 -0
- package/dist/runtime/wakeMomentRetention.d.ts +7 -0
- package/dist/runtime/wakeMomentRetention.d.ts.map +1 -0
- package/dist/runtime/wakeMomentRetention.js +143 -0
- package/dist/runtime/wakeMomentRows.d.ts +8 -0
- package/dist/runtime/wakeMomentRows.d.ts.map +1 -0
- package/dist/runtime/wakeMomentRows.js +66 -0
- package/dist/runtime/wakeMomentSnapshot.d.ts +56 -0
- package/dist/runtime/wakeMomentSnapshot.d.ts.map +1 -0
- package/dist/runtime/wakeMomentSnapshot.js +248 -0
- package/package.json +22 -11
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import { link, lstat, open, readFile, realpath, rename, stat, unlink } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { clearDeadHostRegistrations, hostRegistrationDigest, listHostRegistrations } from "./storeCoordination.js";
|
|
6
|
+
export const OFFLINE_RECONCILIATION_VERSION = "noopolis.daimon.offline-transition-reconciliation.v1";
|
|
7
|
+
export const OFFLINE_RECONCILIATION_BLOCKED_CODE = "offline_reconciliation_required";
|
|
8
|
+
const MAX_BYTES = 16_384;
|
|
9
|
+
const RECEIPT_VERSION = "noopolis.daimon.offline-transition-reconciliation-receipt.v1";
|
|
10
|
+
export const OFFLINE_RECONCILIATION_REQUEST_SCHEMA = {
|
|
11
|
+
$schema: "https://json-schema.org/draft/2020-12/schema", $id: OFFLINE_RECONCILIATION_VERSION, type: "object", additionalProperties: false,
|
|
12
|
+
required: ["version", "agent_id", "delivery_id", "store", "lock", "attestation"], properties: {
|
|
13
|
+
version: { const: OFFLINE_RECONCILIATION_VERSION }, agent_id: { type: "string", minLength: 1, maxLength: MAX_BYTES }, delivery_id: { type: "string", minLength: 1, maxLength: MAX_BYTES },
|
|
14
|
+
store: { type: "object", additionalProperties: false, required: ["dev", "ino"], properties: { dev: { type: "integer", minimum: 1 }, ino: { type: "integer", minimum: 1 } } },
|
|
15
|
+
lock: { type: "object", additionalProperties: false, required: ["dev", "ino", "owner_id", "generation", "pid", "process_start", "boot_id", "pid_namespace_dev", "pid_namespace_ino"], properties: { dev: { type: "integer", minimum: 1 }, ino: { type: "integer", minimum: 1 }, owner_id: { type: "string" }, generation: { type: "string" }, pid: { type: "integer", minimum: 1 }, process_start: { type: "string" }, boot_id: { type: "string" }, pid_namespace_dev: { type: "integer", minimum: 1 }, pid_namespace_ino: { type: "integer", minimum: 1 } } },
|
|
16
|
+
attestation: { type: "object", additionalProperties: false, required: ["version", "authority_id", "attestation_id", "state", "proof"], properties: { version: { const: "noopolis.deployment.container-quiescence.v1" }, authority_id: { type: "string", minLength: 1, maxLength: MAX_BYTES }, attestation_id: { type: "string", minLength: 1, maxLength: MAX_BYTES }, state: { enum: ["absent", "quiescent"] }, proof: { type: "string", minLength: 1, maxLength: MAX_BYTES } } }
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
/** Deployment-only: caller must exclusively mount the private store offline. */
|
|
20
|
+
export async function reconcileOfflineWakeTransition(value, options) {
|
|
21
|
+
try {
|
|
22
|
+
const request = parseOfflineTransitionReconciliationRequest(value);
|
|
23
|
+
const root = await openStore(options.storePath, request.store);
|
|
24
|
+
try {
|
|
25
|
+
const lease = await acquireLease(root.path, root.directory, await (options.leaseIdentity ?? currentLeaseIdentity)(), options.leaseLiveness ?? leaseIsAlive);
|
|
26
|
+
if (lease === undefined)
|
|
27
|
+
return blocked();
|
|
28
|
+
try {
|
|
29
|
+
const target = lockPath(root.path, request.agent_id, request.delivery_id);
|
|
30
|
+
const receiptPath = receiptFile(root.path, request);
|
|
31
|
+
let receipt = await readReceiptOptional(receiptPath);
|
|
32
|
+
if (receipt !== undefined && receipt.request_digest !== digest(request))
|
|
33
|
+
return blocked();
|
|
34
|
+
if (receipt?.state === "reconciled")
|
|
35
|
+
return publicReceipt(receipt);
|
|
36
|
+
const context = authorizationContext(request, await listHostRegistrations(root.path));
|
|
37
|
+
const proof = await options.verifyDeploymentAttestation(context, request.attestation).catch(() => { throw new OfflineTransitionReconciliationBlockedError(); });
|
|
38
|
+
if (!sameProofReceipt(proof, context))
|
|
39
|
+
throw new OfflineTransitionReconciliationBlockedError();
|
|
40
|
+
const cleared = await clearDeadHostRegistrations(root.path, root.directory, lease, options.hostLiveness ?? leaseIsAlive, new Set(proof.authorized_registration_digests)).catch(() => undefined);
|
|
41
|
+
if (cleared === undefined)
|
|
42
|
+
return blocked();
|
|
43
|
+
await assertStore(root, request.store);
|
|
44
|
+
await assertRecord(recordPath(root.path, request.agent_id, request.delivery_id), request);
|
|
45
|
+
if (receipt === undefined)
|
|
46
|
+
receipt = await writeReceipt(receiptPath, { version: RECEIPT_VERSION, reconciliation_id: randomUUID(), request_digest: digest(request), state: "prepared", reconciled_at: "", cleared_registration_digests: [] }, root.directory);
|
|
47
|
+
const lock = await readLockOptional(target);
|
|
48
|
+
if (lock !== undefined) {
|
|
49
|
+
if (!same(lock, request.lock) || !same(await lstat(target), request.lock))
|
|
50
|
+
throw new OfflineTransitionReconciliationBlockedError();
|
|
51
|
+
await assertStore(root, request.store);
|
|
52
|
+
await assertRecord(recordPath(root.path, request.agent_id, request.delivery_id), request);
|
|
53
|
+
await unlink(target);
|
|
54
|
+
await root.directory.sync();
|
|
55
|
+
}
|
|
56
|
+
const reconciled = { ...receipt, state: "reconciled", reconciled_at: new Date().toISOString(), cleared_registration_digests: uniqueDigests([...receipt.cleared_registration_digests, ...cleared]) };
|
|
57
|
+
await replaceReceipt(receiptPath, reconciled, root.directory);
|
|
58
|
+
return publicReceipt(reconciled);
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
await releaseLease(lease, root.directory, root.path);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
await root.directory.close();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (error instanceof OfflineTransitionReconciliationBlockedError)
|
|
70
|
+
return blocked();
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export function parseOfflineTransitionReconciliationRequest(value) {
|
|
75
|
+
const root = strictRecord(value, ["version", "agent_id", "delivery_id", "store", "lock", "attestation"]);
|
|
76
|
+
if (text(root.version) !== OFFLINE_RECONCILIATION_VERSION)
|
|
77
|
+
throw new TypeError("offline reconciliation version is unsupported");
|
|
78
|
+
const store = strictRecord(root.store, ["dev", "ino"]);
|
|
79
|
+
const lock = strictRecord(root.lock, ["dev", "ino", "owner_id", "generation", "pid", "process_start", "boot_id", "pid_namespace_dev", "pid_namespace_ino"]);
|
|
80
|
+
const attestation = strictRecord(root.attestation, ["version", "authority_id", "attestation_id", "state", "proof"]);
|
|
81
|
+
const state = text(attestation.state);
|
|
82
|
+
if (text(attestation.version) !== "noopolis.deployment.container-quiescence.v1" || (state !== "absent" && state !== "quiescent"))
|
|
83
|
+
throw new TypeError("offline reconciliation attestation is invalid");
|
|
84
|
+
const parsedLock = { dev: positive(lock.dev), ino: positive(lock.ino), owner_id: uuid(lock.owner_id), generation: uuid(lock.generation), pid: positive(lock.pid), process_start: nonBlank(lock.process_start), boot_id: nonBlank(lock.boot_id), pid_namespace_dev: positive(lock.pid_namespace_dev), pid_namespace_ino: positive(lock.pid_namespace_ino) };
|
|
85
|
+
return { version: OFFLINE_RECONCILIATION_VERSION, agent_id: nonBlank(root.agent_id), delivery_id: nonBlank(root.delivery_id), store: { dev: positive(store.dev), ino: positive(store.ino) }, lock: parsedLock, attestation: { version: "noopolis.deployment.container-quiescence.v1", authority_id: nonBlank(attestation.authority_id), attestation_id: nonBlank(attestation.attestation_id), state, proof: nonBlank(attestation.proof) } };
|
|
86
|
+
}
|
|
87
|
+
export class OfflineTransitionReconciliationBlockedError extends Error {
|
|
88
|
+
code = OFFLINE_RECONCILIATION_BLOCKED_CODE;
|
|
89
|
+
constructor() { super("offline transition reconciliation is blocked"); }
|
|
90
|
+
}
|
|
91
|
+
/** Normal hosts may start only after the durable offline lease is absent. */
|
|
92
|
+
export async function assertOfflineReconciliationLeaseAvailable(root) { if (await readLeaseOptional(path.join(root, ".offline-reconciliation.lock")) !== undefined)
|
|
93
|
+
throw new OfflineTransitionReconciliationBlockedError(); }
|
|
94
|
+
async function openStore(root, expected) {
|
|
95
|
+
if (!path.isAbsolute(root))
|
|
96
|
+
throw new OfflineTransitionReconciliationBlockedError();
|
|
97
|
+
await assertNoLinks(root);
|
|
98
|
+
const before = await lstat(root);
|
|
99
|
+
if (!before.isDirectory() || before.isSymbolicLink() || before.uid !== process.getuid?.() || (before.mode & 0o777) !== 0o700 || !same(before, expected))
|
|
100
|
+
throw new OfflineTransitionReconciliationBlockedError();
|
|
101
|
+
const directory = await open(root, constants.O_RDONLY | directoryFlag() | noFollow());
|
|
102
|
+
try {
|
|
103
|
+
const canonical = await realpath(root);
|
|
104
|
+
if (!same(await directory.stat(), expected))
|
|
105
|
+
throw new OfflineTransitionReconciliationBlockedError();
|
|
106
|
+
return { path: canonical, directory };
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
await directory.close().catch(() => undefined);
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async function assertStore(root, expected) { await assertNoLinks(root.path); if (!same(await lstat(root.path), expected) || !same(await root.directory.stat(), expected) || await realpath(root.path) !== root.path)
|
|
114
|
+
throw new OfflineTransitionReconciliationBlockedError(); }
|
|
115
|
+
/**
|
|
116
|
+
* Publishes `value` at `target` only if `target` does not already exist, and
|
|
117
|
+
* only ever under complete, fsynced content — the name never appears holding a
|
|
118
|
+
* partial or zero-byte document, which `readLease` would otherwise accept as a
|
|
119
|
+
* safe file and then fail to `JSON.parse`.
|
|
120
|
+
*
|
|
121
|
+
* `link(2)` is mandatory here and `rename(2)` is FORBIDDEN. rename overwrites
|
|
122
|
+
* its destination unconditionally, so two acquirers that both pass the
|
|
123
|
+
* (non-atomic) `readLeaseOptional` pre-check would both publish and both
|
|
124
|
+
* believe they hold the exclusive offline-reconciliation lease. link fails with
|
|
125
|
+
* EEXIST when the target exists, which is the mutual exclusion `acquireLease`
|
|
126
|
+
* converts into a blocked result. Exported solely so that contract can be
|
|
127
|
+
* asserted directly; it is not re-exported from `./index.ts`.
|
|
128
|
+
*/
|
|
129
|
+
export async function publishExclusive(target, value, directory) { const temp = `${target}.${randomUUID()}`; try {
|
|
130
|
+
await writeNew(temp, value);
|
|
131
|
+
await link(temp, target);
|
|
132
|
+
await directory.sync();
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
await unlink(temp).catch(() => undefined);
|
|
136
|
+
} }
|
|
137
|
+
async function acquireLease(root, directory, owner, liveness) { const target = path.join(root, ".offline-reconciliation.lock"); const current = await readLeaseOptional(target); if (current !== undefined) {
|
|
138
|
+
if (!sameNamespace(current, owner) || await liveness(current))
|
|
139
|
+
return undefined;
|
|
140
|
+
await unlink(target);
|
|
141
|
+
await directory.sync();
|
|
142
|
+
} try {
|
|
143
|
+
await publishExclusive(target, owner, directory);
|
|
144
|
+
return owner;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (error.code === "EEXIST")
|
|
148
|
+
return undefined;
|
|
149
|
+
throw error;
|
|
150
|
+
} }
|
|
151
|
+
async function releaseLease(lease, directory, root) { const target = path.join(root, ".offline-reconciliation.lock"); const current = await readLease(target); if (!sameLease(current, lease))
|
|
152
|
+
throw new OfflineTransitionReconciliationBlockedError(); await unlink(target); await directory.sync(); }
|
|
153
|
+
function lockPath(root, agent, delivery) { return path.join(root, `${createHash("sha256").update(`${agent}\u0000${delivery}`).digest("hex")}.transition-lock`); }
|
|
154
|
+
function recordPath(root, agent, delivery) { return path.join(root, `${createHash("sha256").update(`${agent}\u0000${delivery}`).digest("hex")}.json`); }
|
|
155
|
+
function receiptFile(root, request) { return path.join(root, `.reconcile-${createHash("sha256").update(JSON.stringify({ store: request.store, lock: request.lock })).digest("hex")}.json`); }
|
|
156
|
+
function digest(request) { return createHash("sha256").update(JSON.stringify(request)).digest("hex"); }
|
|
157
|
+
function authorizationContext(request, stale_host_registrations) { return { version: "noopolis.daimon.offline-transition-authorization-context.v1", deployment_identity: request.attestation.authority_id, deployment_state: request.attestation.state, nonce: request.attestation.attestation_id, request_digest: digest({ request, stale_host_registrations }), agent_id: request.agent_id, delivery_id: request.delivery_id, store: request.store, lock: request.lock, stale_host_registrations }; }
|
|
158
|
+
function sameProofReceipt(value, context) { try {
|
|
159
|
+
const proof = strictRecord(value, ["request_digest", "nonce", "exclusive_store", "authorized_registration_digests"]);
|
|
160
|
+
return text(proof.request_digest) === context.request_digest && text(proof.nonce) === context.nonce && proof.exclusive_store === true && Array.isArray(proof.authorized_registration_digests) && proof.authorized_registration_digests.every((item) => /^[a-f0-9]{64}$/u.test(text(item))) && proof.authorized_registration_digests.every((item) => context.stale_host_registrations.some((host) => hostRegistrationDigest(host) === item));
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
return false;
|
|
164
|
+
} }
|
|
165
|
+
async function readLock(file) { const entry = await lstat(file); if (!safeFile(entry))
|
|
166
|
+
throw new OfflineTransitionReconciliationBlockedError(); const value = strictRecord(JSON.parse((await readFile(file)).toString("utf8")), ["owner_id", "generation", "pid", "process_start", "boot_id", "pid_namespace_dev", "pid_namespace_ino"]); return { dev: Number(entry.dev), ino: Number(entry.ino), owner_id: uuid(value.owner_id), generation: uuid(value.generation), pid: positive(value.pid), process_start: nonBlank(value.process_start), boot_id: nonBlank(value.boot_id), pid_namespace_dev: positive(value.pid_namespace_dev), pid_namespace_ino: positive(value.pid_namespace_ino) }; }
|
|
167
|
+
async function readLease(file) { const entry = await lstat(file); if (!safeFile(entry))
|
|
168
|
+
throw new OfflineTransitionReconciliationBlockedError(); const value = strictRecord(JSON.parse((await readFile(file)).toString("utf8")), ["owner_id", "pid", "process_start", "boot_id", "pid_namespace_dev", "pid_namespace_ino"]); return { owner_id: uuid(value.owner_id), pid: positive(value.pid), process_start: nonBlank(value.process_start), boot_id: nonBlank(value.boot_id), pid_namespace_dev: positive(value.pid_namespace_dev), pid_namespace_ino: positive(value.pid_namespace_ino) }; }
|
|
169
|
+
async function readLeaseOptional(file) { try {
|
|
170
|
+
return await readLease(file);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
if (error.code === "ENOENT")
|
|
174
|
+
return undefined;
|
|
175
|
+
throw error;
|
|
176
|
+
} }
|
|
177
|
+
async function readLockOptional(file) { try {
|
|
178
|
+
return await readLock(file);
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
if (error.code === "ENOENT")
|
|
182
|
+
return undefined;
|
|
183
|
+
throw error;
|
|
184
|
+
} }
|
|
185
|
+
async function assertRecord(file, request) { const entry = await lstat(file).catch(() => { throw new OfflineTransitionReconciliationBlockedError(); }); if (!safeFile(entry))
|
|
186
|
+
throw new OfflineTransitionReconciliationBlockedError(); const value = JSON.parse((await readFile(file)).toString("utf8")); if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
187
|
+
throw new OfflineTransitionReconciliationBlockedError(); const record = value; if (record.agent_id !== request.agent_id || record.delivery_id !== request.delivery_id)
|
|
188
|
+
throw new OfflineTransitionReconciliationBlockedError(); }
|
|
189
|
+
async function readReceiptOptional(file) { try {
|
|
190
|
+
const entry = await lstat(file);
|
|
191
|
+
if (!safeFile(entry))
|
|
192
|
+
throw new OfflineTransitionReconciliationBlockedError();
|
|
193
|
+
const value = strictRecord(JSON.parse((await readFile(file)).toString("utf8")), ["version", "reconciliation_id", "request_digest", "state", "reconciled_at", "cleared_registration_digests"]);
|
|
194
|
+
const state = text(value.state);
|
|
195
|
+
const cleared_registration_digests = digests(value.cleared_registration_digests);
|
|
196
|
+
if (text(value.version) !== RECEIPT_VERSION || (state !== "prepared" && state !== "reconciled") || !/^[a-f0-9]{64}$/u.test(text(value.request_digest)))
|
|
197
|
+
throw new OfflineTransitionReconciliationBlockedError();
|
|
198
|
+
const receipt = { version: RECEIPT_VERSION, reconciliation_id: uuid(value.reconciliation_id), request_digest: text(value.request_digest), state, reconciled_at: text(value.reconciled_at), cleared_registration_digests };
|
|
199
|
+
if (state === "prepared" && receipt.reconciled_at)
|
|
200
|
+
throw new OfflineTransitionReconciliationBlockedError();
|
|
201
|
+
if (state === "reconciled" && !receipt.reconciled_at)
|
|
202
|
+
throw new OfflineTransitionReconciliationBlockedError();
|
|
203
|
+
return receipt;
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
if (error.code === "ENOENT")
|
|
207
|
+
return undefined;
|
|
208
|
+
throw error;
|
|
209
|
+
} }
|
|
210
|
+
async function writeReceipt(target, receipt, directory) { const temp = `${target}.${randomUUID()}`; try {
|
|
211
|
+
await writeNew(temp, receipt);
|
|
212
|
+
await link(temp, target);
|
|
213
|
+
await directory.sync();
|
|
214
|
+
return receipt;
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
if (error.code === "EEXIST")
|
|
218
|
+
throw new OfflineTransitionReconciliationBlockedError();
|
|
219
|
+
throw error;
|
|
220
|
+
}
|
|
221
|
+
finally {
|
|
222
|
+
await unlink(temp).catch(() => undefined);
|
|
223
|
+
} }
|
|
224
|
+
async function replaceReceipt(target, receipt, directory) { const temp = `${target}.${randomUUID()}`; try {
|
|
225
|
+
await writeNew(temp, receipt);
|
|
226
|
+
await rename(temp, target);
|
|
227
|
+
await directory.sync();
|
|
228
|
+
}
|
|
229
|
+
finally {
|
|
230
|
+
await unlink(temp).catch(() => undefined);
|
|
231
|
+
} }
|
|
232
|
+
async function writeNew(file, value) { const handle = await open(file, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | noFollow(), 0o600); try {
|
|
233
|
+
await handle.writeFile(JSON.stringify(value));
|
|
234
|
+
await handle.sync();
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
await handle.close();
|
|
238
|
+
} }
|
|
239
|
+
function publicReceipt(receipt) { return receipt; }
|
|
240
|
+
function blocked() { return { version: OFFLINE_RECONCILIATION_VERSION, state: "blocked", code: OFFLINE_RECONCILIATION_BLOCKED_CODE }; }
|
|
241
|
+
function strictRecord(value, keys) { if (value === null || typeof value !== "object" || Array.isArray(value) || (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null))
|
|
242
|
+
throw new TypeError("offline reconciliation request is invalid"); const result = Object.create(null); for (const key of Reflect.ownKeys(value)) {
|
|
243
|
+
if (typeof key !== "string")
|
|
244
|
+
throw new TypeError("offline reconciliation request is invalid");
|
|
245
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
246
|
+
if (descriptor === undefined || !descriptor.enumerable || !("value" in descriptor))
|
|
247
|
+
throw new TypeError("offline reconciliation request is invalid");
|
|
248
|
+
result[key] = descriptor.value;
|
|
249
|
+
} if (Object.keys(result).length !== keys.length || keys.some((key) => !Object.hasOwn(result, key)))
|
|
250
|
+
throw new TypeError("offline reconciliation request is invalid"); return result; }
|
|
251
|
+
function text(value) { if (typeof value !== "string" || Buffer.byteLength(value, "utf8") > MAX_BYTES)
|
|
252
|
+
throw new TypeError("offline reconciliation request is invalid"); return value; }
|
|
253
|
+
function nonBlank(value) { const result = text(value); if (!result.trim())
|
|
254
|
+
throw new TypeError("offline reconciliation request is invalid"); return result; }
|
|
255
|
+
function uuid(value) { const result = nonBlank(value); if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(result))
|
|
256
|
+
throw new TypeError("offline reconciliation request is invalid"); return result; }
|
|
257
|
+
function positive(value) { if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1)
|
|
258
|
+
throw new TypeError("offline reconciliation request is invalid"); return value; }
|
|
259
|
+
function digests(value) { if (!Array.isArray(value) || value.length > 128 || value.some((item) => !/^[a-f0-9]{64}$/u.test(text(item))))
|
|
260
|
+
throw new OfflineTransitionReconciliationBlockedError(); return uniqueDigests(value); }
|
|
261
|
+
function uniqueDigests(values) { return [...new Set(values)].sort(); }
|
|
262
|
+
function same(left, right) { return Number(left.dev) === right.dev && Number(left.ino) === right.ino; }
|
|
263
|
+
function sameNamespace(left, right) { return left.pid_namespace_dev === right.pid_namespace_dev && left.pid_namespace_ino === right.pid_namespace_ino; }
|
|
264
|
+
function sameLease(left, right) { return left.owner_id === right.owner_id && left.pid === right.pid && left.process_start === right.process_start && left.boot_id === right.boot_id && sameNamespace(left, right); }
|
|
265
|
+
function safeFile(entry) { return entry.isFile() && !entry.isSymbolicLink() && Number(entry.uid) === process.getuid?.() && (Number(entry.mode) & 0o777) === 0o600 && Number(entry.size) <= MAX_BYTES; }
|
|
266
|
+
function noFollow() { return constants.O_NOFOLLOW ?? 0; }
|
|
267
|
+
function directoryFlag() { return constants.O_DIRECTORY ?? 0; }
|
|
268
|
+
async function assertNoLinks(target) { let current = path.parse(target).root; for (const part of path.relative(current, target).split(path.sep).filter(Boolean)) {
|
|
269
|
+
current = path.join(current, part);
|
|
270
|
+
if ((await lstat(current)).isSymbolicLink() && current !== "/var")
|
|
271
|
+
throw new OfflineTransitionReconciliationBlockedError();
|
|
272
|
+
} }
|
|
273
|
+
async function currentLeaseIdentity() { if (process.platform !== "linux")
|
|
274
|
+
throw new OfflineTransitionReconciliationBlockedError(); const boot_id = (await readFile("/proc/sys/kernel/random/boot_id", "utf8")).trim(); const namespace = await stat("/proc/self/ns/pid"); const process_start = await linuxProcessStart(process.pid); if (!boot_id || !Number.isSafeInteger(Number(namespace.dev)) || !Number.isSafeInteger(Number(namespace.ino)))
|
|
275
|
+
throw new OfflineTransitionReconciliationBlockedError(); return { owner_id: randomUUID(), pid: process.pid, process_start, boot_id, pid_namespace_dev: Number(namespace.dev), pid_namespace_ino: Number(namespace.ino) }; }
|
|
276
|
+
async function leaseIsAlive(lease) { if (process.platform !== "linux")
|
|
277
|
+
throw new OfflineTransitionReconciliationBlockedError(); const namespace = await stat("/proc/self/ns/pid"); if (!sameNamespace(lease, { pid_namespace_dev: Number(namespace.dev), pid_namespace_ino: Number(namespace.ino) }))
|
|
278
|
+
throw new OfflineTransitionReconciliationBlockedError(); const boot = (await readFile("/proc/sys/kernel/random/boot_id", "utf8")).trim(); if (!boot)
|
|
279
|
+
throw new OfflineTransitionReconciliationBlockedError(); if (boot !== lease.boot_id)
|
|
280
|
+
return false; try {
|
|
281
|
+
return await linuxProcessStart(lease.pid) === lease.process_start;
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
if (error.code === "ENOENT")
|
|
285
|
+
return false;
|
|
286
|
+
throw new OfflineTransitionReconciliationBlockedError();
|
|
287
|
+
} }
|
|
288
|
+
async function linuxProcessStart(pid) { const statText = await readFile(`/proc/${pid}/stat`, "utf8"); const close = statText.lastIndexOf(")"); const start = statText.slice(close + 2).trim().split(/\s+/u)[19]; if (close < 0 || start === undefined || !/^\d+$/u.test(start))
|
|
289
|
+
throw new OfflineTransitionReconciliationBlockedError(); return start; }
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type OrganizationRuntimeWakeAcceptance, type OrganizationRuntimeWakeAcceptanceRequest, type OrganizationRuntimeWakeReceiptStatus, type WakeReceiptCode, type WakeReceiptState } from "./wakeAcceptanceTypes.js";
|
|
2
|
+
export type StoredWakeAcceptanceRecord = Readonly<{
|
|
3
|
+
acceptance_id: string;
|
|
4
|
+
agent_id: string;
|
|
5
|
+
delivery_id: string;
|
|
6
|
+
request_digest: string;
|
|
7
|
+
event: OrganizationRuntimeWakeAcceptanceRequest["event"];
|
|
8
|
+
state: WakeReceiptState;
|
|
9
|
+
/** Set only through native scheduler acceptance; absent means a real delivery instant. */
|
|
10
|
+
native_schedule?: true;
|
|
11
|
+
accepted_at: string;
|
|
12
|
+
updated_at: string;
|
|
13
|
+
claim_generation?: string;
|
|
14
|
+
execution_id?: string;
|
|
15
|
+
deferred?: boolean;
|
|
16
|
+
execution_error?: string;
|
|
17
|
+
code?: WakeReceiptCode;
|
|
18
|
+
text?: string;
|
|
19
|
+
}>;
|
|
20
|
+
export declare function publicAcceptance(record: StoredWakeAcceptanceRecord): OrganizationRuntimeWakeAcceptance;
|
|
21
|
+
export declare function publicStatus(record: StoredWakeAcceptanceRecord): OrganizationRuntimeWakeReceiptStatus;
|
|
22
|
+
export declare function parseStoredWakeAcceptance(value: unknown): StoredWakeAcceptanceRecord;
|
|
23
|
+
/** Private failure diagnostic, surfaced through the existing availability error. */
|
|
24
|
+
export declare function sanitizeExecutionError(value: string): string;
|
|
25
|
+
//# sourceMappingURL=wakeAcceptanceRecord.d.ts.map
|
|
@@ -0,0 +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,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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { redactCredentialText } from "../core/credentialRedaction.js";
|
|
2
|
+
import { WAKE_ACCEPTANCE_VERSION, WAKE_RECEIPT_STATUS_VERSION, parseWakeAcceptanceRequest, sanitizeWakeCompletionText, wakeAcceptanceDigest } from "./wakeAcceptanceTypes.js";
|
|
3
|
+
export function publicAcceptance(record) {
|
|
4
|
+
return { version: WAKE_ACCEPTANCE_VERSION, acceptance_id: record.acceptance_id, agent_id: record.agent_id, delivery_id: record.delivery_id, request_digest: record.request_digest, state: "accepted", accepted_at: record.accepted_at };
|
|
5
|
+
}
|
|
6
|
+
export function publicStatus(record) {
|
|
7
|
+
return { version: WAKE_RECEIPT_STATUS_VERSION, acceptance_id: record.acceptance_id, agent_id: record.agent_id, delivery_id: record.delivery_id, request_digest: record.request_digest, state: record.state, accepted_at: record.accepted_at, updated_at: record.updated_at, ...(record.execution_id === undefined ? {} : { execution_id: record.execution_id }), ...(record.deferred === undefined ? {} : { deferred: record.deferred }), ...(record.code === undefined ? {} : { code: record.code }), ...(record.text === undefined ? {} : { text: record.text }) };
|
|
8
|
+
}
|
|
9
|
+
export function parseStoredWakeAcceptance(value) {
|
|
10
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
11
|
+
throw new Error("wake acceptance record is invalid");
|
|
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", "native_schedule"];
|
|
14
|
+
if (Object.keys(record).some((key) => !keys.includes(key)))
|
|
15
|
+
throw new Error("wake acceptance record is invalid");
|
|
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");
|
|
19
|
+
const state = string(record.state);
|
|
20
|
+
if (!["accepted", "running", "completed", "failed", "stopped"].includes(state))
|
|
21
|
+
throw new Error("wake acceptance record is invalid");
|
|
22
|
+
const code = record.code === undefined ? undefined : string(record.code);
|
|
23
|
+
const claimGeneration = record.claim_generation === undefined ? undefined : string(record.claim_generation);
|
|
24
|
+
const executionId = record.execution_id === undefined ? undefined : string(record.execution_id);
|
|
25
|
+
if (executionId !== undefined && !uuid(executionId) || record.deferred !== undefined && typeof record.deferred !== "boolean")
|
|
26
|
+
throw new Error("wake acceptance attention state is invalid");
|
|
27
|
+
const executionError = record.execution_error === undefined ? undefined : sanitizeExecutionError(string(record.execution_error));
|
|
28
|
+
if (executionError === "" || record.execution_error !== undefined && Buffer.byteLength(string(record.execution_error)) > MAX_EXECUTION_ERROR_BYTES)
|
|
29
|
+
throw new Error("wake acceptance execution error is invalid");
|
|
30
|
+
const completionText = record.text === undefined ? undefined : sanitizeWakeCompletionText(string(record.text));
|
|
31
|
+
if (claimGeneration !== undefined && !uuid(claimGeneration))
|
|
32
|
+
throw new Error("wake acceptance record is invalid");
|
|
33
|
+
if (code !== undefined && !["engine_failed", "host_stopped", "host_stopping", "queued_wake_stopped", "active_wake_aborted", "queue_full", "unknown_agent"].includes(code))
|
|
34
|
+
throw new Error("wake acceptance record is invalid");
|
|
35
|
+
// `accepted` is the one non-terminal state a record can be arrived at FROM an ended
|
|
36
|
+
// execution: the dispatcher returns an undisposed delivery there for restart, and the
|
|
37
|
+
// outcome that returned it is the only account of why. `running` and `completed` still
|
|
38
|
+
// refuse a code, where one would be nonsense rather than evidence.
|
|
39
|
+
if ((state === "running" || state === "completed") && code !== undefined)
|
|
40
|
+
throw new Error("wake acceptance record is invalid");
|
|
41
|
+
if ((state === "failed" || state === "stopped") && code === undefined)
|
|
42
|
+
throw new Error("wake acceptance record is invalid");
|
|
43
|
+
if ((state !== "completed" && state !== "failed" && completionText !== undefined) || completionText !== record.text)
|
|
44
|
+
throw new Error("wake acceptance record is invalid");
|
|
45
|
+
if (string(record.request_digest) !== wakeAcceptanceDigest(parsed) || !uuid(string(record.acceptance_id)))
|
|
46
|
+
throw new Error("wake acceptance record is invalid");
|
|
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 }) };
|
|
48
|
+
}
|
|
49
|
+
function string(value) { if (typeof value !== "string")
|
|
50
|
+
throw new Error("wake acceptance record is invalid"); return value; }
|
|
51
|
+
function timestamp(value) { const result = string(value); if (Number.isNaN(Date.parse(result)) || new Date(result).toISOString() !== result)
|
|
52
|
+
throw new Error("wake acceptance record is invalid"); return result; }
|
|
53
|
+
function uuid(value) { return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(value); }
|
|
54
|
+
const MAX_EXECUTION_ERROR_BYTES = 2048;
|
|
55
|
+
/** Private failure diagnostic, surfaced through the existing availability error. */
|
|
56
|
+
export function sanitizeExecutionError(value) {
|
|
57
|
+
return redactCredentialText(value, [], MAX_EXECUTION_ERROR_BYTES).trim();
|
|
58
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export declare const TERMINAL_RECEIPT_IDEMPOTENCY_HORIZON = 2048;
|
|
2
|
+
export declare const WAKE_ACCEPTANCE_COMPACTION_THRESHOLD = 2112;
|
|
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;
|
|
18
|
+
export type RetentionCandidate = Readonly<{
|
|
19
|
+
file: string;
|
|
20
|
+
state: "accepted" | "running" | "completed" | "failed" | "stopped";
|
|
21
|
+
updatedAt: string;
|
|
22
|
+
acceptedAt?: string;
|
|
23
|
+
acceptanceId: string;
|
|
24
|
+
}>;
|
|
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
|
+
*/
|
|
35
|
+
export declare function terminalFilesToCompact(records: readonly RetentionCandidate[]): readonly string[];
|
|
36
|
+
//# sourceMappingURL=wakeAcceptanceRetention.d.ts.map
|
|
@@ -0,0 +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;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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export const TERMINAL_RECEIPT_IDEMPOTENCY_HORIZON = 2_048;
|
|
2
|
+
export const WAKE_ACCEPTANCE_COMPACTION_THRESHOLD = 2_112;
|
|
3
|
+
export const MAX_WAKE_ACCEPTANCE_RECORDS = 2_176;
|
|
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
|
+
*/
|
|
30
|
+
export function terminalFilesToCompact(records) {
|
|
31
|
+
if (records.length < WAKE_ACCEPTANCE_COMPACTION_THRESHOLD)
|
|
32
|
+
return [];
|
|
33
|
+
const terminal = records
|
|
34
|
+
.filter((record) => record.state === "completed" || record.state === "failed" || record.state === "stopped")
|
|
35
|
+
.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt) || right.acceptanceId.localeCompare(left.acceptanceId));
|
|
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);
|
|
38
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { type TransitionLock } from "./wakeAcceptanceProcessIdentity.js";
|
|
2
|
+
import { type OrganizationRuntimeWakeAcceptanceRequest, type OrganizationRuntimeWakeReceiptStatus, type WakeReceiptCode, type WakeReceiptState } from "./wakeAcceptanceTypes.js";
|
|
3
|
+
import { type StoredWakeAcceptanceRecord } from "./wakeAcceptanceRecord.js";
|
|
4
|
+
type Stored = StoredWakeAcceptanceRecord;
|
|
5
|
+
type ActivityRow = OrganizationRuntimeWakeReceiptStatus & Readonly<{
|
|
6
|
+
active: boolean;
|
|
7
|
+
queue_position?: number;
|
|
8
|
+
execution_error?: string;
|
|
9
|
+
}>;
|
|
10
|
+
export type WakeExecutionClaim = Readonly<{
|
|
11
|
+
acceptance_id: string;
|
|
12
|
+
owner_id: string;
|
|
13
|
+
generation: string;
|
|
14
|
+
expires_at: string;
|
|
15
|
+
acceptance_ids?: readonly string[];
|
|
16
|
+
execution_id?: string;
|
|
17
|
+
}>;
|
|
18
|
+
export type WakeExecutionClaimResult = Readonly<{
|
|
19
|
+
state: "acquired";
|
|
20
|
+
claim: WakeExecutionClaim;
|
|
21
|
+
}> | Readonly<{
|
|
22
|
+
state: "held";
|
|
23
|
+
retry_at: string;
|
|
24
|
+
}> | Readonly<{
|
|
25
|
+
state: "terminal";
|
|
26
|
+
}>;
|
|
27
|
+
export type WakeAcceptanceStoreTestOptions = Readonly<{
|
|
28
|
+
claimTtlMs?: number;
|
|
29
|
+
afterFinalLockAssertion?: () => Promise<void>;
|
|
30
|
+
nowForTest?: () => number;
|
|
31
|
+
ownerLiveness?: (lock: TransitionLock) => Promise<boolean>;
|
|
32
|
+
processIdentity?: () => Promise<Omit<TransitionLock, "owner_id" | "generation">>;
|
|
33
|
+
}>;
|
|
34
|
+
/** Durable, private idempotency authority; callers must pre-create its 0700 root. */
|
|
35
|
+
export declare class WakeAcceptanceStore {
|
|
36
|
+
private readonly root;
|
|
37
|
+
private readonly directory;
|
|
38
|
+
private readonly identity;
|
|
39
|
+
private readonly registration;
|
|
40
|
+
private readonly claimTtlMs;
|
|
41
|
+
private readonly now;
|
|
42
|
+
private readonly owner;
|
|
43
|
+
private readonly ownerLiveness;
|
|
44
|
+
private readonly afterFinalLockAssertion?;
|
|
45
|
+
private mutations;
|
|
46
|
+
private readonly index;
|
|
47
|
+
private onRecordRead?;
|
|
48
|
+
private claimTransitionLockTiming?;
|
|
49
|
+
private constructor();
|
|
50
|
+
static open(root: string, options?: WakeAcceptanceStoreTestOptions): Promise<WakeAcceptanceStore>;
|
|
51
|
+
accept(request: OrganizationRuntimeWakeAcceptanceRequest, nativeSchedule?: boolean): Promise<{
|
|
52
|
+
readonly record: Stored;
|
|
53
|
+
readonly created: boolean;
|
|
54
|
+
}>;
|
|
55
|
+
private acceptNow;
|
|
56
|
+
status(acceptanceId: string): Promise<OrganizationRuntimeWakeReceiptStatus | undefined>;
|
|
57
|
+
activity(): Promise<readonly Omit<ActivityRow, "execution_error">[]>;
|
|
58
|
+
/** Internal availability view; diagnostics never enter the public receipt wire. */
|
|
59
|
+
activityWithExecutionErrors(): Promise<readonly ActivityRow[]>;
|
|
60
|
+
private activityRows;
|
|
61
|
+
recoverable(agentIds: ReadonlySet<string>, onStale?: (record: Stored) => void): Promise<readonly Stored[]>;
|
|
62
|
+
transition(acceptanceId: string, state: WakeReceiptState, code?: WakeReceiptCode): Promise<Stored>;
|
|
63
|
+
/** Fuse race seam: never stops a record that was claimed after enumeration. */
|
|
64
|
+
transitionAcceptedToStopped(acceptanceId: string, code?: "host_stopping" | "queued_wake_stopped"): Promise<Stored>;
|
|
65
|
+
acquireClaim(acceptanceId: string, ownerId: string, acceptanceIds?: readonly string[], executionId?: string): Promise<WakeExecutionClaimResult>;
|
|
66
|
+
claimHeartbeatIntervalMs(): number;
|
|
67
|
+
renewClaim(acceptanceId: string, claim: WakeExecutionClaim): Promise<WakeExecutionClaim>;
|
|
68
|
+
/** `text` carries the completion output on success and the engine failure cause on failure. */
|
|
69
|
+
transitionClaimed(acceptanceId: string, claim: WakeExecutionClaim, state: WakeReceiptState, code?: WakeReceiptCode, completedText?: string, attention?: {
|
|
70
|
+
execution_id?: string;
|
|
71
|
+
deferred?: boolean;
|
|
72
|
+
clear_execution?: boolean;
|
|
73
|
+
execution_error?: string | null;
|
|
74
|
+
}): Promise<Stored>;
|
|
75
|
+
releaseClaim(claim: WakeExecutionClaim): Promise<void>;
|
|
76
|
+
releaseClaims(ownerId: string): Promise<void>;
|
|
77
|
+
private transitionNow;
|
|
78
|
+
close(): Promise<void>;
|
|
79
|
+
private serialize;
|
|
80
|
+
private findByAcceptanceId;
|
|
81
|
+
private pathForAcceptanceId;
|
|
82
|
+
private claimFor;
|
|
83
|
+
private lockFor;
|
|
84
|
+
private acquireTransitionLock;
|
|
85
|
+
private assertTransitionLock;
|
|
86
|
+
private releaseTransitionLock;
|
|
87
|
+
private fileFor;
|
|
88
|
+
private files;
|
|
89
|
+
private claimFiles;
|
|
90
|
+
private readOptional;
|
|
91
|
+
private read;
|
|
92
|
+
private readClaimOptional;
|
|
93
|
+
private readClaim;
|
|
94
|
+
private readLockOptional;
|
|
95
|
+
private readLock;
|
|
96
|
+
private transitionNowClaimed;
|
|
97
|
+
private compactTerminalRecords;
|
|
98
|
+
private writeNew;
|
|
99
|
+
private replace;
|
|
100
|
+
private replaceValue;
|
|
101
|
+
private verify;
|
|
102
|
+
}
|
|
103
|
+
export declare class WakeInboxFullError extends Error {
|
|
104
|
+
constructor(message?: string);
|
|
105
|
+
}
|
|
106
|
+
export declare class WakeAcceptanceConflictError extends Error {
|
|
107
|
+
constructor();
|
|
108
|
+
}
|
|
109
|
+
export { WakeExecutionClaimLostError, WakeTransitionLockContentionError } from "./wakeAcceptanceClaimDiagnostics.js";
|
|
110
|
+
/** A container boundary requires deployment-authorized offline reconciliation. */
|
|
111
|
+
export { WakeTransitionLockBlockedError } from "./wakeAcceptanceProcessIdentity.js";
|
|
112
|
+
export { publicAcceptance } from "./wakeAcceptanceRecord.js";
|
|
113
|
+
//# sourceMappingURL=wakeAcceptanceStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wakeAcceptanceStore.d.ts","sourceRoot":"","sources":["../../src/runtime/wakeAcceptanceStore.ts"],"names":[],"mappings":"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"}
|