hippo-memory 1.68.0 → 1.70.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 +6 -3
- package/dist/agent-memories/apply.d.ts +3 -3
- package/dist/agent-memories/apply.js +16 -31
- package/dist/agent-memories/claude-code.d.ts +1 -3
- package/dist/agent-memories/claude-code.js +11 -7
- package/dist/agent-memories/copilot.d.ts +3 -1
- package/dist/agent-memories/copilot.js +5 -4
- package/dist/agent-memories/files.js +3 -2
- package/dist/agent-memories/gemini.js +6 -5
- package/dist/agent-memories/keys.js +3 -2
- package/dist/agent-memories/legacy.d.ts +2 -2
- package/dist/agent-memories/legacy.js +2 -2
- package/dist/agent-memories/report.d.ts +1 -1
- package/dist/agent-memories/report.js +1 -1
- package/dist/agent-memories/source.d.ts +1 -1
- package/dist/agent-memories/source.js +6 -5
- package/dist/agent-memories/sync.d.ts +1 -1
- package/dist/agent-memories/sync.js +24 -33
- package/dist/agent-memories/types.d.ts +1 -1
- package/dist/api/assemble.d.ts +2 -2
- package/dist/api/assemble.js +42 -32
- package/dist/api/audit.d.ts +4 -7
- package/dist/api/audit.js +6 -20
- package/dist/api/auth.d.ts +5 -18
- package/dist/api/auth.js +44 -194
- package/dist/api/auto-sleep.d.ts +13 -0
- package/dist/api/auto-sleep.js +32 -0
- package/dist/{availability.d.ts → api/availability.d.ts} +2 -2
- package/dist/{availability.js → api/availability.js} +12 -29
- package/dist/{context-auto.js → api/context-auto.js} +2 -1
- package/dist/{context-render.d.ts → api/context-render.d.ts} +4 -4
- package/dist/{context-render.js → api/context-render.js} +7 -6
- package/dist/api/context-select.d.ts +14 -4
- package/dist/api/context-select.js +50 -60
- package/dist/api/context-types.d.ts +5 -5
- package/dist/api/context.d.ts +2 -4
- package/dist/api/context.js +113 -85
- package/dist/api/dormant.d.ts +3 -3
- package/dist/api/dormant.js +38 -107
- package/dist/api/drill-down.d.ts +2 -2
- package/dist/api/drill-down.js +37 -65
- package/dist/api/forget.d.ts +4 -13
- package/dist/api/forget.js +13 -35
- package/dist/api/goals.d.ts +1 -1
- package/dist/api/goals.js +2 -2
- package/dist/api/index.d.ts +26 -0
- package/dist/api/index.js +29 -0
- package/dist/api/instruction-detect.js +74 -0
- package/dist/api/learn.js +63 -55
- package/dist/api/ledger-db.d.ts +20 -0
- package/dist/api/ledger-db.js +79 -0
- package/dist/api/on-store.d.ts +16 -0
- package/dist/api/on-store.js +36 -0
- package/dist/api/outcome.d.ts +9 -46
- package/dist/api/outcome.js +15 -57
- package/dist/{pilot-arm.d.ts → api/pilot-arm.d.ts} +1 -1
- package/dist/{pilot-arm.js → api/pilot-arm.js} +15 -23
- package/dist/api/promote.d.ts +7 -18
- package/dist/api/promote.js +30 -152
- package/dist/{prompt-hook.d.ts → api/prompt-hook.d.ts} +7 -7
- package/dist/{prompt-hook.js → api/prompt-hook.js} +34 -53
- package/dist/api/quarantine.d.ts +5 -5
- package/dist/api/quarantine.js +30 -106
- package/dist/api/recall-core.d.ts +4 -0
- package/dist/api/recall-core.js +112 -0
- package/dist/{recall-history.js → api/recall-history.js} +30 -25
- package/dist/{recall-pipeline.d.ts → api/recall-pipeline.d.ts} +5 -5
- package/dist/{recall-pipeline.js → api/recall-pipeline.js} +47 -42
- package/dist/api/recall-record.d.ts +10 -13
- package/dist/api/recall-record.js +10 -30
- package/dist/api/recall-request.d.ts +2 -2
- package/dist/api/recall-request.js +3 -3
- package/dist/api/recall-types.d.ts +41 -16
- package/dist/api/recall.d.ts +1 -1
- package/dist/api/recall.js +39 -37
- package/dist/api/remember.d.ts +12 -13
- package/dist/api/remember.js +38 -27
- package/dist/api/session-owners.d.ts +4 -0
- package/dist/api/session-owners.js +17 -0
- package/dist/api/sleep-run.d.ts +7 -7
- package/dist/api/sleep-run.js +63 -75
- package/dist/api/sleep.d.ts +1 -1
- package/dist/api/tokens.d.ts +2 -2
- package/dist/api/tokens.js +9 -21
- package/dist/api/types.d.ts +2 -2
- package/dist/api/types.js +1 -1
- package/dist/capture/caller-session.d.ts +2 -2
- package/dist/capture/caller-session.js +8 -8
- package/dist/{capture-error.d.ts → capture/capture-error.d.ts} +2 -2
- package/dist/{capture-error.js → capture/capture-error.js} +7 -7
- package/dist/{codex-patch.js → capture/codex-patch.js} +1 -1
- package/dist/capture/command.d.ts +1 -1
- package/dist/capture/command.js +54 -41
- package/dist/capture/compact-resume-caller.d.ts +1 -1
- package/dist/capture/compact-resume-caller.js +7 -7
- package/dist/capture/compact.d.ts +4 -1
- package/dist/capture/compact.js +59 -22
- package/dist/capture/compaction-items-caller.d.ts +1 -1
- package/dist/capture/compaction-items-caller.js +7 -5
- package/dist/{compaction-items.js → capture/compaction-items.js} +27 -3
- package/dist/{compaction-record.d.ts → capture/compaction-record.d.ts} +10 -6
- package/dist/{compaction-record.js → capture/compaction-record.js} +48 -94
- package/dist/{compaction-spool.js → capture/compaction-spool.js} +17 -13
- package/dist/capture/copilot-transcript.d.ts +3 -0
- package/dist/capture/copilot-transcript.js +9 -2
- package/dist/capture/extract.js +2 -2
- package/dist/capture/failure-caller.d.ts +2 -2
- package/dist/capture/failure-caller.js +6 -6
- package/dist/capture/failure-reading.d.ts +2 -5
- package/dist/capture/failure-reading.js +11 -12
- package/dist/{handoff-evidence.d.ts → capture/handoff-evidence.d.ts} +1 -1
- package/dist/{handoff-evidence.js → capture/handoff-evidence.js} +2 -1
- package/dist/capture/pre-compact-caller.d.ts +1 -1
- package/dist/capture/pre-compact-caller.js +2 -2
- package/dist/{session-digest.d.ts → capture/session-digest.d.ts} +1 -5
- package/dist/{session-digest.js → capture/session-digest.js} +17 -23
- package/dist/capture/session-end-caller.d.ts +2 -2
- package/dist/capture/session-end-caller.js +1 -1
- package/dist/capture/session-texts.d.ts +1 -1
- package/dist/capture/session-texts.js +5 -5
- package/dist/capture/session-worker.d.ts +13 -0
- package/dist/capture/session-worker.js +196 -0
- package/dist/{share-scrub.js → capture/share-scrub.js} +2 -2
- package/dist/capture/transcript.js +68 -74
- package/dist/capture/working-state.d.ts +0 -3
- package/dist/capture/working-state.js +7 -7
- package/dist/{audit-prune.d.ts → cli/audit-prune.d.ts} +1 -2
- package/dist/{audit-prune.js → cli/audit-prune.js} +5 -39
- package/dist/cli/audit.d.ts +2 -2
- package/dist/cli/audit.js +77 -72
- package/dist/cli/auth.d.ts +2 -1
- package/dist/cli/auth.js +18 -20
- package/dist/cli/briefs.d.ts +4 -3
- package/dist/cli/briefs.js +59 -181
- package/dist/cli/card.d.ts +2 -1
- package/dist/cli/card.js +25 -23
- package/dist/{client.d.ts → cli/client.d.ts} +1 -1
- package/dist/{client.js → cli/client.js} +1 -1
- package/dist/cli/compact-resume-payload.d.ts +8 -0
- package/dist/cli/compact-resume-payload.js +39 -0
- package/dist/cli/context.d.ts +2 -13
- package/dist/cli/context.js +41 -71
- package/dist/cli/continuity.d.ts +6 -5
- package/dist/cli/continuity.js +109 -99
- package/dist/{correction-latency.d.ts → cli/correction-latency.d.ts} +1 -1
- package/dist/cli/curate.d.ts +9 -9
- package/dist/cli/curate.js +177 -149
- package/dist/cli/dag.d.ts +4 -4
- package/dist/cli/dag.js +46 -34
- package/dist/cli/decisions.d.ts +4 -3
- package/dist/cli/decisions.js +108 -218
- package/dist/cli/eval.d.ts +1 -3
- package/dist/cli/eval.js +43 -31
- package/dist/cli/explain.d.ts +1 -1
- package/dist/cli/explain.js +35 -19
- package/dist/cli/flag-values.d.ts +25 -0
- package/dist/cli/flag-values.js +103 -0
- package/dist/cli/flags.d.ts +303 -0
- package/dist/cli/flags.js +169 -0
- package/dist/cli/goals.d.ts +2 -1
- package/dist/cli/goals.js +39 -34
- package/dist/cli/hook-runtime.d.ts +49 -0
- package/dist/cli/hook-runtime.js +155 -0
- package/dist/cli/init.d.ts +2 -1
- package/dist/cli/init.js +151 -118
- package/dist/cli/install-steps.d.ts +7 -0
- package/dist/cli/install-steps.js +110 -0
- package/dist/cli/last-sleep.d.ts +2 -1
- package/dist/cli/last-sleep.js +9 -7
- package/dist/cli/maintenance.d.ts +5 -4
- package/dist/cli/maintenance.js +31 -27
- package/dist/cli/object-verbs.d.ts +40 -0
- package/dist/cli/object-verbs.js +65 -0
- package/dist/{owner-validation.d.ts → cli/owner-validation.d.ts} +0 -1
- package/dist/{owner-validation.js → cli/owner-validation.js} +2 -2
- package/dist/cli/playbooks.d.ts +4 -3
- package/dist/cli/playbooks.js +77 -280
- package/dist/cli/print.d.ts +18 -0
- package/dist/cli/print.js +85 -0
- package/dist/cli/projects.d.ts +2 -3
- package/dist/cli/projects.js +56 -49
- package/dist/{provenance-coverage.d.ts → cli/provenance-coverage.d.ts} +1 -1
- package/dist/cli/quality-repair-once.js +4 -4
- package/dist/{quality-repair.js → cli/quality-repair.js} +23 -37
- package/dist/cli/recall.d.ts +2 -4
- package/dist/cli/recall.js +101 -150
- package/dist/{refine-llm.d.ts → cli/refine-llm.d.ts} +1 -1
- package/dist/{refine-llm.js → cli/refine-llm.js} +70 -82
- package/dist/cli/remember.d.ts +1 -3
- package/dist/cli/remember.js +124 -103
- package/dist/{scheduler.d.ts → cli/scheduler.d.ts} +3 -1
- package/dist/{scheduler.js → cli/scheduler.js} +13 -7
- package/dist/cli/serve.d.ts +1 -1
- package/dist/cli/serve.js +34 -4
- package/dist/cli/session-hooks.d.ts +4 -4
- package/dist/cli/session-hooks.js +265 -191
- package/dist/cli/setup.d.ts +2 -1
- package/dist/cli/setup.js +111 -45
- package/dist/cli/shared.d.ts +5 -95
- package/dist/cli/shared.js +18 -369
- package/dist/cli/slack.d.ts +2 -1
- package/dist/cli/slack.js +31 -55
- package/dist/cli/sleep-render.d.ts +4 -0
- package/dist/cli/sleep-render.js +61 -0
- package/dist/cli/sleep.d.ts +2 -8
- package/dist/cli/sleep.js +20 -76
- package/dist/cli/status.d.ts +3 -3
- package/dist/cli/status.js +39 -41
- package/dist/{stdin.js → cli/stdin.js} +6 -6
- package/dist/cli/transfer.d.ts +4 -4
- package/dist/cli/transfer.js +68 -42
- package/dist/cli/usage.js +8 -3
- package/dist/cli.d.ts +289 -5
- package/dist/cli.js +184 -117
- package/dist/connectors/dlq.d.ts +44 -0
- package/dist/connectors/dlq.js +30 -0
- package/dist/connectors/github/backfill.d.ts +1 -1
- package/dist/connectors/github/backfill.js +29 -66
- package/dist/connectors/github/cli-impl.js +59 -74
- package/dist/connectors/github/deletion.d.ts +5 -6
- package/dist/connectors/github/deletion.js +18 -52
- package/dist/connectors/github/dlq.d.ts +7 -61
- package/dist/connectors/github/dlq.js +19 -119
- package/dist/connectors/github/ingest.d.ts +2 -31
- package/dist/connectors/github/ingest.js +20 -82
- package/dist/connectors/github/octokit-client.d.ts +1 -1
- package/dist/connectors/github/octokit-client.js +2 -1
- package/dist/connectors/github/tenant-routing.d.ts +2 -2
- package/dist/connectors/github/tenant-routing.js +10 -36
- package/dist/connectors/github/transform.d.ts +1 -1
- package/dist/connectors/github/types.d.ts +1 -1
- package/dist/connectors/github/types.js +15 -18
- package/dist/connectors/github/webhook.d.ts +3 -2
- package/dist/connectors/github/webhook.js +84 -87
- package/dist/connectors/slack/backfill.d.ts +1 -1
- package/dist/connectors/slack/backfill.js +5 -29
- package/dist/connectors/slack/deletion.d.ts +4 -7
- package/dist/connectors/slack/deletion.js +20 -48
- package/dist/connectors/slack/dlq.d.ts +7 -49
- package/dist/connectors/slack/dlq.js +25 -118
- package/dist/connectors/slack/ingest.d.ts +5 -18
- package/dist/connectors/slack/ingest.js +27 -90
- package/dist/connectors/slack/signature.js +2 -1
- package/dist/connectors/slack/tenant-routing.d.ts +4 -1
- package/dist/connectors/slack/tenant-routing.js +13 -14
- package/dist/connectors/slack/transform.d.ts +1 -1
- package/dist/connectors/slack/types.d.ts +1 -1
- package/dist/connectors/slack/types.js +3 -12
- package/dist/connectors/slack/web-client.js +2 -2
- package/dist/connectors/slack/webhook.d.ts +3 -2
- package/dist/connectors/slack/webhook.js +75 -82
- package/dist/connectors/slack/workspaces.d.ts +4 -17
- package/dist/connectors/slack/workspaces.js +4 -34
- package/dist/consolidate/conflicts.d.ts +1 -1
- package/dist/consolidate/conflicts.js +4 -4
- package/dist/{dag.d.ts → consolidate/dag.d.ts} +1 -1
- package/dist/{dag.js → consolidate/dag.js} +60 -81
- package/dist/consolidate/decay.d.ts +2 -2
- package/dist/consolidate/decay.js +28 -22
- package/dist/{dedupe.js → consolidate/dedupe.js} +11 -19
- package/dist/consolidate/flush-units.d.ts +2 -2
- package/dist/{half-life-migration.d.ts → consolidate/half-life-migration.d.ts} +3 -9
- package/dist/consolidate/half-life-migration.js +106 -0
- package/dist/consolidate/llm-passes.js +8 -8
- package/dist/{memory-value.d.ts → consolidate/memory-value.d.ts} +7 -2
- package/dist/{memory-value.js → consolidate/memory-value.js} +9 -7
- package/dist/consolidate/merge.js +57 -54
- package/dist/{merged-row.d.ts → consolidate/merged-row.d.ts} +1 -1
- package/dist/{merged-row.js → consolidate/merged-row.js} +2 -2
- package/dist/consolidate/physics-pass.js +46 -46
- package/dist/{replay.d.ts → consolidate/replay.d.ts} +1 -1
- package/dist/{replay.js → consolidate/replay.js} +2 -2
- package/dist/consolidate/run.d.ts +7 -13
- package/dist/consolidate/run.js +6 -37
- package/dist/consolidate/sleep.d.ts +1 -1
- package/dist/consolidate/sleep.js +64 -134
- package/dist/{trace.js → consolidate/trace.js} +4 -6
- package/dist/consolidate/traces.js +34 -29
- package/dist/{ablation.js → core/ablation.js} +1 -1
- package/dist/{agent-memories/tools.d.ts → core/agent-memory-tools.d.ts} +1 -1
- package/dist/{agent-memories/tools.js → core/agent-memory-tools.js} +1 -1
- package/dist/{ambient.js → core/ambient.js} +12 -10
- package/dist/{capture-contract.d.ts → core/capture-contract.d.ts} +16 -3
- package/dist/core/capture-contract.js +149 -0
- package/dist/{compare.d.ts → core/compare.d.ts} +2 -0
- package/dist/{compare.js → core/compare.js} +10 -3
- package/dist/{config.d.ts → core/config.d.ts} +6 -6
- package/dist/{config.js → core/config.js} +99 -72
- package/dist/core/handoff.js +87 -0
- package/dist/{memory-quality.js → core/memory-quality.js} +1 -1
- package/dist/{memory.d.ts → core/memory.d.ts} +19 -5
- package/dist/{memory.js → core/memory.js} +117 -82
- package/dist/{physics.d.ts → core/physics.d.ts} +1 -1
- package/dist/{physics.js → core/physics.js} +2 -1
- package/dist/{project-identity.d.ts → core/project-identity.d.ts} +0 -5
- package/dist/{project-identity.js → core/project-identity.js} +5 -17
- package/dist/{project-remote.js → core/project-remote.js} +4 -4
- package/dist/{prompt-recall.d.ts → core/prompt-recall.d.ts} +5 -0
- package/dist/{prompt-recall.js → core/prompt-recall.js} +14 -1
- package/dist/{salience.js → core/salience.js} +35 -20
- package/dist/{search/types.d.ts → core/search-types.d.ts} +2 -2
- package/dist/{search/types.js → core/search-types.js} +1 -1
- package/dist/core/session-digest-row.d.ts +5 -0
- package/dist/core/session-digest-row.js +6 -0
- package/dist/{dashboard-actions.d.ts → dashboard/dashboard-actions.d.ts} +1 -1
- package/dist/{dashboard-actions.js → dashboard/dashboard-actions.js} +5 -5
- package/dist/{dashboard-queries.d.ts → dashboard/dashboard-queries.d.ts} +7 -2
- package/dist/{dashboard-queries.js → dashboard/dashboard-queries.js} +6 -10
- package/dist/{dashboard-snapshot.d.ts → dashboard/dashboard-snapshot.d.ts} +9 -9
- package/dist/{dashboard-snapshot.js → dashboard/dashboard-snapshot.js} +101 -104
- package/dist/{dashboard.js → dashboard/dashboard.js} +124 -53
- package/dist/db/backup.js +1 -1
- package/dist/db/busy.d.ts +18 -1
- package/dist/db/busy.js +74 -9
- package/dist/db/connect.d.ts +10 -2
- package/dist/db/connect.js +43 -10
- package/dist/db/index.d.ts +9 -0
- package/dist/db/index.js +8 -0
- package/dist/db/meta.d.ts +4 -0
- package/dist/db/meta.js +11 -1
- package/dist/db/migrate.d.ts +8 -1
- package/dist/db/migrate.js +25 -30
- package/dist/db/migrations/v08.js +1 -1
- package/dist/db/migrations/v14.js +39 -35
- package/dist/db/migrations/v16.js +29 -26
- package/dist/db/migrations/v18.js +6 -5
- package/dist/db/migrations/v20.js +4 -2
- package/dist/db/migrations/v22.js +39 -36
- package/dist/db/migrations/v24.js +27 -22
- package/dist/db/migrations/v29.js +37 -32
- package/dist/db/migrations/v31.js +36 -31
- package/dist/db/migrations/v35.js +1 -1
- package/dist/db/migrations/v39.js +1 -1
- package/dist/db/migrations/v40.js +15 -14
- package/dist/db/migrations/v43.js +7 -6
- package/dist/db/migrations/v44.js +1 -1
- package/dist/db/migrations/v45.js +1 -1
- package/dist/db/migrations/v46.js +1 -1
- package/dist/db/migrations/v47.js +1 -1
- package/dist/db/migrations/v48.js +1 -1
- package/dist/db/migrations/v49.js +1 -1
- package/dist/db/migrations/v50.js +8 -7
- package/dist/db/migrations/v52.js +1 -1
- package/dist/db/open.d.ts +9 -1
- package/dist/db/open.js +21 -4
- package/dist/{physics-state.d.ts → db/physics-state.d.ts} +3 -3
- package/dist/{physics-state.js → db/physics-state.js} +9 -16
- package/dist/{raw-archive-mirror-cleanup.d.ts → db/raw-archive-mirror-cleanup.d.ts} +5 -5
- package/dist/{raw-archive-mirror-cleanup.js → db/raw-archive-mirror-cleanup.js} +11 -6
- package/dist/db/request-stores.d.ts +15 -2
- package/dist/db/request-stores.js +37 -15
- package/dist/db/tables.d.ts +2 -0
- package/dist/db/tables.js +6 -0
- package/dist/{vector-store.d.ts → db/vector-store.d.ts} +4 -2
- package/dist/{vector-store.js → db/vector-store.js} +76 -51
- package/dist/db/wal-checkpointer.d.ts +11 -0
- package/dist/db/wal-checkpointer.js +92 -0
- package/dist/doctor.js +105 -136
- package/dist/entry/json-hooks.d.ts +1 -1
- package/dist/entry/json-hooks.js +1 -1
- package/dist/entry/project-identity.d.ts +1 -1
- package/dist/entry/project-identity.js +1 -1
- package/dist/entry/session-text.d.ts +3 -3
- package/dist/entry/session-text.js +3 -3
- package/dist/{eval-stats.js → eval/eval-stats.js} +12 -9
- package/dist/{eval-suite.d.ts → eval/eval-suite.d.ts} +1 -1
- package/dist/{eval-suite.js → eval/eval-suite.js} +25 -23
- package/dist/{eval.d.ts → eval/eval.d.ts} +1 -1
- package/dist/{eval.js → eval/eval.js} +29 -22
- package/dist/{judgment.d.ts → eval/judgment.d.ts} +1 -3
- package/dist/{judgment.js → eval/judgment.js} +4 -9
- package/dist/extensions/openclaw-plugin/index.js +1 -2
- package/dist/graph/delta.d.ts +3 -2
- package/dist/graph/delta.js +9 -23
- package/dist/{graph-extract.d.ts → graph/extract.d.ts} +6 -6
- package/dist/{graph-extract.js → graph/extract.js} +37 -52
- package/dist/{graph-recall.d.ts → graph/recall.d.ts} +2 -2
- package/dist/{graph-recall.js → graph/recall.js} +55 -36
- package/dist/{graph-stream.d.ts → graph/stream.d.ts} +2 -2
- package/dist/{graph-stream.js → graph/stream.js} +9 -7
- package/dist/{graph-view.d.ts → graph/view.d.ts} +6 -3
- package/dist/{graph-view.js → graph/view.js} +127 -167
- package/dist/graph/write.d.ts +4 -76
- package/dist/graph/write.js +13 -397
- package/dist/hooks/codex-session.js +1 -1
- package/dist/hooks/codex-wrapper.js +14 -15
- package/dist/hooks/copilot.d.ts +48 -13
- package/dist/hooks/copilot.js +124 -39
- package/dist/{cli → hooks}/hook-blocks.js +1 -1
- package/dist/hooks/json-hooks.d.ts +3 -1
- package/dist/hooks/json-hooks.js +40 -122
- package/dist/hooks/opencode.js +35 -27
- package/dist/hooks/shared.d.ts +7 -5
- package/dist/hooks/shared.js +19 -8
- package/dist/importers/core.d.ts +2 -6
- package/dist/importers/core.js +41 -39
- package/dist/importers/markdown-parse.d.ts +1 -10
- package/dist/importers/markdown-parse.js +2 -19
- package/dist/importers/markdown.js +2 -1
- package/dist/importers/sources.js +50 -46
- package/dist/importers/vault.js +71 -92
- package/dist/index.d.ts +22 -22
- package/dist/index.js +21 -21
- package/dist/{autolearn.d.ts → learn/autolearn.d.ts} +2 -2
- package/dist/{autolearn.js → learn/autolearn.js} +13 -11
- package/dist/{churn-git.d.ts → learn/churn-git.d.ts} +1 -1
- package/dist/{churn-git.js → learn/churn-git.js} +6 -4
- package/dist/{extract.d.ts → learn/extract.d.ts} +1 -1
- package/dist/learn/extract.js +125 -0
- package/dist/{forward-claim-detector.d.ts → learn/forward-claim-detector.d.ts} +1 -1
- package/dist/{forward-claim-detector.js → learn/forward-claim-detector.js} +1 -1
- package/dist/{invalidation.d.ts → learn/invalidation.d.ts} +4 -0
- package/dist/{invalidation.js → learn/invalidation.js} +83 -99
- package/dist/mcp/admin-tools.d.ts +1 -1
- package/dist/mcp/admin-tools.js +37 -60
- package/dist/mcp/format.d.ts +5 -5
- package/dist/mcp/format.js +7 -6
- package/dist/mcp/framing.d.ts +6 -0
- package/dist/mcp/framing.js +11 -3
- package/dist/mcp/memory-tools.d.ts +2 -2
- package/dist/mcp/memory-tools.js +12 -31
- package/dist/mcp/protocol.d.ts +6 -10
- package/dist/mcp/protocol.js +8 -14
- package/dist/mcp/recall-tools.d.ts +2 -2
- package/dist/mcp/recall-tools.js +68 -50
- package/dist/mcp/request.js +65 -63
- package/dist/mcp/server.js +1 -1
- package/dist/mcp/session-state.d.ts +1 -2
- package/dist/mcp/session-state.js +2 -2
- package/dist/mcp/shared-gate.js +1 -1
- package/dist/mcp/stdio.js +69 -31
- package/dist/mcp/tool-args.js +2 -1
- package/dist/mcp/tools.js +2 -2
- package/dist/{customer-notes.d.ts → objects/customer-notes.d.ts} +7 -24
- package/dist/objects/customer-notes.js +112 -0
- package/dist/{decisions.d.ts → objects/decisions.d.ts} +13 -28
- package/dist/objects/decisions.js +101 -0
- package/dist/objects/descriptor.d.ts +52 -0
- package/dist/objects/descriptor.js +4 -0
- package/dist/objects/fields.d.ts +15 -0
- package/dist/objects/fields.js +21 -0
- package/dist/{incidents.d.ts → objects/incidents.d.ts} +17 -44
- package/dist/objects/incidents.js +130 -0
- package/dist/objects/lifecycle.d.ts +27 -0
- package/dist/objects/lifecycle.js +96 -0
- package/dist/{policies.d.ts → objects/policies.d.ts} +14 -27
- package/dist/objects/policies.js +189 -0
- package/dist/{processes.d.ts → objects/processes.d.ts} +14 -34
- package/dist/objects/processes.js +146 -0
- package/dist/{project-briefs.d.ts → objects/project-briefs.d.ts} +19 -40
- package/dist/objects/project-briefs.js +255 -0
- package/dist/{skills.d.ts → objects/skills.d.ts} +11 -26
- package/dist/objects/skills.js +156 -0
- package/dist/postinstall.js +4 -2
- package/dist/predictions/planning-fallacy.d.ts +4 -76
- package/dist/predictions/planning-fallacy.js +4 -129
- package/dist/rerankers/clef.d.ts +2 -6
- package/dist/rerankers/clef.js +27 -47
- package/dist/rerankers/cross-encoder.d.ts +0 -7
- package/dist/rerankers/cross-encoder.js +15 -23
- package/dist/rerankers/index.js +8 -7
- package/dist/rerankers/jev.d.ts +1 -4
- package/dist/rerankers/jev.js +30 -49
- package/dist/rerankers/llm.d.ts +2 -4
- package/dist/rerankers/llm.js +33 -50
- package/dist/rerankers/outage-warning.d.ts +7 -0
- package/dist/rerankers/outage-warning.js +31 -0
- package/dist/rerankers/remote.d.ts +3 -0
- package/dist/rerankers/remote.js +23 -0
- package/dist/rerankers/types.d.ts +1 -1
- package/dist/search/as-of.d.ts +1 -1
- package/dist/search/bm25-search.d.ts +2 -2
- package/dist/search/bm25-search.js +7 -7
- package/dist/search/bm25.d.ts +1 -1
- package/dist/search/bm25.js +1 -1
- package/dist/search/boosts.d.ts +5 -1
- package/dist/search/boosts.js +34 -13
- package/dist/search/breakdown.d.ts +2 -2
- package/dist/search/breakdown.js +2 -1
- package/dist/search/explain.d.ts +1 -1
- package/dist/search/explain.js +3 -2
- package/dist/search/finalize.d.ts +2 -2
- package/dist/search/finalize.js +4 -3
- package/dist/search/fusion.d.ts +1 -1
- package/dist/search/fusion.js +3 -3
- package/dist/search/hybrid-score.d.ts +2 -2
- package/dist/search/hybrid-score.js +1 -1
- package/dist/search/hybrid.d.ts +4 -4
- package/dist/search/hybrid.js +11 -8
- package/dist/{multihop.d.ts → search/multihop.d.ts} +2 -2
- package/dist/{multihop.js → search/multihop.js} +7 -5
- package/dist/{path-context.js → search/path-context.js} +3 -1
- package/dist/search/physics-search.d.ts +4 -4
- package/dist/search/physics-search.js +15 -15
- package/dist/search/rerank.d.ts +3 -3
- package/dist/search/rerank.js +4 -3
- package/dist/search/temporal.d.ts +1 -1
- package/dist/search/temporal.js +5 -2
- package/dist/search/vector.d.ts +3 -3
- package/dist/search/vector.js +17 -11
- package/dist/server/auth.d.ts +1 -1
- package/dist/server/auth.js +26 -18
- package/dist/server/boot.d.ts +24 -0
- package/dist/server/boot.js +465 -0
- package/dist/server/client-ip.d.ts +5 -1
- package/dist/server/client-ip.js +18 -6
- package/dist/server/cursor.d.ts +1 -1
- package/dist/server/cursor.js +2 -3
- package/dist/server/deadline.d.ts +13 -0
- package/dist/server/deadline.js +45 -0
- package/dist/server/key-check-bounds.d.ts +8 -0
- package/dist/server/key-check-bounds.js +46 -0
- package/dist/server/lifecycle.js +1 -1
- package/dist/server/mcp-http.d.ts +1 -4
- package/dist/server/mcp-http.js +34 -24
- package/dist/server/ready.d.ts +7 -0
- package/dist/server/ready.js +38 -0
- package/dist/server/request.d.ts +10 -4
- package/dist/server/request.js +63 -12
- package/dist/server/route-table.d.ts +15 -0
- package/dist/server/route-table.js +209 -0
- package/dist/server/routes/admin.js +13 -8
- package/dist/server/routes/customer-notes.d.ts +5 -5
- package/dist/server/routes/customer-notes.js +32 -97
- package/dist/server/routes/decisions.d.ts +5 -5
- package/dist/server/routes/decisions.js +42 -105
- package/dist/server/routes/incidents.d.ts +5 -5
- package/dist/server/routes/incidents.js +42 -95
- package/dist/server/routes/memories.js +21 -20
- package/dist/server/routes/object-routes.d.ts +40 -0
- package/dist/server/routes/object-routes.js +80 -0
- package/dist/server/routes/policies.d.ts +6 -6
- package/dist/server/routes/policies.js +40 -124
- package/dist/server/routes/predictions.js +29 -45
- package/dist/server/routes/processes.d.ts +5 -5
- package/dist/server/routes/processes.js +38 -118
- package/dist/server/routes/project-briefs.d.ts +6 -6
- package/dist/server/routes/project-briefs.js +38 -110
- package/dist/server/routes/recall.js +14 -12
- package/dist/server/routes/skills.d.ts +6 -6
- package/dist/server/routes/skills.js +37 -125
- package/dist/{server-detect.js → server/server-detect.js} +3 -2
- package/dist/server/sleep-child.d.ts +2 -0
- package/dist/server/sleep-child.js +19 -0
- package/dist/server/sleep-offload.d.ts +20 -0
- package/dist/server/sleep-offload.js +70 -0
- package/dist/server/tls.d.ts +6 -0
- package/dist/server/tls.js +24 -0
- package/dist/server/types.d.ts +27 -8
- package/dist/server/validation.d.ts +3 -4
- package/dist/server/validation.js +6 -11
- package/dist/server.d.ts +41 -50
- package/dist/server.js +26 -560
- package/dist/{project-merge.d.ts → sharing/project-merge.d.ts} +1 -1
- package/dist/{project-merge.js → sharing/project-merge.js} +26 -45
- package/dist/{scope.js → sharing/scope.js} +1 -1
- package/dist/{shared.d.ts → sharing/shared.d.ts} +10 -9
- package/dist/{shared.js → sharing/shared.js} +100 -77
- package/dist/{ambient-store.d.ts → store/ambient.d.ts} +2 -2
- package/dist/{ambient-store.js → store/ambient.js} +10 -10
- package/dist/store/audit-event.d.ts +12 -6
- package/dist/store/audit-event.js +6 -5
- package/dist/{audit.d.ts → store/audit.d.ts} +27 -3
- package/dist/{audit.js → store/audit.js} +91 -6
- package/dist/{auth.d.ts → store/auth.d.ts} +15 -32
- package/dist/{auth.js → store/auth.js} +100 -92
- package/dist/store/candidates.d.ts +23 -12
- package/dist/store/candidates.js +87 -35
- package/dist/{card-detail.d.ts → store/card-detail.d.ts} +3 -3
- package/dist/{card-detail.js → store/card-detail.js} +1 -1
- package/dist/{store-cards.d.ts → store/cards.d.ts} +14 -9
- package/dist/{store-cards.js → store/cards.js} +85 -146
- package/dist/store/compactions.d.ts +78 -0
- package/dist/store/compactions.js +93 -0
- package/dist/store/conflicts.d.ts +22 -5
- package/dist/store/conflicts.js +160 -109
- package/dist/store/connectors/github.d.ts +84 -0
- package/dist/store/connectors/github.js +180 -0
- package/dist/store/connectors/slack.d.ts +69 -0
- package/dist/store/connectors/slack.js +177 -0
- package/dist/store/dashboard-reads.d.ts +27 -0
- package/dist/store/dashboard-reads.js +92 -0
- package/dist/store/delete-and-batch.d.ts +20 -24
- package/dist/store/delete-and-batch.js +64 -40
- package/dist/{delivery-recorder.d.ts → store/delivery-recorder.d.ts} +12 -5
- package/dist/{delivery-recorder.js → store/delivery-recorder.js} +42 -30
- package/dist/store/descendant-page.d.ts +12 -0
- package/dist/store/descendant-page.js +99 -0
- package/dist/store/diagnostics.d.ts +47 -0
- package/dist/store/diagnostics.js +51 -0
- package/dist/store/doctor-reads.d.ts +16 -0
- package/dist/store/doctor-reads.js +19 -0
- package/dist/{dormant.d.ts → store/dormant.d.ts} +46 -12
- package/dist/{dormant.js → store/dormant.js} +151 -6
- package/dist/{embeddings.d.ts → store/embeddings/index.d.ts} +10 -6
- package/dist/{embeddings.js → store/embeddings/index.js} +60 -44
- package/dist/{local-embedding.d.ts → store/embeddings/local.d.ts} +1 -1
- package/dist/{local-embedding.js → store/embeddings/local.js} +68 -57
- package/dist/{embedding-provider.d.ts → store/embeddings/provider.d.ts} +2 -2
- package/dist/{embedding-provider.js → store/embeddings/provider.js} +47 -32
- package/dist/store/entry-reads.d.ts +46 -7
- package/dist/store/entry-reads.js +120 -21
- package/dist/store/entry-row.d.ts +8 -2
- package/dist/store/entry-row.js +28 -8
- package/dist/store/entry-writes.d.ts +33 -4
- package/dist/store/entry-writes.js +108 -26
- package/dist/{failure-log.d.ts → store/failure-log.d.ts} +7 -2
- package/dist/{failure-log.js → store/failure-log.js} +9 -2
- package/dist/{goals.d.ts → store/goals.d.ts} +6 -46
- package/dist/{goals.js → store/goals.js} +45 -94
- package/dist/store/graph-queue.d.ts +29 -0
- package/dist/store/graph-queue.js +101 -0
- package/dist/{graph/read.d.ts → store/graph-reads.d.ts} +26 -34
- package/dist/{graph/read.js → store/graph-reads.js} +63 -115
- package/dist/{graph/types.d.ts → store/graph-rows.d.ts} +68 -8
- package/dist/{graph/rows.js → store/graph-rows.js} +14 -3
- package/dist/store/graph-view-rows.d.ts +12 -0
- package/dist/store/graph-view-rows.js +67 -0
- package/dist/store/graph-writes.d.ts +58 -0
- package/dist/store/graph-writes.js +256 -0
- package/dist/store/half-life.d.ts +34 -0
- package/dist/store/half-life.js +77 -0
- package/dist/store/handoffs.d.ts +6 -3
- package/dist/store/handoffs.js +70 -31
- package/dist/store/index-and-stats.d.ts +8 -1
- package/dist/store/index-and-stats.js +51 -48
- package/dist/store/index.d.ts +4 -0
- package/dist/store/index.js +3 -0
- package/dist/store/key-audit.d.ts +2 -2
- package/dist/store/key-audit.js +4 -4
- package/dist/store/key-writes.d.ts +12 -5
- package/dist/store/key-writes.js +30 -4
- package/dist/store/ledger-turn.d.ts +17 -0
- package/dist/store/ledger-turn.js +27 -0
- package/dist/store/markdown.d.ts +1 -1
- package/dist/store/markdown.js +4 -3
- package/dist/store/mirrors.d.ts +5 -7
- package/dist/store/mirrors.js +39 -25
- package/dist/store/object-types.d.ts +189 -0
- package/dist/store/object-types.js +4 -0
- package/dist/store/open.d.ts +8 -4
- package/dist/store/open.js +34 -23
- package/dist/store/planning-fallacy-evidence.d.ts +42 -0
- package/dist/store/planning-fallacy-evidence.js +81 -0
- package/dist/store/port.d.ts +646 -0
- package/dist/store/port.js +17 -0
- package/dist/{predictions/store.d.ts → store/predictions.d.ts} +15 -2
- package/dist/{predictions/store.js → store/predictions.js} +52 -67
- package/dist/{quarantine.d.ts → store/quarantine.d.ts} +8 -8
- package/dist/{quarantine.js → store/quarantine.js} +64 -22
- package/dist/{raw-archive.d.ts → store/raw-archive.d.ts} +5 -3
- package/dist/{raw-archive.js → store/raw-archive.js} +11 -5
- package/dist/{recall-scope.d.ts → store/recall-scope.d.ts} +4 -7
- package/dist/{recall-scope.js → store/recall-scope.js} +8 -9
- package/dist/{recall-trace.d.ts → store/recall-trace.d.ts} +13 -14
- package/dist/{recall-trace.js → store/recall-trace.js} +38 -43
- package/dist/store/rejected-values.d.ts +55 -0
- package/dist/store/rejected-values.js +162 -0
- package/dist/{rejection.d.ts → store/rejection.d.ts} +2 -2
- package/dist/{rejection.js → store/rejection.js} +3 -2
- package/dist/store/rows.d.ts +2 -3
- package/dist/store/rows.js +18 -11
- package/dist/store/search-rows.d.ts +15 -4
- package/dist/store/search-rows.js +43 -36
- package/dist/store/sessions.d.ts +18 -2
- package/dist/store/sessions.js +83 -46
- package/dist/store/sqlite/commit-watch.d.ts +4 -0
- package/dist/store/sqlite/commit-watch.js +29 -0
- package/dist/store/sqlite/connector-events-group.d.ts +5 -0
- package/dist/store/sqlite/connector-events-group.js +50 -0
- package/dist/store/sqlite/connector-writes-group.d.ts +6 -0
- package/dist/store/sqlite/connector-writes-group.js +65 -0
- package/dist/store/sqlite/dag-reads-group.d.ts +3 -0
- package/dist/store/sqlite/dag-reads-group.js +45 -0
- package/dist/store/sqlite/entry-writes-group.d.ts +18 -0
- package/dist/store/sqlite/entry-writes-group.js +170 -0
- package/dist/store/sqlite/error-codec.d.ts +17 -0
- package/dist/store/sqlite/error-codec.js +59 -0
- package/dist/store/sqlite/executor-counts.d.ts +10 -0
- package/dist/store/sqlite/executor-counts.js +11 -0
- package/dist/store/sqlite/executor.d.ts +28 -0
- package/dist/store/sqlite/executor.js +286 -0
- package/dist/store/sqlite/graph-reads-group.d.ts +5 -0
- package/dist/store/sqlite/graph-reads-group.js +18 -0
- package/dist/store/sqlite/local.d.ts +21 -0
- package/dist/store/sqlite/local.js +38 -0
- package/dist/store/sqlite/object-rows.d.ts +102 -0
- package/dist/store/sqlite/object-rows.js +218 -0
- package/dist/store/sqlite/objects-group.d.ts +20 -0
- package/dist/store/sqlite/objects-group.js +314 -0
- package/dist/store/sqlite/predictions-group.d.ts +5 -0
- package/dist/store/sqlite/predictions-group.js +28 -0
- package/dist/store/sqlite/quarantine-group.d.ts +5 -0
- package/dist/store/sqlite/quarantine-group.js +38 -0
- package/dist/store/sqlite/store.d.ts +26 -0
- package/dist/store/sqlite/store.js +295 -0
- package/dist/store/sqlite/vector-pack.d.ts +18 -0
- package/dist/store/sqlite/vector-pack.js +46 -0
- package/dist/store/sqlite/vector-reads-group.d.ts +3 -0
- package/dist/store/sqlite/vector-reads-group.js +23 -0
- package/dist/store/sqlite/worker-entry.d.ts +2 -0
- package/dist/store/sqlite/worker-entry.js +8 -0
- package/dist/store/sqlite/worker-jobs.d.ts +5 -0
- package/dist/store/sqlite/worker-jobs.js +116 -0
- package/dist/store/sqlite/worker-ops.d.ts +124 -0
- package/dist/store/sqlite/worker-ops.js +82 -0
- package/dist/store/sqlite/worker-store.d.ts +8 -0
- package/dist/store/sqlite/worker-store.js +76 -0
- package/dist/store/summaries.d.ts +2 -11
- package/dist/store/summaries.js +17 -44
- package/dist/{summary-dirty.d.ts → store/summary-dirty.d.ts} +1 -1
- package/dist/store/tenant-lookup.d.ts +1 -1
- package/dist/{tenant.d.ts → store/tenant.d.ts} +2 -2
- package/dist/{tenant.js → store/tenant.js} +1 -1
- package/dist/store/token-ledger-rows.d.ts +61 -0
- package/dist/store/token-ledger-rows.js +68 -0
- package/dist/{token-ledger.d.ts → store/token-ledger.d.ts} +2 -9
- package/dist/{token-ledger.js → store/token-ledger.js} +31 -78
- package/dist/store/tombstone-checks.d.ts +12 -0
- package/dist/store/tombstone-checks.js +31 -0
- package/dist/store/usage-reports.d.ts +7 -0
- package/dist/store/usage-reports.js +26 -0
- package/dist/store/vector-writes.d.ts +10 -3
- package/dist/store/vector-writes.js +35 -5
- package/dist/{working-memory.d.ts → store/working-memory.d.ts} +5 -1
- package/dist/{working-memory.js → store/working-memory.js} +39 -41
- package/dist/support-bundle.d.ts +1 -1
- package/dist/support-bundle.js +13 -33
- package/dist/{gated-write.d.ts → trust/gated-write.d.ts} +2 -2
- package/dist/{gated-write.js → trust/gated-write.js} +6 -6
- package/dist/trust/quarantine.d.ts +4 -0
- package/dist/trust/quarantine.js +8 -0
- package/dist/trust/reject-flow.d.ts +23 -0
- package/dist/trust/reject-flow.js +67 -0
- package/dist/util/anthropic-messages.d.ts +31 -0
- package/dist/util/anthropic-messages.js +46 -0
- package/dist/util/atomic-write.d.ts +3 -0
- package/dist/util/atomic-write.js +107 -0
- package/dist/util/crash-handlers.d.ts +5 -0
- package/dist/util/crash-handlers.js +30 -0
- package/dist/{env.d.ts → util/env.d.ts} +17 -2
- package/dist/{env.js → util/env.js} +22 -2
- package/dist/util/home-path.js +67 -0
- package/dist/{http-retry.d.ts → util/http-retry.d.ts} +6 -2
- package/dist/{http-retry.js → util/http-retry.js} +38 -7
- package/dist/{http-util.d.ts → util/http-util.d.ts} +14 -3
- package/dist/{http-util.js → util/http-util.js} +31 -11
- package/dist/util/json.d.ts +17 -0
- package/dist/util/json.js +25 -0
- package/dist/{log.d.ts → util/log.d.ts} +5 -2
- package/dist/{log.js → util/log.js} +12 -3
- package/dist/util/real-path.d.ts +3 -0
- package/dist/util/real-path.js +15 -0
- package/dist/util/request-scope.d.ts +27 -0
- package/dist/util/request-scope.js +47 -0
- package/dist/{same-text.d.ts → util/same-text.d.ts} +1 -1
- package/dist/{secret-detect.js → util/secret-detect.js} +5 -4
- package/dist/util/stored-json.d.ts +9 -0
- package/dist/util/stored-json.js +8 -0
- package/dist/util/time.d.ts +2 -0
- package/dist/util/time.js +3 -0
- package/dist/util/token-text.d.ts +18 -0
- package/dist/util/token-text.js +23 -0
- package/dist/{version.d.ts → util/version.d.ts} +1 -1
- package/dist/{version.js → util/version.js} +1 -1
- package/extensions/openclaw-plugin/index.ts +1 -5
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/dist/api.d.ts +0 -26
- package/dist/api.js +0 -29
- package/dist/capture-contract.js +0 -49
- package/dist/connectors/github/idempotency.d.ts +0 -19
- package/dist/connectors/github/idempotency.js +0 -27
- package/dist/connectors/slack/idempotency.d.ts +0 -17
- package/dist/connectors/slack/idempotency.js +0 -31
- package/dist/customer-notes.js +0 -336
- package/dist/db.d.ts +0 -9
- package/dist/db.js +0 -8
- package/dist/decisions.js +0 -326
- package/dist/extract.js +0 -133
- package/dist/graph/rows.d.ts +0 -45
- package/dist/graph/types.js +0 -11
- package/dist/half-life-migration.js +0 -182
- package/dist/handoff.js +0 -68
- package/dist/home-path.js +0 -24
- package/dist/incidents.js +0 -349
- package/dist/instruction-detect.js +0 -27
- package/dist/json.d.ts +0 -7
- package/dist/json.js +0 -11
- package/dist/ledger-db.d.ts +0 -10
- package/dist/ledger-db.js +0 -42
- package/dist/policies.js +0 -434
- package/dist/processes.js +0 -371
- package/dist/project-briefs.js +0 -523
- package/dist/reject-flow.d.ts +0 -69
- package/dist/reject-flow.js +0 -260
- package/dist/session-owners.d.ts +0 -7
- package/dist/session-owners.js +0 -54
- package/dist/skills.js +0 -367
- package/dist/store-port.d.ts +0 -191
- package/dist/store-port.js +0 -166
- /package/dist/{context-auto.d.ts → api/context-auto.d.ts} +0 -0
- /package/dist/{instruction-detect.d.ts → api/instruction-detect.d.ts} +0 -0
- /package/dist/{recall-history.d.ts → api/recall-history.d.ts} +0 -0
- /package/dist/{codex-patch.d.ts → capture/codex-patch.d.ts} +0 -0
- /package/dist/{compaction-items.d.ts → capture/compaction-items.d.ts} +0 -0
- /package/dist/{compaction-spool.d.ts → capture/compaction-spool.d.ts} +0 -0
- /package/dist/{share-scrub.d.ts → capture/share-scrub.d.ts} +0 -0
- /package/dist/{correction-latency.js → cli/correction-latency.js} +0 -0
- /package/dist/{provenance-coverage.js → cli/provenance-coverage.js} +0 -0
- /package/dist/{quality-repair.d.ts → cli/quality-repair.d.ts} +0 -0
- /package/dist/{stdin.d.ts → cli/stdin.d.ts} +0 -0
- /package/dist/{dedupe.d.ts → consolidate/dedupe.d.ts} +0 -0
- /package/dist/{memory-value-weights.d.ts → consolidate/memory-value-weights.d.ts} +0 -0
- /package/dist/{memory-value-weights.js → consolidate/memory-value-weights.js} +0 -0
- /package/dist/{overlap-index.d.ts → consolidate/overlap-index.d.ts} +0 -0
- /package/dist/{overlap-index.js → consolidate/overlap-index.js} +0 -0
- /package/dist/{trace.d.ts → consolidate/trace.d.ts} +0 -0
- /package/dist/{ablation.d.ts → core/ablation.d.ts} +0 -0
- /package/dist/{ambient.d.ts → core/ambient.d.ts} +0 -0
- /package/dist/{api-errors.d.ts → core/api-errors.d.ts} +0 -0
- /package/dist/{api-errors.js → core/api-errors.js} +0 -0
- /package/dist/{card.d.ts → core/card.d.ts} +0 -0
- /package/dist/{card.js → core/card.js} +0 -0
- /package/dist/{handoff.d.ts → core/handoff.d.ts} +0 -0
- /package/dist/{memory-quality.d.ts → core/memory-quality.d.ts} +0 -0
- /package/dist/{physics-config.d.ts → core/physics-config.d.ts} +0 -0
- /package/dist/{physics-config.js → core/physics-config.js} +0 -0
- /package/dist/{project-remote.d.ts → core/project-remote.d.ts} +0 -0
- /package/dist/{salience.d.ts → core/salience.d.ts} +0 -0
- /package/dist/{dashboard-params.d.ts → dashboard/dashboard-params.d.ts} +0 -0
- /package/dist/{dashboard-params.js → dashboard/dashboard-params.js} +0 -0
- /package/dist/{dashboard-types.d.ts → dashboard/dashboard-types.d.ts} +0 -0
- /package/dist/{dashboard-types.js → dashboard/dashboard-types.js} +0 -0
- /package/dist/{dashboard.d.ts → dashboard/dashboard.d.ts} +0 -0
- /package/dist/{eval-stats.d.ts → eval/eval-stats.d.ts} +0 -0
- /package/dist/{cli → hooks}/hook-blocks.d.ts +0 -0
- /package/dist/{path-context.d.ts → search/path-context.d.ts} +0 -0
- /package/dist/{rrf.d.ts → search/rrf.d.ts} +0 -0
- /package/dist/{rrf.js → search/rrf.js} +0 -0
- /package/dist/{rate-limit.d.ts → server/rate-limit.d.ts} +0 -0
- /package/dist/{rate-limit.js → server/rate-limit.js} +0 -0
- /package/dist/{server-detect.d.ts → server/server-detect.d.ts} +0 -0
- /package/dist/{scope.d.ts → sharing/scope.d.ts} +0 -0
- /package/dist/{summary-dirty.js → store/summary-dirty.js} +0 -0
- /package/dist/{yaml.d.ts → store/yaml.d.ts} +0 -0
- /package/dist/{yaml.js → store/yaml.js} +0 -0
- /package/dist/{escape.d.ts → util/escape.d.ts} +0 -0
- /package/dist/{escape.js → util/escape.js} +0 -0
- /package/dist/{home-path.d.ts → util/home-path.d.ts} +0 -0
- /package/dist/{keyset.d.ts → util/keyset.d.ts} +0 -0
- /package/dist/{keyset.js → util/keyset.js} +0 -0
- /package/dist/{same-text.js → util/same-text.js} +0 -0
- /package/dist/{secret-detect.d.ts → util/secret-detect.d.ts} +0 -0
- /package/dist/{db → util}/sqlite-blocked.d.ts +0 -0
- /package/dist/{db → util}/sqlite-blocked.js +0 -0
- /package/dist/{tokenize.d.ts → util/tokenize.d.ts} +0 -0
- /package/dist/{tokenize.js → util/tokenize.js} +0 -0
- /package/dist/{transcript-tail.d.ts → util/transcript-tail.d.ts} +0 -0
- /package/dist/{transcript-tail.js → util/transcript-tail.js} +0 -0
- /package/dist/{write-budget.d.ts → util/write-budget.d.ts} +0 -0
- /package/dist/{write-budget.js → util/write-budget.js} +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { IN_LIST_CHUNK, loadEntities, loadEntitiesByIds, loadEntitiesByName, loadNeighborRelations, loadRelations, loadRelationsAmong } from './graph-reads.js';
|
|
2
|
+
/** The items whose source memory `canRead` admits: a NULL memoryId has no scope to hide, and a missing memory fails closed. */
|
|
3
|
+
function readableOnly(db, tenantId, items, canRead) {
|
|
4
|
+
if (!canRead)
|
|
5
|
+
return items;
|
|
6
|
+
const ids = [...new Set(items.flatMap((i) => (i.memoryId === null ? [] : [i.memoryId])))];
|
|
7
|
+
const readable = new Set();
|
|
8
|
+
for (let i = 0; i < ids.length; i += IN_LIST_CHUNK) {
|
|
9
|
+
const slice = ids.slice(i, i + IN_LIST_CHUNK);
|
|
10
|
+
// SAFETY: rows' shape matches the id and scope columns named in the SELECT.
|
|
11
|
+
const rows = db.prepare(`SELECT id, scope FROM memories WHERE +tenant_id = ? AND id IN (${slice.map(() => '?').join(',')})`)
|
|
12
|
+
.all(tenantId, ...slice);
|
|
13
|
+
for (const r of rows)
|
|
14
|
+
if (canRead(r.scope))
|
|
15
|
+
readable.add(r.id);
|
|
16
|
+
}
|
|
17
|
+
return items.filter((i) => i.memoryId === null || readable.has(i.memoryId));
|
|
18
|
+
}
|
|
19
|
+
function wholeGraphRows({ hippoRoot, db, tenantId }, limit) {
|
|
20
|
+
const entities = loadEntities(hippoRoot, tenantId, { limit }, db);
|
|
21
|
+
const relations = loadRelations(hippoRoot, tenantId, { limit }, db);
|
|
22
|
+
return { entities, relations, truncated: entities.length >= limit || relations.length >= limit };
|
|
23
|
+
}
|
|
24
|
+
/** The named entities with their 1-hop neighbours and the edges among that union; null when the caller may read none of the named ones. */
|
|
25
|
+
function focusRows({ hippoRoot, db, tenantId }, name, limit, canRead) {
|
|
26
|
+
// The name is queried directly, so it is found on a graph larger than `limit`; one name can map to many entities, so the matches are capped.
|
|
27
|
+
const named = loadEntitiesByName(hippoRoot, tenantId, name, { limit }, db);
|
|
28
|
+
// A hidden focus must not answer through its neighbours that the name exists.
|
|
29
|
+
const focus = readableOnly(db, tenantId, named, canRead);
|
|
30
|
+
if (focus.length === 0)
|
|
31
|
+
return null;
|
|
32
|
+
const focusIds = focus.map((e) => e.id);
|
|
33
|
+
const hop = loadNeighborRelations(hippoRoot, tenantId, focusIds, { limit }, db);
|
|
34
|
+
const union = new Set(focusIds);
|
|
35
|
+
let neighboursCapped = false;
|
|
36
|
+
for (const r of hop) {
|
|
37
|
+
if (union.size >= limit) {
|
|
38
|
+
neighboursCapped = true; // node cap filled before all neighbours were added
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
union.add(r.fromEntityId);
|
|
42
|
+
union.add(r.toEntityId);
|
|
43
|
+
}
|
|
44
|
+
const unionIds = [...union].slice(0, limit);
|
|
45
|
+
const entities = loadEntitiesByIds(hippoRoot, tenantId, unionIds, db);
|
|
46
|
+
// Both endpoints in the set: neighbour-to-neighbour edges are included, and the LIMIT never drops one for an out-of-union row.
|
|
47
|
+
const relations = loadRelationsAmong(hippoRoot, tenantId, unionIds, { limit }, db);
|
|
48
|
+
const truncated = named.length >= limit ||
|
|
49
|
+
hop.length >= limit || // neighbour scan capped -> a 1-hop neighbour may be omitted
|
|
50
|
+
neighboursCapped || // node cap filled before all neighbours were consumed
|
|
51
|
+
union.size > unionIds.length ||
|
|
52
|
+
relations.length >= limit;
|
|
53
|
+
return { entities, relations, truncated };
|
|
54
|
+
}
|
|
55
|
+
/** What `GraphReads.graphRows` answers, read on `db`: the caller opens the one snapshot that keeps entity ids and relation ids from two different rebuilds apart. */
|
|
56
|
+
export function graphViewRows(hippoRoot, db, tenantId, spec) {
|
|
57
|
+
const source = { hippoRoot, db, tenantId };
|
|
58
|
+
const raw = spec.entity !== undefined ? focusRows(source, spec.entity, spec.limit, spec.canRead) : wholeGraphRows(source, spec.limit);
|
|
59
|
+
if (raw === null)
|
|
60
|
+
return { entities: [], relations: [], truncated: false };
|
|
61
|
+
return {
|
|
62
|
+
entities: readableOnly(db, tenantId, raw.entities, spec.canRead),
|
|
63
|
+
relations: readableOnly(db, tenantId, raw.relations, spec.canRead),
|
|
64
|
+
truncated: raw.truncated,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=graph-view-rows.js.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type DatabaseSyncLike } from '../db/index.js';
|
|
2
|
+
import { type EntityType, type RelationType, type SourceKind, type SourceObjectType, type SourceObjectRef, type Entity, type Relation, type InsertEntityOpts, type InsertRelationOpts, type UpdateEntityOpts } from './graph-rows.js';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the `source_kind` for a graph row from AT LEAST ONE valid provenance path,
|
|
5
|
+
* with the no-raw invariant intact. The code-level mirror of the DB trigger guard (the
|
|
6
|
+
* trigger is the unbypassable backstop). Two paths:
|
|
7
|
+
* - MEMORY path (`memoryId` not null): the memory must exist, be same-tenant, and be
|
|
8
|
+
* consolidated (distilled/superseded); raw is rejected. Returns its kind.
|
|
9
|
+
* - OBJECT path (`memoryId` null, `sourceObject` set): the object row must exist, be
|
|
10
|
+
* same-tenant, and have status active|superseded (4-way per object table). Objects are
|
|
11
|
+
* consolidated BY CONSTRUCTION, so this returns 'distilled'.
|
|
12
|
+
* All-null (no memory AND no source object) is rejected.
|
|
13
|
+
*/
|
|
14
|
+
interface ResolvedGraphSource {
|
|
15
|
+
sourceKind: SourceKind;
|
|
16
|
+
memoryId: string | null;
|
|
17
|
+
}
|
|
18
|
+
export declare function resolveConsolidatedSource(db: DatabaseSyncLike, tenantId: string, memoryId: string | null, sourceObject: SourceObjectRef | null, label: string): ResolvedGraphSource;
|
|
19
|
+
/**
|
|
20
|
+
* Insert a graph entity extracted from a consolidated memory. Throws if the source
|
|
21
|
+
* memory is missing / cross-tenant / raw (the DB trigger is the backstop).
|
|
22
|
+
*/
|
|
23
|
+
export declare function insertEntity(hippoRoot: string, tenantId: string, opts: InsertEntityOpts, txDb?: DatabaseSyncLike): Entity;
|
|
24
|
+
/** Renames an entity or moves its memory provenance in place, keeping id and created_at; null when the row is gone.
|
|
25
|
+
* A delete plus an insert would cascade away every relation that points at it. */
|
|
26
|
+
export declare function updateEntity(hippoRoot: string, tenantId: string, id: number, opts: UpdateEntityOpts, txDb?: DatabaseSyncLike): Entity | null;
|
|
27
|
+
/**
|
|
28
|
+
* Insert a graph relation between two entities, sourced from a consolidated memory.
|
|
29
|
+
* Both entities must exist in the same tenant; the source memory must be consolidated.
|
|
30
|
+
*/
|
|
31
|
+
export declare function insertRelation(hippoRoot: string, tenantId: string, opts: InsertRelationOpts, txDb?: DatabaseSyncLike): Relation;
|
|
32
|
+
/** The source object still holds the loader's rule (active or superseded); a closed or gone one gets no new graph row. */
|
|
33
|
+
export declare function objectInForce(db: DatabaseSyncLike, tenantId: string, ref: SourceObjectRef): boolean;
|
|
34
|
+
/** The lowest-id entity of this type anchored to the source object, which is the row a rebuild keeps. */
|
|
35
|
+
export declare function entityIdBySource(db: DatabaseSyncLike, tenantId: string, entityType: EntityType, sourceObject: SourceObjectRef): number | undefined;
|
|
36
|
+
export declare function relationPresent(db: DatabaseSyncLike, tenantId: string, fromEntityId: number, toEntityId: number, relType: RelationType): boolean;
|
|
37
|
+
export declare function deleteEntityRow(db: DatabaseSyncLike, tenantId: string, id: number): void;
|
|
38
|
+
export declare function deleteRelationRow(db: DatabaseSyncLike, tenantId: string, id: number): void;
|
|
39
|
+
/** Runs one tenant's graph writes in `fn` on `txDb` under one BEGIN IMMEDIATE, so two rebuilds serialize instead of
|
|
40
|
+
* interleaving and a throw rolls back the whole chunk. The sole sanctioned place to wrap graph writes in a transaction. */
|
|
41
|
+
export declare function runGraphRebuildTransaction<T>(hippoRoot: string, tenantId: string, fn: (txDb: DatabaseSyncLike) => T, opts?: {
|
|
42
|
+
busyWaitMs?: number;
|
|
43
|
+
}): T;
|
|
44
|
+
/**
|
|
45
|
+
* Remove the graph rows sourced from one first-class object, by its (type, id). Used when a
|
|
46
|
+
* MIRRORLESS object is closed: it has no mirror memory, so `markGraphDirty` cannot
|
|
47
|
+
* enqueue a rebuild (the queue is memory-keyed). Closing must still drop the object's
|
|
48
|
+
* now-stale entity + edges from the graph, so we remove them directly here. Fail-soft
|
|
49
|
+
* like `markGraphDirty` (never throws into the object close caller; graph staleness is
|
|
50
|
+
* recoverable). Deleting the entity cascade-deletes any relation where it is an endpoint
|
|
51
|
+
* (relations FK entities ON DELETE CASCADE); the explicit relations DELETE also covers a
|
|
52
|
+
* relation whose OWN provenance is this object (defensive — every such edge has the object
|
|
53
|
+
* as an endpoint today, so the cascade already covers it). DELETE fires no BEFORE
|
|
54
|
+
* INSERT/UPDATE guard trigger.
|
|
55
|
+
*/
|
|
56
|
+
export declare function removeGraphEntitiesForObject(hippoRoot: string, tenantId: string, sourceObjectType: SourceObjectType, sourceObjectId: number): void;
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=graph-writes.d.ts.map
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
// The writer of the entities and relations tables. Every row resolves a consolidated source first, never a raw memory;
|
|
2
|
+
// the schema triggers are the backstop for a write that skips this module.
|
|
3
|
+
import { openHippoDb, closeHippoDb, withWriteScope } from '../db/index.js';
|
|
4
|
+
import { assertTenantId } from './tenant.js';
|
|
5
|
+
import { errorMessage, log } from '../util/log.js';
|
|
6
|
+
import { GRAPH_ENTITY_TYPES, GRAPH_RELATION_TYPES, MAX_ENTITY_NAME_LEN, rowToEntity, rowToRelation, ENTITY_COLS, RELATION_COLS } from './graph-rows.js';
|
|
7
|
+
const SOURCE_OBJECT_TABLE = {
|
|
8
|
+
decision: 'decisions',
|
|
9
|
+
policy: 'policies',
|
|
10
|
+
customer: 'customer_notes',
|
|
11
|
+
project: 'project_briefs',
|
|
12
|
+
};
|
|
13
|
+
export function resolveConsolidatedSource(db, tenantId, memoryId, sourceObject, label) {
|
|
14
|
+
const { memKind, effectiveMemoryId } = checkSourceMemory(db, tenantId, memoryId, sourceObject, label);
|
|
15
|
+
assertSourceObjectUsable(db, tenantId, sourceObject, label);
|
|
16
|
+
// source_kind is the memory's kind when a memory is present, else 'distilled' for an
|
|
17
|
+
// object-only row (objects are consolidated by construction). All-null is rejected.
|
|
18
|
+
if (memKind != null)
|
|
19
|
+
return { sourceKind: memKind, memoryId: effectiveMemoryId };
|
|
20
|
+
if (sourceObject != null)
|
|
21
|
+
return { sourceKind: 'distilled', memoryId: null };
|
|
22
|
+
throw new Error(`${label}: graph row needs a memory or a source object`);
|
|
23
|
+
}
|
|
24
|
+
function checkSourceMemory(db, tenantId, memoryId, sourceObject, label) {
|
|
25
|
+
let memKind = null;
|
|
26
|
+
let effectiveMemoryId = memoryId;
|
|
27
|
+
if (memoryId != null) {
|
|
28
|
+
// SAFETY: row's shape matches the two columns (kind, tenant_id) named in
|
|
29
|
+
// the SELECT above.
|
|
30
|
+
const row = db.prepare(`SELECT kind, tenant_id FROM memories WHERE id = ?`).get(memoryId);
|
|
31
|
+
if (!row) {
|
|
32
|
+
// Stale / forgotten mirror. Tolerate it IFF a valid source object provides provenance:
|
|
33
|
+
// graph-extract reads object rows then inserts, and a mirror forgotten/pruned in that window
|
|
34
|
+
// must NOT roll back the whole tenant rebuild - the active object survives mirror loss.
|
|
35
|
+
// Anchor to the object; drop the dead memory pointer.
|
|
36
|
+
if (sourceObject == null) {
|
|
37
|
+
throw new Error(`${label}: source memory ${memoryId} not found`);
|
|
38
|
+
}
|
|
39
|
+
effectiveMemoryId = null;
|
|
40
|
+
}
|
|
41
|
+
else if (row.tenant_id !== tenantId) {
|
|
42
|
+
throw new Error(`${label}: source memory ${memoryId} belongs to another tenant`);
|
|
43
|
+
}
|
|
44
|
+
else if (row.kind === 'raw') {
|
|
45
|
+
throw new Error(`${label}: source memory ${memoryId} is raw; the graph indexes consolidated state only`);
|
|
46
|
+
}
|
|
47
|
+
else if (row.kind !== 'distilled' && row.kind !== 'superseded') {
|
|
48
|
+
throw new Error(`${label}: source memory ${memoryId} has unsupported kind '${row.kind}'`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
memKind = row.kind;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { memKind, effectiveMemoryId };
|
|
55
|
+
}
|
|
56
|
+
function assertSourceObjectUsable(db, tenantId, sourceObject, label) {
|
|
57
|
+
// Validate the object pointer WHENEVER it is provided, not only when memory is null:
|
|
58
|
+
// a dual-set row whose object is wrong/closed/cross-tenant would become
|
|
59
|
+
// the active provenance after ON DELETE SET NULL and could then block the memory delete.
|
|
60
|
+
if (sourceObject != null) {
|
|
61
|
+
const table = SOURCE_OBJECT_TABLE[sourceObject.type];
|
|
62
|
+
if (!table) {
|
|
63
|
+
throw new Error(`${label}: unsupported source_object_type '${sourceObject.type}'`);
|
|
64
|
+
}
|
|
65
|
+
// `table` is a fixed value from the SOURCE_OBJECT_TABLE map (never user-supplied), so
|
|
66
|
+
// this string interpolation is safe; `id`/`tenant_id` stay parametrized.
|
|
67
|
+
// SAFETY: row's shape matches the single `status` column named in the
|
|
68
|
+
// SELECT above.
|
|
69
|
+
const row = db.prepare(`SELECT status FROM ${table} WHERE id = ? AND tenant_id = ?`).get(sourceObject.id, tenantId);
|
|
70
|
+
if (!row) {
|
|
71
|
+
throw new Error(`${label}: source ${sourceObject.type} ${sourceObject.id} not found for tenant ${tenantId}`);
|
|
72
|
+
}
|
|
73
|
+
if (row.status !== 'active' && row.status !== 'superseded') {
|
|
74
|
+
throw new Error(`${label}: source ${sourceObject.type} ${sourceObject.id} has status '${row.status}' (must be active|superseded)`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Insert a graph entity extracted from a consolidated memory. Throws if the source
|
|
80
|
+
* memory is missing / cross-tenant / raw (the DB trigger is the backstop).
|
|
81
|
+
*/
|
|
82
|
+
export function insertEntity(hippoRoot, tenantId, opts, txDb) {
|
|
83
|
+
assertTenantId('insertEntity', tenantId);
|
|
84
|
+
if (!GRAPH_ENTITY_TYPES.has(opts.entityType)) {
|
|
85
|
+
throw new Error(`insertEntity: entityType must be one of ${Array.from(GRAPH_ENTITY_TYPES).join('|')}; got ${opts.entityType}`);
|
|
86
|
+
}
|
|
87
|
+
const name = checkedName('insertEntity', opts.name);
|
|
88
|
+
const now = new Date().toISOString();
|
|
89
|
+
const memoryId = opts.memoryId ?? null;
|
|
90
|
+
const sourceObject = opts.sourceObject ?? null;
|
|
91
|
+
const ownDb = txDb ? null : openHippoDb(hippoRoot);
|
|
92
|
+
const db = txDb ?? ownDb;
|
|
93
|
+
try {
|
|
94
|
+
const { sourceKind, memoryId: effectiveMemoryId } = resolveConsolidatedSource(db, tenantId, memoryId, sourceObject, 'insertEntity');
|
|
95
|
+
const result = db.prepare(`
|
|
96
|
+
INSERT INTO entities(tenant_id, entity_type, name, memory_id, source_kind, source_object_type, source_object_id, created_at)
|
|
97
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
98
|
+
`).run(tenantId, opts.entityType, name, effectiveMemoryId, sourceKind, sourceObject?.type ?? null, sourceObject?.id ?? null, now);
|
|
99
|
+
const id = Number(result.lastInsertRowid ?? 0);
|
|
100
|
+
// SAFETY: row's shape matches the columns named in ENTITY_COLS above.
|
|
101
|
+
const row = db.prepare(`SELECT ${ENTITY_COLS} FROM entities WHERE id = ?`).get(id);
|
|
102
|
+
if (!row)
|
|
103
|
+
throw new Error('insertEntity: failed to reload inserted entity');
|
|
104
|
+
return rowToEntity(row);
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
if (ownDb)
|
|
108
|
+
closeHippoDb(ownDb);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function checkedName(label, raw) {
|
|
112
|
+
const name = (raw ?? '').trim();
|
|
113
|
+
if (name.length === 0)
|
|
114
|
+
throw new Error(`${label}: name is required`);
|
|
115
|
+
if (name.length > MAX_ENTITY_NAME_LEN) {
|
|
116
|
+
throw new Error(`${label}: name exceeds the ${MAX_ENTITY_NAME_LEN}-char cap`);
|
|
117
|
+
}
|
|
118
|
+
return name;
|
|
119
|
+
}
|
|
120
|
+
/** Renames an entity or moves its memory provenance in place, keeping id and created_at; null when the row is gone.
|
|
121
|
+
* A delete plus an insert would cascade away every relation that points at it. */
|
|
122
|
+
export function updateEntity(hippoRoot, tenantId, id, opts, txDb) {
|
|
123
|
+
assertTenantId('updateEntity', tenantId);
|
|
124
|
+
const name = checkedName('updateEntity', opts.name);
|
|
125
|
+
const db = txDb ?? openHippoDb(hippoRoot);
|
|
126
|
+
try {
|
|
127
|
+
// SAFETY: row's shape matches the columns named in ENTITY_COLS above.
|
|
128
|
+
const row = db.prepare(`SELECT ${ENTITY_COLS} FROM entities WHERE id = ? AND tenant_id = ?`).get(id, tenantId);
|
|
129
|
+
if (!row)
|
|
130
|
+
return null;
|
|
131
|
+
const entity = rowToEntity(row);
|
|
132
|
+
const sourceObject = entity.sourceObjectType === undefined || entity.sourceObjectId === undefined
|
|
133
|
+
? null
|
|
134
|
+
: { type: entity.sourceObjectType, id: entity.sourceObjectId };
|
|
135
|
+
const resolved = resolveConsolidatedSource(db, tenantId, opts.memoryId ?? null, sourceObject, 'updateEntity');
|
|
136
|
+
db.prepare(`UPDATE entities SET name = ?, memory_id = ?, source_kind = ? WHERE id = ? AND tenant_id = ?`)
|
|
137
|
+
.run(name, resolved.memoryId, resolved.sourceKind, id, tenantId);
|
|
138
|
+
return { ...entity, name, memoryId: resolved.memoryId, sourceKind: resolved.sourceKind };
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
if (db !== txDb)
|
|
142
|
+
closeHippoDb(db);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Insert a graph relation between two entities, sourced from a consolidated memory.
|
|
147
|
+
* Both entities must exist in the same tenant; the source memory must be consolidated.
|
|
148
|
+
*/
|
|
149
|
+
export function insertRelation(hippoRoot, tenantId, opts, txDb) {
|
|
150
|
+
assertTenantId('insertRelation', tenantId);
|
|
151
|
+
if (!GRAPH_RELATION_TYPES.has(opts.relType)) {
|
|
152
|
+
throw new Error(`insertRelation: relType must be one of ${Array.from(GRAPH_RELATION_TYPES).join('|')}; got ${opts.relType}`);
|
|
153
|
+
}
|
|
154
|
+
const now = new Date().toISOString();
|
|
155
|
+
const memoryId = opts.memoryId ?? null;
|
|
156
|
+
const sourceObject = opts.sourceObject ?? null;
|
|
157
|
+
const ownDb = txDb ? null : openHippoDb(hippoRoot);
|
|
158
|
+
const db = txDb ?? ownDb;
|
|
159
|
+
try {
|
|
160
|
+
for (const [eid, role] of [[opts.fromEntityId, 'from'], [opts.toEntityId, 'to']]) {
|
|
161
|
+
// SAFETY: ent's shape matches the single `tenant_id` column named in
|
|
162
|
+
// the SELECT above.
|
|
163
|
+
const ent = db.prepare(`SELECT tenant_id FROM entities WHERE id = ?`).get(eid);
|
|
164
|
+
if (!ent)
|
|
165
|
+
throw new Error(`insertRelation: ${role}_entity ${eid} not found`);
|
|
166
|
+
if (ent.tenant_id !== tenantId) {
|
|
167
|
+
throw new Error(`insertRelation: ${role}_entity ${eid} belongs to another tenant (no cross-tenant edges)`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const { sourceKind, memoryId: effectiveMemoryId } = resolveConsolidatedSource(db, tenantId, memoryId, sourceObject, 'insertRelation');
|
|
171
|
+
const result = db.prepare(`
|
|
172
|
+
INSERT INTO relations(tenant_id, from_entity_id, to_entity_id, rel_type, memory_id, source_kind, source_object_type, source_object_id, created_at)
|
|
173
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
174
|
+
`).run(tenantId, opts.fromEntityId, opts.toEntityId, opts.relType, effectiveMemoryId, sourceKind, sourceObject?.type ?? null, sourceObject?.id ?? null, now);
|
|
175
|
+
const id = Number(result.lastInsertRowid ?? 0);
|
|
176
|
+
// SAFETY: row's shape matches the columns named in RELATION_COLS above.
|
|
177
|
+
const row = db.prepare(`SELECT ${RELATION_COLS} FROM relations WHERE id = ?`).get(id);
|
|
178
|
+
if (!row)
|
|
179
|
+
throw new Error('insertRelation: failed to reload inserted relation');
|
|
180
|
+
return rowToRelation(row);
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
if (ownDb)
|
|
184
|
+
closeHippoDb(ownDb);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/** The source object still holds the loader's rule (active or superseded); a closed or gone one gets no new graph row. */
|
|
188
|
+
export function objectInForce(db, tenantId, ref) {
|
|
189
|
+
// `table` comes from the fixed SOURCE_OBJECT_TABLE map, never from input.
|
|
190
|
+
const table = SOURCE_OBJECT_TABLE[ref.type];
|
|
191
|
+
// SAFETY: row's shape matches the single `status` column named in the SELECT.
|
|
192
|
+
const row = db.prepare(`SELECT status FROM ${table} WHERE id = ? AND tenant_id = ?`).get(ref.id, tenantId);
|
|
193
|
+
return row?.status === 'active' || row?.status === 'superseded';
|
|
194
|
+
}
|
|
195
|
+
/** The lowest-id entity of this type anchored to the source object, which is the row a rebuild keeps. */
|
|
196
|
+
export function entityIdBySource(db, tenantId, entityType, sourceObject) {
|
|
197
|
+
// SAFETY: row's shape matches the single `id` column named in the SELECT.
|
|
198
|
+
const row = db.prepare(`SELECT id FROM entities WHERE tenant_id = ? AND entity_type = ? AND source_object_type = ? AND source_object_id = ? ORDER BY id LIMIT 1`).get(tenantId, entityType, sourceObject.type, sourceObject.id);
|
|
199
|
+
return row?.id;
|
|
200
|
+
}
|
|
201
|
+
export function relationPresent(db, tenantId, fromEntityId, toEntityId, relType) {
|
|
202
|
+
// SAFETY: row's shape matches the single aliased column named in the SELECT.
|
|
203
|
+
const present = db.prepare(`SELECT 1 AS hit FROM relations WHERE tenant_id = ? AND from_entity_id = ? AND to_entity_id = ? AND rel_type = ? LIMIT 1`).get(tenantId, fromEntityId, toEntityId, relType);
|
|
204
|
+
return present !== undefined;
|
|
205
|
+
}
|
|
206
|
+
export function deleteEntityRow(db, tenantId, id) {
|
|
207
|
+
db.prepare(`DELETE FROM entities WHERE id = ? AND tenant_id = ?`).run(id, tenantId);
|
|
208
|
+
}
|
|
209
|
+
export function deleteRelationRow(db, tenantId, id) {
|
|
210
|
+
db.prepare(`DELETE FROM relations WHERE id = ? AND tenant_id = ?`).run(id, tenantId);
|
|
211
|
+
}
|
|
212
|
+
/** Runs one tenant's graph writes in `fn` on `txDb` under one BEGIN IMMEDIATE, so two rebuilds serialize instead of
|
|
213
|
+
* interleaving and a throw rolls back the whole chunk. The sole sanctioned place to wrap graph writes in a transaction. */
|
|
214
|
+
export function runGraphRebuildTransaction(hippoRoot, tenantId, fn, opts) {
|
|
215
|
+
assertTenantId('runGraphRebuildTransaction', tenantId);
|
|
216
|
+
const db = openHippoDb(hippoRoot, opts);
|
|
217
|
+
try {
|
|
218
|
+
return withWriteScope(db, 'graph_rebuild', () => fn(db));
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
closeHippoDb(db);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Remove the graph rows sourced from one first-class object, by its (type, id). Used when a
|
|
226
|
+
* MIRRORLESS object is closed: it has no mirror memory, so `markGraphDirty` cannot
|
|
227
|
+
* enqueue a rebuild (the queue is memory-keyed). Closing must still drop the object's
|
|
228
|
+
* now-stale entity + edges from the graph, so we remove them directly here. Fail-soft
|
|
229
|
+
* like `markGraphDirty` (never throws into the object close caller; graph staleness is
|
|
230
|
+
* recoverable). Deleting the entity cascade-deletes any relation where it is an endpoint
|
|
231
|
+
* (relations FK entities ON DELETE CASCADE); the explicit relations DELETE also covers a
|
|
232
|
+
* relation whose OWN provenance is this object (defensive — every such edge has the object
|
|
233
|
+
* as an endpoint today, so the cascade already covers it). DELETE fires no BEFORE
|
|
234
|
+
* INSERT/UPDATE guard trigger.
|
|
235
|
+
*/
|
|
236
|
+
export function removeGraphEntitiesForObject(hippoRoot, tenantId, sourceObjectType, sourceObjectId) {
|
|
237
|
+
try {
|
|
238
|
+
assertTenantId('removeGraphEntitiesForObject', tenantId);
|
|
239
|
+
const db = openHippoDb(hippoRoot);
|
|
240
|
+
try {
|
|
241
|
+
withWriteScope(db, 'remove_graph_entities', () => {
|
|
242
|
+
db.prepare(`DELETE FROM relations WHERE tenant_id = ? AND source_object_type = ? AND source_object_id = ?`)
|
|
243
|
+
.run(tenantId, sourceObjectType, sourceObjectId);
|
|
244
|
+
db.prepare(`DELETE FROM entities WHERE tenant_id = ? AND source_object_type = ? AND source_object_id = ?`)
|
|
245
|
+
.run(tenantId, sourceObjectType, sourceObjectId);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
finally {
|
|
249
|
+
closeHippoDb(db);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
log.warn(`removeGraphEntitiesForObject: failed for tenant=${tenantId} ${sourceObjectType}#${sourceObjectId}: ${errorMessage(err)}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=graph-writes.js.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { MemoryEntry } from '../core/memory.js';
|
|
2
|
+
import { conflictResolveAuditsAt, resolvedConflictsAt } from './conflicts.js';
|
|
3
|
+
import { objectMemoryRowsAt } from './entry-reads.js';
|
|
4
|
+
/** What a move is planned from. The object and conflict rows are read only while the typed move is pending. */
|
|
5
|
+
export interface HalfLifeRows {
|
|
6
|
+
/** The base the store's memories are on. */
|
|
7
|
+
from: number;
|
|
8
|
+
/** True until the store has moved its object memories off their old flat half-life. */
|
|
9
|
+
typedPending: boolean;
|
|
10
|
+
all: MemoryEntry[];
|
|
11
|
+
objectRows: ReturnType<typeof objectMemoryRowsAt>;
|
|
12
|
+
conflictAudits: ReturnType<typeof conflictResolveAuditsAt>;
|
|
13
|
+
resolvedConflicts: ReturnType<typeof resolvedConflictsAt>;
|
|
14
|
+
}
|
|
15
|
+
/** Copies carrying their new half-life, and the bases their audit rows name. */
|
|
16
|
+
export interface HalfLifeMove {
|
|
17
|
+
from: number;
|
|
18
|
+
to: number;
|
|
19
|
+
entries: readonly MemoryEntry[];
|
|
20
|
+
}
|
|
21
|
+
/** The base this store's memories are on: 7 days when none was ever recorded. */
|
|
22
|
+
export declare function recordedHalfLifeBase(hippoRoot: string): number;
|
|
23
|
+
/** Moves the store's half-lives to base `to` as `plan` decides from the rows read here, then records the base. `outcome` is null when no move is due; a dry run plans and writes nothing. */
|
|
24
|
+
export declare function moveHalfLives<R>(hippoRoot: string, to: number, opts: {
|
|
25
|
+
dryRun: boolean;
|
|
26
|
+
actor: string;
|
|
27
|
+
}, plan: (rows: HalfLifeRows) => {
|
|
28
|
+
moves: readonly HalfLifeMove[];
|
|
29
|
+
outcome: R;
|
|
30
|
+
}): {
|
|
31
|
+
from: number;
|
|
32
|
+
outcome: R | null;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=half-life.d.ts.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// A half-life move reads, writes, audits and records its base on one handle, so it commits whole or not at all.
|
|
2
|
+
import { closeHippoDb, getMeta, openHippoDb, setMeta, withWriteScope } from '../db/index.js';
|
|
3
|
+
import { appendAuditEvent } from './audit.js';
|
|
4
|
+
import { conflictResolveAuditsAt, resolvedConflictsAt } from './conflicts.js';
|
|
5
|
+
import { objectMemoryRowsAt, selectAllEntries } from './entry-reads.js';
|
|
6
|
+
import { setHalfLivesAt } from './entry-writes.js';
|
|
7
|
+
import { HALF_LIFE_BASE_META_KEY, TYPED_HALF_LIFE_META_KEY, openStore } from './open.js';
|
|
8
|
+
/** The base every store used before the base was recorded. */
|
|
9
|
+
const LEGACY_HALF_LIFE_BASE = 7;
|
|
10
|
+
function readBase(db) {
|
|
11
|
+
const raw = Number(getMeta(db, HALF_LIFE_BASE_META_KEY, String(LEGACY_HALF_LIFE_BASE)));
|
|
12
|
+
return Number.isFinite(raw) && raw > 0 ? raw : LEGACY_HALF_LIFE_BASE;
|
|
13
|
+
}
|
|
14
|
+
/** The base this store's memories are on: 7 days when none was ever recorded. */
|
|
15
|
+
export function recordedHalfLifeBase(hippoRoot) {
|
|
16
|
+
const db = openHippoDb(hippoRoot);
|
|
17
|
+
try {
|
|
18
|
+
return readBase(db);
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
closeHippoDb(db);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function readRows(db, from, typedPending) {
|
|
25
|
+
const all = selectAllEntries(db);
|
|
26
|
+
return {
|
|
27
|
+
from,
|
|
28
|
+
typedPending,
|
|
29
|
+
all,
|
|
30
|
+
objectRows: typedPending ? objectMemoryRowsAt(db) : [],
|
|
31
|
+
conflictAudits: typedPending ? conflictResolveAuditsAt(db) : [],
|
|
32
|
+
resolvedConflicts: typedPending ? resolvedConflictsAt(db) : [],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Writes the move, then one audit event per tenant with each id's old half-life, so the move can be undone. */
|
|
36
|
+
function writeMove(db, move, old, actor) {
|
|
37
|
+
setHalfLivesAt(db, move.entries.map((e) => ({ id: e.id, halfLifeDays: e.half_life_days })));
|
|
38
|
+
const byTenant = new Map();
|
|
39
|
+
for (const e of move.entries) {
|
|
40
|
+
// One record per tenant, filled in place: copying it per row made the write grow with the square of the store.
|
|
41
|
+
let record = byTenant.get(e.tenantId);
|
|
42
|
+
if (!record)
|
|
43
|
+
byTenant.set(e.tenantId, (record = {}));
|
|
44
|
+
record[e.id] = old.get(e.id);
|
|
45
|
+
}
|
|
46
|
+
for (const [tenantId, oldHalfLives] of byTenant) {
|
|
47
|
+
appendAuditEvent(db, { tenantId, actor, op: 'half_life_migrate', metadata: { from: move.from, to: move.to, ids: Object.keys(oldHalfLives), oldHalfLives } });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Moves the store's half-lives to base `to` as `plan` decides from the rows read here, then records the base. `outcome` is null when no move is due; a dry run plans and writes nothing. */
|
|
51
|
+
export function moveHalfLives(hippoRoot, to, opts, plan) {
|
|
52
|
+
const db = openStore(hippoRoot);
|
|
53
|
+
try {
|
|
54
|
+
const run = () => {
|
|
55
|
+
const from = readBase(db);
|
|
56
|
+
const typedPending = getMeta(db, TYPED_HALF_LIFE_META_KEY, '') === '';
|
|
57
|
+
if (!(Number.isFinite(to) && to > 0) || (from === to && !typedPending))
|
|
58
|
+
return { from, outcome: null };
|
|
59
|
+
const rows = readRows(db, from, typedPending);
|
|
60
|
+
const { moves, outcome } = plan(rows);
|
|
61
|
+
if (opts.dryRun)
|
|
62
|
+
return { from, outcome };
|
|
63
|
+
const old = new Map(rows.all.map((e) => [e.id, e.half_life_days]));
|
|
64
|
+
for (const move of moves)
|
|
65
|
+
writeMove(db, move, old, opts.actor);
|
|
66
|
+
setMeta(db, HALF_LIFE_BASE_META_KEY, String(to));
|
|
67
|
+
setMeta(db, TYPED_HALF_LIFE_META_KEY, '1');
|
|
68
|
+
return { from, outcome };
|
|
69
|
+
};
|
|
70
|
+
// Plan, write, audit and record the base under one write lock, so a concurrent write or sleep cannot interleave.
|
|
71
|
+
return opts.dryRun ? run() : withWriteScope(db, 'migrate_half_life', run);
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
closeHippoDb(db);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=half-life.js.map
|
package/dist/store/handoffs.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type SessionHandoff, type HandoffOutcome, type HandoffEvidence } from '../handoff.js';
|
|
1
|
+
import { type SessionHandoff, type HandoffOutcome, type HandoffEvidence } from '../core/handoff.js';
|
|
2
2
|
import type { TaskSnapshot } from './rows.js';
|
|
3
3
|
import { type ContinuityKey } from './sessions.js';
|
|
4
4
|
/** Column list shared by every session_handoffs SELECT; store-cards.ts reuses it for the card handoff lookup. */
|
|
@@ -23,7 +23,10 @@ export declare function loadHandoffById(hippoRoot: string, tenantId: string, id:
|
|
|
23
23
|
export declare function stampHandoffOutcome(hippoRoot: string, tenantId: string, sessionId: string, outcome: HandoffOutcome): number;
|
|
24
24
|
/** Auto-write a handoff at session-end from the session's active snapshot, else from `derived`, its transcript state.
|
|
25
25
|
* @param evidence best-effort git state; outcome comes from the newest session_complete event.
|
|
26
|
-
* @
|
|
27
|
-
|
|
26
|
+
* @param options.inPlace rewrite an earlier transcript read instead of adding a revision, for a close that runs after every reply.
|
|
27
|
+
* @returns null when neither source is the session's, a newer handoff covers the snapshot, the session's latest handoff was not read off its transcript or already holds `derived`, or, in place, a handoff landed after the read. */
|
|
28
|
+
export declare function writeSessionEndHandoff(hippoRoot: string, tenantId: string, sessionId: string, evidence: HandoffEvidence | null, derived?: Pick<TaskSnapshot, 'task' | 'summary' | 'next_step'> | null, key?: ContinuityKey, options?: {
|
|
29
|
+
inPlace?: boolean;
|
|
30
|
+
}): SessionHandoff | null;
|
|
28
31
|
export {};
|
|
29
32
|
//# sourceMappingURL=handoffs.d.ts.map
|
package/dist/store/handoffs.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { closeHippoDb, openHippoDb } from '../db.js';
|
|
2
|
-
import { rowToSessionHandoff, isHandoffOutcome, } from '../handoff.js';
|
|
3
|
-
import { scopeAdmitSql } from '
|
|
4
|
-
import { assertTenantId } from '
|
|
1
|
+
import { closeHippoDb, openHippoDb } from '../db/index.js';
|
|
2
|
+
import { rowToSessionHandoff, isHandoffOutcome, } from '../core/handoff.js';
|
|
3
|
+
import { scopeAdmitSql } from './recall-scope.js';
|
|
4
|
+
import { assertTenantId } from './tenant.js';
|
|
5
5
|
import { openStore } from './open.js';
|
|
6
6
|
import { continuityStamp, continuityWhere, loadActiveTaskSnapshot } from './sessions.js';
|
|
7
7
|
/** Column list shared by every session_handoffs SELECT; store-cards.ts reuses it for the card handoff lookup. */
|
|
@@ -128,39 +128,42 @@ export function stampHandoffOutcome(hippoRoot, tenantId, sessionId, outcome) {
|
|
|
128
128
|
closeHippoDb(db);
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
|
-
/**
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
// Strict '>': a same-millisecond tie must not swallow the session's only write (test 6e).
|
|
144
|
-
if (existing && existing.updatedAt > active.updated_at)
|
|
131
|
+
/** Rewrites the session's newest handoff when it is still a transcript read, in one statement so a handoff written meanwhile is never overwritten; null when none was rewritten. */
|
|
132
|
+
function replaceTranscriptHandoff(hippoRoot, tenantId, handoff, key) {
|
|
133
|
+
const { conditions, params } = handoffConditions(tenantId, handoff.sessionId, {}, key);
|
|
134
|
+
const newest = `SELECT id FROM session_handoffs WHERE ${conditions.join(' AND ')} ORDER BY created_at DESC, id DESC LIMIT 1`;
|
|
135
|
+
const db = openStore(hippoRoot);
|
|
136
|
+
try {
|
|
137
|
+
const result = db.prepare(`
|
|
138
|
+
UPDATE session_handoffs SET repo_root = ?, task_id = ?, summary = ?, next_action = ?, artifacts_json = ?, scope = ?, created_at = ?,
|
|
139
|
+
constraints_json = ?, evidence_json = ?, outcome = ?, target_runtime = ?, card_id = ?
|
|
140
|
+
WHERE id = (${newest}) AND json_valid(evidence_json) AND json_extract(evidence_json, '$.derivedFrom') = 'transcript'
|
|
141
|
+
`).run(handoff.repoRoot ?? null, handoff.taskId ?? null, handoff.summary, handoff.nextAction ?? null, JSON.stringify(handoff.artifacts ?? []), handoff.scope ?? null, new Date().toISOString(), JSON.stringify(handoff.constraints ?? []), handoff.evidence ? JSON.stringify(handoff.evidence) : null, handoff.outcome ?? null, handoff.targetRuntime ?? null, handoff.cardId ?? null, ...params);
|
|
142
|
+
if (Number(result.changes ?? 0) === 0)
|
|
145
143
|
return null;
|
|
146
|
-
|
|
144
|
+
// SAFETY: row's shape matches HANDOFF_COLUMNS.
|
|
145
|
+
const row = db.prepare(`SELECT ${HANDOFF_COLUMNS} FROM session_handoffs WHERE id = (${newest})`).get(...params);
|
|
146
|
+
return row ? rowToSessionHandoff(row) : null;
|
|
147
147
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (!derived || (existing && existing.evidence?.derivedFrom !== 'transcript'))
|
|
151
|
-
return null;
|
|
152
|
-
// A retried session end reads the same transcript, so it must not add a second revision.
|
|
153
|
-
if (existing && existing.taskId === derived.task && existing.summary === derived.summary && existing.nextAction === derived.next_step)
|
|
154
|
-
return null;
|
|
155
|
-
snapshot = { ...derived, scope: null };
|
|
156
|
-
handoffEvidence = { ...evidence, derivedFrom: 'transcript' };
|
|
148
|
+
finally {
|
|
149
|
+
closeHippoDb(db);
|
|
157
150
|
}
|
|
158
|
-
|
|
151
|
+
}
|
|
152
|
+
function transcriptHandoffSource(existing, derived, evidence) {
|
|
153
|
+
// Only an earlier transcript read gives way; `hippo handoff create` and unmarked older handoffs keep winning.
|
|
154
|
+
if (!derived || (existing && existing.evidence?.derivedFrom !== 'transcript'))
|
|
155
|
+
return null;
|
|
156
|
+
// A retried session end reads the same transcript, so it must not add a second revision.
|
|
157
|
+
if (existing && existing.taskId === derived.task && existing.summary === derived.summary && existing.nextAction === derived.next_step)
|
|
158
|
+
return null;
|
|
159
|
+
return { snapshot: { ...derived, scope: null }, evidence: { ...evidence, derivedFrom: 'transcript' } };
|
|
160
|
+
}
|
|
161
|
+
function buildSessionEndHandoff(sessionId, snapshot, existing, handoffEvidence, outcome) {
|
|
159
162
|
// A same-task refresh carries forward envelope fields nobody cleared; a scope
|
|
160
163
|
// mismatch must not leak private metadata into an unscoped envelope.
|
|
161
164
|
const carryForward = existing != null && existing.taskId === snapshot.task
|
|
162
165
|
&& (existing.scope ?? null) === (snapshot.scope ?? null);
|
|
163
|
-
return
|
|
166
|
+
return {
|
|
164
167
|
version: 1,
|
|
165
168
|
sessionId,
|
|
166
169
|
repoRoot: carryForward ? existing.repoRoot : undefined,
|
|
@@ -174,7 +177,43 @@ export function writeSessionEndHandoff(hippoRoot, tenantId, sessionId, evidence,
|
|
|
174
177
|
constraints: carryForward ? existing.constraints : undefined,
|
|
175
178
|
targetRuntime: carryForward ? existing.targetRuntime : undefined,
|
|
176
179
|
cardId: carryForward ? existing.cardId : undefined,
|
|
177
|
-
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/** Auto-write a handoff at session-end from the session's active snapshot, else from `derived`, its transcript state.
|
|
183
|
+
* @param evidence best-effort git state; outcome comes from the newest session_complete event.
|
|
184
|
+
* @param options.inPlace rewrite an earlier transcript read instead of adding a revision, for a close that runs after every reply.
|
|
185
|
+
* @returns null when neither source is the session's, a newer handoff covers the snapshot, the session's latest handoff was not read off its transcript or already holds `derived`, or, in place, a handoff landed after the read. */
|
|
186
|
+
export function writeSessionEndHandoff(hippoRoot, tenantId, sessionId, evidence, derived = null, key, options = {}) {
|
|
187
|
+
assertTenantId('writeSessionEndHandoff', tenantId);
|
|
188
|
+
if (key)
|
|
189
|
+
continuityStamp(key); // a partial key is a caller bug, so fail loud rather than write nothing
|
|
190
|
+
const active = loadActiveTaskSnapshot(hippoRoot, tenantId, key);
|
|
191
|
+
const existing = loadLatestHandoff(hippoRoot, tenantId, sessionId, {}, key);
|
|
192
|
+
let snapshot;
|
|
193
|
+
let handoffEvidence = evidence;
|
|
194
|
+
let fromTranscript = false;
|
|
195
|
+
// After every reply the transcript is newer than the last compaction's snapshot, which the open chat keeps for the next one.
|
|
196
|
+
const snapshotGivesWay = options.inPlace === true && derived !== null && active?.source === 'pre-compact';
|
|
197
|
+
if (active && active.session_id === sessionId && !snapshotGivesWay) {
|
|
198
|
+
// Strict '>': a same-millisecond tie must not swallow the session's only write (test 6e).
|
|
199
|
+
if (existing && existing.updatedAt > active.updated_at)
|
|
200
|
+
return null;
|
|
201
|
+
snapshot = active;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
const fromDerived = transcriptHandoffSource(existing, derived, evidence);
|
|
205
|
+
if (!fromDerived)
|
|
206
|
+
return null;
|
|
207
|
+
snapshot = fromDerived.snapshot;
|
|
208
|
+
handoffEvidence = fromDerived.evidence;
|
|
209
|
+
fromTranscript = true;
|
|
210
|
+
}
|
|
211
|
+
const outcome = sessionOutcome(hippoRoot, tenantId, sessionId);
|
|
212
|
+
const handoff = buildSessionEndHandoff(sessionId, snapshot, existing, handoffEvidence, outcome);
|
|
213
|
+
// A miss means a handoff landed since the read, and a new transcript row would hide it.
|
|
214
|
+
if (fromTranscript && options.inPlace && existing)
|
|
215
|
+
return replaceTranscriptHandoff(hippoRoot, tenantId, handoff, key);
|
|
216
|
+
return saveSessionHandoff(hippoRoot, tenantId, handoff, key);
|
|
178
217
|
}
|
|
179
218
|
function sessionOutcome(hippoRoot, tenantId, sessionId) {
|
|
180
219
|
const db = openHippoDb(hippoRoot);
|