@remnic/core 9.64.1 → 9.64.3
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 +12 -11
- package/dist/access-admin-ops-surface.js +23 -22
- package/dist/access-authorization-probe.d.ts +12 -11
- package/dist/access-authorization-probe.js +24 -23
- package/dist/access-boundary.d.ts +13 -12
- package/dist/access-boundary.js +23 -22
- package/dist/access-cli.js +70 -68
- 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 +12 -11
- package/dist/access-extraction-force-flush.js +23 -22
- package/dist/access-health-types.d.ts +1 -1
- package/dist/access-http-lcm-compaction.d.ts +12 -11
- package/dist/access-http-lifecycle-flush.d.ts +12 -11
- package/dist/access-http-offline-stream.d.ts +12 -11
- package/dist/access-http-query.d.ts +2 -2
- package/dist/access-http-query.js +25 -24
- package/dist/access-http.d.ts +13 -12
- package/dist/access-http.js +40 -39
- package/dist/access-identity-continuity-surface.d.ts +9 -9
- package/dist/access-identity-continuity-surface.js +23 -22
- package/dist/access-lcm-surface.d.ts +12 -11
- package/dist/access-lcm-surface.js +23 -22
- package/dist/access-mcp-output-schemas.js +1 -1
- package/dist/access-mcp.d.ts +12 -186
- package/dist/access-mcp.js +32 -31
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-Dj9uR4Cq.d.ts → access-namespace-preflight-CYeI1R2_.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +23 -22
- package/dist/access-observe-write-surface.d.ts +12 -11
- package/dist/access-observe-write-surface.js +23 -22
- package/dist/access-offline-manifest.d.ts +9 -9
- package/dist/access-operations-batch.js +26 -25
- package/dist/access-operations.d.ts +16 -15
- package/dist/access-operations.js +29 -28
- package/dist/access-recall-concurrency.d.ts +12 -11
- package/dist/access-recall-concurrency.js +23 -22
- package/dist/access-recall-response.d.ts +12 -11
- package/dist/access-recall-response.js +23 -22
- package/dist/access-recall-surface.d.ts +12 -11
- package/dist/access-recall-surface.js +23 -22
- package/dist/access-schema.d.ts +88 -88
- package/dist/access-schema.js +3 -3
- package/dist/{access-service-Bd0lzaHp.d.ts → access-service-BKtdXnyk.d.ts} +358 -76
- package/dist/access-service-helpers.d.ts +12 -11
- package/dist/access-service.d.ts +12 -11
- package/dist/access-service.js +23 -22
- package/dist/access-surface-catalog.d.ts +12 -11
- package/dist/access-surface-catalog.js +27 -24
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/access-wearables-meetings-surface.d.ts +3 -3
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +1 -1
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/ambient-provenance.d.ts +1 -1
- package/dist/artifact-search.d.ts +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +9 -9
- package/dist/briefing-window.d.ts +2 -2
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +10 -10
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer-turn-helpers.d.ts +1 -1
- package/dist/buffer.d.ts +2 -2
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{capsule-crypto-GWVG7LGC.js → capsule-crypto-7FJQINUR.js} +2 -2
- package/dist/{catalog-rKYbN7zF.d.ts → catalog-CLAqQO2L.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 +11 -11
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-D267K4V5.js → chunk-246HFJVG.js} +2 -2
- package/dist/{chunk-OWHERGF2.js → chunk-2NLLXCJG.js} +2 -2
- package/dist/{chunk-2RZCOG63.js → chunk-2QI2JBLQ.js} +359 -238
- package/dist/chunk-2QI2JBLQ.js.map +1 -0
- package/dist/{chunk-WNO5W2TP.js → chunk-3A46U7XG.js} +2 -2
- package/dist/{chunk-XFAWGUNX.js → chunk-3LOQN3TO.js} +10 -5
- package/dist/chunk-3LOQN3TO.js.map +1 -0
- package/dist/{chunk-5Q5BEWJ3.js → chunk-44DSGZFF.js} +2 -2
- package/dist/{chunk-VENMDW4U.js → chunk-55SJFHVD.js} +6 -6
- package/dist/{chunk-VCBG52MM.js → chunk-5HERQ5FX.js} +7 -7
- package/dist/{chunk-IRXMJLTW.js → chunk-5HK3CJAR.js} +2 -2
- package/dist/{chunk-VSKA2ATE.js → chunk-6LTCUN3T.js} +2 -2
- package/dist/{chunk-IHPYTG6F.js → chunk-7BVO64UC.js} +2 -2
- package/dist/{chunk-ZUIVJ3BB.js → chunk-7V3AZWWZ.js} +4 -4
- package/dist/{chunk-Y5ZIQFWH.js → chunk-A2IBK3TG.js} +2 -2
- package/dist/{chunk-6I6IOMKS.js → chunk-C6AKYOFO.js} +2 -2
- package/dist/{chunk-ZGGTIBWN.js → chunk-CKZHKFY3.js} +3 -3
- package/dist/{chunk-FMGTFMT3.js → chunk-DA2O3F5V.js} +25 -11
- package/dist/chunk-DA2O3F5V.js.map +1 -0
- package/dist/{chunk-GSQDPL45.js → chunk-DC4FJY2G.js} +22 -7
- package/dist/{chunk-GSQDPL45.js.map → chunk-DC4FJY2G.js.map} +1 -1
- package/dist/{chunk-JE3AKPOO.js → chunk-DG6MJD7W.js} +2 -2
- package/dist/{chunk-P4SD7BSA.js → chunk-DHKV6E4A.js} +2 -2
- package/dist/{chunk-KOE3RLNN.js → chunk-EJDLQRUO.js} +2 -2
- package/dist/{chunk-VD2OT77P.js → chunk-GEULB2VI.js} +2 -1
- package/dist/chunk-GEULB2VI.js.map +1 -0
- package/dist/{chunk-DRS3OX77.js → chunk-GVRLED7R.js} +2 -2
- package/dist/{chunk-EAWJSY2Z.js → chunk-H5CGAD7L.js} +1 -1
- package/dist/{chunk-DLZBOEJY.js → chunk-IFK3PVM7.js} +2 -2
- package/dist/{chunk-E7MYSCSL.js → chunk-IJXECCUV.js} +2 -2
- package/dist/{chunk-RKNJBZ55.js → chunk-JBPKEARU.js} +4 -4
- package/dist/{chunk-NMQXUGTU.js → chunk-JCSUNXYJ.js} +3 -3
- package/dist/{chunk-5W7CTZ2E.js → chunk-KQAFEZQX.js} +4 -4
- package/dist/{chunk-YY63AMGP.js → chunk-KRPE7ANR.js} +2 -2
- package/dist/{chunk-AGC3Q53R.js → chunk-LOETWOEB.js} +2 -2
- package/dist/{chunk-7X35RPN3.js → chunk-LZKCMK3U.js} +2 -2
- package/dist/{chunk-4KKVDOCD.js → chunk-MJRVF7SF.js} +26 -25
- package/dist/chunk-MJRVF7SF.js.map +1 -0
- package/dist/{chunk-K547KS3X.js → chunk-ML3U4KPR.js} +4 -4
- package/dist/{chunk-HIEWDJ2O.js → chunk-MSTNSVXI.js} +2 -1
- package/dist/chunk-MSTNSVXI.js.map +1 -0
- package/dist/{chunk-CI6YIT5S.js → chunk-NO7B6DRB.js} +2 -2
- package/dist/{chunk-Q3IRE6E4.js → chunk-ON2P3SHG.js} +2 -2
- package/dist/{chunk-2Q4UAPLD.js → chunk-OQIRBGUU.js} +4 -4
- package/dist/{chunk-WDFXRHOZ.js → chunk-PE76XIDM.js} +3 -3
- package/dist/{chunk-MVIYRRVJ.js → chunk-PMVPCZJZ.js} +5 -5
- package/dist/{chunk-VCNGVU62.js → chunk-PVIXAMWM.js} +2 -2
- package/dist/{chunk-QHNO6AND.js → chunk-RWLRKMZK.js} +2 -2
- package/dist/{chunk-UWSETW6O.js → chunk-SB6YBB2V.js} +2 -2
- package/dist/{chunk-DTQ3OB7O.js → chunk-SHQFYZTD.js} +2 -2
- package/dist/chunk-TKI2WOL5.js +256 -0
- package/dist/chunk-TKI2WOL5.js.map +1 -0
- package/dist/chunk-TY35YQ6E.js +77 -0
- package/dist/chunk-TY35YQ6E.js.map +1 -0
- package/dist/{chunk-AL43367I.js → chunk-UMDZXW5J.js} +23 -1
- package/dist/chunk-UMDZXW5J.js.map +1 -0
- package/dist/{chunk-G5OB4XZX.js → chunk-VANZKHTN.js} +4 -4
- package/dist/{chunk-IPUUMLSM.js → chunk-VLES5S4K.js} +271 -62
- package/dist/chunk-VLES5S4K.js.map +1 -0
- package/dist/{chunk-DPPTG6VJ.js → chunk-VRYEXPRX.js} +1 -1
- package/dist/chunk-VRYEXPRX.js.map +1 -0
- package/dist/{chunk-3CYVTO6A.js → chunk-VUP47UJI.js} +3 -3
- package/dist/{chunk-OTVHRZZD.js → chunk-WBM5NR4E.js} +2 -2
- package/dist/{chunk-UVYI6VIX.js → chunk-X7Y7WX73.js} +1 -1
- package/dist/{chunk-7D3TTGHY.js → chunk-XACYILRA.js} +38 -12
- package/dist/chunk-XACYILRA.js.map +1 -0
- package/dist/{chunk-B2GICNOJ.js → chunk-XH4IQVTN.js} +2 -2
- package/dist/{chunk-OWAYQK5V.js → chunk-XZUCNVGE.js} +8 -8
- package/dist/{chunk-4FSCGYTQ.js → chunk-YFQTDE7N.js} +2 -2
- package/dist/{chunk-RMB22Q3R.js → chunk-YXGU3MDQ.js} +2 -2
- package/dist/{chunk-XSPRZZEX.js → chunk-Z6CJLYXT.js} +4 -4
- package/dist/{chunk-DZ2AVS2H.js → chunk-ZSYE2QVJ.js} +2 -2
- package/dist/{cli-0dDmOsJ8.d.ts → cli-CLvBewKf.d.ts} +5 -5
- package/dist/cli.d.ts +13 -13
- package/dist/cli.js +56 -55
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +10 -10
- 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 +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +10 -10
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +10 -10
- 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/converge-config.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +2 -2
- package/dist/convergence-refresh.js +12 -12
- 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 +12 -12
- 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-Cr8u-XwC.d.ts → dependency-propagation-delivery-DMqIw9Zh.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 +10 -10
- 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/external-wiki-access.d.ts +12 -11
- package/dist/external-wiki-access.js +24 -23
- 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 +12 -13
- 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 +10 -10
- 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 +709 -700
- package/dist/index.js +116 -80
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/engine.js +3 -3
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +11 -11
- 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 +10 -10
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +10 -10
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +11 -11
- package/dist/{maintenance-BpNjuZk4.d.ts → maintenance-DITiehFX.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +12 -11
- package/dist/mcp-read-only-tools.js +1 -1
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-snapshot.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +2 -2
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +3 -3
- package/dist/namespaces/migrate.js +11 -11
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +7 -7
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +10 -10
- 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 +13 -13
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +19 -19
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +16 -16
- package/dist/{orchestrator-B3ZQ8CTJ.d.ts → orchestrator-6fPa2l9x.d.ts} +8 -8
- package/dist/orchestrator.d.ts +9 -9
- package/dist/orchestrator.js +70 -68
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-q5emoXD6.d.ts → pipeline-DHpYtfM3.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-CQN-i7Ai.d.ts → public-http-BT36aBb-.d.ts} +1 -1
- package/dist/{qmd-YC6YGphs.d.ts → qmd-BaX31tM0.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +2 -2
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +2 -2
- package/dist/recall-concurrency-config.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-memory-map.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-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/reconcile/cursor.d.ts +1 -1
- package/dist/reconcile/manifest.d.ts +1 -1
- package/dist/reconcile/plan.d.ts +1 -1
- package/dist/replay/normalizers/chatgpt.d.ts +1 -1
- package/dist/replay/normalizers/claude.d.ts +1 -1
- package/dist/replay/normalizers/openclaw.d.ts +1 -1
- package/dist/replay/normalizers/shared.d.ts +1 -1
- package/dist/replay/runner.d.ts +1 -1
- package/dist/replay/types.d.ts +1 -1
- package/dist/replica-divergence.d.ts +1 -1
- package/dist/replica-peers-config.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +2 -2
- 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-De8F7YQ6.d.ts → scope-profiles-1hYWJ9bM.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 +6 -6
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +10 -10
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/lancedb-backend.js +2 -2
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.js +2 -2
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/orama-backend.js +2 -2
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-Bf-hm2LQ.d.ts → semantic-consolidation-Chmddvcg.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +11 -11
- package/dist/semantic-rule-promotion.js +10 -10
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +10 -10
- package/dist/{service-D83osSRn.d.ts → service-DMs_dCCg.d.ts} +2 -2
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +9 -9
- package/dist/signal.d.ts +1 -1
- package/dist/source-agent-qualifier.d.ts +1 -1
- package/dist/source-agent-qualifier.js +10 -10
- package/dist/{storage-BHWbpbhj.d.ts → storage-CzorrpcN.d.ts} +12 -3
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +9 -9
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/support-passport/index.d.ts +15 -14
- package/dist/support-passport/index.js +26 -25
- 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/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-CpgsN-Gb.d.ts → types-BP5MC8UU.d.ts} +10 -5
- 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 +10 -10
- package/dist/who-knows-cli.d.ts +155 -0
- package/dist/who-knows-cli.js +109 -0
- package/dist/who-knows-cli.js.map +1 -0
- package/dist/who-knows.d.ts +127 -0
- package/dist/who-knows.js +118 -0
- package/dist/who-knows.js.map +1 -0
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/access-boundary.ts +1 -0
- package/src/access-http.ts +15 -0
- package/src/access-mcp-output-schemas.ts +1 -0
- package/src/access-mcp.ts +3 -2
- package/src/access-operations-batch.ts +8 -0
- package/src/access-service.ts +26 -0
- package/src/access-surface-catalog.ts +2 -0
- package/src/cli/okf-commands.ts +23 -0
- package/src/cli.ts +2 -1
- package/src/config.ts +2 -1
- package/src/index.ts +3 -0
- package/src/mcp-read-only-tools.ts +1 -0
- package/src/okf/cli.ts +42 -0
- package/src/okf/config.ts +34 -0
- package/src/okf/lint.ts +110 -0
- package/src/okf/sweep.ts +63 -0
- package/src/okf/type-mapping.test.ts +207 -0
- package/src/okf/type-mapping.ts +79 -0
- package/src/orchestrator.ts +2 -0
- package/src/storage/entity-store.ts +9 -5
- package/src/storage/profile-header.ts +33 -9
- package/src/storage/questions-file.ts +50 -0
- package/src/storage.ts +76 -63
- package/src/types.ts +4 -5
- package/src/who-knows-cli.ts +96 -0
- package/src/who-knows.test.ts +257 -0
- package/src/who-knows.ts +364 -0
- package/dist/chunk-2RZCOG63.js.map +0 -1
- package/dist/chunk-4KKVDOCD.js.map +0 -1
- package/dist/chunk-7D3TTGHY.js.map +0 -1
- package/dist/chunk-AL43367I.js.map +0 -1
- package/dist/chunk-DPPTG6VJ.js.map +0 -1
- package/dist/chunk-FMGTFMT3.js.map +0 -1
- package/dist/chunk-HIEWDJ2O.js.map +0 -1
- package/dist/chunk-IPUUMLSM.js.map +0 -1
- package/dist/chunk-VD2OT77P.js.map +0 -1
- package/dist/chunk-XFAWGUNX.js.map +0 -1
- /package/dist/{capsule-crypto-GWVG7LGC.js.map → capsule-crypto-7FJQINUR.js.map} +0 -0
- /package/dist/{chunk-D267K4V5.js.map → chunk-246HFJVG.js.map} +0 -0
- /package/dist/{chunk-OWHERGF2.js.map → chunk-2NLLXCJG.js.map} +0 -0
- /package/dist/{chunk-WNO5W2TP.js.map → chunk-3A46U7XG.js.map} +0 -0
- /package/dist/{chunk-5Q5BEWJ3.js.map → chunk-44DSGZFF.js.map} +0 -0
- /package/dist/{chunk-VENMDW4U.js.map → chunk-55SJFHVD.js.map} +0 -0
- /package/dist/{chunk-VCBG52MM.js.map → chunk-5HERQ5FX.js.map} +0 -0
- /package/dist/{chunk-IRXMJLTW.js.map → chunk-5HK3CJAR.js.map} +0 -0
- /package/dist/{chunk-VSKA2ATE.js.map → chunk-6LTCUN3T.js.map} +0 -0
- /package/dist/{chunk-IHPYTG6F.js.map → chunk-7BVO64UC.js.map} +0 -0
- /package/dist/{chunk-ZUIVJ3BB.js.map → chunk-7V3AZWWZ.js.map} +0 -0
- /package/dist/{chunk-Y5ZIQFWH.js.map → chunk-A2IBK3TG.js.map} +0 -0
- /package/dist/{chunk-6I6IOMKS.js.map → chunk-C6AKYOFO.js.map} +0 -0
- /package/dist/{chunk-ZGGTIBWN.js.map → chunk-CKZHKFY3.js.map} +0 -0
- /package/dist/{chunk-JE3AKPOO.js.map → chunk-DG6MJD7W.js.map} +0 -0
- /package/dist/{chunk-P4SD7BSA.js.map → chunk-DHKV6E4A.js.map} +0 -0
- /package/dist/{chunk-KOE3RLNN.js.map → chunk-EJDLQRUO.js.map} +0 -0
- /package/dist/{chunk-DRS3OX77.js.map → chunk-GVRLED7R.js.map} +0 -0
- /package/dist/{chunk-EAWJSY2Z.js.map → chunk-H5CGAD7L.js.map} +0 -0
- /package/dist/{chunk-DLZBOEJY.js.map → chunk-IFK3PVM7.js.map} +0 -0
- /package/dist/{chunk-E7MYSCSL.js.map → chunk-IJXECCUV.js.map} +0 -0
- /package/dist/{chunk-RKNJBZ55.js.map → chunk-JBPKEARU.js.map} +0 -0
- /package/dist/{chunk-NMQXUGTU.js.map → chunk-JCSUNXYJ.js.map} +0 -0
- /package/dist/{chunk-5W7CTZ2E.js.map → chunk-KQAFEZQX.js.map} +0 -0
- /package/dist/{chunk-YY63AMGP.js.map → chunk-KRPE7ANR.js.map} +0 -0
- /package/dist/{chunk-AGC3Q53R.js.map → chunk-LOETWOEB.js.map} +0 -0
- /package/dist/{chunk-7X35RPN3.js.map → chunk-LZKCMK3U.js.map} +0 -0
- /package/dist/{chunk-K547KS3X.js.map → chunk-ML3U4KPR.js.map} +0 -0
- /package/dist/{chunk-CI6YIT5S.js.map → chunk-NO7B6DRB.js.map} +0 -0
- /package/dist/{chunk-Q3IRE6E4.js.map → chunk-ON2P3SHG.js.map} +0 -0
- /package/dist/{chunk-2Q4UAPLD.js.map → chunk-OQIRBGUU.js.map} +0 -0
- /package/dist/{chunk-WDFXRHOZ.js.map → chunk-PE76XIDM.js.map} +0 -0
- /package/dist/{chunk-MVIYRRVJ.js.map → chunk-PMVPCZJZ.js.map} +0 -0
- /package/dist/{chunk-VCNGVU62.js.map → chunk-PVIXAMWM.js.map} +0 -0
- /package/dist/{chunk-QHNO6AND.js.map → chunk-RWLRKMZK.js.map} +0 -0
- /package/dist/{chunk-UWSETW6O.js.map → chunk-SB6YBB2V.js.map} +0 -0
- /package/dist/{chunk-DTQ3OB7O.js.map → chunk-SHQFYZTD.js.map} +0 -0
- /package/dist/{chunk-G5OB4XZX.js.map → chunk-VANZKHTN.js.map} +0 -0
- /package/dist/{chunk-3CYVTO6A.js.map → chunk-VUP47UJI.js.map} +0 -0
- /package/dist/{chunk-OTVHRZZD.js.map → chunk-WBM5NR4E.js.map} +0 -0
- /package/dist/{chunk-UVYI6VIX.js.map → chunk-X7Y7WX73.js.map} +0 -0
- /package/dist/{chunk-B2GICNOJ.js.map → chunk-XH4IQVTN.js.map} +0 -0
- /package/dist/{chunk-OWAYQK5V.js.map → chunk-XZUCNVGE.js.map} +0 -0
- /package/dist/{chunk-4FSCGYTQ.js.map → chunk-YFQTDE7N.js.map} +0 -0
- /package/dist/{chunk-RMB22Q3R.js.map → chunk-YXGU3MDQ.js.map} +0 -0
- /package/dist/{chunk-XSPRZZEX.js.map → chunk-Z6CJLYXT.js.map} +0 -0
- /package/dist/{chunk-DZ2AVS2H.js.map → chunk-ZSYE2QVJ.js.map} +0 -0
|
@@ -45,6 +45,9 @@ import {
|
|
|
45
45
|
serializeEntityFile,
|
|
46
46
|
StorageManager,
|
|
47
47
|
} from "../storage.js";
|
|
48
|
+
// Issue #1533 Phase B: importers take entity-file parsing from this storage/
|
|
49
|
+
// subsystem module, not the storage.ts god file (see check-ratchets.mjs).
|
|
50
|
+
export { parseEntityFile } from "../storage.js";
|
|
48
51
|
import { parseOriginClass } from "../security/origin-authority.js";
|
|
49
52
|
|
|
50
53
|
export interface EntityStoreDeps {
|
|
@@ -64,6 +67,7 @@ export interface EntityStoreDeps {
|
|
|
64
67
|
getMemoryStatusVersion(): number;
|
|
65
68
|
invalidateKnowledgeIndexCache(): void;
|
|
66
69
|
knowledgeIndexCache: { result: string; builtAt: number } | null;
|
|
70
|
+
okfConformanceEnabled(): boolean;
|
|
67
71
|
normalizeEntityName(raw: string, type: string): string;
|
|
68
72
|
readAllEntityFiles(): Promise<EntityFile[]>;
|
|
69
73
|
readStorageSecureFile(filePath: string): Promise<string>;
|
|
@@ -142,7 +146,7 @@ export class EntityStore {
|
|
|
142
146
|
located.entity.updated = new Date().toISOString();
|
|
143
147
|
await this.deps.writeStorageSecureFile(
|
|
144
148
|
located.filePath,
|
|
145
|
-
serializeEntityFile(located.entity, this.deps.entitySchemas),
|
|
149
|
+
serializeEntityFile(located.entity, this.deps.entitySchemas, this.deps.okfConformanceEnabled()),
|
|
146
150
|
);
|
|
147
151
|
reconcileIfJournalMovedSync(stateDir, idsAtResolve, this.deps.currentHistoricalIds());
|
|
148
152
|
this.deps.invalidateKnowledgeIndexCache();
|
|
@@ -352,7 +356,7 @@ export class EntityStore {
|
|
|
352
356
|
entity.updated = new Date().toISOString();
|
|
353
357
|
|
|
354
358
|
await this.deps.snapshotBeforeWrite(filePath, "write");
|
|
355
|
-
await this.deps.writeStorageSecureFile(filePath, serializeEntityFile(entity, this.deps.entitySchemas));
|
|
359
|
+
await this.deps.writeStorageSecureFile(filePath, serializeEntityFile(entity, this.deps.entitySchemas, this.deps.okfConformanceEnabled()));
|
|
356
360
|
this.deps.invalidateKnowledgeIndexCache();
|
|
357
361
|
this.deps.bumpMemoryStatusVersion(); // invalidate entity cache
|
|
358
362
|
this.deps.bumpEntityMutationVersion();
|
|
@@ -401,7 +405,7 @@ export class EntityStore {
|
|
|
401
405
|
const wrote = await withEntityCanonicalMutationLock(stateDir, async () => {
|
|
402
406
|
const raw = await this.readEntity(entityName);
|
|
403
407
|
if (!raw) return false;
|
|
404
|
-
const serialized = serializeEntityFile(parseEntityFile(raw, this.deps.entitySchemas), this.deps.entitySchemas);
|
|
408
|
+
const serialized = serializeEntityFile(parseEntityFile(raw, this.deps.entitySchemas), this.deps.entitySchemas, this.deps.okfConformanceEnabled());
|
|
405
409
|
if (raw.trimEnd() === serialized.trimEnd()) return false;
|
|
406
410
|
const filePath = this.deps.resolveEntityFilePath(entityName);
|
|
407
411
|
if (filePath === null) return false;
|
|
@@ -484,7 +488,7 @@ export class EntityStore {
|
|
|
484
488
|
entity.synthesisVersion = Math.max(0, entity.synthesisVersion ?? 0)
|
|
485
489
|
+ (options.incrementVersion === false ? 0 : 1);
|
|
486
490
|
entity.updated = entityUpdatedAt;
|
|
487
|
-
await this.deps.writeStorageSecureFile(filePath, serializeEntityFile(entity, this.deps.entitySchemas));
|
|
491
|
+
await this.deps.writeStorageSecureFile(filePath, serializeEntityFile(entity, this.deps.entitySchemas, this.deps.okfConformanceEnabled()));
|
|
488
492
|
await this.deps.removeEntitySynthesisQueueEntries([
|
|
489
493
|
...new Set([name, this.deps.normalizeEntityName(entity.name, entity.type)]),
|
|
490
494
|
]);
|
|
@@ -898,7 +902,7 @@ export class EntityStore {
|
|
|
898
902
|
mergedEntity.updated = mergedEntity.updated || new Date().toISOString();
|
|
899
903
|
|
|
900
904
|
const canonicalPath = path.join(this.deps.entitiesDir, `${canonical}.md`);
|
|
901
|
-
await this.deps.writeStorageSecureFile(canonicalPath, serializeEntityFile(mergedEntity, this.deps.entitySchemas));
|
|
905
|
+
await this.deps.writeStorageSecureFile(canonicalPath, serializeEntityFile(mergedEntity, this.deps.entitySchemas, this.deps.okfConformanceEnabled()));
|
|
902
906
|
this.deps.bumpEntityMutationVersion();
|
|
903
907
|
|
|
904
908
|
// Remove non-canonical files
|
|
@@ -245,12 +245,6 @@ function findHtmlTagPrefix(line: string): HtmlTag | null {
|
|
|
245
245
|
return null;
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
function isRawHtmlBlockTerminator(line: string): boolean {
|
|
249
|
-
const normalizedLine = line.toLowerCase();
|
|
250
|
-
return RAW_HTML_BLOCK_TAGS.some((name) =>
|
|
251
|
-
hasRawHtmlBlockEndMarker(normalizedLine, `</${name}>`),
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
248
|
|
|
255
249
|
function findHtmlTags(line: string): HtmlTag[] {
|
|
256
250
|
const tags: HtmlTag[] = [];
|
|
@@ -429,9 +423,6 @@ function shouldCloseHtmlBlock(line: string, endMarker: string): boolean {
|
|
|
429
423
|
}
|
|
430
424
|
|
|
431
425
|
|
|
432
|
-
function hasRawHtmlBlockEndMarker(line: string, endMarker: string): boolean {
|
|
433
|
-
return line.includes(endMarker);
|
|
434
|
-
}
|
|
435
426
|
function canStartGenericHtmlBlock(
|
|
436
427
|
lines: ProfileLine[],
|
|
437
428
|
index: number,
|
|
@@ -896,3 +887,36 @@ export function renderProfileWithLastUpdated(content: string, updatedAt: string)
|
|
|
896
887
|
insertHeaderAfter(lines, titleIndex, header);
|
|
897
888
|
return renderProfileLines(lines);
|
|
898
889
|
}
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* OKF v0.1 profile frontmatter (issue #1946). `profile.md` gains a leading
|
|
893
|
+
* frontmatter block so the memory directory is a conformant OKF knowledge
|
|
894
|
+
* bundle; every reader strips it so the bytes injected into prompts are
|
|
895
|
+
* unchanged. Line-scan based (no regex) per the regex-safety rule.
|
|
896
|
+
*/
|
|
897
|
+
|
|
898
|
+
/** Prepend the OKF block when enabled and not already present. No-op otherwise. */
|
|
899
|
+
export function withOkfProfileFrontmatter(content: string, timestamp: string, enabled: boolean): string {
|
|
900
|
+
if (!enabled || stripOkfProfileFrontmatter(content) !== content) return content;
|
|
901
|
+
return `---\ntype: Profile\ntitle: User Profile\ntimestamp: ${timestamp}\n---\n${content}`;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
/**
|
|
905
|
+
* Strip the OKF profile block from the start of `profile.md` content.
|
|
906
|
+
* Only a leading block whose keys include `type: Profile` is removed, so
|
|
907
|
+
* hand-written content without the marker round-trips byte-identically.
|
|
908
|
+
*/
|
|
909
|
+
export function stripOkfProfileFrontmatter(content: string): string {
|
|
910
|
+
if (!content.startsWith("---\n") && !content.startsWith("---\r\n")) return content;
|
|
911
|
+
const lines = content.split("\n");
|
|
912
|
+
for (let index = 1; index < lines.length; index += 1) {
|
|
913
|
+
const line = lines[index]!;
|
|
914
|
+
if (line === "---" || line === "---\r") {
|
|
915
|
+
return lines.slice(1, index).some((l) => l.startsWith("type: Profile"))
|
|
916
|
+
? lines.slice(index + 1).join("\n")
|
|
917
|
+
: content;
|
|
918
|
+
}
|
|
919
|
+
if (line === "" || line === "\r" || line === "...") return content;
|
|
920
|
+
}
|
|
921
|
+
return content;
|
|
922
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Question file format (issue #1946 extraction from storage.ts so the
|
|
3
|
+
* surface file stays under its structural ceiling). Pure text parsing —
|
|
4
|
+
* no filesystem, no caches; StorageManager delegates through so the
|
|
5
|
+
* selfDeps consumers (MemoryReadStore) keep their seam unchanged.
|
|
6
|
+
*/
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
|
|
9
|
+
export interface ParsedQuestionFile {
|
|
10
|
+
id: string;
|
|
11
|
+
question: string;
|
|
12
|
+
context: string;
|
|
13
|
+
priority: number;
|
|
14
|
+
resolved: boolean;
|
|
15
|
+
created: string;
|
|
16
|
+
filePath: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function parseQuestionFile(raw: string, filePath: string): ParsedQuestionFile | null {
|
|
20
|
+
if (!raw.startsWith("---\n")) return null;
|
|
21
|
+
const close = raw.indexOf("\n---\n\n", 4);
|
|
22
|
+
if (close === -1) return null;
|
|
23
|
+
const frontmatterStr = raw.slice(4, close);
|
|
24
|
+
const body = raw.slice(close + 6).trim();
|
|
25
|
+
|
|
26
|
+
const id = extractFrontmatterValue(frontmatterStr, "id") ?? path.basename(filePath, ".md");
|
|
27
|
+
const created = extractFrontmatterValue(frontmatterStr, "created") ?? "";
|
|
28
|
+
const priority = parseFloat(extractFrontmatterValue(frontmatterStr, "priority") ?? "0.5");
|
|
29
|
+
const resolved = extractFrontmatterValue(frontmatterStr, "resolved") === "true";
|
|
30
|
+
|
|
31
|
+
const contextMarker = "**Context:**";
|
|
32
|
+
const contextAt = body.indexOf(contextMarker);
|
|
33
|
+
const question = contextAt === -1 ? body : body.slice(0, contextAt).trim();
|
|
34
|
+
const context = contextAt === -1 ? "" : body.slice(contextAt + contextMarker.length).trim();
|
|
35
|
+
|
|
36
|
+
return { id, question, context, priority, resolved, created, filePath };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function extractFrontmatterValue(frontmatter: string, key: string): string | null {
|
|
40
|
+
const prefix = `${key}:`;
|
|
41
|
+
for (const line of frontmatter.split("\n")) {
|
|
42
|
+
if (!line.startsWith(prefix)) continue;
|
|
43
|
+
let value = line.slice(prefix.length).trim();
|
|
44
|
+
if (value.startsWith('"') && value.endsWith('"') && value.length >= 2) {
|
|
45
|
+
value = value.slice(1, -1);
|
|
46
|
+
}
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
package/src/storage.ts
CHANGED
|
@@ -30,7 +30,9 @@ import { createTombstoneMigrationSourceContents } from "./storage/tombstone-migr
|
|
|
30
30
|
import { MemoryReadStore, readWindowedMemories, type WindowedMemoryReadOptions, type WindowedMemoryReadResult } from "./storage/memory-read-store.js";
|
|
31
31
|
import { hasSupersessionAudit } from "./storage/supersession-audit.js";
|
|
32
32
|
import { runCommittedInvalidation } from "./storage/committed-invalidation.js";
|
|
33
|
-
import { renderProfileWithLastUpdated } from "./storage/profile-header.js";
|
|
33
|
+
import { renderProfileWithLastUpdated, stripOkfProfileFrontmatter, withOkfProfileFrontmatter } from "./storage/profile-header.js";
|
|
34
|
+
import { parseQuestionFile as parseQuestionFileText } from "./storage/questions-file.js";
|
|
35
|
+
import { assertNotOkfReservedBasename, OKF_QUESTION_TYPE, okfTypeForEntityKind, okfTypeForMemory } from "./okf/type-mapping.js";
|
|
34
36
|
import { readMaybeEncryptedLines, readMemoryActionEventRowsFromLines } from "./storage/secure-line-reader.js";
|
|
35
37
|
import {
|
|
36
38
|
appendLifecycleEventsSerialized,
|
|
@@ -319,6 +321,8 @@ function serializeFrontmatter(fm: MemoryFrontmatter): string {
|
|
|
319
321
|
`confidenceTier: ${fm.confidenceTier}`,
|
|
320
322
|
`tags: [${fm.tags.map((t) => `"${t}"`).join(", ")}]`,
|
|
321
323
|
];
|
|
324
|
+
// OKF v0.1 interop (issue #1946): inert presentation metadata; `category` stays canonical.
|
|
325
|
+
if (fm.type !== undefined) lines.push(`type: ${fm.type}`);
|
|
322
326
|
if (fm.origin) lines.push(`origin: ${/^[A-Za-z0-9:_.*-]+$/.test(fm.origin) ? fm.origin : JSON.stringify(fm.origin)}`);
|
|
323
327
|
if (fm.entityRef) lines.push(`entityRef: ${fm.entityRef}`);
|
|
324
328
|
if (fm.sourceConnector) {
|
|
@@ -855,6 +859,7 @@ export function parseFrontmatter(raw: string): { frontmatter: MemoryFrontmatter;
|
|
|
855
859
|
frontmatter: {
|
|
856
860
|
id: fm.id ?? "",
|
|
857
861
|
category: (fm.category ?? "fact") as MemoryCategory,
|
|
862
|
+
type: parseFrontmatterStringValue(fm.type),
|
|
858
863
|
created: fm.created ?? new Date().toISOString(),
|
|
859
864
|
updated: fm.updated ?? new Date().toISOString(),
|
|
860
865
|
source: fm.source ?? "unknown",
|
|
@@ -1099,15 +1104,16 @@ function parseEntityFrontmatter(raw: string): {
|
|
|
1099
1104
|
|
|
1100
1105
|
const values: Record<string, string> = {};
|
|
1101
1106
|
const extraLines: string[] = [];
|
|
1102
|
-
const recognizedKeys =
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1107
|
+
const recognizedKeys: Record<string, true> = {
|
|
1108
|
+
created: true,
|
|
1109
|
+
updated: true,
|
|
1110
|
+
type: true,
|
|
1111
|
+
synthesis_updated_at: true,
|
|
1112
|
+
synthesis_timeline_count: true,
|
|
1113
|
+
synthesis_structured_fact_count: true,
|
|
1114
|
+
synthesis_structured_fact_digest: true,
|
|
1115
|
+
synthesis_version: true,
|
|
1116
|
+
};
|
|
1111
1117
|
for (const line of match[1].split(/\r?\n/)) {
|
|
1112
1118
|
if (/^\s/.test(line)) {
|
|
1113
1119
|
extraLines.push(line);
|
|
@@ -1119,7 +1125,7 @@ function parseEntityFrontmatter(raw: string): {
|
|
|
1119
1125
|
continue;
|
|
1120
1126
|
}
|
|
1121
1127
|
const key = line.slice(0, colonIdx).trim();
|
|
1122
|
-
if (
|
|
1128
|
+
if (recognizedKeys[key] !== true) {
|
|
1123
1129
|
extraLines.push(line);
|
|
1124
1130
|
continue;
|
|
1125
1131
|
}
|
|
@@ -1413,7 +1419,11 @@ export function parseEntityFile(content: string, entitySchemas?: PluginConfig["e
|
|
|
1413
1419
|
* Writes the compiled-truth + timeline format while remaining parse-compatible
|
|
1414
1420
|
* with the legacy in-memory `summary` and `facts` fields.
|
|
1415
1421
|
*/
|
|
1416
|
-
export function serializeEntityFile(
|
|
1422
|
+
export function serializeEntityFile(
|
|
1423
|
+
entity: EntityFile,
|
|
1424
|
+
entitySchemas?: PluginConfig["entitySchemas"],
|
|
1425
|
+
okfType?: boolean,
|
|
1426
|
+
): string {
|
|
1417
1427
|
const synthesis = entity.synthesis || entity.summary || "";
|
|
1418
1428
|
const created = entity.created?.trim() || entity.updated || new Date().toISOString();
|
|
1419
1429
|
const updated = entity.updated || created;
|
|
@@ -1457,7 +1467,10 @@ export function serializeEntityFile(entity: EntityFile, entitySchemas?: PluginCo
|
|
|
1457
1467
|
: [`synthesis_structured_fact_count: ${synthesisStructuredFactCount}`]),
|
|
1458
1468
|
...(synthesisStructuredFactDigest ? [`synthesis_structured_fact_digest: "${synthesisStructuredFactDigest}"`] : []),
|
|
1459
1469
|
`synthesis_version: ${synthesisVersion}`,
|
|
1460
|
-
...(
|
|
1470
|
+
...(okfType === false ? [] : [`type: ${okfTypeForEntityKind(entity.type)}`]),
|
|
1471
|
+
...(okfType === false
|
|
1472
|
+
? (entity.extraFrontmatterLines ?? [])
|
|
1473
|
+
: (entity.extraFrontmatterLines ?? []).filter((line) => !line.startsWith("type:"))),
|
|
1461
1474
|
"---",
|
|
1462
1475
|
"",
|
|
1463
1476
|
`# ${entity.name}`,
|
|
@@ -2261,6 +2274,24 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
2261
2274
|
StorageManager.scopedCacheInvalidationByDir.set(memoryDir, enabled !== false);
|
|
2262
2275
|
}
|
|
2263
2276
|
|
|
2277
|
+
/** OKF `type` emission gate registrations per memory dir (issue #1946). */
|
|
2278
|
+
private static readonly okfConformanceByDir = new Map<string, boolean>();
|
|
2279
|
+
|
|
2280
|
+
/** Register the OKF conformance gate for a memory dir. Unregistered dirs default to
|
|
2281
|
+
* conformance-on; namespace child dirs (<memoryDir>/namespaces/<tok>) inherit the
|
|
2282
|
+
* nearest registered ancestor. Only an explicit `false` disables. */
|
|
2283
|
+
static setOkfConformanceDefault(memoryDir: string, enabled: boolean | undefined): void {
|
|
2284
|
+
StorageManager.okfConformanceByDir.set(memoryDir, enabled !== false);
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
okfConformanceEnabled(): boolean {
|
|
2288
|
+
for (let dir = this.baseDir; ; dir = path.dirname(dir)) {
|
|
2289
|
+
const registered = StorageManager.okfConformanceByDir.get(dir);
|
|
2290
|
+
if (registered !== undefined) return registered;
|
|
2291
|
+
if (dir === path.dirname(dir)) return true;
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2264
2295
|
/**
|
|
2265
2296
|
* The LIVE class object of this instance (issue #1809 review of the
|
|
2266
2297
|
* storage decomposition): extracted store modules must read/write the
|
|
@@ -2648,6 +2679,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
2648
2679
|
return this.writeStorageSecureFile(target, content);
|
|
2649
2680
|
}
|
|
2650
2681
|
protected writeStorageSecureFile(filePath: string, content: string | Buffer, forceEncrypt = false): Promise<void> {
|
|
2682
|
+
assertNotOkfReservedBasename(filePath);
|
|
2651
2683
|
const writeKey = this.resolveWriteKey(forceEncrypt);
|
|
2652
2684
|
return writeMaybeEncryptedFile(filePath, content, writeKey, {}, this.baseDir).then(() => {
|
|
2653
2685
|
// No manual sniff-cache update needed (issue #1909 round 10): this rewrite
|
|
@@ -3577,7 +3609,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
3577
3609
|
const completionFingerprint = await runLegacyEntityCanonicalIdMigration(
|
|
3578
3610
|
this as unknown as EntityCanonicalIdMigrationHost,
|
|
3579
3611
|
(content) => parseEntityFile(content, this.entitySchemas),
|
|
3580
|
-
(entity) => serializeEntityFile(entity, this.entitySchemas),
|
|
3612
|
+
(entity) => serializeEntityFile(entity, this.entitySchemas, this.okfConformanceEnabled()),
|
|
3581
3613
|
createMemoryEntityRefSerializer(serializeFrontmatter)
|
|
3582
3614
|
);
|
|
3583
3615
|
return completionFingerprint;
|
|
@@ -3659,6 +3691,13 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
3659
3691
|
}) ?? null
|
|
3660
3692
|
);
|
|
3661
3693
|
}
|
|
3694
|
+
|
|
3695
|
+
/** Derive the inert OKF `type` at the serialization choke point when conformance is on
|
|
3696
|
+
* and the parsed frontmatter carried none (issue #1946). Never touches `category`. */
|
|
3697
|
+
private withOkfType(fm: MemoryFrontmatter): MemoryFrontmatter {
|
|
3698
|
+
if (this.okfConformanceEnabled() && fm.type === undefined) fm.type = okfTypeForMemory(fm);
|
|
3699
|
+
return fm;
|
|
3700
|
+
}
|
|
3662
3701
|
async writeMemory(
|
|
3663
3702
|
category: MemoryCategory,
|
|
3664
3703
|
content: string,
|
|
@@ -3812,7 +3851,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
3812
3851
|
};
|
|
3813
3852
|
await applyTombstoneGate();
|
|
3814
3853
|
|
|
3815
|
-
const fileContent = `${serializeFrontmatter(fm)}\n\n${sanitized.text}\n`;
|
|
3854
|
+
const fileContent = `${serializeFrontmatter(this.withOkfType(fm))}\n\n${sanitized.text}\n`;
|
|
3816
3855
|
|
|
3817
3856
|
const filePath = await this.resolveCategoryWritePath(category, id, today);
|
|
3818
3857
|
const persistFile = async (): Promise<MemoryFile | null> => {
|
|
@@ -3837,7 +3876,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
3837
3876
|
await applyTombstoneGate();
|
|
3838
3877
|
await this.writeTombstoneBlockedMemory(
|
|
3839
3878
|
filePath,
|
|
3840
|
-
`${serializeFrontmatter(fm)}\n\n${sanitized.text}\n`,
|
|
3879
|
+
`${serializeFrontmatter(this.withOkfType(fm))}\n\n${sanitized.text}\n`,
|
|
3841
3880
|
fm,
|
|
3842
3881
|
sanitized.text,
|
|
3843
3882
|
async () => this.invalidateAllMemoriesCache()
|
|
@@ -4172,7 +4211,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
4172
4211
|
return "";
|
|
4173
4212
|
}
|
|
4174
4213
|
const filePath = path.join(dir, `${id}.md`);
|
|
4175
|
-
await this.writeStorageSecureFile(filePath, `${serializeFrontmatter(fm)}\n\n${sanitized.text}\n`);
|
|
4214
|
+
await this.writeStorageSecureFile(filePath, `${serializeFrontmatter(this.withOkfType(fm))}\n\n${sanitized.text}\n`);
|
|
4176
4215
|
const actor =
|
|
4177
4216
|
typeof options.actor === "string" && options.actor.length > 0 ? options.actor : "storage.writeArtifact";
|
|
4178
4217
|
await this.appendGeneratedMemoryLifecycleEventFailOpen("storage.writeArtifact", {
|
|
@@ -4225,7 +4264,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
4225
4264
|
|
|
4226
4265
|
async readProfile(): Promise<string> {
|
|
4227
4266
|
try {
|
|
4228
|
-
return await readMaybeEncryptedFile(this.profilePath, this._secureStoreKey, this.baseDir);
|
|
4267
|
+
return stripOkfProfileFrontmatter(await readMaybeEncryptedFile(this.profilePath, this._secureStoreKey, this.baseDir));
|
|
4229
4268
|
} catch (error) {
|
|
4230
4269
|
if (error instanceof SecureStoreLockedError) {
|
|
4231
4270
|
throw error;
|
|
@@ -4236,7 +4275,12 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
4236
4275
|
}
|
|
4237
4276
|
|
|
4238
4277
|
async writeProfile(content: string): Promise<void> {
|
|
4239
|
-
const
|
|
4278
|
+
const timestamp = new Date().toISOString();
|
|
4279
|
+
const stampedContent = withOkfProfileFrontmatter(
|
|
4280
|
+
renderProfileWithLastUpdated(content, timestamp),
|
|
4281
|
+
timestamp,
|
|
4282
|
+
this.okfConformanceEnabled(),
|
|
4283
|
+
);
|
|
4240
4284
|
await this.ensureDirectories();
|
|
4241
4285
|
await this.snapshotBeforeWrite(this.profilePath, "consolidation");
|
|
4242
4286
|
await this.writeStorageSecureFile(this.profilePath, stampedContent);
|
|
@@ -4912,6 +4956,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
4912
4956
|
return path.join(root, dir, this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
4913
4957
|
}
|
|
4914
4958
|
private async writeMemoryFileAtomic(targetPath: string, memory: MemoryFile): Promise<void> {
|
|
4959
|
+
assertNotOkfReservedBasename(targetPath);
|
|
4915
4960
|
// Whole-record rewrite (tier moves) — #2213. Repair, not just detect:
|
|
4916
4961
|
// the source is unlinked after the move, so a mapping parked across this
|
|
4917
4962
|
// write would strand the moved copy with nothing left to reconcile from.
|
|
@@ -4921,7 +4966,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
4921
4966
|
const persist = (): Promise<void> =>
|
|
4922
4967
|
writeMaybeEncryptedFile(
|
|
4923
4968
|
targetPath,
|
|
4924
|
-
`${serializeFrontmatter(frontmatter)}\n\n${memory.content}\n`,
|
|
4969
|
+
`${serializeFrontmatter(this.withOkfType(frontmatter))}\n\n${memory.content}\n`,
|
|
4925
4970
|
this.resolveWriteKey(),
|
|
4926
4971
|
{},
|
|
4927
4972
|
this.baseDir
|
|
@@ -5070,7 +5115,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
5070
5115
|
},
|
|
5071
5116
|
refIdsAtWrite
|
|
5072
5117
|
);
|
|
5073
|
-
const fileContent = `${serializeFrontmatter(updatedFm)}\n\n${current.content}\n`;
|
|
5118
|
+
const fileContent = `${serializeFrontmatter(this.withOkfType(updatedFm))}\n\n${current.content}\n`;
|
|
5074
5119
|
const destPath = path.join(destDir, path.basename(current.path));
|
|
5075
5120
|
// Snapshot a pre-existing destination (retried archive) so a repair
|
|
5076
5121
|
// failure restores it instead of deleting the only archived copy (§14).
|
|
@@ -5260,7 +5305,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
5260
5305
|
if (!sanitized.clean) {
|
|
5261
5306
|
log.warn(`updated memory content sanitized for ${memory.frontmatter.id}; violations=${sanitized.violations.join(", ")}`);
|
|
5262
5307
|
}
|
|
5263
|
-
const fileContent = `${serializeFrontmatter(updated)}\n\n${sanitized.text}\n`;
|
|
5308
|
+
const fileContent = `${serializeFrontmatter(this.withOkfType(updated))}\n\n${sanitized.text}\n`;
|
|
5264
5309
|
await this.writeTombstoneBlockedUpdate(memory, fileContent, updated, sanitized.text, async () => {
|
|
5265
5310
|
this.invalidateAllMemoriesCache();
|
|
5266
5311
|
if (this.isColdOrArchiveTierPath(memory.path)) this.invalidateColdMemoriesCache();
|
|
@@ -5350,7 +5395,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
5350
5395
|
const refIds = typeof updated.entityRef === "string" ? resolveIds : null;
|
|
5351
5396
|
const afterStatus = updated.status ?? "active";
|
|
5352
5397
|
|
|
5353
|
-
const fileContent = `${serializeFrontmatter(updated)}\n\n${memory.content}\n`;
|
|
5398
|
+
const fileContent = `${serializeFrontmatter(this.withOkfType(updated))}\n\n${memory.content}\n`;
|
|
5354
5399
|
await this.writeTombstoneBlockedFrontmatter(memory, fileContent, updated, async () => {
|
|
5355
5400
|
this.invalidateAllMemoriesCache();
|
|
5356
5401
|
// Rebuild the blocked index from the post-write cold-tier cache.
|
|
@@ -6038,11 +6083,12 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
6038
6083
|
await mkdir(this.questionsDir, { recursive: true });
|
|
6039
6084
|
|
|
6040
6085
|
const id = this.generateId("q");
|
|
6041
|
-
const frontmatter = {
|
|
6086
|
+
const frontmatter: Record<string, unknown> = {
|
|
6042
6087
|
id,
|
|
6043
6088
|
created: new Date().toISOString(),
|
|
6044
6089
|
priority,
|
|
6045
6090
|
resolved: false,
|
|
6091
|
+
...(this.okfConformanceEnabled() ? { type: OKF_QUESTION_TYPE } : {}),
|
|
6046
6092
|
};
|
|
6047
6093
|
|
|
6048
6094
|
const content = `---\n${Object.entries(frontmatter)
|
|
@@ -6076,41 +6122,8 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
6076
6122
|
StorageManager.questionsCache.delete(this.questionsDir);
|
|
6077
6123
|
}
|
|
6078
6124
|
|
|
6079
|
-
private parseQuestionFile(
|
|
6080
|
-
raw
|
|
6081
|
-
filePath: string
|
|
6082
|
-
): {
|
|
6083
|
-
id: string;
|
|
6084
|
-
question: string;
|
|
6085
|
-
context: string;
|
|
6086
|
-
priority: number;
|
|
6087
|
-
resolved: boolean;
|
|
6088
|
-
created: string;
|
|
6089
|
-
filePath: string;
|
|
6090
|
-
} | null {
|
|
6091
|
-
const match = raw.match(/^---\n([\s\S]*?)\n---\n\n([\s\S]*)$/);
|
|
6092
|
-
if (!match) return null;
|
|
6093
|
-
|
|
6094
|
-
const frontmatterStr = match[1];
|
|
6095
|
-
const body = match[2].trim();
|
|
6096
|
-
|
|
6097
|
-
// Parse frontmatter
|
|
6098
|
-
const id = this.extractFrontmatterValue(frontmatterStr, "id") ?? path.basename(filePath, ".md");
|
|
6099
|
-
const created = this.extractFrontmatterValue(frontmatterStr, "created") ?? "";
|
|
6100
|
-
const priority = parseFloat(this.extractFrontmatterValue(frontmatterStr, "priority") ?? "0.5");
|
|
6101
|
-
const resolved = this.extractFrontmatterValue(frontmatterStr, "resolved") === "true";
|
|
6102
|
-
|
|
6103
|
-
// Extract question and context from body
|
|
6104
|
-
const contextMatch = body.match(/\*\*Context:\*\*\s*(.*)/);
|
|
6105
|
-
const question = contextMatch ? body.slice(0, contextMatch.index).trim() : body;
|
|
6106
|
-
const context = contextMatch ? contextMatch[1].trim() : "";
|
|
6107
|
-
|
|
6108
|
-
return { id, question, context, priority, resolved, created, filePath };
|
|
6109
|
-
}
|
|
6110
|
-
|
|
6111
|
-
private extractFrontmatterValue(frontmatter: string, key: string): string | null {
|
|
6112
|
-
const match = frontmatter.match(new RegExp(`^${key}:\\s*"?([^"\\n]*)"?`, "m"));
|
|
6113
|
-
return match ? match[1] : null;
|
|
6125
|
+
private parseQuestionFile(raw: string, filePath: string) {
|
|
6126
|
+
return parseQuestionFileText(raw, filePath);
|
|
6114
6127
|
}
|
|
6115
6128
|
|
|
6116
6129
|
async resolveQuestion(id: string): Promise<boolean> {
|
|
@@ -6534,7 +6547,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
6534
6547
|
{ ...current.frontmatter, accessCount: entry.newCount, lastAccessed: entry.lastAccessed },
|
|
6535
6548
|
rowIds
|
|
6536
6549
|
);
|
|
6537
|
-
const fileContent = `${serializeFrontmatter(newFm)}\n\n${current.content}\n`;
|
|
6550
|
+
const fileContent = `${serializeFrontmatter(this.withOkfType(newFm))}\n\n${current.content}\n`;
|
|
6538
6551
|
await this.writeTombstoneBlockedFrontmatter(current, fileContent, newFm);
|
|
6539
6552
|
if (typeof current.frontmatter.entityRef === "string") {
|
|
6540
6553
|
await this.entityRefRepair.repair(
|
|
@@ -6855,7 +6868,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
6855
6868
|
};
|
|
6856
6869
|
|
|
6857
6870
|
const filePath = await this.resolveCategoryWritePath(category, id, today);
|
|
6858
|
-
const fileContent = `${serializeFrontmatter(fm)}\n\n${sanitized.text}\n`;
|
|
6871
|
+
const fileContent = `${serializeFrontmatter(this.withOkfType(fm))}\n\n${sanitized.text}\n`;
|
|
6859
6872
|
|
|
6860
6873
|
const written = await this.writeTombstoneBlockedChunk(
|
|
6861
6874
|
filePath,
|
|
@@ -6999,7 +7012,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
6999
7012
|
},
|
|
7000
7013
|
refIdsAtWrite
|
|
7001
7014
|
);
|
|
7002
|
-
const fileContent = `${serializeFrontmatter(updatedFm)}\n\n${current.content}\n`;
|
|
7015
|
+
const fileContent = `${serializeFrontmatter(this.withOkfType(updatedFm))}\n\n${current.content}\n`;
|
|
7003
7016
|
await this.writeTombstoneBlockedFrontmatter(current, fileContent, updatedFm);
|
|
7004
7017
|
if (this.isColdOrArchiveTierPath(current.path)) this.invalidateColdMemoriesCache();
|
|
7005
7018
|
if (typeof current.frontmatter.entityRef === "string") {
|
|
@@ -7147,7 +7160,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
7147
7160
|
{ ...current.frontmatter, status: "archived", archivedAt: now, updated: now },
|
|
7148
7161
|
rowIds
|
|
7149
7162
|
);
|
|
7150
|
-
const fileContent = `${serializeFrontmatter(updatedFm)}\n\n${current.content}\n`;
|
|
7163
|
+
const fileContent = `${serializeFrontmatter(this.withOkfType(updatedFm))}\n\n${current.content}\n`;
|
|
7151
7164
|
await this.writeTombstoneBlockedFrontmatter(current, fileContent, updatedFm);
|
|
7152
7165
|
if (typeof current.frontmatter.entityRef === "string") {
|
|
7153
7166
|
await this.entityRefRepair.repair(
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { BoundedJsonlStateConfig } from "./bounded-jsonl-state.js";
|
|
2
2
|
import type { MeetingsConfig } from "./meetings/types.js";
|
|
3
3
|
import type { LocationConfig } from "./location/types.js";
|
|
4
|
+
import type { OkfConfig } from "./okf/config.js";
|
|
4
5
|
import type { ActivityConfig } from "./activity/types.js";
|
|
5
6
|
import type { WearablesConfig } from "./wearables/types.js";
|
|
6
7
|
import type { ExtractionLivenessConfig } from "./extraction-liveness.js";
|
|
@@ -1227,17 +1228,13 @@ export interface PluginConfig extends BoundedJsonlStateConfig, SecurityConfig {
|
|
|
1227
1228
|
converge: ConvergeConfig;
|
|
1228
1229
|
/** Claim-level provenance spans (#1575); see `ProvenanceConfig` for defaults. */
|
|
1229
1230
|
provenance: ProvenanceConfig;
|
|
1230
|
-
/**
|
|
1231
|
-
* Wearable transcript ingestion (Limitless / Bee / Omi connectors).
|
|
1232
|
-
* Disabled by default; see docs/wearables.md.
|
|
1233
|
-
*/
|
|
1234
1231
|
wearables: WearablesConfig;
|
|
1235
1232
|
activity: ActivityConfig;
|
|
1236
1233
|
meetings: MeetingsConfig;
|
|
1237
1234
|
location: LocationConfig;
|
|
1235
|
+
okf: OkfConfig;
|
|
1238
1236
|
/**
|
|
1239
1237
|
* At-rest encryption configuration (issue #690 PR 3/4).
|
|
1240
|
-
*
|
|
1241
1238
|
* When `secureStoreEnabled` is true, `StorageManager` reads and
|
|
1242
1239
|
* writes memory files through the `secure-fs` encryption layer.
|
|
1243
1240
|
* The store must be unlocked via `remnic secure-store unlock` before
|
|
@@ -2808,6 +2805,8 @@ export interface MemoryFrontmatter extends SourceConnectorProvenance, OriginMeta
|
|
|
2808
2805
|
toolScoped?: true;
|
|
2809
2806
|
id: string;
|
|
2810
2807
|
category: MemoryCategory;
|
|
2808
|
+
/** OKF v0.1 interop metadata (issue #1946). Inert: presentation only, never overrides `category`. */
|
|
2809
|
+
type?: string;
|
|
2811
2810
|
created: string;
|
|
2812
2811
|
updated: string;
|
|
2813
2812
|
source: string;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input-validation + rendering helpers for the `remnic who-knows` CLI
|
|
3
|
+
* command (issue #2057). Extracted so validation paths can be unit-tested
|
|
4
|
+
* without booting an orchestrator (same pattern as `recall-xray-cli.ts`).
|
|
5
|
+
*
|
|
6
|
+
* Rules 14 + 51: bare `--limit`, non-integer or out-of-range values, and an
|
|
7
|
+
* empty topic throw listed-options errors — never silent defaults.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
validateWhoKnowsInput,
|
|
12
|
+
WHO_KNOWS_DEFAULT_LIMIT,
|
|
13
|
+
WHO_KNOWS_MAX_LIMIT,
|
|
14
|
+
type WhoKnowsResult,
|
|
15
|
+
} from "./who-knows.js";
|
|
16
|
+
|
|
17
|
+
export interface ParsedWhoKnowsCliOptions {
|
|
18
|
+
topic: string;
|
|
19
|
+
limit: number;
|
|
20
|
+
namespace?: string;
|
|
21
|
+
json: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Split raw argv into the positional topic and a flag bag. Value flags error when bare. */
|
|
25
|
+
export function extractWhoKnowsRawArgs(rest: string[]): {
|
|
26
|
+
topic: string;
|
|
27
|
+
options: Record<string, unknown>;
|
|
28
|
+
} {
|
|
29
|
+
const VALUE_FLAGS: Record<string, true> = { "--limit": true, "--namespace": true };
|
|
30
|
+
const positional: string[] = [];
|
|
31
|
+
const options: Record<string, unknown> = {};
|
|
32
|
+
for (let i = 0; i < rest.length; i++) {
|
|
33
|
+
const token = rest[i];
|
|
34
|
+
if (token.startsWith("--")) {
|
|
35
|
+
if (token === "--json") {
|
|
36
|
+
options.json = true;
|
|
37
|
+
} else if (VALUE_FLAGS[token]) {
|
|
38
|
+
const value = rest[i + 1];
|
|
39
|
+
if (value === undefined || value.startsWith("--")) {
|
|
40
|
+
throw new Error(`who-knows: ${token} expects a value`);
|
|
41
|
+
}
|
|
42
|
+
options[token.slice(2)] = value;
|
|
43
|
+
i += 1;
|
|
44
|
+
} else {
|
|
45
|
+
throw new Error(`who-knows: unknown option ${token} (expected --limit, --namespace, or --json)`);
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
positional.push(token);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return { topic: positional.join(" ").trim(), options };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Validate the full option bag. Throws listed-options errors for bad input. */
|
|
55
|
+
export function parseWhoKnowsCliOptions(rawTopic: unknown, options: Record<string, unknown>): ParsedWhoKnowsCliOptions {
|
|
56
|
+
if (typeof rawTopic !== "string" || rawTopic.trim().length === 0) {
|
|
57
|
+
throw new Error("who-knows: topic is required and must be non-empty");
|
|
58
|
+
}
|
|
59
|
+
let limit = WHO_KNOWS_DEFAULT_LIMIT;
|
|
60
|
+
if (options.limit !== undefined) {
|
|
61
|
+
const parsed = typeof options.limit === "number" ? options.limit : Number(options.limit);
|
|
62
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > WHO_KNOWS_MAX_LIMIT) {
|
|
63
|
+
throw new Error(`who-knows: --limit expects an integer between 1 and ${WHO_KNOWS_MAX_LIMIT}`);
|
|
64
|
+
}
|
|
65
|
+
limit = parsed;
|
|
66
|
+
}
|
|
67
|
+
const namespace = typeof options.namespace === "string" && options.namespace.trim().length > 0
|
|
68
|
+
? options.namespace.trim()
|
|
69
|
+
: undefined;
|
|
70
|
+
validateWhoKnowsInput(rawTopic, limit);
|
|
71
|
+
return { topic: rawTopic.trim(), limit, namespace, json: options.json === true };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function renderWhoKnowsJson(result: WhoKnowsResult): string {
|
|
75
|
+
return JSON.stringify(result, null, 2);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function renderWhoKnowsText(result: WhoKnowsResult): string {
|
|
79
|
+
if (result.results.length === 0) {
|
|
80
|
+
return `who knows "${result.topic}": no evidence found`;
|
|
81
|
+
}
|
|
82
|
+
const lines = [`who knows "${result.topic}" (top ${result.results.length})`];
|
|
83
|
+
result.results.forEach((hit, index) => {
|
|
84
|
+
const name = hit.entityName || hit.entityId;
|
|
85
|
+
lines.push(`${index + 1}. ${name} [${hit.entityId}] — score ${hit.score.toFixed(4)} — ${hit.rationale}`);
|
|
86
|
+
for (const ref of hit.evidence) {
|
|
87
|
+
lines.push(` - ${ref.id} (${ref.path}) updated ${ref.updated}`);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
return lines.join("\n");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function renderWhoKnows(result: WhoKnowsResult, json: boolean): string {
|
|
94
|
+
return json ? renderWhoKnowsJson(result) : renderWhoKnowsText(result);
|
|
95
|
+
}
|
|
96
|
+
|