@remnic/core 9.65.3 → 9.65.5

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 (436) hide show
  1. package/dist/access-admin-ops-surface.d.ts +11 -11
  2. package/dist/access-admin-ops-surface.js +20 -18
  3. package/dist/access-authorization-probe.d.ts +11 -11
  4. package/dist/access-authorization-probe.js +21 -19
  5. package/dist/access-boundary.d.ts +11 -11
  6. package/dist/access-boundary.js +20 -18
  7. package/dist/access-cli.js +55 -53
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-coding-context-resolution.d.ts +1 -1
  10. package/dist/access-extraction-force-flush.d.ts +11 -11
  11. package/dist/access-extraction-force-flush.js +20 -18
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-lcm-compaction.d.ts +11 -11
  14. package/dist/access-http-lifecycle-flush.d.ts +11 -11
  15. package/dist/access-http-offline-stream.d.ts +11 -11
  16. package/dist/access-http-query.d.ts +2 -2
  17. package/dist/access-http-query.js +22 -20
  18. package/dist/access-http.d.ts +12 -12
  19. package/dist/access-http.js +31 -29
  20. package/dist/access-identity-continuity-surface.d.ts +9 -9
  21. package/dist/access-identity-continuity-surface.js +20 -18
  22. package/dist/access-lcm-surface.d.ts +11 -11
  23. package/dist/access-lcm-surface.js +20 -18
  24. package/dist/access-mcp.d.ts +11 -11
  25. package/dist/access-mcp.js +25 -23
  26. package/dist/access-memory-search-fanout.d.ts +2 -2
  27. package/dist/{access-namespace-preflight-B7Usyz-K.d.ts → access-namespace-preflight-D_6mo8ms.d.ts} +1 -1
  28. package/dist/access-namespace-preflight.d.ts +3 -3
  29. package/dist/access-namespace-preflight.js +20 -18
  30. package/dist/access-observe-write-surface.d.ts +11 -11
  31. package/dist/access-observe-write-surface.js +20 -18
  32. package/dist/access-offline-manifest.d.ts +9 -9
  33. package/dist/access-offline-manifest.js +3 -3
  34. package/dist/access-operations-batch.js +21 -19
  35. package/dist/access-operations.d.ts +16 -16
  36. package/dist/access-operations.js +24 -22
  37. package/dist/access-recall-concurrency.d.ts +11 -11
  38. package/dist/access-recall-concurrency.js +20 -18
  39. package/dist/access-recall-response.d.ts +11 -11
  40. package/dist/access-recall-response.js +20 -18
  41. package/dist/access-recall-surface.d.ts +11 -11
  42. package/dist/access-recall-surface.js +20 -18
  43. package/dist/access-schema.d.ts +83 -83
  44. package/dist/access-service-helpers.d.ts +11 -11
  45. package/dist/{access-service-DkaIG3n8.d.ts → access-service-sbiNS5UB.d.ts} +71 -71
  46. package/dist/access-service.d.ts +11 -11
  47. package/dist/access-service.js +20 -18
  48. package/dist/access-surface-catalog.d.ts +11 -11
  49. package/dist/access-surface-catalog.js +22 -20
  50. package/dist/access-surface-catalog.js.map +1 -1
  51. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  52. package/dist/action-confidence.d.ts +1 -1
  53. package/dist/active-memory-bridge.d.ts +1 -1
  54. package/dist/active-recall.d.ts +1 -1
  55. package/dist/active-recall.js +5 -1
  56. package/dist/active-recall.js.map +1 -1
  57. package/dist/ambient-provenance.d.ts +1 -1
  58. package/dist/artifact-search.d.ts +1 -1
  59. package/dist/{auto-sync-H64ZCNIR.js → auto-sync-XVMLL2RH.js} +5 -5
  60. package/dist/behavior-learner.d.ts +1 -1
  61. package/dist/behavior-signals.d.ts +1 -1
  62. package/dist/bootstrap.d.ts +9 -9
  63. package/dist/briefing-window.d.ts +2 -2
  64. package/dist/briefing.d.ts +2 -2
  65. package/dist/briefing.js +4 -4
  66. package/dist/buffer-surprise-report.d.ts +1 -1
  67. package/dist/buffer-turn-helpers.d.ts +1 -1
  68. package/dist/buffer.d.ts +2 -2
  69. package/dist/bulk-import/index.d.ts +3 -3
  70. package/dist/calibration.d.ts +1 -1
  71. package/dist/capabilities.d.ts +1 -1
  72. package/dist/{catalog-CX2BZEJh.d.ts → catalog-DO_7zfkv.d.ts} +1 -1
  73. package/dist/causal-behavior.d.ts +1 -1
  74. package/dist/causal-consolidation.d.ts +1 -1
  75. package/dist/causal-consolidation.js +9 -6
  76. package/dist/causal-consolidation.js.map +1 -1
  77. package/dist/causal-trajectory-graph.d.ts +1 -1
  78. package/dist/chunk-236PXYG7.js +232 -0
  79. package/dist/chunk-236PXYG7.js.map +1 -0
  80. package/dist/{chunk-YF6UHWOV.js → chunk-2EPOGPKO.js} +3 -3
  81. package/dist/{chunk-IQSC3V2E.js → chunk-2IXQSGCU.js} +2 -2
  82. package/dist/{chunk-GUXS322H.js → chunk-2MVTAIL3.js} +2 -2
  83. package/dist/{chunk-TDKSCV62.js → chunk-3NH3VP3U.js} +2 -2
  84. package/dist/{chunk-6TAX66IA.js → chunk-4JSF7UUP.js} +2 -2
  85. package/dist/{chunk-URHCUXKI.js → chunk-AXGFOFNY.js} +2 -2
  86. package/dist/{chunk-BKYPJUQL.js → chunk-BA2GLSIP.js} +10 -10
  87. package/dist/{chunk-D27J626P.js → chunk-BK5G2MHO.js} +2 -2
  88. package/dist/{chunk-EV3YFLCB.js → chunk-BW4GAF57.js} +2 -2
  89. package/dist/{chunk-DHTQP334.js → chunk-CQBIN77D.js} +2 -2
  90. package/dist/{chunk-WN5FSGLE.js → chunk-CV3GNPOE.js} +45 -50
  91. package/dist/chunk-CV3GNPOE.js.map +1 -0
  92. package/dist/{chunk-6VALIZKG.js → chunk-DORFF5N5.js} +2 -2
  93. package/dist/{chunk-7QOO4LGC.js → chunk-DPGH6LHQ.js} +331 -73
  94. package/dist/chunk-DPGH6LHQ.js.map +1 -0
  95. package/dist/{chunk-76PL4XLG.js → chunk-DPNXADEI.js} +7 -2
  96. package/dist/chunk-DPNXADEI.js.map +1 -0
  97. package/dist/{chunk-MRTUN665.js → chunk-DUEDOYZD.js} +2 -2
  98. package/dist/{chunk-QFMO32TO.js → chunk-DUZARALI.js} +3 -3
  99. package/dist/{chunk-7KFIMGMP.js → chunk-ECLJ4LA2.js} +2 -2
  100. package/dist/{chunk-PDVQ5JU3.js → chunk-FBR7PIL4.js} +2 -2
  101. package/dist/{chunk-RK4WXUI2.js → chunk-HF5BUTI6.js} +2 -2
  102. package/dist/{chunk-3DVBKTSO.js → chunk-HSZMX3ZJ.js} +4 -4
  103. package/dist/{chunk-ODZG724P.js → chunk-I2HTKOOP.js} +2 -2
  104. package/dist/{chunk-GN55KU2P.js → chunk-IIRCHGWD.js} +2 -2
  105. package/dist/{chunk-AYYGRVRP.js → chunk-IURMJBGP.js} +2 -2
  106. package/dist/{chunk-4XDGYCZI.js → chunk-J3ATBB7M.js} +2 -2
  107. package/dist/{chunk-E4MVQQVX.js → chunk-JPAKBNTM.js} +2 -2
  108. package/dist/{chunk-NZWEEALH.js → chunk-KFIOPZ25.js} +2 -2
  109. package/dist/{chunk-EIVIB73I.js → chunk-KOO37E4Y.js} +2 -2
  110. package/dist/{chunk-VA5KMSAE.js → chunk-KTPXXVDQ.js} +3 -3
  111. package/dist/{chunk-NXKJHSDN.js → chunk-LBFFNDFM.js} +1 -1
  112. package/dist/chunk-LBFFNDFM.js.map +1 -0
  113. package/dist/{chunk-Z4RPXHJH.js → chunk-LYBIHM4N.js} +4 -4
  114. package/dist/{chunk-G57LQRP6.js → chunk-MFOSZUIT.js} +2 -2
  115. package/dist/{chunk-TYUS5TLG.js → chunk-N56GVOWR.js} +3 -3
  116. package/dist/{chunk-BQUEAVNW.js → chunk-NH6LC57D.js} +2 -2
  117. package/dist/{chunk-AUO2LJ3K.js → chunk-NLEH4RTB.js} +2 -2
  118. package/dist/{chunk-AYDDB3XI.js → chunk-OCCHUEZB.js} +2 -2
  119. package/dist/{chunk-57HVIG5U.js → chunk-OWQNJJY2.js} +2 -2
  120. package/dist/{chunk-OJD4WS2E.js → chunk-OZDFB22S.js} +2 -2
  121. package/dist/{chunk-2VXWFYJE.js → chunk-R2MZCYA6.js} +3 -3
  122. package/dist/{chunk-LBWQ65SX.js → chunk-T42L3S6A.js} +4 -4
  123. package/dist/{chunk-PAYGC3BD.js → chunk-THVI4Y7X.js} +7 -7
  124. package/dist/{chunk-S7Q5CM7E.js → chunk-TJFI3K2O.js} +15 -3
  125. package/dist/chunk-TJFI3K2O.js.map +1 -0
  126. package/dist/{chunk-R47WINCY.js → chunk-UCKG36HO.js} +2 -2
  127. package/dist/{chunk-QXIQPCCN.js → chunk-UFR6HX7A.js} +1 -1
  128. package/dist/{chunk-CDUUDBWJ.js → chunk-VFYRYFLL.js} +2 -2
  129. package/dist/{chunk-P4DHENRE.js → chunk-WDXD6ITO.js} +2 -2
  130. package/dist/{chunk-H5FW4S5Q.js → chunk-YB4GBWBU.js} +31 -31
  131. package/dist/{chunk-MBDJJTAT.js → chunk-YDKF4MSJ.js} +3 -3
  132. package/dist/{chunk-AZAA5DNP.js → chunk-YOXVZJFM.js} +2 -2
  133. package/dist/{chunk-OLWTCWQ2.js → chunk-YZJM6CLF.js} +8 -8
  134. package/dist/chunk-ZCUTSMR2.js +61 -0
  135. package/dist/chunk-ZCUTSMR2.js.map +1 -0
  136. package/dist/{chunk-LUNJ3WFO.js → chunk-ZK4BFABK.js} +4 -4
  137. package/dist/{chunk-RDFF2NAU.js → chunk-ZXBTTMGZ.js} +184 -88
  138. package/dist/chunk-ZXBTTMGZ.js.map +1 -0
  139. package/dist/{cli-ChKeYMZv.d.ts → cli-BqdqPdG_.d.ts} +5 -5
  140. package/dist/cli.d.ts +13 -13
  141. package/dist/cli.js +44 -42
  142. package/dist/coding/pre-action-gate.d.ts +1 -1
  143. package/dist/compounding/engine.d.ts +2 -2
  144. package/dist/compounding/engine.js +4 -4
  145. package/dist/compounding/preference-consolidator.d.ts +1 -1
  146. package/dist/compression-optimizer.d.ts +1 -1
  147. package/dist/config.d.ts +1 -1
  148. package/dist/config.js +5 -1
  149. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  150. package/dist/connectors/codex-materialize-runner.js +8 -5
  151. package/dist/connectors/codex-materialize.d.ts +14 -1
  152. package/dist/connectors/codex-materialize.js +10 -1
  153. package/dist/connectors/index.d.ts +1 -1
  154. package/dist/connectors/index.js +8 -5
  155. package/dist/consolidation-provenance-check.d.ts +2 -2
  156. package/dist/consolidation-undo.d.ts +2 -2
  157. package/dist/contradiction/index.d.ts +3 -3
  158. package/dist/contradiction/index.js +1 -1
  159. package/dist/converge-config.d.ts +1 -1
  160. package/dist/convergence-refresh.d.ts +2 -2
  161. package/dist/convergence-refresh.js +6 -6
  162. package/dist/conversation-index/backend.d.ts +1 -1
  163. package/dist/conversation-index/chunker.d.ts +1 -1
  164. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  165. package/dist/conversation-index/indexer.d.ts +1 -1
  166. package/dist/conversation-index/search.d.ts +1 -1
  167. package/dist/corpus-watermark.d.ts +1 -1
  168. package/dist/corpus-watermark.js +6 -6
  169. package/dist/cross-lingual-recall.d.ts +1 -1
  170. package/dist/day-summary.d.ts +1 -1
  171. package/dist/delinearize.d.ts +1 -1
  172. package/dist/dependency-propagation-config.d.ts +1 -1
  173. package/dist/{dependency-propagation-delivery-B8ZMBBCY.d.ts → dependency-propagation-delivery-D23_x-s5.d.ts} +1 -1
  174. package/dist/direct-answer-wiring.d.ts +1 -1
  175. package/dist/direct-answer.d.ts +1 -1
  176. package/dist/embedding-fallback.d.ts +1 -1
  177. package/dist/enrichment/index.d.ts +1 -1
  178. package/dist/entity-origin-fields.d.ts +1 -1
  179. package/dist/entity-retrieval.d.ts +2 -2
  180. package/dist/entity-retrieval.js +4 -4
  181. package/dist/entity-schema.d.ts +1 -1
  182. package/dist/episodic-context.d.ts +1 -1
  183. package/dist/explicit-capture.d.ts +9 -9
  184. package/dist/explicit-capture.js +1 -1
  185. package/dist/external-wiki-access.d.ts +11 -11
  186. package/dist/external-wiki-access.js +21 -19
  187. package/dist/external-wiki-collection-registration.d.ts +1 -1
  188. package/dist/external-wiki-collection.d.ts +1 -1
  189. package/dist/external-wiki-mcp-tools.d.ts +11 -11
  190. package/dist/extraction-error-classification.d.ts +1 -1
  191. package/dist/extraction-faithfulness.d.ts +1 -1
  192. package/dist/extraction-judge-telemetry.d.ts +1 -1
  193. package/dist/extraction-judge-training.d.ts +1 -1
  194. package/dist/extraction-judge.d.ts +1 -1
  195. package/dist/extraction-judge.js +2 -2
  196. package/dist/extraction-liveness.d.ts +1 -1
  197. package/dist/extraction-normalization.d.ts +1 -1
  198. package/dist/extraction-prompt.d.ts +1 -1
  199. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  200. package/dist/extraction-source-grounding.d.ts +1 -1
  201. package/dist/extraction.d.ts +1 -1
  202. package/dist/extraction.js +9 -7
  203. package/dist/fallback-llm.d.ts +1 -1
  204. package/dist/graph-dashboard-diff.d.ts +1 -1
  205. package/dist/graph-dashboard-key.d.ts +1 -1
  206. package/dist/graph-dashboard-parser.d.ts +1 -1
  207. package/dist/graph-edge-reinforcement.d.ts +1 -1
  208. package/dist/graph-path-reconstruction.d.ts +1 -1
  209. package/dist/graph-path-scoring.d.ts +1 -1
  210. package/dist/graph-snapshot.d.ts +1 -1
  211. package/dist/graph.d.ts +1 -1
  212. package/dist/harmonic-retrieval.js +1 -1
  213. package/dist/importance.d.ts +1 -1
  214. package/dist/importers/index.d.ts +1 -1
  215. package/dist/in-flight-reads.d.ts +1 -1
  216. package/dist/{index-CexDrJzC.d.ts → index--QhGIXF2.d.ts} +2 -2
  217. package/dist/index.d.ts +763 -716
  218. package/dist/index.js +79 -58
  219. package/dist/intent.d.ts +1 -1
  220. package/dist/lcm/engine.d.ts +1 -1
  221. package/dist/lcm/index.d.ts +1 -1
  222. package/dist/lcm/tools.d.ts +1 -1
  223. package/dist/lifecycle.d.ts +1 -1
  224. package/dist/live-connectors-runner.d.ts +1 -1
  225. package/dist/local-llm.d.ts +1 -1
  226. package/dist/local-model-endpoint.d.ts +1 -1
  227. package/dist/maintenance/memory-governance.d.ts +1 -1
  228. package/dist/maintenance/memory-governance.js +4 -4
  229. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  230. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +4 -4
  231. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  232. package/dist/maintenance/rebuild-memory-projection.js +5 -5
  233. package/dist/{maintenance-nkdtSrVr.d.ts → maintenance-PFvY1Pw_.d.ts} +3 -3
  234. package/dist/mcp-memory-inspector-app.d.ts +11 -11
  235. package/dist/memory-action-policy.d.ts +1 -1
  236. package/dist/memory-cache.d.ts +1 -1
  237. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  238. package/dist/memory-projection-store.d.ts +1 -1
  239. package/dist/memory-provenance.d.ts +1 -1
  240. package/dist/memory-snapshot.d.ts +1 -1
  241. package/dist/memory-subject-cli.d.ts +11 -11
  242. package/dist/memory-subject.d.ts +11 -11
  243. package/dist/memory-worth-outcomes.d.ts +2 -2
  244. package/dist/models-json.d.ts +1 -1
  245. package/dist/namespaces/migrate.d.ts +3 -3
  246. package/dist/namespaces/migrate.js +5 -5
  247. package/dist/namespaces/principal.d.ts +1 -1
  248. package/dist/namespaces/search.d.ts +1 -1
  249. package/dist/namespaces/storage.d.ts +3 -3
  250. package/dist/namespaces/storage.js +4 -4
  251. package/dist/native-knowledge.d.ts +1 -1
  252. package/dist/offline-sync-impression-drain.d.ts +1 -1
  253. package/dist/operator-doctor-corpus.d.ts +1 -1
  254. package/dist/operator-doctor-corpus.js +7 -7
  255. package/dist/operator-doctor-replica.d.ts +1 -1
  256. package/dist/operator-toolkit.d.ts +3 -3
  257. package/dist/operator-toolkit.js +16 -13
  258. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  259. package/dist/orchestration/maintenance.d.ts +4 -4
  260. package/dist/orchestration/maintenance.js +10 -10
  261. package/dist/{orchestrator-Bvq1-RQs.d.ts → orchestrator-4wzJrPVm.d.ts} +8 -8
  262. package/dist/orchestrator.d.ts +9 -9
  263. package/dist/orchestrator.js +55 -53
  264. package/dist/patterns-cli.d.ts +1 -1
  265. package/dist/{pipeline-C8vfIiTX.d.ts → pipeline-CgXgdIrF.d.ts} +1 -1
  266. package/dist/policy-runtime.d.ts +1 -1
  267. package/dist/proactive-contention.d.ts +1 -1
  268. package/dist/provenance.d.ts +1 -1
  269. package/dist/{public-http-Cy0aYbys.d.ts → public-http-BP3VQDl5.d.ts} +1 -1
  270. package/dist/{qmd-B9p1SZTZ.d.ts → qmd-BppGGxsi.d.ts} +1 -1
  271. package/dist/qmd-preflight.d.ts +2 -2
  272. package/dist/qmd-recall-cache.d.ts +1 -1
  273. package/dist/qmd.d.ts +2 -2
  274. package/dist/recall-concurrency-config.d.ts +1 -1
  275. package/dist/recall-disclosure-escalation.d.ts +1 -1
  276. package/dist/recall-explain-renderer.d.ts +1 -1
  277. package/dist/recall-explain-renderer.js +3 -3
  278. package/dist/recall-memory-map.d.ts +1 -1
  279. package/dist/recall-planner-llm.d.ts +1 -1
  280. package/dist/recall-state.d.ts +1 -1
  281. package/dist/recall-tag-filter.d.ts +1 -1
  282. package/dist/recall-timings.d.ts +1 -1
  283. package/dist/recall-xray-cli.d.ts +1 -1
  284. package/dist/recall-xray-cli.js +4 -4
  285. package/dist/recall-xray-renderer.d.ts +1 -1
  286. package/dist/recall-xray-renderer.js +3 -3
  287. package/dist/recall-xray.d.ts +1 -1
  288. package/dist/recall-xray.js +2 -2
  289. package/dist/reconcile/cursor.d.ts +1 -1
  290. package/dist/reconcile/manifest.d.ts +1 -1
  291. package/dist/reconcile/manifest.js +2 -2
  292. package/dist/reconcile/plan.d.ts +1 -1
  293. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  294. package/dist/replay/normalizers/claude.d.ts +1 -1
  295. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  296. package/dist/replay/normalizers/shared.d.ts +1 -1
  297. package/dist/replay/runner.d.ts +1 -1
  298. package/dist/replay/types.d.ts +1 -1
  299. package/dist/replica-divergence.d.ts +1 -1
  300. package/dist/replica-peers-config.d.ts +1 -1
  301. package/dist/resolution-4552BNRV.js +1 -1
  302. package/dist/resolve-auth-token.d.ts +1 -1
  303. package/dist/resume-bundles.js +6 -2
  304. package/dist/retrieval-agents.d.ts +2 -2
  305. package/dist/retrieval-tiers.d.ts +1 -1
  306. package/dist/routing/engine.d.ts +1 -1
  307. package/dist/routing/store.d.ts +1 -1
  308. package/dist/salvage-envelope.d.ts +1 -1
  309. package/dist/salvage-envelope.js +1 -1
  310. package/dist/schemas.d.ts +136 -136
  311. package/dist/{scope-profiles-DLrRxFWR.d.ts → scope-profiles-ChZUtxDU.d.ts} +1 -1
  312. package/dist/search/embed-helper.d.ts +1 -1
  313. package/dist/search/factory.d.ts +1 -1
  314. package/dist/search/index.d.ts +1 -1
  315. package/dist/search/lancedb-backend.d.ts +1 -1
  316. package/dist/search/meilisearch-backend.d.ts +1 -1
  317. package/dist/search/noop-backend.d.ts +1 -1
  318. package/dist/search/orama-backend.d.ts +1 -1
  319. package/dist/search/port.d.ts +1 -1
  320. package/dist/search/remote-backend.d.ts +1 -1
  321. package/dist/{semantic-consolidation-DlN6xe20.d.ts → semantic-consolidation-mSPwQSmF.d.ts} +1 -1
  322. package/dist/semantic-consolidation.d.ts +2 -2
  323. package/dist/semantic-consolidation.js +9 -6
  324. package/dist/semantic-rule-promotion.js +4 -4
  325. package/dist/semantic-rule-verifier.d.ts +1 -1
  326. package/dist/semantic-rule-verifier.js +4 -4
  327. package/dist/{service-GkYyVfm9.d.ts → service-BICWLwSP.d.ts} +2 -2
  328. package/dist/session-observer-bands.d.ts +1 -1
  329. package/dist/session-observer-state.d.ts +1 -1
  330. package/dist/shared-context/manager.d.ts +7 -7
  331. package/dist/signal.d.ts +1 -1
  332. package/dist/skills-registry.js +4 -56
  333. package/dist/skills-registry.js.map +1 -1
  334. package/dist/source-agent-qualifier.d.ts +1 -1
  335. package/dist/source-agent-qualifier.js +8 -5
  336. package/dist/{storage-BIDzuKIn.d.ts → storage-B7urx1K3.d.ts} +1 -1
  337. package/dist/storage.d.ts +2 -2
  338. package/dist/storage.js +6 -6
  339. package/dist/subject-config.d.ts +1 -1
  340. package/dist/summarizer.d.ts +1 -1
  341. package/dist/summary-snapshot.d.ts +1 -1
  342. package/dist/support-passport/index.d.ts +14 -14
  343. package/dist/support-passport/index.js +23 -21
  344. package/dist/temporal-supersession.d.ts +2 -2
  345. package/dist/temporal-timeline-recall.d.ts +1 -1
  346. package/dist/temporal-validity.d.ts +1 -1
  347. package/dist/threading.d.ts +1 -1
  348. package/dist/tier-migration.d.ts +2 -2
  349. package/dist/tier-routing.d.ts +1 -1
  350. package/dist/topics.d.ts +1 -1
  351. package/dist/transcript.d.ts +1 -1
  352. package/dist/transfer/types.d.ts +78 -78
  353. package/dist/trust-score-stage.d.ts +1 -1
  354. package/dist/trust-score.d.ts +1 -1
  355. package/dist/{types-BxAcOl5Q.d.ts → types-ETU5N6nB.d.ts} +111 -4
  356. package/dist/types.d.ts +1 -1
  357. package/dist/types.js +1 -1
  358. package/dist/utility-runtime.d.ts +1 -1
  359. package/dist/verified-recall.js +4 -4
  360. package/dist/who-knows-cli.d.ts +11 -11
  361. package/dist/who-knows-cli.js +5 -5
  362. package/dist/who-knows.d.ts +11 -11
  363. package/dist/who-knows.js +4 -4
  364. package/dist/write-envelope.d.ts +1 -1
  365. package/dist/write-envelope.js +1 -1
  366. package/package.json +2 -2
  367. package/src/cli/skills-commands.ts +150 -0
  368. package/src/cli.ts +4 -2
  369. package/src/config.ts +4 -2
  370. package/src/connectors/codex-materialize-runner.ts +16 -0
  371. package/src/connectors/codex-materialize-skills.test.ts +141 -0
  372. package/src/connectors/codex-materialize.ts +58 -40
  373. package/src/connectors/materialize-paths.ts +50 -0
  374. package/src/connectors/materialize-skills.ts +127 -0
  375. package/src/index.ts +5 -10
  376. package/src/procedural/skill-io.test.ts +190 -0
  377. package/src/procedural/skill-io.ts +220 -0
  378. package/src/procedural/skill-projection.test.ts +214 -0
  379. package/src/procedural/skill-projection.ts +356 -0
  380. package/src/review/frontmatter.test.ts +15 -0
  381. package/src/review/frontmatter.ts +20 -0
  382. package/src/review/review-deck-snapshot.ts +4 -20
  383. package/src/review/review-deck.ts +1 -12
  384. package/src/types.ts +2 -3
  385. package/dist/chunk-76PL4XLG.js.map +0 -1
  386. package/dist/chunk-7QOO4LGC.js.map +0 -1
  387. package/dist/chunk-NXKJHSDN.js.map +0 -1
  388. package/dist/chunk-RDFF2NAU.js.map +0 -1
  389. package/dist/chunk-S7Q5CM7E.js.map +0 -1
  390. package/dist/chunk-WN5FSGLE.js.map +0 -1
  391. /package/dist/{auto-sync-H64ZCNIR.js.map → auto-sync-XVMLL2RH.js.map} +0 -0
  392. /package/dist/{chunk-YF6UHWOV.js.map → chunk-2EPOGPKO.js.map} +0 -0
  393. /package/dist/{chunk-IQSC3V2E.js.map → chunk-2IXQSGCU.js.map} +0 -0
  394. /package/dist/{chunk-GUXS322H.js.map → chunk-2MVTAIL3.js.map} +0 -0
  395. /package/dist/{chunk-TDKSCV62.js.map → chunk-3NH3VP3U.js.map} +0 -0
  396. /package/dist/{chunk-6TAX66IA.js.map → chunk-4JSF7UUP.js.map} +0 -0
  397. /package/dist/{chunk-URHCUXKI.js.map → chunk-AXGFOFNY.js.map} +0 -0
  398. /package/dist/{chunk-BKYPJUQL.js.map → chunk-BA2GLSIP.js.map} +0 -0
  399. /package/dist/{chunk-D27J626P.js.map → chunk-BK5G2MHO.js.map} +0 -0
  400. /package/dist/{chunk-EV3YFLCB.js.map → chunk-BW4GAF57.js.map} +0 -0
  401. /package/dist/{chunk-DHTQP334.js.map → chunk-CQBIN77D.js.map} +0 -0
  402. /package/dist/{chunk-6VALIZKG.js.map → chunk-DORFF5N5.js.map} +0 -0
  403. /package/dist/{chunk-MRTUN665.js.map → chunk-DUEDOYZD.js.map} +0 -0
  404. /package/dist/{chunk-QFMO32TO.js.map → chunk-DUZARALI.js.map} +0 -0
  405. /package/dist/{chunk-7KFIMGMP.js.map → chunk-ECLJ4LA2.js.map} +0 -0
  406. /package/dist/{chunk-PDVQ5JU3.js.map → chunk-FBR7PIL4.js.map} +0 -0
  407. /package/dist/{chunk-RK4WXUI2.js.map → chunk-HF5BUTI6.js.map} +0 -0
  408. /package/dist/{chunk-3DVBKTSO.js.map → chunk-HSZMX3ZJ.js.map} +0 -0
  409. /package/dist/{chunk-ODZG724P.js.map → chunk-I2HTKOOP.js.map} +0 -0
  410. /package/dist/{chunk-GN55KU2P.js.map → chunk-IIRCHGWD.js.map} +0 -0
  411. /package/dist/{chunk-AYYGRVRP.js.map → chunk-IURMJBGP.js.map} +0 -0
  412. /package/dist/{chunk-4XDGYCZI.js.map → chunk-J3ATBB7M.js.map} +0 -0
  413. /package/dist/{chunk-E4MVQQVX.js.map → chunk-JPAKBNTM.js.map} +0 -0
  414. /package/dist/{chunk-NZWEEALH.js.map → chunk-KFIOPZ25.js.map} +0 -0
  415. /package/dist/{chunk-EIVIB73I.js.map → chunk-KOO37E4Y.js.map} +0 -0
  416. /package/dist/{chunk-VA5KMSAE.js.map → chunk-KTPXXVDQ.js.map} +0 -0
  417. /package/dist/{chunk-Z4RPXHJH.js.map → chunk-LYBIHM4N.js.map} +0 -0
  418. /package/dist/{chunk-G57LQRP6.js.map → chunk-MFOSZUIT.js.map} +0 -0
  419. /package/dist/{chunk-TYUS5TLG.js.map → chunk-N56GVOWR.js.map} +0 -0
  420. /package/dist/{chunk-BQUEAVNW.js.map → chunk-NH6LC57D.js.map} +0 -0
  421. /package/dist/{chunk-AUO2LJ3K.js.map → chunk-NLEH4RTB.js.map} +0 -0
  422. /package/dist/{chunk-AYDDB3XI.js.map → chunk-OCCHUEZB.js.map} +0 -0
  423. /package/dist/{chunk-57HVIG5U.js.map → chunk-OWQNJJY2.js.map} +0 -0
  424. /package/dist/{chunk-OJD4WS2E.js.map → chunk-OZDFB22S.js.map} +0 -0
  425. /package/dist/{chunk-2VXWFYJE.js.map → chunk-R2MZCYA6.js.map} +0 -0
  426. /package/dist/{chunk-LBWQ65SX.js.map → chunk-T42L3S6A.js.map} +0 -0
  427. /package/dist/{chunk-PAYGC3BD.js.map → chunk-THVI4Y7X.js.map} +0 -0
  428. /package/dist/{chunk-R47WINCY.js.map → chunk-UCKG36HO.js.map} +0 -0
  429. /package/dist/{chunk-QXIQPCCN.js.map → chunk-UFR6HX7A.js.map} +0 -0
  430. /package/dist/{chunk-CDUUDBWJ.js.map → chunk-VFYRYFLL.js.map} +0 -0
  431. /package/dist/{chunk-P4DHENRE.js.map → chunk-WDXD6ITO.js.map} +0 -0
  432. /package/dist/{chunk-H5FW4S5Q.js.map → chunk-YB4GBWBU.js.map} +0 -0
  433. /package/dist/{chunk-MBDJJTAT.js.map → chunk-YDKF4MSJ.js.map} +0 -0
  434. /package/dist/{chunk-AZAA5DNP.js.map → chunk-YOXVZJFM.js.map} +0 -0
  435. /package/dist/{chunk-OLWTCWQ2.js.map → chunk-YZJM6CLF.js.map} +0 -0
  436. /package/dist/{chunk-LUNJ3WFO.js.map → chunk-ZK4BFABK.js.map} +0 -0
@@ -1,6 +1,16 @@
1
1
  import {
2
2
  estimateTokenCount
3
3
  } from "./chunk-TOTT6S2V.js";
4
+ import {
5
+ SKILL_FILE_NAME,
6
+ renderSkillBundle
7
+ } from "./chunk-236PXYG7.js";
8
+ import {
9
+ isValidSkillSlug
10
+ } from "./chunk-ZCUTSMR2.js";
11
+ import {
12
+ pathIsInside
13
+ } from "./chunk-GCASGYIO.js";
4
14
  import {
5
15
  expandTildePath
6
16
  } from "./chunk-EYIEWJNI.js";
@@ -16,8 +26,105 @@ import {
16
26
  import {
17
27
  createHash
18
28
  } from "crypto";
29
+ import fs3 from "fs";
30
+ import path3 from "path";
31
+
32
+ // src/connectors/materialize-paths.ts
19
33
  import fs from "fs";
20
34
  import path from "path";
35
+ function ensureSafeManagedSubdir(memoriesDir, subdir, label) {
36
+ const memoriesReal = fs.realpathSync(memoriesDir);
37
+ try {
38
+ const stat = fs.lstatSync(subdir);
39
+ if (stat.isSymbolicLink()) {
40
+ throw new Error("is a symbolic link");
41
+ }
42
+ if (!stat.isDirectory()) {
43
+ throw new Error("is not a directory");
44
+ }
45
+ } catch (err) {
46
+ if (err.code !== "ENOENT") {
47
+ throw new Error(
48
+ `codex-materialize: unsafe ${label} directory at ${subdir}: ${err instanceof Error ? err.message : String(err)}`
49
+ );
50
+ }
51
+ fs.mkdirSync(subdir, { recursive: true });
52
+ }
53
+ const subdirReal = fs.realpathSync(subdir);
54
+ if (!pathIsInside(memoriesReal, subdirReal)) {
55
+ throw new Error(
56
+ `codex-materialize: unsafe ${label} directory at ${subdir}: resolves outside ${memoriesDir}`
57
+ );
58
+ }
59
+ return path.normalize(subdir);
60
+ }
61
+
62
+ // src/connectors/materialize-skills.ts
63
+ import fs2 from "fs";
64
+ import path2 from "path";
65
+ var SKILLS_SUBDIR = "skills";
66
+ function planSkillFiles(bundles, previouslyProjectedSlugs) {
67
+ const files = [];
68
+ const seen = /* @__PURE__ */ new Set();
69
+ for (const bundle of bundles ?? []) {
70
+ if (!isValidSkillSlug(bundle.slug) || seen.has(bundle.slug)) continue;
71
+ seen.add(bundle.slug);
72
+ files.push({ slug: bundle.slug, body: renderSkillBundle(bundle) });
73
+ }
74
+ const previous = previouslyProjectedSlugs.filter((slug) => isValidSkillSlug(slug));
75
+ return {
76
+ supplied: bundles !== void 0,
77
+ files,
78
+ retiredSlugs: bundles === void 0 ? [] : previous.filter((slug) => !seen.has(slug))
79
+ };
80
+ }
81
+ function skillFilePath(memoriesDir, slug) {
82
+ return path2.join(memoriesDir, SKILLS_SUBDIR, slug, SKILL_FILE_NAME);
83
+ }
84
+ function skillFileRelPath(slug) {
85
+ return path2.join(SKILLS_SUBDIR, slug, SKILL_FILE_NAME);
86
+ }
87
+ function retiredSkillsAlreadyRemoved(memoriesDir, retiredSlugs) {
88
+ return retiredSlugs.every((slug) => !fs2.existsSync(path2.join(memoriesDir, SKILLS_SUBDIR, slug)));
89
+ }
90
+ function stageSkillFiles(tmpDir, files) {
91
+ for (const file of files) {
92
+ const stagedDir = path2.join(tmpDir, SKILLS_SUBDIR, file.slug);
93
+ fs2.mkdirSync(stagedDir, { recursive: true });
94
+ fs2.writeFileSync(path2.join(stagedDir, SKILL_FILE_NAME), file.body);
95
+ }
96
+ }
97
+ function commitSkillFiles(memoriesDir, tmpDir, plan) {
98
+ if (!plan.supplied) return;
99
+ if (plan.files.length === 0 && plan.retiredSlugs.length === 0) return;
100
+ const skillsDir = ensureSafeManagedSubdir(memoriesDir, path2.join(memoriesDir, SKILLS_SUBDIR), SKILLS_SUBDIR);
101
+ for (const slug of plan.retiredSlugs) {
102
+ const retiredDir = path2.join(skillsDir, slug);
103
+ try {
104
+ if (fs2.lstatSync(retiredDir).isSymbolicLink()) continue;
105
+ } catch (err) {
106
+ if (err.code === "ENOENT") continue;
107
+ throw err;
108
+ }
109
+ try {
110
+ fs2.rmSync(retiredDir, { recursive: true, force: true });
111
+ } catch (err) {
112
+ throw new Error(
113
+ `codex-materialize: failed to remove retired skill ${slug}: ${err instanceof Error ? err.message : String(err)}`
114
+ );
115
+ }
116
+ }
117
+ for (const file of plan.files) {
118
+ const destDir = path2.join(skillsDir, file.slug);
119
+ fs2.mkdirSync(destDir, { recursive: true });
120
+ fs2.renameSync(
121
+ path2.join(tmpDir, SKILLS_SUBDIR, file.slug, SKILL_FILE_NAME),
122
+ path2.join(destDir, SKILL_FILE_NAME)
123
+ );
124
+ }
125
+ }
126
+
127
+ // src/connectors/codex-materialize.ts
21
128
  var MATERIALIZE_VERSION = 1;
22
129
  var SENTINEL_FILE = ".remnic-managed";
23
130
  var TMP_DIR = ".remnic-tmp";
@@ -37,10 +144,10 @@ function materializeForNamespace(namespace, options) {
37
144
  const now = options.now ?? /* @__PURE__ */ new Date();
38
145
  const maxSummaryTokens = typeof options.maxSummaryTokens === "number" && options.maxSummaryTokens >= 0 ? options.maxSummaryTokens : 4500;
39
146
  const rolloutRetentionDays = typeof options.rolloutRetentionDays === "number" && options.rolloutRetentionDays >= 0 ? options.rolloutRetentionDays : 30;
40
- const sentinelPath = path.join(memoriesDir, SENTINEL_FILE);
147
+ const sentinelPath = path3.join(memoriesDir, SENTINEL_FILE);
41
148
  const existingSentinel = readSentinel(sentinelPath);
42
149
  if (!existingSentinel) {
43
- if (fs.existsSync(memoriesDir)) {
150
+ if (fs3.existsSync(memoriesDir)) {
44
151
  logger.warn(
45
152
  `sentinel ${SENTINEL_FILE} missing in ${memoriesDir}; skipping materialization to preserve hand-edits`
46
153
  );
@@ -59,7 +166,7 @@ function materializeForNamespace(namespace, options) {
59
166
  contentHash: ""
60
167
  };
61
168
  }
62
- fs.mkdirSync(memoriesDir, { recursive: true });
169
+ fs3.mkdirSync(memoriesDir, { recursive: true });
63
170
  const memories = [...options.memories];
64
171
  const rolloutsSupplied = options.rolloutSummaries !== void 0;
65
172
  const rolloutSummaries = options.rolloutSummaries ?? [];
@@ -106,28 +213,32 @@ function materializeForNamespace(namespace, options) {
106
213
  name: `${sanitizeSlug(r.slug)}.md`,
107
214
  body: renderRolloutSummary(r)
108
215
  }));
109
- const destRolloutsDir = path.join(memoriesDir, ROLLOUT_SUBDIR);
216
+ const destRolloutsDir = path3.join(memoriesDir, ROLLOUT_SUBDIR);
110
217
  const retainedRolloutNames = new Set(rolloutFiles.map((r) => r.name));
218
+ const skillPlan = planSkillFiles(options.skills, existingSentinel.projected_skills ?? []);
111
219
  const hash = computeContentHash({
112
220
  namespace,
113
221
  memorySummary,
114
222
  memoryMd,
115
223
  rawMemories,
116
- rolloutFiles
224
+ rolloutFiles,
225
+ skillFiles: skillPlan.files
117
226
  });
118
227
  if (existingSentinel.content_hash === hash) {
119
228
  const requiredFiles = [
120
- path.join(memoriesDir, "memory_summary.md"),
121
- path.join(memoriesDir, "MEMORY.md"),
122
- path.join(memoriesDir, "raw_memories.md"),
123
- ...rolloutFiles.map((r) => path.join(memoriesDir, ROLLOUT_SUBDIR, r.name))
229
+ path3.join(memoriesDir, "memory_summary.md"),
230
+ path3.join(memoriesDir, "MEMORY.md"),
231
+ path3.join(memoriesDir, "raw_memories.md"),
232
+ ...rolloutFiles.map((r) => path3.join(memoriesDir, ROLLOUT_SUBDIR, r.name)),
233
+ ...skillPlan.files.map((s) => skillFilePath(memoriesDir, s.slug))
124
234
  ];
125
- const allPresent = requiredFiles.every((f) => fs.existsSync(f));
235
+ const allPresent = requiredFiles.every((f) => fs3.existsSync(f));
126
236
  const rolloutsClean = !rolloutsSupplied || rolloutDirectoryMatchesRetainedSet(
127
- ensureSafeRolloutsDir(memoriesDir, destRolloutsDir),
237
+ ensureSafeManagedSubdir(memoriesDir, destRolloutsDir, ROLLOUT_SUBDIR),
128
238
  retainedRolloutNames
129
239
  );
130
- if (allPresent && rolloutsClean) {
240
+ const skillsClean = retiredSkillsAlreadyRemoved(memoriesDir, skillPlan.retiredSlugs);
241
+ if (allPresent && rolloutsClean && skillsClean) {
131
242
  logger.debug?.(`no-op materialization for namespace=${namespace} (hash unchanged)`);
132
243
  return {
133
244
  namespace,
@@ -144,46 +255,50 @@ function materializeForNamespace(namespace, options) {
144
255
  );
145
256
  }
146
257
  const runTag = `${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
147
- const tmpDir = path.join(memoriesDir, `${TMP_DIR}-${runTag}`);
258
+ const tmpDir = path3.join(memoriesDir, `${TMP_DIR}-${runTag}`);
148
259
  const TMP_STALE_MS = 60 * 60 * 1e3;
149
260
  const wallClockMs = Date.now();
150
261
  try {
151
- for (const entry of fs.readdirSync(memoriesDir, { withFileTypes: true })) {
262
+ for (const entry of fs3.readdirSync(memoriesDir, { withFileTypes: true })) {
152
263
  if (!entry.isDirectory()) continue;
153
264
  if (!entry.name.startsWith(TMP_DIR)) continue;
154
- const stalePath = path.join(memoriesDir, entry.name);
265
+ const stalePath = path3.join(memoriesDir, entry.name);
155
266
  try {
156
- const stat = fs.statSync(stalePath);
267
+ const stat = fs3.statSync(stalePath);
157
268
  if (wallClockMs - stat.mtimeMs < TMP_STALE_MS) continue;
158
- fs.rmSync(stalePath, { recursive: true, force: true });
269
+ fs3.rmSync(stalePath, { recursive: true, force: true });
159
270
  } catch {
160
271
  }
161
272
  }
162
273
  } catch {
163
274
  }
164
- fs.mkdirSync(tmpDir, { recursive: true });
165
- fs.mkdirSync(path.join(tmpDir, ROLLOUT_SUBDIR), { recursive: true });
275
+ fs3.mkdirSync(tmpDir, { recursive: true });
276
+ fs3.mkdirSync(path3.join(tmpDir, ROLLOUT_SUBDIR), { recursive: true });
166
277
  const filesWritten = [];
167
- fs.writeFileSync(path.join(tmpDir, "memory_summary.md"), memorySummary);
278
+ fs3.writeFileSync(path3.join(tmpDir, "memory_summary.md"), memorySummary);
168
279
  filesWritten.push("memory_summary.md");
169
- fs.writeFileSync(path.join(tmpDir, "MEMORY.md"), memoryMd);
280
+ fs3.writeFileSync(path3.join(tmpDir, "MEMORY.md"), memoryMd);
170
281
  filesWritten.push("MEMORY.md");
171
- fs.writeFileSync(path.join(tmpDir, "raw_memories.md"), rawMemories);
282
+ fs3.writeFileSync(path3.join(tmpDir, "raw_memories.md"), rawMemories);
172
283
  filesWritten.push("raw_memories.md");
173
284
  for (const rollout of rolloutFiles) {
174
- fs.writeFileSync(path.join(tmpDir, ROLLOUT_SUBDIR, rollout.name), rollout.body);
175
- filesWritten.push(path.join(ROLLOUT_SUBDIR, rollout.name));
285
+ fs3.writeFileSync(path3.join(tmpDir, ROLLOUT_SUBDIR, rollout.name), rollout.body);
286
+ filesWritten.push(path3.join(ROLLOUT_SUBDIR, rollout.name));
287
+ }
288
+ stageSkillFiles(tmpDir, skillPlan.files);
289
+ for (const skill of skillPlan.files) {
290
+ filesWritten.push(skillFileRelPath(skill.slug));
176
291
  }
177
292
  for (const rel of ["memory_summary.md", "MEMORY.md", "raw_memories.md"]) {
178
- const src = path.join(tmpDir, rel);
179
- const dest = path.join(memoriesDir, rel);
180
- fs.renameSync(src, dest);
293
+ const src = path3.join(tmpDir, rel);
294
+ const dest = path3.join(memoriesDir, rel);
295
+ fs3.renameSync(src, dest);
181
296
  }
182
- const safeDestRolloutsDir = ensureSafeRolloutsDir(memoriesDir, destRolloutsDir);
297
+ const safeDestRolloutsDir = ensureSafeManagedSubdir(memoriesDir, destRolloutsDir, ROLLOUT_SUBDIR);
183
298
  if (rolloutsSupplied) {
184
299
  let existingRollouts;
185
300
  try {
186
- existingRollouts = fs.readdirSync(safeDestRolloutsDir, { withFileTypes: true });
301
+ existingRollouts = fs3.readdirSync(safeDestRolloutsDir, { withFileTypes: true });
187
302
  } catch (err) {
188
303
  if (err.code !== "ENOENT") throw err;
189
304
  existingRollouts = [];
@@ -193,7 +308,7 @@ function materializeForNamespace(namespace, options) {
193
308
  if (!entry.name.endsWith(".md")) continue;
194
309
  if (retainedRolloutNames.has(entry.name)) continue;
195
310
  try {
196
- fs.unlinkSync(path.join(safeDestRolloutsDir, entry.name));
311
+ fs3.unlinkSync(path3.join(safeDestRolloutsDir, entry.name));
197
312
  } catch (err) {
198
313
  throw new Error(
199
314
  `codex-materialize: failed to prune stale rollout summary ${entry.name}: ${err instanceof Error ? err.message : String(err)}`
@@ -202,19 +317,21 @@ function materializeForNamespace(namespace, options) {
202
317
  }
203
318
  }
204
319
  for (const rollout of rolloutFiles) {
205
- const src = path.join(tmpDir, ROLLOUT_SUBDIR, rollout.name);
206
- const dest = path.join(safeDestRolloutsDir, rollout.name);
207
- fs.renameSync(src, dest);
320
+ const src = path3.join(tmpDir, ROLLOUT_SUBDIR, rollout.name);
321
+ const dest = path3.join(safeDestRolloutsDir, rollout.name);
322
+ fs3.renameSync(src, dest);
208
323
  }
324
+ commitSkillFiles(memoriesDir, tmpDir, skillPlan);
209
325
  const sentinel = {
210
326
  version: MATERIALIZE_VERSION,
211
327
  namespace,
212
328
  updated_at: now.toISOString(),
213
- content_hash: hash
329
+ content_hash: hash,
330
+ projected_skills: skillPlan.supplied ? skillPlan.files.map((s) => s.slug) : existingSentinel.projected_skills ?? []
214
331
  };
215
332
  writeSentinelAtomically(sentinelPath, sentinel);
216
333
  try {
217
- fs.rmSync(tmpDir, { recursive: true, force: true });
334
+ fs3.rmSync(tmpDir, { recursive: true, force: true });
218
335
  } catch {
219
336
  }
220
337
  logger.info(
@@ -231,9 +348,9 @@ function materializeForNamespace(namespace, options) {
231
348
  };
232
349
  }
233
350
  function ensureSentinel(memoriesDir, namespace, now = /* @__PURE__ */ new Date()) {
234
- fs.mkdirSync(memoriesDir, { recursive: true });
235
- const sentinelPath = path.join(memoriesDir, SENTINEL_FILE);
236
- if (fs.existsSync(sentinelPath)) {
351
+ fs3.mkdirSync(memoriesDir, { recursive: true });
352
+ const sentinelPath = path3.join(memoriesDir, SENTINEL_FILE);
353
+ if (fs3.existsSync(sentinelPath)) {
237
354
  readSentinel(sentinelPath);
238
355
  return;
239
356
  }
@@ -444,24 +561,24 @@ function validateMemoryMd(content) {
444
561
  }
445
562
  function resolveCodexHome(override) {
446
563
  if (override && override.trim().length > 0) {
447
- return path.resolve(expandTildePath(override.trim()));
564
+ return path3.resolve(expandTildePath(override.trim()));
448
565
  }
449
566
  const fromEnv = readEnvVar("CODEX_HOME");
450
567
  if (fromEnv && fromEnv.trim().length > 0) {
451
- return path.resolve(expandTildePath(fromEnv.trim()));
568
+ return path3.resolve(expandTildePath(fromEnv.trim()));
452
569
  }
453
- return path.resolve(resolveHomeDir(), ".codex");
570
+ return path3.resolve(resolveHomeDir(), ".codex");
454
571
  }
455
572
  function resolveCodexMemoriesDir(codexHome) {
456
- return path.join(resolveCodexHome(codexHome), "memories");
573
+ return path3.join(resolveCodexHome(codexHome), "memories");
457
574
  }
458
575
  function hasCodexMaterializeSentinel(codexHome) {
459
- return readSentinel(path.join(resolveCodexMemoriesDir(codexHome), SENTINEL_FILE)) !== null;
576
+ return readSentinel(path3.join(resolveCodexMemoriesDir(codexHome), SENTINEL_FILE)) !== null;
460
577
  }
461
578
  function rolloutDirectoryMatchesRetainedSet(rolloutsDir, retainedNames) {
462
579
  let entries;
463
580
  try {
464
- entries = fs.readdirSync(rolloutsDir, { withFileTypes: true });
581
+ entries = fs3.readdirSync(rolloutsDir, { withFileTypes: true });
465
582
  } catch {
466
583
  return retainedNames.size === 0;
467
584
  }
@@ -472,49 +589,21 @@ function rolloutDirectoryMatchesRetainedSet(rolloutsDir, retainedNames) {
472
589
  }
473
590
  return true;
474
591
  }
475
- function isPathInside(parent, child) {
476
- const relative = path.relative(parent, child);
477
- return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
478
- }
479
- function ensureSafeRolloutsDir(memoriesDir, rolloutsDir) {
480
- const memoriesReal = fs.realpathSync(memoriesDir);
481
- try {
482
- const stat = fs.lstatSync(rolloutsDir);
483
- if (stat.isSymbolicLink()) {
484
- throw new Error("is a symbolic link");
485
- }
486
- if (!stat.isDirectory()) {
487
- throw new Error("is not a directory");
488
- }
489
- } catch (err) {
490
- if (err.code !== "ENOENT") {
491
- throw new Error(
492
- `codex-materialize: unsafe ${ROLLOUT_SUBDIR} directory at ${rolloutsDir}: ${err instanceof Error ? err.message : String(err)}`
493
- );
494
- }
495
- fs.mkdirSync(rolloutsDir, { recursive: true });
496
- }
497
- const rolloutsReal = fs.realpathSync(rolloutsDir);
498
- if (!isPathInside(memoriesReal, rolloutsReal)) {
499
- throw new Error(
500
- `codex-materialize: unsafe ${ROLLOUT_SUBDIR} directory at ${rolloutsDir}: resolves outside ${memoriesDir}`
501
- );
502
- }
503
- return rolloutsDir;
504
- }
505
592
  function readSentinel(sentinelPath) {
506
- if (!fs.existsSync(sentinelPath)) return null;
593
+ if (!fs3.existsSync(sentinelPath)) return null;
507
594
  try {
508
- const raw = fs.readFileSync(sentinelPath, "utf-8");
595
+ const raw = fs3.readFileSync(sentinelPath, "utf-8");
509
596
  const parsed = JSON.parse(raw);
510
597
  if (typeof parsed !== "object" || parsed === null || typeof parsed.version !== "number" || typeof parsed.namespace !== "string" || typeof parsed.updated_at !== "string" || typeof parsed.content_hash !== "string") {
511
598
  throw new Error("invalid sentinel schema");
512
599
  }
600
+ const projected = Array.isArray(parsed.projected_skills) ? parsed.projected_skills.filter((slug) => typeof slug === "string") : [];
513
601
  return {
514
602
  version: parsed.version,
515
603
  namespace: parsed.namespace,
516
604
  updated_at: parsed.updated_at,
517
- content_hash: parsed.content_hash
605
+ content_hash: parsed.content_hash,
606
+ projected_skills: projected
518
607
  };
519
608
  } catch (err) {
520
609
  throw new Error(
@@ -525,14 +614,14 @@ function readSentinel(sentinelPath) {
525
614
  function writeSentinelAtomically(sentinelPath, sentinel) {
526
615
  const tmpPath = `${sentinelPath}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`;
527
616
  try {
528
- fs.writeFileSync(tmpPath, `${JSON.stringify(sentinel, null, 2)}
617
+ fs3.writeFileSync(tmpPath, `${JSON.stringify(sentinel, null, 2)}
529
618
  `, {
530
619
  flag: "wx"
531
620
  });
532
- fs.renameSync(tmpPath, sentinelPath);
621
+ fs3.renameSync(tmpPath, sentinelPath);
533
622
  } catch (err) {
534
623
  try {
535
- fs.rmSync(tmpPath, { force: true });
624
+ fs3.rmSync(tmpPath, { force: true });
536
625
  } catch {
537
626
  }
538
627
  throw err;
@@ -658,22 +747,29 @@ function computeContentHash(input) {
658
747
  `);
659
748
  hash.update(r.body);
660
749
  }
750
+ const sortedSkills = [...input.skillFiles].sort((a, b) => a.slug < b.slug ? -1 : a.slug > b.slug ? 1 : 0);
751
+ for (const s of sortedSkills) {
752
+ hash.update(`
753
+ ---skill:${s.slug}---
754
+ `);
755
+ hash.update(s.body);
756
+ }
661
757
  return hash.digest("hex");
662
758
  }
663
759
  function describeMemoriesDir(memoriesDir) {
664
- if (!fs.existsSync(memoriesDir)) return null;
665
- const sentinelPath = path.join(memoriesDir, SENTINEL_FILE);
760
+ if (!fs3.existsSync(memoriesDir)) return null;
761
+ const sentinelPath = path3.join(memoriesDir, SENTINEL_FILE);
666
762
  const sentinel = readSentinel(sentinelPath);
667
763
  const files = [];
668
- for (const entry of fs.readdirSync(memoriesDir, { withFileTypes: true })) {
764
+ for (const entry of fs3.readdirSync(memoriesDir, { withFileTypes: true })) {
669
765
  if (entry.isFile() && OWNED_FILES.has(entry.name)) files.push(entry.name);
670
766
  }
671
- const rolloutsDir = path.join(memoriesDir, ROLLOUT_SUBDIR);
672
- if (fs.existsSync(rolloutsDir)) {
767
+ const rolloutsDir = path3.join(memoriesDir, ROLLOUT_SUBDIR);
768
+ if (fs3.existsSync(rolloutsDir)) {
673
769
  try {
674
- for (const entry of fs.readdirSync(rolloutsDir, { withFileTypes: true })) {
770
+ for (const entry of fs3.readdirSync(rolloutsDir, { withFileTypes: true })) {
675
771
  if (entry.isFile() && entry.name.endsWith(".md")) {
676
- files.push(path.join(ROLLOUT_SUBDIR, entry.name));
772
+ files.push(path3.join(ROLLOUT_SUBDIR, entry.name));
677
773
  }
678
774
  }
679
775
  } catch {
@@ -704,4 +800,4 @@ export {
704
800
  truncateToTokenBudget,
705
801
  describeMemoriesDir
706
802
  };
707
- //# sourceMappingURL=chunk-RDFF2NAU.js.map
803
+ //# sourceMappingURL=chunk-ZXBTTMGZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/connectors/codex-materialize.ts","../src/connectors/materialize-paths.ts","../src/connectors/materialize-skills.ts"],"sourcesContent":["/**\n * codex-materialize.ts — Codex CLI native memory artifact materialization (#378)\n *\n * Periodically writes Remnic memories into the file layout that Codex CLI's\n * phase-2 consolidation reads directly under `<codex_home>/memories/`:\n *\n * memory_summary.md — always-loaded at session start (tight budget)\n * MEMORY.md — searchable handbook (task-group schema)\n * raw_memories.md — mechanical merge of raw memories, latest first\n * rollout_summaries/<slug>.md — per-session recaps\n *\n * Codex's own read path is agnostic to which producer wrote these files — it\n * tags reads by `memory_md` / `memory_summary` / `raw_memories` /\n * `rollout_summaries` / `skills`. By materializing Remnic content into this\n * exact layout we let Codex pick up Remnic memories without a single MCP call.\n *\n * Safety invariants\n * ─────────────────\n * - **Atomic writes.** Every file is rendered under `.remnic-tmp/` and then\n * `rename()`d into place so Codex never observes a half-written file.\n * - **Sentinel-based opt-in.** If `<codex_home>/memories/.remnic-managed` is\n * missing, we SKIP materialization entirely and log a warning. This honors\n * user hand-edits to the directory — a user who manually curated their\n * Codex memory layout will never have those edits overwritten.\n * - **Schema validation.** `MEMORY.md` content is validated against the\n * task-group schema before write. Invalid content throws and nothing is\n * written.\n * - **Idempotent no-ops.** A content hash is written into the sentinel. If\n * the re-rendered hash matches the previous run, we skip writes entirely.\n * - **Token budget.** `memory_summary.md` is truncated to fit under the\n * configured script-aware token estimate, leaving headroom under Codex's\n * 5000-token summary cap.\n *\n * Privacy\n * ───────\n * This module does not persist any user content outside `<codex_home>/memories`\n * — it only mirrors the memories that Remnic already wrote. It does not log\n * memory content to stdout; it logs file names, counts, and hashes.\n */\n\nimport {\n createHash,\n} from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { log } from \"../logger.js\";\nimport { readEnvVar, resolveHomeDir } from \"../runtime/env.js\";\nimport type { MemoryFile } from \"../types.js\";\nimport { estimateTokenCount } from \"../token-estimate.js\";\nimport type { SkillBundle } from \"../procedural/skill-projection.js\";\nimport { expandTildePath } from \"../utils/path.js\";\nimport { ensureSafeManagedSubdir } from \"./materialize-paths.js\";\nimport {\n commitSkillFiles,\n planSkillFiles,\n retiredSkillsAlreadyRemoved,\n skillFilePath,\n skillFileRelPath,\n stageSkillFiles,\n type SkillFile,\n} from \"./materialize-skills.js\";\n\n// ─── Types ─────────────────────────────────────────────────────────────────\n\n/**\n * Input for {@link materializeForNamespace}. Prefer passing pre-loaded\n * `memories` so this module stays I/O-agnostic and trivially testable.\n */\nexport interface MaterializeOptions {\n /** Pre-loaded Remnic memories for this namespace (required). */\n memories: MemoryFile[];\n /** Override `<codex_home>`. Defaults to `$CODEX_HOME` or `~/.codex`. */\n codexHome?: string;\n /** Maximum estimated token size of memory_summary.md. Default 4500. */\n maxSummaryTokens?: number;\n /** Maximum age of rollout_summaries/*.md in days. Default 30. */\n rolloutRetentionDays?: number;\n /** Per-session rollout summaries to render. */\n rolloutSummaries?: RolloutSummaryInput[];\n /**\n * Projected procedural skill bundles (issue #2369). `undefined` leaves\n * `skills/` untouched; an array — even an empty one — is authoritative for\n * the slugs Remnic projected, so retired procedures get their folder\n * removed. Folders this materializer never projected are never touched.\n */\n skills?: SkillBundle[];\n /** Current time, injected for deterministic tests. */\n now?: Date;\n /** Optional logger override for tests. */\n logger?: { info: (msg: string) => void; warn: (msg: string) => void; debug?: (msg: string) => void };\n}\n\n/** Input describing one Codex rollout summary file. */\nexport interface RolloutSummaryInput {\n /** Stable slug for the file (becomes `<slug>.md`). */\n slug: string;\n /** Working directory used during the rollout. */\n cwd?: string;\n /** Path to the raw Codex rollout log, if known. */\n rolloutPath?: string;\n /** ISO-8601 timestamp of the last update. */\n updatedAt?: string;\n /** Opaque thread / session id. */\n threadId?: string;\n /** Markdown body for the recap. */\n body: string;\n /** Freeform keywords / search hints. */\n keywords?: string[];\n}\n\n/** Result of a materialization run. */\nexport interface MaterializeResult {\n /** Namespace that was materialized. */\n namespace: string;\n /** `<codex_home>/memories` path this run targeted. */\n memoriesDir: string;\n /** Was anything actually written (vs. skipped / idempotent no-op)? */\n wrote: boolean;\n /** True if the sentinel was missing and we skipped with a warning. */\n skippedNoSentinel: boolean;\n /** True if the hash matched the previous run and we short-circuited. */\n skippedIdempotent: boolean;\n /** Files that were written this run (relative to `memoriesDir`). */\n filesWritten: string[];\n /** Content hash computed for this run. */\n contentHash: string;\n}\n\n/** On-disk shape of the `.remnic-managed` sentinel. */\ninterface SentinelFile {\n version: number;\n namespace: string;\n updated_at: string;\n content_hash: string;\n /**\n * Slugs under `skills/` that THIS materializer projected (issue #2369).\n * Absent on sentinels written before skill projection existed, which reads\n * as \"we have projected nothing\", so hand-created folders stay untouched.\n */\n projected_skills?: string[];\n}\n\n// ─── Constants ─────────────────────────────────────────────────────────────\n\n/** Bump when the on-disk layout or semantics change. */\nexport const MATERIALIZE_VERSION = 1;\n\n/** Sentinel file name at the root of the materialized memories dir. */\nexport const SENTINEL_FILE = \".remnic-managed\";\n\n/** Scratch directory used for atomic renames. */\nexport const TMP_DIR = \".remnic-tmp\";\n\n/** File names we own. Anything else in the directory is considered user-managed. */\nconst OWNED_FILES = new Set<string>([\n \"memory_summary.md\",\n \"MEMORY.md\",\n \"raw_memories.md\",\n]);\n\n/** Sub-directory for per-session rollout recaps. */\nconst ROLLOUT_SUBDIR = \"rollout_summaries\";\n\n// ─── Public entry points ───────────────────────────────────────────────────\n\n/**\n * Materialize a Remnic namespace into Codex's native memory layout.\n *\n * Returns a {@link MaterializeResult} describing what happened. Callers\n * should treat \"skipped\" as success — the sentinel / idempotent cases are\n * expected and intentional.\n *\n * @throws if `MEMORY.md` fails schema validation (we do not write garbage).\n */\nexport function materializeForNamespace(\n namespace: string,\n options: MaterializeOptions,\n): MaterializeResult {\n const logger = options.logger ?? {\n info: (msg) => log.info(`[codex-materialize] ${msg}`),\n warn: (msg) => log.warn(`[codex-materialize] ${msg}`),\n debug: (msg) => log.debug(`[codex-materialize] ${msg}`),\n };\n const memoriesDir = resolveCodexMemoriesDir(options.codexHome);\n const now = options.now ?? new Date();\n // Honor `0` as \"no summary budget\" — parseConfig already clamps to non-\n // negative integers, so any provided number is meaningful. Only fall back\n // to the default when the caller did not provide the option at all.\n const maxSummaryTokens =\n typeof options.maxSummaryTokens === \"number\" && options.maxSummaryTokens >= 0\n ? options.maxSummaryTokens\n : 4500;\n const rolloutRetentionDays =\n typeof options.rolloutRetentionDays === \"number\" && options.rolloutRetentionDays >= 0\n ? options.rolloutRetentionDays\n : 30;\n\n // ── Sentinel check ─────────────────────────────────────────────────────\n // We deliberately do NOT `mkdirSync(memoriesDir)` before reading the\n // sentinel: creating `~/.codex/memories/` for every user (including ones\n // who never use Codex) would make Remnic's post-consolidation hook leave\n // empty opt-in directories behind on disk. Instead we only check whether\n // the sentinel already exists — if the parent dir doesn't exist, the\n // sentinel can't exist either and we fall straight through to the skip\n // path without touching the filesystem. The `mkdirSync` for `memoriesDir`\n // happens later, only once we know we're actually going to write.\n const sentinelPath = path.join(memoriesDir, SENTINEL_FILE);\n const existingSentinel = readSentinel(sentinelPath);\n if (!existingSentinel) {\n // Log at `debug` when the entire memories dir doesn't exist — that's\n // the common \"user never opted in\" case and should not be noisy.\n // Keep the `warn` level only when the dir exists but lacks a sentinel,\n // which is the \"user hand-curated layout, don't overwrite\" case that\n // genuinely warrants attention.\n if (fs.existsSync(memoriesDir)) {\n logger.warn(\n `sentinel ${SENTINEL_FILE} missing in ${memoriesDir}; skipping materialization to preserve hand-edits`,\n );\n } else {\n logger.debug?.(\n `skipping materialization — ${memoriesDir} does not exist (user not opted in)`,\n );\n }\n return {\n namespace,\n memoriesDir,\n wrote: false,\n skippedNoSentinel: true,\n skippedIdempotent: false,\n filesWritten: [],\n contentHash: \"\",\n };\n }\n\n // Now that we know the user has opted in (sentinel exists), it's safe to\n // ensure the memories dir is present. In practice this is almost always a\n // no-op because the sentinel read above already succeeded, but a defensive\n // mkdirSync protects against a race where the dir was removed between the\n // sentinel read and the first write.\n fs.mkdirSync(memoriesDir, { recursive: true });\n\n // ── Render ─────────────────────────────────────────────────────────────\n const memories = [...options.memories];\n // Track whether the caller actually supplied a rollout set. `undefined`\n // means \"don't touch rollout_summaries/\"; an empty array is still\n // authoritative and means \"we own this dir and it should be empty\".\n const rolloutsSupplied = options.rolloutSummaries !== undefined;\n const rolloutSummaries = options.rolloutSummaries ?? [];\n\n // Prune-before-render: MEMORY.md and memory_summary.md both embed rollout\n // filenames in their body, so they must only ever see the *retained* set.\n // Running pruneRollouts after the renderers (as an earlier revision did)\n // caused MEMORY.md to list `rollout_summaries/<slug>.md` paths for rollouts\n // that were then pruned and never written — a broken link pointing at a\n // ghost file. See review feedback on PR #392.\n const retainedRollouts = pruneRollouts(rolloutSummaries, rolloutRetentionDays, now);\n\n // Deduplicate on sanitized filename. Two different slugs (\"Session 1\" and\n // \"session!!!1\") can sanitize to the same output (\"session-1\"), which would\n // otherwise make the first entry's tmp file get overwritten and cause the\n // later rename step to crash with ENOENT. For each collision slot we keep\n // the entry with the newest `updatedAt` so an unsorted input (or a caller\n // that accidentally appends older recaps after newer ones) can't have an\n // older recap clobber a newer one.\n // We do this at the retained-input level (not just at the written-file\n // level) so MEMORY.md's \"rollout_summary_files\" section lists each slot\n // exactly once and matches what actually gets written to disk.\n const dedupedRollouts: RolloutSummaryInput[] = [];\n const seenNames = new Map<string, number>();\n const parseTs = (value: string | undefined): number => {\n if (!value) return Number.NEGATIVE_INFINITY;\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : Number.NEGATIVE_INFINITY;\n };\n for (const r of retainedRollouts) {\n const name = `${sanitizeSlug(r.slug)}.md`;\n const existingIdx = seenNames.get(name);\n if (existingIdx === undefined) {\n seenNames.set(name, dedupedRollouts.length);\n dedupedRollouts.push(r);\n continue;\n }\n // Newest-wins: only replace the existing entry if the incoming one has a\n // strictly newer timestamp. Ties keep the earlier entry (stable for\n // unsorted inputs) because overwriting on ties would flip rendering output\n // for benign call-order changes.\n const existing = dedupedRollouts[existingIdx];\n if (parseTs(r.updatedAt) > parseTs(existing.updatedAt)) {\n dedupedRollouts[existingIdx] = r;\n }\n }\n\n const memorySummary = renderMemorySummary({\n namespace,\n memories,\n rolloutSummaries: dedupedRollouts,\n maxTokens: maxSummaryTokens,\n });\n\n const memoryMd = renderMemoryMd({\n namespace,\n memories,\n rolloutSummaries: dedupedRollouts,\n });\n\n // Fail fast on schema issues — do not write garbage.\n const validation = validateMemoryMd(memoryMd);\n if (!validation.valid) {\n const reason = validation.errors.join(\"; \");\n logger.warn(`MEMORY.md failed schema validation: ${reason}`);\n throw new Error(`codex-materialize: MEMORY.md schema validation failed: ${reason}`);\n }\n\n const rawMemories = renderRawMemories({ memories });\n\n const rolloutFiles = dedupedRollouts.map((r) => ({\n name: `${sanitizeSlug(r.slug)}.md`,\n body: renderRolloutSummary(r),\n }));\n const destRolloutsDir = path.join(memoriesDir, ROLLOUT_SUBDIR);\n const retainedRolloutNames = new Set(rolloutFiles.map((r) => r.name));\n\n // Skill bundles (issue #2369) — planning, ownership, and disk layout live in\n // materialize-skills.ts.\n const skillPlan = planSkillFiles(options.skills, existingSentinel.projected_skills ?? []);\n\n // ── Idempotence check ──────────────────────────────────────────────────\n const hash = computeContentHash({\n namespace,\n memorySummary,\n memoryMd,\n rawMemories,\n rolloutFiles,\n skillFiles: skillPlan.files,\n });\n\n if (existingSentinel.content_hash === hash) {\n // Idempotence early-return is only safe when the managed files we would\n // have written are still on disk. If a user or external process deleted\n // `MEMORY.md` / `memory_summary.md` / `raw_memories.md` (or any retained\n // rollout file) while the sentinel's hash stayed the same, we must fall\n // through and rewrite — otherwise Codex would be stuck with missing\n // artifacts until a memory-content change happens to flip the hash.\n const requiredFiles = [\n path.join(memoriesDir, \"memory_summary.md\"),\n path.join(memoriesDir, \"MEMORY.md\"),\n path.join(memoriesDir, \"raw_memories.md\"),\n ...rolloutFiles.map((r) => path.join(memoriesDir, ROLLOUT_SUBDIR, r.name)),\n ...skillPlan.files.map((s) => skillFilePath(memoriesDir, s.slug)),\n ];\n const allPresent = requiredFiles.every((f) => fs.existsSync(f));\n const rolloutsClean =\n !rolloutsSupplied ||\n rolloutDirectoryMatchesRetainedSet(\n ensureSafeManagedSubdir(memoriesDir, destRolloutsDir, ROLLOUT_SUBDIR),\n retainedRolloutNames,\n );\n const skillsClean = retiredSkillsAlreadyRemoved(memoriesDir, skillPlan.retiredSlugs);\n if (allPresent && rolloutsClean && skillsClean) {\n logger.debug?.(`no-op materialization for namespace=${namespace} (hash unchanged)`);\n return {\n namespace,\n memoriesDir,\n wrote: false,\n skippedNoSentinel: false,\n skippedIdempotent: true,\n filesWritten: [],\n contentHash: hash,\n };\n }\n logger.debug?.(\n `hash unchanged for namespace=${namespace} but managed files need refresh — forcing rewrite`,\n );\n }\n\n // ── Atomic writes ──────────────────────────────────────────────────────\n // Use a unique, per-run staging sub-directory so two overlapping runs\n // (e.g. a session-end trigger overlapping with a consolidation post-hook)\n // can't stomp each other's tmp files mid-rename. The old \"fixed TMP_DIR,\n // wipe-on-entry\" layout meant run B would delete run A's staging area out\n // from under it, causing ENOENT on A's rename loop. Per-run uniqueness\n // turns the shared dir into an insulated workspace. See review feedback on\n // PR #392.\n const runTag = `${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n const tmpDir = path.join(memoriesDir, `${TMP_DIR}-${runTag}`);\n // Opportunistic GC for stale scratch dirs left behind by a previous\n // crashed run. We only remove entries whose mtime is older than the\n // stale-threshold below — that way we never delete another in-flight\n // run's staging area out from under it. The threshold is deliberately\n // generous (1h) because a healthy materialize completes in milliseconds\n // and there's no legitimate reason for a live staging dir to be older.\n //\n // NB: we compare against `Date.now()` (wall-clock), not against the\n // injected `options.now`. Tests and deterministic replays commonly\n // inject a non-current timestamp, but file mtimes on disk are always\n // wall-clock, so mixing the two would either false-positive delete\n // fresh dirs (test-time in the past) or false-negative skip stale ones\n // (test-time in the future).\n const TMP_STALE_MS = 60 * 60 * 1000;\n const wallClockMs = Date.now();\n try {\n for (const entry of fs.readdirSync(memoriesDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n if (!entry.name.startsWith(TMP_DIR)) continue;\n const stalePath = path.join(memoriesDir, entry.name);\n try {\n const stat = fs.statSync(stalePath);\n if (wallClockMs - stat.mtimeMs < TMP_STALE_MS) continue;\n fs.rmSync(stalePath, { recursive: true, force: true });\n } catch {\n // ignore — another concurrent run may own it, or we lack perms\n }\n }\n } catch {\n // ignore — dir may not exist yet\n }\n fs.mkdirSync(tmpDir, { recursive: true });\n fs.mkdirSync(path.join(tmpDir, ROLLOUT_SUBDIR), { recursive: true });\n\n const filesWritten: string[] = [];\n\n fs.writeFileSync(path.join(tmpDir, \"memory_summary.md\"), memorySummary);\n filesWritten.push(\"memory_summary.md\");\n\n fs.writeFileSync(path.join(tmpDir, \"MEMORY.md\"), memoryMd);\n filesWritten.push(\"MEMORY.md\");\n\n fs.writeFileSync(path.join(tmpDir, \"raw_memories.md\"), rawMemories);\n filesWritten.push(\"raw_memories.md\");\n\n for (const rollout of rolloutFiles) {\n fs.writeFileSync(path.join(tmpDir, ROLLOUT_SUBDIR, rollout.name), rollout.body);\n filesWritten.push(path.join(ROLLOUT_SUBDIR, rollout.name));\n }\n\n stageSkillFiles(tmpDir, skillPlan.files);\n for (const skill of skillPlan.files) {\n filesWritten.push(skillFileRelPath(skill.slug));\n }\n\n // Rename into place. Atomic per-file is sufficient — Codex reads each file\n // independently and tolerates an inconsistent in-between snapshot across\n // files for the duration of the rename loop (milliseconds).\n for (const rel of [\"memory_summary.md\", \"MEMORY.md\", \"raw_memories.md\"]) {\n const src = path.join(tmpDir, rel);\n const dest = path.join(memoriesDir, rel);\n fs.renameSync(src, dest);\n }\n\n const safeDestRolloutsDir = ensureSafeManagedSubdir(memoriesDir, destRolloutsDir, ROLLOUT_SUBDIR);\n // Only garbage-collect rollout files when the caller actually supplied a\n // `rolloutSummaries` array — otherwise we'd wipe legitimately\n // user/Codex-created recap files on every session-end run, since those\n // calls typically omit the rollout set entirely. When rollouts were\n // supplied (even as an empty array — meaning \"we own this dir and it\n // should be empty\"), we clear the stale files we previously owned.\n if (rolloutsSupplied) {\n let existingRollouts: fs.Dirent[];\n try {\n existingRollouts = fs.readdirSync(safeDestRolloutsDir, { withFileTypes: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") throw err;\n existingRollouts = [];\n }\n for (const entry of existingRollouts) {\n if (!entry.isFile()) continue;\n if (!entry.name.endsWith(\".md\")) continue;\n if (retainedRolloutNames.has(entry.name)) continue;\n try {\n fs.unlinkSync(path.join(safeDestRolloutsDir, entry.name));\n } catch (err) {\n throw new Error(\n `codex-materialize: failed to prune stale rollout summary ${entry.name}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n for (const rollout of rolloutFiles) {\n const src = path.join(tmpDir, ROLLOUT_SUBDIR, rollout.name);\n const dest = path.join(safeDestRolloutsDir, rollout.name);\n fs.renameSync(src, dest);\n }\n\n commitSkillFiles(memoriesDir, tmpDir, skillPlan);\n\n // Update sentinel last so a crash leaves hash mismatched → next run rewrites.\n const sentinel: SentinelFile = {\n version: MATERIALIZE_VERSION,\n namespace,\n updated_at: now.toISOString(),\n content_hash: hash,\n projected_skills: skillPlan.supplied\n ? skillPlan.files.map((s) => s.slug)\n : (existingSentinel.projected_skills ?? []),\n };\n writeSentinelAtomically(sentinelPath, sentinel);\n\n try {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n } catch {\n // ignore\n }\n\n logger.info(\n `materialized namespace=${namespace} files=${filesWritten.length} hash=${hash.slice(0, 12)}`,\n );\n\n return {\n namespace,\n memoriesDir,\n wrote: true,\n skippedNoSentinel: false,\n skippedIdempotent: false,\n filesWritten,\n contentHash: hash,\n };\n}\n\n/**\n * Create (or refresh) the `.remnic-managed` sentinel. Callers must do this\n * explicitly the first time they want Remnic to start managing a directory —\n * we never write it implicitly, because its presence is the user's opt-in.\n */\nexport function ensureSentinel(memoriesDir: string, namespace: string, now: Date = new Date()): void {\n fs.mkdirSync(memoriesDir, { recursive: true });\n const sentinelPath = path.join(memoriesDir, SENTINEL_FILE);\n if (fs.existsSync(sentinelPath)) {\n readSentinel(sentinelPath);\n return;\n }\n const sentinel: SentinelFile = {\n version: MATERIALIZE_VERSION,\n namespace,\n updated_at: now.toISOString(),\n content_hash: \"\",\n };\n writeSentinelAtomically(sentinelPath, sentinel);\n}\n\n// ─── Rendering ─────────────────────────────────────────────────────────────\n\ninterface RenderContext {\n namespace: string;\n memories: MemoryFile[];\n rolloutSummaries: RolloutSummaryInput[];\n // Historically this interface exposed a `now: Date` field, but neither\n // `renderMemoryMd` nor `renderMemorySummary` ever read it (rendered output\n // is purely a function of `namespace`, `memories`, and `rolloutSummaries`).\n // The field was flagged as dead weight in PR #392 review and removed.\n // If a future renderer needs a timestamp, re-add it here and update both\n // call sites and the schema test.\n}\n\ninterface SummaryRenderContext extends RenderContext {\n maxTokens: number;\n}\n\n/**\n * Render `memory_summary.md` — the always-loaded file.\n * Budget-capped at `maxTokens` whitespace tokens.\n */\nexport function renderMemorySummary(ctx: SummaryRenderContext): string {\n const lines: string[] = [];\n lines.push(\"# Memory Summary\");\n lines.push(\"\");\n lines.push(`_namespace: ${ctx.namespace}_`);\n lines.push(`_source: remnic_`);\n lines.push(\"\");\n\n const highValue = selectSummaryMemories(ctx.memories, 12);\n if (highValue.length > 0) {\n lines.push(\"## Top memories\");\n lines.push(\"\");\n for (const mem of highValue) {\n lines.push(`- ${oneLineSummary(mem)}`);\n }\n lines.push(\"\");\n }\n\n if (ctx.rolloutSummaries.length > 0) {\n lines.push(\"## Recent rollouts\");\n lines.push(\"\");\n const sorted = [...ctx.rolloutSummaries]\n .sort((a, b) => (b.updatedAt ?? \"\").localeCompare(a.updatedAt ?? \"\"))\n .slice(0, 5);\n for (const r of sorted) {\n const when = r.updatedAt ? ` (${r.updatedAt})` : \"\";\n lines.push(`- ${r.slug}${when}`);\n }\n lines.push(\"\");\n }\n\n // Collapse trailing newlines to one without the anchored /\\n+$/ quantifier,\n // which backtracks polynomially (CodeQL js/polynomial-redos).\n const joined = lines.join(\"\\n\");\n let joinedEnd = joined.length;\n while (joinedEnd > 0 && joined[joinedEnd - 1] === \"\\n\") joinedEnd--;\n const full = joinedEnd === joined.length ? joined : `${joined.slice(0, joinedEnd)}\\n`;\n return truncateToTokenBudget(full, ctx.maxTokens);\n}\n\n/**\n * Render `MEMORY.md` — the searchable handbook in Codex's task-group schema.\n */\nexport function renderMemoryMd(ctx: RenderContext): string {\n const lines: string[] = [];\n lines.push(`# Task Group: ${ctx.namespace}`);\n lines.push(`scope: ${ctx.namespace}`);\n lines.push(`applies_to: cwd=*; reuse_rule=namespace-match`);\n lines.push(\"\");\n\n // One \"task\" per top-level topic cluster. For the first cut we group by\n // memory category so the schema validator always sees at least one task.\n const byCategory = groupMemoriesByCategory(ctx.memories);\n let taskIndex = 1;\n if (byCategory.size === 0) {\n lines.push(`## Task ${taskIndex}: baseline — no memories yet`);\n lines.push(\"\");\n lines.push(\"### rollout_summary_files\");\n for (const r of ctx.rolloutSummaries) {\n lines.push(\n `- rollout_summaries/${sanitizeSlug(r.slug)}.md (cwd=${r.cwd ?? \"*\"}, rollout_path=${r.rolloutPath ?? \"\"}, updated_at=${r.updatedAt ?? \"\"}, thread_id=${r.threadId ?? \"\"})`,\n );\n }\n if (ctx.rolloutSummaries.length === 0) {\n lines.push(\"- (none)\");\n }\n lines.push(\"\");\n lines.push(\"### keywords\");\n lines.push(`- ${ctx.namespace}`);\n lines.push(\"\");\n taskIndex += 1;\n } else {\n for (const [category, mems] of byCategory) {\n lines.push(`## Task ${taskIndex}: ${category} memories, outcome=surface-to-codex`);\n lines.push(\"\");\n lines.push(\"### rollout_summary_files\");\n const relevantRollouts = ctx.rolloutSummaries.slice(0, 5);\n if (relevantRollouts.length === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const r of relevantRollouts) {\n lines.push(\n `- rollout_summaries/${sanitizeSlug(r.slug)}.md (cwd=${r.cwd ?? \"*\"}, rollout_path=${r.rolloutPath ?? \"\"}, updated_at=${r.updatedAt ?? \"\"}, thread_id=${r.threadId ?? \"\"})`,\n );\n }\n }\n lines.push(\"\");\n lines.push(\"### keywords\");\n const keywords = collectKeywords(mems, category, ctx.namespace);\n lines.push(`- ${keywords.join(\", \")}`);\n lines.push(\"\");\n taskIndex += 1;\n }\n }\n\n lines.push(\"## User preferences\");\n const prefs = pickCategory(ctx.memories, [\"preference\"]);\n if (prefs.length === 0) {\n lines.push(\"- (none recorded)\");\n } else {\n for (const pref of prefs.slice(0, 20)) {\n lines.push(`- ${oneLineSummary(pref)}`);\n }\n }\n lines.push(\"\");\n\n lines.push(\"## Reusable knowledge\");\n const knowledge = pickCategory(ctx.memories, [\"fact\", \"decision\", \"principle\", \"rule\", \"skill\"]);\n if (knowledge.length === 0) {\n lines.push(\"- (none recorded)\");\n } else {\n for (const mem of knowledge.slice(0, 30)) {\n lines.push(`- ${oneLineSummary(mem)}`);\n }\n }\n lines.push(\"\");\n\n lines.push(\"## Failures and how to do differently\");\n const corrections = pickCategory(ctx.memories, [\"correction\"]);\n if (corrections.length === 0) {\n lines.push(\"- (none recorded)\");\n } else {\n for (const mem of corrections.slice(0, 20)) {\n lines.push(`- ${oneLineSummary(mem)}`);\n }\n }\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n\n/** Render `raw_memories.md` — mechanical dump, latest first. */\nexport function renderRawMemories(ctx: { memories: MemoryFile[] }): string {\n const sorted = [...ctx.memories].sort((a, b) => {\n const aUpdated = a.frontmatter.updated ?? a.frontmatter.created ?? \"\";\n const bUpdated = b.frontmatter.updated ?? b.frontmatter.created ?? \"\";\n return bUpdated.localeCompare(aUpdated);\n });\n\n const lines: string[] = [\"# Raw Memories\", \"\", \"_source: remnic — latest first_\", \"\"];\n for (const mem of sorted) {\n const fm = mem.frontmatter;\n const id = fm.id ?? \"unknown\";\n const category = fm.category ?? \"unknown\";\n const updated = fm.updated ?? fm.created ?? \"\";\n lines.push(`## ${id} (${category}, updated=${updated})`);\n lines.push(\"\");\n lines.push(mem.content.trim());\n lines.push(\"\");\n }\n return lines.join(\"\\n\");\n}\n\n/** Render a single rollout summary file. */\nexport function renderRolloutSummary(input: RolloutSummaryInput): string {\n const lines: string[] = [];\n lines.push(`# Rollout Summary: ${input.slug}`);\n lines.push(\"\");\n const meta: string[] = [];\n if (input.cwd) meta.push(`cwd=${input.cwd}`);\n if (input.rolloutPath) meta.push(`rollout_path=${input.rolloutPath}`);\n if (input.updatedAt) meta.push(`updated_at=${input.updatedAt}`);\n if (input.threadId) meta.push(`thread_id=${input.threadId}`);\n if (meta.length > 0) {\n lines.push(`_${meta.join(\"; \")}_`);\n lines.push(\"\");\n }\n if (input.keywords && input.keywords.length > 0) {\n lines.push(`**keywords:** ${input.keywords.join(\", \")}`);\n lines.push(\"\");\n }\n lines.push(input.body.trim());\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\n// ─── Schema validation ─────────────────────────────────────────────────────\n\nexport interface MemoryMdValidation {\n valid: boolean;\n errors: string[];\n}\n\n/**\n * Validate that a rendered `MEMORY.md` matches Codex's task-group schema.\n * We enforce the minimum set of structural requirements called out in #378:\n *\n * - one `# Task Group:` header\n * - `scope:` and `applies_to:` lines directly beneath it\n * - at least one `## Task N:` section\n * - each task section has `### rollout_summary_files` and `### keywords`\n * - `## User preferences`, `## Reusable knowledge`,\n * `## Failures and how to do differently` sections all present\n */\nexport function validateMemoryMd(content: string): MemoryMdValidation {\n const errors: string[] = [];\n const lines = content.split(/\\r?\\n/u);\n\n const taskGroupIndex = lines.findIndex((l) => /^#\\s+Task Group:\\s+\\S+/u.test(l));\n if (taskGroupIndex === -1) {\n errors.push(\"missing `# Task Group:` header\");\n } else {\n const tail = lines.slice(taskGroupIndex + 1, taskGroupIndex + 5);\n if (!tail.some((l) => /^scope:\\s*\\S+/u.test(l))) {\n errors.push(\"missing `scope:` line under Task Group header\");\n }\n if (!tail.some((l) => /^applies_to:\\s*\\S+/u.test(l))) {\n errors.push(\"missing `applies_to:` line under Task Group header\");\n }\n }\n\n const taskHeaders = lines.filter((l) => /^##\\s+Task\\s+\\d+:/u.test(l));\n if (taskHeaders.length === 0) {\n errors.push(\"at least one `## Task N:` section is required\");\n }\n\n // For every task section, make sure we have rollout_summary_files + keywords\n // before the next `##` header at the same level.\n const sectionRegex = /^##\\s+/u;\n for (let i = 0; i < lines.length; i++) {\n if (!/^##\\s+Task\\s+\\d+:/u.test(lines[i])) continue;\n let hasRollout = false;\n let hasKeywords = false;\n for (let j = i + 1; j < lines.length; j++) {\n if (sectionRegex.test(lines[j])) break;\n if (/^###\\s+rollout_summary_files\\s*$/u.test(lines[j])) hasRollout = true;\n if (/^###\\s+keywords\\s*$/u.test(lines[j])) hasKeywords = true;\n }\n if (!hasRollout) errors.push(`task block at line ${i + 1} missing \\`### rollout_summary_files\\``);\n if (!hasKeywords) errors.push(`task block at line ${i + 1} missing \\`### keywords\\``);\n }\n\n const requiredSections = [\n /^##\\s+User preferences\\s*$/u,\n /^##\\s+Reusable knowledge\\s*$/u,\n /^##\\s+Failures and how to do differently\\s*$/u,\n ];\n for (const re of requiredSections) {\n if (!lines.some((l) => re.test(l))) {\n errors.push(`missing required section: ${re.source}`);\n }\n }\n\n return { valid: errors.length === 0, errors };\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────\n\nfunction resolveCodexHome(override?: string): string {\n if (override && override.trim().length > 0) {\n return path.resolve(expandTildePath(override.trim()));\n }\n const fromEnv = readEnvVar(\"CODEX_HOME\");\n if (fromEnv && fromEnv.trim().length > 0) {\n return path.resolve(expandTildePath(fromEnv.trim()));\n }\n return path.resolve(resolveHomeDir(), \".codex\");\n}\n\nexport function resolveCodexMemoriesDir(codexHome?: string): string {\n return path.join(resolveCodexHome(codexHome), \"memories\");\n}\n\nexport function hasCodexMaterializeSentinel(codexHome?: string): boolean {\n return readSentinel(path.join(resolveCodexMemoriesDir(codexHome), SENTINEL_FILE)) !== null;\n}\n\nfunction rolloutDirectoryMatchesRetainedSet(\n rolloutsDir: string,\n retainedNames: Set<string>,\n): boolean {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(rolloutsDir, { withFileTypes: true });\n } catch {\n return retainedNames.size === 0;\n }\n for (const entry of entries) {\n if (!entry.isFile()) continue;\n if (!entry.name.endsWith(\".md\")) continue;\n if (!retainedNames.has(entry.name)) return false;\n }\n return true;\n}\n\nfunction readSentinel(sentinelPath: string): SentinelFile | null {\n if (!fs.existsSync(sentinelPath)) return null;\n try {\n const raw = fs.readFileSync(sentinelPath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<SentinelFile>;\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n typeof parsed.version !== \"number\" ||\n typeof parsed.namespace !== \"string\" ||\n typeof parsed.updated_at !== \"string\" ||\n typeof parsed.content_hash !== \"string\"\n ) {\n throw new Error(\"invalid sentinel schema\");\n }\n // A sentinel written before issue #2369 has no `projected_skills`, which\n // reads as \"nothing projected\" — so an unrelated skills/ folder written by\n // a user or another tool is never treated as ours.\n const projected = Array.isArray(parsed.projected_skills)\n ? parsed.projected_skills.filter((slug): slug is string => typeof slug === \"string\")\n : [];\n return {\n version: parsed.version,\n namespace: parsed.namespace,\n updated_at: parsed.updated_at,\n content_hash: parsed.content_hash,\n projected_skills: projected,\n };\n } catch (err) {\n throw new Error(\n `codex-materialize: corrupt ${SENTINEL_FILE} sentinel at ${sentinelPath}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nfunction writeSentinelAtomically(\n sentinelPath: string,\n sentinel: SentinelFile,\n): void {\n const tmpPath = `${sentinelPath}.${process.pid}.${Date.now()}.${Math.random()\n .toString(16)\n .slice(2)}.tmp`;\n try {\n fs.writeFileSync(tmpPath, `${JSON.stringify(sentinel, null, 2)}\\n`, {\n flag: \"wx\",\n });\n fs.renameSync(tmpPath, sentinelPath);\n } catch (err) {\n try {\n fs.rmSync(tmpPath, { force: true });\n } catch {\n // ignore cleanup failures; preserve the original write/rename error\n }\n throw err;\n }\n}\n\nfunction selectSummaryMemories(memories: MemoryFile[], limit: number): MemoryFile[] {\n const scored = memories\n .filter((m) => !m.frontmatter.status || m.frontmatter.status === \"active\")\n .map((m) => {\n const confidence = typeof m.frontmatter.confidence === \"number\" ? m.frontmatter.confidence : 0;\n const importance =\n typeof m.frontmatter.importance === \"object\" &&\n m.frontmatter.importance !== null &&\n typeof (m.frontmatter.importance as { score?: number }).score === \"number\"\n ? ((m.frontmatter.importance as { score: number }).score ?? 0)\n : 0;\n const updated = m.frontmatter.updated ?? m.frontmatter.created ?? \"\";\n return { memory: m, score: importance * 2 + confidence, updated };\n });\n\n scored.sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n return b.updated.localeCompare(a.updated);\n });\n\n return scored.slice(0, limit).map((s) => s.memory);\n}\n\nfunction oneLineSummary(memory: MemoryFile): string {\n const raw = memory.content.replace(/\\s+/gu, \" \").trim();\n if (raw.length <= 160) return raw;\n return `${raw.slice(0, 157)}...`;\n}\n\nfunction groupMemoriesByCategory(memories: MemoryFile[]): Map<string, MemoryFile[]> {\n const map = new Map<string, MemoryFile[]>();\n for (const memory of memories) {\n if (memory.frontmatter.status && memory.frontmatter.status !== \"active\") continue;\n const category = memory.frontmatter.category ?? \"unknown\";\n const list = map.get(category) ?? [];\n list.push(memory);\n map.set(category, list);\n }\n return map;\n}\n\nfunction pickCategory(memories: MemoryFile[], categories: string[]): MemoryFile[] {\n const allowed = new Set(categories);\n return memories.filter(\n (m) =>\n (!m.frontmatter.status || m.frontmatter.status === \"active\") &&\n allowed.has(m.frontmatter.category ?? \"\"),\n );\n}\n\nfunction collectKeywords(memories: MemoryFile[], category: string, namespace: string): string[] {\n const keywords = new Set<string>();\n keywords.add(category);\n keywords.add(namespace);\n for (const mem of memories.slice(0, 10)) {\n for (const tag of mem.frontmatter.tags ?? []) {\n if (typeof tag === \"string\" && tag.trim().length > 0) keywords.add(tag.trim());\n }\n }\n return [...keywords].slice(0, 16);\n}\n\nfunction pruneRollouts(\n rollouts: RolloutSummaryInput[],\n retentionDays: number,\n now: Date,\n): RolloutSummaryInput[] {\n // Negative retention → \"infinite retention\" escape hatch. `parseConfig`\n // clamps the knob to >= 0, so in practice only callers passing a negative\n // value intentionally get the all-pass behavior.\n if (retentionDays < 0) return rollouts;\n // retentionDays === 0 → cutoff is exactly `now`, which prunes every\n // rollout whose `updatedAt` is in the past (i.e. all of them in practice).\n // This matches the documented semantics of \"retain for 0 days\".\n const cutoffMs = now.getTime() - retentionDays * 24 * 60 * 60 * 1000;\n return rollouts.filter((r) => {\n if (!r.updatedAt) return true;\n const t = Date.parse(r.updatedAt);\n if (!Number.isFinite(t)) return true;\n return t >= cutoffMs;\n });\n}\n\nfunction sanitizeSlug(slug: string): string {\n const sanitized = slug\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/gu, \"-\")\n .slice(0, 96);\n const trimmed = trimHyphenEdges(sanitized);\n return trimmed || \"rollout\";\n}\n\nfunction trimHyphenEdges(value: string): string {\n let start = 0;\n let end = value.length;\n while (start < end && value[start] === \"-\") start += 1;\n while (end > start && value[end - 1] === \"-\") end -= 1;\n return value.slice(start, end);\n}\n/** Shared script-aware approximation used by the budget check. */\nexport function approximateTokenCount(text: string): number {\n return estimateTokenCount(text);\n}\n\n/**\n * Truncate `text` so it fits under `maxTokens`. We drop trailing lines until\n * under budget, then append a marker so readers can see that truncation occurred.\n */\nexport function truncateToTokenBudget(text: string, maxTokens: number): string {\n if (maxTokens <= 0) return \"\";\n if (approximateTokenCount(text) <= maxTokens) return text;\n\n const lineMarker = \"_[truncated for summary budget]_\";\n const tailMarker = \"[truncated]\";\n if (approximateTokenCount(tailMarker) > maxTokens) return \"\";\n const lineMarkerTokens = approximateTokenCount(lineMarker);\n\n const lines = text.split(/\\r?\\n/u);\n const lineBudget = Math.max(0, maxTokens - lineMarkerTokens);\n while (lines.length > 0 && approximateTokenCount(lines.join(\"\\n\")) > lineBudget) {\n lines.pop();\n }\n lines.push(lineMarker);\n let result = lines.join(\"\\n\");\n\n if (approximateTokenCount(result) > maxTokens) {\n const codePoints = [...result];\n let low = 0;\n let high = codePoints.length;\n while (low < high) {\n const mid = Math.ceil((low + high) / 2);\n const prefix = codePoints.slice(0, mid).join(\"\");\n const candidate = prefix.length > 0 ? `${prefix} ${tailMarker}` : tailMarker;\n if (approximateTokenCount(candidate) <= maxTokens) low = mid;\n else high = mid - 1;\n }\n const prefix = codePoints.slice(0, low).join(\"\");\n result = prefix.length > 0 ? `${prefix} ${tailMarker}` : tailMarker;\n }\n return result;\n}\n\nfunction computeContentHash(input: {\n namespace: string;\n memorySummary: string;\n memoryMd: string;\n rawMemories: string;\n rolloutFiles: Array<{ name: string; body: string }>;\n skillFiles: Array<{ slug: string; body: string }>;\n}): string {\n const hash = createHash(\"sha256\");\n hash.update(`v${MATERIALIZE_VERSION}\\n`);\n hash.update(`namespace=${input.namespace}\\n`);\n hash.update(\"---memory_summary---\\n\");\n hash.update(input.memorySummary);\n hash.update(\"\\n---memory_md---\\n\");\n hash.update(input.memoryMd);\n hash.update(\"\\n---raw_memories---\\n\");\n hash.update(input.rawMemories);\n const sortedRollouts = [...input.rolloutFiles].sort((a, b) => a.name.localeCompare(b.name));\n for (const r of sortedRollouts) {\n hash.update(`\\n---rollout:${r.name}---\\n`);\n hash.update(r.body);\n }\n // Sorted by slug so call order cannot flip the hash (§26).\n const sortedSkills = [...input.skillFiles].sort((a, b) => (a.slug < b.slug ? -1 : a.slug > b.slug ? 1 : 0));\n for (const s of sortedSkills) {\n hash.update(`\\n---skill:${s.slug}---\\n`);\n hash.update(s.body);\n }\n return hash.digest(\"hex\");\n}\n\n// ─── Stat helper for tests / debugging ─────────────────────────────────────\n\n/**\n * Return basic stats about a materialized memories dir. Useful for tests and\n * debug CLI output. Returns `null` if the dir does not exist.\n */\nexport function describeMemoriesDir(memoriesDir: string): {\n exists: boolean;\n hasSentinel: boolean;\n files: string[];\n sentinel: SentinelFile | null;\n} | null {\n if (!fs.existsSync(memoriesDir)) return null;\n const sentinelPath = path.join(memoriesDir, SENTINEL_FILE);\n const sentinel = readSentinel(sentinelPath);\n const files: string[] = [];\n for (const entry of fs.readdirSync(memoriesDir, { withFileTypes: true })) {\n if (entry.isFile() && OWNED_FILES.has(entry.name)) files.push(entry.name);\n }\n const rolloutsDir = path.join(memoriesDir, ROLLOUT_SUBDIR);\n if (fs.existsSync(rolloutsDir)) {\n try {\n for (const entry of fs.readdirSync(rolloutsDir, { withFileTypes: true })) {\n if (entry.isFile() && entry.name.endsWith(\".md\")) {\n files.push(path.join(ROLLOUT_SUBDIR, entry.name));\n }\n }\n } catch {\n // ignore\n }\n }\n return {\n exists: true,\n hasSentinel: sentinel !== null,\n files: files.sort(),\n sentinel,\n };\n}\n","/**\n * materialize-paths.ts — containment guard for the materializer's managed\n * sub-directories (`rollout_summaries/`, `skills/`).\n *\n * Extracted from codex-materialize.ts so the skills section (issue #2369) and\n * the rollout section share ONE containment implementation instead of forking\n * the check (rule 22).\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { pathIsInside } from \"../utils/path-containment.js\";\n\n/**\n * Resolve a managed sub-directory of `memoriesDir`, creating it when absent,\n * and refuse a symlinked or escaping target. Returns the (unchanged) path so\n * callers can use it directly.\n */\nexport function ensureSafeManagedSubdir(memoriesDir: string, subdir: string, label: string): string {\n const memoriesReal = fs.realpathSync(memoriesDir);\n\n try {\n const stat = fs.lstatSync(subdir);\n if (stat.isSymbolicLink()) {\n throw new Error(\"is a symbolic link\");\n }\n if (!stat.isDirectory()) {\n throw new Error(\"is not a directory\");\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw new Error(\n `codex-materialize: unsafe ${label} directory at ${subdir}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n fs.mkdirSync(subdir, { recursive: true });\n }\n\n const subdirReal = fs.realpathSync(subdir);\n if (!pathIsInside(memoriesReal, subdirReal)) {\n throw new Error(\n `codex-materialize: unsafe ${label} directory at ${subdir}: resolves outside ${memoriesDir}`,\n );\n }\n\n return path.normalize(subdir);\n}\n","/**\n * materialize-skills.ts — the `skills/` section of the Codex materializer\n * (issue #2369).\n *\n * Extracted from codex-materialize.ts (which sits at its structural LOC cap)\n * so the skill staging / commit / prune rules live in one small module. Format\n * and slug rules stay in the host-agnostic `procedural/skill-projection.ts`;\n * this module only decides what lands on disk.\n *\n * Ownership rule: Remnic removes ONLY the slugs a previous run recorded in the\n * sentinel's `projected_skills`. A skill folder a user (or another tool)\n * created is never in that list, so it is never a removal candidate.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { renderSkillBundle, SKILL_FILE_NAME, type SkillBundle } from \"../procedural/skill-projection.js\";\nimport { isValidSkillSlug } from \"../skills-registry.js\";\nimport { ensureSafeManagedSubdir } from \"./materialize-paths.js\";\n\n/** Sub-directory for projected procedural skill bundles. */\nexport const SKILLS_SUBDIR = \"skills\";\n\nexport interface SkillFile {\n slug: string;\n body: string;\n}\n\nexport interface SkillPlan {\n /** False when the caller omitted `skills` — leave `skills/` untouched. */\n supplied: boolean;\n /** Bundles to write, deduplicated on slug. */\n files: SkillFile[];\n /** Previously projected slugs this run no longer projects. */\n retiredSlugs: string[];\n}\n\n/**\n * Decide what this run writes and removes. `undefined` bundles mean \"not our\n * business this run\"; an empty array is authoritative and retires everything\n * previously projected.\n */\nexport function planSkillFiles(\n bundles: SkillBundle[] | undefined,\n previouslyProjectedSlugs: readonly string[],\n): SkillPlan {\n const files: SkillFile[] = [];\n const seen = new Set<string>();\n for (const bundle of bundles ?? []) {\n // Invalid or duplicate slugs are dropped so two bundles can never target\n // one folder and leave the second rename with no source (§37).\n if (!isValidSkillSlug(bundle.slug) || seen.has(bundle.slug)) continue;\n seen.add(bundle.slug);\n files.push({ slug: bundle.slug, body: renderSkillBundle(bundle) });\n }\n const previous = previouslyProjectedSlugs.filter((slug) => isValidSkillSlug(slug));\n return {\n supplied: bundles !== undefined,\n files,\n retiredSlugs: bundles === undefined ? [] : previous.filter((slug) => !seen.has(slug)),\n };\n}\n\n/** Absolute path of a projected bundle's SKILL.md under `memoriesDir`. */\nexport function skillFilePath(memoriesDir: string, slug: string): string {\n return path.join(memoriesDir, SKILLS_SUBDIR, slug, SKILL_FILE_NAME);\n}\n\n/** Relative path recorded in `MaterializeResult.filesWritten`. */\nexport function skillFileRelPath(slug: string): string {\n return path.join(SKILLS_SUBDIR, slug, SKILL_FILE_NAME);\n}\n\n/**\n * True when no retired folder is still on disk. Guards the idempotent\n * early-return: a hash match is only a safe no-op if the removals also landed.\n */\nexport function retiredSkillsAlreadyRemoved(memoriesDir: string, retiredSlugs: readonly string[]): boolean {\n return retiredSlugs.every((slug) => !fs.existsSync(path.join(memoriesDir, SKILLS_SUBDIR, slug)));\n}\n\n/** Render bundles into the per-run staging directory. */\nexport function stageSkillFiles(tmpDir: string, files: readonly SkillFile[]): void {\n for (const file of files) {\n const stagedDir = path.join(tmpDir, SKILLS_SUBDIR, file.slug);\n fs.mkdirSync(stagedDir, { recursive: true });\n fs.writeFileSync(path.join(stagedDir, SKILL_FILE_NAME), file.body);\n }\n}\n\n/**\n * Remove retired folders, then rename each staged SKILL.md into place. Per-file\n * renames (never directory renames) so an existing folder cannot cause\n * ENOTEMPTY and so Codex never observes a half-written file.\n */\nexport function commitSkillFiles(memoriesDir: string, tmpDir: string, plan: SkillPlan): void {\n if (!plan.supplied) return;\n if (plan.files.length === 0 && plan.retiredSlugs.length === 0) return;\n\n const skillsDir = ensureSafeManagedSubdir(memoriesDir, path.join(memoriesDir, SKILLS_SUBDIR), SKILLS_SUBDIR);\n for (const slug of plan.retiredSlugs) {\n const retiredDir = path.join(skillsDir, slug);\n try {\n // Never follow a symlink out of the managed tree while pruning.\n if (fs.lstatSync(retiredDir).isSymbolicLink()) continue;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") continue;\n throw err;\n }\n try {\n fs.rmSync(retiredDir, { recursive: true, force: true });\n } catch (err) {\n throw new Error(\n `codex-materialize: failed to remove retired skill ${slug}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n for (const file of plan.files) {\n const destDir = path.join(skillsDir, file.slug);\n fs.mkdirSync(destDir, { recursive: true });\n fs.renameSync(\n path.join(tmpDir, SKILLS_SUBDIR, file.slug, SKILL_FILE_NAME),\n path.join(destDir, SKILL_FILE_NAME),\n );\n }\n}\n"],"mappings":"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","names":["fs","path","fs","path","path","fs","path","fs","prefix"]}
@@ -1,16 +1,16 @@
1
1
  import { CompoundingPromotionReport } from './compounding/engine.js';
2
2
  import { ConversationIndexBackendInspection } from './conversation-index/backend.js';
3
3
  import { MigrateObservationsResult } from './maintenance/migrate-observations.js';
4
- import { M as MemoryFile, m as MemoryFrontmatter, w as MemoryStatus, a8 as BehaviorSignalEvent, Q as QmdSearchResult, ad as BulkImportResult, ai as MemoryActionEvent, K as MemoryLifecycleEvent } from './types-BxAcOl5Q.js';
5
- import { C as ConversationIndexCoordinator, T as TierMigrationCoordinator, O as Orchestrator } from './orchestrator-Bvq1-RQs.js';
6
- import { S as StorageManager } from './storage-BIDzuKIn.js';
4
+ import { M as MemoryFile, m as MemoryFrontmatter, w as MemoryStatus, a9 as BehaviorSignalEvent, Q as QmdSearchResult, ae as BulkImportResult, aj as MemoryActionEvent, K as MemoryLifecycleEvent } from './types-ETU5N6nB.js';
5
+ import { C as ConversationIndexCoordinator, T as TierMigrationCoordinator, O as Orchestrator } from './orchestrator-4wzJrPVm.js';
6
+ import { S as StorageManager } from './storage-B7urx1K3.js';
7
7
  import { TrustZoneDemoSeedResult, TrustZoneName, TrustZonePromotionResult, TrustZoneStoreStatus } from './trust-zones.js';
8
- import { f as EngramAccessService } from './access-service-DkaIG3n8.js';
8
+ import { f as EngramAccessService } from './access-service-sbiNS5UB.js';
9
9
  import { Writable, Readable } from 'node:stream';
10
10
  import { ResolveSecretRefFn } from './resolve-auth-token.js';
11
11
  import { CausalTrajectoryStoreStatus } from './causal-trajectory.js';
12
12
  import { C as ConnectorRunResult, a as ConnectorsOutputFormat } from './connectors-cli-2iaQ5tX2.js';
13
- import { P as ProcessBatchFn } from './pipeline-C8vfIiTX.js';
13
+ import { P as ProcessBatchFn } from './pipeline-CgXgdIrF.js';
14
14
  import { MemoryGovernanceRunResult, MemoryGovernanceSummary, MemoryGovernanceMetrics, MemoryGovernanceQualityScore, MemoryGovernanceReviewQueueEntry, MemoryGovernanceAppliedAction, MemoryGovernanceTransitionReport, MemoryGovernanceManifest, MemoryGovernanceRestoreManifest, RestoreMemoryGovernanceRunResult } from './maintenance/memory-governance.js';
15
15
  import { RebuildMemoryProjectionResult, RepairMemoryProjectionResult, VerifyMemoryProjectionResult } from './maintenance/rebuild-memory-projection.js';
16
16
  import { RebuildObservationsResult } from './maintenance/rebuild-observations.js';