@remnic/core 9.15.0 → 9.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-admin-ops-surface.d.ts +10 -7
- package/dist/access-admin-ops-surface.js +21 -21
- package/dist/access-boundary.d.ts +10 -7
- package/dist/access-boundary.js +21 -22
- package/dist/access-cli.js +73 -75
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +8 -7
- package/dist/access-http.js +27 -28
- package/dist/access-identity-continuity-surface.d.ts +6 -6
- package/dist/access-identity-continuity-surface.js +21 -21
- package/dist/access-lcm-surface.d.ts +10 -7
- package/dist/access-lcm-surface.js +21 -21
- package/dist/access-mcp.d.ts +10 -7
- package/dist/access-mcp.js +26 -27
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/access-namespace-preflight-B9e5GnyZ.d.ts +146 -0
- package/dist/access-namespace-preflight.d.ts +8 -0
- package/dist/access-namespace-preflight.js +158 -0
- package/dist/access-observe-write-surface.d.ts +10 -7
- package/dist/access-observe-write-surface.js +21 -21
- package/dist/access-operations-batch.js +23 -24
- package/dist/access-operations.d.ts +11 -8
- package/dist/access-operations.js +25 -26
- package/dist/access-recall-concurrency.d.ts +10 -7
- package/dist/access-recall-concurrency.js +21 -21
- package/dist/access-recall-response.d.ts +10 -7
- package/dist/access-recall-response.js +21 -21
- package/dist/access-recall-surface.d.ts +10 -7
- package/dist/access-recall-surface.js +21 -21
- package/dist/access-schema.js +3 -3
- package/dist/{access-service-DbZ1G3zV.d.ts → access-service-DgmJd_A-.d.ts} +10 -118
- package/dist/access-service.d.ts +10 -7
- package/dist/access-service.js +21 -21
- package/dist/access-surface-catalog.d.ts +10 -7
- 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/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +6 -6
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +6 -6
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +2 -2
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{capsule-crypto-GWVG7LGC.js → capsule-crypto-7FJQINUR.js} +2 -2
- package/dist/capsule-crypto-7FJQINUR.js.map +1 -0
- package/dist/{catalog-BWqHb5HT.d.ts → catalog-g_dfT6oL.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 +7 -7
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-OWHERGF2.js → chunk-2NLLXCJG.js} +2 -2
- package/dist/{chunk-YQQYS2K4.js → chunk-42DJZZUB.js} +2 -2
- package/dist/{chunk-YUQOAKPX.js → chunk-47WFEKT7.js} +5 -5
- package/dist/{chunk-YO3ZB3PJ.js → chunk-4E5H4FPC.js} +30 -15
- package/dist/chunk-4E5H4FPC.js.map +1 -0
- package/dist/{chunk-226RNKRU.js → chunk-5HFIHWOF.js} +37 -37
- package/dist/{chunk-A56B2AJR.js → chunk-5MDE5MIC.js} +3 -3
- package/dist/{chunk-W2OST2HH.js → chunk-6EJL2O3G.js} +2 -2
- package/dist/{chunk-ALSGMEJR.js → chunk-7CPOZH6Y.js} +5 -5
- package/dist/{chunk-MMGGVZ4Q.js → chunk-7VZWZVYG.js} +40 -18
- package/dist/{chunk-MMGGVZ4Q.js.map → chunk-7VZWZVYG.js.map} +1 -1
- package/dist/{chunk-WSHJAY5M.js → chunk-B57BIBXI.js} +2 -2
- package/dist/{chunk-KN6UGAQB.js → chunk-B6NCHYAK.js} +7 -2
- package/dist/chunk-B6NCHYAK.js.map +1 -0
- package/dist/{chunk-AS6UOOXF.js → chunk-BNH2VVWP.js} +2 -2
- package/dist/{chunk-6KIQT7RG.js → chunk-BZ52BJ6C.js} +2 -2
- package/dist/chunk-BZ52BJ6C.js.map +1 -0
- package/dist/{chunk-5RZHHANR.js → chunk-CXFVZ3PK.js} +54 -54
- package/dist/{chunk-SK7AMF2J.js → chunk-DETNBTZS.js} +3 -3
- package/dist/{chunk-TY6NBWV4.js → chunk-EEUZQQRJ.js} +2 -2
- package/dist/{chunk-YVKF3HEW.js → chunk-FJ5IQ3SI.js} +1 -1
- package/dist/chunk-FJ5IQ3SI.js.map +1 -0
- package/dist/{chunk-HLG7VAZP.js → chunk-GQOKO77V.js} +2 -2
- package/dist/{chunk-CAZ2SHEP.js → chunk-H4MDUPER.js} +2 -2
- package/dist/{chunk-TC5HBIIT.js → chunk-HBYQAOED.js} +2 -2
- package/dist/{chunk-YSDVEPV2.js → chunk-IRX5UCGN.js} +10 -10
- package/dist/{chunk-3HYWNJDA.js → chunk-JN4N2TMQ.js} +423 -45
- package/dist/chunk-JN4N2TMQ.js.map +1 -0
- package/dist/{chunk-IQFS4AU7.js → chunk-JTW4TGPV.js} +2 -2
- package/dist/{chunk-I4NJ2CDY.js → chunk-KLXG4BBO.js} +4 -6
- package/dist/{chunk-I4NJ2CDY.js.map → chunk-KLXG4BBO.js.map} +1 -1
- package/dist/{chunk-5W7CTZ2E.js → chunk-KQAFEZQX.js} +4 -4
- package/dist/{chunk-PYHOAXTI.js → chunk-LRGSLV7M.js} +4 -4
- package/dist/{chunk-Y6XODVJ4.js → chunk-NAY25BGS.js} +9 -9
- package/dist/{chunk-7HZMTXXB.js → chunk-O7ACJAHR.js} +18 -11
- package/dist/{chunk-7HZMTXXB.js.map → chunk-O7ACJAHR.js.map} +1 -1
- package/dist/{chunk-QJAQNXWI.js → chunk-ONHRRJZM.js} +6 -6
- package/dist/{chunk-O4K3DWK2.js → chunk-OOGGUXAG.js} +2 -2
- package/dist/{chunk-CQ6WP3PA.js → chunk-P53HGVJS.js} +5 -5
- package/dist/{chunk-U3ZAVRP3.js → chunk-PXJEL55X.js} +2 -2
- package/dist/{chunk-DF552QUN.js → chunk-QCLQ4BGA.js} +5 -5
- package/dist/{chunk-IAHNKI2E.js → chunk-QDNE35FU.js} +2 -2
- package/dist/{chunk-XMAD32BW.js → chunk-RRS5CDB6.js} +2 -2
- package/dist/{chunk-3QAH2S33.js → chunk-SYCVU556.js} +3 -3
- package/dist/{chunk-QZGN4773.js → chunk-T4EAQPQQ.js} +3 -3
- package/dist/{chunk-7G7DVA2C.js → chunk-T4OTDMX4.js} +2 -2
- package/dist/{chunk-XRNU7OEQ.js → chunk-U6QWUFSM.js} +3 -3
- package/dist/{chunk-UDIJMITR.js → chunk-UJIBXOJA.js} +23 -23
- package/dist/chunk-UJIBXOJA.js.map +1 -0
- package/dist/{chunk-CQMEM5CC.js → chunk-WIKOHCQZ.js} +2 -2
- package/dist/{chunk-UVYI6VIX.js → chunk-X7Y7WX73.js} +1 -1
- package/dist/{chunk-3332THSR.js → chunk-XJT6LNLY.js} +4 -4
- package/dist/{chunk-AVPXXV6J.js → chunk-XKGPIWGI.js} +4 -4
- package/dist/{chunk-EZ25VE3G.js → chunk-YNDLCWXS.js} +4 -4
- package/dist/{chunk-46OH3OVK.js → chunk-YXTSUIXC.js} +5 -1
- package/dist/chunk-YXTSUIXC.js.map +1 -0
- package/dist/{cli-5tNLVTvJ.d.ts → cli-BXCd2cgK.d.ts} +5 -5
- package/dist/cli.d.ts +12 -9
- package/dist/cli.js +51 -52
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +6 -6
- 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 +6 -6
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +6 -6
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +2 -2
- package/dist/contradiction/index.js +4 -4
- 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/dashboard-runtime.js +2 -2
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.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-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +6 -6
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +6 -6
- 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.d.ts +3 -2
- package/dist/extraction.js +6 -4
- 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-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +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 +16 -15
- package/dist/index.js +84 -86
- 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/index.js +3 -3
- 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 +2 -1
- package/dist/local-llm.js +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 +6 -6
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +6 -6
- package/dist/maintenance/rebuild-memory-projection.js +7 -7
- package/dist/mcp-memory-inspector-app.d.ts +10 -7
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-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 +5 -5
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +6 -6
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync-impression-drain.d.ts +1 -1
- package/dist/offline-sync-impression-drain.js +4 -4
- package/dist/operator-toolkit.d.ts +2 -2
- package/dist/operator-toolkit.js +18 -18
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +3 -3
- package/dist/orchestration/maintenance.js +10 -10
- package/dist/{orchestrator-CQJ8U7En.d.ts → orchestrator-BHfWtvEJ.d.ts} +5 -5
- package/dist/orchestrator.d.ts +6 -6
- package/dist/orchestrator.js +74 -75
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-Cn-kvYeV.d.ts → pipeline-CBYcnmDC.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/{qmd-oh9VXz1d.d.ts → qmd-BIq-jrV4.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-explain-renderer.js +3 -3
- package/dist/recall-memory-map.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-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-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/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/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/{scope-profiles-EpJG7yKP.d.ts → scope-profiles-DDno-uvy.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 +4 -4
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +6 -6
- 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-DILZEQq3.d.ts → semantic-consolidation-7RIJFDwY.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +7 -7
- package/dist/semantic-rule-promotion.js +6 -6
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +6 -6
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/{storage-NIyKYD8g.d.ts → storage-DkphZiOJ.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +5 -5
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +2 -2
- package/dist/summary-snapshot.d.ts +1 -1
- 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/backup.js +2 -2
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +2 -2
- package/dist/transfer/import-sqlite.js +2 -2
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-D_fG2ix8.d.ts → types-2q_MRFcM.d.ts} +6 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +6 -6
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/access-http.test.ts +91 -0
- package/src/access-http.ts +13 -14
- package/src/access-namespace-preflight.test.ts +111 -0
- package/src/access-namespace-preflight.ts +111 -0
- package/src/access-operations-batch.ts +25 -2
- package/src/access-service-observe-scope.test.ts +81 -0
- package/src/access-service.ts +64 -78
- package/src/config.test.ts +7 -0
- package/src/config.ts +6 -0
- package/src/extraction-thinking.test.ts +44 -0
- package/src/extraction.ts +12 -0
- package/src/local-llm-thinking.test.ts +13 -1
- package/src/local-llm.ts +2 -1
- package/src/orchestration/qmd-result-resolver.test.ts +103 -0
- package/src/orchestration/qmd-result-resolver.ts +11 -0
- package/src/scopes/scope-plan.ts +66 -0
- package/src/types.ts +6 -0
- package/dist/chunk-3HYWNJDA.js.map +0 -1
- package/dist/chunk-46OH3OVK.js.map +0 -1
- package/dist/chunk-6KIQT7RG.js.map +0 -1
- package/dist/chunk-KF5EUVKQ.js +0 -289
- package/dist/chunk-KF5EUVKQ.js.map +0 -1
- package/dist/chunk-KN6UGAQB.js.map +0 -1
- package/dist/chunk-UDIJMITR.js.map +0 -1
- package/dist/chunk-YO3ZB3PJ.js.map +0 -1
- package/dist/chunk-YVKF3HEW.js.map +0 -1
- /package/dist/{capsule-crypto-GWVG7LGC.js.map → access-namespace-preflight.js.map} +0 -0
- /package/dist/{chunk-OWHERGF2.js.map → chunk-2NLLXCJG.js.map} +0 -0
- /package/dist/{chunk-YQQYS2K4.js.map → chunk-42DJZZUB.js.map} +0 -0
- /package/dist/{chunk-YUQOAKPX.js.map → chunk-47WFEKT7.js.map} +0 -0
- /package/dist/{chunk-226RNKRU.js.map → chunk-5HFIHWOF.js.map} +0 -0
- /package/dist/{chunk-A56B2AJR.js.map → chunk-5MDE5MIC.js.map} +0 -0
- /package/dist/{chunk-W2OST2HH.js.map → chunk-6EJL2O3G.js.map} +0 -0
- /package/dist/{chunk-ALSGMEJR.js.map → chunk-7CPOZH6Y.js.map} +0 -0
- /package/dist/{chunk-WSHJAY5M.js.map → chunk-B57BIBXI.js.map} +0 -0
- /package/dist/{chunk-AS6UOOXF.js.map → chunk-BNH2VVWP.js.map} +0 -0
- /package/dist/{chunk-5RZHHANR.js.map → chunk-CXFVZ3PK.js.map} +0 -0
- /package/dist/{chunk-SK7AMF2J.js.map → chunk-DETNBTZS.js.map} +0 -0
- /package/dist/{chunk-TY6NBWV4.js.map → chunk-EEUZQQRJ.js.map} +0 -0
- /package/dist/{chunk-HLG7VAZP.js.map → chunk-GQOKO77V.js.map} +0 -0
- /package/dist/{chunk-CAZ2SHEP.js.map → chunk-H4MDUPER.js.map} +0 -0
- /package/dist/{chunk-TC5HBIIT.js.map → chunk-HBYQAOED.js.map} +0 -0
- /package/dist/{chunk-YSDVEPV2.js.map → chunk-IRX5UCGN.js.map} +0 -0
- /package/dist/{chunk-IQFS4AU7.js.map → chunk-JTW4TGPV.js.map} +0 -0
- /package/dist/{chunk-5W7CTZ2E.js.map → chunk-KQAFEZQX.js.map} +0 -0
- /package/dist/{chunk-PYHOAXTI.js.map → chunk-LRGSLV7M.js.map} +0 -0
- /package/dist/{chunk-Y6XODVJ4.js.map → chunk-NAY25BGS.js.map} +0 -0
- /package/dist/{chunk-QJAQNXWI.js.map → chunk-ONHRRJZM.js.map} +0 -0
- /package/dist/{chunk-O4K3DWK2.js.map → chunk-OOGGUXAG.js.map} +0 -0
- /package/dist/{chunk-CQ6WP3PA.js.map → chunk-P53HGVJS.js.map} +0 -0
- /package/dist/{chunk-U3ZAVRP3.js.map → chunk-PXJEL55X.js.map} +0 -0
- /package/dist/{chunk-DF552QUN.js.map → chunk-QCLQ4BGA.js.map} +0 -0
- /package/dist/{chunk-IAHNKI2E.js.map → chunk-QDNE35FU.js.map} +0 -0
- /package/dist/{chunk-XMAD32BW.js.map → chunk-RRS5CDB6.js.map} +0 -0
- /package/dist/{chunk-3QAH2S33.js.map → chunk-SYCVU556.js.map} +0 -0
- /package/dist/{chunk-QZGN4773.js.map → chunk-T4EAQPQQ.js.map} +0 -0
- /package/dist/{chunk-7G7DVA2C.js.map → chunk-T4OTDMX4.js.map} +0 -0
- /package/dist/{chunk-XRNU7OEQ.js.map → chunk-U6QWUFSM.js.map} +0 -0
- /package/dist/{chunk-CQMEM5CC.js.map → chunk-WIKOHCQZ.js.map} +0 -0
- /package/dist/{chunk-UVYI6VIX.js.map → chunk-X7Y7WX73.js.map} +0 -0
- /package/dist/{chunk-3332THSR.js.map → chunk-XJT6LNLY.js.map} +0 -0
- /package/dist/{chunk-AVPXXV6J.js.map → chunk-XKGPIWGI.js.map} +0 -0
- /package/dist/{chunk-EZ25VE3G.js.map → chunk-YNDLCWXS.js.map} +0 -0
package/src/access-service.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { readdirSync, unlinkSync } from "node:fs";
|
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
7
7
|
import { ZodError } from "zod";
|
|
8
8
|
import { AccessIdempotencyStore, hashAccessIdempotencyPayload } from "./access-idempotency.js";
|
|
9
|
+
import { enforceNamespaceAllowList, tokenCapabilityStore } from "./access-token-capabilities.js";
|
|
9
10
|
import {
|
|
10
11
|
recordCitationUsage as recordCitationUsageForAccess,
|
|
11
12
|
type CitationUsageRequest,
|
|
@@ -130,8 +131,11 @@ import {
|
|
|
130
131
|
import {
|
|
131
132
|
type ScopePlan,
|
|
132
133
|
resolveScopePlan,
|
|
134
|
+
resolveScopedWritableNamespaceValue,
|
|
133
135
|
resolveWritableNamespaceValue,
|
|
136
|
+
type WritableNamespaceResult,
|
|
134
137
|
} from "./scopes/scope-plan.js";
|
|
138
|
+
import { resolveNamespaceWritablePreflight, type EngramAccessNamespaceWritableRequest } from "./access-namespace-preflight.js";
|
|
135
139
|
import { namespaceIdentityFromToken } from "./namespaces/identity.js";
|
|
136
140
|
import { namespaceCollectionName } from "./namespaces/search.js";
|
|
137
141
|
import { SecureStoreLockedError } from "./secure-store/index.js";
|
|
@@ -277,52 +281,6 @@ import { EngramAccessInputError, NamespaceNotWritableError } from "./access-erro
|
|
|
277
281
|
// working after these classes moved to ./access-errors (issue #1888).
|
|
278
282
|
export { EngramAccessInputError, NamespaceNotWritableError } from "./access-errors.js";
|
|
279
283
|
|
|
280
|
-
function qmdCollectionPathParts(resultPath: string): {
|
|
281
|
-
collection: string;
|
|
282
|
-
relativePath: string;
|
|
283
|
-
} | null {
|
|
284
|
-
if (!resultPath || nodePath.isAbsolute(resultPath)) return null;
|
|
285
|
-
const normalized = resultPath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
286
|
-
const slashIndex = normalized.indexOf("/");
|
|
287
|
-
if (slashIndex <= 0 || slashIndex >= normalized.length - 1) return null;
|
|
288
|
-
const collection = normalized.slice(0, slashIndex);
|
|
289
|
-
if (/^\d{4}-\d{2}-\d{2}$/.test(collection)) return null;
|
|
290
|
-
return {
|
|
291
|
-
collection,
|
|
292
|
-
relativePath: normalized.slice(slashIndex + 1),
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
function qmdResultPathCandidates(
|
|
297
|
-
storageDir: string,
|
|
298
|
-
resultPath: string,
|
|
299
|
-
): string[] {
|
|
300
|
-
const candidates = new Set<string>();
|
|
301
|
-
const storageRoot = nodePath.resolve(storageDir);
|
|
302
|
-
const addCandidate = (candidate: string) => {
|
|
303
|
-
const resolved = nodePath.resolve(candidate);
|
|
304
|
-
if (isPathInsideStorageRoot(storageRoot, resolved)) {
|
|
305
|
-
candidates.add(resolved);
|
|
306
|
-
}
|
|
307
|
-
};
|
|
308
|
-
const addRelativeCandidates = (relativePath: string) => {
|
|
309
|
-
const normalized = relativePath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
310
|
-
if (!normalized) return;
|
|
311
|
-
addCandidate(nodePath.join(storageRoot, normalized));
|
|
312
|
-
if (/^\d{4}-\d{2}-\d{2}\//.test(normalized)) {
|
|
313
|
-
addCandidate(nodePath.join(storageRoot, "facts", normalized));
|
|
314
|
-
}
|
|
315
|
-
};
|
|
316
|
-
|
|
317
|
-
if (nodePath.isAbsolute(resultPath)) {
|
|
318
|
-
addCandidate(resultPath);
|
|
319
|
-
} else {
|
|
320
|
-
addRelativeCandidates(resultPath);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
return [...candidates];
|
|
324
|
-
}
|
|
325
|
-
|
|
326
284
|
export type AccessProfilingReportRequest = {
|
|
327
285
|
format?: string;
|
|
328
286
|
limit?: number;
|
|
@@ -958,7 +916,7 @@ export interface CodingScopedWriteInput {
|
|
|
958
916
|
cwd?: string;
|
|
959
917
|
projectTag?: string;
|
|
960
918
|
}
|
|
961
|
-
|
|
919
|
+
export type { EngramAccessNamespaceWritableRequest } from "./access-namespace-preflight.js";
|
|
962
920
|
/**
|
|
963
921
|
* Internal, single-resolution plan describing the effective memory scope for a
|
|
964
922
|
* write-producing access request (#1495, seed for epic #1494). One plan is
|
|
@@ -1588,6 +1546,14 @@ export class EngramAccessService {
|
|
|
1588
1546
|
return { principal, codingContext, overlay, profilePlan };
|
|
1589
1547
|
}
|
|
1590
1548
|
|
|
1549
|
+
private assertTokenCanWriteNamespace(namespace: string): void {
|
|
1550
|
+
enforceNamespaceAllowList(
|
|
1551
|
+
tokenCapabilityStore.getStore(),
|
|
1552
|
+
namespace,
|
|
1553
|
+
this.orchestrator.config.defaultNamespace,
|
|
1554
|
+
);
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1591
1557
|
/**
|
|
1592
1558
|
* Resolve the write namespace for explicit-write tools (memory_store /
|
|
1593
1559
|
* suggestion_submit), project-scoping the write the same way recall does so a
|
|
@@ -1603,49 +1569,56 @@ export class EngramAccessService {
|
|
|
1603
1569
|
sessionKey?: string;
|
|
1604
1570
|
authenticatedPrincipal?: string;
|
|
1605
1571
|
},
|
|
1572
|
+
enforceToken: boolean = true,
|
|
1606
1573
|
): Promise<string> {
|
|
1607
|
-
const
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
request.namespace,
|
|
1574
|
+
const requested = request.namespace?.trim();
|
|
1575
|
+
if (requested) {
|
|
1576
|
+
const namespace = this.writableNamespaceFor(
|
|
1577
|
+
requested,
|
|
1612
1578
|
request.sessionKey,
|
|
1613
1579
|
request.authenticatedPrincipal,
|
|
1614
1580
|
);
|
|
1581
|
+
if (enforceToken) this.assertTokenCanWriteNamespace(namespace);
|
|
1582
|
+
return namespace;
|
|
1615
1583
|
}
|
|
1584
|
+
|
|
1616
1585
|
const { principal, overlay, profilePlan } = await this.resolveCodingScopeInputs(request);
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1586
|
+
const result = resolveScopedWritableNamespaceValue({
|
|
1587
|
+
sessionKey: request.sessionKey,
|
|
1588
|
+
authenticatedPrincipal: request.authenticatedPrincipal,
|
|
1589
|
+
principal,
|
|
1590
|
+
codingOverlay: overlay,
|
|
1591
|
+
scopeProfile: profilePlan,
|
|
1592
|
+
config: this.orchestrator.config,
|
|
1593
|
+
});
|
|
1594
|
+
if (result.ok) {
|
|
1595
|
+
if (enforceToken) this.assertTokenCanWriteNamespace(result.namespace);
|
|
1596
|
+
return result.namespace;
|
|
1627
1597
|
}
|
|
1628
|
-
if (
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
request.sessionKey,
|
|
1634
|
-
request.authenticatedPrincipal,
|
|
1598
|
+
if (profilePlan && result.namespace === profilePlan.writeNamespace) {
|
|
1599
|
+
throw new NamespaceNotWritableError(
|
|
1600
|
+
result.namespace,
|
|
1601
|
+
principal,
|
|
1602
|
+
`scope profile ${profilePlan.profileId} has no writable layer for principal ${principal ?? "anonymous"}`,
|
|
1635
1603
|
);
|
|
1636
1604
|
}
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
// no separate write policy.
|
|
1641
|
-
const base = defaultNamespaceForPrincipal(principal, this.orchestrator.config);
|
|
1642
|
-
if (!canWriteNamespace(principal, base, this.orchestrator.config)) {
|
|
1643
|
-
throw new NamespaceNotWritableError(base, principal);
|
|
1605
|
+
|
|
1606
|
+
if (result.reason === "unsupported") {
|
|
1607
|
+
throw new EngramAccessInputError(`unsupported namespace: ${result.namespace}`);
|
|
1644
1608
|
}
|
|
1645
|
-
|
|
1609
|
+
throw new NamespaceNotWritableError(result.namespace, principal);
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
async namespaceWritablePreflight(
|
|
1613
|
+
request: EngramAccessNamespaceWritableRequest,
|
|
1614
|
+
): Promise<WritableNamespaceResult> {
|
|
1615
|
+
return resolveNamespaceWritablePreflight(
|
|
1616
|
+
request,
|
|
1617
|
+
(preflightRequest) => this.resolveCodingScopedWriteNamespace(preflightRequest, false),
|
|
1618
|
+
);
|
|
1646
1619
|
}
|
|
1647
1620
|
|
|
1648
|
-
/**
|
|
1621
|
+
/**
|
|
1649
1622
|
* `list`/`get` use this so a record written by a project-scoped session is
|
|
1650
1623
|
* listable/fetchable by the SAME session without manually supplying the
|
|
1651
1624
|
* overlaid namespace (review P2). Derivation is IDENTICAL to the write path
|
|
@@ -1748,6 +1721,7 @@ export class EngramAccessService {
|
|
|
1748
1721
|
request.sessionKey,
|
|
1749
1722
|
request.authenticatedPrincipal,
|
|
1750
1723
|
);
|
|
1724
|
+
this.assertTokenCanWriteNamespace(writeNamespace);
|
|
1751
1725
|
return {
|
|
1752
1726
|
principal,
|
|
1753
1727
|
explicitNamespace: request.namespace!.trim(),
|
|
@@ -1825,6 +1799,15 @@ export class EngramAccessService {
|
|
|
1825
1799
|
this.orchestrator.setCodingContextForSession(request.sessionKey!, null);
|
|
1826
1800
|
}
|
|
1827
1801
|
};
|
|
1802
|
+
const assertWriteNamespaceAllowed = (namespace: string): void => {
|
|
1803
|
+
try {
|
|
1804
|
+
this.assertTokenCanWriteNamespace(namespace);
|
|
1805
|
+
} catch (error) {
|
|
1806
|
+
clearSeededContext();
|
|
1807
|
+
throw error;
|
|
1808
|
+
}
|
|
1809
|
+
};
|
|
1810
|
+
|
|
1828
1811
|
|
|
1829
1812
|
const overlaidBase = this.orchestrator.applyCodingNamespaceOverlay(
|
|
1830
1813
|
request.sessionKey,
|
|
@@ -1876,6 +1859,7 @@ export class EngramAccessService {
|
|
|
1876
1859
|
readNamespaces.includes(layer.namespace),
|
|
1877
1860
|
),
|
|
1878
1861
|
);
|
|
1862
|
+
assertWriteNamespaceAllowed(profilePlan.writeNamespace);
|
|
1879
1863
|
return {
|
|
1880
1864
|
principal,
|
|
1881
1865
|
baseNamespace: profilePlan.baseNamespace,
|
|
@@ -1928,6 +1912,7 @@ export class EngramAccessService {
|
|
|
1928
1912
|
clearSeededContext();
|
|
1929
1913
|
throw new NamespaceNotWritableError(baseNamespace, principal);
|
|
1930
1914
|
}
|
|
1915
|
+
assertWriteNamespaceAllowed(writeNamespace);
|
|
1931
1916
|
return {
|
|
1932
1917
|
principal,
|
|
1933
1918
|
// scopeDebug.baseNamespace must report the principal SELF base
|
|
@@ -1965,6 +1950,7 @@ export class EngramAccessService {
|
|
|
1965
1950
|
const ns = combineNamespaces(baseNamespace, fallback);
|
|
1966
1951
|
if (!readNamespaces.includes(ns)) readNamespaces.push(ns);
|
|
1967
1952
|
}
|
|
1953
|
+
assertWriteNamespaceAllowed(writeNamespace);
|
|
1968
1954
|
return {
|
|
1969
1955
|
principal,
|
|
1970
1956
|
baseNamespace,
|
package/src/config.test.ts
CHANGED
|
@@ -1179,6 +1179,13 @@ test('parseConfig localLlmDisableThinking "0"/"no"/"off" all coerce to false', (
|
|
|
1179
1179
|
assert.equal(parseConfig({ localLlmDisableThinking: "off" }).localLlmDisableThinking, false);
|
|
1180
1180
|
});
|
|
1181
1181
|
|
|
1182
|
+
test("parseConfig localLlmThinkingThresholdChars defaults conservatively and accepts zero to disable (#1997)", () => {
|
|
1183
|
+
assert.equal(parseConfig({}).localLlmThinkingThresholdChars, 3_000);
|
|
1184
|
+
assert.equal(parseConfig({ localLlmThinkingThresholdChars: 0 }).localLlmThinkingThresholdChars, 0);
|
|
1185
|
+
assert.equal(parseConfig({ localLlmThinkingThresholdChars: "3000" }).localLlmThinkingThresholdChars, 3_000);
|
|
1186
|
+
assert.equal(parseConfig({ localLlmThinkingThresholdChars: 3_000 }).localLlmThinkingThresholdChars, 3_000);
|
|
1187
|
+
});
|
|
1188
|
+
|
|
1182
1189
|
test("parseConfig procedural numeric fields coerce from CLI-style strings (issue #519)", () => {
|
|
1183
1190
|
const result = parseConfig({
|
|
1184
1191
|
openaiApiKey: "sk-test",
|
package/src/config.ts
CHANGED
|
@@ -2856,6 +2856,12 @@ export function parseConfig(
|
|
|
2856
2856
|
["", "none", "low", "medium", "high", "max"].includes(cfg.localLlmReasoningEffort)
|
|
2857
2857
|
? cfg.localLlmReasoningEffort
|
|
2858
2858
|
: "none",
|
|
2859
|
+
localLlmThinkingThresholdChars: (() => {
|
|
2860
|
+
const threshold = coerceNumber(cfg.localLlmThinkingThresholdChars);
|
|
2861
|
+
return threshold !== undefined && Number.isInteger(threshold) && threshold >= 0
|
|
2862
|
+
? threshold
|
|
2863
|
+
: 3_000;
|
|
2864
|
+
})(),
|
|
2859
2865
|
// Extraction retry/backoff + circuit breaker (extraction hot-loop hardening)
|
|
2860
2866
|
extractionRetryEnabled: coerceBooleanLike(cfg.extractionRetryEnabled) ?? true,
|
|
2861
2867
|
extractionRetryScheduleMs:
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { shouldEnableLocalExtractionThinking } from "./extraction.js";
|
|
5
|
+
import type { PluginConfig } from "./types.js";
|
|
6
|
+
|
|
7
|
+
function config(overrides: Partial<PluginConfig> = {}): PluginConfig {
|
|
8
|
+
return {
|
|
9
|
+
localLlmDisableThinking: true,
|
|
10
|
+
localLlmThinkingThresholdChars: 3_000,
|
|
11
|
+
...overrides,
|
|
12
|
+
} as PluginConfig;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
test("short local extraction enables thinking when configured (#1997)", () => {
|
|
16
|
+
assert.equal(shouldEnableLocalExtractionThinking(config(), 2_999), true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("length-aware local thinking stays disabled at the threshold and above (#1997)", () => {
|
|
20
|
+
assert.equal(shouldEnableLocalExtractionThinking(config(), 3_000), false);
|
|
21
|
+
assert.equal(shouldEnableLocalExtractionThinking(config(), 3_001), false);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("disabled threshold and explicit global opt-out preserve existing behavior (#1997)", () => {
|
|
25
|
+
assert.equal(shouldEnableLocalExtractionThinking(config({ localLlmThinkingThresholdChars: 0 }), 1), false);
|
|
26
|
+
assert.equal(shouldEnableLocalExtractionThinking(config({ localLlmDisableThinking: false }), 1), false);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("four-transcript selection matrix keeps short sparse cases in thinking mode (#1997)", () => {
|
|
30
|
+
const cases = [
|
|
31
|
+
{ name: "sparse commitment", transcript: "A".repeat(750), thinking: true },
|
|
32
|
+
{ name: "sparse correction", transcript: "B".repeat(1_600), thinking: true },
|
|
33
|
+
{ name: "dense technical discussion", transcript: "C".repeat(3_000), thinking: false },
|
|
34
|
+
{ name: "dense multi-turn discussion", transcript: "D".repeat(6_000), thinking: false },
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
for (const scenario of cases) {
|
|
38
|
+
assert.equal(
|
|
39
|
+
shouldEnableLocalExtractionThinking(config(), scenario.transcript.length),
|
|
40
|
+
scenario.thinking,
|
|
41
|
+
scenario.name,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
});
|
package/src/extraction.ts
CHANGED
|
@@ -147,6 +147,15 @@ function normalizeProfileUpdateKey(update: string): string {
|
|
|
147
147
|
return update.trim().toLowerCase();
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
export function shouldEnableLocalExtractionThinking(
|
|
151
|
+
config: Pick<PluginConfig, "localLlmDisableThinking" | "localLlmThinkingThresholdChars">,
|
|
152
|
+
conversationChars: number,
|
|
153
|
+
): boolean {
|
|
154
|
+
return config.localLlmDisableThinking &&
|
|
155
|
+
config.localLlmThinkingThresholdChars > 0 &&
|
|
156
|
+
conversationChars < config.localLlmThinkingThresholdChars;
|
|
157
|
+
}
|
|
158
|
+
|
|
150
159
|
export class ExtractionEngine {
|
|
151
160
|
private client: OpenAI | null;
|
|
152
161
|
private localLlm: LocalLlmClient;
|
|
@@ -1523,6 +1532,9 @@ ${truncatedConversation}`;
|
|
|
1523
1532
|
temperature: 0.1,
|
|
1524
1533
|
maxTokens: contextSizes.maxOutputTokens,
|
|
1525
1534
|
operation: "extraction",
|
|
1535
|
+
disableThinking: shouldEnableLocalExtractionThinking(this.config, conversation.length)
|
|
1536
|
+
? false
|
|
1537
|
+
: undefined,
|
|
1526
1538
|
priority: "background",
|
|
1527
1539
|
},
|
|
1528
1540
|
);
|
|
@@ -83,7 +83,7 @@ function captureFetchBodies(): {
|
|
|
83
83
|
async function runOneChatCompletion(
|
|
84
84
|
client: LocalLlmClient,
|
|
85
85
|
operation: string | null = "extraction",
|
|
86
|
-
options: { forceDisableThinking?: boolean } = {},
|
|
86
|
+
options: { forceDisableThinking?: boolean; disableThinking?: boolean } = {},
|
|
87
87
|
): Promise<void> {
|
|
88
88
|
await client.chatCompletion(
|
|
89
89
|
[{ role: "user", content: "hello" }],
|
|
@@ -344,3 +344,15 @@ test("disableThinking=false never injects chat_template_kwargs, regardless of ba
|
|
|
344
344
|
}
|
|
345
345
|
assert.equal("chat_template_kwargs" in (bodies[0] ?? {}), false);
|
|
346
346
|
});
|
|
347
|
+
|
|
348
|
+
test("request-level thinking override leaves short extraction thinking enabled (#1997)", async () => {
|
|
349
|
+
const client = new LocalLlmClient(createConfig());
|
|
350
|
+
primeClient(client, { thinking: true, detected: "ollama" });
|
|
351
|
+
const { restore, bodies } = captureFetchBodies();
|
|
352
|
+
try {
|
|
353
|
+
await runOneChatCompletion(client, "extraction", { disableThinking: false });
|
|
354
|
+
} finally {
|
|
355
|
+
restore();
|
|
356
|
+
}
|
|
357
|
+
assert.equal("reasoning_effort" in (bodies[0] ?? {}), false);
|
|
358
|
+
});
|
package/src/local-llm.ts
CHANGED
|
@@ -220,6 +220,7 @@ interface LocalLlmChatCompletionOptions {
|
|
|
220
220
|
timeoutMs?: number;
|
|
221
221
|
operation?: string;
|
|
222
222
|
forceDisableThinking?: boolean;
|
|
223
|
+
disableThinking?: boolean;
|
|
223
224
|
priority?: LocalLlmRequestPriority;
|
|
224
225
|
}
|
|
225
226
|
|
|
@@ -989,7 +990,7 @@ export class LocalLlmClient {
|
|
|
989
990
|
// backend hasn't been positively identified as thinking-capable.
|
|
990
991
|
const shouldSuppressThinking =
|
|
991
992
|
options.forceDisableThinking === true ||
|
|
992
|
-
(this._disableThinking &&
|
|
993
|
+
((options.disableThinking ?? this._disableThinking) &&
|
|
993
994
|
THINKING_SUPPRESSED_OPERATIONS.has(operation));
|
|
994
995
|
if (
|
|
995
996
|
shouldSuppressThinking &&
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
|
|
7
|
+
import { parseConfig } from "../config.js";
|
|
8
|
+
import { StorageManager } from "../index.js";
|
|
9
|
+
import {
|
|
10
|
+
QmdResultResolver,
|
|
11
|
+
qmdResultPathCandidates,
|
|
12
|
+
} from "./qmd-result-resolver.js";
|
|
13
|
+
|
|
14
|
+
test("qmdResultPathCandidates probes the facts/ fallback for relative date paths", () => {
|
|
15
|
+
const root = path.join(os.tmpdir(), "remnic-resolver-rel");
|
|
16
|
+
const candidates = qmdResultPathCandidates(root, "2026-07-21/fact-x.md");
|
|
17
|
+
assert.deepEqual(
|
|
18
|
+
candidates.sort(),
|
|
19
|
+
[
|
|
20
|
+
path.join(root, "2026-07-21", "fact-x.md"),
|
|
21
|
+
path.join(root, "facts", "2026-07-21", "fact-x.md"),
|
|
22
|
+
].sort(),
|
|
23
|
+
"relative date paths probe both the literal and the facts/ location",
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("qmdResultPathCandidates probes the facts/ fallback for absolute date paths inside the storage root (issue #2111)", () => {
|
|
28
|
+
const root = path.join(os.tmpdir(), "remnic-resolver-abs");
|
|
29
|
+
const absolute = path.join(root, "2026-07-21", "fact-x.md");
|
|
30
|
+
const candidates = qmdResultPathCandidates(root, absolute);
|
|
31
|
+
assert.deepEqual(
|
|
32
|
+
candidates.sort(),
|
|
33
|
+
[absolute, path.join(root, "facts", "2026-07-21", "fact-x.md")].sort(),
|
|
34
|
+
"pre-absolutized date paths must probe the facts/ location too",
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("qmdResultPathCandidates keeps non-date absolute paths literal", () => {
|
|
39
|
+
const root = path.join(os.tmpdir(), "remnic-resolver-abs-nondate");
|
|
40
|
+
const absolute = path.join(root, "entities", "person-x.md");
|
|
41
|
+
assert.deepEqual(
|
|
42
|
+
qmdResultPathCandidates(root, absolute),
|
|
43
|
+
[absolute],
|
|
44
|
+
"non-date absolute paths must not grow a facts/ variant",
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("qmdResultPathCandidates rejects absolute paths outside the storage root", () => {
|
|
49
|
+
const root = path.join(os.tmpdir(), "remnic-resolver-abs-outside");
|
|
50
|
+
const outside = path.join(os.tmpdir(), "elsewhere", "2026-07-21", "fact-x.md");
|
|
51
|
+
assert.deepEqual(
|
|
52
|
+
qmdResultPathCandidates(root, outside),
|
|
53
|
+
[],
|
|
54
|
+
"containment must drop escaping paths, including their facts/ variant",
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("readQmdResultMemory resolves an absolute date path whose file lives under facts/ (issue #2111)", async () => {
|
|
59
|
+
const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-resolver-e2e-"));
|
|
60
|
+
try {
|
|
61
|
+
const storage = new StorageManager(dir);
|
|
62
|
+
await storage.ensureDirectories();
|
|
63
|
+
const factDir = path.join(dir, "facts", "2026-07-21");
|
|
64
|
+
await mkdir(factDir, { recursive: true });
|
|
65
|
+
const factPath = path.join(factDir, "fact-cookie-note.md");
|
|
66
|
+
await writeFile(
|
|
67
|
+
factPath,
|
|
68
|
+
[
|
|
69
|
+
"---",
|
|
70
|
+
"id: fact-cookie-note",
|
|
71
|
+
"category: fact",
|
|
72
|
+
"created: 2026-07-21T00:00:00.000Z",
|
|
73
|
+
"updated: 2026-07-21T00:00:00.000Z",
|
|
74
|
+
"status: active",
|
|
75
|
+
"---",
|
|
76
|
+
"",
|
|
77
|
+
"The storefront manages a uniqueId cookie with a 90-day expiration.",
|
|
78
|
+
"",
|
|
79
|
+
].join("\n"),
|
|
80
|
+
"utf8",
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const config = parseConfig({ memoryDir: dir });
|
|
84
|
+
const resolver = new QmdResultResolver({
|
|
85
|
+
getConfig: () => config,
|
|
86
|
+
storageFor: async () => storage,
|
|
87
|
+
storageDirNamespace: () => config.defaultNamespace,
|
|
88
|
+
qmdCollectionNamespaceFromPrefix: () => null,
|
|
89
|
+
namespaceFromPath: () => config.defaultNamespace,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Daemon-mode shape: the result path is already absolutized against the
|
|
93
|
+
// storage root but is missing the facts/ segment because the hot-facts
|
|
94
|
+
// collection was registered at the facts/ subtree.
|
|
95
|
+
const preAbsolutized = path.join(dir, "2026-07-21", "fact-cookie-note.md");
|
|
96
|
+
const memory = await resolver.readQmdResultMemory(preAbsolutized, storage);
|
|
97
|
+
assert.ok(memory, "the memory must resolve via the facts/ fallback");
|
|
98
|
+
assert.equal(memory.frontmatter.id, "fact-cookie-note");
|
|
99
|
+
assert.equal(path.resolve(memory.path), path.resolve(factPath));
|
|
100
|
+
} finally {
|
|
101
|
+
await rm(dir, { recursive: true, force: true });
|
|
102
|
+
}
|
|
103
|
+
});
|
|
@@ -84,6 +84,17 @@ export function qmdResultPathCandidates(
|
|
|
84
84
|
|
|
85
85
|
if (path.isAbsolute(resultPath)) {
|
|
86
86
|
addCandidate(resultPath);
|
|
87
|
+
// Daemon-mode results can arrive pre-absolutized against the storage
|
|
88
|
+
// root while the file lives under facts/<date>/ (hot-facts collection
|
|
89
|
+
// registered at the facts/ subtree — issue #2111). Mirror the relative
|
|
90
|
+
// branch's facts/ fallback; addCandidate re-checks containment.
|
|
91
|
+
const relative = path.relative(storageRoot, path.resolve(resultPath));
|
|
92
|
+
if (relative && !relative.startsWith("..") && !path.isAbsolute(relative)) {
|
|
93
|
+
const normalized = relative.split(path.sep).join("/");
|
|
94
|
+
if (/^\d{4}-\d{2}-\d{2}\//.test(normalized)) {
|
|
95
|
+
addCandidate(path.join(storageRoot, "facts", normalized));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
87
98
|
} else {
|
|
88
99
|
addRelativeCandidates(resultPath);
|
|
89
100
|
}
|
package/src/scopes/scope-plan.ts
CHANGED
|
@@ -489,6 +489,72 @@ export function resolveWritableNamespaceValue(
|
|
|
489
489
|
return { ok: true, namespace: resolved };
|
|
490
490
|
}
|
|
491
491
|
|
|
492
|
+
/**
|
|
493
|
+
* Inputs already derived by the access-service's read-only coding-context
|
|
494
|
+
* resolver. Keeping context discovery outside this pure function lets writes
|
|
495
|
+
* and preflight checks apply identical namespace and ACL rules.
|
|
496
|
+
*/
|
|
497
|
+
export interface ScopedWritableNamespaceInput {
|
|
498
|
+
readonly namespace?: string;
|
|
499
|
+
readonly sessionKey?: string;
|
|
500
|
+
readonly authenticatedPrincipal?: string;
|
|
501
|
+
readonly principal: string | undefined;
|
|
502
|
+
readonly codingOverlay: CodingNamespaceOverlay | null;
|
|
503
|
+
readonly scopeProfile: ResolvedScopeProfilePlan | null;
|
|
504
|
+
readonly config: PluginConfig;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Resolve the namespace an explicit write or implicit coding-scoped write
|
|
509
|
+
* would use. The caller supplies the same derived coding inputs for the real
|
|
510
|
+
* write and the read-only preflight.
|
|
511
|
+
*/
|
|
512
|
+
export function resolveScopedWritableNamespaceValue(
|
|
513
|
+
input: ScopedWritableNamespaceInput,
|
|
514
|
+
): WritableNamespaceResult {
|
|
515
|
+
const requested = input.namespace?.trim();
|
|
516
|
+
if (requested) {
|
|
517
|
+
return resolveWritableNamespaceValue(
|
|
518
|
+
requested,
|
|
519
|
+
input.sessionKey,
|
|
520
|
+
input.authenticatedPrincipal,
|
|
521
|
+
input.config,
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
if (input.scopeProfile) {
|
|
525
|
+
const selectedLayer = input.scopeProfile.layers.find(
|
|
526
|
+
(layer) => layer.id === input.scopeProfile?.writeLayer,
|
|
527
|
+
);
|
|
528
|
+
const writeNamespaceReadable =
|
|
529
|
+
input.scopeProfile.writeNamespace.length > 0 &&
|
|
530
|
+
input.scopeProfile.readNamespaces.includes(input.scopeProfile.writeNamespace);
|
|
531
|
+
if (!selectedLayer?.writable || !writeNamespaceReadable) {
|
|
532
|
+
return {
|
|
533
|
+
ok: false,
|
|
534
|
+
reason: "not_writable",
|
|
535
|
+
namespace: input.scopeProfile.writeNamespace,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
return { ok: true, namespace: input.scopeProfile.writeNamespace };
|
|
539
|
+
}
|
|
540
|
+
if (!input.codingOverlay) {
|
|
541
|
+
return resolveWritableNamespaceValue(
|
|
542
|
+
undefined,
|
|
543
|
+
input.sessionKey,
|
|
544
|
+
input.authenticatedPrincipal,
|
|
545
|
+
input.config,
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
const baseNamespace = defaultNamespaceForPrincipal(input.principal, input.config);
|
|
549
|
+
if (!canWriteNamespace(input.principal, baseNamespace, input.config)) {
|
|
550
|
+
return { ok: false, reason: "not_writable", namespace: baseNamespace };
|
|
551
|
+
}
|
|
552
|
+
return {
|
|
553
|
+
ok: true,
|
|
554
|
+
namespace: combineNamespaces(baseNamespace, input.codingOverlay.namespace),
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
|
|
492
558
|
/**
|
|
493
559
|
* Namespace preflight (issue #1888 part 3): would a write to `namespace` by a
|
|
494
560
|
* caller carrying `caps` succeed? Combines the token's write-op scope, its
|
package/src/types.ts
CHANGED
|
@@ -1624,6 +1624,12 @@ export interface PluginConfig extends BoundedJsonlStateConfig {
|
|
|
1624
1624
|
* `chat_template_kwargs`, so this is the only think-off dialect it honors.
|
|
1625
1625
|
* Issue #1996. */
|
|
1626
1626
|
localLlmReasoningEffort: string;
|
|
1627
|
+
/**
|
|
1628
|
+
* Maximum transcript length that re-enables thinking for local extraction.
|
|
1629
|
+
* Set to `0` to keep thinking suppressed for every extraction. Default:
|
|
1630
|
+
* `3000`. Consolidation is unaffected.
|
|
1631
|
+
*/
|
|
1632
|
+
localLlmThinkingThresholdChars: number;
|
|
1627
1633
|
// Extraction retry/backoff + circuit breaker (extraction hot-loop hardening)
|
|
1628
1634
|
/** Master gate. When false, restores pre-change behavior (extractor called on every triggered observe; no gate). */
|
|
1629
1635
|
extractionRetryEnabled: boolean;
|