@jungjaehoon/mama-core 2.4.1 → 4.1.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/README.md +76 -239
- package/db/migrations/030-case-first-memory-substrate.sql +13 -98
- package/db/migrations/034-add-connector-event-scope-columns.sql +9 -13
- package/db/migrations/039-add-connector-event-operator-ingest-seq.sql +9 -95
- package/db/migrations/062-refresh-connector-event-sequences.sql +9 -113
- package/db/migrations/063-refresh-legacy-connector-event-updates.sql +9 -32
- package/db/migrations/067-add-connector-event-source-entity-id.sql +9 -13
- package/db/migrations/069-create-registry-nodes.sql +52 -0
- package/db/migrations/070-record-identity.sql +35 -0
- package/db/migrations/071-service-operation-origins.sql +187 -0
- package/db/migrations/072-observation-versions.sql +29 -0
- package/db/migrations/073-registry-corrections.sql +45 -0
- package/db/migrations/074-work-graph-ref-kinds.sql +39 -0
- package/db/migrations/075-agent-judgments.sql +58 -0
- package/db/migrations/076-scoped-checkpoint-bindings.sql +15 -0
- package/db/migrations/077-legacy-record-kind.sql +6 -0
- package/db/migrations/078-source-ingest-commands.sql +18 -0
- package/db/migrations/079-twin-edge-relations.sql +43 -0
- package/db/migrations/080-restore-duration-days.sql +7 -0
- package/db/migrations/081-mailbox.sql +61 -0
- package/db/migrations/082-commitments-row-id.sql +12 -0
- package/db/migrations/083-observation-is-the-evidence.sql +49 -0
- package/db/migrations/084-scope-kind-is-not-the-cores-to-list.sql +34 -0
- package/db/migrations/085-a-migration-has-a-source.sql +37 -0
- package/db/migrations/086-the-mailbox-is-generic.sql +110 -0
- package/db/migrations/087-mailbox-payload.sql +5 -0
- package/db/migrations/088-native-input-journal.sql +14 -0
- package/db/migrations/089-native-turn-receipt-lookup.sql +3 -0
- package/db/migrations/090-model-run-native-inputs.sql +29 -0
- package/db/migrations/091-native-turn-results.sql +11 -0
- package/db/migrations/092-restore-decision-fts.sql +34 -0
- package/db/migrations/093-native-turn-primary-kind.sql +14 -0
- package/db/migrations/094-commitment-run-provenance.sql +9 -0
- package/db/migrations/095-model-run-native-input-identity.sql +39 -0
- package/db/migrations/096-drop-connector-event-index-fts.sql +9 -0
- package/db/migrations/097-native-input-json-validity.sql +37 -0
- package/db/migrations/098-workflow-memory-kind.sql +105 -0
- package/db/migrations/099-commitment-revision-graph.sql +2 -0
- package/dist/action-contracts.d.ts +212 -0
- package/dist/action-contracts.js +10 -0
- package/dist/api/catalog.d.ts +118 -0
- package/dist/api/catalog.js +1756 -0
- package/dist/api/dispatch.d.ts +76 -0
- package/dist/api/dispatch.js +372 -0
- package/dist/canonicalize.d.ts +2 -2
- package/dist/canonicalize.js +3 -3
- package/dist/client/client.d.ts +33 -0
- package/dist/client/client.js +123 -0
- package/dist/client/ipc.d.ts +81 -0
- package/dist/client/ipc.js +314 -0
- package/dist/db-adapter/base-adapter.d.ts +6 -66
- package/dist/db-adapter/base-adapter.js +6 -6
- package/dist/db-adapter/index.d.ts +5 -5
- package/dist/db-adapter/index.js +2 -5
- package/dist/db-adapter/node-sqlite-adapter.d.ts +85 -15
- package/dist/db-adapter/node-sqlite-adapter.js +1985 -570
- package/dist/db-manager.d.ts +53 -97
- package/dist/db-manager.js +121 -603
- package/dist/embedding/embedder.d.ts +132 -0
- package/dist/embedding/embedder.js +299 -0
- package/dist/identity/principal-repository.d.ts +2 -2
- package/dist/index.d.ts +43 -58
- package/dist/index.js +97 -145
- package/dist/{context-compile/channel-grant.d.ts → knowledge/access.d.ts} +12 -17
- package/dist/knowledge/access.js +663 -0
- package/dist/knowledge/case-errors.d.ts +31 -0
- package/dist/knowledge/case-errors.js +40 -0
- package/dist/{cases/search-rollup.d.ts → knowledge/case-search-rollup.d.ts} +5 -4
- package/dist/{cases/search-rollup.js → knowledge/case-search-rollup.js} +6 -8
- package/dist/{cases/store.d.ts → knowledge/case-store.d.ts} +3 -6
- package/dist/{cases/store.js → knowledge/case-store.js} +7 -42
- package/dist/{cases/timeline-range.d.ts → knowledge/case-timeline-range.d.ts} +3 -3
- package/dist/{cases/timeline-range.js → knowledge/case-timeline-range.js} +47 -25
- package/dist/{cases/types.d.ts → knowledge/case-types.d.ts} +8 -2
- package/dist/{cases/types.js → knowledge/case-types.js} +1 -1
- package/dist/knowledge/commitment-revision-migration.d.ts +4 -0
- package/dist/knowledge/commitment-revision-migration.js +50 -0
- package/dist/knowledge/commitments.d.ts +192 -0
- package/dist/knowledge/commitments.js +386 -0
- package/dist/knowledge/decision-edges.d.ts +70 -0
- package/dist/knowledge/decision-edges.js +123 -0
- package/dist/{agent-graph/types.d.ts → knowledge/graph-query.d.ts} +80 -70
- package/dist/knowledge/graph-query.js +1585 -0
- package/dist/knowledge/identity.d.ts +16 -0
- package/dist/knowledge/identity.js +22 -0
- package/dist/knowledge/index.d.ts +47 -0
- package/dist/knowledge/index.js +90 -0
- package/dist/knowledge/judgment-edge.d.ts +6 -0
- package/dist/knowledge/judgment-edge.js +22 -0
- package/dist/knowledge/judgments.d.ts +118 -0
- package/dist/knowledge/judgments.js +802 -0
- package/dist/knowledge/observations.d.ts +160 -0
- package/dist/knowledge/observations.js +449 -0
- package/dist/knowledge/question-type.d.ts +34 -0
- package/dist/knowledge/question-type.js +70 -0
- package/dist/{search → knowledge}/ranker-features.js +1 -1
- package/dist/{search → knowledge}/search-quality.d.ts +0 -1
- package/dist/knowledge/search.d.ts +38 -0
- package/dist/knowledge/search.js +91 -0
- package/dist/knowledge/source-ingest.d.ts +65 -0
- package/dist/knowledge/source-ingest.js +174 -0
- package/dist/{edges/types.d.ts → knowledge/twin-edge-types.d.ts} +31 -4
- package/dist/{edges/types.js → knowledge/twin-edge-types.js} +13 -2
- package/dist/knowledge/work-dates.d.ts +49 -0
- package/dist/knowledge/work-dates.js +120 -0
- package/dist/mama-api.d.ts +114 -778
- package/dist/mama-api.js +313 -2461
- package/dist/memory/api.d.ts +264 -24
- package/dist/memory/api.js +1633 -843
- package/dist/memory/bootstrap-builder.d.ts +2 -1
- package/dist/memory/bootstrap-builder.js +5 -5
- package/dist/memory/channel-summary-state-store.d.ts +3 -2
- package/dist/memory/channel-summary-state-store.js +53 -51
- package/dist/memory/channel-summary-store.d.ts +5 -3
- package/dist/memory/channel-summary-store.js +3 -8
- package/dist/memory/dashboard-read.d.ts +46 -0
- package/dist/memory/dashboard-read.js +94 -0
- package/dist/memory/event-store.d.ts +3 -3
- package/dist/memory/event-store.js +3 -10
- package/dist/memory/finding-store.d.ts +3 -2
- package/dist/memory/finding-store.js +2 -7
- package/dist/memory/graph-read.d.ts +52 -0
- package/dist/memory/graph-read.js +130 -0
- package/dist/memory/judgment-types.d.ts +394 -0
- package/dist/memory/judgment-types.js +16 -0
- package/dist/memory/provenance-audit.d.ts +5 -2
- package/dist/memory/provenance-audit.js +8 -14
- package/dist/memory/provenance-live.d.ts +141 -0
- package/dist/memory/provenance-live.js +409 -0
- package/dist/memory/provenance-query.d.ts +5 -4
- package/dist/memory/provenance-query.js +21 -29
- package/dist/memory/provenance-resolver.d.ts +191 -0
- package/dist/memory/provenance-resolver.js +155 -0
- package/dist/memory/provenance.d.ts +1 -11
- package/dist/memory/provenance.js +2 -33
- package/dist/memory/recall-sanitize.d.ts +55 -0
- package/dist/memory/recall-sanitize.js +144 -0
- package/dist/memory/secret-filter.d.ts +32 -0
- package/dist/memory/secret-filter.js +126 -0
- package/dist/memory/truth-store.d.ts +2 -1
- package/dist/memory/truth-store.js +1 -4
- package/dist/memory/types.d.ts +74 -24
- package/dist/memory/types.js +75 -5
- package/dist/memory/write-adapters.d.ts +98 -0
- package/dist/memory/write-adapters.js +242 -0
- package/dist/operations/owner-action-effects.d.ts +53 -0
- package/dist/operations/owner-action-effects.js +96 -0
- package/dist/provenance/source-ref.d.ts +1 -1
- package/dist/provenance/source-ref.js +0 -2
- package/dist/registry/corrections.d.ts +31 -0
- package/dist/registry/corrections.js +332 -0
- package/dist/registry/record-identity.d.ts +49 -0
- package/dist/registry/record-identity.js +133 -0
- package/dist/registry/store.d.ts +101 -0
- package/dist/registry/store.js +395 -0
- package/dist/registry/types.d.ts +28 -0
- package/dist/registry/types.js +5 -0
- package/dist/relevance-scorer.js +2 -2
- package/dist/runtime/agent-event-bus.d.ts +50 -0
- package/dist/runtime/agent-event-bus.js +101 -0
- package/dist/runtime/drivers/claude-cli-wrapper.d.ts +152 -0
- package/dist/runtime/drivers/claude-cli-wrapper.js +375 -0
- package/dist/runtime/drivers/claude-effort.d.ts +4 -0
- package/dist/runtime/drivers/claude-effort.js +16 -0
- package/dist/runtime/drivers/cli-arg-redaction.d.ts +2 -0
- package/dist/runtime/drivers/cli-arg-redaction.js +18 -0
- package/dist/runtime/drivers/cli-secret-redaction.d.ts +17 -0
- package/dist/runtime/drivers/cli-secret-redaction.js +126 -0
- package/dist/runtime/drivers/codex-app-server-process.d.ts +277 -0
- package/dist/runtime/drivers/codex-app-server-process.js +2342 -0
- package/dist/runtime/drivers/codex-auxiliary-tools.d.ts +17 -0
- package/dist/runtime/drivers/codex-auxiliary-tools.js +267 -0
- package/dist/runtime/drivers/codex-home.d.ts +20 -0
- package/dist/runtime/drivers/codex-home.js +674 -0
- package/dist/runtime/drivers/codex-thread-registry.d.ts +63 -0
- package/dist/runtime/drivers/codex-thread-registry.js +433 -0
- package/dist/runtime/drivers/persistent-cli-adapter.d.ts +160 -0
- package/dist/runtime/drivers/persistent-cli-adapter.js +396 -0
- package/dist/runtime/drivers/persistent-cli-process.d.ts +425 -0
- package/dist/runtime/drivers/persistent-cli-process.js +1529 -0
- package/dist/runtime/drivers/types.d.ts +456 -0
- package/dist/runtime/drivers/types.js +110 -0
- package/dist/runtime/mailbox.d.ts +223 -0
- package/dist/runtime/mailbox.js +582 -0
- package/dist/runtime/model-run-store.d.ts +28 -0
- package/dist/{model-runs/store.js → runtime/model-run-store.js} +81 -41
- package/dist/{model-runs/types.d.ts → runtime/model-run-types.d.ts} +33 -4
- package/dist/{model-runs/types.js → runtime/model-run-types.js} +1 -1
- package/dist/runtime/native-effect-observer.d.ts +22 -0
- package/dist/runtime/native-effect-observer.js +103 -0
- package/dist/runtime/native-input-journal.d.ts +46 -0
- package/dist/runtime/native-input-journal.js +308 -0
- package/dist/runtime/native-prompt.d.ts +118 -0
- package/dist/runtime/native-prompt.js +496 -0
- package/dist/runtime/native-session.d.ts +10 -0
- package/dist/{agent-graph/index.js → runtime/native-session.js} +9 -6
- package/dist/runtime/native-tool-trace-observer.d.ts +5 -0
- package/dist/runtime/native-tool-trace-observer.js +65 -0
- package/dist/runtime/native-turn.d.ts +272 -0
- package/dist/runtime/native-turn.js +1041 -0
- package/dist/runtime/operations.d.ts +236 -0
- package/dist/runtime/operations.js +565 -0
- package/dist/runtime/post-tool-handler.d.ts +74 -0
- package/dist/runtime/post-tool-handler.js +137 -0
- package/dist/runtime/prompt-layers.d.ts +126 -0
- package/dist/runtime/prompt-layers.js +239 -0
- package/dist/runtime/runtime-process.d.ts +102 -0
- package/dist/runtime/runtime-process.js +206 -0
- package/dist/runtime/runtime.d.ts +278 -0
- package/dist/runtime/runtime.js +563 -0
- package/dist/runtime/session-pool.d.ts +176 -0
- package/dist/runtime/session-pool.js +369 -0
- package/dist/runtime/stimulus-payload.d.ts +5 -0
- package/dist/runtime/stimulus-payload.js +50 -0
- package/dist/runtime/subagent-bridge.d.ts +24 -0
- package/dist/{agent-graph/types.js → runtime/subagent-bridge.js} +1 -1
- package/dist/runtime/text-completion.d.ts +22 -0
- package/dist/{agent-situation/types.js → runtime/text-completion.js} +1 -1
- package/dist/runtime/token-estimator.d.ts +25 -0
- package/dist/runtime/token-estimator.js +75 -0
- package/dist/runtime/tool-trace-store.d.ts +22 -0
- package/dist/{model-runs → runtime}/tool-trace-store.js +46 -27
- package/dist/runtime/trace-summary.d.ts +5 -0
- package/dist/runtime/trace-summary.js +74 -0
- package/dist/runtime/turn-text.d.ts +23 -0
- package/dist/runtime/turn-text.js +41 -0
- package/dist/storage/database.d.ts +67 -0
- package/dist/storage/database.js +158 -0
- package/package.json +20 -34
- package/dist/agent-graph/alias-write.d.ts +0 -3
- package/dist/agent-graph/alias-write.js +0 -234
- package/dist/agent-graph/entity-resolve.d.ts +0 -3
- package/dist/agent-graph/entity-resolve.js +0 -271
- package/dist/agent-graph/errors.d.ts +0 -4
- package/dist/agent-graph/errors.js +0 -11
- package/dist/agent-graph/graph-query.d.ts +0 -5
- package/dist/agent-graph/graph-query.js +0 -360
- package/dist/agent-graph/index.d.ts +0 -6
- package/dist/agent-situation/builder.d.ts +0 -8
- package/dist/agent-situation/builder.js +0 -239
- package/dist/agent-situation/cache-key.d.ts +0 -4
- package/dist/agent-situation/cache-key.js +0 -64
- package/dist/agent-situation/index.d.ts +0 -7
- package/dist/agent-situation/index.js +0 -28
- package/dist/agent-situation/packet-store.d.ts +0 -27
- package/dist/agent-situation/packet-store.js +0 -228
- package/dist/agent-situation/ranking-policy.d.ts +0 -18
- package/dist/agent-situation/ranking-policy.js +0 -75
- package/dist/agent-situation/source-readers.d.ts +0 -52
- package/dist/agent-situation/source-readers.js +0 -300
- package/dist/agent-situation/types.d.ts +0 -195
- package/dist/cases/wiki-page-index.d.ts +0 -37
- package/dist/cases/wiki-page-index.js +0 -201
- package/dist/config-loader.d.ts +0 -68
- package/dist/config-loader.js +0 -239
- package/dist/connectors/event-index.d.ts +0 -24
- package/dist/connectors/event-index.js +0 -245
- package/dist/connectors/raw-query.d.ts +0 -40
- package/dist/connectors/raw-query.js +0 -412
- package/dist/connectors/types.d.ts +0 -117
- package/dist/connectors/types.js +0 -3
- package/dist/context-compile/boundary-defaults.d.ts +0 -12
- package/dist/context-compile/boundary-defaults.js +0 -105
- package/dist/context-compile/channel-grant.js +0 -66
- package/dist/context-compile/compiler-policy.d.ts +0 -39
- package/dist/context-compile/compiler-policy.js +0 -147
- package/dist/context-compile/compiler.d.ts +0 -18
- package/dist/context-compile/compiler.js +0 -404
- package/dist/context-compile/index.d.ts +0 -10
- package/dist/context-compile/index.js +0 -26
- package/dist/context-compile/packet-store.d.ts +0 -8
- package/dist/context-compile/packet-store.js +0 -239
- package/dist/context-compile/ref.d.ts +0 -7
- package/dist/context-compile/ref.js +0 -102
- package/dist/context-compile/source-readers.d.ts +0 -70
- package/dist/context-compile/source-readers.js +0 -840
- package/dist/context-compile/types.d.ts +0 -155
- package/dist/context-compile/types.js +0 -11
- package/dist/context-compile/visibility.d.ts +0 -21
- package/dist/context-compile/visibility.js +0 -224
- package/dist/decision-tracker.d.ts +0 -206
- package/dist/decision-tracker.js +0 -481
- package/dist/edges/ref-validation.d.ts +0 -7
- package/dist/edges/ref-validation.js +0 -321
- package/dist/edges/store.d.ts +0 -8
- package/dist/edges/store.js +0 -129
- package/dist/embedding-client.d.ts +0 -28
- package/dist/embedding-client.js +0 -53
- package/dist/embedding-server/index.d.ts +0 -67
- package/dist/embedding-server/index.js +0 -405
- package/dist/embedding-server/mobile/auth.d.ts +0 -44
- package/dist/embedding-server/mobile/auth.js +0 -150
- package/dist/embedding-server/mobile/daemon.d.ts +0 -129
- package/dist/embedding-server/mobile/daemon.js +0 -313
- package/dist/embedding-server/mobile/output-parser.d.ts +0 -115
- package/dist/embedding-server/mobile/output-parser.js +0 -241
- package/dist/embedding-server/mobile/session-api.d.ts +0 -57
- package/dist/embedding-server/mobile/session-api.js +0 -261
- package/dist/embedding-server/mobile/session-manager.d.ts +0 -138
- package/dist/embedding-server/mobile/session-manager.js +0 -378
- package/dist/embedding-server/mobile/websocket-handler.d.ts +0 -137
- package/dist/embedding-server/mobile/websocket-handler.js +0 -486
- package/dist/embeddings.d.ts +0 -68
- package/dist/embeddings.js +0 -244
- package/dist/entities/audit-metrics.d.ts +0 -68
- package/dist/entities/audit-metrics.js +0 -124
- package/dist/entities/candidate-generator.d.ts +0 -8
- package/dist/entities/candidate-generator.js +0 -24
- package/dist/entities/entity-linked-decision-counts.d.ts +0 -2
- package/dist/entities/entity-linked-decision-counts.js +0 -29
- package/dist/entities/entity-list.d.ts +0 -22
- package/dist/entities/entity-list.js +0 -3
- package/dist/entities/entity-orphan-list.d.ts +0 -17
- package/dist/entities/entity-orphan-list.js +0 -3
- package/dist/entities/entity-search.d.ts +0 -20
- package/dist/entities/entity-search.js +0 -3
- package/dist/entities/errors.d.ts +0 -55
- package/dist/entities/errors.js +0 -100
- package/dist/entities/lineage-store.d.ts +0 -28
- package/dist/entities/lineage-store.js +0 -204
- package/dist/entities/normalization.d.ts +0 -14
- package/dist/entities/normalization.js +0 -63
- package/dist/entities/policy-store.d.ts +0 -8
- package/dist/entities/policy-store.js +0 -75
- package/dist/entities/policy-types.d.ts +0 -72
- package/dist/entities/policy-types.js +0 -59
- package/dist/entities/projection.d.ts +0 -8
- package/dist/entities/projection.js +0 -82
- package/dist/entities/provenance-query.d.ts +0 -32
- package/dist/entities/provenance-query.js +0 -3
- package/dist/entities/read-identity.d.ts +0 -31
- package/dist/entities/read-identity.js +0 -264
- package/dist/entities/recall-bridge.d.ts +0 -5
- package/dist/entities/recall-bridge.js +0 -171
- package/dist/entities/resolution-engine.d.ts +0 -8
- package/dist/entities/resolution-engine.js +0 -3
- package/dist/entities/rollback-preview.d.ts +0 -35
- package/dist/entities/rollback-preview.js +0 -3
- package/dist/entities/source-locator.d.ts +0 -3
- package/dist/entities/source-locator.js +0 -32
- package/dist/entities/store.d.ts +0 -69
- package/dist/entities/store.js +0 -544
- package/dist/entities/types.d.ts +0 -166
- package/dist/entities/types.js +0 -30
- package/dist/memory/extraction-prompt.d.ts +0 -4
- package/dist/memory/extraction-prompt.js +0 -89
- package/dist/memory/scope-backfill.d.ts +0 -14
- package/dist/memory/scope-backfill.js +0 -3
- package/dist/memory/scope-store.d.ts +0 -4
- package/dist/memory/scope-store.js +0 -9
- package/dist/memory-store.d.ts +0 -87
- package/dist/memory-store.js +0 -78
- package/dist/model-runs/store.d.ts +0 -13
- package/dist/model-runs/tool-trace-store.d.ts +0 -8
- package/dist/notification-manager.d.ts +0 -7
- package/dist/notification-manager.js +0 -12
- package/dist/outcome-tracker.d.ts +0 -151
- package/dist/outcome-tracker.js +0 -271
- package/dist/query-intent.d.ts +0 -23
- package/dist/query-intent.js +0 -114
- package/dist/runtime/trusted-provenance.d.ts +0 -3
- package/dist/runtime/trusted-provenance.js +0 -6
- package/dist/search/question-type.d.ts +0 -5
- package/dist/search/question-type.js +0 -41
- package/dist/test-utils.d.ts +0 -80
- package/dist/test-utils.js +0 -218
- package/dist/tier-validator.d.ts +0 -43
- package/dist/tier-validator.js +0 -159
- package/dist/time-formatter.d.ts +0 -25
- package/dist/time-formatter.js +0 -93
- /package/dist/{search → knowledge}/feedback-store.d.ts +0 -0
- /package/dist/{search → knowledge}/feedback-store.js +0 -0
- /package/dist/{search → knowledge}/ranker-features.d.ts +0 -0
- /package/dist/{search → knowledge}/ranker-rescore.d.ts +0 -0
- /package/dist/{search → knowledge}/ranker-rescore.js +0 -0
- /package/dist/{search → knowledge}/ranker-trainer.d.ts +0 -0
- /package/dist/{search → knowledge}/ranker-trainer.js +0 -0
- /package/dist/{search → knowledge}/search-quality.js +0 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading owner work back out of the commitment log.
|
|
3
|
+
*
|
|
4
|
+
* `appendJudgment` has written `commitments` and `commitment_assignments` since
|
|
5
|
+
* migration 075: a commitment row carries identity, the current revision and the
|
|
6
|
+
* head record, and one assignment row per revision carries the patch that
|
|
7
|
+
* revision applied. Nothing read them back. The only SELECT against either table
|
|
8
|
+
* was the writer's own CAS check, so the substrate could be written and never
|
|
9
|
+
* answered from - the shape this refactor exists to close.
|
|
10
|
+
*
|
|
11
|
+
* Current values are a fold, not a column. Each assignment states `set` and
|
|
12
|
+
* `clear` for that revision only, and the view is those applied in revision
|
|
13
|
+
* order. That is what keeps a correction from erasing what it corrected: the
|
|
14
|
+
* revision that changed a title is still readable next to the one that set it,
|
|
15
|
+
* and `history: 'all'` returns them.
|
|
16
|
+
*
|
|
17
|
+
* @module knowledge/commitments
|
|
18
|
+
*/
|
|
19
|
+
import type { DatabaseAdapter } from '../db-manager.js';
|
|
20
|
+
import type { JudgmentAccess, JudgmentKnowledgeOptions } from './judgments.js';
|
|
21
|
+
import type { JudgmentEventMeta, JudgmentReceipt, OwnerWorkPatch, RecordLink, WorkReference } from '../memory/judgment-types.js';
|
|
22
|
+
import type { MemoryScopeRef } from '../memory/types.js';
|
|
23
|
+
/** One revision of a commitment, as the assignment row recorded it. */
|
|
24
|
+
export interface CommitmentRevision {
|
|
25
|
+
revision: number;
|
|
26
|
+
operation: 'create' | 'revise' | 'withdraw';
|
|
27
|
+
recordRef: WorkReference;
|
|
28
|
+
set: OwnerWorkPatch;
|
|
29
|
+
clear: Array<keyof OwnerWorkPatch>;
|
|
30
|
+
/** Source event time; null means this legacy revision had no event time. */
|
|
31
|
+
eventDatetime: number | null;
|
|
32
|
+
createdAt: number;
|
|
33
|
+
}
|
|
34
|
+
/** The compact lifecycle entry returned for a progress-oriented chain read. */
|
|
35
|
+
export interface CommitmentChainEntry {
|
|
36
|
+
revision: number;
|
|
37
|
+
operation: CommitmentRevision['operation'];
|
|
38
|
+
eventDatetime: number | null;
|
|
39
|
+
status: string | null;
|
|
40
|
+
stage: string | null;
|
|
41
|
+
summary: string | null;
|
|
42
|
+
}
|
|
43
|
+
export interface CommitmentView {
|
|
44
|
+
commitmentId: string;
|
|
45
|
+
rowId: number;
|
|
46
|
+
revision: number;
|
|
47
|
+
latestJudgmentRef: WorkReference;
|
|
48
|
+
/** The fold of every assignment up to `revision`. */
|
|
49
|
+
values: OwnerWorkPatch;
|
|
50
|
+
withdrawn: boolean;
|
|
51
|
+
/** The judgment record each surviving revision was written by, oldest first. */
|
|
52
|
+
basis: WorkReference[];
|
|
53
|
+
createdAt: number;
|
|
54
|
+
updatedAt: number;
|
|
55
|
+
/** Present only when the caller asked for `history: 'all'`. */
|
|
56
|
+
history?: CommitmentRevision[];
|
|
57
|
+
/** Present only when the caller asked for the internal `history: 'chain'`. */
|
|
58
|
+
chain?: CommitmentChainEntry[];
|
|
59
|
+
}
|
|
60
|
+
export interface CommitmentPage {
|
|
61
|
+
items: CommitmentView[];
|
|
62
|
+
nextCursor: string | null;
|
|
63
|
+
coverage: {
|
|
64
|
+
returned: number;
|
|
65
|
+
total: number | null;
|
|
66
|
+
complete: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Why the page is not the whole answer. Empty when it is. A caller that
|
|
69
|
+
* cannot tell a complete page from a truncated one will read the first page
|
|
70
|
+
* as the board, which is the failure this field exists to prevent.
|
|
71
|
+
*/
|
|
72
|
+
reasons: string[];
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export interface WorkRead {
|
|
76
|
+
commitmentId?: string;
|
|
77
|
+
rowId?: number;
|
|
78
|
+
/** Only revisions effective at or before this epoch millisecond are folded. */
|
|
79
|
+
asOf?: number;
|
|
80
|
+
history?: 'current' | 'chain' | 'all';
|
|
81
|
+
limit?: number;
|
|
82
|
+
cursor?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Read owner work: one commitment, or a bounded page of them.
|
|
86
|
+
*
|
|
87
|
+
* `asOf` folds revisions by their source event time when recorded, or by the
|
|
88
|
+
* commit clock for judgments without an event time. A backfill committed today
|
|
89
|
+
* can therefore answer what was current at a historical instant. A commitment
|
|
90
|
+
* whose first revision is later than `asOf` is absent, not empty.
|
|
91
|
+
*/
|
|
92
|
+
export declare function readWork(adapter: DatabaseAdapter, query: WorkRead, access: JudgmentAccess): CommitmentPage;
|
|
93
|
+
/**
|
|
94
|
+
* What the caller states when it commits owner work.
|
|
95
|
+
*
|
|
96
|
+
* `commandId` is the caller's idempotency key and `summary` is what the record
|
|
97
|
+
* says; both are required because a commitment is a judgment first. Everything
|
|
98
|
+
* else about the work lives in the patch, which is the only vocabulary this
|
|
99
|
+
* module knows - no product's task shape reaches here.
|
|
100
|
+
*/
|
|
101
|
+
export interface WorkCommand {
|
|
102
|
+
commandId: string;
|
|
103
|
+
/** Native run that authored this work, when it was written during a model turn. */
|
|
104
|
+
modelRunId?: string | null;
|
|
105
|
+
/** What the caller is committing to, in its own words. */
|
|
106
|
+
summary: string;
|
|
107
|
+
reasoning?: string;
|
|
108
|
+
scopes?: MemoryScopeRef[];
|
|
109
|
+
/** Carried onto the record so a commitment names what caused it. */
|
|
110
|
+
sourceRefs?: string[];
|
|
111
|
+
/**
|
|
112
|
+
* Relations this command records as edges in the same transaction as the
|
|
113
|
+
* work. A commitment is a judgment first: a revision that only states how
|
|
114
|
+
* this work relates to other records is still a revision.
|
|
115
|
+
*/
|
|
116
|
+
links?: RecordLink[];
|
|
117
|
+
eventDatetime?: number | null;
|
|
118
|
+
/**
|
|
119
|
+
* When this command happened, if the caller keeps its own clock. It stamps
|
|
120
|
+
* the record and the commitment row alike, so a board that filters on
|
|
121
|
+
* `updatedAt` reads the time the caller states rather than the wall clock.
|
|
122
|
+
*/
|
|
123
|
+
recordedAt?: number;
|
|
124
|
+
/**
|
|
125
|
+
* Provenance carried onto the record's memory_events row. An importer names
|
|
126
|
+
* itself here so an imported row's history says who wrote it - not the agent
|
|
127
|
+
* that merely ran the migration.
|
|
128
|
+
*/
|
|
129
|
+
event?: JudgmentEventMeta;
|
|
130
|
+
}
|
|
131
|
+
export interface CreateWorkCommand extends WorkCommand {
|
|
132
|
+
/** What this new commitment is about; becomes the record topic. */
|
|
133
|
+
topic: string;
|
|
134
|
+
set: OwnerWorkPatch;
|
|
135
|
+
/**
|
|
136
|
+
* Import vocabulary: the identity this work already had in a predecessor
|
|
137
|
+
* store. A migration that brings existing owner rows into the commitment log
|
|
138
|
+
* names their task id and revision so the log keeps the row's number and CAS
|
|
139
|
+
* history instead of minting a new identity. Absent for work first stated
|
|
140
|
+
* through this command log.
|
|
141
|
+
*/
|
|
142
|
+
imported?: {
|
|
143
|
+
rowId: number;
|
|
144
|
+
revision?: number;
|
|
145
|
+
createdAt?: number;
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
export interface ReviseWorkCommand extends WorkCommand {
|
|
149
|
+
commitmentId: string;
|
|
150
|
+
/** The revision record's topic; the work item's topic when omitted. */
|
|
151
|
+
topic?: string;
|
|
152
|
+
expectedRevision?: number;
|
|
153
|
+
set?: OwnerWorkPatch;
|
|
154
|
+
clear?: Array<keyof OwnerWorkPatch>;
|
|
155
|
+
}
|
|
156
|
+
export interface WithdrawWorkCommand extends WorkCommand {
|
|
157
|
+
commitmentId: string;
|
|
158
|
+
/** The withdrawal record's topic; the work item's topic when omitted. */
|
|
159
|
+
topic?: string;
|
|
160
|
+
expectedRevision: number;
|
|
161
|
+
}
|
|
162
|
+
export interface WorkWriteResult {
|
|
163
|
+
commitmentId: string;
|
|
164
|
+
revision: number;
|
|
165
|
+
recordRef: WorkReference;
|
|
166
|
+
receipt: JudgmentReceipt;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Commit new owner work.
|
|
170
|
+
*
|
|
171
|
+
* The work and the record that states it commit together: `appendJudgment` owns
|
|
172
|
+
* the transaction, and this is the vocabulary in front of it. A caller that
|
|
173
|
+
* wrote a task row here and a record there is the split this replaces.
|
|
174
|
+
*/
|
|
175
|
+
export declare function createWork(command: CreateWorkCommand, access: JudgmentAccess, options: JudgmentKnowledgeOptions): Promise<WorkWriteResult>;
|
|
176
|
+
/**
|
|
177
|
+
* Revise owner work at an expected revision.
|
|
178
|
+
*
|
|
179
|
+
* The revision is the caller's claim about what it read. A concurrent write
|
|
180
|
+
* moves it and this fails loudly rather than overwriting what the caller never
|
|
181
|
+
* saw - the same compare-and-set the ledger it replaces performed.
|
|
182
|
+
*/
|
|
183
|
+
export declare function reviseWork(command: ReviseWorkCommand, access: JudgmentAccess, options: JudgmentKnowledgeOptions): Promise<WorkWriteResult>;
|
|
184
|
+
/**
|
|
185
|
+
* Withdraw owner work.
|
|
186
|
+
*
|
|
187
|
+
* Withdrawal is a revision like any other: the values stay readable and the
|
|
188
|
+
* commitment is marked. Nothing is deleted, so a withdrawn commitment can still
|
|
189
|
+
* answer what it held and who withdrew it.
|
|
190
|
+
*/
|
|
191
|
+
export declare function withdrawWork(command: WithdrawWorkCommand, access: JudgmentAccess, options: JudgmentKnowledgeOptions): Promise<WorkWriteResult>;
|
|
192
|
+
//# sourceMappingURL=commitments.d.ts.map
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Reading owner work back out of the commitment log.
|
|
4
|
+
*
|
|
5
|
+
* `appendJudgment` has written `commitments` and `commitment_assignments` since
|
|
6
|
+
* migration 075: a commitment row carries identity, the current revision and the
|
|
7
|
+
* head record, and one assignment row per revision carries the patch that
|
|
8
|
+
* revision applied. Nothing read them back. The only SELECT against either table
|
|
9
|
+
* was the writer's own CAS check, so the substrate could be written and never
|
|
10
|
+
* answered from - the shape this refactor exists to close.
|
|
11
|
+
*
|
|
12
|
+
* Current values are a fold, not a column. Each assignment states `set` and
|
|
13
|
+
* `clear` for that revision only, and the view is those applied in revision
|
|
14
|
+
* order. That is what keeps a correction from erasing what it corrected: the
|
|
15
|
+
* revision that changed a title is still readable next to the one that set it,
|
|
16
|
+
* and `history: 'all'` returns them.
|
|
17
|
+
*
|
|
18
|
+
* @module knowledge/commitments
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.readWork = readWork;
|
|
22
|
+
exports.createWork = createWork;
|
|
23
|
+
exports.reviseWork = reviseWork;
|
|
24
|
+
exports.withdrawWork = withdrawWork;
|
|
25
|
+
const judgments_js_1 = require("./judgments.js");
|
|
26
|
+
const work_dates_js_1 = require("./work-dates.js");
|
|
27
|
+
const DEFAULT_LIMIT = 25;
|
|
28
|
+
const MAX_LIMIT = 100;
|
|
29
|
+
function parseLimit(value) {
|
|
30
|
+
if (value === undefined)
|
|
31
|
+
return DEFAULT_LIMIT;
|
|
32
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > MAX_LIMIT) {
|
|
33
|
+
throw new judgments_js_1.JudgmentError('INVALID_COMMAND', `limit must be an integer from 1 to ${MAX_LIMIT}`);
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
function parseCursor(value) {
|
|
38
|
+
if (value === undefined)
|
|
39
|
+
return 0;
|
|
40
|
+
const afterTaskId = Number(value);
|
|
41
|
+
if (!Number.isSafeInteger(afterTaskId) || afterTaskId < 0) {
|
|
42
|
+
throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'cursor is not a commitment page cursor');
|
|
43
|
+
}
|
|
44
|
+
return afterTaskId;
|
|
45
|
+
}
|
|
46
|
+
function parseAsOf(value) {
|
|
47
|
+
if (value === undefined)
|
|
48
|
+
return null;
|
|
49
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
50
|
+
throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'asOf must be an epoch millisecond integer');
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
function parsePatch(json, field) {
|
|
55
|
+
const parsed = JSON.parse(json);
|
|
56
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
57
|
+
throw new judgments_js_1.JudgmentError('INVALID_COMMAND', `${field} is not a work patch object`);
|
|
58
|
+
}
|
|
59
|
+
return parsed;
|
|
60
|
+
}
|
|
61
|
+
function parseClear(json) {
|
|
62
|
+
const parsed = JSON.parse(json);
|
|
63
|
+
if (!Array.isArray(parsed)) {
|
|
64
|
+
throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'clear_json is not a field list');
|
|
65
|
+
}
|
|
66
|
+
return parsed;
|
|
67
|
+
}
|
|
68
|
+
function applyRevision(values, revision) {
|
|
69
|
+
for (const [field, value] of Object.entries(revision.set)) {
|
|
70
|
+
values[field] = value;
|
|
71
|
+
}
|
|
72
|
+
for (const field of revision.clear) {
|
|
73
|
+
delete values[field];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Fold the assignments into the values they leave behind.
|
|
78
|
+
*
|
|
79
|
+
* `clear` is applied after `set` within one revision: a revision that sets and
|
|
80
|
+
* clears the same field is stating that the field ends the revision absent,
|
|
81
|
+
* which is what the writer's own ordering already means.
|
|
82
|
+
*/
|
|
83
|
+
function foldAssignments(revisions) {
|
|
84
|
+
const values = {};
|
|
85
|
+
for (const revision of revisions) {
|
|
86
|
+
applyRevision(values, revision);
|
|
87
|
+
}
|
|
88
|
+
return values;
|
|
89
|
+
}
|
|
90
|
+
function stringField(values, field) {
|
|
91
|
+
const value = values[field];
|
|
92
|
+
return typeof value === 'string' ? value : null;
|
|
93
|
+
}
|
|
94
|
+
/** A revision's summary, only when its record is visible to the caller. */
|
|
95
|
+
function readJudgmentSummary(adapter, recordId, admitted) {
|
|
96
|
+
if (!recordVisible(adapter, recordId, admitted))
|
|
97
|
+
return null;
|
|
98
|
+
const row = adapter.prepare('SELECT summary FROM decisions WHERE id = ?').get(recordId);
|
|
99
|
+
return row && typeof row.summary === 'string' ? row.summary : null;
|
|
100
|
+
}
|
|
101
|
+
function buildChain(adapter, revisions, admitted) {
|
|
102
|
+
const values = {};
|
|
103
|
+
return revisions.map((revision) => {
|
|
104
|
+
applyRevision(values, revision);
|
|
105
|
+
return {
|
|
106
|
+
revision: revision.revision,
|
|
107
|
+
operation: revision.operation,
|
|
108
|
+
eventDatetime: revision.eventDatetime,
|
|
109
|
+
status: revision.operation === 'withdraw' ? 'cancelled' : stringField(values, 'status'),
|
|
110
|
+
stage: stringField(values, 'stage'),
|
|
111
|
+
summary: readJudgmentSummary(adapter, revision.recordRef.id, admitted),
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Whether the caller may read this commitment.
|
|
117
|
+
*
|
|
118
|
+
* A commitment carries no scope of its own; its head record does, through the
|
|
119
|
+
* same `memory_scope_bindings` every judgment read uses. An unbound record has
|
|
120
|
+
* no partition boundary to violate and stays readable, exactly as
|
|
121
|
+
* `referenceExists` decides it for a memory ref.
|
|
122
|
+
*/
|
|
123
|
+
function recordVisible(adapter, recordId, admitted) {
|
|
124
|
+
const row = adapter
|
|
125
|
+
.prepare('SELECT COUNT(*) AS bindings FROM memory_scope_bindings WHERE memory_id = ?')
|
|
126
|
+
.get(recordId);
|
|
127
|
+
if (!row)
|
|
128
|
+
return false;
|
|
129
|
+
if (row.bindings === 0)
|
|
130
|
+
return true;
|
|
131
|
+
if (admitted.length === 0)
|
|
132
|
+
return false;
|
|
133
|
+
const placeholders = admitted.map(() => '?').join(', ');
|
|
134
|
+
return (adapter
|
|
135
|
+
.prepare(`SELECT 1 FROM memory_scope_bindings
|
|
136
|
+
WHERE memory_id = ? AND scope_id IN (${placeholders}) LIMIT 1`)
|
|
137
|
+
.get(recordId, ...admitted) !== undefined);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Read owner work: one commitment, or a bounded page of them.
|
|
141
|
+
*
|
|
142
|
+
* `asOf` folds revisions by their source event time when recorded, or by the
|
|
143
|
+
* commit clock for judgments without an event time. A backfill committed today
|
|
144
|
+
* can therefore answer what was current at a historical instant. A commitment
|
|
145
|
+
* whose first revision is later than `asOf` is absent, not empty.
|
|
146
|
+
*/
|
|
147
|
+
function readWork(adapter, query, access) {
|
|
148
|
+
const admitted = (0, judgments_js_1.admittedScopeIds)(access);
|
|
149
|
+
const limit = parseLimit(query.limit);
|
|
150
|
+
const afterTaskId = parseCursor(query.cursor);
|
|
151
|
+
const asOf = parseAsOf(query.asOf);
|
|
152
|
+
const wantsHistory = query.history === 'all';
|
|
153
|
+
const wantsChain = query.history === 'chain';
|
|
154
|
+
if (query.history !== undefined &&
|
|
155
|
+
query.history !== 'all' &&
|
|
156
|
+
query.history !== 'current' &&
|
|
157
|
+
query.history !== 'chain') {
|
|
158
|
+
throw new judgments_js_1.JudgmentError('INVALID_COMMAND', "history must be 'current', 'chain', or 'all'");
|
|
159
|
+
}
|
|
160
|
+
if (query.commitmentId !== undefined && query.rowId !== undefined) {
|
|
161
|
+
throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'Ask by commitmentId or rowId, not both');
|
|
162
|
+
}
|
|
163
|
+
const reasons = [];
|
|
164
|
+
let rows;
|
|
165
|
+
let total = null;
|
|
166
|
+
if (query.commitmentId !== undefined) {
|
|
167
|
+
rows = adapter
|
|
168
|
+
.prepare('SELECT * FROM commitments WHERE commitment_id = ?')
|
|
169
|
+
.all(query.commitmentId);
|
|
170
|
+
}
|
|
171
|
+
else if (query.rowId !== undefined) {
|
|
172
|
+
rows = adapter
|
|
173
|
+
.prepare('SELECT * FROM commitments WHERE row_id = ?')
|
|
174
|
+
.all(query.rowId);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
// One extra row decides whether another page exists without a second count.
|
|
178
|
+
rows = adapter
|
|
179
|
+
.prepare('SELECT * FROM commitments WHERE row_id > ? ORDER BY row_id ASC LIMIT ?')
|
|
180
|
+
.all(afterTaskId, limit + 1);
|
|
181
|
+
total = adapter.prepare('SELECT COUNT(*) AS n FROM commitments').get().n;
|
|
182
|
+
}
|
|
183
|
+
const hasMore = query.commitmentId === undefined && query.rowId === undefined ? rows.length > limit : false;
|
|
184
|
+
const pageRows = hasMore ? rows.slice(0, limit) : rows;
|
|
185
|
+
const items = [];
|
|
186
|
+
let scopeHidden = 0;
|
|
187
|
+
for (const row of pageRows) {
|
|
188
|
+
if (!recordVisible(adapter, row.head_record_id, admitted)) {
|
|
189
|
+
scopeHidden += 1;
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
const assignments = adapter
|
|
193
|
+
.prepare(asOf === null
|
|
194
|
+
? `SELECT assignment.*, judgment.event_datetime AS judgment_event_datetime
|
|
195
|
+
FROM commitment_assignments assignment
|
|
196
|
+
JOIN decisions judgment ON judgment.id = assignment.record_id
|
|
197
|
+
WHERE assignment.commitment_id = ? ORDER BY assignment.revision ASC`
|
|
198
|
+
: `SELECT assignment.*, judgment.event_datetime AS judgment_event_datetime FROM commitment_assignments assignment
|
|
199
|
+
JOIN decisions judgment ON judgment.id = assignment.record_id
|
|
200
|
+
WHERE assignment.commitment_id = ?
|
|
201
|
+
AND COALESCE(assignment.applies_from, judgment.event_datetime, assignment.created_at) <= ?
|
|
202
|
+
ORDER BY assignment.revision ASC`)
|
|
203
|
+
.all(...(asOf === null ? [row.commitment_id] : [row.commitment_id, asOf]));
|
|
204
|
+
if (assignments.length === 0) {
|
|
205
|
+
// Bounded away entirely: the commitment had not been created at `asOf`.
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const revisions = assignments.map((assignment) => ({
|
|
209
|
+
revision: assignment.revision,
|
|
210
|
+
operation: assignment.operation,
|
|
211
|
+
recordRef: { kind: 'memory', id: assignment.record_id },
|
|
212
|
+
set: parsePatch(assignment.set_json, 'set_json'),
|
|
213
|
+
clear: parseClear(assignment.clear_json),
|
|
214
|
+
eventDatetime: assignment.applies_from ?? assignment.judgment_event_datetime ?? null,
|
|
215
|
+
createdAt: assignment.created_at,
|
|
216
|
+
}));
|
|
217
|
+
const head = revisions[revisions.length - 1];
|
|
218
|
+
items.push({
|
|
219
|
+
commitmentId: row.commitment_id,
|
|
220
|
+
rowId: row.row_id,
|
|
221
|
+
revision: head.revision,
|
|
222
|
+
latestJudgmentRef: head.recordRef,
|
|
223
|
+
values: foldAssignments(revisions),
|
|
224
|
+
withdrawn: revisions.some((revision) => revision.operation === 'withdraw'),
|
|
225
|
+
basis: revisions.map((revision) => revision.recordRef),
|
|
226
|
+
createdAt: row.created_at,
|
|
227
|
+
updatedAt: asOf === null ? row.updated_at : (head.eventDatetime ?? head.createdAt),
|
|
228
|
+
...(wantsHistory ? { history: revisions } : {}),
|
|
229
|
+
...(wantsChain ? { chain: buildChain(adapter, revisions, admitted) } : {}),
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
if (hasMore) {
|
|
233
|
+
reasons.push('more commitments follow this page');
|
|
234
|
+
}
|
|
235
|
+
if (scopeHidden > 0) {
|
|
236
|
+
// Named, never silent: a page short by rows the caller cannot read is a
|
|
237
|
+
// different answer from a page that is short because there is no more work.
|
|
238
|
+
reasons.push(`${scopeHidden} commitment(s) outside the caller's scopes`);
|
|
239
|
+
}
|
|
240
|
+
if (asOf !== null) {
|
|
241
|
+
reasons.push(`bounded to revisions effective at or before ${asOf}`);
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
items,
|
|
245
|
+
nextCursor: hasMore ? String(pageRows[pageRows.length - 1].row_id) : null,
|
|
246
|
+
coverage: {
|
|
247
|
+
returned: items.length,
|
|
248
|
+
total,
|
|
249
|
+
complete: !hasMore && scopeHidden === 0,
|
|
250
|
+
reasons,
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* The record half of a work command, with absent fields omitted rather than set
|
|
256
|
+
* to `undefined`.
|
|
257
|
+
*
|
|
258
|
+
* The command payload is canonicalized and hashed into `command_bindings`, and
|
|
259
|
+
* the canonicalizer rejects an explicit `undefined` - correctly, since a key
|
|
260
|
+
* present with no value and a key absent are different payloads and must not
|
|
261
|
+
* hash alike.
|
|
262
|
+
*/
|
|
263
|
+
function recordFields(command) {
|
|
264
|
+
return {
|
|
265
|
+
commandId: command.commandId,
|
|
266
|
+
...(command.modelRunId === undefined ? {} : { modelRunId: command.modelRunId }),
|
|
267
|
+
topic: command.topic,
|
|
268
|
+
summary: command.summary,
|
|
269
|
+
recordKind: 'commitment',
|
|
270
|
+
...(command.reasoning === undefined ? {} : { reasoning: command.reasoning }),
|
|
271
|
+
...(command.scopes === undefined ? {} : { scopes: command.scopes }),
|
|
272
|
+
...(command.sourceRefs === undefined ? {} : { sourceRefs: command.sourceRefs }),
|
|
273
|
+
...(command.links === undefined ? {} : { links: command.links }),
|
|
274
|
+
...(command.eventDatetime === undefined ? {} : { eventDatetime: command.eventDatetime }),
|
|
275
|
+
...(command.recordedAt === undefined ? {} : { recordedAt: command.recordedAt }),
|
|
276
|
+
...(command.event === undefined ? {} : { event: command.event }),
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function requireWorkReceipt(receipt) {
|
|
280
|
+
if (!receipt.work) {
|
|
281
|
+
// appendJudgment writes the commitment inside the same transaction as the
|
|
282
|
+
// record, so a receipt without one means the command was not a commitment.
|
|
283
|
+
throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'The judgment carried no commitment receipt');
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
commitmentId: receipt.work.commitmentId,
|
|
287
|
+
revision: receipt.work.revision,
|
|
288
|
+
recordRef: { kind: 'memory', id: receipt.recordId },
|
|
289
|
+
receipt,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Commit new owner work.
|
|
294
|
+
*
|
|
295
|
+
* The work and the record that states it commit together: `appendJudgment` owns
|
|
296
|
+
* the transaction, and this is the vocabulary in front of it. A caller that
|
|
297
|
+
* wrote a task row here and a record there is the split this replaces.
|
|
298
|
+
*/
|
|
299
|
+
async function createWork(command, access, options) {
|
|
300
|
+
(0, work_dates_js_1.assertWorkPatchValues)(command.set);
|
|
301
|
+
const receipt = await (0, judgments_js_1.appendJudgment)({
|
|
302
|
+
...recordFields(command),
|
|
303
|
+
work: {
|
|
304
|
+
operation: 'create',
|
|
305
|
+
set: command.set,
|
|
306
|
+
...(command.imported === undefined ? {} : { imported: command.imported }),
|
|
307
|
+
},
|
|
308
|
+
}, access, options);
|
|
309
|
+
return requireWorkReceipt(receipt);
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Revise owner work at an expected revision.
|
|
313
|
+
*
|
|
314
|
+
* The revision is the caller's claim about what it read. A concurrent write
|
|
315
|
+
* moves it and this fails loudly rather than overwriting what the caller never
|
|
316
|
+
* saw - the same compare-and-set the ledger it replaces performed.
|
|
317
|
+
*/
|
|
318
|
+
async function reviseWork(command, access, options) {
|
|
319
|
+
const statesNothing = command.set === undefined &&
|
|
320
|
+
(command.clear === undefined || command.clear.length === 0) &&
|
|
321
|
+
(command.links === undefined || command.links.length === 0);
|
|
322
|
+
if (statesNothing) {
|
|
323
|
+
throw new judgments_js_1.JudgmentError('INVALID_COMMAND', 'A revision must set, clear, or link at least one field');
|
|
324
|
+
}
|
|
325
|
+
if (command.set !== undefined) {
|
|
326
|
+
(0, work_dates_js_1.assertWorkPatchValues)(command.set);
|
|
327
|
+
}
|
|
328
|
+
// A revision is the caller's claim about what it read; a commitment it cannot
|
|
329
|
+
// see is one it cannot name. The read gate answers 'unavailable' rather than
|
|
330
|
+
// 'denied' so an outside-scope id probes the same silence as a wrong one.
|
|
331
|
+
if (readWork(options.adapter, { commitmentId: command.commitmentId }, access).items.length === 0) {
|
|
332
|
+
throw new judgments_js_1.JudgmentError('REFERENCE_NOT_FOUND', `Commitment is unavailable: ${command.commitmentId}`);
|
|
333
|
+
}
|
|
334
|
+
const topic = command.topic ?? workTopic(options.adapter, command.commitmentId);
|
|
335
|
+
const receipt = await (0, judgments_js_1.appendJudgment)({
|
|
336
|
+
...recordFields({ ...command, topic }),
|
|
337
|
+
work: {
|
|
338
|
+
operation: 'revise',
|
|
339
|
+
commitmentId: command.commitmentId,
|
|
340
|
+
...(command.expectedRevision === undefined
|
|
341
|
+
? {}
|
|
342
|
+
: { expectedRevision: command.expectedRevision }),
|
|
343
|
+
...(command.set === undefined ? {} : { set: command.set }),
|
|
344
|
+
...(command.clear === undefined ? {} : { clear: command.clear }),
|
|
345
|
+
},
|
|
346
|
+
}, access, options);
|
|
347
|
+
return requireWorkReceipt(receipt);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Withdraw owner work.
|
|
351
|
+
*
|
|
352
|
+
* Withdrawal is a revision like any other: the values stay readable and the
|
|
353
|
+
* commitment is marked. Nothing is deleted, so a withdrawn commitment can still
|
|
354
|
+
* answer what it held and who withdrew it.
|
|
355
|
+
*/
|
|
356
|
+
async function withdrawWork(command, access, options) {
|
|
357
|
+
// Same gate as a revision: withdrawal is a claim about what the caller read.
|
|
358
|
+
if (readWork(options.adapter, { commitmentId: command.commitmentId }, access).items.length === 0) {
|
|
359
|
+
throw new judgments_js_1.JudgmentError('REFERENCE_NOT_FOUND', `Commitment is unavailable: ${command.commitmentId}`);
|
|
360
|
+
}
|
|
361
|
+
const topic = command.topic ?? workTopic(options.adapter, command.commitmentId);
|
|
362
|
+
const receipt = await (0, judgments_js_1.appendJudgment)({
|
|
363
|
+
...recordFields({ ...command, topic }),
|
|
364
|
+
work: {
|
|
365
|
+
operation: 'withdraw',
|
|
366
|
+
commitmentId: command.commitmentId,
|
|
367
|
+
expectedRevision: command.expectedRevision,
|
|
368
|
+
},
|
|
369
|
+
}, access, options);
|
|
370
|
+
return requireWorkReceipt(receipt);
|
|
371
|
+
}
|
|
372
|
+
function workTopic(adapter, commitmentId) {
|
|
373
|
+
const row = adapter
|
|
374
|
+
.prepare(`SELECT decision.topic
|
|
375
|
+
FROM commitment_assignments AS assignment
|
|
376
|
+
JOIN decisions AS decision ON decision.id = assignment.record_id
|
|
377
|
+
WHERE assignment.commitment_id = ? AND assignment.operation = 'create'
|
|
378
|
+
ORDER BY assignment.revision
|
|
379
|
+
LIMIT 1`)
|
|
380
|
+
.get(commitmentId);
|
|
381
|
+
if (!row) {
|
|
382
|
+
throw new judgments_js_1.JudgmentError('REFERENCE_NOT_FOUND', `Commitment is unavailable: ${commitmentId}`);
|
|
383
|
+
}
|
|
384
|
+
return row.topic;
|
|
385
|
+
}
|
|
386
|
+
//# sourceMappingURL=commitments.js.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { DatabaseAdapter } from '../db-manager.js';
|
|
2
|
+
/**
|
|
3
|
+
* decision_edges + link_audit_log write boundary.
|
|
4
|
+
*
|
|
5
|
+
* Every mutation of the decision-edge graph goes through this module, so
|
|
6
|
+
* `decision_edges` and `link_audit_log` each have exactly one writing module
|
|
7
|
+
* inside `knowledge/` (the sibling judgments.ts owns the judgment-command
|
|
8
|
+
* edge insert). Each function performs the edge change and its audit row
|
|
9
|
+
* inside ONE adapter transaction - a link write and its audit row commit or
|
|
10
|
+
* fail together.
|
|
11
|
+
*/
|
|
12
|
+
type EdgeWriter = Pick<DatabaseAdapter, 'prepare' | 'transaction'>;
|
|
13
|
+
export interface DecisionEdgeKey {
|
|
14
|
+
fromId: string;
|
|
15
|
+
toId: string;
|
|
16
|
+
relationship: string;
|
|
17
|
+
}
|
|
18
|
+
export interface DecisionEdgeRow extends DecisionEdgeKey {
|
|
19
|
+
reason: string | null;
|
|
20
|
+
createdBy: string | null;
|
|
21
|
+
approvedByUser: number | null;
|
|
22
|
+
decisionId: string | null;
|
|
23
|
+
evidence: string | null;
|
|
24
|
+
createdAt: number | null;
|
|
25
|
+
}
|
|
26
|
+
export interface ProposedDecisionEdge extends DecisionEdgeKey {
|
|
27
|
+
reason: string;
|
|
28
|
+
decisionId: string | null;
|
|
29
|
+
evidence: string | null;
|
|
30
|
+
}
|
|
31
|
+
export interface DecisionEdgeDeleteFailure {
|
|
32
|
+
link: string;
|
|
33
|
+
error: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Insert-or-replace one decision edge row with explicit governance columns.
|
|
37
|
+
* Used by the public createEdge API (createdBy 'llm', approvedByUser 1) and by
|
|
38
|
+
* the backup-restore path (columns replayed from the backup file).
|
|
39
|
+
*/
|
|
40
|
+
export declare function upsertDecisionEdge(adapter: EdgeWriter, edge: DecisionEdgeRow): void;
|
|
41
|
+
/**
|
|
42
|
+
* Record a proposed edge pending user approval, plus its 'proposed' audit row.
|
|
43
|
+
*/
|
|
44
|
+
export declare function proposeDecisionEdge(adapter: EdgeWriter, edge: ProposedDecisionEdge): void;
|
|
45
|
+
/**
|
|
46
|
+
* Approve a pending edge, plus its 'approved' audit row.
|
|
47
|
+
*/
|
|
48
|
+
export declare function approveDecisionEdge(adapter: EdgeWriter, key: DecisionEdgeKey): void;
|
|
49
|
+
/**
|
|
50
|
+
* Reject a proposed edge: the 'rejected' audit row is written before the edge
|
|
51
|
+
* is deleted, in the same transaction.
|
|
52
|
+
*/
|
|
53
|
+
export declare function rejectDecisionEdge(adapter: EdgeWriter, key: DecisionEdgeKey, reason: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* Remove the auto-generated edge population (created_by='user' with no
|
|
56
|
+
* proposal context) and record one 'deprecated' audit row per removed link.
|
|
57
|
+
* `links` is the already-scanned target set; it only feeds the audit rows.
|
|
58
|
+
*/
|
|
59
|
+
export declare function deprecateAutoDecisionEdges(adapter: EdgeWriter, links: readonly DecisionEdgeKey[], reason: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Delete one batch of edges, writing a 'deprecated' audit row for each. A
|
|
62
|
+
* per-link failure is collected and the batch continues, matching the cleanup
|
|
63
|
+
* tool's accounting; a failure of the batch itself throws to the caller.
|
|
64
|
+
*/
|
|
65
|
+
export declare function deleteDecisionEdgesWithAudit(adapter: EdgeWriter, links: readonly DecisionEdgeKey[], reason: string): {
|
|
66
|
+
deleted: number;
|
|
67
|
+
failures: DecisionEdgeDeleteFailure[];
|
|
68
|
+
};
|
|
69
|
+
export {};
|
|
70
|
+
//# sourceMappingURL=decision-edges.d.ts.map
|