spawnfile 0.1.17 → 0.1.19
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 +1 -1
- package/dist/auth/importers.js +21 -5
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.js +1 -0
- package/dist/auth/profileStore.js +4 -1
- package/dist/auth/trainingGrokWriteback.d.ts +4 -0
- package/dist/auth/trainingGrokWriteback.js +119 -0
- package/dist/auth/trainingGrokWritebackLock.d.ts +5 -0
- package/dist/auth/trainingGrokWritebackLock.js +56 -0
- package/dist/cli/authCommands.js +9 -5
- package/dist/cli/compileBuildCommands.js +4 -0
- package/dist/cli/devCommands.js +4 -2
- package/dist/cli/downCommand.d.ts +2 -0
- package/dist/cli/downCommand.js +3 -0
- package/dist/cli/envFileOption.d.ts +18 -0
- package/dist/cli/envFileOption.js +20 -0
- package/dist/cli/lifecycleCommands.d.ts +1 -1
- package/dist/cli/lifecycleCommands.js +3 -1
- package/dist/cli/lifecyclePlan.d.ts +1 -0
- package/dist/cli/lifecyclePlan.js +2 -0
- package/dist/cli/paideiaDelegation.d.ts +2 -1
- package/dist/cli/paideiaDelegation.js +5 -4
- package/dist/cli/recordCommands.d.ts +17 -0
- package/dist/cli/recordCommands.js +43 -0
- package/dist/cli/releaseCommand.d.ts +6 -0
- package/dist/cli/releaseCommand.js +91 -0
- package/dist/cli/runCli.d.ts +7 -1
- package/dist/cli/runCli.js +11 -6
- package/dist/cli/runPublishCommands.js +5 -3
- package/dist/cli/trainCommand.js +73 -20
- package/dist/cli/upCommand.js +5 -1
- package/dist/cli/volumeCommands.d.ts +8 -0
- package/dist/cli/volumeCommands.js +53 -0
- package/dist/compiler/agentNodeMerge.js +3 -2
- package/dist/compiler/buildCompilePlan.js +4 -0
- package/dist/compiler/buildCompilePlanAgent.js +3 -1
- package/dist/compiler/buildCompilePlanTraversal.js +2 -0
- package/dist/compiler/buildCompilePlanTraversalHelpers.d.ts +2 -2
- package/dist/compiler/buildCompilePlanTraversalHelpers.js +4 -3
- package/dist/compiler/buildProject.d.ts +10 -0
- package/dist/compiler/buildProject.js +14 -2
- package/dist/compiler/cleanCompileOutput.d.ts +2 -0
- package/dist/compiler/cleanCompileOutput.js +14 -0
- package/dist/compiler/compilePlanHelpers.js +2 -0
- package/dist/compiler/compileProject.d.ts +10 -0
- package/dist/compiler/compileProject.js +29 -3
- package/dist/compiler/containerArtifactSummaries.js +1 -0
- package/dist/compiler/containerArtifacts.d.ts +4 -4
- package/dist/compiler/containerArtifacts.js +18 -34
- package/dist/compiler/containerArtifactsPlans.js +7 -0
- package/dist/compiler/containerArtifactsTypes.d.ts +7 -0
- package/dist/compiler/containerDaimonBrokerRender.d.ts +3 -1
- package/dist/compiler/containerDaimonBrokerRender.js +6 -3
- package/dist/compiler/containerDaimonGrokTaskClock.d.ts +5 -0
- package/dist/compiler/containerDaimonGrokTaskClock.js +29 -0
- package/dist/compiler/containerDaimonGrokWorkerProvisioning.d.ts +1 -1
- package/dist/compiler/containerDaimonGrokWorkerProvisioning.js +38 -16
- package/dist/compiler/containerDaimonGrokWorkerRender.d.ts +33 -8
- package/dist/compiler/containerDaimonGrokWorkerRender.js +18 -5
- package/dist/compiler/containerDaimonOwnershipGuardRender.d.ts +14 -1
- package/dist/compiler/containerDaimonOwnershipGuardRender.js +15 -2
- package/dist/compiler/containerDaimonUidEntrypointRender.js +6 -12
- package/dist/compiler/containerTargetResources.d.ts +10 -0
- package/dist/compiler/containerTargetResources.js +21 -13
- package/dist/compiler/containerWorkspaceResourceRender.js +4 -1
- package/dist/compiler/index.d.ts +2 -0
- package/dist/compiler/index.js +2 -0
- package/dist/compiler/mcpPlaceholders.d.ts +11 -0
- package/dist/compiler/mcpPlaceholders.js +58 -0
- package/dist/compiler/mcpServerInheritance.d.ts +18 -0
- package/dist/compiler/mcpServerInheritance.js +43 -0
- package/dist/compiler/moltnetArtifactTypes.d.ts +1 -0
- package/dist/compiler/moltnetArtifacts.js +1 -0
- package/dist/compiler/preflightCompilePlan.d.ts +9 -0
- package/dist/compiler/preflightCompilePlan.js +38 -0
- package/dist/compiler/recordingAgentFacts.d.ts +4 -0
- package/dist/compiler/recordingAgentFacts.js +35 -0
- package/dist/compiler/recordingCapability.d.ts +4 -0
- package/dist/compiler/recordingCapability.js +22 -0
- package/dist/compiler/recordingReport.d.ts +4 -0
- package/dist/compiler/recordingReport.js +18 -0
- package/dist/compiler/runProject.d.ts +2 -1
- package/dist/compiler/runProject.js +2 -0
- package/dist/compiler/surfaces.d.ts +1 -2
- package/dist/compiler/surfaces.js +0 -1
- package/dist/compiler/syncProjectAuth.js +2 -1
- package/dist/compiler/training/broker/clockProbe.d.ts +6 -0
- package/dist/compiler/training/broker/clockProbe.js +27 -0
- package/dist/compiler/training/broker/declaration.d.ts +4 -2
- package/dist/compiler/training/broker/declaration.js +4 -2
- package/dist/compiler/training/broker/entrypoint.js +33 -18
- package/dist/compiler/training/broker/evaluatorSecrets.d.ts +2 -0
- package/dist/compiler/training/broker/evaluatorSecrets.js +60 -0
- package/dist/compiler/training/broker/index.d.ts +3 -2
- package/dist/compiler/training/broker/index.js +3 -2
- package/dist/compiler/training/broker/main.js +1 -1
- package/dist/compiler/training/broker/paths.d.ts +96 -56
- package/dist/compiler/training/broker/paths.js +97 -89
- package/dist/compiler/training/broker/processes.d.ts +9 -0
- package/dist/compiler/training/broker/processes.js +4 -1
- package/dist/compiler/training/broker/projection.d.ts +3 -2
- package/dist/compiler/training/broker/projection.js +21 -9
- package/dist/compiler/training/broker/provisioning.d.ts +6 -15
- package/dist/compiler/training/broker/provisioning.js +71 -53
- package/dist/compiler/training/broker/registration.d.ts +3 -1
- package/dist/compiler/training/broker/registration.js +29 -21
- package/dist/compiler/training/broker/reset.d.ts +9 -0
- package/dist/compiler/training/broker/reset.js +71 -0
- package/dist/compiler/training/broker/runtime.d.ts +10 -13
- package/dist/compiler/training/broker/runtime.js +69 -115
- package/dist/compiler/training/broker/supervisor.d.ts +10 -11
- package/dist/compiler/training/broker/supervisor.js +22 -23
- package/dist/compiler/training/broker/taskClock.d.ts +5 -0
- package/dist/compiler/training/broker/taskClock.js +41 -0
- package/dist/compiler/training/compiledAgent.d.ts +21 -0
- package/dist/compiler/training/compiledAgent.js +62 -0
- package/dist/compiler/training/container/contract.d.ts +23 -0
- package/dist/compiler/training/container/contract.js +23 -5
- package/dist/compiler/training/container/evaluators.d.ts +48 -0
- package/dist/compiler/training/container/evaluators.js +50 -0
- package/dist/compiler/training/container/grokWriteback.d.ts +8 -0
- package/dist/compiler/training/container/grokWriteback.js +26 -0
- package/dist/compiler/training/container/index.d.ts +2 -1
- package/dist/compiler/training/container/index.js +2 -1
- package/dist/compiler/training/container/launch.d.ts +3 -0
- package/dist/compiler/training/container/launch.js +119 -28
- package/dist/compiler/training/container/nativeSlots.d.ts +14 -0
- package/dist/compiler/training/container/nativeSlots.js +13 -0
- package/dist/compiler/training/container/outputCopy.d.ts +2 -0
- package/dist/compiler/training/container/outputCopy.js +72 -0
- package/dist/compiler/training/container/outputVolume.d.ts +27 -0
- package/dist/compiler/training/container/outputVolume.js +161 -0
- package/dist/compiler/training/container/prepare.d.ts +3 -1
- package/dist/compiler/training/container/prepare.js +57 -12
- package/dist/compiler/training/container/security.d.ts +5 -3
- package/dist/compiler/training/container/security.js +15 -5
- package/dist/compiler/training/container/subjectIsolation.d.ts +5 -0
- package/dist/compiler/training/container/subjectIsolation.js +15 -0
- package/dist/compiler/training/context.d.ts +8 -0
- package/dist/compiler/training/context.js +12 -12
- package/dist/compiler/training/contract.d.ts +2 -0
- package/dist/compiler/training/contract.js +2 -0
- package/dist/compiler/training/execution.d.ts +417 -0
- package/dist/compiler/training/execution.js +160 -0
- package/dist/compiler/training/index.d.ts +8 -0
- package/dist/compiler/training/index.js +7 -0
- package/dist/compiler/training/moments.d.ts +80 -0
- package/dist/compiler/training/moments.js +118 -0
- package/dist/compiler/training/output.d.ts +2 -0
- package/dist/compiler/training/output.js +20 -0
- package/dist/compiler/training/plan/contract.d.ts +287 -0
- package/dist/compiler/training/plan/contract.js +49 -0
- package/dist/compiler/training/plan/index.d.ts +5 -0
- package/dist/compiler/training/plan/index.js +4 -0
- package/dist/compiler/training/plan/load.d.ts +9 -0
- package/dist/compiler/training/plan/load.js +153 -0
- package/dist/compiler/training/plan/references.d.ts +19 -0
- package/dist/compiler/training/plan/references.js +57 -0
- package/dist/compiler/training/plan/resolve.d.ts +4 -0
- package/dist/compiler/training/plan/resolve.js +73 -0
- package/dist/compiler/training/plan/targets.d.ts +11 -0
- package/dist/compiler/training/plan/targets.js +71 -0
- package/dist/compiler/training/plan/types.d.ts +36 -0
- package/dist/compiler/training/plan/types.js +1 -0
- package/dist/compiler/training/preparation/assets/Dockerfile +13 -2
- package/dist/compiler/training/preparation/assets/package-lock.json +2 -2
- package/dist/compiler/training/preparation/broker.d.ts +3 -3
- package/dist/compiler/training/preparation/broker.js +6 -4
- package/dist/compiler/training/preparation/contract.d.ts +27 -2
- package/dist/compiler/training/preparation/contract.js +23 -4
- package/dist/compiler/training/preparation/files.d.ts +5 -1
- package/dist/compiler/training/preparation/files.js +76 -15
- package/dist/compiler/training/preparation/image.js +9 -4
- package/dist/compiler/training/preparation/inputs.d.ts +1 -0
- package/dist/compiler/training/preparation/inputs.js +18 -10
- package/dist/compiler/training/preparation/prepare.d.ts +5 -0
- package/dist/compiler/training/preparation/prepare.js +66 -29
- package/dist/compiler/training/preparation/scratch.d.ts +6 -17
- package/dist/compiler/training/preparation/scratch.js +89 -23
- package/dist/compiler/training/repair/contract.d.ts +338 -4
- package/dist/compiler/training/repair/contract.js +2 -0
- package/dist/compiler/training/repair/index.d.ts +1 -1
- package/dist/compiler/training/repair/index.js +1 -1
- package/dist/compiler/training/repair/prepare.d.ts +155 -3
- package/dist/compiler/training/repair/prepare.js +6 -2
- package/dist/compiler/training/repair/witness.d.ts +152 -3
- package/dist/compiler/training/repair/witness.js +8 -2
- package/dist/compiler/training/resolution.d.ts +25 -0
- package/dist/compiler/training/resolution.js +69 -0
- package/dist/compiler/training/rewind/contract.d.ts +321 -0
- package/dist/compiler/training/rewind/contract.js +39 -0
- package/dist/compiler/training/rewind/deployedResource.d.ts +22 -0
- package/dist/compiler/training/rewind/deployedResource.js +19 -0
- package/dist/compiler/training/rewind/feed.d.ts +12 -0
- package/dist/compiler/training/rewind/feed.js +182 -0
- package/dist/compiler/training/rewind/feedContent.d.ts +6 -0
- package/dist/compiler/training/rewind/feedContent.js +38 -0
- package/dist/compiler/training/rewind/git.d.ts +8 -0
- package/dist/compiler/training/rewind/git.js +159 -0
- package/dist/compiler/training/rewind/gitArchive.d.ts +2 -0
- package/dist/compiler/training/rewind/gitArchive.js +7 -0
- package/dist/compiler/training/rewind/gitHistory.d.ts +3 -0
- package/dist/compiler/training/rewind/gitHistory.js +55 -0
- package/dist/compiler/training/rewind/gitProcess.d.ts +19 -0
- package/dist/compiler/training/rewind/gitProcess.js +81 -0
- package/dist/compiler/training/rewind/gitTree.d.ts +14 -0
- package/dist/compiler/training/rewind/gitTree.js +90 -0
- package/dist/compiler/training/rewind/history.d.ts +28 -0
- package/dist/compiler/training/rewind/history.js +239 -0
- package/dist/compiler/training/rewind/index.d.ts +18 -0
- package/dist/compiler/training/rewind/index.js +15 -0
- package/dist/compiler/training/rewind/inputs.d.ts +9 -0
- package/dist/compiler/training/rewind/inputs.js +67 -0
- package/dist/compiler/training/rewind/instant.d.ts +4 -0
- package/dist/compiler/training/rewind/instant.js +24 -0
- package/dist/compiler/training/rewind/leakCheck.d.ts +10 -0
- package/dist/compiler/training/rewind/leakCheck.js +56 -0
- package/dist/compiler/training/rewind/leakFeed.d.ts +5 -0
- package/dist/compiler/training/rewind/leakFeed.js +25 -0
- package/dist/compiler/training/rewind/leakFiles.d.ts +10 -0
- package/dist/compiler/training/rewind/leakFiles.js +106 -0
- package/dist/compiler/training/rewind/leakGit.d.ts +3 -0
- package/dist/compiler/training/rewind/leakGit.js +78 -0
- package/dist/compiler/training/rewind/leakGitPayload.d.ts +4 -0
- package/dist/compiler/training/rewind/leakGitPayload.js +57 -0
- package/dist/compiler/training/rewind/leakInputs.d.ts +7 -0
- package/dist/compiler/training/rewind/leakInputs.js +135 -0
- package/dist/compiler/training/rewind/leakLayout.d.ts +2 -0
- package/dist/compiler/training/rewind/leakLayout.js +17 -0
- package/dist/compiler/training/rewind/leakProvenance.d.ts +3 -0
- package/dist/compiler/training/rewind/leakProvenance.js +88 -0
- package/dist/compiler/training/rewind/materialize.d.ts +136 -0
- package/dist/compiler/training/rewind/materialize.js +212 -0
- package/dist/compiler/training/rewind/memory.d.ts +10 -0
- package/dist/compiler/training/rewind/memory.js +84 -0
- package/dist/compiler/training/rewind/memorySchemas.d.ts +87 -0
- package/dist/compiler/training/rewind/memorySchemas.js +50 -0
- package/dist/compiler/training/rewind/moltnet.d.ts +2 -0
- package/dist/compiler/training/rewind/moltnet.js +54 -0
- package/dist/compiler/training/rewind/moltnetJson.d.ts +13 -0
- package/dist/compiler/training/rewind/moltnetJson.js +180 -0
- package/dist/compiler/training/rewind/moltnetSchemas.d.ts +1226 -0
- package/dist/compiler/training/rewind/moltnetSchemas.js +75 -0
- package/dist/compiler/training/rewind/moltnetSqlite.d.ts +31 -0
- package/dist/compiler/training/rewind/moltnetSqlite.js +192 -0
- package/dist/compiler/training/rewind/moltnetSqliteData.d.ts +10 -0
- package/dist/compiler/training/rewind/moltnetSqliteData.js +113 -0
- package/dist/compiler/training/rewind/recordInput.d.ts +40 -0
- package/dist/compiler/training/rewind/recordInput.js +49 -0
- package/dist/compiler/training/rewind/recordedBundle.d.ts +4 -0
- package/dist/compiler/training/rewind/recordedBundle.js +58 -0
- package/dist/compiler/training/rewind/recordedCommit.d.ts +2 -0
- package/dist/compiler/training/rewind/recordedCommit.js +10 -0
- package/dist/compiler/training/rewind/select.d.ts +18 -0
- package/dist/compiler/training/rewind/select.js +64 -0
- package/dist/compiler/training/rewind/snapshotManifest.d.ts +42 -0
- package/dist/compiler/training/rewind/snapshotManifest.js +134 -0
- package/dist/compiler/training/rewind/taskClock.d.ts +12 -0
- package/dist/compiler/training/rewind/taskClock.js +40 -0
- package/dist/compiler/training/rewind/timestamps.d.ts +4 -0
- package/dist/compiler/training/rewind/timestamps.js +26 -0
- package/dist/compiler/training/rewind/types.d.ts +43 -0
- package/dist/compiler/training/rewind/types.js +1 -0
- package/dist/compiler/training/rewind/volumes.d.ts +12 -0
- package/dist/compiler/training/rewind/volumes.js +58 -0
- package/dist/compiler/training/selection.d.ts +7 -0
- package/dist/compiler/training/selection.js +15 -0
- package/dist/compiler/types.d.ts +6 -3
- package/dist/compiler/upProject.d.ts +1 -0
- package/dist/compiler/upProject.js +21 -5
- package/dist/compiler/workspaceBundleArtifacts.d.ts +16 -1
- package/dist/compiler/workspaceBundleArtifacts.js +69 -20
- package/dist/compiler/workspaceBundleCache.d.ts +23 -0
- package/dist/compiler/workspaceBundleCache.js +79 -0
- package/dist/compiler/workspaceBundleDependencies.d.ts +21 -0
- package/dist/compiler/workspaceBundleDependencies.js +122 -0
- package/dist/compiler/workspaceBundleFiles.d.ts +51 -0
- package/dist/compiler/workspaceBundleFiles.js +251 -0
- package/dist/compiler/workspaceBundleGenerated.d.ts +25 -0
- package/dist/compiler/workspaceBundleGenerated.js +103 -0
- package/dist/compiler/workspaceBundleGit.d.ts +64 -0
- package/dist/compiler/workspaceBundleGit.js +154 -0
- package/dist/compiler/workspaceBundleKey.d.ts +34 -0
- package/dist/compiler/workspaceBundleKey.js +17 -0
- package/dist/compiler/workspaceBundleResolve.d.ts +56 -0
- package/dist/compiler/workspaceBundleResolve.js +144 -0
- package/dist/compiler/workspaceBundleRun.d.ts +41 -0
- package/dist/compiler/workspaceBundleRun.js +79 -0
- package/dist/compiler/workspaceBundleTar.d.ts +47 -0
- package/dist/compiler/workspaceBundleTar.js +140 -0
- package/dist/compiler/workspaceBundleTree.d.ts +15 -0
- package/dist/compiler/workspaceBundleTree.js +58 -0
- package/dist/compiler/workspaceGitFetch.d.ts +41 -0
- package/dist/compiler/workspaceGitFetch.js +155 -0
- package/dist/compiler/workspaceGitPins.d.ts +33 -0
- package/dist/compiler/workspaceGitPins.js +127 -0
- package/dist/compiler/workspaceResources.d.ts +5 -1
- package/dist/compiler/workspaceResources.js +32 -5
- package/dist/deployment/activation.d.ts +3 -0
- package/dist/deployment/activation.js +12 -0
- package/dist/deployment/canaryCutover.d.ts +1 -1
- package/dist/deployment/candidateRecording.d.ts +8 -0
- package/dist/deployment/candidateRecording.js +22 -0
- package/dist/deployment/dockerManager.d.ts +5 -3
- package/dist/deployment/dockerManager.js +12 -2
- package/dist/deployment/downDeployment.d.ts +2 -0
- package/dist/deployment/downDeployment.js +6 -2
- package/dist/deployment/homeStore.d.ts +9 -1
- package/dist/deployment/homeStore.js +16 -53
- package/dist/deployment/index.d.ts +6 -0
- package/dist/deployment/index.js +6 -0
- package/dist/deployment/pidLock.d.ts +25 -0
- package/dist/deployment/pidLock.js +81 -0
- package/dist/deployment/record.d.ts +85 -1
- package/dist/deployment/record.js +11 -5
- package/dist/deployment/recordPublication.d.ts +15 -0
- package/dist/deployment/recordPublication.js +76 -0
- package/dist/deployment/recordedMemoryRetention.d.ts +18 -0
- package/dist/deployment/recordedMemoryRetention.js +27 -0
- package/dist/deployment/resourceLog.d.ts +140 -0
- package/dist/deployment/resourceLog.js +78 -0
- package/dist/distribution/buildDistributionReport.d.ts +3 -0
- package/dist/distribution/buildDistributionReport.js +5 -0
- package/dist/distribution/consumeImage.d.ts +3 -0
- package/dist/distribution/consumeImage.js +23 -31
- package/dist/distribution/consumeImageLifecycle.d.ts +4 -1
- package/dist/distribution/consumeImageLifecycle.js +14 -3
- package/dist/distribution/consumeImageSupport.d.ts +7 -0
- package/dist/distribution/consumeImageSupport.js +25 -0
- package/dist/distribution/distributionReportSchema.d.ts +47 -0
- package/dist/distribution/distributionReportSchema.js +20 -0
- package/dist/distribution/renderImageInterface.js +1 -1
- package/dist/distribution/types.d.ts +15 -0
- package/dist/filesystem/durableWrite.d.ts +10 -0
- package/dist/filesystem/durableWrite.js +87 -0
- package/dist/filesystem/index.d.ts +2 -0
- package/dist/filesystem/index.js +2 -0
- package/dist/filesystem/retainedJsonl.d.ts +23 -0
- package/dist/filesystem/retainedJsonl.js +123 -0
- package/dist/manifest/commandSchemas.d.ts +5 -0
- package/dist/manifest/commandSchemas.js +5 -0
- package/dist/manifest/executionSchemas.d.ts +20 -0
- package/dist/manifest/executionSchemas.js +13 -3
- package/dist/manifest/index.d.ts +2 -0
- package/dist/manifest/index.js +2 -0
- package/dist/manifest/loadManifest.js +3 -26
- package/dist/manifest/mcpSchemas.d.ts +61 -0
- package/dist/manifest/mcpSchemas.js +57 -11
- package/dist/manifest/memorySchemas.d.ts +1 -1
- package/dist/manifest/memorySchemas.js +1 -1
- package/dist/manifest/parseManifest.d.ts +7 -0
- package/dist/manifest/parseManifest.js +65 -0
- package/dist/manifest/renderSpawnfile.js +4 -1
- package/dist/manifest/renderSpawnfileWorkspace.js +6 -2
- package/dist/manifest/schemas.d.ts +1206 -132
- package/dist/manifest/schemas.js +14 -4
- package/dist/manifest/teamNetworkSchemas.d.ts +1 -1
- package/dist/manifest/trainingDataSchemas.d.ts +357 -0
- package/dist/manifest/trainingDataSchemas.js +31 -0
- package/dist/manifest/trainingSchemas.d.ts +49 -0
- package/dist/manifest/trainingSchemas.js +44 -0
- package/dist/manifest/volumeFeedSchemas.d.ts +52 -0
- package/dist/manifest/volumeFeedSchemas.js +104 -0
- package/dist/manifest/workspaceSchemas.d.ts +182 -5
- package/dist/manifest/workspaceSchemas.js +111 -7
- package/dist/recording/compose.d.ts +3 -0
- package/dist/recording/compose.js +93 -0
- package/dist/recording/deployment.d.ts +15 -0
- package/dist/recording/deployment.js +38 -0
- package/dist/recording/history.d.ts +16 -0
- package/dist/recording/history.js +47 -0
- package/dist/recording/index.d.ts +9 -0
- package/dist/recording/index.js +9 -0
- package/dist/recording/moment.d.ts +61 -0
- package/dist/recording/moment.js +36 -0
- package/dist/recording/parse.d.ts +15 -0
- package/dist/recording/parse.js +74 -0
- package/dist/recording/read.d.ts +8 -0
- package/dist/recording/read.js +61 -0
- package/dist/recording/store.d.ts +10 -0
- package/dist/recording/store.js +94 -0
- package/dist/recording/sync.d.ts +24 -0
- package/dist/recording/sync.js +126 -0
- package/dist/recording/types.d.ts +45 -0
- package/dist/recording/types.js +2 -0
- package/dist/release/drainControl.d.ts +54 -0
- package/dist/release/drainControl.js +137 -0
- package/dist/release/drainPhase.d.ts +37 -0
- package/dist/release/drainPhase.js +161 -0
- package/dist/release/index.d.ts +11 -0
- package/dist/release/index.js +11 -0
- package/dist/release/ledger.d.ts +75 -0
- package/dist/release/ledger.js +111 -0
- package/dist/release/notify.d.ts +58 -0
- package/dist/release/notify.js +126 -0
- package/dist/release/pending.d.ts +35 -0
- package/dist/release/pending.js +60 -0
- package/dist/release/postDeploy.d.ts +32 -0
- package/dist/release/postDeploy.js +62 -0
- package/dist/release/releaseDefaults.d.ts +9 -0
- package/dist/release/releaseDefaults.js +115 -0
- package/dist/release/releaseDocker.d.ts +38 -0
- package/dist/release/releaseDocker.js +94 -0
- package/dist/release/releaseTypes.d.ts +94 -0
- package/dist/release/releaseTypes.js +1 -0
- package/dist/release/runRelease.d.ts +9 -0
- package/dist/release/runRelease.js +218 -0
- package/dist/release/swap.d.ts +23 -0
- package/dist/release/swap.js +55 -0
- package/dist/release/types.d.ts +50 -0
- package/dist/release/types.js +29 -0
- package/dist/report/index.d.ts +1 -0
- package/dist/report/index.js +1 -0
- package/dist/report/recording.d.ts +57 -0
- package/dist/report/recording.js +26 -0
- package/dist/report/types.d.ts +58 -0
- package/dist/runtime/container.js +8 -13
- package/dist/runtime/daimon/adapter.js +15 -4
- package/dist/runtime/daimon/config.d.ts +4 -0
- package/dist/runtime/daimon/config.js +53 -4
- package/dist/runtime/daimon/contract-manifest.json +1 -0
- package/dist/runtime/daimon/contract-manifest.sha256 +1 -0
- package/dist/runtime/daimon/contractManifest.d.ts +59 -8
- package/dist/runtime/daimon/contractManifest.js +26 -10
- package/dist/runtime/daimon/grokTurnLimits.d.ts +25 -0
- package/dist/runtime/daimon/grokTurnLimits.js +51 -0
- package/dist/runtime/daimon/grokWorkerConfigBytes.d.ts +17 -0
- package/dist/runtime/daimon/grokWorkerConfigBytes.js +17 -0
- package/dist/runtime/daimon/grokWorkerContract.d.ts +5 -0
- package/dist/runtime/daimon/grokWorkerContract.js +13 -1
- package/dist/runtime/daimon/recording.d.ts +19 -0
- package/dist/runtime/daimon/recording.js +50 -0
- package/dist/runtime/daimon/scheduleAuthority.d.ts +8 -0
- package/dist/runtime/daimon/scheduleAuthority.js +19 -5
- package/dist/runtime/daimon/wakeMoments.d.ts +15 -0
- package/dist/runtime/daimon/wakeMoments.js +17 -0
- package/dist/runtime/daimonInstall.d.ts +3 -0
- package/dist/runtime/daimonInstall.js +25 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/install.d.ts +2 -0
- package/dist/runtime/install.js +1 -0
- package/dist/runtime/openclaw/adapter.js +3 -0
- package/dist/runtime/pi/adapter.js +3 -0
- package/dist/runtime/pi/containerTargets.js +6 -0
- package/dist/runtime/picoclaw/adapter.js +3 -0
- package/dist/runtime/registry.d.ts +3 -0
- package/dist/runtime/registry.js +13 -1
- package/dist/runtime/types.d.ts +15 -0
- package/dist/runtime/usageLedgerRead.d.ts +6 -0
- package/dist/runtime/usageLedgerRead.js +3 -3
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.js +1 -0
- package/dist/shared/recording.d.ts +8 -0
- package/dist/shared/recording.js +25 -0
- package/dist/target/dockerCommandExecutorCore.js +1 -1
- package/dist/target/dockerTargetBinding.js +2 -1
- package/dist/volume/feedLand.d.ts +31 -0
- package/dist/volume/feedLand.js +174 -0
- package/dist/volume/feedLandings.d.ts +45 -0
- package/dist/volume/feedLandings.js +111 -0
- package/dist/volume/feedLayout.d.ts +61 -0
- package/dist/volume/feedLayout.js +234 -0
- package/dist/volume/feedLock.d.ts +7 -0
- package/dist/volume/feedLock.js +131 -0
- package/dist/volume/feedManifest.d.ts +27 -0
- package/dist/volume/feedManifest.js +123 -0
- package/dist/volume/feedPrepare.d.ts +16 -0
- package/dist/volume/feedPrepare.js +228 -0
- package/dist/volume/feedProject.d.ts +39 -0
- package/dist/volume/feedProject.js +92 -0
- package/dist/volume/feedRecord.d.ts +55 -0
- package/dist/volume/feedRecord.js +148 -0
- package/dist/volume/feedRef.d.ts +43 -0
- package/dist/volume/feedRef.js +117 -0
- package/dist/volume/feedRefresh.d.ts +15 -0
- package/dist/volume/feedRefresh.js +187 -0
- package/dist/volume/feedSource.d.ts +66 -0
- package/dist/volume/feedSource.js +104 -0
- package/dist/volume/feedTarget.d.ts +70 -0
- package/dist/volume/feedTarget.js +9 -0
- package/dist/volume/feedTestKit.d.ts +11 -0
- package/dist/volume/feedTestKit.js +45 -0
- package/dist/volume/feedVerify.d.ts +18 -0
- package/dist/volume/feedVerify.js +104 -0
- package/dist/volume/index.d.ts +13 -0
- package/dist/volume/index.js +13 -0
- package/moltnet-releases.json +4 -4
- package/package.json +3 -3
- package/runtimes.yaml +8 -6
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { chmod, lstat, mkdir, readFile, readdir, readlink, realpath, symlink, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { momentRecordSchema, parseMomentRecord, parseWakeMoments } from "../../../recording/index.js";
|
|
4
|
+
import { deployResourceLogPath, deployResourcesAt, deployResourcesSchema } from "../../../deployment/index.js";
|
|
5
|
+
import { readFeedLandings } from "../../../volume/index.js";
|
|
6
|
+
export const inside = (root, target) => {
|
|
7
|
+
const relative = path.relative(root, target);
|
|
8
|
+
return relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
|
|
9
|
+
};
|
|
10
|
+
export const safeSegment = (value) => {
|
|
11
|
+
if (!value || value === "." || value === ".." || /[/\\\0]/u.test(value))
|
|
12
|
+
throw new Error(`Unsafe history identity ${JSON.stringify(value)}`);
|
|
13
|
+
return value;
|
|
14
|
+
};
|
|
15
|
+
export const historyKey = (identity) => `${safeSegment(encodeURIComponent(identity.declaredBy))}/${safeSegment(identity.id)}`;
|
|
16
|
+
const reason = (error) => error instanceof Error ? error.message : String(error);
|
|
17
|
+
/** All reads of the consumer history layout pass through this containment boundary. */
|
|
18
|
+
export class History {
|
|
19
|
+
root;
|
|
20
|
+
constructor(root) { this.root = root; }
|
|
21
|
+
async path(relative) {
|
|
22
|
+
if (path.isAbsolute(relative) || relative.includes("\\") || relative.includes("\0"))
|
|
23
|
+
throw new Error(`Unsafe history path ${relative}`);
|
|
24
|
+
const target = path.resolve(this.root, relative);
|
|
25
|
+
if (!inside(this.root, target))
|
|
26
|
+
throw new Error(`History path escapes root: ${relative}`);
|
|
27
|
+
let ancestor = target;
|
|
28
|
+
while (true) {
|
|
29
|
+
try {
|
|
30
|
+
const physical = await realpath(ancestor);
|
|
31
|
+
if (!inside(this.root, physical))
|
|
32
|
+
throw new Error(`History symlink escape: ${relative}`);
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (error.code !== "ENOENT")
|
|
37
|
+
throw error;
|
|
38
|
+
if (ancestor === this.root)
|
|
39
|
+
throw new Error(`History root no longer exists: ${this.root}`);
|
|
40
|
+
ancestor = path.dirname(ancestor);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
await lstat(target);
|
|
45
|
+
// A dangling symlink is not a missing history entry.
|
|
46
|
+
const physical = await realpath(target);
|
|
47
|
+
if (!inside(this.root, physical))
|
|
48
|
+
throw new Error(`History symlink escape: ${relative}`);
|
|
49
|
+
return target;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (error.code !== "ENOENT")
|
|
53
|
+
throw error;
|
|
54
|
+
const entry = await lstat(target).catch(() => null);
|
|
55
|
+
if (entry?.isSymbolicLink())
|
|
56
|
+
throw new Error(`Dangling history symlink: ${relative}`);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async bytes(relative) {
|
|
61
|
+
const file = await this.path(relative);
|
|
62
|
+
if (file === null)
|
|
63
|
+
return null;
|
|
64
|
+
if (!(await lstat(await realpath(file))).isFile())
|
|
65
|
+
throw new Error(`History entry must be a regular file: ${relative}`);
|
|
66
|
+
return readFile(file);
|
|
67
|
+
}
|
|
68
|
+
async text(relative) { return (await this.bytes(relative))?.toString("utf8") ?? null; }
|
|
69
|
+
async jsonl(relative, schema) {
|
|
70
|
+
const payload = await this.text(relative);
|
|
71
|
+
if (payload === null)
|
|
72
|
+
return null;
|
|
73
|
+
const lines = payload.split("\n");
|
|
74
|
+
if (lines.at(-1) === "")
|
|
75
|
+
lines.pop();
|
|
76
|
+
return lines.map((line, index) => {
|
|
77
|
+
try {
|
|
78
|
+
return schema.parse(JSON.parse(line));
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
throw new Error(`Invalid history ${relative}:${index + 1}: ${reason(error)}`);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
async feedLandings(key, resource) {
|
|
86
|
+
const relative = `${key}/landings.jsonl`, file = await this.path(relative);
|
|
87
|
+
if (!file)
|
|
88
|
+
return [];
|
|
89
|
+
if (!(await lstat(await realpath(file))).isFile())
|
|
90
|
+
throw new Error(`History entry must be a regular file: ${relative}`);
|
|
91
|
+
const result = readFeedLandings(path.dirname(file));
|
|
92
|
+
if (result.errors.length)
|
|
93
|
+
throw new Error(`Invalid history ${result.errors.map((error) => `${relative}:${error.replace(/^(?:wake moments )?line /u, "")}`).join("; ")}`);
|
|
94
|
+
result.entries.forEach((entry, index) => {
|
|
95
|
+
if (entry.resource !== resource)
|
|
96
|
+
throw new Error(`Invalid history ${relative}:${index + 1}: Landing resource disagrees with the history input`);
|
|
97
|
+
});
|
|
98
|
+
return result.entries;
|
|
99
|
+
}
|
|
100
|
+
async wakeMoments(relative) {
|
|
101
|
+
const payload = await this.text(relative);
|
|
102
|
+
if (payload === null)
|
|
103
|
+
return null;
|
|
104
|
+
const result = parseWakeMoments(payload);
|
|
105
|
+
if (result.errors.length)
|
|
106
|
+
throw new Error(`Invalid history ${result.errors.map((error) => `${relative}:${error.replace(/^(?:wake moments )?line /u, "")}`).join("; ")}`);
|
|
107
|
+
return result.entries;
|
|
108
|
+
}
|
|
109
|
+
/** One imported deployment, preserving its original absolute identity without opening that path. */
|
|
110
|
+
async deploymentResources(at, agentId) {
|
|
111
|
+
const directory = await this.path("deployments");
|
|
112
|
+
if (!directory)
|
|
113
|
+
return null;
|
|
114
|
+
const logs = [];
|
|
115
|
+
for (const name of (await readdir(directory)).sort()) {
|
|
116
|
+
const relative = `deployments/${name}`, entry = await this.path(relative);
|
|
117
|
+
if (!entry)
|
|
118
|
+
throw new Error(`History entry vanished: ${relative}`);
|
|
119
|
+
if (name.endsWith(".resource-log.jsonl"))
|
|
120
|
+
logs.push(relative);
|
|
121
|
+
else if ((await lstat(await realpath(entry))).isDirectory() && await this.path(`${relative}/resource-log.jsonl`))
|
|
122
|
+
logs.push(`${relative}/resource-log.jsonl`);
|
|
123
|
+
}
|
|
124
|
+
if (!logs.length)
|
|
125
|
+
return null;
|
|
126
|
+
if (logs.length !== 1)
|
|
127
|
+
throw new Error("Rewind history must contain one deployment resource log; multiple deployments are ambiguous");
|
|
128
|
+
const relative = logs[0], entries = await this.jsonl(relative, deployResourcesSchema) ?? [];
|
|
129
|
+
if (!entries.length)
|
|
130
|
+
return null;
|
|
131
|
+
const identities = new Set(entries.map((entry) => entry.deployment_id));
|
|
132
|
+
const recordPath = entries[0].deployment_id;
|
|
133
|
+
if (identities.size !== 1 || !path.isAbsolute(recordPath) || path.resolve(recordPath) !== recordPath) {
|
|
134
|
+
throw new Error(`Invalid history ${relative}: expected one canonical deployment_id`);
|
|
135
|
+
}
|
|
136
|
+
const originalLog = deployResourceLogPath(recordPath);
|
|
137
|
+
const mirror = path.basename(recordPath) === "record.json"
|
|
138
|
+
? `deployments/${path.basename(path.dirname(recordPath))}/${path.basename(originalLog)}`
|
|
139
|
+
: `deployments/${path.basename(originalLog)}`;
|
|
140
|
+
if (relative !== mirror)
|
|
141
|
+
throw new Error(`Invalid history ${relative}: deployment_id requires ${mirror}`);
|
|
142
|
+
if (!agentId)
|
|
143
|
+
throw new Error("Deployment resource lookup requires the compiled agent ID");
|
|
144
|
+
return deployResourcesAt(entries, recordPath, at, agentId);
|
|
145
|
+
}
|
|
146
|
+
async records() {
|
|
147
|
+
const directory = await this.path("moments");
|
|
148
|
+
if (!directory)
|
|
149
|
+
return [];
|
|
150
|
+
const records = [];
|
|
151
|
+
const seen = new Set();
|
|
152
|
+
const walk = async (relative) => {
|
|
153
|
+
const file = await this.path(relative);
|
|
154
|
+
if (!file)
|
|
155
|
+
throw new Error(`History entry vanished: ${relative}`);
|
|
156
|
+
const physical = await realpath(file);
|
|
157
|
+
if ((await lstat(physical)).isDirectory()) {
|
|
158
|
+
if (seen.has(physical))
|
|
159
|
+
throw new Error(`Repeated moment history directory: ${relative}`);
|
|
160
|
+
seen.add(physical);
|
|
161
|
+
for (const name of (await readdir(file)).sort())
|
|
162
|
+
await walk(`${relative}/${name}`);
|
|
163
|
+
}
|
|
164
|
+
else if (relative.endsWith(".jsonl"))
|
|
165
|
+
records.push(...(await this.jsonl(relative, momentRecordSchema) ?? []));
|
|
166
|
+
else if (relative.endsWith(".json")) {
|
|
167
|
+
try {
|
|
168
|
+
records.push(parseMomentRecord((await this.text(relative))));
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
throw new Error(`Invalid history ${relative}: ${reason(error)}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
await walk("moments");
|
|
176
|
+
return records;
|
|
177
|
+
}
|
|
178
|
+
/** Validate all tree entries before git or another local parser receives the directory. */
|
|
179
|
+
async repository(relative) {
|
|
180
|
+
const root = await this.path(relative);
|
|
181
|
+
if (!root)
|
|
182
|
+
return null;
|
|
183
|
+
const seen = new Set();
|
|
184
|
+
const walk = async (entry) => {
|
|
185
|
+
const file = await this.path(entry);
|
|
186
|
+
if (!file)
|
|
187
|
+
throw new Error(`History entry vanished: ${entry}`);
|
|
188
|
+
const physical = await realpath(file), stats = await lstat(physical);
|
|
189
|
+
if (seen.has(physical))
|
|
190
|
+
return;
|
|
191
|
+
seen.add(physical);
|
|
192
|
+
if (stats.isDirectory())
|
|
193
|
+
for (const name of await readdir(file))
|
|
194
|
+
await walk(`${entry}/${name}`);
|
|
195
|
+
else if (!stats.isFile())
|
|
196
|
+
throw new Error(`Special history file: ${entry}`);
|
|
197
|
+
};
|
|
198
|
+
await walk(relative);
|
|
199
|
+
return root;
|
|
200
|
+
}
|
|
201
|
+
async copyTree(relative, destination) {
|
|
202
|
+
const source = await this.path(relative);
|
|
203
|
+
if (!source)
|
|
204
|
+
throw new Error(`Missing retained tree: ${relative}`);
|
|
205
|
+
const stats = await lstat(source);
|
|
206
|
+
if (!stats.isDirectory())
|
|
207
|
+
throw new Error(`Retained tree must be a real directory: ${relative}`);
|
|
208
|
+
const copy = async (entry, target) => {
|
|
209
|
+
const file = await this.path(entry);
|
|
210
|
+
if (!file)
|
|
211
|
+
throw new Error(`History entry vanished: ${entry}`);
|
|
212
|
+
const stat = await lstat(file);
|
|
213
|
+
if (stat.isSymbolicLink()) {
|
|
214
|
+
await symlink(await readlink(file), target);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (stat.isDirectory()) {
|
|
218
|
+
await mkdir(target, { recursive: true });
|
|
219
|
+
for (const name of (await readdir(file)).sort())
|
|
220
|
+
await copy(`${entry}/${name}`, path.join(target, name));
|
|
221
|
+
}
|
|
222
|
+
else if (stat.isFile()) {
|
|
223
|
+
await writeFile(target, (await this.bytes(entry)));
|
|
224
|
+
await chmod(target, stat.mode & 0o777);
|
|
225
|
+
}
|
|
226
|
+
else
|
|
227
|
+
throw new Error(`Special history file: ${entry}`);
|
|
228
|
+
};
|
|
229
|
+
await copy(relative, destination);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
export const openHistory = async (directory) => {
|
|
233
|
+
if (directory === undefined)
|
|
234
|
+
return undefined;
|
|
235
|
+
const root = await realpath(path.resolve(directory));
|
|
236
|
+
if (!(await lstat(root)).isDirectory())
|
|
237
|
+
throw new Error(`History must be a directory: ${directory}`);
|
|
238
|
+
return new History(root);
|
|
239
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export * from "./contract.js";
|
|
2
|
+
export * from "./history.js";
|
|
3
|
+
export * from "./inputs.js";
|
|
4
|
+
export * from "./instant.js";
|
|
5
|
+
export * from "./leakCheck.js";
|
|
6
|
+
export * from "./materialize.js";
|
|
7
|
+
export * from "./select.js";
|
|
8
|
+
export * from "./taskClock.js";
|
|
9
|
+
export { feedLandingAt } from "../../../volume/index.js";
|
|
10
|
+
export { selectFeedCommit } from "./feed.js";
|
|
11
|
+
export { selectCommitAt } from "./gitProcess.js";
|
|
12
|
+
export { selectMemoryPrefix, parseMemoryLedger } from "./memory.js";
|
|
13
|
+
export { rewindMoltnetJson } from "./moltnetJson.js";
|
|
14
|
+
export { selectVolumeSnapshot } from "./volumes.js";
|
|
15
|
+
export type * from "./types.js";
|
|
16
|
+
export { inspectMoltnetSqlite } from "./moltnetSqlite.js";
|
|
17
|
+
export type { MoltnetMessageFilter, MoltnetSqliteInspection } from "./moltnetSqlite.js";
|
|
18
|
+
export type { MoltnetMessage } from "./moltnetSchemas.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./contract.js";
|
|
2
|
+
export * from "./history.js";
|
|
3
|
+
export * from "./inputs.js";
|
|
4
|
+
export * from "./instant.js";
|
|
5
|
+
export * from "./leakCheck.js";
|
|
6
|
+
export * from "./materialize.js";
|
|
7
|
+
export * from "./select.js";
|
|
8
|
+
export * from "./taskClock.js";
|
|
9
|
+
export { feedLandingAt } from "../../../volume/index.js";
|
|
10
|
+
export { selectFeedCommit } from "./feed.js";
|
|
11
|
+
export { selectCommitAt } from "./gitProcess.js";
|
|
12
|
+
export { selectMemoryPrefix, parseMemoryLedger } from "./memory.js";
|
|
13
|
+
export { rewindMoltnetJson } from "./moltnetJson.js";
|
|
14
|
+
export { selectVolumeSnapshot } from "./volumes.js";
|
|
15
|
+
export { inspectMoltnetSqlite } from "./moltnetSqlite.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LoadedTrainingProject, TrainingPlan } from "../plan/index.js";
|
|
2
|
+
import type { RewindInput } from "./types.js";
|
|
3
|
+
/** The same compiled resources, accessible bank sources and surface attachments P2 resolves. */
|
|
4
|
+
export declare const resolveRewindInputs: (plan: TrainingPlan, project: LoadedTrainingProject, selector: string) => {
|
|
5
|
+
inputs: RewindInput[];
|
|
6
|
+
selected: import("./select.js").SelectedExample;
|
|
7
|
+
at: string;
|
|
8
|
+
agentSlug: string;
|
|
9
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { resolveTrainingOverride, resolveTrainingResource } from "../plan/references.js";
|
|
3
|
+
import { selectTrainingExample } from "./select.js";
|
|
4
|
+
import { normalizeInstant } from "./instant.js";
|
|
5
|
+
/** The same compiled resources, accessible bank sources and surface attachments P2 resolves. */
|
|
6
|
+
export const resolveRewindInputs = (plan, project, selector) => {
|
|
7
|
+
const selected = selectTrainingExample(plan, selector);
|
|
8
|
+
const agent = project.compilePlan.nodes.find((node) => node.value.kind === "agent" && node.id === plan.agent.id);
|
|
9
|
+
if (!agent)
|
|
10
|
+
throw new Error(`No compiled training agent ${plan.agent.id}`);
|
|
11
|
+
const raw = project.datasets[selected.sourcePath]?.value.examples.find((example) => example.id === selected.id);
|
|
12
|
+
if (!raw || normalizeInstant(raw.at) !== normalizeInstant(selected.example.at))
|
|
13
|
+
throw new Error(`Loaded example disagrees with plan: ${selector}`);
|
|
14
|
+
const inputs = [];
|
|
15
|
+
const declarationBase = (id) => {
|
|
16
|
+
const node = project.compilePlan.nodes.find((candidate) => candidate.id === id);
|
|
17
|
+
if (!node)
|
|
18
|
+
throw new Error(`Missing declaring node ${id}`);
|
|
19
|
+
return path.dirname(node.value.kind === "agent" ? node.value.sourcePath ?? node.value.source : node.value.source);
|
|
20
|
+
};
|
|
21
|
+
for (const resource of agent.value.workspaceResources ?? []) {
|
|
22
|
+
const { declaredBy } = resolveTrainingResource(project.compilePlan, agent, resource.id, "Rewind resource");
|
|
23
|
+
inputs.push({ section: "resources", id: resource.id, declaredBy, declarationBase: declarationBase(declaredBy),
|
|
24
|
+
declaration: resource, overridden: false });
|
|
25
|
+
}
|
|
26
|
+
const banks = new Set();
|
|
27
|
+
for (const entry of agent.value.memoryAccess ?? []) {
|
|
28
|
+
const key = JSON.stringify([entry.source, entry.bank.id]);
|
|
29
|
+
if (banks.has(key))
|
|
30
|
+
continue;
|
|
31
|
+
banks.add(key);
|
|
32
|
+
const node = project.compilePlan.nodes.find((candidate) => candidate.value.source === entry.source);
|
|
33
|
+
if (!node)
|
|
34
|
+
throw new Error(`Memory bank ${entry.bank.id} has no declaring node`);
|
|
35
|
+
inputs.push({ section: "memory", id: entry.bank.id, declaredBy: node.id,
|
|
36
|
+
declarationBase: declarationBase(node.id), declaration: entry.bank, overridden: false });
|
|
37
|
+
}
|
|
38
|
+
const networks = new Set();
|
|
39
|
+
for (const attachment of agent.value.surfaces?.moltnet ?? []) {
|
|
40
|
+
const sources = new Set([attachment.teamSource, ...Object.keys(attachment.contextRooms ?? {})]);
|
|
41
|
+
for (const node of project.compilePlan.nodes) {
|
|
42
|
+
if (node.value.kind !== "team" || !sources.has(node.value.source))
|
|
43
|
+
continue;
|
|
44
|
+
for (const network of node.value.networks ?? []) {
|
|
45
|
+
if (network.id !== attachment.network)
|
|
46
|
+
continue;
|
|
47
|
+
const key = JSON.stringify([node.id, network.id]);
|
|
48
|
+
if (networks.has(key))
|
|
49
|
+
continue;
|
|
50
|
+
networks.add(key);
|
|
51
|
+
inputs.push({ section: "networks", id: network.id, declaredBy: node.id,
|
|
52
|
+
declarationBase: declarationBase(node.id), declaration: network, overridden: false });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (const section of ["resources", "memory", "networks"]) {
|
|
57
|
+
for (const declaration of raw[section] ?? []) {
|
|
58
|
+
const identity = resolveTrainingOverride(project.compilePlan, agent, section, declaration.id, `Rewind override ${selector}`);
|
|
59
|
+
const index = inputs.findIndex((input) => input.section === section && input.id === identity.id && input.declaredBy === identity.declaredBy);
|
|
60
|
+
if (index === -1)
|
|
61
|
+
throw new Error(`Missing effective override ${section}:${identity.id}`);
|
|
62
|
+
inputs[index] = { ...inputs[index], declaration, declarationBase: path.dirname(selected.sourcePath), overridden: true };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
inputs.sort((a, b) => a.section.localeCompare(b.section) || a.declaredBy.localeCompare(b.declaredBy) || a.id.localeCompare(b.id));
|
|
66
|
+
return { inputs, selected, at: normalizeInstant(raw.at), agentSlug: agent.slug };
|
|
67
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** RFC3339Nano ordering, including offsets and fractions Date.parse would truncate. */
|
|
2
|
+
export declare const instantNanos: (value: string) => bigint;
|
|
3
|
+
export declare const compareInstants: (left: string, right: string) => number;
|
|
4
|
+
export declare const normalizeInstant: (value: string) => string;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { trainingInstantSchema } from "../../../manifest/index.js";
|
|
2
|
+
/** RFC3339Nano ordering, including offsets and fractions Date.parse would truncate. */
|
|
3
|
+
export const instantNanos = (value) => {
|
|
4
|
+
trainingInstantSchema.parse(value);
|
|
5
|
+
const match = /^(.*T\d{2}:\d{2})(?::(\d{2})(?:\.(\d{1,9}))?)?(Z|[+-]\d{2}:\d{2})$/u.exec(value);
|
|
6
|
+
if (!match)
|
|
7
|
+
throw new Error(`Unsupported instant ${value}: at most nanosecond precision is required`);
|
|
8
|
+
const seconds = Date.parse(`${match[1]}:${match[2] ?? "00"}${match[4]}`);
|
|
9
|
+
if (!Number.isFinite(seconds))
|
|
10
|
+
throw new Error(`Invalid instant ${value}`);
|
|
11
|
+
return BigInt(seconds) * 1000000n + BigInt((match[3] ?? "").padEnd(9, "0"));
|
|
12
|
+
};
|
|
13
|
+
export const compareInstants = (left, right) => {
|
|
14
|
+
const a = instantNanos(left), b = instantNanos(right);
|
|
15
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
16
|
+
};
|
|
17
|
+
export const normalizeInstant = (value) => {
|
|
18
|
+
const ns = instantNanos(value), seconds = ns / 1000000000n;
|
|
19
|
+
const fraction = (ns % 1000000000n + 1000000000n) % 1000000000n;
|
|
20
|
+
const floorSeconds = ns < 0n && fraction !== 0n ? seconds - 1n : seconds;
|
|
21
|
+
const base = new Date(Number(floorSeconds * 1000n)).toISOString().replace(/\.000Z$/u, "");
|
|
22
|
+
const tail = fraction.toString().padStart(9, "0").replace(/0+$/u, "");
|
|
23
|
+
return `${base}${tail ? `.${tail}` : ""}Z`;
|
|
24
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type LeakCheck, type MaterializedMoment } from "./contract.js";
|
|
2
|
+
export interface LeakCheckOptions {
|
|
3
|
+
historyDir?: string;
|
|
4
|
+
}
|
|
5
|
+
/** Independent acceptance boundary: only disk reports, disk payloads and disk history are trusted. */
|
|
6
|
+
export declare const inspectTrainingMoment: (bundle: string, options?: LeakCheckOptions, skipRefused?: boolean) => Promise<{
|
|
7
|
+
moment: MaterializedMoment;
|
|
8
|
+
check: LeakCheck | null;
|
|
9
|
+
}>;
|
|
10
|
+
export declare const leakCheckTrainingMoment: (bundle: string, options?: LeakCheckOptions) => Promise<LeakCheck>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { readFile, realpath } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { materializedMomentSchema, leakCheckSchema } from "./contract.js";
|
|
4
|
+
import { openHistory } from "./history.js";
|
|
5
|
+
import { diskPath, inspectBundleFiles, restoreInspectedAccessTimes, snapshotBundleFiles } from "./leakFiles.js";
|
|
6
|
+
import { inspectGitBundle } from "./leakGit.js";
|
|
7
|
+
import { inspectInputProvenance } from "./leakProvenance.js";
|
|
8
|
+
import { addInputFinding, inspectFeedBundle, inspectMemoryBundle, inspectMoltnetBundle, inspectVolumeBundle } from "./leakInputs.js";
|
|
9
|
+
/** Independent acceptance boundary: only disk reports, disk payloads and disk history are trusted. */
|
|
10
|
+
export const inspectTrainingMoment = async (bundle, options = {}, skipRefused = false) => {
|
|
11
|
+
const root = await realpath(path.resolve(bundle));
|
|
12
|
+
const files = await snapshotBundleFiles(root);
|
|
13
|
+
try {
|
|
14
|
+
const moment = materializedMomentSchema.parse(JSON.parse(await readFile(await diskPath(root, "moment.json"), "utf8")));
|
|
15
|
+
if (skipRefused && moment.status === "refused")
|
|
16
|
+
return { moment, check: null };
|
|
17
|
+
const report = { version: "spawnfile.leak-check.v1", at: moment.effectiveAt, ok: false,
|
|
18
|
+
checked: { files: 0, gitObjects: 0, memoryEvents: 0, moltnetMessages: 0, moltnetEvents: 0, snapshots: 0 }, findings: [] };
|
|
19
|
+
await inspectBundleFiles(root, moment.inputs, report, files);
|
|
20
|
+
for (const input of moment.inputs) {
|
|
21
|
+
const kind = input.kind === "memory" ? "memory-event"
|
|
22
|
+
: input.kind === "moltnet" ? "moltnet-message" : input.kind === "feed" ? "feed-identity"
|
|
23
|
+
: input.kind === "volume" ? "snapshot" : "git-object";
|
|
24
|
+
try {
|
|
25
|
+
if (!input.path || input.refusal || !input.fidelity)
|
|
26
|
+
throw new Error("Input is not materialized");
|
|
27
|
+
const directory = await diskPath(root, input.path);
|
|
28
|
+
// Do not hand git/SQLite a payload with escaping paths, even for a failed check.
|
|
29
|
+
if (report.findings.some((finding) => finding.class === "symlink-escape"
|
|
30
|
+
&& (finding.path === input.path || finding.path.startsWith(`${input.path}/`))))
|
|
31
|
+
continue;
|
|
32
|
+
if (["git", "bundle", "feed"].includes(input.kind))
|
|
33
|
+
await inspectInputProvenance(root, input, report, options.historyDir);
|
|
34
|
+
if (input.kind === "git")
|
|
35
|
+
await inspectGitBundle(directory, input, report);
|
|
36
|
+
if (input.kind === "memory")
|
|
37
|
+
await inspectMemoryBundle(root, input, report);
|
|
38
|
+
if (input.kind === "feed")
|
|
39
|
+
await inspectFeedBundle(root, input, report, moment, await openHistory(options.historyDir));
|
|
40
|
+
if (input.kind === "moltnet")
|
|
41
|
+
await inspectMoltnetBundle(root, input, report);
|
|
42
|
+
if (input.kind === "volume")
|
|
43
|
+
await inspectVolumeBundle(root, input, report, await openHistory(options.historyDir));
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
addInputFinding(report, input, kind, error instanceof Error ? error.message : String(error), input.path ?? ".");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
report.ok = report.findings.length === 0;
|
|
50
|
+
return { moment, check: leakCheckSchema.parse(report) };
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
await restoreInspectedAccessTimes(files);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
export const leakCheckTrainingMoment = async (bundle, options = {}) => (await inspectTrainingMoment(bundle, options)).check;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type FeedIdentity } from "../../../volume/index.js";
|
|
2
|
+
import type { MaterializedInput, MaterializedMoment } from "./contract.js";
|
|
3
|
+
import { type History } from "./history.js";
|
|
4
|
+
/** Publication metadata can follow the bound only when independent history proves the incoming pin/window. */
|
|
5
|
+
export declare const permitsFeedPublicationTime: (identity: FeedIdentity, input: MaterializedInput, moment: MaterializedMoment, history?: History) => Promise<boolean>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { feedLandingAt } from "../../../volume/index.js";
|
|
2
|
+
import { historyKey } from "./history.js";
|
|
3
|
+
import { compareInstants } from "./instant.js";
|
|
4
|
+
import { recordInputErrors } from "./recordInput.js";
|
|
5
|
+
import { selectMomentRecord } from "./select.js";
|
|
6
|
+
/** Publication metadata can follow the bound only when independent history proves the incoming pin/window. */
|
|
7
|
+
export const permitsFeedPublicationTime = async (identity, input, moment, history) => {
|
|
8
|
+
if (!history || identity.landed_at !== input.source.landedAt)
|
|
9
|
+
return false;
|
|
10
|
+
if (input.basis === "record" && input.fidelity === "exact" && moment.record.matched) {
|
|
11
|
+
const record = selectMomentRecord(await history.records(), moment.agent, moment.at, [input]);
|
|
12
|
+
const pin = record?.feeds.find((entry) => entry.id === input.id);
|
|
13
|
+
return Boolean(record && pin && compareInstants(record.wake.startedAt, moment.effectiveAt) === 0
|
|
14
|
+
&& !recordInputErrors(record, input).length && pin.revision === identity.revision
|
|
15
|
+
&& pin.tree.replace(/^trees\//u, "") === identity.tree.replace(/^trees\//u, "")
|
|
16
|
+
&& pin.commit === input.source.commit && compareInstants(pin.landedAt, identity.landed_at) === 0);
|
|
17
|
+
}
|
|
18
|
+
if (input.basis !== "landing-log" || input.fidelity !== "approximate")
|
|
19
|
+
return false;
|
|
20
|
+
const landing = feedLandingAt(await history.feedLandings(`feeds/${historyKey(input)}`, input.id), moment.effectiveAt);
|
|
21
|
+
return Boolean(landing?.ambiguous && landing.revision === identity.revision
|
|
22
|
+
&& landing.tree.replace(/^trees\//u, "") === identity.tree.replace(/^trees\//u, "")
|
|
23
|
+
&& landing.commit === input.source.commit && landing.switching_at === input.source.switchingAt
|
|
24
|
+
&& compareInstants(landing.landed_at, identity.landed_at) === 0);
|
|
25
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BigIntStats } from "node:fs";
|
|
2
|
+
import type { LeakCheck, MaterializedInput } from "./contract.js";
|
|
3
|
+
export declare const inputAtPath: (inputs: MaterializedInput[], relative: string) => MaterializedInput | undefined;
|
|
4
|
+
export declare const diskPath: (root: string, relative: string) => Promise<string>;
|
|
5
|
+
/** Capture metadata before any inspection read can advance an entry's access time. */
|
|
6
|
+
export declare const snapshotBundleFiles: (root: string) => Promise<Map<string, BigIntStats>>;
|
|
7
|
+
/** Preserve the inspected access times, including future ones; never hide an existing violation. */
|
|
8
|
+
export declare const restoreInspectedAccessTimes: (files: Map<string, BigIntStats>) => Promise<void>;
|
|
9
|
+
/** No symlinks are traversed. Inspection never reads a target outside the bundle. */
|
|
10
|
+
export declare const inspectBundleFiles: (root: string, inputs: MaterializedInput[], report: LeakCheck, files: Map<string, BigIntStats>) => Promise<void>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { lstat, lutimes, readdir, readlink, realpath, utimes } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { inside } from "./history.js";
|
|
4
|
+
import { instantNanos } from "./instant.js";
|
|
5
|
+
export const inputAtPath = (inputs, relative) => inputs.find((input) => input.path !== null && (relative === input.path || relative.startsWith(`${input.path}/`)));
|
|
6
|
+
export const diskPath = async (root, relative) => {
|
|
7
|
+
const candidate = path.resolve(root, relative);
|
|
8
|
+
if (!inside(root, candidate) || path.isAbsolute(relative))
|
|
9
|
+
throw new Error(`Bundle path escapes root: ${relative}`);
|
|
10
|
+
if (!inside(root, await realpath(candidate)))
|
|
11
|
+
throw new Error(`Bundle symlink escapes root: ${relative}`);
|
|
12
|
+
return candidate;
|
|
13
|
+
};
|
|
14
|
+
/** Capture metadata before any inspection read can advance an entry's access time. */
|
|
15
|
+
export const snapshotBundleFiles = async (root) => {
|
|
16
|
+
const files = new Map();
|
|
17
|
+
const visit = async (file) => {
|
|
18
|
+
const stats = await lstat(file, { bigint: true });
|
|
19
|
+
files.set(file, stats);
|
|
20
|
+
if (stats.isDirectory())
|
|
21
|
+
for (const name of (await readdir(file)).sort())
|
|
22
|
+
await visit(path.join(file, name));
|
|
23
|
+
};
|
|
24
|
+
await visit(root);
|
|
25
|
+
return files;
|
|
26
|
+
};
|
|
27
|
+
/** Preserve the inspected access times, including future ones; never hide an existing violation. */
|
|
28
|
+
export const restoreInspectedAccessTimes = async (files) => {
|
|
29
|
+
for (const [file, stats] of [...files].reverse()) {
|
|
30
|
+
// Numeric strings preserve sub-millisecond precision; negative numeric arguments mean "now" in Node.
|
|
31
|
+
await (stats.isSymbolicLink() ? lutimes : utimes)(file, String(Number(stats.atimeNs / 1000n) / 1_000_000), String(Number(stats.mtimeNs / 1000n) / 1_000_000));
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/** No symlinks are traversed. Inspection never reads a target outside the bundle. */
|
|
35
|
+
export const inspectBundleFiles = async (root, inputs, report, files) => {
|
|
36
|
+
const at = instantNanos(report.at);
|
|
37
|
+
const latestDate = new Date(Math.min(253_402_300_799_999, Date.parse(report.at) + 14 * 3600_000)).toISOString().slice(0, 10);
|
|
38
|
+
const visit = async (file) => {
|
|
39
|
+
const relative = path.relative(root, file).split(path.sep).join("/") || ".";
|
|
40
|
+
const owner = inputAtPath(inputs, relative);
|
|
41
|
+
const input = owner ? { section: owner.section, id: owner.id, declaredBy: owner.declaredBy } : null;
|
|
42
|
+
const add = (kind, detail) => {
|
|
43
|
+
report.findings.push({ input, class: kind, path: relative, detail });
|
|
44
|
+
};
|
|
45
|
+
const stats = files.get(file);
|
|
46
|
+
if (!owner && relative !== ".") {
|
|
47
|
+
const reportFile = ["moment.json", "leak-check.json", "task-clock.json"].includes(relative) && stats.isFile();
|
|
48
|
+
const wrapper = stats.isDirectory() && inputs.some((entry) => entry.path?.startsWith(`${relative}/`));
|
|
49
|
+
if (!reportFile && !wrapper)
|
|
50
|
+
add("bundle-entry", "Unexpected entry outside the materialized inputs and reports");
|
|
51
|
+
}
|
|
52
|
+
report.checked.files++;
|
|
53
|
+
if (stats.mtimeNs > at)
|
|
54
|
+
add("file-time", "Modification time is later than the moment");
|
|
55
|
+
if (stats.atimeNs > at)
|
|
56
|
+
add("file-time", "Access time is later than the moment");
|
|
57
|
+
const allowedGitDirectory = owner?.kind === "git" && relative === `${owner.path}/.git` && stats.isDirectory();
|
|
58
|
+
if (path.basename(file).toLowerCase() === ".git" && !allowedGitDirectory) {
|
|
59
|
+
add("git-object", "Unexpected .git repository metadata outside the materialized git resource repository");
|
|
60
|
+
}
|
|
61
|
+
const head = files.get(path.join(file, "HEAD"));
|
|
62
|
+
const objects = files.get(path.join(file, "objects"));
|
|
63
|
+
const refs = files.get(path.join(file, "refs"));
|
|
64
|
+
if (stats.isDirectory() && head && (head.isFile() || head.isSymbolicLink())
|
|
65
|
+
&& objects && (objects.isDirectory() || objects.isSymbolicLink())
|
|
66
|
+
&& refs && (refs.isDirectory() || refs.isSymbolicLink()) && !allowedGitDirectory) {
|
|
67
|
+
add("git-object", "Unexpected bare repository (HEAD, objects/, refs/) outside the materialized git resource repository");
|
|
68
|
+
}
|
|
69
|
+
for (const match of path.basename(file).matchAll(/\d{4}-\d{2}-\d{2}/gu)) {
|
|
70
|
+
const date = match[0];
|
|
71
|
+
const parsed = Date.parse(`${date}T00:00:00Z`);
|
|
72
|
+
if (Number.isFinite(parsed) && new Date(parsed).toISOString().startsWith(date) && date > latestDate) {
|
|
73
|
+
add("dated-path", `Calendar date ${date} is later than the latest possible local date ${latestDate}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (stats.isSymbolicLink()) {
|
|
77
|
+
const link = await readlink(file);
|
|
78
|
+
if (path.isAbsolute(link) || !inside(root, path.resolve(path.dirname(file), link))) {
|
|
79
|
+
add("symlink-escape", `Unsafe symlink target ${JSON.stringify(link)}`);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Even a dangling leaf can cross an existing symlink in a parent component.
|
|
83
|
+
let target = path.resolve(path.dirname(file), link);
|
|
84
|
+
for (;;) {
|
|
85
|
+
try {
|
|
86
|
+
if (!inside(root, await realpath(target)))
|
|
87
|
+
add("symlink-escape", "Symlink resolves outside the bundle");
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
if (error.code !== "ENOENT") {
|
|
92
|
+
add("symlink-escape", `Cannot resolve symlink: ${String(error)}`);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
if (target === root)
|
|
96
|
+
break;
|
|
97
|
+
target = path.dirname(target);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (!stats.isDirectory() && !stats.isFile())
|
|
102
|
+
add("symlink-escape", "Special files are not allowed in a moment bundle");
|
|
103
|
+
};
|
|
104
|
+
for (const file of files.keys())
|
|
105
|
+
await visit(file);
|
|
106
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { LeakCheck, MaterializedInput } from "./contract.js";
|
|
2
|
+
/** Enumerate every stored object, independently of the materializer's chosen-object list. */
|
|
3
|
+
export declare const inspectGitBundle: (repository: string, input: MaterializedInput, report: LeakCheck) => Promise<void>;
|