@remnic/core 9.69.47 → 9.69.49
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 +14 -14
- package/dist/access-admin-ops-surface.js +32 -30
- package/dist/access-authorization-probe.d.ts +14 -14
- package/dist/access-authorization-probe.js +33 -31
- package/dist/access-boundary.d.ts +14 -14
- package/dist/access-boundary.js +32 -30
- package/dist/access-cli.js +99 -98
- 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 +14 -14
- package/dist/access-extraction-force-flush.js +32 -30
- package/dist/access-health-types.d.ts +1 -1
- package/dist/access-http-briefing.d.ts +14 -14
- package/dist/access-http-briefing.js +33 -31
- package/dist/access-http-lcm-compaction.d.ts +14 -14
- package/dist/access-http-lifecycle-flush.d.ts +14 -14
- package/dist/access-http-offline-stream.d.ts +14 -14
- package/dist/access-http-query.d.ts +2 -2
- package/dist/access-http-query.js +34 -32
- package/dist/access-http.d.ts +15 -15
- package/dist/access-http.js +52 -50
- package/dist/access-identity-continuity-surface.d.ts +11 -11
- package/dist/access-identity-continuity-surface.js +32 -30
- package/dist/access-lcm-surface.d.ts +14 -14
- package/dist/access-lcm-surface.js +32 -30
- package/dist/access-mcp-shared-context-tools.d.ts +14 -14
- package/dist/access-mcp.d.ts +14 -14
- package/dist/access-mcp.js +42 -40
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-CetF9ziA.d.ts → access-namespace-preflight-DqRw_g-8.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +32 -30
- package/dist/access-observe-transcript.d.ts +11 -11
- package/dist/access-observe-write-category.d.ts +3 -3
- package/dist/access-observe-write-surface.d.ts +14 -14
- package/dist/access-observe-write-surface.js +32 -30
- package/dist/access-offline-manifest.d.ts +11 -11
- package/dist/access-operations-batch.js +34 -32
- package/dist/access-operations.d.ts +14 -14
- package/dist/access-operations.js +41 -39
- package/dist/access-recall-concurrency.d.ts +14 -14
- package/dist/access-recall-concurrency.js +32 -30
- package/dist/access-recall-response.d.ts +14 -14
- package/dist/access-recall-response.js +32 -30
- package/dist/access-recall-surface.d.ts +14 -14
- package/dist/access-recall-surface.js +32 -30
- package/dist/access-schema.d.ts +114 -114
- package/dist/{access-service-BXYrJ3pO.d.ts → access-service-70VHaltr.d.ts} +73 -73
- package/dist/access-service-helpers.d.ts +14 -14
- package/dist/access-service.d.ts +14 -14
- package/dist/access-service.js +32 -30
- package/dist/access-surface-catalog.d.ts +14 -14
- package/dist/access-surface-catalog.js +34 -32
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/access-wearables-meetings-surface.d.ts +4 -4
- 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/activity/digest.d.ts +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/background-generation.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 +11 -11
- package/dist/briefing-window.d.ts +2 -2
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +11 -11
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer-turn-helpers.d.ts +1 -1
- package/dist/buffer.d.ts +2 -2
- package/dist/buffer.js +5 -5
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-Bns9zpl3.d.ts → catalog-Byi9prz9.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 +12 -12
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-DE4ZGH2N.js → chunk-2IVHOQRY.js} +8 -3
- package/dist/chunk-2IVHOQRY.js.map +1 -0
- package/dist/{chunk-MQT3WP3F.js → chunk-3MX4GWJO.js} +2 -2
- package/dist/{chunk-PXJ6HE2W.js → chunk-3RABJOGD.js} +2 -2
- package/dist/{chunk-V2XNMIAM.js → chunk-4WSR7MYV.js} +2 -2
- package/dist/{chunk-6A6HSXWV.js → chunk-5WIGM42T.js} +2 -2
- package/dist/{chunk-GGROFIYX.js → chunk-6DYCSSHN.js} +2 -2
- package/dist/{chunk-55XWRL6F.js → chunk-6VLOKESS.js} +2 -2
- package/dist/{chunk-OS4JVTHR.js → chunk-76RTJ533.js} +3 -3
- package/dist/{chunk-4LPIVP77.js → chunk-7VTQETLT.js} +2 -2
- package/dist/{chunk-X2NFFBTO.js → chunk-A7GQBJP5.js} +4 -4
- package/dist/{chunk-G2SJRFGP.js → chunk-AIKUSXIS.js} +6 -6
- package/dist/{chunk-MNG536IS.js → chunk-AJLQH4RO.js} +13 -13
- package/dist/{chunk-XEHLYA5Z.js → chunk-AOMVOC2E.js} +3 -3
- package/dist/{chunk-XXLH6KFO.js → chunk-BHXY5FXL.js} +2 -2
- package/dist/{chunk-PA67GXYJ.js → chunk-C3YEB7CR.js} +5 -5
- package/dist/{chunk-SK6HEQTW.js → chunk-DHTOYRDE.js} +2 -2
- package/dist/{chunk-WQW6KPVC.js → chunk-DNAD57VY.js} +1 -1
- package/dist/chunk-DNAD57VY.js.map +1 -0
- package/dist/{chunk-P3YNEMYY.js → chunk-E64HBW7M.js} +2 -2
- package/dist/{chunk-NMA7RQPR.js → chunk-EBLKS57G.js} +2 -2
- package/dist/{chunk-2QX65IEC.js → chunk-EHUUXLLA.js} +2 -2
- package/dist/{chunk-LYMJ36UI.js → chunk-EST3J4LX.js} +2 -2
- package/dist/{chunk-B6VDWDFN.js → chunk-EUP4AXIW.js} +2 -2
- package/dist/{chunk-XZUHXKM3.js → chunk-FLZJMXFV.js} +2 -2
- package/dist/{chunk-GXJSLNYO.js → chunk-FVRZDZ7J.js} +2 -2
- package/dist/{chunk-645WOU5I.js → chunk-H7BZBSP6.js} +4 -4
- package/dist/{chunk-2JFSQWFH.js → chunk-HIBNECBQ.js} +5 -5
- package/dist/{chunk-7ZNJN5WZ.js → chunk-IHOXK2I6.js} +55 -6
- package/dist/chunk-IHOXK2I6.js.map +1 -0
- package/dist/{chunk-QLCMOHRE.js → chunk-IIDXU2CY.js} +2 -2
- package/dist/{chunk-2NKY7OC6.js → chunk-IMJPJY7V.js} +2 -2
- package/dist/{chunk-JYXLW22X.js → chunk-JG4AP36X.js} +2 -2
- package/dist/{chunk-3RKVSECD.js → chunk-JI5Q6EOY.js} +7 -7
- package/dist/{chunk-XKHRNAK7.js → chunk-JIWZVOQM.js} +2 -2
- package/dist/{chunk-7YUX52XZ.js → chunk-JVM3CEGL.js} +3 -3
- package/dist/{chunk-QB4VXCFN.js → chunk-K26LFJE4.js} +2 -2
- package/dist/{chunk-Y5VT7BIT.js → chunk-K4KE5MYE.js} +2 -2
- package/dist/{chunk-TQSCR5DU.js → chunk-KG2OOAFF.js} +6 -6
- package/dist/{chunk-VV5GCNKG.js → chunk-KHLNIDWB.js} +2 -2
- package/dist/{chunk-LIAM7U2J.js → chunk-LE2UESGS.js} +2 -2
- package/dist/{chunk-YXWMZAAN.js → chunk-LLFMZYFS.js} +2 -2
- package/dist/{chunk-PPJLJD2D.js → chunk-LX32KV2C.js} +2 -2
- package/dist/{chunk-44BILQ7U.js → chunk-N57PUWUE.js} +39 -39
- package/dist/{chunk-V7IONNTJ.js → chunk-NDWBT2VV.js} +2 -2
- package/dist/{chunk-DRLZB3CN.js → chunk-OTGIAJQ2.js} +2 -2
- package/dist/{chunk-T3T5HTZZ.js → chunk-P36WML7L.js} +2 -2
- package/dist/{chunk-SJ7ZNUXB.js → chunk-PAQ7YGJY.js} +2 -2
- package/dist/{chunk-YOSLKZLZ.js → chunk-PSQRBCGR.js} +2 -2
- package/dist/{chunk-FGRJJBFO.js → chunk-PZHN7R35.js} +2 -2
- package/dist/{chunk-QMWKENNK.js → chunk-Q4AUIFUA.js} +4 -4
- package/dist/{chunk-CD7VTZIG.js → chunk-QQA6VTOY.js} +2 -2
- package/dist/{chunk-ROBGBT3D.js → chunk-RBHQA2UU.js} +50 -50
- package/dist/{chunk-HG74GEVY.js → chunk-RS53SDCA.js} +2 -2
- package/dist/{chunk-SS33RR4F.js → chunk-SKYYPVBW.js} +8 -8
- package/dist/{chunk-OSTXIFZW.js → chunk-SNOAFXKX.js} +38 -4
- package/dist/chunk-SNOAFXKX.js.map +1 -0
- package/dist/{chunk-EWBDJQ5Y.js → chunk-SYJZUVTN.js} +3 -3
- package/dist/{chunk-IO7K7GES.js → chunk-T3F2HWIG.js} +2 -2
- package/dist/{chunk-BMENHAJL.js → chunk-T3OLYUU6.js} +2 -2
- package/dist/{chunk-AS4YKT75.js → chunk-TUSY4KRE.js} +207 -44
- package/dist/chunk-TUSY4KRE.js.map +1 -0
- package/dist/{chunk-QGAKUOKU.js → chunk-U3ZRHNNG.js} +2 -2
- package/dist/{chunk-LIDJWAQV.js → chunk-UB4UVALS.js} +2 -2
- package/dist/chunk-UD6W67JM.js +260 -0
- package/dist/chunk-UD6W67JM.js.map +1 -0
- package/dist/{chunk-WYU66IVZ.js → chunk-UE7L4EDU.js} +3 -3
- package/dist/{chunk-I6IJDTRP.js → chunk-VBRS7Z3O.js} +2 -2
- package/dist/{chunk-EGOWY342.js → chunk-WGCASEEQ.js} +2 -2
- package/dist/{chunk-QKFYJVDG.js → chunk-WHSNLCRO.js} +2 -2
- package/dist/{chunk-JXLEQIJ7.js → chunk-XQFHKPNB.js} +7 -7
- package/dist/{chunk-NE45P3OF.js → chunk-YA5M7OC4.js} +2 -2
- package/dist/{chunk-WL3PGPGU.js → chunk-YKWWG3CM.js} +2 -2
- package/dist/{chunk-EZ25VE3G.js → chunk-YNDLCWXS.js} +4 -4
- package/dist/{chunk-MMQVWKFY.js → chunk-YOC3EEZH.js} +12 -12
- package/dist/{chunk-ZEIJQ4I3.js → chunk-Z2OKRO3E.js} +2 -2
- package/dist/{chunk-5KBI2MOC.js → chunk-ZDGSHXJU.js} +1 -1
- package/dist/{chunk-R4JTUTU6.js → chunk-ZYZW46HZ.js} +3 -3
- package/dist/{cli-B8YyIrPR.d.ts → cli-CdJiBilM.d.ts} +5 -5
- package/dist/cli.d.ts +16 -16
- package/dist/cli.js +71 -69
- package/dist/coding/export-okf-codegraph.d.ts +1 -1
- package/dist/coding/export-okf-codegraph.js +13 -13
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +12 -12
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -2
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +11 -11
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +11 -11
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +4 -4
- package/dist/converge-config.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +2 -2
- package/dist/convergence-refresh.js +13 -13
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/corpus-watermark.d.ts +1 -1
- package/dist/corpus-watermark.js +13 -13
- package/dist/cross-lingual-recall.d.ts +1 -1
- package/dist/dashboard-runtime.js +2 -2
- package/dist/day-summary.d.ts +1 -1
- package/dist/deep-recall-http-glue.d.ts +14 -14
- package/dist/deep-recall-mcp-tools.d.ts +14 -14
- package/dist/deep-recall-policy-llm.d.ts +2 -2
- package/dist/deep-recall-seeds.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-B-LvcDaq.d.ts → dependency-propagation-delivery-BgHy44WX.d.ts} +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/directory-sidecars.d.ts +87 -0
- package/dist/directory-sidecars.js +22 -0
- package/dist/directory-sidecars.js.map +1 -0
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-origin-fields.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +13 -13
- package/dist/entity-schema.d.ts +1 -1
- package/dist/episodic-context.d.ts +1 -1
- package/dist/eval-trajectory-contracts.d.ts +1 -1
- package/dist/eval-trajectory-store.d.ts +1 -1
- package/dist/eval-trajectory.d.ts +1 -1
- package/dist/event-order-recall.js +2 -2
- package/dist/explicit-capture.d.ts +11 -11
- package/dist/external-wiki-access.d.ts +14 -14
- package/dist/external-wiki-access.js +33 -31
- 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 +14 -14
- package/dist/extraction-error-classification.d.ts +1 -1
- package/dist/extraction-evidence-class.d.ts +1 -1
- package/dist/extraction-faithfulness.d.ts +2 -2
- package/dist/extraction-judge-telemetry.d.ts +2 -2
- package/dist/extraction-judge-training.d.ts +2 -2
- package/dist/extraction-judge.d.ts +2 -2
- 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-span-config.d.ts +1 -1
- package/dist/extraction-span-materialize.d.ts +1 -1
- package/dist/extraction-span-wire.d.ts +1 -1
- package/dist/extraction.d.ts +2 -2
- package/dist/extraction.js +15 -15
- package/dist/fallback-llm-codex-subscription.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/{generic-recall-paths-Bfc7zigS.d.ts → generic-recall-paths-BoueWXYr.d.ts} +1 -1
- package/dist/graph-append-error.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-jsonl.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/importers/test-utils.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +1 -1
- package/dist/{index-C7IA1DxB.d.ts → index-cwbrXoxe.d.ts} +3 -3
- package/dist/index.d.ts +719 -719
- package/dist/index.js +132 -127
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/engine.js +2 -2
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +4 -4
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/{local-llm-DH4tWtck.d.ts → local-llm-B0vd_rp9.d.ts} +1 -1
- package/dist/local-llm-helpers.d.ts +2 -2
- package/dist/local-llm.d.ts +2 -2
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/location/index.d.ts +5 -5
- package/dist/location/index.js +13 -13
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +11 -11
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +11 -11
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +12 -12
- package/dist/{maintenance-n6yeTQhR.d.ts → maintenance-DJgQkoLh.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +14 -14
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-browse-http-glue.d.ts +14 -14
- package/dist/memory-browse-mcp-tools.d.ts +14 -14
- package/dist/memory-browse-operations.js +33 -31
- package/dist/memory-browse.d.ts +1 -1
- package/dist/memory-browse.js +7 -5
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-controller.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-snapshot.d.ts +1 -1
- package/dist/memory-subject-cli.d.ts +14 -14
- package/dist/memory-subject.d.ts +14 -14
- 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 +6 -6
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +11 -11
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync-impression-drain.d.ts +1 -1
- package/dist/operator-doctor-corpus.d.ts +1 -1
- package/dist/operator-doctor-corpus.js +14 -14
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +21 -21
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +19 -19
- package/dist/{orchestrator-Cirjo3ZB.d.ts → orchestrator-Kx5zwNUm.d.ts} +10 -10
- package/dist/orchestrator.d.ts +11 -11
- package/dist/orchestrator.js +99 -98
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-DK79FrgH.d.ts → pipeline-9SYxxign.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/proactive-contention.d.ts +2 -2
- package/dist/provenance.d.ts +1 -1
- package/dist/{public-http-VB85y0ZH.d.ts → public-http-Bvol6Jr4.d.ts} +1 -1
- package/dist/{qmd-BT0ErlRS.d.ts → qmd-DjwuG9Xa.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-context-composition.d.ts +43 -3
- package/dist/recall-context-composition.js +5 -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-navigate-access.d.ts +1 -1
- package/dist/recall-navigate-access.js +2 -2
- package/dist/recall-navigate-disclosure.d.ts +1 -1
- package/dist/recall-navigate-disclosure.js +2 -2
- package/dist/recall-navigate.d.ts +1 -1
- package/dist/recall-navigate.js +2 -2
- package/dist/recall-navigation-http-glue.d.ts +14 -14
- package/dist/recall-navigation-mcp-tools.d.ts +14 -14
- package/dist/recall-navigation-operations.js +33 -31
- package/dist/recall-navigation-renderer.d.ts +1 -1
- package/dist/recall-navigation.d.ts +1 -1
- package/dist/recall-navigation.js +32 -30
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state-view-admission.d.ts +2 -2
- package/dist/recall-state-view-admission.js +8 -5
- package/dist/recall-state-view-anchors.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 +3 -3
- package/dist/retrieval-agents.d.ts +2 -2
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/salvage-envelope.d.ts +1 -1
- package/dist/schemas.d.ts +160 -160
- package/dist/{scope-profiles-BgPQx9iE.d.ts → scope-profiles-DPegZtRf.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +5 -5
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +9 -9
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-BrAWKVcm.d.ts → semantic-consolidation-DMzhKRYl.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +12 -12
- package/dist/semantic-rule-promotion.js +11 -11
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +11 -11
- package/dist/{service-CqHOTg87.d.ts → service-E99KuPvi.d.ts} +2 -2
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +7 -7
- package/dist/signal.d.ts +1 -1
- package/dist/source-agent-qualifier.d.ts +1 -1
- package/dist/source-agent-qualifier.js +14 -14
- package/dist/standup/build.js +11 -11
- package/dist/{storage-mD2YQ8_2.d.ts → storage-BS7ux8F7.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +10 -10
- package/dist/subject-config.d.ts +1 -1
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/support-passport/index.d.ts +17 -17
- package/dist/support-passport/index.js +35 -33
- package/dist/{tagging-CiAVA-ID.d.ts → tagging-BhOEcSXP.d.ts} +2 -2
- package/dist/temporal-supersession.d.ts +2 -2
- package/dist/temporal-timeline-recall.d.ts +1 -1
- package/dist/temporal-timeline-recall.js +2 -2
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +2 -2
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/export-okf.d.ts +1 -1
- package/dist/transfer/export-okf.js +11 -11
- package/dist/transfer/types.d.ts +78 -78
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-DgDaoY61.d.ts → types-DQ2H8gAC.d.ts} +19 -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 +11 -11
- package/dist/who-knows-cli.d.ts +14 -14
- package/dist/who-knows-cli.js +12 -12
- package/dist/who-knows.d.ts +14 -14
- package/dist/who-knows.js +11 -11
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/config.ts +4 -0
- package/src/directory-sidecars.test.ts +268 -0
- package/src/directory-sidecars.ts +383 -0
- package/src/experience/session-experience-config.ts +51 -0
- package/src/experience/session-experience-lifecycle.test.ts +139 -0
- package/src/experience/session-experience.test.ts +233 -0
- package/src/experience/session-experience.ts +240 -0
- package/src/orchestration/generic-recall-paths.ts +5 -1
- package/src/orchestration/session-context.ts +50 -0
- package/src/recall-context-composition.test.ts +66 -0
- package/src/recall-context-composition.ts +102 -2
- package/src/types.ts +3 -0
- package/dist/chunk-7ZNJN5WZ.js.map +0 -1
- package/dist/chunk-AS4YKT75.js.map +0 -1
- package/dist/chunk-DE4ZGH2N.js.map +0 -1
- package/dist/chunk-OSTXIFZW.js.map +0 -1
- package/dist/chunk-WQW6KPVC.js.map +0 -1
- /package/dist/{chunk-MQT3WP3F.js.map → chunk-3MX4GWJO.js.map} +0 -0
- /package/dist/{chunk-PXJ6HE2W.js.map → chunk-3RABJOGD.js.map} +0 -0
- /package/dist/{chunk-V2XNMIAM.js.map → chunk-4WSR7MYV.js.map} +0 -0
- /package/dist/{chunk-6A6HSXWV.js.map → chunk-5WIGM42T.js.map} +0 -0
- /package/dist/{chunk-GGROFIYX.js.map → chunk-6DYCSSHN.js.map} +0 -0
- /package/dist/{chunk-55XWRL6F.js.map → chunk-6VLOKESS.js.map} +0 -0
- /package/dist/{chunk-OS4JVTHR.js.map → chunk-76RTJ533.js.map} +0 -0
- /package/dist/{chunk-4LPIVP77.js.map → chunk-7VTQETLT.js.map} +0 -0
- /package/dist/{chunk-X2NFFBTO.js.map → chunk-A7GQBJP5.js.map} +0 -0
- /package/dist/{chunk-G2SJRFGP.js.map → chunk-AIKUSXIS.js.map} +0 -0
- /package/dist/{chunk-MNG536IS.js.map → chunk-AJLQH4RO.js.map} +0 -0
- /package/dist/{chunk-XEHLYA5Z.js.map → chunk-AOMVOC2E.js.map} +0 -0
- /package/dist/{chunk-XXLH6KFO.js.map → chunk-BHXY5FXL.js.map} +0 -0
- /package/dist/{chunk-PA67GXYJ.js.map → chunk-C3YEB7CR.js.map} +0 -0
- /package/dist/{chunk-SK6HEQTW.js.map → chunk-DHTOYRDE.js.map} +0 -0
- /package/dist/{chunk-P3YNEMYY.js.map → chunk-E64HBW7M.js.map} +0 -0
- /package/dist/{chunk-NMA7RQPR.js.map → chunk-EBLKS57G.js.map} +0 -0
- /package/dist/{chunk-2QX65IEC.js.map → chunk-EHUUXLLA.js.map} +0 -0
- /package/dist/{chunk-LYMJ36UI.js.map → chunk-EST3J4LX.js.map} +0 -0
- /package/dist/{chunk-B6VDWDFN.js.map → chunk-EUP4AXIW.js.map} +0 -0
- /package/dist/{chunk-XZUHXKM3.js.map → chunk-FLZJMXFV.js.map} +0 -0
- /package/dist/{chunk-GXJSLNYO.js.map → chunk-FVRZDZ7J.js.map} +0 -0
- /package/dist/{chunk-645WOU5I.js.map → chunk-H7BZBSP6.js.map} +0 -0
- /package/dist/{chunk-2JFSQWFH.js.map → chunk-HIBNECBQ.js.map} +0 -0
- /package/dist/{chunk-QLCMOHRE.js.map → chunk-IIDXU2CY.js.map} +0 -0
- /package/dist/{chunk-2NKY7OC6.js.map → chunk-IMJPJY7V.js.map} +0 -0
- /package/dist/{chunk-JYXLW22X.js.map → chunk-JG4AP36X.js.map} +0 -0
- /package/dist/{chunk-3RKVSECD.js.map → chunk-JI5Q6EOY.js.map} +0 -0
- /package/dist/{chunk-XKHRNAK7.js.map → chunk-JIWZVOQM.js.map} +0 -0
- /package/dist/{chunk-7YUX52XZ.js.map → chunk-JVM3CEGL.js.map} +0 -0
- /package/dist/{chunk-QB4VXCFN.js.map → chunk-K26LFJE4.js.map} +0 -0
- /package/dist/{chunk-Y5VT7BIT.js.map → chunk-K4KE5MYE.js.map} +0 -0
- /package/dist/{chunk-TQSCR5DU.js.map → chunk-KG2OOAFF.js.map} +0 -0
- /package/dist/{chunk-VV5GCNKG.js.map → chunk-KHLNIDWB.js.map} +0 -0
- /package/dist/{chunk-LIAM7U2J.js.map → chunk-LE2UESGS.js.map} +0 -0
- /package/dist/{chunk-YXWMZAAN.js.map → chunk-LLFMZYFS.js.map} +0 -0
- /package/dist/{chunk-PPJLJD2D.js.map → chunk-LX32KV2C.js.map} +0 -0
- /package/dist/{chunk-44BILQ7U.js.map → chunk-N57PUWUE.js.map} +0 -0
- /package/dist/{chunk-V7IONNTJ.js.map → chunk-NDWBT2VV.js.map} +0 -0
- /package/dist/{chunk-DRLZB3CN.js.map → chunk-OTGIAJQ2.js.map} +0 -0
- /package/dist/{chunk-T3T5HTZZ.js.map → chunk-P36WML7L.js.map} +0 -0
- /package/dist/{chunk-SJ7ZNUXB.js.map → chunk-PAQ7YGJY.js.map} +0 -0
- /package/dist/{chunk-YOSLKZLZ.js.map → chunk-PSQRBCGR.js.map} +0 -0
- /package/dist/{chunk-FGRJJBFO.js.map → chunk-PZHN7R35.js.map} +0 -0
- /package/dist/{chunk-QMWKENNK.js.map → chunk-Q4AUIFUA.js.map} +0 -0
- /package/dist/{chunk-CD7VTZIG.js.map → chunk-QQA6VTOY.js.map} +0 -0
- /package/dist/{chunk-ROBGBT3D.js.map → chunk-RBHQA2UU.js.map} +0 -0
- /package/dist/{chunk-HG74GEVY.js.map → chunk-RS53SDCA.js.map} +0 -0
- /package/dist/{chunk-SS33RR4F.js.map → chunk-SKYYPVBW.js.map} +0 -0
- /package/dist/{chunk-EWBDJQ5Y.js.map → chunk-SYJZUVTN.js.map} +0 -0
- /package/dist/{chunk-IO7K7GES.js.map → chunk-T3F2HWIG.js.map} +0 -0
- /package/dist/{chunk-BMENHAJL.js.map → chunk-T3OLYUU6.js.map} +0 -0
- /package/dist/{chunk-QGAKUOKU.js.map → chunk-U3ZRHNNG.js.map} +0 -0
- /package/dist/{chunk-LIDJWAQV.js.map → chunk-UB4UVALS.js.map} +0 -0
- /package/dist/{chunk-WYU66IVZ.js.map → chunk-UE7L4EDU.js.map} +0 -0
- /package/dist/{chunk-I6IJDTRP.js.map → chunk-VBRS7Z3O.js.map} +0 -0
- /package/dist/{chunk-EGOWY342.js.map → chunk-WGCASEEQ.js.map} +0 -0
- /package/dist/{chunk-QKFYJVDG.js.map → chunk-WHSNLCRO.js.map} +0 -0
- /package/dist/{chunk-JXLEQIJ7.js.map → chunk-XQFHKPNB.js.map} +0 -0
- /package/dist/{chunk-NE45P3OF.js.map → chunk-YA5M7OC4.js.map} +0 -0
- /package/dist/{chunk-WL3PGPGU.js.map → chunk-YKWWG3CM.js.map} +0 -0
- /package/dist/{chunk-EZ25VE3G.js.map → chunk-YNDLCWXS.js.map} +0 -0
- /package/dist/{chunk-MMQVWKFY.js.map → chunk-YOC3EEZH.js.map} +0 -0
- /package/dist/{chunk-ZEIJQ4I3.js.map → chunk-Z2OKRO3E.js.map} +0 -0
- /package/dist/{chunk-5KBI2MOC.js.map → chunk-ZDGSHXJU.js.map} +0 -0
- /package/dist/{chunk-R4JTUTU6.js.map → chunk-ZYZW46HZ.js.map} +0 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @remnic/core — per-directory abstract/overview sidecars (issue #2977).
|
|
3
|
+
*
|
|
4
|
+
* One derived `overview.md` per memory directory (category roots and every
|
|
5
|
+
* directory beneath them, including `namespaces/<ns>/` subtrees), rendered
|
|
6
|
+
* bottom-up from existing memory content:
|
|
7
|
+
*
|
|
8
|
+
* - the ABSTRACT is a single line (<=256 chars) composed from child titles;
|
|
9
|
+
* - the OVERVIEW body lists one preview line per child memory and embeds
|
|
10
|
+
* each child DIRECTORY's abstract, so a parent summarizes its subtree
|
|
11
|
+
* without embedding full child overviews.
|
|
12
|
+
*
|
|
13
|
+
* Determinism: no LLM, no embeddings. Content is assembled with the same
|
|
14
|
+
* preview machinery the OKF index files use (`normalizeProjectionPreview`).
|
|
15
|
+
*
|
|
16
|
+
* Invalidation: each sidecar stores a content-free fingerprint of its subtree
|
|
17
|
+
* (child name|size|mtime for files, recursive fingerprints for child dirs).
|
|
18
|
+
* Any add/edit/delete anywhere below a directory changes its fingerprint, so
|
|
19
|
+
* `loadDirectorySidecar` can detect staleness with `readdir`+`stat` alone and
|
|
20
|
+
* refresh without reading child memory files first. Eager regeneration runs
|
|
21
|
+
* through {@link runDirectorySidecarMaintenance}; lazy refresh on read covers
|
|
22
|
+
* direct-write paths that bypass scheduled maintenance (Gotcha #43).
|
|
23
|
+
*
|
|
24
|
+
* Isolation: sidecars are derived artifacts, excluded from generic recall via
|
|
25
|
+
* `isGenericRecallExcludedPath` (basename match, the same tradeoff OKF makes
|
|
26
|
+
* for `index.md`/`log.md`) while staying full-text searchable. Files at the
|
|
27
|
+
* sidecar path WITHOUT the marker are user content: never overwritten, never
|
|
28
|
+
* removed.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import { createHash } from "node:crypto";
|
|
32
|
+
import { lstatSync, readFileSync, readdirSync, statSync, unlinkSync } from "node:fs";
|
|
33
|
+
import path from "node:path";
|
|
34
|
+
|
|
35
|
+
import { writeFileAtomically } from "./maintenance/atomic-file.js";
|
|
36
|
+
import { normalizeProjectionPreview } from "./memory-projection-format.js";
|
|
37
|
+
import { OKF_RESERVED_BASENAMES } from "./okf/type-mapping.js";
|
|
38
|
+
import { RECALL_FALLBACK_DIRS } from "./utils/category-dir.js";
|
|
39
|
+
|
|
40
|
+
export const DIRECTORY_SIDECAR_BASENAME = "overview.md";
|
|
41
|
+
export const DIRECTORY_SIDECAR_MARKER = "<!-- remnic-directory-sidecar -->";
|
|
42
|
+
|
|
43
|
+
const ABSTRACT_MAX_CHARS = 256;
|
|
44
|
+
const OVERVIEW_MAX_CHARS = 4000;
|
|
45
|
+
const DEFAULT_QUERY_LIMIT = 5;
|
|
46
|
+
|
|
47
|
+
/** Basenames never treated as child memories (ours plus OKF's reserved ones). */
|
|
48
|
+
const RESERVED_CHILD_BASENAMES: Readonly<Record<string, true>> = Object.freeze({
|
|
49
|
+
...OKF_RESERVED_BASENAMES,
|
|
50
|
+
[DIRECTORY_SIDECAR_BASENAME]: true,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export interface DirectorySidecar {
|
|
54
|
+
/** Absolute directory the sidecar describes. */
|
|
55
|
+
readonly dir: string;
|
|
56
|
+
/** Single-line L0 abstract (<=256 chars). */
|
|
57
|
+
readonly abstract: string;
|
|
58
|
+
/** Abstract plus the per-child preview body (<=4000 chars). */
|
|
59
|
+
readonly overview: string;
|
|
60
|
+
/** Number of memory `.md` children in this directory. */
|
|
61
|
+
readonly childCount: number;
|
|
62
|
+
/** False when the stored fingerprint no longer matches the subtree. */
|
|
63
|
+
readonly fresh: boolean;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface DirectorySidecarMatch extends DirectorySidecar {
|
|
67
|
+
readonly score: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface DirectorySidecarReport {
|
|
71
|
+
written: string[];
|
|
72
|
+
removed: string[];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
interface ParsedSidecar {
|
|
76
|
+
abstract: string;
|
|
77
|
+
overview: string;
|
|
78
|
+
childCount: number;
|
|
79
|
+
fingerprint: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function listEntries(dir: string) {
|
|
83
|
+
try {
|
|
84
|
+
return readdirSync(dir, { withFileTypes: true });
|
|
85
|
+
} catch {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Root check that refuses symlinks (fs-boundary rule, PRs #1938/#1999). */
|
|
91
|
+
function isRealDirectory(entryPath: string): boolean {
|
|
92
|
+
try {
|
|
93
|
+
const stats = lstatSync(entryPath);
|
|
94
|
+
return !stats.isSymbolicLink() && stats.isDirectory();
|
|
95
|
+
} catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function memoryChildren(dir: string): string[] {
|
|
101
|
+
// Dirent.isFile() is false for symlinks, so a linked memory never enters the corpus.
|
|
102
|
+
return listEntries(dir)
|
|
103
|
+
.filter((entry) => entry.isFile() && !RESERVED_CHILD_BASENAMES[entry.name] && entry.name.endsWith(".md"))
|
|
104
|
+
.map((entry) => entry.name)
|
|
105
|
+
.sort((a, b) => a.localeCompare(b));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function directoryChildren(dir: string): string[] {
|
|
109
|
+
// Dirent.isDirectory() is false for symlinks (fs-boundary rule, PRs #1938/#1999).
|
|
110
|
+
return listEntries(dir)
|
|
111
|
+
.filter((entry) => entry.isDirectory())
|
|
112
|
+
.map((entry) => entry.name)
|
|
113
|
+
.sort((a, b) => a.localeCompare(b));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Content-free subtree fingerprint: sha256 over sorted child descriptors.
|
|
118
|
+
* Files contribute `name|size|mtimeMs`; directories contribute their own
|
|
119
|
+
* recursive fingerprint, so any change below a directory invalidates every
|
|
120
|
+
* ancestor. Reads no file contents.
|
|
121
|
+
*/
|
|
122
|
+
export function directoryFingerprint(dir: string): string {
|
|
123
|
+
const hash = createHash("sha256");
|
|
124
|
+
for (const name of memoryChildren(dir)) {
|
|
125
|
+
try {
|
|
126
|
+
const stats = statSync(path.join(dir, name));
|
|
127
|
+
hash.update(`f|${name}|${stats.size}|${Math.trunc(stats.mtimeMs)}\n`);
|
|
128
|
+
} catch {
|
|
129
|
+
hash.update(`f|${name}|missing\n`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
for (const name of directoryChildren(dir)) {
|
|
133
|
+
hash.update(`d|${name}|${directoryFingerprint(path.join(dir, name))}\n`);
|
|
134
|
+
}
|
|
135
|
+
return hash.digest("hex");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function readFileOrNull(target: string): string | null {
|
|
139
|
+
try {
|
|
140
|
+
return readFileSync(target, "utf8");
|
|
141
|
+
} catch {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function parseSidecar(content: string): ParsedSidecar | null {
|
|
147
|
+
if (!content.startsWith(DIRECTORY_SIDECAR_MARKER)) return null;
|
|
148
|
+
const fingerprint = /^fingerprint: ([0-9a-f]{64})$/m.exec(content)?.[1];
|
|
149
|
+
if (!fingerprint) return null;
|
|
150
|
+
const abstract = /^## Abstract\n([^\n]+)$/m.exec(content)?.[1] ?? "";
|
|
151
|
+
const overviewStart = content.indexOf("## Abstract");
|
|
152
|
+
const overview =
|
|
153
|
+
overviewStart === -1 ? "" : content.slice(overviewStart, overviewStart + OVERVIEW_MAX_CHARS).trim();
|
|
154
|
+
// The `* name — preview` child bullets are the rendered child count.
|
|
155
|
+
const childCount = (content.match(/^\* .+$/gm) ?? []).length;
|
|
156
|
+
return { abstract, overview, childCount, fingerprint };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function sidecarPath(dir: string): string {
|
|
160
|
+
return path.join(dir, DIRECTORY_SIDECAR_BASENAME);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function renderSidecar(dir: string, fingerprint: string, childAbstracts: Map<string, string>): string | null {
|
|
164
|
+
const children = memoryChildren(dir);
|
|
165
|
+
const childDirs = directoryChildren(dir).filter((name) => childAbstracts.has(path.join(dir, name)));
|
|
166
|
+
if (children.length === 0 && childDirs.length === 0) return null;
|
|
167
|
+
|
|
168
|
+
const previews = children.map((name) => {
|
|
169
|
+
try {
|
|
170
|
+
return normalizeProjectionPreview(readFileSync(path.join(dir, name), "utf8"), 120);
|
|
171
|
+
} catch {
|
|
172
|
+
return "";
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
const titles = children.map(
|
|
176
|
+
(name, index) => previews[index].split(" ").slice(0, 8).join(" ") || name.replace(/\.md$/, ""),
|
|
177
|
+
);
|
|
178
|
+
const abstract = normalizeProjectionPreview(
|
|
179
|
+
`${path.basename(dir)}/ — ${children.length} memories: ${titles.slice(0, 5).join(" · ")}`,
|
|
180
|
+
ABSTRACT_MAX_CHARS,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
const lines = [
|
|
184
|
+
DIRECTORY_SIDECAR_MARKER,
|
|
185
|
+
`fingerprint: ${fingerprint}`,
|
|
186
|
+
`# ${path.basename(dir)}/ overview`,
|
|
187
|
+
"",
|
|
188
|
+
"## Abstract",
|
|
189
|
+
abstract,
|
|
190
|
+
"",
|
|
191
|
+
"## Children",
|
|
192
|
+
];
|
|
193
|
+
for (const [index, name] of children.entries()) {
|
|
194
|
+
lines.push(`* ${name} — ${previews[index]}`);
|
|
195
|
+
}
|
|
196
|
+
for (const name of childDirs) {
|
|
197
|
+
lines.push(`### ${name}/`);
|
|
198
|
+
lines.push(childAbstracts.get(path.join(dir, name)) ?? "");
|
|
199
|
+
}
|
|
200
|
+
lines.push("");
|
|
201
|
+
return lines.join("\n");
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** Scope roots whose category subtrees carry sidecars: the memory root plus every namespace root. */
|
|
205
|
+
function scopeRoots(memoryDir: string): string[] {
|
|
206
|
+
const roots = [memoryDir];
|
|
207
|
+
const namespacesRoot = path.join(memoryDir, "namespaces");
|
|
208
|
+
for (const entry of listEntries(namespacesRoot)) {
|
|
209
|
+
if (entry.isDirectory() && isRealDirectory(path.join(namespacesRoot, entry.name))) {
|
|
210
|
+
roots.push(path.join(namespacesRoot, entry.name));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return roots;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Every directory that should carry a sidecar, deepest first (post-order) so
|
|
218
|
+
* parents render after their children and can embed child abstracts.
|
|
219
|
+
*/
|
|
220
|
+
function collectSidecarDirs(scopeRoot: string): string[] {
|
|
221
|
+
const dirs: string[] = [];
|
|
222
|
+
const walk = (dir: string, isCategoryRoot: boolean): boolean => {
|
|
223
|
+
let carries = memoryChildren(dir).length > 0;
|
|
224
|
+
for (const name of directoryChildren(dir)) {
|
|
225
|
+
carries = walk(path.join(dir, name), false) || carries;
|
|
226
|
+
}
|
|
227
|
+
// A directory that stopped carrying memories must still be visited so its
|
|
228
|
+
// orphaned sidecar can be pruned or rewritten (cache-invalidation completeness).
|
|
229
|
+
const hasSidecar = readFileOrNull(sidecarPath(dir))?.startsWith(DIRECTORY_SIDECAR_MARKER) === true;
|
|
230
|
+
if (isCategoryRoot || carries || hasSidecar) dirs.push(dir);
|
|
231
|
+
return carries;
|
|
232
|
+
};
|
|
233
|
+
for (const category of RECALL_FALLBACK_DIRS) {
|
|
234
|
+
const categoryDir = path.join(scopeRoot, category);
|
|
235
|
+
if (!isRealDirectory(categoryDir)) continue;
|
|
236
|
+
walk(categoryDir, true);
|
|
237
|
+
}
|
|
238
|
+
return dirs;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Regenerate directory sidecars incrementally. Unchanged sidecars are left
|
|
243
|
+
* untouched; emptied directories lose theirs; user files at the sidecar path
|
|
244
|
+
* (no marker) are never written or removed. With `enabled: false` every
|
|
245
|
+
* generated sidecar is removed — the OKF index-maintenance contract.
|
|
246
|
+
*/
|
|
247
|
+
export async function runDirectorySidecarMaintenance(
|
|
248
|
+
memoryDir: string,
|
|
249
|
+
enabled: boolean,
|
|
250
|
+
): Promise<DirectorySidecarReport> {
|
|
251
|
+
const written: string[] = [];
|
|
252
|
+
const removed: string[] = [];
|
|
253
|
+
for (const scope of scopeRoots(memoryDir)) {
|
|
254
|
+
const childAbstracts = new Map<string, string>();
|
|
255
|
+
for (const dir of collectSidecarDirs(scope)) {
|
|
256
|
+
const target = sidecarPath(dir);
|
|
257
|
+
const raw = readFileOrNull(target);
|
|
258
|
+
const existing = raw !== null && raw.startsWith(DIRECTORY_SIDECAR_MARKER) ? raw : null;
|
|
259
|
+
if (!enabled) {
|
|
260
|
+
if (existing !== null) {
|
|
261
|
+
unlinkSync(target);
|
|
262
|
+
removed.push(target);
|
|
263
|
+
}
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
const next = renderSidecar(dir, directoryFingerprint(dir), childAbstracts);
|
|
267
|
+
if (next === null) {
|
|
268
|
+
if (existing !== null) {
|
|
269
|
+
unlinkSync(target);
|
|
270
|
+
removed.push(target);
|
|
271
|
+
}
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
const parsedNext = parseSidecar(next);
|
|
275
|
+
if (parsedNext) childAbstracts.set(dir, parsedNext.abstract);
|
|
276
|
+
if (raw === next) continue;
|
|
277
|
+
if (existing === null && raw !== null) continue; // user-authored file: hands off
|
|
278
|
+
await writeFileAtomically(target, next);
|
|
279
|
+
written.push(target);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return { written, removed };
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Read a directory's sidecar for retrieval. By default a stale sidecar is
|
|
287
|
+
* refreshed in place (child directories first), which is what makes direct
|
|
288
|
+
* writes that bypass maintenance still converge. With `{ refresh: false }`
|
|
289
|
+
* the stored sidecar is returned as-is with `fresh: false` so callers can
|
|
290
|
+
* observe staleness without writes.
|
|
291
|
+
*/
|
|
292
|
+
export async function loadDirectorySidecar(
|
|
293
|
+
dir: string,
|
|
294
|
+
options: { refresh?: boolean } = {},
|
|
295
|
+
): Promise<DirectorySidecar | null> {
|
|
296
|
+
const refresh = options.refresh !== false;
|
|
297
|
+
const target = sidecarPath(dir);
|
|
298
|
+
const stored = readFileOrNull(target);
|
|
299
|
+
const generated = stored !== null && stored.startsWith(DIRECTORY_SIDECAR_MARKER);
|
|
300
|
+
const parsed = generated ? parseSidecar(stored) : null;
|
|
301
|
+
const fingerprint = directoryFingerprint(dir);
|
|
302
|
+
if (parsed !== null && (parsed.fingerprint === fingerprint || !refresh)) {
|
|
303
|
+
return {
|
|
304
|
+
dir,
|
|
305
|
+
abstract: parsed.abstract,
|
|
306
|
+
overview: parsed.overview,
|
|
307
|
+
childCount: parsed.childCount,
|
|
308
|
+
fresh: parsed.fingerprint === fingerprint,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
if (!refresh) return null;
|
|
312
|
+
|
|
313
|
+
// Refresh bottom-up so this directory's body embeds current child abstracts.
|
|
314
|
+
const childAbstracts = new Map<string, string>();
|
|
315
|
+
for (const name of directoryChildren(dir)) {
|
|
316
|
+
const child = await loadDirectorySidecar(path.join(dir, name));
|
|
317
|
+
if (child) childAbstracts.set(path.join(dir, name), child.abstract);
|
|
318
|
+
}
|
|
319
|
+
const next = renderSidecar(dir, directoryFingerprint(dir), childAbstracts);
|
|
320
|
+
if (next === null) {
|
|
321
|
+
if (generated) unlinkSync(target);
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
if (readFileOrNull(target) !== next) {
|
|
325
|
+
if (stored !== null && !generated) {
|
|
326
|
+
// User-authored file at the sidecar path: serve nothing rather than clobber it.
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
await writeFileAtomically(target, next);
|
|
330
|
+
}
|
|
331
|
+
const refreshed = parseSidecar(next);
|
|
332
|
+
return refreshed
|
|
333
|
+
? {
|
|
334
|
+
dir,
|
|
335
|
+
abstract: refreshed.abstract,
|
|
336
|
+
overview: refreshed.overview,
|
|
337
|
+
childCount: refreshed.childCount,
|
|
338
|
+
fresh: true,
|
|
339
|
+
}
|
|
340
|
+
: null;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Overview-query primitive for hierarchical retrieval (layer 1 of #2977):
|
|
345
|
+
* score every sidecar's abstract (+3 per query term) and overview (+1 per
|
|
346
|
+
* term) lexically, then return the most specific matches — when both a
|
|
347
|
+
* directory and its descendant match, only the descendant is kept, matching
|
|
348
|
+
* the drill-down semantics the full retrieval mode will build on.
|
|
349
|
+
*/
|
|
350
|
+
export async function findDirectorySidecarsForQuery(
|
|
351
|
+
memoryDir: string,
|
|
352
|
+
query: string,
|
|
353
|
+
options: { namespace?: string; limit?: number } = {},
|
|
354
|
+
): Promise<DirectorySidecarMatch[]> {
|
|
355
|
+
const scope = options.namespace ? path.join(memoryDir, "namespaces", options.namespace) : memoryDir;
|
|
356
|
+
if (!isRealDirectory(scope)) return [];
|
|
357
|
+
const terms = query
|
|
358
|
+
.toLowerCase()
|
|
359
|
+
.split(/[^a-z0-9]+/)
|
|
360
|
+
.filter((term) => term.length >= 2);
|
|
361
|
+
|
|
362
|
+
const matches: DirectorySidecarMatch[] = [];
|
|
363
|
+
for (const root of scopeRoots(scope)) {
|
|
364
|
+
for (const dir of collectSidecarDirs(root)) {
|
|
365
|
+
const sidecar = await loadDirectorySidecar(dir);
|
|
366
|
+
if (!sidecar) continue;
|
|
367
|
+
const abstractLower = sidecar.abstract.toLowerCase();
|
|
368
|
+
const overviewLower = sidecar.overview.toLowerCase();
|
|
369
|
+
let score = 0;
|
|
370
|
+
for (const term of terms) {
|
|
371
|
+
if (abstractLower.includes(term)) score += 3;
|
|
372
|
+
else if (overviewLower.includes(term)) score += 1;
|
|
373
|
+
}
|
|
374
|
+
if (score > 0) matches.push({ ...sidecar, score });
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
matches.sort((a, b) => b.score - a.score || a.dir.localeCompare(b.dir));
|
|
378
|
+
|
|
379
|
+
const limit = options.limit ?? DEFAULT_QUERY_LIMIT;
|
|
380
|
+
return matches
|
|
381
|
+
.filter((candidate) => !matches.some((other) => other.dir.startsWith(`${candidate.dir}${path.sep}`)))
|
|
382
|
+
.slice(0, limit);
|
|
383
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-end experience extraction config (issue #2979) — the
|
|
3
|
+
* `sessionExperience` block.
|
|
4
|
+
*
|
|
5
|
+
* Parsed like `recallNavigation`: shape-validated, fail-closed on unknown
|
|
6
|
+
* keys, no silent clamping. Defaults OFF (a machine-generated memory write
|
|
7
|
+
* from the completed session must be an explicit operator opt-in); the
|
|
8
|
+
* `conservative` preset pins `enabled: false`.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { coerceBool } from "../connectors/coerce.js";
|
|
12
|
+
|
|
13
|
+
export interface SessionExperienceConfig {
|
|
14
|
+
/**
|
|
15
|
+
* Master switch for session-end Situation/Approach/Reflection episode
|
|
16
|
+
* extraction. Default false.
|
|
17
|
+
*/
|
|
18
|
+
enabled: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const SESSION_EXPERIENCE_CONFIG_DEFAULTS: SessionExperienceConfig = {
|
|
22
|
+
enabled: false,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function parseFlag(src: Record<string, unknown>, key: string, fallback: boolean): boolean {
|
|
26
|
+
const value = src[key];
|
|
27
|
+
if (value === undefined || value === null) return fallback;
|
|
28
|
+
const coerced = coerceBool(value);
|
|
29
|
+
if (coerced === undefined) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`sessionExperience.${key} must be a boolean (or "true"/"false"/"1"/"0"); got ${JSON.stringify(value)}`,
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
return coerced;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function parseSessionExperienceConfig(raw: unknown): SessionExperienceConfig {
|
|
38
|
+
if (raw === undefined || raw === null) return { ...SESSION_EXPERIENCE_CONFIG_DEFAULTS };
|
|
39
|
+
if (typeof raw !== "object" || Array.isArray(raw)) {
|
|
40
|
+
throw new Error(`sessionExperience must be an object; got ${JSON.stringify(raw)}`);
|
|
41
|
+
}
|
|
42
|
+
const src = raw as Record<string, unknown>;
|
|
43
|
+
const { enabled: _enabled, ...unknown } = src;
|
|
44
|
+
const unknownKey = Object.keys(unknown)[0];
|
|
45
|
+
if (unknownKey !== undefined) {
|
|
46
|
+
throw new Error(`sessionExperience contains unknown key ${JSON.stringify(unknownKey)}`);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
enabled: parseFlag(src, "enabled", SESSION_EXPERIENCE_CONFIG_DEFAULTS.enabled),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-end experience extraction through the real flush lifecycle
|
|
3
|
+
* (issue #2979): `flushSession(reason: "session_end")` drains the buffer
|
|
4
|
+
* and then derives at most one agent-experience episode; `before_reset`
|
|
5
|
+
* must not write one; gate off must write nothing anywhere.
|
|
6
|
+
*/
|
|
7
|
+
import assert from "node:assert/strict";
|
|
8
|
+
import { readFile } from "node:fs/promises";
|
|
9
|
+
import test from "node:test";
|
|
10
|
+
|
|
11
|
+
import { Orchestrator } from "../orchestrator.js";
|
|
12
|
+
import {
|
|
13
|
+
cleanupDir,
|
|
14
|
+
makeHarmonicLifecycleConfig,
|
|
15
|
+
markdownFilesUnder,
|
|
16
|
+
mkTempMemoryDir,
|
|
17
|
+
singleFactResult,
|
|
18
|
+
stubExtraction,
|
|
19
|
+
} from "../testing/orchestrator-lite.js";
|
|
20
|
+
|
|
21
|
+
async function sessionEndMemories(memoryDir: string): Promise<string[]> {
|
|
22
|
+
const matches: string[] = [];
|
|
23
|
+
for (const file of await markdownFilesUnder(`${memoryDir}/procedures`)) {
|
|
24
|
+
if ((await readFile(file, "utf8")).includes("Reflection: ")) matches.push(file);
|
|
25
|
+
}
|
|
26
|
+
return matches;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function withOrchestrator(
|
|
30
|
+
label: string,
|
|
31
|
+
overrides: Record<string, unknown>,
|
|
32
|
+
run: (orchestrator: Orchestrator, memoryDir: string) => Promise<void>,
|
|
33
|
+
): Promise<void> {
|
|
34
|
+
const memoryDir = await mkTempMemoryDir(label);
|
|
35
|
+
let orchestrator: Orchestrator | undefined;
|
|
36
|
+
try {
|
|
37
|
+
orchestrator = new Orchestrator(makeHarmonicLifecycleConfig(memoryDir, overrides));
|
|
38
|
+
stubExtraction(orchestrator, (turns) => singleFactResult("The harmonic probe fact persists."));
|
|
39
|
+
await run(orchestrator, memoryDir);
|
|
40
|
+
} finally {
|
|
41
|
+
await orchestrator?.destroy().catch(() => undefined);
|
|
42
|
+
await cleanupDir(memoryDir);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const SESSION = "session-end-experience";
|
|
47
|
+
|
|
48
|
+
const SUCCESS_TURNS: Array<[role: "user" | "assistant", content: string]> = [
|
|
49
|
+
["user", "Fix the flaky payments integration test that times out after thirty seconds."],
|
|
50
|
+
["assistant", "I will reproduce the timeout and inspect the payments test setup."],
|
|
51
|
+
["assistant", "Added the missing await to the setup call. Verified: the payments test passes now."],
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
test("session_end flush writes exactly one pending_review agent-experience episode", async () => {
|
|
55
|
+
await withOrchestrator(
|
|
56
|
+
"sx-e2e-on",
|
|
57
|
+
{ sessionExperience: { enabled: true } },
|
|
58
|
+
async (orchestrator, memoryDir) => {
|
|
59
|
+
for (const [role, content] of SUCCESS_TURNS) {
|
|
60
|
+
await orchestrator.processTurn(role, content, SESSION);
|
|
61
|
+
}
|
|
62
|
+
await orchestrator.flushSession(SESSION, { reason: "session_end" });
|
|
63
|
+
const experiences = await sessionEndMemories(memoryDir);
|
|
64
|
+
assert.equal(experiences.length, 1, "one session = at most one experience episode");
|
|
65
|
+
const body = await readFile(experiences[0], "utf8");
|
|
66
|
+
assert.match(body, /Situation: Fix the flaky payments integration test/);
|
|
67
|
+
assert.match(body, /Approach: /);
|
|
68
|
+
assert.match(body, /Reflection: /);
|
|
69
|
+
assert.match(body, /status: pending_review/);
|
|
70
|
+
assert.match(body, /subject: agent/);
|
|
71
|
+
assert.match(body, /category: procedure/);
|
|
72
|
+
assert.match(body, /experience_session_hash/);
|
|
73
|
+
// A second session_end drain sees an empty buffer and must not duplicate.
|
|
74
|
+
await orchestrator.flushSession(SESSION, { reason: "session_end" });
|
|
75
|
+
assert.equal((await sessionEndMemories(memoryDir)).length, 1, "replay must not duplicate");
|
|
76
|
+
},
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("a failed session_end records the failure reflection", async () => {
|
|
81
|
+
await withOrchestrator(
|
|
82
|
+
"sx-e2e-fail",
|
|
83
|
+
{ sessionExperience: { enabled: true } },
|
|
84
|
+
async (orchestrator, memoryDir) => {
|
|
85
|
+
await orchestrator.processTurn(
|
|
86
|
+
"user",
|
|
87
|
+
"Migrate the billing export job to the new queue library before the release cut.",
|
|
88
|
+
SESSION,
|
|
89
|
+
);
|
|
90
|
+
await orchestrator.processTurn(
|
|
91
|
+
"assistant",
|
|
92
|
+
"The migration failed: the new queue library cannot serialize the billing payload format.",
|
|
93
|
+
SESSION,
|
|
94
|
+
);
|
|
95
|
+
await orchestrator.flushSession(SESSION, { reason: "session_end" });
|
|
96
|
+
const experiences = await sessionEndMemories(memoryDir);
|
|
97
|
+
assert.equal(experiences.length, 1);
|
|
98
|
+
const body = await readFile(experiences[0], "utf8");
|
|
99
|
+
assert.match(body, /experience_outcome: failure|experience_outcome=failure/);
|
|
100
|
+
assert.match(body, /fail/i);
|
|
101
|
+
},
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("gate off (default): a session_end flush writes no experience anywhere", async () => {
|
|
106
|
+
await withOrchestrator("sx-e2e-off", {}, async (orchestrator, memoryDir) => {
|
|
107
|
+
for (const [role, content] of SUCCESS_TURNS) {
|
|
108
|
+
await orchestrator.processTurn(role, content, SESSION);
|
|
109
|
+
}
|
|
110
|
+
await orchestrator.flushSession(SESSION, { reason: "session_end" });
|
|
111
|
+
assert.equal((await sessionEndMemories(memoryDir)).length, 0, "gate off must write nothing");
|
|
112
|
+
for (const file of await markdownFilesUnder(memoryDir)) {
|
|
113
|
+
const body = await readFile(file, "utf8");
|
|
114
|
+
assert.doesNotMatch(
|
|
115
|
+
body,
|
|
116
|
+
/Reflection: /,
|
|
117
|
+
`no experience body may appear anywhere while gated off (saw ${file})`,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test("before_reset drains the buffer but writes no experience episode", async () => {
|
|
124
|
+
await withOrchestrator(
|
|
125
|
+
"sx-e2e-reset",
|
|
126
|
+
{ sessionExperience: { enabled: true } },
|
|
127
|
+
async (orchestrator, memoryDir) => {
|
|
128
|
+
for (const [role, content] of SUCCESS_TURNS) {
|
|
129
|
+
await orchestrator.processTurn(role, content, SESSION);
|
|
130
|
+
}
|
|
131
|
+
await orchestrator.flushSession(SESSION, { reason: "before_reset" });
|
|
132
|
+
assert.equal(
|
|
133
|
+
(await sessionEndMemories(memoryDir)).length,
|
|
134
|
+
0,
|
|
135
|
+
"experiences are session_end-only in v1",
|
|
136
|
+
);
|
|
137
|
+
},
|
|
138
|
+
);
|
|
139
|
+
});
|