@remnic/core 9.3.624 → 9.3.625

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 (261) hide show
  1. package/dist/access-cli.js +18 -16
  2. package/dist/access-cli.js.map +1 -1
  3. package/dist/access-http.d.ts +12 -5
  4. package/dist/access-http.js +10 -9
  5. package/dist/access-mcp.d.ts +5 -5
  6. package/dist/access-mcp.js +8 -8
  7. package/dist/access-schema.d.ts +5 -5
  8. package/dist/{access-service-CBNEKjzN.d.ts → access-service-C_sfOHsX.d.ts} +26 -3
  9. package/dist/access-service.d.ts +5 -5
  10. package/dist/access-service.js +7 -7
  11. package/dist/action-confidence.d.ts +1 -1
  12. package/dist/active-memory-bridge.d.ts +1 -1
  13. package/dist/active-recall.d.ts +1 -1
  14. package/dist/active-recall.js +2 -1
  15. package/dist/active-recall.js.map +1 -1
  16. package/dist/behavior-learner.d.ts +1 -1
  17. package/dist/behavior-signals.d.ts +1 -1
  18. package/dist/bootstrap.d.ts +4 -4
  19. package/dist/briefing.d.ts +1 -1
  20. package/dist/briefing.js +3 -3
  21. package/dist/buffer-surprise-report.d.ts +1 -1
  22. package/dist/buffer.d.ts +1 -1
  23. package/dist/calibration.d.ts +1 -1
  24. package/dist/causal-behavior.d.ts +1 -1
  25. package/dist/causal-consolidation.d.ts +1 -1
  26. package/dist/causal-consolidation.js +4 -4
  27. package/dist/{chunk-7TPH6UZL.js → chunk-2RHI3FGV.js} +540 -17
  28. package/dist/chunk-2RHI3FGV.js.map +1 -0
  29. package/dist/{chunk-GYTVOLNX.js → chunk-3MNBW7R7.js} +2 -2
  30. package/dist/{chunk-QFQQFX2H.js → chunk-3R2UZV3U.js} +2 -2
  31. package/dist/{chunk-O4UNM6OR.js → chunk-532VCWYW.js} +2 -2
  32. package/dist/{chunk-2UFQYU5F.js → chunk-57QXN2CS.js} +2 -2
  33. package/dist/chunk-7WV3F5DQ.js +22 -0
  34. package/dist/chunk-7WV3F5DQ.js.map +1 -0
  35. package/dist/{chunk-RKW6QR7W.js → chunk-AZ4RI3QD.js} +1461 -78
  36. package/dist/chunk-AZ4RI3QD.js.map +1 -0
  37. package/dist/{chunk-KQFQ3IS5.js → chunk-F3FY3D3S.js} +43 -7
  38. package/dist/chunk-F3FY3D3S.js.map +1 -0
  39. package/dist/{chunk-4R4KTDIE.js → chunk-FPNQF475.js} +1 -1
  40. package/dist/chunk-FPNQF475.js.map +1 -0
  41. package/dist/{chunk-UGEBPVNI.js → chunk-GE7Q7KXP.js} +2 -2
  42. package/dist/{chunk-GLWW3EJQ.js → chunk-KB4MFBF5.js} +3 -3
  43. package/dist/{chunk-5GOMXHLC.js → chunk-KKTXCFD7.js} +255 -1
  44. package/dist/chunk-KKTXCFD7.js.map +1 -0
  45. package/dist/{chunk-FH3PPO42.js → chunk-KVFYTRMV.js} +2 -2
  46. package/dist/{chunk-BNW5NJJH.js → chunk-LQYTQCXM.js} +2 -2
  47. package/dist/{chunk-AYHXQR53.js → chunk-MVQN73GT.js} +2 -2
  48. package/dist/{chunk-ZZPIJPPD.js → chunk-N5RGXWLQ.js} +2 -2
  49. package/dist/chunk-NDAH7BJ5.js +213 -0
  50. package/dist/chunk-NDAH7BJ5.js.map +1 -0
  51. package/dist/{chunk-R3OQGYOU.js → chunk-P2D2MM47.js} +2 -2
  52. package/dist/{chunk-PSUB67YB.js → chunk-PW6GURU3.js} +2 -2
  53. package/dist/{chunk-W3BKVM64.js → chunk-QDV6VAD4.js} +2 -2
  54. package/dist/{chunk-3QSU4NFF.js → chunk-QHXW3LZV.js} +3 -3
  55. package/dist/{chunk-I6UCUHLK.js → chunk-SHV5Y2WU.js} +182 -3
  56. package/dist/chunk-SHV5Y2WU.js.map +1 -0
  57. package/dist/{chunk-OZXVGYGZ.js → chunk-STDAAGH7.js} +2 -2
  58. package/dist/{chunk-FMGWXIES.js → chunk-TZDSNIRO.js} +5 -5
  59. package/dist/{chunk-2L54V4ZO.js → chunk-UELS6WWF.js} +2 -2
  60. package/dist/{chunk-PJGB7XRR.js → chunk-UGHUNQ74.js} +502 -134
  61. package/dist/chunk-UGHUNQ74.js.map +1 -0
  62. package/dist/{chunk-FG76RDVI.js → chunk-Y3TMFC6I.js} +136 -4
  63. package/dist/chunk-Y3TMFC6I.js.map +1 -0
  64. package/dist/{chunk-BPSGLMQ4.js → chunk-YQNADJCT.js} +2 -2
  65. package/dist/{cli-Cw729yLf.d.ts → cli-EZv6YE6_.d.ts} +3 -3
  66. package/dist/cli.d.ts +6 -6
  67. package/dist/cli.js +23 -21
  68. package/dist/compounding/engine.d.ts +1 -1
  69. package/dist/compounding/engine.js +3 -3
  70. package/dist/compounding/preference-consolidator.d.ts +1 -1
  71. package/dist/compression-optimizer.d.ts +1 -1
  72. package/dist/config.d.ts +1 -1
  73. package/dist/config.js +2 -1
  74. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  75. package/dist/connectors/codex-materialize-runner.js +3 -3
  76. package/dist/connectors/codex-materialize.d.ts +1 -1
  77. package/dist/connectors/index.d.ts +1 -1
  78. package/dist/connectors/index.js +3 -3
  79. package/dist/consolidation-provenance-check.d.ts +1 -1
  80. package/dist/consolidation-undo.d.ts +1 -1
  81. package/dist/contradiction/index.d.ts +2 -2
  82. package/dist/conversation-index/backend.d.ts +1 -1
  83. package/dist/conversation-index/chunker.d.ts +1 -1
  84. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  85. package/dist/conversation-index/indexer.d.ts +1 -1
  86. package/dist/conversation-index/search.d.ts +1 -1
  87. package/dist/day-summary.d.ts +1 -1
  88. package/dist/delinearize.d.ts +1 -1
  89. package/dist/direct-answer-wiring.d.ts +1 -1
  90. package/dist/direct-answer.d.ts +1 -1
  91. package/dist/embedding-fallback.d.ts +1 -1
  92. package/dist/enrichment/index.d.ts +1 -1
  93. package/dist/entity-retrieval.d.ts +1 -1
  94. package/dist/entity-retrieval.js +3 -3
  95. package/dist/entity-schema.d.ts +1 -1
  96. package/dist/explicit-capture.d.ts +4 -4
  97. package/dist/extraction-judge-telemetry.d.ts +1 -1
  98. package/dist/extraction-judge-training.d.ts +1 -1
  99. package/dist/extraction-judge.d.ts +1 -1
  100. package/dist/extraction.d.ts +1 -1
  101. package/dist/fallback-llm.d.ts +1 -1
  102. package/dist/identity-continuity.d.ts +1 -1
  103. package/dist/importance.d.ts +1 -1
  104. package/dist/index.d.ts +307 -9
  105. package/dist/index.js +155 -29
  106. package/dist/index.js.map +1 -1
  107. package/dist/intent.d.ts +1 -1
  108. package/dist/lcm/engine.d.ts +1 -1
  109. package/dist/lcm/index.d.ts +1 -1
  110. package/dist/lcm/tools.d.ts +1 -1
  111. package/dist/lifecycle.d.ts +1 -1
  112. package/dist/live-connectors-runner.d.ts +1 -1
  113. package/dist/local-llm.d.ts +1 -1
  114. package/dist/maintenance/memory-governance.d.ts +1 -1
  115. package/dist/maintenance/memory-governance.js +3 -3
  116. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
  117. package/dist/maintenance/rebuild-memory-projection.js +4 -4
  118. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  119. package/dist/memory-action-policy.d.ts +1 -1
  120. package/dist/memory-cache.d.ts +1 -1
  121. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  122. package/dist/memory-projection-store.d.ts +1 -1
  123. package/dist/memory-provenance.d.ts +1 -1
  124. package/dist/memory-worth-outcomes.d.ts +1 -1
  125. package/dist/models-json.d.ts +1 -1
  126. package/dist/namespaces/migrate.d.ts +1 -1
  127. package/dist/namespaces/migrate.js +4 -4
  128. package/dist/namespaces/principal.d.ts +1 -1
  129. package/dist/namespaces/search.d.ts +1 -1
  130. package/dist/namespaces/storage.d.ts +1 -1
  131. package/dist/namespaces/storage.js +3 -3
  132. package/dist/native-knowledge.d.ts +1 -1
  133. package/dist/operator-toolkit.d.ts +1 -1
  134. package/dist/operator-toolkit.js +8 -7
  135. package/dist/{orchestrator-CqWOjfgl.d.ts → orchestrator-CEycaY3M.d.ts} +361 -4
  136. package/dist/orchestrator.d.ts +4 -4
  137. package/dist/orchestrator.js +13 -11
  138. package/dist/patterns-cli.d.ts +1 -1
  139. package/dist/policy-runtime.d.ts +1 -1
  140. package/dist/qmd-recall-cache.d.ts +1 -1
  141. package/dist/qmd.d.ts +1 -1
  142. package/dist/recall-disclosure-escalation.d.ts +1 -1
  143. package/dist/recall-explain-renderer.d.ts +1 -1
  144. package/dist/recall-explain-renderer.js +3 -3
  145. package/dist/recall-planner-llm.d.ts +1 -1
  146. package/dist/recall-state.d.ts +1 -1
  147. package/dist/recall-tag-filter.d.ts +1 -1
  148. package/dist/recall-xray-cli.d.ts +1 -1
  149. package/dist/recall-xray-cli.js +4 -4
  150. package/dist/recall-xray-renderer.d.ts +1 -1
  151. package/dist/recall-xray-renderer.js +3 -3
  152. package/dist/recall-xray.d.ts +1 -1
  153. package/dist/recall-xray.js +2 -2
  154. package/dist/resolve-auth-token.d.ts +1 -1
  155. package/dist/resume-bundles.js +3 -2
  156. package/dist/retrieval-agents.d.ts +1 -1
  157. package/dist/retrieval-tiers.d.ts +1 -1
  158. package/dist/routing/engine.d.ts +1 -1
  159. package/dist/routing/store.d.ts +1 -1
  160. package/dist/schemas.d.ts +10 -10
  161. package/dist/search/embed-helper.d.ts +1 -1
  162. package/dist/search/factory.d.ts +1 -1
  163. package/dist/search/index.d.ts +1 -1
  164. package/dist/search/lancedb-backend.d.ts +1 -1
  165. package/dist/search/meilisearch-backend.d.ts +1 -1
  166. package/dist/search/noop-backend.d.ts +1 -1
  167. package/dist/search/orama-backend.d.ts +1 -1
  168. package/dist/search/port.d.ts +1 -1
  169. package/dist/search/remote-backend.d.ts +1 -1
  170. package/dist/{semantic-SLAa_prH.d.ts → semantic-DJR8_DMQ.d.ts} +1 -1
  171. package/dist/{semantic-consolidation-4HkHWgeI.d.ts → semantic-consolidation-FbhPeJjB.d.ts} +1 -1
  172. package/dist/semantic-consolidation.d.ts +2 -2
  173. package/dist/semantic-consolidation.js +4 -4
  174. package/dist/semantic-rule-promotion.js +3 -3
  175. package/dist/semantic-rule-verifier.d.ts +1 -1
  176. package/dist/semantic-rule-verifier.js +3 -3
  177. package/dist/session-observer-bands.d.ts +1 -1
  178. package/dist/session-observer-state.d.ts +1 -1
  179. package/dist/shared-context/manager.d.ts +5 -5
  180. package/dist/signal.d.ts +1 -1
  181. package/dist/storage.d.ts +19 -1
  182. package/dist/storage.js +2 -2
  183. package/dist/summarizer.d.ts +1 -1
  184. package/dist/summary-snapshot.d.ts +1 -1
  185. package/dist/temporal-supersession.d.ts +1 -1
  186. package/dist/temporal-validity.d.ts +1 -1
  187. package/dist/threading.d.ts +1 -1
  188. package/dist/tier-migration.d.ts +1 -1
  189. package/dist/tier-routing.d.ts +1 -1
  190. package/dist/topics.d.ts +1 -1
  191. package/dist/transcript.d.ts +1 -1
  192. package/dist/types-D5VRAI04.d.ts +3134 -0
  193. package/dist/types.d.ts +3 -2862
  194. package/dist/types.js +1 -1
  195. package/dist/utility-runtime.d.ts +1 -1
  196. package/dist/verified-recall.js +3 -3
  197. package/package.json +1 -1
  198. package/src/access-http.ts +167 -0
  199. package/src/access-mcp.ts +198 -0
  200. package/src/access-service.ts +65 -0
  201. package/src/cli.ts +187 -0
  202. package/src/config.ts +7 -0
  203. package/src/index.ts +7 -0
  204. package/src/orchestrator.ts +42 -0
  205. package/src/storage.ts +106 -0
  206. package/src/types.ts +5 -0
  207. package/src/wearables/cleanup.test.ts +134 -0
  208. package/src/wearables/cleanup.ts +188 -0
  209. package/src/wearables/cli.test.ts +170 -0
  210. package/src/wearables/cli.ts +441 -0
  211. package/src/wearables/config.test.ts +143 -0
  212. package/src/wearables/config.ts +332 -0
  213. package/src/wearables/corrections.test.ts +118 -0
  214. package/src/wearables/corrections.ts +211 -0
  215. package/src/wearables/day-store.test.ts +143 -0
  216. package/src/wearables/day-store.ts +238 -0
  217. package/src/wearables/errors.test.ts +32 -0
  218. package/src/wearables/errors.ts +29 -0
  219. package/src/wearables/index.ts +114 -0
  220. package/src/wearables/memory-gen.test.ts +342 -0
  221. package/src/wearables/memory-gen.ts +413 -0
  222. package/src/wearables/pipeline.test.ts +608 -0
  223. package/src/wearables/pipeline.ts +519 -0
  224. package/src/wearables/redaction.test.ts +94 -0
  225. package/src/wearables/redaction.ts +156 -0
  226. package/src/wearables/registry.test.ts +62 -0
  227. package/src/wearables/registry.ts +133 -0
  228. package/src/wearables/service.test.ts +425 -0
  229. package/src/wearables/service.ts +691 -0
  230. package/src/wearables/speakers.test.ts +110 -0
  231. package/src/wearables/speakers.ts +174 -0
  232. package/src/wearables/storage-io.test.ts +105 -0
  233. package/src/wearables/sync-state.test.ts +134 -0
  234. package/src/wearables/sync-state.ts +186 -0
  235. package/src/wearables/types.ts +285 -0
  236. package/dist/chunk-4R4KTDIE.js.map +0 -1
  237. package/dist/chunk-5GOMXHLC.js.map +0 -1
  238. package/dist/chunk-7TPH6UZL.js.map +0 -1
  239. package/dist/chunk-FG76RDVI.js.map +0 -1
  240. package/dist/chunk-I6UCUHLK.js.map +0 -1
  241. package/dist/chunk-KQFQ3IS5.js.map +0 -1
  242. package/dist/chunk-PJGB7XRR.js.map +0 -1
  243. package/dist/chunk-RKW6QR7W.js.map +0 -1
  244. /package/dist/{chunk-GYTVOLNX.js.map → chunk-3MNBW7R7.js.map} +0 -0
  245. /package/dist/{chunk-QFQQFX2H.js.map → chunk-3R2UZV3U.js.map} +0 -0
  246. /package/dist/{chunk-O4UNM6OR.js.map → chunk-532VCWYW.js.map} +0 -0
  247. /package/dist/{chunk-2UFQYU5F.js.map → chunk-57QXN2CS.js.map} +0 -0
  248. /package/dist/{chunk-UGEBPVNI.js.map → chunk-GE7Q7KXP.js.map} +0 -0
  249. /package/dist/{chunk-GLWW3EJQ.js.map → chunk-KB4MFBF5.js.map} +0 -0
  250. /package/dist/{chunk-FH3PPO42.js.map → chunk-KVFYTRMV.js.map} +0 -0
  251. /package/dist/{chunk-BNW5NJJH.js.map → chunk-LQYTQCXM.js.map} +0 -0
  252. /package/dist/{chunk-AYHXQR53.js.map → chunk-MVQN73GT.js.map} +0 -0
  253. /package/dist/{chunk-ZZPIJPPD.js.map → chunk-N5RGXWLQ.js.map} +0 -0
  254. /package/dist/{chunk-R3OQGYOU.js.map → chunk-P2D2MM47.js.map} +0 -0
  255. /package/dist/{chunk-PSUB67YB.js.map → chunk-PW6GURU3.js.map} +0 -0
  256. /package/dist/{chunk-W3BKVM64.js.map → chunk-QDV6VAD4.js.map} +0 -0
  257. /package/dist/{chunk-3QSU4NFF.js.map → chunk-QHXW3LZV.js.map} +0 -0
  258. /package/dist/{chunk-OZXVGYGZ.js.map → chunk-STDAAGH7.js.map} +0 -0
  259. /package/dist/{chunk-FMGWXIES.js.map → chunk-TZDSNIRO.js.map} +0 -0
  260. /package/dist/{chunk-2L54V4ZO.js.map → chunk-UELS6WWF.js.map} +0 -0
  261. /package/dist/{chunk-BPSGLMQ4.js.map → chunk-YQNADJCT.js.map} +0 -0
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-LMDRGRJ2.js";
12
12
  import {
13
13
  parseConfig
14
- } from "./chunk-5GOMXHLC.js";
14
+ } from "./chunk-KKTXCFD7.js";
15
15
  import {
16
16
  resolveObjectiveStateStoreDir,
17
17
  validateObjectiveStateSnapshot
@@ -268,4 +268,4 @@ export {
268
268
  recordResumeBundle,
269
269
  getResumeBundleStatus
270
270
  };
271
- //# sourceMappingURL=chunk-FH3PPO42.js.map
271
+ //# sourceMappingURL=chunk-KVFYTRMV.js.map
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  compareEntityTimestamps,
6
6
  normalizeEntityName
7
- } from "./chunk-PJGB7XRR.js";
7
+ } from "./chunk-UGHUNQ74.js";
8
8
  import {
9
9
  sanitizeMemoryContent
10
10
  } from "./chunk-FVQJYWH7.js";
@@ -677,4 +677,4 @@ export {
677
677
  entityIndexVersion,
678
678
  entityRecentTranscriptLookbackHours
679
679
  };
680
- //# sourceMappingURL=chunk-BNW5NJJH.js.map
680
+ //# sourceMappingURL=chunk-LQYTQCXM.js.map
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  ALL_CATEGORY_DIRS,
6
6
  NamespaceStorageRouter
7
- } from "./chunk-W3BKVM64.js";
7
+ } from "./chunk-QDV6VAD4.js";
8
8
  import {
9
9
  namespaceIdentityFromToken,
10
10
  namespaceIdentityToken
@@ -202,4 +202,4 @@ export {
202
202
  verifyNamespaces,
203
203
  runNamespaceMigration
204
204
  };
205
- //# sourceMappingURL=chunk-AYHXQR53.js.map
205
+ //# sourceMappingURL=chunk-MVQN73GT.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  StorageManager
3
- } from "./chunk-PJGB7XRR.js";
3
+ } from "./chunk-UGHUNQ74.js";
4
4
 
5
5
  // src/semantic-rule-promotion.ts
6
6
  import { createHash, randomUUID } from "crypto";
@@ -529,4 +529,4 @@ export {
529
529
  setSemanticRulePromotionTestHooks,
530
530
  promoteSemanticRuleFromMemory
531
531
  };
532
- //# sourceMappingURL=chunk-ZZPIJPPD.js.map
532
+ //# sourceMappingURL=chunk-N5RGXWLQ.js.map
@@ -0,0 +1,213 @@
1
+ // src/wearables/corrections.ts
2
+ import { promises as fsPromises } from "fs";
3
+ import * as path from "path";
4
+ var MAX_PATTERN_LENGTH = 256;
5
+ function escapeRegExp(value) {
6
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7
+ }
8
+ function compileCorrectionRule(rule, label) {
9
+ if (typeof rule.match !== "string" || rule.match.length === 0) {
10
+ throw new Error(`${label}: match must be a non-empty string`);
11
+ }
12
+ if (rule.match.length > MAX_PATTERN_LENGTH) {
13
+ throw new Error(
14
+ `${label}: match exceeds ${MAX_PATTERN_LENGTH} characters \u2014 correction patterns must stay short`
15
+ );
16
+ }
17
+ if (typeof rule.replace !== "string") {
18
+ throw new Error(`${label}: replace must be a string`);
19
+ }
20
+ const flags = rule.caseInsensitive === false ? "g" : "gi";
21
+ let pattern;
22
+ if (rule.regex === true) {
23
+ try {
24
+ pattern = new RegExp(rule.match, flags);
25
+ } catch (err) {
26
+ throw new Error(
27
+ `${label}: match is not a valid regular expression: ${err instanceof Error ? err.message : String(err)}`
28
+ );
29
+ }
30
+ } else {
31
+ const escaped = escapeRegExp(rule.match);
32
+ const leading = /^[\p{L}\p{N}_]/u.test(rule.match) ? "\\b" : "";
33
+ const trailing = /[\p{L}\p{N}_]$/u.test(rule.match) ? "\\b" : "";
34
+ pattern = new RegExp(`${leading}${escaped}${trailing}`, flags);
35
+ }
36
+ if (pattern.test("")) {
37
+ throw new Error(
38
+ `${label}: pattern matches the empty string and would corrupt every transcript`
39
+ );
40
+ }
41
+ pattern.lastIndex = 0;
42
+ return { rule, pattern };
43
+ }
44
+ function compileCorrectionRules(rules, labelPrefix) {
45
+ return rules.map(
46
+ (rule, index) => compileCorrectionRule(rule, `${labelPrefix}[${index}]`)
47
+ );
48
+ }
49
+ function applyCorrections(text, rules, sourceId) {
50
+ let applied = 0;
51
+ let result = text;
52
+ for (const { rule, pattern } of rules) {
53
+ if (Array.isArray(rule.sources) && rule.sources.length > 0 && !rule.sources.includes(sourceId)) {
54
+ continue;
55
+ }
56
+ pattern.lastIndex = 0;
57
+ result = result.replace(pattern, () => {
58
+ applied += 1;
59
+ return rule.replace;
60
+ });
61
+ }
62
+ return { text: result, applied };
63
+ }
64
+ function correctionsFilePath(memoryDir) {
65
+ return path.join(memoryDir, "state", "wearables", "corrections.json");
66
+ }
67
+ async function loadCorrectionsFile(memoryDir) {
68
+ const filePath = correctionsFilePath(memoryDir);
69
+ let raw;
70
+ try {
71
+ raw = await fsPromises.readFile(filePath, "utf-8");
72
+ } catch (err) {
73
+ if (err.code === "ENOENT") return [];
74
+ throw err;
75
+ }
76
+ let parsed;
77
+ try {
78
+ parsed = JSON.parse(raw);
79
+ } catch (err) {
80
+ throw new Error(
81
+ `wearables corrections file is not valid JSON (state/wearables/corrections.json): ${err instanceof Error ? err.message : String(err)}`
82
+ );
83
+ }
84
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || !Array.isArray(parsed.rules)) {
85
+ throw new Error(
86
+ 'wearables corrections file has an unexpected shape (state/wearables/corrections.json); expected {"version":1,"rules":[...]}'
87
+ );
88
+ }
89
+ const rules = parsed.rules;
90
+ compileCorrectionRules(rules, "state corrections");
91
+ return rules;
92
+ }
93
+ async function saveCorrectionsFile(memoryDir, rules) {
94
+ compileCorrectionRules(rules, "state corrections");
95
+ const filePath = correctionsFilePath(memoryDir);
96
+ await fsPromises.mkdir(path.dirname(filePath), { recursive: true });
97
+ const payload = { version: 1, rules };
98
+ const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now().toString(36)}`;
99
+ await fsPromises.writeFile(
100
+ tmpPath,
101
+ `${JSON.stringify(payload, null, 2)}
102
+ `,
103
+ "utf-8"
104
+ );
105
+ try {
106
+ await fsPromises.rename(tmpPath, filePath);
107
+ } catch (err) {
108
+ await fsPromises.unlink(tmpPath).catch(() => void 0);
109
+ throw err;
110
+ }
111
+ }
112
+
113
+ // src/wearables/redaction.ts
114
+ var REDACTION_PLACEHOLDER = "[redacted]";
115
+ var BUILT_IN_PATTERNS = [
116
+ /\b\d{3}-\d{2}-\d{4}\b/g,
117
+ // Starts and ENDS on a digit so a trailing separator is never
118
+ // consumed (replacing it would glue the placeholder to the next word).
119
+ /\b\d(?:[ -]?\d){12,18}\b/g
120
+ ];
121
+ var CARD_MIN_DIGITS = 13;
122
+ function redactText(text, userPatterns) {
123
+ let redactions = 0;
124
+ let result = text;
125
+ result = result.replace(BUILT_IN_PATTERNS[0], () => {
126
+ redactions += 1;
127
+ return REDACTION_PLACEHOLDER;
128
+ });
129
+ result = result.replace(BUILT_IN_PATTERNS[1], (match) => {
130
+ const digits = match.replace(/\D/g, "");
131
+ if (digits.length < CARD_MIN_DIGITS || digits.length > 19) {
132
+ return match;
133
+ }
134
+ redactions += 1;
135
+ return REDACTION_PLACEHOLDER;
136
+ });
137
+ for (const pattern of userPatterns) {
138
+ result = result.replace(pattern, () => {
139
+ redactions += 1;
140
+ return REDACTION_PLACEHOLDER;
141
+ });
142
+ }
143
+ return { text: result, redactions };
144
+ }
145
+ function compileRedactionPatterns(patterns) {
146
+ return patterns.map((pattern, index) => {
147
+ if (typeof pattern !== "string" || pattern.trim().length === 0) {
148
+ throw new Error(
149
+ `wearables.redactionPatterns[${index}] must be a non-empty string`
150
+ );
151
+ }
152
+ if (pattern.length > 256) {
153
+ throw new Error(
154
+ `wearables.redactionPatterns[${index}] exceeds 256 characters \u2014 redaction patterns must stay short`
155
+ );
156
+ }
157
+ try {
158
+ return new RegExp(pattern, "gi");
159
+ } catch (err) {
160
+ throw new Error(
161
+ `wearables.redactionPatterns[${index}] is not a valid regular expression: ${err instanceof Error ? err.message : String(err)}`
162
+ );
163
+ }
164
+ });
165
+ }
166
+ var OFF_THE_RECORD = /\boff\s+the\s+record\b/i;
167
+ var BACK_ON_THE_RECORD = /\b(?:back\s+)?on\s+the\s+record\b/i;
168
+ function applyOffTheRecord(conversation) {
169
+ let offRecord = false;
170
+ let droppedSegments = 0;
171
+ const segments = [];
172
+ for (const segment of conversation.segments) {
173
+ if (!offRecord && OFF_THE_RECORD.test(segment.text)) {
174
+ offRecord = true;
175
+ segments.push({
176
+ ...segment,
177
+ text: "[off the record \u2014 segment elided]"
178
+ });
179
+ continue;
180
+ }
181
+ if (offRecord) {
182
+ if (BACK_ON_THE_RECORD.test(segment.text)) {
183
+ offRecord = false;
184
+ segments.push({
185
+ ...segment,
186
+ text: "[back on the record]"
187
+ });
188
+ } else {
189
+ droppedSegments += 1;
190
+ }
191
+ continue;
192
+ }
193
+ segments.push(segment);
194
+ }
195
+ return {
196
+ conversation: { ...conversation, segments },
197
+ droppedSegments
198
+ };
199
+ }
200
+
201
+ export {
202
+ compileCorrectionRule,
203
+ compileCorrectionRules,
204
+ applyCorrections,
205
+ correctionsFilePath,
206
+ loadCorrectionsFile,
207
+ saveCorrectionsFile,
208
+ REDACTION_PLACEHOLDER,
209
+ redactText,
210
+ compileRedactionPatterns,
211
+ applyOffTheRecord
212
+ };
213
+ //# sourceMappingURL=chunk-NDAH7BJ5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/wearables/corrections.ts","../src/wearables/redaction.ts"],"sourcesContent":["/**\n * Wearable transcript corrections — user-specific replacement rules.\n *\n * ASR engines consistently mishear the same proper nouns for the same\n * person (\"remnick\" for \"Remnic\", a colleague's name, product jargon).\n * Rules come from two places, merged at sync time:\n *\n * 1. `wearables.corrections` in plugin config (declarative, versioned\n * with the operator's config).\n * 2. A CLI-managed rules file at `state/wearables/corrections.json`\n * (added interactively via `remnic wearables corrections add`).\n *\n * Literal rules are regex-escaped before compilation and replacements\n * are applied via a function (never a replacement string) so `$` in\n * either side can't corrupt output.\n */\n\nimport { promises as fsPromises } from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport type { WearableCorrectionRule } from \"./types.js\";\n\nexport interface CompiledCorrectionRule {\n rule: WearableCorrectionRule;\n pattern: RegExp;\n}\n\nexport interface CorrectionApplication {\n text: string;\n applied: number;\n}\n\n/** Hard cap on rule pattern length (bounds hostile/pathological regexes). */\nconst MAX_PATTERN_LENGTH = 256;\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Validate and compile a correction rule. Throws a descriptive error on\n * invalid input (empty match, regex that doesn't compile, regex that\n * matches the empty string) — callers surface this at config parse or\n * CLI time rather than skipping the rule silently.\n */\nexport function compileCorrectionRule(\n rule: WearableCorrectionRule,\n label: string,\n): CompiledCorrectionRule {\n if (typeof rule.match !== \"string\" || rule.match.length === 0) {\n throw new Error(`${label}: match must be a non-empty string`);\n }\n if (rule.match.length > MAX_PATTERN_LENGTH) {\n throw new Error(\n `${label}: match exceeds ${MAX_PATTERN_LENGTH} characters — correction patterns must stay short`,\n );\n }\n if (typeof rule.replace !== \"string\") {\n throw new Error(`${label}: replace must be a string`);\n }\n const flags = rule.caseInsensitive === false ? \"g\" : \"gi\";\n let pattern: RegExp;\n if (rule.regex === true) {\n try {\n // Operator-supplied regexes are the documented feature here\n // (rules live in the operator's own config / state file, never in\n // request input); the length cap above bounds pathological\n // patterns. CodeQL js/regex-injection is dismissed by design for\n // this site.\n pattern = new RegExp(rule.match, flags);\n } catch (err) {\n throw new Error(\n `${label}: match is not a valid regular expression: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n } else {\n // Literal rules match on word boundaries when both edges of the\n // match are word characters, so \"remnick\" doesn't fire inside\n // \"remnickson\" unless the user opts into regex mode.\n const escaped = escapeRegExp(rule.match);\n const leading = /^[\\p{L}\\p{N}_]/u.test(rule.match) ? \"\\\\b\" : \"\";\n const trailing = /[\\p{L}\\p{N}_]$/u.test(rule.match) ? \"\\\\b\" : \"\";\n pattern = new RegExp(`${leading}${escaped}${trailing}`, flags);\n }\n if (pattern.test(\"\")) {\n throw new Error(\n `${label}: pattern matches the empty string and would corrupt every transcript`,\n );\n }\n pattern.lastIndex = 0;\n return { rule, pattern };\n}\n\n/** Compile a rule list, labeling errors with their index. */\nexport function compileCorrectionRules(\n rules: WearableCorrectionRule[],\n labelPrefix: string,\n): CompiledCorrectionRule[] {\n return rules.map((rule, index) =>\n compileCorrectionRule(rule, `${labelPrefix}[${index}]`),\n );\n}\n\n/** Apply every applicable rule to a piece of transcript text. */\nexport function applyCorrections(\n text: string,\n rules: CompiledCorrectionRule[],\n sourceId: string,\n): CorrectionApplication {\n let applied = 0;\n let result = text;\n for (const { rule, pattern } of rules) {\n if (\n Array.isArray(rule.sources) &&\n rule.sources.length > 0 &&\n !rule.sources.includes(sourceId)\n ) {\n continue;\n }\n pattern.lastIndex = 0;\n result = result.replace(pattern, () => {\n applied += 1;\n // Replacement via function: `$` in rule.replace stays literal.\n return rule.replace;\n });\n }\n return { text: result, applied };\n}\n\n// ---------------------------------------------------------------------------\n// CLI-managed rules file\n// ---------------------------------------------------------------------------\n\ninterface CorrectionsFileShape {\n version: 1;\n rules: WearableCorrectionRule[];\n}\n\nexport function correctionsFilePath(memoryDir: string): string {\n return path.join(memoryDir, \"state\", \"wearables\", \"corrections.json\");\n}\n\n/**\n * Load CLI-managed correction rules. A missing file means no rules; a\n * malformed file throws (operators should know their corrections are\n * not being applied rather than silently losing them).\n */\nexport async function loadCorrectionsFile(\n memoryDir: string,\n): Promise<WearableCorrectionRule[]> {\n const filePath = correctionsFilePath(memoryDir);\n let raw: string;\n try {\n raw = await fsPromises.readFile(filePath, \"utf-8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw err;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw new Error(\n `wearables corrections file is not valid JSON (state/wearables/corrections.json): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n Array.isArray(parsed) ||\n !Array.isArray((parsed as CorrectionsFileShape).rules)\n ) {\n throw new Error(\n 'wearables corrections file has an unexpected shape (state/wearables/corrections.json); expected {\"version\":1,\"rules\":[...]}',\n );\n }\n const rules = (parsed as CorrectionsFileShape).rules;\n // Validate every persisted rule up front so a hand-edited bad rule\n // fails at load with its index, not mid-sync.\n compileCorrectionRules(rules, \"state corrections\");\n return rules;\n}\n\n/** Persist CLI-managed rules atomically (temp file + rename). */\nexport async function saveCorrectionsFile(\n memoryDir: string,\n rules: WearableCorrectionRule[],\n): Promise<void> {\n compileCorrectionRules(rules, \"state corrections\");\n const filePath = correctionsFilePath(memoryDir);\n await fsPromises.mkdir(path.dirname(filePath), { recursive: true });\n const payload: CorrectionsFileShape = { version: 1, rules };\n const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now().toString(36)}`;\n await fsPromises.writeFile(\n tmpPath,\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf-8\",\n );\n try {\n await fsPromises.rename(tmpPath, filePath);\n } catch (err) {\n // Clean up the temp file on rename failure; the original (if any)\n // is untouched.\n await fsPromises.unlink(tmpPath).catch(() => undefined);\n throw err;\n }\n}\n","/**\n * Wearable transcript redaction — privacy guard applied before any\n * transcript text is persisted or fed to extraction.\n *\n * Always-on recorders capture things nobody intended to store: card\n * numbers read aloud, SSNs dictated to a pharmacy line. Built-in\n * patterns cover the unambiguous, high-sensitivity cases; users can add\n * their own regexes via `wearables.redactionPatterns` (validated at\n * config parse — invalid patterns are rejected loudly, never ignored).\n *\n * All built-in patterns are simple linear scans (no nested quantifiers)\n * to stay safely outside polynomial-ReDoS territory.\n */\n\nimport type { WearableConversation } from \"./types.js\";\n\nexport const REDACTION_PLACEHOLDER = \"[redacted]\";\n\n/**\n * Built-in patterns. Conservative by design — false positives erase\n * real transcript content, so each pattern targets formats that are\n * near-certain PII:\n * - US SSN with separators (123-45-6789). Bare 9-digit runs are NOT\n * matched (too many false positives: ids, tracking numbers).\n * - Payment-card-like runs: 13–19 digits in groups separated by\n * spaces/dashes (4111 1111 1111 1111) or contiguous 15–16 digits.\n */\nconst BUILT_IN_PATTERNS: RegExp[] = [\n /\\b\\d{3}-\\d{2}-\\d{4}\\b/g,\n // Starts and ENDS on a digit so a trailing separator is never\n // consumed (replacing it would glue the placeholder to the next word).\n /\\b\\d(?:[ -]?\\d){12,18}\\b/g,\n];\n\n/** Minimum digit count before a digit-run is treated as a card number. */\nconst CARD_MIN_DIGITS = 13;\n\nexport interface RedactionResult {\n text: string;\n redactions: number;\n}\n\nexport function redactText(\n text: string,\n userPatterns: RegExp[],\n): RedactionResult {\n let redactions = 0;\n let result = text;\n\n // SSN pattern first (more specific than the digit-run pattern).\n result = result.replace(BUILT_IN_PATTERNS[0], () => {\n redactions += 1;\n return REDACTION_PLACEHOLDER;\n });\n\n // Digit-run pattern with a post-match digit-count check so short\n // grouped numbers (\"call 555 0125 today\") survive.\n result = result.replace(BUILT_IN_PATTERNS[1], (match) => {\n const digits = match.replace(/\\D/g, \"\");\n if (digits.length < CARD_MIN_DIGITS || digits.length > 19) {\n return match;\n }\n redactions += 1;\n return REDACTION_PLACEHOLDER;\n });\n\n for (const pattern of userPatterns) {\n result = result.replace(pattern, () => {\n redactions += 1;\n return REDACTION_PLACEHOLDER;\n });\n }\n\n return { text: result, redactions };\n}\n\n/**\n * Compile user-supplied redaction patterns. Throws with a descriptive\n * message on the first invalid pattern — config parsing surfaces this\n * to the operator instead of silently skipping the rule.\n */\nexport function compileRedactionPatterns(patterns: string[]): RegExp[] {\n return patterns.map((pattern, index) => {\n if (typeof pattern !== \"string\" || pattern.trim().length === 0) {\n throw new Error(\n `wearables.redactionPatterns[${index}] must be a non-empty string`,\n );\n }\n if (pattern.length > 256) {\n throw new Error(\n `wearables.redactionPatterns[${index}] exceeds 256 characters — redaction patterns must stay short`,\n );\n }\n try {\n // Operator-supplied regexes from the operator's own config —\n // length-capped above; never request input.\n return new RegExp(pattern, \"gi\");\n } catch (err) {\n throw new Error(\n `wearables.redactionPatterns[${index}] is not a valid regular expression: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n}\n\nconst OFF_THE_RECORD = /\\boff\\s+the\\s+record\\b/i;\nconst BACK_ON_THE_RECORD = /\\b(?:back\\s+)?on\\s+the\\s+record\\b/i;\n\nexport interface OffTheRecordResult {\n conversation: WearableConversation;\n droppedSegments: number;\n}\n\n/**\n * Drop segments between a spoken \"off the record\" marker and the next\n * \"(back) on the record\" marker (or conversation end). The marker\n * segments themselves are kept, with the off-record span replaced by a\n * visible placeholder so the transcript shows that content was elided\n * by request rather than lost.\n */\nexport function applyOffTheRecord(\n conversation: WearableConversation,\n): OffTheRecordResult {\n let offRecord = false;\n let droppedSegments = 0;\n const segments = [];\n for (const segment of conversation.segments) {\n if (!offRecord && OFF_THE_RECORD.test(segment.text)) {\n offRecord = true;\n segments.push({\n ...segment,\n text: \"[off the record — segment elided]\",\n });\n continue;\n }\n if (offRecord) {\n if (BACK_ON_THE_RECORD.test(segment.text)) {\n offRecord = false;\n segments.push({\n ...segment,\n text: \"[back on the record]\",\n });\n } else {\n droppedSegments += 1;\n }\n continue;\n }\n segments.push(segment);\n }\n return {\n conversation: { ...conversation, segments },\n droppedSegments,\n };\n}\n"],"mappings":"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","names":[]}
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-HQ6NIBL6.js";
4
4
  import {
5
5
  StorageManager
6
- } from "./chunk-PJGB7XRR.js";
6
+ } from "./chunk-UGHUNQ74.js";
7
7
  import {
8
8
  getCachedEpisodeMap,
9
9
  setCachedEpisodeMap
@@ -105,4 +105,4 @@ async function searchVerifiedEpisodes(options) {
105
105
  export {
106
106
  searchVerifiedEpisodes
107
107
  };
108
- //# sourceMappingURL=chunk-R3OQGYOU.js.map
108
+ //# sourceMappingURL=chunk-P2D2MM47.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-SOBJ6NEY.js";
4
4
  import {
5
5
  summarizeDisclosureTokens
6
- } from "./chunk-BPSGLMQ4.js";
6
+ } from "./chunk-YQNADJCT.js";
7
7
  import {
8
8
  summarizeRetrievedMemoryProvenance
9
9
  } from "./chunk-AC5LO7IU.js";
@@ -567,4 +567,4 @@ export {
567
567
  renderRecallExplain,
568
568
  parseRecallExplainFormat
569
569
  };
570
- //# sourceMappingURL=chunk-PSUB67YB.js.map
570
+ //# sourceMappingURL=chunk-PW6GURU3.js.map
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-ZFXCQPNO.js";
5
5
  import {
6
6
  StorageManager
7
- } from "./chunk-PJGB7XRR.js";
7
+ } from "./chunk-UGHUNQ74.js";
8
8
  import {
9
9
  isSafeRouteNamespace
10
10
  } from "./chunk-U3PN77QT.js";
@@ -161,4 +161,4 @@ export {
161
161
  getCategoryDir,
162
162
  NamespaceStorageRouter
163
163
  };
164
- //# sourceMappingURL=chunk-W3BKVM64.js.map
164
+ //# sourceMappingURL=chunk-QDV6VAD4.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  parseXrayFormat
3
- } from "./chunk-PSUB67YB.js";
3
+ } from "./chunk-PW6GURU3.js";
4
4
  import {
5
5
  RECALL_DISCLOSURE_LEVELS,
6
6
  isRecallDisclosure
7
- } from "./chunk-4R4KTDIE.js";
7
+ } from "./chunk-FPNQF475.js";
8
8
 
9
9
  // src/recall-xray-cli.ts
10
10
  function parseXrayDisclosureFlag(value) {
@@ -50,4 +50,4 @@ export {
50
50
  parseXrayBudgetFlag,
51
51
  parseXrayCliOptions
52
52
  };
53
- //# sourceMappingURL=chunk-3QSU4NFF.js.map
53
+ //# sourceMappingURL=chunk-QHXW3LZV.js.map
@@ -11,13 +11,13 @@ import {
11
11
  } from "./chunk-D24OXEPB.js";
12
12
  import {
13
13
  EngramAccessInputError
14
- } from "./chunk-KQFQ3IS5.js";
14
+ } from "./chunk-F3FY3D3S.js";
15
15
  import {
16
16
  projectTagProjectId
17
17
  } from "./chunk-EDQVAMQI.js";
18
18
  import {
19
19
  validateBriefingFormat
20
- } from "./chunk-OZXVGYGZ.js";
20
+ } from "./chunk-STDAAGH7.js";
21
21
  import {
22
22
  expandTildePath
23
23
  } from "./chunk-EYIEWJNI.js";
@@ -136,6 +136,24 @@ function parseMcpRequest(schemaName, args) {
136
136
  details.length > 0 ? `${validation.error.error}: ${details}` : validation.error.error
137
137
  );
138
138
  }
139
+ function optionalNonEmptyString(value, label) {
140
+ if (value === void 0 || value === null || value === "") return void 0;
141
+ if (typeof value !== "string") {
142
+ throw new Error(`${label} expects a string; got ${JSON.stringify(value)}`);
143
+ }
144
+ return value;
145
+ }
146
+ function optionalPositiveInteger(value, label) {
147
+ if (value === void 0 || value === null || value === "") return void 0;
148
+ if (typeof value !== "number" && typeof value !== "string") {
149
+ throw new Error(`${label} expects a positive integer; got ${JSON.stringify(value)}`);
150
+ }
151
+ const parsed = typeof value === "number" ? value : Number(value);
152
+ if (!Number.isFinite(parsed) || parsed <= 0 || !Number.isInteger(parsed)) {
153
+ throw new Error(`${label} expects a positive integer; got ${JSON.stringify(value)}`);
154
+ }
155
+ return parsed;
156
+ }
139
157
  function getObjectProperties(value) {
140
158
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
141
159
  }
@@ -324,6 +342,119 @@ var EngramMcpServer = class {
324
342
  additionalProperties: false
325
343
  }
326
344
  },
345
+ {
346
+ name: "engram.wearables_status",
347
+ description: "Status of wearable transcript sources (Limitless / Bee / Omi): configured sources, connector availability, last sync, stored transcript days.",
348
+ inputSchema: {
349
+ type: "object",
350
+ properties: {},
351
+ additionalProperties: false
352
+ }
353
+ },
354
+ {
355
+ name: "engram.wearables_sync",
356
+ description: "Pull, clean, and store wearable transcripts for one source or all enabled sources; optionally creates trust-gated memories per the source's memoryMode.",
357
+ inputSchema: {
358
+ type: "object",
359
+ properties: {
360
+ source: {
361
+ type: "string",
362
+ description: "Source id (e.g. limitless, bee, omi). Omit to sync every enabled source."
363
+ },
364
+ date: {
365
+ type: "string",
366
+ description: "Sync exactly this day (YYYY-MM-DD). Overrides days."
367
+ },
368
+ days: {
369
+ type: "integer",
370
+ minimum: 1,
371
+ maximum: 90,
372
+ description: "Lookback window in days ending today (default 2)."
373
+ },
374
+ forceMemories: {
375
+ type: "boolean",
376
+ description: "Re-run memory extraction even for unchanged days."
377
+ }
378
+ },
379
+ additionalProperties: false
380
+ }
381
+ },
382
+ {
383
+ name: "engram.transcript_day",
384
+ description: "Return the full stored wearable transcript(s) for a day, across all sources or one source, with cross-source overlap hints.",
385
+ inputSchema: {
386
+ type: "object",
387
+ properties: {
388
+ date: {
389
+ type: "string",
390
+ description: "Day to read (YYYY-MM-DD). Required."
391
+ },
392
+ source: {
393
+ type: "string",
394
+ description: "Optional source id to scope to (e.g. limitless)."
395
+ }
396
+ },
397
+ required: ["date"],
398
+ additionalProperties: false
399
+ }
400
+ },
401
+ {
402
+ name: "engram.transcript_search",
403
+ description: "Search stored wearable transcripts. Results carry source + date so callers can pull the full day via engram.transcript_day.",
404
+ inputSchema: {
405
+ type: "object",
406
+ properties: {
407
+ query: {
408
+ type: "string",
409
+ description: "Search query. Required; non-empty."
410
+ },
411
+ source: {
412
+ type: "string",
413
+ description: "Optional source id filter."
414
+ },
415
+ from: {
416
+ type: "string",
417
+ description: "Optional inclusive start date (YYYY-MM-DD)."
418
+ },
419
+ to: {
420
+ type: "string",
421
+ description: "Optional inclusive end date (YYYY-MM-DD)."
422
+ },
423
+ limit: {
424
+ type: "integer",
425
+ minimum: 1,
426
+ maximum: 50,
427
+ description: "Maximum results (default 10)."
428
+ }
429
+ },
430
+ required: ["query"],
431
+ additionalProperties: false
432
+ }
433
+ },
434
+ {
435
+ name: "engram.transcript_memories",
436
+ description: "List memories created from wearable transcripts, filterable by source and/or day. Includes pending_review candidates awaiting approval.",
437
+ inputSchema: {
438
+ type: "object",
439
+ properties: {
440
+ source: {
441
+ type: "string",
442
+ description: "Optional source id filter (e.g. limitless)."
443
+ },
444
+ date: {
445
+ type: "string",
446
+ description: "Optional transcript day filter (YYYY-MM-DD)."
447
+ },
448
+ limit: {
449
+ type: "integer",
450
+ minimum: 1,
451
+ maximum: 200,
452
+ description: "Maximum results (default 50)."
453
+ }
454
+ },
455
+ additionalProperties: false
456
+ }
457
+ },
327
458
  {
328
459
  name: "engram.action_confidence",
329
460
  description: "Advisory ask/draft/act/refuse/escalate decision helper for interruption budgeting. Read-only; never mutates memory.",
@@ -2101,6 +2232,54 @@ ${body}`;
2101
2232
  ...disclosure !== void 0 ? { disclosure } : {}
2102
2233
  });
2103
2234
  }
2235
+ case "engram.wearables_status":
2236
+ return this.service.wearablesStatus();
2237
+ case "engram.wearables_sync": {
2238
+ const source = optionalNonEmptyString(args.source, "engram.wearables_sync: source");
2239
+ const date = optionalNonEmptyString(args.date, "engram.wearables_sync: date");
2240
+ const days = optionalPositiveInteger(args.days, "engram.wearables_sync: days");
2241
+ let forceMemories;
2242
+ if (args.forceMemories !== void 0 && args.forceMemories !== null) {
2243
+ if (typeof args.forceMemories !== "boolean") {
2244
+ throw new Error(
2245
+ `engram.wearables_sync: forceMemories expects a boolean; got ${JSON.stringify(args.forceMemories)}`
2246
+ );
2247
+ }
2248
+ forceMemories = args.forceMemories;
2249
+ }
2250
+ return this.service.wearablesSync({ source, date, days, forceMemories });
2251
+ }
2252
+ case "engram.transcript_day": {
2253
+ const date = typeof args.date === "string" ? args.date : "";
2254
+ if (date.trim().length === 0) {
2255
+ throw new Error(
2256
+ "engram.transcript_day: date is required and must be YYYY-MM-DD"
2257
+ );
2258
+ }
2259
+ const source = optionalNonEmptyString(args.source, "engram.transcript_day: source");
2260
+ return this.service.wearablesTranscriptDay({ date, source });
2261
+ }
2262
+ case "engram.transcript_search": {
2263
+ const query = typeof args.query === "string" ? args.query : "";
2264
+ if (query.trim().length === 0) {
2265
+ throw new Error(
2266
+ "engram.transcript_search: query is required and must be non-empty"
2267
+ );
2268
+ }
2269
+ return this.service.wearablesTranscriptSearch({
2270
+ query,
2271
+ source: optionalNonEmptyString(args.source, "engram.transcript_search: source"),
2272
+ from: optionalNonEmptyString(args.from, "engram.transcript_search: from"),
2273
+ to: optionalNonEmptyString(args.to, "engram.transcript_search: to"),
2274
+ limit: optionalPositiveInteger(args.limit, "engram.transcript_search: limit")
2275
+ });
2276
+ }
2277
+ case "engram.transcript_memories":
2278
+ return this.service.wearablesTranscriptMemories({
2279
+ source: optionalNonEmptyString(args.source, "engram.transcript_memories: source"),
2280
+ date: optionalNonEmptyString(args.date, "engram.transcript_memories: date"),
2281
+ limit: optionalPositiveInteger(args.limit, "engram.transcript_memories: limit")
2282
+ });
2104
2283
  case "engram.action_confidence": {
2105
2284
  const body = parseMcpRequest("actionConfidence", args);
2106
2285
  return this.service.actionConfidence(body);
@@ -2903,4 +3082,4 @@ ${body}`;
2903
3082
  export {
2904
3083
  EngramMcpServer
2905
3084
  };
2906
- //# sourceMappingURL=chunk-I6UCUHLK.js.map
3085
+ //# sourceMappingURL=chunk-SHV5Y2WU.js.map