hippo-memory 1.71.0 → 2.0.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 +7 -5
- package/dist/agent-memories/apply.d.ts +0 -11
- package/dist/agent-memories/apply.js +11 -26
- package/dist/agent-memories/claude-code.js +1 -1
- package/dist/agent-memories/codex.js +1 -1
- package/dist/agent-memories/copilot.d.ts +1 -3
- package/dist/agent-memories/copilot.js +1 -17
- package/dist/agent-memories/project-folds.d.ts +10 -0
- package/dist/agent-memories/project-folds.js +34 -0
- package/dist/agent-memories/sync.js +8 -6
- package/dist/api/assemble.js +3 -2
- package/dist/api/audit.d.ts +30 -2
- package/dist/api/audit.js +48 -7
- package/dist/api/auth.d.ts +11 -9
- package/dist/api/auth.js +39 -40
- package/dist/api/auto-sleep.d.ts +5 -2
- package/dist/api/auto-sleep.js +7 -3
- package/dist/api/availability.js +2 -3
- package/dist/api/cards.d.ts +42 -0
- package/dist/api/cards.js +52 -0
- package/dist/api/conflicts.d.ts +28 -0
- package/dist/api/conflicts.js +61 -0
- package/dist/api/context-auto.js +4 -2
- package/dist/api/context-render.js +4 -3
- package/dist/api/context-select.js +15 -29
- package/dist/api/context.js +29 -18
- package/dist/api/continuity.d.ts +47 -0
- package/dist/api/continuity.js +66 -0
- package/dist/api/dormant.js +4 -2
- package/dist/api/drill-down.js +3 -2
- package/dist/api/embeddings.d.ts +17 -0
- package/dist/api/embeddings.js +28 -0
- package/dist/api/error-reply.d.ts +8 -0
- package/dist/api/error-reply.js +21 -0
- package/dist/api/forget.d.ts +7 -3
- package/dist/api/forget.js +24 -14
- package/dist/api/goals.d.ts +1 -1
- package/dist/api/goals.js +5 -9
- package/dist/api/graph.js +2 -1
- package/dist/api/index.d.ts +4 -2
- package/dist/api/index.js +4 -2
- package/dist/api/instruction-detect.js +5 -1
- package/dist/api/learn.d.ts +5 -1
- package/dist/api/learn.js +71 -44
- package/dist/api/ledger-db.d.ts +2 -6
- package/dist/api/ledger-db.js +4 -36
- package/dist/api/memories.d.ts +21 -1
- package/dist/api/memories.js +51 -1
- package/dist/api/objects.d.ts +1 -1
- package/dist/api/objects.js +2 -1
- package/dist/api/outcome.d.ts +5 -5
- package/dist/api/outcome.js +17 -16
- package/dist/api/pilot-arm.d.ts +1 -11
- package/dist/api/pilot-arm.js +5 -45
- package/dist/api/predictions.d.ts +3 -1
- package/dist/api/predictions.js +8 -1
- package/dist/api/projects.d.ts +21 -0
- package/dist/api/projects.js +24 -0
- package/dist/api/promote.d.ts +3 -3
- package/dist/api/promote.js +26 -28
- package/dist/api/prompt-hook.d.ts +17 -2
- package/dist/api/prompt-hook.js +45 -4
- package/dist/api/quarantine.js +2 -1
- package/dist/api/recall-cli.d.ts +3 -0
- package/dist/api/recall-cli.js +13 -4
- package/dist/api/recall-core.js +10 -5
- package/dist/api/recall-pipeline.js +23 -24
- package/dist/api/recall-request.js +1 -1
- package/dist/api/recall-types.d.ts +3 -1
- package/dist/api/recall.d.ts +0 -3
- package/dist/api/recall.js +51 -73
- package/dist/api/remember-local.d.ts +5 -2
- package/dist/api/remember-local.js +15 -7
- package/dist/api/remember.d.ts +7 -3
- package/dist/api/remember.js +19 -16
- package/dist/api/session-end.d.ts +46 -0
- package/dist/api/session-end.js +131 -0
- package/dist/api/sleep-run.d.ts +1 -1
- package/dist/api/sleep-run.js +16 -11
- package/dist/api/sleep.js +4 -3
- package/dist/api/status.d.ts +24 -0
- package/dist/api/status.js +40 -0
- package/dist/api/store-init.d.ts +4 -0
- package/dist/api/store-init.js +9 -0
- package/dist/api/tokens.js +2 -2
- package/dist/api/types.d.ts +3 -7
- package/dist/api/types.js +6 -1
- package/dist/capture/caller-session.d.ts +0 -3
- package/dist/capture/caller-session.js +1 -12
- package/dist/capture/capture-error.d.ts +2 -2
- package/dist/capture/capture-error.js +23 -18
- package/dist/capture/codex-patch.js +3 -1
- package/dist/capture/command.js +36 -95
- package/dist/capture/compact.js +10 -5
- package/dist/capture/compaction-items-caller.js +11 -20
- package/dist/capture/compaction-record.d.ts +7 -93
- package/dist/capture/compaction-record.js +29 -426
- package/dist/capture/compaction-spool.d.ts +7 -7
- package/dist/capture/compaction-spool.js +60 -51
- package/dist/capture/copilot-transcript.d.ts +2 -1
- package/dist/capture/copilot-transcript.js +2 -1
- package/dist/capture/extract.d.ts +5 -2
- package/dist/capture/extract.js +4 -3
- package/dist/capture/failure-caller.d.ts +1 -1
- package/dist/capture/failure-caller.js +21 -16
- package/dist/capture/failure-reading.d.ts +2 -1
- package/dist/capture/failure-reading.js +7 -9
- package/dist/capture/pre-compact-caller.js +5 -4
- package/dist/capture/session-digest.js +4 -3
- package/dist/capture/session-end-caller.js +3 -2
- package/dist/capture/session-worker.js +22 -10
- package/dist/capture/transcript.d.ts +2 -1
- package/dist/capture/transcript.js +6 -3
- package/dist/capture/working-state.d.ts +4 -2
- package/dist/capture/working-state.js +4 -2
- package/dist/cli/audit-prune.d.ts +0 -25
- package/dist/cli/audit-prune.js +1 -27
- package/dist/cli/audit.js +20 -20
- package/dist/cli/auth.d.ts +1 -1
- package/dist/cli/auth.js +16 -17
- package/dist/cli/briefs.d.ts +1 -4
- package/dist/cli/briefs.js +37 -292
- package/dist/cli/card.js +41 -33
- package/dist/cli/client.d.ts +6 -2
- package/dist/cli/client.js +37 -21
- package/dist/cli/compact-resume-payload.js +1 -1
- package/dist/cli/context.d.ts +1 -1
- package/dist/cli/context.js +13 -13
- package/dist/cli/continuity.d.ts +1 -1
- package/dist/cli/continuity.js +36 -39
- package/dist/cli/curate.d.ts +2 -2
- package/dist/cli/curate.js +32 -36
- package/dist/cli/dag.d.ts +1 -1
- package/dist/cli/dag.js +23 -8
- package/dist/cli/decisions.d.ts +0 -2
- package/dist/cli/decisions.js +7 -285
- package/dist/cli/eval.d.ts +1 -1
- package/dist/cli/eval.js +12 -13
- package/dist/cli/explain.d.ts +1 -1
- package/dist/cli/explain.js +21 -25
- package/dist/cli/flag-values.js +16 -6
- package/dist/cli/flags.d.ts +0 -289
- package/dist/cli/flags.js +3 -138
- package/dist/cli/graph.d.ts +3 -0
- package/dist/cli/graph.js +83 -0
- package/dist/cli/hook-runtime.d.ts +6 -6
- package/dist/cli/hook-runtime.js +9 -36
- package/dist/cli/incidents.d.ts +3 -0
- package/dist/cli/incidents.js +112 -0
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.js +28 -19
- package/dist/cli/install-steps.d.ts +2 -1
- package/dist/cli/install-steps.js +11 -3
- package/dist/cli/last-sleep.js +1 -1
- package/dist/cli/maintenance.d.ts +3 -3
- package/dist/cli/maintenance.js +29 -30
- package/dist/cli/notes.d.ts +2 -0
- package/dist/cli/notes.js +41 -0
- package/dist/cli/object-verbs.d.ts +2 -2
- package/dist/cli/object-verbs.js +4 -4
- package/dist/cli/open-browser.d.ts +14 -0
- package/dist/cli/open-browser.js +26 -0
- package/dist/cli/playbooks.d.ts +3 -4
- package/dist/cli/playbooks.js +126 -290
- package/dist/cli/predictions.d.ts +3 -0
- package/dist/cli/predictions.js +174 -0
- package/dist/cli/print.js +2 -1
- package/dist/cli/projects.js +30 -22
- package/dist/cli/quality-repair-once.d.ts +1 -1
- package/dist/cli/quality-repair-once.js +6 -5
- package/dist/cli/recall.js +13 -7
- package/dist/cli/refine-llm.js +18 -17
- package/dist/cli/remember.js +17 -17
- package/dist/cli/scheduler.js +2 -1
- package/dist/cli/serve.js +11 -6
- package/dist/cli/session-hooks.d.ts +1 -5
- package/dist/cli/session-hooks.js +89 -168
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.js +17 -10
- package/dist/cli/shared.d.ts +2 -6
- package/dist/cli/shared.js +9 -29
- package/dist/cli/sleep-render.js +6 -3
- package/dist/cli/sleep.js +6 -37
- package/dist/cli/status.d.ts +3 -3
- package/dist/cli/status.js +32 -35
- package/dist/cli/transfer.d.ts +3 -3
- package/dist/cli/transfer.js +64 -43
- package/dist/cli/usage.d.ts +1 -80
- package/dist/cli/usage.js +2 -696
- package/dist/cli/verb-row.d.ts +34 -0
- package/dist/cli/verb-row.js +6 -0
- package/dist/cli/verbs/health.d.ts +27 -0
- package/dist/cli/verbs/health.js +234 -0
- package/dist/cli/verbs/memory.d.ts +16 -0
- package/dist/cli/verbs/memory.js +236 -0
- package/dist/cli/verbs/objects.d.ts +20 -0
- package/dist/cli/verbs/objects.js +257 -0
- package/dist/cli/verbs/sessions.d.ts +31 -0
- package/dist/cli/verbs/sessions.js +314 -0
- package/dist/cli/verbs.d.ts +81 -0
- package/dist/cli/verbs.js +7 -0
- package/dist/cli/versioned-verbs.d.ts +51 -0
- package/dist/cli/versioned-verbs.js +79 -0
- package/dist/cli.d.ts +1 -272
- package/dist/cli.js +24 -315
- package/dist/connectors/dlq.d.ts +39 -3
- package/dist/connectors/dlq.js +39 -4
- package/dist/connectors/github/backfill.js +12 -3
- package/dist/connectors/github/deletion.js +2 -1
- package/dist/connectors/github/dlq.js +31 -73
- package/dist/connectors/github/ingest.d.ts +2 -6
- package/dist/connectors/github/ingest.js +5 -29
- package/dist/connectors/github/tenant-routing.js +2 -1
- package/dist/connectors/github/webhook.d.ts +2 -1
- package/dist/connectors/github/webhook.js +35 -2
- package/dist/connectors/ingest.d.ts +10 -0
- package/dist/connectors/ingest.js +29 -0
- package/dist/connectors/slack/deletion.js +2 -1
- package/dist/connectors/slack/dlq.js +49 -71
- package/dist/connectors/slack/ingest.d.ts +2 -6
- package/dist/connectors/slack/ingest.js +4 -28
- package/dist/connectors/slack/tenant-routing.js +2 -1
- package/dist/connectors/slack/webhook.d.ts +2 -1
- package/dist/connectors/slack/webhook.js +2 -1
- package/dist/consolidate/conflicts.js +2 -2
- package/dist/consolidate/dag.js +29 -18
- package/dist/consolidate/dedupe.d.ts +7 -0
- package/dist/consolidate/dedupe.js +6 -4
- package/dist/consolidate/llm-passes.js +45 -19
- package/dist/consolidate/memory-value.js +3 -2
- package/dist/consolidate/merge.js +8 -8
- package/dist/consolidate/physics-pass.d.ts +6 -1
- package/dist/consolidate/physics-pass.js +26 -6
- package/dist/consolidate/replay.js +11 -4
- package/dist/consolidate/sleep.js +9 -6
- package/dist/consolidate/traces.js +5 -5
- package/dist/core/ablation.d.ts +10 -0
- package/dist/core/ablation.js +12 -0
- package/dist/{sharing/scope.d.ts → core/active-scope.d.ts} +1 -1
- package/dist/{sharing/scope.js → core/active-scope.js} +1 -1
- package/dist/core/ambient.d.ts +4 -0
- package/dist/core/ambient.js +39 -18
- package/dist/core/api-errors.d.ts +16 -0
- package/dist/core/api-errors.js +20 -0
- package/dist/core/card.js +3 -1
- package/dist/core/compaction-timing.d.ts +7 -0
- package/dist/core/compaction-timing.js +9 -0
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.js +22 -18
- package/dist/core/cosine.d.ts +3 -0
- package/dist/core/cosine.js +19 -0
- package/dist/{store → core}/markdown.d.ts +1 -1
- package/dist/{store → core}/markdown.js +4 -4
- package/dist/core/memory-audit.d.ts +17 -0
- package/dist/core/memory-audit.js +54 -0
- package/dist/core/memory.d.ts +14 -8
- package/dist/core/memory.js +35 -23
- package/dist/{consolidate → core}/merged-row.d.ts +1 -1
- package/dist/{consolidate → core}/merged-row.js +1 -1
- package/dist/core/physics.d.ts +3 -1
- package/dist/core/physics.js +23 -18
- package/dist/core/prediction.d.ts +3 -0
- package/dist/core/prediction.js +6 -0
- package/dist/core/project-identity.d.ts +3 -0
- package/dist/core/project-identity.js +12 -2
- package/dist/{store → core}/recall-scope.d.ts +1 -10
- package/dist/{store → core}/recall-scope.js +2 -19
- package/dist/core/search-types.d.ts +1 -1
- package/dist/dashboard/dashboard-actions.d.ts +2 -2
- package/dist/dashboard/dashboard-actions.js +5 -5
- package/dist/dashboard/dashboard-queries.js +2 -7
- package/dist/dashboard/dashboard-snapshot.js +1 -3
- package/dist/dashboard/dashboard.js +16 -5
- package/dist/db/busy.d.ts +2 -7
- package/dist/db/busy.js +21 -26
- package/dist/db/connect.d.ts +2 -2
- package/dist/db/connect.js +7 -7
- package/dist/db/index.d.ts +3 -3
- package/dist/db/index.js +3 -3
- package/dist/db/migrate.js +14 -7
- package/dist/db/migrations/index.d.ts +1 -1
- package/dist/db/migrations/index.js +3 -1
- package/dist/db/migrations/v11.js +1 -0
- package/dist/db/migrations/v14.js +1 -0
- package/dist/db/migrations/v55.d.ts +3 -0
- package/dist/db/migrations/v55.js +17 -0
- package/dist/db/open.d.ts +0 -2
- package/dist/db/open.js +6 -10
- package/dist/db/physics-state.d.ts +0 -4
- package/dist/db/physics-state.js +7 -33
- package/dist/db/request-stores.d.ts +1 -0
- package/dist/db/request-stores.js +2 -1
- package/dist/db/tables.d.ts +2 -0
- package/dist/db/tables.js +6 -2
- package/dist/db/vector-store.js +19 -5
- package/dist/db/wal-checkpointer.js +2 -1
- package/dist/doctor.d.ts +3 -0
- package/dist/doctor.js +18 -15
- package/dist/embeddings/local.d.ts +62 -0
- package/dist/embeddings/local.js +146 -0
- package/dist/{store/embeddings → embeddings}/provider.d.ts +5 -2
- package/dist/{store/embeddings → embeddings}/provider.js +19 -25
- package/dist/embeddings/transformers.d.ts +26 -0
- package/dist/embeddings/transformers.js +89 -0
- package/dist/entry/session-text.d.ts +1 -1
- package/dist/entry/session-text.js +1 -1
- package/dist/entry/store-kit.d.ts +37 -0
- package/dist/entry/store-kit.js +25 -0
- package/dist/entry/testing.d.ts +6 -0
- package/dist/entry/testing.js +7 -0
- package/dist/eval/eval-suite.js +17 -11
- package/dist/eval/eval.js +1 -1
- package/dist/eval/judgment.js +12 -5
- package/dist/graph/extract.js +3 -3
- package/dist/graph/recall.js +1 -1
- package/dist/graph/view.js +13 -5
- package/dist/graph/write.d.ts +1 -1
- package/dist/graph/write.js +9 -9
- package/dist/hooks/codex-session.js +3 -2
- package/dist/hooks/codex-wrapper.js +2 -1
- package/dist/hooks/json-hooks.js +10 -4
- package/dist/hooks/opencode.js +8 -5
- package/dist/hooks/shared.d.ts +0 -6
- package/dist/hooks/shared.js +4 -15
- package/dist/importers/core.js +4 -4
- package/dist/importers/sources.js +5 -4
- package/dist/importers/vault.d.ts +1 -1
- package/dist/importers/vault.js +25 -23
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -3
- package/dist/learn/autolearn.d.ts +15 -3
- package/dist/learn/autolearn.js +38 -16
- package/dist/learn/churn-git.js +13 -4
- package/dist/learn/extract.d.ts +3 -2
- package/dist/learn/extract.js +7 -5
- package/dist/learn/forward-claim-detector.js +4 -2
- package/dist/learn/invalidation.d.ts +2 -1
- package/dist/learn/invalidation.js +18 -9
- package/dist/mcp/admin-tools.d.ts +2 -2
- package/dist/mcp/admin-tools.js +27 -48
- package/dist/mcp/format.js +3 -2
- package/dist/mcp/framing.d.ts +1 -0
- package/dist/mcp/framing.js +1 -1
- package/dist/mcp/memory-tools.d.ts +1 -1
- package/dist/mcp/memory-tools.js +8 -9
- package/dist/mcp/protocol.d.ts +11 -7
- package/dist/mcp/protocol.js +25 -12
- package/dist/mcp/recall-tools.js +12 -9
- package/dist/mcp/request.js +22 -20
- package/dist/mcp/stdio.js +37 -16
- package/dist/mcp/tool-args.js +2 -1
- package/dist/mcp/tools.js +44 -21
- package/dist/objects/customer-notes.d.ts +2 -2
- package/dist/objects/decisions.d.ts +2 -2
- package/dist/objects/descriptor.d.ts +1 -1
- package/dist/objects/incidents.d.ts +2 -2
- package/dist/objects/lifecycle.d.ts +1 -1
- package/dist/objects/lifecycle.js +2 -1
- package/dist/objects/policies.d.ts +2 -2
- package/dist/objects/policies.js +2 -1
- package/dist/objects/processes.d.ts +2 -2
- package/dist/objects/project-briefs.d.ts +2 -2
- package/dist/objects/project-briefs.js +2 -3
- package/dist/objects/skills.d.ts +2 -2
- package/dist/postinstall.js +1 -1
- package/dist/rerankers/clef.js +3 -6
- package/dist/rerankers/cross-encoder.d.ts +31 -2
- package/dist/rerankers/cross-encoder.js +71 -98
- package/dist/rerankers/index.js +5 -4
- package/dist/rerankers/jev.js +2 -4
- package/dist/rerankers/outage-warning.d.ts +3 -1
- package/dist/rerankers/outage-warning.js +5 -3
- package/dist/search/bm25-search.js +1 -1
- package/dist/search/boosts.js +1 -1
- package/dist/search/embed-memories.d.ts +12 -0
- package/dist/search/embed-memories.js +389 -0
- package/dist/search/engine.d.ts +8 -0
- package/dist/search/engine.js +10 -0
- package/dist/search/goal-boost.d.ts +1 -1
- package/dist/search/goal-boost.js +6 -3
- package/dist/search/hybrid.d.ts +9 -2
- package/dist/search/hybrid.js +9 -4
- package/dist/search/physics-search.d.ts +6 -3
- package/dist/search/physics-search.js +22 -15
- package/dist/search/rerank.js +1 -1
- package/dist/search/vector.d.ts +8 -6
- package/dist/search/vector.js +14 -17
- package/dist/server/auth.d.ts +3 -1
- package/dist/server/auth.js +24 -15
- package/dist/server/boot.d.ts +2 -1
- package/dist/server/boot.js +34 -84
- package/dist/server/client-ip.d.ts +9 -6
- package/dist/server/client-ip.js +36 -17
- package/dist/server/deadline.d.ts +0 -2
- package/dist/server/deadline.js +1 -7
- package/dist/server/defaults.d.ts +1 -0
- package/dist/server/defaults.js +1 -0
- package/dist/server/mcp-http.js +16 -11
- package/dist/server/request.js +7 -2
- package/dist/server/route-checks.d.ts +7 -0
- package/dist/server/route-checks.js +42 -0
- package/dist/server/route-table.d.ts +9 -8
- package/dist/server/route-table.js +127 -133
- package/dist/server/routes/admin.d.ts +8 -8
- package/dist/server/routes/admin.js +13 -21
- package/dist/server/routes/customer-notes.d.ts +6 -6
- package/dist/server/routes/customer-notes.js +1 -2
- package/dist/server/routes/decisions.d.ts +6 -6
- package/dist/server/routes/decisions.js +2 -4
- package/dist/server/routes/incidents.d.ts +6 -6
- package/dist/server/routes/incidents.js +2 -5
- package/dist/server/routes/memories.d.ts +9 -9
- package/dist/server/routes/memories.js +19 -40
- package/dist/server/routes/object-routes.d.ts +6 -6
- package/dist/server/routes/object-routes.js +4 -7
- package/dist/server/routes/policies.d.ts +7 -7
- package/dist/server/routes/policies.js +2 -4
- package/dist/server/routes/predictions.d.ts +6 -6
- package/dist/server/routes/predictions.js +9 -13
- package/dist/server/routes/processes.d.ts +6 -6
- package/dist/server/routes/processes.js +1 -2
- package/dist/server/routes/project-briefs.d.ts +7 -7
- package/dist/server/routes/project-briefs.js +2 -4
- package/dist/server/routes/recall.d.ts +5 -5
- package/dist/server/routes/recall.js +6 -10
- package/dist/server/routes/skills.d.ts +7 -7
- package/dist/server/routes/skills.js +2 -4
- package/dist/server/server-detect.d.ts +7 -1
- package/dist/server/server-detect.js +36 -11
- package/dist/server/sleep-child.js +26 -7
- package/dist/server/sleep-offload.d.ts +11 -5
- package/dist/server/sleep-offload.js +17 -11
- package/dist/server/tls.d.ts +7 -2
- package/dist/server/tls.js +17 -5
- package/dist/server/types.d.ts +29 -12
- package/dist/server/validation.d.ts +1 -2
- package/dist/server/validation.js +6 -11
- package/dist/server.d.ts +4 -40
- package/dist/server.js +3 -29
- package/dist/sharing/global-store.d.ts +4 -5
- package/dist/sharing/global-store.js +8 -13
- package/dist/sharing/global-sync.js +38 -45
- package/dist/sharing/project-merge.d.ts +7 -14
- package/dist/sharing/project-merge.js +57 -121
- package/dist/sharing/search-both.js +10 -3
- package/dist/sharing/share.d.ts +2 -0
- package/dist/sharing/share.js +39 -38
- package/dist/store/ambient.js +7 -7
- package/dist/store/audit-event.d.ts +1 -1
- package/dist/store/audit.d.ts +0 -16
- package/dist/store/audit.js +4 -55
- package/dist/store/auth.d.ts +4 -2
- package/dist/store/auth.js +7 -3
- package/dist/store/candidates.d.ts +3 -2
- package/dist/store/candidates.js +59 -30
- package/dist/store/capture-write.d.ts +17 -0
- package/dist/store/capture-write.js +35 -0
- package/dist/store/cards.js +6 -5
- package/dist/store/compaction-caller.d.ts +18 -0
- package/dist/store/compaction-caller.js +29 -0
- package/dist/store/compactions-record.d.ts +115 -0
- package/dist/store/compactions-record.js +418 -0
- package/dist/store/compactions.js +6 -4
- package/dist/store/conflicts.d.ts +7 -1
- package/dist/store/conflicts.js +13 -9
- package/dist/store/connectors/dlq.d.ts +10 -0
- package/dist/store/connectors/dlq.js +33 -0
- package/dist/store/connectors/event-log.d.ts +13 -0
- package/dist/store/connectors/event-log.js +24 -0
- package/dist/store/connectors/github.d.ts +7 -9
- package/dist/store/connectors/github.js +35 -60
- package/dist/store/connectors/slack.d.ts +2 -11
- package/dist/store/connectors/slack.js +24 -57
- package/dist/store/dashboard-reads.js +8 -6
- package/dist/store/delete-and-batch.d.ts +6 -0
- package/dist/store/delete-and-batch.js +40 -6
- package/dist/store/delivery-recorder.d.ts +12 -5
- package/dist/store/delivery-recorder.js +13 -11
- package/dist/store/descendant-page.js +8 -4
- package/dist/store/dormant.d.ts +1 -1
- package/dist/store/dormant.js +10 -4
- package/dist/store/embeddings/index.d.ts +2 -12
- package/dist/store/embeddings/index.js +5 -374
- package/dist/store/entry-reads.d.ts +35 -4
- package/dist/store/entry-reads.js +86 -19
- package/dist/store/entry-row.js +9 -2
- package/dist/store/entry-writes.d.ts +15 -12
- package/dist/store/entry-writes.js +54 -22
- package/dist/store/failure-log-at.d.ts +8 -0
- package/dist/store/failure-log-at.js +16 -0
- package/dist/store/failure-log.d.ts +2 -2
- package/dist/store/failure-log.js +5 -3
- package/dist/{trust → store}/gated-write.d.ts +3 -1
- package/dist/{trust → store}/gated-write.js +7 -5
- package/dist/store/goals.js +22 -19
- package/dist/store/graph-reads.js +9 -6
- package/dist/store/graph-view-rows.js +2 -1
- package/dist/store/graph-writes.d.ts +6 -6
- package/dist/store/graph-writes.js +48 -71
- package/dist/store/half-life.js +2 -2
- package/dist/store/handoffs.d.ts +10 -4
- package/dist/store/handoffs.js +10 -9
- package/dist/store/index-and-stats.js +2 -2
- package/dist/store/index.d.ts +2 -2
- package/dist/store/index.js +1 -1
- package/dist/store/key-writes.js +1 -1
- package/dist/store/ledger-turn.d.ts +9 -0
- package/dist/store/ledger-turn.js +38 -0
- package/dist/store/mirrors.js +19 -10
- package/dist/store/open.d.ts +2 -5
- package/dist/store/open.js +42 -54
- package/dist/store/pilot-arm.d.ts +12 -0
- package/dist/store/pilot-arm.js +42 -0
- package/dist/store/port.d.ts +68 -6
- package/dist/store/port.js +8 -0
- package/dist/store/predictions.d.ts +1 -2
- package/dist/store/predictions.js +3 -6
- package/dist/store/project-tags.d.ts +62 -0
- package/dist/store/project-tags.js +67 -0
- package/dist/store/quality-repair.js +1 -1
- package/dist/store/quarantine.js +2 -1
- package/dist/store/recall-trace.d.ts +2 -0
- package/dist/store/recall-trace.js +20 -3
- package/dist/store/rejected-values.js +16 -10
- package/dist/store/rejection-probe.d.ts +4 -0
- package/dist/store/rejection-probe.js +19 -0
- package/dist/store/rejection.d.ts +0 -17
- package/dist/store/rejection.js +1 -21
- package/dist/store/rows.js +2 -2
- package/dist/store/rule-sql.d.ts +11 -0
- package/dist/store/rule-sql.js +31 -6
- package/dist/store/search-rows.d.ts +5 -5
- package/dist/store/search-rows.js +18 -16
- package/dist/store/sessions.js +4 -2
- package/dist/store/set-aside.d.ts +14 -0
- package/dist/store/set-aside.js +23 -0
- package/dist/store/sqlite/busy.d.ts +3 -0
- package/dist/store/sqlite/busy.js +8 -0
- package/dist/store/sqlite/connector-events-group.js +4 -7
- package/dist/store/sqlite/connector-writes-group.js +6 -4
- package/dist/store/sqlite/entry-writes-group.d.ts +3 -3
- package/dist/store/sqlite/entry-writes-group.js +3 -3
- package/dist/store/sqlite/error-codec.js +4 -3
- package/dist/store/sqlite/executor.js +10 -4
- package/dist/store/sqlite/graph-reads-group.js +1 -1
- package/dist/store/sqlite/held-connection.d.ts +11 -0
- package/dist/store/sqlite/held-connection.js +41 -0
- package/dist/store/sqlite/last-recall-group.d.ts +13 -0
- package/dist/store/sqlite/last-recall-group.js +57 -0
- package/dist/store/sqlite/local.d.ts +0 -17
- package/dist/store/sqlite/local.js +0 -31
- package/dist/store/sqlite/maintenance-groups.d.ts +6 -0
- package/dist/store/sqlite/maintenance-groups.js +60 -0
- package/dist/store/sqlite/object-rows.d.ts +1 -1
- package/dist/store/sqlite/objects-group.d.ts +1 -1
- package/dist/store/sqlite/objects-group.js +15 -7
- package/dist/store/sqlite/store.d.ts +1 -8
- package/dist/store/sqlite/store.js +13 -22
- package/dist/store/summaries.d.ts +10 -3
- package/dist/store/summaries.js +54 -11
- package/dist/store/token-ledger-rows.js +3 -2
- package/dist/store/token-ledger.d.ts +0 -7
- package/dist/store/token-ledger.js +0 -35
- package/dist/store/vector-index.js +8 -4
- package/dist/support-bundle.js +2 -3
- package/dist/trust/reject-flow.js +2 -2
- package/dist/util/agent-homes.d.ts +15 -0
- package/dist/util/agent-homes.js +34 -0
- package/dist/util/anthropic-messages.d.ts +6 -1
- package/dist/util/anthropic-messages.js +26 -7
- package/dist/util/atomic-write.d.ts +5 -2
- package/dist/util/atomic-write.js +12 -8
- package/dist/util/chunked.d.ts +3 -0
- package/dist/util/chunked.js +10 -0
- package/dist/util/ellipsize.d.ts +3 -0
- package/dist/util/ellipsize.js +5 -0
- package/dist/util/env.d.ts +12 -2
- package/dist/util/env.js +12 -2
- package/dist/util/format.d.ts +5 -0
- package/dist/util/format.js +10 -0
- package/dist/util/hook-payload.d.ts +8 -0
- package/dist/util/hook-payload.js +37 -0
- package/dist/util/http-retry.d.ts +6 -0
- package/dist/util/http-retry.js +43 -5
- package/dist/util/http-util.d.ts +0 -8
- package/dist/util/http-util.js +10 -21
- package/dist/util/limits.d.ts +7 -0
- package/dist/util/limits.js +14 -0
- package/dist/util/log.d.ts +4 -0
- package/dist/util/log.js +9 -0
- package/dist/util/request-scope.d.ts +9 -3
- package/dist/util/request-scope.js +18 -9
- package/dist/util/secret-detect.js +6 -1
- package/dist/util/spawn-argv.d.ts +9 -0
- package/dist/util/spawn-argv.js +57 -0
- package/dist/util/sql.d.ts +3 -0
- package/dist/util/sql.js +6 -0
- package/dist/util/sqlite-blocked.d.ts +2 -0
- package/dist/util/sqlite-blocked.js +5 -0
- package/dist/util/stream-tee.d.ts +3 -0
- package/dist/util/stream-tee.js +35 -0
- package/dist/util/time.d.ts +4 -0
- package/dist/util/time.js +4 -0
- package/dist/util/vector-codec.d.ts +4 -0
- package/dist/util/vector-codec.js +15 -0
- package/dist/util/version.d.ts +1 -1
- package/dist/util/version.js +1 -1
- 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 +4 -2
- package/dist/api/on-store.d.ts +0 -16
- package/dist/api/on-store.js +0 -38
- package/dist/store/embeddings/local.d.ts +0 -15
- package/dist/store/embeddings/local.js +0 -175
- /package/dist/{cli → api}/correction-latency.d.ts +0 -0
- /package/dist/{cli → api}/correction-latency.js +0 -0
- /package/dist/{cli → api}/provenance-coverage.d.ts +0 -0
- /package/dist/{cli → api}/provenance-coverage.js +0 -0
- /package/dist/{store → core}/object-types.d.ts +0 -0
- /package/dist/{store → core}/object-types.js +0 -0
- /package/dist/{capture → util}/compaction-items.d.ts +0 -0
- /package/dist/{capture → util}/compaction-items.js +0 -0
- /package/dist/{store → util}/yaml.d.ts +0 -0
- /package/dist/{store → util}/yaml.js +0 -0
package/dist/consolidate/dag.js
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import { createMemory, Layer } from '../core/memory.js';
|
|
2
2
|
import { writeEntry, writeEntriesTogether } from '../store/entry-writes.js';
|
|
3
|
-
import { loadAllDirtySummaries, loadChildrenOfSummary, applyRebuildResult, clearSummaryDirtyAfterBuild, } from '../store/summaries.js';
|
|
4
|
-
import { RejectedValueError } from '../
|
|
3
|
+
import { loadAllDirtySummaries, loadChildrenOfSummary, loadChildrenOfSummaries, childrenKey, applyRebuildResult, clearSummaryDirtyAfterBuild, } from '../store/summaries.js';
|
|
4
|
+
import { RejectedValueError } from '../core/api-errors.js';
|
|
5
5
|
import { generateDagSummary } from './dag-summary.js';
|
|
6
|
-
import {
|
|
6
|
+
import { overlapPartners } from './overlap-index.js';
|
|
7
|
+
import { derivationScope, derivationPartitionKey } from '../core/recall-scope.js';
|
|
7
8
|
import { loadConfig } from '../core/config.js';
|
|
8
9
|
import { neverAutoShareTags } from '../sharing/share.js';
|
|
9
10
|
import { errorFields, errorMessage, log } from '../util/log.js';
|
|
10
11
|
const SUMMARY_FALLBACK_CHARS = 40;
|
|
11
12
|
const DEFAULT_REBUILD_CAP = 20;
|
|
13
|
+
// Facts join a cluster when their tag sets overlap at least this much.
|
|
14
|
+
const CLUSTER_JACCARD_MIN = 0.5;
|
|
12
15
|
export function clusterFacts(facts) {
|
|
13
16
|
if (facts.length === 0)
|
|
14
17
|
return [];
|
|
15
18
|
const entityTags = facts.map((f) => f.tags.filter((t) => t.startsWith('speaker:') || t.startsWith('topic:')));
|
|
19
|
+
const tagSets = entityTags.map((tags) => new Set(tags));
|
|
20
|
+
// Every tag indexed, not a prefix: a repeated tag counts twice in `shared`, so the prefix-filter bound would not hold.
|
|
21
|
+
const partnersOf = overlapPartners(tagSets, () => 1);
|
|
16
22
|
const assigned = new Set();
|
|
17
23
|
const clusters = [];
|
|
18
24
|
for (let i = 0; i < facts.length; i++) {
|
|
@@ -20,19 +26,18 @@ export function clusterFacts(facts) {
|
|
|
20
26
|
continue;
|
|
21
27
|
const cluster = [i];
|
|
22
28
|
assigned.add(i);
|
|
23
|
-
for (
|
|
29
|
+
for (const j of partnersOf(i)) {
|
|
24
30
|
if (assigned.has(j))
|
|
25
31
|
continue;
|
|
26
|
-
const shared = entityTags[i].filter((t) =>
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
if (jaccard >= 0.5) {
|
|
32
|
+
const shared = entityTags[i].filter((t) => tagSets[j].has(t)).length;
|
|
33
|
+
const inBoth = [...tagSets[i]].filter((t) => tagSets[j].has(t)).length;
|
|
34
|
+
if (shared / (tagSets[i].size + tagSets[j].size - inBoth) >= CLUSTER_JACCARD_MIN) {
|
|
30
35
|
cluster.push(j);
|
|
31
36
|
assigned.add(j);
|
|
32
37
|
}
|
|
33
38
|
}
|
|
34
39
|
const members = cluster.map((idx) => facts[idx]);
|
|
35
|
-
const sharedTags = entityTags[cluster[0]].filter((t) => cluster.every((idx) =>
|
|
40
|
+
const sharedTags = entityTags[cluster[0]].filter((t) => cluster.every((idx) => tagSets[idx].has(t)));
|
|
36
41
|
const label = sharedTags
|
|
37
42
|
.map((t) => t.split(':')[1])
|
|
38
43
|
.join(': ') || members[0].content.slice(0, SUMMARY_FALLBACK_CHARS);
|
|
@@ -45,7 +50,7 @@ export function clusterFacts(facts) {
|
|
|
45
50
|
function partitionFactsByTenant(unparented) {
|
|
46
51
|
const unparentedByTenant = new Map();
|
|
47
52
|
for (const fact of unparented) {
|
|
48
|
-
const key = derivationPartitionKey(fact.
|
|
53
|
+
const key = derivationPartitionKey(fact.tenant_id, fact.scope, fact.origin_project);
|
|
49
54
|
const bucket = unparentedByTenant.get(key);
|
|
50
55
|
if (bucket)
|
|
51
56
|
bucket.push(fact);
|
|
@@ -98,7 +103,7 @@ async function summarizeCluster(hippoRoot, cluster, home, opts, result) {
|
|
|
98
103
|
result.factsLinked += writeEntriesTogether(hippoRoot, cluster.members.map((member) => ({ ...member, dag_parent_id: summaryEntry.id })));
|
|
99
104
|
// Member writes just marked this fresh summary dirty; clear it, or the same sleep cycle's
|
|
100
105
|
// rebuild pass would re-rebuild every new summary at twice the LLM cost.
|
|
101
|
-
clearSummaryDirtyAfterBuild(hippoRoot, summaryEntry.id, summaryEntry.
|
|
106
|
+
clearSummaryDirtyAfterBuild(hippoRoot, summaryEntry.id, summaryEntry.tenant_id, 'buildDag');
|
|
102
107
|
}
|
|
103
108
|
export async function buildDag(hippoRoot, facts, opts) {
|
|
104
109
|
const result = { candidateClusters: 0, summariesCreated: 0, factsLinked: 0, rejected: 0 };
|
|
@@ -106,7 +111,7 @@ export async function buildDag(hippoRoot, facts, opts) {
|
|
|
106
111
|
const unparented = facts.filter((f) => f.dag_level === 1 && !f.dag_parent_id && f.tags.includes('extracted'));
|
|
107
112
|
for (const [, tenantFacts] of partitionFactsByTenant(unparented)) {
|
|
108
113
|
const home = {
|
|
109
|
-
tenantId: tenantFacts[0].
|
|
114
|
+
tenantId: tenantFacts[0].tenant_id,
|
|
110
115
|
scope: derivationScope(tenantFacts[0].scope),
|
|
111
116
|
originProject: tenantFacts[0].origin_project,
|
|
112
117
|
baseHalfLifeDays,
|
|
@@ -121,8 +126,11 @@ export async function buildDag(hippoRoot, facts, opts) {
|
|
|
121
126
|
return result;
|
|
122
127
|
}
|
|
123
128
|
/** Regenerate one dirty summary from its children and tally the outcome; throws reach the caller's isolation. */
|
|
124
|
-
async function rebuildOneSummary(hippoRoot, summary, opts, result) {
|
|
125
|
-
|
|
129
|
+
async function rebuildOneSummary(hippoRoot, summary, opts, result, preloaded, queuedIds) {
|
|
130
|
+
// A queued child may have been rebuilt earlier in this drain, so its preloaded content is stale: reread then.
|
|
131
|
+
const children = preloaded.some((c) => queuedIds.has(c.id))
|
|
132
|
+
? loadChildrenOfSummary(hippoRoot, summary.id, summary.tenant_id)
|
|
133
|
+
: preloaded;
|
|
126
134
|
if (children.length === 0) {
|
|
127
135
|
clearZeroChildSummary(hippoRoot, summary, result);
|
|
128
136
|
return;
|
|
@@ -179,7 +187,8 @@ function summaryLabel(summary) {
|
|
|
179
187
|
* A concurrent sleep's second writer gets changed=false (UPDATE requires summary_dirty=1) and is skipped silently; a tombstone hit counts as `refused`. */
|
|
180
188
|
export async function rebuildDirtySummaries(hippoRoot, opts) {
|
|
181
189
|
const cap = opts.cap ?? DEFAULT_REBUILD_CAP;
|
|
182
|
-
|
|
190
|
+
// One past the cap tells whether more were waiting without reading the rest.
|
|
191
|
+
const dirty = loadAllDirtySummaries(hippoRoot, cap + 1);
|
|
183
192
|
const capped = dirty.length > cap;
|
|
184
193
|
const queue = dirty.slice(0, cap);
|
|
185
194
|
const result = {
|
|
@@ -190,6 +199,8 @@ export async function rebuildDirtySummaries(hippoRoot, opts) {
|
|
|
190
199
|
failed: 0,
|
|
191
200
|
capped,
|
|
192
201
|
};
|
|
202
|
+
const childrenByParent = loadChildrenOfSummaries(hippoRoot, queue);
|
|
203
|
+
const queuedIds = new Set(queue.map((s) => s.id));
|
|
193
204
|
for (const [index, summary] of queue.entries()) {
|
|
194
205
|
// Yield the macrotask queue every 25 summaries: each iteration is synchronous SQLite, so a batch of up to 1000
|
|
195
206
|
// would starve timers and IPC (server keep-alives, Vitest's birpc heartbeat).
|
|
@@ -197,13 +208,13 @@ export async function rebuildDirtySummaries(hippoRoot, opts) {
|
|
|
197
208
|
await new Promise((resolve) => setImmediate(resolve));
|
|
198
209
|
}
|
|
199
210
|
try {
|
|
200
|
-
await rebuildOneSummary(hippoRoot, summary, opts, result);
|
|
211
|
+
await rebuildOneSummary(hippoRoot, summary, opts, result, childrenByParent.get(childrenKey(summary.tenant_id, summary.id)) ?? [], queuedIds);
|
|
201
212
|
}
|
|
202
213
|
catch (err) {
|
|
203
214
|
// One throw doesn't abort the queue; log enough to triage an exotic
|
|
204
215
|
// failure (SQLite I/O, prepare), since audit() already catches its own.
|
|
205
216
|
result.failed++;
|
|
206
|
-
log.error(`rebuildDirtySummaries: summary ${summary.id} (tenant ${summary.
|
|
217
|
+
log.error(`rebuildDirtySummaries: summary ${summary.id} (tenant ${summary.tenant_id}) failed: ${errorMessage(err)}`, errorFields(err));
|
|
207
218
|
}
|
|
208
219
|
}
|
|
209
220
|
return result;
|
|
@@ -269,7 +280,7 @@ export async function buildEntityProfiles(hippoRoot, l2Summaries, opts) {
|
|
|
269
280
|
const unparented = l2Summaries.filter((s) => s.dag_level === 2 && !s.dag_parent_id);
|
|
270
281
|
for (const [, tenantL2s] of partitionFactsByTenant(unparented)) {
|
|
271
282
|
const home = {
|
|
272
|
-
tenantId: tenantL2s[0].
|
|
283
|
+
tenantId: tenantL2s[0].tenant_id,
|
|
273
284
|
scope: derivationScope(tenantL2s[0].scope),
|
|
274
285
|
originProject: tenantL2s[0].origin_project,
|
|
275
286
|
baseHalfLifeDays,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** Store-level dedup: same text apart from spacing, keeping the stronger copy; split out so `api.sleep` can dedupe without cli -> api imports.
|
|
2
2
|
* Survivor order is total and tenant-scoped: strength bucket, retrieval_count, then compareEntryIdentity; raw and superseded rows are not candidates. */
|
|
3
|
+
import { type MemoryEntry } from '../core/memory.js';
|
|
3
4
|
export interface DedupPair {
|
|
4
5
|
kept: string;
|
|
5
6
|
keptContent: string;
|
|
@@ -19,11 +20,17 @@ export interface DedupResult {
|
|
|
19
20
|
/** Quantize strength to an integer bucket so ties are a true equivalence relation (equal iff same multiple of `STRENGTH_TIE_EPSILON`).
|
|
20
21
|
* Non-finite input maps to 0: a NaN bucket would make the comparator return NaN and break the total order. */
|
|
21
22
|
export declare function strengthBucket(strength: number | null | undefined): number;
|
|
23
|
+
/** Every row of the store, read once by a caller that also needs them, with the ids of rows backing an object. */
|
|
24
|
+
export interface LoadedStore {
|
|
25
|
+
readonly entries: readonly MemoryEntry[];
|
|
26
|
+
readonly backing: ReadonlySet<string>;
|
|
27
|
+
}
|
|
22
28
|
/** Remove the weaker copy of same-text (apart from spacing) memories within one tenant; cross-tenant pairs are never duplicates (isolation boundary).
|
|
23
29
|
* Higher strength wins, then more retrievals; `threshold` is accepted for old callers and ignored. */
|
|
24
30
|
export declare function deduplicateStore(hippoRoot: string, options?: {
|
|
25
31
|
threshold?: number;
|
|
26
32
|
dryRun?: boolean;
|
|
27
33
|
actor?: string;
|
|
34
|
+
loaded?: LoadedStore;
|
|
28
35
|
}): DedupResult;
|
|
29
36
|
//# sourceMappingURL=dedupe.d.ts.map
|
|
@@ -5,7 +5,7 @@ import { loadCurrentDistilledEntries } from '../store/entry-reads.js';
|
|
|
5
5
|
import { deleteEntriesOneByOne, memoriesBackingObjects } from '../store/delete-and-batch.js';
|
|
6
6
|
import { compareEntryIdentity } from '../core/compare.js';
|
|
7
7
|
import { canAutoDelete } from '../core/memory.js';
|
|
8
|
-
import { derivationPartitionKey } from '../
|
|
8
|
+
import { derivationPartitionKey } from '../core/recall-scope.js';
|
|
9
9
|
import { duplicateKey } from '../util/same-text.js';
|
|
10
10
|
/** Quantization step for strength-tie comparisons: the 0.01 epsilon applied by rounding instead of an abs-diff threshold, so the tiebreak is transitive. */
|
|
11
11
|
const STRENGTH_TIE_EPSILON = 0.01;
|
|
@@ -34,7 +34,7 @@ function entriesByPartition(entries) {
|
|
|
34
34
|
const entriesByTenant = new Map();
|
|
35
35
|
for (const entry of entries) {
|
|
36
36
|
// EI2: also split by restricted scope, else a private copy can delete the readable one.
|
|
37
|
-
const key = derivationPartitionKey(entry.
|
|
37
|
+
const key = derivationPartitionKey(entry.tenant_id, entry.scope, entry.origin_project);
|
|
38
38
|
const bucket = entriesByTenant.get(key);
|
|
39
39
|
if (bucket)
|
|
40
40
|
bucket.push(entry);
|
|
@@ -73,18 +73,20 @@ function partitionPairs(tenantEntries, removed, backing) {
|
|
|
73
73
|
}
|
|
74
74
|
return [...groups.values()].flatMap((group) => group.pairs);
|
|
75
75
|
}
|
|
76
|
+
/** The rows loadCurrentDistilledEntries selects, picked from a whole-store read. */
|
|
77
|
+
const isCurrentDistilled = (e) => (e.kind ?? 'distilled') === 'distilled' && !e.superseded_by;
|
|
76
78
|
/** Remove the weaker copy of same-text (apart from spacing) memories within one tenant; cross-tenant pairs are never duplicates (isolation boundary).
|
|
77
79
|
* Higher strength wins, then more retrievals; `threshold` is accepted for old callers and ignored. */
|
|
78
80
|
export function deduplicateStore(hippoRoot, options = {}) {
|
|
79
81
|
const dryRun = options.dryRun ?? false;
|
|
80
82
|
// Only current distilled rows compete: raw rows are append-only (the delete
|
|
81
83
|
// trigger would abort sleep mid-loop) and superseded rows are history.
|
|
82
|
-
const entries = loadCurrentDistilledEntries(hippoRoot);
|
|
84
|
+
const entries = options.loaded?.entries.filter(isCurrentDistilled) ?? loadCurrentDistilledEntries(hippoRoot);
|
|
83
85
|
const entriesByTenant = entriesByPartition(entries);
|
|
84
86
|
// Shared across tenant groups: ids are globally unique UUIDs, so `removed` cannot collide across tenants and deleteEntry deletes by primary key alone.
|
|
85
87
|
const removed = new Set();
|
|
86
88
|
const pairs = [];
|
|
87
|
-
const backing = memoriesBackingObjects(hippoRoot);
|
|
89
|
+
const backing = options.loaded?.backing ?? memoriesBackingObjects(hippoRoot);
|
|
88
90
|
for (const tenantEntries of entriesByTenant.values()) {
|
|
89
91
|
// The survivor total order (see the file-level docstring), scoped per
|
|
90
92
|
// tenant group: the total order holds within a tenant only, matching the partition above.
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { envAnthropicApiKey, envDagRebuildCap } from '../util/env.js';
|
|
2
2
|
import { Layer } from '../core/memory.js';
|
|
3
|
-
import { log } from '../util/log.js';
|
|
3
|
+
import { errorFields, errorMessage, log } from '../util/log.js';
|
|
4
4
|
import { keptAsWritten } from './run.js';
|
|
5
5
|
import { isReusable } from '../core/memory-quality.js';
|
|
6
|
+
import { isPermanentFailure } from '../util/anthropic-messages.js';
|
|
7
|
+
// Bounds the LLM calls one sleep spends on extraction.
|
|
8
|
+
const EXTRACTION_BATCH_LIMIT = 20;
|
|
6
9
|
/** The key, model options and once-per-line error reporter every LLM phase shares. */
|
|
7
10
|
function sleepLlm(run, fetcher) {
|
|
8
11
|
const { config, result } = run;
|
|
@@ -28,21 +31,10 @@ export async function llmPasses(run, fetcher) {
|
|
|
28
31
|
run.result.extractionCandidates = extractionCandidates.length;
|
|
29
32
|
const llm = sleepLlm(run, fetcher);
|
|
30
33
|
if (llm.apiKey && extractionCandidates.length > 0 && !run.dryRun) {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
const facts = await extractFacts(candidate.content, { ...llm.llmOpts, onError: llm.llmError('extraction') });
|
|
37
|
-
if (facts.length > 0) {
|
|
38
|
-
extractedCount += storeExtractedFacts(run.hippoRoot, candidate, facts).length;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
catch (err) {
|
|
42
|
-
llm.llmError('extraction')(String(err));
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
run.result.extracted = extractedCount;
|
|
34
|
+
const stopped = await extractionPass(run, llm, extractionCandidates.slice(0, EXTRACTION_BATCH_LIMIT));
|
|
35
|
+
// The DAG passes call the same API with the same key and model, so they would fail the same way.
|
|
36
|
+
if (stopped)
|
|
37
|
+
return;
|
|
46
38
|
}
|
|
47
39
|
await dagBuildPass(run, llm);
|
|
48
40
|
if (llm.apiKey && !run.dryRun) {
|
|
@@ -50,6 +42,37 @@ export async function llmPasses(run, fetcher) {
|
|
|
50
42
|
await entityProfilePass(run, llm);
|
|
51
43
|
}
|
|
52
44
|
}
|
|
45
|
+
/** Extracts facts from each candidate; true when it stopped on a failure every later call would repeat (bad key, no credit, unknown model). */
|
|
46
|
+
async function extractionPass(run, llm, batch) {
|
|
47
|
+
const { extractFacts, storeExtractedFacts } = await import('../learn/extract.js');
|
|
48
|
+
const report = llm.llmError('extraction');
|
|
49
|
+
let extractedCount = 0;
|
|
50
|
+
let stopped = false;
|
|
51
|
+
const onError = (msg, failure) => {
|
|
52
|
+
report(msg);
|
|
53
|
+
if (failure && isPermanentFailure(failure))
|
|
54
|
+
stopped = true;
|
|
55
|
+
};
|
|
56
|
+
for (const [index, candidate] of batch.entries()) {
|
|
57
|
+
try {
|
|
58
|
+
const facts = await extractFacts(candidate.content, { ...llm.llmOpts, onError });
|
|
59
|
+
if (facts.length > 0) {
|
|
60
|
+
extractedCount += storeExtractedFacts(run.hippoRoot, candidate, facts).length;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
report(errorMessage(err));
|
|
65
|
+
log.warn('consolidate extraction threw', errorFields(err));
|
|
66
|
+
}
|
|
67
|
+
if (stopped) {
|
|
68
|
+
const skipped = batch.length - index - 1;
|
|
69
|
+
report(`stopped after a failure that will not clear on retry; ${skipped} of ${batch.length} candidates skipped, and the DAG passes with them`);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
run.result.extracted = extractedCount;
|
|
74
|
+
return stopped;
|
|
75
|
+
}
|
|
53
76
|
// 1.7. DAG summarization — cluster extracted facts and generate summaries
|
|
54
77
|
async function dagBuildPass(run, { apiKey, llmError, llmOpts }) {
|
|
55
78
|
const extractedFacts = run.survivors.filter((e) => e.tags.includes('extracted') && e.dag_level === 1 && !e.superseded_by && isReusable(e));
|
|
@@ -65,7 +88,8 @@ async function dagBuildPass(run, { apiKey, llmError, llmOpts }) {
|
|
|
65
88
|
}
|
|
66
89
|
}
|
|
67
90
|
catch (err) {
|
|
68
|
-
llmError('dag')(
|
|
91
|
+
llmError('dag')(errorMessage(err));
|
|
92
|
+
log.warn('consolidate dag threw', errorFields(err));
|
|
69
93
|
}
|
|
70
94
|
}
|
|
71
95
|
// 1.8. DAG summary rebuild: drain the summary_dirty queue set by child-write hooks; same apiKey/dryRun gate as buildDag.
|
|
@@ -99,7 +123,8 @@ async function dagRebuildPass(run, { llmError, llmOpts }) {
|
|
|
99
123
|
}
|
|
100
124
|
}
|
|
101
125
|
catch (err) {
|
|
102
|
-
llmError('dag rebuild')(
|
|
126
|
+
llmError('dag rebuild')(errorMessage(err));
|
|
127
|
+
log.warn('consolidate dag rebuild threw', errorFields(err));
|
|
103
128
|
}
|
|
104
129
|
}
|
|
105
130
|
// 1.9. DAG entity profiles: cluster L2 summaries into per-entity L3 profiles; runs even when 1.7 was skipped (re-clusters existing L2s every sleep).
|
|
@@ -118,7 +143,8 @@ async function entityProfilePass(run, { llmError, llmOpts }) {
|
|
|
118
143
|
}
|
|
119
144
|
}
|
|
120
145
|
catch (err) {
|
|
121
|
-
llmError('dag profiles')(
|
|
146
|
+
llmError('dag profiles')(errorMessage(err));
|
|
147
|
+
log.warn('consolidate dag profiles threw', errorFields(err));
|
|
122
148
|
}
|
|
123
149
|
}
|
|
124
150
|
//# sourceMappingURL=llm-passes.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** Learned memory-value scorer, a rescue-only veto in the sleep decay pass (it can only shrink the condemned set); mirrors benchmarks/memory-value/*.mjs.
|
|
2
2
|
* rescueSet rescues a condemned entry iff it ranks in the top 30% (RESCUE_BUDGET) of its tenant's non-pinned set; memory-value-wiring.test.ts guards parity. */
|
|
3
3
|
import { DEFAULT_TENANT_ID } from '../util/env.js';
|
|
4
|
+
import { strengthAblation } from '../core/ablation.js';
|
|
4
5
|
import { calculateStrength } from '../core/memory.js';
|
|
5
6
|
import { compareEntryIdentity } from '../core/compare.js';
|
|
6
7
|
import { MEMORY_VALUE_WEIGHTS, SOURCE_ARTIFACT_SHA256 } from './memory-value-weights.js';
|
|
@@ -31,7 +32,7 @@ export function computeMvFeatures(entry, now) {
|
|
|
31
32
|
return {
|
|
32
33
|
age_days: ageDays,
|
|
33
34
|
half_life_days: entry.half_life_days,
|
|
34
|
-
strength: calculateStrength(entry, now), // clock-basis, never
|
|
35
|
+
strength: calculateStrength(entry, now, { ablation: strengthAblation() }), // clock-basis, never the production decay basis — see doc comment above
|
|
35
36
|
retrieval_count: entry.retrieval_count,
|
|
36
37
|
outcome_positive: pos,
|
|
37
38
|
outcome_negative: neg,
|
|
@@ -113,7 +114,7 @@ export function rankNonPinnedByTenant(entries, now, weights = MEMORY_VALUE_WEIGH
|
|
|
113
114
|
continue; // pinned entries never compete for rescue (never condemned)
|
|
114
115
|
// Default an undefined tenantId as dag.ts:341 does: a raw/legacy row can carry one at runtime,
|
|
115
116
|
// and keying it "undefined" would split it into its own singleton tenant.
|
|
116
|
-
const tenantId = e.
|
|
117
|
+
const tenantId = e.tenant_id ?? DEFAULT_TENANT_ID;
|
|
117
118
|
const list = byTenant.get(tenantId);
|
|
118
119
|
if (list)
|
|
119
120
|
list.push(e);
|
|
@@ -3,10 +3,10 @@ import { tokenize } from '../util/tokenize.js';
|
|
|
3
3
|
import { jaccardMinShared, overlapPartners } from './overlap-index.js';
|
|
4
4
|
import { compareEntryIdentity } from '../core/compare.js';
|
|
5
5
|
import { duplicateKey, mergedText } from '../util/same-text.js';
|
|
6
|
-
import { successorAfterRetirement } from '
|
|
6
|
+
import { successorAfterRetirement } from '../core/merged-row.js';
|
|
7
7
|
import { rejectionDigest } from '../store/rejection.js';
|
|
8
8
|
import { reportAuditWriteFailure } from '../store/audit.js';
|
|
9
|
-
import { derivationScope, derivationPartitionKey } from '../
|
|
9
|
+
import { derivationScope, derivationPartitionKey } from '../core/recall-scope.js';
|
|
10
10
|
import { jaccardSets } from './conflicts.js';
|
|
11
11
|
import { keptAsWritten } from './run.js';
|
|
12
12
|
import { isReusable } from '../core/memory-quality.js';
|
|
@@ -23,7 +23,7 @@ export function retireHeldTexts(run) {
|
|
|
23
23
|
const rejectedIn = (tenantId) => (text) => run.tombstones.find(tenantId, rejectionDigest(text)) !== null;
|
|
24
24
|
for (let i = survivors.length - 1; i >= 0; i--) {
|
|
25
25
|
const row = survivors[i];
|
|
26
|
-
const successor = run.retirable(row) ? successorAfterRetirement(row, byId, rejectedIn(row.
|
|
26
|
+
const successor = run.retirable(row) ? successorAfterRetirement(row, byId, rejectedIn(row.tenant_id)) : undefined;
|
|
27
27
|
if (successor === undefined)
|
|
28
28
|
continue;
|
|
29
29
|
run.result.details.push(` ✂️ ${row.id} held a retired text${successor ? `, ${successor.id} holds the rest` : ''}`);
|
|
@@ -51,7 +51,7 @@ function partitionMergeCandidates(survivors) {
|
|
|
51
51
|
// Map keeps insertion order, so a single-tenant store gets one partition in the original order.
|
|
52
52
|
const mergeCandidatesByTenant = new Map();
|
|
53
53
|
for (const entry of mergeCandidates) {
|
|
54
|
-
const key = derivationPartitionKey(entry.
|
|
54
|
+
const key = derivationPartitionKey(entry.tenant_id, entry.scope, entry.origin_project);
|
|
55
55
|
const bucket = mergeCandidatesByTenant.get(key);
|
|
56
56
|
if (bucket)
|
|
57
57
|
bucket.push(entry);
|
|
@@ -70,7 +70,7 @@ export function mergePass(run) {
|
|
|
70
70
|
let mergesSkippedRejected = 0;
|
|
71
71
|
for (const [, tenantCandidates] of mergeCandidatesByTenant) {
|
|
72
72
|
const partition = {
|
|
73
|
-
tenantId: tenantCandidates[0].
|
|
73
|
+
tenantId: tenantCandidates[0].tenant_id,
|
|
74
74
|
scope: derivationScope(tenantCandidates[0].scope),
|
|
75
75
|
origin: tenantCandidates[0].origin_project,
|
|
76
76
|
};
|
|
@@ -156,8 +156,8 @@ function mergeRejected(run, semantic, cluster, related, used) {
|
|
|
156
156
|
const { tombstones } = run;
|
|
157
157
|
const newDigest = rejectionDigest(semantic.content);
|
|
158
158
|
const oldDigest = rejectionDigest(legacyMergeContents(related)); // tombstones from older releases hold this format's digest
|
|
159
|
-
const newHit = tombstones.find(semantic.
|
|
160
|
-
const tombstone = newHit ?? tombstones.find(semantic.
|
|
159
|
+
const newHit = tombstones.find(semantic.tenant_id, newDigest);
|
|
160
|
+
const tombstone = newHit ?? tombstones.find(semantic.tenant_id, oldDigest);
|
|
161
161
|
const mergeDigest = newHit ? newDigest : oldDigest;
|
|
162
162
|
if (!tombstone)
|
|
163
163
|
return false;
|
|
@@ -167,7 +167,7 @@ function mergeRejected(run, semantic, cluster, related, used) {
|
|
|
167
167
|
used.add(e.id);
|
|
168
168
|
try {
|
|
169
169
|
tombstones.audit({
|
|
170
|
-
tenantId: semantic.
|
|
170
|
+
tenantId: semantic.tenant_id,
|
|
171
171
|
actor: 'sleep',
|
|
172
172
|
op: 'reject_refusal',
|
|
173
173
|
metadata: {
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import { type PhysicsParticle } from '../core/physics.js';
|
|
2
|
+
import type { MemoryEntry } from '../core/memory.js';
|
|
1
3
|
import type { SleepRun } from './run.js';
|
|
2
|
-
export declare function physicsPass(run: SleepRun): void;
|
|
4
|
+
export declare function physicsPass(run: SleepRun, maxParticles?: number): void;
|
|
5
|
+
/** Every stored particle in load order up to the cap; past it, the most recently recalled survivors (memory id breaks ties),
|
|
6
|
+
* then particles with no survivor. */
|
|
7
|
+
export declare function particlesToSimulate(stored: PhysicsParticle[], entries: ReadonlyMap<string, MemoryEntry>, max?: number): PhysicsParticle[];
|
|
3
8
|
//# sourceMappingURL=physics-pass.d.ts.map
|
|
@@ -3,8 +3,10 @@ import { loadStoredParticles, saveStoredParticles } from '../store/vector-index.
|
|
|
3
3
|
import { simulate } from '../core/physics.js';
|
|
4
4
|
import { errorMessage } from '../util/log.js';
|
|
5
5
|
const STATS_DECIMALS = 4;
|
|
6
|
+
// Every substep is all-pairs, so one sleep moves at most this many particles; the rest keep their stored state until they are recalled.
|
|
7
|
+
const SLEEP_PHYSICS_MAX_PARTICLES = 1000;
|
|
6
8
|
// 2. Physics simulation pass
|
|
7
|
-
export function physicsPass(run) {
|
|
9
|
+
export function physicsPass(run, maxParticles = SLEEP_PHYSICS_MAX_PARTICLES) {
|
|
8
10
|
if (run.dryRun)
|
|
9
11
|
return;
|
|
10
12
|
const { config, result } = run;
|
|
@@ -12,27 +14,45 @@ export function physicsPass(run) {
|
|
|
12
14
|
const physicsEnabled = config.physics.enabled === true
|
|
13
15
|
|| (config.physics.enabled === 'auto');
|
|
14
16
|
if (physicsEnabled)
|
|
15
|
-
simulateStoredParticles(run);
|
|
17
|
+
simulateStoredParticles(run, maxParticles);
|
|
16
18
|
}
|
|
17
19
|
catch (error) {
|
|
18
20
|
result.details.push(` ⚠️ physics simulation skipped: ${errorMessage(error)}`);
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
|
-
function simulateStoredParticles(run) {
|
|
23
|
+
function simulateStoredParticles(run, maxParticles) {
|
|
22
24
|
const { result, survivors } = run;
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
25
|
+
const stored = loadStoredParticles(run.hippoRoot);
|
|
26
|
+
if (stored.length === 0)
|
|
25
27
|
return;
|
|
26
28
|
// Build entry lookup for property refresh
|
|
27
29
|
const entryMap = new Map(survivors.map(e => [e.id, e]));
|
|
30
|
+
const particles = particlesToSimulate(stored, entryMap, maxParticles);
|
|
28
31
|
refreshParticleProperties(particles, entryMap, run.now);
|
|
29
32
|
const stats = simulate(particles, survivorForces(run));
|
|
30
33
|
saveStoredParticles(run.hippoRoot, particles);
|
|
31
34
|
result.physicsSimulated = stats.particleCount;
|
|
32
|
-
|
|
35
|
+
const capped = particles.length < stored.length ? ` (the ${particles.length} most recently recalled of ${stored.length})` : '';
|
|
36
|
+
result.details.push(` ⚛️ physics: ${stats.particleCount} particles${capped}, ` +
|
|
33
37
|
`avg vel ${stats.avgVelocityMagnitude.toFixed(STATS_DECIMALS)}, ` +
|
|
34
38
|
`energy ${stats.energy.total.toFixed(STATS_DECIMALS)}`);
|
|
35
39
|
}
|
|
40
|
+
/** Every stored particle in load order up to the cap; past it, the most recently recalled survivors (memory id breaks ties),
|
|
41
|
+
* then particles with no survivor. */
|
|
42
|
+
export function particlesToSimulate(stored, entries, max = SLEEP_PHYSICS_MAX_PARTICLES) {
|
|
43
|
+
if (stored.length <= max)
|
|
44
|
+
return stored;
|
|
45
|
+
const recalled = (p) => entries.get(p.memoryId)?.last_retrieved ?? '';
|
|
46
|
+
const ranked = [...stored].sort((a, b) => {
|
|
47
|
+
const [ra, rb] = [recalled(a), recalled(b)];
|
|
48
|
+
if (ra !== rb)
|
|
49
|
+
return ra < rb ? 1 : -1;
|
|
50
|
+
return a.memoryId < b.memoryId ? -1 : a.memoryId > b.memoryId ? 1 : 0;
|
|
51
|
+
});
|
|
52
|
+
const kept = new Set(ranked.slice(0, max));
|
|
53
|
+
// Load order, not rank order: the force sums run in this order, so a capped run matches an uncapped one over the same set.
|
|
54
|
+
return stored.filter((p) => kept.has(p));
|
|
55
|
+
}
|
|
36
56
|
function survivorForces(run) {
|
|
37
57
|
// Build conflict pairs from survivors
|
|
38
58
|
const conflictPairs = new Map();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** Replay: during `hippo sleep`, sample N survivors weighted by reward, valence, under-rehearsal and age, then apply the `markRetrieved` strengthening.
|
|
2
2
|
* A lightweight deterministic analog of hippocampal replay, so important memories stay strong without being queried; distinct from decay, physics and merge. */
|
|
3
|
+
import { HOUR_MS } from '../util/time.js';
|
|
3
4
|
import { isOutcomeSlowAblated } from '../core/ablation.js';
|
|
4
5
|
import { resolveConfidence } from '../core/memory.js';
|
|
5
6
|
const VALENCE_WEIGHT = {
|
|
@@ -8,6 +9,12 @@ const VALENCE_WEIGHT = {
|
|
|
8
9
|
negative: 1.5,
|
|
9
10
|
critical: 2.0,
|
|
10
11
|
};
|
|
12
|
+
// Floor keeps every weight positive for sampleForReplay; the rest scale reward and idle boosts.
|
|
13
|
+
const REWARD_FLOOR = 0.1;
|
|
14
|
+
const REWARD_POSITIVE_GAIN = 0.5;
|
|
15
|
+
const REWARD_NET_GAIN = 0.25;
|
|
16
|
+
const IDLE_BOOST_GAIN = 0.1;
|
|
17
|
+
const STRENGTH_FLOOR = 0.1;
|
|
11
18
|
/** Priority score for ranking survivors for replay (higher = more likely sampled); pure in the entry and current time. */
|
|
12
19
|
export function replayPriority(entry, now, outcomeAblated) {
|
|
13
20
|
const pos = entry.outcome_positive ?? 0;
|
|
@@ -16,18 +23,18 @@ export function replayPriority(entry, now, outcomeAblated) {
|
|
|
16
23
|
// The clamp is required because sampleForReplay needs all weights positive.
|
|
17
24
|
const rewardSignal = outcomeAblated
|
|
18
25
|
? 1.0 // EVAL-ONLY ablation (see ablation.ts): outcome-off also silences replay's reward bias
|
|
19
|
-
: Math.max(
|
|
26
|
+
: Math.max(REWARD_FLOOR, 1 + pos * REWARD_POSITIVE_GAIN + (pos - neg) * REWARD_NET_GAIN);
|
|
20
27
|
const valence = VALENCE_WEIGHT[entry.emotional_valence] ?? 1.0;
|
|
21
28
|
// Under-rehearsed memories benefit most from replay.
|
|
22
29
|
const underRehearsed = 1 / (1 + (entry.retrieval_count ?? 0));
|
|
23
30
|
// Idle-time boost: memories that haven't been touched recently need rehearsal more.
|
|
24
31
|
const lastRetrieved = new Date(entry.last_retrieved);
|
|
25
32
|
const deltaMs = now.getTime() - lastRetrieved.getTime();
|
|
26
|
-
const ageHours = Number.isFinite(deltaMs) ? Math.max(0, deltaMs /
|
|
27
|
-
const idleBoost = 1 + Math.log1p(ageHours) *
|
|
33
|
+
const ageHours = Number.isFinite(deltaMs) ? Math.max(0, deltaMs / HOUR_MS) : 0;
|
|
34
|
+
const idleBoost = 1 + Math.log1p(ageHours) * IDLE_BOOST_GAIN;
|
|
28
35
|
// Weight by current strength so dead-and-decaying memories don't waste replay slots.
|
|
29
36
|
const rawStrength = Number.isFinite(entry.strength) ? entry.strength : 0;
|
|
30
|
-
const strengthFloor = Math.max(
|
|
37
|
+
const strengthFloor = Math.max(STRENGTH_FLOOR, rawStrength);
|
|
31
38
|
return rewardSignal * valence * underRehearsed * idleBoost * strengthFloor;
|
|
32
39
|
}
|
|
33
40
|
/** Deterministic 32-bit RNG (Mulberry32): same seed, same sequence, so replay is reproducible without a random-number dependency. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Consolidation engine ("Sleep"): decay pass (drop entries below the strength threshold), merge pass (semantic summaries of overlapping episodics), stats. */
|
|
2
|
-
import { evalNow } from '../core/ablation.js';
|
|
2
|
+
import { evalNow, strengthAblation } from '../core/ablation.js';
|
|
3
3
|
import { canAutoDelete } from '../core/memory.js';
|
|
4
4
|
import { loadAllEntriesWithBase } from '../store/entry-reads.js';
|
|
5
5
|
import { commitInChunks, memoriesBackingObjects } from '../store/delete-and-batch.js';
|
|
@@ -11,7 +11,7 @@ import { loadConfig } from '../core/config.js';
|
|
|
11
11
|
import { recordAuditEventsRowByRow, reportAuditWriteFailure } from '../store/audit.js';
|
|
12
12
|
import { lazyTombstoneChecks } from '../store/tombstone-checks.js';
|
|
13
13
|
import { migrateDefaultHalfLife, LEGACY_TYPED_HALF_LIFE } from './half-life-migration.js';
|
|
14
|
-
import { errorMessage, log } from '../util/log.js';
|
|
14
|
+
import { errorFields, errorMessage, log } from '../util/log.js';
|
|
15
15
|
import { WRITE_BUDGET } from '../util/write-budget.js';
|
|
16
16
|
import { decayPass } from './decay.js';
|
|
17
17
|
import { familyUnits, groupFlush } from './flush-units.js';
|
|
@@ -68,6 +68,7 @@ function sessionDecayOptions(hippoRoot, config) {
|
|
|
68
68
|
decayBasis: config.decayBasis,
|
|
69
69
|
avgSessionIntervalDays: sessionCtx.avgSessionIntervalDays,
|
|
70
70
|
sleepCount: sessionCtx.sleepCount,
|
|
71
|
+
ablation: strengthAblation(),
|
|
71
72
|
};
|
|
72
73
|
}
|
|
73
74
|
/** Every pass between decay and the flush; the tombstone-check handle closes whichever of them throws. */
|
|
@@ -96,7 +97,8 @@ function migrateHalfLives(hippoRoot, dryRun, result) {
|
|
|
96
97
|
result.details.push(` ⏳ ${dryRun ? 'would move' : 'moved'} ${halfLife.rescaled} memories from the ${halfLife.from}-day to the ${halfLife.to}-day half-life`);
|
|
97
98
|
}
|
|
98
99
|
if (halfLife.typed > 0) {
|
|
99
|
-
result.details.push(` ⏳ ${dryRun ? 'would move' : 'moved'} ${halfLife.typed} memories of decisions, incidents and other objects
|
|
100
|
+
result.details.push(` ⏳ ${dryRun ? 'would move' : 'moved'} ${halfLife.typed} memories of decisions, incidents and other objects ` +
|
|
101
|
+
`from the ${LEGACY_TYPED_HALF_LIFE}-day to the ${halfLife.to}-day half-life`);
|
|
100
102
|
}
|
|
101
103
|
return halfLife;
|
|
102
104
|
}
|
|
@@ -126,7 +128,8 @@ async function expireDormant(run, budget) {
|
|
|
126
128
|
const cutoff = new Date(run.now.getTime() - config.dormant.retentionDays * DAY_MS).toISOString();
|
|
127
129
|
result.dormantExpired = await expireDormantBefore(run.hippoRoot, cutoff, { dryRun, budget, busyWaitMs: SLEEP_DB_WAIT_MS });
|
|
128
130
|
if (result.dormantExpired > 0) {
|
|
129
|
-
result.details.push(` ⌛ ${dryRun ? 'would expire' : 'expired'} ${result.dormantExpired} dormant memor${result.dormantExpired === 1 ? 'y' : 'ies'}
|
|
131
|
+
result.details.push(` ⌛ ${dryRun ? 'would expire' : 'expired'} ${result.dormantExpired} dormant memor${result.dormantExpired === 1 ? 'y' : 'ies'} ` +
|
|
132
|
+
`older than ${config.dormant.retentionDays} days`);
|
|
130
133
|
}
|
|
131
134
|
}
|
|
132
135
|
// 4. Log run
|
|
@@ -153,7 +156,7 @@ function auditRescues(run, { rescuedEntries, rankById }) {
|
|
|
153
156
|
const rescueEvent = (entry) => {
|
|
154
157
|
const rank = rankById.get(entry.id);
|
|
155
158
|
return {
|
|
156
|
-
tenantId: entry.
|
|
159
|
+
tenantId: entry.tenant_id,
|
|
157
160
|
actor: 'sleep',
|
|
158
161
|
op: 'mv_rescue',
|
|
159
162
|
targetId: entry.id,
|
|
@@ -175,7 +178,7 @@ function auditRescues(run, { rescuedEntries, rankById }) {
|
|
|
175
178
|
}
|
|
176
179
|
catch (err) {
|
|
177
180
|
// An audit store that will not open must never crash the mutation it records.
|
|
178
|
-
log.
|
|
181
|
+
log.warn(`mv_rescue audit unavailable: ${errorMessage(err)}`, { errorClass: errorFields(err).errorClass });
|
|
179
182
|
result.details.push(` ⚠️ memory-value: mv_rescue audit unavailable this cycle ` +
|
|
180
183
|
`(${rescuedEntries.length} rescue${rescuedEntries.length === 1 ? '' : 's'} not audited)`);
|
|
181
184
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isRecallBoostAblated } from '../core/ablation.js';
|
|
1
|
+
import { isRecallBoostAblated, strengthAblation } from '../core/ablation.js';
|
|
2
2
|
import { Layer, createMemory, markRetrieved } from '../core/memory.js';
|
|
3
3
|
import { findPromotableSessions, traceExistsForSession, listSessionEvents } from '../store/sessions.js';
|
|
4
4
|
import { rejectionDigest } from '../store/rejection.js';
|
|
@@ -6,7 +6,7 @@ import { sampleForReplay } from './replay.js';
|
|
|
6
6
|
import { renderTraceContent } from './trace.js';
|
|
7
7
|
import { resolveTenantId } from '../store/tenant.js';
|
|
8
8
|
import { reportAuditWriteFailure } from '../store/audit.js';
|
|
9
|
-
import { commonDerivationScope } from '../
|
|
9
|
+
import { commonDerivationScope } from '../core/recall-scope.js';
|
|
10
10
|
import { log } from '../util/log.js';
|
|
11
11
|
import { REPLAY_COUNT_DEFAULT } from './run.js';
|
|
12
12
|
import { isJsonString } from '../util/json.js';
|
|
@@ -103,12 +103,12 @@ function sessionEnding(events) {
|
|
|
103
103
|
// sleep; check the tombstone under the entry's own stamped tenantId, never a guessed one.
|
|
104
104
|
function traceRejected(run, trace, sessionId) {
|
|
105
105
|
const traceDigest = rejectionDigest(trace.content);
|
|
106
|
-
const tombstone = run.tombstones.find(trace.
|
|
106
|
+
const tombstone = run.tombstones.find(trace.tenant_id, traceDigest);
|
|
107
107
|
if (!tombstone)
|
|
108
108
|
return false;
|
|
109
109
|
try {
|
|
110
110
|
run.tombstones.audit({
|
|
111
|
-
tenantId: trace.
|
|
111
|
+
tenantId: trace.tenant_id,
|
|
112
112
|
actor: 'sleep',
|
|
113
113
|
op: 'reject_refusal',
|
|
114
114
|
metadata: {
|
|
@@ -136,7 +136,7 @@ export function replayPass(run) {
|
|
|
136
136
|
const picked = sampleForReplay(survivors, replayCount, now, seed);
|
|
137
137
|
if (picked.length === 0)
|
|
138
138
|
return;
|
|
139
|
-
const rehearsed = markRetrieved(picked, now);
|
|
139
|
+
const rehearsed = markRetrieved(picked, now, { ablation: strengthAblation() });
|
|
140
140
|
const rehearsedById = new Map(rehearsed.map((e) => [e.id, e]));
|
|
141
141
|
// Update survivors in place so downstream passes see rehearsed state.
|
|
142
142
|
for (let i = 0; i < survivors.length; i++) {
|
package/dist/core/ablation.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
/** EVAL-ONLY ablation switches (HIPPO_ABLATE_*, HIPPO_EVAL_RECENCY_DAYS, HIPPO_FAKE_NOW): each cuts ONE mechanism (outcome also replayPriority bias).
|
|
2
2
|
* Not a production surface. Env is read once per process; tests that mutate these vars MUST call _resetAblationCacheForTests() in beforeEach AND afterEach. See
|
|
3
3
|
* docs/ARCHITECTURE.md#srccoreablationts. */
|
|
4
|
+
/** The three switches strength scoring honours, resolved by the entry layer and handed to core in DecayOptions. */
|
|
5
|
+
export interface StrengthAblation {
|
|
6
|
+
readonly decay: boolean;
|
|
7
|
+
readonly recallBoost: boolean;
|
|
8
|
+
readonly outcomeSlow: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** Production scoring: nothing ablated. Core falls back to this, so it never reads the environment. */
|
|
11
|
+
export declare const NO_STRENGTH_ABLATION: StrengthAblation;
|
|
12
|
+
/** The frozen strength switches for this process; entry-layer callers pass them as `DecayOptions.ablation`. */
|
|
13
|
+
export declare function strengthAblation(): StrengthAblation;
|
|
4
14
|
export declare function isDecayAblated(): boolean;
|
|
5
15
|
export declare function isRecallBoostAblated(): boolean;
|
|
6
16
|
export declare function isOutcomeSlowAblated(): boolean;
|