@remnic/core 9.63.3 → 9.63.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-admin-ops-surface.d.ts +11 -11
- package/dist/access-admin-ops-surface.js +23 -23
- package/dist/access-authorization-probe.d.ts +11 -11
- package/dist/access-authorization-probe.js +24 -24
- package/dist/access-boundary.d.ts +11 -11
- package/dist/access-boundary.js +23 -23
- package/dist/access-cli.js +55 -54
- 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 +23 -23
- 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 +13 -1
- package/dist/access-http-query.js +27 -24
- package/dist/access-http.d.ts +12 -12
- package/dist/access-http.js +34 -33
- package/dist/access-identity-continuity-surface.d.ts +9 -9
- package/dist/access-identity-continuity-surface.js +23 -23
- package/dist/access-lcm-surface.d.ts +11 -11
- package/dist/access-lcm-surface.js +23 -23
- 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-yO4LMGFH.d.ts → access-namespace-preflight-DB0zXFek.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +23 -23
- package/dist/access-observe-write-surface.d.ts +11 -11
- package/dist/access-observe-write-surface.js +23 -23
- package/dist/access-offline-manifest.d.ts +9 -9
- package/dist/access-offline-manifest.js +3 -3
- package/dist/access-operations-batch.js +24 -24
- package/dist/access-operations.d.ts +14 -14
- package/dist/access-operations.js +27 -27
- package/dist/access-recall-concurrency.d.ts +11 -11
- package/dist/access-recall-concurrency.js +23 -23
- package/dist/access-recall-response.d.ts +11 -11
- package/dist/access-recall-response.js +23 -23
- package/dist/access-recall-surface.d.ts +11 -11
- package/dist/access-recall-surface.js +23 -23
- package/dist/access-schema.d.ts +88 -88
- package/dist/{access-service-M4LgO141.d.ts → access-service-cKQrte9Z.d.ts} +71 -77
- package/dist/access-service-helpers.d.ts +11 -11
- package/dist/access-service.d.ts +11 -11
- package/dist/access-service.js +23 -23
- package/dist/access-surface-catalog.d.ts +11 -11
- package/dist/access-surface-catalog.js +25 -25
- 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/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 +11 -11
- 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/{capsule-merge-HCJJMLPS.js → capsule-merge-SGIVB3WA.js} +5 -5
- package/dist/{catalog-CyYTf_ok.d.ts → catalog-CCzmf8IH.d.ts} +3 -11
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +12 -12
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-XFCQIQQU.js → chunk-2UM6WHME.js} +3 -3
- package/dist/{chunk-6F2UMP4H.js → chunk-3Z5TGRFA.js} +8 -8
- package/dist/{chunk-JJX5XEIG.js → chunk-77QZW2D6.js} +4 -4
- package/dist/{chunk-X4MGNVOO.js → chunk-7AF243WZ.js} +1 -1
- package/dist/{chunk-2ASAS3CQ.js → chunk-7KQB4EBS.js} +2 -2
- package/dist/{chunk-3LJ2L3T3.js → chunk-7LF2OHIJ.js} +2 -2
- package/dist/{chunk-VAMQU4W7.js → chunk-AYVCKGA6.js} +2 -2
- package/dist/{chunk-GTRGH4ZT.js → chunk-BB2LH5JM.js} +2 -2
- package/dist/{chunk-XMMESCPD.js → chunk-C64XATK7.js} +17 -27
- package/dist/chunk-C64XATK7.js.map +1 -0
- package/dist/{chunk-6UZR7KEK.js → chunk-CUDSA46O.js} +8 -2
- package/dist/chunk-CUDSA46O.js.map +1 -0
- package/dist/{chunk-PADG72LJ.js → chunk-DXDAQZ2K.js} +2 -2
- package/dist/{chunk-EJQXDKYK.js → chunk-DYZR3Z6D.js} +3 -3
- package/dist/{chunk-VN7IIQGS.js → chunk-E4KMY4KR.js} +2 -2
- package/dist/{chunk-ZQKXRKMR.js → chunk-EFKZT6AY.js} +2 -2
- package/dist/{chunk-DNRTKO2U.js → chunk-EJY3HJMT.js} +2 -2
- package/dist/{chunk-RYGJGXL6.js → chunk-ERPBRXVZ.js} +2 -2
- package/dist/{chunk-5UFQCU6M.js → chunk-F6JYBVL6.js} +27 -57
- package/dist/{chunk-5UFQCU6M.js.map → chunk-F6JYBVL6.js.map} +1 -1
- package/dist/{chunk-JWPG65LH.js → chunk-FHKXVTM5.js} +38 -39
- package/dist/chunk-FHKXVTM5.js.map +1 -0
- package/dist/{chunk-RPKJHYVE.js → chunk-FPEZ74F7.js} +2 -2
- package/dist/{chunk-Z334TJRB.js → chunk-GF7RQWXC.js} +2 -2
- package/dist/{chunk-6D7PZKCJ.js → chunk-GG4DN63W.js} +2 -2
- package/dist/{chunk-IM56VPKO.js → chunk-GTD4Q62X.js} +2 -6
- package/dist/{chunk-A73QHOZP.js → chunk-I5FLIB2J.js} +2 -2
- package/dist/{chunk-JJ7JW62R.js → chunk-IVXVLDNT.js} +12 -22
- package/dist/chunk-IVXVLDNT.js.map +1 -0
- package/dist/{chunk-NRFU5MVH.js → chunk-JOEJG4SD.js} +47 -1
- package/dist/chunk-JOEJG4SD.js.map +1 -0
- package/dist/{chunk-EJLTNPRY.js → chunk-KHCUVYCY.js} +3 -3
- package/dist/{chunk-QSIQVC32.js → chunk-KYTRF64R.js} +2 -2
- package/dist/{chunk-R74NCKEY.js → chunk-LX4TNSAE.js} +4 -4
- package/dist/{chunk-H6ZXNH5I.js → chunk-MUJ4QFUQ.js} +3 -3
- package/dist/{chunk-4NMVX5U7.js → chunk-NA56NSKL.js} +2 -2
- package/dist/{chunk-MR5HWQHS.js → chunk-NKB43PGI.js} +2 -2
- package/dist/{chunk-DLQQU4EG.js → chunk-NS5ETDYD.js} +2 -2
- package/dist/{chunk-44KHFMCM.js → chunk-OETHJBAL.js} +76 -53
- package/dist/{chunk-44KHFMCM.js.map → chunk-OETHJBAL.js.map} +1 -1
- package/dist/{chunk-KWN6NOHQ.js → chunk-PB4WVYGC.js} +2 -2
- package/dist/{chunk-Q35XGIEM.js → chunk-PBRCYYO7.js} +2 -2
- package/dist/{chunk-QYN5PXDZ.js → chunk-PMVPCZJZ.js} +4 -4
- package/dist/{chunk-AJSZ2EK6.js → chunk-QI5RDDEL.js} +3 -3
- package/dist/{chunk-I6OQCT3Y.js → chunk-QRWMS6SI.js} +2 -2
- package/dist/{chunk-ITYAXU4S.js → chunk-R6UMNP5C.js} +3 -3
- package/dist/{chunk-5W62VEFH.js → chunk-RWMSMTQP.js} +2 -2
- package/dist/{chunk-FKJVEW6O.js → chunk-SYVGVK4S.js} +2 -2
- package/dist/{chunk-TRPX6F2G.js → chunk-TSTI6A3A.js} +10 -13
- package/dist/chunk-TSTI6A3A.js.map +1 -0
- package/dist/{chunk-XZPSBGHA.js → chunk-UCLMKNHA.js} +2 -2
- package/dist/{chunk-ZMSZVISA.js → chunk-UFKPQBXH.js} +3 -3
- package/dist/{chunk-B2OOJCUX.js → chunk-UGHCZS6K.js} +2 -2
- package/dist/chunk-V3KIRICY.js +727 -0
- package/dist/chunk-V3KIRICY.js.map +1 -0
- package/dist/{chunk-6ZYQ36IB.js → chunk-VPHSMJ2E.js} +15 -2
- package/dist/chunk-VPHSMJ2E.js.map +1 -0
- package/dist/{chunk-E2GYBTSP.js → chunk-VYEPACWY.js} +2 -2
- package/dist/{chunk-5W5N7XJZ.js → chunk-X7LEDA74.js} +20 -753
- package/dist/chunk-X7LEDA74.js.map +1 -0
- package/dist/{chunk-KMAP7SNQ.js → chunk-XCB6QDL6.js} +2 -2
- package/dist/{chunk-WDUG2CH3.js → chunk-YEQCMA5L.js} +2 -2
- package/dist/{chunk-LZCSOUJ7.js → chunk-YFCEBB5P.js} +2 -2
- package/dist/{chunk-IKXUG6KC.js → chunk-YXMHUBN2.js} +2 -2
- package/dist/{chunk-GFNS3BHV.js → chunk-ZUPKNWRZ.js} +3 -3
- package/dist/{chunk-GSTIBXBW.js → chunk-ZVPVTPGI.js} +2 -2
- package/dist/{cli-Bw9z-KqX.d.ts → cli-BFBDYV0D.d.ts} +5 -5
- package/dist/cli.d.ts +13 -13
- package/dist/cli.js +45 -44
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +11 -11
- 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/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +11 -11
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +11 -11
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-provenance-check.js +5 -5
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/consolidation-undo.js +4 -4
- 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 +13 -13
- 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 +13 -13
- 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-BxhvAppj.d.ts → dependency-propagation-delivery-DiY5T63p.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 +11 -11
- package/dist/entity-schema.d.ts +1 -1
- package/dist/episodic-context.d.ts +1 -1
- package/dist/explicit-capture.d.ts +9 -9
- package/dist/explicit-capture.js +5 -5
- package/dist/external-wiki-access.d.ts +11 -11
- package/dist/external-wiki-access.js +24 -24
- 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 +14 -14
- package/dist/fallback-llm.d.ts +1 -1
- 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.d.ts +697 -697
- package/dist/index.js +57 -56
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- 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 +11 -11
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +11 -11
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +12 -12
- package/dist/{maintenance-uJb74j64.d.ts → maintenance-CaqA4z7V.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-cache.js +1 -1
- package/dist/memory-corpus-version.js +2 -2
- 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 +12 -12
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +4 -4
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +11 -11
- 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 +14 -14
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +20 -19
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +17 -16
- package/dist/{orchestrator-CFi-5JSR.d.ts → orchestrator-CSc9GfQv.d.ts} +8 -8
- package/dist/orchestrator.d.ts +9 -9
- package/dist/orchestrator.js +55 -54
- package/dist/page-versioning.js +4 -4
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-BdF3ferY.d.ts → pipeline-X606GdRJ.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-DK-QwaBu.d.ts → public-http-8PcrDIYi.d.ts} +1 -1
- package/dist/{qmd-CBSxevyb.d.ts → qmd-DCKeR-GX.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 +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-memory-map.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/manifest.js +2 -2
- 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/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 +108 -108
- package/dist/{scope-profiles-CeMv7pP0.d.ts → scope-profiles-_Y_RHCeE.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 +3 -3
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +3 -3
- 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-B-85brYj.d.ts → semantic-consolidation-DT2VSrU0.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +12 -12
- package/dist/semantic-rule-promotion.js +11 -11
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +11 -11
- package/dist/{service-CoO0HA2E.d.ts → service-BMo-gwDE.d.ts} +3 -3
- 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 +9 -9
- package/dist/signal.d.ts +1 -1
- package/dist/source-agent-qualifier.d.ts +1 -1
- package/dist/source-agent-qualifier.js +13 -13
- package/dist/{storage-BVAVitkO.d.ts → storage-CGzJGUUu.d.ts} +49 -24
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +10 -10
- 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 +26 -26
- 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/capsule-import.js +5 -5
- package/dist/transfer/types.d.ts +66 -66
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-DWHOxlZP.d.ts → types-CBEAYU76.d.ts} +112 -128
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +11 -11
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/access-http-query.ts +12 -0
- package/src/access-http.test.ts +32 -0
- package/src/access-http.ts +3 -7
- package/src/admin/admin-surfaces.test.ts +5 -10
- package/src/admin/admin-surfaces.ts +0 -16
- package/src/binary-lifecycle/pipeline.test.ts +1 -1
- package/src/binary-lifecycle/pipeline.ts +23 -9
- package/src/buffer.ts +6 -0
- package/src/chat/chat-cli.test.ts +53 -0
- package/src/chat/chat-cli.ts +22 -58
- package/src/dedup/index.test.ts +65 -1
- package/src/dedup/index.ts +24 -2
- package/src/maintenance/namespace-planner.ts +0 -2
- package/src/meetings/build.test.ts +20 -4
- package/src/meetings/build.ts +2 -2
- package/src/meetings/day-source.test.ts +3 -1
- package/src/meetings/day-source.ts +1 -12
- package/src/meetings/fuse.test.ts +64 -15
- package/src/meetings/fuse.ts +18 -12
- package/src/meetings/types.ts +4 -19
- package/src/memory-cache-derived.test.ts +90 -0
- package/src/memory-cache.ts +40 -42
- package/src/namespaces/catalog.test.ts +53 -8
- package/src/namespaces/catalog.ts +5 -37
- package/src/orchestration/turn-ingestion-snapshot.test.ts +167 -0
- package/src/orchestration/turn-ingestion.ts +2 -1
- package/src/storage/content-hash-index.ts +54 -0
- package/src/storage-contract/content-hash.test.ts +59 -1
- package/src/storage-fact-hash-index-defer.test.ts +9 -9
- package/src/storage.ts +39 -40
- package/dist/chunk-5W5N7XJZ.js.map +0 -1
- package/dist/chunk-6UZR7KEK.js.map +0 -1
- package/dist/chunk-6ZYQ36IB.js.map +0 -1
- package/dist/chunk-JJ7JW62R.js.map +0 -1
- package/dist/chunk-JWPG65LH.js.map +0 -1
- package/dist/chunk-NRFU5MVH.js.map +0 -1
- package/dist/chunk-TRPX6F2G.js.map +0 -1
- package/dist/chunk-XMMESCPD.js.map +0 -1
- /package/dist/{capsule-merge-HCJJMLPS.js.map → capsule-merge-SGIVB3WA.js.map} +0 -0
- /package/dist/{chunk-XFCQIQQU.js.map → chunk-2UM6WHME.js.map} +0 -0
- /package/dist/{chunk-6F2UMP4H.js.map → chunk-3Z5TGRFA.js.map} +0 -0
- /package/dist/{chunk-JJX5XEIG.js.map → chunk-77QZW2D6.js.map} +0 -0
- /package/dist/{chunk-X4MGNVOO.js.map → chunk-7AF243WZ.js.map} +0 -0
- /package/dist/{chunk-2ASAS3CQ.js.map → chunk-7KQB4EBS.js.map} +0 -0
- /package/dist/{chunk-3LJ2L3T3.js.map → chunk-7LF2OHIJ.js.map} +0 -0
- /package/dist/{chunk-VAMQU4W7.js.map → chunk-AYVCKGA6.js.map} +0 -0
- /package/dist/{chunk-GTRGH4ZT.js.map → chunk-BB2LH5JM.js.map} +0 -0
- /package/dist/{chunk-PADG72LJ.js.map → chunk-DXDAQZ2K.js.map} +0 -0
- /package/dist/{chunk-EJQXDKYK.js.map → chunk-DYZR3Z6D.js.map} +0 -0
- /package/dist/{chunk-VN7IIQGS.js.map → chunk-E4KMY4KR.js.map} +0 -0
- /package/dist/{chunk-ZQKXRKMR.js.map → chunk-EFKZT6AY.js.map} +0 -0
- /package/dist/{chunk-DNRTKO2U.js.map → chunk-EJY3HJMT.js.map} +0 -0
- /package/dist/{chunk-RYGJGXL6.js.map → chunk-ERPBRXVZ.js.map} +0 -0
- /package/dist/{chunk-RPKJHYVE.js.map → chunk-FPEZ74F7.js.map} +0 -0
- /package/dist/{chunk-Z334TJRB.js.map → chunk-GF7RQWXC.js.map} +0 -0
- /package/dist/{chunk-6D7PZKCJ.js.map → chunk-GG4DN63W.js.map} +0 -0
- /package/dist/{chunk-IM56VPKO.js.map → chunk-GTD4Q62X.js.map} +0 -0
- /package/dist/{chunk-A73QHOZP.js.map → chunk-I5FLIB2J.js.map} +0 -0
- /package/dist/{chunk-EJLTNPRY.js.map → chunk-KHCUVYCY.js.map} +0 -0
- /package/dist/{chunk-QSIQVC32.js.map → chunk-KYTRF64R.js.map} +0 -0
- /package/dist/{chunk-R74NCKEY.js.map → chunk-LX4TNSAE.js.map} +0 -0
- /package/dist/{chunk-H6ZXNH5I.js.map → chunk-MUJ4QFUQ.js.map} +0 -0
- /package/dist/{chunk-4NMVX5U7.js.map → chunk-NA56NSKL.js.map} +0 -0
- /package/dist/{chunk-MR5HWQHS.js.map → chunk-NKB43PGI.js.map} +0 -0
- /package/dist/{chunk-DLQQU4EG.js.map → chunk-NS5ETDYD.js.map} +0 -0
- /package/dist/{chunk-KWN6NOHQ.js.map → chunk-PB4WVYGC.js.map} +0 -0
- /package/dist/{chunk-Q35XGIEM.js.map → chunk-PBRCYYO7.js.map} +0 -0
- /package/dist/{chunk-QYN5PXDZ.js.map → chunk-PMVPCZJZ.js.map} +0 -0
- /package/dist/{chunk-AJSZ2EK6.js.map → chunk-QI5RDDEL.js.map} +0 -0
- /package/dist/{chunk-I6OQCT3Y.js.map → chunk-QRWMS6SI.js.map} +0 -0
- /package/dist/{chunk-ITYAXU4S.js.map → chunk-R6UMNP5C.js.map} +0 -0
- /package/dist/{chunk-5W62VEFH.js.map → chunk-RWMSMTQP.js.map} +0 -0
- /package/dist/{chunk-FKJVEW6O.js.map → chunk-SYVGVK4S.js.map} +0 -0
- /package/dist/{chunk-XZPSBGHA.js.map → chunk-UCLMKNHA.js.map} +0 -0
- /package/dist/{chunk-ZMSZVISA.js.map → chunk-UFKPQBXH.js.map} +0 -0
- /package/dist/{chunk-B2OOJCUX.js.map → chunk-UGHCZS6K.js.map} +0 -0
- /package/dist/{chunk-E2GYBTSP.js.map → chunk-VYEPACWY.js.map} +0 -0
- /package/dist/{chunk-KMAP7SNQ.js.map → chunk-XCB6QDL6.js.map} +0 -0
- /package/dist/{chunk-WDUG2CH3.js.map → chunk-YEQCMA5L.js.map} +0 -0
- /package/dist/{chunk-LZCSOUJ7.js.map → chunk-YFCEBB5P.js.map} +0 -0
- /package/dist/{chunk-IKXUG6KC.js.map → chunk-YXMHUBN2.js.map} +0 -0
- /package/dist/{chunk-GFNS3BHV.js.map → chunk-ZUPKNWRZ.js.map} +0 -0
- /package/dist/{chunk-GSTIBXBW.js.map → chunk-ZVPVTPGI.js.map} +0 -0
|
@@ -294,11 +294,25 @@ async function stageRedirect(
|
|
|
294
294
|
}
|
|
295
295
|
|
|
296
296
|
if (asset.redirectedAt === undefined) {
|
|
297
|
-
|
|
298
|
-
|
|
297
|
+
let remoteSeen = false;
|
|
298
|
+
for (const mdPath of mdFiles) {
|
|
299
|
+
try {
|
|
300
|
+
const content = await readMarkdownFile(mdPath);
|
|
301
|
+
if (content.includes(asset.mirroredPath)) {
|
|
302
|
+
remoteSeen = true;
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
} catch {
|
|
306
|
+
// Verify already succeeded; a later read error is not a local ref.
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
if (!remoteSeen) {
|
|
310
|
+
if (!dryRun) {
|
|
311
|
+
asset.status = "mirrored";
|
|
312
|
+
}
|
|
313
|
+
log.info(`[binary-lifecycle] preserved mirrored asset without redirected marker: ${asset.originalPath}${dryRun ? " [dry-run]" : ""}`);
|
|
314
|
+
continue;
|
|
299
315
|
}
|
|
300
|
-
log.info(`[binary-lifecycle] preserved mirrored asset without redirected marker: ${asset.originalPath}${dryRun ? " [dry-run]" : ""}`);
|
|
301
|
-
continue;
|
|
302
316
|
}
|
|
303
317
|
|
|
304
318
|
if (!Number.isFinite(new Date(asset.mirroredAt).getTime())) {
|
|
@@ -400,9 +414,6 @@ async function stageRedirect(
|
|
|
400
414
|
continue;
|
|
401
415
|
}
|
|
402
416
|
|
|
403
|
-
const redirectedAt = new Date().toISOString();
|
|
404
|
-
asset.redirectedAt = redirectedAt;
|
|
405
|
-
|
|
406
417
|
const verifyResult = await countRemainingLocalReferences(
|
|
407
418
|
memoryDir,
|
|
408
419
|
asset,
|
|
@@ -411,7 +422,10 @@ async function stageRedirect(
|
|
|
411
422
|
readMarkdownFile,
|
|
412
423
|
);
|
|
413
424
|
if (verifyResult.errors.length > 0 || verifyResult.remaining > 0) {
|
|
414
|
-
|
|
425
|
+
asset.status = "error";
|
|
426
|
+
// Failed verify must not read as a completed redirect (#2471); this also
|
|
427
|
+
// clears stale stamps written by manifests from before that fix.
|
|
428
|
+
delete asset.redirectedAt;
|
|
415
429
|
for (const msg of verifyResult.errors) {
|
|
416
430
|
log.error(`[binary-lifecycle] ${msg}`);
|
|
417
431
|
errors.push(msg);
|
|
@@ -424,7 +438,7 @@ async function stageRedirect(
|
|
|
424
438
|
continue;
|
|
425
439
|
}
|
|
426
440
|
asset.status = "redirected";
|
|
427
|
-
|
|
441
|
+
asset.redirectedAt = new Date().toISOString();
|
|
428
442
|
redirected++;
|
|
429
443
|
log.info(`[binary-lifecycle] redirected: ${asset.originalPath}`);
|
|
430
444
|
}
|
package/src/buffer.ts
CHANGED
|
@@ -619,6 +619,12 @@ export class SmartBuffer {
|
|
|
619
619
|
log.debug(
|
|
620
620
|
`buffer[${bufferKey}]: ${mutation.turnCountInWindow} turns, signal=${mutation.signalLevel}, decision=${decision}`,
|
|
621
621
|
);
|
|
622
|
+
if (decision !== "keep_buffering" && extractionTurns === undefined) {
|
|
623
|
+
extractionTurns = [
|
|
624
|
+
...mutation.retainedTurnsSnapshot,
|
|
625
|
+
...mutation.activeTurnsSnapshot,
|
|
626
|
+
];
|
|
627
|
+
}
|
|
622
628
|
return extractionTurns ? { decision, extractionTurns } : { decision };
|
|
623
629
|
}
|
|
624
630
|
|
|
@@ -15,6 +15,12 @@ import { withTempDir as managedWithTempDir } from "../testing/tmp-dir.js";
|
|
|
15
15
|
import type { EngramAccessService } from "../access-service.js";
|
|
16
16
|
import { parseConfig } from "../config.js";
|
|
17
17
|
import { runChatCli } from "./chat-cli.js";
|
|
18
|
+
import { processChatMessage } from "./chat-factory.js";
|
|
19
|
+
import {
|
|
20
|
+
createChatSession,
|
|
21
|
+
loadChatSession,
|
|
22
|
+
markPendingPlan,
|
|
23
|
+
} from "./chat-session.js";
|
|
18
24
|
import { DEFAULT_CHAT_CONFIG } from "./chat-config.js";
|
|
19
25
|
|
|
20
26
|
/** Capture stdout.write for the duration of `fn`. */
|
|
@@ -137,3 +143,50 @@ test("CLI: resumes an existing session by id", async () => {
|
|
|
137
143
|
assert.ok(second.includes("[session:"), "resumed run should also print a session id");
|
|
138
144
|
});
|
|
139
145
|
});
|
|
146
|
+
|
|
147
|
+
test("CLI --once: pending plan is visible on reload the same way as HTTP (issue #2479)", async () => {
|
|
148
|
+
await withTempDir(async (memoryDir) => {
|
|
149
|
+
const service = makeService({
|
|
150
|
+
memoryDir,
|
|
151
|
+
configRef: parseConfig({ memoryDir, chat: { ...DEFAULT_CHAT_CONFIG, enabled: true } }),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// CLI side: first turn mints the session.
|
|
155
|
+
const first = await captureStdout(() =>
|
|
156
|
+
runChatCli({ service, config: service.configRef!.chat, memoryDir, once: true, input: "hello" }),
|
|
157
|
+
);
|
|
158
|
+
const sessionId = /\[session: ([^\]]+)\]/.exec(first)![1]!;
|
|
159
|
+
// Pending plan minted by an earlier correction-preview turn.
|
|
160
|
+
await markPendingPlan(memoryDir, sessionId, "plan-cli-2479");
|
|
161
|
+
await captureStdout(() =>
|
|
162
|
+
runChatCli({ service, config: service.configRef!.chat, memoryDir, once: true, input: "anything else?", sessionId }),
|
|
163
|
+
);
|
|
164
|
+
const viaCli = await loadChatSession(memoryDir, sessionId);
|
|
165
|
+
// HTTP side: identical scenario through the shared processor.
|
|
166
|
+
const httpSession = await createChatSession(memoryDir, {});
|
|
167
|
+
await processChatMessage({
|
|
168
|
+
service,
|
|
169
|
+
config: service.configRef!.chat,
|
|
170
|
+
memoryDir,
|
|
171
|
+
message: "hello",
|
|
172
|
+
chatSessionId: httpSession.id,
|
|
173
|
+
});
|
|
174
|
+
await markPendingPlan(memoryDir, httpSession.id, "plan-http-2479");
|
|
175
|
+
await processChatMessage({
|
|
176
|
+
service,
|
|
177
|
+
config: service.configRef!.chat,
|
|
178
|
+
memoryDir,
|
|
179
|
+
message: "anything else?",
|
|
180
|
+
chatSessionId: httpSession.id,
|
|
181
|
+
});
|
|
182
|
+
const viaHttp = await loadChatSession(memoryDir, httpSession.id);
|
|
183
|
+
|
|
184
|
+
assert.equal(viaCli?.pendingPlanId, "plan-cli-2479", "CLI turn must leave the pending plan visible on reload");
|
|
185
|
+
assert.equal(viaHttp?.pendingPlanId, "plan-http-2479", "HTTP turn must leave the pending plan visible on reload");
|
|
186
|
+
// Transcript shape parity: both surfaces append the same role sequence.
|
|
187
|
+
assert.deepEqual(
|
|
188
|
+
viaCli!.transcript.map((e) => e.role),
|
|
189
|
+
viaHttp!.transcript.map((e) => e.role),
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
});
|
package/src/chat/chat-cli.ts
CHANGED
|
@@ -6,28 +6,25 @@
|
|
|
6
6
|
* and `--once` / non-TTY mode for scripting/tests
|
|
7
7
|
* (`echo "question" | remnic chat --once`).
|
|
8
8
|
*
|
|
9
|
+
* Every turn routes through the shared `processChatMessage` factory
|
|
10
|
+
* (issue #2479) so session lifecycle, transcript persistence, and
|
|
11
|
+
* pending-plan/promotion markers behave identically to the HTTP/MCP
|
|
12
|
+
* surfaces.
|
|
13
|
+
*
|
|
9
14
|
* This module is imported by cli.ts with a single thin registration line —
|
|
10
15
|
* the god-file ratchet (#1520) tracks cli.ts LOC.
|
|
11
16
|
*/
|
|
12
17
|
|
|
13
|
-
import readline from "node:readline";
|
|
14
18
|
import { createInterface } from "node:readline";
|
|
15
|
-
import { randomUUID } from "node:crypto";
|
|
16
19
|
|
|
17
20
|
import type { EngramAccessService } from "../access-service.js";
|
|
18
|
-
import type {
|
|
19
|
-
import
|
|
20
|
-
import type { ChatTurnResult } from "./chat-types.js";
|
|
21
|
-
import { ChatEngine } from "./chat-engine.js";
|
|
22
|
-
import { createProductionChatLlmAdapter } from "./chat-llm.js";
|
|
23
|
-
import { createChatExecutor } from "./chat-executor.js";
|
|
21
|
+
import type { ChatConfig, ChatTurnResult } from "./chat-types.js";
|
|
22
|
+
import { processChatMessage } from "./chat-factory.js";
|
|
24
23
|
import {
|
|
25
24
|
createChatSession,
|
|
26
25
|
loadChatSession,
|
|
27
|
-
appendTranscriptEntry,
|
|
28
26
|
sessionBelongsToPrincipal,
|
|
29
27
|
} from "./chat-session.js";
|
|
30
|
-
import { isConfirmationMessage } from "./chat-engine.js";
|
|
31
28
|
|
|
32
29
|
/**
|
|
33
30
|
* Read all of stdin to a UTF-8 string (non-TTY / scripting mode).
|
|
@@ -78,16 +75,10 @@ export async function runChatCli(opts: ChatCliOptions): Promise<void> {
|
|
|
78
75
|
return;
|
|
79
76
|
}
|
|
80
77
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
): Promise<{ content: string } | null>;
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// Load or create session FIRST so the executor inherits the session's
|
|
89
|
-
// stored namespace/sessionKey scope — a resumed session created via MCP
|
|
90
|
-
// must not lose its scope binding (codex review, Thread 19).
|
|
78
|
+
// Resolve the session up front so the banner and --once output print a
|
|
79
|
+
// stable session id. Each turn then routes through processChatMessage,
|
|
80
|
+
// which reloads the session from disk — persisted state markers
|
|
81
|
+
// (pending plan/promotion) stay authoritative across turns.
|
|
91
82
|
let session;
|
|
92
83
|
if (opts.sessionId) {
|
|
93
84
|
session = await loadChatSession(opts.memoryDir, opts.sessionId);
|
|
@@ -107,21 +98,15 @@ export async function runChatCli(opts: ChatCliOptions): Promise<void> {
|
|
|
107
98
|
});
|
|
108
99
|
}
|
|
109
100
|
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
executor,
|
|
120
|
-
maxToolCallsPerTurn: config.maxToolCallsPerTurn,
|
|
121
|
-
...(config.model ? { model: config.model } : {}),
|
|
122
|
-
correctionAvailable: false,
|
|
123
|
-
scopeInspectAvailable: false,
|
|
124
|
-
});
|
|
101
|
+
const processTurn = (message: string): Promise<ChatTurnResult> =>
|
|
102
|
+
processChatMessage({
|
|
103
|
+
service: opts.service,
|
|
104
|
+
config,
|
|
105
|
+
memoryDir: opts.memoryDir,
|
|
106
|
+
message,
|
|
107
|
+
chatSessionId: session.id,
|
|
108
|
+
principal: opts.principal,
|
|
109
|
+
});
|
|
125
110
|
|
|
126
111
|
// ── Non-TTY / --once mode ───────────────────────────────────────────
|
|
127
112
|
if (opts.once) {
|
|
@@ -131,17 +116,7 @@ export async function runChatCli(opts: ChatCliOptions): Promise<void> {
|
|
|
131
116
|
process.stdout.write("[error] No input provided.\n");
|
|
132
117
|
return;
|
|
133
118
|
}
|
|
134
|
-
const
|
|
135
|
-
role: "user",
|
|
136
|
-
content: message,
|
|
137
|
-
});
|
|
138
|
-
session.transcript.push(userEntry);
|
|
139
|
-
const result = await engine.processMessage(message, session);
|
|
140
|
-
const assistantEntry = await appendTranscriptEntry(opts.memoryDir, session.id, {
|
|
141
|
-
role: "assistant",
|
|
142
|
-
content: result.reply,
|
|
143
|
-
});
|
|
144
|
-
session.transcript.push(assistantEntry);
|
|
119
|
+
const result = await processTurn(message);
|
|
145
120
|
process.stdout.write(result.reply + "\n");
|
|
146
121
|
process.stdout.write(`[session: ${session.id}]\n`);
|
|
147
122
|
return;
|
|
@@ -173,18 +148,7 @@ export async function runChatCli(opts: ChatCliOptions): Promise<void> {
|
|
|
173
148
|
// Serialize turns: a second line waits for the first to finish so
|
|
174
149
|
// transcript updates and engine state don't race on the same session.
|
|
175
150
|
inFlight = inFlight.then(async () => {
|
|
176
|
-
const
|
|
177
|
-
role: "user",
|
|
178
|
-
content: message,
|
|
179
|
-
});
|
|
180
|
-
session!.transcript.push(userEntry);
|
|
181
|
-
|
|
182
|
-
const result = await engine.processMessage(message, session!);
|
|
183
|
-
const assistantEntry = await appendTranscriptEntry(opts.memoryDir, session!.id, {
|
|
184
|
-
role: "assistant",
|
|
185
|
-
content: result.reply,
|
|
186
|
-
});
|
|
187
|
-
session!.transcript.push(assistantEntry);
|
|
151
|
+
const result = await processTurn(message);
|
|
188
152
|
|
|
189
153
|
console.log(`\nassistant> ${result.reply}\n`);
|
|
190
154
|
if (result.pendingPlan) {
|
package/src/dedup/index.test.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { tmpdir } from "node:os";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import test from "node:test";
|
|
6
6
|
|
|
7
|
-
import { findContradictions, findDuplicates } from "./index.js";
|
|
7
|
+
import { NEGATION_WORDS, findContradictions, findDuplicates } from "./index.js";
|
|
8
8
|
|
|
9
9
|
test("findContradictions detects can versus cannot statements", async () => {
|
|
10
10
|
const memoryDir = await mkdtemp(path.join(tmpdir(), "remnic-dedup-contradiction-"));
|
|
@@ -149,3 +149,67 @@ test("dedup scans reject symlinked category directories outside memoryDir", asyn
|
|
|
149
149
|
await rm(outsideDir, { recursive: true, force: true });
|
|
150
150
|
}
|
|
151
151
|
});
|
|
152
|
+
|
|
153
|
+
test("strip-negation pattern is derived from NEGATION_WORDS", async () => {
|
|
154
|
+
NEGATION_WORDS.add("seldom");
|
|
155
|
+
const memoryDir = await mkdtemp(path.join(tmpdir(), "remnic-dedup-negation-"));
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
const factsDir = path.join(memoryDir, "facts");
|
|
159
|
+
await mkdir(factsDir);
|
|
160
|
+
await writeFile(
|
|
161
|
+
path.join(factsDir, "plain.md"),
|
|
162
|
+
["---", "id: mem-plain", "category: fact", "---", "The user enjoys morning runs."].join("\n"),
|
|
163
|
+
"utf8"
|
|
164
|
+
);
|
|
165
|
+
await writeFile(
|
|
166
|
+
path.join(factsDir, "seldom.md"),
|
|
167
|
+
["---", "id: mem-seldom", "category: fact", "---", "The user seldom enjoys morning runs."].join("\n"),
|
|
168
|
+
"utf8"
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
const result = findContradictions({ memoryDir, categories: ["facts"] });
|
|
172
|
+
|
|
173
|
+
// "high" requires the stripped texts to match exactly, which only happens
|
|
174
|
+
// when the strip pattern honors the word the test added to the set.
|
|
175
|
+
assert.equal(result.contradictions.length, 1);
|
|
176
|
+
assert.equal(result.contradictions[0]?.severity, "high");
|
|
177
|
+
assert.equal(result.contradictions[0]?.reason, "Negated version of similar content");
|
|
178
|
+
} finally {
|
|
179
|
+
NEGATION_WORDS.delete("seldom");
|
|
180
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test("strip-negation cache rebuilds on same-size vocabulary swap", async () => {
|
|
185
|
+
const memoryDir = await mkdtemp(path.join(tmpdir(), "remnic-dedup-negation-swap-"));
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
const factsDir = path.join(memoryDir, "facts");
|
|
189
|
+
await mkdir(factsDir);
|
|
190
|
+
await writeFile(
|
|
191
|
+
path.join(factsDir, "plain.md"),
|
|
192
|
+
["---", "id: mem-swap-plain", "category: fact", "---", "The user enjoys morning runs."].join("\n"),
|
|
193
|
+
"utf8"
|
|
194
|
+
);
|
|
195
|
+
await writeFile(
|
|
196
|
+
path.join(factsDir, "rarely.md"),
|
|
197
|
+
["---", "id: mem-swap-rarely", "category: fact", "---", "The user rarely enjoys morning runs."].join("\n"),
|
|
198
|
+
"utf8"
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
// Warm the pattern cache with the current vocabulary (no "rarely" yet).
|
|
202
|
+
assert.equal(findContradictions({ memoryDir, categories: ["facts"] }).contradictions.length, 0);
|
|
203
|
+
|
|
204
|
+
// Same-size swap: the size-keyed cache would keep serving the stale pattern.
|
|
205
|
+
NEGATION_WORDS.delete("never");
|
|
206
|
+
NEGATION_WORDS.add("rarely");
|
|
207
|
+
const result = findContradictions({ memoryDir, categories: ["facts"] });
|
|
208
|
+
assert.equal(result.contradictions.length, 1);
|
|
209
|
+
assert.equal(result.contradictions[0]?.severity, "high");
|
|
210
|
+
} finally {
|
|
211
|
+
NEGATION_WORDS.delete("rarely");
|
|
212
|
+
NEGATION_WORDS.add("never");
|
|
213
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
214
|
+
}
|
|
215
|
+
});
|
package/src/dedup/index.ts
CHANGED
|
@@ -245,7 +245,7 @@ function tokenizeForSimilarity(text: string): Set<string> {
|
|
|
245
245
|
|
|
246
246
|
// ── Contradiction detection ──────────────────────────────────────────────────
|
|
247
247
|
|
|
248
|
-
const NEGATION_WORDS = new Set([
|
|
248
|
+
export const NEGATION_WORDS = new Set([
|
|
249
249
|
"not",
|
|
250
250
|
"don't",
|
|
251
251
|
"doesn't",
|
|
@@ -317,9 +317,31 @@ function containsNegation(text: string): boolean {
|
|
|
317
317
|
return words.some((w) => NEGATION_WORDS.has(w));
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
+
function escapeRegExp(value: string): string {
|
|
321
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Single vocabulary source: the strip pattern is derived from NEGATION_WORDS,
|
|
325
|
+
// never hand-maintained. Keyed on the alternation content so any vocabulary
|
|
326
|
+
// change (not just a size change) rebuilds the pattern.
|
|
327
|
+
let stripNegationPattern: RegExp | null = null;
|
|
328
|
+
let stripNegationPatternSource: string | null = null;
|
|
329
|
+
|
|
330
|
+
function stripNegationRegex(): RegExp {
|
|
331
|
+
const alternation = [...NEGATION_WORDS]
|
|
332
|
+
.sort((a, b) => b.length - a.length)
|
|
333
|
+
.map(escapeRegExp)
|
|
334
|
+
.join("|");
|
|
335
|
+
if (stripNegationPattern === null || stripNegationPatternSource !== alternation) {
|
|
336
|
+
stripNegationPattern = new RegExp(`\\b(?:${alternation})\\b`, "gi");
|
|
337
|
+
stripNegationPatternSource = alternation;
|
|
338
|
+
}
|
|
339
|
+
return stripNegationPattern;
|
|
340
|
+
}
|
|
341
|
+
|
|
320
342
|
function stripNegation(text: string): string {
|
|
321
343
|
return text
|
|
322
|
-
.replace(
|
|
344
|
+
.replace(stripNegationRegex(), "")
|
|
323
345
|
.replace(/\s+/g, " ")
|
|
324
346
|
.trim();
|
|
325
347
|
}
|
|
@@ -177,8 +177,6 @@ function candidatePriority(candidate: NamespaceMaintenanceCandidate): number {
|
|
|
177
177
|
if (candidate.source === "configured") return 2;
|
|
178
178
|
if (candidate.kind === "team-project") return 3;
|
|
179
179
|
if (candidate.kind === "project") return 4;
|
|
180
|
-
if (candidate.kind === "self") return 5;
|
|
181
|
-
if (candidate.kind === "legacy") return 6;
|
|
182
180
|
if (candidate.kind === "branch") return 8;
|
|
183
181
|
return 7;
|
|
184
182
|
}
|
|
@@ -5,12 +5,12 @@ import { MeetingsBuilder, type MeetingDayData, type MeetingsDayBuildSummary, typ
|
|
|
5
5
|
import { DEFAULT_MEETINGS_CONFIG } from "./config.js";
|
|
6
6
|
import { MeetingRecordStore, type MeetingRecordFileIo } from "./store.js";
|
|
7
7
|
import type {
|
|
8
|
-
MeetingActivitySnapshot,
|
|
9
8
|
MeetingsConfig,
|
|
10
9
|
MeetingAppSpan,
|
|
11
10
|
MeetingAudioWindow,
|
|
12
11
|
MeetingRecord,
|
|
13
12
|
} from "./types.js";
|
|
13
|
+
import type { ActivitySnapshot } from "../activity/types.js";
|
|
14
14
|
import type { FusionConversationInput, FusionSegmentInput } from "../wearables/fusion/types.js";
|
|
15
15
|
import type { MeetingMemoryGenerator, MeetingMemoryOutcome } from "./memory-generator.js";
|
|
16
16
|
|
|
@@ -174,9 +174,25 @@ test("degradation — audio only yields a record with no screen-context section"
|
|
|
174
174
|
});
|
|
175
175
|
|
|
176
176
|
test("full — app+audio with activity fuses transcript and screen context", async () => {
|
|
177
|
-
const activity:
|
|
178
|
-
{
|
|
179
|
-
|
|
177
|
+
const activity: ActivitySnapshot[] = [
|
|
178
|
+
{
|
|
179
|
+
machine: "workstation",
|
|
180
|
+
capturedAtUtc: "2026-03-10T14:05:00.000Z",
|
|
181
|
+
app: "Preview",
|
|
182
|
+
windowTitle: "Q3-roadmap.pdf",
|
|
183
|
+
text: "",
|
|
184
|
+
textSource: "ax",
|
|
185
|
+
contentHash: "snap-1",
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
machine: "workstation",
|
|
189
|
+
capturedAtUtc: "2026-03-10T14:30:00.000Z",
|
|
190
|
+
app: "Zoom",
|
|
191
|
+
windowTitle: "",
|
|
192
|
+
text: "meeting chat",
|
|
193
|
+
textSource: "ax",
|
|
194
|
+
contentHash: "snap-2",
|
|
195
|
+
},
|
|
180
196
|
];
|
|
181
197
|
const { builder: b, store } = builder(
|
|
182
198
|
{
|
package/src/meetings/build.ts
CHANGED
|
@@ -22,10 +22,10 @@ import type {
|
|
|
22
22
|
MeetingMemoryOutcome,
|
|
23
23
|
MeetingsDayFactGenResult,
|
|
24
24
|
} from "./memory-generator.js";
|
|
25
|
+
import type { ActivitySnapshot } from "../activity/types.js";
|
|
25
26
|
import type { FusionConversationInput } from "../wearables/fusion/types.js";
|
|
26
27
|
import type {
|
|
27
28
|
DetectedMeeting,
|
|
28
|
-
MeetingActivitySnapshot,
|
|
29
29
|
MeetingRecord,
|
|
30
30
|
MeetingsConfig,
|
|
31
31
|
MeetingsDetectionInput,
|
|
@@ -38,7 +38,7 @@ export interface MeetingDayData {
|
|
|
38
38
|
/** Fusion conversation inputs across all wearable sources for the day. */
|
|
39
39
|
conversations: FusionConversationInput[];
|
|
40
40
|
/** Screen-activity snapshots for the day. */
|
|
41
|
-
activity?:
|
|
41
|
+
activity?: ActivitySnapshot[];
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
/** Supplies a day's signals. Backed by fixtures in tests; by the activity +
|
|
@@ -127,7 +127,9 @@ test("loadDayData assembles detection + activity for the requested day, keyed to
|
|
|
127
127
|
assert.equal(data.detection.appSpans[0]?.app, "Zoom");
|
|
128
128
|
assert.deepEqual(data.detection.audioWindows, [], "no wearable transcripts → no audio windows");
|
|
129
129
|
assert.equal(data.activity?.length, 2);
|
|
130
|
-
|
|
130
|
+
// Activity is the raw ActivitySnapshot list now — no rename mapper in between.
|
|
131
|
+
assert.equal(data.activity?.[0]?.windowTitle, "Standup");
|
|
132
|
+
assert.equal(data.activity?.[0]?.capturedAtUtc, "2026-03-10T14:00:00.000Z");
|
|
131
133
|
assert.equal(data.conversations.length, 0);
|
|
132
134
|
});
|
|
133
135
|
|
|
@@ -28,7 +28,6 @@ import type { FusionConversationInput, FusionSegmentInput } from "../wearables/f
|
|
|
28
28
|
import type { MeetingDayData, MeetingsDaySource } from "./build.js";
|
|
29
29
|
import { MeetingsInputError } from "./errors.js";
|
|
30
30
|
import type {
|
|
31
|
-
MeetingActivitySnapshot,
|
|
32
31
|
MeetingAppSpan,
|
|
33
32
|
MeetingAudioWindow,
|
|
34
33
|
MeetingsConfig,
|
|
@@ -97,15 +96,6 @@ export function storageWearableDayReader(store: WearableDayTranscriptStore): Mee
|
|
|
97
96
|
};
|
|
98
97
|
}
|
|
99
98
|
|
|
100
|
-
/** Map an activity snapshot to the redaction-safe screen snapshot fusion sees. */
|
|
101
|
-
function toMeetingActivitySnapshot(snapshot: ActivitySnapshot): MeetingActivitySnapshot {
|
|
102
|
-
const out: MeetingActivitySnapshot = { tsUtc: snapshot.capturedAtUtc, app: snapshot.app };
|
|
103
|
-
if (snapshot.windowTitle.length > 0) out.title = snapshot.windowTitle;
|
|
104
|
-
if (snapshot.browserUrl !== undefined && snapshot.browserUrl.length > 0) out.url = snapshot.browserUrl;
|
|
105
|
-
if (snapshot.text.length > 0) out.text = snapshot.text;
|
|
106
|
-
return out;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
99
|
/**
|
|
110
100
|
* Fallback dwell for a lone trailing meeting-app tick on a machine that
|
|
111
101
|
* captured no other snapshot to estimate a cadence from. Five minutes keeps
|
|
@@ -341,12 +331,11 @@ export class ActivityWearablesMeetingsDaySource implements MeetingsDaySource {
|
|
|
341
331
|
const snapshots = this.deps.activity
|
|
342
332
|
? await this.deps.activity.listSnapshotsForDay(null, startUtc, endUtc)
|
|
343
333
|
: [];
|
|
344
|
-
const activity = snapshots.map(toMeetingActivitySnapshot);
|
|
345
334
|
const appSpans = deriveAppSpans(snapshots, this.deps.config.appPatterns);
|
|
346
335
|
const bodies = await this.deps.wearables.readDayBodies(date);
|
|
347
336
|
const tzBySource = new Map(bodies.map((b) => [b.source, b.timezone ?? ""] as const));
|
|
348
337
|
const conversations = shiftFusionInputsToUtc(reconstructFusionInputs(date, bodies), tzBySource);
|
|
349
338
|
const audioWindows = buildAudioWindows(conversations);
|
|
350
|
-
return { detection: { date, appSpans, audioWindows }, conversations, activity };
|
|
339
|
+
return { detection: { date, appSpans, audioWindows }, conversations, activity: snapshots };
|
|
351
340
|
}
|
|
352
341
|
}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
2
4
|
import { test } from "node:test";
|
|
3
5
|
|
|
4
6
|
import { DEFAULT_MEETINGS_CONFIG } from "./config.js";
|
|
5
7
|
import { fuseMeeting } from "./fuse.js";
|
|
6
|
-
import type {
|
|
7
|
-
|
|
8
|
-
MeetingActivitySnapshot,
|
|
9
|
-
MeetingsConfig,
|
|
10
|
-
} from "./types.js";
|
|
8
|
+
import type { ActivitySnapshot } from "../activity/types.js";
|
|
9
|
+
import type { DetectedMeeting, MeetingsConfig } from "./types.js";
|
|
11
10
|
import type { FusionConversationInput, FusionSegmentInput } from "../wearables/fusion/types.js";
|
|
12
11
|
|
|
13
12
|
const DATE = "2026-03-10";
|
|
@@ -51,8 +50,17 @@ function conv(
|
|
|
51
50
|
return { source, conversationId: id, startIso, endIso, segments };
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
function snap(
|
|
55
|
-
|
|
53
|
+
function snap(
|
|
54
|
+
overrides: Partial<ActivitySnapshot> & { capturedAtUtc: string; app: string },
|
|
55
|
+
): ActivitySnapshot {
|
|
56
|
+
return {
|
|
57
|
+
machine: "workstation",
|
|
58
|
+
windowTitle: "",
|
|
59
|
+
text: "",
|
|
60
|
+
textSource: "ax",
|
|
61
|
+
contentHash: "snap-hash",
|
|
62
|
+
...overrides,
|
|
63
|
+
};
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
test("fusion prefers the higher-trust source in overlap regions and records corroboratedBy without duplicating text", () => {
|
|
@@ -97,10 +105,10 @@ test("screen context includes a >=20s dwell and omits a 5s alt-tab; meeting-app
|
|
|
97
105
|
]),
|
|
98
106
|
],
|
|
99
107
|
activity: [
|
|
100
|
-
snap({
|
|
101
|
-
snap({
|
|
102
|
-
snap({
|
|
103
|
-
snap({
|
|
108
|
+
snap({ capturedAtUtc: "2026-03-10T14:05:00.000Z", app: "Preview", windowTitle: "Q3-roadmap.pdf", text: "Q3 roadmap draft" }),
|
|
109
|
+
snap({ capturedAtUtc: "2026-03-10T14:05:25.000Z", app: "Notes", windowTitle: "scratch" }), // Preview dwell 25s → include; Notes starts
|
|
110
|
+
snap({ capturedAtUtc: "2026-03-10T14:05:30.000Z", app: "Preview", windowTitle: "Q3-roadmap.pdf" }), // Notes dwell 5s → exclude
|
|
111
|
+
snap({ capturedAtUtc: "2026-03-10T14:10:00.000Z", app: "Zoom", text: "Jane: agenda item one" }), // meeting-app → excerpt
|
|
104
112
|
],
|
|
105
113
|
},
|
|
106
114
|
config(),
|
|
@@ -122,9 +130,9 @@ test("context excerpts respect maxContextChars", () => {
|
|
|
122
130
|
meeting: meeting(),
|
|
123
131
|
conversations: [],
|
|
124
132
|
activity: [
|
|
125
|
-
snap({
|
|
126
|
-
snap({
|
|
127
|
-
snap({
|
|
133
|
+
snap({ capturedAtUtc: "2026-03-10T14:01:00.000Z", app: "Zoom", text: "aaaa" }),
|
|
134
|
+
snap({ capturedAtUtc: "2026-03-10T14:02:00.000Z", app: "Zoom", text: "bbbb" }),
|
|
135
|
+
snap({ capturedAtUtc: "2026-03-10T14:03:00.000Z", app: "Zoom", text: "cccc" }),
|
|
128
136
|
],
|
|
129
137
|
},
|
|
130
138
|
config({ maxContextChars: 8 }),
|
|
@@ -199,10 +207,51 @@ test("a lone trailing other-app snapshot is not inflated to the meeting end", ()
|
|
|
199
207
|
],
|
|
200
208
|
// A single Notes snapshot 1 min before the window end. With no later
|
|
201
209
|
// snapshot, the trailing run must NOT count dwell up to the meeting end.
|
|
202
|
-
activity: [snap({
|
|
210
|
+
activity: [snap({ capturedAtUtc: "2026-03-10T14:29:00.000Z", app: "Notes", windowTitle: "scratch" })],
|
|
203
211
|
},
|
|
204
212
|
config(),
|
|
205
213
|
);
|
|
206
214
|
assert.equal(fused.snapshotCount, 1);
|
|
207
215
|
assert.deepEqual(fused.screenContext, [], "a lone trailing snapshot has zero observed dwell");
|
|
208
216
|
});
|
|
217
|
+
|
|
218
|
+
test("fusion reads ActivitySnapshot fields — capturedAtUtc, browserUrl runs, windowTitle fallback", () => {
|
|
219
|
+
const fused = fuseMeeting(
|
|
220
|
+
{
|
|
221
|
+
meeting: meeting(),
|
|
222
|
+
conversations: [],
|
|
223
|
+
activity: [
|
|
224
|
+
snap({ capturedAtUtc: "2026-03-10T14:05:00.000Z", app: "Chrome", browserUrl: "https://github.com/org/repo/pull/1" }),
|
|
225
|
+
snap({ capturedAtUtc: "2026-03-10T14:06:00.000Z", app: "Chrome", browserUrl: "https://github.com/org/repo/pull/1" }),
|
|
226
|
+
// Different URL on the same app → a separate dwell run.
|
|
227
|
+
snap({ capturedAtUtc: "2026-03-10T14:06:30.000Z", app: "Chrome", browserUrl: "https://example.com/doc" }),
|
|
228
|
+
snap({ capturedAtUtc: "2026-03-10T14:07:00.000Z", app: "Chrome", browserUrl: "https://example.com/doc" }),
|
|
229
|
+
// Empty browserUrl falls back to the window title for key and label.
|
|
230
|
+
snap({ capturedAtUtc: "2026-03-10T14:07:30.000Z", app: "Chrome", windowTitle: "Spec v2" }),
|
|
231
|
+
snap({ capturedAtUtc: "2026-03-10T14:08:00.000Z", app: "Chrome", windowTitle: "Spec v2" }),
|
|
232
|
+
],
|
|
233
|
+
},
|
|
234
|
+
config(),
|
|
235
|
+
);
|
|
236
|
+
assert.equal(fused.snapshotCount, 6);
|
|
237
|
+
assert.deepEqual(
|
|
238
|
+
fused.screenContext.map((e) => e.label),
|
|
239
|
+
[
|
|
240
|
+
"Chrome: github.com/org/repo/pull/1",
|
|
241
|
+
"Chrome: example.com/doc",
|
|
242
|
+
"Chrome: Spec v2",
|
|
243
|
+
],
|
|
244
|
+
);
|
|
245
|
+
// Run dwell ends at the next different-key snapshot (90s, 60s) or, for the
|
|
246
|
+
// trailing run, at its own last snapshot (30s).
|
|
247
|
+
assert.deepEqual(fused.screenContext.map((e) => e.dwellSeconds), [90, 60, 30]);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
test("MeetingActivitySnapshot and its rename mapper are gone", () => {
|
|
251
|
+
const here = import.meta.dirname;
|
|
252
|
+
for (const file of ["types.ts", "fuse.ts", "day-source.ts", "build.ts"]) {
|
|
253
|
+
const src = readFileSync(join(here, file), "utf8");
|
|
254
|
+
assert.ok(!src.includes("MeetingActivitySnapshot"), `${file} must not reference MeetingActivitySnapshot`);
|
|
255
|
+
assert.ok(!src.includes("toMeetingActivitySnapshot"), `${file} must not reference toMeetingActivitySnapshot`);
|
|
256
|
+
}
|
|
257
|
+
});
|