@amalgm/shell 0.1.164-preview.36072132286 → 0.1.164-preview.36809057014
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/PURPOSE.md +642 -128
- package/README.md +10 -8
- package/dist/accepted-tail.d.ts +26 -0
- package/dist/accepted-tail.js +37 -0
- package/dist/accepted-tail.js.map +1 -0
- package/dist/agent-execution.d.ts +16 -1
- package/dist/agent-execution.js +13 -5
- package/dist/agent-execution.js.map +1 -1
- package/dist/apply-cleanup.d.ts +28 -0
- package/dist/apply-cleanup.js +166 -0
- package/dist/apply-cleanup.js.map +1 -0
- package/dist/apply-recovery.d.ts +47 -0
- package/dist/apply-recovery.js +99 -0
- package/dist/apply-recovery.js.map +1 -0
- package/dist/apply-rows.d.ts +72 -0
- package/dist/apply-rows.js +150 -0
- package/dist/apply-rows.js.map +1 -0
- package/dist/apply-saves.d.ts +85 -0
- package/dist/apply-saves.js +238 -0
- package/dist/apply-saves.js.map +1 -0
- package/dist/boot.js +2 -1
- package/dist/boot.js.map +1 -1
- package/dist/capture-work.d.ts +8 -0
- package/dist/capture-work.js +67 -0
- package/dist/capture-work.js.map +1 -0
- package/dist/cargo-group.d.ts +45 -0
- package/dist/cargo-group.js +88 -0
- package/dist/cargo-group.js.map +1 -0
- package/dist/channel-session.d.ts +4 -2
- package/dist/channel-session.js +4 -3
- package/dist/channel-session.js.map +1 -1
- package/dist/chat-composition.d.ts +2 -0
- package/dist/chat-composition.js +1 -0
- package/dist/chat-composition.js.map +1 -1
- package/dist/cli.js +20 -1
- package/dist/cli.js.map +1 -1
- package/dist/construct-apply-host.d.ts +4 -2
- package/dist/construct-apply-host.js +8 -3
- package/dist/construct-apply-host.js.map +1 -1
- package/dist/construct-door.js +1 -1
- package/dist/construct-door.js.map +1 -1
- package/dist/construct-ledger.d.ts +6 -1
- package/dist/construct-ledger.js +21 -33
- package/dist/construct-ledger.js.map +1 -1
- package/dist/content-cache-collection.d.ts +18 -0
- package/dist/content-cache-collection.js +99 -0
- package/dist/content-cache-collection.js.map +1 -0
- package/dist/content-cache-host.d.ts +83 -17
- package/dist/content-cache-host.js +335 -95
- package/dist/content-cache-host.js.map +1 -1
- package/dist/content-cache-namespace.d.ts +59 -0
- package/dist/content-cache-namespace.js +210 -0
- package/dist/content-cache-namespace.js.map +1 -0
- package/dist/content-cache-ownership.d.ts +13 -0
- package/dist/content-cache-ownership.js +75 -0
- package/dist/content-cache-ownership.js.map +1 -0
- package/dist/content-cache-retention.d.ts +23 -0
- package/dist/content-cache-retention.js +195 -0
- package/dist/content-cache-retention.js.map +1 -0
- package/dist/content-capture-pool.d.ts +287 -0
- package/dist/content-capture-pool.js +461 -0
- package/dist/content-capture-pool.js.map +1 -0
- package/dist/content-capture-worker.d.ts +8 -0
- package/dist/content-capture-worker.js +109 -0
- package/dist/content-capture-worker.js.map +1 -0
- package/dist/content-clock.d.ts +42 -0
- package/dist/content-clock.js +166 -0
- package/dist/content-clock.js.map +1 -0
- package/dist/content-direct.d.ts +2 -0
- package/dist/content-direct.js +12 -0
- package/dist/content-direct.js.map +1 -1
- package/dist/content-failure.d.ts +18 -0
- package/dist/content-failure.js +38 -0
- package/dist/content-failure.js.map +1 -0
- package/dist/content-stream-thread.d.ts +60 -0
- package/dist/content-stream-thread.js +95 -0
- package/dist/content-stream-thread.js.map +1 -0
- package/dist/content-stream-worker.d.ts +7 -0
- package/dist/content-stream-worker.js +52 -0
- package/dist/content-stream-worker.js.map +1 -0
- package/dist/declaration-absorption.d.ts +37 -0
- package/dist/declaration-absorption.js +119 -0
- package/dist/declaration-absorption.js.map +1 -0
- package/dist/declaration-chain.d.ts +36 -0
- package/dist/declaration-chain.js +96 -0
- package/dist/declaration-chain.js.map +1 -0
- package/dist/declaration-commit.d.ts +31 -0
- package/dist/declaration-commit.js +49 -0
- package/dist/declaration-commit.js.map +1 -0
- package/dist/declaration-hold.d.ts +22 -0
- package/dist/declaration-hold.js +24 -0
- package/dist/declaration-hold.js.map +1 -0
- package/dist/declaration-journal.d.ts +62 -0
- package/dist/declaration-journal.js +99 -0
- package/dist/declaration-journal.js.map +1 -0
- package/dist/declaration-save.d.ts +31 -0
- package/dist/declaration-save.js +134 -0
- package/dist/declaration-save.js.map +1 -0
- package/dist/detection/accepted-result.d.ts +19 -1
- package/dist/detection/accepted-result.js +36 -5
- package/dist/detection/accepted-result.js.map +1 -1
- package/dist/detection/admission-save.d.ts +55 -0
- package/dist/detection/admission-save.js +48 -0
- package/dist/detection/admission-save.js.map +1 -0
- package/dist/detection/admission-units.d.ts +66 -0
- package/dist/detection/admission-units.js +322 -0
- package/dist/detection/admission-units.js.map +1 -0
- package/dist/detection/alias-discovery.d.ts +12 -0
- package/dist/detection/alias-discovery.js +80 -0
- package/dist/detection/alias-discovery.js.map +1 -0
- package/dist/detection/alias-examination.d.ts +30 -0
- package/dist/detection/alias-examination.js +49 -0
- package/dist/detection/alias-examination.js.map +1 -0
- package/dist/detection/apply-ownership.d.ts +81 -0
- package/dist/detection/apply-ownership.js +232 -0
- package/dist/detection/apply-ownership.js.map +1 -0
- package/dist/detection/basis-advanced.d.ts +11 -0
- package/dist/detection/basis-advanced.js +26 -0
- package/dist/detection/basis-advanced.js.map +1 -0
- package/dist/detection/capture-outcome.d.ts +16 -0
- package/dist/detection/capture-outcome.js +92 -0
- package/dist/detection/capture-outcome.js.map +1 -0
- package/dist/detection/container-membership.d.ts +32 -0
- package/dist/detection/container-membership.js +49 -0
- package/dist/detection/container-membership.js.map +1 -0
- package/dist/detection/detect-cancelled.d.ts +6 -0
- package/dist/detection/detect-cancelled.js +10 -0
- package/dist/detection/detect-cancelled.js.map +1 -0
- package/dist/detection/directory-proof.d.ts +47 -0
- package/dist/detection/directory-proof.js +77 -0
- package/dist/detection/directory-proof.js.map +1 -0
- package/dist/detection/disposition-rows.d.ts +18 -0
- package/dist/detection/disposition-rows.js +29 -0
- package/dist/detection/disposition-rows.js.map +1 -0
- package/dist/detection/dispositions.d.ts +130 -0
- package/dist/detection/dispositions.js +248 -0
- package/dist/detection/dispositions.js.map +1 -0
- package/dist/detection/git-notice.d.ts +88 -0
- package/dist/detection/git-notice.js +444 -0
- package/dist/detection/git-notice.js.map +1 -0
- package/dist/detection/ground-proof.d.ts +130 -0
- package/dist/detection/ground-proof.js +274 -0
- package/dist/detection/ground-proof.js.map +1 -0
- package/dist/detection/ground-reader.d.ts +29 -0
- package/dist/detection/ground-reader.js +102 -0
- package/dist/detection/ground-reader.js.map +1 -0
- package/dist/detection/held-territory.d.ts +51 -0
- package/dist/detection/held-territory.js +205 -0
- package/dist/detection/held-territory.js.map +1 -0
- package/dist/detection/identity-discovery.d.ts +45 -0
- package/dist/detection/identity-discovery.js +287 -0
- package/dist/detection/identity-discovery.js.map +1 -0
- package/dist/detection/maintenance-sweep.d.ts +108 -0
- package/dist/detection/maintenance-sweep.js +325 -0
- package/dist/detection/maintenance-sweep.js.map +1 -0
- package/dist/detection/name-reach.d.ts +12 -0
- package/dist/detection/name-reach.js +28 -0
- package/dist/detection/name-reach.js.map +1 -0
- package/dist/detection/notebook-basis.d.ts +5 -7
- package/dist/detection/notebook-basis.js +6 -7
- package/dist/detection/notebook-basis.js.map +1 -1
- package/dist/detection/owed-selection.d.ts +51 -0
- package/dist/detection/owed-selection.js +169 -0
- package/dist/detection/owed-selection.js.map +1 -0
- package/dist/detection/portable.d.ts +34 -34
- package/dist/detection/portable.js +67 -93
- package/dist/detection/portable.js.map +1 -1
- package/dist/detection/reconciliation-coverage.d.ts +7 -0
- package/dist/detection/reconciliation-coverage.js +16 -0
- package/dist/detection/reconciliation-coverage.js.map +1 -0
- package/dist/detection/repository-publication.d.ts +20 -0
- package/dist/detection/repository-publication.js +79 -0
- package/dist/detection/repository-publication.js.map +1 -0
- package/dist/detection/repository-routes.d.ts +43 -0
- package/dist/detection/repository-routes.js +97 -0
- package/dist/detection/repository-routes.js.map +1 -0
- package/dist/detection/root-examination.d.ts +94 -0
- package/dist/detection/root-examination.js +523 -0
- package/dist/detection/root-examination.js.map +1 -0
- package/dist/detection/runtime.d.ts +131 -64
- package/dist/detection/runtime.js +808 -1103
- package/dist/detection/runtime.js.map +1 -1
- package/dist/detection/scoped-identity-port.d.ts +34 -0
- package/dist/detection/scoped-identity-port.js +81 -0
- package/dist/detection/scoped-identity-port.js.map +1 -0
- package/dist/detection/seal-law.d.ts +66 -0
- package/dist/detection/seal-law.js +116 -0
- package/dist/detection/seal-law.js.map +1 -0
- package/dist/detection/sharing-policy.d.ts +11 -0
- package/dist/detection/sharing-policy.js +32 -0
- package/dist/detection/sharing-policy.js.map +1 -0
- package/dist/detection/thread-database.d.ts +4 -0
- package/dist/detection/thread-database.js +30 -0
- package/dist/detection/thread-database.js.map +1 -0
- package/dist/detection/unreadable.d.ts +11 -0
- package/dist/detection/unreadable.js +9 -0
- package/dist/detection/unreadable.js.map +1 -0
- package/dist/detection/verified-content.d.ts +6 -0
- package/dist/detection/verified-content.js +12 -0
- package/dist/detection/verified-content.js.map +1 -0
- package/dist/detection/walk-law.d.ts +34 -0
- package/dist/detection/walk-law.js +55 -0
- package/dist/detection/walk-law.js.map +1 -0
- package/dist/development/fly-guest.js +2 -1
- package/dist/development/fly-guest.js.map +1 -1
- package/dist/entity-apply-host.d.ts +29 -13
- package/dist/entity-apply-host.js +1426 -461
- package/dist/entity-apply-host.js.map +1 -1
- package/dist/entity-apply-store.d.ts +77 -30
- package/dist/entity-apply-store.js +221 -516
- package/dist/entity-apply-store.js.map +1 -1
- package/dist/entity-record-observability.js +2 -0
- package/dist/entity-record-observability.js.map +1 -1
- package/dist/entity-record-saves.d.ts +20 -0
- package/dist/entity-record-saves.js +91 -0
- package/dist/entity-record-saves.js.map +1 -0
- package/dist/entity-record-store.d.ts +15 -7
- package/dist/entity-record-store.js +57 -117
- package/dist/entity-record-store.js.map +1 -1
- package/dist/files-register-host.d.ts +22 -3
- package/dist/files-register-host.js +70 -31
- package/dist/files-register-host.js.map +1 -1
- package/dist/filesystem.js +3 -2
- package/dist/filesystem.js.map +1 -1
- package/dist/git-binding.d.ts +65 -0
- package/dist/git-binding.js +220 -0
- package/dist/git-binding.js.map +1 -0
- package/dist/git-capture.d.ts +39 -0
- package/dist/git-capture.js +86 -0
- package/dist/git-capture.js.map +1 -0
- package/dist/git-card.d.ts +12 -0
- package/dist/git-card.js +123 -0
- package/dist/git-card.js.map +1 -0
- package/dist/git-checkpoint-construction.d.ts +41 -0
- package/dist/git-checkpoint-construction.js +96 -0
- package/dist/git-checkpoint-construction.js.map +1 -0
- package/dist/git-checkpoint-preparation.d.ts +37 -0
- package/dist/git-checkpoint-preparation.js +145 -0
- package/dist/git-checkpoint-preparation.js.map +1 -0
- package/dist/git-command.d.ts +61 -8
- package/dist/git-command.js +217 -63
- package/dist/git-command.js.map +1 -1
- package/dist/git-configuration.d.ts +40 -0
- package/dist/git-configuration.js +217 -0
- package/dist/git-configuration.js.map +1 -0
- package/dist/git-evidence.d.ts +61 -0
- package/dist/git-evidence.js +181 -0
- package/dist/git-evidence.js.map +1 -0
- package/dist/git-index-entries.d.ts +15 -0
- package/dist/git-index-entries.js +44 -0
- package/dist/git-index-entries.js.map +1 -0
- package/dist/git-index-format.d.ts +35 -0
- package/dist/git-index-format.js +293 -0
- package/dist/git-index-format.js.map +1 -0
- package/dist/git-index-witness.d.ts +33 -0
- package/dist/git-index-witness.js +69 -0
- package/dist/git-index-witness.js.map +1 -0
- package/dist/git-literal-host.d.ts +82 -0
- package/dist/git-literal-host.js +172 -0
- package/dist/git-literal-host.js.map +1 -0
- package/dist/git-literal-read.d.ts +88 -0
- package/dist/git-literal-read.js +170 -0
- package/dist/git-literal-read.js.map +1 -0
- package/dist/git-literal-replay.d.ts +33 -0
- package/dist/git-literal-replay.js +268 -0
- package/dist/git-literal-replay.js.map +1 -0
- package/dist/git-native-file.d.ts +42 -0
- package/dist/git-native-file.js +145 -0
- package/dist/git-native-file.js.map +1 -0
- package/dist/git-native-index.d.ts +21 -0
- package/dist/git-native-index.js +44 -0
- package/dist/git-native-index.js.map +1 -0
- package/dist/git-operation-host.d.ts +48 -0
- package/dist/git-operation-host.js +127 -0
- package/dist/git-operation-host.js.map +1 -0
- package/dist/git-private-index.d.ts +11 -0
- package/dist/git-private-index.js +42 -0
- package/dist/git-private-index.js.map +1 -0
- package/dist/git-private-repository.d.ts +4 -0
- package/dist/git-private-repository.js +69 -0
- package/dist/git-private-repository.js.map +1 -0
- package/dist/git-private-view.d.ts +39 -0
- package/dist/git-private-view.js +162 -0
- package/dist/git-private-view.js.map +1 -0
- package/dist/git-ref-store.d.ts +12 -0
- package/dist/git-ref-store.js +68 -0
- package/dist/git-ref-store.js.map +1 -0
- package/dist/git-registration-host.d.ts +20 -30
- package/dist/git-registration-host.js +86 -249
- package/dist/git-registration-host.js.map +1 -1
- package/dist/git-repository-host.d.ts +148 -22
- package/dist/git-repository-host.js +633 -650
- package/dist/git-repository-host.js.map +1 -1
- package/dist/git-worktree-host.d.ts +2 -0
- package/dist/git-worktree-host.js +16 -0
- package/dist/git-worktree-host.js.map +1 -0
- package/dist/graph-publication.d.ts +75 -0
- package/dist/graph-publication.js +203 -0
- package/dist/graph-publication.js.map +1 -0
- package/dist/ground-basis.d.ts +242 -0
- package/dist/ground-basis.js +1023 -0
- package/dist/ground-basis.js.map +1 -0
- package/dist/ground-checkpoint-worker.d.ts +1 -0
- package/dist/ground-checkpoint-worker.js +84 -0
- package/dist/ground-checkpoint-worker.js.map +1 -0
- package/dist/ground-checkpoints.d.ts +16 -0
- package/dist/ground-checkpoints.js +45 -0
- package/dist/ground-checkpoints.js.map +1 -0
- package/dist/ground-coordination.d.ts +107 -3
- package/dist/ground-coordination.js +249 -24
- package/dist/ground-coordination.js.map +1 -1
- package/dist/ground-database.d.ts +42 -0
- package/dist/ground-database.js +290 -0
- package/dist/ground-database.js.map +1 -0
- package/dist/ground-differences.d.ts +23 -0
- package/dist/ground-differences.js +47 -0
- package/dist/ground-differences.js.map +1 -0
- package/dist/ground-holders.d.ts +4 -0
- package/dist/ground-holders.js +15 -0
- package/dist/ground-holders.js.map +1 -0
- package/dist/ground-initialization-worker.d.ts +1 -0
- package/dist/ground-initialization-worker.js +20 -0
- package/dist/ground-initialization-worker.js.map +1 -0
- package/dist/ground-initialization.d.ts +35 -0
- package/dist/ground-initialization.js +102 -0
- package/dist/ground-initialization.js.map +1 -0
- package/dist/ground-install-saves.d.ts +63 -0
- package/dist/ground-install-saves.js +139 -0
- package/dist/ground-install-saves.js.map +1 -0
- package/dist/ground-inventory-schema.d.ts +18 -0
- package/dist/ground-inventory-schema.js +168 -0
- package/dist/ground-inventory-schema.js.map +1 -0
- package/dist/ground-profile.d.ts +7 -0
- package/dist/ground-profile.js +52 -0
- package/dist/ground-profile.js.map +1 -0
- package/dist/ground-root-index.d.ts +2 -1
- package/dist/ground-root-index.js +16 -14
- package/dist/ground-root-index.js.map +1 -1
- package/dist/ground-row.d.ts +62 -0
- package/dist/ground-row.js +70 -0
- package/dist/ground-row.js.map +1 -0
- package/dist/ground-save-ops.d.ts +44 -0
- package/dist/ground-save-ops.js +41 -0
- package/dist/ground-save-ops.js.map +1 -0
- package/dist/ground-saver-worker.d.ts +1 -0
- package/dist/ground-saver-worker.js +156 -0
- package/dist/ground-saver-worker.js.map +1 -0
- package/dist/ground-saver.d.ts +75 -0
- package/dist/ground-saver.js +216 -0
- package/dist/ground-saver.js.map +1 -0
- package/dist/ground-store.d.ts +84 -0
- package/dist/ground-store.js +473 -0
- package/dist/ground-store.js.map +1 -0
- package/dist/ground-territory.d.ts +130 -0
- package/dist/ground-territory.js +511 -0
- package/dist/ground-territory.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/installation/ownership.d.ts +0 -2
- package/dist/installation/ownership.js +3 -15
- package/dist/installation/ownership.js.map +1 -1
- package/dist/machine-host.d.ts +3 -2
- package/dist/machine-host.js +28 -16
- package/dist/machine-host.js.map +1 -1
- package/dist/materialized-graph.d.ts +7 -7
- package/dist/materialized-graph.js +11 -23
- package/dist/materialized-graph.js.map +1 -1
- package/dist/module-thread.d.ts +9 -0
- package/dist/module-thread.js +10 -0
- package/dist/module-thread.js.map +1 -0
- package/dist/native/fsevents-stream.node +0 -0
- package/dist/physical-path-witness.d.ts +64 -0
- package/dist/physical-path-witness.js +168 -0
- package/dist/physical-path-witness.js.map +1 -0
- package/dist/register-upload-fusion.d.ts +5 -4
- package/dist/register-upload-fusion.js +9 -6
- package/dist/register-upload-fusion.js.map +1 -1
- package/dist/registry-graph.d.ts +3 -2
- package/dist/registry-graph.js +9 -6
- package/dist/registry-graph.js.map +1 -1
- package/dist/registry-page-cache.d.ts +5 -2
- package/dist/registry-page-cache.js.map +1 -1
- package/dist/repository-identity-steps.d.ts +5 -0
- package/dist/repository-identity-steps.js +33 -0
- package/dist/repository-identity-steps.js.map +1 -0
- package/dist/runtime-node-flags.d.ts +10 -0
- package/dist/runtime-node-flags.js +11 -0
- package/dist/runtime-node-flags.js.map +1 -0
- package/dist/service/adapter.d.ts +1 -1
- package/dist/service/adapter.js +1 -1
- package/dist/service/adapter.js.map +1 -1
- package/dist/service/cli.js +16 -20
- package/dist/service/cli.js.map +1 -1
- package/dist/service/control.d.ts +2 -2
- package/dist/service/keepalive.d.ts +4 -11
- package/dist/service/keepalive.js +65 -118
- package/dist/service/keepalive.js.map +1 -1
- package/dist/service/policy.d.ts +36 -0
- package/dist/service/policy.js +25 -0
- package/dist/service/policy.js.map +1 -0
- package/dist/service/portable.d.ts +1 -1
- package/dist/service/portable.js +1 -1
- package/dist/service/portable.js.map +1 -1
- package/dist/service/recovery.d.ts +10 -9
- package/dist/service/recovery.js +29 -19
- package/dist/service/recovery.js.map +1 -1
- package/dist/service/windows-action.d.ts +5 -3
- package/dist/service/windows-action.js +6 -9
- package/dist/service/windows-action.js.map +1 -1
- package/dist/service/windows-task.js +5 -5
- package/dist/service/windows-task.js.map +1 -1
- package/dist/sharing-admission.d.ts +17 -0
- package/dist/sharing-admission.js +128 -0
- package/dist/sharing-admission.js.map +1 -0
- package/dist/snapshot-delivery-baseline.d.ts +12 -3
- package/dist/snapshot-delivery-baseline.js +41 -42
- package/dist/snapshot-delivery-baseline.js.map +1 -1
- package/dist/source-proof.d.ts +36 -0
- package/dist/source-proof.js +70 -0
- package/dist/source-proof.js.map +1 -0
- package/dist/source-signature.d.ts +56 -0
- package/dist/source-signature.js +56 -0
- package/dist/source-signature.js.map +1 -0
- package/dist/source-witness.d.ts +15 -0
- package/dist/source-witness.js +29 -0
- package/dist/source-witness.js.map +1 -0
- package/dist/sqlite-durability.d.ts +31 -0
- package/dist/sqlite-durability.js +28 -0
- package/dist/sqlite-durability.js.map +1 -0
- package/dist/sqlite.d.ts +8 -2
- package/dist/sqlite.js +27 -4
- package/dist/sqlite.js.map +1 -1
- package/dist/sync-address.d.ts +19 -0
- package/dist/sync-address.js +52 -0
- package/dist/sync-address.js.map +1 -0
- package/dist/sync-setting.d.ts +15 -0
- package/dist/sync-setting.js +13 -0
- package/dist/sync-setting.js.map +1 -1
- package/dist/turns.d.ts +42 -0
- package/dist/turns.js +112 -0
- package/dist/turns.js.map +1 -0
- package/dist/updates/bootstrap.d.ts +53 -7
- package/dist/updates/bootstrap.js +224 -137
- package/dist/updates/bootstrap.js.map +1 -1
- package/dist/updates/controller.d.ts +8 -0
- package/dist/updates/controller.js +27 -3
- package/dist/updates/controller.js.map +1 -1
- package/dist/updates/store.d.ts +3 -0
- package/dist/updates/store.js +12 -0
- package/dist/updates/store.js.map +1 -1
- package/dist/user-ground-host.d.ts +364 -69
- package/dist/user-ground-host.js +5231 -3366
- package/dist/user-ground-host.js.map +1 -1
- package/dist/watching/fsevents.d.ts +52 -1
- package/dist/watching/fsevents.js +60 -25
- package/dist/watching/fsevents.js.map +1 -1
- package/dist/watching/host.d.ts +129 -5
- package/dist/watching/host.js +433 -80
- package/dist/watching/host.js.map +1 -1
- package/dist/watching/index.d.ts +1 -1
- package/dist/wire-binary.d.ts +3 -2
- package/dist/wire-binary.js +10 -8
- package/dist/wire-binary.js.map +1 -1
- package/dist/wire-client.d.ts +3 -4
- package/dist/wire-client.js +18 -44
- package/dist/wire-client.js.map +1 -1
- package/dist/wire-outbox.d.ts +34 -0
- package/dist/wire-outbox.js +127 -0
- package/dist/wire-outbox.js.map +1 -0
- package/dist/workspace-host.d.ts +4 -0
- package/dist/workspace-host.js +12 -1
- package/dist/workspace-host.js.map +1 -1
- package/examinations/fixtures/private-wire-authority.js +133 -10
- package/npm-shrinkwrap.json +43 -56
- package/package.json +26 -13
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { dirname } from "node:path";
|
|
2
|
+
import { ensurePrivateDir } from "./filesystem.js";
|
|
3
|
+
import { beginGroundEpoch, groundIncarnation, retireGroundViews } from "./ground-basis.js";
|
|
4
|
+
import { startGroundCheckpoints, stopGroundCheckpoints } from "./ground-checkpoints.js";
|
|
5
|
+
import { ensureGroundDifferences } from "./ground-differences.js";
|
|
6
|
+
import { releaseHeldGroundFile } from "./ground-holders.js";
|
|
7
|
+
import { assertGroundInitialized, objectAt } from "./ground-initialization.js";
|
|
8
|
+
import { ensureInventorySchema } from "./ground-inventory-schema.js";
|
|
9
|
+
import { startGroundSaver, stopGroundSaver } from "./ground-saver.js";
|
|
10
|
+
import { databaseFileName, openFileDatabase } from "./sqlite.js";
|
|
11
|
+
/** A publication row holds only what the authority must be told: the small
|
|
12
|
+
* meta facts and the head-commit operation naming this graph's pages. The
|
|
13
|
+
* pages themselves are write-once rows in their own table, because a status
|
|
14
|
+
* transition rewrites its whole row — overflow pages included — through the
|
|
15
|
+
* WAL at synchronous=FULL, and page bytes must never ride that rewrite.
|
|
16
|
+
*
|
|
17
|
+
* Every row owns exactly one Register declaration, named by its root. While
|
|
18
|
+
* a row names a declaration, that root's ground is held from ordinary Detect;
|
|
19
|
+
* the row is the machine's only pending responsibility for it. */
|
|
20
|
+
const SNAPSHOT_PUBLICATIONS_SCHEMA = `
|
|
21
|
+
CREATE TABLE IF NOT EXISTS snapshot_publications (
|
|
22
|
+
sequence INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23
|
+
mutation_id TEXT NOT NULL UNIQUE,
|
|
24
|
+
resource_id TEXT NOT NULL,
|
|
25
|
+
declaration_root TEXT NOT NULL,
|
|
26
|
+
meta_json TEXT NOT NULL,
|
|
27
|
+
operation_blob BLOB NOT NULL,
|
|
28
|
+
created_at INTEGER NOT NULL,
|
|
29
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending', 'rejected')),
|
|
30
|
+
submitted_at INTEGER
|
|
31
|
+
);
|
|
32
|
+
CREATE INDEX IF NOT EXISTS snapshot_publications_by_declaration
|
|
33
|
+
ON snapshot_publications(declaration_root);
|
|
34
|
+
CREATE TABLE IF NOT EXISTS snapshot_publication_pages (
|
|
35
|
+
mutation_id TEXT NOT NULL,
|
|
36
|
+
page_index INTEGER NOT NULL,
|
|
37
|
+
sha256 TEXT NOT NULL,
|
|
38
|
+
bytes BLOB NOT NULL,
|
|
39
|
+
PRIMARY KEY (mutation_id, page_index)
|
|
40
|
+
);`;
|
|
41
|
+
/** A publication journal in any other shape names no declaration, so no
|
|
42
|
+
* current reader may interpret it. An empty one carries no responsibility
|
|
43
|
+
* and is recreated; a non-empty one may hold a submitted mutation whose
|
|
44
|
+
* outcome exists only at the authority, so the open refuses rather than
|
|
45
|
+
* guess — the file stays exactly as it was. */
|
|
46
|
+
function requireCurrentJournal(database, columns) {
|
|
47
|
+
if (columns.size === 0 || columns.has("declaration_root"))
|
|
48
|
+
return;
|
|
49
|
+
const rows = database.prepare("SELECT COUNT(*) AS count FROM snapshot_publications").get().count;
|
|
50
|
+
if (rows > 0) {
|
|
51
|
+
throw new Error(`snapshot publication journal is in an unsupported shape with ${rows} row(s); `
|
|
52
|
+
+ "it names no declaration and cannot be replayed");
|
|
53
|
+
}
|
|
54
|
+
database.transaction(() => {
|
|
55
|
+
database.exec("DROP TABLE snapshot_publications");
|
|
56
|
+
database.exec("DROP TABLE IF EXISTS snapshot_publication_blobs");
|
|
57
|
+
database.exec("DROP TABLE IF EXISTS snapshot_publication_pages");
|
|
58
|
+
})();
|
|
59
|
+
}
|
|
60
|
+
/** The durability policy of the file's two writers, the migration and the
|
|
61
|
+
* saver thread, applied before their first write.
|
|
62
|
+
* A commit pays only for its own frames. No commit checkpoints: moving the
|
|
63
|
+
* log into the database flushes the drive, and the committing thread would
|
|
64
|
+
* wait for it. The file's checkpoint thread does that work
|
|
65
|
+
* (ground-checkpoints.ts). No commit resizes the log either: cutting the file
|
|
66
|
+
* back frees everything earlier commits wrote, which one commit would wait
|
|
67
|
+
* for. A restarted log reuses the space it grew to until the checkpoint
|
|
68
|
+
* thread finds it quiet and cuts it back, or a writer closes with no other
|
|
69
|
+
* connection open. */
|
|
70
|
+
export function configureGroundConnection(database) {
|
|
71
|
+
database.pragma("busy_timeout = 5000");
|
|
72
|
+
database.pragma("journal_mode = WAL");
|
|
73
|
+
database.pragma("synchronous = FULL");
|
|
74
|
+
database.pragma("wal_autocheckpoint = 0");
|
|
75
|
+
database.pragma("journal_size_limit = -1");
|
|
76
|
+
return database;
|
|
77
|
+
}
|
|
78
|
+
const columnsOf = (database, table) => new Set(database.prepare(`PRAGMA table_info(${table})`).all().map(({ name }) => name));
|
|
79
|
+
/** The one migration, and the process's ground epoch after it, on the
|
|
80
|
+
* migrating thread's own connection. Only the initialization owner calls it,
|
|
81
|
+
* once per file per process, while no other connection is open. */
|
|
82
|
+
export function migrateGroundDatabase(file) {
|
|
83
|
+
const started = performance.now();
|
|
84
|
+
ensurePrivateDir(dirname(file));
|
|
85
|
+
const database = configureGroundConnection(openFileDatabase(file));
|
|
86
|
+
try {
|
|
87
|
+
requireCurrentJournal(database, columnsOf(database, "snapshot_publications"));
|
|
88
|
+
// A seal is disposable reuse evidence: another shape is dropped, never read.
|
|
89
|
+
const sealColumns = columnsOf(database, "repository_git_evidence");
|
|
90
|
+
if (sealColumns.size > 0 && !sealColumns.has("selection_key"))
|
|
91
|
+
database.exec("DROP TABLE repository_git_evidence");
|
|
92
|
+
database.exec(`
|
|
93
|
+
CREATE TABLE IF NOT EXISTS ground_identity (
|
|
94
|
+
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
95
|
+
user_id TEXT NOT NULL,
|
|
96
|
+
user_email TEXT NOT NULL,
|
|
97
|
+
device_id TEXT NOT NULL
|
|
98
|
+
);
|
|
99
|
+
CREATE TABLE IF NOT EXISTS record_outbox (
|
|
100
|
+
local_sequence INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
101
|
+
mutation_id TEXT NOT NULL UNIQUE,
|
|
102
|
+
authority_id TEXT NOT NULL,
|
|
103
|
+
entity_id TEXT NOT NULL,
|
|
104
|
+
record_json TEXT NOT NULL,
|
|
105
|
+
status TEXT NOT NULL CHECK(status IN ('pending', 'accepted')),
|
|
106
|
+
global_sequence INTEGER,
|
|
107
|
+
created_at INTEGER NOT NULL,
|
|
108
|
+
accepted_at INTEGER,
|
|
109
|
+
CHECK((status = 'pending' AND global_sequence IS NULL AND accepted_at IS NULL)
|
|
110
|
+
OR (status = 'accepted' AND global_sequence > 0 AND accepted_at IS NOT NULL))
|
|
111
|
+
);
|
|
112
|
+
CREATE TABLE IF NOT EXISTS record_inbox (
|
|
113
|
+
authority_id TEXT NOT NULL,
|
|
114
|
+
entity_id TEXT NOT NULL,
|
|
115
|
+
global_sequence INTEGER NOT NULL CHECK(global_sequence > 0),
|
|
116
|
+
delivery_sequence INTEGER NOT NULL CHECK(delivery_sequence > 0),
|
|
117
|
+
mutation_id TEXT NOT NULL,
|
|
118
|
+
record_json TEXT NOT NULL,
|
|
119
|
+
received_at INTEGER NOT NULL,
|
|
120
|
+
resolved_at INTEGER,
|
|
121
|
+
PRIMARY KEY(entity_id, global_sequence),
|
|
122
|
+
UNIQUE(entity_id, mutation_id),
|
|
123
|
+
UNIQUE(authority_id, delivery_sequence)
|
|
124
|
+
);
|
|
125
|
+
CREATE TABLE IF NOT EXISTS entity_receive_cursors (
|
|
126
|
+
entity_id TEXT PRIMARY KEY,
|
|
127
|
+
authority_id TEXT NOT NULL,
|
|
128
|
+
received_through INTEGER NOT NULL CHECK(received_through >= 0)
|
|
129
|
+
);
|
|
130
|
+
CREATE TABLE IF NOT EXISTS authority_delivery_cursors (
|
|
131
|
+
authority_id TEXT PRIMARY KEY,
|
|
132
|
+
received_through INTEGER NOT NULL CHECK(received_through >= 0),
|
|
133
|
+
history_floor INTEGER NOT NULL DEFAULT 0 CHECK(history_floor >= 0)
|
|
134
|
+
);
|
|
135
|
+
CREATE TABLE IF NOT EXISTS authority_snapshot_baselines (
|
|
136
|
+
authority_id TEXT PRIMARY KEY,
|
|
137
|
+
delivery_sequence INTEGER NOT NULL CHECK(delivery_sequence >= 0)
|
|
138
|
+
);
|
|
139
|
+
${SNAPSHOT_PUBLICATIONS_SCHEMA}
|
|
140
|
+
CREATE TABLE IF NOT EXISTS constructs (
|
|
141
|
+
uuid TEXT PRIMARY KEY,
|
|
142
|
+
type TEXT NOT NULL,
|
|
143
|
+
name TEXT NOT NULL,
|
|
144
|
+
status TEXT NOT NULL,
|
|
145
|
+
version TEXT NOT NULL,
|
|
146
|
+
payload_version TEXT,
|
|
147
|
+
updated_at_ms INTEGER NOT NULL
|
|
148
|
+
);
|
|
149
|
+
CREATE TABLE IF NOT EXISTS entity_apply_state (
|
|
150
|
+
entity_id TEXT PRIMARY KEY,
|
|
151
|
+
authority_id TEXT NOT NULL,
|
|
152
|
+
resolved_through INTEGER NOT NULL CHECK(resolved_through >= 0),
|
|
153
|
+
materialized_sequence INTEGER,
|
|
154
|
+
materialized_record_json TEXT,
|
|
155
|
+
CHECK((materialized_sequence IS NULL AND materialized_record_json IS NULL)
|
|
156
|
+
OR (materialized_sequence > 0 AND materialized_record_json IS NOT NULL))
|
|
157
|
+
);
|
|
158
|
+
CREATE TABLE IF NOT EXISTS entity_apply_intents (
|
|
159
|
+
entity_id TEXT PRIMARY KEY,
|
|
160
|
+
authority_id TEXT NOT NULL,
|
|
161
|
+
intent_json TEXT NOT NULL,
|
|
162
|
+
recovery_location TEXT,
|
|
163
|
+
retirement_json TEXT
|
|
164
|
+
);
|
|
165
|
+
CREATE TABLE IF NOT EXISTS workspace_add_intents (
|
|
166
|
+
workspace_uuid TEXT PRIMARY KEY,
|
|
167
|
+
destination_path TEXT NOT NULL UNIQUE,
|
|
168
|
+
intent_json TEXT NOT NULL
|
|
169
|
+
);
|
|
170
|
+
CREATE TABLE IF NOT EXISTS repository_git_evidence (
|
|
171
|
+
uuid TEXT PRIMARY KEY,
|
|
172
|
+
fingerprint TEXT NOT NULL,
|
|
173
|
+
observed_payload TEXT NOT NULL,
|
|
174
|
+
identity_hash TEXT NOT NULL,
|
|
175
|
+
selection_key TEXT,
|
|
176
|
+
selected_payload TEXT,
|
|
177
|
+
selected_transport TEXT,
|
|
178
|
+
CHECK((selection_key IS NULL) = (selected_payload IS NULL)
|
|
179
|
+
AND (selection_key IS NULL) = (selected_transport IS NULL))
|
|
180
|
+
);
|
|
181
|
+
CREATE TABLE IF NOT EXISTS detect_dispositions (
|
|
182
|
+
sequence INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
183
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
184
|
+
incarnation TEXT NOT NULL,
|
|
185
|
+
fact TEXT NOT NULL CHECK(fact IN ('ready', 'outcome', 'observation')),
|
|
186
|
+
collection_id TEXT,
|
|
187
|
+
recorded_at INTEGER NOT NULL,
|
|
188
|
+
event_json TEXT NOT NULL,
|
|
189
|
+
CHECK(fact = 'observation' OR collection_id IS NOT NULL)
|
|
190
|
+
);
|
|
191
|
+
CREATE INDEX IF NOT EXISTS detect_dispositions_by_collection
|
|
192
|
+
ON detect_dispositions(collection_id, fact) WHERE collection_id IS NOT NULL;
|
|
193
|
+
CREATE INDEX IF NOT EXISTS record_inbox_apply
|
|
194
|
+
ON record_inbox(authority_id, entity_id, global_sequence);
|
|
195
|
+
CREATE INDEX IF NOT EXISTS record_inbox_entity_apply
|
|
196
|
+
ON record_inbox(entity_id, global_sequence DESC);
|
|
197
|
+
CREATE INDEX IF NOT EXISTS record_outbox_pending
|
|
198
|
+
ON record_outbox(status, local_sequence);
|
|
199
|
+
CREATE INDEX IF NOT EXISTS record_outbox_pending_entity
|
|
200
|
+
ON record_outbox(status, entity_id, local_sequence);
|
|
201
|
+
CREATE INDEX IF NOT EXISTS record_outbox_local_work
|
|
202
|
+
ON record_outbox(authority_id, entity_id, global_sequence);
|
|
203
|
+
`);
|
|
204
|
+
if (!columnsOf(database, "record_inbox").has("resolved_at")) {
|
|
205
|
+
database.exec("ALTER TABLE record_inbox ADD COLUMN resolved_at INTEGER");
|
|
206
|
+
}
|
|
207
|
+
// A cursor that predates its floor may have jumped at any adopted
|
|
208
|
+
// snapshot, so the largest adopted baseline is its only honest floor.
|
|
209
|
+
if (!columnsOf(database, "authority_delivery_cursors").has("history_floor")) {
|
|
210
|
+
database.exec(`ALTER TABLE authority_delivery_cursors
|
|
211
|
+
ADD COLUMN history_floor INTEGER NOT NULL DEFAULT 0 CHECK(history_floor >= 0)`);
|
|
212
|
+
database.exec(`UPDATE authority_delivery_cursors SET history_floor = MIN(received_through, COALESCE(
|
|
213
|
+
(SELECT delivery_sequence FROM authority_snapshot_baselines AS baseline
|
|
214
|
+
WHERE baseline.authority_id = authority_delivery_cursors.authority_id), 0))`);
|
|
215
|
+
}
|
|
216
|
+
database.exec("DROP INDEX IF EXISTS record_inbox_delivery");
|
|
217
|
+
// Resolved history is retained; readers of unresolved work pay only for it.
|
|
218
|
+
database.exec(`CREATE INDEX IF NOT EXISTS record_inbox_unresolved
|
|
219
|
+
ON record_inbox(authority_id, entity_id, global_sequence) WHERE resolved_at IS NULL`);
|
|
220
|
+
const inventories = ensureInventorySchema(database);
|
|
221
|
+
ensureGroundDifferences(database);
|
|
222
|
+
database.exec("DROP TABLE IF EXISTS mutation_journal");
|
|
223
|
+
// Once per file per process, like the migration: every connection this
|
|
224
|
+
// process opens later reads the same epoch.
|
|
225
|
+
beginGroundEpoch(database);
|
|
226
|
+
const count = (table) => database.prepare(`SELECT COUNT(*) FROM ${table}`).pluck().get();
|
|
227
|
+
return {
|
|
228
|
+
incarnation: groundIncarnation(database),
|
|
229
|
+
...inventories,
|
|
230
|
+
entities: count("entity_rows"),
|
|
231
|
+
notebook: count("notebook_rows"),
|
|
232
|
+
roots: count("ground_roots"),
|
|
233
|
+
migrationMs: performance.now() - started,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
database.close();
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/** Every ordinary connection to an initialized ground file, named as every
|
|
241
|
+
* connection names it (databaseFileName). Each one only reads: the file's
|
|
242
|
+
* saver thread (ground-saver.ts) makes every write, so no read ever waits
|
|
243
|
+
* behind a commit on its own thread. None checkpoints, so the first one starts the file's
|
|
244
|
+
* checkpoint thread and its saver thread. */
|
|
245
|
+
export function openGroundConnection(file) {
|
|
246
|
+
const name = databaseFileName(file);
|
|
247
|
+
assertGroundInitialized(name);
|
|
248
|
+
const database = openFileDatabase(name, { readonly: true, fileMustExist: true });
|
|
249
|
+
database.pragma("busy_timeout = 5000");
|
|
250
|
+
startGroundCheckpoints(name, objectAt(name));
|
|
251
|
+
startGroundSaver(name, objectAt(name));
|
|
252
|
+
return database;
|
|
253
|
+
}
|
|
254
|
+
const held = new Map();
|
|
255
|
+
function bound(file) {
|
|
256
|
+
const name = databaseFileName(file);
|
|
257
|
+
const current = held.get(name);
|
|
258
|
+
if (!current) {
|
|
259
|
+
const database = openGroundConnection(name);
|
|
260
|
+
const entry = { key: objectAt(name), database };
|
|
261
|
+
held.set(name, entry);
|
|
262
|
+
return entry;
|
|
263
|
+
}
|
|
264
|
+
if (objectAt(name) !== current.key) {
|
|
265
|
+
throw new Error(`the ground database ${JSON.stringify(file)} was replaced beneath its open binding`);
|
|
266
|
+
}
|
|
267
|
+
return current;
|
|
268
|
+
}
|
|
269
|
+
export function groundDatabase(file) {
|
|
270
|
+
const { database } = bound(file);
|
|
271
|
+
if (database.inTransaction)
|
|
272
|
+
throw new Error("the ground connection was acquired inside an open transaction");
|
|
273
|
+
return database;
|
|
274
|
+
}
|
|
275
|
+
/** Every other owner has closed by now: each content thread lets its read
|
|
276
|
+
* connection go after the job it is running, the saver finishes its queue,
|
|
277
|
+
* and the checkpoint thread's own connection closes last and makes the final
|
|
278
|
+
* checkpoint there. Released means no thread of this process holds the file:
|
|
279
|
+
* the final checkpoint is part of closing, and Windows refuses to remove a
|
|
280
|
+
* file any handle still has open. */
|
|
281
|
+
export async function releaseGroundDatabase(file) {
|
|
282
|
+
const name = databaseFileName(file);
|
|
283
|
+
const current = held.get(name);
|
|
284
|
+
held.delete(name);
|
|
285
|
+
current?.database.close();
|
|
286
|
+
retireGroundViews(name);
|
|
287
|
+
await Promise.all([releaseHeldGroundFile(name), stopGroundSaver(name)]);
|
|
288
|
+
await stopGroundCheckpoints(name);
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=ground-database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ground-database.js","sourceRoot":"","sources":["../src/ground-database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Where the two ground inventories disagree, kept exact by their one writer,
|
|
2
|
+
* so a reader finds it in time proportional to the disagreement, never to
|
|
3
|
+
* the ground.
|
|
4
|
+
*
|
|
5
|
+
* O (entities) and B (detection_notebook) agree on an identity in a root when
|
|
6
|
+
* both place it there at one type, parent, name, lifecycle and address and,
|
|
7
|
+
* for all but a folder or workspace, whose result is its membership, at one
|
|
8
|
+
* version. Every other placement disagrees: an identity one inventory places
|
|
9
|
+
* in a root the other does not, or both place there differently. The
|
|
10
|
+
* relation is defined once, as the view ground_disagreements, and
|
|
11
|
+
* ground_differences is that view stored: created complete, then restated by
|
|
12
|
+
* each ground write batch, in its own transaction, for every identity whose
|
|
13
|
+
* compared fields it changed. */
|
|
14
|
+
import type Database from "better-sqlite3";
|
|
15
|
+
import type { GroundTransition } from "./ground-basis.js";
|
|
16
|
+
/** Created with the relation it stores, complete, in one transaction. */
|
|
17
|
+
export declare function ensureGroundDifferences(database: Database.Database): void;
|
|
18
|
+
/** Inside the batch that wrote these transitions, after its last row write:
|
|
19
|
+
* each identity whose compared fields changed is stated again from the view,
|
|
20
|
+
* whose per-identity read is a few key lookups. */
|
|
21
|
+
export declare function restateGroundDifferences(database: Database.Database, transitions: Iterable<GroundTransition>): void;
|
|
22
|
+
/** Every identity O and B hold differently in this root. */
|
|
23
|
+
export declare const groundDifferences: (database: Database.Database, rootUUID: string) => string[];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { cachedStatement } from "./sqlite.js";
|
|
2
|
+
/** The fields agreement reads, beside presence. A write that changes none of
|
|
3
|
+
* them leaves every agreement as it was. */
|
|
4
|
+
const COMPARED = ["rootUUID", "type", "parentUUID", "name", "status", "relativePath", "version"];
|
|
5
|
+
/** A visible identity lies once in each inventory, so the two arms never
|
|
6
|
+
* name one pair. */
|
|
7
|
+
const DISAGREEMENTS = `
|
|
8
|
+
CREATE VIEW ground_disagreements(root_uuid, uuid) AS
|
|
9
|
+
SELECT o.root_uuid, o.uuid FROM entities o WHERE NOT EXISTS (
|
|
10
|
+
SELECT 1 FROM detection_notebook b WHERE b.uuid = o.uuid AND b.root_uuid = o.root_uuid
|
|
11
|
+
AND b.type = o.type AND b.parent_uuid IS o.parent_uuid AND b.name = o.name AND b.status = o.status
|
|
12
|
+
AND b.relative_path = o.relative_path AND (b.version = o.version OR o.type IN ('workspace', 'folder')))
|
|
13
|
+
UNION ALL
|
|
14
|
+
SELECT b.root_uuid, b.uuid FROM detection_notebook b WHERE NOT EXISTS (
|
|
15
|
+
SELECT 1 FROM entities o WHERE o.uuid = b.uuid AND o.root_uuid = b.root_uuid)`;
|
|
16
|
+
/** Created with the relation it stores, complete, in one transaction. */
|
|
17
|
+
export function ensureGroundDifferences(database) {
|
|
18
|
+
if (database.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'ground_differences'").get())
|
|
19
|
+
return;
|
|
20
|
+
database.transaction(() => database.exec(`${DISAGREEMENTS};
|
|
21
|
+
CREATE TABLE ground_differences (
|
|
22
|
+
root_uuid TEXT NOT NULL, uuid TEXT NOT NULL, PRIMARY KEY(root_uuid, uuid)
|
|
23
|
+
) WITHOUT ROWID;
|
|
24
|
+
CREATE INDEX ground_differences_by_uuid ON ground_differences(uuid);
|
|
25
|
+
INSERT INTO ground_differences(root_uuid, uuid) SELECT root_uuid, uuid FROM ground_disagreements;`))();
|
|
26
|
+
}
|
|
27
|
+
/** Inside the batch that wrote these transitions, after its last row write:
|
|
28
|
+
* each identity whose compared fields changed is stated again from the view,
|
|
29
|
+
* whose per-identity read is a few key lookups. */
|
|
30
|
+
export function restateGroundDifferences(database, transitions) {
|
|
31
|
+
const touched = new Set();
|
|
32
|
+
for (const { before, after } of transitions) {
|
|
33
|
+
if (!before || !after || COMPARED.some(field => before[field] !== after[field]))
|
|
34
|
+
touched.add((after ?? before).uuid);
|
|
35
|
+
}
|
|
36
|
+
if (!touched.size)
|
|
37
|
+
return;
|
|
38
|
+
const forget = cachedStatement(database, "DELETE FROM ground_differences WHERE uuid = ?");
|
|
39
|
+
const state = cachedStatement(database, "INSERT INTO ground_differences(root_uuid, uuid) SELECT root_uuid, uuid FROM ground_disagreements WHERE uuid = ?");
|
|
40
|
+
for (const uuid of touched) {
|
|
41
|
+
forget.run(uuid);
|
|
42
|
+
state.run(uuid);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Every identity O and B hold differently in this root. */
|
|
46
|
+
export const groundDifferences = (database, rootUUID) => cachedStatement(database, "SELECT uuid FROM ground_differences WHERE root_uuid = ?").pluck().all(rootUUID);
|
|
47
|
+
//# sourceMappingURL=ground-differences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ground-differences.js","sourceRoot":"","sources":["../src/ground-differences.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;4CAC4C;AAC5C,MAAM,QAAQ,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,CACjE,CAAC;AAE/B;oBACoB;AACpB,MAAM,aAAa,GAAG;;;;;;;;oFAQ8D,CAAC;AAErF,yEAAyE;AACzE,MAAM,UAAU,uBAAuB,CAAC,QAA2B;IACjE,IAAI,QAAQ,CAAC,OAAO,CAAC,kFAAkF,CAAC,CAAC,GAAG,EAAE;QAAE,OAAO;IACvH,QAAQ,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,aAAa;;;;;sGAK2C,CAAC,CAAC,EAAE,CAAC;AAC3G,CAAC;AAED;;mDAEmD;AACnD,MAAM,UAAU,wBAAwB,CAAC,QAA2B,EAAE,WAAuC;IAC3G,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,WAAW,EAAE,CAAC;QAC5C,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,MAAM,CAAE,CAAC,IAAI,CAAC,CAAC;IACxH,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,IAAI;QAAE,OAAO;IAC1B,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,EAAE,+CAA+C,CAAC,CAAC;IAC1F,MAAM,KAAK,GAAG,eAAe,CAAC,QAAQ,EACpC,iHAAiH,CAAC,CAAC;IACrH,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAAC,CAAC;AACpE,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAA2B,EAAE,QAAgB,EAAY,EAAE,CAC3F,eAAe,CAAC,QAAQ,EAAE,yDAAyD,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAa,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function holdGroundFiles(release: (file: string) => Promise<void>): void;
|
|
2
|
+
/** Resolves once no registered thread holds `file`, named as every
|
|
3
|
+
* connection names it (databaseFileName). */
|
|
4
|
+
export declare function releaseHeldGroundFile(file: string): Promise<void>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Threads that keep their own connections to ground files (the content
|
|
2
|
+
* threads, content-capture-pool.ts) register how they let one file go, and
|
|
3
|
+
* releasing a ground file (ground-database.ts) waits for every one of them.
|
|
4
|
+
* Registering inverts the import, so the saver, checkpoint and
|
|
5
|
+
* initialization threads never load the content threads' modules. */
|
|
6
|
+
const holders = new Set();
|
|
7
|
+
export function holdGroundFiles(release) {
|
|
8
|
+
holders.add(release);
|
|
9
|
+
}
|
|
10
|
+
/** Resolves once no registered thread holds `file`, named as every
|
|
11
|
+
* connection names it (databaseFileName). */
|
|
12
|
+
export async function releaseHeldGroundFile(file) {
|
|
13
|
+
await Promise.all([...holders].map(release => release(file)));
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=ground-holders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ground-holders.js","sourceRoot":"","sources":["../src/ground-holders.ts"],"names":[],"mappings":"AAAA;;;;qEAIqE;AACrE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmC,CAAC;AAE3D,MAAM,UAAU,eAAe,CAAC,OAAwC;IACtE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACvB,CAAC;AAED;6CAC6C;AAC7C,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAY;IACtD,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bootstrap thread: it migrates one ground database, begins its epoch,
|
|
3
|
+
* reports what it committed and exits. While it runs it holds the file's
|
|
4
|
+
* only connection (ground-initialization.ts).
|
|
5
|
+
*/
|
|
6
|
+
import { parentPort, workerData } from "node:worker_threads";
|
|
7
|
+
import { migrateGroundDatabase } from "./ground-database.js";
|
|
8
|
+
const port = parentPort;
|
|
9
|
+
if (!port)
|
|
10
|
+
throw new Error("ground initialization must run on a worker thread");
|
|
11
|
+
try {
|
|
12
|
+
// Absolute high-resolution times: each thread's own clock has its own origin.
|
|
13
|
+
const startedAt = performance.timeOrigin + performance.now();
|
|
14
|
+
const migration = migrateGroundDatabase(workerData.file);
|
|
15
|
+
port.postMessage({ ok: true, migration, startedAt, reportedAt: performance.timeOrigin + performance.now() });
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
port.postMessage({ ok: false, error });
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=ground-initialization-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ground-initialization-worker.js","sourceRoot":"","sources":["../src/ground-initialization-worker.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,IAAI,GAAG,UAAU,CAAC;AACxB,IAAI,CAAC,IAAI;IAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;AAEhF,IAAI,CAAC;IACH,8EAA8E;IAC9E,MAAM,SAAS,GAAG,WAAW,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAC7D,MAAM,SAAS,GAAG,qBAAqB,CAAE,UAA+B,CAAC,IAAI,CAAC,CAAC;IAC/E,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAC/G,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** What the bootstrap thread committed, in counts, never rows. */
|
|
2
|
+
export interface GroundMigration {
|
|
3
|
+
/** The epoch this initialization began. */
|
|
4
|
+
readonly incarnation: string;
|
|
5
|
+
/** The inventory storage it found. */
|
|
6
|
+
readonly from: "fresh" | "flat" | "generations";
|
|
7
|
+
readonly entities: number;
|
|
8
|
+
readonly notebook: number;
|
|
9
|
+
readonly roots: number;
|
|
10
|
+
/** Open, migration body, commits and epoch, on the bootstrap thread. */
|
|
11
|
+
readonly migrationMs: number;
|
|
12
|
+
/** The conversion's exact-contents check, inside its transaction. */
|
|
13
|
+
readonly validationMs: number;
|
|
14
|
+
/** Secondary keys this open built because their stored form differed. */
|
|
15
|
+
readonly keysBuilt: number;
|
|
16
|
+
}
|
|
17
|
+
export interface GroundInitialization extends GroundMigration {
|
|
18
|
+
/** From the request to the thread starting the migration: spawn and module loading. */
|
|
19
|
+
readonly startupMs: number;
|
|
20
|
+
/** From the thread's report to its exit, when the outcome becomes known. */
|
|
21
|
+
readonly exitMs: number;
|
|
22
|
+
/** From the request to a validated result. */
|
|
23
|
+
readonly readinessMs: number;
|
|
24
|
+
/** The main thread's two synchronous sections: starting the thread, and
|
|
25
|
+
* confirming its committed result, including that thread's first SQLite use. */
|
|
26
|
+
readonly spawnMs: number;
|
|
27
|
+
readonly confirmMs: number;
|
|
28
|
+
}
|
|
29
|
+
export declare const objectAt: (file: string) => string | null;
|
|
30
|
+
/** Awaited before a file's first handle; later calls share the outcome. The
|
|
31
|
+
* host never replaces an initialized file, so another object at its name
|
|
32
|
+
* fails every later opener rather than initializing beside a held one. */
|
|
33
|
+
export declare function initializeGroundDatabase(file: string): Promise<GroundInitialization>;
|
|
34
|
+
/** Every opener of a ground file, read-only or not, on any connection. */
|
|
35
|
+
export declare function assertGroundInitialized(file: string): void;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one owner of a ground database's initialization in this process.
|
|
3
|
+
*
|
|
4
|
+
* Migration and the process's ground epoch run once per file per process,
|
|
5
|
+
* before any ordinary handle exists. They run on a bootstrap thread, never
|
|
6
|
+
* the main one: atomicity belongs to the migration's transactions, not to
|
|
7
|
+
* the thread that runs them. The outcome is known only once that thread has
|
|
8
|
+
* exited, and no opener may read or write the file until its committed
|
|
9
|
+
* result is validated here. A failed initialization leaves nothing
|
|
10
|
+
* recorded, so the next attempt validates the file afresh.
|
|
11
|
+
*/
|
|
12
|
+
import { statSync } from "node:fs";
|
|
13
|
+
import { moduleThread } from "./module-thread.js";
|
|
14
|
+
import { physicalKey } from "./source-signature.js";
|
|
15
|
+
import { databaseFileName, openFileDatabase } from "./sqlite.js";
|
|
16
|
+
const at = () => performance.timeOrigin + performance.now();
|
|
17
|
+
const WORKER = new URL("./ground-initialization-worker.js", import.meta.url);
|
|
18
|
+
const initializing = new Map();
|
|
19
|
+
/** Each initialized file, by the object it initialized. */
|
|
20
|
+
const initialized = new Map();
|
|
21
|
+
export const objectAt = (file) => {
|
|
22
|
+
try {
|
|
23
|
+
return physicalKey(statSync(file, { bigint: true }));
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (error.code === "ENOENT")
|
|
27
|
+
return null;
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
/** Awaited before a file's first handle; later calls share the outcome. The
|
|
32
|
+
* host never replaces an initialized file, so another object at its name
|
|
33
|
+
* fails every later opener rather than initializing beside a held one. */
|
|
34
|
+
export function initializeGroundDatabase(file) {
|
|
35
|
+
const name = databaseFileName(file);
|
|
36
|
+
let pending = initializing.get(name);
|
|
37
|
+
if (!pending) {
|
|
38
|
+
pending = bootstrap(name);
|
|
39
|
+
initializing.set(name, pending);
|
|
40
|
+
pending.catch(() => { if (initializing.get(name) === pending)
|
|
41
|
+
initializing.delete(name); });
|
|
42
|
+
}
|
|
43
|
+
return pending;
|
|
44
|
+
}
|
|
45
|
+
/** Every opener of a ground file, read-only or not, on any connection. */
|
|
46
|
+
export function assertGroundInitialized(file) {
|
|
47
|
+
const name = databaseFileName(file);
|
|
48
|
+
const key = initialized.get(name);
|
|
49
|
+
if (key === undefined)
|
|
50
|
+
throw new Error(`the ground database ${JSON.stringify(file)} is opened before its initialization completed`);
|
|
51
|
+
if (objectAt(name) !== key)
|
|
52
|
+
throw new Error(`the ground database ${JSON.stringify(file)} was replaced after its initialization`);
|
|
53
|
+
}
|
|
54
|
+
function bootstrap(name) {
|
|
55
|
+
const requested = at();
|
|
56
|
+
return new Promise((resolveInitialization, reject) => {
|
|
57
|
+
const worker = moduleThread(WORKER, { workerData: { file: name } });
|
|
58
|
+
const spawnMs = at() - requested;
|
|
59
|
+
let report = null;
|
|
60
|
+
worker.once("message", (message) => { report = message; });
|
|
61
|
+
worker.once("error", error => { report ??= { ok: false, error }; });
|
|
62
|
+
// Only an exited thread has released the file: a reply alone is not an outcome.
|
|
63
|
+
worker.once("exit", code => {
|
|
64
|
+
const outcome = report;
|
|
65
|
+
if (!outcome?.ok) {
|
|
66
|
+
reject(outcome?.error ?? new Error(`ground initialization thread exited with code ${code} before reporting`));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const validating = at();
|
|
70
|
+
try {
|
|
71
|
+
validate(name, outcome.migration);
|
|
72
|
+
const now = at();
|
|
73
|
+
resolveInitialization(Object.freeze({ ...outcome.migration,
|
|
74
|
+
startupMs: outcome.startedAt - requested,
|
|
75
|
+
exitMs: validating - outcome.reportedAt,
|
|
76
|
+
readinessMs: now - requested,
|
|
77
|
+
spawnMs,
|
|
78
|
+
confirmMs: now - validating }));
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
reject(error);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/** The committed file must carry the reported epoch and the generation form. */
|
|
87
|
+
function validate(name, migration) {
|
|
88
|
+
const database = openFileDatabase(name, { readonly: true, fileMustExist: true });
|
|
89
|
+
try {
|
|
90
|
+
const incarnation = database.prepare("SELECT identity FROM ground_incarnation WHERE singleton = 1").pluck().get();
|
|
91
|
+
const views = database.prepare(`SELECT COUNT(*) FROM sqlite_master
|
|
92
|
+
WHERE type = 'view' AND name IN ('entities', 'detection_notebook')`).pluck().get();
|
|
93
|
+
if (incarnation !== migration.incarnation || views !== 2) {
|
|
94
|
+
throw new Error("the ground database does not hold the initialization its thread reported");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
database.close();
|
|
99
|
+
}
|
|
100
|
+
initialized.set(name, objectAt(name));
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=ground-initialization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ground-initialization.js","sourceRoot":"","sources":["../src/ground-initialization.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
import { type RepositorySealCandidate } from "./detection/seal-law.js";
|
|
3
|
+
import type { RepositoryObservationPair } from "./git-repository-host.js";
|
|
4
|
+
import type { GroundRow } from "./ground-row.js";
|
|
5
|
+
import type { SourceFingerprint } from "./source-signature.js";
|
|
6
|
+
/** Who this ground file belongs to. */
|
|
7
|
+
export interface GroundOwner {
|
|
8
|
+
readonly userId: string;
|
|
9
|
+
readonly userEmail: string;
|
|
10
|
+
readonly deviceId: string;
|
|
11
|
+
}
|
|
12
|
+
export interface InstalledRows {
|
|
13
|
+
readonly owner: GroundOwner;
|
|
14
|
+
readonly resourceId: string;
|
|
15
|
+
/** One root's rows: all it observed, and what it selected for sharing,
|
|
16
|
+
* absent when selection could not complete and sharing stands as it was. */
|
|
17
|
+
readonly rows: {
|
|
18
|
+
readonly observed: readonly GroundRow[];
|
|
19
|
+
readonly shared: readonly GroundRow[] | null;
|
|
20
|
+
};
|
|
21
|
+
readonly repositoryObservations: readonly Omit<RepositoryObservationPair, "proof">[];
|
|
22
|
+
/** Rows this root held before; each one an inventory's new rows no longer
|
|
23
|
+
* name leaves that inventory. */
|
|
24
|
+
readonly previous: readonly Pick<GroundRow, "uuid" | "rootUUID">[];
|
|
25
|
+
readonly seals: readonly RepositorySealCandidate[];
|
|
26
|
+
}
|
|
27
|
+
/** `install.rows`. */
|
|
28
|
+
export declare function installRows(database: Database.Database, input: InstalledRows): void;
|
|
29
|
+
/** `install.references`: new references and their parents' derived
|
|
30
|
+
* membership. Each inventory re-derives its own parent version from its own
|
|
31
|
+
* active children, so a notebook never inherits observation-only state. */
|
|
32
|
+
export declare function installReferences(database: Database.Database, input: {
|
|
33
|
+
readonly owner: GroundOwner;
|
|
34
|
+
readonly rows: readonly GroundRow[];
|
|
35
|
+
}): void;
|
|
36
|
+
/** `install.refreshRoot`: a same-filesystem rename preserves identity and
|
|
37
|
+
* bytes but may advance the root directory's ctime, so the revealed root's
|
|
38
|
+
* one derived fingerprint is refreshed before its binding makes the committed
|
|
39
|
+
* graph observable. */
|
|
40
|
+
export declare function refreshRoot(database: Database.Database, input: {
|
|
41
|
+
readonly workspaceId: string;
|
|
42
|
+
readonly absolutePath: string;
|
|
43
|
+
readonly fingerprint: SourceFingerprint;
|
|
44
|
+
}): void;
|
|
45
|
+
/** `install.clearRoot`: every row one root holds, in both inventories. */
|
|
46
|
+
export declare function clearRoot(database: Database.Database, input: {
|
|
47
|
+
readonly resourceId: string;
|
|
48
|
+
readonly rootUUID: string;
|
|
49
|
+
}): void;
|
|
50
|
+
/** One Add's journaled intent: its workspace, destination and exact JSON. */
|
|
51
|
+
export interface AddIntentRow {
|
|
52
|
+
readonly workspaceId: string;
|
|
53
|
+
readonly destinationPath: string;
|
|
54
|
+
readonly intentJson: string;
|
|
55
|
+
}
|
|
56
|
+
/** `add.beginIntent`: the proposed intent, or the one already journaled for
|
|
57
|
+
* that workspace. A destination another pending Add owns refuses. */
|
|
58
|
+
export declare function beginAddIntent(database: Database.Database, proposed: AddIntentRow): {
|
|
59
|
+
readonly intentJson: string;
|
|
60
|
+
readonly created: boolean;
|
|
61
|
+
};
|
|
62
|
+
/** `add.clearIntent`. */
|
|
63
|
+
export declare function clearAddIntent(database: Database.Database, workspaceId: string): void;
|