hippo-memory 1.32.0 → 1.33.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/dist/api.d.ts +24 -17
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +78 -142
- package/dist/api.js.map +1 -1
- package/dist/audit-prune.d.ts.map +1 -1
- package/dist/audit-prune.js +7 -1
- package/dist/audit-prune.js.map +1 -1
- package/dist/audit.d.ts +3 -2
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js +13 -6
- package/dist/audit.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +6 -0
- package/dist/auth.js.map +1 -1
- package/dist/autolearn.js +4 -4
- package/dist/autolearn.js.map +1 -1
- package/dist/benchmarks/e1.3/incident-recall-eval.js +4 -0
- package/dist/benchmarks/e1.3/incident-recall-eval.js.map +1 -1
- package/dist/benchmarks/e1.3/slack-1000-event-smoke.js +2 -2
- package/dist/benchmarks/e1.3/slack-1000-event-smoke.js.map +1 -1
- package/dist/capture.d.ts.map +1 -1
- package/dist/capture.js +93 -66
- package/dist/capture.js.map +1 -1
- package/dist/client.d.ts +0 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +32 -14
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -4
- package/dist/config.js.map +1 -1
- package/dist/connectors/github/backfill.d.ts.map +1 -1
- package/dist/connectors/github/backfill.js +25 -16
- package/dist/connectors/github/backfill.js.map +1 -1
- package/dist/connectors/github/cli-impl.d.ts +2 -1
- package/dist/connectors/github/cli-impl.d.ts.map +1 -1
- package/dist/connectors/github/cli-impl.js +20 -4
- package/dist/connectors/github/cli-impl.js.map +1 -1
- package/dist/connectors/github/deletion.d.ts.map +1 -1
- package/dist/connectors/github/deletion.js +2 -0
- package/dist/connectors/github/deletion.js.map +1 -1
- package/dist/connectors/github/dlq.d.ts.map +1 -1
- package/dist/connectors/github/dlq.js +9 -1
- package/dist/connectors/github/dlq.js.map +1 -1
- package/dist/connectors/github/idempotency.d.ts.map +1 -1
- package/dist/connectors/github/idempotency.js +2 -0
- package/dist/connectors/github/idempotency.js.map +1 -1
- package/dist/connectors/github/octokit-client.d.ts +2 -1
- package/dist/connectors/github/octokit-client.d.ts.map +1 -1
- package/dist/connectors/github/octokit-client.js +8 -3
- package/dist/connectors/github/octokit-client.js.map +1 -1
- package/dist/connectors/github/tenant-routing.d.ts.map +1 -1
- package/dist/connectors/github/tenant-routing.js +8 -0
- package/dist/connectors/github/tenant-routing.js.map +1 -1
- package/dist/connectors/github/types.d.ts +14 -5
- package/dist/connectors/github/types.d.ts.map +1 -1
- package/dist/connectors/github/types.js +35 -29
- package/dist/connectors/github/types.js.map +1 -1
- package/dist/connectors/slack/backfill.d.ts.map +1 -1
- package/dist/connectors/slack/backfill.js +2 -0
- package/dist/connectors/slack/backfill.js.map +1 -1
- package/dist/connectors/slack/deletion.d.ts.map +1 -1
- package/dist/connectors/slack/deletion.js +2 -0
- package/dist/connectors/slack/deletion.js.map +1 -1
- package/dist/connectors/slack/dlq.d.ts.map +1 -1
- package/dist/connectors/slack/dlq.js +3 -1
- package/dist/connectors/slack/dlq.js.map +1 -1
- package/dist/connectors/slack/idempotency.d.ts.map +1 -1
- package/dist/connectors/slack/idempotency.js +2 -0
- package/dist/connectors/slack/idempotency.js.map +1 -1
- package/dist/connectors/slack/tenant-routing.d.ts.map +1 -1
- package/dist/connectors/slack/tenant-routing.js +4 -0
- package/dist/connectors/slack/tenant-routing.js.map +1 -1
- package/dist/connectors/slack/types.d.ts +8 -3
- package/dist/connectors/slack/types.d.ts.map +1 -1
- package/dist/connectors/slack/types.js +22 -10
- package/dist/connectors/slack/types.js.map +1 -1
- package/dist/connectors/slack/web-client.d.ts +0 -9
- package/dist/connectors/slack/web-client.d.ts.map +1 -1
- package/dist/connectors/slack/web-client.js +11 -11
- package/dist/connectors/slack/web-client.js.map +1 -1
- package/dist/connectors/slack/workspaces.d.ts.map +1 -1
- package/dist/connectors/slack/workspaces.js +2 -0
- package/dist/connectors/slack/workspaces.js.map +1 -1
- package/dist/consolidate.d.ts.map +1 -1
- package/dist/consolidate.js +8 -3
- package/dist/consolidate.js.map +1 -1
- package/dist/customer-notes.d.ts.map +1 -1
- package/dist/customer-notes.js +17 -0
- package/dist/customer-notes.js.map +1 -1
- package/dist/dag.js +1 -1
- package/dist/dag.js.map +1 -1
- package/dist/dashboard.d.ts.map +1 -1
- package/dist/dashboard.js +5 -2
- package/dist/dashboard.js.map +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +24 -0
- package/dist/db.js.map +1 -1
- package/dist/decisions.d.ts.map +1 -1
- package/dist/decisions.js +10 -0
- package/dist/decisions.js.map +1 -1
- package/dist/dedupe.d.ts +14 -6
- package/dist/dedupe.d.ts.map +1 -1
- package/dist/dedupe.js +61 -39
- package/dist/dedupe.js.map +1 -1
- package/dist/embedding-provider.d.ts.map +1 -1
- package/dist/embedding-provider.js +24 -15
- package/dist/embedding-provider.js.map +1 -1
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/embeddings.js +17 -1
- package/dist/embeddings.js.map +1 -1
- package/dist/eval-suite.d.ts.map +1 -1
- package/dist/eval-suite.js +5 -0
- package/dist/eval-suite.js.map +1 -1
- package/dist/extract.d.ts.map +1 -1
- package/dist/extract.js +10 -3
- package/dist/extract.js.map +1 -1
- package/dist/goals.d.ts.map +1 -1
- package/dist/goals.js +26 -12
- package/dist/goals.js.map +1 -1
- package/dist/graph-extract.d.ts.map +1 -1
- package/dist/graph-extract.js +9 -1
- package/dist/graph-extract.js.map +1 -1
- package/dist/graph-view.d.ts.map +1 -1
- package/dist/graph-view.js.map +1 -1
- package/dist/graph.d.ts.map +1 -1
- package/dist/graph.js +38 -13
- package/dist/graph.js.map +1 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +42 -21
- package/dist/hooks.js.map +1 -1
- package/dist/importers.d.ts.map +1 -1
- package/dist/importers.js +23 -42
- package/dist/importers.js.map +1 -1
- package/dist/incidents.d.ts.map +1 -1
- package/dist/incidents.js +14 -0
- package/dist/incidents.js.map +1 -1
- package/dist/mcp/server.d.ts +4 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +58 -28
- package/dist/mcp/server.js.map +1 -1
- package/dist/memory-value.d.ts +0 -10
- package/dist/memory-value.d.ts.map +1 -1
- package/dist/memory-value.js +8 -2
- package/dist/memory-value.js.map +1 -1
- package/dist/memory.js.map +1 -1
- package/dist/physics-state.d.ts.map +1 -1
- package/dist/physics-state.js +5 -0
- package/dist/physics-state.js.map +1 -1
- package/dist/physics.js.map +1 -1
- package/dist/policies.d.ts.map +1 -1
- package/dist/policies.js +22 -0
- package/dist/policies.js.map +1 -1
- package/dist/predictions.d.ts.map +1 -1
- package/dist/predictions.js +14 -0
- package/dist/predictions.js.map +1 -1
- package/dist/processes.d.ts +7 -1
- package/dist/processes.d.ts.map +1 -1
- package/dist/processes.js +21 -2
- package/dist/processes.js.map +1 -1
- package/dist/project-briefs.d.ts.map +1 -1
- package/dist/project-briefs.js +28 -2
- package/dist/project-briefs.js.map +1 -1
- package/dist/raw-archive-mirror-cleanup.d.ts.map +1 -1
- package/dist/raw-archive-mirror-cleanup.js +2 -0
- package/dist/raw-archive-mirror-cleanup.js.map +1 -1
- package/dist/raw-archive.d.ts +0 -9
- package/dist/raw-archive.d.ts.map +1 -1
- package/dist/raw-archive.js +3 -9
- package/dist/raw-archive.js.map +1 -1
- package/dist/recall-scope.d.ts.map +1 -1
- package/dist/recall-scope.js +11 -6
- package/dist/recall-scope.js.map +1 -1
- package/dist/recall-trace.d.ts.map +1 -1
- package/dist/recall-trace.js +7 -3
- package/dist/recall-trace.js.map +1 -1
- package/dist/refine-llm.d.ts.map +1 -1
- package/dist/refine-llm.js +3 -0
- package/dist/refine-llm.js.map +1 -1
- package/dist/reject-flow.d.ts.map +1 -1
- package/dist/reject-flow.js +2 -0
- package/dist/reject-flow.js.map +1 -1
- package/dist/rejection.d.ts.map +1 -1
- package/dist/rejection.js +3 -0
- package/dist/rejection.js.map +1 -1
- package/dist/replay.js.map +1 -1
- package/dist/rerankers/cross-encoder.d.ts.map +1 -1
- package/dist/rerankers/cross-encoder.js +11 -4
- package/dist/rerankers/cross-encoder.js.map +1 -1
- package/dist/rerankers/index.d.ts.map +1 -1
- package/dist/rerankers/index.js +5 -3
- package/dist/rerankers/index.js.map +1 -1
- package/dist/rerankers/llm.d.ts.map +1 -1
- package/dist/rerankers/llm.js +8 -5
- package/dist/rerankers/llm.js.map +1 -1
- package/dist/rerankers/types.d.ts +6 -1
- package/dist/rerankers/types.d.ts.map +1 -1
- package/dist/scheduler.d.ts +16 -0
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +15 -5
- package/dist/scheduler.js.map +1 -1
- package/dist/search.d.ts +4 -6
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js.map +1 -1
- package/dist/server-detect.d.ts.map +1 -1
- package/dist/server-detect.js +2 -0
- package/dist/server-detect.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +194 -135
- package/dist/server.js.map +1 -1
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +10 -3
- package/dist/skills.js.map +1 -1
- package/dist/src/api.js +78 -142
- package/dist/src/api.js.map +1 -1
- package/dist/src/audit-prune.js +7 -1
- package/dist/src/audit-prune.js.map +1 -1
- package/dist/src/audit.js +13 -6
- package/dist/src/audit.js.map +1 -1
- package/dist/src/auth.js +6 -0
- package/dist/src/auth.js.map +1 -1
- package/dist/src/autolearn.js +4 -4
- package/dist/src/autolearn.js.map +1 -1
- package/dist/src/capture.js +93 -66
- package/dist/src/capture.js.map +1 -1
- package/dist/src/client.js +32 -14
- package/dist/src/client.js.map +1 -1
- package/dist/src/config.js +7 -4
- package/dist/src/config.js.map +1 -1
- package/dist/src/connectors/github/backfill.js +25 -16
- package/dist/src/connectors/github/backfill.js.map +1 -1
- package/dist/src/connectors/github/cli-impl.js +20 -4
- package/dist/src/connectors/github/cli-impl.js.map +1 -1
- package/dist/src/connectors/github/deletion.js +2 -0
- package/dist/src/connectors/github/deletion.js.map +1 -1
- package/dist/src/connectors/github/dlq.js +9 -1
- package/dist/src/connectors/github/dlq.js.map +1 -1
- package/dist/src/connectors/github/idempotency.js +2 -0
- package/dist/src/connectors/github/idempotency.js.map +1 -1
- package/dist/src/connectors/github/octokit-client.js +8 -3
- package/dist/src/connectors/github/octokit-client.js.map +1 -1
- package/dist/src/connectors/github/tenant-routing.js +8 -0
- package/dist/src/connectors/github/tenant-routing.js.map +1 -1
- package/dist/src/connectors/github/types.js +35 -29
- package/dist/src/connectors/github/types.js.map +1 -1
- package/dist/src/connectors/slack/backfill.js +2 -0
- package/dist/src/connectors/slack/backfill.js.map +1 -1
- package/dist/src/connectors/slack/deletion.js +2 -0
- package/dist/src/connectors/slack/deletion.js.map +1 -1
- package/dist/src/connectors/slack/dlq.js +3 -1
- package/dist/src/connectors/slack/dlq.js.map +1 -1
- package/dist/src/connectors/slack/idempotency.js +2 -0
- package/dist/src/connectors/slack/idempotency.js.map +1 -1
- package/dist/src/connectors/slack/tenant-routing.js +4 -0
- package/dist/src/connectors/slack/tenant-routing.js.map +1 -1
- package/dist/src/connectors/slack/types.js +22 -10
- package/dist/src/connectors/slack/types.js.map +1 -1
- package/dist/src/connectors/slack/web-client.js +11 -11
- package/dist/src/connectors/slack/web-client.js.map +1 -1
- package/dist/src/connectors/slack/workspaces.js +2 -0
- package/dist/src/connectors/slack/workspaces.js.map +1 -1
- package/dist/src/consolidate.js +8 -3
- package/dist/src/consolidate.js.map +1 -1
- package/dist/src/customer-notes.js +17 -0
- package/dist/src/customer-notes.js.map +1 -1
- package/dist/src/dag.js +1 -1
- package/dist/src/dag.js.map +1 -1
- package/dist/src/dashboard.js +5 -2
- package/dist/src/dashboard.js.map +1 -1
- package/dist/src/db.js +24 -0
- package/dist/src/db.js.map +1 -1
- package/dist/src/decisions.js +10 -0
- package/dist/src/decisions.js.map +1 -1
- package/dist/src/dedupe.js +61 -39
- package/dist/src/dedupe.js.map +1 -1
- package/dist/src/embedding-provider.js +24 -15
- package/dist/src/embedding-provider.js.map +1 -1
- package/dist/src/embeddings.js +17 -1
- package/dist/src/embeddings.js.map +1 -1
- package/dist/src/eval-suite.js +5 -0
- package/dist/src/eval-suite.js.map +1 -1
- package/dist/src/extract.js +10 -3
- package/dist/src/extract.js.map +1 -1
- package/dist/src/goals.js +26 -12
- package/dist/src/goals.js.map +1 -1
- package/dist/src/graph-extract.js +9 -1
- package/dist/src/graph-extract.js.map +1 -1
- package/dist/src/graph-view.js.map +1 -1
- package/dist/src/graph.js +38 -13
- package/dist/src/graph.js.map +1 -1
- package/dist/src/hooks.js +42 -21
- package/dist/src/hooks.js.map +1 -1
- package/dist/src/importers.js +23 -42
- package/dist/src/importers.js.map +1 -1
- package/dist/src/incidents.js +14 -0
- package/dist/src/incidents.js.map +1 -1
- package/dist/src/mcp/server.js +58 -28
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/memory-value.js +8 -2
- package/dist/src/memory-value.js.map +1 -1
- package/dist/src/memory.js.map +1 -1
- package/dist/src/physics-state.js +5 -0
- package/dist/src/physics-state.js.map +1 -1
- package/dist/src/physics.js.map +1 -1
- package/dist/src/policies.js +22 -0
- package/dist/src/policies.js.map +1 -1
- package/dist/src/predictions.js +14 -0
- package/dist/src/predictions.js.map +1 -1
- package/dist/src/processes.js +21 -2
- package/dist/src/processes.js.map +1 -1
- package/dist/src/project-briefs.js +28 -2
- package/dist/src/project-briefs.js.map +1 -1
- package/dist/src/raw-archive-mirror-cleanup.js +2 -0
- package/dist/src/raw-archive-mirror-cleanup.js.map +1 -1
- package/dist/src/raw-archive.js +3 -9
- package/dist/src/raw-archive.js.map +1 -1
- package/dist/src/recall-scope.js +11 -6
- package/dist/src/recall-scope.js.map +1 -1
- package/dist/src/recall-trace.js +7 -3
- package/dist/src/recall-trace.js.map +1 -1
- package/dist/src/refine-llm.js +3 -0
- package/dist/src/refine-llm.js.map +1 -1
- package/dist/src/reject-flow.js +2 -0
- package/dist/src/reject-flow.js.map +1 -1
- package/dist/src/rejection.js +3 -0
- package/dist/src/rejection.js.map +1 -1
- package/dist/src/replay.js.map +1 -1
- package/dist/src/rerankers/cross-encoder.js +11 -4
- package/dist/src/rerankers/cross-encoder.js.map +1 -1
- package/dist/src/rerankers/index.js +5 -3
- package/dist/src/rerankers/index.js.map +1 -1
- package/dist/src/rerankers/llm.js +8 -5
- package/dist/src/rerankers/llm.js.map +1 -1
- package/dist/src/scheduler.js +15 -5
- package/dist/src/scheduler.js.map +1 -1
- package/dist/src/search.js.map +1 -1
- package/dist/src/server-detect.js +2 -0
- package/dist/src/server-detect.js.map +1 -1
- package/dist/src/server.js +194 -135
- package/dist/src/server.js.map +1 -1
- package/dist/src/skills.js +10 -3
- package/dist/src/skills.js.map +1 -1
- package/dist/src/store.js +140 -14
- package/dist/src/store.js.map +1 -1
- package/dist/src/trace.js +15 -7
- package/dist/src/trace.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/working-memory.js +8 -0
- package/dist/src/working-memory.js.map +1 -1
- package/dist/src/yaml.js +12 -3
- package/dist/src/yaml.js.map +1 -1
- package/dist/store.d.ts +16 -3
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +140 -14
- package/dist/store.js.map +1 -1
- package/dist/trace.d.ts.map +1 -1
- package/dist/trace.js +15 -7
- package/dist/trace.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/working-memory.d.ts +6 -2
- package/dist/working-memory.d.ts.map +1 -1
- package/dist/working-memory.js +8 -0
- package/dist/working-memory.js.map +1 -1
- package/dist/yaml.d.ts.map +1 -1
- package/dist/yaml.js +12 -3
- package/dist/yaml.js.map +1 -1
- package/dist-ui/assets/{index-Cxa4RcAh.js → index-DOqenbV2.js} +11 -11
- package/dist-ui/index.html +1 -1
- package/extensions/openclaw-plugin/index.ts +50 -10
- 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 -1
package/dist/src/skills.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/skills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAQ9C,MAAM,CAAC,MAAM,kBAAkB,GAA6B,IAAI,GAAG,CAAc;IAC/E,QAAQ;IACR,YAAY;IACZ,QAAQ;CACT,CAAC,CAAC;AAEH;uDACuD;AACvD,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AACtC,MAAM,CAAC,MAAM,0BAA0B,GAAG,IAAI,CAAC;AAC/C,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAC1C;sFACsF;AACtF,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/skills.ts"],"names":[],"mappings":"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"}
|
package/dist/src/store.js
CHANGED
|
@@ -175,7 +175,11 @@ export function serializeEntry(entry) {
|
|
|
175
175
|
if (entry.origin_project !== undefined && entry.origin_project !== null) {
|
|
176
176
|
frontmatter['origin_project'] = entry.origin_project;
|
|
177
177
|
}
|
|
178
|
-
|
|
178
|
+
// Spread into a fresh object literal: dumpFrontmatter's Record<string,
|
|
179
|
+
// YamlValue> parameter needs an index signature, which a named interface
|
|
180
|
+
// reference (EntryFrontmatterFields) doesn't structurally provide even
|
|
181
|
+
// though every property's value type already matches.
|
|
182
|
+
const fm = dumpFrontmatter({ ...frontmatter });
|
|
179
183
|
return `${fm}\n\n${entry.content}\n`;
|
|
180
184
|
}
|
|
181
185
|
/**
|
|
@@ -185,6 +189,11 @@ export function deserializeEntry(raw) {
|
|
|
185
189
|
const { data, content } = parseFrontmatter(raw);
|
|
186
190
|
if (!data['id'] || !data['layer'])
|
|
187
191
|
return null;
|
|
192
|
+
// SAFETY: every `as X` below narrows a raw YAML frontmatter field to an
|
|
193
|
+
// enum/union member of MemoryEntry; frontmatter is only ever written by
|
|
194
|
+
// serializeEntry (whose own fields are typed), so out-of-range values here
|
|
195
|
+
// would indicate hand-edited files, which this parser is not required to
|
|
196
|
+
// reject — matches the pre-existing permissive-parse behavior.
|
|
188
197
|
return {
|
|
189
198
|
id: String(data['id']),
|
|
190
199
|
created: String(data['created'] ?? new Date().toISOString()),
|
|
@@ -231,7 +240,11 @@ function normalizeStringArray(value) {
|
|
|
231
240
|
return value.map((item) => String(item));
|
|
232
241
|
}
|
|
233
242
|
function rowToEntry(row) {
|
|
234
|
-
|
|
243
|
+
// SAFETY: every `as X` below narrows a SQLite column value to an
|
|
244
|
+
// enum/union member of MemoryEntry; `row` comes from MEMORY_SELECT_COLUMNS
|
|
245
|
+
// / MEMORY_SEARCH_COLUMNS, which are the only queries producing MemoryRow,
|
|
246
|
+
// and the DB layer only ever writes these columns from the same enums.
|
|
247
|
+
const entry = {
|
|
235
248
|
id: row.id,
|
|
236
249
|
created: row.created,
|
|
237
250
|
last_retrieved: row.last_retrieved,
|
|
@@ -273,13 +286,14 @@ function rowToEntry(row) {
|
|
|
273
286
|
last_rebuilt_at: row.last_rebuilt_at ?? null,
|
|
274
287
|
rebuild_count: Number(row.rebuild_count ?? 0),
|
|
275
288
|
dag_level_3_built_at: row.dag_level_3_built_at ?? null,
|
|
276
|
-
// F1 (v1.7.0): preserve bm25_score from the FTS path. `'bm25_score' in row`
|
|
277
|
-
// distinguishes "absent column" (non-FTS path) from "column present but
|
|
278
|
-
// value 0" — though FTS5 bm25() never returns 0, this is defensive.
|
|
279
|
-
...('bm25_score' in row && row.bm25_score !== undefined && row.bm25_score !== null
|
|
280
|
-
? { bm25_score: Number(row.bm25_score) }
|
|
281
|
-
: {}),
|
|
282
289
|
};
|
|
290
|
+
// F1 (v1.7.0): preserve bm25_score from the FTS path. `'bm25_score' in row`
|
|
291
|
+
// distinguishes "absent column" (non-FTS path) from "column present but
|
|
292
|
+
// value 0" — though FTS5 bm25() never returns 0, this is defensive.
|
|
293
|
+
if ('bm25_score' in row && row.bm25_score !== undefined && row.bm25_score !== null) {
|
|
294
|
+
entry.bm25_score = Number(row.bm25_score);
|
|
295
|
+
}
|
|
296
|
+
return entry;
|
|
283
297
|
}
|
|
284
298
|
function parseJsonArray(raw) {
|
|
285
299
|
if (!raw)
|
|
@@ -309,12 +323,15 @@ function parseLastTraceId(raw) {
|
|
|
309
323
|
return null;
|
|
310
324
|
return trimmed;
|
|
311
325
|
}
|
|
326
|
+
function isPlainJsonObject(x) {
|
|
327
|
+
return x !== null && typeof x === 'object' && !Array.isArray(x);
|
|
328
|
+
}
|
|
312
329
|
function parseJsonObject(raw) {
|
|
313
330
|
if (!raw)
|
|
314
331
|
return {};
|
|
315
332
|
try {
|
|
316
333
|
const parsed = JSON.parse(raw);
|
|
317
|
-
if (
|
|
334
|
+
if (isPlainJsonObject(parsed)) {
|
|
318
335
|
return parsed;
|
|
319
336
|
}
|
|
320
337
|
return {};
|
|
@@ -585,6 +602,8 @@ function loadSearchRows(db, query, limit, tenantId, scopeFilter) {
|
|
|
585
602
|
// this no-terms path had the same shape). Apply LIMIT so all four
|
|
586
603
|
// candidate paths honour the caller's cap when set.
|
|
587
604
|
const sql = `SELECT ${MEMORY_SELECT_COLUMNS} FROM memories${tenantOnlyPredicate}${archivedClauseTenantOnly}${scopeClauseTenantOnly} ORDER BY created ASC, id ASC LIMIT ?`;
|
|
605
|
+
// SAFETY: sql selects exactly MEMORY_SELECT_COLUMNS, whose column list
|
|
606
|
+
// matches MemoryRow's field set.
|
|
588
607
|
return db.prepare(sql).all(...tenantParams, ...scopeParams, limit);
|
|
589
608
|
}
|
|
590
609
|
// v1.7.1 — test/diagnostic hook: `HIPPO_FORCE_LIKE_PATH=1` forces the
|
|
@@ -603,6 +622,8 @@ function loadSearchRows(db, query, limit, tenantId, scopeFilter) {
|
|
|
603
622
|
// F1 (v1.7.0): MEMORY_SEARCH_COLUMNS adds bm25_score as the trailing
|
|
604
623
|
// result column. Every other column is m.<col> AS <col> so rowToEntry
|
|
605
624
|
// sees the same shape it always has.
|
|
625
|
+
// SAFETY: MEMORY_SEARCH_COLUMNS aliases every column to the same name
|
|
626
|
+
// MEMORY_SELECT_COLUMNS uses (plus bm25_score), matching MemoryRow.
|
|
606
627
|
const rows = db.prepare(`
|
|
607
628
|
SELECT ${MEMORY_SEARCH_COLUMNS}
|
|
608
629
|
FROM memories m
|
|
@@ -624,6 +645,8 @@ function loadSearchRows(db, query, limit, tenantId, scopeFilter) {
|
|
|
624
645
|
const like = `%${escapeLike(term)}%`;
|
|
625
646
|
return [like, like];
|
|
626
647
|
});
|
|
648
|
+
// SAFETY: this query selects exactly MEMORY_SELECT_COLUMNS, matching
|
|
649
|
+
// MemoryRow's field set.
|
|
627
650
|
const rows = db.prepare(`
|
|
628
651
|
SELECT ${MEMORY_SELECT_COLUMNS}
|
|
629
652
|
FROM memories
|
|
@@ -639,6 +662,8 @@ function loadSearchRows(db, query, limit, tenantId, scopeFilter) {
|
|
|
639
662
|
// candidate-pool size. Apply LIMIT here so all four paths honour the
|
|
640
663
|
// caller's cap.
|
|
641
664
|
const fallback = `SELECT ${MEMORY_SELECT_COLUMNS} FROM memories${tenantOnlyPredicate}${archivedClauseTenantOnly}${scopeClauseTenantOnly} ORDER BY created ASC, id ASC LIMIT ?`;
|
|
665
|
+
// SAFETY: fallback selects exactly MEMORY_SELECT_COLUMNS, matching
|
|
666
|
+
// MemoryRow's field set.
|
|
642
667
|
return db.prepare(fallback).all(...tenantParams, ...scopeParams, limit);
|
|
643
668
|
}
|
|
644
669
|
function writeMarkdownMirror(hippoRoot, entry) {
|
|
@@ -724,6 +749,8 @@ export function purgeMirrorBestEffort(hippoRoot, id, isRaw, logPrefix) {
|
|
|
724
749
|
}
|
|
725
750
|
}
|
|
726
751
|
function bootstrapLegacyStore(db, hippoRoot) {
|
|
752
|
+
// SAFETY: countRow's shape matches the single `COUNT(*) AS count` column
|
|
753
|
+
// selected above; `.get()` returns undefined only when no row exists.
|
|
727
754
|
const countRow = db.prepare(`SELECT COUNT(*) AS count FROM memories`).get();
|
|
728
755
|
const memoryCount = Number(countRow?.count ?? 0);
|
|
729
756
|
if (memoryCount > 0)
|
|
@@ -788,7 +815,7 @@ function bootstrapLegacyStore(db, hippoRoot) {
|
|
|
788
815
|
const runs = Array.isArray(legacyStats.consolidation_runs) ? legacyStats.consolidation_runs : [];
|
|
789
816
|
const insertRun = db.prepare(`INSERT INTO consolidation_runs(timestamp, decayed, merged, removed) VALUES (?, ?, ?, ?)`);
|
|
790
817
|
for (const run of runs) {
|
|
791
|
-
if (!run
|
|
818
|
+
if (!isPlainJsonObject(run))
|
|
792
819
|
continue;
|
|
793
820
|
const row = run;
|
|
794
821
|
insertRun.run(String(row.timestamp ?? new Date().toISOString()), Number(row.decayed ?? 0), Number(row.merged ?? 0), Number(row.removed ?? 0));
|
|
@@ -827,6 +854,9 @@ function loadLegacyIndexFile(hippoRoot) {
|
|
|
827
854
|
return { version: 1, entries: {}, last_retrieval_ids: [], last_trace_id: null };
|
|
828
855
|
}
|
|
829
856
|
try {
|
|
857
|
+
// SAFETY: index.json is only ever written by writeIndexMirror below,
|
|
858
|
+
// which always serializes a HippoIndex; a hand-edited or corrupted file
|
|
859
|
+
// that violates the shape falls through to the catch block's fallback.
|
|
830
860
|
return JSON.parse(fs.readFileSync(indexPath, 'utf8'));
|
|
831
861
|
}
|
|
832
862
|
catch {
|
|
@@ -844,6 +874,10 @@ function loadLegacyStatsFile(hippoRoot) {
|
|
|
844
874
|
};
|
|
845
875
|
}
|
|
846
876
|
try {
|
|
877
|
+
// SAFETY: stats.json is only ever written by writeStatsMirror below,
|
|
878
|
+
// which always emits exactly these four fields; callers additionally
|
|
879
|
+
// guard every read with `?? 0` / `Array.isArray`, tolerating a
|
|
880
|
+
// hand-edited or corrupted file even if this optimistic cast is wrong.
|
|
847
881
|
return JSON.parse(fs.readFileSync(statsPath, 'utf8'));
|
|
848
882
|
}
|
|
849
883
|
catch {
|
|
@@ -968,9 +1002,12 @@ function deleteFtsRow(db, id) {
|
|
|
968
1002
|
* without duplicating this query.
|
|
969
1003
|
*/
|
|
970
1004
|
export function buildIndexFromDb(db) {
|
|
1005
|
+
// SAFETY: rows' shape matches the seven columns named in the SELECT below.
|
|
971
1006
|
const rows = db.prepare(`SELECT id, created, last_retrieved, strength, layer, tags_json, pinned FROM memories ORDER BY created ASC, id ASC`).all();
|
|
972
1007
|
const entries = {};
|
|
973
1008
|
for (const row of rows) {
|
|
1009
|
+
// SAFETY: layer is only ever written from the Layer enum by this
|
|
1010
|
+
// module's own INSERT/UPDATE paths.
|
|
974
1011
|
const layer = row.layer;
|
|
975
1012
|
entries[row.id] = {
|
|
976
1013
|
id: row.id,
|
|
@@ -989,6 +1026,7 @@ export function buildIndexFromDb(db) {
|
|
|
989
1026
|
// them, handing the reader mismatched last_retrieval_ids / last_trace_id
|
|
990
1027
|
// and re-opening the mislinkage hole saveIndex's BEGIN/COMMIT closed on
|
|
991
1028
|
// the write side. One SELECT = one SQLite read snapshot.
|
|
1029
|
+
// SAFETY: lockstepRows' shape matches the key/value columns named above.
|
|
992
1030
|
const lockstepRows = db.prepare(`SELECT key, value FROM meta WHERE key IN ('last_retrieval_ids', 'last_trace_id')`).all();
|
|
993
1031
|
const lockstep = new Map(lockstepRows.map((r) => [r.key, r.value]));
|
|
994
1032
|
return {
|
|
@@ -999,12 +1037,18 @@ export function buildIndexFromDb(db) {
|
|
|
999
1037
|
};
|
|
1000
1038
|
}
|
|
1001
1039
|
function buildStatsFromDb(db) {
|
|
1040
|
+
// SAFETY: runs' shape matches the four columns named in the SELECT above.
|
|
1002
1041
|
const runs = db.prepare(`SELECT timestamp, decayed, merged, removed FROM consolidation_runs ORDER BY timestamp ASC, id ASC`).all();
|
|
1003
1042
|
return {
|
|
1004
1043
|
total_remembered: Number(getMeta(db, 'total_remembered', '0')),
|
|
1005
1044
|
total_recalled: Number(getMeta(db, 'total_recalled', '0')),
|
|
1006
1045
|
total_forgotten: Number(getMeta(db, 'total_forgotten', '0')),
|
|
1007
|
-
consolidation_runs: runs
|
|
1046
|
+
consolidation_runs: runs.map((run) => ({
|
|
1047
|
+
timestamp: run.timestamp,
|
|
1048
|
+
decayed: run.decayed,
|
|
1049
|
+
merged: run.merged,
|
|
1050
|
+
removed: run.removed,
|
|
1051
|
+
})),
|
|
1008
1052
|
};
|
|
1009
1053
|
}
|
|
1010
1054
|
/**
|
|
@@ -1021,10 +1065,14 @@ function writeStatsMirror(hippoRoot, stats) {
|
|
|
1021
1065
|
fs.writeFileSync(path.join(hippoRoot, 'stats.json'), JSON.stringify(stats, null, 2), 'utf8');
|
|
1022
1066
|
}
|
|
1023
1067
|
function syncMirrorFiles(hippoRoot, db) {
|
|
1068
|
+
// SAFETY: this query selects exactly MEMORY_SELECT_COLUMNS, matching
|
|
1069
|
+
// MemoryRow's field set.
|
|
1024
1070
|
const entries = db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories ORDER BY created ASC, id ASC`).all();
|
|
1025
1071
|
for (const entry of entries.map(rowToEntry)) {
|
|
1026
1072
|
writeMarkdownMirror(hippoRoot, entry);
|
|
1027
1073
|
}
|
|
1074
|
+
// SAFETY: conflicts' shape matches the eight columns named in the SELECT
|
|
1075
|
+
// above.
|
|
1028
1076
|
const conflicts = db.prepare(`
|
|
1029
1077
|
SELECT id, memory_a_id, memory_b_id, reason, score, status, detected_at, updated_at
|
|
1030
1078
|
FROM memory_conflicts
|
|
@@ -1225,6 +1273,8 @@ export function readEntry(hippoRoot, id, tenantId) {
|
|
|
1225
1273
|
initStore(hippoRoot);
|
|
1226
1274
|
const db = openHippoDb(hippoRoot);
|
|
1227
1275
|
try {
|
|
1276
|
+
// SAFETY: both branches select exactly MEMORY_SELECT_COLUMNS, matching
|
|
1277
|
+
// MemoryRow's field set.
|
|
1228
1278
|
const row = tenantId !== undefined
|
|
1229
1279
|
? db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories WHERE id = ? AND tenant_id = ?`).get(id, tenantId)
|
|
1230
1280
|
: db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories WHERE id = ?`).get(id);
|
|
@@ -1251,6 +1301,8 @@ export function loadEntriesByIds(hippoRoot, ids, tenantId) {
|
|
|
1251
1301
|
// T2: no ORDER BY meant row order followed SQLite's IN(...) scan order
|
|
1252
1302
|
// (undefined w.r.t. the caller's `ids` order). created ASC, id ASC
|
|
1253
1303
|
// makes it deterministic.
|
|
1304
|
+
// SAFETY: both branches select exactly MEMORY_SELECT_COLUMNS, matching
|
|
1305
|
+
// MemoryRow's field set.
|
|
1254
1306
|
const rows = tenantId !== undefined
|
|
1255
1307
|
? db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories WHERE id IN (${placeholders}) AND tenant_id = ? ORDER BY created ASC, content ASC, id ASC`).all(...capped, tenantId)
|
|
1256
1308
|
: db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories WHERE id IN (${placeholders}) ORDER BY created ASC, content ASC, id ASC`).all(...capped);
|
|
@@ -1288,10 +1340,12 @@ export function loadSessionRawMemories(hippoRoot, sessionId, tenantId, cap) {
|
|
|
1288
1340
|
if (cap !== undefined && cap > 0) {
|
|
1289
1341
|
sql += ' ORDER BY created DESC, id DESC LIMIT ?';
|
|
1290
1342
|
params.push(cap);
|
|
1343
|
+
// SAFETY: sql starts from MEMORY_SELECT_COLUMNS, matching MemoryRow.
|
|
1291
1344
|
const rows = db.prepare(sql).all(...params);
|
|
1292
1345
|
return rows.reverse().map(rowToEntry);
|
|
1293
1346
|
}
|
|
1294
1347
|
sql += ' ORDER BY created ASC, id ASC';
|
|
1348
|
+
// SAFETY: sql starts from MEMORY_SELECT_COLUMNS, matching MemoryRow.
|
|
1295
1349
|
const rows = db.prepare(sql).all(...params);
|
|
1296
1350
|
return rows.map(rowToEntry);
|
|
1297
1351
|
}
|
|
@@ -1338,6 +1392,7 @@ export function countSessionRawMemories(hippoRoot, sessionId, tenantId, scope) {
|
|
|
1338
1392
|
// AND != 'unknown:legacy'). Mirrors api.passesScopeFilterForRecall.
|
|
1339
1393
|
sql += ` AND (scope IS NULL OR (scope NOT LIKE '%:private:%' AND scope != 'unknown:legacy'))`;
|
|
1340
1394
|
}
|
|
1395
|
+
// SAFETY: row's shape matches the single `COUNT(*) AS c` column above.
|
|
1341
1396
|
const row = db.prepare(sql).get(...params);
|
|
1342
1397
|
return Number(row?.c ?? 0);
|
|
1343
1398
|
}
|
|
@@ -1392,6 +1447,7 @@ export function loadFreshRawMemories(hippoRoot, count, tenantId, sessionId) {
|
|
|
1392
1447
|
// cross-ingest-stable.
|
|
1393
1448
|
sql += ' ORDER BY created DESC, content ASC, id ASC LIMIT ?';
|
|
1394
1449
|
params.push(capped);
|
|
1450
|
+
// SAFETY: sql starts from MEMORY_SELECT_COLUMNS, matching MemoryRow.
|
|
1395
1451
|
const rows = db.prepare(sql).all(...params);
|
|
1396
1452
|
return rows.map(rowToEntry);
|
|
1397
1453
|
}
|
|
@@ -1408,6 +1464,8 @@ export function loadChildrenOf(hippoRoot, parentId, tenantId) {
|
|
|
1408
1464
|
initStore(hippoRoot);
|
|
1409
1465
|
const db = openHippoDb(hippoRoot);
|
|
1410
1466
|
try {
|
|
1467
|
+
// SAFETY: both branches select exactly MEMORY_SELECT_COLUMNS, matching
|
|
1468
|
+
// MemoryRow's field set.
|
|
1411
1469
|
const rows = tenantId !== undefined
|
|
1412
1470
|
? db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories WHERE dag_parent_id = ? AND tenant_id = ? ORDER BY created ASC, id ASC`).all(parentId, tenantId)
|
|
1413
1471
|
: db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories WHERE dag_parent_id = ? ORDER BY created ASC, id ASC`).all(parentId);
|
|
@@ -1437,6 +1495,7 @@ export function loadChildrenOf(hippoRoot, parentId, tenantId) {
|
|
|
1437
1495
|
* with `id` existed.
|
|
1438
1496
|
*/
|
|
1439
1497
|
export function deleteEntryCore(db, id, opts) {
|
|
1498
|
+
// SAFETY: row's shape matches the three columns named in the SELECT above.
|
|
1440
1499
|
const row = db
|
|
1441
1500
|
.prepare(`SELECT id, tenant_id, dag_parent_id FROM memories WHERE id = ?`)
|
|
1442
1501
|
.get(id);
|
|
@@ -1511,6 +1570,8 @@ export function batchWriteAndDelete(hippoRoot, toWrite, toDeleteIds) {
|
|
|
1511
1570
|
const tenantById = new Map();
|
|
1512
1571
|
if (toDeleteIds.length > 0) {
|
|
1513
1572
|
const placeholders = toDeleteIds.map(() => '?').join(',');
|
|
1573
|
+
// SAFETY: rows' shape matches the two columns named in the SELECT
|
|
1574
|
+
// above.
|
|
1514
1575
|
const rows = db.prepare(`SELECT dag_parent_id, tenant_id FROM memories WHERE id IN (${placeholders})`).all(...toDeleteIds);
|
|
1515
1576
|
for (const row of rows) {
|
|
1516
1577
|
if (row.dag_parent_id) {
|
|
@@ -1633,6 +1694,8 @@ export function loadAllEntries(hippoRoot, tenantId) {
|
|
|
1633
1694
|
initStore(hippoRoot);
|
|
1634
1695
|
const db = openHippoDb(hippoRoot);
|
|
1635
1696
|
try {
|
|
1697
|
+
// SAFETY: both branches select exactly MEMORY_SELECT_COLUMNS, matching
|
|
1698
|
+
// MemoryRow's field set.
|
|
1636
1699
|
const rows = tenantId !== undefined
|
|
1637
1700
|
? db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories WHERE tenant_id = ? ORDER BY created ASC, id ASC`).all(tenantId)
|
|
1638
1701
|
: db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories ORDER BY created ASC, id ASC`).all();
|
|
@@ -1709,6 +1772,7 @@ export function rebuildIndex(hippoRoot) {
|
|
|
1709
1772
|
initStore(hippoRoot);
|
|
1710
1773
|
const db = openHippoDb(hippoRoot);
|
|
1711
1774
|
try {
|
|
1775
|
+
// SAFETY: rows' shape matches the single `id` column selected above.
|
|
1712
1776
|
const existingIds = new Set(db.prepare(`SELECT id FROM memories`).all().map((row) => row.id));
|
|
1713
1777
|
const legacyEntries = loadLegacyEntriesFromMarkdown(hippoRoot).filter((entry) => !existingIds.has(entry.id));
|
|
1714
1778
|
if (legacyEntries.length > 0) {
|
|
@@ -1803,6 +1867,7 @@ export function loadSessionDecayContext(hippoRoot) {
|
|
|
1803
1867
|
const db = openHippoDb(hippoRoot);
|
|
1804
1868
|
try {
|
|
1805
1869
|
// Get recent consolidation timestamps (last 20)
|
|
1870
|
+
// SAFETY: rows' shape matches the single `timestamp` column above.
|
|
1806
1871
|
const rows = db.prepare(`SELECT timestamp FROM consolidation_runs ORDER BY timestamp DESC, id DESC LIMIT 20`).all();
|
|
1807
1872
|
const sleepCount = Number(getMeta(db, 'sleep_count', '0')) || rows.length;
|
|
1808
1873
|
if (rows.length < 2) {
|
|
@@ -1876,6 +1941,7 @@ export function saveActiveTaskSnapshot(hippoRoot, tenantId, snapshot) {
|
|
|
1876
1941
|
`).run(snapshot.task, snapshot.summary, snapshot.next_step, snapshot.source ?? 'cli', snapshot.session_id ?? null, snapshot.scope ?? null, tenantId, now, now);
|
|
1877
1942
|
db.exec('COMMIT');
|
|
1878
1943
|
const id = Number(result.lastInsertRowid ?? 0);
|
|
1944
|
+
// SAFETY: row's shape matches the ten columns named in the SELECT above.
|
|
1879
1945
|
const row = db.prepare(`
|
|
1880
1946
|
SELECT id, task, summary, next_step, status, source, session_id, scope, created_at, updated_at
|
|
1881
1947
|
FROM task_snapshots
|
|
@@ -1906,6 +1972,7 @@ export function loadActiveTaskSnapshot(hippoRoot, tenantId) {
|
|
|
1906
1972
|
initStore(hippoRoot);
|
|
1907
1973
|
const db = openHippoDb(hippoRoot);
|
|
1908
1974
|
try {
|
|
1975
|
+
// SAFETY: row's shape matches the ten columns named in the SELECT above.
|
|
1909
1976
|
const row = db.prepare(`
|
|
1910
1977
|
SELECT id, task, summary, next_step, status, source, session_id, scope, created_at, updated_at
|
|
1911
1978
|
FROM task_snapshots
|
|
@@ -1931,6 +1998,7 @@ export function clearActiveTaskSnapshot(hippoRoot, tenantId, clearedStatus = 'cl
|
|
|
1931
1998
|
const db = openHippoDb(hippoRoot);
|
|
1932
1999
|
const now = new Date().toISOString();
|
|
1933
2000
|
try {
|
|
2001
|
+
// SAFETY: active's shape matches the single `id` column selected above.
|
|
1934
2002
|
const active = db.prepare(`SELECT id FROM task_snapshots WHERE status = 'active' AND tenant_id = ? ORDER BY updated_at DESC, id DESC LIMIT 1`).get(tenantId);
|
|
1935
2003
|
if (!active?.id) {
|
|
1936
2004
|
removeActiveTaskMirror(hippoRoot, tenantId);
|
|
@@ -1957,6 +2025,8 @@ export function appendSessionEvent(hippoRoot, tenantId, event) {
|
|
|
1957
2025
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1958
2026
|
`).run(event.session_id, event.task ?? null, event.event_type, event.content, event.source ?? 'cli', event.scope ?? null, JSON.stringify(event.metadata ?? {}), tenantId, now);
|
|
1959
2027
|
const id = Number(result.lastInsertRowid ?? 0);
|
|
2028
|
+
// SAFETY: row's shape matches the nine columns named in the SELECT
|
|
2029
|
+
// above.
|
|
1960
2030
|
const row = db.prepare(`
|
|
1961
2031
|
SELECT id, session_id, task, event_type, content, source, scope, metadata_json, created_at
|
|
1962
2032
|
FROM session_events
|
|
@@ -1966,6 +2036,8 @@ export function appendSessionEvent(hippoRoot, tenantId, event) {
|
|
|
1966
2036
|
throw new Error('Failed to reload saved session event');
|
|
1967
2037
|
}
|
|
1968
2038
|
const loaded = rowToSessionEvent(row);
|
|
2039
|
+
// SAFETY: recentRows' shape matches the nine columns named in the
|
|
2040
|
+
// SELECT above.
|
|
1969
2041
|
const recentRows = db.prepare(`
|
|
1970
2042
|
SELECT id, session_id, task, event_type, content, source, scope, metadata_json, created_at
|
|
1971
2043
|
FROM session_events
|
|
@@ -1999,6 +2071,8 @@ export function listSessionEvents(hippoRoot, tenantId, options = {}) {
|
|
|
1999
2071
|
const limit = Math.max(1, Math.trunc(options.limit ?? 8));
|
|
2000
2072
|
params.push(limit);
|
|
2001
2073
|
const where = `WHERE ${clauses.join(' AND ')}`;
|
|
2074
|
+
// SAFETY: rows' shape matches the nine columns named in the SELECT
|
|
2075
|
+
// above.
|
|
2002
2076
|
const rows = db.prepare(`
|
|
2003
2077
|
SELECT id, session_id, task, event_type, content, source, scope, metadata_json, created_at
|
|
2004
2078
|
FROM session_events
|
|
@@ -2021,6 +2095,8 @@ export function findPromotableSessions(hippoRoot, tenantId, sinceMs) {
|
|
|
2021
2095
|
initStore(hippoRoot);
|
|
2022
2096
|
const db = openHippoDb(hippoRoot);
|
|
2023
2097
|
try {
|
|
2098
|
+
// SAFETY: rows' shape matches the single `session_id` column selected
|
|
2099
|
+
// above.
|
|
2024
2100
|
const rows = db.prepare(`
|
|
2025
2101
|
SELECT DISTINCT session_id FROM session_events
|
|
2026
2102
|
WHERE event_type = 'session_complete' AND created_at >= ? AND tenant_id = ?
|
|
@@ -2065,6 +2141,8 @@ export function listMemoryConflicts(hippoRoot, status = 'open', tenantId) {
|
|
|
2065
2141
|
// Tenanted query — JOIN to memories on both conflict members and require
|
|
2066
2142
|
// each in-tenant, so neither a normal cross-tenant pair nor a stale
|
|
2067
2143
|
// pre-fix row surfaces (consistent with resolveConflict).
|
|
2144
|
+
// SAFETY: both branches select the same eight mc.* columns (aliased
|
|
2145
|
+
// to MemoryConflictRow's field names) from memory_conflicts.
|
|
2068
2146
|
rows = allStatuses
|
|
2069
2147
|
? db.prepare(`
|
|
2070
2148
|
SELECT mc.id, mc.memory_a_id, mc.memory_b_id, mc.reason, mc.score,
|
|
@@ -2087,6 +2165,8 @@ export function listMemoryConflicts(hippoRoot, status = 'open', tenantId) {
|
|
|
2087
2165
|
}
|
|
2088
2166
|
else {
|
|
2089
2167
|
// Unscoped query — legacy direct-mode (CLI, tests, consolidate).
|
|
2168
|
+
// SAFETY: both branches select the same eight columns matching
|
|
2169
|
+
// MemoryConflictRow's field set.
|
|
2090
2170
|
rows = allStatuses
|
|
2091
2171
|
? db.prepare(`
|
|
2092
2172
|
SELECT id, memory_a_id, memory_b_id, reason, score, status, detected_at, updated_at
|
|
@@ -2116,6 +2196,7 @@ export function replaceDetectedConflicts(hippoRoot, detected, detectedAt = new D
|
|
|
2116
2196
|
// inserting rows and when rebuilding conflicts_with_json, so a stale
|
|
2117
2197
|
// cross-tenant row can neither persist nor leak a foreign id.
|
|
2118
2198
|
const tenantById = new Map();
|
|
2199
|
+
// SAFETY: rows' shape matches the two columns named in the SELECT below.
|
|
2119
2200
|
for (const r of db.prepare(`SELECT id, tenant_id FROM memories`).all()) {
|
|
2120
2201
|
tenantById.set(r.id, r.tenant_id);
|
|
2121
2202
|
}
|
|
@@ -2130,6 +2211,8 @@ export function replaceDetectedConflicts(hippoRoot, detected, detectedAt = new D
|
|
|
2130
2211
|
score: conflict.score,
|
|
2131
2212
|
}));
|
|
2132
2213
|
const detectedKeys = new Set(canonicalDetected.map((conflict) => `${conflict.memory_a_id}::${conflict.memory_b_id}`));
|
|
2214
|
+
// SAFETY: openRows' shape matches the eight columns named in the SELECT
|
|
2215
|
+
// above.
|
|
2133
2216
|
const openRows = db.prepare(`
|
|
2134
2217
|
SELECT id, memory_a_id, memory_b_id, reason, score, status, detected_at, updated_at
|
|
2135
2218
|
FROM memory_conflicts
|
|
@@ -2162,6 +2245,7 @@ export function replaceDetectedConflicts(hippoRoot, detected, detectedAt = new D
|
|
|
2162
2245
|
updated_at = excluded.updated_at
|
|
2163
2246
|
`).run(conflict.memory_a_id, conflict.memory_b_id, conflict.reason, conflict.score, detectedAt, detectedAt);
|
|
2164
2247
|
}
|
|
2248
|
+
// SAFETY: openConflicts' shape matches the two columns named above.
|
|
2165
2249
|
const openConflicts = db.prepare(`
|
|
2166
2250
|
SELECT memory_a_id, memory_b_id
|
|
2167
2251
|
FROM memory_conflicts
|
|
@@ -2180,6 +2264,8 @@ export function replaceDetectedConflicts(hippoRoot, detected, detectedAt = new D
|
|
|
2180
2264
|
refMap.get(row.memory_a_id).add(row.memory_b_id);
|
|
2181
2265
|
refMap.get(row.memory_b_id).add(row.memory_a_id);
|
|
2182
2266
|
}
|
|
2267
|
+
// SAFETY: memoryRows' shape matches the single `id` column selected
|
|
2268
|
+
// above.
|
|
2183
2269
|
const memoryRows = db.prepare(`SELECT id FROM memories`).all();
|
|
2184
2270
|
for (const memory of memoryRows) {
|
|
2185
2271
|
const refs = Array.from(refMap.get(memory.id) ?? []).sort();
|
|
@@ -2226,6 +2312,8 @@ export function resolveConflict(hippoRoot, conflictId, keepId, forgetLoser = fal
|
|
|
2226
2312
|
const memScope = tenantId !== undefined ? ' AND tenant_id = ?' : '';
|
|
2227
2313
|
const memArgs = tenantId !== undefined ? [tenantId] : [];
|
|
2228
2314
|
try {
|
|
2315
|
+
// SAFETY: both branches select the same eight columns (aliased in the
|
|
2316
|
+
// tenanted branch) matching MemoryConflictRow's field set.
|
|
2229
2317
|
const row = (tenantId !== undefined
|
|
2230
2318
|
? db.prepare(`
|
|
2231
2319
|
SELECT mc.id, mc.memory_a_id, mc.memory_b_id, mc.reason, mc.score,
|
|
@@ -2273,6 +2361,8 @@ export function resolveConflict(hippoRoot, conflictId, keepId, forgetLoser = fal
|
|
|
2273
2361
|
const extraRemovedRawIds = [];
|
|
2274
2362
|
const removeLoser = forgetLoser || opts?.rejectLoserValue === true;
|
|
2275
2363
|
if (removeLoser) {
|
|
2364
|
+
// SAFETY: loserRow's shape matches the three columns named in the
|
|
2365
|
+
// SELECT above.
|
|
2276
2366
|
const loserRow = db
|
|
2277
2367
|
.prepare(`SELECT kind, content, tenant_id FROM memories WHERE id = ?${memScope}`)
|
|
2278
2368
|
.get(loserId, ...memArgs);
|
|
@@ -2303,6 +2393,8 @@ export function resolveConflict(hippoRoot, conflictId, keepId, forgetLoser = fal
|
|
|
2303
2393
|
// to keep it in this same resolution, and this branch must not
|
|
2304
2394
|
// undo that choice in the same transaction.
|
|
2305
2395
|
const loserTenantId = loserRow.tenant_id ?? 'default';
|
|
2396
|
+
// SAFETY: dupRows' shape matches the three columns named in the
|
|
2397
|
+
// SELECT above.
|
|
2306
2398
|
const dupRows = db
|
|
2307
2399
|
.prepare(`SELECT id, kind, content FROM memories WHERE tenant_id = ? AND id != ? AND id != ?`)
|
|
2308
2400
|
.all(loserTenantId, loserId, keepId);
|
|
@@ -2337,6 +2429,8 @@ export function resolveConflict(hippoRoot, conflictId, keepId, forgetLoser = fal
|
|
|
2337
2429
|
.run(loserId, ...memArgs);
|
|
2338
2430
|
}
|
|
2339
2431
|
// Clean up conflicts_with references
|
|
2432
|
+
// SAFETY: keepRow's shape matches the single `conflicts_with_json`
|
|
2433
|
+
// column selected above.
|
|
2340
2434
|
const keepRow = db.prepare(`SELECT conflicts_with_json FROM memories WHERE id = ?${memScope}`).get(keepId, ...memArgs);
|
|
2341
2435
|
if (keepRow) {
|
|
2342
2436
|
const refs = JSON.parse(keepRow.conflicts_with_json || '[]');
|
|
@@ -2345,6 +2439,8 @@ export function resolveConflict(hippoRoot, conflictId, keepId, forgetLoser = fal
|
|
|
2345
2439
|
.run(JSON.stringify(cleaned), keepId, ...memArgs);
|
|
2346
2440
|
}
|
|
2347
2441
|
if (!loserRemoved) {
|
|
2442
|
+
// SAFETY: loserRow's shape matches the single `conflicts_with_json`
|
|
2443
|
+
// column named in the SELECT below.
|
|
2348
2444
|
const loserRow = db.prepare(`SELECT conflicts_with_json FROM memories WHERE id = ?${memScope}`).get(loserId, ...memArgs);
|
|
2349
2445
|
if (loserRow) {
|
|
2350
2446
|
const refs = JSON.parse(loserRow.conflicts_with_json || '[]');
|
|
@@ -2356,18 +2452,26 @@ export function resolveConflict(hippoRoot, conflictId, keepId, forgetLoser = fal
|
|
|
2356
2452
|
// AT1: the missing audit (plan §5 — resolveConflict wrote ZERO audit_log
|
|
2357
2453
|
// rows on any path before this). Every path — weaken, forget, reject —
|
|
2358
2454
|
// lands exactly one conflict_resolve row.
|
|
2359
|
-
|
|
2455
|
+
const conflictResolveMeta = {
|
|
2360
2456
|
conflictId,
|
|
2361
2457
|
keepId,
|
|
2362
2458
|
loserId,
|
|
2363
2459
|
disposition: loserRemoved ? (loserWasRaw ? 'archived_raw' : 'deleted') : 'weakened',
|
|
2364
2460
|
rejected: Boolean(opts?.rejectLoserValue),
|
|
2365
|
-
rejectedDigest,
|
|
2366
2461
|
// AT1 P1 fix: every row this call removed, not just loserId — the
|
|
2367
2462
|
// same-tenant duplicate sweep above (extraRemovedIds) needs an
|
|
2368
2463
|
// audit trail too.
|
|
2369
2464
|
removedIds: loserRemoved ? [loserId, ...extraRemovedIds] : [],
|
|
2370
|
-
}
|
|
2465
|
+
};
|
|
2466
|
+
// Assigned only when present so the serialized audit payload keeps
|
|
2467
|
+
// omitting the key, exactly as the pre-migration object literal did.
|
|
2468
|
+
if (rejectedDigest !== undefined)
|
|
2469
|
+
conflictResolveMeta.rejectedDigest = rejectedDigest;
|
|
2470
|
+
// Fresh spread literal: ConflictResolveMeta is a closed interface (no
|
|
2471
|
+
// index signature) and isn't directly assignable to audit()'s
|
|
2472
|
+
// Record<string, JsonValue> metadata param; a spread into a fresh
|
|
2473
|
+
// object literal satisfies it without widening the declared type above.
|
|
2474
|
+
audit(db, 'conflict_resolve', keepId, { ...conflictResolveMeta }, opts?.rejectedBy ?? 'cli', tenantId);
|
|
2371
2475
|
db.exec('COMMIT');
|
|
2372
2476
|
syncMirrorFiles(hippoRoot, db);
|
|
2373
2477
|
// AT1 P1b fix: mirror purge + reaper stamp for EVERY removed loser, not
|
|
@@ -2431,6 +2535,8 @@ export function saveSessionHandoff(hippoRoot, tenantId, handoff) {
|
|
|
2431
2535
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2432
2536
|
`).run(handoff.sessionId, handoff.repoRoot ?? null, handoff.taskId ?? null, handoff.summary, handoff.nextAction ?? null, JSON.stringify(handoff.artifacts ?? []), handoff.scope ?? null, tenantId, now);
|
|
2433
2537
|
const id = Number(result.lastInsertRowid ?? 0);
|
|
2538
|
+
// SAFETY: row's shape matches the nine columns named in the SELECT
|
|
2539
|
+
// above.
|
|
2434
2540
|
const row = db.prepare(`
|
|
2435
2541
|
SELECT id, session_id, repo_root, task_id, summary, next_action, artifacts_json, scope, created_at
|
|
2436
2542
|
FROM session_handoffs
|
|
@@ -2455,6 +2561,8 @@ export function loadLatestHandoff(hippoRoot, tenantId, sessionId) {
|
|
|
2455
2561
|
try {
|
|
2456
2562
|
let row;
|
|
2457
2563
|
if (sessionId) {
|
|
2564
|
+
// SAFETY: row's shape matches the nine columns named in the SELECT
|
|
2565
|
+
// below.
|
|
2458
2566
|
row = db.prepare(`
|
|
2459
2567
|
SELECT id, session_id, repo_root, task_id, summary, next_action, artifacts_json, scope, created_at
|
|
2460
2568
|
FROM session_handoffs
|
|
@@ -2464,6 +2572,8 @@ export function loadLatestHandoff(hippoRoot, tenantId, sessionId) {
|
|
|
2464
2572
|
`).get(sessionId, tenantId);
|
|
2465
2573
|
}
|
|
2466
2574
|
else {
|
|
2575
|
+
// SAFETY: row's shape matches the nine columns named in the SELECT
|
|
2576
|
+
// below.
|
|
2467
2577
|
row = db.prepare(`
|
|
2468
2578
|
SELECT id, session_id, repo_root, task_id, summary, next_action, artifacts_json, scope, created_at
|
|
2469
2579
|
FROM session_handoffs
|
|
@@ -2486,6 +2596,8 @@ export function loadHandoffById(hippoRoot, tenantId, id) {
|
|
|
2486
2596
|
initStore(hippoRoot);
|
|
2487
2597
|
const db = openHippoDb(hippoRoot);
|
|
2488
2598
|
try {
|
|
2599
|
+
// SAFETY: row's shape matches the nine columns named in the SELECT
|
|
2600
|
+
// above.
|
|
2489
2601
|
const row = db.prepare(`
|
|
2490
2602
|
SELECT id, session_id, repo_root, task_id, summary, next_action, artifacts_json, scope, created_at
|
|
2491
2603
|
FROM session_handoffs
|
|
@@ -2519,6 +2631,8 @@ export function loadDirtySummaries(hippoRoot, tenantId) {
|
|
|
2519
2631
|
initStore(hippoRoot);
|
|
2520
2632
|
const db = openHippoDb(hippoRoot);
|
|
2521
2633
|
try {
|
|
2634
|
+
// SAFETY: this query selects exactly MEMORY_SELECT_COLUMNS, matching
|
|
2635
|
+
// MemoryRow's field set.
|
|
2522
2636
|
const rows = db.prepare(`
|
|
2523
2637
|
SELECT ${MEMORY_SELECT_COLUMNS}
|
|
2524
2638
|
FROM memories
|
|
@@ -2553,6 +2667,8 @@ export function markSummaryDirtyInTx(db, summaryId, tenantId, actor) {
|
|
|
2553
2667
|
// v0.30 / E5: widened dag_level=2 -> IN (2, 3). RETURNING dag_level reads
|
|
2554
2668
|
// actual level in same round trip so audit metadata stays accurate without
|
|
2555
2669
|
// a SELECT-before-UPDATE extra DB op on this hot path (5 caller sites).
|
|
2670
|
+
// SAFETY: result's shape matches the single `dag_level` column returned
|
|
2671
|
+
// above.
|
|
2556
2672
|
const result = db.prepare(`
|
|
2557
2673
|
UPDATE memories
|
|
2558
2674
|
SET summary_dirty = 1
|
|
@@ -2587,6 +2703,8 @@ export function markSummaryDirty(hippoRoot, summaryId, tenantId, actor = 'cli')
|
|
|
2587
2703
|
try {
|
|
2588
2704
|
// v0.30 / E5: widened dag_level=2 -> IN (2, 3). RETURNING dag_level reads
|
|
2589
2705
|
// actual level in same round trip.
|
|
2706
|
+
// SAFETY: result's shape matches the single `dag_level` column returned
|
|
2707
|
+
// above.
|
|
2590
2708
|
const result = db.prepare(`
|
|
2591
2709
|
UPDATE memories
|
|
2592
2710
|
SET summary_dirty = 1
|
|
@@ -2631,6 +2749,8 @@ export function loadAllL2Summaries(hippoRoot) {
|
|
|
2631
2749
|
initStore(hippoRoot);
|
|
2632
2750
|
const db = openHippoDb(hippoRoot);
|
|
2633
2751
|
try {
|
|
2752
|
+
// SAFETY: this query selects exactly MEMORY_SELECT_COLUMNS, matching
|
|
2753
|
+
// MemoryRow's field set.
|
|
2634
2754
|
const rows = db.prepare(`
|
|
2635
2755
|
SELECT ${MEMORY_SELECT_COLUMNS}
|
|
2636
2756
|
FROM memories
|
|
@@ -2658,6 +2778,8 @@ export function loadAllDirtySummaries(hippoRoot) {
|
|
|
2658
2778
|
initStore(hippoRoot);
|
|
2659
2779
|
const db = openHippoDb(hippoRoot);
|
|
2660
2780
|
try {
|
|
2781
|
+
// SAFETY: this query selects exactly MEMORY_SELECT_COLUMNS, matching
|
|
2782
|
+
// MemoryRow's field set.
|
|
2661
2783
|
const rows = db.prepare(`
|
|
2662
2784
|
SELECT ${MEMORY_SELECT_COLUMNS}
|
|
2663
2785
|
FROM memories
|
|
@@ -2683,6 +2805,8 @@ export function loadChildrenOfSummary(hippoRoot, summaryId, tenantId) {
|
|
|
2683
2805
|
initStore(hippoRoot);
|
|
2684
2806
|
const db = openHippoDb(hippoRoot);
|
|
2685
2807
|
try {
|
|
2808
|
+
// SAFETY: this query selects exactly MEMORY_SELECT_COLUMNS, matching
|
|
2809
|
+
// MemoryRow's field set.
|
|
2686
2810
|
const rows = db.prepare(`
|
|
2687
2811
|
SELECT ${MEMORY_SELECT_COLUMNS}
|
|
2688
2812
|
FROM memories
|
|
@@ -2864,6 +2988,8 @@ export function clearSummaryDirtyAfterBuild(hippoRoot, summaryId, tenantId, acto
|
|
|
2864
2988
|
try {
|
|
2865
2989
|
// v0.30 / E5: widened dag_level=2 -> IN (2, 3). RETURNING dag_level reads
|
|
2866
2990
|
// actual level so audit metadata stays accurate without an extra SELECT.
|
|
2991
|
+
// SAFETY: result's shape matches the single `dag_level` column returned
|
|
2992
|
+
// below.
|
|
2867
2993
|
const result = db.prepare(`
|
|
2868
2994
|
UPDATE memories
|
|
2869
2995
|
SET summary_dirty = 0
|