@remnic/core 9.62.0 → 9.62.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-admin-ops-surface.d.ts +11 -11
- package/dist/access-admin-ops-surface.js +28 -28
- package/dist/access-audit.js +2 -2
- package/dist/access-authorization-probe.d.ts +11 -11
- package/dist/access-authorization-probe.js +29 -29
- package/dist/access-boundary.d.ts +11 -11
- package/dist/access-boundary.js +28 -28
- package/dist/access-cli.js +93 -91
- package/dist/access-cli.js.map +1 -1
- package/dist/access-coding-context-resolution.d.ts +1 -1
- package/dist/access-extraction-force-flush.d.ts +11 -11
- package/dist/access-extraction-force-flush.js +28 -28
- package/dist/access-health-types.d.ts +1 -1
- package/dist/access-http-lcm-compaction.d.ts +11 -11
- package/dist/access-http-lifecycle-flush.d.ts +11 -11
- package/dist/access-http-offline-stream.d.ts +11 -11
- package/dist/access-http-query.js +28 -28
- package/dist/access-http.d.ts +12 -12
- package/dist/access-http.js +38 -38
- package/dist/access-identity-continuity-surface.d.ts +9 -9
- package/dist/access-identity-continuity-surface.js +28 -28
- package/dist/access-lcm-surface.d.ts +11 -11
- package/dist/access-lcm-surface.js +28 -28
- package/dist/access-mcp.d.ts +11 -11
- package/dist/access-mcp.js +33 -33
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-EMvicnrb.d.ts → access-namespace-preflight-yO4LMGFH.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +28 -28
- package/dist/access-observe-write-surface.d.ts +11 -11
- package/dist/access-observe-write-surface.js +28 -28
- package/dist/access-offline-manifest.d.ts +9 -9
- package/dist/access-offline-manifest.js +2 -2
- package/dist/access-operations-batch.js +29 -29
- package/dist/access-operations.d.ts +11 -11
- package/dist/access-operations.js +32 -32
- package/dist/access-recall-concurrency.d.ts +11 -11
- package/dist/access-recall-concurrency.js +28 -28
- package/dist/access-recall-response.d.ts +11 -11
- package/dist/access-recall-response.js +28 -28
- package/dist/access-recall-surface.d.ts +11 -11
- package/dist/access-recall-surface.js +28 -28
- package/dist/{access-service-BeDYQQ62.d.ts → access-service-M4LgO141.d.ts} +7 -7
- package/dist/access-service-helpers.d.ts +11 -11
- package/dist/access-service.d.ts +11 -11
- package/dist/access-service.js +28 -28
- package/dist/access-surface-catalog.d.ts +11 -11
- package/dist/access-surface-catalog.js +30 -30
- package/dist/access-wearables-meetings-surface.d.ts +3 -3
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-memory-bridge.js +2 -2
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +3 -3
- package/dist/ambient-provenance.d.ts +1 -1
- package/dist/artifact-search.d.ts +1 -1
- package/dist/{auto-sync-FMWQQB3J.js → auto-sync-Z52VWMNC.js} +3 -3
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-learner.js +2 -2
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +9 -9
- package/dist/briefing-window.d.ts +2 -2
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +13 -12
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer-turn-helpers.d.ts +1 -1
- package/dist/buffer.d.ts +2 -2
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-B2SxZ6LU.d.ts → catalog-CyYTf_ok.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-behavior.js +3 -3
- package/dist/causal-chain.js +3 -3
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +16 -16
- package/dist/causal-retrieval.js +3 -3
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/causal-trajectory.js +2 -2
- package/dist/{chunk-B2QHVLJO.js → chunk-256FBCVX.js} +22 -10
- package/dist/chunk-256FBCVX.js.map +1 -0
- package/dist/{chunk-QP2IZTUR.js → chunk-2TYIAKU5.js} +2 -2
- package/dist/{chunk-HQBVQICL.js → chunk-347ZR6D4.js} +2 -2
- package/dist/{chunk-76YNCJ5H.js → chunk-3F3CVVDS.js} +2 -2
- package/dist/{chunk-TE4MKFT2.js → chunk-3MA7JVXN.js} +4 -4
- package/dist/{chunk-KHQ57QLJ.js → chunk-46WM6JX2.js} +7 -3
- package/dist/chunk-46WM6JX2.js.map +1 -0
- package/dist/chunk-47DU4SGJ.js +92 -0
- package/dist/chunk-47DU4SGJ.js.map +1 -0
- package/dist/{chunk-AWRJBAIH.js → chunk-4FFROSFG.js} +37 -14
- package/dist/{chunk-AWRJBAIH.js.map → chunk-4FFROSFG.js.map} +1 -1
- package/dist/{chunk-N4OYPGZS.js → chunk-4HO3542O.js} +2 -2
- package/dist/{chunk-HEEEMJ26.js → chunk-4IZ2IT7D.js} +3 -3
- package/dist/{chunk-4XAVQLBR.js → chunk-4Y2RHVCV.js} +2 -2
- package/dist/{chunk-33JBK2XP.js → chunk-5F6HMNMZ.js} +2 -2
- package/dist/{chunk-5WQMORU5.js → chunk-5PFGMO33.js} +2 -2
- package/dist/{chunk-6HEM6HTQ.js → chunk-6GGTATZF.js} +2 -2
- package/dist/{chunk-W3Y6FYRK.js → chunk-7BJYTX6Q.js} +2 -2
- package/dist/{chunk-2GRLJMKJ.js → chunk-7DRSWPUV.js} +3 -3
- package/dist/{chunk-TVVEYCNW.js → chunk-7K5Q6COX.js} +4 -4
- package/dist/{chunk-HXXGZ4KV.js → chunk-ALNZEWGN.js} +2 -2
- package/dist/{chunk-5WVUO6QT.js → chunk-AR253JBM.js} +1 -1
- package/dist/chunk-AR253JBM.js.map +1 -0
- package/dist/{chunk-S3B3UIQ3.js → chunk-AYIHDC5S.js} +2 -2
- package/dist/{chunk-2RIDW23Y.js → chunk-BBHFAVMP.js} +8 -8
- package/dist/{chunk-MJ4UGUR6.js → chunk-BHO6RHE5.js} +3 -3
- package/dist/{chunk-URN7XWGC.js → chunk-BP6WMYLP.js} +3 -3
- package/dist/{chunk-YUIBXMZY.js → chunk-CALURYWR.js} +284 -249
- package/dist/chunk-CALURYWR.js.map +1 -0
- package/dist/{chunk-D5HDJWNN.js → chunk-CH627RRV.js} +4 -4
- package/dist/{chunk-C3R732UY.js → chunk-CLJ5QS6J.js} +257 -60
- package/dist/chunk-CLJ5QS6J.js.map +1 -0
- package/dist/{chunk-YLHM5BQQ.js → chunk-DCUMFQYM.js} +171 -8
- package/dist/chunk-DCUMFQYM.js.map +1 -0
- package/dist/{chunk-ZBJMUXZH.js → chunk-DJ7HMNSL.js} +15 -8
- package/dist/chunk-DJ7HMNSL.js.map +1 -0
- package/dist/{chunk-XDK6ZFLL.js → chunk-DROAPP6N.js} +3 -3
- package/dist/{chunk-MU3TPZOV.js → chunk-DTLF2SLZ.js} +2 -2
- package/dist/{chunk-I67HKRBF.js → chunk-EFWHCTYJ.js} +2 -2
- package/dist/{chunk-XD4VGLDL.js → chunk-FF6E6HOT.js} +56 -52
- package/dist/chunk-FF6E6HOT.js.map +1 -0
- package/dist/{chunk-NP7FLVZW.js → chunk-G2FCSILA.js} +2 -2
- package/dist/{chunk-3GPBFDXH.js → chunk-H23GIXJC.js} +2 -2
- package/dist/{chunk-WT6UL3UA.js → chunk-H7PRHUBD.js} +2 -2
- package/dist/{chunk-4JGSG7QN.js → chunk-HSBQJRV2.js} +2 -2
- package/dist/{chunk-L33N3BCA.js → chunk-HVKMJAEF.js} +2 -2
- package/dist/{chunk-CSOYVTRX.js → chunk-IIPJKCZB.js} +3 -3
- package/dist/{chunk-E57E5SCS.js → chunk-IRLH4NM2.js} +3 -3
- package/dist/{chunk-H32ANIFP.js → chunk-IZRNVNPV.js} +2 -2
- package/dist/{chunk-XBR5BAKW.js → chunk-JCJGYNIS.js} +3 -3
- package/dist/{chunk-EIQFIJDM.js → chunk-JDI7G6EA.js} +2 -2
- package/dist/{chunk-QWPAQLYV.js → chunk-JFLKSD5V.js} +2 -2
- package/dist/{chunk-KQS72GCR.js → chunk-LJOIZPJH.js} +2 -2
- package/dist/{chunk-N4EPIKSY.js → chunk-LLGDVG52.js} +3 -3
- package/dist/{chunk-7N7DB4L5.js → chunk-LTJTP5YQ.js} +10 -9
- package/dist/chunk-LTJTP5YQ.js.map +1 -0
- package/dist/{chunk-VOELBUS4.js → chunk-NXH34IPL.js} +2 -2
- package/dist/{chunk-XL3TATMJ.js → chunk-OQIRBGUU.js} +21 -12
- package/dist/chunk-OQIRBGUU.js.map +1 -0
- package/dist/chunk-PJKTFXE2.js +119 -0
- package/dist/chunk-PJKTFXE2.js.map +1 -0
- package/dist/{chunk-JGW2EUCQ.js → chunk-PMRUMGK6.js} +2 -2
- package/dist/{chunk-KAB7TZN3.js → chunk-PSNN25DW.js} +2 -2
- package/dist/{chunk-LRGSLV7M.js → chunk-PYHOAXTI.js} +4 -4
- package/dist/{chunk-PA5OPZX2.js → chunk-QCI73Z7C.js} +2 -2
- package/dist/{chunk-EHMMRZOZ.js → chunk-QICOU4RY.js} +2 -2
- package/dist/{chunk-FW73HN33.js → chunk-RFH7U5LT.js} +2 -2
- package/dist/{chunk-4SGDYYWV.js → chunk-RPKJHYVE.js} +2 -2
- package/dist/{chunk-DSA47WBN.js → chunk-RYST72N5.js} +13 -2
- package/dist/chunk-RYST72N5.js.map +1 -0
- package/dist/{chunk-L4DLLKPN.js → chunk-SZ4HFZKB.js} +2 -2
- package/dist/chunk-T3GIETKV.js +152 -0
- package/dist/chunk-T3GIETKV.js.map +1 -0
- package/dist/{chunk-MYZ4NA43.js → chunk-TGSMU3F2.js} +3 -3
- package/dist/{chunk-CM4SZZBN.js → chunk-TIRJV2LW.js} +2 -2
- package/dist/{chunk-EGW4O32Z.js → chunk-UDTME32W.js} +7 -4
- package/dist/chunk-UDTME32W.js.map +1 -0
- package/dist/{chunk-CIA6ZUBA.js → chunk-WMOJIOIG.js} +2 -2
- package/dist/{chunk-W4Q54HM3.js → chunk-WR2YKUIW.js} +2 -2
- package/dist/{chunk-VWDTV6SH.js → chunk-X6E7TT3A.js} +2 -2
- package/dist/{chunk-D4OCJSLV.js → chunk-YDPAE2RD.js} +2 -2
- package/dist/{chunk-G3YBWFUC.js → chunk-YIIC5IDU.js} +35 -18
- package/dist/chunk-YIIC5IDU.js.map +1 -0
- package/dist/{chunk-QRKYABS6.js → chunk-YSR3DXGC.js} +2 -2
- package/dist/{chunk-LBJBNWS2.js → chunk-YTHQHH5U.js} +2 -2
- package/dist/{chunk-GN7HO2LA.js → chunk-ZPGHA7EO.js} +12 -12
- package/dist/{chunk-VUDALPI5.js → chunk-ZQKXRKMR.js} +19 -5
- package/dist/chunk-ZQKXRKMR.js.map +1 -0
- package/dist/{chunk-FQSDU634.js → chunk-ZS4JADYY.js} +3 -3
- package/dist/{cli-DB_uakTc.d.ts → cli-Bw9z-KqX.d.ts} +5 -5
- package/dist/cli.d.ts +13 -13
- package/dist/cli.js +62 -62
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/coding/pre-action-gate.js +3 -3
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +13 -12
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +3 -3
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +13 -12
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +13 -12
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +2 -2
- package/dist/converge-config.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +2 -2
- package/dist/convergence-refresh.js +15 -14
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/corpus-watermark.d.ts +1 -1
- package/dist/corpus-watermark.js +15 -14
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/dependency-propagation-config.d.ts +1 -1
- package/dist/{dependency-propagation-delivery-DcOVpK3y.d.ts → dependency-propagation-delivery-BxhvAppj.d.ts} +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer-wiring.js +3 -3
- package/dist/direct-answer.d.ts +1 -1
- package/dist/direct-answer.js +2 -2
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-origin-fields.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +13 -12
- package/dist/entity-schema.d.ts +1 -1
- package/dist/episodic-context.d.ts +92 -0
- package/dist/episodic-context.js +16 -0
- package/dist/episodic-context.js.map +1 -0
- package/dist/explicit-capture.d.ts +9 -9
- package/dist/external-wiki-access.d.ts +11 -11
- package/dist/external-wiki-access.js +29 -29
- package/dist/external-wiki-collection-registration.d.ts +1 -1
- package/dist/external-wiki-collection.d.ts +1 -1
- package/dist/external-wiki-mcp-tools.d.ts +11 -11
- package/dist/extraction-error-classification.d.ts +1 -1
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction-liveness.d.ts +1 -1
- package/dist/extraction-normalization.d.ts +1 -1
- package/dist/extraction-normalization.js +2 -2
- package/dist/extraction-prompt.d.ts +1 -1
- package/dist/extraction-source-grounding-rules.d.ts +1 -1
- package/dist/extraction-source-grounding.d.ts +1 -1
- package/dist/extraction-source-grounding.js +3 -3
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +18 -18
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/{forget-5TWK7CZT.js → forget-SZ2BXDGF.js} +2 -2
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-path-reconstruction.d.ts +1 -1
- package/dist/graph-path-scoring.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/harmonic-construction.js +2 -2
- package/dist/harmonic-retrieval.js +2 -2
- package/dist/importance.d.ts +1 -1
- package/dist/importers/index.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +1 -1
- package/dist/index.d.ts +22 -21
- package/dist/index.js +118 -103
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +8 -2
- package/dist/lcm/engine.js +4 -4
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +9 -9
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +13 -12
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +13 -12
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +14 -13
- package/dist/{maintenance-5c1olVtB.d.ts → maintenance-uJb74j64.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +11 -11
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-snapshot.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +2 -2
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +3 -3
- package/dist/namespaces/migrate.js +14 -13
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +6 -5
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +13 -12
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync-impression-drain.d.ts +1 -1
- package/dist/operator-doctor-corpus.d.ts +1 -1
- package/dist/operator-doctor-corpus.js +16 -15
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +21 -20
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +18 -17
- package/dist/{orchestrator-HPuY6I4i.d.ts → orchestrator-CFi-5JSR.d.ts} +23 -8
- package/dist/orchestrator.d.ts +9 -9
- package/dist/orchestrator.js +93 -91
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-CvVe1Q2_.d.ts → pipeline-BdF3ferY.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/policy-runtime.js +3 -3
- package/dist/proactive-contention.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/provenance.js +2 -2
- package/dist/{public-http-D0JKFkyf.d.ts → public-http-DK-QwaBu.d.ts} +1 -1
- package/dist/{qmd-Bd0Tp76_.d.ts → qmd-D_62bYNl.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +2 -2
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +2 -2
- package/dist/recall-concurrency-config.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-memory-map.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-query-policy.js +2 -2
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-timings.d.ts +1 -1
- package/dist/recall-tokenization.d.ts +3 -1
- package/dist/recall-tokenization.js +5 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/reconcile/cursor.d.ts +1 -1
- package/dist/reconcile/manifest.d.ts +10 -1
- package/dist/reconcile/manifest.js +1 -1
- package/dist/reconcile/plan.d.ts +1 -1
- package/dist/replay/normalizers/chatgpt.d.ts +1 -1
- package/dist/replay/normalizers/claude.d.ts +1 -1
- package/dist/replay/normalizers/openclaw.d.ts +1 -1
- package/dist/replay/normalizers/shared.d.ts +1 -1
- package/dist/replay/runner.d.ts +1 -1
- package/dist/replay/types.d.ts +1 -1
- package/dist/replica-divergence.d.ts +1 -1
- package/dist/replica-peers-config.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +6 -6
- package/dist/retrieval-agents.d.ts +2 -2
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/salvage-envelope.d.ts +1 -1
- package/dist/{scope-profiles-ClLtm9gK.d.ts → scope-profiles-CeMv7pP0.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +5 -4
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +9 -8
- package/dist/search/lancedb-backend.d.ts +14 -1
- package/dist/search/lancedb-backend.js +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +22 -1
- package/dist/search/orama-backend.js +2 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-B1EkeEDj.d.ts → semantic-consolidation-B-85brYj.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +14 -14
- package/dist/semantic-rule-promotion.js +13 -12
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +13 -13
- package/dist/{service-Cf3ANQj9.d.ts → service-CoO0HA2E.d.ts} +2 -2
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/source-agent-qualifier.d.ts +1 -1
- package/dist/source-agent-qualifier.js +15 -14
- package/dist/{storage-DS2O_6Qt.d.ts → storage-BVAVitkO.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +12 -11
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/support-passport/index.d.ts +14 -14
- package/dist/support-passport/index.js +31 -31
- package/dist/temporal-supersession.d.ts +2 -2
- package/dist/temporal-timeline-recall.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +2 -2
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/import-sqlite.js +2 -2
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/trust-zones.js +2 -2
- package/dist/{types-BOANGhCJ.d.ts → types-DWHOxlZP.d.ts} +3 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/user-message-cleaning.d.ts +23 -0
- package/dist/user-message-cleaning.js +10 -0
- package/dist/user-message-cleaning.js.map +1 -0
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +13 -13
- package/dist/whitespace.d.ts +26 -1
- package/dist/whitespace.js +11 -3
- package/dist/work-product-ledger.js +2 -2
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +12 -2
- package/src/access-service-offline-file-content.test.ts +1 -0
- package/src/cli.ts +14 -13
- package/src/config.ts +11 -0
- package/src/entity-retrieval.ts +4 -7
- package/src/episodic-context-recall.integration.test.ts +169 -0
- package/src/episodic-context.test.ts +266 -0
- package/src/episodic-context.ts +274 -0
- package/src/harmonic-construction.test.ts +187 -2
- package/src/harmonic-retrieval.ts +54 -32
- package/src/index.ts +3 -4
- package/src/lcm/engine.ts +18 -1
- package/src/lifecycle/tombstones.test.ts +134 -0
- package/src/lifecycle/tombstones.ts +29 -2
- package/src/orchestration/episodic-context-section.ts +255 -0
- package/src/orchestration/recall-internal-deps.ts +2 -0
- package/src/orchestration/recall-internal.ts +40 -25
- package/src/orchestration/recall-result-formatter.ts +37 -0
- package/src/orchestration/recall-section-coordinator.ts +20 -14
- package/src/recall-tokenization.ts +14 -8
- package/src/reconcile/manifest.test.ts +133 -4
- package/src/reconcile/manifest.ts +43 -7
- package/src/search/factory.ts +1 -0
- package/src/search/lancedb-backend.ts +24 -16
- package/src/search/orama-backend.test.ts +208 -1
- package/src/search/orama-backend.ts +133 -18
- package/src/search/orama-cjk-tokenizer.test.ts +108 -0
- package/src/search/orama-cjk-tokenizer.ts +143 -0
- package/src/storage/tombstone-migration-sources.test.ts +116 -0
- package/src/storage/tombstone-migration-sources.ts +90 -0
- package/src/storage.ts +13 -34
- package/src/types.ts +3 -3
- package/src/user-message-cleaning.ts +139 -0
- package/src/whitespace.test.ts +178 -0
- package/src/whitespace.ts +119 -0
- package/dist/chunk-5WVUO6QT.js.map +0 -1
- package/dist/chunk-6MKAMLQL.js +0 -16
- package/dist/chunk-6MKAMLQL.js.map +0 -1
- package/dist/chunk-7N7DB4L5.js.map +0 -1
- package/dist/chunk-B2QHVLJO.js.map +0 -1
- package/dist/chunk-C3R732UY.js.map +0 -1
- package/dist/chunk-DSA47WBN.js.map +0 -1
- package/dist/chunk-EGW4O32Z.js.map +0 -1
- package/dist/chunk-G3YBWFUC.js.map +0 -1
- package/dist/chunk-KHQ57QLJ.js.map +0 -1
- package/dist/chunk-VUDALPI5.js.map +0 -1
- package/dist/chunk-XD4VGLDL.js.map +0 -1
- package/dist/chunk-XL3TATMJ.js.map +0 -1
- package/dist/chunk-YLHM5BQQ.js.map +0 -1
- package/dist/chunk-YUIBXMZY.js.map +0 -1
- package/dist/chunk-ZBJMUXZH.js.map +0 -1
- /package/dist/{auto-sync-FMWQQB3J.js.map → auto-sync-Z52VWMNC.js.map} +0 -0
- /package/dist/{chunk-QP2IZTUR.js.map → chunk-2TYIAKU5.js.map} +0 -0
- /package/dist/{chunk-HQBVQICL.js.map → chunk-347ZR6D4.js.map} +0 -0
- /package/dist/{chunk-76YNCJ5H.js.map → chunk-3F3CVVDS.js.map} +0 -0
- /package/dist/{chunk-TE4MKFT2.js.map → chunk-3MA7JVXN.js.map} +0 -0
- /package/dist/{chunk-N4OYPGZS.js.map → chunk-4HO3542O.js.map} +0 -0
- /package/dist/{chunk-HEEEMJ26.js.map → chunk-4IZ2IT7D.js.map} +0 -0
- /package/dist/{chunk-4XAVQLBR.js.map → chunk-4Y2RHVCV.js.map} +0 -0
- /package/dist/{chunk-33JBK2XP.js.map → chunk-5F6HMNMZ.js.map} +0 -0
- /package/dist/{chunk-5WQMORU5.js.map → chunk-5PFGMO33.js.map} +0 -0
- /package/dist/{chunk-6HEM6HTQ.js.map → chunk-6GGTATZF.js.map} +0 -0
- /package/dist/{chunk-W3Y6FYRK.js.map → chunk-7BJYTX6Q.js.map} +0 -0
- /package/dist/{chunk-2GRLJMKJ.js.map → chunk-7DRSWPUV.js.map} +0 -0
- /package/dist/{chunk-TVVEYCNW.js.map → chunk-7K5Q6COX.js.map} +0 -0
- /package/dist/{chunk-HXXGZ4KV.js.map → chunk-ALNZEWGN.js.map} +0 -0
- /package/dist/{chunk-S3B3UIQ3.js.map → chunk-AYIHDC5S.js.map} +0 -0
- /package/dist/{chunk-2RIDW23Y.js.map → chunk-BBHFAVMP.js.map} +0 -0
- /package/dist/{chunk-MJ4UGUR6.js.map → chunk-BHO6RHE5.js.map} +0 -0
- /package/dist/{chunk-URN7XWGC.js.map → chunk-BP6WMYLP.js.map} +0 -0
- /package/dist/{chunk-D5HDJWNN.js.map → chunk-CH627RRV.js.map} +0 -0
- /package/dist/{chunk-XDK6ZFLL.js.map → chunk-DROAPP6N.js.map} +0 -0
- /package/dist/{chunk-MU3TPZOV.js.map → chunk-DTLF2SLZ.js.map} +0 -0
- /package/dist/{chunk-I67HKRBF.js.map → chunk-EFWHCTYJ.js.map} +0 -0
- /package/dist/{chunk-NP7FLVZW.js.map → chunk-G2FCSILA.js.map} +0 -0
- /package/dist/{chunk-3GPBFDXH.js.map → chunk-H23GIXJC.js.map} +0 -0
- /package/dist/{chunk-WT6UL3UA.js.map → chunk-H7PRHUBD.js.map} +0 -0
- /package/dist/{chunk-4JGSG7QN.js.map → chunk-HSBQJRV2.js.map} +0 -0
- /package/dist/{chunk-L33N3BCA.js.map → chunk-HVKMJAEF.js.map} +0 -0
- /package/dist/{chunk-CSOYVTRX.js.map → chunk-IIPJKCZB.js.map} +0 -0
- /package/dist/{chunk-E57E5SCS.js.map → chunk-IRLH4NM2.js.map} +0 -0
- /package/dist/{chunk-H32ANIFP.js.map → chunk-IZRNVNPV.js.map} +0 -0
- /package/dist/{chunk-XBR5BAKW.js.map → chunk-JCJGYNIS.js.map} +0 -0
- /package/dist/{chunk-EIQFIJDM.js.map → chunk-JDI7G6EA.js.map} +0 -0
- /package/dist/{chunk-QWPAQLYV.js.map → chunk-JFLKSD5V.js.map} +0 -0
- /package/dist/{chunk-KQS72GCR.js.map → chunk-LJOIZPJH.js.map} +0 -0
- /package/dist/{chunk-N4EPIKSY.js.map → chunk-LLGDVG52.js.map} +0 -0
- /package/dist/{chunk-VOELBUS4.js.map → chunk-NXH34IPL.js.map} +0 -0
- /package/dist/{chunk-JGW2EUCQ.js.map → chunk-PMRUMGK6.js.map} +0 -0
- /package/dist/{chunk-KAB7TZN3.js.map → chunk-PSNN25DW.js.map} +0 -0
- /package/dist/{chunk-LRGSLV7M.js.map → chunk-PYHOAXTI.js.map} +0 -0
- /package/dist/{chunk-PA5OPZX2.js.map → chunk-QCI73Z7C.js.map} +0 -0
- /package/dist/{chunk-EHMMRZOZ.js.map → chunk-QICOU4RY.js.map} +0 -0
- /package/dist/{chunk-FW73HN33.js.map → chunk-RFH7U5LT.js.map} +0 -0
- /package/dist/{chunk-4SGDYYWV.js.map → chunk-RPKJHYVE.js.map} +0 -0
- /package/dist/{chunk-L4DLLKPN.js.map → chunk-SZ4HFZKB.js.map} +0 -0
- /package/dist/{chunk-MYZ4NA43.js.map → chunk-TGSMU3F2.js.map} +0 -0
- /package/dist/{chunk-CM4SZZBN.js.map → chunk-TIRJV2LW.js.map} +0 -0
- /package/dist/{chunk-CIA6ZUBA.js.map → chunk-WMOJIOIG.js.map} +0 -0
- /package/dist/{chunk-W4Q54HM3.js.map → chunk-WR2YKUIW.js.map} +0 -0
- /package/dist/{chunk-VWDTV6SH.js.map → chunk-X6E7TT3A.js.map} +0 -0
- /package/dist/{chunk-D4OCJSLV.js.map → chunk-YDPAE2RD.js.map} +0 -0
- /package/dist/{chunk-QRKYABS6.js.map → chunk-YSR3DXGC.js.map} +0 -0
- /package/dist/{chunk-LBJBNWS2.js.map → chunk-YTHQHH5U.js.map} +0 -0
- /package/dist/{chunk-GN7HO2LA.js.map → chunk-ZPGHA7EO.js.map} +0 -0
- /package/dist/{chunk-FQSDU634.js.map → chunk-ZS4JADYY.js.map} +0 -0
- /package/dist/{forget-5TWK7CZT.js.map → forget-SZ2BXDGF.js.map} +0 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Episodic context planning (issue #2331, harmonic-memory P3).
|
|
3
|
+
*
|
|
4
|
+
* Turns the structured `sources` provenance on recalled facts into episode
|
|
5
|
+
* windows over the LCM archive: resolve each source's turn, group overlapping
|
|
6
|
+
* turn ranges within a session into merged episodes, and cap the episode
|
|
7
|
+
* count/span. Pure planning — no archive access — plus an async wrapper that
|
|
8
|
+
* applies the single documented fallback (quote lookup) through an injected
|
|
9
|
+
* locator so the planner stays testable without SQLite.
|
|
10
|
+
*
|
|
11
|
+
* Window bounds are `[start, end)` throughout (`toTurn` exclusive); the
|
|
12
|
+
* archive's `getMessages` bounds are inclusive, so the fetch site passes
|
|
13
|
+
* `toTurn - 1`.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { ProvenanceSource } from "./types.js";
|
|
17
|
+
|
|
18
|
+
/** One fact contributing to episodic planning, with its final recall rank. */
|
|
19
|
+
export interface EpisodicFactInput {
|
|
20
|
+
memoryId: string;
|
|
21
|
+
/** Final recall rank of the fact (0 = best). Lower wins. */
|
|
22
|
+
rank: number;
|
|
23
|
+
sources?: ProvenanceSource[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** A merged, fetch-ready episode window. */
|
|
27
|
+
export interface EpisodeWindow {
|
|
28
|
+
sessionKey: string;
|
|
29
|
+
/** Inclusive first turn. */
|
|
30
|
+
fromTurn: number;
|
|
31
|
+
/** EXCLUSIVE end turn (`[start, end)` semantics). */
|
|
32
|
+
toTurn: number;
|
|
33
|
+
/** Best (lowest) rank among contributing facts — drives ordering. */
|
|
34
|
+
factRank: number;
|
|
35
|
+
/** Sorted, deduplicated contributing memory ids (citation line). */
|
|
36
|
+
memoryIds: string[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Locates a quote's turn index within a session, or null on a miss. */
|
|
40
|
+
export type QuoteLocator = (
|
|
41
|
+
quote: string,
|
|
42
|
+
sessionKey: string,
|
|
43
|
+
) => Promise<number | null>;
|
|
44
|
+
|
|
45
|
+
const TURN_FIELD_SEPARATOR = String.fromCharCode(1);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Resolve a provenance `turnId` to a numeric LCM turn index, or null.
|
|
49
|
+
*
|
|
50
|
+
* Extraction writes `turnId` as the host turn fingerprint
|
|
51
|
+
* (`buildTurnFingerprint`: `role␁content␁thread␁turnIndex`), so the numeric
|
|
52
|
+
* LCM turn index is the LAST `␁`-separated field. A bare integer string is
|
|
53
|
+
* also accepted. Anything else is unresolvable — skip, never guess.
|
|
54
|
+
*/
|
|
55
|
+
export function resolveProvenanceTurnIndex(turnId: unknown): number | null {
|
|
56
|
+
if (typeof turnId !== "string" || turnId.length === 0) return null;
|
|
57
|
+
const lastField = turnId.includes(TURN_FIELD_SEPARATOR)
|
|
58
|
+
? turnId.split(TURN_FIELD_SEPARATOR).pop()!
|
|
59
|
+
: turnId;
|
|
60
|
+
if (!/^\d+$/.test(lastField)) return null;
|
|
61
|
+
const parsed = Number.parseInt(lastField, 10);
|
|
62
|
+
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
interface DraftWindow {
|
|
66
|
+
sessionKey: string;
|
|
67
|
+
fromTurn: number;
|
|
68
|
+
toTurn: number;
|
|
69
|
+
factRank: number;
|
|
70
|
+
bestTurn: number;
|
|
71
|
+
memoryIds: Set<string>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function windowForTurn(
|
|
75
|
+
sessionKey: string,
|
|
76
|
+
turn: number,
|
|
77
|
+
rank: number,
|
|
78
|
+
memoryId: string,
|
|
79
|
+
): DraftWindow {
|
|
80
|
+
const fromTurn = Math.max(0, turn - 1);
|
|
81
|
+
return {
|
|
82
|
+
sessionKey,
|
|
83
|
+
fromTurn,
|
|
84
|
+
toTurn: turn + 2,
|
|
85
|
+
factRank: rank,
|
|
86
|
+
bestTurn: turn,
|
|
87
|
+
memoryIds: new Set([memoryId]),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function mergeDrafts(drafts: DraftWindow[], maxTurnsPerEpisode: number): EpisodeWindow[] {
|
|
92
|
+
const bySession = new Map<string, DraftWindow[]>();
|
|
93
|
+
for (const draft of drafts) {
|
|
94
|
+
const list = bySession.get(draft.sessionKey);
|
|
95
|
+
if (list) list.push(draft);
|
|
96
|
+
else bySession.set(draft.sessionKey, [draft]);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const windows: EpisodeWindow[] = [];
|
|
100
|
+
for (const [, sessionDrafts] of bySession) {
|
|
101
|
+
// Sort by fromTurn, then toTurn, so a shuffle cannot change merge results.
|
|
102
|
+
sessionDrafts.sort(
|
|
103
|
+
(a, b) => a.fromTurn - b.fromTurn || a.toTurn - b.toTurn,
|
|
104
|
+
);
|
|
105
|
+
let current: DraftWindow | null = null;
|
|
106
|
+
const flush = () => {
|
|
107
|
+
if (!current) return;
|
|
108
|
+
windows.push(finalizeWindow(current, maxTurnsPerEpisode));
|
|
109
|
+
current = null;
|
|
110
|
+
};
|
|
111
|
+
for (const draft of sessionDrafts) {
|
|
112
|
+
if (current && draft.fromTurn <= current.toTurn) {
|
|
113
|
+
// Overlapping or adjacent ([a,b) + [b,c) share no turn but read as one
|
|
114
|
+
// continuous episode): merge. Merged bounds stay [start, end).
|
|
115
|
+
current.toTurn = Math.max(current.toTurn, draft.toTurn);
|
|
116
|
+
if (draft.factRank < current.factRank) {
|
|
117
|
+
current.factRank = draft.factRank;
|
|
118
|
+
current.bestTurn = draft.bestTurn;
|
|
119
|
+
}
|
|
120
|
+
for (const id of draft.memoryIds) current.memoryIds.add(id);
|
|
121
|
+
} else {
|
|
122
|
+
flush();
|
|
123
|
+
current = { ...draft, memoryIds: new Set(draft.memoryIds) };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
flush();
|
|
127
|
+
}
|
|
128
|
+
return windows;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function finalizeWindow(draft: DraftWindow, maxTurnsPerEpisode: number): EpisodeWindow {
|
|
132
|
+
let { fromTurn, toTurn } = draft;
|
|
133
|
+
const span = toTurn - fromTurn;
|
|
134
|
+
if (maxTurnsPerEpisode > 0 && span > maxTurnsPerEpisode) {
|
|
135
|
+
// Trim the tail but keep the highest-ranked fact's turn inside: anchor one
|
|
136
|
+
// turn of leading context on the best turn, clamped to the merged range.
|
|
137
|
+
fromTurn = Math.min(
|
|
138
|
+
Math.max(draft.bestTurn - 1, draft.fromTurn),
|
|
139
|
+
draft.toTurn - maxTurnsPerEpisode,
|
|
140
|
+
);
|
|
141
|
+
// maxTurnsPerEpisode === 1 (or a clamp collision) can push the anchor
|
|
142
|
+
// above the best turn; slide back down so the best turn stays included.
|
|
143
|
+
if (fromTurn + maxTurnsPerEpisode <= draft.bestTurn) {
|
|
144
|
+
fromTurn = Math.min(draft.bestTurn, draft.toTurn - maxTurnsPerEpisode);
|
|
145
|
+
}
|
|
146
|
+
toTurn = fromTurn + maxTurnsPerEpisode;
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
sessionKey: draft.sessionKey,
|
|
150
|
+
fromTurn,
|
|
151
|
+
toTurn,
|
|
152
|
+
factRank: draft.factRank,
|
|
153
|
+
memoryIds: [...draft.memoryIds].sort(),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Total, stable ordering: rank asc, sessionKey asc, fromTurn asc, then residual identity. */
|
|
158
|
+
export function compareEpisodeWindows(
|
|
159
|
+
left: EpisodeWindow,
|
|
160
|
+
right: EpisodeWindow,
|
|
161
|
+
): number {
|
|
162
|
+
const leftIds = left.memoryIds.join("\u{0}");
|
|
163
|
+
const rightIds = right.memoryIds.join("\u{0}");
|
|
164
|
+
return (
|
|
165
|
+
left.factRank - right.factRank ||
|
|
166
|
+
(left.sessionKey < right.sessionKey ? -1 : left.sessionKey > right.sessionKey ? 1 : 0) ||
|
|
167
|
+
left.fromTurn - right.fromTurn ||
|
|
168
|
+
left.toTurn - right.toTurn ||
|
|
169
|
+
(leftIds < rightIds ? -1 : leftIds > rightIds ? 1 : 0)
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Plan episode windows from recalled facts' structured provenance.
|
|
175
|
+
*
|
|
176
|
+
* Pure: no archive access. Facts without a structured `sources` array are
|
|
177
|
+
* skipped (no legacy scalar `source` parsing). Sources whose `turnId` does
|
|
178
|
+
* not resolve to a number are skipped — the caller decides whether to attempt
|
|
179
|
+
* the quote fallback for facts that lost every source.
|
|
180
|
+
*
|
|
181
|
+
* `maxEpisodes` or `maxTurnsPerEpisode` of 0 disables the section: returns
|
|
182
|
+
* `[]` before any work (zero semantics, checklist item 33).
|
|
183
|
+
*/
|
|
184
|
+
export function planEpisodeWindows(options: {
|
|
185
|
+
recalledFacts: ReadonlyArray<EpisodicFactInput>;
|
|
186
|
+
maxEpisodes: number;
|
|
187
|
+
maxTurnsPerEpisode: number;
|
|
188
|
+
}): EpisodeWindow[] {
|
|
189
|
+
if (options.maxEpisodes <= 0 || options.maxTurnsPerEpisode <= 0) return [];
|
|
190
|
+
const drafts: DraftWindow[] = [];
|
|
191
|
+
for (const fact of options.recalledFacts) {
|
|
192
|
+
if (!fact || !Array.isArray(fact.sources)) continue;
|
|
193
|
+
for (const source of fact.sources) {
|
|
194
|
+
if (!source || typeof source.sessionKey !== "string" || source.sessionKey.length === 0) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const turn = resolveProvenanceTurnIndex(source.turnId);
|
|
198
|
+
if (turn === null) continue;
|
|
199
|
+
drafts.push(
|
|
200
|
+
windowForTurn(source.sessionKey, turn, fact.rank, fact.memoryId),
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (drafts.length === 0) return [];
|
|
205
|
+
const windows = mergeDrafts(drafts, options.maxTurnsPerEpisode);
|
|
206
|
+
return windows.sort(compareEpisodeWindows).slice(0, options.maxEpisodes);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Facts whose sources all failed turn resolution but that carry a quote.
|
|
211
|
+
* These are the ONLY candidates for the quote-lookup fallback.
|
|
212
|
+
*/
|
|
213
|
+
export function factsNeedingQuoteFallback(
|
|
214
|
+
recalledFacts: ReadonlyArray<EpisodicFactInput>,
|
|
215
|
+
): EpisodicFactInput[] {
|
|
216
|
+
return recalledFacts.filter(
|
|
217
|
+
(fact) =>
|
|
218
|
+
fact &&
|
|
219
|
+
Array.isArray(fact.sources) &&
|
|
220
|
+
fact.sources.length > 0 &&
|
|
221
|
+
fact.sources.some((source) => typeof source?.quote === "string" && source.quote.length > 0) &&
|
|
222
|
+
!fact.sources.some((source) => resolveProvenanceTurnIndex(source?.turnId) !== null),
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Plan episode windows, applying the single documented fallback: for a fact
|
|
228
|
+
* whose turnIds ALL failed resolution but that has a quote, locate the quote
|
|
229
|
+
* in the archive and window around the located turn. A locator miss means the
|
|
230
|
+
* fact contributes no episode. Falls back to the pure plan when no locator is
|
|
231
|
+
* supplied.
|
|
232
|
+
*/
|
|
233
|
+
export async function planEpisodeWindowsWithFallback(options: {
|
|
234
|
+
recalledFacts: ReadonlyArray<EpisodicFactInput>;
|
|
235
|
+
maxEpisodes: number;
|
|
236
|
+
maxTurnsPerEpisode: number;
|
|
237
|
+
locateQuote?: QuoteLocator;
|
|
238
|
+
}): Promise<EpisodeWindow[]> {
|
|
239
|
+
const facts = [...options.recalledFacts];
|
|
240
|
+
const locator = options.locateQuote;
|
|
241
|
+
if (locator && facts.length > 0) {
|
|
242
|
+
for (const fact of factsNeedingQuoteFallback(options.recalledFacts)) {
|
|
243
|
+
for (const source of fact.sources ?? []) {
|
|
244
|
+
if (typeof source?.quote !== "string" || source.quote.length === 0) continue;
|
|
245
|
+
if (typeof source.sessionKey !== "string" || source.sessionKey.length === 0) continue;
|
|
246
|
+
let turn: number | null = null;
|
|
247
|
+
try {
|
|
248
|
+
turn = await locator(source.quote, source.sessionKey);
|
|
249
|
+
} catch {
|
|
250
|
+
turn = null;
|
|
251
|
+
}
|
|
252
|
+
if (turn === null || !Number.isSafeInteger(turn) || turn < 0) continue;
|
|
253
|
+
facts.push({
|
|
254
|
+
memoryId: fact.memoryId,
|
|
255
|
+
rank: fact.rank,
|
|
256
|
+
sources: [
|
|
257
|
+
{
|
|
258
|
+
sessionKey: source.sessionKey,
|
|
259
|
+
turnId: String(turn),
|
|
260
|
+
observedAt: source.observedAt,
|
|
261
|
+
quote: source.quote,
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
});
|
|
265
|
+
break; // one located quote per fact is enough to window it
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return planEpisodeWindows({
|
|
270
|
+
recalledFacts: facts,
|
|
271
|
+
maxEpisodes: options.maxEpisodes,
|
|
272
|
+
maxTurnsPerEpisode: options.maxTurnsPerEpisode,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
|
-
import { appendFile, mkdir, mkdtemp, open, readFile, rm, stat, unlink, utimes, writeFile } from "node:fs/promises";
|
|
3
|
+
import { appendFile, mkdir, mkdtemp, open, readdir, readFile, rm, stat, unlink, utimes, writeFile } from "node:fs/promises";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import test from "node:test";
|
|
7
7
|
import {
|
|
8
|
+
HARMONIC_SOURCE_MEMORY_INSERTED_AT_KEY,
|
|
8
9
|
getAbstractionNodeStoreStatus,
|
|
9
10
|
upsertAbstractionNode,
|
|
10
11
|
upsertAbstractionNodes,
|
|
@@ -26,12 +27,14 @@ import {
|
|
|
26
27
|
deriveHarmonicRecords,
|
|
27
28
|
normalizeCueAnchorInputs,
|
|
28
29
|
} from "./harmonic-construction.js";
|
|
29
|
-
import { searchHarmonicRetrieval } from "./harmonic-retrieval.js";
|
|
30
|
+
import { searchHarmonicRetrieval, type HarmonicRetrievalResult } from "./harmonic-retrieval.js";
|
|
30
31
|
import { readJsonFile, withJsonStoreMutationLock } from "./json-store.js";
|
|
31
32
|
import {
|
|
32
33
|
filterHarmonicEntityMentions,
|
|
33
34
|
persistConstructedHarmonicRecords,
|
|
34
35
|
} from "./orchestration/harmonic-construction-persist.js";
|
|
36
|
+
import { compareDeterministicStrings } from "./deterministic-order.js";
|
|
37
|
+
import { stripAttributesSuffix } from "./structured-attributes.js";
|
|
35
38
|
import { Orchestrator } from "./orchestrator.js";
|
|
36
39
|
import { ExtractedFactSchema, ExtractionResultSchema } from "./schemas.js";
|
|
37
40
|
import type { ExtractionResult, MemoryFile } from "./types.js";
|
|
@@ -1259,6 +1262,188 @@ test("harmonic anchors stay scoped to projected active sources in a mixed episod
|
|
|
1259
1262
|
}
|
|
1260
1263
|
});
|
|
1261
1264
|
|
|
1265
|
+
async function persistRecencyFixture(memoryDir: string): Promise<{
|
|
1266
|
+
storageDir: string;
|
|
1267
|
+
persistedIds: string[];
|
|
1268
|
+
contentById: Map<string, string>;
|
|
1269
|
+
}> {
|
|
1270
|
+
const config = parseConfig({
|
|
1271
|
+
openaiApiKey: "sk-test",
|
|
1272
|
+
memoryDir,
|
|
1273
|
+
workspaceDir: path.join(memoryDir, "workspace"),
|
|
1274
|
+
qmdEnabled: false,
|
|
1275
|
+
embeddingFallbackEnabled: false,
|
|
1276
|
+
chunkingEnabled: false,
|
|
1277
|
+
harmonicRetrievalEnabled: true,
|
|
1278
|
+
abstractionAnchorsEnabled: false,
|
|
1279
|
+
});
|
|
1280
|
+
const orchestrator = new Orchestrator(config) as unknown as PersistenceHarness;
|
|
1281
|
+
const storage = await orchestrator.getStorage("default");
|
|
1282
|
+
await storage.ensureDirectories();
|
|
1283
|
+
const contents = [
|
|
1284
|
+
"Atlas fact zero of the oldest insertion pair.",
|
|
1285
|
+
"Atlas fact one of the oldest insertion pair.",
|
|
1286
|
+
"Atlas fact two at the middle insertion time.",
|
|
1287
|
+
"Atlas fact three of the newest insertion pair.",
|
|
1288
|
+
"Atlas fact four of the newest insertion pair.",
|
|
1289
|
+
];
|
|
1290
|
+
const { persistedIds } = await orchestrator.persistExtraction(
|
|
1291
|
+
{
|
|
1292
|
+
facts: contents.map((content) => ({
|
|
1293
|
+
category: "fact",
|
|
1294
|
+
content,
|
|
1295
|
+
confidence: 0.99,
|
|
1296
|
+
tags: ["atlas"],
|
|
1297
|
+
entityRef: "atlas-project",
|
|
1298
|
+
cueAnchors: [],
|
|
1299
|
+
})),
|
|
1300
|
+
entities: [{ name: "atlas-project", type: "company", facts: [] }],
|
|
1301
|
+
profileUpdates: [],
|
|
1302
|
+
questions: [],
|
|
1303
|
+
relationships: [],
|
|
1304
|
+
episodeTitle: "Atlas insertion ordering",
|
|
1305
|
+
},
|
|
1306
|
+
storage,
|
|
1307
|
+
null,
|
|
1308
|
+
{ sessionKey: "session:harmonic-recency" }
|
|
1309
|
+
);
|
|
1310
|
+
const expectedContents = new Set(contents);
|
|
1311
|
+
const contentById = new Map<string, string>();
|
|
1312
|
+
const factIds: string[] = [];
|
|
1313
|
+
for (const persistedId of persistedIds) {
|
|
1314
|
+
const memory = await storage.getMemoryById(persistedId);
|
|
1315
|
+
if (!memory) continue;
|
|
1316
|
+
const content = memory.frontmatter.structuredAttributes
|
|
1317
|
+
? stripAttributesSuffix(memory.content)
|
|
1318
|
+
: memory.content;
|
|
1319
|
+
if (!expectedContents.has(content)) continue;
|
|
1320
|
+
factIds.push(persistedId);
|
|
1321
|
+
contentById.set(persistedId, content);
|
|
1322
|
+
}
|
|
1323
|
+
assert.equal(factIds.length, 5, `expected the five fact memories, got ${persistedIds.length} persisted`);
|
|
1324
|
+
return { storageDir: storage.dir, persistedIds: factIds, contentById };
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
async function rewriteTopicInsertedAt(
|
|
1328
|
+
storageDir: string,
|
|
1329
|
+
insertedAtById: Record<string, string> | null,
|
|
1330
|
+
recordedAt?: string
|
|
1331
|
+
): Promise<void> {
|
|
1332
|
+
const nodesDir = path.join(storageDir, "state", "abstraction-nodes", "nodes");
|
|
1333
|
+
for (const dayEntry of await readdir(nodesDir, { withFileTypes: true })) {
|
|
1334
|
+
if (!dayEntry.isDirectory()) continue;
|
|
1335
|
+
for (const entryName of await readdir(path.join(nodesDir, dayEntry.name))) {
|
|
1336
|
+
if (!entryName.endsWith(".json")) continue;
|
|
1337
|
+
const filePath = path.join(nodesDir, dayEntry.name, entryName);
|
|
1338
|
+
const node = JSON.parse(await readFile(filePath, "utf8")) as Record<string, unknown>;
|
|
1339
|
+
if (node.kind !== "topic") continue;
|
|
1340
|
+
const metadata = { ...(node.metadata as Record<string, string>) };
|
|
1341
|
+
if (insertedAtById === null) {
|
|
1342
|
+
delete metadata[HARMONIC_SOURCE_MEMORY_INSERTED_AT_KEY];
|
|
1343
|
+
} else {
|
|
1344
|
+
metadata[HARMONIC_SOURCE_MEMORY_INSERTED_AT_KEY] = JSON.stringify(insertedAtById);
|
|
1345
|
+
}
|
|
1346
|
+
await writeFile(
|
|
1347
|
+
filePath,
|
|
1348
|
+
`${JSON.stringify({ ...node, metadata, ...(recordedAt ? { recordedAt } : {}) }, null, 2)}\n`
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
async function findProjectedTopic(
|
|
1355
|
+
storageDir: string
|
|
1356
|
+
): Promise<HarmonicRetrievalResult | undefined> {
|
|
1357
|
+
const results = await searchHarmonicRetrieval({
|
|
1358
|
+
memoryDir: storageDir,
|
|
1359
|
+
query: "atlas",
|
|
1360
|
+
maxResults: 5,
|
|
1361
|
+
anchorsEnabled: false,
|
|
1362
|
+
});
|
|
1363
|
+
return results.find((result) => result.node.kind === "topic");
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
test("harmonic projection orders sources newest-first with deterministic tiebreak", async () => {
|
|
1367
|
+
const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-harmonic-recency-"));
|
|
1368
|
+
try {
|
|
1369
|
+
const { storageDir, persistedIds, contentById } = await persistRecencyFixture(memoryDir);
|
|
1370
|
+
const ascendingIds = [...persistedIds].sort(compareDeterministicStrings);
|
|
1371
|
+
const [first, second, third, fourth, fifth] = ascendingIds.map((memoryId) => memoryId);
|
|
1372
|
+
assert.ok(first && second && third && fourth && fifth);
|
|
1373
|
+
const oldest = "2026-01-01T00:00:00.000Z";
|
|
1374
|
+
const middle = "2026-02-01T00:00:00.000Z";
|
|
1375
|
+
const newest = "2026-03-01T00:00:00.000Z";
|
|
1376
|
+
const insertedAtByRank = [oldest, oldest, middle, newest, newest];
|
|
1377
|
+
await rewriteTopicInsertedAt(
|
|
1378
|
+
storageDir,
|
|
1379
|
+
Object.fromEntries(ascendingIds.map((memoryId, index) => [memoryId, insertedAtByRank[index]]))
|
|
1380
|
+
);
|
|
1381
|
+
|
|
1382
|
+
const topic = await findProjectedTopic(storageDir);
|
|
1383
|
+
assert.ok(topic, "topic node must stay retrievable");
|
|
1384
|
+
assert.deepEqual(topic.node.sourceMemoryIds, [fourth, fifth, third, first, second]);
|
|
1385
|
+
assert.equal(topic.node.title, contentById.get(fourth));
|
|
1386
|
+
assert.equal(
|
|
1387
|
+
topic.node.summary,
|
|
1388
|
+
[fourth, fifth, third].map((memoryId) => contentById.get(memoryId)).join("; ")
|
|
1389
|
+
);
|
|
1390
|
+
} finally {
|
|
1391
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
1392
|
+
}
|
|
1393
|
+
});
|
|
1394
|
+
|
|
1395
|
+
test("harmonic projection keeps ascending id order for equal or missing insertion timestamps", async () => {
|
|
1396
|
+
const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-harmonic-recency-equal-"));
|
|
1397
|
+
try {
|
|
1398
|
+
const { storageDir, persistedIds, contentById } = await persistRecencyFixture(memoryDir);
|
|
1399
|
+
const ascendingIds = [...persistedIds].sort(compareDeterministicStrings);
|
|
1400
|
+
const [first, second, third, fourth, fifth] = ascendingIds.map((memoryId) => memoryId);
|
|
1401
|
+
assert.ok(first && second && third && fourth && fifth);
|
|
1402
|
+
const expectedSummary = [first, second, third]
|
|
1403
|
+
.map((memoryId) => contentById.get(memoryId))
|
|
1404
|
+
.join("; ");
|
|
1405
|
+
|
|
1406
|
+
await rewriteTopicInsertedAt(
|
|
1407
|
+
storageDir,
|
|
1408
|
+
Object.fromEntries(ascendingIds.map((memoryId) => [memoryId, "2026-01-01T00:00:00.000Z"]))
|
|
1409
|
+
);
|
|
1410
|
+
let topic = await findProjectedTopic(storageDir);
|
|
1411
|
+
assert.ok(topic);
|
|
1412
|
+
assert.deepEqual(topic.node.sourceMemoryIds, ascendingIds);
|
|
1413
|
+
assert.equal(topic.node.title, contentById.get(first));
|
|
1414
|
+
assert.equal(topic.node.summary, expectedSummary);
|
|
1415
|
+
|
|
1416
|
+
await rewriteTopicInsertedAt(storageDir, null);
|
|
1417
|
+
topic = await findProjectedTopic(storageDir);
|
|
1418
|
+
assert.ok(topic);
|
|
1419
|
+
assert.deepEqual(topic.node.sourceMemoryIds, ascendingIds);
|
|
1420
|
+
assert.equal(topic.node.title, contentById.get(first));
|
|
1421
|
+
assert.equal(topic.node.summary, expectedSummary);
|
|
1422
|
+
|
|
1423
|
+
await rewriteTopicInsertedAt(
|
|
1424
|
+
storageDir,
|
|
1425
|
+
{
|
|
1426
|
+
[first]: "not-a-timestamp",
|
|
1427
|
+
[second]: "2026-01-01T00:00:00.000Z",
|
|
1428
|
+
[third]: "2026-02-01T00:00:00.000Z",
|
|
1429
|
+
[fourth]: "definitely not a date",
|
|
1430
|
+
[fifth]: "2026-03-01T00:00:00.000Z",
|
|
1431
|
+
},
|
|
1432
|
+
"2026-06-01T00:00:00.000Z"
|
|
1433
|
+
);
|
|
1434
|
+
topic = await findProjectedTopic(storageDir);
|
|
1435
|
+
assert.ok(topic);
|
|
1436
|
+
assert.deepEqual(topic.node.sourceMemoryIds, [first, fourth, fifth, third, second]);
|
|
1437
|
+
assert.equal(topic.node.title, contentById.get(first));
|
|
1438
|
+
assert.equal(
|
|
1439
|
+
topic.node.summary,
|
|
1440
|
+
[first, fourth, fifth].map((memoryId) => contentById.get(memoryId)).join("; ")
|
|
1441
|
+
);
|
|
1442
|
+
} finally {
|
|
1443
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
1444
|
+
}
|
|
1445
|
+
});
|
|
1446
|
+
|
|
1262
1447
|
test("non-default namespace construction ignores the default store override", async () => {
|
|
1263
1448
|
const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-harmonic-namespace-"));
|
|
1264
1449
|
try {
|
|
@@ -13,6 +13,7 @@ import { compareDeterministicStrings } from "./deterministic-order.js";
|
|
|
13
13
|
import { countRecallTokenOverlap, normalizeRecallTokens } from "./recall-tokenization.js";
|
|
14
14
|
import { stripAttributesSuffix } from "./structured-attributes.js";
|
|
15
15
|
import { isValidityExpiredNow } from "./temporal-validity.js";
|
|
16
|
+
import { isRecord } from "./store-contract.js";
|
|
16
17
|
import type { MemoryFile } from "./types.js";
|
|
17
18
|
|
|
18
19
|
type SourceMemoryMap = Map<string, MemoryFile>;
|
|
@@ -42,6 +43,22 @@ async function readSourceMemories(options: {
|
|
|
42
43
|
return sourceMemories;
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
function parseSourceMemoryInsertedAt(node: AbstractionNode): Map<string, string> {
|
|
47
|
+
const insertedAtById = new Map<string, string>();
|
|
48
|
+
const insertedAtRaw = node.metadata?.[HARMONIC_SOURCE_MEMORY_INSERTED_AT_KEY];
|
|
49
|
+
if (!insertedAtRaw) return insertedAtById;
|
|
50
|
+
try {
|
|
51
|
+
const parsed = JSON.parse(insertedAtRaw) as unknown;
|
|
52
|
+
if (!isRecord(parsed)) return insertedAtById;
|
|
53
|
+
for (const [memoryId, value] of Object.entries(parsed)) {
|
|
54
|
+
if (typeof value === "string") insertedAtById.set(memoryId, value);
|
|
55
|
+
}
|
|
56
|
+
} catch {
|
|
57
|
+
// Malformed insertion metadata leaves ordering on the recordedAt fallback.
|
|
58
|
+
}
|
|
59
|
+
return insertedAtById;
|
|
60
|
+
}
|
|
61
|
+
|
|
45
62
|
function projectSourceBackedNode(
|
|
46
63
|
node: AbstractionNode,
|
|
47
64
|
sourceMemories: SourceMemoryMap,
|
|
@@ -62,6 +79,19 @@ function projectSourceBackedNode(
|
|
|
62
79
|
});
|
|
63
80
|
if (activeSourceMemoryIds.length === 0) return null;
|
|
64
81
|
|
|
82
|
+
// Newest-first source order keeps the projected title and summary on the most
|
|
83
|
+
// recently inserted facts. Equal or missing timestamps fall back to ascending
|
|
84
|
+
// id order, which matches the stored sourceMemoryIds order.
|
|
85
|
+
const insertedAtById = parseSourceMemoryInsertedAt(node);
|
|
86
|
+
const insertedAtMs = (memoryId: string): number => {
|
|
87
|
+
const parsedMs = Date.parse(insertedAtById.get(memoryId) ?? "");
|
|
88
|
+
return Number.isFinite(parsedMs) ? parsedMs : Date.parse(node.recordedAt);
|
|
89
|
+
};
|
|
90
|
+
activeSourceMemoryIds.sort(
|
|
91
|
+
(left, right) =>
|
|
92
|
+
insertedAtMs(right) - insertedAtMs(left) || compareDeterministicStrings(left, right)
|
|
93
|
+
);
|
|
94
|
+
|
|
65
95
|
const activeMemories = activeSourceMemoryIds.flatMap((memoryId) => {
|
|
66
96
|
const memory = sourceMemories.get(memoryId);
|
|
67
97
|
return memory ? [memory] : [];
|
|
@@ -69,40 +99,32 @@ function projectSourceBackedNode(
|
|
|
69
99
|
const activeContents = activeMemories.map((memory) =>
|
|
70
100
|
memory.frontmatter.structuredAttributes ? stripAttributesSuffix(memory.content) : memory.content
|
|
71
101
|
);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (activeInsertedAt.length > 0) {
|
|
82
|
-
metadata = {
|
|
83
|
-
[HARMONIC_SOURCE_MEMORY_INSERTED_AT_KEY]: JSON.stringify(Object.fromEntries(activeInsertedAt)),
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
} catch {
|
|
87
|
-
metadata = undefined;
|
|
88
|
-
}
|
|
102
|
+
let metadata: Record<string, string> | undefined;
|
|
103
|
+
const activeInsertedAt = activeSourceMemoryIds.flatMap((memoryId) => {
|
|
104
|
+
const value = insertedAtById.get(memoryId);
|
|
105
|
+
return typeof value === "string" ? [[memoryId, value] as const] : [];
|
|
106
|
+
});
|
|
107
|
+
if (activeInsertedAt.length > 0) {
|
|
108
|
+
metadata = {
|
|
109
|
+
[HARMONIC_SOURCE_MEMORY_INSERTED_AT_KEY]: JSON.stringify(Object.fromEntries(activeInsertedAt)),
|
|
110
|
+
};
|
|
89
111
|
}
|
|
90
112
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
113
|
+
return {
|
|
114
|
+
...node,
|
|
115
|
+
sourceMemoryIds: activeSourceMemoryIds,
|
|
116
|
+
title: activeContents[0]?.slice(0, 80) ?? node.title,
|
|
117
|
+
summary: activeContents.slice(0, 3).join("; ").slice(0, 400),
|
|
118
|
+
tags: [...new Set(activeMemories.flatMap((memory) => memory.frontmatter.tags))].sort(compareDeterministicStrings),
|
|
119
|
+
entityRefs: [
|
|
120
|
+
...new Set(
|
|
121
|
+
activeMemories.flatMap((memory) =>
|
|
122
|
+
typeof memory.frontmatter.entityRef === "string" ? [memory.frontmatter.entityRef] : []
|
|
123
|
+
)
|
|
124
|
+
),
|
|
125
|
+
].sort(compareDeterministicStrings),
|
|
126
|
+
metadata,
|
|
127
|
+
};
|
|
106
128
|
}
|
|
107
129
|
|
|
108
130
|
function anchorMatchesProjectedNode(
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
*
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
export { collapseWhitespace, displayWidth, graphemeUnits, padEndDisplay, truncateCodePointSafe, truncateGraphemeSafe } from "./whitespace.js";
|
|
15
|
+
|
|
14
16
|
// ---------------------------------------------------------------------------
|
|
15
17
|
// Plugin entry resolution
|
|
16
18
|
// ---------------------------------------------------------------------------
|
|
@@ -1446,10 +1448,7 @@ export {
|
|
|
1446
1448
|
|
|
1447
1449
|
// Coding-graph engine contract (#1551 PR1), implemented by optional @remnic/coding-graph.
|
|
1448
1450
|
|
|
1449
|
-
export {
|
|
1450
|
-
CODING_GRAPH_ENGINE_VERSION,
|
|
1451
|
-
TIER_1_LANGUAGES,
|
|
1452
|
-
} from "./coding/coding-graph-types.js";
|
|
1451
|
+
export { CODING_GRAPH_ENGINE_VERSION, TIER_1_LANGUAGES } from "./coding/coding-graph-types.js";
|
|
1453
1452
|
|
|
1454
1453
|
export type {
|
|
1455
1454
|
CodingGraphEngine,
|
package/src/lcm/engine.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type Database from "better-sqlite3";
|
|
2
2
|
import { openLcmDatabase, ensureLcmStateDir } from "./schema.js";
|
|
3
|
-
import { LcmArchive, type LcmStructuredRecallMatch } from "./archive.js";
|
|
3
|
+
import { LcmArchive, type LcmMessage, type LcmStructuredRecallMatch } from "./archive.js";
|
|
4
4
|
import { LcmDag } from "./dag.js";
|
|
5
5
|
import { LcmSummarizer, type SummarizeFn } from "./summarizer.js";
|
|
6
6
|
import {
|
|
@@ -541,6 +541,23 @@ export class LcmEngine {
|
|
|
541
541
|
};
|
|
542
542
|
}
|
|
543
543
|
|
|
544
|
+
/**
|
|
545
|
+
* Retrieve raw archived messages for a turn range (inclusive bounds),
|
|
546
|
+
* read-only and unshaped — no token-budget trimming (issue #2331
|
|
547
|
+
* episodic-context). Callers own truncation and cleaning.
|
|
548
|
+
*/
|
|
549
|
+
async getTurnRange(
|
|
550
|
+
sessionId: string,
|
|
551
|
+
fromTurn: number,
|
|
552
|
+
toTurn: number,
|
|
553
|
+
): Promise<LcmMessage[]> {
|
|
554
|
+
if (!this.config.enabled) return [];
|
|
555
|
+
const normalizedSessionId = normalizeLcmSessionId(sessionId);
|
|
556
|
+
if (!normalizedSessionId) return [];
|
|
557
|
+
await this.ensureInitialized();
|
|
558
|
+
return this.archive!.getMessages(normalizedSessionId, fromTurn, toTurn);
|
|
559
|
+
}
|
|
560
|
+
|
|
544
561
|
/** Retrieve raw messages for a turn range (lossless expansion). */
|
|
545
562
|
async expandContext(
|
|
546
563
|
sessionId: string,
|