hippo-memory 1.61.0 → 1.63.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 +37 -53
- package/dist/agent-memories/apply.d.ts +3 -1
- package/dist/agent-memories/apply.js +23 -1
- package/dist/agent-memories/claude-code.d.ts +4 -1
- package/dist/agent-memories/claude-code.js +53 -9
- package/dist/agent-memories/report.d.ts +1 -0
- package/dist/agent-memories/report.js +2 -2
- package/dist/agent-memories/sync.d.ts +3 -3
- package/dist/agent-memories/sync.js +46 -24
- package/dist/agent-memories/types.d.ts +0 -2
- package/dist/ambient-store.d.ts +4 -4
- package/dist/ambient-store.js +4 -3
- package/dist/api/assemble.d.ts +7 -10
- package/dist/api/assemble.js +62 -66
- package/dist/api/audit.d.ts +2 -2
- package/dist/api/audit.js +2 -2
- package/dist/api/auth.d.ts +6 -6
- package/dist/api/auth.js +5 -7
- package/dist/api/context-select.d.ts +50 -0
- package/dist/api/context-select.js +342 -0
- package/dist/api/context-types.d.ts +12 -17
- package/dist/api/context.d.ts +5 -4
- package/dist/api/context.js +208 -535
- package/dist/api/dormant.js +1 -1
- package/dist/api/drill-down.d.ts +4 -4
- package/dist/api/drill-down.js +56 -41
- package/dist/api/outcome.d.ts +8 -13
- package/dist/api/outcome.js +13 -17
- package/dist/api/promote.d.ts +5 -8
- package/dist/api/promote.js +55 -66
- package/dist/api/quarantine.js +3 -2
- package/dist/api/recall-types.d.ts +43 -55
- package/dist/api/recall.d.ts +3 -3
- package/dist/api/recall.js +310 -456
- package/dist/api/remember.d.ts +2 -2
- package/dist/api/sleep.d.ts +7 -35
- package/dist/api/sleep.js +206 -220
- package/dist/api/tokens.d.ts +2 -2
- package/dist/api/tokens.js +2 -2
- package/dist/api/types.d.ts +6 -10
- package/dist/api/types.js +2 -4
- package/dist/audit-prune.d.ts +4 -6
- package/dist/audit-prune.js +3 -5
- package/dist/audit.js +11 -33
- package/dist/auth.d.ts +8 -9
- package/dist/auth.js +5 -7
- package/dist/autolearn.d.ts +1 -1
- package/dist/autolearn.js +1 -1
- package/dist/availability.js +3 -5
- package/dist/capture/command.d.ts +5 -4
- package/dist/capture/command.js +8 -22
- package/dist/capture/compact.d.ts +2 -2
- package/dist/capture/compact.js +11 -15
- package/dist/capture/extract.js +37 -115
- package/dist/capture-error.d.ts +1 -1
- package/dist/capture-error.js +1 -1
- package/dist/churn-git.d.ts +1 -1
- package/dist/churn-git.js +1 -1
- package/dist/cli/audit.js +3 -4
- package/dist/cli/auth.js +3 -6
- package/dist/cli/briefs.js +324 -306
- package/dist/cli/context.js +44 -34
- package/dist/cli/continuity.js +283 -271
- package/dist/cli/curate.d.ts +1 -1
- package/dist/cli/curate.js +43 -58
- package/dist/cli/dag.js +5 -9
- package/dist/cli/decisions.js +334 -345
- package/dist/cli/explain.js +68 -61
- package/dist/cli/goals.js +1 -1
- package/dist/cli/init.js +1 -1
- package/dist/cli/maintenance.js +62 -51
- package/dist/cli/playbooks.js +391 -379
- package/dist/cli/projects.js +11 -6
- package/dist/cli/recall.js +30 -44
- package/dist/cli/remember.js +118 -87
- package/dist/cli/session-hooks.js +106 -115
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.js +267 -250
- package/dist/cli/shared.js +3 -3
- package/dist/cli/slack.js +1 -1
- package/dist/cli/sleep.js +27 -1
- package/dist/cli/status.d.ts +4 -4
- package/dist/cli/status.js +80 -76
- package/dist/cli/transfer.js +88 -107
- package/dist/cli/usage.js +9 -6
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +4 -9
- package/dist/compaction-record.d.ts +2 -2
- package/dist/compaction-record.js +89 -68
- package/dist/compare.d.ts +11 -16
- package/dist/compare.js +11 -16
- package/dist/config.d.ts +19 -18
- package/dist/config.js +90 -67
- package/dist/connectors/github/backfill.d.ts +2 -2
- package/dist/connectors/github/backfill.js +8 -15
- package/dist/connectors/github/cli-impl.js +3 -8
- package/dist/connectors/github/deletion.d.ts +5 -12
- package/dist/connectors/github/deletion.js +5 -12
- package/dist/connectors/github/dlq.d.ts +6 -9
- package/dist/connectors/github/dlq.js +2 -3
- package/dist/connectors/github/ingest.d.ts +5 -7
- package/dist/connectors/github/ingest.js +8 -12
- package/dist/connectors/github/octokit-client.d.ts +3 -5
- package/dist/connectors/github/octokit-client.js +5 -6
- package/dist/connectors/github/signature.d.ts +9 -39
- package/dist/connectors/github/signature.js +9 -39
- package/dist/connectors/github/tenant-routing.d.ts +1 -1
- package/dist/connectors/github/tenant-routing.js +1 -1
- package/dist/connectors/github/transform.js +2 -2
- package/dist/connectors/github/types.d.ts +2 -10
- package/dist/connectors/github/types.js +1 -3
- package/dist/connectors/slack/deletion.d.ts +3 -8
- package/dist/connectors/slack/deletion.js +3 -8
- package/dist/connectors/slack/dlq.d.ts +1 -1
- package/dist/connectors/slack/ingest.d.ts +1 -1
- package/dist/connectors/slack/ingest.js +7 -16
- package/dist/connectors/slack/signature.d.ts +1 -1
- package/dist/connectors/slack/tenant-routing.d.ts +3 -5
- package/dist/connectors/slack/tenant-routing.js +3 -5
- package/dist/connectors/slack/transform.d.ts +5 -6
- package/dist/connectors/slack/transform.js +5 -6
- package/dist/connectors/slack/types.d.ts +2 -6
- package/dist/connectors/slack/types.js +1 -3
- package/dist/connectors/slack/web-client.js +10 -3
- package/dist/connectors/slack/workspaces.d.ts +3 -5
- package/dist/connectors/slack/workspaces.js +3 -5
- package/dist/consolidate/conflicts.js +3 -14
- package/dist/consolidate/decay.js +9 -29
- package/dist/consolidate/llm-passes.js +4 -5
- package/dist/consolidate/merge.js +8 -23
- package/dist/consolidate/run.d.ts +1 -8
- package/dist/consolidate/run.js +3 -25
- package/dist/consolidate/sleep.js +5 -17
- package/dist/consolidate/traces.js +9 -21
- package/dist/customer-notes.d.ts +5 -7
- package/dist/customer-notes.js +82 -76
- package/dist/dag.d.ts +10 -21
- package/dist/dag.js +189 -203
- package/dist/db/continuity.js +2 -2
- package/dist/db/migrations/v14.js +1 -1
- package/dist/db/migrations/v15.js +1 -2
- package/dist/db/migrations/v16.js +3 -4
- package/dist/db/migrations/v17.js +2 -3
- package/dist/db/migrations/v19.js +1 -1
- package/dist/db/migrations/v20.js +1 -1
- package/dist/db/migrations/v21.js +2 -6
- package/dist/db/migrations/v22.js +2 -4
- package/dist/db/migrations/v23.js +1 -1
- package/dist/db/migrations/v24.js +4 -6
- package/dist/db/migrations/v25.js +2 -3
- package/dist/db/migrations/v26.js +3 -3
- package/dist/db/migrations/v27.js +2 -10
- package/dist/db/migrations/v28.js +5 -8
- package/dist/db/migrations/v29.js +3 -4
- package/dist/db/migrations/v30.js +2 -2
- package/dist/db/migrations/v31.js +1 -1
- package/dist/db/migrations/v32.js +1 -1
- package/dist/db/migrations/v33.js +3 -3
- package/dist/db/migrations/v34.js +1 -1
- package/dist/db/migrations/v35.js +3 -4
- package/dist/db/migrations/v36.js +3 -4
- package/dist/db/migrations/v37.js +5 -5
- package/dist/db/migrations/v38.js +7 -8
- package/dist/db/migrations/v39.js +1 -1
- package/dist/db/migrations/v40.js +4 -16
- package/dist/db/migrations/v41.js +3 -4
- package/dist/db/migrations/v42.js +3 -4
- package/dist/db/migrations/v45.js +1 -1
- package/dist/db/migrations/v46.js +1 -1
- package/dist/db/migrations/v47.js +1 -1
- package/dist/db/migrations/v48.js +1 -1
- package/dist/decisions.d.ts +2 -2
- package/dist/decisions.js +97 -80
- package/dist/dedupe.js +86 -61
- package/dist/delivery-recorder.js +154 -135
- package/dist/doctor.js +129 -110
- package/dist/dormant.js +1 -4
- package/dist/embedding-provider.d.ts +4 -8
- package/dist/embedding-provider.js +4 -8
- package/dist/embeddings.js +55 -47
- package/dist/env.d.ts +1 -1
- package/dist/env.js +12 -12
- package/dist/escape.d.ts +5 -0
- package/dist/escape.js +10 -0
- package/dist/eval-stats.d.ts +1 -2
- package/dist/eval-stats.js +1 -2
- package/dist/eval-suite.js +27 -21
- package/dist/extract.js +4 -9
- package/dist/failure-log.d.ts +3 -3
- package/dist/failure-log.js +1 -1
- package/dist/forward-claim-detector.d.ts +2 -4
- package/dist/forward-claim-detector.js +6 -11
- package/dist/goals.d.ts +3 -3
- package/dist/goals.js +103 -91
- package/dist/graph/read.d.ts +2 -2
- package/dist/graph/read.js +5 -6
- package/dist/graph/types.d.ts +8 -8
- package/dist/graph/write.d.ts +7 -14
- package/dist/graph/write.js +16 -23
- package/dist/graph-extract.d.ts +7 -8
- package/dist/graph-extract.js +62 -72
- package/dist/graph-recall.d.ts +2 -2
- package/dist/graph-recall.js +55 -49
- package/dist/graph-stream.d.ts +5 -6
- package/dist/graph-stream.js +66 -57
- package/dist/graph-view.d.ts +2 -2
- package/dist/graph-view.js +7 -7
- package/dist/half-life-migration.d.ts +1 -2
- package/dist/half-life-migration.js +2 -3
- package/dist/hooks/codex-session.js +1 -1
- package/dist/hooks/codex-wrapper.d.ts +1 -1
- package/dist/hooks/codex-wrapper.js +3 -2
- package/dist/hooks/json-hooks.d.ts +2 -2
- package/dist/hooks/json-hooks.js +5 -4
- package/dist/hooks/opencode.d.ts +1 -1
- package/dist/hooks/opencode.js +5 -4
- package/dist/hooks/shared.d.ts +3 -7
- package/dist/hooks/shared.js +1 -8
- package/dist/http-util.d.ts +2 -3
- package/dist/http-util.js +3 -0
- package/dist/importers/core.d.ts +2 -9
- package/dist/importers/core.js +15 -30
- package/dist/importers/sources.js +2 -1
- package/dist/importers/vault.js +2 -20
- package/dist/incidents.d.ts +1 -1
- package/dist/incidents.js +46 -39
- package/dist/instruction-detect.d.ts +1 -1
- package/dist/instruction-detect.js +1 -1
- package/dist/invalidation.d.ts +3 -0
- package/dist/invalidation.js +160 -114
- package/dist/json.d.ts +5 -0
- package/dist/json.js +4 -0
- package/dist/judgment.js +1 -2
- package/dist/local-embedding.js +1 -1
- package/dist/mcp/admin-tools.js +7 -17
- package/dist/mcp/format.js +1 -1
- package/dist/mcp/framing.js +3 -6
- package/dist/mcp/protocol.d.ts +2 -5
- package/dist/mcp/protocol.js +1 -3
- package/dist/mcp/recall-tools.js +12 -15
- package/dist/mcp/request.js +4 -3
- package/dist/mcp/session-state.js +2 -3
- package/dist/mcp/stdio.js +2 -1
- package/dist/mcp/tools.js +9 -6
- package/dist/memory-value-weights.d.ts +5 -8
- package/dist/memory-value-weights.js +5 -8
- package/dist/memory-value.d.ts +13 -13
- package/dist/memory-value.js +26 -37
- package/dist/memory.d.ts +20 -22
- package/dist/memory.js +24 -48
- package/dist/multihop.d.ts +1 -1
- package/dist/multihop.js +3 -2
- package/dist/owner-validation.d.ts +4 -5
- package/dist/owner-validation.js +4 -5
- package/dist/physics.d.ts +4 -4
- package/dist/physics.js +7 -9
- package/dist/policies.d.ts +9 -10
- package/dist/policies.js +96 -81
- package/dist/postinstall.js +3 -6
- package/dist/predictions/planning-fallacy.d.ts +9 -14
- package/dist/predictions/planning-fallacy.js +10 -16
- package/dist/predictions/store.d.ts +15 -23
- package/dist/predictions/store.js +36 -33
- package/dist/processes.d.ts +2 -7
- package/dist/processes.js +88 -72
- package/dist/project-briefs.d.ts +2 -3
- package/dist/project-briefs.js +141 -118
- package/dist/project-identity.d.ts +22 -9
- package/dist/project-identity.js +47 -12
- package/dist/project-merge.d.ts +28 -5
- package/dist/project-merge.js +213 -46
- package/dist/project-remote.d.ts +12 -0
- package/dist/project-remote.js +138 -0
- package/dist/prompt-recall.js +1 -2
- package/dist/rate-limit.d.ts +1 -1
- package/dist/rate-limit.js +1 -1
- package/dist/raw-archive.d.ts +9 -0
- package/dist/raw-archive.js +70 -53
- package/dist/recall-history.d.ts +19 -20
- package/dist/recall-history.js +24 -42
- package/dist/recall-pipeline.js +4 -28
- package/dist/recall-scope.d.ts +7 -8
- package/dist/recall-scope.js +7 -8
- package/dist/recall-trace.d.ts +5 -9
- package/dist/recall-trace.js +6 -10
- package/dist/refine-llm.d.ts +1 -1
- package/dist/refine-llm.js +2 -2
- package/dist/reject-flow.d.ts +3 -4
- package/dist/reject-flow.js +122 -117
- package/dist/rejection.d.ts +5 -6
- package/dist/rejection.js +7 -15
- package/dist/rerankers/clef.d.ts +1 -1
- package/dist/rerankers/jev.d.ts +1 -2
- package/dist/rerankers/jev.js +4 -5
- package/dist/rerankers/llm.d.ts +1 -2
- package/dist/rerankers/llm.js +1 -2
- package/dist/rerankers/types.d.ts +1 -2
- package/dist/rrf.d.ts +2 -2
- package/dist/rrf.js +2 -2
- package/dist/search/bm25-search.d.ts +1 -1
- package/dist/search/bm25-search.js +2 -1
- package/dist/search/boosts.js +2 -1
- package/dist/search/hybrid.d.ts +1 -1
- package/dist/search/hybrid.js +2 -1
- package/dist/search/physics-search.d.ts +1 -1
- package/dist/search/physics-search.js +2 -1
- package/dist/search/types.d.ts +2 -0
- package/dist/search/types.js +3 -1
- package/dist/secret-detect.d.ts +4 -5
- package/dist/secret-detect.js +6 -10
- package/dist/server/auth.js +5 -5
- package/dist/server/client-ip.js +1 -1
- package/dist/server/cursor.js +2 -1
- package/dist/server/mcp-http.js +4 -4
- package/dist/server/request.d.ts +3 -6
- package/dist/server/request.js +6 -7
- package/dist/server/routes/admin.js +5 -4
- package/dist/server/routes/customer-notes.js +6 -5
- package/dist/server/routes/decisions.js +4 -3
- package/dist/server/routes/incidents.js +7 -5
- package/dist/server/routes/memories.js +7 -7
- package/dist/server/routes/policies.js +3 -2
- package/dist/server/routes/predictions.js +12 -15
- package/dist/server/routes/processes.js +3 -2
- package/dist/server/routes/project-briefs.js +8 -7
- package/dist/server/routes/recall.js +95 -93
- package/dist/server/routes/skills.js +6 -5
- package/dist/server/types.d.ts +1 -1
- package/dist/server/validation.d.ts +1 -2
- package/dist/server/validation.js +7 -14
- package/dist/server-detect.js +72 -58
- package/dist/server.d.ts +2 -2
- package/dist/server.js +131 -117
- package/dist/shared.d.ts +26 -17
- package/dist/shared.js +102 -104
- package/dist/skills.d.ts +3 -3
- package/dist/skills.js +88 -72
- package/dist/store/audit-event.d.ts +2 -2
- package/dist/store/audit-event.js +1 -1
- package/dist/store/candidates.d.ts +2 -2
- package/dist/store/candidates.js +4 -3
- package/dist/store/conflicts.js +30 -22
- package/dist/store/delete-and-batch.d.ts +11 -14
- package/dist/store/delete-and-batch.js +40 -91
- package/dist/store/entry-reads.d.ts +17 -25
- package/dist/store/entry-reads.js +59 -40
- package/dist/store/entry-row.d.ts +6 -24
- package/dist/store/entry-row.js +6 -24
- package/dist/store/entry-writes.d.ts +6 -7
- package/dist/store/entry-writes.js +13 -11
- package/dist/store/handoffs.d.ts +1 -1
- package/dist/store/handoffs.js +7 -10
- package/dist/store/index-and-stats.d.ts +2 -6
- package/dist/store/index-and-stats.js +4 -10
- package/dist/store/mirrors.d.ts +6 -19
- package/dist/store/mirrors.js +14 -39
- package/dist/store/open.js +9 -31
- package/dist/store/rows.d.ts +5 -11
- package/dist/store/rows.js +6 -11
- package/dist/store/search-rows.d.ts +17 -34
- package/dist/store/search-rows.js +34 -56
- package/dist/store/sessions.d.ts +4 -5
- package/dist/store/sessions.js +5 -6
- package/dist/store/summaries.d.ts +13 -17
- package/dist/store/summaries.js +26 -70
- package/dist/support-bundle.js +4 -8
- package/dist/tenant.d.ts +1 -5
- package/dist/token-ledger.d.ts +1 -1
- package/dist/token-ledger.js +3 -5
- package/dist/trace.js +1 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/working-memory.d.ts +1 -1
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/physics.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ export declare function computeMass(strength: number, retrievalCount: number): n
|
|
|
52
52
|
export declare function computeCharge(valence: EmotionalValence): number;
|
|
53
53
|
export declare function computeTemperature(ageDays: number, temperatureDecay: number): number;
|
|
54
54
|
/**
|
|
55
|
-
*
|
|
55
|
+
* Query gravity (retrieval-time, virtual — does not update position).
|
|
56
56
|
* Returns scalar force magnitude for ranking.
|
|
57
57
|
*
|
|
58
58
|
* F_query(i) = G_Q * mass(i) * max(0, cosine(pos_i, query))^2
|
|
@@ -64,7 +64,7 @@ export declare function queryGravityMagnitude(particle: PhysicsParticle, queryEm
|
|
|
64
64
|
*/
|
|
65
65
|
export declare function velocityAlignmentBonus(particle: PhysicsParticle, queryEmbedding: number[]): number;
|
|
66
66
|
/**
|
|
67
|
-
*
|
|
67
|
+
* Inter-memory attraction force vector (consolidation-time).
|
|
68
68
|
* Attractive force from particle j on particle i.
|
|
69
69
|
*
|
|
70
70
|
* F_attract(i,j) = G_M * m_i * m_j * max(0, cosine(i,j))^3 * direction(j→i in embedding space)
|
|
@@ -74,7 +74,7 @@ export declare function velocityAlignmentBonus(particle: PhysicsParticle, queryE
|
|
|
74
74
|
*/
|
|
75
75
|
export declare function attractionForce(pi: PhysicsParticle, pj: PhysicsParticle, G_memory: number): number[];
|
|
76
76
|
/**
|
|
77
|
-
*
|
|
77
|
+
* Conflict repulsion force vector (consolidation-time).
|
|
78
78
|
* Repulsive force pushing i away from j.
|
|
79
79
|
*
|
|
80
80
|
* F_repel(i,j) = K_R * m_i * m_j / max(0.01, cosine_distance(i,j))^2
|
|
@@ -82,7 +82,7 @@ export declare function attractionForce(pi: PhysicsParticle, pj: PhysicsParticle
|
|
|
82
82
|
*/
|
|
83
83
|
export declare function repulsionForce(pi: PhysicsParticle, pj: PhysicsParticle, K_repulsion: number): number[];
|
|
84
84
|
/**
|
|
85
|
-
*
|
|
85
|
+
* Drag force vector (consolidation-time).
|
|
86
86
|
* F_drag(i) = -drag * velocity(i) / max(1, effective_half_life(i))
|
|
87
87
|
*
|
|
88
88
|
* effectiveHalfLife should be passed in from the memory's current half_life_days.
|
package/dist/physics.js
CHANGED
|
@@ -79,11 +79,9 @@ const CHARGE_MAP = {
|
|
|
79
79
|
critical: -1.0,
|
|
80
80
|
};
|
|
81
81
|
export function computeMass(strength, retrievalCount) {
|
|
82
|
-
// EVAL-ONLY ablation (see ablation.ts): under the recall-boost flag,
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
// arm's physics-pool rankings (codex P2). Covers both the init and refresh
|
|
86
|
-
// callers in physics-state.ts.
|
|
82
|
+
// EVAL-ONLY ablation (see ablation.ts): under the recall-boost flag mass ignores retrieval history, since
|
|
83
|
+
// query gravity ranks by mass and prior counts would leak strengthening into the ablated arm's
|
|
84
|
+
// physics-pool rankings. Covers both the init and refresh callers in physics-state.ts.
|
|
87
85
|
const effectiveCount = isRecallBoostAblated() ? 0 : retrievalCount;
|
|
88
86
|
return Math.max(0.01, strength * (1 + 0.1 * Math.log2(effectiveCount + 1)));
|
|
89
87
|
}
|
|
@@ -97,7 +95,7 @@ export function computeTemperature(ageDays, temperatureDecay) {
|
|
|
97
95
|
// Force computations
|
|
98
96
|
// ---------------------------------------------------------------------------
|
|
99
97
|
/**
|
|
100
|
-
*
|
|
98
|
+
* Query gravity (retrieval-time, virtual — does not update position).
|
|
101
99
|
* Returns scalar force magnitude for ranking.
|
|
102
100
|
*
|
|
103
101
|
* F_query(i) = G_Q * mass(i) * max(0, cosine(pos_i, query))^2
|
|
@@ -121,7 +119,7 @@ export function velocityAlignmentBonus(particle, queryEmbedding) {
|
|
|
121
119
|
return Math.max(0, alignment);
|
|
122
120
|
}
|
|
123
121
|
/**
|
|
124
|
-
*
|
|
122
|
+
* Inter-memory attraction force vector (consolidation-time).
|
|
125
123
|
* Attractive force from particle j on particle i.
|
|
126
124
|
*
|
|
127
125
|
* F_attract(i,j) = G_M * m_i * m_j * max(0, cosine(i,j))^3 * direction(j→i in embedding space)
|
|
@@ -139,7 +137,7 @@ export function attractionForce(pi, pj, G_memory) {
|
|
|
139
137
|
return vecScale(direction, magnitude);
|
|
140
138
|
}
|
|
141
139
|
/**
|
|
142
|
-
*
|
|
140
|
+
* Conflict repulsion force vector (consolidation-time).
|
|
143
141
|
* Repulsive force pushing i away from j.
|
|
144
142
|
*
|
|
145
143
|
* F_repel(i,j) = K_R * m_i * m_j / max(0.01, cosine_distance(i,j))^2
|
|
@@ -154,7 +152,7 @@ export function repulsionForce(pi, pj, K_repulsion) {
|
|
|
154
152
|
return vecScale(direction, magnitude);
|
|
155
153
|
}
|
|
156
154
|
/**
|
|
157
|
-
*
|
|
155
|
+
* Drag force vector (consolidation-time).
|
|
158
156
|
* F_drag(i) = -drag * velocity(i) / max(1, effective_half_life(i))
|
|
159
157
|
*
|
|
160
158
|
* effectiveHalfLife should be passed in from the memory's current half_life_days.
|
package/dist/policies.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Policy first-class object.
|
|
3
3
|
*
|
|
4
4
|
* The "bi-temporal-first" object type: a named rule/statement that is in force
|
|
5
5
|
* over an EFFECTIVE-TIME range and evolves via supersession. Two time axes:
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
* loadPoliciesAsOf's asOfDate) is normalized to canonical ISO-8601 datetime
|
|
31
31
|
* (`toISOString`) at the store boundary BEFORE any persist or compare, so the
|
|
32
32
|
* fixed-width values sort lexically and the half-open [valid_from, valid_to)
|
|
33
|
-
* comparison is correct (
|
|
34
|
-
*
|
|
33
|
+
* comparison is correct (a date-only asOf vs a datetime valid_from would
|
|
34
|
+
* otherwise make a same-day policy invisible).
|
|
35
35
|
*
|
|
36
36
|
* Dual-write atomicity: `savePolicy` writes the memory + policies row (and, on
|
|
37
37
|
* supersede, the predecessor's UPDATE) inside writeEntry's SAVEPOINT.
|
|
@@ -129,21 +129,20 @@ export declare function loadActivePolicies(hippoRoot: string, tenantId: string,
|
|
|
129
129
|
* - `superseded` rows that cover T BUT whose successor was not yet effective at T
|
|
130
130
|
* (successor.valid_from > asOf) - i.e. an earlier version that was genuinely in
|
|
131
131
|
* force then. This is the core valid-time correctness: a Jan-Jun policy
|
|
132
|
-
* superseded in May is still the answer for `asof March`.
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
* successor-aware filter mirrors the existing recall-history.ts asOf pattern.)
|
|
132
|
+
* superseded in May is still the answer for `asof March`. Filtering on
|
|
133
|
+
* status='active' alone would conflate transaction-time with valid-time; the
|
|
134
|
+
* successor-aware filter mirrors the existing recall-history.ts asOf pattern.
|
|
136
135
|
*
|
|
137
136
|
* `closed` rows are EXCLUDED: closing is a deliberate transaction-time retirement,
|
|
138
137
|
* and resurrecting closed policies for a historical valid-time is full
|
|
139
138
|
* transaction-time-travel (deferred). Returns an ARRAY (overlapping same-name
|
|
140
139
|
* ranges are allowed in v1). Optionally filtered to one policy_name.
|
|
141
140
|
*
|
|
142
|
-
* Date-only `asOfDate` (
|
|
141
|
+
* Date-only `asOfDate` (YYYY-MM-DD, no time component) resolves to the END
|
|
143
142
|
* of that UTC day (23:59:59.999Z), so "as of [day D]" includes a policy that
|
|
144
143
|
* became effective at any instant during D - this is the read-side fix for the
|
|
145
|
-
* common create-then-asof-today workflow, keeping the stored valid_from honest
|
|
146
|
-
*
|
|
144
|
+
* common create-then-asof-today workflow, keeping the stored valid_from honest.
|
|
145
|
+
* A full datetime asOf is used as the precise instant.
|
|
147
146
|
*/
|
|
148
147
|
export declare function loadPoliciesAsOf(hippoRoot: string, tenantId: string, asOfDate: string, opts?: {
|
|
149
148
|
name?: string;
|
package/dist/policies.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Policy first-class object.
|
|
3
3
|
*
|
|
4
4
|
* The "bi-temporal-first" object type: a named rule/statement that is in force
|
|
5
5
|
* over an EFFECTIVE-TIME range and evolves via supersession. Two time axes:
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
* loadPoliciesAsOf's asOfDate) is normalized to canonical ISO-8601 datetime
|
|
31
31
|
* (`toISOString`) at the store boundary BEFORE any persist or compare, so the
|
|
32
32
|
* fixed-width values sort lexically and the half-open [valid_from, valid_to)
|
|
33
|
-
* comparison is correct (
|
|
34
|
-
*
|
|
33
|
+
* comparison is correct (a date-only asOf vs a datetime valid_from would
|
|
34
|
+
* otherwise make a same-day policy invisible).
|
|
35
35
|
*
|
|
36
36
|
* Dual-write atomicity: `savePolicy` writes the memory + policies row (and, on
|
|
37
37
|
* supersede, the predecessor's UPDATE) inside writeEntry's SAVEPOINT.
|
|
@@ -111,9 +111,79 @@ function buildPolicyContent(policyName, policyText, validFrom, validTo) {
|
|
|
111
111
|
const range = validTo ? `${validFrom} to ${validTo}` : `${validFrom} onward`;
|
|
112
112
|
return `${policyName}\n\n${policyText}\n\nEffective: ${range}`;
|
|
113
113
|
}
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
114
|
+
// Preflight the supersede target BEFORE inserting the new row (so the new
|
|
115
|
+
// autoincrement id can never be its own supersede target); read the
|
|
116
|
+
// predecessor version in the same SELECT for server-derived versioning.
|
|
117
|
+
// Mirrors saveProcess / saveDecision.
|
|
118
|
+
function preflightPolicySupersede(db, tenantId, supersedesId) {
|
|
119
|
+
// SAFETY: SELECT projects exactly status, version; .get() returns that
|
|
120
|
+
// shape for the matching row, or undefined when no policy/tenant pair matches.
|
|
121
|
+
const pred = db.prepare(`SELECT status, version FROM policies WHERE id = ? AND tenant_id = ?`).get(supersedesId, tenantId);
|
|
122
|
+
if (!pred) {
|
|
123
|
+
throw new NotFoundError(`savePolicy: policy ${supersedesId} to supersede not found for tenant ${tenantId}`);
|
|
124
|
+
}
|
|
125
|
+
if (pred.status !== 'active') {
|
|
126
|
+
throw new ConflictError(`savePolicy: policy ${supersedesId} is not active (status='${pred.status}'); only active policies can be superseded.`);
|
|
127
|
+
}
|
|
128
|
+
return pred.version + 1;
|
|
129
|
+
}
|
|
130
|
+
function insertPolicyRow(db, memoryId, w, version) {
|
|
131
|
+
const result = db.prepare(`
|
|
132
|
+
INSERT INTO policies(
|
|
133
|
+
memory_id, tenant_id, policy_name, policy_text, valid_from, valid_to,
|
|
134
|
+
version, status, superseded_by, superseded_at, change_summary, closed_at, created_at
|
|
135
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, ?, NULL, ?)
|
|
136
|
+
`).run(memoryId, w.tenantId, w.policyName, w.policyText, w.validFrom, w.validTo, version, w.changeSummary, w.now);
|
|
137
|
+
return Number(result.lastInsertRowid ?? 0);
|
|
138
|
+
}
|
|
139
|
+
function supersedePolicyRow(db, w, supersedesId, policyId, version) {
|
|
140
|
+
const sup = db.prepare(`
|
|
141
|
+
UPDATE policies
|
|
142
|
+
SET status = 'superseded', superseded_by = ?, superseded_at = ?
|
|
143
|
+
WHERE id = ? AND tenant_id = ? AND status = 'active' AND id != ?
|
|
144
|
+
`).run(policyId, w.now, supersedesId, w.tenantId, policyId);
|
|
145
|
+
if (sup.changes === 0) {
|
|
146
|
+
throw new ConflictError(`savePolicy: policy ${supersedesId} could not be superseded (no longer active or self-reference).`);
|
|
147
|
+
}
|
|
148
|
+
appendAuditEvent(db, {
|
|
149
|
+
tenantId: w.tenantId,
|
|
150
|
+
actor: w.actor,
|
|
151
|
+
op: 'policy_supersede',
|
|
152
|
+
targetId: String(supersedesId),
|
|
153
|
+
metadata: {
|
|
154
|
+
policy_id: supersedesId,
|
|
155
|
+
superseded_by: policyId,
|
|
156
|
+
new_version: version,
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/** The afterWrite body: preflight, INSERT, supersede, reload, create audit, all in one SAVEPOINT. */
|
|
161
|
+
function writePolicyRow(db, memoryId, w) {
|
|
162
|
+
const version = w.supersedesId !== undefined ? preflightPolicySupersede(db, w.tenantId, w.supersedesId) : 1;
|
|
163
|
+
const policyId = insertPolicyRow(db, memoryId, w, version);
|
|
164
|
+
if (w.supersedesId !== undefined)
|
|
165
|
+
supersedePolicyRow(db, w, w.supersedesId, policyId, version);
|
|
166
|
+
// SAFETY: SELECT ${POLICY_COLS} projects exactly the PolicyRow columns;
|
|
167
|
+
// .get() returns that row, or undefined only if the just-inserted id can't
|
|
168
|
+
// be found.
|
|
169
|
+
const row = db.prepare(`SELECT ${POLICY_COLS} FROM policies WHERE id = ?`)
|
|
170
|
+
.get(policyId);
|
|
171
|
+
if (!row)
|
|
172
|
+
throw new Error('savePolicy: failed to reload saved policy row');
|
|
173
|
+
// GDPR-light metadata: ids + flags only, no policy text.
|
|
174
|
+
appendAuditEvent(db, {
|
|
175
|
+
tenantId: w.tenantId,
|
|
176
|
+
actor: w.actor,
|
|
177
|
+
op: 'policy_create',
|
|
178
|
+
targetId: String(policyId),
|
|
179
|
+
metadata: {
|
|
180
|
+
policy_id: policyId,
|
|
181
|
+
version,
|
|
182
|
+
open_ended: w.validTo === null,
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
return row;
|
|
186
|
+
}
|
|
117
187
|
/**
|
|
118
188
|
* Create a policy (or a new version that supersedes an existing one). Writes the
|
|
119
189
|
* memory mirror + the policies row atomically inside writeEntry's SAVEPOINT.
|
|
@@ -136,8 +206,7 @@ export function savePolicy(hippoRoot, tenantId, opts, actor = 'cli') {
|
|
|
136
206
|
// (a date-only asOf resolves to end-of-day in loadPoliciesAsOf), NOT by
|
|
137
207
|
// backdating the stored valid_from - backdating to midnight would make an
|
|
138
208
|
// earlier-same-day as-of wrongly report the policy already in force and would
|
|
139
|
-
// hide a superseded predecessor for that earlier time
|
|
140
|
-
// 2026-05-30 round 2). An explicit --from is honored as-is.
|
|
209
|
+
// hide a superseded predecessor for that earlier time. An explicit --from is honored as-is.
|
|
141
210
|
const { validFrom, validTo } = validatePolicyDates(opts.validFrom, opts.validTo, now);
|
|
142
211
|
const isSupersede = opts.supersedesPolicyId !== undefined;
|
|
143
212
|
const changeSummary = isSupersede ? (opts.changeSummary ?? null) : null;
|
|
@@ -151,75 +220,22 @@ export function savePolicy(hippoRoot, tenantId, opts, actor = 'cli') {
|
|
|
151
220
|
baseHalfLifeDays: objectHalfLifeDays(hippoRoot),
|
|
152
221
|
tenantId,
|
|
153
222
|
});
|
|
223
|
+
const w = {
|
|
224
|
+
tenantId,
|
|
225
|
+
actor,
|
|
226
|
+
policyName: opts.policyName,
|
|
227
|
+
policyText: opts.policyText,
|
|
228
|
+
validFrom,
|
|
229
|
+
validTo,
|
|
230
|
+
changeSummary,
|
|
231
|
+
supersedesId: opts.supersedesPolicyId,
|
|
232
|
+
now,
|
|
233
|
+
};
|
|
154
234
|
let savedRow;
|
|
155
235
|
writeEntry(hippoRoot, mem, {
|
|
156
236
|
actor,
|
|
157
237
|
afterWrite: (db, memoryId) => {
|
|
158
|
-
|
|
159
|
-
// autoincrement id can never be its own supersede target); read the
|
|
160
|
-
// predecessor version in the same SELECT for server-derived versioning.
|
|
161
|
-
// Mirrors saveProcess / saveDecision (codex P1 2026-05-28).
|
|
162
|
-
let version = 1;
|
|
163
|
-
if (opts.supersedesPolicyId !== undefined) {
|
|
164
|
-
// SAFETY: SELECT projects exactly status, version; .get() returns that
|
|
165
|
-
// shape for the matching row, or undefined when no policy/tenant pair matches.
|
|
166
|
-
const pred = db.prepare(`SELECT status, version FROM policies WHERE id = ? AND tenant_id = ?`).get(opts.supersedesPolicyId, tenantId);
|
|
167
|
-
if (!pred) {
|
|
168
|
-
throw new NotFoundError(`savePolicy: policy ${opts.supersedesPolicyId} to supersede not found for tenant ${tenantId}`);
|
|
169
|
-
}
|
|
170
|
-
if (pred.status !== 'active') {
|
|
171
|
-
throw new ConflictError(`savePolicy: policy ${opts.supersedesPolicyId} is not active (status='${pred.status}'); only active policies can be superseded.`);
|
|
172
|
-
}
|
|
173
|
-
version = pred.version + 1;
|
|
174
|
-
}
|
|
175
|
-
const result = db.prepare(`
|
|
176
|
-
INSERT INTO policies(
|
|
177
|
-
memory_id, tenant_id, policy_name, policy_text, valid_from, valid_to,
|
|
178
|
-
version, status, superseded_by, superseded_at, change_summary, closed_at, created_at
|
|
179
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, ?, NULL, ?)
|
|
180
|
-
`).run(memoryId, tenantId, opts.policyName, opts.policyText, validFrom, validTo, version, changeSummary, now);
|
|
181
|
-
const policyId = Number(result.lastInsertRowid ?? 0);
|
|
182
|
-
if (opts.supersedesPolicyId !== undefined) {
|
|
183
|
-
const sup = db.prepare(`
|
|
184
|
-
UPDATE policies
|
|
185
|
-
SET status = 'superseded', superseded_by = ?, superseded_at = ?
|
|
186
|
-
WHERE id = ? AND tenant_id = ? AND status = 'active' AND id != ?
|
|
187
|
-
`).run(policyId, now, opts.supersedesPolicyId, tenantId, policyId);
|
|
188
|
-
if (sup.changes === 0) {
|
|
189
|
-
throw new ConflictError(`savePolicy: policy ${opts.supersedesPolicyId} could not be superseded (no longer active or self-reference).`);
|
|
190
|
-
}
|
|
191
|
-
appendAuditEvent(db, {
|
|
192
|
-
tenantId,
|
|
193
|
-
actor,
|
|
194
|
-
op: 'policy_supersede',
|
|
195
|
-
targetId: String(opts.supersedesPolicyId),
|
|
196
|
-
metadata: {
|
|
197
|
-
policy_id: opts.supersedesPolicyId,
|
|
198
|
-
superseded_by: policyId,
|
|
199
|
-
new_version: version,
|
|
200
|
-
},
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
// SAFETY: SELECT ${POLICY_COLS} projects exactly the PolicyRow columns;
|
|
204
|
-
// .get() returns that row, or undefined only if the just-inserted id can't
|
|
205
|
-
// be found.
|
|
206
|
-
const row = db.prepare(`SELECT ${POLICY_COLS} FROM policies WHERE id = ?`)
|
|
207
|
-
.get(policyId);
|
|
208
|
-
if (!row)
|
|
209
|
-
throw new Error('savePolicy: failed to reload saved policy row');
|
|
210
|
-
savedRow = row;
|
|
211
|
-
// GDPR-light metadata: ids + flags only, no policy text.
|
|
212
|
-
appendAuditEvent(db, {
|
|
213
|
-
tenantId,
|
|
214
|
-
actor,
|
|
215
|
-
op: 'policy_create',
|
|
216
|
-
targetId: String(policyId),
|
|
217
|
-
metadata: {
|
|
218
|
-
policy_id: policyId,
|
|
219
|
-
version,
|
|
220
|
-
open_ended: validTo === null,
|
|
221
|
-
},
|
|
222
|
-
});
|
|
238
|
+
savedRow = writePolicyRow(db, memoryId, w);
|
|
223
239
|
},
|
|
224
240
|
afterCommit: () => markGraphDirty(hippoRoot, tenantId, mem.id),
|
|
225
241
|
});
|
|
@@ -273,7 +289,7 @@ export function closePolicy(hippoRoot, tenantId, id, actor = 'cli') {
|
|
|
273
289
|
// Closing removes the object from the graph. Remove its rows DIRECTLY (deterministic),
|
|
274
290
|
// not only via an enqueued rebuild whose queue item is lost if the mirror is later
|
|
275
291
|
// forgotten (the queue row cascade-deletes with the memory), which would leave the closed
|
|
276
|
-
// object stale and could block that forget
|
|
292
|
+
// object stale and could block that forget. Still enqueue when a mirror exists
|
|
277
293
|
// so a concurrent rebuild re-derives consistently (harmless if it also runs).
|
|
278
294
|
removeGraphEntitiesForObject(hippoRoot, tenantId, 'policy', closed.id);
|
|
279
295
|
if (closed.memoryId) {
|
|
@@ -359,21 +375,20 @@ export function loadActivePolicies(hippoRoot, tenantId, opts = {}) {
|
|
|
359
375
|
* - `superseded` rows that cover T BUT whose successor was not yet effective at T
|
|
360
376
|
* (successor.valid_from > asOf) - i.e. an earlier version that was genuinely in
|
|
361
377
|
* force then. This is the core valid-time correctness: a Jan-Jun policy
|
|
362
|
-
* superseded in May is still the answer for `asof March`.
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
* successor-aware filter mirrors the existing recall-history.ts asOf pattern.)
|
|
378
|
+
* superseded in May is still the answer for `asof March`. Filtering on
|
|
379
|
+
* status='active' alone would conflate transaction-time with valid-time; the
|
|
380
|
+
* successor-aware filter mirrors the existing recall-history.ts asOf pattern.
|
|
366
381
|
*
|
|
367
382
|
* `closed` rows are EXCLUDED: closing is a deliberate transaction-time retirement,
|
|
368
383
|
* and resurrecting closed policies for a historical valid-time is full
|
|
369
384
|
* transaction-time-travel (deferred). Returns an ARRAY (overlapping same-name
|
|
370
385
|
* ranges are allowed in v1). Optionally filtered to one policy_name.
|
|
371
386
|
*
|
|
372
|
-
* Date-only `asOfDate` (
|
|
387
|
+
* Date-only `asOfDate` (YYYY-MM-DD, no time component) resolves to the END
|
|
373
388
|
* of that UTC day (23:59:59.999Z), so "as of [day D]" includes a policy that
|
|
374
389
|
* became effective at any instant during D - this is the read-side fix for the
|
|
375
|
-
* common create-then-asof-today workflow, keeping the stored valid_from honest
|
|
376
|
-
*
|
|
390
|
+
* common create-then-asof-today workflow, keeping the stored valid_from honest.
|
|
391
|
+
* A full datetime asOf is used as the precise instant.
|
|
377
392
|
*/
|
|
378
393
|
export function loadPoliciesAsOf(hippoRoot, tenantId, asOfDate, opts = {}) {
|
|
379
394
|
assertTenantId('loadPoliciesAsOf', tenantId);
|
package/dist/postinstall.js
CHANGED
|
@@ -7,12 +7,9 @@ function main() {
|
|
|
7
7
|
if (envSkipPostinstall())
|
|
8
8
|
return;
|
|
9
9
|
try {
|
|
10
|
-
// Repair-only
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// postinstall is a consent violation and reads as binary hijacking to
|
|
14
|
-
// supply-chain scanners (issue #133). First install is `hippo hook
|
|
15
|
-
// install codex` only.
|
|
10
|
+
// Repair-only, for users who opted in (a Codex update can restore the real binary over our shim).
|
|
11
|
+
// Swapping the binary from postinstall is a consent violation that supply-chain scanners read as
|
|
12
|
+
// hijacking, so first install is `hippo hook install codex` only.
|
|
16
13
|
repairCodexWrapperIfInstalled();
|
|
17
14
|
}
|
|
18
15
|
catch {
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Surface delivered on `RecallResult.planningFallacyHint` when an
|
|
3
3
|
* agent's recall query carries a forward-prediction phrase AND the closest
|
|
4
4
|
* matching prediction class has closed historical data.
|
|
5
5
|
*
|
|
6
6
|
* The agent sees its track record at the moment of forecasting, anchoring
|
|
7
7
|
* on the outside view (Lovallo-Kahneman 2003) rather than the inside-view
|
|
8
8
|
* inside the planning fallacy.
|
|
9
|
-
*
|
|
10
|
-
* Plan: docs/plans/2026-05-26-j32-auto-injection.md.
|
|
11
9
|
*/
|
|
12
10
|
export interface PlanningFallacyHint {
|
|
13
11
|
classTag: string;
|
|
@@ -25,13 +23,11 @@ export interface PlanningFallacyHint {
|
|
|
25
23
|
meanRatio: number | null;
|
|
26
24
|
}
|
|
27
25
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* Trial 2a confirmed the pre-v1.13.4 silent paths were the most common
|
|
32
|
-
* real-world J3.2 failure mode: a natural-language query carries a
|
|
26
|
+
* "Watching" variant emitted when the forward-claim regex matched but no
|
|
27
|
+
* PlanningFallacyHint baserate was returned. Silence was the most common
|
|
28
|
+
* real-world failure: a natural-language query carries a
|
|
33
29
|
* forward-claim phrase but its non-stopword tokens don't overlap with
|
|
34
|
-
* any prediction class tag, so hippo
|
|
30
|
+
* any prediction class tag, so hippo emitted nothing despite
|
|
35
31
|
* the regex match. The watching variant surfaces the detection event
|
|
36
32
|
* + a one-line suggestion so the agent can either re-tag the prediction
|
|
37
33
|
* or pass the suggestion through to the user.
|
|
@@ -48,7 +44,7 @@ export interface PlanningFallacyWatching {
|
|
|
48
44
|
suggestion: string;
|
|
49
45
|
}
|
|
50
46
|
/**
|
|
51
|
-
*
|
|
47
|
+
* Richer return type for
|
|
52
48
|
* `computePlanningFallacyOutput`. Carries EITHER `hint` (baserate
|
|
53
49
|
* available) OR `watching` (regex fired, no baserate), or NEITHER (mode=off,
|
|
54
50
|
* no queryText, no regex match, or nClosed=0 silent path). Never both.
|
|
@@ -71,7 +67,7 @@ export interface ComputePlanningFallacyHintOpts {
|
|
|
71
67
|
actor?: string;
|
|
72
68
|
}
|
|
73
69
|
/**
|
|
74
|
-
*
|
|
70
|
+
* Planning-fallacy orchestrator.
|
|
75
71
|
*
|
|
76
72
|
* Composes the forward-claim detector + class resolver + baserate compute,
|
|
77
73
|
* with telemetry-grade audit emission at every decision point (success,
|
|
@@ -83,7 +79,7 @@ export interface ComputePlanningFallacyHintOpts {
|
|
|
83
79
|
* - no forward-claim regex match
|
|
84
80
|
* - resolved class has nClosed=0 (no historical data yet; silent)
|
|
85
81
|
*
|
|
86
|
-
* Returns `{ watching: ... }` on
|
|
82
|
+
* Returns `{ watching: ... }` on:
|
|
87
83
|
* - resolver returns no class (no overlap ≥ 1; emits no_class_match audit)
|
|
88
84
|
* - resolver returns tiebreak (≥2 classes tied at best; emits tiebreak audit)
|
|
89
85
|
*
|
|
@@ -93,8 +89,7 @@ export interface ComputePlanningFallacyHintOpts {
|
|
|
93
89
|
* audit carries n_closed + mean_ratio in metadata so no telemetry is lost),
|
|
94
90
|
* then emits recall_autodebias_hint audit + returns the hint.
|
|
95
91
|
*
|
|
96
|
-
* Latency budget
|
|
97
|
-
* on full match+resolve+baserate path. Well under 50ms target.
|
|
92
|
+
* Latency budget: well under 50ms; a miss pays only the regex.
|
|
98
93
|
*/
|
|
99
94
|
export declare function computePlanningFallacyOutput(hippoRoot: string, tenantId: string, queryText: string, opts?: ComputePlanningFallacyHintOpts): PlanningFallacyOutput;
|
|
100
95
|
//# sourceMappingURL=planning-fallacy.d.ts.map
|
|
@@ -11,8 +11,8 @@ import { computePredictionBaserate } from './store.js';
|
|
|
11
11
|
* Indexed via idx_predictions_tenant_class (db.ts:1015) → O(log n) seek
|
|
12
12
|
* plus a small DISTINCT scan over the per-tenant class-tag set.
|
|
13
13
|
*
|
|
14
|
-
* Scope behaviour (
|
|
15
|
-
*
|
|
14
|
+
* Scope behaviour (deliberate): class_tag selection is TENANT-GLOBAL,
|
|
15
|
+
* NOT scope-filtered against
|
|
16
16
|
* the recall's opts.scope. The class_tag is an aggregator label across
|
|
17
17
|
* historical predictions in the class, not a per-memory scope-bound
|
|
18
18
|
* property. A no-scope recall CAN surface a class_tag from a privately-
|
|
@@ -75,7 +75,7 @@ function resolveClassFromTokens(hippoRoot, tenantId, queryTokens) {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
78
|
-
*
|
|
78
|
+
* Planning-fallacy orchestrator.
|
|
79
79
|
*
|
|
80
80
|
* Composes the forward-claim detector + class resolver + baserate compute,
|
|
81
81
|
* with telemetry-grade audit emission at every decision point (success,
|
|
@@ -87,7 +87,7 @@ function resolveClassFromTokens(hippoRoot, tenantId, queryTokens) {
|
|
|
87
87
|
* - no forward-claim regex match
|
|
88
88
|
* - resolved class has nClosed=0 (no historical data yet; silent)
|
|
89
89
|
*
|
|
90
|
-
* Returns `{ watching: ... }` on
|
|
90
|
+
* Returns `{ watching: ... }` on:
|
|
91
91
|
* - resolver returns no class (no overlap ≥ 1; emits no_class_match audit)
|
|
92
92
|
* - resolver returns tiebreak (≥2 classes tied at best; emits tiebreak audit)
|
|
93
93
|
*
|
|
@@ -97,8 +97,7 @@ function resolveClassFromTokens(hippoRoot, tenantId, queryTokens) {
|
|
|
97
97
|
* audit carries n_closed + mean_ratio in metadata so no telemetry is lost),
|
|
98
98
|
* then emits recall_autodebias_hint audit + returns the hint.
|
|
99
99
|
*
|
|
100
|
-
* Latency budget
|
|
101
|
-
* on full match+resolve+baserate path. Well under 50ms target.
|
|
100
|
+
* Latency budget: well under 50ms; a miss pays only the regex.
|
|
102
101
|
*/
|
|
103
102
|
export function computePlanningFallacyOutput(hippoRoot, tenantId, queryText, opts = {}) {
|
|
104
103
|
// Env read FIRST so AUTODEBIAS=off pays zero regex cost. Per-call read
|
|
@@ -115,19 +114,14 @@ export function computePlanningFallacyOutput(hippoRoot, tenantId, queryText, opt
|
|
|
115
114
|
const actor = opts.actor ?? 'recall';
|
|
116
115
|
const resolution = resolveClassFromTokens(hippoRoot, tenantId, match.classQueryTokens);
|
|
117
116
|
if (resolution.tiebreak) {
|
|
118
|
-
// Telemetry: forward-claim detected, ≥2 classes tied at best overlap.
|
|
119
|
-
//
|
|
120
|
-
// can render a "watching but no baserate (tiebreak)" line. Audit emission
|
|
121
|
-
// unchanged (the audit channel is the telemetry-grade source of truth).
|
|
117
|
+
// Telemetry: forward-claim detected, ≥2 classes tied at best overlap. The watching variant lets the
|
|
118
|
+
// caller render "watching but no baserate (tiebreak)"; the audit channel stays the source of truth.
|
|
122
119
|
return watchingWithAudit(hippoRoot, tenantId, actor, match, 'tiebreak', TIEBREAK_SUGGESTION);
|
|
123
120
|
}
|
|
124
121
|
if (!resolution.classTag) {
|
|
125
|
-
// Telemetry: forward-claim detected, no class scored ≥ 1.
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
// legitimate forward-claims that have NO obvious class signal.
|
|
129
|
-
// v1.13.4: now ALSO returns a watching variant so the caller surface
|
|
130
|
-
// can render a "watching but no baserate (no class match)" line.
|
|
122
|
+
// Telemetry: forward-claim detected, no class scored ≥ 1. High volume here means regex+token-overlap
|
|
123
|
+
// misses real forward-claims with no class signal, the case for an embedding fallback.
|
|
124
|
+
// The watching variant lets the caller render "watching but no baserate (no class match)".
|
|
131
125
|
return watchingWithAudit(hippoRoot, tenantId, actor, match, 'no_class_match', NO_CLASS_MATCH_SUGGESTION);
|
|
132
126
|
}
|
|
133
127
|
// emitAudit=false: avoid double-write to predict_baserate channel.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Prediction first-class object.
|
|
3
3
|
*
|
|
4
4
|
* Canonical store for ex-ante claims that can be closed against ex-post
|
|
5
5
|
* outcomes. The `predictions` table holds every field (including
|
|
@@ -19,10 +19,8 @@
|
|
|
19
19
|
* a failure in either step rolls back both. Pattern matches supersede
|
|
20
20
|
* (api.ts:1486) and the Slack/GitHub connectors.
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* (estimate_value, actual_value) at query time. J3 is a follow-up episode;
|
|
25
|
-
* this module ships the data layer.
|
|
22
|
+
* The planning-fallacy detector reads `loadPredictionsByClass` and computes
|
|
23
|
+
* per-class base rates from (estimate_value, actual_value) at query time.
|
|
26
24
|
*/
|
|
27
25
|
import { type KeysetPosition } from '../keyset.js';
|
|
28
26
|
export type ClosureState = 'open' | 'closed' | 'closed-unknown';
|
|
@@ -71,18 +69,22 @@ export interface ListPredictionsOpts {
|
|
|
71
69
|
* The memory is tagged `['prediction', classTag]` with `source='prediction'`
|
|
72
70
|
* and `kind='distilled'`. It surfaces in `hippo recall` so the agent can
|
|
73
71
|
* see open predictions naturally; the predictions table is the canonical
|
|
74
|
-
* structured store used by
|
|
72
|
+
* structured store used by the planning-fallacy detector.
|
|
75
73
|
*/
|
|
76
74
|
export declare function savePrediction(hippoRoot: string, tenantId: string, opts: SavePredictionOpts, actor?: string): Prediction;
|
|
77
75
|
/**
|
|
78
76
|
* Close an existing open prediction. Updates the predictions row only;
|
|
79
77
|
* the memory mirror is NOT mutated in v1 (predictions table is canonical).
|
|
80
|
-
*
|
|
81
|
-
* actualValue) at query time.
|
|
78
|
+
* Accuracy is computed from (estimateValue, actualValue) at query time.
|
|
82
79
|
*/
|
|
83
80
|
export declare function closePrediction(hippoRoot: string, tenantId: string, id: number, opts: ClosePredictionOpts, actor?: string): Prediction;
|
|
84
81
|
export declare function loadPredictionById(hippoRoot: string, tenantId: string, id: number): Prediction | null;
|
|
85
82
|
export declare function loadPredictionsByClass(hippoRoot: string, tenantId: string, classTag: string, opts?: ListPredictionsOpts): Prediction[];
|
|
83
|
+
/** Every prediction in the tenant, open and closed, across all classes: the `status=all` list without a class. */
|
|
84
|
+
export declare function loadAllPredictions(hippoRoot: string, tenantId: string, opts?: {
|
|
85
|
+
limit?: number;
|
|
86
|
+
after?: KeysetPosition;
|
|
87
|
+
}): Prediction[];
|
|
86
88
|
export interface PredictionBaserate {
|
|
87
89
|
classTag: string;
|
|
88
90
|
/** Count of closed predictions with a numeric actual_value (excludes
|
|
@@ -105,28 +107,18 @@ export interface PredictionBaserate {
|
|
|
105
107
|
summary: string;
|
|
106
108
|
}
|
|
107
109
|
/**
|
|
108
|
-
* Compute base-rate stats for closed predictions in a class
|
|
109
|
-
*
|
|
110
|
-
* Lovallo-Kahneman (2003) inside-vs-outside view.
|
|
110
|
+
* Compute base-rate stats for closed predictions in a class for the
|
|
111
|
+
* planning-fallacy detector: Lovallo-Kahneman (2003) inside-vs-outside view.
|
|
111
112
|
*
|
|
112
113
|
* Filter: closure_state='closed' AND estimate_value IS NOT NULL AND
|
|
113
114
|
* actual_value IS NOT NULL. Excludes closed-unknown (no actual to
|
|
114
115
|
* compare against) and open (not yet resolved).
|
|
115
116
|
*
|
|
116
|
-
* Audit-emit is
|
|
117
|
-
* drift risk). Plan-eng-critic round 1 HIGH recommendation: emit inside
|
|
118
|
-
* helper, not at 3 call sites.
|
|
117
|
+
* Audit-emit is built in here, not at the 3 call sites, so callers cannot drift.
|
|
119
118
|
*/
|
|
120
119
|
export declare function computePredictionBaserate(hippoRoot: string, tenantId: string, classTag: string, actor?: string,
|
|
121
|
-
/**
|
|
122
|
-
*
|
|
123
|
-
* emitAudit=false and emits its own `recall_autodebias_hint` audit row
|
|
124
|
-
* instead, so the predict_baserate channel stays scoped to deliberate
|
|
125
|
-
* CLI / HTTP / MCP predict-baserate calls and does NOT pollute on every
|
|
126
|
-
* recall containing a forward-claim phrase. Default true preserves the
|
|
127
|
-
* v1.13.0 J3 audit semantics for the 3 direct callers (cmdPredict
|
|
128
|
-
* baserate, /v1/predictions/stats route, hippo_predict_baserate MCP
|
|
129
|
-
* handler) — none of them pass this argument. */
|
|
120
|
+
/** False skips the predict_baserate audit so that channel only records deliberate
|
|
121
|
+
* baserate calls, not every recall the planning-fallacy orchestrator inspects. */
|
|
130
122
|
emitAudit?: boolean): PredictionBaserate;
|
|
131
123
|
export declare function loadOpenPredictions(hippoRoot: string, tenantId: string, opts?: {
|
|
132
124
|
classTag?: string;
|