@snoai/memory 1.2.8 → 1.2.10

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 (177) hide show
  1. package/README.md +4 -4
  2. package/dist/{access-tracker-D1e-2-Bb.d.ts → access-tracker-BOPHSJjf.d.ts} +4 -4
  3. package/dist/{adapter-TCrv5P-C.d.ts → adapter-lyb6RaQE.d.ts} +2 -2
  4. package/dist/{atomic-memory-extraction-C0n0wHzt.d.ts → atomic-memory-extraction-B_XpkhMd.d.ts} +7 -5
  5. package/dist/{atomic-memory-extraction-BG42OXou.js → atomic-memory-extraction-o2v8mp7G.js} +109 -50
  6. package/dist/{b-profile-section-dictionary-provider-y3DMQ518.d.ts → b-profile-section-dictionary-provider-BK5NBs-y.d.ts} +1 -1
  7. package/dist/{capture-policy-detector-BY7v5Cq1.d.ts → capture-policy-detector-BvVGmxxX.d.ts} +1 -1
  8. package/dist/{classifier-DnbbtwTS.d.ts → classifier-CXQxJJPP.d.ts} +1 -1
  9. package/dist/client.d.ts +1 -1
  10. package/dist/{coding-skin-_Qu3INZD.js → coding-skin-azRXA51Z.js} +2 -1
  11. package/dist/coding-skin.d.ts +1 -0
  12. package/dist/coding-skin.js +2 -2
  13. package/dist/{config-BCZRhUvW.js → config-C7LzSWhG.js} +9 -4
  14. package/dist/{connection-C9YD5sgm.js → connection-PQcq3TPO.js} +1 -1
  15. package/dist/{derived-suppression-cache-BLAH0nB9.d.ts → derived-suppression-cache-Ckwjey7I.d.ts} +1 -1
  16. package/dist/diagnostic-encoder.js +1 -1
  17. package/dist/{index-dQMkc_6y.d.ts → index-CsPUNkcm.d.ts} +2 -2
  18. package/dist/{index-BO4RU_mc.d.ts → index-DPfJrOFD.d.ts} +1 -1
  19. package/dist/{index-DL8AVj0Z.d.ts → index-Pb9LrHgL.d.ts} +4 -5
  20. package/dist/index.d.ts +12 -9
  21. package/dist/index.js +97 -47
  22. package/dist/internal/config/index.d.ts +1 -1
  23. package/dist/internal/config/index.js +4 -5
  24. package/dist/internal/config/plugin-config-schema.d.ts +1 -1
  25. package/dist/internal/config/plugin-config-schema.js +1 -1
  26. package/dist/internal/config/product-mode.d.ts +1 -1
  27. package/dist/internal/config/settings.d.ts +1 -1
  28. package/dist/internal/config/settings.js +4 -4
  29. package/dist/internal/config/skin-defaults.d.ts +1 -1
  30. package/dist/internal/contract/profile.d.ts +1 -1
  31. package/dist/internal/contract/routes.d.ts +1 -1
  32. package/dist/internal/engine/bindings/memory-cli-shared.d.ts +4 -4
  33. package/dist/internal/engine/bindings/memory-forget-tool.js +1 -1
  34. package/dist/internal/engine/bindings/memory-list-tool.js +1 -1
  35. package/dist/internal/engine/bindings/memory-recall-tool.js +1 -1
  36. package/dist/internal/engine/bindings/memory-reflection-resolve-tool.js +1 -1
  37. package/dist/internal/engine/bindings/memory-stats-tool.js +2 -2
  38. package/dist/internal/engine/bindings/memory-store-tool.js +4 -4
  39. package/dist/internal/engine/bindings/memory-tool-access.d.ts +1 -1
  40. package/dist/internal/engine/bindings/memory-tool-access.js +1 -1
  41. package/dist/internal/engine/bindings/memory-tool-results.d.ts +1 -1
  42. package/dist/internal/engine/bindings/memory-tool-results.js +1 -1
  43. package/dist/internal/engine/bindings/memory-tool-schemas.d.ts +5 -5
  44. package/dist/internal/engine/bindings/memory-tool-schemas.js +1 -1
  45. package/dist/internal/engine/bindings/memory-update-tool.js +3 -3
  46. package/dist/internal/engine/bindings/sno-station-mem-ambient-learning-hook.d.ts +4 -4
  47. package/dist/internal/engine/bindings/sno-station-mem-ambient-learning-hook.js +4 -4
  48. package/dist/internal/engine/bindings/sno-station-mem-auto-recall-hook.d.ts +4 -4
  49. package/dist/internal/engine/bindings/sno-station-mem-auto-recall-hook.js +2 -2
  50. package/dist/internal/engine/bindings/sno-station-mem-insight-distill-factory.d.ts +6 -6
  51. package/dist/internal/engine/bindings/sno-station-mem-insight-distill-factory.js +7 -5
  52. package/dist/internal/engine/bindings/sno-station-mem-message-transcript.js +2 -2
  53. package/dist/internal/engine/bindings/sno-station-mem-reset-hook.d.ts +3 -3
  54. package/dist/internal/engine/bindings/sno-station-mem-runtime-mode.d.ts +1 -1
  55. package/dist/internal/engine/bindings/sno-station-mem-runtime-mode.js +3 -3
  56. package/dist/internal/engine/extraction/atomic-memory-extraction.d.ts +1 -1
  57. package/dist/internal/engine/extraction/atomic-memory-extraction.js +1 -1
  58. package/dist/internal/engine/extraction/b-profile-section-dictionary-provider.d.ts +1 -1
  59. package/dist/internal/engine/extraction/b-profile-section-rekey.d.ts +5 -5
  60. package/dist/internal/engine/extraction/capture-policy-detector.d.ts +1 -1
  61. package/dist/internal/engine/extraction/memory-metadata-codec.d.ts +2 -2
  62. package/dist/internal/engine/extraction/memory-temporality-classifier.d.ts +1 -1
  63. package/dist/internal/engine/extraction/memory-temporality-classifier.js +1 -1
  64. package/dist/internal/engine/observability/adapter.d.ts +1 -1
  65. package/dist/internal/engine/observability/memory-snapshot.d.ts +1 -1
  66. package/dist/internal/engine/observability/observable-embedder.d.ts +1 -1
  67. package/dist/internal/engine/observability/observable-llm-client.d.ts +1 -1
  68. package/dist/internal/engine/observability/observable-llm-client.js +0 -2
  69. package/dist/internal/engine/observability/observable-memory-store.d.ts +1 -1
  70. package/dist/internal/engine/observability/observable-memory-store.js +2 -2
  71. package/dist/internal/engine/observability/observable-retriever.d.ts +1 -1
  72. package/dist/internal/engine/observability/observable-retriever.js +2 -2
  73. package/dist/internal/engine/observability/runtime-diagnostics.d.ts +1 -1
  74. package/dist/internal/engine/observability/runtime-diagnostics.js +3 -3
  75. package/dist/internal/engine/operations/daily-spend-estimator.js +1 -1
  76. package/dist/internal/engine/operations/memory-tier-promoter.d.ts +1 -1
  77. package/dist/internal/engine/operations/runtime-audit-log.d.ts +3 -3
  78. package/dist/internal/engine/operations/runtime-audit-log.js +2 -2
  79. package/dist/internal/engine/provider/provider-registration.d.ts +4 -4
  80. package/dist/internal/engine/provider/provider-row-renderer.d.ts +1 -1
  81. package/dist/internal/engine/reflection/reflection-command-hooks.d.ts +1 -1
  82. package/dist/internal/engine/reflection/reflection-command-hooks.js +1 -1
  83. package/dist/internal/engine/reflection/reflection-deps.d.ts +1 -1
  84. package/dist/internal/engine/reflection/reflection-embedded-generator.d.ts +1 -1
  85. package/dist/internal/engine/reflection/reflection-embedded-generator.js +1 -1
  86. package/dist/internal/engine/reflection/reflection-injection-hooks.d.ts +1 -1
  87. package/dist/internal/engine/reflection/reflection-injection-hooks.js +1 -1
  88. package/dist/internal/engine/reflection/reflection-lifecycle-hooks.d.ts +1 -1
  89. package/dist/internal/engine/reflection/reflection-lifecycle-hooks.js +1 -1
  90. package/dist/internal/engine/reflection/strategy-hook-runner.d.ts +3 -3
  91. package/dist/internal/engine/reflection/strategy-hook-runner.js +2 -2
  92. package/dist/internal/engine/rem/classifier.d.ts +1 -1
  93. package/dist/internal/engine/rem/index.d.ts +2 -2
  94. package/dist/internal/engine/rem/index.js +9 -7
  95. package/dist/internal/engine/retrieval/access-tracker.d.ts +1 -1
  96. package/dist/internal/engine/retrieval/retriever.d.ts +1 -1
  97. package/dist/internal/engine/retrieval/retriever.js +1 -1
  98. package/dist/internal/engine/security/memory-scope-policy.js +1 -1
  99. package/dist/internal/engine/security/scopes.js +2 -2
  100. package/dist/internal/engine/shared/memory-kind-policy.d.ts +1 -1
  101. package/dist/internal/engine/shared/paths.d.ts +2 -2
  102. package/dist/internal/engine/shared/types.d.ts +2 -2
  103. package/dist/internal/engine/shared/types.js +1 -1
  104. package/dist/internal/engine/shared/utils.d.ts +1 -1
  105. package/dist/internal/engine/shared/utils.js +2 -3
  106. package/dist/internal/engine/telemetry/memory-telemetry-api.js +2 -2
  107. package/dist/internal/engine/telemetry/observe-ledger.d.ts +1 -1
  108. package/dist/internal/engine/telemetry/observe-ledger.js +46 -19
  109. package/dist/internal/model/llm-client.d.ts +2 -2
  110. package/dist/internal/model/llm-client.js +1 -1
  111. package/dist/internal/model/llm-mode-routing.d.ts +1 -1
  112. package/dist/internal/model/llm-mode-routing.js +1 -1
  113. package/dist/internal/store/atomic-memory-cutover-sql.js +1 -1
  114. package/dist/internal/store/connection.js +1 -1
  115. package/dist/internal/store/maintenance.d.ts +2 -2
  116. package/dist/internal/store/maintenance.js +444 -40
  117. package/dist/internal/store/memory-kinds-cutover-migrator.js +1 -1
  118. package/dist/internal/store/migrations.js +1 -1
  119. package/dist/internal/store/store.d.ts +2 -2
  120. package/dist/internal/store/store.js +1 -1
  121. package/dist/{llm-client-RqmOEQkg.d.ts → llm-client-BTaUVmDe.d.ts} +1 -1
  122. package/dist/{llm-client-fVrzPcyz.js → llm-client-ConEyQEs.js} +51 -12
  123. package/dist/{log-site-catalog.generated-Bb9w8j4f.js → log-site-catalog.generated-C9RmyAA0.js} +227 -192
  124. package/dist/log-site-catalog.json +1 -1
  125. package/dist/{memory-kind-policy-BOGb8thm.d.ts → memory-kind-policy-ClQEXeOL.d.ts} +1 -1
  126. package/dist/{memory-metadata-codec-DcSqjbWR.d.ts → memory-metadata-codec-wVAuoKrG.d.ts} +1 -1
  127. package/dist/{memory-runtime-DSP8cXik.js → memory-runtime-HibOMCFa.js} +482 -297
  128. package/dist/{memory-scope-policy-DICSCURA.js → memory-scope-policy--TiLZnrE.js} +2 -2
  129. package/dist/{memory-snapshot-C5BnJ2rO.d.ts → memory-snapshot-uTdxJnIh.d.ts} +2 -2
  130. package/dist/{memory-store-base-z593oJ4h.d.ts → memory-store-base-Bk2dOKED.d.ts} +5 -6
  131. package/dist/{memory-store-shared-DqpWJXZZ.js → memory-store-shared-CURizQIy.js} +1 -1
  132. package/dist/{memory-telemetry-receipts-YsxbwOAf.js → memory-telemetry-receipts-cjIQGwdp.js} +5 -1
  133. package/dist/{memory-temporality-classifier-SzlUCgTj.d.ts → memory-temporality-classifier-CcxfHYoT.d.ts} +1 -1
  134. package/dist/{memory-temporality-classifier-CeSOL2vq.js → memory-temporality-classifier-MBJyJdvB.js} +2 -2
  135. package/dist/{memory-tier-promoter-Z7jprFB7.d.ts → memory-tier-promoter-MkZPQ8u1.d.ts} +1 -1
  136. package/dist/memory-tool-dependencies--SrMdT3P.d.ts +14 -0
  137. package/dist/{memory-tool-dependencies-CnaGABQG.js → memory-tool-dependencies-DUMY8SwB.js} +3 -3
  138. package/dist/{model-call-table-BZJQkbKX.js → model-call-table-BE97f37s.js} +6 -1
  139. package/dist/{observable-embedder-DjhGxHx2.d.ts → observable-embedder-CGr3Zejf.d.ts} +1 -1
  140. package/dist/{observable-llm-client-CLJLMmwA.d.ts → observable-llm-client-CXUA7Gi3.d.ts} +3 -3
  141. package/dist/{observable-memory-store-B48HV2NK.d.ts → observable-memory-store-BwwKcUzf.d.ts} +4 -4
  142. package/dist/{observable-retriever-CAdHncKh.d.ts → observable-retriever-BZpdv93Y.d.ts} +5 -5
  143. package/dist/paths-DmmPxD_v.d.ts +1 -0
  144. package/dist/{plugin-config-schema-VBSPGEG3.d.ts → plugin-config-schema-BrhMvnXJ.d.ts} +3 -1
  145. package/dist/{plugin-config-schema-hIfZTELX.js → plugin-config-schema-Di-uKTP0.js} +1 -1
  146. package/dist/{profile-CQNCtVIu.d.ts → profile-CF5oDjR7.d.ts} +1 -1
  147. package/dist/{profile-section-writer-joJEIYhF.js → profile-section-writer-CmNa95uN.js} +3 -3
  148. package/dist/{reflection-command-hooks-Cl0ShtbF.d.ts → reflection-command-hooks-CM2mWb69.d.ts} +4 -4
  149. package/dist/{reflection-command-hooks-CG8n1GNK.js → reflection-command-hooks-CnTj8cKL.js} +3 -3
  150. package/dist/{reflection-deps-B0_cPBZt.d.ts → reflection-deps-B5I0nYZS.d.ts} +2 -2
  151. package/dist/{reflection-embedded-generator-C5kA0T0v.d.ts → reflection-embedded-generator-CogQIBcG.d.ts} +3 -3
  152. package/dist/{reflection-embedded-generator-D342_5o_.js → reflection-embedded-generator-DR525Moy.js} +1 -1
  153. package/dist/{reflection-injection-hooks-CtgcjLGx.d.ts → reflection-injection-hooks-BnbfZqpj.d.ts} +4 -4
  154. package/dist/{reflection-lifecycle-hooks-Pd7P9wya.d.ts → reflection-lifecycle-hooks-DMDhtidj.d.ts} +3 -3
  155. package/dist/{rem-batch-executor-DsXWpJYU.js → rem-batch-executor-8x4FBLtW.js} +1 -1
  156. package/dist/{rem-trigger-DZaplx_E.js → rem-trigger-DmRERTNH.js} +1672 -1003
  157. package/dist/{retriever-ZoLvPRHq.js → retriever-BXQmJMh0.js} +16 -3
  158. package/dist/{retriever-DQdyGlkr.d.ts → retriever-BpxV-0fB.d.ts} +8 -8
  159. package/dist/{runtime-audit-log-BCeujlEp.js → runtime-audit-log-DK6xAYxh.js} +103 -2
  160. package/dist/{runtime-audit-log-Bn3JLBPj.d.ts → runtime-audit-log-DdhLlTxi.d.ts} +4 -2
  161. package/dist/{scopes-CSOn6zdd.js → scopes-a4Kly9n7.js} +1 -1
  162. package/dist/{server-Dw34jY1d.js → server-CCduS_Ea.js} +17 -320
  163. package/dist/sidecar/main.js +11 -4
  164. package/dist/sno-station-mem-runtime-dependencies-AdFFr3bU.d.ts +31 -0
  165. package/dist/{sno-station-mem-runtime-dependencies-DAMOKR9y.js → sno-station-mem-runtime-dependencies-CexFtaY6.js} +9 -9
  166. package/dist/{store-DKndKig1.d.ts → store-BDIAl2cc.d.ts} +1 -1
  167. package/dist/{store-CUk-jEGA.js → store-BQxkgJTX.js} +31 -23
  168. package/dist/{strategy-hook-runner-BSk_o6Yt.d.ts → strategy-hook-runner-DT9emgCZ.d.ts} +7 -7
  169. package/dist/{strategy-hook-runner-CWApiUZW.js → strategy-hook-runner-SvyyGBXw.js} +1 -1
  170. package/dist/{types-Del9J7UB.d.ts → types-Ae3a8562.d.ts} +1 -1
  171. package/dist/{utils-Ctb9aevJ.d.ts → utils-CDw2ttQf.d.ts} +2 -3
  172. package/package.json +2 -2
  173. package/settings.default.json +4 -4
  174. package/dist/memory-tool-dependencies-CJNppsKh.d.ts +0 -14
  175. package/dist/paths-D3dEsoE4.d.ts +0 -1
  176. package/dist/sno-station-mem-runtime-dependencies-8CRIkARK.d.ts +0 -31
  177. package/dist/{unplaced-candidate-migration-CbQHzcEM.js → unplaced-candidate-migration-BCcdQkcx.js} +1 -1
@@ -1,6 +1,6 @@
1
1
  import { CHUNKING_VERSION, DEFAULT_BM25_WEIGHT, DEFAULT_RECALL_LIFECYCLE, DEFAULT_RERANK_MODEL, DEFAULT_RERANK_TIMEOUT_MS, DEFAULT_VECTOR_WEIGHT, IMPORTANCE_WEIGHT_BASE, LIGHTWEIGHT_COSINE_WEIGHT, LIGHTWEIGHT_FUSION_WEIGHT, LIGHTWEIGHT_RERANK_PENALTY, MMR_LAMBDA, RECENCY_WEIGHT, RERANK_BLEND_CROSS, RERANK_BLEND_VECTOR, TIME_DECAY_FLOOR, experimentCandidatePoolOverride, experimentMmrDisabled } from "./internal/config/index.js";
2
2
  import "./internal/engine/shared/types.js";
3
- import { RetrievalError } from "./internal/engine/shared/errors.js";
3
+ import { EmbeddingError, RetrievalError } from "./internal/engine/shared/errors.js";
4
4
  import { o as isMemoryExpired, s as parseInsightMetadata } from "./memory-metadata-codec-DL1sbJiN.js";
5
5
  import { clamp01 } from "./internal/engine/shared/utils.js";
6
6
  import { i as memoryOperationSignal } from "./operation-cancellation-CTKWwNHk.js";
@@ -375,6 +375,19 @@ function collectParallelStage(results, key, fallbackIds) {
375
375
  }
376
376
  //#endregion
377
377
  //#region src/engine/retrieval/retriever-search-modes.ts
378
+ /**
379
+ * Ordinary long prose is chunked and averaged by the embedder. Text it cannot cut under the model's limit (a pasted log or hash
380
+ * dump) is rejected, and would fail the whole recall, so only then is the query cut to the limit; keyword search still sees all of it.
381
+ */
382
+ async function embedQuery(embedder, query) {
383
+ await embedder.warmup();
384
+ try {
385
+ return await embedder.embed(query);
386
+ } catch (error) {
387
+ if (!(error instanceof EmbeddingError)) throw error;
388
+ return embedder.embed(embedder.truncateToTokens(query, 512));
389
+ }
390
+ }
378
391
  Object.assign(MemoryRetriever.prototype, {
379
392
  async aggregationComplete(context, trace) {
380
393
  trace?.startStage("aggregation_evidence", []);
@@ -420,7 +433,7 @@ Object.assign(MemoryRetriever.prototype, {
420
433
  return mapped;
421
434
  },
422
435
  async vectorOnly(context, trace) {
423
- const vector = await this.embedder.embed(context.query);
436
+ const vector = await embedQuery(this.embedder, context.query);
424
437
  this.throwIfAborted(context);
425
438
  const searchLimit = this.config.temporalExpiry ? Math.max(this.config.candidatePoolSize, context.limit * 2) : context.limit;
426
439
  trace?.startStage("vector_search", []);
@@ -463,7 +476,7 @@ Object.assign(MemoryRetriever.prototype, {
463
476
  },
464
477
  async precisionRecall(context, trace) {
465
478
  trace?.startStage("embed_query", []);
466
- const queryVector = await this.embedder.embed(context.query);
479
+ const queryVector = await embedQuery(this.embedder, context.query);
467
480
  trace?.endStage([]);
468
481
  this.throwIfAborted(context);
469
482
  const bm25Query = context.query;
@@ -1,13 +1,13 @@
1
- import { h as MemoryCategory, l as DecayScore, r as AggregationQuery, u as DecayableMemory, x as RetrievalResult, y as MemorySearchResult } from "./types-Del9J7UB.js";
2
- import { sn as RecallLifecycleConfig } from "./index-DL8AVj0Z.js";
1
+ import { h as MemoryCategory, l as DecayScore, r as AggregationQuery, u as DecayableMemory, x as RetrievalResult, y as MemorySearchResult } from "./types-Ae3a8562.js";
2
+ import { sn as RecallLifecycleConfig } from "./index-Pb9LrHgL.js";
3
3
  import { t as Embedder } from "./embedding-provider-client-vynZMuit.js";
4
4
  import "./trace-C1JxMfs-.js";
5
- import "./memory-metadata-codec-DcSqjbWR.js";
6
- import { K as RemFacetPolicy } from "./index-BO4RU_mc.js";
7
- import { C as MemoryStore } from "./memory-store-base-z593oJ4h.js";
8
- import "./store-DKndKig1.js";
9
- import { n as AccessTracker } from "./access-tracker-D1e-2-Bb.js";
10
- import { r as TierPromoter } from "./memory-tier-promoter-Z7jprFB7.js";
5
+ import "./memory-metadata-codec-wVAuoKrG.js";
6
+ import { K as RemFacetPolicy } from "./index-DPfJrOFD.js";
7
+ import { C as MemoryStore } from "./memory-store-base-Bk2dOKED.js";
8
+ import "./store-BDIAl2cc.js";
9
+ import { n as AccessTracker } from "./access-tracker-BOPHSJjf.js";
10
+ import { r as TierPromoter } from "./memory-tier-promoter-MkZPQ8u1.js";
11
11
  import "@snoai/utils/logger";
12
12
  //#region src/engine/retrieval/retrieval-trace.d.ts
13
13
  /** @file retrieval-trace.ts
@@ -5,8 +5,9 @@ import path from "node:path";
5
5
  import { appendFile } from "node:fs/promises";
6
6
  import { randomUUID } from "node:crypto";
7
7
  import { AsyncLocalStorage } from "node:async_hooks";
8
- import { appendFileSync, createReadStream, existsSync, mkdirSync } from "node:fs";
8
+ import { appendFileSync, closeSync, createReadStream, existsSync, fsyncSync, mkdirSync, openSync, readSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
9
9
  import { createInterface } from "node:readline";
10
+ import { StringDecoder } from "node:string_decoder";
10
11
  //#region src/engine/operations/jsonl-lines.ts
11
12
  const log = createLogger("sno-station-mem:jsonl");
12
13
  /** Preserve complete records without materializing an unbounded log as one string. */
@@ -131,6 +132,7 @@ function enqueueAuditWrite(auditPath, line) {
131
132
  const next = (auditWriteQueues.get(auditPath) ?? Promise.resolve(true)).catch(() => void 0).then(async () => {
132
133
  mkdirSync(path.dirname(auditPath), { recursive: true });
133
134
  await appendFile(auditPath, line);
135
+ compactAuditLog(auditPath);
134
136
  return true;
135
137
  }).catch((error) => {
136
138
  createLogger("sno-station-mem:audit").error("Audit entry append failed", { error }, {
@@ -151,6 +153,104 @@ function enqueueAuditWrite(auditPath, line) {
151
153
  function getAuditPath(stateDir) {
152
154
  return path.join(stateDir, "audit.jsonl");
153
155
  }
156
+ /** Retain the recent tail and two days of REM replay evidence when the audit exceeds 16 MiB. */
157
+ function compactAuditLog(auditPath) {
158
+ try {
159
+ compactAuditFile(auditPath);
160
+ } catch (error) {
161
+ createLogger("sno-station-mem:audit").error("Audit compaction failed; existing records retained", { error }, {
162
+ event_name: "memory.audit.compact.failed",
163
+ file: "packages/memory/src/engine/operations/runtime-audit-log.ts",
164
+ function: "compactAuditLog",
165
+ site_id: "memory.audit.compact.failed"
166
+ });
167
+ }
168
+ }
169
+ function compactAuditFile(auditPath) {
170
+ if (!existsSync(auditPath) || statSync(auditPath).size <= 16777216) return;
171
+ const fd = openSync(auditPath, "r");
172
+ const retained = [];
173
+ const openAttempts = /* @__PURE__ */ new Map();
174
+ let tail;
175
+ let size = 0;
176
+ try {
177
+ size = statSync(auditPath).size;
178
+ const tailStart = Math.max(0, size - 8388608);
179
+ tail = Buffer.alloc(size - tailStart);
180
+ const tailRead = readSync(fd, tail, 0, tail.length, tailStart);
181
+ tail = tail.subarray(0, tailRead);
182
+ const newline = tail.indexOf(10);
183
+ const prefixEnd = newline < 0 ? size : tailStart + newline + 1;
184
+ tail = newline < 0 ? Buffer.alloc(0) : tail.subarray(newline + 1);
185
+ const cutoff = (/* @__PURE__ */ new Date(Date.now() - 1728e5)).toISOString();
186
+ const buffer = Buffer.alloc(65536);
187
+ let position = 0;
188
+ let pending = "";
189
+ let linePosition = 0;
190
+ const decoder = new StringDecoder("utf8");
191
+ let oversized = false;
192
+ while (position < prefixEnd) {
193
+ const count = readSync(fd, buffer, 0, Math.min(buffer.length, prefixEnd - position), position);
194
+ if (count === 0) break;
195
+ position += count;
196
+ const parts = (pending + decoder.write(buffer.subarray(0, count))).split("\n");
197
+ pending = parts.pop() ?? "";
198
+ for (const line of parts) {
199
+ if (oversized) {
200
+ oversized = false;
201
+ linePosition++;
202
+ continue;
203
+ }
204
+ try {
205
+ const entry = JSON.parse(line);
206
+ if (isRecord(entry) && typeof entry["event"] === "string" && entry["event"].startsWith("rem_") && typeof entry["timestamp"] === "string" && entry["timestamp"] >= cutoff && (entry["event"] !== "rem_trigger_evaluated" || isRecord(entry["details"]) && entry["details"]["row"] === "dispatch")) retained.push({
207
+ position: linePosition,
208
+ line: line + "\n"
209
+ });
210
+ if (isRecord(entry) && isRecord(entry["details"])) {
211
+ const id = entry["details"]["audit_operation_id"];
212
+ if (typeof id === "string" && entry["decision"] === "mutation-attempt-open") openAttempts.set(id, {
213
+ position: linePosition,
214
+ line: line + "\n"
215
+ });
216
+ if (typeof id === "string" && entry["details"]["mutation_outcome"] !== void 0) openAttempts.delete(id);
217
+ }
218
+ } catch {}
219
+ linePosition++;
220
+ }
221
+ if (pending.length > 1048576 || oversized) {
222
+ pending = "";
223
+ oversized = true;
224
+ }
225
+ }
226
+ } finally {
227
+ closeSync(fd);
228
+ }
229
+ const temporary = `${auditPath}.${randomUUID()}.tmp`;
230
+ try {
231
+ writeFileSync(temporary, [...retained, ...openAttempts.values()].sort((a, b) => a.position - b.position).map((record) => record.line).join(""), { mode: 384 });
232
+ appendFileSync(temporary, tail);
233
+ const output = openSync(temporary, "r+");
234
+ try {
235
+ fsyncSync(output);
236
+ } finally {
237
+ closeSync(output);
238
+ }
239
+ const grown = statSync(auditPath).size;
240
+ if (grown > size) {
241
+ const late = Buffer.alloc(grown - size);
242
+ const source = openSync(auditPath, "r");
243
+ try {
244
+ appendFileSync(temporary, late.subarray(0, readSync(source, late, 0, late.length, size)));
245
+ } finally {
246
+ closeSync(source);
247
+ }
248
+ }
249
+ renameSync(temporary, auditPath);
250
+ } finally {
251
+ rmSync(temporary, { force: true });
252
+ }
253
+ }
154
254
  /** Returns cost path from audit log state state without side effects. */
155
255
  function getCostPath(stateDir) {
156
256
  return path.join(stateDir, "cost.jsonl");
@@ -217,6 +317,7 @@ function appendAuditEntrySync(stateDir, entry) {
217
317
  ...prepared,
218
318
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
219
319
  })}\n`);
320
+ compactAuditLog(auditPath);
220
321
  } catch (error) {
221
322
  createLogger("sno-station-mem:audit").error("memory.audit.append.failed", { error }, {
222
323
  event_name: "memory.audit.append.failed",
@@ -427,4 +528,4 @@ async function flushAuditWrites() {
427
528
  await Promise.allSettled(pending);
428
529
  }
429
530
  //#endregion
430
- export { flushAuditWrites as a, recoverInterruptedMutationAttempts as c, runWithMutationAttempt as d, currentMutationAttemptId as i, runWithMemoryAudit as l, appendAuditEntryStrict as n, getAuditPath as o, appendAuditEntrySync as r, getCostPath as s, appendAuditEntry as t, runWithMemoryAuditSync as u };
531
+ export { currentMutationAttemptId as a, getCostPath as c, runWithMemoryAuditSync as d, runWithMutationAttempt as f, compactAuditLog as i, recoverInterruptedMutationAttempts as l, appendAuditEntryStrict as n, flushAuditWrites as o, readJsonlLines as p, appendAuditEntrySync as r, getAuditPath as s, appendAuditEntry as t, runWithMemoryAudit as u };
@@ -1,4 +1,4 @@
1
- import "./paths-D3dEsoE4.js";
1
+ import "./paths-DmmPxD_v.js";
2
2
  //#region src/engine/operations/runtime-audit-log.d.ts
3
3
  type AuditEvent = "tool_call" | "hook_trigger" | "kill_switch" | "startup" | "error" | "auto_recall" | "ambient_learning" | "session_summary" | "envelope_strip" | "storage_integrity" | "memory_injected" | "memory_searched" | "memory_read" | "memory_updated" | "memory_superseded" | "memory_deleted" | "memory_purged" | "rem_trigger_evaluated" | "rem_triggered" | "rem_completed" | "rem_failed";
4
4
  type AuditStatus = "ok" | "error" | "skipped" | "partial";
@@ -125,6 +125,8 @@ interface MutationAttemptRunOptions<T> {
125
125
  }
126
126
  /** Returns audit path from audit log state state without side effects. */
127
127
  declare function getAuditPath(stateDir: string): string;
128
+ /** Retain the recent tail and two days of REM replay evidence when the audit exceeds 16 MiB. */
129
+ declare function compactAuditLog(auditPath: string): void;
128
130
  /** Returns cost path from audit log state state without side effects. */
129
131
  declare function getCostPath(stateDir: string): string;
130
132
  /** Persists audit entry through the single audit log state write path. */
@@ -146,4 +148,4 @@ declare function runWithMemoryAuditSync<T, E extends MemoryAuditEvent>(options:
146
148
  /** Implements flush audit writes as the local audit log state operation. */
147
149
  declare function flushAuditWrites(): Promise<void>;
148
150
  //#endregion
149
- export { runWithMutationAttempt as S, getAuditPath as _, MemoryAuditEvent as a, runWithMemoryAudit as b, MutationAttemptCompletion as c, MutationAttemptWriter as d, appendAuditEntry as f, flushAuditWrites as g, currentMutationAttemptId as h, MemoryAuditDetailsByEvent as i, MutationAttemptOutcome as l, appendAuditEntrySync as m, AuditEvent as n, MemoryAuditRunOptions as o, appendAuditEntryStrict as p, AuditStatus as r, MemoryAuditSyncRunOptions as s, AuditEntry as t, MutationAttemptRunOptions as u, getCostPath as v, runWithMemoryAuditSync as x, recoverInterruptedMutationAttempts as y };
151
+ export { runWithMutationAttempt as C, runWithMemoryAuditSync as S, flushAuditWrites as _, MemoryAuditEvent as a, recoverInterruptedMutationAttempts as b, MutationAttemptCompletion as c, MutationAttemptWriter as d, appendAuditEntry as f, currentMutationAttemptId as g, compactAuditLog as h, MemoryAuditDetailsByEvent as i, MutationAttemptOutcome as l, appendAuditEntrySync as m, AuditEvent as n, MemoryAuditRunOptions as o, appendAuditEntryStrict as p, AuditStatus as r, MemoryAuditSyncRunOptions as s, AuditEntry as t, MutationAttemptRunOptions as u, getAuditPath as v, runWithMemoryAudit as x, getCostPath as y };
@@ -1,4 +1,4 @@
1
- import { c as SCOPE_PATTERNS, i as isSystemBypassId, o as shouldWarnLegacyFallbackBypassId } from "./memory-scope-policy-DICSCURA.js";
1
+ import { c as SCOPE_PATTERNS, i as isSystemBypassId, o as shouldWarnLegacyFallbackBypassId } from "./memory-scope-policy--TiLZnrE.js";
2
2
  import { createLogger, privateLogReference } from "@snoai/utils/logger";
3
3
  //#region src/engine/security/scope-helpers.ts
4
4
  /** @file scope-helpers.ts
@@ -1,5 +1,5 @@
1
- import { Et as ModelCallRefusedError, G as parseRemOperationType, W as REM_BUILT_OPERATION_TYPES, ct as readJsonlLines, it as getAuditPath, n as remNeedsHost, nt as appendAuditEntryStrict } from "./rem-trigger-DZaplx_E.js";
2
- import { Ar as MEMORY_ERROR_STATUS, C as getSnoStationMemStateDir, Fr as memoryMethod, Mr as MEMORY_ROUTES, Nr as MEMORY_SKIN_HEADER, S as getSidecarSocketPath, _ as readRemTestHoldMs, c as REM_SIDECAR_ORIGIN, d as getRemDiscoveryPath, f as getRemJobJournalPath, g as readRemOperationalConfig, i as REM_JOBS_PATH_PREFIX, kr as MEMORY_DEFAULT_SKIN_ID, l as REM_SOURCE, nr as MEMORY_SHUTDOWN_TIMEOUT_MS, r as REM_CORRELATION_ID_HEADER, s as REM_SIDECAR_HOST, u as getRemChassisJournalPath, v as SettingsUnavailableError, y as getDiscoveryPath } from "./config-BCZRhUvW.js";
1
+ import { At as getAuditPath, Dt as appendAuditEntryStrict, K as REM_BUILT_OPERATION_TYPES, Ot as compactAuditLog, Pt as readJsonlLines, bt as ModelCallRefusedError, d as RemJobStore, f as parseRemJobStats, n as remNeedsHost, q as parseRemOperationType } from "./rem-trigger-DmRERTNH.js";
2
+ import { Ar as MEMORY_ERROR_STATUS, C as getSnoStationMemStateDir, Fr as memoryMethod, Mr as MEMORY_ROUTES, Nr as MEMORY_SKIN_HEADER, S as getSidecarSocketPath, _ as readRemTestHoldMs, c as REM_SIDECAR_ORIGIN, d as getRemDiscoveryPath, f as getRemJobJournalPath, g as readRemOperationalConfig, i as REM_JOBS_PATH_PREFIX, kr as MEMORY_DEFAULT_SKIN_ID, l as REM_SOURCE, nr as MEMORY_SHUTDOWN_TIMEOUT_MS, r as REM_CORRELATION_ID_HEADER, s as REM_SIDECAR_HOST, u as getRemChassisJournalPath, v as SettingsUnavailableError, y as getDiscoveryPath } from "./config-C7LzSWhG.js";
3
3
  import { t as ContractError } from "./error-D-wb-rZw.js";
4
4
  import { setImmediate } from "node:timers/promises";
5
5
  import { createLogger, currentLogContext, effectiveLogLevel, emitDiagnostic } from "@snoai/utils/logger";
@@ -80,7 +80,7 @@ function readRequestBody(request, signal) {
80
80
  }
81
81
  //#endregion
82
82
  //#region src/sidecar/memory-routes.ts
83
- const log$2 = createLogger("sno-station-mem:memory-routes");
83
+ const log$1 = createLogger("sno-station-mem:memory-routes");
84
84
  async function serveMemoryRoute(request, response, pathname, openPool, activeTasks) {
85
85
  const method = memoryMethod(pathname);
86
86
  if (!method || request.method !== "POST") return false;
@@ -123,7 +123,7 @@ async function serveMemoryRoute(request, response, pathname, openPool, activeTas
123
123
  }));
124
124
  return true;
125
125
  }
126
- log$2.error("Memory engine request failed", {
126
+ log$1.error("Memory engine request failed", {
127
127
  method,
128
128
  skinId,
129
129
  error,
@@ -208,318 +208,9 @@ var RemChassisJournal = class {
208
208
  } finally {
209
209
  await handle.close();
210
210
  }
211
- if (!journalAlreadyExisted) await syncDirectory$2(parent);
212
- }
213
- };
214
- async function syncDirectory$2(directory) {
215
- if (process.platform === "win32") return;
216
- const handle = await open(directory, "r");
217
- try {
218
- await handle.sync();
219
- } finally {
220
- await handle.close();
221
- }
222
- }
223
- //#endregion
224
- //#region src/sidecar/rem-job-store.ts
225
- /** @file rem-job-store.ts
226
- * @purpose Persists append-only REM job state transitions.
227
- * @boundary Durable local JSONL journal used by the standalone REM sidecar.
228
- */
229
- const log$1 = createLogger("sno-station-mem:rem-jobs");
230
- const remJobStateSchema = z.enum([
231
- "queued",
232
- "running",
233
- "done",
234
- "failed",
235
- "skipped"
236
- ]);
237
- const remJobMeasurementsSchema = z.object({
238
- rows_considered: z.number().int().nonnegative(),
239
- pairs_built: z.number().int().nonnegative().optional(),
240
- pair_cap_binding: z.boolean().optional(),
241
- model_calls: z.number().int().nonnegative(),
242
- model_tokens: z.number().int().nonnegative(),
243
- wall_ms: z.number().int().nonnegative()
244
- }).strict();
245
- const remJobStatsSchema = z.object({
246
- operations: z.number().int().nonnegative(),
247
- applied_count: z.number().int().nonnegative().optional(),
248
- actionable_candidate_count: z.number().int().nonnegative().optional(),
249
- applied_fraction: z.number().min(0).max(1).nullable().optional(),
250
- scan: z.object({
251
- scope: z.string().min(1),
252
- candidate_count: z.number().int().nonnegative(),
253
- stamped_skipped_count: z.number().int().nonnegative().optional(),
254
- actionable_candidate_count: z.number().int().nonnegative().optional()
255
- }).strict().optional(),
256
- parse_failure_count: z.number().int().nonnegative().optional(),
257
- top_refusal_reasons: z.array(z.string().min(1)).max(2).optional(),
258
- measured: remJobMeasurementsSchema.optional(),
259
- by_operation: z.array(z.object({
260
- operation: z.string().min(1),
261
- applied_count: z.number().int().nonnegative(),
262
- actionable_candidate_count: z.number().int().nonnegative(),
263
- candidate_count: z.number().int().nonnegative(),
264
- parse_failure_count: z.number().int().nonnegative(),
265
- top_refusal_reasons: z.array(z.string().min(1)).max(2),
266
- measured: remJobMeasurementsSchema
267
- }).strict()).min(1).optional()
268
- }).strict();
269
- function parseRemJobStats(value) {
270
- const parsed = remJobStatsSchema.safeParse(value);
271
- return parsed.success ? parsed.data : void 0;
272
- }
273
- const remWaveJobSchema = z.object({
274
- payloadVersion: z.literal(1),
275
- waveId: z.string().min(1),
276
- correlationId: z.string().min(1),
277
- scope: z.string().min(1),
278
- requestedOperations: z.array(z.string().min(1)).min(1),
279
- state: remJobStateSchema,
280
- startedAt: z.string().datetime().nullable(),
281
- finishedAt: z.string().datetime().nullable(),
282
- stats: remJobStatsSchema,
283
- error: z.string().min(1).optional()
284
- }).strict();
285
- const legacyJobSchema = z.object({
286
- job_id: z.string().min(1),
287
- state: remJobStateSchema,
288
- type: z.string().min(1),
289
- scope: z.string().min(1),
290
- started_at: z.string().datetime().nullable(),
291
- finished_at: z.string().datetime().nullable(),
292
- stats: remJobStatsSchema,
293
- error: z.string().min(1).optional(),
294
- correlation_id: z.string().min(1)
295
- }).strict();
296
- const OPERATION_ORDER = [
297
- "rem-replace",
298
- "rem-update",
299
- "rem-distill",
300
- "rem-retire"
301
- ];
302
- var RemJobStore = class RemJobStore {
303
- journalPath;
304
- onDurableTransition;
305
- jobs = /* @__PURE__ */ new Map();
306
- persistedJobs = /* @__PURE__ */ new Set();
307
- mergeKeys = /* @__PURE__ */ new Map();
308
- operationQueue = Promise.resolve();
309
- constructor(journalPath, onDurableTransition) {
310
- this.journalPath = journalPath;
311
- this.onDurableTransition = onDurableTransition;
312
- }
313
- static async open(journalPath, onDurableTransition = () => void 0) {
314
- const store = new RemJobStore(journalPath, onDurableTransition);
315
- await store.migrateLegacyJournal().catch((error) => store.reportFailure(error));
316
- await store.load();
317
- return store;
318
- }
319
- isPersisted(jobId) {
320
- return this.persistedJobs.has(jobId);
321
- }
322
- get(jobId) {
323
- const job = this.jobs.get(jobId);
324
- return job === void 0 ? void 0 : toRemJob(job);
325
- }
326
- nonTerminalJobs() {
327
- return Array.from(this.jobs.values()).filter((job) => job.state === "queued" || job.state === "running").map(toRemJob);
328
- }
329
- async createQueued(type, scope, correlationId) {
330
- return this.enqueue(async () => {
331
- const requestedOperations = canonicalOperations(typeof type === "string" ? [type] : type);
332
- if (requestedOperations.length === 0) throw new Error("REM wave requires at least one supported operation");
333
- const mergeKey = `${correlationId}\0${scope}`;
334
- const existingId = this.mergeKeys.get(mergeKey);
335
- const existing = existingId === void 0 ? void 0 : this.jobs.get(existingId);
336
- if (existing !== void 0 && existing.state === "queued") {
337
- const mergedOperations = canonicalOperations([...existing.requestedOperations, ...requestedOperations]);
338
- if (mergedOperations.length === existing.requestedOperations.length) return {
339
- created: false,
340
- job: toRemJob(existing)
341
- };
342
- const updated = remWaveJobSchema.parse({
343
- ...existing,
344
- requestedOperations: mergedOperations
345
- });
346
- const durable = await this.persist(updated);
347
- this.jobs.set(updated.waveId, updated);
348
- if (durable) this.onDurableTransition(toRemJob(updated));
349
- return {
350
- created: false,
351
- job: toRemJob(updated)
352
- };
353
- }
354
- if (existing !== void 0 && existing.state !== "skipped" && requestedOperations.every((operation) => existing.requestedOperations.includes(operation))) return {
355
- created: false,
356
- job: toRemJob(existing)
357
- };
358
- const job = remWaveJobSchema.parse({
359
- payloadVersion: 1,
360
- waveId: `rem-wave-${randomUUID()}`,
361
- correlationId,
362
- scope,
363
- requestedOperations,
364
- state: "queued",
365
- startedAt: null,
366
- finishedAt: null,
367
- stats: { operations: 0 }
368
- });
369
- const durable = await this.persist(job);
370
- this.jobs.set(job.waveId, job);
371
- this.mergeKeys.set(mergeKey, job.waveId);
372
- const outward = toRemJob(job);
373
- if (durable) this.onDurableTransition(outward);
374
- return {
375
- created: true,
376
- job: outward
377
- };
378
- });
379
- }
380
- async transition(jobId, transition) {
381
- return this.enqueue(async () => {
382
- const current = this.jobs.get(jobId);
383
- if (!current) throw new Error(`REM job not found: ${jobId}`);
384
- const next = remWaveJobSchema.parse({
385
- ...current,
386
- state: transition.state,
387
- ...transition.started_at === void 0 ? {} : { startedAt: transition.started_at },
388
- ...transition.finished_at === void 0 ? {} : { finishedAt: transition.finished_at },
389
- ...transition.stats === void 0 ? {} : { stats: transition.stats },
390
- ...transition.error === void 0 ? {} : { error: transition.error }
391
- });
392
- const durable = await this.persist(next);
393
- this.jobs.set(jobId, next);
394
- const outward = toRemJob(next);
395
- if (durable) this.onDurableTransition(outward);
396
- return outward;
397
- });
398
- }
399
- async load() {
400
- if (!existsSync(this.journalPath)) return;
401
- const bytes = await readFile(this.journalPath);
402
- const lines = bytes.toString("utf8").split("\n");
403
- const endsWithNewline = bytes.length === 0 || bytes[bytes.length - 1] === 10;
404
- for (const [index, line] of lines.entries()) {
405
- if (!line) continue;
406
- if (!endsWithNewline && index === lines.length - 1) {
407
- const lastNewline = bytes.lastIndexOf(10);
408
- await this.truncateJournal(lastNewline < 0 ? 0 : lastNewline + 1);
409
- return;
410
- }
411
- try {
412
- const parsed = JSON.parse(line);
413
- const job = remWaveJobSchema.parse(parsed);
414
- this.jobs.set(job.waveId, job);
415
- this.mergeKeys.set(`${job.correlationId}\0${job.scope}`, job.waveId);
416
- } catch (error) {
417
- log$1.error("rem.journal.failed", {
418
- path: this.journalPath,
419
- line: index + 1,
420
- error
421
- }, {
422
- event_name: "rem.journal.failed",
423
- file: "packages/memory/src/sidecar/rem-job-store.ts",
424
- function: "load",
425
- site_id: "rem-job-store.load.invalid-line"
426
- });
427
- }
428
- }
429
- }
430
- async migrateLegacyJournal() {
431
- const legacyPath = path.join(path.dirname(this.journalPath), "rem-jobs.jsonl");
432
- if (!existsSync(legacyPath)) return;
433
- const latest = /* @__PURE__ */ new Map();
434
- for await (const line of readJsonlLines(legacyPath)) try {
435
- const parsed = JSON.parse(line);
436
- const job = legacyJobSchema.parse(parsed);
437
- latest.set(job.job_id, job);
438
- } catch (error) {
439
- const reason = error instanceof Error ? error.message : String(error);
440
- this.reportFailure(reason);
441
- }
442
- const interrupted = [...latest.values()].filter((job) => job.state === "queued" || job.state === "running");
443
- if (interrupted.length > 0) {
444
- const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
445
- const handle = await open(legacyPath, "a");
446
- try {
447
- for (const job of interrupted) await handle.writeFile(`${JSON.stringify({
448
- ...job,
449
- state: "failed",
450
- finished_at: finishedAt,
451
- error: "sidecar_upgrade_interrupted"
452
- })}\n`, "utf8");
453
- await handle.sync();
454
- } finally {
455
- await handle.close();
456
- }
457
- }
458
- await rename(legacyPath, path.join(path.dirname(legacyPath), "rem-jobs.v0.jsonl"));
459
- }
460
- reportFailure(error) {
461
- log$1.error("rem.journal.failed", {
462
- error,
463
- path: this.journalPath
464
- }, {
465
- event_name: "rem.journal.failed",
466
- file: "packages/memory/src/sidecar/rem-job-store.ts",
467
- function: "reportFailure",
468
- site_id: "rem.journal.failed"
469
- });
470
- }
471
- async persist(job) {
472
- this.persistedJobs.delete(job.waveId);
473
- await this.append(job);
474
- this.persistedJobs.add(job.waveId);
475
- return true;
476
- }
477
- async truncateJournal(length) {
478
- const handle = await open(this.journalPath, "r+");
479
- try {
480
- await handle.truncate(length);
481
- await handle.sync();
482
- } finally {
483
- await handle.close();
484
- }
485
- }
486
- async append(job) {
487
- const parent = path.dirname(this.journalPath);
488
- await mkdir(parent, { recursive: true });
489
- const journalAlreadyExisted = existsSync(this.journalPath);
490
- const handle = await open(this.journalPath, "a");
491
- try {
492
- await handle.writeFile(`${JSON.stringify(job)}\n`, "utf8");
493
- await handle.sync();
494
- } finally {
495
- await handle.close();
496
- }
497
211
  if (!journalAlreadyExisted) await syncDirectory$1(parent);
498
212
  }
499
- enqueue(operation) {
500
- const result = this.operationQueue.then(operation);
501
- this.operationQueue = result.then(() => void 0, () => void 0);
502
- return result;
503
- }
504
213
  };
505
- function canonicalOperations(operations) {
506
- const unique = new Set(operations);
507
- return OPERATION_ORDER.filter((operation) => unique.has(operation));
508
- }
509
- function toRemJob(job) {
510
- return {
511
- job_id: job.waveId,
512
- state: job.state,
513
- type: job.requestedOperations[0] ?? "rem-replace",
514
- scope: job.scope,
515
- started_at: job.startedAt,
516
- finished_at: job.finishedAt,
517
- stats: job.stats,
518
- ...job.error === void 0 ? {} : { error: job.error },
519
- correlation_id: job.correlationId,
520
- requested_operations: [...job.requestedOperations]
521
- };
522
- }
523
214
  async function syncDirectory$1(directory) {
524
215
  if (process.platform === "win32") return;
525
216
  const handle = await open(directory, "r");
@@ -643,7 +334,7 @@ async function startOwnedRemSidecar() {
643
334
  async open() {
644
335
  if (currentMemory) return currentMemory;
645
336
  if (settingsError) throw settingsError;
646
- openingMemory ??= import("./memory-runtime-DSP8cXik.js").then((module) => module.MemoryRuntimePool.open()).then((pool) => {
337
+ openingMemory ??= import("./memory-runtime-HibOMCFa.js").then((module) => module.MemoryRuntimePool.open()).then((pool) => {
647
338
  currentMemory = pool;
648
339
  if (stopping) pool.stopTimers();
649
340
  return pool;
@@ -1038,7 +729,7 @@ async function runChassisJob(store, journal, waveId, holdMs, runtime) {
1038
729
  cleanRefusalReasons.push(reason);
1039
730
  await appendChassisRefusal(journal, queued, operation, "refused", reason);
1040
731
  }
1041
- const { runRemProductionOrderedWave } = await import("./rem-batch-executor-DsXWpJYU.js");
732
+ const { runRemProductionOrderedWave } = await import("./rem-batch-executor-8x4FBLtW.js");
1042
733
  const result = enabledOperations.length === 0 ? {
1043
734
  decision: "allow",
1044
735
  reasonCode: null,
@@ -1167,11 +858,15 @@ async function runChassisJob(store, journal, waveId, holdMs, runtime) {
1167
858
  }
1168
859
  async function persistCompletedJob(store, job, stats) {
1169
860
  const auditPersisted = await auditRem("rem_completed", job, { stats });
1170
- await store.transition(job.job_id, {
1171
- state: "done",
1172
- finished_at: (/* @__PURE__ */ new Date()).toISOString(),
1173
- stats
1174
- });
861
+ try {
862
+ await store.transition(job.job_id, {
863
+ state: "done",
864
+ finished_at: (/* @__PURE__ */ new Date()).toISOString(),
865
+ stats
866
+ });
867
+ } catch (error) {
868
+ reportSidecarFailure("completion-job-journal", error);
869
+ }
1175
870
  if (store.isPersisted(job.job_id)) return "job_journal";
1176
871
  if (auditPersisted) return "completed_audit";
1177
872
  reportSidecarFailure("completion-persistence", /* @__PURE__ */ new Error("completed work has no durable completion receipt"));
@@ -1268,6 +963,8 @@ async function recoverInterruptedJobs(store, completedJobStats, jobs) {
1268
963
  }
1269
964
  async function readCompletedJobStats(wantedJobs) {
1270
965
  const completed = /* @__PURE__ */ new Map();
966
+ if (wantedJobs.size === 0) return completed;
967
+ compactAuditLog(getAuditPath(getSnoStationMemStateDir()));
1271
968
  for await (const line of readJsonlLines(getAuditPath(getSnoStationMemStateDir()))) {
1272
969
  if (line.length === 0) continue;
1273
970
  try {
@@ -1,4 +1,4 @@
1
- import { jr as MEMORY_RECONNECT_INTERVAL_MS, m as isRemTraceEnabled, p as getRemTraceLogPath, v as SettingsUnavailableError } from "../config-BCZRhUvW.js";
1
+ import { jr as MEMORY_RECONNECT_INTERVAL_MS, m as isRemTraceEnabled, p as getRemTraceLogPath, v as SettingsUnavailableError } from "../config-C7LzSWhG.js";
2
2
  import { setTimeout } from "node:timers/promises";
3
3
  import { addLogFileTarget, closeLogger, createLogger } from "@snoai/utils/logger";
4
4
  //#region src/sidecar/main.ts
@@ -6,9 +6,9 @@ import { addLogFileTarget, closeLogger, createLogger } from "@snoai/utils/logger
6
6
  * @purpose Boots the standalone local REM sidecar process.
7
7
  * @boundary Process environment, sidecar lifecycle, and local request-log destination.
8
8
  */
9
- const { startRemSidecar, DuplicateSidecarError } = await import("../server-Dw34jY1d.js");
9
+ const { startRemSidecar, DuplicateSidecarError } = await import("../server-CCduS_Ea.js");
10
10
  let sidecar;
11
- while (!sidecar) try {
11
+ for (let attempt = 1; !sidecar; attempt++) try {
12
12
  sidecar = await startRemSidecar();
13
13
  } catch (error) {
14
14
  if (error instanceof DuplicateSidecarError) {
@@ -16,12 +16,19 @@ while (!sidecar) try {
16
16
  process.exit(0);
17
17
  }
18
18
  if (error instanceof SettingsUnavailableError) throw error;
19
- createLogger("sno-station-mem:sidecar").error("Memory service startup failed; retrying", { error }, {
19
+ createLogger("sno-station-mem:sidecar").error(attempt >= 3 ? "Memory service startup failed after three attempts; stopping" : "Memory service startup failed; retrying", {
20
+ error,
21
+ attempt
22
+ }, {
20
23
  event_name: "memory.sidecar.startup.failed",
21
24
  file: "packages/memory/src/sidecar/main.ts",
22
25
  function: "<module>",
23
26
  site_id: "sidecar.main.startup.failed"
24
27
  });
28
+ if (attempt >= 3) {
29
+ await closeLogger();
30
+ process.exit(1);
31
+ }
25
32
  await setTimeout(MEMORY_RECONNECT_INTERVAL_MS);
26
33
  }
27
34
  if (isRemTraceEnabled()) addLogFileTarget(getRemTraceLogPath());