hippo-memory 1.60.0 → 1.61.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 +1 -1
- package/dist/ablation.js +9 -27
- package/dist/agent-memories/apply.js +4 -1
- package/dist/agent-memories/claude-code.js +1 -1
- package/dist/agent-memories/codex.js +1 -1
- package/dist/agent-memories/gemini.js +1 -1
- package/dist/agent-memories/legacy.js +1 -1
- package/dist/agent-memories/source.js +1 -1
- package/dist/agent-memories/sync.js +8 -3
- package/dist/ambient-store.d.ts +14 -0
- package/dist/ambient-store.js +90 -0
- package/dist/ambient.d.ts +23 -0
- package/dist/ambient.js +72 -50
- package/dist/api/assemble.d.ts +93 -0
- package/dist/api/assemble.js +152 -0
- package/dist/api/audit.d.ts +17 -0
- package/dist/api/audit.js +23 -0
- package/dist/api/auth.d.ts +79 -0
- package/dist/api/auth.js +178 -0
- package/dist/api/context-types.d.ts +105 -0
- package/dist/api/context-types.js +3 -0
- package/dist/api/context.d.ts +31 -0
- package/dist/api/context.js +705 -0
- package/dist/api/dormant.d.ts +30 -0
- package/dist/api/dormant.js +140 -0
- package/dist/api/drill-down.d.ts +84 -0
- package/dist/api/drill-down.js +123 -0
- package/dist/api/forget.d.ts +57 -0
- package/dist/api/forget.js +87 -0
- package/dist/api/goals.d.ts +18 -0
- package/dist/api/goals.js +33 -0
- package/dist/api/learn.d.ts +31 -0
- package/dist/api/learn.js +88 -0
- package/dist/api/outcome.d.ts +61 -0
- package/dist/api/outcome.js +66 -0
- package/dist/api/promote.d.ts +54 -0
- package/dist/api/promote.js +203 -0
- package/dist/api/quarantine.d.ts +24 -0
- package/dist/api/quarantine.js +121 -0
- package/dist/api/recall-types.d.ts +390 -0
- package/dist/api/recall-types.js +3 -0
- package/dist/api/recall.d.ts +36 -0
- package/dist/api/recall.js +634 -0
- package/dist/api/remember.d.ts +35 -0
- package/dist/api/remember.js +43 -0
- package/dist/api/sleep.d.ts +136 -0
- package/dist/api/sleep.js +271 -0
- package/dist/api/tokens.d.ts +26 -0
- package/dist/api/tokens.js +60 -0
- package/dist/api/types.d.ts +56 -0
- package/dist/api/types.js +38 -0
- package/dist/api.d.ts +20 -1262
- package/dist/api.js +25 -2727
- package/dist/audit.d.ts +3 -0
- package/dist/audit.js +6 -3
- package/dist/auth.d.ts +45 -4
- package/dist/auth.js +125 -48
- package/dist/autolearn.js +2 -2
- package/dist/capture/command.d.ts +33 -0
- package/dist/capture/command.js +264 -0
- package/dist/capture/compact.d.ts +44 -0
- package/dist/capture/compact.js +354 -0
- package/dist/capture/extract.d.ts +21 -0
- package/dist/capture/extract.js +464 -0
- package/dist/capture/transcript.d.ts +40 -0
- package/dist/capture/transcript.js +193 -0
- package/dist/capture-error.js +2 -1
- package/dist/churn-git.js +4 -2
- package/dist/cli/audit.d.ts +3 -0
- package/dist/cli/audit.js +159 -0
- package/dist/cli/auth.d.ts +2 -0
- package/dist/cli/auth.js +171 -0
- package/dist/cli/briefs.d.ts +4 -0
- package/dist/cli/briefs.js +435 -0
- package/dist/cli/card.d.ts +3 -0
- package/dist/cli/card.js +333 -0
- package/dist/cli/context.d.ts +15 -0
- package/dist/cli/context.js +366 -0
- package/dist/cli/continuity.d.ts +6 -0
- package/dist/cli/continuity.js +445 -0
- package/dist/cli/curate.d.ts +19 -0
- package/dist/cli/curate.js +555 -0
- package/dist/cli/dag.d.ts +5 -0
- package/dist/cli/dag.js +177 -0
- package/dist/cli/decisions.d.ts +4 -0
- package/dist/cli/decisions.js +528 -0
- package/dist/cli/eval.d.ts +5 -0
- package/dist/cli/eval.js +213 -0
- package/dist/cli/explain.d.ts +4 -0
- package/dist/cli/explain.js +150 -0
- package/dist/cli/goals.d.ts +2 -0
- package/dist/cli/goals.js +196 -0
- package/dist/cli/hook-blocks.d.ts +18 -0
- package/dist/cli/hook-blocks.js +233 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.js +305 -0
- package/dist/cli/maintenance.d.ts +4 -0
- package/dist/cli/maintenance.js +179 -0
- package/dist/cli/playbooks.d.ts +4 -0
- package/dist/cli/playbooks.js +556 -0
- package/dist/cli/projects.js +1 -1
- package/dist/cli/recall.d.ts +7 -0
- package/dist/cli/recall.js +597 -0
- package/dist/cli/remember.d.ts +5 -0
- package/dist/cli/remember.js +442 -0
- package/dist/cli/serve.d.ts +5 -0
- package/dist/cli/serve.js +40 -0
- package/dist/cli/session-hooks.d.ts +29 -0
- package/dist/cli/session-hooks.js +637 -0
- package/dist/cli/setup.d.ts +4 -0
- package/dist/cli/setup.js +376 -0
- package/dist/cli/shared.d.ts +15 -19
- package/dist/cli/shared.js +50 -341
- package/dist/cli/slack.d.ts +2 -0
- package/dist/cli/slack.js +171 -0
- package/dist/cli/status.d.ts +18 -0
- package/dist/cli/status.js +400 -0
- package/dist/cli/transfer.d.ts +10 -0
- package/dist/cli/transfer.js +438 -0
- package/dist/cli/usage.d.ts +85 -0
- package/dist/cli/usage.js +741 -0
- package/dist/cli.d.ts +71 -120
- package/dist/cli.js +170 -8469
- package/dist/client.js +15 -8
- package/dist/compaction-record.js +6 -4
- package/dist/connectors/github/backfill.js +94 -87
- package/dist/connectors/github/cli-impl.js +4 -3
- package/dist/connectors/github/dlq.js +67 -54
- package/dist/connectors/github/ingest.js +34 -35
- package/dist/connectors/github/tenant-routing.js +3 -2
- package/dist/connectors/github/webhook.js +135 -216
- package/dist/connectors/slack/dlq.js +49 -61
- package/dist/connectors/slack/ingest.js +55 -48
- package/dist/connectors/slack/tenant-routing.js +4 -3
- package/dist/connectors/slack/webhook.js +72 -74
- package/dist/consolidate/conflicts.d.ts +10 -0
- package/dist/consolidate/conflicts.js +178 -0
- package/dist/consolidate/decay.d.ts +12 -0
- package/dist/consolidate/decay.js +145 -0
- package/dist/consolidate/llm-passes.d.ts +3 -0
- package/dist/consolidate/llm-passes.js +141 -0
- package/dist/consolidate/merge.d.ts +7 -0
- package/dist/consolidate/merge.js +251 -0
- package/dist/consolidate/physics-pass.d.ts +3 -0
- package/dist/consolidate/physics-pass.js +60 -0
- package/dist/consolidate/run.d.ts +69 -0
- package/dist/consolidate/run.js +76 -0
- package/dist/consolidate/sleep.d.ts +18 -0
- package/dist/consolidate/sleep.js +209 -0
- package/dist/consolidate/traces.d.ts +4 -0
- package/dist/consolidate/traces.js +178 -0
- package/dist/context-auto.js +7 -11
- package/dist/context-render.d.ts +1 -1
- package/dist/context-render.js +1 -1
- package/dist/customer-notes.d.ts +3 -0
- package/dist/customer-notes.js +6 -4
- package/dist/dag.js +6 -5
- package/dist/dashboard-actions.d.ts +20 -0
- package/dist/dashboard-actions.js +88 -0
- package/dist/dashboard-params.d.ts +45 -0
- package/dist/dashboard-params.js +127 -0
- package/dist/dashboard-queries.d.ts +15 -0
- package/dist/dashboard-queries.js +355 -0
- package/dist/dashboard-snapshot.d.ts +138 -0
- package/dist/dashboard-snapshot.js +308 -0
- package/dist/dashboard-types.d.ts +163 -0
- package/dist/dashboard-types.js +3 -0
- package/dist/dashboard.d.ts +6 -7
- package/dist/dashboard.js +228 -202
- package/dist/db/busy.d.ts +5 -0
- package/dist/db/busy.js +24 -0
- package/dist/db/continuity.d.ts +5 -0
- package/dist/db/continuity.js +145 -0
- package/dist/db/meta.d.ts +8 -0
- package/dist/db/meta.js +35 -0
- package/dist/db/migrate.d.ts +9 -0
- package/dist/db/migrate.js +138 -0
- package/dist/db/migrations/index.d.ts +5 -0
- package/dist/db/migrations/index.js +109 -0
- package/dist/db/migrations/types.d.ts +14 -0
- package/dist/db/migrations/types.js +2 -0
- package/dist/db/migrations/v01.d.ts +3 -0
- package/dist/db/migrations/v01.js +38 -0
- package/dist/db/migrations/v02.d.ts +3 -0
- package/dist/db/migrations/v02.js +21 -0
- package/dist/db/migrations/v03.d.ts +3 -0
- package/dist/db/migrations/v03.js +22 -0
- package/dist/db/migrations/v04.d.ts +3 -0
- package/dist/db/migrations/v04.js +28 -0
- package/dist/db/migrations/v05.d.ts +3 -0
- package/dist/db/migrations/v05.js +21 -0
- package/dist/db/migrations/v06.d.ts +3 -0
- package/dist/db/migrations/v06.js +25 -0
- package/dist/db/migrations/v07.d.ts +3 -0
- package/dist/db/migrations/v07.js +13 -0
- package/dist/db/migrations/v08.d.ts +3 -0
- package/dist/db/migrations/v08.js +8 -0
- package/dist/db/migrations/v09.d.ts +3 -0
- package/dist/db/migrations/v09.js +13 -0
- package/dist/db/migrations/v10.d.ts +3 -0
- package/dist/db/migrations/v10.js +17 -0
- package/dist/db/migrations/v11.d.ts +3 -0
- package/dist/db/migrations/v11.js +15 -0
- package/dist/db/migrations/v12.d.ts +3 -0
- package/dist/db/migrations/v12.js +11 -0
- package/dist/db/migrations/v13.d.ts +3 -0
- package/dist/db/migrations/v13.js +15 -0
- package/dist/db/migrations/v14.d.ts +3 -0
- package/dist/db/migrations/v14.js +66 -0
- package/dist/db/migrations/v15.d.ts +3 -0
- package/dist/db/migrations/v15.js +42 -0
- package/dist/db/migrations/v16.d.ts +3 -0
- package/dist/db/migrations/v16.js +61 -0
- package/dist/db/migrations/v17.d.ts +3 -0
- package/dist/db/migrations/v17.js +46 -0
- package/dist/db/migrations/v18.d.ts +3 -0
- package/dist/db/migrations/v18.js +60 -0
- package/dist/db/migrations/v19.d.ts +3 -0
- package/dist/db/migrations/v19.js +28 -0
- package/dist/db/migrations/v20.d.ts +3 -0
- package/dist/db/migrations/v20.js +42 -0
- package/dist/db/migrations/v21.d.ts +3 -0
- package/dist/db/migrations/v21.js +16 -0
- package/dist/db/migrations/v22.d.ts +3 -0
- package/dist/db/migrations/v22.js +82 -0
- package/dist/db/migrations/v23.d.ts +3 -0
- package/dist/db/migrations/v23.js +48 -0
- package/dist/db/migrations/v24.d.ts +3 -0
- package/dist/db/migrations/v24.js +72 -0
- package/dist/db/migrations/v25.d.ts +3 -0
- package/dist/db/migrations/v25.js +46 -0
- package/dist/db/migrations/v26.d.ts +3 -0
- package/dist/db/migrations/v26.js +23 -0
- package/dist/db/migrations/v27.d.ts +3 -0
- package/dist/db/migrations/v27.js +57 -0
- package/dist/db/migrations/v28.d.ts +3 -0
- package/dist/db/migrations/v28.js +38 -0
- package/dist/db/migrations/v29.d.ts +3 -0
- package/dist/db/migrations/v29.js +78 -0
- package/dist/db/migrations/v30.d.ts +3 -0
- package/dist/db/migrations/v30.js +92 -0
- package/dist/db/migrations/v31.d.ts +3 -0
- package/dist/db/migrations/v31.js +74 -0
- package/dist/db/migrations/v32.d.ts +3 -0
- package/dist/db/migrations/v32.js +102 -0
- package/dist/db/migrations/v33.d.ts +3 -0
- package/dist/db/migrations/v33.js +104 -0
- package/dist/db/migrations/v34.d.ts +3 -0
- package/dist/db/migrations/v34.js +93 -0
- package/dist/db/migrations/v35.d.ts +3 -0
- package/dist/db/migrations/v35.js +98 -0
- package/dist/db/migrations/v36.d.ts +3 -0
- package/dist/db/migrations/v36.js +98 -0
- package/dist/db/migrations/v37.d.ts +3 -0
- package/dist/db/migrations/v37.js +219 -0
- package/dist/db/migrations/v38.d.ts +3 -0
- package/dist/db/migrations/v38.js +277 -0
- package/dist/db/migrations/v39.d.ts +3 -0
- package/dist/db/migrations/v39.js +59 -0
- package/dist/db/migrations/v40.d.ts +3 -0
- package/dist/db/migrations/v40.js +74 -0
- package/dist/db/migrations/v41.d.ts +3 -0
- package/dist/db/migrations/v41.js +43 -0
- package/dist/db/migrations/v42.d.ts +3 -0
- package/dist/db/migrations/v42.js +41 -0
- package/dist/db/migrations/v43.d.ts +3 -0
- package/dist/db/migrations/v43.js +67 -0
- package/dist/db/migrations/v44.d.ts +3 -0
- package/dist/db/migrations/v44.js +28 -0
- package/dist/db/migrations/v45.d.ts +3 -0
- package/dist/db/migrations/v45.js +30 -0
- package/dist/db/migrations/v46.d.ts +3 -0
- package/dist/db/migrations/v46.js +25 -0
- package/dist/db/migrations/v47.d.ts +3 -0
- package/dist/db/migrations/v47.js +17 -0
- package/dist/db/migrations/v48.d.ts +3 -0
- package/dist/db/migrations/v48.js +10 -0
- package/dist/db/migrations/v49.d.ts +3 -0
- package/dist/db/migrations/v49.js +31 -0
- package/dist/db/migrations/v50.d.ts +3 -0
- package/dist/db/migrations/v50.js +67 -0
- package/dist/db/migrations/v51.d.ts +3 -0
- package/dist/db/migrations/v51.js +14 -0
- package/dist/db/migrations/v52.d.ts +3 -0
- package/dist/db/migrations/v52.js +7 -0
- package/dist/db/open.d.ts +23 -0
- package/dist/db/open.js +146 -0
- package/dist/db/sqlite.d.ts +21 -0
- package/dist/db/sqlite.js +8 -0
- package/dist/db/tables.d.ts +7 -0
- package/dist/db/tables.js +38 -0
- package/dist/db.d.ts +6 -46
- package/dist/db.js +5 -3049
- package/dist/decisions.d.ts +4 -1
- package/dist/decisions.js +9 -7
- package/dist/dedupe.js +3 -2
- package/dist/delivery-recorder.js +4 -1
- package/dist/doctor.js +3 -3
- package/dist/embedding-provider.d.ts +1 -1
- package/dist/embedding-provider.js +4 -3
- package/dist/embeddings.d.ts +9 -52
- package/dist/embeddings.js +43 -297
- package/dist/env.d.ts +75 -0
- package/dist/env.js +119 -0
- package/dist/eval-suite.js +1 -1
- package/dist/eval.js +2 -2
- package/dist/extract.js +1 -1
- package/dist/gated-write.js +3 -1
- package/dist/goals.d.ts +3 -1
- package/dist/goals.js +18 -0
- package/dist/graph/read.d.ts +73 -0
- package/dist/graph/read.js +325 -0
- package/dist/graph/rows.d.ts +45 -0
- package/dist/graph/rows.js +51 -0
- package/dist/graph/types.d.ts +83 -0
- package/dist/graph/types.js +11 -0
- package/dist/graph/write.d.ts +93 -0
- package/dist/{graph.js → graph/write.js} +6 -384
- package/dist/graph-extract.js +2 -1
- package/dist/graph-recall.d.ts +1 -1
- package/dist/graph-recall.js +2 -2
- package/dist/graph-stream.js +1 -1
- package/dist/graph-view.d.ts +1 -1
- package/dist/graph-view.js +1 -1
- package/dist/half-life-migration.d.ts +1 -1
- package/dist/half-life-migration.js +2 -1
- package/dist/hooks/codex-session.d.ts +8 -0
- package/dist/hooks/codex-session.js +76 -0
- package/dist/hooks/codex-wrapper.d.ts +55 -0
- package/dist/hooks/codex-wrapper.js +288 -0
- package/dist/hooks/json-hooks.d.ts +63 -0
- package/dist/hooks/json-hooks.js +356 -0
- package/dist/hooks/opencode.d.ts +50 -0
- package/dist/hooks/opencode.js +202 -0
- package/dist/hooks/shared.d.ts +54 -0
- package/dist/hooks/shared.js +77 -0
- package/dist/http-retry.d.ts +2 -0
- package/dist/http-retry.js +4 -3
- package/dist/http-util.d.ts +3 -0
- package/dist/http-util.js +10 -0
- package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
- package/dist/importers/core.js +141 -0
- package/dist/importers/markdown-parse.d.ts +41 -0
- package/dist/importers/markdown-parse.js +132 -0
- package/dist/importers/markdown.d.ts +3 -0
- package/dist/importers/markdown.js +92 -0
- package/dist/importers/sources.d.ts +7 -0
- package/dist/importers/sources.js +229 -0
- package/dist/importers/vault.d.ts +11 -0
- package/dist/importers/vault.js +352 -0
- package/dist/incidents.d.ts +3 -0
- package/dist/incidents.js +7 -5
- package/dist/index.d.ts +25 -6
- package/dist/index.js +23 -6
- package/dist/invalidation.js +2 -1
- package/dist/judgment.js +2 -1
- package/dist/keyset.d.ts +13 -0
- package/dist/keyset.js +8 -0
- package/dist/local-embedding.d.ts +13 -0
- package/dist/local-embedding.js +165 -0
- package/dist/log.d.ts +7 -0
- package/dist/log.js +19 -1
- package/dist/mcp/admin-tools.d.ts +8 -0
- package/dist/mcp/admin-tools.js +116 -0
- package/dist/mcp/format.d.ts +27 -0
- package/dist/mcp/format.js +135 -0
- package/dist/mcp/memory-tools.d.ts +5 -0
- package/dist/mcp/memory-tools.js +83 -0
- package/dist/mcp/protocol.d.ts +83 -0
- package/dist/mcp/protocol.js +55 -0
- package/dist/mcp/recall-tools.d.ts +6 -0
- package/dist/mcp/recall-tools.js +320 -0
- package/dist/mcp/request.d.ts +10 -0
- package/dist/mcp/request.js +163 -0
- package/dist/mcp/server.d.ts +4 -75
- package/dist/mcp/server.js +7 -1190
- package/dist/mcp/session-state.d.ts +11 -0
- package/dist/mcp/session-state.js +28 -0
- package/dist/mcp/stdio.d.ts +8 -0
- package/dist/mcp/stdio.js +79 -0
- package/dist/mcp/tools.d.ts +11 -0
- package/dist/mcp/tools.js +247 -0
- package/dist/memory.d.ts +3 -0
- package/dist/memory.js +27 -1
- package/dist/multihop.d.ts +1 -1
- package/dist/multihop.js +2 -1
- package/dist/owner-validation.js +2 -1
- package/dist/physics-state.js +10 -7
- package/dist/policies.d.ts +3 -0
- package/dist/policies.js +8 -6
- package/dist/postinstall.js +3 -2
- package/dist/predictions/planning-fallacy.d.ts +100 -0
- package/dist/predictions/planning-fallacy.js +190 -0
- package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
- package/dist/predictions/store.js +434 -0
- package/dist/processes.d.ts +3 -0
- package/dist/processes.js +7 -5
- package/dist/project-briefs.d.ts +3 -0
- package/dist/project-briefs.js +7 -5
- package/dist/project-identity.js +3 -2
- package/dist/project-merge.js +3 -1
- package/dist/quarantine.d.ts +2 -1
- package/dist/quarantine.js +8 -5
- package/dist/raw-archive.js +1 -1
- package/dist/recall-history.js +3 -2
- package/dist/recall-pipeline.d.ts +2 -2
- package/dist/recall-pipeline.js +16 -8
- package/dist/recall-scope.js +1 -1
- package/dist/recall-trace.d.ts +1 -1
- package/dist/refine-llm.js +2 -1
- package/dist/reject-flow.js +6 -1
- package/dist/rerankers/clef.js +6 -5
- package/dist/rerankers/jev.d.ts +1 -1
- package/dist/rerankers/jev.js +4 -4
- package/dist/rerankers/llm.d.ts +4 -2
- package/dist/rerankers/llm.js +58 -38
- package/dist/rerankers/types.d.ts +1 -1
- package/dist/salience.js +1 -1
- package/dist/scheduler.d.ts +1 -0
- package/dist/scheduler.js +26 -4
- package/dist/scope.js +4 -3
- package/dist/search/as-of.d.ts +10 -0
- package/dist/search/as-of.js +22 -0
- package/dist/search/bm25-search.d.ts +14 -0
- package/dist/search/bm25-search.js +43 -0
- package/dist/search/bm25.d.ts +15 -0
- package/dist/search/bm25.js +54 -0
- package/dist/search/boosts.d.ts +54 -0
- package/dist/search/boosts.js +94 -0
- package/dist/search/breakdown.d.ts +7 -0
- package/dist/search/breakdown.js +20 -0
- package/dist/search/explain.d.ts +25 -0
- package/dist/search/explain.js +31 -0
- package/dist/search/finalize.d.ts +8 -0
- package/dist/search/finalize.js +52 -0
- package/dist/search/fusion.d.ts +27 -0
- package/dist/search/fusion.js +42 -0
- package/dist/search/hybrid-score.d.ts +20 -0
- package/dist/search/hybrid-score.js +73 -0
- package/dist/search/hybrid.d.ts +46 -0
- package/dist/search/hybrid.js +64 -0
- package/dist/search/physics-search.d.ts +29 -0
- package/dist/search/physics-search.js +162 -0
- package/dist/search/rerank.d.ts +10 -0
- package/dist/search/rerank.js +72 -0
- package/dist/search/temporal.d.ts +15 -0
- package/dist/search/temporal.js +45 -0
- package/dist/search/types.d.ts +91 -0
- package/dist/search/types.js +2 -0
- package/dist/search/vector.d.ts +30 -0
- package/dist/search/vector.js +71 -0
- package/dist/secret-detect.d.ts +2 -0
- package/dist/secret-detect.js +2 -1
- package/dist/server/auth.d.ts +52 -0
- package/dist/server/auth.js +221 -0
- package/dist/server/client-ip.d.ts +25 -0
- package/dist/server/client-ip.js +92 -0
- package/dist/server/cursor.d.ts +23 -0
- package/dist/server/cursor.js +58 -0
- package/dist/server/lifecycle.d.ts +7 -0
- package/dist/server/lifecycle.js +29 -0
- package/dist/server/mcp-http.d.ts +5 -0
- package/dist/server/mcp-http.js +199 -0
- package/dist/server/request.d.ts +33 -0
- package/dist/server/request.js +103 -0
- package/dist/server/routes/admin.d.ts +9 -0
- package/dist/server/routes/admin.js +158 -0
- package/dist/server/routes/customer-notes.d.ts +7 -0
- package/dist/server/routes/customer-notes.js +112 -0
- package/dist/server/routes/decisions.d.ts +7 -0
- package/dist/server/routes/decisions.js +133 -0
- package/dist/server/routes/incidents.d.ts +7 -0
- package/dist/server/routes/incidents.js +126 -0
- package/dist/server/routes/memories.d.ts +10 -0
- package/dist/server/routes/memories.js +179 -0
- package/dist/server/routes/policies.d.ts +8 -0
- package/dist/server/routes/policies.js +151 -0
- package/dist/server/routes/predictions.d.ts +7 -0
- package/dist/server/routes/predictions.js +164 -0
- package/dist/server/routes/processes.d.ts +7 -0
- package/dist/server/routes/processes.js +161 -0
- package/dist/server/routes/project-briefs.d.ts +8 -0
- package/dist/server/routes/project-briefs.js +136 -0
- package/dist/server/routes/recall.d.ts +8 -0
- package/dist/server/routes/recall.js +340 -0
- package/dist/server/routes/skills.d.ts +8 -0
- package/dist/server/routes/skills.js +150 -0
- package/dist/server/types.d.ts +56 -0
- package/dist/server/types.js +2 -0
- package/dist/server/validation.d.ts +14 -0
- package/dist/server/validation.js +91 -0
- package/dist/server.d.ts +7 -61
- package/dist/server.js +69 -2362
- package/dist/session-digest.d.ts +1 -1
- package/dist/session-digest.js +9 -2
- package/dist/shared.d.ts +3 -1
- package/dist/shared.js +26 -22
- package/dist/skills.d.ts +3 -0
- package/dist/skills.js +7 -5
- package/dist/stdin.js +2 -2
- package/dist/store/audit-event.d.ts +19 -0
- package/dist/store/audit-event.js +33 -0
- package/dist/store/candidates.d.ts +42 -0
- package/dist/store/candidates.js +152 -0
- package/dist/store/conflicts.d.ts +44 -0
- package/dist/store/conflicts.js +444 -0
- package/dist/store/delete-and-batch.d.ts +63 -0
- package/dist/store/delete-and-batch.js +310 -0
- package/dist/store/entry-reads.d.ts +92 -0
- package/dist/store/entry-reads.js +255 -0
- package/dist/store/entry-row.d.ts +67 -0
- package/dist/store/entry-row.js +208 -0
- package/dist/store/entry-writes.d.ts +46 -0
- package/dist/store/entry-writes.js +148 -0
- package/dist/store/handoffs.d.ts +26 -0
- package/dist/store/handoffs.js +184 -0
- package/dist/store/index-and-stats.d.ts +52 -0
- package/dist/store/index-and-stats.js +214 -0
- package/dist/store/markdown.d.ts +10 -0
- package/dist/store/markdown.js +108 -0
- package/dist/store/mirrors.d.ts +49 -0
- package/dist/store/mirrors.js +312 -0
- package/dist/store/open.d.ts +15 -0
- package/dist/store/open.js +223 -0
- package/dist/store/rows.d.ts +178 -0
- package/dist/store/rows.js +158 -0
- package/dist/store/search-rows.d.ts +86 -0
- package/dist/store/search-rows.js +254 -0
- package/dist/store/sessions.d.ts +83 -0
- package/dist/store/sessions.js +272 -0
- package/dist/store/summaries.d.ts +94 -0
- package/dist/store/summaries.js +377 -0
- package/dist/store/tenant-lookup.d.ts +12 -0
- package/dist/store/tenant-lookup.js +16 -0
- package/dist/store-cards.js +2 -1
- package/dist/summary-dirty.d.ts +4 -0
- package/dist/summary-dirty.js +32 -0
- package/dist/support-bundle.js +4 -3
- package/dist/tenant.js +2 -2
- package/dist/tokenize.d.ts +2 -0
- package/dist/tokenize.js +16 -0
- package/dist/transcript-tail.d.ts +7 -0
- package/dist/transcript-tail.js +48 -0
- package/dist/vector-store.d.ts +27 -0
- package/dist/vector-store.js +210 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/working-memory.js +1 -1
- package/dist/yaml.js +36 -11
- package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
- package/dist-ui/assets/index-DPN7cP19.js +33 -0
- package/dist-ui/assets/index-dFloKRVr.css +1 -0
- package/dist-ui/index.html +3 -25
- 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 +1 -1
- package/dist/capture.d.ts +0 -155
- package/dist/capture.js +0 -1295
- package/dist/consolidate.d.ts +0 -58
- package/dist/consolidate.js +0 -1124
- package/dist/graph.d.ts +0 -245
- package/dist/hooks.d.ts +0 -208
- package/dist/hooks.js +0 -1076
- package/dist/importers.js +0 -900
- package/dist/predictions.js +0 -620
- package/dist/search.d.ts +0 -320
- package/dist/search.js +0 -970
- package/dist/store.d.ts +0 -776
- package/dist/store.js +0 -3473
- package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
- package/dist-ui/assets/index-BhT8RvO6.js +0 -61
- package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
- package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { MemoryEntry, type DecayOptions } from '../memory.js';
|
|
2
|
+
import { type DatabaseSyncLike } from '../db.js';
|
|
3
|
+
import { type DormantMove } from '../dormant.js';
|
|
4
|
+
import { loadConfig } from '../config.js';
|
|
5
|
+
export interface ConsolidationResult {
|
|
6
|
+
decayed: number;
|
|
7
|
+
removed: number;
|
|
8
|
+
/** Faded memories moved to the dormant store instead of deleted (config
|
|
9
|
+
* `dormant.enabled`; src/dormant.ts). Always 0 when that is off. */
|
|
10
|
+
dormant: number;
|
|
11
|
+
/** Dormant memories deleted for good this sleep because they outlived
|
|
12
|
+
* `dormant.retentionDays` without a restore. */
|
|
13
|
+
dormantExpired: number;
|
|
14
|
+
merged: number;
|
|
15
|
+
semanticCreated: number;
|
|
16
|
+
replayed: number;
|
|
17
|
+
promotedTraces: number;
|
|
18
|
+
/** T7: sessions skipped because their events span two derivation scopes. */
|
|
19
|
+
tracesSkippedMixedScope: number;
|
|
20
|
+
extractionCandidates: number;
|
|
21
|
+
extracted: number;
|
|
22
|
+
dagCandidateClusters: number;
|
|
23
|
+
dagSummariesCreated: number;
|
|
24
|
+
summariesRebuilt: number;
|
|
25
|
+
summariesRebuildFailed: number;
|
|
26
|
+
summariesZeroChildSkipped: number;
|
|
27
|
+
summariesRebuildRefused: number;
|
|
28
|
+
summariesRebuildCapped: boolean;
|
|
29
|
+
entityProfilesCreated: number;
|
|
30
|
+
dryRun: boolean;
|
|
31
|
+
details: string[];
|
|
32
|
+
physicsSimulated: number;
|
|
33
|
+
/** Ids the decay pass removes (or would remove, under dryRun). */
|
|
34
|
+
removedIds?: string[];
|
|
35
|
+
}
|
|
36
|
+
export declare const REPLAY_COUNT_DEFAULT = 5;
|
|
37
|
+
export declare function keptAsWritten(entry: MemoryEntry): boolean;
|
|
38
|
+
/** JSON value shape for a session event's free-form metadata field, cast to
|
|
39
|
+
* once at its `Record<string, unknown>` origin so it can be narrowed via
|
|
40
|
+
* isJsonString below rather than left as unparsed `unknown`. */
|
|
41
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
42
|
+
[key: string]: JsonValue;
|
|
43
|
+
};
|
|
44
|
+
export declare function isJsonString(value: JsonValue): value is string;
|
|
45
|
+
/** The sleep's one tombstone-check handle: opened on first use, never under dryRun, closed once. */
|
|
46
|
+
interface LazyDb {
|
|
47
|
+
get: () => DatabaseSyncLike | null;
|
|
48
|
+
close: () => void;
|
|
49
|
+
}
|
|
50
|
+
export declare function lazyConsolidateDb(hippoRoot: string, dryRun: boolean): LazyDb;
|
|
51
|
+
/** State every sleep stage reads or appends to; the pending lists are flushed in one transaction at the end. */
|
|
52
|
+
export interface SleepRun {
|
|
53
|
+
hippoRoot: string;
|
|
54
|
+
now: Date;
|
|
55
|
+
dryRun: boolean;
|
|
56
|
+
config: ReturnType<typeof loadConfig>;
|
|
57
|
+
decayOpts: DecayOptions;
|
|
58
|
+
result: ConsolidationResult;
|
|
59
|
+
all: MemoryEntry[];
|
|
60
|
+
retirable: (entry: MemoryEntry) => boolean;
|
|
61
|
+
getConsolidateDb: () => DatabaseSyncLike | null;
|
|
62
|
+
survivors: MemoryEntry[];
|
|
63
|
+
pendingWrites: MemoryEntry[];
|
|
64
|
+
pendingDeletes: string[];
|
|
65
|
+
pendingDormant: DormantMove[];
|
|
66
|
+
}
|
|
67
|
+
export declare function newConsolidationResult(dryRun: boolean): ConsolidationResult;
|
|
68
|
+
export {};
|
|
69
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { openHippoDb, closeHippoDb } from '../db.js';
|
|
2
|
+
import { NO_MERGE_TAGS } from '../shared.js';
|
|
3
|
+
export const REPLAY_COUNT_DEFAULT = 5;
|
|
4
|
+
export function keptAsWritten(entry) {
|
|
5
|
+
return entry.tags.some((tag) => NO_MERGE_TAGS.has(tag));
|
|
6
|
+
}
|
|
7
|
+
export function isJsonString(value) {
|
|
8
|
+
return typeof value === 'string';
|
|
9
|
+
}
|
|
10
|
+
// AT1 rejection-guard db handle (docs/plans/2026-08-15-at1-rejected-value-tombstone.md):
|
|
11
|
+
// covers BOTH the auto-promote pass (1.4) and the merge
|
|
12
|
+
// pass (3) — both build deterministic content that
|
|
13
|
+
// batchWriteAndDelete writes through the guard's bypass, so both need a
|
|
14
|
+
// producer-side tombstone check before pushing to pendingWrites.
|
|
15
|
+
//
|
|
16
|
+
// T3 fix (2026-08-15 hardening pass, perf hygiene): memoized lazy getter,
|
|
17
|
+
// not an eager open. The handle only serves these two tombstone checks —
|
|
18
|
+
// a sleep with zero promotable sessions and zero merge clusters never
|
|
19
|
+
// reaches either use site, so opening it unconditionally on every
|
|
20
|
+
// non-dry-run sleep paid a db-open cost for nothing. dryRun still never
|
|
21
|
+
// opens (getConsolidateDb short-circuits before touching the handle).
|
|
22
|
+
// consolidateDbOpened (not just a truthy handle check) is the
|
|
23
|
+
// single source of truth for "was this ever opened", so the finally
|
|
24
|
+
// closes it exactly once and never double-opens.
|
|
25
|
+
//
|
|
26
|
+
// AT1 P2 fix (codex, handle-leak restructure): the getter's lifetime must
|
|
27
|
+
// start IMMEDIATELY before the try whose finally closes it, covering every
|
|
28
|
+
// phase that can touch it — not just the merge pass. An exception thrown by
|
|
29
|
+
// auto-promote (1.4), replay (1.5), batch extraction (1.6), the DAG
|
|
30
|
+
// passes (1.7-1.9), or physics (2) would otherwise propagate past an open handle
|
|
31
|
+
// with nothing to close it.
|
|
32
|
+
export function lazyConsolidateDb(hippoRoot, dryRun) {
|
|
33
|
+
let consolidateDbHandle = null;
|
|
34
|
+
let consolidateDbOpened = false;
|
|
35
|
+
const get = () => {
|
|
36
|
+
if (dryRun)
|
|
37
|
+
return null;
|
|
38
|
+
if (!consolidateDbOpened) {
|
|
39
|
+
consolidateDbHandle = openHippoDb(hippoRoot);
|
|
40
|
+
consolidateDbOpened = true;
|
|
41
|
+
}
|
|
42
|
+
return consolidateDbHandle;
|
|
43
|
+
};
|
|
44
|
+
const close = () => {
|
|
45
|
+
if (consolidateDbHandle)
|
|
46
|
+
closeHippoDb(consolidateDbHandle);
|
|
47
|
+
};
|
|
48
|
+
return { get, close };
|
|
49
|
+
}
|
|
50
|
+
export function newConsolidationResult(dryRun) {
|
|
51
|
+
return {
|
|
52
|
+
decayed: 0,
|
|
53
|
+
removed: 0,
|
|
54
|
+
dormant: 0,
|
|
55
|
+
dormantExpired: 0,
|
|
56
|
+
merged: 0,
|
|
57
|
+
semanticCreated: 0,
|
|
58
|
+
replayed: 0,
|
|
59
|
+
promotedTraces: 0,
|
|
60
|
+
tracesSkippedMixedScope: 0,
|
|
61
|
+
extractionCandidates: 0,
|
|
62
|
+
extracted: 0,
|
|
63
|
+
dagCandidateClusters: 0,
|
|
64
|
+
dagSummariesCreated: 0,
|
|
65
|
+
summariesRebuilt: 0,
|
|
66
|
+
summariesRebuildFailed: 0,
|
|
67
|
+
summariesZeroChildSkipped: 0,
|
|
68
|
+
summariesRebuildRefused: 0,
|
|
69
|
+
summariesRebuildCapped: false,
|
|
70
|
+
entityProfilesCreated: 0,
|
|
71
|
+
dryRun,
|
|
72
|
+
details: [],
|
|
73
|
+
physicsSimulated: 0,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consolidation engine ("Sleep") for Hippo.
|
|
3
|
+
*
|
|
4
|
+
* Steps:
|
|
5
|
+
* 1. Decay pass - remove entries below strength threshold
|
|
6
|
+
* 2. Merge pass - find episodic entries with high text overlap, create semantic summaries
|
|
7
|
+
* 3. Stats tracking
|
|
8
|
+
*/
|
|
9
|
+
import { type ConsolidationResult } from './run.js';
|
|
10
|
+
/**
|
|
11
|
+
* Run a full consolidation pass.
|
|
12
|
+
*/
|
|
13
|
+
export declare function consolidate(hippoRoot: string, options?: {
|
|
14
|
+
dryRun?: boolean;
|
|
15
|
+
now?: Date;
|
|
16
|
+
fetcher?: typeof fetch;
|
|
17
|
+
}): Promise<ConsolidationResult>;
|
|
18
|
+
//# sourceMappingURL=sleep.d.ts.map
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consolidation engine ("Sleep") for Hippo.
|
|
3
|
+
*
|
|
4
|
+
* Steps:
|
|
5
|
+
* 1. Decay pass - remove entries below strength threshold
|
|
6
|
+
* 2. Merge pass - find episodic entries with high text overlap, create semantic summaries
|
|
7
|
+
* 3. Stats tracking
|
|
8
|
+
*/
|
|
9
|
+
import { evalNow } from '../ablation.js';
|
|
10
|
+
import { canAutoDelete } from '../memory.js';
|
|
11
|
+
import { loadAllEntries } from '../store/entry-reads.js';
|
|
12
|
+
import { batchWriteAndDelete, memoriesBackingObjects } from '../store/delete-and-batch.js';
|
|
13
|
+
import { appendConsolidationRun, loadSessionDecayContext, incrementSleepCount } from '../store/index-and-stats.js';
|
|
14
|
+
import { replaceDetectedConflicts } from '../store/conflicts.js';
|
|
15
|
+
import { openHippoDb, closeHippoDb } from '../db.js';
|
|
16
|
+
import { countExpiredDormant, purgeExpiredDormant } from '../dormant.js';
|
|
17
|
+
import { loadConfig } from '../config.js';
|
|
18
|
+
import { appendAuditEvent, reportAuditWriteFailure } from '../audit.js';
|
|
19
|
+
import { migrateDefaultHalfLife, LEGACY_TYPED_HALF_LIFE } from '../half-life-migration.js';
|
|
20
|
+
import { log } from '../log.js';
|
|
21
|
+
import { decayPass } from './decay.js';
|
|
22
|
+
import { retireHeldTexts, mergePass } from './merge.js';
|
|
23
|
+
import { detectConflicts } from './conflicts.js';
|
|
24
|
+
import { lazyConsolidateDb, newConsolidationResult } from './run.js';
|
|
25
|
+
import { promoteSessionTraces, replayPass } from './traces.js';
|
|
26
|
+
import { llmPasses } from './llm-passes.js';
|
|
27
|
+
import { physicsPass } from './physics-pass.js';
|
|
28
|
+
/**
|
|
29
|
+
* Run a full consolidation pass.
|
|
30
|
+
*/
|
|
31
|
+
export async function consolidate(hippoRoot, options = {}) {
|
|
32
|
+
const now = options.now ?? evalNow(); // honors HIPPO_FAKE_NOW (eval-only; see ablation.ts)
|
|
33
|
+
const dryRun = options.dryRun ?? false;
|
|
34
|
+
const result = newConsolidationResult(dryRun);
|
|
35
|
+
const halfLife = migrateHalfLives(hippoRoot, dryRun, result);
|
|
36
|
+
// L9: host-wide by design. Consolidation runs across all tenants in one
|
|
37
|
+
// pass — per-tenant filtering would create N consolidation runs per host
|
|
38
|
+
// with no cross-tenant dedup. The api.sleep audit row tags this with the
|
|
39
|
+
// admin synthetic actor; see api.ts:2050 for the rationale.
|
|
40
|
+
const all = loadAllEntries(hippoRoot);
|
|
41
|
+
if (dryRun)
|
|
42
|
+
for (const e of all)
|
|
43
|
+
e.half_life_days = halfLife.halfLives.get(e.id) ?? e.half_life_days;
|
|
44
|
+
const backingObjects = memoriesBackingObjects(hippoRoot);
|
|
45
|
+
// Retirable: auto-deletable (never pinned, raw or kept for good) and not backing a first-class object.
|
|
46
|
+
const retirable = (entry) => canAutoDelete(entry) && !backingObjects.has(entry.id);
|
|
47
|
+
const snapshot = new Map(structuredClone(all).map((e) => [e.id, e]));
|
|
48
|
+
// Load decay options from config + session context
|
|
49
|
+
const config = loadConfig(hippoRoot);
|
|
50
|
+
const sessionCtx = loadSessionDecayContext(hippoRoot);
|
|
51
|
+
const decayOpts = {
|
|
52
|
+
decayBasis: config.decayBasis,
|
|
53
|
+
avgSessionIntervalDays: sessionCtx.avgSessionIntervalDays,
|
|
54
|
+
sleepCount: sessionCtx.sleepCount,
|
|
55
|
+
};
|
|
56
|
+
const consolidateDb = lazyConsolidateDb(hippoRoot, dryRun);
|
|
57
|
+
const run = {
|
|
58
|
+
hippoRoot, now, dryRun, config, decayOpts, result, all, retirable,
|
|
59
|
+
getConsolidateDb: consolidateDb.get,
|
|
60
|
+
survivors: [],
|
|
61
|
+
// Collect all writes/deletes and batch them at the end
|
|
62
|
+
pendingWrites: [],
|
|
63
|
+
pendingDeletes: [],
|
|
64
|
+
pendingDormant: [],
|
|
65
|
+
};
|
|
66
|
+
const decay = decayPass(run);
|
|
67
|
+
let mergesSkippedRejected = 0;
|
|
68
|
+
try {
|
|
69
|
+
promoteSessionTraces(run);
|
|
70
|
+
replayPass(run);
|
|
71
|
+
await llmPasses(run, options.fetcher);
|
|
72
|
+
physicsPass(run);
|
|
73
|
+
retireHeldTexts(run);
|
|
74
|
+
mergesSkippedRejected = mergePass(run);
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
consolidateDb.close();
|
|
78
|
+
}
|
|
79
|
+
if (mergesSkippedRejected > 0) {
|
|
80
|
+
log.warn(`consolidate: skipped ${mergesSkippedRejected} merge(s) whose content matches a rejected value`);
|
|
81
|
+
}
|
|
82
|
+
flushPending(run, snapshot);
|
|
83
|
+
expireDormant(run);
|
|
84
|
+
if (!dryRun)
|
|
85
|
+
logRun(run, decay);
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
// A changed default half-life moves memories still on the old base first,
|
|
89
|
+
// so this pass decays them at the new one (src/half-life-migration.ts).
|
|
90
|
+
function migrateHalfLives(hippoRoot, dryRun, result) {
|
|
91
|
+
const halfLife = migrateDefaultHalfLife(hippoRoot, loadConfig(hippoRoot).defaultHalfLifeDays, { dryRun });
|
|
92
|
+
if (halfLife.rescaled > 0) {
|
|
93
|
+
result.details.push(` ⏳ ${dryRun ? 'would move' : 'moved'} ${halfLife.rescaled} memories from the ${halfLife.from}-day to the ${halfLife.to}-day half-life`);
|
|
94
|
+
}
|
|
95
|
+
if (halfLife.typed > 0) {
|
|
96
|
+
result.details.push(` ⏳ ${dryRun ? 'would move' : 'moved'} ${halfLife.typed} memories of decisions, incidents and other objects from the ${LEGACY_TYPED_HALF_LIFE}-day to the ${halfLife.to}-day half-life`);
|
|
97
|
+
}
|
|
98
|
+
return halfLife;
|
|
99
|
+
}
|
|
100
|
+
function flushPending(run, snapshot) {
|
|
101
|
+
const { result, pendingDeletes, pendingDormant } = run;
|
|
102
|
+
result.removedIds = pendingDeletes;
|
|
103
|
+
// One transaction; the snapshot keeps what the DAG passes and other writers changed while sleep ran.
|
|
104
|
+
// Dormant moves ride in the same transaction (src/dormant.ts).
|
|
105
|
+
if (run.dryRun)
|
|
106
|
+
return;
|
|
107
|
+
const left = new Set(batchWriteAndDelete(run.hippoRoot, run.pendingWrites, pendingDeletes, { snapshot, dormant: pendingDormant }));
|
|
108
|
+
for (const id of [...pendingDeletes, ...pendingDormant.map((m) => m.entry.id)]) {
|
|
109
|
+
if (!left.has(id))
|
|
110
|
+
result.details.push(` ↩ ${id} not removed: pinned or already gone before sleep saved`);
|
|
111
|
+
}
|
|
112
|
+
result.removedIds = pendingDeletes.filter((id) => left.has(id));
|
|
113
|
+
result.removed = result.removedIds.length;
|
|
114
|
+
result.dormant = pendingDormant.filter((m) => left.has(m.entry.id)).length;
|
|
115
|
+
}
|
|
116
|
+
// Dormant retention: a dormant memory nobody restored within
|
|
117
|
+
// dormant.retentionDays is deleted for good (0 keeps them forever). Runs
|
|
118
|
+
// even when dormant.enabled is off, so turning it off still ages out what
|
|
119
|
+
// earlier sleeps kept.
|
|
120
|
+
function expireDormant(run) {
|
|
121
|
+
const { config, result, dryRun } = run;
|
|
122
|
+
if (!(config.dormant.retentionDays > 0))
|
|
123
|
+
return;
|
|
124
|
+
const cutoff = new Date(run.now.getTime() - config.dormant.retentionDays * 24 * 60 * 60 * 1000).toISOString();
|
|
125
|
+
const db = openHippoDb(run.hippoRoot);
|
|
126
|
+
try {
|
|
127
|
+
result.dormantExpired = dryRun ? countExpiredDormant(db, cutoff) : purgeExpiredDormant(db, cutoff);
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
closeHippoDb(db);
|
|
131
|
+
}
|
|
132
|
+
if (result.dormantExpired > 0) {
|
|
133
|
+
result.details.push(` ⌛ ${dryRun ? 'would expire' : 'expired'} ${result.dormantExpired} dormant memor${result.dormantExpired === 1 ? 'y' : 'ies'} older than ${config.dormant.retentionDays} days`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// -------------------------------------------------------------------------
|
|
137
|
+
// 4. Log run
|
|
138
|
+
// -------------------------------------------------------------------------
|
|
139
|
+
function logRun(run, decay) {
|
|
140
|
+
const { hippoRoot, now, result } = run;
|
|
141
|
+
const detectedConflicts = detectConflicts(run.survivors, now, run.decayOpts, decay.rescuedIds);
|
|
142
|
+
replaceDetectedConflicts(hippoRoot, detectedConflicts, now.toISOString());
|
|
143
|
+
if (detectedConflicts.length > 0) {
|
|
144
|
+
result.details.push(` ⚠️ detected ${detectedConflicts.length} memory conflict${detectedConflicts.length === 1 ? '' : 's'}`);
|
|
145
|
+
}
|
|
146
|
+
appendConsolidationRun(hippoRoot, {
|
|
147
|
+
timestamp: now.toISOString(),
|
|
148
|
+
decayed: result.decayed,
|
|
149
|
+
merged: result.merged,
|
|
150
|
+
removed: result.removed,
|
|
151
|
+
});
|
|
152
|
+
incrementSleepCount(hippoRoot);
|
|
153
|
+
if (decay.rescuedEntries.length > 0)
|
|
154
|
+
auditRescues(run, decay);
|
|
155
|
+
}
|
|
156
|
+
// One audit row per rescue (attributability, D1). Written here, AFTER
|
|
157
|
+
// batchWriteAndDelete has committed this cycle's writes/deletes
|
|
158
|
+
// (and after conflict detection + run logging), not inline in the decay
|
|
159
|
+
// pass — same durability posture as api.ts's top-level 'consolidate'
|
|
160
|
+
// summary audit row (written only once the whole sleep has completed).
|
|
161
|
+
// Writing it earlier would assert rescues for a cycle whose effects
|
|
162
|
+
// never landed if a later phase threw. Real writes only — dry-run
|
|
163
|
+
// previews the decision (details line above) but persists nothing.
|
|
164
|
+
function auditRescues(run, { rescuedEntries, rankById }) {
|
|
165
|
+
const { result } = run;
|
|
166
|
+
try {
|
|
167
|
+
const auditDb = openHippoDb(run.hippoRoot);
|
|
168
|
+
try {
|
|
169
|
+
// Review-round F5: per-row try/catch, not one try/catch around the
|
|
170
|
+
// whole loop — a single failed appendAuditEvent must not silently
|
|
171
|
+
// drop every remaining row. Mirrors the physics pass's
|
|
172
|
+
// skipped-warning precedent: count losses, keep
|
|
173
|
+
// the overall fail-soft posture, tell the operator via details.
|
|
174
|
+
let auditFailures = 0;
|
|
175
|
+
for (const entry of rescuedEntries) {
|
|
176
|
+
try {
|
|
177
|
+
const rank = rankById.get(entry.id);
|
|
178
|
+
appendAuditEvent(auditDb, {
|
|
179
|
+
tenantId: entry.tenantId,
|
|
180
|
+
actor: 'sleep',
|
|
181
|
+
op: 'mv_rescue',
|
|
182
|
+
targetId: entry.id,
|
|
183
|
+
metadata: rank
|
|
184
|
+
? { rank: rank.rank, totalNonPinned: rank.totalNonPinned, keepN: rank.keepN, score: rank.score }
|
|
185
|
+
: {},
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
auditFailures++;
|
|
190
|
+
reportAuditWriteFailure('mv_rescue', String(error), entry.id);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (auditFailures > 0) {
|
|
194
|
+
result.details.push(` ⚠️ memory-value: ${auditFailures} mv_rescue audit row${auditFailures === 1 ? '' : 's'} ` +
|
|
195
|
+
`failed to write (the rescue itself still landed)`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
finally {
|
|
199
|
+
closeHippoDb(auditDb);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// openHippoDb/closeHippoDb-level failure: audit must never crash a
|
|
204
|
+
// mutation (mirrors store.ts's audit() posture).
|
|
205
|
+
result.details.push(` ⚠️ memory-value: mv_rescue audit unavailable this cycle ` +
|
|
206
|
+
`(${rescuedEntries.length} rescue${rescuedEntries.length === 1 ? '' : 's'} not audited)`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=sleep.js.map
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { isRecallBoostAblated } from '../ablation.js';
|
|
2
|
+
import { Layer, createMemory, markRetrieved } from '../memory.js';
|
|
3
|
+
import { findPromotableSessions, traceExistsForSession, listSessionEvents } from '../store/sessions.js';
|
|
4
|
+
import { rejectionDigest, findRejectedValue } from '../rejection.js';
|
|
5
|
+
import { sampleForReplay } from '../replay.js';
|
|
6
|
+
import { renderTraceContent } from '../trace.js';
|
|
7
|
+
import { resolveTenantId } from '../tenant.js';
|
|
8
|
+
import { appendAuditEvent, reportAuditWriteFailure } from '../audit.js';
|
|
9
|
+
import { commonDerivationScope } from '../recall-scope.js';
|
|
10
|
+
import { log } from '../log.js';
|
|
11
|
+
import { REPLAY_COUNT_DEFAULT, isJsonString } from './run.js';
|
|
12
|
+
// -------------------------------------------------------------------------
|
|
13
|
+
// 1.4. Auto-promote complete sessions to traces
|
|
14
|
+
// -------------------------------------------------------------------------
|
|
15
|
+
//
|
|
16
|
+
// For each session within the configured window that has a `session_complete`
|
|
17
|
+
// event and no existing trace (idempotency via the source_session_id column),
|
|
18
|
+
// render the action sequence as markdown and persist a Layer.Trace memory.
|
|
19
|
+
// Traces inherit decay, search, replay, and physics from the base MemoryEntry.
|
|
20
|
+
export function promoteSessionTraces(run) {
|
|
21
|
+
const { result } = run;
|
|
22
|
+
if (run.dryRun || run.config.autoTraceCapture === false)
|
|
23
|
+
return;
|
|
24
|
+
let tracesSkippedRejected = 0;
|
|
25
|
+
const windowDays = run.config.autoTraceWindowDays ?? 7;
|
|
26
|
+
const sinceMs = run.now.getTime() - windowDays * 24 * 60 * 60 * 1000;
|
|
27
|
+
// Auto-trace currently runs in a single-tenant context (the env-resolved
|
|
28
|
+
// tenant for this process). Multi-tenant deployments that want
|
|
29
|
+
// consolidation across all tenants need a per-tenant loop layered on top
|
|
30
|
+
// of this — tracked in docs/plans/2026-05-02-continuity-tables-tenant-scope.md.
|
|
31
|
+
const consolidationTenant = resolveTenantId({});
|
|
32
|
+
const promotable = findPromotableSessions(run.hippoRoot, consolidationTenant, sinceMs);
|
|
33
|
+
for (const session of promotable) {
|
|
34
|
+
const built = sessionTrace(run, consolidationTenant, session.session_id);
|
|
35
|
+
if (!built)
|
|
36
|
+
continue;
|
|
37
|
+
const { trace, outcome } = built;
|
|
38
|
+
if (traceRejected(run, trace, session.session_id)) {
|
|
39
|
+
tracesSkippedRejected++;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
run.pendingWrites.push(trace);
|
|
43
|
+
run.survivors.push(trace);
|
|
44
|
+
result.promotedTraces++;
|
|
45
|
+
result.details.push(` 🧬 promoted trace ${trace.id} from session ${session.session_id} (${outcome})`);
|
|
46
|
+
}
|
|
47
|
+
if (result.promotedTraces > 0) {
|
|
48
|
+
result.details.push(` 🧬 promoted ${result.promotedTraces} trace${result.promotedTraces === 1 ? '' : 's'} from completed session${result.promotedTraces === 1 ? '' : 's'}`);
|
|
49
|
+
}
|
|
50
|
+
if (tracesSkippedRejected > 0) {
|
|
51
|
+
log.warn(`consolidate: skipped ${tracesSkippedRejected} auto-promoted trace(s) whose content matches a rejected value`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** The trace a completed session renders to, or null when it already has one or cannot be promoted. */
|
|
55
|
+
function sessionTrace(run, consolidationTenant, sessionId) {
|
|
56
|
+
// Idempotency: skip if a trace for this session already exists.
|
|
57
|
+
if (traceExistsForSession(run.hippoRoot, consolidationTenant, sessionId))
|
|
58
|
+
return null;
|
|
59
|
+
const events = listSessionEvents(run.hippoRoot, consolidationTenant, {
|
|
60
|
+
session_id: sessionId,
|
|
61
|
+
limit: 1000,
|
|
62
|
+
});
|
|
63
|
+
// T7: a mixed-scope session would otherwise leak into one trace.
|
|
64
|
+
const sessionScope = commonDerivationScope(events.map((e) => e.scope));
|
|
65
|
+
if (!sessionScope.ok) {
|
|
66
|
+
run.result.tracesSkippedMixedScope++;
|
|
67
|
+
run.result.details.push(` ⏭ skipped session ${sessionId}: events span mixed scopes`);
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const completeEvent = events.find((e) => e.event_type === 'session_complete');
|
|
71
|
+
if (!completeEvent)
|
|
72
|
+
return null; // defence-in-depth; findPromotableSessions filters already.
|
|
73
|
+
const outcomeRaw = completeEvent.content;
|
|
74
|
+
if (outcomeRaw !== 'success' && outcomeRaw !== 'failure' && outcomeRaw !== 'partial') {
|
|
75
|
+
// Malformed terminal event — skip rather than crash the whole sleep.
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const outcome = outcomeRaw;
|
|
79
|
+
const steps = events
|
|
80
|
+
.filter((e) => e.event_type !== 'session_complete')
|
|
81
|
+
.map((e) => ({ action: e.content, observation: '' }));
|
|
82
|
+
// SAFETY: session event metadata is a free-form Record<string, unknown>
|
|
83
|
+
// bag; summary is optional and is only trusted once isJsonString below
|
|
84
|
+
// confirms it is actually a string.
|
|
85
|
+
const summaryValue = completeEvent.metadata.summary;
|
|
86
|
+
const summary = isJsonString(summaryValue) ? summaryValue : '(untitled)';
|
|
87
|
+
const trace = createMemory(renderTraceContent({ task: summary, steps, outcome }), {
|
|
88
|
+
layer: Layer.Trace,
|
|
89
|
+
trace_outcome: outcome,
|
|
90
|
+
source_session_id: sessionId,
|
|
91
|
+
tags: ['auto-promoted'],
|
|
92
|
+
source: 'auto-promote',
|
|
93
|
+
scope: sessionScope.scope,
|
|
94
|
+
// T1 fix (2026-08-15 hardening pass): stamp the trace into the SAME
|
|
95
|
+
// tenant the traceExistsForSession idempotency check (above) runs
|
|
96
|
+
// under. Before
|
|
97
|
+
// this, createMemory omitted tenantId and the trace always landed
|
|
98
|
+
// 'default' (memory.ts:535) while the idempotency check ran under
|
|
99
|
+
// consolidationTenant — for any non-default tenant that check never
|
|
100
|
+
// hit, and the trace regenerated every sleep.
|
|
101
|
+
tenantId: consolidationTenant,
|
|
102
|
+
baseHalfLifeDays: run.config.defaultHalfLifeDays,
|
|
103
|
+
});
|
|
104
|
+
return { trace, outcome };
|
|
105
|
+
}
|
|
106
|
+
// AT1 (same producer-side pattern as the merge pass below): traceExistsForSession
|
|
107
|
+
// only sees rows CURRENTLY in the store — once a rejected trace is
|
|
108
|
+
// removed, that idempotency check no longer blocks regeneration, and
|
|
109
|
+
// this write would otherwise reach batchWriteAndDelete's guard bypass
|
|
110
|
+
// unchecked, resurrecting it every sleep. Check under THE ENTRY'S OWN
|
|
111
|
+
// stamped tenantId (read off `trace` after createMemory — never guess
|
|
112
|
+
// the tenant) + the built content's digest. A hit skips the push
|
|
113
|
+
// entirely: not counted as promoted, not added to survivors.
|
|
114
|
+
function traceRejected(run, trace, sessionId) {
|
|
115
|
+
const consolidateDb = run.getConsolidateDb();
|
|
116
|
+
if (!consolidateDb)
|
|
117
|
+
return false;
|
|
118
|
+
const traceDigest = rejectionDigest(trace.content);
|
|
119
|
+
const tombstone = findRejectedValue(consolidateDb, trace.tenantId, traceDigest);
|
|
120
|
+
if (!tombstone)
|
|
121
|
+
return false;
|
|
122
|
+
try {
|
|
123
|
+
appendAuditEvent(consolidateDb, {
|
|
124
|
+
tenantId: trace.tenantId,
|
|
125
|
+
actor: 'sleep',
|
|
126
|
+
op: 'reject_refusal',
|
|
127
|
+
metadata: {
|
|
128
|
+
digest: traceDigest,
|
|
129
|
+
reason: tombstone.reason,
|
|
130
|
+
sourceSessionId: sessionId,
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
reportAuditWriteFailure('reject_refusal', String(error));
|
|
136
|
+
}
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
// -------------------------------------------------------------------------
|
|
140
|
+
// 1.5. Replay pass — rehearse high-value survivors
|
|
141
|
+
// -------------------------------------------------------------------------
|
|
142
|
+
//
|
|
143
|
+
// Biologically-inspired counterpart to hippocampal replay during slow-wave
|
|
144
|
+
// sleep: sample N memories weighted by outcome + valence + under-rehearsal
|
|
145
|
+
// + idle time, then apply the same retrieval-strengthening `markRetrieved`
|
|
146
|
+
// applies to real queries. Distinct from decay (removal), physics (motion),
|
|
147
|
+
// and merge (compression) — this is the "rehearse the important stuff so
|
|
148
|
+
// it doesn't fade" pass.
|
|
149
|
+
export function replayPass(run) {
|
|
150
|
+
const { survivors, now } = run;
|
|
151
|
+
const replayCount = run.config.replay?.count ?? REPLAY_COUNT_DEFAULT;
|
|
152
|
+
// EVAL-ONLY ablation (see ablation.ts): replay rehearsal IS recall
|
|
153
|
+
// strengthening (same markRetrieved dynamics), so the strengthen-off arm
|
|
154
|
+
// silences the whole pass - markRetrieved would return unmutated entries
|
|
155
|
+
// and persisting them anyway would still refresh updated_at / mirrors.
|
|
156
|
+
if (!(replayCount > 0 && survivors.length > 0 && !isRecallBoostAblated()))
|
|
157
|
+
return;
|
|
158
|
+
const seed = Math.floor(now.getTime() / 1000) & 0xffffffff;
|
|
159
|
+
const picked = sampleForReplay(survivors, replayCount, now, seed);
|
|
160
|
+
if (picked.length === 0)
|
|
161
|
+
return;
|
|
162
|
+
const rehearsed = markRetrieved(picked, now);
|
|
163
|
+
const rehearsedById = new Map(rehearsed.map((e) => [e.id, e]));
|
|
164
|
+
// Update survivors in place so downstream passes see rehearsed state.
|
|
165
|
+
for (let i = 0; i < survivors.length; i++) {
|
|
166
|
+
const replacement = rehearsedById.get(survivors[i].id);
|
|
167
|
+
if (replacement)
|
|
168
|
+
survivors[i] = replacement;
|
|
169
|
+
}
|
|
170
|
+
run.result.replayed = rehearsed.length;
|
|
171
|
+
run.result.details.push(` 💭 replayed ${rehearsed.length} memor${rehearsed.length === 1 ? 'y' : 'ies'}: ` +
|
|
172
|
+
rehearsed.map((e) => e.id).join(', '));
|
|
173
|
+
if (!run.dryRun) {
|
|
174
|
+
for (const r of rehearsed)
|
|
175
|
+
run.pendingWrites.push(r);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=traces.js.map
|
package/dist/context-auto.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFileSync } from 'child_process';
|
|
2
2
|
const SKIPPED_PATH_TERMS = ['src', 'dist', 'test', 'tests', 'node_modules', 'index'];
|
|
3
|
+
// stderr is dropped because git's warnings (line-ending notices, for one) would otherwise become query terms.
|
|
4
|
+
function readGit(args) {
|
|
5
|
+
return execFileSync('git', args, { encoding: 'utf8', timeout: 3000, stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true }).trim();
|
|
6
|
+
}
|
|
3
7
|
/** A context query from the cwd's git state ('' means `getContext` lists by strength); kept out of the api layer, which never shells out. */
|
|
4
8
|
export function autoDetectContext() {
|
|
5
9
|
try {
|
|
6
|
-
const diff =
|
|
7
|
-
encoding: 'utf8',
|
|
8
|
-
timeout: 3000,
|
|
9
|
-
windowsHide: true,
|
|
10
|
-
}).trim();
|
|
10
|
+
const diff = readGit(['diff', '--name-only', 'HEAD']);
|
|
11
11
|
if (diff) {
|
|
12
12
|
const terms = diff
|
|
13
13
|
.split('\n')
|
|
@@ -17,11 +17,7 @@ export function autoDetectContext() {
|
|
|
17
17
|
if (terms.length > 0)
|
|
18
18
|
return terms.join(' ');
|
|
19
19
|
}
|
|
20
|
-
const branch =
|
|
21
|
-
encoding: 'utf8',
|
|
22
|
-
timeout: 3000,
|
|
23
|
-
windowsHide: true,
|
|
24
|
-
}).trim();
|
|
20
|
+
const branch = readGit(['branch', '--show-current']);
|
|
25
21
|
if (branch && branch !== 'main' && branch !== 'master') {
|
|
26
22
|
return branch.replace(/[-_/]/g, ' ');
|
|
27
23
|
}
|
package/dist/context-render.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type MemoryEntry } from './memory.js';
|
|
2
2
|
import { type SessionHandoff } from './handoff.js';
|
|
3
|
-
import type { SessionEvent, TaskSnapshot } from './store.js';
|
|
3
|
+
import type { SessionEvent, TaskSnapshot } from './store/rows.js';
|
|
4
4
|
import type { AssembleCost, AssembleResult, AssembledContextItem, ContextCost, ContextResultEntry, DrillDownChild, DrillDownCost, DrillDownResult } from './api.js';
|
|
5
5
|
export declare function snapshotText(s: TaskSnapshot): string;
|
|
6
6
|
export declare function handoffText(h: SessionHandoff): string;
|
package/dist/context-render.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The strings a context block prints. The budget prices these same strings, so selection and print cannot drift.
|
|
2
2
|
import { calculateStrength, confidenceFacets, confidenceLabel } from './memory.js';
|
|
3
3
|
import { evalNow } from './ablation.js';
|
|
4
|
-
import { estimateTokens } from './
|
|
4
|
+
import { estimateTokens } from './token-ledger.js';
|
|
5
5
|
import { renderAmbientSummary } from './ambient.js';
|
|
6
6
|
import { formatHandoffEvidenceLine } from './handoff.js';
|
|
7
7
|
export function snapshotText(s) {
|
package/dist/customer-notes.d.ts
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
* Lifecycle: active -> superseded (a corrected version) or active -> closed (retired).
|
|
21
21
|
*/
|
|
22
|
+
import { type KeysetPosition } from './keyset.js';
|
|
22
23
|
export type NoteStatus = 'active' | 'superseded' | 'closed';
|
|
23
24
|
export declare const VALID_NOTE_STATES: ReadonlySet<NoteStatus>;
|
|
24
25
|
/** Field caps (untrusted at the HTTP/SDK boundary). note is a body, so a larger cap
|
|
@@ -61,6 +62,8 @@ export interface ListCustomerNotesOpts {
|
|
|
61
62
|
/** Filter to a single customer. */
|
|
62
63
|
customer?: string;
|
|
63
64
|
limit?: number;
|
|
65
|
+
/** Resume after this row: the position the previous page ended on. */
|
|
66
|
+
after?: KeysetPosition;
|
|
64
67
|
}
|
|
65
68
|
/**
|
|
66
69
|
* Create a customer_note (or a new version that supersedes an existing one). Writes
|
package/dist/customer-notes.js
CHANGED
|
@@ -21,12 +21,13 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import { BadRequestError, ConflictError, NotFoundError } from './api-errors.js';
|
|
23
23
|
import { openHippoDb, closeHippoDb } from './db.js';
|
|
24
|
-
import { writeEntry } from './store.js';
|
|
24
|
+
import { writeEntry } from './store/entry-writes.js';
|
|
25
25
|
import { assertTenantId } from './tenant.js';
|
|
26
|
-
import { markGraphDirty, removeGraphEntitiesForObject } from './graph.js';
|
|
26
|
+
import { markGraphDirty, removeGraphEntitiesForObject } from './graph/write.js';
|
|
27
27
|
import { createMemory, Layer } from './memory.js';
|
|
28
28
|
import { appendAuditEvent } from './audit.js';
|
|
29
29
|
import { objectHalfLifeDays } from './half-life-migration.js';
|
|
30
|
+
import { keysetAfter } from './keyset.js';
|
|
30
31
|
export const VALID_NOTE_STATES = new Set([
|
|
31
32
|
'active',
|
|
32
33
|
'superseded',
|
|
@@ -284,6 +285,7 @@ export function loadCustomerNoteById(hippoRoot, tenantId, id) {
|
|
|
284
285
|
export function loadCustomerNotes(hippoRoot, tenantId, opts = {}) {
|
|
285
286
|
assertTenantId('loadCustomerNotes', tenantId);
|
|
286
287
|
const limit = opts.limit ?? 100;
|
|
288
|
+
const after = keysetAfter('created_at', 'id', opts.after);
|
|
287
289
|
if (opts.status && !VALID_NOTE_STATES.has(opts.status)) {
|
|
288
290
|
throw new BadRequestError(`loadCustomerNotes: status must be one of ${Array.from(VALID_NOTE_STATES).join('|')}; got ${opts.status}`);
|
|
289
291
|
}
|
|
@@ -299,13 +301,13 @@ export function loadCustomerNotes(hippoRoot, tenantId, opts = {}) {
|
|
|
299
301
|
clauses.push('customer = ?');
|
|
300
302
|
params.push(opts.customer);
|
|
301
303
|
}
|
|
302
|
-
params.push(limit);
|
|
304
|
+
params.push(...after.params, limit);
|
|
303
305
|
// SAFETY: SELECT ${NOTE_COLS} projects exactly the CustomerNoteRow columns
|
|
304
306
|
// regardless of the dynamic WHERE clause built above; .all() returns rows
|
|
305
307
|
// in that shape.
|
|
306
308
|
const rows = db.prepare(`
|
|
307
309
|
SELECT ${NOTE_COLS} FROM customer_notes
|
|
308
|
-
WHERE ${clauses.join(' AND ')}
|
|
310
|
+
WHERE ${clauses.join(' AND ')}${after.sql}
|
|
309
311
|
ORDER BY created_at DESC, id DESC
|
|
310
312
|
LIMIT ?
|
|
311
313
|
`).all(...params);
|