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.
Files changed (377) hide show
  1. package/README.md +37 -53
  2. package/dist/agent-memories/apply.d.ts +3 -1
  3. package/dist/agent-memories/apply.js +23 -1
  4. package/dist/agent-memories/claude-code.d.ts +4 -1
  5. package/dist/agent-memories/claude-code.js +53 -9
  6. package/dist/agent-memories/report.d.ts +1 -0
  7. package/dist/agent-memories/report.js +2 -2
  8. package/dist/agent-memories/sync.d.ts +3 -3
  9. package/dist/agent-memories/sync.js +46 -24
  10. package/dist/agent-memories/types.d.ts +0 -2
  11. package/dist/ambient-store.d.ts +4 -4
  12. package/dist/ambient-store.js +4 -3
  13. package/dist/api/assemble.d.ts +7 -10
  14. package/dist/api/assemble.js +62 -66
  15. package/dist/api/audit.d.ts +2 -2
  16. package/dist/api/audit.js +2 -2
  17. package/dist/api/auth.d.ts +6 -6
  18. package/dist/api/auth.js +5 -7
  19. package/dist/api/context-select.d.ts +50 -0
  20. package/dist/api/context-select.js +342 -0
  21. package/dist/api/context-types.d.ts +12 -17
  22. package/dist/api/context.d.ts +5 -4
  23. package/dist/api/context.js +208 -535
  24. package/dist/api/dormant.js +1 -1
  25. package/dist/api/drill-down.d.ts +4 -4
  26. package/dist/api/drill-down.js +56 -41
  27. package/dist/api/outcome.d.ts +8 -13
  28. package/dist/api/outcome.js +13 -17
  29. package/dist/api/promote.d.ts +5 -8
  30. package/dist/api/promote.js +55 -66
  31. package/dist/api/quarantine.js +3 -2
  32. package/dist/api/recall-types.d.ts +43 -55
  33. package/dist/api/recall.d.ts +3 -3
  34. package/dist/api/recall.js +310 -456
  35. package/dist/api/remember.d.ts +2 -2
  36. package/dist/api/sleep.d.ts +7 -35
  37. package/dist/api/sleep.js +206 -220
  38. package/dist/api/tokens.d.ts +2 -2
  39. package/dist/api/tokens.js +2 -2
  40. package/dist/api/types.d.ts +6 -10
  41. package/dist/api/types.js +2 -4
  42. package/dist/audit-prune.d.ts +4 -6
  43. package/dist/audit-prune.js +3 -5
  44. package/dist/audit.js +11 -33
  45. package/dist/auth.d.ts +8 -9
  46. package/dist/auth.js +5 -7
  47. package/dist/autolearn.d.ts +1 -1
  48. package/dist/autolearn.js +1 -1
  49. package/dist/availability.js +3 -5
  50. package/dist/capture/command.d.ts +5 -4
  51. package/dist/capture/command.js +8 -22
  52. package/dist/capture/compact.d.ts +2 -2
  53. package/dist/capture/compact.js +11 -15
  54. package/dist/capture/extract.js +37 -115
  55. package/dist/capture-error.d.ts +1 -1
  56. package/dist/capture-error.js +1 -1
  57. package/dist/churn-git.d.ts +1 -1
  58. package/dist/churn-git.js +1 -1
  59. package/dist/cli/audit.js +3 -4
  60. package/dist/cli/auth.js +3 -6
  61. package/dist/cli/briefs.js +324 -306
  62. package/dist/cli/context.js +44 -34
  63. package/dist/cli/continuity.js +283 -271
  64. package/dist/cli/curate.d.ts +1 -1
  65. package/dist/cli/curate.js +43 -58
  66. package/dist/cli/dag.js +5 -9
  67. package/dist/cli/decisions.js +334 -345
  68. package/dist/cli/explain.js +68 -61
  69. package/dist/cli/goals.js +1 -1
  70. package/dist/cli/init.js +1 -1
  71. package/dist/cli/maintenance.js +62 -51
  72. package/dist/cli/playbooks.js +391 -379
  73. package/dist/cli/projects.js +11 -6
  74. package/dist/cli/recall.js +30 -44
  75. package/dist/cli/remember.js +118 -87
  76. package/dist/cli/session-hooks.js +106 -115
  77. package/dist/cli/setup.d.ts +1 -1
  78. package/dist/cli/setup.js +267 -250
  79. package/dist/cli/shared.js +3 -3
  80. package/dist/cli/slack.js +1 -1
  81. package/dist/cli/sleep.js +27 -1
  82. package/dist/cli/status.d.ts +4 -4
  83. package/dist/cli/status.js +80 -76
  84. package/dist/cli/transfer.js +88 -107
  85. package/dist/cli/usage.js +9 -6
  86. package/dist/cli.d.ts +1 -1
  87. package/dist/cli.js +4 -9
  88. package/dist/compaction-record.d.ts +2 -2
  89. package/dist/compaction-record.js +89 -68
  90. package/dist/compare.d.ts +11 -16
  91. package/dist/compare.js +11 -16
  92. package/dist/config.d.ts +19 -18
  93. package/dist/config.js +90 -67
  94. package/dist/connectors/github/backfill.d.ts +2 -2
  95. package/dist/connectors/github/backfill.js +8 -15
  96. package/dist/connectors/github/cli-impl.js +3 -8
  97. package/dist/connectors/github/deletion.d.ts +5 -12
  98. package/dist/connectors/github/deletion.js +5 -12
  99. package/dist/connectors/github/dlq.d.ts +6 -9
  100. package/dist/connectors/github/dlq.js +2 -3
  101. package/dist/connectors/github/ingest.d.ts +5 -7
  102. package/dist/connectors/github/ingest.js +8 -12
  103. package/dist/connectors/github/octokit-client.d.ts +3 -5
  104. package/dist/connectors/github/octokit-client.js +5 -6
  105. package/dist/connectors/github/signature.d.ts +9 -39
  106. package/dist/connectors/github/signature.js +9 -39
  107. package/dist/connectors/github/tenant-routing.d.ts +1 -1
  108. package/dist/connectors/github/tenant-routing.js +1 -1
  109. package/dist/connectors/github/transform.js +2 -2
  110. package/dist/connectors/github/types.d.ts +2 -10
  111. package/dist/connectors/github/types.js +1 -3
  112. package/dist/connectors/slack/deletion.d.ts +3 -8
  113. package/dist/connectors/slack/deletion.js +3 -8
  114. package/dist/connectors/slack/dlq.d.ts +1 -1
  115. package/dist/connectors/slack/ingest.d.ts +1 -1
  116. package/dist/connectors/slack/ingest.js +7 -16
  117. package/dist/connectors/slack/signature.d.ts +1 -1
  118. package/dist/connectors/slack/tenant-routing.d.ts +3 -5
  119. package/dist/connectors/slack/tenant-routing.js +3 -5
  120. package/dist/connectors/slack/transform.d.ts +5 -6
  121. package/dist/connectors/slack/transform.js +5 -6
  122. package/dist/connectors/slack/types.d.ts +2 -6
  123. package/dist/connectors/slack/types.js +1 -3
  124. package/dist/connectors/slack/web-client.js +10 -3
  125. package/dist/connectors/slack/workspaces.d.ts +3 -5
  126. package/dist/connectors/slack/workspaces.js +3 -5
  127. package/dist/consolidate/conflicts.js +3 -14
  128. package/dist/consolidate/decay.js +9 -29
  129. package/dist/consolidate/llm-passes.js +4 -5
  130. package/dist/consolidate/merge.js +8 -23
  131. package/dist/consolidate/run.d.ts +1 -8
  132. package/dist/consolidate/run.js +3 -25
  133. package/dist/consolidate/sleep.js +5 -17
  134. package/dist/consolidate/traces.js +9 -21
  135. package/dist/customer-notes.d.ts +5 -7
  136. package/dist/customer-notes.js +82 -76
  137. package/dist/dag.d.ts +10 -21
  138. package/dist/dag.js +189 -203
  139. package/dist/db/continuity.js +2 -2
  140. package/dist/db/migrations/v14.js +1 -1
  141. package/dist/db/migrations/v15.js +1 -2
  142. package/dist/db/migrations/v16.js +3 -4
  143. package/dist/db/migrations/v17.js +2 -3
  144. package/dist/db/migrations/v19.js +1 -1
  145. package/dist/db/migrations/v20.js +1 -1
  146. package/dist/db/migrations/v21.js +2 -6
  147. package/dist/db/migrations/v22.js +2 -4
  148. package/dist/db/migrations/v23.js +1 -1
  149. package/dist/db/migrations/v24.js +4 -6
  150. package/dist/db/migrations/v25.js +2 -3
  151. package/dist/db/migrations/v26.js +3 -3
  152. package/dist/db/migrations/v27.js +2 -10
  153. package/dist/db/migrations/v28.js +5 -8
  154. package/dist/db/migrations/v29.js +3 -4
  155. package/dist/db/migrations/v30.js +2 -2
  156. package/dist/db/migrations/v31.js +1 -1
  157. package/dist/db/migrations/v32.js +1 -1
  158. package/dist/db/migrations/v33.js +3 -3
  159. package/dist/db/migrations/v34.js +1 -1
  160. package/dist/db/migrations/v35.js +3 -4
  161. package/dist/db/migrations/v36.js +3 -4
  162. package/dist/db/migrations/v37.js +5 -5
  163. package/dist/db/migrations/v38.js +7 -8
  164. package/dist/db/migrations/v39.js +1 -1
  165. package/dist/db/migrations/v40.js +4 -16
  166. package/dist/db/migrations/v41.js +3 -4
  167. package/dist/db/migrations/v42.js +3 -4
  168. package/dist/db/migrations/v45.js +1 -1
  169. package/dist/db/migrations/v46.js +1 -1
  170. package/dist/db/migrations/v47.js +1 -1
  171. package/dist/db/migrations/v48.js +1 -1
  172. package/dist/decisions.d.ts +2 -2
  173. package/dist/decisions.js +97 -80
  174. package/dist/dedupe.js +86 -61
  175. package/dist/delivery-recorder.js +154 -135
  176. package/dist/doctor.js +129 -110
  177. package/dist/dormant.js +1 -4
  178. package/dist/embedding-provider.d.ts +4 -8
  179. package/dist/embedding-provider.js +4 -8
  180. package/dist/embeddings.js +55 -47
  181. package/dist/env.d.ts +1 -1
  182. package/dist/env.js +12 -12
  183. package/dist/escape.d.ts +5 -0
  184. package/dist/escape.js +10 -0
  185. package/dist/eval-stats.d.ts +1 -2
  186. package/dist/eval-stats.js +1 -2
  187. package/dist/eval-suite.js +27 -21
  188. package/dist/extract.js +4 -9
  189. package/dist/failure-log.d.ts +3 -3
  190. package/dist/failure-log.js +1 -1
  191. package/dist/forward-claim-detector.d.ts +2 -4
  192. package/dist/forward-claim-detector.js +6 -11
  193. package/dist/goals.d.ts +3 -3
  194. package/dist/goals.js +103 -91
  195. package/dist/graph/read.d.ts +2 -2
  196. package/dist/graph/read.js +5 -6
  197. package/dist/graph/types.d.ts +8 -8
  198. package/dist/graph/write.d.ts +7 -14
  199. package/dist/graph/write.js +16 -23
  200. package/dist/graph-extract.d.ts +7 -8
  201. package/dist/graph-extract.js +62 -72
  202. package/dist/graph-recall.d.ts +2 -2
  203. package/dist/graph-recall.js +55 -49
  204. package/dist/graph-stream.d.ts +5 -6
  205. package/dist/graph-stream.js +66 -57
  206. package/dist/graph-view.d.ts +2 -2
  207. package/dist/graph-view.js +7 -7
  208. package/dist/half-life-migration.d.ts +1 -2
  209. package/dist/half-life-migration.js +2 -3
  210. package/dist/hooks/codex-session.js +1 -1
  211. package/dist/hooks/codex-wrapper.d.ts +1 -1
  212. package/dist/hooks/codex-wrapper.js +3 -2
  213. package/dist/hooks/json-hooks.d.ts +2 -2
  214. package/dist/hooks/json-hooks.js +5 -4
  215. package/dist/hooks/opencode.d.ts +1 -1
  216. package/dist/hooks/opencode.js +5 -4
  217. package/dist/hooks/shared.d.ts +3 -7
  218. package/dist/hooks/shared.js +1 -8
  219. package/dist/http-util.d.ts +2 -3
  220. package/dist/http-util.js +3 -0
  221. package/dist/importers/core.d.ts +2 -9
  222. package/dist/importers/core.js +15 -30
  223. package/dist/importers/sources.js +2 -1
  224. package/dist/importers/vault.js +2 -20
  225. package/dist/incidents.d.ts +1 -1
  226. package/dist/incidents.js +46 -39
  227. package/dist/instruction-detect.d.ts +1 -1
  228. package/dist/instruction-detect.js +1 -1
  229. package/dist/invalidation.d.ts +3 -0
  230. package/dist/invalidation.js +160 -114
  231. package/dist/json.d.ts +5 -0
  232. package/dist/json.js +4 -0
  233. package/dist/judgment.js +1 -2
  234. package/dist/local-embedding.js +1 -1
  235. package/dist/mcp/admin-tools.js +7 -17
  236. package/dist/mcp/format.js +1 -1
  237. package/dist/mcp/framing.js +3 -6
  238. package/dist/mcp/protocol.d.ts +2 -5
  239. package/dist/mcp/protocol.js +1 -3
  240. package/dist/mcp/recall-tools.js +12 -15
  241. package/dist/mcp/request.js +4 -3
  242. package/dist/mcp/session-state.js +2 -3
  243. package/dist/mcp/stdio.js +2 -1
  244. package/dist/mcp/tools.js +9 -6
  245. package/dist/memory-value-weights.d.ts +5 -8
  246. package/dist/memory-value-weights.js +5 -8
  247. package/dist/memory-value.d.ts +13 -13
  248. package/dist/memory-value.js +26 -37
  249. package/dist/memory.d.ts +20 -22
  250. package/dist/memory.js +24 -48
  251. package/dist/multihop.d.ts +1 -1
  252. package/dist/multihop.js +3 -2
  253. package/dist/owner-validation.d.ts +4 -5
  254. package/dist/owner-validation.js +4 -5
  255. package/dist/physics.d.ts +4 -4
  256. package/dist/physics.js +7 -9
  257. package/dist/policies.d.ts +9 -10
  258. package/dist/policies.js +96 -81
  259. package/dist/postinstall.js +3 -6
  260. package/dist/predictions/planning-fallacy.d.ts +9 -14
  261. package/dist/predictions/planning-fallacy.js +10 -16
  262. package/dist/predictions/store.d.ts +15 -23
  263. package/dist/predictions/store.js +36 -33
  264. package/dist/processes.d.ts +2 -7
  265. package/dist/processes.js +88 -72
  266. package/dist/project-briefs.d.ts +2 -3
  267. package/dist/project-briefs.js +141 -118
  268. package/dist/project-identity.d.ts +22 -9
  269. package/dist/project-identity.js +47 -12
  270. package/dist/project-merge.d.ts +28 -5
  271. package/dist/project-merge.js +213 -46
  272. package/dist/project-remote.d.ts +12 -0
  273. package/dist/project-remote.js +138 -0
  274. package/dist/prompt-recall.js +1 -2
  275. package/dist/rate-limit.d.ts +1 -1
  276. package/dist/rate-limit.js +1 -1
  277. package/dist/raw-archive.d.ts +9 -0
  278. package/dist/raw-archive.js +70 -53
  279. package/dist/recall-history.d.ts +19 -20
  280. package/dist/recall-history.js +24 -42
  281. package/dist/recall-pipeline.js +4 -28
  282. package/dist/recall-scope.d.ts +7 -8
  283. package/dist/recall-scope.js +7 -8
  284. package/dist/recall-trace.d.ts +5 -9
  285. package/dist/recall-trace.js +6 -10
  286. package/dist/refine-llm.d.ts +1 -1
  287. package/dist/refine-llm.js +2 -2
  288. package/dist/reject-flow.d.ts +3 -4
  289. package/dist/reject-flow.js +122 -117
  290. package/dist/rejection.d.ts +5 -6
  291. package/dist/rejection.js +7 -15
  292. package/dist/rerankers/clef.d.ts +1 -1
  293. package/dist/rerankers/jev.d.ts +1 -2
  294. package/dist/rerankers/jev.js +4 -5
  295. package/dist/rerankers/llm.d.ts +1 -2
  296. package/dist/rerankers/llm.js +1 -2
  297. package/dist/rerankers/types.d.ts +1 -2
  298. package/dist/rrf.d.ts +2 -2
  299. package/dist/rrf.js +2 -2
  300. package/dist/search/bm25-search.d.ts +1 -1
  301. package/dist/search/bm25-search.js +2 -1
  302. package/dist/search/boosts.js +2 -1
  303. package/dist/search/hybrid.d.ts +1 -1
  304. package/dist/search/hybrid.js +2 -1
  305. package/dist/search/physics-search.d.ts +1 -1
  306. package/dist/search/physics-search.js +2 -1
  307. package/dist/search/types.d.ts +2 -0
  308. package/dist/search/types.js +3 -1
  309. package/dist/secret-detect.d.ts +4 -5
  310. package/dist/secret-detect.js +6 -10
  311. package/dist/server/auth.js +5 -5
  312. package/dist/server/client-ip.js +1 -1
  313. package/dist/server/cursor.js +2 -1
  314. package/dist/server/mcp-http.js +4 -4
  315. package/dist/server/request.d.ts +3 -6
  316. package/dist/server/request.js +6 -7
  317. package/dist/server/routes/admin.js +5 -4
  318. package/dist/server/routes/customer-notes.js +6 -5
  319. package/dist/server/routes/decisions.js +4 -3
  320. package/dist/server/routes/incidents.js +7 -5
  321. package/dist/server/routes/memories.js +7 -7
  322. package/dist/server/routes/policies.js +3 -2
  323. package/dist/server/routes/predictions.js +12 -15
  324. package/dist/server/routes/processes.js +3 -2
  325. package/dist/server/routes/project-briefs.js +8 -7
  326. package/dist/server/routes/recall.js +95 -93
  327. package/dist/server/routes/skills.js +6 -5
  328. package/dist/server/types.d.ts +1 -1
  329. package/dist/server/validation.d.ts +1 -2
  330. package/dist/server/validation.js +7 -14
  331. package/dist/server-detect.js +72 -58
  332. package/dist/server.d.ts +2 -2
  333. package/dist/server.js +131 -117
  334. package/dist/shared.d.ts +26 -17
  335. package/dist/shared.js +102 -104
  336. package/dist/skills.d.ts +3 -3
  337. package/dist/skills.js +88 -72
  338. package/dist/store/audit-event.d.ts +2 -2
  339. package/dist/store/audit-event.js +1 -1
  340. package/dist/store/candidates.d.ts +2 -2
  341. package/dist/store/candidates.js +4 -3
  342. package/dist/store/conflicts.js +30 -22
  343. package/dist/store/delete-and-batch.d.ts +11 -14
  344. package/dist/store/delete-and-batch.js +40 -91
  345. package/dist/store/entry-reads.d.ts +17 -25
  346. package/dist/store/entry-reads.js +59 -40
  347. package/dist/store/entry-row.d.ts +6 -24
  348. package/dist/store/entry-row.js +6 -24
  349. package/dist/store/entry-writes.d.ts +6 -7
  350. package/dist/store/entry-writes.js +13 -11
  351. package/dist/store/handoffs.d.ts +1 -1
  352. package/dist/store/handoffs.js +7 -10
  353. package/dist/store/index-and-stats.d.ts +2 -6
  354. package/dist/store/index-and-stats.js +4 -10
  355. package/dist/store/mirrors.d.ts +6 -19
  356. package/dist/store/mirrors.js +14 -39
  357. package/dist/store/open.js +9 -31
  358. package/dist/store/rows.d.ts +5 -11
  359. package/dist/store/rows.js +6 -11
  360. package/dist/store/search-rows.d.ts +17 -34
  361. package/dist/store/search-rows.js +34 -56
  362. package/dist/store/sessions.d.ts +4 -5
  363. package/dist/store/sessions.js +5 -6
  364. package/dist/store/summaries.d.ts +13 -17
  365. package/dist/store/summaries.js +26 -70
  366. package/dist/support-bundle.js +4 -8
  367. package/dist/tenant.d.ts +1 -5
  368. package/dist/token-ledger.d.ts +1 -1
  369. package/dist/token-ledger.js +3 -5
  370. package/dist/trace.js +1 -3
  371. package/dist/version.d.ts +1 -1
  372. package/dist/version.js +1 -1
  373. package/dist/working-memory.d.ts +1 -1
  374. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  375. package/extensions/openclaw-plugin/package.json +1 -1
  376. package/openclaw.plugin.json +1 -1
  377. package/package.json +1 -1
@@ -1,14 +1,14 @@
1
1
  import { type CommandContext } from './shared.js';
2
2
  export declare function cmdStatus(hippoRoot: string): void;
3
3
  /**
4
- * `hippo tokens [--days <n>] [--json] [--global]`: the token ledger
5
- * (ROADMAP TE0). Tokens of memory text handed to agents per surface, blocks
6
- * the per-prompt hook skipped as unchanged (TE2) and the tokens that saved,
4
+ * `hippo tokens [--days <n>] [--json] [--global]`: the token ledger.
5
+ * Tokens of memory text handed to agents per surface, blocks
6
+ * the per-prompt hook skipped as unchanged and the tokens that saved,
7
7
  * and the hook blocks' tokens later model calls re-read, counted when each session ends.
8
8
  * Counts are estimates (characters / 4), the same estimate every budget uses.
9
9
  */
10
10
  export declare function cmdTokens(hippoRoot: string, flags: Record<string, string | boolean | string[]>): void;
11
- /** `hippo failures [--days <n>] [--json] [--global]`: failed tool calls by outcome, and repeats across sessions (CD13). */
11
+ /** `hippo failures [--days <n>] [--json] [--global]`: failed tool calls by outcome, and repeats across sessions. */
12
12
  export declare function cmdFailures(hippoRoot: string, flags: Record<string, string | boolean | string[]>): void;
13
13
  export declare function handleCorrectionLatency({ hippoRoot, flags }: CommandContext): void;
14
14
  export declare function handleProvenance({ hippoRoot, flags }: CommandContext): void;
@@ -31,36 +31,7 @@ export function cmdStatus(hippoRoot) {
31
31
  const entries = loadAllEntries(hippoRoot);
32
32
  const stats = loadStats(hippoRoot);
33
33
  const now = evalNow();
34
- const byLayer = {
35
- [Layer.Buffer]: 0,
36
- [Layer.Episodic]: 0,
37
- [Layer.Semantic]: 0,
38
- [Layer.Trace]: 0,
39
- };
40
- const byConfidence = {
41
- verified: 0,
42
- observed: 0,
43
- inferred: 0,
44
- stale: 0,
45
- };
46
- let totalStrength = 0;
47
- let pinned = 0;
48
- let atRisk = 0; // strength < 0.2
49
- let agedOut = 0;
50
- for (const e of entries) {
51
- const s = calculateStrength(e, now);
52
- byLayer[e.layer] = (byLayer[e.layer] ?? 0) + 1;
53
- totalStrength += s;
54
- if (e.pinned)
55
- pinned++;
56
- if (s < 0.2)
57
- atRisk++;
58
- const facets = confidenceFacets(e, now);
59
- byConfidence[facets.tier] = (byConfidence[facets.tier] ?? 0) + 1;
60
- if (facets.agedOut)
61
- agedOut++;
62
- }
63
- const avgStrength = entries.length > 0 ? totalStrength / entries.length : 0;
34
+ const { byLayer, byConfidence, pinned, atRisk, agedOut, avgStrength } = tallyStatus(entries, now);
64
35
  console.log('Hippo Status');
65
36
  console.log('---------------------------');
66
37
  console.log(`Total memories: ${entries.length}`);
@@ -92,7 +63,44 @@ export function cmdStatus(hippoRoot) {
92
63
  else {
93
64
  console.log(`Last sleep: never`);
94
65
  }
95
- // Embedding status (provider-aware)
66
+ printEmbeddingStatus(hippoRoot, entries);
67
+ printPhysicsStatus(hippoRoot);
68
+ }
69
+ function tallyStatus(entries, now) {
70
+ const byLayer = {
71
+ [Layer.Buffer]: 0,
72
+ [Layer.Episodic]: 0,
73
+ [Layer.Semantic]: 0,
74
+ [Layer.Trace]: 0,
75
+ };
76
+ const byConfidence = {
77
+ verified: 0,
78
+ observed: 0,
79
+ inferred: 0,
80
+ stale: 0,
81
+ };
82
+ let totalStrength = 0;
83
+ let pinned = 0;
84
+ let atRisk = 0; // strength < 0.2
85
+ let agedOut = 0;
86
+ for (const e of entries) {
87
+ const s = calculateStrength(e, now);
88
+ byLayer[e.layer] = (byLayer[e.layer] ?? 0) + 1;
89
+ totalStrength += s;
90
+ if (e.pinned)
91
+ pinned++;
92
+ if (s < 0.2)
93
+ atRisk++;
94
+ const facets = confidenceFacets(e, now);
95
+ byConfidence[facets.tier] = (byConfidence[facets.tier] ?? 0) + 1;
96
+ if (facets.agedOut)
97
+ agedOut++;
98
+ }
99
+ const avgStrength = entries.length > 0 ? totalStrength / entries.length : 0;
100
+ return { byLayer, byConfidence, pinned, atRisk, agedOut, avgStrength };
101
+ }
102
+ // Embedding status (provider-aware)
103
+ function printEmbeddingStatus(hippoRoot, entries) {
96
104
  const embedProvider = (() => {
97
105
  try {
98
106
  return resolveEmbeddingProvider(hippoRoot);
@@ -105,42 +113,43 @@ export function cmdStatus(hippoRoot) {
105
113
  console.log('');
106
114
  if (!embedProvider) {
107
115
  console.log(`Embeddings: misconfigured (check embeddings.provider / apiBaseUrl), BM25 only`);
116
+ return;
117
+ }
118
+ const embeddingsDisabled = loadConfig(hippoRoot).embeddings.enabled === false;
119
+ const embAvail = embedProvider.isAvailable();
120
+ if (embeddingsDisabled) {
121
+ console.log(`Embeddings: disabled in config (embeddings.enabled = false), BM25 only`);
122
+ }
123
+ else if (embedProvider.kind === 'local') {
124
+ console.log(`Embeddings: ${embAvail ? `available [${embedProvider.id}]` : 'not installed (BM25 only)'}`);
125
+ }
126
+ else if (embAvail) {
127
+ console.log(`Embeddings: ${embedProvider.kind} api [${embedProvider.id}]`);
108
128
  }
109
129
  else {
110
- const embeddingsDisabled = loadConfig(hippoRoot).embeddings.enabled === false;
111
- const embAvail = embedProvider.isAvailable();
112
- if (embeddingsDisabled) {
113
- console.log(`Embeddings: disabled in config (embeddings.enabled = false), BM25 only`);
114
- }
115
- else if (embedProvider.kind === 'local') {
116
- console.log(`Embeddings: ${embAvail ? `available [${embedProvider.id}]` : 'not installed (BM25 only)'}`);
117
- }
118
- else if (embAvail) {
119
- console.log(`Embeddings: ${embedProvider.kind} api [${embedProvider.id}]`);
120
- }
121
- else {
122
- console.log(`Embeddings: ${embedProvider.kind} configured but ${embedProvider.keyEnv} not set (BM25 only)`);
123
- }
124
- // Show cached counts whenever vectors exist on disk (even when disabled or
125
- // the key was removed), so the user still sees what is already indexed.
126
- const embIndex = loadEmbeddingIndex(hippoRoot);
127
- if (embAvail || Object.keys(embIndex).length > 0) {
128
- const activeIds = new Set(entries.map((e) => e.id));
129
- const activeEmbedded = Object.keys(embIndex).filter((id) => activeIds.has(id)).length;
130
- const orphaned = Object.keys(embIndex).length - activeEmbedded;
131
- const dims = Object.values(embIndex)[0]?.length;
132
- let line = `Embedded: ${activeEmbedded}/${entries.length} memories`;
133
- if (dims)
134
- line += ` (${dims}-dim)`;
135
- if (orphaned > 0)
136
- line += ` (${orphaned} orphaned, run \`hippo embed\` to prune)`;
137
- console.log(line);
138
- if (embeddingModelRequiresReindex(hippoRoot, embedProvider.id, embIndex)) {
139
- console.log(` model changed, run \`hippo embed\` to reindex`);
140
- }
141
- }
130
+ console.log(`Embeddings: ${embedProvider.kind} configured but ${embedProvider.keyEnv} not set (BM25 only)`);
131
+ }
132
+ // Show cached counts whenever vectors exist on disk (even when disabled or
133
+ // the key was removed), so the user still sees what is already indexed.
134
+ const embIndex = loadEmbeddingIndex(hippoRoot);
135
+ if (!embAvail && Object.keys(embIndex).length === 0)
136
+ return;
137
+ const activeIds = new Set(entries.map((e) => e.id));
138
+ const activeEmbedded = Object.keys(embIndex).filter((id) => activeIds.has(id)).length;
139
+ const orphaned = Object.keys(embIndex).length - activeEmbedded;
140
+ const dims = Object.values(embIndex)[0]?.length;
141
+ let line = `Embedded: ${activeEmbedded}/${entries.length} memories`;
142
+ if (dims)
143
+ line += ` (${dims}-dim)`;
144
+ if (orphaned > 0)
145
+ line += ` (${orphaned} orphaned, run \`hippo embed\` to prune)`;
146
+ console.log(line);
147
+ if (embeddingModelRequiresReindex(hippoRoot, embedProvider.id, embIndex)) {
148
+ console.log(` model changed, run \`hippo embed\` to reindex`);
142
149
  }
143
- // Physics status
150
+ }
151
+ // Physics status
152
+ function printPhysicsStatus(hippoRoot) {
144
153
  try {
145
154
  const db = openHippoDb(hippoRoot);
146
155
  try {
@@ -150,13 +159,8 @@ export function cmdStatus(hippoRoot) {
150
159
  const physConfig = loadConfig(hippoRoot);
151
160
  const energy = computeSystemEnergy(particles, physConfig.physics.G_memory);
152
161
  let sumVelMag = 0;
153
- let maxVelMag = 0;
154
- for (const p of particles) {
155
- const mag = vecNorm(p.velocity);
156
- sumVelMag += mag;
157
- if (mag > maxVelMag)
158
- maxVelMag = mag;
159
- }
162
+ for (const p of particles)
163
+ sumVelMag += vecNorm(p.velocity);
160
164
  const avgVelMag = sumVelMag / particles.length;
161
165
  console.log('');
162
166
  console.log(`Physics: ${particles.length} particles, energy: ${fmt(energy.total, 4)} (KE: ${fmt(energy.kinetic, 4)}, PE: ${fmt(energy.potential, 4)}), avg vel: ${fmt(avgVelMag, 4)}`);
@@ -213,9 +217,9 @@ function cmdInspect(hippoRoot, id) {
213
217
  console.log(entry.content);
214
218
  }
215
219
  /**
216
- * `hippo tokens [--days <n>] [--json] [--global]`: the token ledger
217
- * (ROADMAP TE0). Tokens of memory text handed to agents per surface, blocks
218
- * the per-prompt hook skipped as unchanged (TE2) and the tokens that saved,
220
+ * `hippo tokens [--days <n>] [--json] [--global]`: the token ledger.
221
+ * Tokens of memory text handed to agents per surface, blocks
222
+ * the per-prompt hook skipped as unchanged and the tokens that saved,
219
223
  * and the hook blocks' tokens later model calls re-read, counted when each session ends.
220
224
  * Counts are estimates (characters / 4), the same estimate every budget uses.
221
225
  */
@@ -254,7 +258,7 @@ export function cmdTokens(hippoRoot, flags) {
254
258
  console.log(' Re-reads are counted for hook and compact-resume blocks when a session ends; other surfaces, and open or crashed sessions, show sent only.');
255
259
  console.log(" Re-reads usually bill at the provider's cached-input rate, a fraction of the full input price.");
256
260
  }
257
- /** `hippo failures [--days <n>] [--json] [--global]`: failed tool calls by outcome, and repeats across sessions (CD13). */
261
+ /** `hippo failures [--days <n>] [--json] [--global]`: failed tool calls by outcome, and repeats across sessions. */
258
262
  export function cmdFailures(hippoRoot, flags) {
259
263
  // The store the capture-error hook writes to; a report never creates one.
260
264
  const root = flags['global'] ? getGlobalRoot() : hookStoreRoot(hippoRoot);
@@ -289,7 +293,7 @@ export function cmdFailures(hippoRoot, flags) {
289
293
  for (const [label, count, note] of rows) {
290
294
  console.log(` ${label.padEnd(13)}${String(count).padStart(6)} ${note}`.trimEnd());
291
295
  }
292
- // Counts, not a rate: a share means little without a holdout arm to compare against (CD11).
296
+ // Counts, not a rate: a share means little without a holdout arm to compare against.
293
297
  if (summary.rated > 0) {
294
298
  const noSession = errors - summary.rated;
295
299
  const unrated = noSession > 0 ? ` ${noSession} more had no session id.` : '';
@@ -46,10 +46,8 @@ async function cmdWatch(command, hippoRoot) {
46
46
  entry.schema_fit = watchFit;
47
47
  entry.half_life_days = deriveHalfLife(loadConfig(hippoRoot).defaultHalfLifeDays, entry);
48
48
  entry.strength = calculateStrength(entry);
49
- // AT1 (plan §3 containment): mechanical content from a failed command — a
50
- // rejection-guard refusal here must not crash the watcher. Skip silently
51
- // (loud enough via the message below) and still exit with the wrapped
52
- // command's real exit code.
49
+ // A rejection-guard refusal of a failed command's output must not crash the watcher:
50
+ // skip with the message below and still exit with the wrapped command's real exit code.
53
51
  try {
54
52
  writeEntry(hippoRoot, entry);
55
53
  updateStats(hippoRoot, { remembered: 1 });
@@ -112,18 +110,8 @@ export function cmdImport(hippoRoot, args, flags) {
112
110
  ? [String(flags['tag'])]
113
111
  : [];
114
112
  const targetRoot = useGlobal ? getGlobalRoot() : hippoRoot;
115
- if (flags['agents']) {
116
- const opts = { machine: currentMachine(), dryRun };
117
- // A folder without a store of its own imports as session end would there, so its notes are not hidden.
118
- const report = useGlobal || isInitialized(hippoRoot)
119
- ? importForStore(useGlobal ? getGlobalRoot() : hippoRoot, opts)
120
- : importAtSessionEnd(process.cwd(), undefined, opts);
121
- for (const line of detailLines(report, dryRun))
122
- console.log(line);
123
- for (const warning of report.warnings)
124
- printError(`hippo: agent memories: ${warning}`);
125
- return;
126
- }
113
+ if (flags['agents'])
114
+ return importAgentMemories(hippoRoot, useGlobal, dryRun);
127
115
  if (useGlobal) {
128
116
  initGlobal();
129
117
  }
@@ -136,99 +124,35 @@ export function cmdImport(hippoRoot, args, flags) {
136
124
  extraTags,
137
125
  hippoRoot,
138
126
  };
139
- // K1 vault import: a FOLDER importer that mirrors the connector pattern
127
+ // Vault import: a FOLDER importer that mirrors the connector pattern
140
128
  // (kind='raw' + tag provenance + archiveRaw deletions), so it dispatches
141
129
  // separately from the single-file `importer` function-pointer slot below.
142
130
  // It writes through api.remember/archiveRaw which are tenant-scoped, so we
143
131
  // resolve the tenant and pass it through. --global is not supported for
144
132
  // vault import (the connector raw-archive path is tenant-local).
145
- if (flags['vault']) {
146
- const folderPath = String(flags['vault']);
147
- if (!fs.existsSync(folderPath) || !fs.statSync(folderPath).isDirectory()) {
148
- printError(`Vault folder not found (or not a directory): ${folderPath}`);
149
- process.exit(1);
150
- }
151
- if (useGlobal) {
152
- printError('hippo import --vault does not support --global (raw rows are tenant-local).');
153
- process.exit(1);
154
- }
155
- if (typeof flags['name'] !== 'string' || !flags['name'].trim()) {
156
- // --name is the vault identity key for the destructive source-deletion sync;
157
- // inferring it from the folder basename let same-basename vaults collide and
158
- // clobber each other (codex R10 P2). A valueless `--name` parses as boolean
159
- // true, and String(true) === "true" would silently import under vault:true:*
160
- // - reject a non-string so it fails fast instead (codex R11 P2).
161
- printError('hippo import --vault requires --name <vault> (a non-empty identity key for source-deletion sync).');
162
- process.exit(1);
163
- }
164
- if (flags['scope'] !== undefined && (typeof flags['scope'] !== 'string' || !flags['scope'].trim())) {
165
- // Same valueless-flag trap: a bare `--scope` must not become scope "true".
166
- // Example uses the source-prefixed private form, since a bare `private` scope
167
- // is NOT treated as private by recall and importVault rejects it (R13 P2).
168
- printError('hippo import --vault: --scope requires a value (e.g. --scope vault:private:notes).');
169
- process.exit(1);
170
- }
171
- const tenantId = resolveTenantId({});
172
- const vaultOptions = {
173
- ...importOptions,
174
- tenantId,
175
- name: flags['name'] ? String(flags['name']) : undefined,
176
- scope: flags['scope'] ? String(flags['scope']) : undefined,
177
- };
178
- const vaultResult = importVault(folderPath, vaultOptions);
179
- console.log(`\nImport Vault: ${folderPath}${dryRun ? ' (dry run - no writes)' : ''}`);
180
- console.log(` Notes found: ${vaultResult.total}`);
181
- console.log(` ${dryRun ? 'Would import: ' : 'Imported: '}${vaultResult.imported}`);
182
- console.log(` Skipped (unchanged): ${vaultResult.skipped}`);
183
- if ((vaultResult.rejected ?? 0) > 0) {
184
- console.log(` Rejected (tombstoned): ${vaultResult.rejected}`);
185
- }
186
- warnRedacted(vaultResult.redacted);
187
- console.log(` ${dryRun ? 'Would archive: ' : 'Archived (removed): '}${vaultResult.archived ?? 0}`);
188
- console.log(` Store: ${hippoRoot}`);
189
- // Batch producer, same contract as the single-file import below: vault rows
190
- // write through api.remember (which never embeds), so backfill them here.
191
- // Floating promise is deliberate; see the comment at the single-file site.
192
- if (!dryRun && vaultResult.imported >= 1) {
193
- void embedAll(hippoRoot).catch(() => { });
194
- }
195
- return;
196
- }
197
- // Determine which importer to use based on flag
198
- let filePath;
199
- let importer;
200
- let importerName = '';
201
- if (flags['chatgpt']) {
202
- filePath = String(flags['chatgpt']);
203
- importer = importChatGPT;
204
- importerName = 'ChatGPT';
205
- }
206
- else if (flags['claude']) {
207
- filePath = String(flags['claude']);
208
- importer = importClaude;
209
- importerName = 'Claude';
210
- }
211
- else if (flags['cursor']) {
212
- filePath = String(flags['cursor']);
213
- importer = importCursor;
214
- importerName = 'Cursor';
215
- }
216
- else if (flags['file']) {
217
- filePath = String(flags['file']);
218
- importer = importGenericFile;
219
- importerName = 'File';
220
- }
221
- else if (flags['markdown']) {
222
- filePath = String(flags['markdown']);
223
- importer = importMarkdown;
224
- importerName = 'Markdown';
225
- }
226
- else if (args[0]) {
227
- // Positional: try to auto-detect from extension
228
- filePath = args[0];
229
- importer = importGenericFile;
230
- importerName = 'File';
231
- }
133
+ if (flags['vault'])
134
+ return importVaultFolder(hippoRoot, flags, importOptions, useGlobal, dryRun);
135
+ importFromFile(targetRoot, args, flags, importOptions, useGlobal, dryRun);
136
+ }
137
+ // Determine which importer to use based on flag
138
+ function pickImporter(args, flags) {
139
+ if (flags['chatgpt'])
140
+ return { filePath: String(flags['chatgpt']), importer: importChatGPT, importerName: 'ChatGPT' };
141
+ if (flags['claude'])
142
+ return { filePath: String(flags['claude']), importer: importClaude, importerName: 'Claude' };
143
+ if (flags['cursor'])
144
+ return { filePath: String(flags['cursor']), importer: importCursor, importerName: 'Cursor' };
145
+ if (flags['file'])
146
+ return { filePath: String(flags['file']), importer: importGenericFile, importerName: 'File' };
147
+ if (flags['markdown'])
148
+ return { filePath: String(flags['markdown']), importer: importMarkdown, importerName: 'Markdown' };
149
+ // Positional: try to auto-detect from extension
150
+ if (args[0])
151
+ return { filePath: args[0], importer: importGenericFile, importerName: 'File' };
152
+ return { filePath: undefined, importer: undefined, importerName: '' };
153
+ }
154
+ function importFromFile(targetRoot, args, flags, importOptions, useGlobal, dryRun) {
155
+ const { filePath, importer, importerName } = pickImporter(args, flags);
232
156
  if (!filePath || !importer) {
233
157
  printError('Usage: hippo import <--chatgpt|--claude|--cursor|--file|--markdown|--vault> <path>, or hippo import --agents [--dry-run]');
234
158
  process.exit(1);
@@ -272,6 +196,65 @@ export function cmdImport(hippoRoot, args, flags) {
272
196
  console.log(` Store: ${storeLabel}`);
273
197
  }
274
198
  }
199
+ function importAgentMemories(hippoRoot, useGlobal, dryRun) {
200
+ const opts = { machine: currentMachine(), dryRun };
201
+ // A folder without a store of its own imports as session end would there, so its notes are not hidden.
202
+ const report = useGlobal || isInitialized(hippoRoot)
203
+ ? importForStore(useGlobal ? getGlobalRoot() : hippoRoot, opts)
204
+ : importAtSessionEnd(process.cwd(), undefined, opts);
205
+ for (const line of detailLines(report, dryRun))
206
+ console.log(line);
207
+ for (const warning of report.warnings)
208
+ printError(`hippo: agent memories: ${warning}`);
209
+ }
210
+ function importVaultFolder(hippoRoot, flags, importOptions, useGlobal, dryRun) {
211
+ const folderPath = String(flags['vault']);
212
+ if (!fs.existsSync(folderPath) || !fs.statSync(folderPath).isDirectory()) {
213
+ printError(`Vault folder not found (or not a directory): ${folderPath}`);
214
+ process.exit(1);
215
+ }
216
+ if (useGlobal) {
217
+ printError('hippo import --vault does not support --global (raw rows are tenant-local).');
218
+ process.exit(1);
219
+ }
220
+ if (typeof flags['name'] !== 'string' || !flags['name'].trim()) {
221
+ // --name keys the destructive source-deletion sync; a folder-basename default lets same-basename vaults clobber
222
+ // each other, and a valueless `--name` (boolean true) would silently import under vault:true:*.
223
+ printError('hippo import --vault requires --name <vault> (a non-empty identity key for source-deletion sync).');
224
+ process.exit(1);
225
+ }
226
+ if (flags['scope'] !== undefined && (typeof flags['scope'] !== 'string' || !flags['scope'].trim())) {
227
+ // Same valueless-flag trap: a bare `--scope` must not become scope "true".
228
+ // Example uses the source-prefixed private form, since a bare `private` scope
229
+ // is NOT treated as private by recall and importVault rejects it.
230
+ printError('hippo import --vault: --scope requires a value (e.g. --scope vault:private:notes).');
231
+ process.exit(1);
232
+ }
233
+ const tenantId = resolveTenantId({});
234
+ const vaultOptions = {
235
+ ...importOptions,
236
+ tenantId,
237
+ name: flags['name'] ? String(flags['name']) : undefined,
238
+ scope: flags['scope'] ? String(flags['scope']) : undefined,
239
+ };
240
+ const vaultResult = importVault(folderPath, vaultOptions);
241
+ console.log(`\nImport Vault: ${folderPath}${dryRun ? ' (dry run - no writes)' : ''}`);
242
+ console.log(` Notes found: ${vaultResult.total}`);
243
+ console.log(` ${dryRun ? 'Would import: ' : 'Imported: '}${vaultResult.imported}`);
244
+ console.log(` Skipped (unchanged): ${vaultResult.skipped}`);
245
+ if ((vaultResult.rejected ?? 0) > 0) {
246
+ console.log(` Rejected (tombstoned): ${vaultResult.rejected}`);
247
+ }
248
+ warnRedacted(vaultResult.redacted);
249
+ console.log(` ${dryRun ? 'Would archive: ' : 'Archived (removed): '}${vaultResult.archived ?? 0}`);
250
+ console.log(` Store: ${hippoRoot}`);
251
+ // Batch producer, same contract as the single-file import above: vault rows
252
+ // write through api.remember (which never embeds), so backfill them here.
253
+ // Floating promise is deliberate; see the comment at the single-file site.
254
+ if (!dryRun && vaultResult.imported >= 1) {
255
+ void embedAll(hippoRoot).catch(() => { });
256
+ }
257
+ }
275
258
  // ---------------------------------------------------------------------------
276
259
  // Promote command
277
260
  // ---------------------------------------------------------------------------
@@ -388,9 +371,7 @@ export function handleShare({ hippoRoot, args, flags }) {
388
371
  }
389
372
  }
390
373
  export function handlePeers({ flags }) {
391
- // D4 v1.12.10: tenant-scoped by default. --all-tenants restores the
392
- // pre-D4 host-wide view for the rare operator who genuinely wants
393
- // cross-tenant peer discovery.
374
+ // Tenant-scoped by default; --all-tenants gives the host-wide view for cross-tenant peer discovery.
394
375
  const allTenants = flags['all-tenants'] === true;
395
376
  const tenantScope = allTenants ? undefined : resolveTenantId({});
396
377
  const peers = listPeers(undefined, tenantScope);
package/dist/cli/usage.js CHANGED
@@ -1,5 +1,7 @@
1
1
  // Help text for every verb, keyed like the command table in cli.ts; no command logic lives here.
2
2
  import { TAIL_MAX_LINES } from '../support-bundle.js';
3
+ import { DEFAULT_LOCAL_BUMP, DEFAULT_RECALL_BUDGET } from '../search/types.js';
4
+ import { DEFAULT_ASSEMBLE_BUDGET } from '../api/assemble.js';
3
5
  export function printAuditPruneUsage() {
4
6
  console.log('hippo audit prune --older-than <Nd> [--dry-run] [--tenant <t>]');
5
7
  console.log(' --older-than <Nd> Delete audit_log rows with ts older than N days (e.g. 90d).');
@@ -102,7 +104,7 @@ export const VERB_USAGE = {
102
104
  --global Store in global store ($HIPPO_HOME or ~/.hippo/)`],
103
105
  recall: [`
104
106
  recall <query> Search and retrieve memories (local + global)
105
- --budget <n> Token budget for the whole printed block (default: 4000)
107
+ --budget <n> Token budget for the whole printed block (default: ${DEFAULT_RECALL_BUDGET})
106
108
  --min-results <n> Minimum results regardless of budget (default: 1)
107
109
  --json Output as JSON
108
110
  --why Show match reasons and source annotations
@@ -193,7 +195,7 @@ export const VERB_USAGE = {
193
195
  --json Output as JSON`],
194
196
  assemble: [`
195
197
  assemble --session <id> Build a session's chronological context window
196
- --budget N Token budget for the printed window (default 4000)
198
+ --budget N Token budget for the printed window (default ${DEFAULT_ASSEMBLE_BUDGET})
197
199
  --fresh-tail N Recent rows always kept verbatim (default 10)
198
200
  --no-summarize-older Disable older-row summary substitution
199
201
  --scope <s> Restrict to exact scope (default: deny *:private:*)
@@ -205,7 +207,7 @@ export const VERB_USAGE = {
205
207
  --pin Pin the new memory (default: pinned if the old one was)`],
206
208
  explain: [`
207
209
  explain <query> Show full score breakdown for each retrieved memory
208
- --budget <n> Token budget, counted as recall prints (default: 4000)
210
+ --budget <n> Token budget, counted as recall prints (default: ${DEFAULT_RECALL_BUDGET})
209
211
  --limit <n> Cap the number of results displayed
210
212
  --json Output as JSON
211
213
  --physics | --classic Force search mode (default: from config)
@@ -221,7 +223,7 @@ export const VERB_USAGE = {
221
223
  --no-mmr Disable MMR for this eval run
222
224
  --mmr-lambda <f> Override MMR lambda for this run
223
225
  --embedding-weight <f> Override cosine weight (default: 0.6)
224
- --local-bump <f> Local-over-global priority multiplier (default: 1.2)
226
+ --local-bump <f> Local-over-global priority multiplier (default: ${DEFAULT_LOCAL_BUMP})
225
227
  --equal-sources Shortcut for --local-bump 1.0
226
228
  --min-mrr <f> Exit non-zero if mean MRR falls below this
227
229
  --json Output full summary as JSON`],
@@ -393,8 +395,9 @@ export const VERB_USAGE = {
393
395
  Fold one project name into another (dry run unless --apply;
394
396
  writes a backup and one audit event first)
395
397
  projects repair [--apply]
396
- Re-tag merged rows older versions of sleep saved as user-global,
397
- by their parents' project (dry run unless --apply)`],
398
+ Set aside misfiled note imports, fold old project names into
399
+ their ids, re-tag merged rows (dry run unless --apply;
400
+ writes a backup and one audit event first)`],
398
401
  quarantine: [`
399
402
  quarantine [list] List memories a connector flagged as an instruction attempt, pending review
400
403
  --all Include approved and rejected rows too (default: pending only)
package/dist/cli.d.ts CHANGED
@@ -253,7 +253,7 @@ export declare const COMMANDS: {
253
253
  usage: string[];
254
254
  };
255
255
  hook: {
256
- run: ({ args, flags }: CommandContext) => Promise<void>;
256
+ run: ({ args }: CommandContext) => Promise<void>;
257
257
  usage: string[];
258
258
  };
259
259
  setup: {
package/dist/cli.js CHANGED
@@ -185,7 +185,7 @@ export function shouldAutoRepairCodexWrapper(currentCommand, flags) {
185
185
  // hook install codex` (a Codex update can restore the real binary over our
186
186
  // shim). Never first-installs — silently swapping the codex binary on routine
187
187
  // commands is a consent violation and reads as binary hijacking to
188
- // supply-chain scanners (issue #133).
188
+ // supply-chain scanners.
189
189
  function maybeRepairCodexWrapper(currentCommand, flags) {
190
190
  if (!shouldAutoRepairCodexWrapper(currentCommand, flags))
191
191
  return;
@@ -407,7 +407,7 @@ export const COMMANDS = {
407
407
  usage: VERB_USAGE.context,
408
408
  },
409
409
  hook: {
410
- run: async ({ args, flags }) => { (await import('./cli/setup.js')).cmdHook(args, flags); },
410
+ run: async ({ args }) => { (await import('./cli/setup.js')).cmdHook(args); },
411
411
  usage: VERB_USAGE.hook,
412
412
  },
413
413
  setup: {
@@ -579,13 +579,8 @@ async function main(command, args, flags, hippoRoot) {
579
579
  return;
580
580
  }
581
581
  maybeRepairCodexWrapper(command, flags);
582
- /** Global --scope well-formedness guard (v1.26.2). parseArgs stores a value-less
583
- * flag as boolean true; downstream the 14 consumer sites either coerced that to
584
- * the literal scope string 'true' (recall filter/unlock input, wm session scope,
585
- * the remember scope-tag dual-write) or silently dropped the user's scoping
586
- * intent (the remember envelope WRITE). Reject it once here, mirroring the
587
- * --hops value-less guard, so every current and future command - including the
588
- * thin-client dispatch relays - sees --scope only as a non-empty string. */
582
+ /** A value-less --scope parses as boolean true, which consumers coerced to the scope 'true' or dropped;
583
+ * reject it once here so every command, thin-client relays included, sees only a non-empty string. */
589
584
  if ('scope' in flags && (typeof flags['scope'] !== 'string' || !flags['scope'].trim())) {
590
585
  printError('--scope requires a non-empty value (e.g. --scope slack:private:C1).');
591
586
  process.exit(1);
@@ -25,8 +25,6 @@ export interface CompactionRecord {
25
25
  status: CompactionStatus;
26
26
  }
27
27
  export type Log = (message: string) => void;
28
- /** Where the session ran: rows written through the global store keep the project the session was in. */
29
- export declare function compactionOrigin(hippoRoot: string, cwd: string | null): string;
30
28
  interface ScrubbedSummary {
31
29
  summary: string;
32
30
  items: string[];
@@ -58,6 +56,8 @@ export interface ItemContext {
58
56
  recordId: string | null;
59
57
  sessionId: string;
60
58
  originProject: string;
59
+ /** Where the session ran, so rows held under the project's older folder name count too. */
60
+ cwd: string | null;
61
61
  items: string[];
62
62
  }
63
63
  /** Items that become rows, then the record `done`, in one transaction so two sessions cannot both insert one text. Mirrors after commit. */