@plurnk/plurnk-service 1.16.5 → 1.18.0
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/.env.defaults +140 -246
- package/INSTALL.md +84 -138
- package/README.md +10 -6
- package/SPEC.md +2468 -1694
- package/dist/Paths.d.ts +2 -0
- package/dist/Paths.d.ts.map +1 -1
- package/dist/Paths.js +2 -0
- package/dist/Paths.js.map +1 -1
- package/dist/build-info.d.ts.map +1 -1
- package/dist/build-info.js +7 -1
- package/dist/build-info.js.map +1 -1
- package/dist/build-info.json +1 -1
- package/dist/content/body-preview.d.ts +8 -0
- package/dist/content/body-preview.d.ts.map +1 -0
- package/dist/content/body-preview.js +39 -0
- package/dist/content/body-preview.js.map +1 -0
- package/dist/content/byte-view.d.ts +1 -4
- package/dist/content/byte-view.d.ts.map +1 -1
- package/dist/content/byte-view.js.map +1 -1
- package/dist/content/edit-collision.d.ts.map +1 -1
- package/dist/content/edit-collision.js +3 -4
- package/dist/content/edit-collision.js.map +1 -1
- package/dist/content/line-anchors.d.ts +2 -2
- package/dist/content/line-anchors.d.ts.map +1 -1
- package/dist/content/line-anchors.js +4 -3
- package/dist/content/line-anchors.js.map +1 -1
- package/dist/content/line-selection.d.ts +9 -0
- package/dist/content/line-selection.d.ts.map +1 -0
- package/dist/content/line-selection.js +29 -0
- package/dist/content/line-selection.js.map +1 -0
- package/dist/content/matcher.d.ts +0 -1
- package/dist/content/matcher.d.ts.map +1 -1
- package/dist/content/matcher.js +2 -3
- package/dist/content/matcher.js.map +1 -1
- package/dist/content/pattern-edits.d.ts +39 -0
- package/dist/content/pattern-edits.d.ts.map +1 -0
- package/dist/content/pattern-edits.js +121 -0
- package/dist/content/pattern-edits.js.map +1 -0
- package/dist/content/read-projector.d.ts +18 -9
- package/dist/content/read-projector.d.ts.map +1 -1
- package/dist/content/read-projector.js +132 -35
- package/dist/content/read-projector.js.map +1 -1
- package/dist/content/read-resolve.d.ts +4 -1
- package/dist/content/read-resolve.d.ts.map +1 -1
- package/dist/content/read-resolve.js +42 -7
- package/dist/content/read-resolve.js.map +1 -1
- package/dist/core/AdmittedTurnExecutor.d.ts +2 -5
- package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
- package/dist/core/AdmittedTurnExecutor.js +96 -88
- package/dist/core/AdmittedTurnExecutor.js.map +1 -1
- package/dist/core/BareBatchRunner.d.ts +6 -1
- package/dist/core/BareBatchRunner.d.ts.map +1 -1
- package/dist/core/BareBatchRunner.js +20 -5
- package/dist/core/BareBatchRunner.js.map +1 -1
- package/dist/core/BudgetReadout.d.ts +2 -3
- package/dist/core/BudgetReadout.d.ts.map +1 -1
- package/dist/core/BudgetReadout.js +23 -32
- package/dist/core/BudgetReadout.js.map +1 -1
- package/dist/core/CapabilityPolicies.d.ts +3 -8
- package/dist/core/CapabilityPolicies.d.ts.map +1 -1
- package/dist/core/CapabilityPolicies.js +2 -28
- package/dist/core/CapabilityPolicies.js.map +1 -1
- package/dist/core/CapabilityResolver.d.ts +10 -10
- package/dist/core/CapabilityResolver.d.ts.map +1 -1
- package/dist/core/CapabilityResolver.js +122 -93
- package/dist/core/CapabilityResolver.js.map +1 -1
- package/dist/core/ChannelWrite.d.ts +15 -11
- package/dist/core/ChannelWrite.d.ts.map +1 -1
- package/dist/core/ChannelWrite.js +12 -13
- package/dist/core/ChannelWrite.js.map +1 -1
- package/dist/core/ChannelWrite.sql +99 -9
- package/dist/core/ClientInteractions.d.ts.map +1 -1
- package/dist/core/ClientInteractions.js +7 -0
- package/dist/core/ClientInteractions.js.map +1 -1
- package/dist/core/CoreSchemeServices.d.ts +13 -10
- package/dist/core/CoreSchemeServices.d.ts.map +1 -1
- package/dist/core/CoreSchemeServices.js +13 -5
- package/dist/core/CoreSchemeServices.js.map +1 -1
- package/dist/core/DataStatementRunner.d.ts +2 -2
- package/dist/core/DataStatementRunner.d.ts.map +1 -1
- package/dist/core/DataStatementRunner.js +208 -161
- package/dist/core/DataStatementRunner.js.map +1 -1
- package/dist/core/Dispatcher.d.ts +24 -26
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +381 -232
- package/dist/core/Dispatcher.js.map +1 -1
- package/dist/core/Dispatcher.sql +66 -0
- package/dist/core/DurableStatement.d.ts.map +1 -1
- package/dist/core/DurableStatement.js +2 -1
- package/dist/core/DurableStatement.js.map +1 -1
- package/dist/core/EditMutations.d.ts +14 -18
- package/dist/core/EditMutations.d.ts.map +1 -1
- package/dist/core/EditMutations.js +211 -280
- package/dist/core/EditMutations.js.map +1 -1
- package/dist/core/EditMutations.sql +15 -0
- package/dist/core/EditSequence.d.ts +13 -0
- package/dist/core/EditSequence.d.ts.map +1 -0
- package/dist/core/EditSequence.js +73 -0
- package/dist/core/EditSequence.js.map +1 -0
- package/dist/core/Engine.d.ts +17 -23
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +74 -164
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/Engine.sql +0 -724
- package/dist/core/EntryAddressBinding.d.ts +7 -17
- package/dist/core/EntryAddressBinding.d.ts.map +1 -1
- package/dist/core/EntryAddressBinding.js +12 -72
- package/dist/core/EntryAddressBinding.js.map +1 -1
- package/dist/core/ExecutionOutputs.d.ts +9 -0
- package/dist/core/ExecutionOutputs.d.ts.map +1 -0
- package/dist/core/ExecutionOutputs.js +36 -0
- package/dist/core/ExecutionOutputs.js.map +1 -0
- package/dist/core/ExecutionOutputs.sql +21 -0
- package/dist/core/ExecutorRegistry.d.ts +11 -5
- package/dist/core/ExecutorRegistry.d.ts.map +1 -1
- package/dist/core/ExecutorRegistry.js +37 -32
- package/dist/core/ExecutorRegistry.js.map +1 -1
- package/dist/core/HostPaths.d.ts +1 -0
- package/dist/core/HostPaths.d.ts.map +1 -1
- package/dist/core/HostPaths.js +4 -0
- package/dist/core/HostPaths.js.map +1 -1
- package/dist/core/InferenceCall.d.ts.map +1 -1
- package/dist/core/InferenceCall.js +1 -2
- package/dist/core/InferenceCall.js.map +1 -1
- package/dist/core/InferenceCall.sql +29 -0
- package/dist/core/KillHandler.d.ts +1 -0
- package/dist/core/KillHandler.d.ts.map +1 -1
- package/dist/core/KillHandler.js +24 -21
- package/dist/core/KillHandler.js.map +1 -1
- package/dist/core/LogBody.d.ts +8 -1
- package/dist/core/LogBody.d.ts.map +1 -1
- package/dist/core/LogBody.js +44 -12
- package/dist/core/LogBody.js.map +1 -1
- package/dist/core/LogEntryProjection.d.ts +1 -0
- package/dist/core/LogEntryProjection.d.ts.map +1 -1
- package/dist/core/LogEntryProjection.js +12 -10
- package/dist/core/LogEntryProjection.js.map +1 -1
- package/dist/core/LogVisibility.d.ts +1 -0
- package/dist/core/LogVisibility.d.ts.map +1 -1
- package/dist/core/LogVisibility.js +3 -0
- package/dist/core/LogVisibility.js.map +1 -1
- package/dist/core/LogWriter.d.ts +2 -3
- package/dist/core/LogWriter.d.ts.map +1 -1
- package/dist/core/LogWriter.js +31 -36
- package/dist/core/LogWriter.js.map +1 -1
- package/dist/core/LogWriter.sql +23 -0
- package/dist/core/LoopDriver.d.ts +11 -8
- package/dist/core/LoopDriver.d.ts.map +1 -1
- package/dist/core/LoopDriver.js +161 -189
- package/dist/core/LoopDriver.js.map +1 -1
- package/dist/core/LoopDriver.sql +11 -0
- package/dist/core/LoopLifecycle.d.ts +32 -2
- package/dist/core/LoopLifecycle.d.ts.map +1 -1
- package/dist/core/LoopLifecycle.js +88 -4
- package/dist/core/LoopLifecycle.js.map +1 -1
- package/dist/core/LoopLifecycle.sql +145 -28
- package/dist/core/LoopPolicyReader.sql +6 -0
- package/dist/core/MembershipMaterialization.d.ts.map +1 -1
- package/dist/core/MembershipMaterialization.js +6 -28
- package/dist/core/MembershipMaterialization.js.map +1 -1
- package/dist/core/ModelCall.d.ts.map +1 -1
- package/dist/core/ModelCall.js +2 -6
- package/dist/core/ModelCall.js.map +1 -1
- package/dist/core/ModelCall.sql +41 -0
- package/dist/core/MutationEffects.d.ts +5 -3
- package/dist/core/MutationEffects.d.ts.map +1 -1
- package/dist/core/MutationEffects.js +10 -28
- package/dist/core/MutationEffects.js.map +1 -1
- package/dist/core/NativeContent.d.ts +6 -0
- package/dist/core/NativeContent.d.ts.map +1 -0
- package/dist/core/NativeContent.js +16 -0
- package/dist/core/NativeContent.js.map +1 -0
- package/dist/core/NativeContent.sql +6 -0
- package/dist/core/NoticeChannel.js +1 -1
- package/dist/core/NoticeChannel.js.map +1 -1
- package/dist/core/OperatorConfig.js +5 -5
- package/dist/core/OperatorConfig.js.map +1 -1
- package/dist/core/PacketBuilder.d.ts +8 -5
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +117 -81
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/PacketBuilder.sql +146 -0
- package/dist/core/PatternSelection.d.ts +28 -0
- package/dist/core/PatternSelection.d.ts.map +1 -0
- package/dist/core/PatternSelection.js +42 -0
- package/dist/core/PatternSelection.js.map +1 -0
- package/dist/core/ProblemLog.d.ts.map +1 -1
- package/dist/core/ProblemLog.js +0 -1
- package/dist/core/ProblemLog.js.map +1 -1
- package/dist/core/PromptFrames.d.ts +12 -0
- package/dist/core/PromptFrames.d.ts.map +1 -0
- package/dist/core/PromptFrames.js +28 -0
- package/dist/core/PromptFrames.js.map +1 -0
- package/dist/core/ProposalLifecycle.d.ts +0 -1
- package/dist/core/ProposalLifecycle.d.ts.map +1 -1
- package/dist/core/ProposalLifecycle.js +26 -23
- package/dist/core/ProposalLifecycle.js.map +1 -1
- package/dist/core/ProposalLifecycle.sql +33 -0
- package/dist/core/ProviderInstantiate.d.ts +1 -1
- package/dist/core/ProviderInstantiate.d.ts.map +1 -1
- package/dist/core/ProviderInstantiate.js +7 -14
- package/dist/core/ProviderInstantiate.js.map +1 -1
- package/dist/core/ReasoningView.d.ts +9 -0
- package/dist/core/ReasoningView.d.ts.map +1 -0
- package/dist/core/ReasoningView.js +47 -0
- package/dist/core/ReasoningView.js.map +1 -0
- package/dist/core/ResourceBindings.d.ts +16 -0
- package/dist/core/ResourceBindings.d.ts.map +1 -0
- package/dist/core/ResourceBindings.js +45 -0
- package/dist/core/ResourceBindings.js.map +1 -0
- package/dist/core/ResourceMutations.d.ts +5 -8
- package/dist/core/ResourceMutations.d.ts.map +1 -1
- package/dist/core/ResourceMutations.js +6 -7
- package/dist/core/ResourceMutations.js.map +1 -1
- package/dist/core/ResourceSelector.d.ts +2 -2
- package/dist/core/ResourceSelector.d.ts.map +1 -1
- package/dist/core/ResourceSelector.js +122 -62
- package/dist/core/ResourceSelector.js.map +1 -1
- package/dist/core/ResourceTransfers.d.ts +4 -2
- package/dist/core/ResourceTransfers.d.ts.map +1 -1
- package/dist/core/ResourceTransfers.js +95 -26
- package/dist/core/ResourceTransfers.js.map +1 -1
- package/dist/core/RuntimeWorker.d.ts +5 -0
- package/dist/core/RuntimeWorker.d.ts.map +1 -0
- package/dist/core/RuntimeWorker.js +15 -0
- package/dist/core/RuntimeWorker.js.map +1 -0
- package/dist/core/RuntimeWorker.sql +11 -0
- package/dist/core/SchemeRegistry.d.ts +12 -16
- package/dist/core/SchemeRegistry.d.ts.map +1 -1
- package/dist/core/SchemeRegistry.js +59 -85
- package/dist/core/SchemeRegistry.js.map +1 -1
- package/dist/core/StoredPacket.d.ts +6 -1
- package/dist/core/StoredPacket.d.ts.map +1 -1
- package/dist/core/StoredPacket.js +30 -10
- package/dist/core/StoredPacket.js.map +1 -1
- package/dist/core/StrikeRail.d.ts +11 -8
- package/dist/core/StrikeRail.d.ts.map +1 -1
- package/dist/core/StrikeRail.js +63 -114
- package/dist/core/StrikeRail.js.map +1 -1
- package/dist/core/StrikeRail.sql +12 -0
- package/dist/core/TerminalResult.d.ts +1 -1
- package/dist/core/TerminalResult.d.ts.map +1 -1
- package/dist/core/TerminalResult.js +2 -2
- package/dist/core/TerminalResult.js.map +1 -1
- package/dist/core/TokenCalibration.d.ts +1 -6
- package/dist/core/TokenCalibration.d.ts.map +1 -1
- package/dist/core/TokenCalibration.js +13 -9
- package/dist/core/TokenCalibration.js.map +1 -1
- package/dist/core/TokenCalibration.sql +15 -0
- package/dist/core/ToolInputSchema.d.ts +6 -0
- package/dist/core/ToolInputSchema.d.ts.map +1 -0
- package/dist/core/ToolInputSchema.js +43 -0
- package/dist/core/ToolInputSchema.js.map +1 -0
- package/dist/core/ToolResources.d.ts.map +1 -1
- package/dist/core/ToolResources.js +77 -51
- package/dist/core/ToolResources.js.map +1 -1
- package/dist/core/Turn.d.ts +5 -2
- package/dist/core/Turn.d.ts.map +1 -1
- package/dist/core/Turn.js +13 -11
- package/dist/core/Turn.js.map +1 -1
- package/dist/core/Turn.sql +25 -39
- package/dist/core/{SendBroadcastHandler.d.ts → TurnDispositionHandler.d.ts} +24 -18
- package/dist/core/TurnDispositionHandler.d.ts.map +1 -0
- package/dist/core/TurnDispositionHandler.js +206 -0
- package/dist/core/TurnDispositionHandler.js.map +1 -0
- package/dist/core/TurnMaterialization.d.ts +2 -3
- package/dist/core/TurnMaterialization.d.ts.map +1 -1
- package/dist/core/TurnMaterialization.js +47 -24
- package/dist/core/TurnMaterialization.js.map +1 -1
- package/dist/core/TurnMaterialization.sql +44 -0
- package/dist/core/TurnOps.d.ts.map +1 -1
- package/dist/core/TurnOps.js +8 -64
- package/dist/core/TurnOps.js.map +1 -1
- package/dist/core/TurnRunner.d.ts +8 -15
- package/dist/core/TurnRunner.d.ts.map +1 -1
- package/dist/core/TurnRunner.js +1175 -1317
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/TurnRunner.sql +74 -0
- package/dist/core/TurnSources.sql +39 -0
- package/dist/core/WorkerControlAddress.d.ts +1 -0
- package/dist/core/WorkerControlAddress.d.ts.map +1 -1
- package/dist/core/WorkerControlAddress.js +5 -0
- package/dist/core/WorkerControlAddress.js.map +1 -1
- package/dist/core/WorkerControlHandler.d.ts +1 -3
- package/dist/core/WorkerControlHandler.d.ts.map +1 -1
- package/dist/core/WorkerControlHandler.js +64 -48
- package/dist/core/WorkerControlHandler.js.map +1 -1
- package/dist/core/WorkerName.d.ts +11 -12
- package/dist/core/WorkerName.d.ts.map +1 -1
- package/dist/core/WorkerName.js +40 -47
- package/dist/core/WorkerName.js.map +1 -1
- package/dist/core/WorkerName.sql +7 -10
- package/dist/core/WorkspaceGate.d.ts +1 -1
- package/dist/core/WorkspaceGate.d.ts.map +1 -1
- package/dist/core/WorkspaceGate.js +33 -10
- package/dist/core/WorkspaceGate.js.map +1 -1
- package/dist/core/ambient.sql +236 -0
- package/dist/core/attachments.d.ts +2 -1
- package/dist/core/attachments.d.ts.map +1 -1
- package/dist/core/attachments.js +5 -4
- package/dist/core/attachments.js.map +1 -1
- package/dist/core/caps/CapsResolve.d.ts +2 -3
- package/dist/core/caps/CapsResolve.d.ts.map +1 -1
- package/dist/core/caps/CapsResolve.js +5 -5
- package/dist/core/caps/CapsResolve.js.map +1 -1
- package/dist/core/caps/DbChannelCaps.d.ts +1 -1
- package/dist/core/caps/DbChannelCaps.d.ts.map +1 -1
- package/dist/core/caps/DbChannelCaps.js +4 -6
- package/dist/core/caps/DbChannelCaps.js.map +1 -1
- package/dist/core/caps/DbEntryCaps.d.ts +2 -1
- package/dist/core/caps/DbEntryCaps.d.ts.map +1 -1
- package/dist/core/caps/DbEntryCaps.js +11 -17
- package/dist/core/caps/DbEntryCaps.js.map +1 -1
- package/dist/core/caps/DbNotifyCaps.d.ts +1 -1
- package/dist/core/caps/DbNotifyCaps.d.ts.map +1 -1
- package/dist/core/caps/DbNotifyCaps.js +3 -5
- package/dist/core/caps/DbNotifyCaps.js.map +1 -1
- package/dist/core/caps/DbProjectionCaps.js +1 -1
- package/dist/core/caps/DbProjectionCaps.js.map +1 -1
- package/dist/core/caps/DbSubscriptionCaps.d.ts +1 -1
- package/dist/core/caps/DbSubscriptionCaps.d.ts.map +1 -1
- package/dist/core/caps/DbSubscriptionCaps.js +5 -7
- package/dist/core/caps/DbSubscriptionCaps.js.map +1 -1
- package/dist/core/caps/SchemeCtxImpl.d.ts +0 -2
- package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -1
- package/dist/core/caps/SchemeCtxImpl.js +4 -20
- package/dist/core/caps/SchemeCtxImpl.js.map +1 -1
- package/dist/core/env-catalog.d.ts +28 -0
- package/dist/core/env-catalog.d.ts.map +1 -0
- package/dist/core/env-catalog.js +99 -0
- package/dist/core/env-catalog.js.map +1 -0
- package/dist/core/env-defaults.d.ts.map +1 -1
- package/dist/core/env-defaults.js +4 -2
- package/dist/core/env-defaults.js.map +1 -1
- package/dist/core/file-materialization.d.ts +4 -1
- package/dist/core/file-materialization.d.ts.map +1 -1
- package/dist/core/file-materialization.js +15 -1
- package/dist/core/file-materialization.js.map +1 -1
- package/dist/core/fork.d.ts +1 -6
- package/dist/core/fork.d.ts.map +1 -1
- package/dist/core/fork.js +9 -153
- package/dist/core/fork.js.map +1 -1
- package/dist/core/fork.sql +162 -185
- package/dist/core/git-env.d.ts +1 -0
- package/dist/core/git-env.d.ts.map +1 -1
- package/dist/core/git-env.js +39 -2
- package/dist/core/git-env.js.map +1 -1
- package/dist/core/git-membership.d.ts.map +1 -1
- package/dist/core/git-membership.js +64 -48
- package/dist/core/git-membership.js.map +1 -1
- package/dist/core/git-state.d.ts.map +1 -1
- package/dist/core/git-state.js +26 -20
- package/dist/core/git-state.js.map +1 -1
- package/dist/core/glob_match.d.ts +4 -0
- package/dist/core/glob_match.d.ts.map +1 -0
- package/dist/core/glob_match.js +7 -0
- package/dist/core/glob_match.js.map +1 -0
- package/dist/core/maintenance.sql +6 -0
- package/dist/core/mutation-types.d.ts +7 -28
- package/dist/core/mutation-types.d.ts.map +1 -1
- package/dist/core/operation-target-groups.d.ts.map +1 -1
- package/dist/core/operation-target-groups.js +2 -1
- package/dist/core/operation-target-groups.js.map +1 -1
- package/dist/core/packet-inject.d.ts.map +1 -1
- package/dist/core/packet-inject.js +2 -3
- package/dist/core/packet-inject.js.map +1 -1
- package/dist/core/packet-wire.d.ts +8 -6
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +381 -388
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/plurnk-uri.d.ts +1 -1
- package/dist/core/plurnk-uri.d.ts.map +1 -1
- package/dist/core/plurnk-uri.js +5 -12
- package/dist/core/plurnk-uri.js.map +1 -1
- package/dist/core/scheme-types.d.ts +3 -3
- package/dist/core/scheme-types.d.ts.map +1 -1
- package/dist/core/scheme-types.js.map +1 -1
- package/dist/core/sha256.d.ts +4 -0
- package/dist/core/sha256.d.ts.map +1 -0
- package/dist/core/sha256.js +6 -0
- package/dist/core/sha256.js.map +1 -0
- package/dist/core/teaching.js +1 -1
- package/dist/core/teaching.js.map +1 -1
- package/dist/core/turn-scheduler.d.ts.map +1 -1
- package/dist/core/turn-scheduler.js +5 -18
- package/dist/core/turn-scheduler.js.map +1 -1
- package/dist/core/turn-signals.d.ts +0 -6
- package/dist/core/turn-signals.d.ts.map +1 -1
- package/dist/core/turn-signals.js +1 -7
- package/dist/core/turn-signals.js.map +1 -1
- package/dist/core/worker-ops.sql +15 -22
- package/dist/core/workspace-settings.d.ts.map +1 -1
- package/dist/core/workspace-settings.js +18 -2
- package/dist/core/workspace-settings.js.map +1 -1
- package/dist/core/workspace-settings.sql +6 -0
- package/dist/digest/Digest.d.ts.map +1 -1
- package/dist/digest/Digest.js +30 -91
- package/dist/digest/Digest.js.map +1 -1
- package/dist/digest/DigestRender.d.ts +1 -0
- package/dist/digest/DigestRender.d.ts.map +1 -1
- package/dist/digest/DigestRender.js +58 -62
- package/dist/digest/DigestRender.js.map +1 -1
- package/dist/digest/digest-rows.d.ts +16 -32
- package/dist/digest/digest-rows.d.ts.map +1 -1
- package/dist/digest/digest.sql +54 -20
- package/dist/schemes/Exec.d.ts +6 -12
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +318 -215
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/ExecOutputScheme.d.ts +8 -6
- package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
- package/dist/schemes/ExecOutputScheme.js +33 -61
- package/dist/schemes/ExecOutputScheme.js.map +1 -1
- package/dist/schemes/ExecScheduler.js +2 -2
- package/dist/schemes/ExecScheduler.js.map +1 -1
- package/dist/schemes/ExecutionInput.d.ts +12 -0
- package/dist/schemes/ExecutionInput.d.ts.map +1 -0
- package/dist/schemes/ExecutionInput.js +94 -0
- package/dist/schemes/ExecutionInput.js.map +1 -0
- package/dist/schemes/File.d.ts +5 -2
- package/dist/schemes/File.d.ts.map +1 -1
- package/dist/schemes/File.js +62 -91
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +84 -79
- package/dist/schemes/Log.js.map +1 -1
- package/dist/schemes/Log.sql +183 -15
- package/dist/schemes/Prompt.d.ts.map +1 -1
- package/dist/schemes/Prompt.js +3 -12
- package/dist/schemes/Prompt.js.map +1 -1
- package/dist/schemes/QuestionTool.d.ts +5 -0
- package/dist/schemes/QuestionTool.d.ts.map +1 -1
- package/dist/schemes/QuestionTool.js +7 -15
- package/dist/schemes/QuestionTool.js.map +1 -1
- package/dist/schemes/Skill.d.ts +12 -7
- package/dist/schemes/Skill.d.ts.map +1 -1
- package/dist/schemes/Skill.js +149 -21
- package/dist/schemes/Skill.js.map +1 -1
- package/dist/schemes/TurnSource.d.ts +12 -0
- package/dist/schemes/TurnSource.d.ts.map +1 -0
- package/dist/schemes/TurnSource.js +117 -0
- package/dist/schemes/TurnSource.js.map +1 -0
- package/dist/schemes/Worker.d.ts +3 -3
- package/dist/schemes/Worker.d.ts.map +1 -1
- package/dist/schemes/Worker.js +61 -208
- package/dist/schemes/Worker.js.map +1 -1
- package/dist/schemes/_entry-crud.d.ts +12 -15
- package/dist/schemes/_entry-crud.d.ts.map +1 -1
- package/dist/schemes/_entry-crud.js +63 -63
- package/dist/schemes/_entry-crud.js.map +1 -1
- package/dist/schemes/_entry-crud.sql +159 -45
- package/dist/schemes/_entry-find.d.ts +1 -3
- package/dist/schemes/_entry-find.d.ts.map +1 -1
- package/dist/schemes/_entry-find.js +111 -112
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/schemes/_entry-find.sql +22 -14
- package/dist/schemes/_entry-fts.d.ts +14 -0
- package/dist/schemes/_entry-fts.d.ts.map +1 -0
- package/dist/schemes/_entry-fts.js +82 -0
- package/dist/schemes/_entry-fts.js.map +1 -0
- package/dist/schemes/_entry-fts.sql +31 -0
- package/dist/schemes/_entry-graph.d.ts.map +1 -1
- package/dist/schemes/_entry-graph.js +6 -14
- package/dist/schemes/_entry-graph.js.map +1 -1
- package/dist/schemes/_entry-graph.sql +29 -44
- package/dist/schemes/_entry-manifest.d.ts +2 -1
- package/dist/schemes/_entry-manifest.d.ts.map +1 -1
- package/dist/schemes/_entry-manifest.js +20 -26
- package/dist/schemes/_entry-manifest.js.map +1 -1
- package/dist/schemes/_entry-manifest.sql +26 -0
- package/dist/schemes/_entry-ops.d.ts +3 -5
- package/dist/schemes/_entry-ops.d.ts.map +1 -1
- package/dist/schemes/_entry-ops.js +30 -43
- package/dist/schemes/_entry-ops.js.map +1 -1
- package/dist/schemes/_entry-ops.sql +5 -6
- package/dist/schemes/_entry-readable.d.ts +8 -0
- package/dist/schemes/_entry-readable.d.ts.map +1 -0
- package/dist/schemes/_entry-readable.js +38 -0
- package/dist/schemes/_entry-readable.js.map +1 -0
- package/dist/schemes/_entry-send.d.ts +1 -1
- package/dist/schemes/_entry-send.d.ts.map +1 -1
- package/dist/schemes/_entry-send.js +3 -3
- package/dist/schemes/_entry-send.js.map +1 -1
- package/dist/schemes/_search-index.d.ts +5 -3
- package/dist/schemes/_search-index.d.ts.map +1 -1
- package/dist/schemes/_search-index.js +169 -160
- package/dist/schemes/_search-index.js.map +1 -1
- package/dist/schemes/_search-index.sql +47 -0
- package/dist/schemes/exec-abort.js +1 -1
- package/dist/schemes/exec-abort.js.map +1 -1
- package/dist/schemes/exec-env.d.ts +3 -0
- package/dist/schemes/exec-env.d.ts.map +1 -1
- package/dist/schemes/exec-env.js +66 -15
- package/dist/schemes/exec-env.js.map +1 -1
- package/dist/schemes/exec-runtime.d.ts +1 -1
- package/dist/schemes/exec-runtime.d.ts.map +1 -1
- package/dist/schemes/exec-runtime.js +1 -1
- package/dist/schemes/exec-runtime.js.map +1 -1
- package/dist/server/ClientReads.d.ts +2 -2
- package/dist/server/ClientReads.d.ts.map +1 -1
- package/dist/server/ClientReads.js +7 -9
- package/dist/server/ClientReads.js.map +1 -1
- package/dist/server/Daemon.d.ts +15 -21
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +165 -168
- package/dist/server/Daemon.js.map +1 -1
- package/dist/server/DaemonModule.d.ts +29 -22
- package/dist/server/DaemonModule.d.ts.map +1 -1
- package/dist/server/DrainSupervisor.d.ts +8 -21
- package/dist/server/DrainSupervisor.d.ts.map +1 -1
- package/dist/server/DrainSupervisor.js +278 -306
- package/dist/server/DrainSupervisor.js.map +1 -1
- package/dist/server/EnvFunctionality.d.ts +43 -0
- package/dist/server/EnvFunctionality.d.ts.map +1 -0
- package/dist/server/EnvFunctionality.js +194 -0
- package/dist/server/EnvFunctionality.js.map +1 -0
- package/dist/server/Functionality.d.ts +12 -11
- package/dist/server/Functionality.d.ts.map +1 -1
- package/dist/server/Functionality.js +279 -142
- package/dist/server/Functionality.js.map +1 -1
- package/dist/server/FunctionalityManager.d.ts +5 -5
- package/dist/server/FunctionalityManager.d.ts.map +1 -1
- package/dist/server/FunctionalityManager.js +29 -57
- package/dist/server/FunctionalityManager.js.map +1 -1
- package/dist/server/MembersFunctionality.d.ts +5 -4
- package/dist/server/MembersFunctionality.d.ts.map +1 -1
- package/dist/server/MembersFunctionality.js +24 -38
- package/dist/server/MembersFunctionality.js.map +1 -1
- package/dist/server/PlurnkSkill.d.ts +11 -0
- package/dist/server/PlurnkSkill.d.ts.map +1 -0
- package/dist/server/PlurnkSkill.js +41 -0
- package/dist/server/PlurnkSkill.js.map +1 -0
- package/dist/server/Retention.d.ts +25 -0
- package/dist/server/Retention.d.ts.map +1 -0
- package/dist/server/Retention.js +57 -0
- package/dist/server/Retention.js.map +1 -0
- package/dist/server/Retention.sql +59 -0
- package/dist/server/ServiceModules.d.ts +5 -0
- package/dist/server/ServiceModules.d.ts.map +1 -0
- package/dist/server/ServiceModules.js +10 -0
- package/dist/server/ServiceModules.js.map +1 -0
- package/dist/server/SkillsFunctionality.d.ts +14 -19
- package/dist/server/SkillsFunctionality.d.ts.map +1 -1
- package/dist/server/SkillsFunctionality.js +102 -106
- package/dist/server/SkillsFunctionality.js.map +1 -1
- package/dist/server/WorkerModelResolver.d.ts +4 -0
- package/dist/server/WorkerModelResolver.d.ts.map +1 -1
- package/dist/server/WorkerModelResolver.js +72 -39
- package/dist/server/WorkerModelResolver.js.map +1 -1
- package/dist/server/WorkspaceCapabilities.d.ts +21 -0
- package/dist/server/WorkspaceCapabilities.d.ts.map +1 -0
- package/dist/server/{WorkerCapabilities.js → WorkspaceCapabilities.js} +40 -40
- package/dist/server/WorkspaceCapabilities.js.map +1 -0
- package/dist/server/WorkspaceResidency.d.ts +38 -0
- package/dist/server/WorkspaceResidency.d.ts.map +1 -0
- package/dist/server/WorkspaceResidency.js +226 -0
- package/dist/server/WorkspaceResidency.js.map +1 -0
- package/dist/server/client-input.d.ts +1 -4
- package/dist/server/client-input.d.ts.map +1 -1
- package/dist/server/client-input.js +5 -46
- package/dist/server/client-input.js.map +1 -1
- package/dist/server/dispatch-as-plurnk.d.ts.map +1 -1
- package/dist/server/dispatch-as-plurnk.js +4 -22
- package/dist/server/dispatch-as-plurnk.js.map +1 -1
- package/dist/server/drain.sql +66 -43
- package/dist/server/envelope.d.ts +8 -1
- package/dist/server/envelope.d.ts.map +1 -1
- package/dist/server/envelope.js +9 -19
- package/dist/server/envelope.js.map +1 -1
- package/dist/server/envelope.sql +49 -13
- package/dist/server/lifecycle-recovery.sql +18 -20
- package/dist/server/logEntry.d.ts +1 -1
- package/dist/server/logEntry.d.ts.map +1 -1
- package/dist/server/logEntry.js +4 -1
- package/dist/server/logEntry.js.map +1 -1
- package/dist/server/logEntry.sql +25 -1
- package/dist/server/loopDocs.d.ts +2 -2
- package/dist/server/loopDocs.d.ts.map +1 -1
- package/dist/server/loopDocs.js +38 -31
- package/dist/server/loopDocs.js.map +1 -1
- package/dist/server/loopDocs.sql +1 -3
- package/dist/server/model-catalog.d.ts.map +1 -1
- package/dist/server/model-catalog.js +2 -1
- package/dist/server/model-catalog.js.map +1 -1
- package/dist/server/model-route.d.ts +1 -1
- package/dist/server/model-route.d.ts.map +1 -1
- package/dist/server/model-route.js +4 -2
- package/dist/server/model-route.js.map +1 -1
- package/dist/server/seam-entry-read.sql +3 -4
- package/dist/server/seam-loop.sql +2 -9
- package/dist/server/workspace-capabilities.sql +64 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +21 -18
- package/dist/service.js.map +1 -1
- package/docs/env.md +55 -0
- package/docs/members.md +83 -0
- package/docs/skills.md +50 -0
- package/migrations/001_workspaces.sql +53 -0
- package/migrations/002_workers.sql +198 -0
- package/migrations/003_loops.sql +326 -0
- package/migrations/004_inference.sql +401 -0
- package/migrations/005_entries.sql +215 -0
- package/migrations/006_log.sql +581 -0
- package/migrations/007_subscriptions.sql +175 -0
- package/migrations/008_interactions.sql +29 -0
- package/package.json +44 -41
- package/digest-sql/channel-dispositions/dispositions.sql +0 -15
- package/digest-sql/channel-state/state.sql +0 -6
- package/digest-sql/curation/curation.sql +0 -6
- package/digest-sql/derivations/derivations.sql +0 -4
- package/digest-sql/embeddings/embeddings.sql +0 -4
- package/digest-sql/entry-dispositions/dispositions.sql +0 -15
- package/digest-sql/entry-state/state.sql +0 -6
- package/digest-sql/token-counts/token-counts.sql +0 -2
- package/dist/core/EmbeddingCall.d.ts +0 -23
- package/dist/core/EmbeddingCall.d.ts.map +0 -1
- package/dist/core/EmbeddingCall.js +0 -149
- package/dist/core/EmbeddingCall.js.map +0 -1
- package/dist/core/OverflowTurn.d.ts +0 -11
- package/dist/core/OverflowTurn.d.ts.map +0 -1
- package/dist/core/OverflowTurn.js +0 -80
- package/dist/core/OverflowTurn.js.map +0 -1
- package/dist/core/Owner.d.ts +0 -8
- package/dist/core/Owner.d.ts.map +0 -1
- package/dist/core/Owner.js +0 -46
- package/dist/core/Owner.js.map +0 -1
- package/dist/core/SendBroadcastHandler.d.ts.map +0 -1
- package/dist/core/SendBroadcastHandler.js +0 -159
- package/dist/core/SendBroadcastHandler.js.map +0 -1
- package/dist/core/VectorPump.d.ts +0 -28
- package/dist/core/VectorPump.d.ts.map +0 -1
- package/dist/core/VectorPump.js +0 -130
- package/dist/core/VectorPump.js.map +0 -1
- package/dist/core/owner.sql +0 -11
- package/dist/core/worker-settings.d.ts +0 -10
- package/dist/core/worker-settings.d.ts.map +0 -1
- package/dist/core/worker-settings.js +0 -53
- package/dist/core/worker-settings.js.map +0 -1
- package/dist/schemes/_entry-chunk.d.ts +0 -14
- package/dist/schemes/_entry-chunk.d.ts.map +0 -1
- package/dist/schemes/_entry-chunk.js +0 -165
- package/dist/schemes/_entry-chunk.js.map +0 -1
- package/dist/schemes/_entry-semantic.d.ts +0 -63
- package/dist/schemes/_entry-semantic.d.ts.map +0 -1
- package/dist/schemes/_entry-semantic.js +0 -299
- package/dist/schemes/_entry-semantic.js.map +0 -1
- package/dist/schemes/_entry-semantic.sql +0 -99
- package/dist/schemes/cosine.d.ts +0 -4
- package/dist/schemes/cosine.d.ts.map +0 -1
- package/dist/schemes/cosine.js +0 -9
- package/dist/schemes/cosine.js.map +0 -1
- package/dist/server/WorkerCapabilities.d.ts +0 -21
- package/dist/server/WorkerCapabilities.d.ts.map +0 -1
- package/dist/server/WorkerCapabilities.js.map +0 -1
- package/dist/server/WorkerResidency.d.ts +0 -40
- package/dist/server/WorkerResidency.d.ts.map +0 -1
- package/dist/server/WorkerResidency.js +0 -283
- package/dist/server/WorkerResidency.js.map +0 -1
- package/dist/server/seam-log-read.sql +0 -21
- package/dist/server/worker-capabilities.sql +0 -28
- package/migrations/001_schema.sql +0 -2207
|
@@ -1,2207 +0,0 @@
|
|
|
1
|
-
-- MIGRATE: 1 baseline
|
|
2
|
-
-- The single current pre-release schema baseline. Shape changes replace it;
|
|
3
|
-
-- existing development databases are deleted and recreated, never upgraded.
|
|
4
|
-
|
|
5
|
-
-- workspaces
|
|
6
|
-
-- project_root: workspace pointer. NULL = headless (no disk side-effects);
|
|
7
|
-
-- non-null = absolute path to the client's source tree, supplied at
|
|
8
|
-
-- workspace.create or workspace.set_root.
|
|
9
|
-
CREATE TABLE IF NOT EXISTS workspaces (
|
|
10
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
11
|
-
version INTEGER NOT NULL DEFAULT 0 CHECK (version >= 0),
|
|
12
|
-
name TEXT NOT NULL UNIQUE CHECK (length(name) > 0),
|
|
13
|
-
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
14
|
-
project_root TEXT,
|
|
15
|
-
-- {§operator-config} validated client workspace settings; each field composes
|
|
16
|
-
-- with operator configuration at its owning use site.
|
|
17
|
-
settings TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(settings))
|
|
18
|
-
) STRICT;
|
|
19
|
-
|
|
20
|
-
CREATE INDEX IF NOT EXISTS workspaces_created_at ON workspaces (created_at);
|
|
21
|
-
|
|
22
|
-
-- model_routes — the immutable resolved model route ({§worker-model-selection}). One row per
|
|
23
|
-
-- complete resolved tuple; append-only. Alias is provenance plus a tuning scope,
|
|
24
|
-
-- not route identity, and is absent on a direct provider/model selection.
|
|
25
|
-
CREATE TABLE IF NOT EXISTS model_routes (
|
|
26
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
27
|
-
alias TEXT CHECK (alias IS NULL OR length(alias) > 0),
|
|
28
|
-
provider TEXT NOT NULL CHECK (length(provider) > 0),
|
|
29
|
-
model TEXT NOT NULL CHECK (length(model) > 0),
|
|
30
|
-
base_url TEXT CHECK (base_url IS NULL OR length(base_url) > 0),
|
|
31
|
-
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
32
|
-
) STRICT;
|
|
33
|
-
|
|
34
|
-
CREATE UNIQUE INDEX IF NOT EXISTS model_routes_identity
|
|
35
|
-
ON model_routes (coalesce(alias, ''), provider, model, coalesce(base_url, ''));
|
|
36
|
-
|
|
37
|
-
-- workers
|
|
38
|
-
CREATE TABLE IF NOT EXISTS workers (
|
|
39
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
40
|
-
version INTEGER NOT NULL DEFAULT 0 CHECK (version >= 0),
|
|
41
|
-
workspace_id INTEGER NOT NULL,
|
|
42
|
-
name TEXT NOT NULL CHECK (length(name) > 0),
|
|
43
|
-
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
44
|
-
-- {§worker-provider-identity}: provider affinity must not collide when
|
|
45
|
-
-- independent databases reuse local integer ids.
|
|
46
|
-
provider_identity TEXT NOT NULL DEFAULT (lower(hex(randomblob(16))))
|
|
47
|
-
CHECK (length(provider_identity) = 32 AND provider_identity NOT GLOB '*[^0-9a-f]*'),
|
|
48
|
-
-- {§worker-model-selection}: the worker's durable resolved model, NULL for non-model
|
|
49
|
-
-- workers or a deliberately modelless unresolved worker. spawn_model_route_id is the
|
|
50
|
-
-- persistent spawn override; NULL means "use my model."
|
|
51
|
-
model_route_id INTEGER REFERENCES model_routes(id),
|
|
52
|
-
spawn_model_route_id INTEGER REFERENCES model_routes(id),
|
|
53
|
-
-- {§worker-reasoning-policy}: nullable only while the worker has no model;
|
|
54
|
-
-- once selected, model and reasoning policy form one durable generation policy.
|
|
55
|
-
reasoning_policy TEXT CHECK (reasoning_policy IS NULL OR length(reasoning_policy) > 0),
|
|
56
|
-
-- workers fork via parent_worker_id; workspaces carry no parent — {§machine-processes-no-fork-workspace}
|
|
57
|
-
parent_worker_id INTEGER CHECK (parent_worker_id IS NULL OR parent_worker_id != id),
|
|
58
|
-
origin TEXT NOT NULL DEFAULT 'client' CHECK (origin IN ('model', 'client', '_plurnk')),
|
|
59
|
-
-- {§methods-model-worker}: durable identity for the workspace's stable
|
|
60
|
-
-- default conversation; unrelated to its human-facing, reclaimable name.
|
|
61
|
-
default_conversation INTEGER NOT NULL DEFAULT 0 CHECK (default_conversation IN (0, 1)),
|
|
62
|
-
-- {§worker-settings}: the worker's own behavioral rules inside the workspace's
|
|
63
|
-
-- world — the workspace is how things are; each worker carries the rules its
|
|
64
|
-
-- loops obey. Client-declared at worker creation, mutable between loops,
|
|
65
|
-
-- validated at the client-input boundary (closed known-key set; unknown keys
|
|
66
|
-
-- never persist).
|
|
67
|
-
settings TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(settings)),
|
|
68
|
-
-- Parent-derived capability ceiling, copied by value at child creation.
|
|
69
|
-
-- Root workers have the unrestricted empty policy.
|
|
70
|
-
capability_bound TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(capability_bound)),
|
|
71
|
-
-- {§env-delta-log-pull}: monotonic observation progress, not a private world snapshot.
|
|
72
|
-
-- Creation captures the workspace high-water; a fork instead copies its
|
|
73
|
-
-- parent's cursor and records the closed event boundary of its snapshot.
|
|
74
|
-
ambient_event_cursor INTEGER CHECK (ambient_event_cursor IS NULL OR ambient_event_cursor >= 0),
|
|
75
|
-
fork_event_boundary INTEGER CHECK (fork_event_boundary IS NULL OR fork_event_boundary >= 0),
|
|
76
|
-
CHECK (fork_event_boundary IS NULL OR parent_worker_id IS NOT NULL),
|
|
77
|
-
CHECK (default_conversation = 0 OR (origin = 'model' AND parent_worker_id IS NULL)),
|
|
78
|
-
CHECK ((model_route_id IS NULL) = (reasoning_policy IS NULL)),
|
|
79
|
-
FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
80
|
-
FOREIGN KEY (parent_worker_id) REFERENCES workers(id) ON DELETE CASCADE
|
|
81
|
-
) STRICT;
|
|
82
|
-
|
|
83
|
-
CREATE INDEX IF NOT EXISTS workers_workspace_id_created_at ON workers (workspace_id, created_at);
|
|
84
|
-
CREATE INDEX IF NOT EXISTS workers_parent_worker_id ON workers (parent_worker_id);
|
|
85
|
-
CREATE UNIQUE INDEX IF NOT EXISTS workers_provider_identity ON workers (provider_identity);
|
|
86
|
-
CREATE UNIQUE INDEX IF NOT EXISTS workers_workspace_default_conversation
|
|
87
|
-
ON workers (workspace_id) WHERE default_conversation = 1;
|
|
88
|
-
-- NOT unique: a name is frozen per worker ({§machine-processes-worker-origin}) but RECLAIMABLE across
|
|
89
|
-
-- time — a terminated worker keeps its name in permanent history while a fresh spawn reuses it;
|
|
90
|
-
-- worker_resolve_by_name picks the newest. A LIVE collision is refused at the spawn gate (Worker.edit
|
|
91
|
-
-- → worker_live_by_name → 409), never by this index. Indexed for the by-name resolve/spawn lookup.
|
|
92
|
-
CREATE INDEX IF NOT EXISTS workers_workspace_name ON workers (workspace_id, name);
|
|
93
|
-
|
|
94
|
-
CREATE TRIGGER IF NOT EXISTS workers_provider_identity_immutable
|
|
95
|
-
BEFORE UPDATE OF provider_identity ON workers
|
|
96
|
-
WHEN NEW.provider_identity != OLD.provider_identity
|
|
97
|
-
BEGIN
|
|
98
|
-
SELECT RAISE(ABORT, 'workers.provider_identity is immutable');
|
|
99
|
-
END;
|
|
100
|
-
|
|
101
|
-
CREATE TRIGGER IF NOT EXISTS workers_fork_event_boundary_immutable
|
|
102
|
-
BEFORE UPDATE OF fork_event_boundary ON workers
|
|
103
|
-
WHEN NEW.fork_event_boundary IS NOT OLD.fork_event_boundary
|
|
104
|
-
BEGIN
|
|
105
|
-
SELECT RAISE(ABORT, 'workers.fork_event_boundary is immutable');
|
|
106
|
-
END;
|
|
107
|
-
|
|
108
|
-
-- {§module-worker-state}: one opaque, provider-validated JSON snapshot per
|
|
109
|
-
-- module owner and Worker. Core owns isolation, inheritance, and lifecycle;
|
|
110
|
-
-- the module owns its state schema and semantics.
|
|
111
|
-
CREATE TABLE IF NOT EXISTS worker_module_state (
|
|
112
|
-
worker_id INTEGER NOT NULL,
|
|
113
|
-
namespace_owner TEXT NOT NULL CHECK (length(namespace_owner) > 0),
|
|
114
|
-
state TEXT NOT NULL CHECK (json_valid(state)),
|
|
115
|
-
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
116
|
-
PRIMARY KEY (worker_id, namespace_owner),
|
|
117
|
-
FOREIGN KEY (worker_id) REFERENCES workers(id) ON DELETE CASCADE
|
|
118
|
-
) STRICT;
|
|
119
|
-
|
|
120
|
-
-- A child snapshots every initialized module state at birth. Later parent
|
|
121
|
-
-- mutations do not propagate; the child and parent are independent authorities.
|
|
122
|
-
CREATE TRIGGER IF NOT EXISTS worker_module_state_inherit
|
|
123
|
-
AFTER INSERT ON workers
|
|
124
|
-
WHEN NEW.parent_worker_id IS NOT NULL
|
|
125
|
-
BEGIN
|
|
126
|
-
INSERT INTO worker_module_state (worker_id, namespace_owner, state, updated_at)
|
|
127
|
-
SELECT NEW.id, namespace_owner, state, updated_at
|
|
128
|
-
FROM worker_module_state
|
|
129
|
-
WHERE worker_id = NEW.parent_worker_id;
|
|
130
|
-
END;
|
|
131
|
-
|
|
132
|
-
-- {§env-delta-log-pull}: one append-only occurrence journal gives every
|
|
133
|
-
-- producer a shared monotonic order. Audience is structural: direct parent,
|
|
134
|
-
-- explicit workspace broadcast, or their union. The event snapshots exactly
|
|
135
|
-
-- what an observer row needs because source-log curation cannot erase history.
|
|
136
|
-
-- source_record_id is forensic identity for the originating log/loop row, not a
|
|
137
|
-
-- foreign key: model log curation must not erase an already-recorded occurrence.
|
|
138
|
-
CREATE TABLE IF NOT EXISTS ambient_events (
|
|
139
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
140
|
-
workspace_id INTEGER NOT NULL,
|
|
141
|
-
producer_worker_id INTEGER NOT NULL,
|
|
142
|
-
target_parent_worker_id INTEGER,
|
|
143
|
-
workspace_broadcast INTEGER NOT NULL DEFAULT 0 CHECK (workspace_broadcast IN (0, 1)),
|
|
144
|
-
kind TEXT NOT NULL CHECK (kind IN ('activity', 'loop_termination')),
|
|
145
|
-
source_record_id INTEGER NOT NULL CHECK (source_record_id >= 1),
|
|
146
|
-
at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
147
|
-
source TEXT,
|
|
148
|
-
op TEXT NOT NULL,
|
|
149
|
-
delimiter TEXT NOT NULL DEFAULT '',
|
|
150
|
-
signal TEXT CHECK (signal IS NULL OR json_valid(signal)),
|
|
151
|
-
scheme TEXT,
|
|
152
|
-
username TEXT,
|
|
153
|
-
password TEXT,
|
|
154
|
-
hostname TEXT,
|
|
155
|
-
port INTEGER CHECK (port IS NULL OR (port BETWEEN 0 AND 65535)),
|
|
156
|
-
pathname TEXT,
|
|
157
|
-
query TEXT,
|
|
158
|
-
fragment TEXT,
|
|
159
|
-
line_marker TEXT CHECK (line_marker IS NULL OR json_valid(line_marker)),
|
|
160
|
-
tx TEXT NOT NULL,
|
|
161
|
-
mimetype_tx TEXT NOT NULL CHECK (length(mimetype_tx) > 0),
|
|
162
|
-
rx TEXT NOT NULL,
|
|
163
|
-
mimetype_rx TEXT NOT NULL CHECK (length(mimetype_rx) > 0),
|
|
164
|
-
status_rx INTEGER NOT NULL CHECK (status_rx BETWEEN 100 AND 599),
|
|
165
|
-
state TEXT NOT NULL CHECK (state IN ('resolved', 'failed', 'cancelled')),
|
|
166
|
-
outcome TEXT,
|
|
167
|
-
attrs TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(attrs)),
|
|
168
|
-
terminated_by TEXT CHECK (terminated_by IS NULL OR terminated_by = 'cancel'),
|
|
169
|
-
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
170
|
-
CHECK (target_parent_worker_id IS NOT NULL OR workspace_broadcast = 1),
|
|
171
|
-
CHECK (
|
|
172
|
-
(kind = 'activity' AND terminated_by IS NULL)
|
|
173
|
-
OR
|
|
174
|
-
(kind = 'loop_termination'
|
|
175
|
-
AND op = 'SEND'
|
|
176
|
-
AND scheme = 'worker'
|
|
177
|
-
AND json_valid(rx)
|
|
178
|
-
AND json_type(rx) = 'object'
|
|
179
|
-
AND json_type(rx, '$.status') = 'integer'
|
|
180
|
-
AND json_extract(rx, '$.status') = status_rx)
|
|
181
|
-
),
|
|
182
|
-
FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
183
|
-
FOREIGN KEY (producer_worker_id) REFERENCES workers(id) ON DELETE CASCADE,
|
|
184
|
-
FOREIGN KEY (target_parent_worker_id) REFERENCES workers(id) ON DELETE CASCADE
|
|
185
|
-
) STRICT;
|
|
186
|
-
|
|
187
|
-
CREATE INDEX IF NOT EXISTS ambient_events_workspace_id_id
|
|
188
|
-
ON ambient_events (workspace_id, id);
|
|
189
|
-
CREATE INDEX IF NOT EXISTS ambient_events_producer_kind_id
|
|
190
|
-
ON ambient_events (producer_worker_id, kind, id);
|
|
191
|
-
CREATE INDEX IF NOT EXISTS ambient_events_parent_id
|
|
192
|
-
ON ambient_events (target_parent_worker_id, id)
|
|
193
|
-
WHERE target_parent_worker_id IS NOT NULL;
|
|
194
|
-
CREATE UNIQUE INDEX IF NOT EXISTS ambient_events_source_identity
|
|
195
|
-
ON ambient_events (producer_worker_id, kind, source_record_id);
|
|
196
|
-
|
|
197
|
-
CREATE TRIGGER IF NOT EXISTS ambient_events_structural_audience
|
|
198
|
-
BEFORE INSERT ON ambient_events
|
|
199
|
-
WHEN NOT EXISTS (
|
|
200
|
-
SELECT 1
|
|
201
|
-
FROM workers producer
|
|
202
|
-
WHERE producer.id = NEW.producer_worker_id
|
|
203
|
-
AND producer.workspace_id = NEW.workspace_id
|
|
204
|
-
AND (
|
|
205
|
-
NEW.target_parent_worker_id IS NULL
|
|
206
|
-
OR NEW.target_parent_worker_id = producer.parent_worker_id
|
|
207
|
-
)
|
|
208
|
-
)
|
|
209
|
-
BEGIN
|
|
210
|
-
SELECT RAISE(ABORT, 'ambient event audience must be the producer direct parent in the same workspace');
|
|
211
|
-
END;
|
|
212
|
-
|
|
213
|
-
-- A worker begins after the history that predates its existence. This trigger
|
|
214
|
-
-- runs in the worker INSERT statement, so an occurrence is either in the
|
|
215
|
-
-- baseline or after it. Fork INSERTs supply their own cursor/boundary and skip
|
|
216
|
-
-- this ordinary-worker baseline. {§env-delta-log-pull}
|
|
217
|
-
CREATE TRIGGER IF NOT EXISTS workers_capture_ambient_baseline
|
|
218
|
-
AFTER INSERT ON workers
|
|
219
|
-
WHEN NEW.ambient_event_cursor IS NULL
|
|
220
|
-
BEGIN
|
|
221
|
-
UPDATE workers
|
|
222
|
-
SET ambient_event_cursor = COALESCE((
|
|
223
|
-
SELECT MAX(ae.id) FROM ambient_events ae WHERE ae.workspace_id = NEW.workspace_id
|
|
224
|
-
), 0)
|
|
225
|
-
WHERE id = NEW.id;
|
|
226
|
-
END;
|
|
227
|
-
|
|
228
|
-
-- loops
|
|
229
|
-
-- policy: complete immutable per-loop capability attenuation and proposal
|
|
230
|
-
-- disposition ({§loop-policy-effective-read}).
|
|
231
|
-
CREATE TABLE IF NOT EXISTS loops (
|
|
232
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
233
|
-
version INTEGER NOT NULL DEFAULT 0 CHECK (version >= 0),
|
|
234
|
-
worker_id INTEGER NOT NULL,
|
|
235
|
-
sequence INTEGER NOT NULL CHECK (sequence >= 1),
|
|
236
|
-
status INTEGER NOT NULL DEFAULT 102 CHECK (status IN (100, 102, 200, 202, 413, 429, 499, 500, 504, 508)),
|
|
237
|
-
prompt TEXT NOT NULL,
|
|
238
|
-
-- {§prompt-causal-source}: canonical actor address for the initial prompt;
|
|
239
|
-
-- NULL means the owning worker itself.
|
|
240
|
-
prompt_source TEXT CHECK (prompt_source IS NULL OR length(prompt_source) > 0),
|
|
241
|
-
policy TEXT NOT NULL DEFAULT '{"capabilities":{},"proposals":"review"}' CHECK (json_valid(policy)),
|
|
242
|
-
-- {§worker-model-selection}: immutable loop snapshots of the resolved model route and the
|
|
243
|
-
-- effective spawn route (was provider_spec/child_provider_spec JSON).
|
|
244
|
-
model_route_id INTEGER REFERENCES model_routes(id),
|
|
245
|
-
spawn_model_route_id INTEGER REFERENCES model_routes(id),
|
|
246
|
-
reasoning_policy TEXT CHECK (reasoning_policy IS NULL OR length(reasoning_policy) > 0),
|
|
247
|
-
max_turns INTEGER NOT NULL DEFAULT 50 CHECK (max_turns >= -1),
|
|
248
|
-
-- {§methods-loop-run-open-paths}: the initial prompt frame's selected paths,
|
|
249
|
-
-- held here until turn 1 materializes that frame (string[] JSON).
|
|
250
|
-
open_paths TEXT NOT NULL DEFAULT '[]' CHECK (json_valid(open_paths)),
|
|
251
|
-
-- {§prompt-loop-containment}: one queued recovery loop may carry the
|
|
252
|
-
-- complete orphan frame set of one concluded source loop.
|
|
253
|
-
orphan_source_loop_id INTEGER,
|
|
254
|
-
-- {§worker-scheme} loop-termination delta: terminated_at is stamped by the trigger
|
|
255
|
-
-- below when status crosses into terminal (every death-path, uniformly).
|
|
256
|
-
terminated_at TEXT,
|
|
257
|
-
terminal_result TEXT,
|
|
258
|
-
-- {§loop-terminal-authorship}: 'cancel' names an external loop.cancel;
|
|
259
|
-
-- NULL covers model terminals and engine verdicts whose result carries the story.
|
|
260
|
-
terminated_by TEXT CHECK (terminated_by IS NULL OR terminated_by = 'cancel'),
|
|
261
|
-
CONSTRAINT loops_generation_policy_contract CHECK (
|
|
262
|
-
(model_route_id IS NULL) = (reasoning_policy IS NULL)
|
|
263
|
-
),
|
|
264
|
-
CONSTRAINT loops_terminal_result_contract CHECK (
|
|
265
|
-
CASE
|
|
266
|
-
WHEN status IN (100, 102, 202) THEN terminal_result IS NULL
|
|
267
|
-
WHEN terminal_result IS NULL OR NOT json_valid(terminal_result) THEN 0
|
|
268
|
-
ELSE
|
|
269
|
-
json_type(terminal_result) IS 'object'
|
|
270
|
-
AND json_type(terminal_result, '$.status') IS 'integer'
|
|
271
|
-
AND (
|
|
272
|
-
json_extract(terminal_result, '$.status') = status
|
|
273
|
-
OR (
|
|
274
|
-
status = 200
|
|
275
|
-
AND json_extract(terminal_result, '$.status') BETWEEN 200 AND 399
|
|
276
|
-
AND json_extract(terminal_result, '$.status') != 202
|
|
277
|
-
)
|
|
278
|
-
OR (
|
|
279
|
-
status = 500
|
|
280
|
-
AND json_extract(terminal_result, '$.status') BETWEEN 400 AND 599
|
|
281
|
-
)
|
|
282
|
-
)
|
|
283
|
-
AND CASE
|
|
284
|
-
WHEN json_extract(terminal_result, '$.status') < 400 THEN
|
|
285
|
-
json_type(terminal_result, '$.problem') IS NULL
|
|
286
|
-
ELSE
|
|
287
|
-
json_type(terminal_result, '$.problem') IS 'object'
|
|
288
|
-
AND json_type(terminal_result, '$.problem.status') IS 'integer'
|
|
289
|
-
AND json_extract(terminal_result, '$.problem.status')
|
|
290
|
-
= json_extract(terminal_result, '$.status')
|
|
291
|
-
AND json_type(terminal_result, '$.problem.type') IS 'text'
|
|
292
|
-
AND length(json_extract(terminal_result, '$.problem.type')) > 0
|
|
293
|
-
AND json_type(terminal_result, '$.problem.title') IS 'text'
|
|
294
|
-
AND length(json_extract(terminal_result, '$.problem.title')) > 0
|
|
295
|
-
AND json_type(terminal_result, '$.problem.detail') IS 'text'
|
|
296
|
-
AND length(json_extract(terminal_result, '$.problem.detail')) > 0
|
|
297
|
-
AND json_type(terminal_result, '$.problem.instance') IS 'text'
|
|
298
|
-
AND length(json_extract(terminal_result, '$.problem.instance')) > 0
|
|
299
|
-
END
|
|
300
|
-
END
|
|
301
|
-
),
|
|
302
|
-
FOREIGN KEY (worker_id) REFERENCES workers(id) ON DELETE CASCADE,
|
|
303
|
-
FOREIGN KEY (orphan_source_loop_id) REFERENCES loops(id)
|
|
304
|
-
) STRICT;
|
|
305
|
-
|
|
306
|
-
CREATE UNIQUE INDEX IF NOT EXISTS loops_worker_id_sequence ON loops (worker_id, sequence);
|
|
307
|
-
CREATE UNIQUE INDEX IF NOT EXISTS loops_orphan_source_loop_id ON loops (orphan_source_loop_id);
|
|
308
|
-
-- {§worker-scheme}: a loop crossing into a terminal status stamps terminated_at, so sibling
|
|
309
|
-
-- workers pull the termination as a folded ambient delta — caught uniformly across every
|
|
310
|
-
-- death-path (SEND, overflow recovery, max-turns, strike, KILL). The stamp updates terminated_at,
|
|
311
|
-
-- never status, so it cannot re-fire this trigger. Terminals: 200 done · 413 budget ·
|
|
312
|
-
-- 429 turn-ceiling · 499 cancel · 500 fail · 504 wall-clock timeout · 508 runaway. (202 = parked/sleeping, NOT terminal.)
|
|
313
|
-
CREATE TRIGGER IF NOT EXISTS loops_stamp_terminated_at
|
|
314
|
-
AFTER UPDATE OF status ON loops
|
|
315
|
-
WHEN NEW.status IN (200, 413, 429, 499, 500, 504, 508) AND OLD.status NOT IN (200, 413, 429, 499, 500, 504, 508)
|
|
316
|
-
BEGIN
|
|
317
|
-
UPDATE loops SET terminated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = NEW.id;
|
|
318
|
-
END;
|
|
319
|
-
|
|
320
|
-
-- A child terminal transition is an occurrence addressed only to its direct
|
|
321
|
-
-- parent. Directly inserted fork history never crosses this transition and
|
|
322
|
-
-- therefore cannot fabricate a new conclusion event.
|
|
323
|
-
CREATE TRIGGER IF NOT EXISTS loops_append_ambient_event
|
|
324
|
-
AFTER UPDATE OF status ON loops
|
|
325
|
-
WHEN NEW.status IN (200, 413, 429, 499, 500, 504, 508) AND OLD.status NOT IN (200, 413, 429, 499, 500, 504, 508)
|
|
326
|
-
BEGIN
|
|
327
|
-
INSERT INTO ambient_events (
|
|
328
|
-
workspace_id, producer_worker_id, target_parent_worker_id,
|
|
329
|
-
workspace_broadcast, kind, source_record_id, source,
|
|
330
|
-
op, delimiter, scheme, pathname,
|
|
331
|
-
tx, mimetype_tx, rx, mimetype_rx, status_rx, state, terminated_by
|
|
332
|
-
)
|
|
333
|
-
SELECT w.workspace_id, NEW.worker_id, w.parent_worker_id,
|
|
334
|
-
0, 'loop_termination', NEW.id, NULL,
|
|
335
|
-
'SEND', '', 'worker', '/' || w.name,
|
|
336
|
-
'', 'text/plain', NEW.terminal_result, 'application/json',
|
|
337
|
-
json_extract(NEW.terminal_result, '$.status'), 'resolved', NEW.terminated_by
|
|
338
|
-
FROM workers w
|
|
339
|
-
WHERE w.id = NEW.worker_id
|
|
340
|
-
AND w.parent_worker_id IS NOT NULL
|
|
341
|
-
-- A loop whose only turns are client-driven operation turns is not the parent's
|
|
342
|
-
-- business (#323). A loop that never got a turn at all — a spawn refused before it
|
|
343
|
-
-- ran, e.g. a branch batch failing git-preflight — is, or the parent waits on a
|
|
344
|
-
-- ghost that vanished from Active Child Workers without a word (#385).
|
|
345
|
-
AND (
|
|
346
|
-
NOT EXISTS (SELECT 1 FROM turns t WHERE t.loop_id = NEW.id)
|
|
347
|
-
OR EXISTS (
|
|
348
|
-
SELECT 1
|
|
349
|
-
FROM turns t
|
|
350
|
-
WHERE t.loop_id = NEW.id
|
|
351
|
-
AND NOT (t.producer = '_plurnk' AND t.kind = 'operation')
|
|
352
|
-
)
|
|
353
|
-
);
|
|
354
|
-
END;
|
|
355
|
-
|
|
356
|
-
-- turns
|
|
357
|
-
-- finish_reason / model: accepted provider-call metadata from the provider
|
|
358
|
-
-- response contract. Physical request accounting is normalized beneath the
|
|
359
|
-
-- logical emission attempt that caused it.
|
|
360
|
-
CREATE TABLE IF NOT EXISTS turns (
|
|
361
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
362
|
-
version INTEGER NOT NULL DEFAULT 0 CHECK (version >= 0),
|
|
363
|
-
loop_id INTEGER NOT NULL,
|
|
364
|
-
sequence INTEGER NOT NULL CHECK (sequence >= 1),
|
|
365
|
-
timestamp TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
366
|
-
-- {§turn-record}: producer and purpose define the turn. Packet/provider
|
|
367
|
-
-- evidence below is an optional inference specialization.
|
|
368
|
-
producer TEXT NOT NULL CHECK (producer IN ('model', 'client', '_plurnk', 'plugin')),
|
|
369
|
-
kind TEXT NOT NULL CHECK (kind IN ('inference', 'initialization', 'overflow', 'operation', 'maintenance')),
|
|
370
|
-
status INTEGER NOT NULL CHECK (status BETWEEN 100 AND 599),
|
|
371
|
-
-- NULL while the producer still owns this turn. Status 102 is both the
|
|
372
|
-
-- provisional running value and the exact completed continue disposition;
|
|
373
|
-
-- completed_at distinguishes those states without inventing another status.
|
|
374
|
-
completed_at TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
375
|
-
-- Provider-derived curation calibration for this turn; NULL when input
|
|
376
|
-
-- capacity is unknown. {§tokenomics-client-gauge}
|
|
377
|
-
usage_curation_budget INTEGER CHECK (usage_curation_budget IS NULL OR usage_curation_budget >= 1),
|
|
378
|
-
-- {§packet-stored-shape}: NULL means no model request was assembled. A
|
|
379
|
-
-- present packet is either the measured request or that request extended
|
|
380
|
-
-- by the paired admitted-response fields.
|
|
381
|
-
packet TEXT CHECK (
|
|
382
|
-
CASE
|
|
383
|
-
WHEN packet IS NULL THEN 1
|
|
384
|
-
WHEN json_valid(packet) = 0 THEN 0
|
|
385
|
-
ELSE COALESCE(
|
|
386
|
-
json_type(packet) = 'object'
|
|
387
|
-
AND json_type(packet, '$.weight') = 'integer'
|
|
388
|
-
AND json_extract(packet, '$.weight') >= 0
|
|
389
|
-
AND json_type(packet, '$.sections') = 'array'
|
|
390
|
-
AND json_type(packet, '$.attributions') = 'array'
|
|
391
|
-
AND (
|
|
392
|
-
(
|
|
393
|
-
json_type(packet, '$.assistant') IS NULL
|
|
394
|
-
AND json_type(packet, '$.assistantRaw') IS NULL
|
|
395
|
-
)
|
|
396
|
-
OR (
|
|
397
|
-
json_type(packet, '$.assistant') = 'object'
|
|
398
|
-
AND json_type(packet, '$.assistant.content') = 'text'
|
|
399
|
-
AND json_type(packet, '$.assistant.ops') = 'array'
|
|
400
|
-
AND json_type(packet, '$.assistant.reasoning') IN ('text', 'null')
|
|
401
|
-
AND json_type(packet, '$.assistantRaw') IS NOT NULL
|
|
402
|
-
)
|
|
403
|
-
),
|
|
404
|
-
0
|
|
405
|
-
)
|
|
406
|
-
END
|
|
407
|
-
),
|
|
408
|
-
finish_reason TEXT,
|
|
409
|
-
model TEXT CHECK (model IS NULL OR length(model) >= 1),
|
|
410
|
-
-- Opaque provider→client metadata plus engine rail keys; absent outside
|
|
411
|
-
-- recorded inference evidence. {§meta-passthrough}, {§rail-truth-engine-verdict}
|
|
412
|
-
meta TEXT CHECK (meta IS NULL OR json_valid(meta)),
|
|
413
|
-
CHECK (completed_at IS NOT NULL OR status = 102),
|
|
414
|
-
CHECK ((producer = 'model') = (kind = 'inference')),
|
|
415
|
-
CHECK (kind NOT IN ('initialization', 'overflow') OR producer = '_plurnk'),
|
|
416
|
-
CHECK (
|
|
417
|
-
kind = 'inference'
|
|
418
|
-
OR (
|
|
419
|
-
usage_curation_budget IS NULL
|
|
420
|
-
AND packet IS NULL
|
|
421
|
-
AND finish_reason IS NULL
|
|
422
|
-
AND model IS NULL
|
|
423
|
-
AND meta IS NULL
|
|
424
|
-
)
|
|
425
|
-
),
|
|
426
|
-
FOREIGN KEY (loop_id) REFERENCES loops(id) ON DELETE CASCADE
|
|
427
|
-
) STRICT;
|
|
428
|
-
|
|
429
|
-
CREATE UNIQUE INDEX IF NOT EXISTS turns_loop_id_sequence ON turns (loop_id, sequence);
|
|
430
|
-
CREATE INDEX IF NOT EXISTS turns_timestamp ON turns (timestamp);
|
|
431
|
-
|
|
432
|
-
-- Producer and purpose are immutable except for the single pre-inference
|
|
433
|
-
-- diversion into overflow recovery. The transition is allowed only before any
|
|
434
|
-
-- model or non-kernel evidence exists.
|
|
435
|
-
CREATE TRIGGER IF NOT EXISTS turns_identity_forward_only
|
|
436
|
-
BEFORE UPDATE OF producer, kind ON turns
|
|
437
|
-
WHEN NOT (
|
|
438
|
-
OLD.producer = NEW.producer
|
|
439
|
-
AND OLD.kind = NEW.kind
|
|
440
|
-
)
|
|
441
|
-
AND NOT (
|
|
442
|
-
OLD.producer = 'model'
|
|
443
|
-
AND OLD.kind = 'inference'
|
|
444
|
-
AND NEW.producer = '_plurnk'
|
|
445
|
-
AND NEW.kind = 'overflow'
|
|
446
|
-
AND OLD.completed_at IS NULL
|
|
447
|
-
AND OLD.packet IS NULL
|
|
448
|
-
AND OLD.usage_curation_budget IS NULL
|
|
449
|
-
AND OLD.finish_reason IS NULL
|
|
450
|
-
AND OLD.model IS NULL
|
|
451
|
-
AND OLD.meta IS NULL
|
|
452
|
-
-- Engine-side embedding calls are not model history; only an emission or BARE call is.
|
|
453
|
-
AND NOT EXISTS (SELECT 1 FROM inference_calls WHERE turn_id = OLD.id AND kind IN ('emission', 'bare'))
|
|
454
|
-
AND NOT EXISTS (
|
|
455
|
-
SELECT 1 FROM log_entries
|
|
456
|
-
WHERE turn_id = OLD.id AND origin != '_plurnk'
|
|
457
|
-
)
|
|
458
|
-
)
|
|
459
|
-
BEGIN
|
|
460
|
-
SELECT RAISE(ABORT, 'turn producer and kind are immutable outside pre-inference overflow diversion');
|
|
461
|
-
END;
|
|
462
|
-
|
|
463
|
-
-- One logical inference occurrence. Workspace ownership is mandatory; a real
|
|
464
|
-
-- causal turn is attached when one exists. Generation and embedding evidence
|
|
465
|
-
-- specialize this identity without duplicating its lifecycle or physical
|
|
466
|
-
-- request ledger. {§tokenomics-provider-usage}
|
|
467
|
-
CREATE TABLE IF NOT EXISTS inference_calls (
|
|
468
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
469
|
-
workspace_id INTEGER NOT NULL,
|
|
470
|
-
turn_id INTEGER,
|
|
471
|
-
sequence INTEGER NOT NULL CHECK (sequence >= 1),
|
|
472
|
-
kind TEXT NOT NULL CHECK (kind IN ('emission', 'bare', 'embedding_query', 'embedding_documents')),
|
|
473
|
-
state TEXT NOT NULL DEFAULT 'pending' CHECK (state IN ('pending', 'response', 'error')),
|
|
474
|
-
-- Exact opaque tag set forwarded with generation calls. Embeddings carry
|
|
475
|
-
-- the empty set through the same general identity.
|
|
476
|
-
attributions TEXT NOT NULL DEFAULT '[]' CHECK (
|
|
477
|
-
json_valid(attributions) AND json_type(attributions) = 'array'
|
|
478
|
-
),
|
|
479
|
-
request_model TEXT NOT NULL CHECK (length(request_model) >= 1),
|
|
480
|
-
timestamp TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
481
|
-
completed_at TEXT,
|
|
482
|
-
CHECK (
|
|
483
|
-
(state = 'pending' AND completed_at IS NULL)
|
|
484
|
-
OR (state IN ('response', 'error') AND completed_at IS NOT NULL)
|
|
485
|
-
),
|
|
486
|
-
CHECK (
|
|
487
|
-
kind IN ('emission', 'bare') OR json_array_length(attributions) = 0
|
|
488
|
-
),
|
|
489
|
-
FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
490
|
-
FOREIGN KEY (turn_id) REFERENCES turns(id) ON DELETE CASCADE
|
|
491
|
-
) STRICT;
|
|
492
|
-
|
|
493
|
-
CREATE UNIQUE INDEX IF NOT EXISTS inference_calls_turn_sequence
|
|
494
|
-
ON inference_calls (turn_id, sequence) WHERE turn_id IS NOT NULL;
|
|
495
|
-
CREATE UNIQUE INDEX IF NOT EXISTS inference_calls_workspace_sequence
|
|
496
|
-
ON inference_calls (workspace_id, sequence) WHERE turn_id IS NULL;
|
|
497
|
-
CREATE INDEX IF NOT EXISTS inference_calls_workspace_id
|
|
498
|
-
ON inference_calls (workspace_id, timestamp, id);
|
|
499
|
-
|
|
500
|
-
CREATE TRIGGER IF NOT EXISTS inference_calls_open_pending
|
|
501
|
-
BEFORE INSERT ON inference_calls
|
|
502
|
-
WHEN NEW.state != 'pending' OR NEW.completed_at IS NOT NULL
|
|
503
|
-
BEGIN
|
|
504
|
-
SELECT RAISE(ABORT, 'inference call must open pending');
|
|
505
|
-
END;
|
|
506
|
-
|
|
507
|
-
CREATE TRIGGER IF NOT EXISTS inference_calls_context_valid
|
|
508
|
-
BEFORE INSERT ON inference_calls
|
|
509
|
-
WHEN NOT (
|
|
510
|
-
(NEW.turn_id IS NULL AND NEW.kind IN ('embedding_query', 'embedding_documents'))
|
|
511
|
-
OR
|
|
512
|
-
(NEW.turn_id IS NOT NULL
|
|
513
|
-
AND COALESCE((
|
|
514
|
-
SELECT w.workspace_id = NEW.workspace_id
|
|
515
|
-
FROM turns t
|
|
516
|
-
JOIN loops l ON l.id = t.loop_id
|
|
517
|
-
JOIN workers w ON w.id = l.worker_id
|
|
518
|
-
WHERE t.id = NEW.turn_id
|
|
519
|
-
), 0) = 1
|
|
520
|
-
AND (
|
|
521
|
-
NEW.kind IN ('embedding_query', 'embedding_documents')
|
|
522
|
-
OR COALESCE((
|
|
523
|
-
SELECT producer = 'model' AND kind = 'inference'
|
|
524
|
-
FROM turns
|
|
525
|
-
WHERE id = NEW.turn_id
|
|
526
|
-
), 0) = 1
|
|
527
|
-
)
|
|
528
|
-
)
|
|
529
|
-
)
|
|
530
|
-
BEGIN
|
|
531
|
-
SELECT RAISE(ABORT, 'inference call requires a valid owning workspace and causal context');
|
|
532
|
-
END;
|
|
533
|
-
|
|
534
|
-
CREATE TRIGGER IF NOT EXISTS inference_calls_request_identity_immutable
|
|
535
|
-
BEFORE UPDATE OF workspace_id, turn_id, sequence, kind, attributions, request_model, timestamp
|
|
536
|
-
ON inference_calls
|
|
537
|
-
BEGIN
|
|
538
|
-
SELECT RAISE(ABORT, 'inference call request identity is immutable');
|
|
539
|
-
END;
|
|
540
|
-
|
|
541
|
-
CREATE TRIGGER IF NOT EXISTS inference_calls_state_forward_only
|
|
542
|
-
BEFORE UPDATE OF state ON inference_calls
|
|
543
|
-
WHEN NOT (
|
|
544
|
-
NEW.state = OLD.state
|
|
545
|
-
OR (OLD.state = 'pending' AND NEW.state IN ('response', 'error'))
|
|
546
|
-
)
|
|
547
|
-
BEGIN
|
|
548
|
-
SELECT RAISE(ABORT, 'inference call state may only close once');
|
|
549
|
-
END;
|
|
550
|
-
|
|
551
|
-
CREATE TRIGGER IF NOT EXISTS inference_calls_terminal_evidence_required
|
|
552
|
-
BEFORE UPDATE OF state ON inference_calls
|
|
553
|
-
WHEN NEW.state != OLD.state
|
|
554
|
-
AND NOT (
|
|
555
|
-
(NEW.state = 'response' AND (
|
|
556
|
-
(NEW.kind IN ('emission', 'bare') AND EXISTS (
|
|
557
|
-
SELECT 1 FROM model_calls WHERE id = NEW.id AND response IS NOT NULL
|
|
558
|
-
))
|
|
559
|
-
OR
|
|
560
|
-
(NEW.kind IN ('embedding_query', 'embedding_documents') AND EXISTS (
|
|
561
|
-
SELECT 1 FROM embedding_calls WHERE id = NEW.id AND output_count IS NOT NULL
|
|
562
|
-
))
|
|
563
|
-
))
|
|
564
|
-
OR
|
|
565
|
-
(NEW.state = 'error' AND (
|
|
566
|
-
(NEW.kind IN ('emission', 'bare') AND EXISTS (
|
|
567
|
-
SELECT 1 FROM model_calls WHERE id = NEW.id AND failure IS NOT NULL
|
|
568
|
-
))
|
|
569
|
-
OR
|
|
570
|
-
(NEW.kind IN ('embedding_query', 'embedding_documents') AND EXISTS (
|
|
571
|
-
SELECT 1 FROM embedding_calls WHERE id = NEW.id AND failure IS NOT NULL
|
|
572
|
-
))
|
|
573
|
-
))
|
|
574
|
-
)
|
|
575
|
-
BEGIN
|
|
576
|
-
SELECT RAISE(ABORT, 'inference call terminal state requires specialization evidence');
|
|
577
|
-
END;
|
|
578
|
-
|
|
579
|
-
CREATE TRIGGER IF NOT EXISTS inference_calls_completion_immutable
|
|
580
|
-
BEFORE UPDATE OF completed_at ON inference_calls
|
|
581
|
-
WHEN OLD.state != 'pending'
|
|
582
|
-
BEGIN
|
|
583
|
-
SELECT RAISE(ABORT, 'inference call completion is immutable');
|
|
584
|
-
END;
|
|
585
|
-
|
|
586
|
-
-- Generation-specific response/failure evidence. The request model and
|
|
587
|
-
-- lifecycle remain on inference_calls; response_model is provider evidence.
|
|
588
|
-
CREATE TABLE IF NOT EXISTS model_calls (
|
|
589
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
590
|
-
-- {§packet-attachment-parts}: exact model-facing log coordinates whose
|
|
591
|
-
-- native bytes were present in this completed request. The ordinary READ
|
|
592
|
-
-- result remains independently durable in the log.
|
|
593
|
-
native_inputs TEXT NOT NULL DEFAULT '[]' CHECK (
|
|
594
|
-
json_valid(native_inputs) AND json_type(native_inputs) = 'array'
|
|
595
|
-
),
|
|
596
|
-
response TEXT CHECK (response IS NULL OR json_valid(response)),
|
|
597
|
-
failure TEXT CHECK (failure IS NULL OR json_valid(failure)),
|
|
598
|
-
capacity TEXT CHECK (
|
|
599
|
-
capacity IS NULL OR (json_valid(capacity) AND json_type(capacity) = 'object')
|
|
600
|
-
),
|
|
601
|
-
finish_reason TEXT,
|
|
602
|
-
response_model TEXT CHECK (response_model IS NULL OR length(response_model) >= 1),
|
|
603
|
-
CHECK (response IS NULL OR (capacity IS NOT NULL AND response_model IS NOT NULL)),
|
|
604
|
-
CHECK (json_array_length(native_inputs) = 0 OR response IS NOT NULL),
|
|
605
|
-
FOREIGN KEY (id) REFERENCES inference_calls(id) ON DELETE CASCADE
|
|
606
|
-
) STRICT;
|
|
607
|
-
|
|
608
|
-
CREATE TRIGGER IF NOT EXISTS model_calls_specializes_generation
|
|
609
|
-
BEFORE INSERT ON model_calls
|
|
610
|
-
WHEN COALESCE((
|
|
611
|
-
SELECT kind IN ('emission', 'bare') FROM inference_calls WHERE id = NEW.id
|
|
612
|
-
), 0) != 1
|
|
613
|
-
BEGIN
|
|
614
|
-
SELECT RAISE(ABORT, 'model call must specialize a generation inference');
|
|
615
|
-
END;
|
|
616
|
-
|
|
617
|
-
CREATE TRIGGER IF NOT EXISTS model_calls_cannot_orphan_inference
|
|
618
|
-
AFTER DELETE ON model_calls
|
|
619
|
-
WHEN EXISTS (SELECT 1 FROM inference_calls WHERE id = OLD.id)
|
|
620
|
-
BEGIN
|
|
621
|
-
SELECT RAISE(ABORT, 'model call specialization cannot be deleted independently');
|
|
622
|
-
END;
|
|
623
|
-
|
|
624
|
-
CREATE TRIGGER IF NOT EXISTS inference_calls_create_model_specialization
|
|
625
|
-
AFTER INSERT ON inference_calls
|
|
626
|
-
WHEN NEW.kind IN ('emission', 'bare')
|
|
627
|
-
BEGIN
|
|
628
|
-
INSERT INTO model_calls (id) VALUES (NEW.id);
|
|
629
|
-
END;
|
|
630
|
-
|
|
631
|
-
CREATE TRIGGER IF NOT EXISTS model_calls_observation_pending
|
|
632
|
-
BEFORE UPDATE OF native_inputs, response, failure, capacity, finish_reason, response_model
|
|
633
|
-
ON model_calls
|
|
634
|
-
WHEN COALESCE((SELECT state FROM inference_calls WHERE id = OLD.id), '') != 'pending'
|
|
635
|
-
BEGIN
|
|
636
|
-
SELECT RAISE(ABORT, 'model call observation is immutable');
|
|
637
|
-
END;
|
|
638
|
-
|
|
639
|
-
CREATE TRIGGER IF NOT EXISTS model_calls_close_response
|
|
640
|
-
AFTER UPDATE OF response ON model_calls
|
|
641
|
-
WHEN NEW.response IS NOT NULL
|
|
642
|
-
BEGIN
|
|
643
|
-
UPDATE inference_calls
|
|
644
|
-
SET state = 'response', completed_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
645
|
-
WHERE id = NEW.id AND state = 'pending';
|
|
646
|
-
END;
|
|
647
|
-
|
|
648
|
-
CREATE TRIGGER IF NOT EXISTS model_calls_close_error
|
|
649
|
-
AFTER UPDATE OF failure ON model_calls
|
|
650
|
-
WHEN NEW.failure IS NOT NULL AND NEW.response IS NULL
|
|
651
|
-
BEGIN
|
|
652
|
-
UPDATE inference_calls
|
|
653
|
-
SET state = 'error', completed_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
654
|
-
WHERE id = NEW.id AND state = 'pending';
|
|
655
|
-
END;
|
|
656
|
-
|
|
657
|
-
-- Embedding-specific cardinality and artifact evidence. input_count is
|
|
658
|
-
-- prepared before physical I/O; output_count or failure closes the shared call.
|
|
659
|
-
CREATE TABLE IF NOT EXISTS embedding_calls (
|
|
660
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
661
|
-
input_count INTEGER CHECK (input_count IS NULL OR input_count >= 0),
|
|
662
|
-
output_count INTEGER CHECK (output_count IS NULL OR output_count >= 0),
|
|
663
|
-
metadata TEXT CHECK (
|
|
664
|
-
metadata IS NULL OR (json_valid(metadata) AND json_type(metadata) = 'object')
|
|
665
|
-
),
|
|
666
|
-
failure TEXT CHECK (failure IS NULL OR json_valid(failure)),
|
|
667
|
-
CHECK (output_count IS NULL OR (input_count IS NOT NULL AND output_count = input_count AND metadata IS NOT NULL)),
|
|
668
|
-
CHECK (NOT (output_count IS NOT NULL AND failure IS NOT NULL)),
|
|
669
|
-
FOREIGN KEY (id) REFERENCES inference_calls(id) ON DELETE CASCADE
|
|
670
|
-
) STRICT;
|
|
671
|
-
|
|
672
|
-
CREATE TRIGGER IF NOT EXISTS embedding_calls_specializes_embedding
|
|
673
|
-
BEFORE INSERT ON embedding_calls
|
|
674
|
-
WHEN COALESCE((
|
|
675
|
-
SELECT kind IN ('embedding_query', 'embedding_documents')
|
|
676
|
-
FROM inference_calls
|
|
677
|
-
WHERE id = NEW.id
|
|
678
|
-
), 0) != 1
|
|
679
|
-
BEGIN
|
|
680
|
-
SELECT RAISE(ABORT, 'embedding call must specialize an embedding inference');
|
|
681
|
-
END;
|
|
682
|
-
|
|
683
|
-
CREATE TRIGGER IF NOT EXISTS embedding_calls_cannot_orphan_inference
|
|
684
|
-
AFTER DELETE ON embedding_calls
|
|
685
|
-
WHEN EXISTS (SELECT 1 FROM inference_calls WHERE id = OLD.id)
|
|
686
|
-
BEGIN
|
|
687
|
-
SELECT RAISE(ABORT, 'embedding call specialization cannot be deleted independently');
|
|
688
|
-
END;
|
|
689
|
-
|
|
690
|
-
CREATE TRIGGER IF NOT EXISTS inference_calls_create_embedding_specialization
|
|
691
|
-
AFTER INSERT ON inference_calls
|
|
692
|
-
WHEN NEW.kind IN ('embedding_query', 'embedding_documents')
|
|
693
|
-
BEGIN
|
|
694
|
-
INSERT INTO embedding_calls (id) VALUES (NEW.id);
|
|
695
|
-
END;
|
|
696
|
-
|
|
697
|
-
CREATE TRIGGER IF NOT EXISTS embedding_calls_observation_pending
|
|
698
|
-
BEFORE UPDATE OF input_count, output_count, metadata, failure ON embedding_calls
|
|
699
|
-
WHEN COALESCE((SELECT state FROM inference_calls WHERE id = OLD.id), '') != 'pending'
|
|
700
|
-
BEGIN
|
|
701
|
-
SELECT RAISE(ABORT, 'embedding call observation is immutable');
|
|
702
|
-
END;
|
|
703
|
-
|
|
704
|
-
CREATE TRIGGER IF NOT EXISTS embedding_calls_input_once
|
|
705
|
-
BEFORE UPDATE OF input_count ON embedding_calls
|
|
706
|
-
WHEN OLD.input_count IS NOT NULL
|
|
707
|
-
BEGIN
|
|
708
|
-
SELECT RAISE(ABORT, 'embedding call input cardinality is immutable');
|
|
709
|
-
END;
|
|
710
|
-
|
|
711
|
-
CREATE TRIGGER IF NOT EXISTS embedding_calls_close_response
|
|
712
|
-
AFTER UPDATE OF output_count ON embedding_calls
|
|
713
|
-
WHEN NEW.output_count IS NOT NULL
|
|
714
|
-
BEGIN
|
|
715
|
-
UPDATE inference_calls
|
|
716
|
-
SET state = 'response', completed_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
717
|
-
WHERE id = NEW.id AND state = 'pending';
|
|
718
|
-
END;
|
|
719
|
-
|
|
720
|
-
CREATE TRIGGER IF NOT EXISTS embedding_calls_close_error
|
|
721
|
-
AFTER UPDATE OF failure ON embedding_calls
|
|
722
|
-
WHEN NEW.failure IS NOT NULL
|
|
723
|
-
BEGIN
|
|
724
|
-
UPDATE inference_calls
|
|
725
|
-
SET state = 'error', completed_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
726
|
-
WHERE id = NEW.id AND state = 'pending';
|
|
727
|
-
END;
|
|
728
|
-
|
|
729
|
-
-- Emission admission specializes one model call without re-owning its response,
|
|
730
|
-
-- provider identity, ordering, or accounting evidence.
|
|
731
|
-
CREATE TABLE IF NOT EXISTS turn_attempts (
|
|
732
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
733
|
-
model_call_id INTEGER NOT NULL UNIQUE,
|
|
734
|
-
accepted INTEGER CHECK (accepted IS NULL OR accepted IN (0, 1)),
|
|
735
|
-
parse_errors TEXT NOT NULL DEFAULT '[]' CHECK (
|
|
736
|
-
json_valid(parse_errors) AND json_type(parse_errors) = 'array'
|
|
737
|
-
),
|
|
738
|
-
FOREIGN KEY (model_call_id) REFERENCES model_calls(id) ON DELETE CASCADE
|
|
739
|
-
) STRICT;
|
|
740
|
-
|
|
741
|
-
CREATE TRIGGER IF NOT EXISTS turn_attempts_request_identity_immutable
|
|
742
|
-
BEFORE UPDATE OF model_call_id ON turn_attempts
|
|
743
|
-
BEGIN
|
|
744
|
-
SELECT RAISE(ABORT, 'emission attempt identity is immutable');
|
|
745
|
-
END;
|
|
746
|
-
|
|
747
|
-
CREATE TRIGGER IF NOT EXISTS turn_attempts_emission_call_only
|
|
748
|
-
BEFORE INSERT ON turn_attempts
|
|
749
|
-
WHEN COALESCE((SELECT kind = 'emission' FROM inference_calls WHERE id = NEW.model_call_id), 0) != 1
|
|
750
|
-
BEGIN
|
|
751
|
-
SELECT RAISE(ABORT, 'turn attempt requires an emission model call');
|
|
752
|
-
END;
|
|
753
|
-
|
|
754
|
-
CREATE TRIGGER IF NOT EXISTS turn_attempts_classification_after_response
|
|
755
|
-
BEFORE UPDATE OF accepted, parse_errors ON turn_attempts
|
|
756
|
-
WHEN COALESCE((SELECT state = 'response' FROM inference_calls WHERE id = OLD.model_call_id), 0) != 1
|
|
757
|
-
BEGIN
|
|
758
|
-
SELECT RAISE(ABORT, 'emission classification requires model response evidence');
|
|
759
|
-
END;
|
|
760
|
-
|
|
761
|
-
CREATE TRIGGER IF NOT EXISTS turn_attempts_classification_once
|
|
762
|
-
BEFORE UPDATE OF accepted, parse_errors
|
|
763
|
-
ON turn_attempts
|
|
764
|
-
WHEN OLD.accepted IS NOT NULL
|
|
765
|
-
BEGIN
|
|
766
|
-
SELECT RAISE(ABORT, 'emission attempt classification is immutable');
|
|
767
|
-
END;
|
|
768
|
-
|
|
769
|
-
CREATE TRIGGER IF NOT EXISTS turn_attempts_one_accepted_insert
|
|
770
|
-
BEFORE INSERT ON turn_attempts
|
|
771
|
-
WHEN NEW.accepted = 1 AND EXISTS (
|
|
772
|
-
SELECT 1
|
|
773
|
-
FROM turn_attempts existing
|
|
774
|
-
JOIN inference_calls old_call ON old_call.id = existing.model_call_id
|
|
775
|
-
JOIN inference_calls new_call ON new_call.id = NEW.model_call_id
|
|
776
|
-
WHERE old_call.turn_id = new_call.turn_id AND existing.accepted = 1
|
|
777
|
-
)
|
|
778
|
-
BEGIN
|
|
779
|
-
SELECT RAISE(ABORT, 'one emission may be accepted per turn');
|
|
780
|
-
END;
|
|
781
|
-
|
|
782
|
-
CREATE TRIGGER IF NOT EXISTS turn_attempts_one_accepted_update
|
|
783
|
-
BEFORE UPDATE OF accepted ON turn_attempts
|
|
784
|
-
WHEN NEW.accepted = 1 AND EXISTS (
|
|
785
|
-
SELECT 1
|
|
786
|
-
FROM turn_attempts existing
|
|
787
|
-
JOIN inference_calls old_call ON old_call.id = existing.model_call_id
|
|
788
|
-
JOIN inference_calls new_call ON new_call.id = NEW.model_call_id
|
|
789
|
-
WHERE old_call.turn_id = new_call.turn_id
|
|
790
|
-
AND existing.id != OLD.id
|
|
791
|
-
AND existing.accepted = 1
|
|
792
|
-
)
|
|
793
|
-
BEGIN
|
|
794
|
-
SELECT RAISE(ABORT, 'one emission may be accepted per turn');
|
|
795
|
-
END;
|
|
796
|
-
|
|
797
|
-
-- {§provider-request-accounting}: one row is opened before one physical
|
|
798
|
-
-- provider request and settled exactly once with the evidence from that request.
|
|
799
|
-
-- Monetary values remain canonical decimal strings; SQLite REAL is never an
|
|
800
|
-
-- accounting representation.
|
|
801
|
-
CREATE TABLE IF NOT EXISTS provider_requests (
|
|
802
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
803
|
-
inference_call_id INTEGER NOT NULL,
|
|
804
|
-
sequence INTEGER NOT NULL CHECK (sequence >= 1),
|
|
805
|
-
provider TEXT NOT NULL CHECK (length(provider) > 0),
|
|
806
|
-
model TEXT NOT NULL CHECK (length(model) > 0),
|
|
807
|
-
state TEXT NOT NULL DEFAULT 'pending' CHECK (state IN ('pending', 'settled')),
|
|
808
|
-
outcome TEXT CHECK (outcome IN ('response', 'error')),
|
|
809
|
-
status INTEGER CHECK (status IS NULL OR status BETWEEN 100 AND 599),
|
|
810
|
-
usage_input INTEGER CHECK (usage_input IS NULL OR usage_input >= 0),
|
|
811
|
-
usage_output INTEGER CHECK (usage_output IS NULL OR usage_output >= 0),
|
|
812
|
-
usage_total INTEGER CHECK (usage_total IS NULL OR usage_total >= 0),
|
|
813
|
-
usage_input_no_cache INTEGER CHECK (usage_input_no_cache IS NULL OR usage_input_no_cache >= 0),
|
|
814
|
-
usage_input_cache_read INTEGER CHECK (usage_input_cache_read IS NULL OR usage_input_cache_read >= 0),
|
|
815
|
-
usage_input_cache_write INTEGER CHECK (usage_input_cache_write IS NULL OR usage_input_cache_write >= 0),
|
|
816
|
-
usage_output_text INTEGER CHECK (usage_output_text IS NULL OR usage_output_text >= 0),
|
|
817
|
-
usage_output_reasoning INTEGER CHECK (usage_output_reasoning IS NULL OR usage_output_reasoning >= 0),
|
|
818
|
-
cost_kind TEXT CHECK (cost_kind IN ('charged', 'estimated', 'unknown')),
|
|
819
|
-
cost_amount TEXT,
|
|
820
|
-
cost_currency TEXT,
|
|
821
|
-
cost_usd_equivalent TEXT,
|
|
822
|
-
cost_source TEXT,
|
|
823
|
-
cost_reason TEXT,
|
|
824
|
-
started_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
825
|
-
completed_at TEXT,
|
|
826
|
-
CHECK (
|
|
827
|
-
(state = 'pending'
|
|
828
|
-
AND outcome IS NULL AND status IS NULL
|
|
829
|
-
AND usage_input IS NULL AND usage_output IS NULL AND usage_total IS NULL
|
|
830
|
-
AND usage_input_no_cache IS NULL AND usage_input_cache_read IS NULL
|
|
831
|
-
AND usage_input_cache_write IS NULL AND usage_output_text IS NULL
|
|
832
|
-
AND usage_output_reasoning IS NULL
|
|
833
|
-
AND cost_kind IS NULL AND cost_amount IS NULL AND cost_currency IS NULL
|
|
834
|
-
AND cost_usd_equivalent IS NULL AND cost_source IS NULL AND cost_reason IS NULL
|
|
835
|
-
AND completed_at IS NULL)
|
|
836
|
-
OR
|
|
837
|
-
(state = 'settled' AND outcome IS NOT NULL AND cost_kind IS NOT NULL AND completed_at IS NOT NULL)
|
|
838
|
-
),
|
|
839
|
-
CHECK (
|
|
840
|
-
cost_amount IS NULL OR (
|
|
841
|
-
length(cost_amount) > 0
|
|
842
|
-
AND cost_amount NOT GLOB '*[^0-9.]*'
|
|
843
|
-
AND cost_amount NOT LIKE '.%'
|
|
844
|
-
AND cost_amount NOT LIKE '%.'
|
|
845
|
-
AND cost_amount NOT LIKE '%.%.%'
|
|
846
|
-
AND (cost_amount = '0' OR cost_amount NOT GLOB '0[0-9]*')
|
|
847
|
-
)
|
|
848
|
-
),
|
|
849
|
-
CHECK (
|
|
850
|
-
cost_usd_equivalent IS NULL OR (
|
|
851
|
-
length(cost_usd_equivalent) > 0
|
|
852
|
-
AND cost_usd_equivalent NOT GLOB '*[^0-9.]*'
|
|
853
|
-
AND cost_usd_equivalent NOT LIKE '.%'
|
|
854
|
-
AND cost_usd_equivalent NOT LIKE '%.'
|
|
855
|
-
AND cost_usd_equivalent NOT LIKE '%.%.%'
|
|
856
|
-
AND (cost_usd_equivalent = '0' OR cost_usd_equivalent NOT GLOB '0[0-9]*')
|
|
857
|
-
)
|
|
858
|
-
),
|
|
859
|
-
CHECK (
|
|
860
|
-
cost_currency IS NULL OR (
|
|
861
|
-
length(cost_currency) BETWEEN 3 AND 12
|
|
862
|
-
AND substr(cost_currency, 1, 1) GLOB '[A-Z]'
|
|
863
|
-
AND cost_currency NOT GLOB '*[^A-Z0-9]*'
|
|
864
|
-
)
|
|
865
|
-
),
|
|
866
|
-
CHECK (
|
|
867
|
-
cost_kind IS NULL
|
|
868
|
-
OR (cost_kind = 'charged'
|
|
869
|
-
AND cost_amount IS NOT NULL AND cost_currency IS NOT NULL
|
|
870
|
-
AND cost_source IS NOT NULL AND length(cost_source) > 0
|
|
871
|
-
AND cost_reason IS NULL)
|
|
872
|
-
OR (cost_kind = 'estimated'
|
|
873
|
-
AND cost_amount IS NOT NULL AND cost_currency IS NOT NULL
|
|
874
|
-
AND cost_usd_equivalent IS NULL
|
|
875
|
-
AND cost_source IS NOT NULL AND length(cost_source) > 0
|
|
876
|
-
AND cost_reason IS NULL)
|
|
877
|
-
OR (cost_kind = 'unknown'
|
|
878
|
-
AND cost_amount IS NULL AND cost_currency IS NULL
|
|
879
|
-
AND cost_usd_equivalent IS NULL AND cost_source IS NULL
|
|
880
|
-
AND cost_reason IS NOT NULL AND length(cost_reason) > 0)
|
|
881
|
-
),
|
|
882
|
-
UNIQUE (inference_call_id, sequence),
|
|
883
|
-
FOREIGN KEY (inference_call_id) REFERENCES inference_calls(id) ON DELETE CASCADE
|
|
884
|
-
) STRICT;
|
|
885
|
-
|
|
886
|
-
CREATE TRIGGER IF NOT EXISTS provider_requests_pending_inference_only
|
|
887
|
-
BEFORE INSERT ON provider_requests
|
|
888
|
-
WHEN COALESCE((SELECT state = 'pending' FROM inference_calls WHERE id = NEW.inference_call_id), 0) != 1
|
|
889
|
-
OR COALESCE((
|
|
890
|
-
SELECT kind NOT IN ('embedding_query', 'embedding_documents') OR ec.input_count IS NOT NULL
|
|
891
|
-
FROM inference_calls ic
|
|
892
|
-
LEFT JOIN embedding_calls ec ON ec.id = ic.id
|
|
893
|
-
WHERE ic.id = NEW.inference_call_id
|
|
894
|
-
), 0) != 1
|
|
895
|
-
BEGIN
|
|
896
|
-
SELECT RAISE(ABORT, 'provider request requires a prepared pending inference call');
|
|
897
|
-
END;
|
|
898
|
-
|
|
899
|
-
CREATE TRIGGER IF NOT EXISTS provider_requests_identity_immutable
|
|
900
|
-
BEFORE UPDATE OF inference_call_id, sequence, provider, model, started_at
|
|
901
|
-
ON provider_requests
|
|
902
|
-
BEGIN
|
|
903
|
-
SELECT RAISE(ABORT, 'provider request identity is immutable');
|
|
904
|
-
END;
|
|
905
|
-
|
|
906
|
-
CREATE INDEX IF NOT EXISTS provider_requests_inference_call_id
|
|
907
|
-
ON provider_requests (inference_call_id, sequence);
|
|
908
|
-
|
|
909
|
-
CREATE TRIGGER IF NOT EXISTS provider_requests_state_forward_only
|
|
910
|
-
BEFORE UPDATE OF state ON provider_requests
|
|
911
|
-
WHEN NOT (NEW.state = OLD.state OR (OLD.state = 'pending' AND NEW.state = 'settled'))
|
|
912
|
-
BEGIN
|
|
913
|
-
SELECT RAISE(ABORT, 'provider request may only settle once');
|
|
914
|
-
END;
|
|
915
|
-
|
|
916
|
-
CREATE TRIGGER IF NOT EXISTS provider_requests_settlement_immutable
|
|
917
|
-
BEFORE UPDATE OF outcome, status,
|
|
918
|
-
usage_input, usage_output, usage_total,
|
|
919
|
-
usage_input_no_cache, usage_input_cache_read, usage_input_cache_write,
|
|
920
|
-
usage_output_text, usage_output_reasoning,
|
|
921
|
-
cost_kind, cost_amount, cost_currency, cost_usd_equivalent,
|
|
922
|
-
cost_source, cost_reason, completed_at
|
|
923
|
-
ON provider_requests
|
|
924
|
-
WHEN OLD.state != 'pending'
|
|
925
|
-
BEGIN
|
|
926
|
-
SELECT RAISE(ABORT, 'provider request settlement is immutable');
|
|
927
|
-
END;
|
|
928
|
-
|
|
929
|
-
-- derivations
|
|
930
|
-
-- Content-addressed deep projections. Entry channels and log projections point
|
|
931
|
-
-- at a COMPLETE artifact by deep_hash; graph, FTS, and vectors are stored once
|
|
932
|
-
-- regardless of how many addresses carry identical content under the same reader/config.
|
|
933
|
-
-- A building row is unattached and safely replaceable after interruption.
|
|
934
|
-
CREATE TABLE IF NOT EXISTS derivations (
|
|
935
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
936
|
-
deep_hash TEXT NOT NULL UNIQUE CHECK (length(deep_hash) > 0),
|
|
937
|
-
state TEXT NOT NULL DEFAULT 'building' CHECK (state IN ('building', 'complete')),
|
|
938
|
-
disposition TEXT CHECK (disposition IN ('vector', 'lexical', 'excluded', 'nonsemantic', 'failed')),
|
|
939
|
-
reason TEXT,
|
|
940
|
-
parse_issues INTEGER CHECK (parse_issues IS NULL OR parse_issues > 0),
|
|
941
|
-
summary TEXT CHECK (
|
|
942
|
-
summary IS NULL OR (
|
|
943
|
-
length(summary) > 0
|
|
944
|
-
AND summary = trim(summary)
|
|
945
|
-
AND instr(summary, char(10)) = 0
|
|
946
|
-
AND instr(summary, char(13)) = 0
|
|
947
|
-
)
|
|
948
|
-
),
|
|
949
|
-
CHECK ((state = 'building' AND disposition IS NULL) OR (state = 'complete' AND disposition IS NOT NULL))
|
|
950
|
-
) STRICT;
|
|
951
|
-
|
|
952
|
-
-- entries
|
|
953
|
-
-- The canonical addressable store. (owner, scheme, authority, pathname) is the identity
|
|
954
|
-
-- tuple, and NO component may be NULL: NULLs are distinct under SQL UNIQUE, so a nullable
|
|
955
|
-
-- component voids the identity index. Bare/file paths persist under the reserved `file`
|
|
956
|
-
-- scheme; they still render as bare paths. {§entry-identity-no-null}
|
|
957
|
-
CREATE TABLE IF NOT EXISTS entries (
|
|
958
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
959
|
-
version INTEGER NOT NULL DEFAULT 0 CHECK (version >= 0),
|
|
960
|
-
scheme TEXT NOT NULL CHECK (length(scheme) > 0),
|
|
961
|
-
-- Canonical RFC authority for resource-addressed schemes. Namespace schemes
|
|
962
|
-
-- fold authored authority into pathname; owner-addressed schemes consume it
|
|
963
|
-
-- into owner_id. Empty is therefore the canonical no-resource-authority value.
|
|
964
|
-
authority TEXT NOT NULL DEFAULT '',
|
|
965
|
-
pathname TEXT NOT NULL,
|
|
966
|
-
-- {§entry-owner} — every entry is owned by a worker: the spawning worker for capability
|
|
967
|
-
-- streams, the workspace's reserved 'commons' worker for shared content. A real row, never
|
|
968
|
-
-- NULL (NULLs are distinct under UNIQUE — a nullable owner would let the commons fragment).
|
|
969
|
-
-- The id never renders into a URI or packet; the model addresses owners by NAME (authority).
|
|
970
|
-
owner_id INTEGER NOT NULL,
|
|
971
|
-
-- Entry-private metadata. Prompt frames use `openPaths` to carry selected
|
|
972
|
-
-- workspace paths into the exact turn that publishes the frame
|
|
973
|
-
-- ({§methods-loop-run-open-paths}).
|
|
974
|
-
attributes TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(attributes)),
|
|
975
|
-
-- SPEC {§membership} — how a file member entered the curated surface. 'git' rows are
|
|
976
|
-
-- reconciled against the repo's members each turn — tracked ls-files PLUS untracked-
|
|
977
|
-
-- but-not-ignored files ({§membership-auto-add}) — registered + un-registered so entries
|
|
978
|
-
-- == members; 'constraint' rows are reconciled from ordinary pick policy.
|
|
979
|
-
-- NULL = not a file member (other schemes don't carry origin).
|
|
980
|
-
membership_origin TEXT CHECK (membership_origin IS NULL OR membership_origin IN ('git', 'constraint')),
|
|
981
|
-
-- SPEC {§membership-change-gated-sync} — the per-member sync stat-detect:
|
|
982
|
-
-- "<mtimeMs>:<size>" of the disk file at its last materialization, or `absent`
|
|
983
|
-
-- after an observed deletion. The pre-turn
|
|
984
|
-
-- sync stat()s every member but re-reads/re-tokenizes/rewrites only one whose
|
|
985
|
-
-- signature changed; an unchanged member is a no-op. NULL = never synced.
|
|
986
|
-
synced_sig TEXT,
|
|
987
|
-
-- User Note 5 — manifest cache-friendliness. Last-modified stamp, bumped on every
|
|
988
|
-
-- addressable representation change; engine_list_workspace_entries orders the catalog
|
|
989
|
-
-- by it ASC so dormant entries hold the stable prompt-cache prefix. Private derivation
|
|
990
|
-
-- attachment does not make an entry recently touched.
|
|
991
|
-
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
992
|
-
FOREIGN KEY (owner_id) REFERENCES workers(id) ON DELETE CASCADE
|
|
993
|
-
) STRICT;
|
|
994
|
-
|
|
995
|
-
-- {§entry-owner} / {§stream-owner-scoped} — owner is the sole visibility and identity axis.
|
|
996
|
-
-- Concurrent workers' capability streams share the loop-relative coordinate (every worker's first
|
|
997
|
-
-- loop is seq 1), so identity keys on the owner and identical coordinates are distinct rows
|
|
998
|
-
-- ({§stream-owner-scoped}).
|
|
999
|
-
CREATE UNIQUE INDEX IF NOT EXISTS entries_identity ON entries (owner_id, scheme, authority, pathname);
|
|
1000
|
-
CREATE UNIQUE INDEX IF NOT EXISTS entries_id_owner ON entries (id, owner_id);
|
|
1001
|
-
|
|
1002
|
-
-- The ONE engine-imposed constraint (SPEC {§stream-constraints}, {§stream-constraints-engine-one-cap}): 100 MiB char-length cap
|
|
1003
|
-
-- per channel content body. All other limits are extrinsic.
|
|
1004
|
-
CREATE TABLE IF NOT EXISTS entry_channels (
|
|
1005
|
-
entry_id INTEGER NOT NULL,
|
|
1006
|
-
name TEXT NOT NULL CHECK (length(name) > 0),
|
|
1007
|
-
content TEXT NOT NULL CHECK (length(content) <= 104857600),
|
|
1008
|
-
mimetype TEXT NOT NULL CHECK (length(mimetype) > 0),
|
|
1009
|
-
weight INTEGER NOT NULL DEFAULT 0 CHECK (weight >= 0),
|
|
1010
|
-
-- Content identity: sha256 of content, stamped at static writes; streamed
|
|
1011
|
-
-- appends leave it NULL. Curation weight remains model-independent.
|
|
1012
|
-
content_hash TEXT,
|
|
1013
|
-
-- Search derivation for this exact addressable channel representation.
|
|
1014
|
-
-- Content or mimetype changes invalidate it at the owning channel row.
|
|
1015
|
-
deep_hash TEXT,
|
|
1016
|
-
state TEXT NOT NULL DEFAULT 'static' CHECK (state IN ('static', 'active', 'closed', 'errored')),
|
|
1017
|
-
-- Exact terminal producer evidence for this representation channel. NULL is
|
|
1018
|
-
-- the ordinary implicit {status:200}; selection/projection metadata belongs
|
|
1019
|
-
-- to core and is never stored here.
|
|
1020
|
-
producer_result TEXT,
|
|
1021
|
-
CONSTRAINT entry_channel_producer_result_contract CHECK (
|
|
1022
|
-
CASE
|
|
1023
|
-
WHEN producer_result IS NULL THEN 1
|
|
1024
|
-
WHEN NOT json_valid(producer_result) THEN 0
|
|
1025
|
-
ELSE
|
|
1026
|
-
json_type(producer_result) IS 'object'
|
|
1027
|
-
AND json_type(producer_result, '$.status') IS 'integer'
|
|
1028
|
-
AND json_extract(producer_result, '$.status') BETWEEN 200 AND 599
|
|
1029
|
-
AND json_extract(producer_result, '$.status') != 202
|
|
1030
|
-
AND CASE
|
|
1031
|
-
WHEN json_extract(producer_result, '$.status') < 400 THEN
|
|
1032
|
-
json_type(producer_result, '$.problem') IS NULL
|
|
1033
|
-
ELSE
|
|
1034
|
-
json_type(producer_result, '$.problem') IS 'object'
|
|
1035
|
-
AND json_type(producer_result, '$.problem.status') IS 'integer'
|
|
1036
|
-
AND json_extract(producer_result, '$.problem.status')
|
|
1037
|
-
= json_extract(producer_result, '$.status')
|
|
1038
|
-
AND json_type(producer_result, '$.problem.type') IS 'text'
|
|
1039
|
-
AND length(json_extract(producer_result, '$.problem.type')) > 0
|
|
1040
|
-
AND json_type(producer_result, '$.problem.title') IS 'text'
|
|
1041
|
-
AND length(json_extract(producer_result, '$.problem.title')) > 0
|
|
1042
|
-
AND json_type(producer_result, '$.problem.detail') IS 'text'
|
|
1043
|
-
AND length(json_extract(producer_result, '$.problem.detail')) > 0
|
|
1044
|
-
END
|
|
1045
|
-
END
|
|
1046
|
-
),
|
|
1047
|
-
PRIMARY KEY (entry_id, name),
|
|
1048
|
-
FOREIGN KEY (entry_id) REFERENCES entries(id) ON DELETE CASCADE,
|
|
1049
|
-
FOREIGN KEY (deep_hash) REFERENCES derivations(deep_hash)
|
|
1050
|
-
) STRICT, WITHOUT ROWID;
|
|
1051
|
-
|
|
1052
|
-
-- A changed channel representation cannot retain search evidence derived from
|
|
1053
|
-
-- its predecessor. This trigger is the one invalidation owner for every write
|
|
1054
|
-
-- path, including model EDIT, plugin channel capabilities, and streams.
|
|
1055
|
-
CREATE TRIGGER IF NOT EXISTS entry_channels_invalidate_derivation
|
|
1056
|
-
AFTER UPDATE OF content, mimetype ON entry_channels
|
|
1057
|
-
WHEN OLD.content IS NOT NEW.content OR OLD.mimetype IS NOT NEW.mimetype
|
|
1058
|
-
BEGIN
|
|
1059
|
-
UPDATE entry_channels
|
|
1060
|
-
SET deep_hash = NULL
|
|
1061
|
-
WHERE entry_id = NEW.entry_id AND name = NEW.name AND deep_hash IS NOT NULL;
|
|
1062
|
-
END;
|
|
1063
|
-
|
|
1064
|
-
-- User Note 5 — bump the entry's updated_at on addressable representation or
|
|
1065
|
-
-- lifecycle writes so the catalog (ordered by updated_at ASC) keeps recently-
|
|
1066
|
-
-- touched entries at the tail and holds the prompt-cache prefix stable across
|
|
1067
|
-
-- turns. Content hashes and search attachments are private metadata, not touches.
|
|
1068
|
-
CREATE TRIGGER IF NOT EXISTS entries_touch_on_channel_write
|
|
1069
|
-
AFTER INSERT ON entry_channels
|
|
1070
|
-
BEGIN
|
|
1071
|
-
UPDATE entries SET updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = NEW.entry_id;
|
|
1072
|
-
END;
|
|
1073
|
-
|
|
1074
|
-
CREATE TRIGGER IF NOT EXISTS entries_touch_on_channel_update
|
|
1075
|
-
AFTER UPDATE OF content, mimetype, weight, state, producer_result ON entry_channels
|
|
1076
|
-
BEGIN
|
|
1077
|
-
UPDATE entries SET updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = NEW.entry_id;
|
|
1078
|
-
END;
|
|
1079
|
-
|
|
1080
|
-
-- symbol_defs
|
|
1081
|
-
-- &graph NODES ({§relation-indexed-dialects}). Code symbol definitions, populated
|
|
1082
|
-
-- once per content-addressed derivation from mimetypes'
|
|
1083
|
-
-- `symbols` channel. Qualified path = container ? container || '.' || name : name.
|
|
1084
|
-
CREATE TABLE IF NOT EXISTS symbol_defs (
|
|
1085
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
1086
|
-
derivation_id INTEGER NOT NULL,
|
|
1087
|
-
name TEXT NOT NULL CHECK (length(name) > 0),
|
|
1088
|
-
kind TEXT NOT NULL,
|
|
1089
|
-
container TEXT,
|
|
1090
|
-
line INTEGER NOT NULL,
|
|
1091
|
-
end_line INTEGER,
|
|
1092
|
-
FOREIGN KEY (derivation_id) REFERENCES derivations(id) ON DELETE CASCADE
|
|
1093
|
-
) STRICT;
|
|
1094
|
-
|
|
1095
|
-
CREATE INDEX IF NOT EXISTS symbol_defs_name ON symbol_defs (name);
|
|
1096
|
-
|
|
1097
|
-
-- symbol_refs
|
|
1098
|
-
-- &graph EDGES ({§relation-indexed-dialects}), from mimetypes' `references` channel.
|
|
1099
|
-
-- name = edge TARGET; container = the SOURCE def's full qualified path (the
|
|
1100
|
-
-- &> join key; module-level → NULL); kind ∈ import|call|instantiate|inherit|
|
|
1101
|
-
-- type|use (frozen, edge metadata only — traversal is kind-agnostic).
|
|
1102
|
-
CREATE TABLE IF NOT EXISTS symbol_refs (
|
|
1103
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
1104
|
-
derivation_id INTEGER NOT NULL,
|
|
1105
|
-
name TEXT NOT NULL CHECK (length(name) > 0),
|
|
1106
|
-
kind TEXT NOT NULL,
|
|
1107
|
-
container TEXT,
|
|
1108
|
-
line INTEGER NOT NULL,
|
|
1109
|
-
col INTEGER,
|
|
1110
|
-
FOREIGN KEY (derivation_id) REFERENCES derivations(id) ON DELETE CASCADE
|
|
1111
|
-
) STRICT;
|
|
1112
|
-
|
|
1113
|
-
CREATE INDEX IF NOT EXISTS symbol_refs_name ON symbol_refs (name);
|
|
1114
|
-
CREATE INDEX IF NOT EXISTS symbol_refs_source ON symbol_refs (derivation_id, container);
|
|
1115
|
-
|
|
1116
|
-
-- derivation_fts (~semantic keyword fallback; {§relation-indexed-dialects})
|
|
1117
|
-
-- Keyword/content index over a derivation's readable content; rowid IS derivations.id.
|
|
1118
|
-
-- Explicit keyword fallback when no embedder is installed. Vector search never
|
|
1119
|
-
-- consults this table: semantic recall is exhaustive over complete vectors.
|
|
1120
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS derivation_fts USING fts5(content);
|
|
1121
|
-
|
|
1122
|
-
-- derivation_embeddings (~semantic vectors; {§relation-indexed-dialects}).
|
|
1123
|
-
-- One canonical wire vector ({§mimetype-embedding-wire}) per CHUNK: a derivation tiles into N chunks,
|
|
1124
|
-
-- each addressed by its <L> line range (line_start..line_end) and embedded
|
|
1125
|
-
-- separately, so a large body is fully searchable instead of truncated at the
|
|
1126
|
-
-- embedder's window. line_start/line_end are stored for Project Findings to expose;
|
|
1127
|
-
-- the rank currently max-pools a derivation's chunks, then projects every attached
|
|
1128
|
-
-- pathname. semantic_rank exhaustively cosine-ranks these.
|
|
1129
|
-
-- CASCADE-deleted with the derivation artifact.
|
|
1130
|
-
CREATE TABLE IF NOT EXISTS derivation_embeddings (
|
|
1131
|
-
derivation_id INTEGER NOT NULL,
|
|
1132
|
-
chunk_seq INTEGER NOT NULL,
|
|
1133
|
-
line_start INTEGER NOT NULL,
|
|
1134
|
-
line_end INTEGER NOT NULL,
|
|
1135
|
-
vector BLOB NOT NULL,
|
|
1136
|
-
-- The model id that produced this vector (mimetypes' `embeddingModel`). Stored
|
|
1137
|
-
-- per row as the dimension/staleness guard: rank filters by the current model so
|
|
1138
|
-
-- a swap never cosine-compares mismatched dimensions.
|
|
1139
|
-
embedding_model TEXT NOT NULL,
|
|
1140
|
-
PRIMARY KEY (derivation_id, chunk_seq),
|
|
1141
|
-
FOREIGN KEY (derivation_id) REFERENCES derivations(id) ON DELETE CASCADE
|
|
1142
|
-
) STRICT;
|
|
1143
|
-
|
|
1144
|
-
-- log_entries
|
|
1145
|
-
-- Chronological event store. sequence is 1-based, scoped to the turn —
|
|
1146
|
-
-- resets at each new turn. URI-bit columns are unprefixed (scheme,
|
|
1147
|
-
-- pathname, …). state/outcome/attrs carry the proposal lifecycle —
|
|
1148
|
-
-- status⊥state: status is the HTTP outcome, state is where in the
|
|
1149
|
-
-- lifecycle the entry sits. Most rows write 'resolved' directly;
|
|
1150
|
-
-- proposing schemes transition 'proposed' → resolved/failed/cancelled.
|
|
1151
|
-
-- initial_folded is the immutable visibility with which the event entered the
|
|
1152
|
-
-- log. Current model-facing membership and folded intervals belong to
|
|
1153
|
-
-- log_entry_projections below; curation never rewrites or removes this event.
|
|
1154
|
-
CREATE TABLE IF NOT EXISTS log_entries (
|
|
1155
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
1156
|
-
version INTEGER NOT NULL DEFAULT 0 CHECK (version >= 0),
|
|
1157
|
-
|
|
1158
|
-
worker_id INTEGER NOT NULL,
|
|
1159
|
-
loop_id INTEGER NOT NULL,
|
|
1160
|
-
turn_id INTEGER NOT NULL,
|
|
1161
|
-
sequence INTEGER NOT NULL CHECK (sequence >= 1),
|
|
1162
|
-
at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
1163
|
-
origin TEXT NOT NULL CHECK (origin IN ('model', 'client', '_plurnk', 'plugin')),
|
|
1164
|
-
-- {§env-delta-attribution}: a causal worker:// identity, log:/// operation
|
|
1165
|
-
-- address, or stable subsystem token ('file'); NULL = the owning worker
|
|
1166
|
-
-- itself, rendered without causal attribution.
|
|
1167
|
-
source TEXT,
|
|
1168
|
-
-- Engine-owned occurrence identity. Source rows are stamped NULL→id by the
|
|
1169
|
-
-- journal trigger; observer and fork copies carry it at insertion.
|
|
1170
|
-
ambient_event_id INTEGER REFERENCES ambient_events(id),
|
|
1171
|
-
-- Fork history is copied evidence, never new activity. Rows with no source
|
|
1172
|
-
-- occurrence still need this structural guard against republication.
|
|
1173
|
-
inherited_history INTEGER NOT NULL DEFAULT 0 CHECK (inherited_history IN (0, 1)),
|
|
1174
|
-
-- Search derivation attached to this durable log result, when available.
|
|
1175
|
-
deep_hash TEXT REFERENCES derivations(deep_hash),
|
|
1176
|
-
-- Exact logical provider call represented by a BARE result, admitted
|
|
1177
|
-
-- model turnOps, or rejected emissionAttempt. Other operation and ambient
|
|
1178
|
-
-- rows carry no model-call identity.
|
|
1179
|
-
model_call_id INTEGER REFERENCES model_calls(id),
|
|
1180
|
-
-- Engine-owned stream publication that produced this observation. The
|
|
1181
|
-
-- publication cursor survives log curation; this relation is evidence,
|
|
1182
|
-
-- never the acknowledgement itself. {§exec-stream}
|
|
1183
|
-
subscription_publication_id INTEGER REFERENCES subscription_publications(id) ON DELETE SET NULL,
|
|
1184
|
-
|
|
1185
|
-
-- 'error' is an ACTIONLESS row ({§operation-results} — errors are log items): a parse failure that
|
|
1186
|
-
-- produced no op still records a log entry (op='error', status_rx≥400, no target) so the model
|
|
1187
|
-
-- can fold/kill/recall its own mistakes like any other log row — one budget surface, the log.
|
|
1188
|
-
-- Exact producer source and rejected-attempt artifacts carry NULL here
|
|
1189
|
-
-- ({§turn-ops-entry}, {§rejected-emission-entry}).
|
|
1190
|
-
-- No op enum here: the grammar op set is grammar's contract (PlurnkOp), and this column is written
|
|
1191
|
-
-- only by the PlurnkOp-typed engine (grammar ops), service row selectors, or NULL for no op.
|
|
1192
|
-
-- A SQL enum would be a hand-copy of grammar's op list that silently goes stale on every new verb
|
|
1193
|
-
-- (it did — FORK/WORK). Validity lives at the parse + type layer, not duplicated in DDL.
|
|
1194
|
-
op TEXT,
|
|
1195
|
-
delimiter TEXT NOT NULL DEFAULT '',
|
|
1196
|
-
signal TEXT CHECK (signal IS NULL OR json_valid(signal)),
|
|
1197
|
-
|
|
1198
|
-
scheme TEXT CHECK (scheme IS NULL OR length(scheme) > 0),
|
|
1199
|
-
username TEXT,
|
|
1200
|
-
password TEXT,
|
|
1201
|
-
hostname TEXT,
|
|
1202
|
-
port INTEGER CHECK (port IS NULL OR (port BETWEEN 0 AND 65535)),
|
|
1203
|
-
pathname TEXT,
|
|
1204
|
-
-- Serialized query without '?'; NULL = absent, '' = explicit empty. {§path-query}
|
|
1205
|
-
query TEXT,
|
|
1206
|
-
fragment TEXT,
|
|
1207
|
-
|
|
1208
|
-
lineMarker TEXT CHECK (lineMarker IS NULL OR json_valid(lineMarker)),
|
|
1209
|
-
|
|
1210
|
-
tx TEXT NOT NULL,
|
|
1211
|
-
mimetype_tx TEXT NOT NULL CHECK (length(mimetype_tx) > 0),
|
|
1212
|
-
|
|
1213
|
-
rx TEXT NOT NULL,
|
|
1214
|
-
mimetype_rx TEXT NOT NULL CHECK (length(mimetype_rx) > 0),
|
|
1215
|
-
status_rx INTEGER NOT NULL CHECK (status_rx BETWEEN 100 AND 599),
|
|
1216
|
-
|
|
1217
|
-
-- Complete canonical LogBody content before coordinate/presentation
|
|
1218
|
-
-- projection; persistence envelopes do not contribute. {§tokenomics-weight-stored-at-write}
|
|
1219
|
-
weight INTEGER NOT NULL DEFAULT 0 CHECK (weight >= 0),
|
|
1220
|
-
|
|
1221
|
-
state TEXT NOT NULL DEFAULT 'resolved'
|
|
1222
|
-
CHECK (state IN ('proposed', 'resolved', 'failed', 'cancelled')),
|
|
1223
|
-
outcome TEXT,
|
|
1224
|
-
attrs TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(attrs)),
|
|
1225
|
-
|
|
1226
|
-
initial_folded TEXT NOT NULL DEFAULT '[]'
|
|
1227
|
-
CHECK (json_valid(initial_folded) AND json_type(initial_folded) = 'array'),
|
|
1228
|
-
|
|
1229
|
-
CHECK (
|
|
1230
|
-
(op IS NULL) = COALESCE(
|
|
1231
|
-
json_extract(attrs, '$.kind') IN ('turnOps', 'emissionAttempt'),
|
|
1232
|
-
0
|
|
1233
|
-
)
|
|
1234
|
-
),
|
|
1235
|
-
CHECK (json_extract(attrs, '$.kind') != 'emissionAttempt' OR origin = 'model'),
|
|
1236
|
-
|
|
1237
|
-
FOREIGN KEY (worker_id) REFERENCES workers(id) ON DELETE CASCADE,
|
|
1238
|
-
FOREIGN KEY (loop_id) REFERENCES loops(id) ON DELETE CASCADE,
|
|
1239
|
-
FOREIGN KEY (turn_id) REFERENCES turns(id) ON DELETE CASCADE
|
|
1240
|
-
) STRICT;
|
|
1241
|
-
|
|
1242
|
-
CREATE UNIQUE INDEX IF NOT EXISTS log_entries_turn_id_sequence ON log_entries (turn_id, sequence);
|
|
1243
|
-
CREATE INDEX IF NOT EXISTS log_entries_worker_id ON log_entries (worker_id);
|
|
1244
|
-
CREATE INDEX IF NOT EXISTS log_entries_loop_id ON log_entries (loop_id);
|
|
1245
|
-
CREATE INDEX IF NOT EXISTS log_entries_at ON log_entries (at);
|
|
1246
|
-
CREATE UNIQUE INDEX IF NOT EXISTS log_entries_model_call_id
|
|
1247
|
-
ON log_entries (model_call_id)
|
|
1248
|
-
WHERE model_call_id IS NOT NULL;
|
|
1249
|
-
CREATE INDEX IF NOT EXISTS log_entries_subscription_publication_id
|
|
1250
|
-
ON log_entries (subscription_publication_id)
|
|
1251
|
-
WHERE subscription_publication_id IS NOT NULL;
|
|
1252
|
-
CREATE UNIQUE INDEX IF NOT EXISTS log_entries_worker_ambient_event
|
|
1253
|
-
ON log_entries (worker_id, ambient_event_id)
|
|
1254
|
-
WHERE ambient_event_id IS NOT NULL;
|
|
1255
|
-
|
|
1256
|
-
-- {§log-history-projection} — log_entries is append-only execution evidence;
|
|
1257
|
-
-- this one-to-one row is the current model-facing projection of that evidence.
|
|
1258
|
-
-- KILL is a terminal active→inactive transition. Scoped KILL mutates only folded
|
|
1259
|
-
-- intervals while active. The initial state is created in the same statement as
|
|
1260
|
-
-- its event so no durable row can exist without one projection state.
|
|
1261
|
-
CREATE TABLE IF NOT EXISTS log_entry_projections (
|
|
1262
|
-
log_entry_id INTEGER NOT NULL PRIMARY KEY,
|
|
1263
|
-
active INTEGER NOT NULL DEFAULT 1 CHECK (active IN (0, 1)),
|
|
1264
|
-
folded TEXT NOT NULL DEFAULT '[]'
|
|
1265
|
-
CHECK (json_valid(folded) AND json_type(folded) = 'array'),
|
|
1266
|
-
FOREIGN KEY (log_entry_id) REFERENCES log_entries(id) ON DELETE CASCADE
|
|
1267
|
-
) STRICT, WITHOUT ROWID;
|
|
1268
|
-
|
|
1269
|
-
-- The ordinary operation surface reads this view. Forensic and lifecycle
|
|
1270
|
-
-- machinery names log_entries directly and therefore retains complete history.
|
|
1271
|
-
CREATE VIEW IF NOT EXISTS active_log_entries AS
|
|
1272
|
-
SELECT le.*, projection.folded
|
|
1273
|
-
FROM log_entries le
|
|
1274
|
-
JOIN log_entry_projections projection ON projection.log_entry_id = le.id
|
|
1275
|
-
WHERE projection.active = 1;
|
|
1276
|
-
|
|
1277
|
-
-- {§packet-attachment-parts} — absence means an attachable READ may still
|
|
1278
|
-
-- contribute native content. Presence is the append-only fact that a completed
|
|
1279
|
-
-- model response crossed that one-shot delivery boundary. This lifecycle is not
|
|
1280
|
-
-- part of the log-curation projection.
|
|
1281
|
-
CREATE TABLE IF NOT EXISTS native_content_deliveries (
|
|
1282
|
-
log_entry_id INTEGER NOT NULL PRIMARY KEY,
|
|
1283
|
-
delivered_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
1284
|
-
FOREIGN KEY (log_entry_id) REFERENCES log_entries(id) ON DELETE CASCADE
|
|
1285
|
-
) STRICT, WITHOUT ROWID;
|
|
1286
|
-
|
|
1287
|
-
CREATE TRIGGER IF NOT EXISTS model_calls_native_inputs_valid
|
|
1288
|
-
BEFORE UPDATE OF native_inputs ON model_calls
|
|
1289
|
-
WHEN (
|
|
1290
|
-
SELECT COUNT(*) != COUNT(DISTINCT value)
|
|
1291
|
-
OR SUM(CASE WHEN type != 'text' OR length(value) = 0 THEN 1 ELSE 0 END) > 0
|
|
1292
|
-
FROM json_each(NEW.native_inputs)
|
|
1293
|
-
)
|
|
1294
|
-
OR EXISTS (
|
|
1295
|
-
SELECT 1
|
|
1296
|
-
FROM json_each(NEW.native_inputs) native
|
|
1297
|
-
WHERE NOT EXISTS (
|
|
1298
|
-
SELECT 1
|
|
1299
|
-
FROM inference_calls call
|
|
1300
|
-
JOIN turns request_turn ON request_turn.id = call.turn_id
|
|
1301
|
-
JOIN loops request_loop ON request_loop.id = request_turn.loop_id
|
|
1302
|
-
JOIN log_entries entry ON entry.worker_id = request_loop.worker_id
|
|
1303
|
-
JOIN turns entry_turn ON entry_turn.id = entry.turn_id
|
|
1304
|
-
JOIN loops entry_loop ON entry_loop.id = entry_turn.loop_id
|
|
1305
|
-
WHERE call.id = NEW.id
|
|
1306
|
-
AND entry.op = 'READ'
|
|
1307
|
-
AND entry.status_rx < 400
|
|
1308
|
-
AND (entry_loop.sequence || '/' || entry_turn.sequence || '/' || entry.sequence) = native.value
|
|
1309
|
-
)
|
|
1310
|
-
)
|
|
1311
|
-
BEGIN
|
|
1312
|
-
SELECT RAISE(ABORT, 'model call native inputs must be unique successful READ coordinates owned by its worker');
|
|
1313
|
-
END;
|
|
1314
|
-
|
|
1315
|
-
-- Closing a model call with response evidence is the native-content delivery
|
|
1316
|
-
-- boundary. Both facts commit in the same SQLite statement; a call that ends
|
|
1317
|
-
-- without a response cannot consume native content.
|
|
1318
|
-
CREATE TRIGGER IF NOT EXISTS native_content_deliveries_from_model_response
|
|
1319
|
-
AFTER UPDATE OF response, native_inputs ON model_calls
|
|
1320
|
-
WHEN NEW.response IS NOT NULL
|
|
1321
|
-
BEGIN
|
|
1322
|
-
INSERT INTO native_content_deliveries (log_entry_id)
|
|
1323
|
-
SELECT entry.id
|
|
1324
|
-
FROM json_each(NEW.native_inputs) native
|
|
1325
|
-
JOIN inference_calls call ON call.id = NEW.id
|
|
1326
|
-
JOIN turns request_turn ON request_turn.id = call.turn_id
|
|
1327
|
-
JOIN loops request_loop ON request_loop.id = request_turn.loop_id
|
|
1328
|
-
JOIN log_entries entry ON entry.worker_id = request_loop.worker_id
|
|
1329
|
-
JOIN turns entry_turn ON entry_turn.id = entry.turn_id
|
|
1330
|
-
JOIN loops entry_loop ON entry_loop.id = entry_turn.loop_id
|
|
1331
|
-
WHERE (entry_loop.sequence || '/' || entry_turn.sequence || '/' || entry.sequence) = native.value
|
|
1332
|
-
ON CONFLICT (log_entry_id) DO NOTHING;
|
|
1333
|
-
END;
|
|
1334
|
-
|
|
1335
|
-
CREATE TRIGGER IF NOT EXISTS native_content_deliveries_immutable
|
|
1336
|
-
BEFORE UPDATE ON native_content_deliveries
|
|
1337
|
-
BEGIN
|
|
1338
|
-
SELECT RAISE(ABORT, 'native-content delivery evidence is immutable');
|
|
1339
|
-
END;
|
|
1340
|
-
|
|
1341
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_initialize_projection
|
|
1342
|
-
AFTER INSERT ON log_entries
|
|
1343
|
-
BEGIN
|
|
1344
|
-
INSERT INTO log_entry_projections (log_entry_id, active, folded)
|
|
1345
|
-
VALUES (NEW.id, 1, NEW.initial_folded);
|
|
1346
|
-
END;
|
|
1347
|
-
|
|
1348
|
-
-- Individual execution events are append-only. Containing-history teardown is
|
|
1349
|
-
-- the one removal owner: a cascading delete has already removed at least one
|
|
1350
|
-
-- ancestor in the workspace→worker→loop→turn chain. A direct row delete while
|
|
1351
|
-
-- that complete owner chain remains would fabricate chronology and is rejected.
|
|
1352
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_delete_with_owner_only
|
|
1353
|
-
BEFORE DELETE ON log_entries
|
|
1354
|
-
WHEN EXISTS (
|
|
1355
|
-
SELECT 1
|
|
1356
|
-
FROM turns
|
|
1357
|
-
JOIN loops ON loops.id = turns.loop_id
|
|
1358
|
-
JOIN workers ON workers.id = loops.worker_id
|
|
1359
|
-
JOIN workspaces ON workspaces.id = workers.workspace_id
|
|
1360
|
-
WHERE turns.id = OLD.turn_id
|
|
1361
|
-
)
|
|
1362
|
-
BEGIN
|
|
1363
|
-
SELECT RAISE(ABORT, 'log entries can only be removed with their containing history');
|
|
1364
|
-
END;
|
|
1365
|
-
|
|
1366
|
-
-- A log row belongs to one exact worker/loop/turn chain. Its writer is either
|
|
1367
|
-
-- that turn's producer or `_plurnk` observing the turn. Primitive absence,
|
|
1368
|
-
-- enum, and foreign-key failures remain owned by their column constraints.
|
|
1369
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_turn_ownership
|
|
1370
|
-
BEFORE INSERT ON log_entries
|
|
1371
|
-
WHEN NEW.worker_id IS NOT NULL
|
|
1372
|
-
AND NEW.loop_id IS NOT NULL
|
|
1373
|
-
AND NEW.turn_id IS NOT NULL
|
|
1374
|
-
AND NEW.origin IN ('model', 'client', '_plurnk', 'plugin')
|
|
1375
|
-
AND EXISTS (SELECT 1 FROM workers WHERE id = NEW.worker_id)
|
|
1376
|
-
AND EXISTS (SELECT 1 FROM loops WHERE id = NEW.loop_id)
|
|
1377
|
-
AND EXISTS (SELECT 1 FROM turns WHERE id = NEW.turn_id)
|
|
1378
|
-
AND NOT EXISTS (
|
|
1379
|
-
SELECT 1
|
|
1380
|
-
FROM turns
|
|
1381
|
-
JOIN loops ON loops.id = turns.loop_id
|
|
1382
|
-
WHERE turns.id = NEW.turn_id
|
|
1383
|
-
AND loops.id = NEW.loop_id
|
|
1384
|
-
AND loops.worker_id = NEW.worker_id
|
|
1385
|
-
AND (NEW.origin = turns.producer OR NEW.origin = '_plurnk')
|
|
1386
|
-
)
|
|
1387
|
-
BEGIN
|
|
1388
|
-
SELECT RAISE(ABORT, 'log entry must match its turn ownership and producer');
|
|
1389
|
-
END;
|
|
1390
|
-
|
|
1391
|
-
-- {§turn-ops-entry} — exact admitted source is authored by the turn producer.
|
|
1392
|
-
-- `_plurnk` may observe another producer's turn through ordinary operation
|
|
1393
|
-
-- rows, but it cannot impersonate that producer's source program.
|
|
1394
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_turn_ops_producer
|
|
1395
|
-
BEFORE INSERT ON log_entries
|
|
1396
|
-
WHEN NEW.op IS NULL
|
|
1397
|
-
AND json_extract(NEW.attrs, '$.kind') = 'turnOps'
|
|
1398
|
-
AND EXISTS (SELECT 1 FROM turns WHERE id = NEW.turn_id)
|
|
1399
|
-
AND NOT EXISTS (
|
|
1400
|
-
SELECT 1
|
|
1401
|
-
FROM turns
|
|
1402
|
-
WHERE turns.id = NEW.turn_id
|
|
1403
|
-
AND turns.producer = NEW.origin
|
|
1404
|
-
)
|
|
1405
|
-
BEGIN
|
|
1406
|
-
SELECT RAISE(ABORT, 'actionless log entry does not match its turn producer');
|
|
1407
|
-
END;
|
|
1408
|
-
|
|
1409
|
-
-- A folded interval is an inclusive [start,end] pair. Ranges are positive,
|
|
1410
|
-
-- sorted, disjoint, and non-adjacent; -1 is the final open-ended endpoint.
|
|
1411
|
-
-- Canonical intervals make visibility equality and curation effects exact.
|
|
1412
|
-
CREATE TRIGGER IF NOT EXISTS log_entry_projections_folded_valid_insert
|
|
1413
|
-
BEFORE INSERT ON log_entry_projections
|
|
1414
|
-
WHEN EXISTS (
|
|
1415
|
-
SELECT 1
|
|
1416
|
-
FROM json_each(NEW.folded) range
|
|
1417
|
-
WHERE range.type != 'array'
|
|
1418
|
-
OR json_array_length(range.value) != 2
|
|
1419
|
-
OR COALESCE(json_type(range.value, '$[0]'), '') != 'integer'
|
|
1420
|
-
OR COALESCE(json_type(range.value, '$[1]'), '') != 'integer'
|
|
1421
|
-
OR json_extract(range.value, '$[0]') < 1
|
|
1422
|
-
OR (
|
|
1423
|
-
json_extract(range.value, '$[1]') != -1
|
|
1424
|
-
AND json_extract(range.value, '$[1]') < json_extract(range.value, '$[0]')
|
|
1425
|
-
)
|
|
1426
|
-
OR EXISTS (
|
|
1427
|
-
SELECT 1
|
|
1428
|
-
FROM json_each(NEW.folded) previous
|
|
1429
|
-
WHERE previous.key = range.key - 1
|
|
1430
|
-
AND (
|
|
1431
|
-
json_extract(previous.value, '$[1]') = -1
|
|
1432
|
-
OR json_extract(range.value, '$[0]') <= json_extract(previous.value, '$[1]') + 1
|
|
1433
|
-
)
|
|
1434
|
-
)
|
|
1435
|
-
)
|
|
1436
|
-
BEGIN
|
|
1437
|
-
SELECT RAISE(ABORT, 'log entry projection folded ranges are invalid');
|
|
1438
|
-
END;
|
|
1439
|
-
|
|
1440
|
-
CREATE TRIGGER IF NOT EXISTS log_entry_projections_folded_valid_update
|
|
1441
|
-
BEFORE UPDATE OF folded ON log_entry_projections
|
|
1442
|
-
WHEN EXISTS (
|
|
1443
|
-
SELECT 1
|
|
1444
|
-
FROM json_each(NEW.folded) range
|
|
1445
|
-
WHERE range.type != 'array'
|
|
1446
|
-
OR json_array_length(range.value) != 2
|
|
1447
|
-
OR COALESCE(json_type(range.value, '$[0]'), '') != 'integer'
|
|
1448
|
-
OR COALESCE(json_type(range.value, '$[1]'), '') != 'integer'
|
|
1449
|
-
OR json_extract(range.value, '$[0]') < 1
|
|
1450
|
-
OR (
|
|
1451
|
-
json_extract(range.value, '$[1]') != -1
|
|
1452
|
-
AND json_extract(range.value, '$[1]') < json_extract(range.value, '$[0]')
|
|
1453
|
-
)
|
|
1454
|
-
OR EXISTS (
|
|
1455
|
-
SELECT 1
|
|
1456
|
-
FROM json_each(NEW.folded) previous
|
|
1457
|
-
WHERE previous.key = range.key - 1
|
|
1458
|
-
AND (
|
|
1459
|
-
json_extract(previous.value, '$[1]') = -1
|
|
1460
|
-
OR json_extract(range.value, '$[0]') <= json_extract(previous.value, '$[1]') + 1
|
|
1461
|
-
)
|
|
1462
|
-
)
|
|
1463
|
-
)
|
|
1464
|
-
BEGIN
|
|
1465
|
-
SELECT RAISE(ABORT, 'log entry projection folded ranges are invalid');
|
|
1466
|
-
END;
|
|
1467
|
-
|
|
1468
|
-
CREATE TRIGGER IF NOT EXISTS log_entry_projections_kill_terminal
|
|
1469
|
-
BEFORE UPDATE OF active ON log_entry_projections
|
|
1470
|
-
WHEN OLD.active = 0 AND NEW.active != 0
|
|
1471
|
-
BEGIN
|
|
1472
|
-
SELECT RAISE(ABORT, 'a killed log entry cannot re-enter the active projection');
|
|
1473
|
-
END;
|
|
1474
|
-
|
|
1475
|
-
CREATE TRIGGER IF NOT EXISTS log_entry_projections_delete_with_event_only
|
|
1476
|
-
BEFORE DELETE ON log_entry_projections
|
|
1477
|
-
WHEN EXISTS (SELECT 1 FROM log_entries WHERE id = OLD.log_entry_id)
|
|
1478
|
-
BEGIN
|
|
1479
|
-
SELECT RAISE(ABORT, 'a durable log event must retain its projection');
|
|
1480
|
-
END;
|
|
1481
|
-
|
|
1482
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_model_call_valid
|
|
1483
|
-
BEFORE INSERT ON log_entries
|
|
1484
|
-
WHEN NEW.model_call_id IS NOT NULL
|
|
1485
|
-
AND NOT EXISTS (
|
|
1486
|
-
SELECT 1
|
|
1487
|
-
FROM model_calls call
|
|
1488
|
-
JOIN inference_calls inference ON inference.id = call.id
|
|
1489
|
-
WHERE call.id = NEW.model_call_id
|
|
1490
|
-
AND inference.turn_id = NEW.turn_id
|
|
1491
|
-
AND inference.state != 'pending'
|
|
1492
|
-
AND (
|
|
1493
|
-
(inference.kind = 'bare' AND NEW.op = 'BARE')
|
|
1494
|
-
OR (
|
|
1495
|
-
inference.kind = 'emission'
|
|
1496
|
-
AND NEW.op IS NULL
|
|
1497
|
-
AND json_extract(NEW.attrs, '$.kind') IN ('turnOps', 'emissionAttempt')
|
|
1498
|
-
)
|
|
1499
|
-
)
|
|
1500
|
-
)
|
|
1501
|
-
BEGIN
|
|
1502
|
-
SELECT RAISE(ABORT, 'log entry model call does not match its represented result');
|
|
1503
|
-
END;
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
-- Successful log-KILL rows are durable curation events even though
|
|
1508
|
-
-- their ordinary packet projection is suppressed. Preserve the exact selected
|
|
1509
|
-
-- set and each target's before/after projection so a broad selector never
|
|
1510
|
-
-- collapses into the lossy fact `matched: N`.
|
|
1511
|
-
CREATE TABLE IF NOT EXISTS log_curation_effects (
|
|
1512
|
-
operation_log_entry_id INTEGER NOT NULL,
|
|
1513
|
-
target_log_entry_id INTEGER NOT NULL,
|
|
1514
|
-
active_before INTEGER NOT NULL CHECK (active_before IN (0, 1)),
|
|
1515
|
-
active_after INTEGER NOT NULL CHECK (active_after IN (0, 1)),
|
|
1516
|
-
folded_before TEXT NOT NULL
|
|
1517
|
-
CHECK (json_valid(folded_before) AND json_type(folded_before) = 'array'),
|
|
1518
|
-
folded_after TEXT NOT NULL
|
|
1519
|
-
CHECK (json_valid(folded_after) AND json_type(folded_after) = 'array'),
|
|
1520
|
-
PRIMARY KEY (operation_log_entry_id, target_log_entry_id),
|
|
1521
|
-
CHECK (operation_log_entry_id != target_log_entry_id),
|
|
1522
|
-
FOREIGN KEY (operation_log_entry_id) REFERENCES log_entries(id) ON DELETE CASCADE,
|
|
1523
|
-
FOREIGN KEY (target_log_entry_id) REFERENCES log_entries(id) ON DELETE CASCADE
|
|
1524
|
-
) STRICT, WITHOUT ROWID;
|
|
1525
|
-
|
|
1526
|
-
CREATE INDEX IF NOT EXISTS log_curation_effects_target
|
|
1527
|
-
ON log_curation_effects (target_log_entry_id);
|
|
1528
|
-
|
|
1529
|
-
-- Curation effects are append-only execution evidence. They may disappear
|
|
1530
|
-
-- only when either referenced event is already being removed with its
|
|
1531
|
-
-- containing history; direct mutation while both events survive is forbidden.
|
|
1532
|
-
CREATE TRIGGER IF NOT EXISTS log_curation_effects_immutable
|
|
1533
|
-
BEFORE UPDATE ON log_curation_effects
|
|
1534
|
-
BEGIN
|
|
1535
|
-
SELECT RAISE(ABORT, 'log curation effects are immutable execution evidence');
|
|
1536
|
-
END;
|
|
1537
|
-
|
|
1538
|
-
CREATE TRIGGER IF NOT EXISTS log_curation_effects_delete_with_history_only
|
|
1539
|
-
BEFORE DELETE ON log_curation_effects
|
|
1540
|
-
WHEN EXISTS (
|
|
1541
|
-
SELECT 1 FROM log_entries WHERE id = OLD.operation_log_entry_id
|
|
1542
|
-
)
|
|
1543
|
-
AND EXISTS (
|
|
1544
|
-
SELECT 1 FROM log_entries WHERE id = OLD.target_log_entry_id
|
|
1545
|
-
)
|
|
1546
|
-
BEGIN
|
|
1547
|
-
SELECT RAISE(ABORT, 'log curation effects can only be removed with their containing history');
|
|
1548
|
-
END;
|
|
1549
|
-
|
|
1550
|
-
-- Make an invalid curation record structurally unavailable: the event must be
|
|
1551
|
-
-- one successful log-KILL row, both rows must belong to the same
|
|
1552
|
-
-- worker, and its state transition must match that op.
|
|
1553
|
-
CREATE TRIGGER IF NOT EXISTS log_curation_effects_valid
|
|
1554
|
-
BEFORE INSERT ON log_curation_effects
|
|
1555
|
-
BEGIN
|
|
1556
|
-
SELECT CASE WHEN
|
|
1557
|
-
NOT EXISTS (
|
|
1558
|
-
SELECT 1
|
|
1559
|
-
FROM log_entries operation
|
|
1560
|
-
JOIN log_entries target ON target.id = NEW.target_log_entry_id
|
|
1561
|
-
WHERE operation.id = NEW.operation_log_entry_id
|
|
1562
|
-
AND operation.op = 'KILL'
|
|
1563
|
-
AND operation.status_rx < 400
|
|
1564
|
-
AND operation.worker_id = target.worker_id
|
|
1565
|
-
)
|
|
1566
|
-
OR NOT EXISTS (
|
|
1567
|
-
-- {§log-kill-scope} — a scoped KILL keeps the row active and changes its visibility;
|
|
1568
|
-
-- a whole KILL retires it with its visibility untouched.
|
|
1569
|
-
SELECT 1
|
|
1570
|
-
FROM log_entries operation
|
|
1571
|
-
WHERE operation.id = NEW.operation_log_entry_id
|
|
1572
|
-
AND operation.op = 'KILL'
|
|
1573
|
-
AND operation.scheme = 'log'
|
|
1574
|
-
AND NEW.active_before = 1
|
|
1575
|
-
AND (
|
|
1576
|
-
NEW.active_after = 1
|
|
1577
|
-
OR (
|
|
1578
|
-
NEW.active_after = 0
|
|
1579
|
-
AND json(NEW.folded_before) = json(NEW.folded_after)
|
|
1580
|
-
)
|
|
1581
|
-
)
|
|
1582
|
-
)
|
|
1583
|
-
OR EXISTS (
|
|
1584
|
-
SELECT 1
|
|
1585
|
-
FROM (
|
|
1586
|
-
SELECT 'before' AS side, key, value, type FROM json_each(NEW.folded_before)
|
|
1587
|
-
UNION ALL
|
|
1588
|
-
SELECT 'after' AS side, key, value, type FROM json_each(NEW.folded_after)
|
|
1589
|
-
) range
|
|
1590
|
-
WHERE range.type != 'array'
|
|
1591
|
-
OR json_array_length(range.value) != 2
|
|
1592
|
-
OR COALESCE(json_type(range.value, '$[0]'), '') != 'integer'
|
|
1593
|
-
OR COALESCE(json_type(range.value, '$[1]'), '') != 'integer'
|
|
1594
|
-
OR json_extract(range.value, '$[0]') < 1
|
|
1595
|
-
OR (
|
|
1596
|
-
json_extract(range.value, '$[1]') != -1
|
|
1597
|
-
AND json_extract(range.value, '$[1]') < json_extract(range.value, '$[0]')
|
|
1598
|
-
)
|
|
1599
|
-
OR EXISTS (
|
|
1600
|
-
SELECT 1
|
|
1601
|
-
FROM (
|
|
1602
|
-
SELECT key, value FROM json_each(
|
|
1603
|
-
CASE range.side
|
|
1604
|
-
WHEN 'before' THEN NEW.folded_before
|
|
1605
|
-
ELSE NEW.folded_after
|
|
1606
|
-
END
|
|
1607
|
-
)
|
|
1608
|
-
) previous
|
|
1609
|
-
WHERE previous.key = range.key - 1
|
|
1610
|
-
AND (
|
|
1611
|
-
json_extract(previous.value, '$[1]') = -1
|
|
1612
|
-
OR json_extract(range.value, '$[0]') <= json_extract(previous.value, '$[1]') + 1
|
|
1613
|
-
)
|
|
1614
|
-
)
|
|
1615
|
-
)
|
|
1616
|
-
THEN RAISE(ABORT, 'invalid log curation effect') END;
|
|
1617
|
-
END;
|
|
1618
|
-
|
|
1619
|
-
-- The dispatcher binds an exact, transient curation plan into attrs on the
|
|
1620
|
-
-- successful log-KILL row. No other row may carry that payload.
|
|
1621
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_curation_payload_valid
|
|
1622
|
-
BEFORE INSERT ON log_entries
|
|
1623
|
-
WHEN json_type(NEW.attrs, '$.__plurnk_curation') IS NOT NULL
|
|
1624
|
-
AND NOT (
|
|
1625
|
-
NEW.op = 'KILL'
|
|
1626
|
-
AND NEW.status_rx < 400
|
|
1627
|
-
AND NEW.scheme = 'log'
|
|
1628
|
-
AND json_type(NEW.attrs, '$.__plurnk_curation') = 'object'
|
|
1629
|
-
)
|
|
1630
|
-
BEGIN
|
|
1631
|
-
SELECT RAISE(ABORT, 'private log curation payload requires a successful log curation row');
|
|
1632
|
-
END;
|
|
1633
|
-
|
|
1634
|
-
-- One outer INSERT owns the whole landed curation event: exact selected rows,
|
|
1635
|
-
-- their before/after projection, and the resulting current
|
|
1636
|
-
-- state. Trigger failure rolls the operation row and all effects back together.
|
|
1637
|
-
-- The private plan is erased before INSERT returns.
|
|
1638
|
-
-- {§log-kill-scope} — a log KILL either retires a row whole (active 1→0, visibility untouched)
|
|
1639
|
-
-- or folds a span of its body (active stays 1, visibility changes).
|
|
1640
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_apply_curation
|
|
1641
|
-
AFTER INSERT ON log_entries
|
|
1642
|
-
WHEN NEW.op = 'KILL'
|
|
1643
|
-
AND NEW.status_rx < 400
|
|
1644
|
-
AND NEW.scheme = 'log'
|
|
1645
|
-
AND json_type(NEW.attrs, '$.__plurnk_curation') = 'object'
|
|
1646
|
-
BEGIN
|
|
1647
|
-
SELECT CASE WHEN
|
|
1648
|
-
COALESCE(json_type(NEW.attrs, '$.__plurnk_curation.targets'), '') != 'array'
|
|
1649
|
-
OR json_array_length(NEW.attrs, '$.__plurnk_curation.targets') = 0
|
|
1650
|
-
OR EXISTS (
|
|
1651
|
-
SELECT 1
|
|
1652
|
-
FROM json_each(NEW.attrs, '$.__plurnk_curation.targets') selected
|
|
1653
|
-
WHERE selected.type != 'object'
|
|
1654
|
-
OR COALESCE(json_type(selected.value, '$.id'), '') != 'integer'
|
|
1655
|
-
OR json_extract(selected.value, '$.id') <= 0
|
|
1656
|
-
OR COALESCE(json_type(selected.value, '$.activeBefore'), '') != 'integer'
|
|
1657
|
-
OR json_extract(selected.value, '$.activeBefore') NOT IN (0, 1)
|
|
1658
|
-
OR COALESCE(json_type(selected.value, '$.activeAfter'), '') != 'integer'
|
|
1659
|
-
OR json_extract(selected.value, '$.activeAfter') NOT IN (0, 1)
|
|
1660
|
-
OR COALESCE(json_type(selected.value, '$.foldedBefore'), '') != 'array'
|
|
1661
|
-
OR COALESCE(json_type(selected.value, '$.foldedAfter'), '') != 'array'
|
|
1662
|
-
OR EXISTS (
|
|
1663
|
-
SELECT 1 FROM json_each(selected.value) field
|
|
1664
|
-
WHERE field.key NOT IN ('id', 'activeBefore', 'activeAfter', 'foldedBefore', 'foldedAfter')
|
|
1665
|
-
)
|
|
1666
|
-
OR EXISTS (
|
|
1667
|
-
SELECT 1
|
|
1668
|
-
FROM (
|
|
1669
|
-
SELECT 'before' AS side, range.key, range.value, range.type
|
|
1670
|
-
FROM json_each(json_extract(selected.value, '$.foldedBefore')) range
|
|
1671
|
-
UNION ALL
|
|
1672
|
-
SELECT 'after' AS side, range.key, range.value, range.type
|
|
1673
|
-
FROM json_each(json_extract(selected.value, '$.foldedAfter')) range
|
|
1674
|
-
) range
|
|
1675
|
-
WHERE range.type != 'array'
|
|
1676
|
-
OR json_array_length(range.value) != 2
|
|
1677
|
-
OR COALESCE(json_type(range.value, '$[0]'), '') != 'integer'
|
|
1678
|
-
OR COALESCE(json_type(range.value, '$[1]'), '') != 'integer'
|
|
1679
|
-
OR json_extract(range.value, '$[0]') < 1
|
|
1680
|
-
OR (
|
|
1681
|
-
json_extract(range.value, '$[1]') != -1
|
|
1682
|
-
AND json_extract(range.value, '$[1]') < json_extract(range.value, '$[0]')
|
|
1683
|
-
)
|
|
1684
|
-
OR EXISTS (
|
|
1685
|
-
SELECT 1
|
|
1686
|
-
FROM json_each(
|
|
1687
|
-
CASE range.side
|
|
1688
|
-
WHEN 'before' THEN json_extract(selected.value, '$.foldedBefore')
|
|
1689
|
-
ELSE json_extract(selected.value, '$.foldedAfter')
|
|
1690
|
-
END
|
|
1691
|
-
) previous
|
|
1692
|
-
WHERE previous.key = range.key - 1
|
|
1693
|
-
AND (
|
|
1694
|
-
json_extract(previous.value, '$[1]') = -1
|
|
1695
|
-
OR json_extract(range.value, '$[0]') <= json_extract(previous.value, '$[1]') + 1
|
|
1696
|
-
)
|
|
1697
|
-
)
|
|
1698
|
-
)
|
|
1699
|
-
)
|
|
1700
|
-
OR (
|
|
1701
|
-
SELECT COUNT(*) FROM json_each(NEW.attrs, '$.__plurnk_curation.targets')
|
|
1702
|
-
) != (
|
|
1703
|
-
SELECT COUNT(DISTINCT json_extract(value, '$.id'))
|
|
1704
|
-
FROM json_each(NEW.attrs, '$.__plurnk_curation.targets')
|
|
1705
|
-
)
|
|
1706
|
-
OR EXISTS (
|
|
1707
|
-
SELECT 1
|
|
1708
|
-
FROM json_each(NEW.attrs, '$.__plurnk_curation.targets') selected
|
|
1709
|
-
LEFT JOIN log_entries target ON target.id = json_extract(selected.value, '$.id')
|
|
1710
|
-
LEFT JOIN log_entry_projections projection ON projection.log_entry_id = target.id
|
|
1711
|
-
WHERE target.id IS NULL
|
|
1712
|
-
OR projection.log_entry_id IS NULL
|
|
1713
|
-
OR target.worker_id != NEW.worker_id
|
|
1714
|
-
OR target.id = NEW.id
|
|
1715
|
-
OR projection.active != json_extract(selected.value, '$.activeBefore')
|
|
1716
|
-
OR json(projection.folded) != json(json_extract(selected.value, '$.foldedBefore'))
|
|
1717
|
-
OR NOT (
|
|
1718
|
-
json_extract(selected.value, '$.activeBefore') = 1
|
|
1719
|
-
AND (
|
|
1720
|
-
json_extract(selected.value, '$.activeAfter') = 1
|
|
1721
|
-
OR json(json_extract(selected.value, '$.foldedBefore')) = json(json_extract(selected.value, '$.foldedAfter'))
|
|
1722
|
-
)
|
|
1723
|
-
)
|
|
1724
|
-
)
|
|
1725
|
-
THEN RAISE(ABORT, 'invalid private log curation payload') END;
|
|
1726
|
-
|
|
1727
|
-
INSERT INTO log_curation_effects (
|
|
1728
|
-
operation_log_entry_id,
|
|
1729
|
-
target_log_entry_id,
|
|
1730
|
-
active_before,
|
|
1731
|
-
active_after,
|
|
1732
|
-
folded_before,
|
|
1733
|
-
folded_after
|
|
1734
|
-
)
|
|
1735
|
-
SELECT
|
|
1736
|
-
NEW.id,
|
|
1737
|
-
target.id,
|
|
1738
|
-
json_extract(selected.value, '$.activeBefore'),
|
|
1739
|
-
json_extract(selected.value, '$.activeAfter'),
|
|
1740
|
-
json_extract(selected.value, '$.foldedBefore'),
|
|
1741
|
-
json_extract(selected.value, '$.foldedAfter')
|
|
1742
|
-
FROM json_each(NEW.attrs, '$.__plurnk_curation.targets') selected
|
|
1743
|
-
JOIN log_entries target ON target.id = json_extract(selected.value, '$.id');
|
|
1744
|
-
|
|
1745
|
-
UPDATE log_entry_projections
|
|
1746
|
-
SET active = (
|
|
1747
|
-
SELECT json_extract(selected.value, '$.activeAfter')
|
|
1748
|
-
FROM json_each(NEW.attrs, '$.__plurnk_curation.targets') selected
|
|
1749
|
-
WHERE json_extract(selected.value, '$.id') = log_entry_projections.log_entry_id
|
|
1750
|
-
),
|
|
1751
|
-
folded = (
|
|
1752
|
-
SELECT json_extract(selected.value, '$.foldedAfter')
|
|
1753
|
-
FROM json_each(NEW.attrs, '$.__plurnk_curation.targets') selected
|
|
1754
|
-
WHERE json_extract(selected.value, '$.id') = log_entry_projections.log_entry_id
|
|
1755
|
-
)
|
|
1756
|
-
WHERE log_entry_id IN (
|
|
1757
|
-
SELECT json_extract(value, '$.id')
|
|
1758
|
-
FROM json_each(NEW.attrs, '$.__plurnk_curation.targets')
|
|
1759
|
-
);
|
|
1760
|
-
|
|
1761
|
-
UPDATE log_entries
|
|
1762
|
-
SET attrs = json_remove(attrs, '$.__plurnk_curation')
|
|
1763
|
-
WHERE id = NEW.id;
|
|
1764
|
-
END;
|
|
1765
|
-
|
|
1766
|
-
-- Column-scoped immutability: the original action's identity, target, and
|
|
1767
|
-
-- initial projection never change. Proposal lifecycle may mutate its outcome;
|
|
1768
|
-
-- curation state lives outside the event row. Keep attrs separate so the
|
|
1769
|
-
-- curation trigger's private-payload removal cannot exempt other columns.
|
|
1770
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_immutable_core
|
|
1771
|
-
BEFORE UPDATE OF
|
|
1772
|
-
worker_id, loop_id, turn_id, sequence, at, origin, source, inherited_history, model_call_id,
|
|
1773
|
-
op, delimiter, signal,
|
|
1774
|
-
scheme, username, password, hostname,
|
|
1775
|
-
port, pathname, query, fragment,
|
|
1776
|
-
lineMarker, tx, mimetype_tx, mimetype_rx, initial_folded
|
|
1777
|
-
ON log_entries
|
|
1778
|
-
BEGIN
|
|
1779
|
-
SELECT RAISE(ABORT, 'log_entries core fields are immutable; only lifecycle outcome and derived attachments may change');
|
|
1780
|
-
END;
|
|
1781
|
-
|
|
1782
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_immutable_attrs
|
|
1783
|
-
BEFORE UPDATE OF attrs ON log_entries
|
|
1784
|
-
WHEN COALESCE((
|
|
1785
|
-
json_type(OLD.attrs, '$.__plurnk_curation') = 'object'
|
|
1786
|
-
AND NEW.attrs = json_remove(OLD.attrs, '$.__plurnk_curation')
|
|
1787
|
-
), 0) = 0
|
|
1788
|
-
BEGIN
|
|
1789
|
-
SELECT RAISE(ABORT, 'log_entries attrs are immutable outside curation payload removal');
|
|
1790
|
-
END;
|
|
1791
|
-
|
|
1792
|
-
-- The engine may stamp an originating row exactly once. No later reassignment
|
|
1793
|
-
-- can sever or counterfeit the occurrence identity.
|
|
1794
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_ambient_event_once
|
|
1795
|
-
BEFORE UPDATE OF ambient_event_id ON log_entries
|
|
1796
|
-
WHEN NOT (OLD.ambient_event_id IS NULL AND NEW.ambient_event_id IS NOT NULL)
|
|
1797
|
-
BEGIN
|
|
1798
|
-
SELECT RAISE(ABORT, 'log_entries ambient event identity may only be assigned once');
|
|
1799
|
-
END;
|
|
1800
|
-
|
|
1801
|
-
-- One relational projection owns activity eligibility, audience, and snapshot
|
|
1802
|
-
-- shape for both immediately-final and proposal-settlement paths.
|
|
1803
|
-
CREATE VIEW IF NOT EXISTS ambient_activity_candidates AS
|
|
1804
|
-
SELECT *
|
|
1805
|
-
FROM (
|
|
1806
|
-
SELECT w.workspace_id,
|
|
1807
|
-
le.worker_id AS producer_worker_id,
|
|
1808
|
-
-- {§env-delta-child-activity} — the runtime's own materialization (turn-0
|
|
1809
|
-
-- initialization, doc-reconciliation maintenance, operation batches) is
|
|
1810
|
-
-- private to the worker it serves and never crosses to the parent.
|
|
1811
|
-
CASE
|
|
1812
|
-
WHEN t.producer = '_plurnk' AND t.kind IN ('operation', 'initialization', 'maintenance') THEN NULL
|
|
1813
|
-
ELSE w.parent_worker_id
|
|
1814
|
-
END AS target_parent_worker_id,
|
|
1815
|
-
CASE
|
|
1816
|
-
WHEN le.state = 'resolved'
|
|
1817
|
-
AND le.status_rx BETWEEN 200 AND 399
|
|
1818
|
-
AND le.status_rx != 304
|
|
1819
|
-
AND (
|
|
1820
|
-
(
|
|
1821
|
-
le.op IN ('EDIT', 'KILL')
|
|
1822
|
-
AND le.scheme = 'worker'
|
|
1823
|
-
AND le.hostname IS NULL
|
|
1824
|
-
AND le.pathname IS NOT NULL
|
|
1825
|
-
)
|
|
1826
|
-
OR (
|
|
1827
|
-
le.op IN ('COPY', 'MOVE')
|
|
1828
|
-
AND json_valid(le.rx)
|
|
1829
|
-
AND EXISTS (
|
|
1830
|
-
SELECT 1 FROM json_each(le.rx, '$.effects') effect
|
|
1831
|
-
WHERE json_type(effect.value) = 'object'
|
|
1832
|
-
AND substr(CAST(json_extract(effect.value, '$.target') AS TEXT), 1, 10) = 'worker:///'
|
|
1833
|
-
)
|
|
1834
|
-
)
|
|
1835
|
-
)
|
|
1836
|
-
THEN 1 ELSE 0
|
|
1837
|
-
END AS workspace_broadcast,
|
|
1838
|
-
le.id AS source_record_id,
|
|
1839
|
-
le.at,
|
|
1840
|
-
le.source,
|
|
1841
|
-
le.op,
|
|
1842
|
-
le.delimiter,
|
|
1843
|
-
le.signal,
|
|
1844
|
-
le.scheme,
|
|
1845
|
-
le.username,
|
|
1846
|
-
le.password,
|
|
1847
|
-
le.hostname,
|
|
1848
|
-
le.port,
|
|
1849
|
-
le.pathname,
|
|
1850
|
-
le.query,
|
|
1851
|
-
le.fragment,
|
|
1852
|
-
le.lineMarker AS line_marker,
|
|
1853
|
-
le.tx,
|
|
1854
|
-
le.mimetype_tx,
|
|
1855
|
-
le.rx,
|
|
1856
|
-
le.mimetype_rx,
|
|
1857
|
-
le.status_rx,
|
|
1858
|
-
le.state,
|
|
1859
|
-
le.outcome,
|
|
1860
|
-
json_remove(le.attrs, '$.__plurnk_curation') AS attrs
|
|
1861
|
-
FROM log_entries le
|
|
1862
|
-
JOIN workers w ON w.id = le.worker_id
|
|
1863
|
-
JOIN loops l ON l.id = le.loop_id
|
|
1864
|
-
JOIN turns t ON t.id = le.turn_id
|
|
1865
|
-
WHERE le.ambient_event_id IS NULL
|
|
1866
|
-
AND le.inherited_history = 0
|
|
1867
|
-
AND le.op IS NOT NULL
|
|
1868
|
-
AND le.state != 'proposed'
|
|
1869
|
-
AND NOT (
|
|
1870
|
-
le.op = 'SEND'
|
|
1871
|
-
AND le.scheme IS NULL
|
|
1872
|
-
AND l.status IN (200, 413, 429, 499, 500, 504, 508)
|
|
1873
|
-
)
|
|
1874
|
-
) candidate
|
|
1875
|
-
WHERE target_parent_worker_id IS NOT NULL OR workspace_broadcast = 1;
|
|
1876
|
-
|
|
1877
|
-
-- Every final op-bearing child row is parent activity. A successful operation
|
|
1878
|
-
-- whose landed effects touch worker:/// additionally acquires the workspace
|
|
1879
|
-
-- audience. Observer rows and copied fork history cannot republish themselves.
|
|
1880
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_append_ambient_event_insert
|
|
1881
|
-
AFTER INSERT ON log_entries
|
|
1882
|
-
WHEN NEW.state != 'proposed'
|
|
1883
|
-
BEGIN
|
|
1884
|
-
INSERT INTO ambient_events (
|
|
1885
|
-
workspace_id, producer_worker_id, target_parent_worker_id,
|
|
1886
|
-
workspace_broadcast, kind, source_record_id, at, source,
|
|
1887
|
-
op, delimiter, signal,
|
|
1888
|
-
scheme, username, password, hostname, port, pathname, query, fragment,
|
|
1889
|
-
line_marker, tx, mimetype_tx, rx, mimetype_rx, status_rx,
|
|
1890
|
-
state, outcome, attrs
|
|
1891
|
-
)
|
|
1892
|
-
SELECT workspace_id, producer_worker_id, target_parent_worker_id,
|
|
1893
|
-
workspace_broadcast, 'activity', source_record_id, at, source,
|
|
1894
|
-
op, delimiter, signal,
|
|
1895
|
-
scheme, username, password, hostname, port, pathname, query, fragment,
|
|
1896
|
-
line_marker, tx, mimetype_tx, rx, mimetype_rx, status_rx,
|
|
1897
|
-
state, outcome, attrs
|
|
1898
|
-
FROM ambient_activity_candidates
|
|
1899
|
-
WHERE source_record_id = NEW.id;
|
|
1900
|
-
|
|
1901
|
-
UPDATE log_entries
|
|
1902
|
-
SET ambient_event_id = (
|
|
1903
|
-
SELECT id FROM ambient_events
|
|
1904
|
-
WHERE producer_worker_id = NEW.worker_id
|
|
1905
|
-
AND kind = 'activity'
|
|
1906
|
-
AND source_record_id = NEW.id
|
|
1907
|
-
)
|
|
1908
|
-
WHERE id = NEW.id
|
|
1909
|
-
AND EXISTS (
|
|
1910
|
-
SELECT 1 FROM ambient_events
|
|
1911
|
-
WHERE producer_worker_id = NEW.worker_id
|
|
1912
|
-
AND kind = 'activity'
|
|
1913
|
-
AND source_record_id = NEW.id
|
|
1914
|
-
);
|
|
1915
|
-
END;
|
|
1916
|
-
|
|
1917
|
-
-- A proposed operation becomes activity only when its lifecycle settles.
|
|
1918
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_append_ambient_event_resolve
|
|
1919
|
-
AFTER UPDATE OF state, status_rx, rx, outcome ON log_entries
|
|
1920
|
-
WHEN OLD.state = 'proposed' AND NEW.state != 'proposed'
|
|
1921
|
-
BEGIN
|
|
1922
|
-
INSERT INTO ambient_events (
|
|
1923
|
-
workspace_id, producer_worker_id, target_parent_worker_id,
|
|
1924
|
-
workspace_broadcast, kind, source_record_id, at, source,
|
|
1925
|
-
op, delimiter, signal,
|
|
1926
|
-
scheme, username, password, hostname, port, pathname, query, fragment,
|
|
1927
|
-
line_marker, tx, mimetype_tx, rx, mimetype_rx, status_rx,
|
|
1928
|
-
state, outcome, attrs
|
|
1929
|
-
)
|
|
1930
|
-
SELECT workspace_id, producer_worker_id, target_parent_worker_id,
|
|
1931
|
-
workspace_broadcast, 'activity', source_record_id, at, source,
|
|
1932
|
-
op, delimiter, signal,
|
|
1933
|
-
scheme, username, password, hostname, port, pathname, query, fragment,
|
|
1934
|
-
line_marker, tx, mimetype_tx, rx, mimetype_rx, status_rx,
|
|
1935
|
-
state, outcome, attrs
|
|
1936
|
-
FROM ambient_activity_candidates
|
|
1937
|
-
WHERE source_record_id = NEW.id;
|
|
1938
|
-
|
|
1939
|
-
UPDATE log_entries
|
|
1940
|
-
SET ambient_event_id = (
|
|
1941
|
-
SELECT id FROM ambient_events
|
|
1942
|
-
WHERE producer_worker_id = NEW.worker_id
|
|
1943
|
-
AND kind = 'activity'
|
|
1944
|
-
AND source_record_id = NEW.id
|
|
1945
|
-
)
|
|
1946
|
-
WHERE id = NEW.id
|
|
1947
|
-
AND EXISTS (
|
|
1948
|
-
SELECT 1 FROM ambient_events
|
|
1949
|
-
WHERE producer_worker_id = NEW.worker_id
|
|
1950
|
-
AND kind = 'activity'
|
|
1951
|
-
AND source_record_id = NEW.id
|
|
1952
|
-
);
|
|
1953
|
-
END;
|
|
1954
|
-
|
|
1955
|
-
-- {§client-interactions}: the durable discoverable half of a client-owned
|
|
1956
|
-
-- interaction. The process-local lifecycle owner holds the awaiting callable;
|
|
1957
|
-
-- this row holds only presentation and routing facts. Settlement deletes the
|
|
1958
|
-
-- row, so client response payloads and owner-private continuation state are
|
|
1959
|
-
-- never copied into persistence.
|
|
1960
|
-
CREATE TABLE IF NOT EXISTS client_interactions (
|
|
1961
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
1962
|
-
worker_id INTEGER NOT NULL,
|
|
1963
|
-
loop_id INTEGER NOT NULL,
|
|
1964
|
-
turn_id INTEGER NOT NULL,
|
|
1965
|
-
request TEXT NOT NULL CHECK (json_valid(request) AND json_type(request) = 'object'),
|
|
1966
|
-
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
1967
|
-
FOREIGN KEY (worker_id) REFERENCES workers(id) ON DELETE CASCADE,
|
|
1968
|
-
FOREIGN KEY (loop_id) REFERENCES loops(id) ON DELETE CASCADE,
|
|
1969
|
-
FOREIGN KEY (turn_id) REFERENCES turns(id) ON DELETE CASCADE
|
|
1970
|
-
) STRICT;
|
|
1971
|
-
|
|
1972
|
-
CREATE INDEX IF NOT EXISTS client_interactions_worker_id_id
|
|
1973
|
-
ON client_interactions (worker_id, id);
|
|
1974
|
-
|
|
1975
|
-
-- subscriptions
|
|
1976
|
-
-- Durable subscription lifecycle per SPEC {§subscriptions}. The row records what
|
|
1977
|
-
-- the worker holds and routes cancellation to a separate process-local callable;
|
|
1978
|
-
-- it never serializes that callable. Closed rows persist for forensics; partial
|
|
1979
|
-
-- unique index enforces one active subscription per entry. The composite
|
|
1980
|
-
-- foreign key makes that entry part of the subscribing Worker's own space.
|
|
1981
|
-
CREATE TABLE IF NOT EXISTS subscriptions (
|
|
1982
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
1983
|
-
version INTEGER NOT NULL DEFAULT 0 CHECK (version >= 0),
|
|
1984
|
-
worker_id INTEGER NOT NULL,
|
|
1985
|
-
entry_id INTEGER NOT NULL,
|
|
1986
|
-
scheme TEXT NOT NULL CHECK (length(scheme) > 0),
|
|
1987
|
-
handle TEXT NOT NULL CHECK (length(handle) > 0),
|
|
1988
|
-
published_channel TEXT CHECK (published_channel IS NULL OR length(published_channel) > 0),
|
|
1989
|
-
opened_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
1990
|
-
-- EXEC `<T,P>` poll policy: NULL = default backoff, 0 = disabled, positive = fixed cadence.
|
|
1991
|
-
-- While the owning loop hibernates (202), an armed policy wakes it to inspect the stream ({§exec-poll}).
|
|
1992
|
-
poll_seconds INTEGER CHECK (poll_seconds IS NULL OR poll_seconds >= 0),
|
|
1993
|
-
-- EXEC `<0>` — turn-scoped: the stream is reaped at the worker's next pre-turn so it never survives
|
|
1994
|
-
-- into the subsequent turn; its terminal output surfaces initially visible like any conclusion. {§exec-poll}
|
|
1995
|
-
turn_scoped INTEGER NOT NULL DEFAULT 0 CHECK (turn_scoped IN (0, 1)),
|
|
1996
|
-
closed_at TEXT,
|
|
1997
|
-
close_status INTEGER CHECK (close_status IS NULL OR (close_status BETWEEN 100 AND 599)),
|
|
1998
|
-
close_result TEXT CHECK (close_result IS NULL OR json_valid(close_result)),
|
|
1999
|
-
channel_results TEXT CHECK (channel_results IS NULL OR json_valid(channel_results)),
|
|
2000
|
-
CHECK ((closed_at IS NULL AND close_status IS NULL AND close_result IS NULL AND channel_results IS NULL)
|
|
2001
|
-
OR (closed_at IS NOT NULL AND close_status IS NOT NULL AND close_result IS NOT NULL AND channel_results IS NOT NULL)),
|
|
2002
|
-
FOREIGN KEY (worker_id) REFERENCES workers(id) ON DELETE CASCADE,
|
|
2003
|
-
FOREIGN KEY (entry_id, worker_id) REFERENCES entries(id, owner_id) ON DELETE CASCADE
|
|
2004
|
-
) STRICT;
|
|
2005
|
-
|
|
2006
|
-
CREATE UNIQUE INDEX IF NOT EXISTS subscriptions_active_one_per_entry
|
|
2007
|
-
ON subscriptions (entry_id)
|
|
2008
|
-
WHERE closed_at IS NULL;
|
|
2009
|
-
|
|
2010
|
-
CREATE INDEX IF NOT EXISTS subscriptions_scheme_active
|
|
2011
|
-
ON subscriptions (scheme)
|
|
2012
|
-
WHERE closed_at IS NULL;
|
|
2013
|
-
|
|
2014
|
-
CREATE INDEX IF NOT EXISTS subscriptions_opened_at ON subscriptions (opened_at);
|
|
2015
|
-
|
|
2016
|
-
CREATE TRIGGER IF NOT EXISTS subscriptions_result_contract_insert
|
|
2017
|
-
BEFORE INSERT ON subscriptions
|
|
2018
|
-
WHEN NEW.closed_at IS NOT NULL
|
|
2019
|
-
OR NEW.close_status IS NOT NULL
|
|
2020
|
-
OR NEW.close_result IS NOT NULL
|
|
2021
|
-
OR NEW.channel_results IS NOT NULL
|
|
2022
|
-
BEGIN
|
|
2023
|
-
SELECT RAISE(ABORT, 'subscription must open before it can settle');
|
|
2024
|
-
END;
|
|
2025
|
-
|
|
2026
|
-
CREATE TRIGGER IF NOT EXISTS subscriptions_result_contract_update
|
|
2027
|
-
BEFORE UPDATE OF closed_at, close_status, close_result, channel_results ON subscriptions
|
|
2028
|
-
WHEN NOT (
|
|
2029
|
-
(NEW.closed_at IS NULL AND NEW.close_status IS NULL AND NEW.close_result IS NULL AND NEW.channel_results IS NULL)
|
|
2030
|
-
OR (
|
|
2031
|
-
NEW.closed_at IS NOT NULL
|
|
2032
|
-
AND NEW.close_status IS NOT NULL
|
|
2033
|
-
AND NEW.close_result IS NOT NULL
|
|
2034
|
-
AND NEW.channel_results IS NOT NULL
|
|
2035
|
-
AND json_valid(NEW.close_result)
|
|
2036
|
-
AND json_valid(NEW.channel_results)
|
|
2037
|
-
AND json_type(NEW.channel_results) = 'object'
|
|
2038
|
-
AND json_type(NEW.close_result, '$.status') = 'integer'
|
|
2039
|
-
AND json_extract(NEW.close_result, '$.status') = NEW.close_status
|
|
2040
|
-
AND (
|
|
2041
|
-
(NEW.close_status < 400 AND json_type(NEW.close_result, '$.problem') IS NULL)
|
|
2042
|
-
OR (
|
|
2043
|
-
NEW.close_status >= 400
|
|
2044
|
-
AND json_type(NEW.close_result, '$.problem') = 'object'
|
|
2045
|
-
AND json_extract(NEW.close_result, '$.problem.status') = NEW.close_status
|
|
2046
|
-
)
|
|
2047
|
-
)
|
|
2048
|
-
)
|
|
2049
|
-
)
|
|
2050
|
-
BEGIN
|
|
2051
|
-
SELECT RAISE(ABORT, 'subscription terminal result violates the operation-result contract');
|
|
2052
|
-
END;
|
|
2053
|
-
|
|
2054
|
-
-- A settlement may override the universal result for exact named channels.
|
|
2055
|
-
-- Unknown channels and malformed results fail before the subscription or any
|
|
2056
|
-
-- representation changes. The JS boundary additionally rejects projection
|
|
2057
|
-
-- fields that are structurally unavailable in ChannelProducerResult.
|
|
2058
|
-
CREATE TRIGGER IF NOT EXISTS subscriptions_channel_results_contract
|
|
2059
|
-
BEFORE UPDATE OF closed_at, close_status, close_result, channel_results ON subscriptions
|
|
2060
|
-
WHEN NEW.closed_at IS NOT NULL AND (
|
|
2061
|
-
EXISTS (
|
|
2062
|
-
SELECT 1
|
|
2063
|
-
FROM json_each(NEW.channel_results) AS channel_result
|
|
2064
|
-
LEFT JOIN entry_channels ec
|
|
2065
|
-
ON ec.entry_id = NEW.entry_id AND ec.name = channel_result.key
|
|
2066
|
-
WHERE ec.name IS NULL
|
|
2067
|
-
OR json_type(channel_result.value) != 'object'
|
|
2068
|
-
OR json_type(channel_result.value, '$.status') != 'integer'
|
|
2069
|
-
OR json_extract(channel_result.value, '$.status') NOT BETWEEN 200 AND 599
|
|
2070
|
-
OR json_extract(channel_result.value, '$.status') = 202
|
|
2071
|
-
OR (
|
|
2072
|
-
json_extract(channel_result.value, '$.status') < 400
|
|
2073
|
-
AND json_type(channel_result.value, '$.problem') IS NOT NULL
|
|
2074
|
-
)
|
|
2075
|
-
OR (
|
|
2076
|
-
json_extract(channel_result.value, '$.status') >= 400
|
|
2077
|
-
AND (
|
|
2078
|
-
json_type(channel_result.value, '$.problem') != 'object'
|
|
2079
|
-
OR json_extract(channel_result.value, '$.problem.status')
|
|
2080
|
-
!= json_extract(channel_result.value, '$.status')
|
|
2081
|
-
)
|
|
2082
|
-
)
|
|
2083
|
-
)
|
|
2084
|
-
)
|
|
2085
|
-
BEGIN
|
|
2086
|
-
SELECT RAISE(ABORT, 'subscription channel result violates the channel producer contract');
|
|
2087
|
-
END;
|
|
2088
|
-
|
|
2089
|
-
-- Subscription settlement is the single atomic transition that closes the
|
|
2090
|
-
-- lifecycle and installs current terminal producer evidence on every channel.
|
|
2091
|
-
-- Overrides are exact; all other channels inherit the universal result.
|
|
2092
|
-
CREATE TRIGGER IF NOT EXISTS subscriptions_settle_channels
|
|
2093
|
-
AFTER UPDATE OF closed_at, close_status, close_result, channel_results ON subscriptions
|
|
2094
|
-
WHEN OLD.closed_at IS NULL AND NEW.closed_at IS NOT NULL
|
|
2095
|
-
BEGIN
|
|
2096
|
-
UPDATE entry_channels
|
|
2097
|
-
SET producer_result = COALESCE(
|
|
2098
|
-
(
|
|
2099
|
-
SELECT json(channel_result.value)
|
|
2100
|
-
FROM json_each(NEW.channel_results) AS channel_result
|
|
2101
|
-
WHERE channel_result.key = entry_channels.name
|
|
2102
|
-
),
|
|
2103
|
-
NEW.close_result
|
|
2104
|
-
),
|
|
2105
|
-
state = CASE WHEN json_extract(
|
|
2106
|
-
COALESCE(
|
|
2107
|
-
(
|
|
2108
|
-
SELECT json(channel_result.value)
|
|
2109
|
-
FROM json_each(NEW.channel_results) AS channel_result
|
|
2110
|
-
WHERE channel_result.key = entry_channels.name
|
|
2111
|
-
),
|
|
2112
|
-
NEW.close_result
|
|
2113
|
-
),
|
|
2114
|
-
'$.status'
|
|
2115
|
-
) >= 400 THEN 'errored' ELSE 'closed' END
|
|
2116
|
-
WHERE entry_id = NEW.entry_id;
|
|
2117
|
-
END;
|
|
2118
|
-
|
|
2119
|
-
-- One durable publication cursor per selected subscription channel. Log rows
|
|
2120
|
-
-- are curated model context and therefore cannot own this lifecycle fact.
|
|
2121
|
-
-- The row survives KILLing any generated observation and disappears only with
|
|
2122
|
-
-- its subscription. {§exec-stream}
|
|
2123
|
-
CREATE TABLE IF NOT EXISTS subscription_publications (
|
|
2124
|
-
id INTEGER NOT NULL PRIMARY KEY,
|
|
2125
|
-
version INTEGER NOT NULL DEFAULT 0 CHECK (version >= 0),
|
|
2126
|
-
subscription_id INTEGER NOT NULL,
|
|
2127
|
-
channel TEXT NOT NULL CHECK (length(channel) > 0),
|
|
2128
|
-
published_end INTEGER NOT NULL DEFAULT 0 CHECK (published_end >= 0),
|
|
2129
|
-
terminal_published INTEGER NOT NULL DEFAULT 0 CHECK (terminal_published IN (0, 1)),
|
|
2130
|
-
UNIQUE (subscription_id, channel),
|
|
2131
|
-
FOREIGN KEY (subscription_id) REFERENCES subscriptions(id) ON DELETE CASCADE
|
|
2132
|
-
) STRICT;
|
|
2133
|
-
|
|
2134
|
-
CREATE INDEX IF NOT EXISTS subscription_publications_pending
|
|
2135
|
-
ON subscription_publications (subscription_id, terminal_published);
|
|
2136
|
-
|
|
2137
|
-
CREATE TRIGGER IF NOT EXISTS subscriptions_seed_publications
|
|
2138
|
-
AFTER INSERT ON subscriptions
|
|
2139
|
-
BEGIN
|
|
2140
|
-
INSERT INTO subscription_publications (subscription_id, channel)
|
|
2141
|
-
SELECT NEW.id, ec.name
|
|
2142
|
-
FROM entry_channels ec
|
|
2143
|
-
WHERE ec.entry_id = NEW.entry_id
|
|
2144
|
-
AND (NEW.published_channel IS NULL OR ec.name = NEW.published_channel);
|
|
2145
|
-
|
|
2146
|
-
SELECT CASE WHEN NOT EXISTS (
|
|
2147
|
-
SELECT 1 FROM subscription_publications WHERE subscription_id = NEW.id
|
|
2148
|
-
) THEN RAISE(ABORT, 'subscription has no publishable channel') END;
|
|
2149
|
-
END;
|
|
2150
|
-
|
|
2151
|
-
-- The generated READ and its cursor transition are one SQLite statement. A
|
|
2152
|
-
-- later log KILL removes evidence from active context without rewinding the
|
|
2153
|
-
-- subscription/channel publication state. {§exec-stream}
|
|
2154
|
-
CREATE TRIGGER IF NOT EXISTS log_entries_advance_subscription_publication
|
|
2155
|
-
AFTER INSERT ON log_entries
|
|
2156
|
-
WHEN NEW.subscription_publication_id IS NOT NULL
|
|
2157
|
-
BEGIN
|
|
2158
|
-
SELECT CASE WHEN
|
|
2159
|
-
NEW.origin != '_plurnk'
|
|
2160
|
-
OR NEW.op != 'READ'
|
|
2161
|
-
OR json_type(NEW.attrs, '$.streamEnd') != 'integer'
|
|
2162
|
-
OR json_extract(NEW.attrs, '$.streamEnd') < 0
|
|
2163
|
-
OR json_type(NEW.attrs, '$.terminal') NOT IN ('true', 'false')
|
|
2164
|
-
THEN RAISE(ABORT, 'subscription publication requires one canonical stream observation') END;
|
|
2165
|
-
|
|
2166
|
-
UPDATE subscription_publications
|
|
2167
|
-
SET published_end = json_extract(NEW.attrs, '$.streamEnd'),
|
|
2168
|
-
terminal_published = json_extract(NEW.attrs, '$.terminal'),
|
|
2169
|
-
version = version + 1
|
|
2170
|
-
WHERE id = NEW.subscription_publication_id
|
|
2171
|
-
AND terminal_published = 0
|
|
2172
|
-
AND (
|
|
2173
|
-
(json_extract(NEW.attrs, '$.terminal') = 0
|
|
2174
|
-
AND json_extract(NEW.attrs, '$.streamEnd') > published_end)
|
|
2175
|
-
OR
|
|
2176
|
-
(json_extract(NEW.attrs, '$.terminal') = 1
|
|
2177
|
-
AND json_extract(NEW.attrs, '$.streamEnd') >= published_end)
|
|
2178
|
-
);
|
|
2179
|
-
|
|
2180
|
-
SELECT CASE WHEN changes() != 1
|
|
2181
|
-
THEN RAISE(ABORT, 'subscription publication transition is stale or already terminal')
|
|
2182
|
-
END;
|
|
2183
|
-
END;
|
|
2184
|
-
|
|
2185
|
-
-- (worker_watermarks removed — {§env-delta} is now pull-from-log, no per-worker snapshot.)
|
|
2186
|
-
|
|
2187
|
-
-- workspace_constraints
|
|
2188
|
-
-- SPEC {§membership} constraint overlay — explicit policy and the inspectable
|
|
2189
|
-
-- exact pick produced by accepted file creation share one representation.
|
|
2190
|
-
-- Per (workspace, effect, glob/target): `pick` (members git misses, resolved by a
|
|
2191
|
-
-- targeted client-dictated scan), `hide` (drop git-tracked matches), `view` (member
|
|
2192
|
-
-- for read; File.edit rejects the write). git-absent, `pick` rows are the sole substrate
|
|
2193
|
-
-- source. Composed at membership resolution; node:path.matchesGlob.
|
|
2194
|
-
CREATE TABLE IF NOT EXISTS workspace_constraints (
|
|
2195
|
-
workspace_id INTEGER NOT NULL,
|
|
2196
|
-
-- include admits files git misses; exclude removes members — the members family's lexicon
|
|
2197
|
-
-- ({§members-projection}). An inclusion is a pattern scan; a creation record is one exact path.
|
|
2198
|
-
effect TEXT NOT NULL CHECK (effect IN ('include', 'exclude')),
|
|
2199
|
-
glob TEXT NOT NULL,
|
|
2200
|
-
-- create: the exact record of a file Plurnk wrote ({§fs-create-record}); members: a
|
|
2201
|
-
-- human-authored definition projected by the members family; model: a definition the model
|
|
2202
|
-
-- proposed under the members scope — never admitted past the repository's ignore rules.
|
|
2203
|
-
source TEXT NOT NULL CHECK (source IN ('create', 'members', 'model')),
|
|
2204
|
-
CHECK (source IN ('members', 'model') OR effect = 'include'),
|
|
2205
|
-
PRIMARY KEY (workspace_id, effect, glob),
|
|
2206
|
-
FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE
|
|
2207
|
-
) STRICT, WITHOUT ROWID;
|