@remnic/core 9.66.8 → 9.66.9
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 +20 -20
- package/dist/access-authorization-probe.d.ts +11 -11
- package/dist/access-authorization-probe.js +21 -21
- package/dist/access-boundary.d.ts +11 -11
- package/dist/access-boundary.js +20 -20
- package/dist/access-cli.js +68 -67
- 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 +20 -20
- 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.d.ts +2 -2
- package/dist/access-http-query.js +22 -22
- package/dist/access-http.d.ts +12 -12
- package/dist/access-http.js +34 -34
- package/dist/access-identity-continuity-surface.d.ts +9 -9
- package/dist/access-identity-continuity-surface.js +20 -20
- package/dist/access-lcm-surface.d.ts +11 -11
- package/dist/access-lcm-surface.js +20 -20
- package/dist/access-mcp-output-schemas.js +1 -1
- package/dist/access-mcp.d.ts +11 -11
- package/dist/access-mcp.js +28 -28
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-50VIkPhB.d.ts → access-namespace-preflight-S8fhQcCo.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +20 -20
- package/dist/access-observe-write-surface.d.ts +11 -11
- package/dist/access-observe-write-surface.js +20 -20
- package/dist/access-offline-manifest.d.ts +9 -9
- package/dist/access-operations-batch.js +21 -21
- package/dist/access-operations.d.ts +16 -16
- package/dist/access-operations.js +26 -26
- package/dist/access-recall-concurrency.d.ts +11 -11
- package/dist/access-recall-concurrency.js +20 -20
- package/dist/access-recall-response.d.ts +11 -11
- package/dist/access-recall-response.js +20 -20
- package/dist/access-recall-surface.d.ts +11 -11
- package/dist/access-recall-surface.js +20 -20
- package/dist/access-schema.d.ts +89 -89
- package/dist/{access-service-C2tV2-uL.d.ts → access-service-DcfM0Vf0.d.ts} +71 -71
- package/dist/access-service-helpers.d.ts +11 -11
- package/dist/access-service.d.ts +11 -11
- package/dist/access-service.js +20 -20
- package/dist/access-surface-catalog.d.ts +11 -11
- package/dist/access-surface-catalog.js +22 -22
- 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-recall.d.ts +1 -1
- package/dist/active-recall.js +2 -2
- package/dist/ambient-provenance.d.ts +1 -1
- package/dist/artifact-search.d.ts +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- 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 +9 -9
- 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/buffer.js +4 -4
- 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-C2jA-gLm.d.ts → catalog-BmBXTtOs.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +10 -10
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-LWI43S46.js → chunk-23F7HGBV.js} +1 -1
- package/dist/{chunk-BDGWA5GK.js → chunk-3HHLOKKU.js} +2 -2
- package/dist/{chunk-FNK4KIYR.js → chunk-47BX23NA.js} +2 -2
- package/dist/{chunk-GO657WPH.js → chunk-52I6AHO6.js} +2 -2
- package/dist/{chunk-KKGWB2LG.js → chunk-5CSKIWEB.js} +3 -3
- package/dist/{chunk-EKUABFXQ.js → chunk-5GZ6UWY5.js} +6 -6
- package/dist/{chunk-MWLBRFLY.js → chunk-5KVMT25I.js} +2 -2
- package/dist/{chunk-6BYJQ3L2.js → chunk-5NZIRM4Q.js} +5 -5
- package/dist/{chunk-UMSTKKMV.js → chunk-7JPKRZD5.js} +2 -2
- package/dist/{chunk-UMZUKOJU.js → chunk-A7GQBJP5.js} +7 -2
- package/dist/chunk-A7GQBJP5.js.map +1 -0
- package/dist/{chunk-VYIPVLRX.js → chunk-AAJK3PZ6.js} +2 -2
- package/dist/{chunk-OERZXNSK.js → chunk-B3TZLAO4.js} +2 -2
- package/dist/{chunk-C24UZSFW.js → chunk-CEH2AFXG.js} +6 -6
- package/dist/{chunk-S63O62DN.js → chunk-CIWOW2FH.js} +2 -2
- package/dist/{chunk-IE7N2YK6.js → chunk-CNZVEU4X.js} +2 -2
- package/dist/{chunk-5UP5R37C.js → chunk-DGKVUPBM.js} +3 -3
- package/dist/{chunk-2YDU4VR7.js → chunk-FNYVWAIK.js} +18 -18
- package/dist/{chunk-XSPVSEAN.js → chunk-FUPIAP6Q.js} +3 -3
- package/dist/{chunk-5IYJWCLC.js → chunk-G3TUQJFU.js} +2 -2
- package/dist/{chunk-K7NUAY36.js → chunk-G775FE2E.js} +8 -8
- package/dist/{chunk-NEWY74GS.js → chunk-GB4R6B5M.js} +2 -2
- package/dist/{chunk-RI4CMRTZ.js → chunk-HWWGPS2N.js} +2 -2
- package/dist/{chunk-I2TIUGLC.js → chunk-IBHUZEKL.js} +2 -2
- package/dist/{chunk-NEDBOZ7G.js → chunk-J67E4JNT.js} +2 -2
- package/dist/{chunk-XUKS57W7.js → chunk-JHU543UU.js} +2 -2
- package/dist/{chunk-XDUQR5R7.js → chunk-JVGBDNXA.js} +2 -2
- package/dist/{chunk-IGOINKTD.js → chunk-K4E3Y3ZX.js} +2 -2
- package/dist/chunk-K4E3Y3ZX.js.map +1 -0
- package/dist/{chunk-GUG4LW4I.js → chunk-KIJCXLW7.js} +2 -2
- package/dist/{chunk-AVYNKPFS.js → chunk-KVXMN33W.js} +4 -4
- package/dist/chunk-LD72P4YS.js +29 -0
- package/dist/chunk-LD72P4YS.js.map +1 -0
- package/dist/chunk-LTDN5WYF.js +202 -0
- package/dist/chunk-LTDN5WYF.js.map +1 -0
- package/dist/{chunk-FI6FT6YX.js → chunk-MBDUNO7J.js} +2 -2
- package/dist/{chunk-MBXTGOFR.js → chunk-MFI4QPW5.js} +2 -2
- package/dist/{chunk-UJICQ77Y.js → chunk-MK7EJLB4.js} +2 -2
- package/dist/{chunk-UOQZOV2J.js → chunk-NABJLNLU.js} +64 -32
- package/dist/chunk-NABJLNLU.js.map +1 -0
- package/dist/{chunk-X32ALJQB.js → chunk-NSP3HFJZ.js} +2 -2
- package/dist/{chunk-6ULLVM2V.js → chunk-OJSCH7QT.js} +8 -8
- package/dist/{chunk-MFIFCXS3.js → chunk-OT7WQ2I3.js} +2 -2
- package/dist/{chunk-XVCYV7WQ.js → chunk-Q3UMNZRK.js} +3 -3
- package/dist/{chunk-O2RJZR6J.js → chunk-Q5YKVBIV.js} +2 -2
- package/dist/{chunk-KMPEBHH5.js → chunk-QU2V4IO3.js} +2 -2
- package/dist/{chunk-SVATDJNY.js → chunk-RF3LMSQW.js} +2 -2
- package/dist/{chunk-OMA2B7GY.js → chunk-RLEJULGN.js} +2 -2
- package/dist/{chunk-KH2LZMD5.js → chunk-SJ5L4ZZX.js} +2 -2
- package/dist/{chunk-2MYBDWUY.js → chunk-SOQLXIQX.js} +2 -2
- package/dist/{chunk-2V4YPDIX.js → chunk-SRILZVR4.js} +2 -2
- package/dist/{chunk-5S6TQ36T.js → chunk-TEJKBBWS.js} +10 -10
- package/dist/{chunk-5S6TQ36T.js.map → chunk-TEJKBBWS.js.map} +1 -1
- package/dist/{chunk-AZLSFKGU.js → chunk-TKSBOV7N.js} +5 -5
- package/dist/{chunk-YSYHSZWD.js → chunk-TWMGWLHD.js} +2 -2
- package/dist/{chunk-QK375NXZ.js → chunk-UAWSKMWQ.js} +2 -2
- package/dist/{chunk-FY62KW6Q.js → chunk-VCYY7XEL.js} +2 -2
- package/dist/{chunk-46XR5FNZ.js → chunk-VSWRJQQW.js} +31 -5
- package/dist/chunk-VSWRJQQW.js.map +1 -0
- package/dist/{chunk-6ZRLH4VS.js → chunk-VX5YHEGJ.js} +3 -3
- package/dist/{chunk-RPHCLGQ7.js → chunk-XVNDP3RO.js} +2 -2
- package/dist/{chunk-XORZMKVF.js → chunk-ZC5L6ME2.js} +3 -3
- package/dist/{chunk-7X63THIR.js → chunk-ZJGHOPEO.js} +28 -28
- package/dist/{chunk-ULTK4NZY.js → chunk-ZVUGRXSY.js} +2 -2
- package/dist/{cli-CsfFMe6n.d.ts → cli-CFpMhqz5.d.ts} +5 -5
- package/dist/cli.d.ts +13 -13
- package/dist/cli.js +51 -51
- package/dist/coding/export-okf-codegraph.d.ts +1 -1
- package/dist/coding/export-okf-codegraph.js +9 -9
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +9 -9
- 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 +2 -2
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +9 -9
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +9 -9
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +3 -3
- package/dist/converge-config.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +2 -2
- package/dist/convergence-refresh.js +11 -11
- 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 +11 -11
- package/dist/cross-lingual-recall.d.ts +1 -1
- 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-D4WMbOwA.d.ts → dependency-propagation-delivery-BC3bCEet.d.ts} +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- 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 +9 -9
- package/dist/entity-schema.d.ts +1 -1
- package/dist/episodic-context.d.ts +1 -1
- package/dist/eval-trajectory-contracts.d.ts +1 -1
- package/dist/eval-trajectory-store.d.ts +1 -1
- package/dist/eval-trajectory.d.ts +1 -1
- package/dist/explicit-capture.d.ts +9 -9
- package/dist/external-wiki-access.d.ts +11 -11
- package/dist/external-wiki-access.js +21 -21
- 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-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.d.ts +1 -1
- package/dist/extraction.js +12 -12
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/{first-start-migration-KHIMCBIC.js → first-start-migration-UG32BSG2.js} +4 -4
- 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-retrieval.js +1 -1
- 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-DuJnzwHv.d.ts → index-D4hS9uxK.d.ts} +2 -2
- package/dist/index.d.ts +719 -700
- package/dist/index.js +79 -76
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/engine.js +2 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +5 -4
- 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/location/index.d.ts +3 -3
- package/dist/location/index.js +11 -11
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +9 -9
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +9 -9
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +10 -10
- package/dist/{maintenance-BBeaeYRR.d.ts → maintenance-BRcc3Hx8.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-controller.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-subject-cli.d.ts +11 -11
- package/dist/memory-subject.d.ts +11 -11
- 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 +10 -10
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +6 -6
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +9 -9
- package/dist/native-binding-hint.d.ts +24 -0
- package/dist/native-binding-hint.js +10 -0
- package/dist/native-binding-hint.js.map +1 -0
- 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 +12 -12
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +19 -19
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +18 -18
- package/dist/{orchestrator-CaqnwNwM.d.ts → orchestrator-Btq9lzAN.d.ts} +8 -8
- package/dist/orchestrator.d.ts +9 -9
- package/dist/orchestrator.js +68 -67
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-CrxVjlJr.d.ts → pipeline-CZoNdFb5.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/proactive-contention.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/{public-http-Cwvl4QZr.d.ts → public-http-C9-CHc40.d.ts} +1 -1
- package/dist/{qmd-BZgbJm0g.d.ts → qmd-VIjSCKIE.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/qmd.js +4 -4
- 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-memory-map.d.ts +1 -1
- package/dist/recall-navigate-access.d.ts +1 -1
- package/dist/recall-navigate.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- 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-xray-cli.d.ts +1 -1
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray.d.ts +1 -1
- package/dist/reconcile/cursor.d.ts +1 -1
- package/dist/reconcile/manifest.d.ts +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 +3 -3
- 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/schemas.d.ts +176 -176
- package/dist/{scope-profiles-DFaojvoP.d.ts → scope-profiles-DqbxQXIS.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 -5
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +9 -9
- package/dist/search/lancedb-backend.d.ts +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 +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-BiX68wZA.d.ts → semantic-consolidation-DW3rEUoW.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +10 -10
- package/dist/semantic-rule-promotion.js +9 -9
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +9 -9
- package/dist/{service-D5h2zZ0M.d.ts → service-B2vJU_Bx.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 +7 -7
- package/dist/signal.d.ts +1 -1
- package/dist/source-agent-qualifier.d.ts +1 -1
- package/dist/source-agent-qualifier.js +11 -11
- package/dist/standup/build.d.ts +9 -3
- package/dist/standup/build.js +99 -7
- package/dist/{storage-CtsaojWD.d.ts → storage-6fn7BPmb.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +8 -8
- package/dist/subject-config.d.ts +1 -1
- 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 +23 -23
- 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/export-okf.d.ts +1 -1
- package/dist/transfer/export-okf.js +10 -10
- package/dist/transfer/types.d.ts +78 -78
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-CIpfYz1I.d.ts → types-eM7QIcX2.d.ts} +4 -0
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +9 -9
- package/dist/who-knows-cli.d.ts +11 -11
- package/dist/who-knows-cli.js +10 -10
- package/dist/who-knows.d.ts +11 -11
- package/dist/who-knows.js +9 -9
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/scripts/ensure-better-sqlite3.mjs +10 -0
- package/src/access-mcp-output-schemas.ts +1 -1
- package/src/activity/config.test.ts +1 -1
- package/src/activity/config.ts +20 -4
- package/src/activity/journal.test.ts +40 -0
- package/src/activity/timeline/index.ts +1 -0
- package/src/activity/timeline/recap-window.test.ts +129 -0
- package/src/activity/timeline/recap-window.ts +55 -0
- package/src/activity/types.ts +4 -0
- package/src/config.test.ts +1 -1
- package/src/dedup/index.ts +7 -0
- package/src/dedup/merge-decision.test.ts +157 -0
- package/src/dedup/merge-decision.ts +78 -0
- package/src/lcm/engine.ts +4 -1
- package/src/native-binding-hint.test.ts +38 -0
- package/src/native-binding-hint.ts +51 -0
- package/src/standup/build.test.ts +138 -12
- package/src/standup/build.ts +172 -23
- package/src/standup/http-glue.ts +1 -1
- package/dist/chunk-46XR5FNZ.js.map +0 -1
- package/dist/chunk-IGOINKTD.js.map +0 -1
- package/dist/chunk-UMZUKOJU.js.map +0 -1
- package/dist/chunk-UOQZOV2J.js.map +0 -1
- package/dist/chunk-VOSWUO3K.js +0 -100
- package/dist/chunk-VOSWUO3K.js.map +0 -1
- /package/dist/{chunk-LWI43S46.js.map → chunk-23F7HGBV.js.map} +0 -0
- /package/dist/{chunk-BDGWA5GK.js.map → chunk-3HHLOKKU.js.map} +0 -0
- /package/dist/{chunk-FNK4KIYR.js.map → chunk-47BX23NA.js.map} +0 -0
- /package/dist/{chunk-GO657WPH.js.map → chunk-52I6AHO6.js.map} +0 -0
- /package/dist/{chunk-KKGWB2LG.js.map → chunk-5CSKIWEB.js.map} +0 -0
- /package/dist/{chunk-EKUABFXQ.js.map → chunk-5GZ6UWY5.js.map} +0 -0
- /package/dist/{chunk-MWLBRFLY.js.map → chunk-5KVMT25I.js.map} +0 -0
- /package/dist/{chunk-6BYJQ3L2.js.map → chunk-5NZIRM4Q.js.map} +0 -0
- /package/dist/{chunk-UMSTKKMV.js.map → chunk-7JPKRZD5.js.map} +0 -0
- /package/dist/{chunk-VYIPVLRX.js.map → chunk-AAJK3PZ6.js.map} +0 -0
- /package/dist/{chunk-OERZXNSK.js.map → chunk-B3TZLAO4.js.map} +0 -0
- /package/dist/{chunk-C24UZSFW.js.map → chunk-CEH2AFXG.js.map} +0 -0
- /package/dist/{chunk-S63O62DN.js.map → chunk-CIWOW2FH.js.map} +0 -0
- /package/dist/{chunk-IE7N2YK6.js.map → chunk-CNZVEU4X.js.map} +0 -0
- /package/dist/{chunk-5UP5R37C.js.map → chunk-DGKVUPBM.js.map} +0 -0
- /package/dist/{chunk-2YDU4VR7.js.map → chunk-FNYVWAIK.js.map} +0 -0
- /package/dist/{chunk-XSPVSEAN.js.map → chunk-FUPIAP6Q.js.map} +0 -0
- /package/dist/{chunk-5IYJWCLC.js.map → chunk-G3TUQJFU.js.map} +0 -0
- /package/dist/{chunk-K7NUAY36.js.map → chunk-G775FE2E.js.map} +0 -0
- /package/dist/{chunk-NEWY74GS.js.map → chunk-GB4R6B5M.js.map} +0 -0
- /package/dist/{chunk-RI4CMRTZ.js.map → chunk-HWWGPS2N.js.map} +0 -0
- /package/dist/{chunk-I2TIUGLC.js.map → chunk-IBHUZEKL.js.map} +0 -0
- /package/dist/{chunk-NEDBOZ7G.js.map → chunk-J67E4JNT.js.map} +0 -0
- /package/dist/{chunk-XUKS57W7.js.map → chunk-JHU543UU.js.map} +0 -0
- /package/dist/{chunk-XDUQR5R7.js.map → chunk-JVGBDNXA.js.map} +0 -0
- /package/dist/{chunk-GUG4LW4I.js.map → chunk-KIJCXLW7.js.map} +0 -0
- /package/dist/{chunk-AVYNKPFS.js.map → chunk-KVXMN33W.js.map} +0 -0
- /package/dist/{chunk-FI6FT6YX.js.map → chunk-MBDUNO7J.js.map} +0 -0
- /package/dist/{chunk-MBXTGOFR.js.map → chunk-MFI4QPW5.js.map} +0 -0
- /package/dist/{chunk-UJICQ77Y.js.map → chunk-MK7EJLB4.js.map} +0 -0
- /package/dist/{chunk-X32ALJQB.js.map → chunk-NSP3HFJZ.js.map} +0 -0
- /package/dist/{chunk-6ULLVM2V.js.map → chunk-OJSCH7QT.js.map} +0 -0
- /package/dist/{chunk-MFIFCXS3.js.map → chunk-OT7WQ2I3.js.map} +0 -0
- /package/dist/{chunk-XVCYV7WQ.js.map → chunk-Q3UMNZRK.js.map} +0 -0
- /package/dist/{chunk-O2RJZR6J.js.map → chunk-Q5YKVBIV.js.map} +0 -0
- /package/dist/{chunk-KMPEBHH5.js.map → chunk-QU2V4IO3.js.map} +0 -0
- /package/dist/{chunk-SVATDJNY.js.map → chunk-RF3LMSQW.js.map} +0 -0
- /package/dist/{chunk-OMA2B7GY.js.map → chunk-RLEJULGN.js.map} +0 -0
- /package/dist/{chunk-KH2LZMD5.js.map → chunk-SJ5L4ZZX.js.map} +0 -0
- /package/dist/{chunk-2MYBDWUY.js.map → chunk-SOQLXIQX.js.map} +0 -0
- /package/dist/{chunk-2V4YPDIX.js.map → chunk-SRILZVR4.js.map} +0 -0
- /package/dist/{chunk-AZLSFKGU.js.map → chunk-TKSBOV7N.js.map} +0 -0
- /package/dist/{chunk-YSYHSZWD.js.map → chunk-TWMGWLHD.js.map} +0 -0
- /package/dist/{chunk-QK375NXZ.js.map → chunk-UAWSKMWQ.js.map} +0 -0
- /package/dist/{chunk-FY62KW6Q.js.map → chunk-VCYY7XEL.js.map} +0 -0
- /package/dist/{chunk-6ZRLH4VS.js.map → chunk-VX5YHEGJ.js.map} +0 -0
- /package/dist/{chunk-RPHCLGQ7.js.map → chunk-XVNDP3RO.js.map} +0 -0
- /package/dist/{chunk-XORZMKVF.js.map → chunk-ZC5L6ME2.js.map} +0 -0
- /package/dist/{chunk-7X63THIR.js.map → chunk-ZJGHOPEO.js.map} +0 -0
- /package/dist/{chunk-ULTK4NZY.js.map → chunk-ZVUGRXSY.js.map} +0 -0
- /package/dist/{first-start-migration-KHIMCBIC.js.map → first-start-migration-UG32BSG2.js.map} +0 -0
package/dist/who-knows.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { bA as WHO_KNOWS_AUTHORSHIP_BONUS, bB as WHO_KNOWS_DEFAULT_LIMIT, bC as WHO_KNOWS_MAX_EVIDENCE, bD as WHO_KNOWS_MAX_LIMIT, bE as WHO_KNOWS_MCP_TOOLS, bF as WhoKnowsEntity, bG as WhoKnowsEvidence, bH as WhoKnowsHit, bI as WhoKnowsHttpOutcome, W as WhoKnowsResult, bJ as WhoKnowsStorage, bT as computeWhoKnows, bZ as handleWhoKnowsHttpQuery, c2 as loadWhoKnowsEntities, c9 as tokenizeTopic, ca as validateWhoKnowsInput } from './access-service-
|
|
2
|
-
import './types-
|
|
3
|
-
import './orchestrator-
|
|
1
|
+
export { bA as WHO_KNOWS_AUTHORSHIP_BONUS, bB as WHO_KNOWS_DEFAULT_LIMIT, bC as WHO_KNOWS_MAX_EVIDENCE, bD as WHO_KNOWS_MAX_LIMIT, bE as WHO_KNOWS_MCP_TOOLS, bF as WhoKnowsEntity, bG as WhoKnowsEvidence, bH as WhoKnowsHit, bI as WhoKnowsHttpOutcome, W as WhoKnowsResult, bJ as WhoKnowsStorage, bT as computeWhoKnows, bZ as handleWhoKnowsHttpQuery, c2 as loadWhoKnowsEntities, c9 as tokenizeTopic, ca as validateWhoKnowsInput } from './access-service-DcfM0Vf0.js';
|
|
2
|
+
import './types-eM7QIcX2.js';
|
|
3
|
+
import './orchestrator-Btq9lzAN.js';
|
|
4
4
|
import './recall-state.js';
|
|
5
5
|
import './utils/serialize-mutations.js';
|
|
6
6
|
import './search/port.js';
|
|
@@ -16,7 +16,7 @@ import './active-context-config.js';
|
|
|
16
16
|
import './types-continuity.js';
|
|
17
17
|
import './included-memories.js';
|
|
18
18
|
import './briefing.js';
|
|
19
|
-
import './storage-
|
|
19
|
+
import './storage-6fn7BPmb.js';
|
|
20
20
|
import './corpus-read-cancellation.js';
|
|
21
21
|
import './artifact-search.js';
|
|
22
22
|
import './active-context-transform.js';
|
|
@@ -39,8 +39,8 @@ import './resolve-provider-secret.js';
|
|
|
39
39
|
import './transcript.js';
|
|
40
40
|
import './session-integrity.js';
|
|
41
41
|
import './summarizer.js';
|
|
42
|
-
import './maintenance-
|
|
43
|
-
import './catalog-
|
|
42
|
+
import './maintenance-BRcc3Hx8.js';
|
|
43
|
+
import './catalog-BmBXTtOs.js';
|
|
44
44
|
import './namespaces/search.js';
|
|
45
45
|
import './compounding/engine.js';
|
|
46
46
|
import './shared-context/manager.js';
|
|
@@ -50,7 +50,7 @@ import './utility-runtime.js';
|
|
|
50
50
|
import './tier-routing.js';
|
|
51
51
|
import './lifecycle.js';
|
|
52
52
|
import './orchestration/compression-guideline-coordinator.js';
|
|
53
|
-
import './semantic-consolidation-
|
|
53
|
+
import './semantic-consolidation-DW3rEUoW.js';
|
|
54
54
|
import './connectors/codex-materialize.js';
|
|
55
55
|
import './logger.js';
|
|
56
56
|
import './embedding-fallback.js';
|
|
@@ -72,10 +72,10 @@ import './conversation-index/chunker.js';
|
|
|
72
72
|
import './conversation-index/backend.js';
|
|
73
73
|
import './faiss-adapter-BHecI1fF.js';
|
|
74
74
|
import './runtime/child-process.js';
|
|
75
|
-
import './dependency-propagation-delivery-
|
|
75
|
+
import './dependency-propagation-delivery-BC3bCEet.js';
|
|
76
76
|
import './namespaces/storage.js';
|
|
77
77
|
import './threading.js';
|
|
78
|
-
import './scope-profiles-
|
|
78
|
+
import './scope-profiles-DqbxQXIS.js';
|
|
79
79
|
import './graph-444E-DrF.js';
|
|
80
80
|
import './recall-xray.js';
|
|
81
81
|
import './memory-provenance.js';
|
|
@@ -88,7 +88,7 @@ import './negative.js';
|
|
|
88
88
|
import './session-observer-state.js';
|
|
89
89
|
import './semantic-BalR6EXU.js';
|
|
90
90
|
import './replay/types.js';
|
|
91
|
-
import './service-
|
|
91
|
+
import './service-B2vJU_Bx.js';
|
|
92
92
|
import './extraction-judge.js';
|
|
93
93
|
import './lcm/engine.js';
|
|
94
94
|
import './lcm/archive.js';
|
|
@@ -110,7 +110,7 @@ import './recall-audit.js';
|
|
|
110
110
|
import './types-B1VHaf2w.js';
|
|
111
111
|
import './transfer/capsule-import.js';
|
|
112
112
|
import './transfer/types.js';
|
|
113
|
-
import './access-namespace-preflight-
|
|
113
|
+
import './access-namespace-preflight-S8fhQcCo.js';
|
|
114
114
|
import './access-token-capabilities.js';
|
|
115
115
|
import 'node:async_hooks';
|
|
116
116
|
import './recall-explain-renderer.js';
|
package/dist/who-knows.js
CHANGED
|
@@ -9,21 +9,21 @@ import {
|
|
|
9
9
|
loadWhoKnowsEntities,
|
|
10
10
|
tokenizeTopic,
|
|
11
11
|
validateWhoKnowsInput
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-UHVXE24Y.js";
|
|
12
|
+
} from "./chunk-AAJK3PZ6.js";
|
|
13
|
+
import "./chunk-G775FE2E.js";
|
|
15
14
|
import "./chunk-4ZWCQJNM.js";
|
|
15
|
+
import "./chunk-UHVXE24Y.js";
|
|
16
16
|
import "./chunk-WVGXCBOC.js";
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-B3TZLAO4.js";
|
|
18
|
+
import "./chunk-5NZIRM4Q.js";
|
|
19
|
+
import "./chunk-GIC6BASP.js";
|
|
19
20
|
import "./chunk-YQNNHLCG.js";
|
|
20
21
|
import "./chunk-6KTXE6A3.js";
|
|
21
22
|
import "./chunk-N37X5RU7.js";
|
|
22
23
|
import "./chunk-NNBZS3DY.js";
|
|
23
|
-
import "./chunk-CYEPCZN5.js";
|
|
24
|
-
import "./chunk-GIC6BASP.js";
|
|
25
24
|
import "./chunk-W7IGLX4G.js";
|
|
26
25
|
import "./chunk-GUMZC2BO.js";
|
|
26
|
+
import "./chunk-CYEPCZN5.js";
|
|
27
27
|
import "./chunk-227UFSEQ.js";
|
|
28
28
|
import "./chunk-ET356KSB.js";
|
|
29
29
|
import "./chunk-72A4L5JJ.js";
|
|
@@ -49,10 +49,10 @@ import "./chunk-RBOJCG4T.js";
|
|
|
49
49
|
import "./chunk-NNZFPYYX.js";
|
|
50
50
|
import "./chunk-5WITETWU.js";
|
|
51
51
|
import "./chunk-6CIAGZ6X.js";
|
|
52
|
-
import "./chunk-
|
|
52
|
+
import "./chunk-CEH2AFXG.js";
|
|
53
53
|
import "./chunk-JXN77SGO.js";
|
|
54
|
-
import "./chunk-ZLQ37WJX.js";
|
|
55
54
|
import "./chunk-IUM3VSHI.js";
|
|
55
|
+
import "./chunk-ZLQ37WJX.js";
|
|
56
56
|
import "./chunk-WKAXBXVA.js";
|
|
57
57
|
import "./chunk-BT7NVCML.js";
|
|
58
58
|
import "./chunk-C64XATK7.js";
|
package/dist/write-envelope.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { y as MemoryCategory, N as MemorySubject } from './types-
|
|
1
|
+
import { y as MemoryCategory, N as MemorySubject } from './types-eM7QIcX2.js';
|
|
2
2
|
import './message-parts/index.js';
|
|
3
3
|
import './bounded-jsonl-state.js';
|
|
4
4
|
import './operator-doctor-types.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/core",
|
|
3
|
-
"version": "9.66.
|
|
3
|
+
"version": "9.66.9",
|
|
4
4
|
"description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -3217,7 +3217,7 @@
|
|
|
3217
3217
|
"core"
|
|
3218
3218
|
],
|
|
3219
3219
|
"peerDependencies": {
|
|
3220
|
-
"@remnic/coding-graph": "^9.66.
|
|
3220
|
+
"@remnic/coding-graph": "^9.66.9"
|
|
3221
3221
|
},
|
|
3222
3222
|
"peerDependenciesMeta": {
|
|
3223
3223
|
"@remnic/coding-graph": {
|
|
@@ -30,6 +30,7 @@ if (!rebuild.ok) {
|
|
|
30
30
|
console.error(
|
|
31
31
|
"[remnic] Install the package dependencies so node-gyp is available locally, then retry installation.",
|
|
32
32
|
);
|
|
33
|
+
console.error(recoveryHint());
|
|
33
34
|
process.exit(rebuild.status ?? 1);
|
|
34
35
|
}
|
|
35
36
|
|
|
@@ -41,6 +42,7 @@ try {
|
|
|
41
42
|
console.error(
|
|
42
43
|
`[remnic] better-sqlite3 rebuild completed but the binding still does not load: ${errorMessage(error)}`,
|
|
43
44
|
);
|
|
45
|
+
console.error(recoveryHint());
|
|
44
46
|
process.exit(1);
|
|
45
47
|
}
|
|
46
48
|
|
|
@@ -123,3 +125,11 @@ function clearBetterSqlite3RequireCache(packageDir) {
|
|
|
123
125
|
function errorMessage(error) {
|
|
124
126
|
return error instanceof Error ? error.message : String(error);
|
|
125
127
|
}
|
|
128
|
+
|
|
129
|
+
function recoveryHint() {
|
|
130
|
+
const nodeMajor = process.versions.node.split(".")[0];
|
|
131
|
+
return (
|
|
132
|
+
`[remnic] Recovery: run \`npm rebuild better-sqlite3 --build-from-source\` with Node ${nodeMajor} ` +
|
|
133
|
+
`(ABI ${process.versions.modules}) — the shipped binding does not match this Node/ABI.`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
@@ -82,7 +82,7 @@ const TOOL_OUTPUT_SCHEMAS: Readonly<Record<string, Record<string, unknown>>> = {
|
|
|
82
82
|
skipped: T_NUMBER,
|
|
83
83
|
removed: T_ARRAY,
|
|
84
84
|
}),
|
|
85
|
-
standup: objectSchema({ date: T_STRING, yesterday: T_STRING, today: T_STRING, highlights: T_ARRAY, blockers: T_ARRAY, activityGrid: T_STRING, markdown: T_STRING }),
|
|
85
|
+
standup: objectSchema({ date: T_STRING, yesterday: T_STRING, today: T_STRING, highlights: T_ARRAY, priorities: T_ARRAY, blockers: T_ARRAY, activityGrid: T_STRING, markdown: T_STRING }),
|
|
86
86
|
action_confidence: objectSchema({
|
|
87
87
|
schemaVersion: T_NUMBER,
|
|
88
88
|
decision: T_STRING,
|
|
@@ -17,7 +17,7 @@ test("parseActivityConfig defaults to an inert, search-only configuration", () =
|
|
|
17
17
|
minConfidence: 0.7,
|
|
18
18
|
minImportance: "normal",
|
|
19
19
|
maxMemoriesPerDay: 0,
|
|
20
|
-
timeline: { enabled: false, journal: { enabled: false }, qa: { enabled: false, maxRangeDays: 31 } },
|
|
20
|
+
timeline: { enabled: false, journal: { enabled: false, source: "file" }, qa: { enabled: false, maxRangeDays: 31 } },
|
|
21
21
|
});
|
|
22
22
|
assert.deepEqual(parseActivityConfig(undefined), defaultActivityConfig());
|
|
23
23
|
});
|
package/src/activity/config.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { coerceBooleanLike, coerceNumber } from "../connectors/coerce.js";
|
|
2
2
|
import { assertValidTimezone } from "./digest.js";
|
|
3
|
+
import { resolveJournalSource } from "./journal-source.js";
|
|
3
4
|
import type { ImportanceLevel } from "../types.js";
|
|
4
5
|
import type {
|
|
5
6
|
ActivityConfig,
|
|
@@ -29,7 +30,7 @@ export function defaultActivityConfig(): ActivityConfig {
|
|
|
29
30
|
minConfidence: 0.7,
|
|
30
31
|
minImportance: "normal",
|
|
31
32
|
maxMemoriesPerDay: 0,
|
|
32
|
-
timeline: { enabled: false, journal: { enabled: false }, qa: { enabled: false, maxRangeDays: 31 } },
|
|
33
|
+
timeline: { enabled: false, journal: { enabled: false, source: "file" }, qa: { enabled: false, maxRangeDays: 31 } },
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
|
|
@@ -200,7 +201,7 @@ export function parseActivityConfig(raw: unknown): ActivityConfig {
|
|
|
200
201
|
* is malformed and must fail rather than silently disabling the layer.
|
|
201
202
|
*/
|
|
202
203
|
function parseTimelineConfig(raw: unknown): ActivityTimelineConfig {
|
|
203
|
-
if (raw === undefined) return { enabled: false, journal: { enabled: false }, qa: parseTimelineQaConfig(undefined) };
|
|
204
|
+
if (raw === undefined) return { enabled: false, journal: { enabled: false, source: "file" }, qa: parseTimelineQaConfig(undefined) };
|
|
204
205
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
205
206
|
throw new TypeError("activity.timeline must be an object");
|
|
206
207
|
}
|
|
@@ -217,7 +218,7 @@ function parseTimelineConfig(raw: unknown): ActivityTimelineConfig {
|
|
|
217
218
|
}
|
|
218
219
|
|
|
219
220
|
function parseTimelineJournalConfig(raw: unknown): ActivityTimelineJournalConfig {
|
|
220
|
-
if (raw === undefined) return { enabled: false };
|
|
221
|
+
if (raw === undefined) return { enabled: false, source: "file" };
|
|
221
222
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
222
223
|
throw new TypeError("activity.timeline.journal must be an object");
|
|
223
224
|
}
|
|
@@ -226,7 +227,22 @@ function parseTimelineJournalConfig(raw: unknown): ActivityTimelineJournalConfig
|
|
|
226
227
|
if (journal.enabled !== undefined && enabledValue === undefined) {
|
|
227
228
|
throw new TypeError("activity.timeline.journal.enabled must be a boolean");
|
|
228
229
|
}
|
|
229
|
-
|
|
230
|
+
const heading = journal.heading;
|
|
231
|
+
if (heading !== undefined && typeof heading !== "string") {
|
|
232
|
+
throw new TypeError("activity.timeline.journal.heading must be a string");
|
|
233
|
+
}
|
|
234
|
+
const source = journal.source === undefined ? "file" : typeof journal.source === "string" ? journal.source : "";
|
|
235
|
+
const resolved = resolveJournalSource({ source, heading: heading ?? "" });
|
|
236
|
+
if (!resolved.ok) {
|
|
237
|
+
if (resolved.error === "unknown_source") {
|
|
238
|
+
throw new RangeError('activity.timeline.journal.source must be one of "file", "vault"');
|
|
239
|
+
}
|
|
240
|
+
throw new RangeError('activity.timeline.journal.heading must be a non-empty string when source is "vault"');
|
|
241
|
+
}
|
|
242
|
+
if (resolved.mode === "vault") {
|
|
243
|
+
return { enabled: enabledValue ?? false, source: "vault", heading: resolved.heading };
|
|
244
|
+
}
|
|
245
|
+
return { enabled: enabledValue ?? false, source: "file" };
|
|
230
246
|
}
|
|
231
247
|
|
|
232
248
|
function parseTimelineQaConfig(raw: unknown): ActivityTimelineQaConfig {
|
|
@@ -32,6 +32,46 @@ test("activity.timeline.journal.enabled defaults off", () => {
|
|
|
32
32
|
);
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
+
test("activity.timeline.journal source defaults to file with no heading", () => {
|
|
36
|
+
const journal = parseActivityConfig(undefined).timeline.journal;
|
|
37
|
+
assert.equal(journal.source, "file");
|
|
38
|
+
assert.equal(journal.heading, undefined);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("activity.timeline.journal vault mode trims and stores the heading", () => {
|
|
42
|
+
const journal = parseActivityConfig({ timeline: { journal: { enabled: true, source: "vault", heading: " Journal " } } }).timeline.journal;
|
|
43
|
+
assert.deepEqual(journal, { enabled: true, source: "vault", heading: "Journal" });
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("activity.timeline.journal vault mode requires a non-empty heading", () => {
|
|
47
|
+
for (const heading of [undefined, "", " "]) {
|
|
48
|
+
assert.throws(
|
|
49
|
+
() => parseActivityConfig({ timeline: { journal: { source: "vault", heading } } }),
|
|
50
|
+
RangeError,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("activity.timeline.journal rejects an unknown source", () => {
|
|
56
|
+
assert.throws(
|
|
57
|
+
() => parseActivityConfig({ timeline: { journal: { source: "memoryDir" } } }),
|
|
58
|
+
/activity\.timeline\.journal\.source must be one of "file", "vault"/,
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("activity.timeline.journal rejects a non-string heading", () => {
|
|
63
|
+
assert.throws(
|
|
64
|
+
() => parseActivityConfig({ timeline: { journal: { heading: 5 } } }),
|
|
65
|
+
/activity\.timeline\.journal\.heading must be a string/,
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("activity.timeline.journal file mode ignores a provided heading", () => {
|
|
70
|
+
const journal = parseActivityConfig({ timeline: { journal: { source: "file", heading: "Ignored" } } }).timeline.journal;
|
|
71
|
+
assert.deepEqual(journal, { enabled: false, source: "file" });
|
|
72
|
+
assert.equal("heading" in journal, false);
|
|
73
|
+
});
|
|
74
|
+
|
|
35
75
|
test("seed is a hard no-op without force", () => {
|
|
36
76
|
withMemoryDir((memoryDir) => {
|
|
37
77
|
const first = seedJournal({
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
clipCardsToRecapWindow,
|
|
6
|
+
type RecapWindowCard,
|
|
7
|
+
} from "./recap-window.js";
|
|
8
|
+
|
|
9
|
+
const MINUTE = 60_000;
|
|
10
|
+
const DAY_START = Date.UTC(2026, 0, 15); // 2026-01-15T00:00:00Z
|
|
11
|
+
const DAY_END = DAY_START + 24 * 60 * 60_000;
|
|
12
|
+
|
|
13
|
+
const iso = (ms: number): string => new Date(ms).toISOString();
|
|
14
|
+
|
|
15
|
+
const card = (id: string, startMs: number, endMs: number): RecapWindowCard => ({
|
|
16
|
+
id,
|
|
17
|
+
startUtc: iso(startMs),
|
|
18
|
+
endUtc: iso(endMs),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe("clipCardsToRecapWindow", () => {
|
|
22
|
+
it("returns [] for empty input", () => {
|
|
23
|
+
assert.deepEqual(clipCardsToRecapWindow([], DAY_START, DAY_END), []);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("excludes a card ending exactly at windowStart and one starting exactly at windowEnd", () => {
|
|
27
|
+
const before = card("before", DAY_START - 2 * MINUTE, DAY_START);
|
|
28
|
+
const after = card("after", DAY_END, DAY_END + 2 * MINUTE);
|
|
29
|
+
const inside = card("inside", DAY_START, DAY_END);
|
|
30
|
+
|
|
31
|
+
const result = clipCardsToRecapWindow([before, after, inside], DAY_START, DAY_END);
|
|
32
|
+
|
|
33
|
+
assert.deepEqual(
|
|
34
|
+
result.map((c) => c.id),
|
|
35
|
+
["inside"],
|
|
36
|
+
);
|
|
37
|
+
assert.equal(result[0]?.startMs, DAY_START);
|
|
38
|
+
assert.equal(result[0]?.endMs, DAY_END);
|
|
39
|
+
assert.equal(result[0]?.durationMs, DAY_END - DAY_START);
|
|
40
|
+
|
|
41
|
+
// Each midnight-touching card lands in exactly one adjacent window.
|
|
42
|
+
const windowMs = DAY_END - DAY_START;
|
|
43
|
+
const prevDay = clipCardsToRecapWindow([before], DAY_START - windowMs, DAY_START);
|
|
44
|
+
const nextDay = clipCardsToRecapWindow([after], DAY_END, DAY_END + windowMs);
|
|
45
|
+
assert.equal(prevDay[0]?.id, "before");
|
|
46
|
+
assert.equal(nextDay[0]?.id, "after");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("clips a card straddling the window start", () => {
|
|
50
|
+
const straddle = card("straddle", DAY_START - 30 * MINUTE, DAY_START + 90 * MINUTE);
|
|
51
|
+
|
|
52
|
+
const result = clipCardsToRecapWindow([straddle], DAY_START, DAY_END);
|
|
53
|
+
|
|
54
|
+
assert.equal(result.length, 1);
|
|
55
|
+
assert.equal(result[0]?.startMs, DAY_START);
|
|
56
|
+
assert.equal(result[0]?.endMs, DAY_START + 90 * MINUTE);
|
|
57
|
+
assert.equal(result[0]?.durationMs, 90 * MINUTE);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("clips a card straddling the window end", () => {
|
|
61
|
+
const straddle = card("tail", DAY_END - 5 * MINUTE, DAY_END + 45 * MINUTE);
|
|
62
|
+
|
|
63
|
+
const result = clipCardsToRecapWindow([straddle], DAY_START, DAY_END);
|
|
64
|
+
|
|
65
|
+
assert.equal(result.length, 1);
|
|
66
|
+
assert.equal(result[0]?.endMs, DAY_END);
|
|
67
|
+
assert.equal(result[0]?.durationMs, 5 * MINUTE);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("skips cards with unparseable timestamps without throwing", () => {
|
|
71
|
+
const good = card("good", DAY_START + MINUTE, DAY_START + 10 * MINUTE);
|
|
72
|
+
const bad: RecapWindowCard[] = [
|
|
73
|
+
{ id: "bad-start", startUtc: "not-a-date", endUtc: iso(DAY_START + 5 * MINUTE) },
|
|
74
|
+
{ id: "bad-end", startUtc: iso(DAY_START), endUtc: "" },
|
|
75
|
+
good,
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
const result = clipCardsToRecapWindow(bad, DAY_START, DAY_END);
|
|
79
|
+
|
|
80
|
+
assert.deepEqual(
|
|
81
|
+
result.map((c) => c.id),
|
|
82
|
+
["good"],
|
|
83
|
+
);
|
|
84
|
+
assert.equal(result[0]?.durationMs, 9 * MINUTE);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("throws RangeError on inverted or empty window", () => {
|
|
88
|
+
assert.throws(
|
|
89
|
+
() => clipCardsToRecapWindow([], DAY_END, DAY_START),
|
|
90
|
+
RangeError,
|
|
91
|
+
);
|
|
92
|
+
assert.throws(
|
|
93
|
+
() => clipCardsToRecapWindow([], DAY_START, DAY_START),
|
|
94
|
+
RangeError,
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("throws RangeError on non-finite window bounds", () => {
|
|
99
|
+
// NaN and Infinity pass `end <= start`, so without an explicit finite
|
|
100
|
+
// check they would produce NaN timestamps instead of an error.
|
|
101
|
+
for (const [start, end] of [
|
|
102
|
+
[Number.NaN, DAY_END],
|
|
103
|
+
[DAY_START, Number.NaN],
|
|
104
|
+
[Number.POSITIVE_INFINITY, DAY_END],
|
|
105
|
+
[DAY_START, Number.POSITIVE_INFINITY],
|
|
106
|
+
] as const) {
|
|
107
|
+
assert.throws(() => clipCardsToRecapWindow([], start, end), /finite/);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("sorts by startMs then id, byte-identical across calls", () => {
|
|
112
|
+
const same = DAY_START + 60 * MINUTE;
|
|
113
|
+
const cards: RecapWindowCard[] = [
|
|
114
|
+
card("z-late", DAY_START + 120 * MINUTE, DAY_START + 130 * MINUTE),
|
|
115
|
+
card("b-tie", same, same + 10 * MINUTE),
|
|
116
|
+
card("a-tie", same, same + 10 * MINUTE),
|
|
117
|
+
card("early", DAY_START + 5 * MINUTE, DAY_START + 6 * MINUTE),
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
const first = clipCardsToRecapWindow(cards, DAY_START, DAY_END);
|
|
121
|
+
const second = clipCardsToRecapWindow(cards, DAY_START, DAY_END);
|
|
122
|
+
|
|
123
|
+
assert.deepEqual(
|
|
124
|
+
first.map((c) => c.id),
|
|
125
|
+
["early", "a-tie", "b-tie", "z-late"],
|
|
126
|
+
);
|
|
127
|
+
assert.deepEqual(first, second);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic half-open recap window clip (issue #2051).
|
|
3
|
+
*
|
|
4
|
+
* Clips cards to [windowStartMs, windowEndMs) so recap renderers share one
|
|
5
|
+
* day-boundary derivation instead of re-deriving it per renderer.
|
|
6
|
+
*/
|
|
7
|
+
export interface RecapWindowCard {
|
|
8
|
+
id: string;
|
|
9
|
+
startUtc: string;
|
|
10
|
+
endUtc: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ClippedRecapCard {
|
|
14
|
+
id: string;
|
|
15
|
+
startMs: number;
|
|
16
|
+
endMs: number;
|
|
17
|
+
durationMs: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function clipCardsToRecapWindow(
|
|
21
|
+
cards: readonly RecapWindowCard[],
|
|
22
|
+
windowStartMs: number,
|
|
23
|
+
windowEndMs: number,
|
|
24
|
+
): ClippedRecapCard[] {
|
|
25
|
+
// NaN fails every comparison, so an unchecked non-finite bound slips past the
|
|
26
|
+
// ordering guard and emits NaN timestamps and durations — `durationMs <= 0`
|
|
27
|
+
// is also false for NaN, so the card is not even dropped.
|
|
28
|
+
if (!Number.isFinite(windowStartMs) || !Number.isFinite(windowEndMs)) {
|
|
29
|
+
throw new RangeError(
|
|
30
|
+
`recap window bounds must be finite; got start ${windowStartMs} and end ${windowEndMs}`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
if (windowEndMs <= windowStartMs) {
|
|
34
|
+
throw new RangeError(
|
|
35
|
+
`recap window end ${windowEndMs} must be greater than start ${windowStartMs}`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
const out: ClippedRecapCard[] = [];
|
|
39
|
+
for (const card of cards) {
|
|
40
|
+
const startMs = Date.parse(card.startUtc);
|
|
41
|
+
const endMs = Date.parse(card.endUtc);
|
|
42
|
+
if (!Number.isFinite(startMs) || !Number.isFinite(endMs)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const clippedStart = Math.max(startMs, windowStartMs);
|
|
46
|
+
const clippedEnd = Math.min(endMs, windowEndMs);
|
|
47
|
+
const durationMs = clippedEnd - clippedStart;
|
|
48
|
+
if (durationMs <= 0) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
out.push({ id: card.id, startMs: clippedStart, endMs: clippedEnd, durationMs });
|
|
52
|
+
}
|
|
53
|
+
out.sort((a, b) => a.startMs - b.startMs || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
54
|
+
return out;
|
|
55
|
+
}
|
package/src/activity/types.ts
CHANGED
|
@@ -99,6 +99,10 @@ export interface ActivitySourceConfig {
|
|
|
99
99
|
/** Opt-in daily journal settings (issue #1984). Default off. */
|
|
100
100
|
export interface ActivityTimelineJournalConfig {
|
|
101
101
|
enabled: boolean;
|
|
102
|
+
/** Where the journal text is read from (issue #1987). */
|
|
103
|
+
source: "file" | "vault";
|
|
104
|
+
/** Vault section heading, trimmed. Required when `source` is `"vault"`; not stored in `"file"` mode. */
|
|
105
|
+
heading?: string;
|
|
102
106
|
}
|
|
103
107
|
|
|
104
108
|
/** Opt-in timeline Q&A range/search settings (issue #1983 PR1). Default off. */
|
package/src/config.test.ts
CHANGED
|
@@ -2569,7 +2569,7 @@ test("parseConfig forwards activity source settings", () => {
|
|
|
2569
2569
|
minConfidence: 0.7,
|
|
2570
2570
|
minImportance: "normal",
|
|
2571
2571
|
maxMemoriesPerDay: 0,
|
|
2572
|
-
timeline: { enabled: false, journal: { enabled: false }, qa: { enabled: false, maxRangeDays: 31 } },
|
|
2572
|
+
timeline: { enabled: false, journal: { enabled: false, source: "file" }, qa: { enabled: false, maxRangeDays: 31 } },
|
|
2573
2573
|
});
|
|
2574
2574
|
});
|
|
2575
2575
|
|
package/src/dedup/index.ts
CHANGED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
decideMergeOnWrite,
|
|
6
|
+
type MergeCandidate,
|
|
7
|
+
type MergeDecisionOptions,
|
|
8
|
+
} from "./merge-decision.js";
|
|
9
|
+
|
|
10
|
+
const OPTS: MergeDecisionOptions = { updateThreshold: 0.8, duplicateThreshold: 0.92 };
|
|
11
|
+
|
|
12
|
+
function candidate(overrides: Partial<MergeCandidate> = {}): MergeCandidate {
|
|
13
|
+
return {
|
|
14
|
+
id: "fact-1",
|
|
15
|
+
similarity: 0.85,
|
|
16
|
+
updatedAt: "2026-01-02T00:00:00.000Z",
|
|
17
|
+
...overrides,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
test("no candidates creates", () => {
|
|
22
|
+
assert.deepEqual(decideMergeOnWrite([], OPTS), { action: "create" });
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("best similarity at or above duplicateThreshold skips as duplicate", () => {
|
|
26
|
+
assert.deepEqual(
|
|
27
|
+
decideMergeOnWrite(
|
|
28
|
+
[candidate({ id: "low", similarity: 0.5 }), candidate({ id: "dup", similarity: 0.92 })],
|
|
29
|
+
OPTS,
|
|
30
|
+
),
|
|
31
|
+
{ action: "skip", reason: "duplicate" },
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("best similarity between thresholds updates the best candidate", () => {
|
|
36
|
+
assert.deepEqual(
|
|
37
|
+
decideMergeOnWrite(
|
|
38
|
+
[candidate({ id: "best", similarity: 0.9 }), candidate({ id: "worst", similarity: 0.81 })],
|
|
39
|
+
OPTS,
|
|
40
|
+
),
|
|
41
|
+
{ action: "update", targetId: "best" },
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("best similarity below updateThreshold creates", () => {
|
|
46
|
+
assert.deepEqual(
|
|
47
|
+
decideMergeOnWrite([candidate({ similarity: 0.79 })], OPTS),
|
|
48
|
+
{ action: "create" },
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("invalid thresholds throw RangeError", () => {
|
|
53
|
+
const bad: MergeDecisionOptions[] = [
|
|
54
|
+
{ updateThreshold: Number.NaN, duplicateThreshold: 0.9 },
|
|
55
|
+
{ updateThreshold: 0.8, duplicateThreshold: Number.POSITIVE_INFINITY },
|
|
56
|
+
{ updateThreshold: -0.1, duplicateThreshold: 0.9 },
|
|
57
|
+
{ updateThreshold: 0.8, duplicateThreshold: 1.1 },
|
|
58
|
+
{ updateThreshold: 0.92, duplicateThreshold: 0.8 }, // duplicate < update
|
|
59
|
+
];
|
|
60
|
+
for (const options of bad) {
|
|
61
|
+
assert.throws(() => decideMergeOnWrite([], options), RangeError);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("updateThreshold 0 is honored, never coerced up", () => {
|
|
66
|
+
const zero = { updateThreshold: 0, duplicateThreshold: 0.92 };
|
|
67
|
+
// similarity 0 is >= 0 -> update, not create and not default-band behavior
|
|
68
|
+
assert.deepEqual(
|
|
69
|
+
decideMergeOnWrite([candidate({ similarity: 0 })], zero),
|
|
70
|
+
{ action: "update", targetId: "fact-1" },
|
|
71
|
+
);
|
|
72
|
+
// no candidates still creates
|
|
73
|
+
assert.deepEqual(decideMergeOnWrite([], zero), { action: "create" });
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("malformed candidates are ignored, never thrown on", () => {
|
|
77
|
+
assert.deepEqual(
|
|
78
|
+
decideMergeOnWrite(
|
|
79
|
+
[
|
|
80
|
+
{ id: "", similarity: 0.99, updatedAt: "2026-01-01T00:00:00.000Z" },
|
|
81
|
+
{ id: " ", similarity: 0.99, updatedAt: "2026-01-01T00:00:00.000Z" },
|
|
82
|
+
{ id: "nan", similarity: Number.NaN, updatedAt: "2026-01-01T00:00:00.000Z" },
|
|
83
|
+
{ id: "inf", similarity: Number.POSITIVE_INFINITY, updatedAt: "2026-01-01T00:00:00.000Z" },
|
|
84
|
+
{ id: "high", similarity: 1.5, updatedAt: "2026-01-01T00:00:00.000Z" },
|
|
85
|
+
{ id: "neg", similarity: -0.2, updatedAt: "2026-01-01T00:00:00.000Z" },
|
|
86
|
+
{ id: "good", similarity: 0.85, updatedAt: "2026-01-02T00:00:00.000Z" },
|
|
87
|
+
],
|
|
88
|
+
OPTS,
|
|
89
|
+
),
|
|
90
|
+
{ action: "update", targetId: "good" },
|
|
91
|
+
);
|
|
92
|
+
// all-malformed behaves like no candidates
|
|
93
|
+
assert.deepEqual(
|
|
94
|
+
decideMergeOnWrite([{ id: "nan", similarity: Number.NaN, updatedAt: "x" }], OPTS),
|
|
95
|
+
{ action: "create" },
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("identical similarity and updatedAt tie-breaks on id ascending, deterministically", () => {
|
|
100
|
+
const candidates = [
|
|
101
|
+
candidate({ id: "b", similarity: 0.9, updatedAt: "2026-03-01T00:00:00.000Z" }),
|
|
102
|
+
candidate({ id: "a", similarity: 0.9, updatedAt: "2026-03-01T00:00:00.000Z" }),
|
|
103
|
+
candidate({ id: "c", similarity: 0.9, updatedAt: "2026-03-01T00:00:00.000Z" }),
|
|
104
|
+
];
|
|
105
|
+
const first = decideMergeOnWrite(candidates, OPTS);
|
|
106
|
+
const second = decideMergeOnWrite([...candidates].reverse(), OPTS);
|
|
107
|
+
assert.deepEqual(first, second);
|
|
108
|
+
assert.deepEqual(first, { action: "update", targetId: "a" });
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test("unparseable updatedAt sorts last", () => {
|
|
112
|
+
const candidates = [
|
|
113
|
+
candidate({ id: "bad-date", similarity: 0.9, updatedAt: "not-a-timestamp" }),
|
|
114
|
+
candidate({ id: "good-date", similarity: 0.9, updatedAt: "2026-03-01T00:00:00.000Z" }),
|
|
115
|
+
];
|
|
116
|
+
assert.deepEqual(decideMergeOnWrite(candidates, OPTS), { action: "update", targetId: "good-date" });
|
|
117
|
+
// newer timestamp wins when both parse
|
|
118
|
+
assert.deepEqual(
|
|
119
|
+
decideMergeOnWrite(
|
|
120
|
+
[
|
|
121
|
+
candidate({ id: "older", updatedAt: "2026-01-01T00:00:00.000Z" }),
|
|
122
|
+
candidate({ id: "newer", updatedAt: "2026-06-01T00:00:00.000Z" }),
|
|
123
|
+
],
|
|
124
|
+
OPTS,
|
|
125
|
+
),
|
|
126
|
+
{ action: "update", targetId: "newer" },
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Two unparseable timestamps must not make the comparator asymmetric: testing
|
|
131
|
+
// each side against NaN independently returned 1 for both orderings, so the
|
|
132
|
+
// winner depended on array order.
|
|
133
|
+
test("two unparseable updatedAt values break the tie by id, whatever the order", () => {
|
|
134
|
+
const options = { updateThreshold: 0.5, duplicateThreshold: 0.95 };
|
|
135
|
+
const alpha = { id: "alpha", similarity: 0.7, updatedAt: "not-a-date" };
|
|
136
|
+
const beta = { id: "beta", similarity: 0.7, updatedAt: "also-not-a-date" };
|
|
137
|
+
|
|
138
|
+
for (const candidates of [[alpha, beta], [beta, alpha]]) {
|
|
139
|
+
assert.deepEqual(decideMergeOnWrite(candidates, options), {
|
|
140
|
+
action: "update",
|
|
141
|
+
targetId: "alpha",
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test("a parseable updatedAt still outranks an unparseable one in both orders", () => {
|
|
147
|
+
const options = { updateThreshold: 0.5, duplicateThreshold: 0.95 };
|
|
148
|
+
const dated = { id: "zeta", similarity: 0.7, updatedAt: "2026-08-19T00:00:00.000Z" };
|
|
149
|
+
const undated = { id: "alpha", similarity: 0.7, updatedAt: "nope" };
|
|
150
|
+
|
|
151
|
+
for (const candidates of [[dated, undated], [undated, dated]]) {
|
|
152
|
+
assert.deepEqual(decideMergeOnWrite(candidates, options), {
|
|
153
|
+
action: "update",
|
|
154
|
+
targetId: "zeta",
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
});
|