@remnic/core 1.1.1 → 1.1.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/abort-error.js +1 -0
- package/dist/abstraction-nodes.js +1 -0
- package/dist/access-audit.js +1 -0
- package/dist/access-cli.js +76 -51
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +50 -5
- package/dist/access-http.js +38 -16
- package/dist/access-idempotency.js +1 -0
- package/dist/access-mcp.d.ts +10 -5
- package/dist/access-mcp.js +37 -14
- package/dist/access-schema.d.ts +133 -13
- package/dist/access-schema.js +20 -1
- package/dist/access-service-_AEUMVyX.d.ts +1981 -0
- package/dist/access-service.d.ts +11 -6
- package/dist/access-service.js +39 -14
- package/dist/active-memory-bridge.js +1 -0
- package/dist/active-recall.js +1 -0
- package/dist/active-recall.js.map +1 -1
- package/dist/behavior-learner.js +1 -0
- package/dist/behavior-learner.js.map +1 -1
- package/dist/behavior-signals.js +1 -0
- package/dist/bootstrap.d.ts +6 -4
- package/dist/bootstrap.js +1 -0
- package/dist/boxes.js +1 -0
- package/dist/briefing.d.ts +9 -5
- package/dist/briefing.js +10 -6
- package/dist/buffer-surprise-report.js +1 -0
- package/dist/buffer-surprise.js +1 -0
- package/dist/buffer.d.ts +1 -1
- package/dist/buffer.js +1 -0
- package/dist/calibration.d.ts +8 -1
- package/dist/calibration.js +10 -2
- package/dist/calibration.js.map +1 -1
- package/dist/capsule-cli.d.ts +137 -0
- package/dist/capsule-cli.js +34 -0
- package/dist/capsule-crypto-5CYAGVC5.js +18 -0
- package/dist/capsule-export-NZQPOTQ4.js +17 -0
- package/dist/capsule-export-NZQPOTQ4.js.map +1 -0
- package/dist/capsule-import-SDCUXLEV.js +16 -0
- package/dist/capsule-import-SDCUXLEV.js.map +1 -0
- package/dist/capsule-merge-DI7PNQ2H.js +189 -0
- package/dist/capsule-merge-DI7PNQ2H.js.map +1 -0
- package/dist/causal-behavior.js +1 -0
- package/dist/causal-behavior.js.map +1 -1
- package/dist/causal-chain.js +1 -0
- package/dist/causal-consolidation.js +12 -9
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-retrieval.js +2 -1
- package/dist/causal-retrieval.js.map +1 -1
- package/dist/causal-trajectory-graph.js +4 -1
- package/dist/causal-trajectory-graph.js.map +1 -1
- package/dist/causal-trajectory.js +2 -1
- package/dist/chunk-2LSZVONP.js +67 -0
- package/dist/chunk-2LSZVONP.js.map +1 -0
- package/dist/chunk-32KD5IHZ.js +245 -0
- package/dist/chunk-32KD5IHZ.js.map +1 -0
- package/dist/{chunk-VDX363PS.js → chunk-34F3PLWZ.js} +10 -3
- package/dist/chunk-34F3PLWZ.js.map +1 -0
- package/dist/chunk-3KIS4VGT.js +228 -0
- package/dist/chunk-3KIS4VGT.js.map +1 -0
- package/dist/chunk-3LCWFNVS.js +350 -0
- package/dist/chunk-3LCWFNVS.js.map +1 -0
- package/dist/chunk-43EKP2UK.js +26 -0
- package/dist/chunk-43EKP2UK.js.map +1 -0
- package/dist/chunk-457A4P3L.js +119 -0
- package/dist/chunk-457A4P3L.js.map +1 -0
- package/dist/{chunk-KUB6JU6H.js → chunk-47WOM4YW.js} +2 -2
- package/dist/{chunk-HK3FGIEW.js → chunk-4PLGJRBV.js} +656 -20
- package/dist/chunk-4PLGJRBV.js.map +1 -0
- package/dist/{chunk-BGJGXLZ7.js → chunk-55FXRRSJ.js} +11 -8
- package/dist/chunk-55FXRRSJ.js.map +1 -0
- package/dist/{chunk-ULYOGL6R.js → chunk-5HRY2WRF.js} +7 -3
- package/dist/chunk-5HRY2WRF.js.map +1 -0
- package/dist/chunk-6TBWYBJ3.js +236 -0
- package/dist/chunk-6TBWYBJ3.js.map +1 -0
- package/dist/chunk-74EMIVE4.js +329 -0
- package/dist/chunk-74EMIVE4.js.map +1 -0
- package/dist/chunk-74WWN7ZW.js +82 -0
- package/dist/chunk-74WWN7ZW.js.map +1 -0
- package/dist/{chunk-B5WXLVDY.js → chunk-7GCMLT7J.js} +245 -25
- package/dist/chunk-7GCMLT7J.js.map +1 -0
- package/dist/chunk-A6XUJE5D.js +126 -0
- package/dist/chunk-A6XUJE5D.js.map +1 -0
- package/dist/chunk-AJA46VX5.js +393 -0
- package/dist/chunk-AJA46VX5.js.map +1 -0
- package/dist/{chunk-DFTTJYSO.js → chunk-AKUCB2OG.js} +525 -24
- package/dist/chunk-AKUCB2OG.js.map +1 -0
- package/dist/chunk-ASIQZXYO.js +277 -0
- package/dist/chunk-ASIQZXYO.js.map +1 -0
- package/dist/{chunk-ZEM3OK2K.js → chunk-B2TL6GA2.js} +3 -3
- package/dist/chunk-BJMBJZ2Y.js +290 -0
- package/dist/chunk-BJMBJZ2Y.js.map +1 -0
- package/dist/chunk-BT7NVCML.js +79 -0
- package/dist/chunk-BT7NVCML.js.map +1 -0
- package/dist/chunk-CK5NTM2S.js +454 -0
- package/dist/chunk-CK5NTM2S.js.map +1 -0
- package/dist/{chunk-3GXCSUXR.js → chunk-CRU27Q4J.js} +2 -2
- package/dist/{chunk-F5VP6YCB.js → chunk-DCE6SQLA.js} +572 -155
- package/dist/chunk-DCE6SQLA.js.map +1 -0
- package/dist/{chunk-CUPFXL3J.js → chunk-DHRQHX36.js} +4 -4
- package/dist/chunk-DHRQHX36.js.map +1 -0
- package/dist/{chunk-GKFXUTJ2.js → chunk-DR7MCMPS.js} +981 -61
- package/dist/chunk-DR7MCMPS.js.map +1 -0
- package/dist/chunk-FP2373TW.js +149 -0
- package/dist/chunk-FP2373TW.js.map +1 -0
- package/dist/{chunk-RBBWYEFJ.js → chunk-G2WADRQ3.js} +1 -1
- package/dist/chunk-G7D6GZ5J.js +48 -0
- package/dist/chunk-G7D6GZ5J.js.map +1 -0
- package/dist/chunk-H7XKCNR6.js +60 -0
- package/dist/chunk-H7XKCNR6.js.map +1 -0
- package/dist/{chunk-VYM3VWOF.js → chunk-IM3JSE73.js} +966 -329
- package/dist/chunk-IM3JSE73.js.map +1 -0
- package/dist/chunk-IXEJRKCZ.js +18 -0
- package/dist/chunk-IXEJRKCZ.js.map +1 -0
- package/dist/chunk-IYY4MCPG.js +275 -0
- package/dist/chunk-IYY4MCPG.js.map +1 -0
- package/dist/{chunk-BK2EFTE2.js → chunk-JWSENLQI.js} +508 -28
- package/dist/chunk-JWSENLQI.js.map +1 -0
- package/dist/chunk-KNKUID7G.js +183 -0
- package/dist/chunk-KNKUID7G.js.map +1 -0
- package/dist/chunk-L2IO2QPY.js +2036 -0
- package/dist/chunk-L2IO2QPY.js.map +1 -0
- package/dist/{chunk-SPI27QT6.js → chunk-L5IIGA5V.js} +9 -4
- package/dist/chunk-L5IIGA5V.js.map +1 -0
- package/dist/{chunk-RGLL5SPU.js → chunk-LVYGDT5V.js} +56 -82
- package/dist/chunk-LVYGDT5V.js.map +1 -0
- package/dist/{chunk-ZAIM4TUE.js → chunk-LW2NMHDW.js} +46 -1
- package/dist/chunk-LW2NMHDW.js.map +1 -0
- package/dist/{chunk-3OGMS3PE.js → chunk-LZRYQK6L.js} +3 -2
- package/dist/chunk-LZRYQK6L.js.map +1 -0
- package/dist/chunk-MDYG7VI7.js +48 -0
- package/dist/chunk-MDYG7VI7.js.map +1 -0
- package/dist/chunk-MXC3AP5I.js +74 -0
- package/dist/chunk-MXC3AP5I.js.map +1 -0
- package/dist/{chunk-S3EEFKNY.js → chunk-N7X62G74.js} +26 -11
- package/dist/chunk-N7X62G74.js.map +1 -0
- package/dist/chunk-NN3TS5BM.js +147 -0
- package/dist/chunk-NN3TS5BM.js.map +1 -0
- package/dist/chunk-OA3L7BFR.js +183 -0
- package/dist/chunk-OA3L7BFR.js.map +1 -0
- package/dist/{chunk-LK6SGL53.js → chunk-OR64ZGRZ.js} +3 -2
- package/dist/chunk-OR64ZGRZ.js.map +1 -0
- package/dist/chunk-OZHRDTDX.js +240 -0
- package/dist/chunk-OZHRDTDX.js.map +1 -0
- package/dist/chunk-PCUKNJAZ.js +165 -0
- package/dist/chunk-PCUKNJAZ.js.map +1 -0
- package/dist/{chunk-6PFRXT4K.js → chunk-PFV5C235.js} +11 -6
- package/dist/chunk-PFV5C235.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/{chunk-XZ2TIKGC.js → chunk-Q7FJ5ZHM.js} +30 -10
- package/dist/chunk-Q7FJ5ZHM.js.map +1 -0
- package/dist/{chunk-7I7FKFZH.js → chunk-R2L7SUX2.js} +6 -6
- package/dist/{chunk-JL2PU6AI.js → chunk-R2XRID2N.js} +2 -2
- package/dist/{chunk-WCLICCGB.js → chunk-RILIVK4O.js} +91 -4
- package/dist/chunk-RILIVK4O.js.map +1 -0
- package/dist/{chunk-C2EFFULQ.js → chunk-RK2Y4XOM.js} +163 -20
- package/dist/chunk-RK2Y4XOM.js.map +1 -0
- package/dist/{chunk-TP4FZJIZ.js → chunk-RULE4VG5.js} +5 -1
- package/dist/chunk-RULE4VG5.js.map +1 -0
- package/dist/{chunk-PVPWZSSI.js → chunk-SMA4IMHV.js} +19 -3
- package/dist/chunk-SMA4IMHV.js.map +1 -0
- package/dist/{chunk-WVVA7F5A.js → chunk-SS253RXF.js} +30 -16
- package/dist/chunk-SS253RXF.js.map +1 -0
- package/dist/chunk-TUFG6VXY.js +875 -0
- package/dist/chunk-TUFG6VXY.js.map +1 -0
- package/dist/chunk-TYEOAFH3.js +251 -0
- package/dist/chunk-TYEOAFH3.js.map +1 -0
- package/dist/chunk-UKJAGEXH.js +260 -0
- package/dist/chunk-UKJAGEXH.js.map +1 -0
- package/dist/{chunk-KVBLZUKV.js → chunk-USFPPRAF.js} +93 -3
- package/dist/chunk-USFPPRAF.js.map +1 -0
- package/dist/{chunk-EPQJM2GC.js → chunk-VTJVUHRK.js} +22 -36
- package/dist/chunk-VTJVUHRK.js.map +1 -0
- package/dist/{chunk-O5ETUNBT.js → chunk-VTU2B4VF.js} +7 -3
- package/dist/chunk-VTU2B4VF.js.map +1 -0
- package/dist/chunk-WIICJPET.js +45 -0
- package/dist/chunk-WIICJPET.js.map +1 -0
- package/dist/{chunk-VBVG2M5G.js → chunk-WPGJYVUH.js} +6 -2
- package/dist/chunk-WPGJYVUH.js.map +1 -0
- package/dist/{chunk-YNQKWQT4.js → chunk-WSZIHQBK.js} +31 -11
- package/dist/{chunk-YNQKWQT4.js.map → chunk-WSZIHQBK.js.map} +1 -1
- package/dist/{chunk-NZLQTHS5.js → chunk-WW3QQF4H.js} +4 -1
- package/dist/chunk-WW3QQF4H.js.map +1 -0
- package/dist/{chunk-FVA6TGI3.js → chunk-Y3WQ4ZWK.js} +42 -2
- package/dist/chunk-Y3WQ4ZWK.js.map +1 -0
- package/dist/chunk-YNJHCGDT.js +309 -0
- package/dist/chunk-YNJHCGDT.js.map +1 -0
- package/dist/{chunk-ALXMCZEU.js → chunk-Z2E7VW55.js} +6 -3
- package/dist/chunk-Z2E7VW55.js.map +1 -0
- package/dist/{chunk-INXV5JBT.js → chunk-ZGXSCMQN.js} +1992 -410
- package/dist/chunk-ZGXSCMQN.js.map +1 -0
- package/dist/{chunk-W6SL7OFG.js → chunk-ZTSE2ZJ6.js} +12 -2
- package/dist/{chunk-W6SL7OFG.js.map → chunk-ZTSE2ZJ6.js.map} +1 -1
- package/dist/chunking.js +1 -0
- package/dist/cipher-GVE2GQ5H.js +28 -0
- package/dist/cipher-GVE2GQ5H.js.map +1 -0
- package/dist/citations.js +1 -0
- package/dist/{cli-BkeRaYfk.d.ts → cli-x2APT9a6.d.ts} +26 -7
- package/dist/cli.d.ts +11 -6
- package/dist/cli.js +68 -34
- package/dist/codex-thread-key.js +1 -0
- package/dist/commitment-ledger.js +1 -0
- package/dist/compression-optimizer.js +1 -0
- package/dist/config.d.ts +2 -1
- package/dist/config.js +5 -2
- package/dist/connectors-cli-DFGtY2DB.d.ts +257 -0
- package/dist/connectors-cli.d.ts +2 -0
- package/dist/connectors-cli.js +22 -0
- package/dist/connectors-cli.js.map +1 -0
- package/dist/consolidation-operator.d.ts +65 -5
- package/dist/consolidation-operator.js +6 -1
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-provenance-check.js +3 -2
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/consolidation-undo.js +1 -0
- package/dist/consolidation-undo.js.map +1 -1
- package/dist/{contradiction-review-WIUBAR52.js → contradiction-review-5LTTVDQV.js} +2 -1
- package/dist/contradiction-review-5LTTVDQV.js.map +1 -0
- package/dist/{contradiction-scan-E3GJTI4F.js → contradiction-scan-3Z6YW7YA.js} +2 -1
- package/dist/{contradiction-scan-E3GJTI4F.js.map → contradiction-scan-3Z6YW7YA.js.map} +1 -1
- package/dist/cross-namespace-budget.js +1 -0
- package/dist/cue-anchors.js +1 -0
- package/dist/dashboard-runtime.js +1 -0
- package/dist/day-summary.js +1 -0
- package/dist/delinearize.js +1 -0
- package/dist/direct-answer-wiring.js +1 -0
- package/dist/direct-answer.js +1 -0
- package/dist/dreams-ledger-LR2NBAZE.js +286 -0
- package/dist/dreams-ledger-LR2NBAZE.js.map +1 -0
- package/dist/embedding-fallback.js +3 -1
- package/dist/{engine-F3GOXGE5.js → engine-ICC2DSQF.js} +10 -7
- package/dist/engine-ICC2DSQF.js.map +1 -0
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +9 -6
- package/dist/entity-schema.js +1 -0
- package/dist/evals.js +1 -0
- package/dist/evidence-pack.d.ts +16 -0
- package/dist/evidence-pack.js +8 -0
- package/dist/evidence-pack.js.map +1 -0
- package/dist/explicit-capture.d.ts +6 -4
- package/dist/explicit-capture.js +1 -0
- package/dist/extraction-judge-telemetry.js +1 -0
- package/dist/extraction-judge-training.js +1 -0
- package/dist/extraction-judge.js +1 -0
- package/dist/extraction.js +9 -8
- package/dist/fallback-llm.js +3 -2
- package/dist/first-start-migration-4MHQEOSD.js +263 -0
- package/dist/first-start-migration-4MHQEOSD.js.map +1 -0
- package/dist/forget-PLR6J5DN.js +69 -0
- package/dist/forget-PLR6J5DN.js.map +1 -0
- package/dist/framework-CyHYDcri.d.ts +153 -0
- package/dist/fs-utils-IRVUFB6G.js +30 -0
- package/dist/fs-utils-IRVUFB6G.js.map +1 -0
- package/dist/graph-dashboard-diff.js +1 -0
- package/dist/graph-dashboard-key.js +1 -0
- package/dist/graph-dashboard-parser.js +1 -0
- package/dist/graph-edge-decay-PWB63GRE.js +207 -0
- package/dist/graph-edge-decay-PWB63GRE.js.map +1 -0
- package/dist/graph-edge-reinforcement.d.ts +81 -0
- package/dist/graph-edge-reinforcement.js +24 -0
- package/dist/graph-edge-reinforcement.js.map +1 -0
- package/dist/graph-events.d.ts +87 -0
- package/dist/graph-events.js +14 -0
- package/dist/graph-events.js.map +1 -0
- package/dist/graph-recall.js +1 -0
- package/dist/graph-retrieval.js +1 -0
- package/dist/graph-snapshot.d.ts +112 -0
- package/dist/graph-snapshot.js +19 -0
- package/dist/graph-snapshot.js.map +1 -0
- package/dist/graph.d.ts +105 -7
- package/dist/graph.js +20 -3
- package/dist/harmonic-retrieval.js +1 -0
- package/dist/himem.js +1 -0
- package/dist/hygiene.js +1 -0
- package/dist/identity-continuity.js +1 -0
- package/dist/importance.js +1 -0
- package/dist/index.d.ts +562 -13
- package/dist/index.js +365 -96
- package/dist/index.js.map +1 -1
- package/dist/intent.js +1 -0
- package/dist/json-extract.js +1 -0
- package/dist/json-store.js +1 -0
- package/dist/kdf-7S6RWKLZ.js +26 -0
- package/dist/kdf-7S6RWKLZ.js.map +1 -0
- package/dist/legacy-hook-compat.js +1 -0
- package/dist/legacy-hook-compat.js.map +1 -1
- package/dist/lifecycle.js +1 -0
- package/dist/live-connectors-runner.d.ts +48 -0
- package/dist/live-connectors-runner.js +17 -0
- package/dist/live-connectors-runner.js.map +1 -0
- package/dist/local-llm.js +3 -2
- package/dist/logger.js +1 -0
- package/dist/memory-action-policy.js +1 -0
- package/dist/memory-cache.d.ts +2 -1
- package/dist/memory-cache.js +4 -1
- package/dist/memory-governance-KG52RITE.js +37 -0
- package/dist/memory-governance-KG52RITE.js.map +1 -0
- package/dist/memory-lifecycle-ledger-utils.d.ts +2 -1
- package/dist/memory-lifecycle-ledger-utils.js +4 -1
- package/dist/memory-projection-format.js +1 -0
- package/dist/{memory-projection-store-DeSXPh1j.d.ts → memory-projection-store-D3vBHS4J.d.ts} +1 -0
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-projection-store.js +1 -0
- package/dist/memory-worth-bench.js +1 -0
- package/dist/memory-worth-bench.js.map +1 -1
- package/dist/memory-worth-filter.js +1 -0
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/memory-worth-outcomes.js +1 -0
- package/dist/memory-worth.js +1 -0
- package/dist/metadata-FC3XPDRQ.js +21 -0
- package/dist/metadata-FC3XPDRQ.js.map +1 -0
- package/dist/migrate-from-identity-anchor-TTEDEJGX.js +8 -0
- package/dist/migrate-from-identity-anchor-TTEDEJGX.js.map +1 -0
- package/dist/model-registry.js +1 -0
- package/dist/models-json.js +1 -0
- package/dist/native-knowledge.js +1 -0
- package/dist/negative.js +1 -0
- package/dist/objective-state-writers.js +1 -0
- package/dist/objective-state-writers.js.map +1 -1
- package/dist/objective-state.js +1 -0
- package/dist/openai-chat-compat.js +1 -0
- package/dist/operator-toolkit.d.ts +46 -2
- package/dist/operator-toolkit.js +29 -17
- package/dist/opik-exporter.js +1 -0
- package/dist/opik-exporter.js.map +1 -1
- package/dist/{orchestrator-CmJ-NTdJ.d.ts → orchestrator-ChkesB8U.d.ts} +177 -13
- package/dist/orchestrator.d.ts +6 -4
- package/dist/orchestrator.js +58 -42
- package/dist/page-versioning.js +1 -0
- package/dist/path-RMTY5Y5A.js +9 -0
- package/dist/path-RMTY5Y5A.js.map +1 -0
- package/dist/patterns-cli.d.ts +160 -0
- package/dist/patterns-cli.js +29 -0
- package/dist/patterns-cli.js.map +1 -0
- package/dist/peers-6OSQ3NK6.js +44 -0
- package/dist/peers-6OSQ3NK6.js.map +1 -0
- package/dist/plugin-id.js +1 -0
- package/dist/policy-runtime.js +1 -0
- package/dist/{port-BADbLZU5.d.ts → port-hqGnoStS.d.ts} +6 -0
- package/dist/profiling.js +1 -0
- package/dist/purge-6ATBGT77.js +205 -0
- package/dist/purge-6ATBGT77.js.map +1 -0
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd-recall-cache.js +1 -0
- package/dist/qmd.d.ts +2 -1
- package/dist/qmd.js +4 -3
- package/dist/reasoning-trace-recall.js +1 -0
- package/dist/reasoning-trace-types.js +1 -0
- package/dist/recall-audit-anomaly.js +1 -0
- package/dist/recall-audit.js +1 -0
- package/dist/recall-disclosure-escalation.d.ts +84 -0
- package/dist/recall-disclosure-escalation.js +14 -0
- package/dist/recall-disclosure-escalation.js.map +1 -0
- package/dist/recall-explain-renderer.js +4 -1
- package/dist/recall-mmr.js +1 -0
- package/dist/recall-qos.js +1 -0
- package/dist/recall-query-policy.js +1 -0
- package/dist/recall-state.d.ts +7 -0
- package/dist/recall-state.js +2 -1
- package/dist/recall-tag-filter.d.ts +56 -0
- package/dist/recall-tag-filter.js +14 -0
- package/dist/recall-tag-filter.js.map +1 -0
- package/dist/recall-tokenization.js +1 -0
- package/dist/recall-xray-cli.d.ts +9 -2
- package/dist/recall-xray-cli.js +9 -4
- package/dist/recall-xray-renderer.js +4 -1
- package/dist/recall-xray.d.ts +116 -2
- package/dist/recall-xray.js +9 -3
- package/dist/reconstruct.js +1 -0
- package/dist/release-changelog.js +2 -0
- package/dist/release-changelog.js.map +1 -1
- package/dist/relevance.js +1 -0
- package/dist/rerank.js +1 -0
- package/dist/{resolution-QBTDHTG7.js → resolution-YGIBORXI.js} +2 -1
- package/dist/{resolution-QBTDHTG7.js.map → resolution-YGIBORXI.js.map} +1 -1
- package/dist/resolve-auth-token.d.ts +51 -0
- package/dist/resolve-auth-token.js +12 -0
- package/dist/resolve-auth-token.js.map +1 -0
- package/dist/resolve-provider-secret.d.ts +13 -1
- package/dist/resolve-provider-secret.js +6 -1
- package/dist/resume-bundles.js +5 -4
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-agents.js +1 -0
- package/dist/retrieval-tiers.js +1 -0
- package/dist/retrieval.js +1 -0
- package/dist/sanitize.js +1 -0
- package/dist/schemas.d.ts +15 -2
- package/dist/schemas.js +2 -1
- package/dist/sdk-compat.js +1 -0
- package/dist/sdk-compat.js.map +1 -1
- package/dist/secure-store-4R2GSO7S.js +156 -0
- package/dist/secure-store-4R2GSO7S.js.map +1 -0
- package/dist/semantic-chunking.js +1 -0
- package/dist/{semantic-consolidation-CxJU6MJk.d.ts → semantic-consolidation-ByBXb-sf.d.ts} +3 -3
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +12 -6
- package/dist/semantic-rule-promotion.d.ts +1 -1
- package/dist/semantic-rule-promotion.js +9 -6
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +9 -6
- package/dist/session-integrity.js +1 -0
- package/dist/session-observer-bands.js +1 -0
- package/dist/session-observer-state.js +1 -0
- package/dist/session-toggles.js +2 -0
- package/dist/session-toggles.js.map +1 -1
- package/dist/signal.js +1 -0
- package/dist/skills-registry.js +2 -0
- package/dist/skills-registry.js.map +1 -1
- package/dist/source-attribution.js +1 -0
- package/dist/state-NCHQ4TRG.js +8 -0
- package/dist/state-NCHQ4TRG.js.map +1 -0
- package/dist/state-store-3EH7HYIN.js +16 -0
- package/dist/state-store-3EH7HYIN.js.map +1 -0
- package/dist/storage.d.ts +76 -2
- package/dist/storage.js +8 -5
- package/dist/store-contract.js +1 -0
- package/dist/summarizer.js +6 -5
- package/dist/summary-snapshot.js +1 -0
- package/dist/temporal-index.js +1 -0
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-supersession.js +2 -1
- package/dist/temporal-validity.d.ts +52 -0
- package/dist/temporal-validity.js +14 -0
- package/dist/temporal-validity.js.map +1 -0
- package/dist/threading.js +1 -0
- package/dist/tier-migration.d.ts +2 -2
- package/dist/tier-migration.js +1 -0
- package/dist/tier-routing.js +1 -0
- package/dist/tier-stats-62ZVDFKS.js +152 -0
- package/dist/tier-stats-62ZVDFKS.js.map +1 -0
- package/dist/tmt.js +1 -0
- package/dist/tokens.js +3 -1
- package/dist/topics.js +1 -0
- package/dist/trace-C5ETWBEF.js +290 -0
- package/dist/trace-C5ETWBEF.js.map +1 -0
- package/dist/transcript.js +1 -0
- package/dist/trust-zones.js +1 -0
- package/dist/tui-RI7P6PBS.js +13 -0
- package/dist/tui-RI7P6PBS.js.map +1 -0
- package/dist/types-V3FJ26TF.js +30 -0
- package/dist/types-V3FJ26TF.js.map +1 -0
- package/dist/types.d.ts +634 -9
- package/dist/types.js +10 -3
- package/dist/utility-learner.js +1 -0
- package/dist/utility-runtime.js +1 -0
- package/dist/utility-telemetry.js +1 -0
- package/dist/verified-recall.js +9 -6
- package/dist/version-utils.js +1 -0
- package/dist/whitespace.js +1 -0
- package/dist/work-product-ledger.js +1 -0
- package/package.json +2 -1
- package/dist/access-service-Br8ZydTK.d.ts +0 -827
- package/dist/chunk-3OGMS3PE.js.map +0 -1
- package/dist/chunk-6PFRXT4K.js.map +0 -1
- package/dist/chunk-ALXMCZEU.js.map +0 -1
- package/dist/chunk-B5WXLVDY.js.map +0 -1
- package/dist/chunk-BGJGXLZ7.js.map +0 -1
- package/dist/chunk-BK2EFTE2.js.map +0 -1
- package/dist/chunk-C2EFFULQ.js.map +0 -1
- package/dist/chunk-CUPFXL3J.js.map +0 -1
- package/dist/chunk-DFTTJYSO.js.map +0 -1
- package/dist/chunk-EPQJM2GC.js.map +0 -1
- package/dist/chunk-F5VP6YCB.js.map +0 -1
- package/dist/chunk-FVA6TGI3.js.map +0 -1
- package/dist/chunk-GKFXUTJ2.js.map +0 -1
- package/dist/chunk-HK3FGIEW.js.map +0 -1
- package/dist/chunk-INXV5JBT.js.map +0 -1
- package/dist/chunk-KVBLZUKV.js.map +0 -1
- package/dist/chunk-LK6SGL53.js.map +0 -1
- package/dist/chunk-LTCGGW2D.js +0 -14
- package/dist/chunk-LTCGGW2D.js.map +0 -1
- package/dist/chunk-NZLQTHS5.js.map +0 -1
- package/dist/chunk-O5ETUNBT.js.map +0 -1
- package/dist/chunk-PVPWZSSI.js.map +0 -1
- package/dist/chunk-RGLL5SPU.js.map +0 -1
- package/dist/chunk-S3EEFKNY.js.map +0 -1
- package/dist/chunk-SPI27QT6.js.map +0 -1
- package/dist/chunk-TP4FZJIZ.js.map +0 -1
- package/dist/chunk-ULYOGL6R.js.map +0 -1
- package/dist/chunk-VBVG2M5G.js.map +0 -1
- package/dist/chunk-VDX363PS.js.map +0 -1
- package/dist/chunk-VYM3VWOF.js.map +0 -1
- package/dist/chunk-WCLICCGB.js.map +0 -1
- package/dist/chunk-WVVA7F5A.js.map +0 -1
- package/dist/chunk-X6GF3FX2.js +0 -26
- package/dist/chunk-X6GF3FX2.js.map +0 -1
- package/dist/chunk-XZ2TIKGC.js.map +0 -1
- package/dist/chunk-ZAIM4TUE.js.map +0 -1
- /package/dist/{contradiction-review-WIUBAR52.js.map → capsule-cli.js.map} +0 -0
- /package/dist/{engine-F3GOXGE5.js.map → capsule-crypto-5CYAGVC5.js.map} +0 -0
- /package/dist/{chunk-KUB6JU6H.js.map → chunk-47WOM4YW.js.map} +0 -0
- /package/dist/{chunk-ZEM3OK2K.js.map → chunk-B2TL6GA2.js.map} +0 -0
- /package/dist/{chunk-3GXCSUXR.js.map → chunk-CRU27Q4J.js.map} +0 -0
- /package/dist/{chunk-RBBWYEFJ.js.map → chunk-G2WADRQ3.js.map} +0 -0
- /package/dist/{chunk-7I7FKFZH.js.map → chunk-R2L7SUX2.js.map} +0 -0
- /package/dist/{chunk-JL2PU6AI.js.map → chunk-R2XRID2N.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/causal-behavior.ts"],"sourcesContent":["/**\n * causal-behavior.ts — CMC Phase 4: Implicit Behavioral Preference Learning\n *\n * Extracts behavioral signals from causal chain analysis. Unlike explicit\n * preference extraction (which reads text), this derives preferences from\n * patterns of action: what goals recur, what actions succeed repeatedly,\n * what outcomes are consistently pursued.\n *\n * Key insight: \"Preferences are recurring causal pathways.\"\n */\n\nimport type { CausalTrajectoryRecord } from \"./causal-trajectory.js\";\nimport type { CausalChainIndex } from \"./causal-chain.js\";\nimport { readChainIndex, resolveChainsDir } from \"./causal-chain.js\";\nimport { normalizeRecallTokens } from \"./recall-tokenization.js\";\nimport { topicOverlapScore } from \"./boxes.js\";\nimport { listJsonFiles, readJsonFile } from \"./json-store.js\";\nimport { isRecord } from \"./store-contract.js\";\nimport type { ConsolidatedPreference } from \"./compounding/preference-consolidator.js\";\nimport path from \"node:path\";\nimport { log } from \"./logger.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type CausalBehaviorSignalType =\n | \"topic_revisitation\"\n | \"action_pattern\"\n | \"outcome_preference\"\n | \"phrasing_style\";\n\nexport interface CausalBehaviorSignal {\n signalType: CausalBehaviorSignalType;\n pattern: string;\n frequency: number;\n sessionCount: number;\n confidence: number;\n trajectoryIds: string[];\n}\n\nexport interface BehaviorConfig {\n minFrequency: number;\n minSessions: number;\n confidenceThreshold: number;\n}\n\n// ─── Signal Extraction ───────────────────────────────────────────────────────\n\n/**\n * Detect topic revisitation: same goal fingerprint appearing in 3+ sessions.\n */\nfunction detectTopicRevisitation(\n trajectories: CausalTrajectoryRecord[],\n config: BehaviorConfig,\n): CausalBehaviorSignal[] {\n const goalGroups = new Map<string, { sessions: Set<string>; trajectoryIds: string[]; goal: string }>();\n\n for (const t of trajectories) {\n const tokens = normalizeRecallTokens(t.goal, []).sort().join(\" \");\n if (!tokens) continue;\n const group = goalGroups.get(tokens) ?? { sessions: new Set(), trajectoryIds: [], goal: t.goal };\n group.sessions.add(t.sessionKey);\n group.trajectoryIds.push(t.trajectoryId);\n goalGroups.set(tokens, group);\n }\n\n const signals: CausalBehaviorSignal[] = [];\n for (const [_key, group] of goalGroups) {\n if (group.trajectoryIds.length < config.minFrequency) continue;\n if (group.sessions.size < config.minSessions) continue;\n\n signals.push({\n signalType: \"topic_revisitation\",\n pattern: group.goal,\n frequency: group.trajectoryIds.length,\n sessionCount: group.sessions.size,\n confidence: Math.min(1, 0.5 + (group.sessions.size / 10)),\n trajectoryIds: group.trajectoryIds.slice(0, 10),\n });\n }\n\n return signals;\n}\n\n/**\n * Detect action patterns: same action with >= 80% success rate, 4+ occurrences.\n */\nfunction detectActionPatterns(\n trajectories: CausalTrajectoryRecord[],\n config: BehaviorConfig,\n): CausalBehaviorSignal[] {\n const actionGroups = new Map<string, {\n sessions: Set<string>;\n trajectoryIds: string[];\n action: string;\n successCount: number;\n totalCount: number;\n }>();\n\n for (const t of trajectories) {\n const tokens = normalizeRecallTokens(t.actionSummary, []).sort().join(\" \");\n if (!tokens) continue;\n const group = actionGroups.get(tokens) ?? {\n sessions: new Set(),\n trajectoryIds: [],\n action: t.actionSummary,\n successCount: 0,\n totalCount: 0,\n };\n group.sessions.add(t.sessionKey);\n group.trajectoryIds.push(t.trajectoryId);\n group.totalCount++;\n if (t.outcomeKind === \"success\") group.successCount++;\n actionGroups.set(tokens, group);\n }\n\n const signals: CausalBehaviorSignal[] = [];\n for (const [_key, group] of actionGroups) {\n if (group.totalCount < Math.max(config.minFrequency, 4)) continue;\n if (group.sessions.size < config.minSessions) continue;\n const successRate = group.successCount / group.totalCount;\n if (successRate < 0.8) continue;\n\n signals.push({\n signalType: \"action_pattern\",\n pattern: group.action,\n frequency: group.totalCount,\n sessionCount: group.sessions.size,\n confidence: Math.min(1, 0.6 + (successRate * 0.3)),\n trajectoryIds: group.trajectoryIds.slice(0, 10),\n });\n }\n\n return signals;\n}\n\n/**\n * Detect outcome preferences: consistent retry patterns leading to success.\n * When a trajectory fails and is retried (via chain edges) successfully,\n * it indicates a strong preference for that outcome.\n */\nfunction detectOutcomePreferences(\n trajectories: CausalTrajectoryRecord[],\n chainIndex: CausalChainIndex,\n config: BehaviorConfig,\n): CausalBehaviorSignal[] {\n const retrySuccesses = new Map<string, {\n sessions: Set<string>;\n trajectoryIds: string[];\n goal: string;\n count: number;\n }>();\n\n const trajectoryMap = new Map(trajectories.map((t) => [t.trajectoryId, t]));\n\n for (const [edgeId, edge] of Object.entries(chainIndex.edges)) {\n if (edge.edgeType !== \"retry\") continue;\n\n const from = trajectoryMap.get(edge.fromTrajectoryId);\n const to = trajectoryMap.get(edge.toTrajectoryId);\n if (!from || !to) continue;\n if (from.outcomeKind !== \"failure\" || to.outcomeKind !== \"success\") continue;\n\n const goalTokens = normalizeRecallTokens(from.goal, []).sort().join(\" \");\n const group = retrySuccesses.get(goalTokens) ?? {\n sessions: new Set(),\n trajectoryIds: [],\n goal: from.goal,\n count: 0,\n };\n group.sessions.add(from.sessionKey);\n group.sessions.add(to.sessionKey);\n group.trajectoryIds.push(from.trajectoryId, to.trajectoryId);\n group.count++;\n retrySuccesses.set(goalTokens, group);\n }\n\n const signals: CausalBehaviorSignal[] = [];\n for (const [_key, group] of retrySuccesses) {\n if (group.count < config.minFrequency) continue;\n if (group.sessions.size < config.minSessions) continue;\n\n signals.push({\n signalType: \"outcome_preference\",\n pattern: group.goal,\n frequency: group.count,\n sessionCount: group.sessions.size,\n confidence: Math.min(1, 0.7 + (group.count / 20)),\n trajectoryIds: [...new Set(group.trajectoryIds)].slice(0, 10),\n });\n }\n\n return signals;\n}\n\n// ─── Preference Synthesis ────────────────────────────────────────────────────\n\n/**\n * Convert behavioral signals into ConsolidatedPreference entries\n * that can be merged with existing IRC preference output.\n */\nexport function synthesizeCausalPreferences(\n signals: CausalBehaviorSignal[],\n confidenceThreshold: number,\n): ConsolidatedPreference[] {\n const preferences: ConsolidatedPreference[] = [];\n\n for (const signal of signals) {\n if (signal.confidence < confidenceThreshold) continue;\n\n let statement: string;\n switch (signal.signalType) {\n case \"topic_revisitation\":\n statement = `The user frequently works on: ${signal.pattern}. This topic has been revisited across ${signal.sessionCount} sessions.`;\n break;\n case \"action_pattern\":\n statement = `The user prefers this approach: ${signal.pattern}. This action pattern has been successful ${signal.frequency} times.`;\n break;\n case \"outcome_preference\":\n statement = `The user persistently pursues: ${signal.pattern}. They retry until successful, indicating strong preference.`;\n break;\n case \"phrasing_style\":\n statement = `The user's phrasing pattern: ${signal.pattern}`;\n break;\n }\n\n preferences.push({\n statement,\n sourceIds: signal.trajectoryIds.slice(0, 5),\n category: \"preference\",\n confidence: signal.confidence,\n keywords: normalizeRecallTokens(signal.pattern, []).slice(0, 10),\n });\n }\n\n return preferences;\n}\n\n// ─── Causal Impact Score ─────────────────────────────────────────────────────\n\n/**\n * Compute the causal impact score for a memory based on its\n * presence in causal chains. Used in lifecycle heat/decay.\n *\n * Formula: 0.1 * incomingEdges + 0.15 * outgoingEdges, clamped to [0, 0.3]\n */\nexport function computeCausalImpactScore(\n memoryId: string,\n chainIndex: CausalChainIndex,\n): number {\n // Memory IDs don't directly map to trajectory IDs, but trajectory-based\n // memories may reference their source trajectory ID. For now, check\n // if the memoryId appears as a trajectory ID in the chain index.\n const incoming = chainIndex.incoming[memoryId]?.length ?? 0;\n const outgoing = chainIndex.outgoing[memoryId]?.length ?? 0;\n const raw = 0.1 * incoming + 0.15 * outgoing;\n return Math.min(0.3, Math.max(0, raw));\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Extract all behavioral signals from causal trajectories and chain analysis.\n */\nexport async function extractCausalBehaviorSignals(options: {\n memoryDir: string;\n causalTrajectoryStoreDir?: string;\n config: BehaviorConfig;\n}): Promise<CausalBehaviorSignal[]> {\n try {\n const { memoryDir, causalTrajectoryStoreDir, config: behaviorConfig } = options;\n\n // Read all trajectories\n const root = causalTrajectoryStoreDir\n ? path.join(memoryDir, causalTrajectoryStoreDir)\n : path.join(memoryDir, \"state\", \"causal-trajectories\");\n const trajectoriesDir = path.join(root, \"trajectories\");\n const files = await listJsonFiles(trajectoriesDir).catch(() => [] as string[]);\n\n const trajectories: CausalTrajectoryRecord[] = [];\n for (const filePath of files) {\n try {\n const raw = await readJsonFile(filePath);\n if (isRecord(raw) && typeof raw.trajectoryId === \"string\") {\n trajectories.push(raw as unknown as CausalTrajectoryRecord);\n }\n } catch {\n // skip\n }\n }\n\n if (trajectories.length === 0) return [];\n\n // Read chain index\n const chainsDir = resolveChainsDir(memoryDir, causalTrajectoryStoreDir);\n const chainIndex = await readChainIndex(chainsDir);\n\n // Extract all signal types\n const signals: CausalBehaviorSignal[] = [\n ...detectTopicRevisitation(trajectories, behaviorConfig),\n ...detectActionPatterns(trajectories, behaviorConfig),\n ...detectOutcomePreferences(trajectories, chainIndex, behaviorConfig),\n ];\n\n log.debug(`[cmc] extracted ${signals.length} behavioral signal(s) from ${trajectories.length} trajectories`);\n return signals;\n } catch (error) {\n log.warn(`[cmc] behavioral signal extraction failed (non-fatal): ${error instanceof Error ? error.message : String(error)}`);\n return [];\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/causal-behavior.ts"],"sourcesContent":["/**\n * causal-behavior.ts — CMC Phase 4: Implicit Behavioral Preference Learning\n *\n * Extracts behavioral signals from causal chain analysis. Unlike explicit\n * preference extraction (which reads text), this derives preferences from\n * patterns of action: what goals recur, what actions succeed repeatedly,\n * what outcomes are consistently pursued.\n *\n * Key insight: \"Preferences are recurring causal pathways.\"\n */\n\nimport type { CausalTrajectoryRecord } from \"./causal-trajectory.js\";\nimport type { CausalChainIndex } from \"./causal-chain.js\";\nimport { readChainIndex, resolveChainsDir } from \"./causal-chain.js\";\nimport { normalizeRecallTokens } from \"./recall-tokenization.js\";\nimport { topicOverlapScore } from \"./boxes.js\";\nimport { listJsonFiles, readJsonFile } from \"./json-store.js\";\nimport { isRecord } from \"./store-contract.js\";\nimport type { ConsolidatedPreference } from \"./compounding/preference-consolidator.js\";\nimport path from \"node:path\";\nimport { log } from \"./logger.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type CausalBehaviorSignalType =\n | \"topic_revisitation\"\n | \"action_pattern\"\n | \"outcome_preference\"\n | \"phrasing_style\";\n\nexport interface CausalBehaviorSignal {\n signalType: CausalBehaviorSignalType;\n pattern: string;\n frequency: number;\n sessionCount: number;\n confidence: number;\n trajectoryIds: string[];\n}\n\nexport interface BehaviorConfig {\n minFrequency: number;\n minSessions: number;\n confidenceThreshold: number;\n}\n\n// ─── Signal Extraction ───────────────────────────────────────────────────────\n\n/**\n * Detect topic revisitation: same goal fingerprint appearing in 3+ sessions.\n */\nfunction detectTopicRevisitation(\n trajectories: CausalTrajectoryRecord[],\n config: BehaviorConfig,\n): CausalBehaviorSignal[] {\n const goalGroups = new Map<string, { sessions: Set<string>; trajectoryIds: string[]; goal: string }>();\n\n for (const t of trajectories) {\n const tokens = normalizeRecallTokens(t.goal, []).sort().join(\" \");\n if (!tokens) continue;\n const group = goalGroups.get(tokens) ?? { sessions: new Set(), trajectoryIds: [], goal: t.goal };\n group.sessions.add(t.sessionKey);\n group.trajectoryIds.push(t.trajectoryId);\n goalGroups.set(tokens, group);\n }\n\n const signals: CausalBehaviorSignal[] = [];\n for (const [_key, group] of goalGroups) {\n if (group.trajectoryIds.length < config.minFrequency) continue;\n if (group.sessions.size < config.minSessions) continue;\n\n signals.push({\n signalType: \"topic_revisitation\",\n pattern: group.goal,\n frequency: group.trajectoryIds.length,\n sessionCount: group.sessions.size,\n confidence: Math.min(1, 0.5 + (group.sessions.size / 10)),\n trajectoryIds: group.trajectoryIds.slice(0, 10),\n });\n }\n\n return signals;\n}\n\n/**\n * Detect action patterns: same action with >= 80% success rate, 4+ occurrences.\n */\nfunction detectActionPatterns(\n trajectories: CausalTrajectoryRecord[],\n config: BehaviorConfig,\n): CausalBehaviorSignal[] {\n const actionGroups = new Map<string, {\n sessions: Set<string>;\n trajectoryIds: string[];\n action: string;\n successCount: number;\n totalCount: number;\n }>();\n\n for (const t of trajectories) {\n const tokens = normalizeRecallTokens(t.actionSummary, []).sort().join(\" \");\n if (!tokens) continue;\n const group = actionGroups.get(tokens) ?? {\n sessions: new Set(),\n trajectoryIds: [],\n action: t.actionSummary,\n successCount: 0,\n totalCount: 0,\n };\n group.sessions.add(t.sessionKey);\n group.trajectoryIds.push(t.trajectoryId);\n group.totalCount++;\n if (t.outcomeKind === \"success\") group.successCount++;\n actionGroups.set(tokens, group);\n }\n\n const signals: CausalBehaviorSignal[] = [];\n for (const [_key, group] of actionGroups) {\n if (group.totalCount < Math.max(config.minFrequency, 4)) continue;\n if (group.sessions.size < config.minSessions) continue;\n const successRate = group.successCount / group.totalCount;\n if (successRate < 0.8) continue;\n\n signals.push({\n signalType: \"action_pattern\",\n pattern: group.action,\n frequency: group.totalCount,\n sessionCount: group.sessions.size,\n confidence: Math.min(1, 0.6 + (successRate * 0.3)),\n trajectoryIds: group.trajectoryIds.slice(0, 10),\n });\n }\n\n return signals;\n}\n\n/**\n * Detect outcome preferences: consistent retry patterns leading to success.\n * When a trajectory fails and is retried (via chain edges) successfully,\n * it indicates a strong preference for that outcome.\n */\nfunction detectOutcomePreferences(\n trajectories: CausalTrajectoryRecord[],\n chainIndex: CausalChainIndex,\n config: BehaviorConfig,\n): CausalBehaviorSignal[] {\n const retrySuccesses = new Map<string, {\n sessions: Set<string>;\n trajectoryIds: string[];\n goal: string;\n count: number;\n }>();\n\n const trajectoryMap = new Map(trajectories.map((t) => [t.trajectoryId, t]));\n\n for (const [edgeId, edge] of Object.entries(chainIndex.edges)) {\n if (edge.edgeType !== \"retry\") continue;\n\n const from = trajectoryMap.get(edge.fromTrajectoryId);\n const to = trajectoryMap.get(edge.toTrajectoryId);\n if (!from || !to) continue;\n if (from.outcomeKind !== \"failure\" || to.outcomeKind !== \"success\") continue;\n\n const goalTokens = normalizeRecallTokens(from.goal, []).sort().join(\" \");\n const group = retrySuccesses.get(goalTokens) ?? {\n sessions: new Set(),\n trajectoryIds: [],\n goal: from.goal,\n count: 0,\n };\n group.sessions.add(from.sessionKey);\n group.sessions.add(to.sessionKey);\n group.trajectoryIds.push(from.trajectoryId, to.trajectoryId);\n group.count++;\n retrySuccesses.set(goalTokens, group);\n }\n\n const signals: CausalBehaviorSignal[] = [];\n for (const [_key, group] of retrySuccesses) {\n if (group.count < config.minFrequency) continue;\n if (group.sessions.size < config.minSessions) continue;\n\n signals.push({\n signalType: \"outcome_preference\",\n pattern: group.goal,\n frequency: group.count,\n sessionCount: group.sessions.size,\n confidence: Math.min(1, 0.7 + (group.count / 20)),\n trajectoryIds: [...new Set(group.trajectoryIds)].slice(0, 10),\n });\n }\n\n return signals;\n}\n\n// ─── Preference Synthesis ────────────────────────────────────────────────────\n\n/**\n * Convert behavioral signals into ConsolidatedPreference entries\n * that can be merged with existing IRC preference output.\n */\nexport function synthesizeCausalPreferences(\n signals: CausalBehaviorSignal[],\n confidenceThreshold: number,\n): ConsolidatedPreference[] {\n const preferences: ConsolidatedPreference[] = [];\n\n for (const signal of signals) {\n if (signal.confidence < confidenceThreshold) continue;\n\n let statement: string;\n switch (signal.signalType) {\n case \"topic_revisitation\":\n statement = `The user frequently works on: ${signal.pattern}. This topic has been revisited across ${signal.sessionCount} sessions.`;\n break;\n case \"action_pattern\":\n statement = `The user prefers this approach: ${signal.pattern}. This action pattern has been successful ${signal.frequency} times.`;\n break;\n case \"outcome_preference\":\n statement = `The user persistently pursues: ${signal.pattern}. They retry until successful, indicating strong preference.`;\n break;\n case \"phrasing_style\":\n statement = `The user's phrasing pattern: ${signal.pattern}`;\n break;\n }\n\n preferences.push({\n statement,\n sourceIds: signal.trajectoryIds.slice(0, 5),\n category: \"preference\",\n confidence: signal.confidence,\n keywords: normalizeRecallTokens(signal.pattern, []).slice(0, 10),\n });\n }\n\n return preferences;\n}\n\n// ─── Causal Impact Score ─────────────────────────────────────────────────────\n\n/**\n * Compute the causal impact score for a memory based on its\n * presence in causal chains. Used in lifecycle heat/decay.\n *\n * Formula: 0.1 * incomingEdges + 0.15 * outgoingEdges, clamped to [0, 0.3]\n */\nexport function computeCausalImpactScore(\n memoryId: string,\n chainIndex: CausalChainIndex,\n): number {\n // Memory IDs don't directly map to trajectory IDs, but trajectory-based\n // memories may reference their source trajectory ID. For now, check\n // if the memoryId appears as a trajectory ID in the chain index.\n const incoming = chainIndex.incoming[memoryId]?.length ?? 0;\n const outgoing = chainIndex.outgoing[memoryId]?.length ?? 0;\n const raw = 0.1 * incoming + 0.15 * outgoing;\n return Math.min(0.3, Math.max(0, raw));\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Extract all behavioral signals from causal trajectories and chain analysis.\n */\nexport async function extractCausalBehaviorSignals(options: {\n memoryDir: string;\n causalTrajectoryStoreDir?: string;\n config: BehaviorConfig;\n}): Promise<CausalBehaviorSignal[]> {\n try {\n const { memoryDir, causalTrajectoryStoreDir, config: behaviorConfig } = options;\n\n // Read all trajectories\n const root = causalTrajectoryStoreDir\n ? path.join(memoryDir, causalTrajectoryStoreDir)\n : path.join(memoryDir, \"state\", \"causal-trajectories\");\n const trajectoriesDir = path.join(root, \"trajectories\");\n const files = await listJsonFiles(trajectoriesDir).catch(() => [] as string[]);\n\n const trajectories: CausalTrajectoryRecord[] = [];\n for (const filePath of files) {\n try {\n const raw = await readJsonFile(filePath);\n if (isRecord(raw) && typeof raw.trajectoryId === \"string\") {\n trajectories.push(raw as unknown as CausalTrajectoryRecord);\n }\n } catch {\n // skip\n }\n }\n\n if (trajectories.length === 0) return [];\n\n // Read chain index\n const chainsDir = resolveChainsDir(memoryDir, causalTrajectoryStoreDir);\n const chainIndex = await readChainIndex(chainsDir);\n\n // Extract all signal types\n const signals: CausalBehaviorSignal[] = [\n ...detectTopicRevisitation(trajectories, behaviorConfig),\n ...detectActionPatterns(trajectories, behaviorConfig),\n ...detectOutcomePreferences(trajectories, chainIndex, behaviorConfig),\n ];\n\n log.debug(`[cmc] extracted ${signals.length} behavioral signal(s) from ${trajectories.length} trajectories`);\n return signals;\n } catch (error) {\n log.warn(`[cmc] behavioral signal extraction failed (non-fatal): ${error instanceof Error ? error.message : String(error)}`);\n return [];\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/causal-chain.js
CHANGED
|
@@ -5,31 +5,32 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
buildExtensionsBlockForConsolidation,
|
|
7
7
|
runPostConsolidationMaterialize
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-55FXRRSJ.js";
|
|
9
9
|
import "./chunk-EJI5XIBB.js";
|
|
10
10
|
import {
|
|
11
11
|
FallbackLlmClient
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-CRU27Q4J.js";
|
|
13
|
+
import "./chunk-Q7FJ5ZHM.js";
|
|
14
14
|
import "./chunk-ODWDQNRE.js";
|
|
15
15
|
import "./chunk-Y27UJK6V.js";
|
|
16
16
|
import "./chunk-UZB5KHKX.js";
|
|
17
17
|
import "./chunk-URB2WSKZ.js";
|
|
18
|
-
import "./chunk-MARWOCVP.js";
|
|
19
18
|
import "./chunk-DT5TVLJE.js";
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-DCE6SQLA.js";
|
|
20
|
+
import "./chunk-YNJHCGDT.js";
|
|
22
21
|
import "./chunk-4KAN3GZ3.js";
|
|
23
|
-
import "./chunk-
|
|
24
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-43EKP2UK.js";
|
|
23
|
+
import "./chunk-PFV5C235.js";
|
|
24
|
+
import "./chunk-RULE4VG5.js";
|
|
25
25
|
import "./chunk-SCU65EZI.js";
|
|
26
26
|
import "./chunk-BOUYNNYD.js";
|
|
27
27
|
import "./chunk-DM2T26WE.js";
|
|
28
28
|
import "./chunk-QSVPYQPG.js";
|
|
29
29
|
import "./chunk-M62O4P4T.js";
|
|
30
30
|
import "./chunk-4DJQYKMN.js";
|
|
31
|
-
import "./chunk-
|
|
31
|
+
import "./chunk-G7D6GZ5J.js";
|
|
32
32
|
import "./chunk-FAAFWE4G.js";
|
|
33
|
+
import "./chunk-MARWOCVP.js";
|
|
33
34
|
import {
|
|
34
35
|
log
|
|
35
36
|
} from "./chunk-2ODBA7MQ.js";
|
|
@@ -40,6 +41,8 @@ import {
|
|
|
40
41
|
listJsonFiles,
|
|
41
42
|
readJsonFile
|
|
42
43
|
} from "./chunk-LPSF4OQH.js";
|
|
44
|
+
import "./chunk-A6XUJE5D.js";
|
|
45
|
+
import "./chunk-PZ5AY32C.js";
|
|
43
46
|
|
|
44
47
|
// src/causal-consolidation.ts
|
|
45
48
|
import { createHash } from "crypto";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/causal-consolidation.ts"],"sourcesContent":["/**\n * causal-consolidation.ts — CMC Phase 2: LLM-Assisted Causal Consolidation\n *\n * Uses an LLM to analyze causal trajectory patterns across sessions.\n * The LLM receives the causal chain graph as context — connected trajectories\n * from different sessions — and identifies recurring behavioral patterns,\n * preference signals, and actionable rules.\n *\n * This is the core CMC innovation: the LLM gets cross-session causal context\n * that no other memory system provides. It can see that a user investigated\n * a bug in session 1, attempted a fix in session 2, and succeeded in session 3 —\n * and synthesize a rule or preference from that chain.\n */\n\nimport { createHash } from \"node:crypto\";\nimport type { CausalTrajectoryRecord } from \"./causal-trajectory.js\";\nimport { readChainIndex, resolveChainsDir, type CausalChainIndex, type CausalEdge } from \"./causal-chain.js\";\nimport { listJsonFiles, readJsonFile } from \"./json-store.js\";\nimport { isRecord } from \"./store-contract.js\";\nimport { FallbackLlmClient } from \"./fallback-llm.js\";\nimport type { GatewayConfig, MemoryFile, PluginConfig } from \"./types.js\";\nimport path from \"node:path\";\nimport { log } from \"./logger.js\";\nimport { runPostConsolidationMaterialize } from \"./connectors/codex-materialize-runner.js\";\nimport type { MaterializeResult, RolloutSummaryInput } from \"./connectors/codex-materialize.js\";\nimport { buildExtensionsBlockForConsolidation } from \"./semantic-consolidation.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface CausalPatternCandidate {\n id: string;\n sourceType: \"causal-pattern\";\n subject: string;\n category: \"principle\" | \"rule\";\n content: string;\n score: number;\n rationale: string;\n outcome: null;\n provenance: string[];\n agent: string | null;\n workflow: string | null;\n}\n\nexport interface ConsolidationConfig {\n minRecurrence: number;\n minSessions: number;\n successThreshold: number;\n}\n\nexport interface LlmConsolidationResult {\n rules: Array<{\n content: string;\n category: \"rule\" | \"principle\" | \"preference\";\n confidence: number;\n evidence: string[];\n }>;\n preferences: Array<{\n statement: string;\n confidence: number;\n evidence: string[];\n }>;\n}\n\n// ─── Trajectory Reading ──────────────────────────────────────────────────────\n\nasync function readAllTrajectories(\n memoryDir: string,\n causalTrajectoryStoreDir?: string,\n): Promise<CausalTrajectoryRecord[]> {\n const root = causalTrajectoryStoreDir\n ? path.join(memoryDir, causalTrajectoryStoreDir)\n : path.join(memoryDir, \"state\", \"causal-trajectories\");\n const trajectoriesDir = path.join(root, \"trajectories\");\n\n const files = await listJsonFiles(trajectoriesDir).catch(() => [] as string[]);\n const results: CausalTrajectoryRecord[] = [];\n\n for (const filePath of files) {\n try {\n const raw = await readJsonFile(filePath);\n if (isRecord(raw) && typeof raw.trajectoryId === \"string\") {\n results.push(raw as unknown as CausalTrajectoryRecord);\n }\n } catch {\n // skip invalid\n }\n }\n\n return results;\n}\n\n// ─── Context Formatting ──────────────────────────────────────────────────────\n\n/**\n * Format trajectories and their causal connections as a readable context\n * for the LLM. Groups by session and shows chain connections.\n */\nfunction formatCausalContext(\n trajectories: CausalTrajectoryRecord[],\n chainIndex: CausalChainIndex,\n maxChars: number = 8000,\n): string {\n // Group trajectories by session\n const bySession = new Map<string, CausalTrajectoryRecord[]>();\n for (const t of trajectories) {\n const list = bySession.get(t.sessionKey) ?? [];\n list.push(t);\n bySession.set(t.sessionKey, list);\n }\n\n const lines: string[] = [];\n lines.push(`## Causal Trajectories (${trajectories.length} across ${bySession.size} sessions)`);\n lines.push(\"\");\n\n // Format each session's trajectories\n for (const [sessionKey, sessionTrajs] of bySession) {\n lines.push(`### Session: ${sessionKey}`);\n for (const t of sessionTrajs.slice(0, 5)) {\n const outcome = t.outcomeKind === \"success\" ? \"+\" : t.outcomeKind === \"failure\" ? \"-\" : \"~\";\n lines.push(`[${outcome}] Goal: ${t.goal}`);\n lines.push(` Action: ${t.actionSummary}`);\n lines.push(` Outcome: ${t.outcomeSummary}`);\n if (t.followUpSummary) lines.push(` Follow-up: ${t.followUpSummary}`);\n if (t.entityRefs?.length) lines.push(` Entities: ${t.entityRefs.join(\", \")}`);\n }\n lines.push(\"\");\n }\n\n // Format causal chain connections\n const edgeCount = Object.keys(chainIndex.edges).length;\n if (edgeCount > 0) {\n lines.push(`## Cross-Session Causal Chains (${edgeCount} connections)`);\n lines.push(\"\");\n\n const trajectoryMap = new Map(trajectories.map((t) => [t.trajectoryId, t]));\n const shown = new Set<string>();\n\n for (const [edgeId, edge] of Object.entries(chainIndex.edges)) {\n if (shown.size >= 10) break; // limit output size\n const from = trajectoryMap.get(edge.fromTrajectoryId);\n const to = trajectoryMap.get(edge.toTrajectoryId);\n if (!from || !to) continue;\n\n lines.push(`${edge.edgeType}: \"${from.goal}\" (${from.sessionKey}) → \"${to.goal}\" (${to.sessionKey})`);\n shown.add(edgeId);\n }\n lines.push(\"\");\n }\n\n const result = lines.join(\"\\n\");\n return result.length > maxChars ? result.slice(0, maxChars) + \"\\n[truncated]\" : result;\n}\n\n// ─── LLM Consolidation ──────────────────────────────────────────────────────\n\nconst CONSOLIDATION_PROMPT = `You are analyzing a user's causal trajectory history across multiple sessions. Trajectories record what the user tried to do (goal), what they did (action), and what happened (outcome).\n\nYour job is to identify:\n1. BEHAVIORAL RULES: Recurring patterns where the same approach consistently succeeds or fails. These should be actionable guidance for future sessions.\n2. PREFERENCES: What the user cares about, prefers, or consistently chooses — even if never explicitly stated. Infer preferences from what they repeatedly do, retry until successful, or always include in their workflow.\n\nIMPORTANT:\n- Look for CROSS-SESSION patterns — things that repeat across different sessions are more significant than within-session patterns.\n- A user who retries the same goal across sessions has a strong implicit preference for that outcome.\n- Consistent action choices reveal preferences even when the user never says \"I prefer X.\"\n- Frame preferences as \"The user would prefer responses that...\" when applicable.\n\nOutput valid JSON only:\n{\n \"rules\": [\n {\"content\": \"actionable rule text\", \"category\": \"rule|principle\", \"confidence\": 0.0-1.0, \"evidence\": [\"trajectory IDs\"]}\n ],\n \"preferences\": [\n {\"statement\": \"The user would prefer...\", \"confidence\": 0.0-1.0, \"evidence\": [\"trajectory IDs\"]}\n ]\n}\n\nIf no clear patterns exist, return {\"rules\": [], \"preferences\": []}.`;\n\nasync function consolidateWithLlm(\n context: string,\n llm: FallbackLlmClient,\n agentId?: string,\n): Promise<LlmConsolidationResult> {\n const response = await llm.chatCompletion(\n [\n { role: \"system\", content: CONSOLIDATION_PROMPT },\n { role: \"user\", content: context },\n ],\n { temperature: 0.2, maxTokens: 2000, agentId },\n );\n\n if (!response?.content) {\n return { rules: [], preferences: [] };\n }\n\n try {\n // Extract JSON from response (may have markdown code fences)\n let jsonStr = response.content.trim();\n const fenceMatch = jsonStr.match(/```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?\\s*```/);\n if (fenceMatch) jsonStr = fenceMatch[1];\n\n const parsed = JSON.parse(jsonStr);\n return {\n rules: Array.isArray(parsed.rules) ? parsed.rules.filter(\n (r: any) => typeof r.content === \"string\" && r.content.length > 5,\n ) : [],\n preferences: Array.isArray(parsed.preferences) ? parsed.preferences.filter(\n (p: any) => typeof p.statement === \"string\" && p.statement.length > 5,\n ) : [],\n };\n } catch {\n log.warn(\"[cmc] failed to parse LLM consolidation response\");\n return { rules: [], preferences: [] };\n }\n}\n\n// ─── Candidate Generation ────────────────────────────────────────────────────\n\nfunction stablePatternId(content: string): string {\n const digest = createHash(\"sha256\")\n .update(`causal-pattern\\0${content}`)\n .digest(\"hex\")\n .slice(0, 16);\n return `causal-pattern:${digest}`;\n}\n\nfunction llmResultToCandidates(result: LlmConsolidationResult): CausalPatternCandidate[] {\n const candidates: CausalPatternCandidate[] = [];\n\n for (const rule of result.rules) {\n const category = rule.category === \"principle\" ? \"principle\" : \"rule\";\n candidates.push({\n id: stablePatternId(rule.content),\n sourceType: \"causal-pattern\",\n subject: rule.content.slice(0, 80),\n category,\n content: rule.content,\n score: Math.min(1, rule.confidence ?? 0.7),\n rationale: \"LLM-identified causal pattern from cross-session trajectory analysis\",\n outcome: null,\n provenance: (rule.evidence ?? []).slice(0, 5),\n agent: null,\n workflow: null,\n });\n }\n\n return candidates;\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Run LLM-assisted consolidation: read trajectories, format causal context,\n * ask LLM to identify patterns and preferences.\n */\nexport async function deriveCausalPromotionCandidates(options: {\n memoryDir: string;\n causalTrajectoryStoreDir?: string;\n config: ConsolidationConfig;\n gatewayConfig?: GatewayConfig;\n gatewayAgentId?: string;\n pluginConfig?: PluginConfig;\n}): Promise<CausalPatternCandidate[]> {\n try {\n const trajectories = await readAllTrajectories(options.memoryDir, options.causalTrajectoryStoreDir);\n if (trajectories.length < options.config.minRecurrence) return [];\n\n const chainsDir = resolveChainsDir(options.memoryDir, options.causalTrajectoryStoreDir);\n const chainIndex = await readChainIndex(chainsDir);\n\n // Format the causal context for the LLM\n let context = formatCausalContext(trajectories, chainIndex);\n\n // Append memory extensions block if available (#382)\n if (options.pluginConfig) {\n const extBlock = await buildExtensionsBlockForConsolidation(options.pluginConfig);\n if (extBlock.length > 0) {\n context += \"\\n\\n\" + extBlock;\n }\n }\n\n // If no LLM available, fall back to empty (no deterministic fallback)\n const llm = new FallbackLlmClient(options.gatewayConfig);\n if (!llm.isAvailable(options.gatewayAgentId)) {\n log.debug(\"[cmc] no LLM available for consolidation — skipping\");\n return [];\n }\n\n // Call LLM for pattern analysis\n const result = await consolidateWithLlm(context, llm, options.gatewayAgentId);\n const candidates = llmResultToCandidates(result);\n\n log.debug(`[cmc] LLM consolidation produced ${candidates.length} rule(s) and ${result.preferences.length} preference(s)`);\n return candidates;\n } catch (error) {\n log.warn(`[cmc] consolidation failed (non-fatal): ${error instanceof Error ? error.message : String(error)}`);\n return [];\n }\n}\n\n/**\n * Get LLM-synthesized preferences from causal trajectory analysis.\n * Returns formatted preference statements for recall injection.\n */\nexport async function synthesizeCausalPreferencesViaLlm(options: {\n memoryDir: string;\n causalTrajectoryStoreDir?: string;\n gatewayConfig?: GatewayConfig;\n gatewayAgentId?: string;\n minTrajectories?: number;\n}): Promise<string | null> {\n try {\n const trajectories = await readAllTrajectories(options.memoryDir, options.causalTrajectoryStoreDir);\n if (trajectories.length < (options.minTrajectories ?? 2)) return null;\n\n const chainsDir = resolveChainsDir(options.memoryDir, options.causalTrajectoryStoreDir);\n const chainIndex = await readChainIndex(chainsDir);\n const context = formatCausalContext(trajectories, chainIndex);\n\n const llm = new FallbackLlmClient(options.gatewayConfig);\n if (!llm.isAvailable(options.gatewayAgentId)) return null;\n\n const result = await consolidateWithLlm(context, llm, options.gatewayAgentId);\n if (result.preferences.length === 0 && result.rules.length === 0) return null;\n\n const lines: string[] = [\"## Behavioral Insights (from Causal Chain Analysis)\", \"\"];\n\n for (const pref of result.preferences) {\n lines.push(`- ${pref.statement}`);\n }\n\n for (const rule of result.rules) {\n lines.push(`- ${rule.content}`);\n }\n\n lines.push(\"\");\n return lines.join(\"\\n\");\n } catch (error) {\n log.warn(`[cmc] preference synthesis failed (non-fatal): ${error instanceof Error ? error.message : String(error)}`);\n return null;\n }\n}\n\n/**\n * Optional post-consolidation hook — materializes Codex-native memory artifacts\n * after a causal consolidation run. Guarded by `codexMaterializeMemories` and\n * `codexMaterializeOnConsolidation`. Returns `null` when disabled or when the\n * sentinel is missing (honors user hand-edits).\n *\n * Split from the orchestrator-owned flow so #378 avoids touching\n * orchestrator.ts while Wave 1 edits are in flight.\n */\nexport async function materializeAfterCausalConsolidation(options: {\n config: PluginConfig;\n namespace?: string;\n memories?: MemoryFile[];\n memoryDir?: string;\n codexHome?: string;\n rolloutSummaries?: RolloutSummaryInput[];\n now?: Date;\n}): Promise<MaterializeResult | null> {\n // Delegates to the shared post-consolidation helper — see\n // runPostConsolidationMaterialize in codex-materialize-runner.ts.\n return runPostConsolidationMaterialize(\"[cmc]\", options);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/causal-consolidation.ts"],"sourcesContent":["/**\n * causal-consolidation.ts — CMC Phase 2: LLM-Assisted Causal Consolidation\n *\n * Uses an LLM to analyze causal trajectory patterns across sessions.\n * The LLM receives the causal chain graph as context — connected trajectories\n * from different sessions — and identifies recurring behavioral patterns,\n * preference signals, and actionable rules.\n *\n * This is the core CMC innovation: the LLM gets cross-session causal context\n * that no other memory system provides. It can see that a user investigated\n * a bug in session 1, attempted a fix in session 2, and succeeded in session 3 —\n * and synthesize a rule or preference from that chain.\n */\n\nimport { createHash } from \"node:crypto\";\nimport type { CausalTrajectoryRecord } from \"./causal-trajectory.js\";\nimport { readChainIndex, resolveChainsDir, type CausalChainIndex, type CausalEdge } from \"./causal-chain.js\";\nimport { listJsonFiles, readJsonFile } from \"./json-store.js\";\nimport { isRecord } from \"./store-contract.js\";\nimport { FallbackLlmClient } from \"./fallback-llm.js\";\nimport type { GatewayConfig, MemoryFile, PluginConfig } from \"./types.js\";\nimport path from \"node:path\";\nimport { log } from \"./logger.js\";\nimport { runPostConsolidationMaterialize } from \"./connectors/codex-materialize-runner.js\";\nimport type { MaterializeResult, RolloutSummaryInput } from \"./connectors/codex-materialize.js\";\nimport { buildExtensionsBlockForConsolidation } from \"./semantic-consolidation.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface CausalPatternCandidate {\n id: string;\n sourceType: \"causal-pattern\";\n subject: string;\n category: \"principle\" | \"rule\";\n content: string;\n score: number;\n rationale: string;\n outcome: null;\n provenance: string[];\n agent: string | null;\n workflow: string | null;\n}\n\nexport interface ConsolidationConfig {\n minRecurrence: number;\n minSessions: number;\n successThreshold: number;\n}\n\nexport interface LlmConsolidationResult {\n rules: Array<{\n content: string;\n category: \"rule\" | \"principle\" | \"preference\";\n confidence: number;\n evidence: string[];\n }>;\n preferences: Array<{\n statement: string;\n confidence: number;\n evidence: string[];\n }>;\n}\n\n// ─── Trajectory Reading ──────────────────────────────────────────────────────\n\nasync function readAllTrajectories(\n memoryDir: string,\n causalTrajectoryStoreDir?: string,\n): Promise<CausalTrajectoryRecord[]> {\n const root = causalTrajectoryStoreDir\n ? path.join(memoryDir, causalTrajectoryStoreDir)\n : path.join(memoryDir, \"state\", \"causal-trajectories\");\n const trajectoriesDir = path.join(root, \"trajectories\");\n\n const files = await listJsonFiles(trajectoriesDir).catch(() => [] as string[]);\n const results: CausalTrajectoryRecord[] = [];\n\n for (const filePath of files) {\n try {\n const raw = await readJsonFile(filePath);\n if (isRecord(raw) && typeof raw.trajectoryId === \"string\") {\n results.push(raw as unknown as CausalTrajectoryRecord);\n }\n } catch {\n // skip invalid\n }\n }\n\n return results;\n}\n\n// ─── Context Formatting ──────────────────────────────────────────────────────\n\n/**\n * Format trajectories and their causal connections as a readable context\n * for the LLM. Groups by session and shows chain connections.\n */\nfunction formatCausalContext(\n trajectories: CausalTrajectoryRecord[],\n chainIndex: CausalChainIndex,\n maxChars: number = 8000,\n): string {\n // Group trajectories by session\n const bySession = new Map<string, CausalTrajectoryRecord[]>();\n for (const t of trajectories) {\n const list = bySession.get(t.sessionKey) ?? [];\n list.push(t);\n bySession.set(t.sessionKey, list);\n }\n\n const lines: string[] = [];\n lines.push(`## Causal Trajectories (${trajectories.length} across ${bySession.size} sessions)`);\n lines.push(\"\");\n\n // Format each session's trajectories\n for (const [sessionKey, sessionTrajs] of bySession) {\n lines.push(`### Session: ${sessionKey}`);\n for (const t of sessionTrajs.slice(0, 5)) {\n const outcome = t.outcomeKind === \"success\" ? \"+\" : t.outcomeKind === \"failure\" ? \"-\" : \"~\";\n lines.push(`[${outcome}] Goal: ${t.goal}`);\n lines.push(` Action: ${t.actionSummary}`);\n lines.push(` Outcome: ${t.outcomeSummary}`);\n if (t.followUpSummary) lines.push(` Follow-up: ${t.followUpSummary}`);\n if (t.entityRefs?.length) lines.push(` Entities: ${t.entityRefs.join(\", \")}`);\n }\n lines.push(\"\");\n }\n\n // Format causal chain connections\n const edgeCount = Object.keys(chainIndex.edges).length;\n if (edgeCount > 0) {\n lines.push(`## Cross-Session Causal Chains (${edgeCount} connections)`);\n lines.push(\"\");\n\n const trajectoryMap = new Map(trajectories.map((t) => [t.trajectoryId, t]));\n const shown = new Set<string>();\n\n for (const [edgeId, edge] of Object.entries(chainIndex.edges)) {\n if (shown.size >= 10) break; // limit output size\n const from = trajectoryMap.get(edge.fromTrajectoryId);\n const to = trajectoryMap.get(edge.toTrajectoryId);\n if (!from || !to) continue;\n\n lines.push(`${edge.edgeType}: \"${from.goal}\" (${from.sessionKey}) → \"${to.goal}\" (${to.sessionKey})`);\n shown.add(edgeId);\n }\n lines.push(\"\");\n }\n\n const result = lines.join(\"\\n\");\n return result.length > maxChars ? result.slice(0, maxChars) + \"\\n[truncated]\" : result;\n}\n\n// ─── LLM Consolidation ──────────────────────────────────────────────────────\n\nconst CONSOLIDATION_PROMPT = `You are analyzing a user's causal trajectory history across multiple sessions. Trajectories record what the user tried to do (goal), what they did (action), and what happened (outcome).\n\nYour job is to identify:\n1. BEHAVIORAL RULES: Recurring patterns where the same approach consistently succeeds or fails. These should be actionable guidance for future sessions.\n2. PREFERENCES: What the user cares about, prefers, or consistently chooses — even if never explicitly stated. Infer preferences from what they repeatedly do, retry until successful, or always include in their workflow.\n\nIMPORTANT:\n- Look for CROSS-SESSION patterns — things that repeat across different sessions are more significant than within-session patterns.\n- A user who retries the same goal across sessions has a strong implicit preference for that outcome.\n- Consistent action choices reveal preferences even when the user never says \"I prefer X.\"\n- Frame preferences as \"The user would prefer responses that...\" when applicable.\n\nOutput valid JSON only:\n{\n \"rules\": [\n {\"content\": \"actionable rule text\", \"category\": \"rule|principle\", \"confidence\": 0.0-1.0, \"evidence\": [\"trajectory IDs\"]}\n ],\n \"preferences\": [\n {\"statement\": \"The user would prefer...\", \"confidence\": 0.0-1.0, \"evidence\": [\"trajectory IDs\"]}\n ]\n}\n\nIf no clear patterns exist, return {\"rules\": [], \"preferences\": []}.`;\n\nasync function consolidateWithLlm(\n context: string,\n llm: FallbackLlmClient,\n agentId?: string,\n): Promise<LlmConsolidationResult> {\n const response = await llm.chatCompletion(\n [\n { role: \"system\", content: CONSOLIDATION_PROMPT },\n { role: \"user\", content: context },\n ],\n { temperature: 0.2, maxTokens: 2000, agentId },\n );\n\n if (!response?.content) {\n return { rules: [], preferences: [] };\n }\n\n try {\n // Extract JSON from response (may have markdown code fences)\n let jsonStr = response.content.trim();\n const fenceMatch = jsonStr.match(/```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?\\s*```/);\n if (fenceMatch) jsonStr = fenceMatch[1];\n\n const parsed = JSON.parse(jsonStr);\n return {\n rules: Array.isArray(parsed.rules) ? parsed.rules.filter(\n (r: any) => typeof r.content === \"string\" && r.content.length > 5,\n ) : [],\n preferences: Array.isArray(parsed.preferences) ? parsed.preferences.filter(\n (p: any) => typeof p.statement === \"string\" && p.statement.length > 5,\n ) : [],\n };\n } catch {\n log.warn(\"[cmc] failed to parse LLM consolidation response\");\n return { rules: [], preferences: [] };\n }\n}\n\n// ─── Candidate Generation ────────────────────────────────────────────────────\n\nfunction stablePatternId(content: string): string {\n const digest = createHash(\"sha256\")\n .update(`causal-pattern\\0${content}`)\n .digest(\"hex\")\n .slice(0, 16);\n return `causal-pattern:${digest}`;\n}\n\nfunction llmResultToCandidates(result: LlmConsolidationResult): CausalPatternCandidate[] {\n const candidates: CausalPatternCandidate[] = [];\n\n for (const rule of result.rules) {\n const category = rule.category === \"principle\" ? \"principle\" : \"rule\";\n candidates.push({\n id: stablePatternId(rule.content),\n sourceType: \"causal-pattern\",\n subject: rule.content.slice(0, 80),\n category,\n content: rule.content,\n score: Math.min(1, rule.confidence ?? 0.7),\n rationale: \"LLM-identified causal pattern from cross-session trajectory analysis\",\n outcome: null,\n provenance: (rule.evidence ?? []).slice(0, 5),\n agent: null,\n workflow: null,\n });\n }\n\n return candidates;\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Run LLM-assisted consolidation: read trajectories, format causal context,\n * ask LLM to identify patterns and preferences.\n */\nexport async function deriveCausalPromotionCandidates(options: {\n memoryDir: string;\n causalTrajectoryStoreDir?: string;\n config: ConsolidationConfig;\n gatewayConfig?: GatewayConfig;\n gatewayAgentId?: string;\n pluginConfig?: PluginConfig;\n}): Promise<CausalPatternCandidate[]> {\n try {\n const trajectories = await readAllTrajectories(options.memoryDir, options.causalTrajectoryStoreDir);\n if (trajectories.length < options.config.minRecurrence) return [];\n\n const chainsDir = resolveChainsDir(options.memoryDir, options.causalTrajectoryStoreDir);\n const chainIndex = await readChainIndex(chainsDir);\n\n // Format the causal context for the LLM\n let context = formatCausalContext(trajectories, chainIndex);\n\n // Append memory extensions block if available (#382)\n if (options.pluginConfig) {\n const extBlock = await buildExtensionsBlockForConsolidation(options.pluginConfig);\n if (extBlock.length > 0) {\n context += \"\\n\\n\" + extBlock;\n }\n }\n\n // If no LLM available, fall back to empty (no deterministic fallback)\n const llm = new FallbackLlmClient(options.gatewayConfig);\n if (!llm.isAvailable(options.gatewayAgentId)) {\n log.debug(\"[cmc] no LLM available for consolidation — skipping\");\n return [];\n }\n\n // Call LLM for pattern analysis\n const result = await consolidateWithLlm(context, llm, options.gatewayAgentId);\n const candidates = llmResultToCandidates(result);\n\n log.debug(`[cmc] LLM consolidation produced ${candidates.length} rule(s) and ${result.preferences.length} preference(s)`);\n return candidates;\n } catch (error) {\n log.warn(`[cmc] consolidation failed (non-fatal): ${error instanceof Error ? error.message : String(error)}`);\n return [];\n }\n}\n\n/**\n * Get LLM-synthesized preferences from causal trajectory analysis.\n * Returns formatted preference statements for recall injection.\n */\nexport async function synthesizeCausalPreferencesViaLlm(options: {\n memoryDir: string;\n causalTrajectoryStoreDir?: string;\n gatewayConfig?: GatewayConfig;\n gatewayAgentId?: string;\n minTrajectories?: number;\n}): Promise<string | null> {\n try {\n const trajectories = await readAllTrajectories(options.memoryDir, options.causalTrajectoryStoreDir);\n if (trajectories.length < (options.minTrajectories ?? 2)) return null;\n\n const chainsDir = resolveChainsDir(options.memoryDir, options.causalTrajectoryStoreDir);\n const chainIndex = await readChainIndex(chainsDir);\n const context = formatCausalContext(trajectories, chainIndex);\n\n const llm = new FallbackLlmClient(options.gatewayConfig);\n if (!llm.isAvailable(options.gatewayAgentId)) return null;\n\n const result = await consolidateWithLlm(context, llm, options.gatewayAgentId);\n if (result.preferences.length === 0 && result.rules.length === 0) return null;\n\n const lines: string[] = [\"## Behavioral Insights (from Causal Chain Analysis)\", \"\"];\n\n for (const pref of result.preferences) {\n lines.push(`- ${pref.statement}`);\n }\n\n for (const rule of result.rules) {\n lines.push(`- ${rule.content}`);\n }\n\n lines.push(\"\");\n return lines.join(\"\\n\");\n } catch (error) {\n log.warn(`[cmc] preference synthesis failed (non-fatal): ${error instanceof Error ? error.message : String(error)}`);\n return null;\n }\n}\n\n/**\n * Optional post-consolidation hook — materializes Codex-native memory artifacts\n * after a causal consolidation run. Guarded by `codexMaterializeMemories` and\n * `codexMaterializeOnConsolidation`. Returns `null` when disabled or when the\n * sentinel is missing (honors user hand-edits).\n *\n * Split from the orchestrator-owned flow so #378 avoids touching\n * orchestrator.ts while Wave 1 edits are in flight.\n */\nexport async function materializeAfterCausalConsolidation(options: {\n config: PluginConfig;\n namespace?: string;\n memories?: MemoryFile[];\n memoryDir?: string;\n codexHome?: string;\n rolloutSummaries?: RolloutSummaryInput[];\n now?: Date;\n}): Promise<MaterializeResult | null> {\n // Delegates to the shared post-consolidation helper — see\n // runPostConsolidationMaterialize in codex-materialize-runner.ts.\n return runPostConsolidationMaterialize(\"[cmc]\", options);\n}\n"],"mappings":"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","names":[]}
|
package/dist/causal-retrieval.js
CHANGED
|
@@ -5,13 +5,14 @@ import {
|
|
|
5
5
|
import "./chunk-URB2WSKZ.js";
|
|
6
6
|
import {
|
|
7
7
|
searchCausalTrajectories
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-G2WADRQ3.js";
|
|
9
9
|
import "./chunk-DT5TVLJE.js";
|
|
10
10
|
import {
|
|
11
11
|
log
|
|
12
12
|
} from "./chunk-2ODBA7MQ.js";
|
|
13
13
|
import "./chunk-DGXUHMOV.js";
|
|
14
14
|
import "./chunk-LPSF4OQH.js";
|
|
15
|
+
import "./chunk-PZ5AY32C.js";
|
|
15
16
|
|
|
16
17
|
// src/causal-retrieval.ts
|
|
17
18
|
function walkUpstream(seedId, index, maxDepth, counterfactualBoost) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/causal-retrieval.ts"],"sourcesContent":["/**\n * causal-retrieval.ts — CMC Phase 3: Causal Retrieval Channel\n *\n * Walks upstream/downstream causal chains during recall to surface\n * connected trajectories. Branching points (multiple outgoing edges\n * with different outcomes) get a counterfactual boost as they represent\n * decision points worth surfacing.\n */\n\nimport type { CausalTrajectoryRecord } from \"./causal-trajectory.js\";\nimport { searchCausalTrajectories } from \"./causal-trajectory.js\";\nimport {\n readChainIndex,\n resolveChainsDir,\n type CausalChainIndex,\n type CausalEdge,\n} from \"./causal-chain.js\";\nimport { log } from \"./logger.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface CausalRetrievalConfig {\n maxDepth: number;\n maxChars: number;\n counterfactualBoost: number;\n}\n\nexport interface CausalRetrievalResult {\n trajectoryId: string;\n direction: \"upstream\" | \"downstream\" | \"seed\";\n depth: number;\n score: number;\n edgeType?: CausalEdge[\"edgeType\"];\n edgeConfidence?: number;\n isCounterfactual: boolean;\n summary: string;\n}\n\n// ─── Graph Traversal ─────────────────────────────────────────────────────────\n\n/**\n * Walk upstream (incoming edges) from a seed trajectory.\n */\nfunction walkUpstream(\n seedId: string,\n index: CausalChainIndex,\n maxDepth: number,\n counterfactualBoost: number,\n): Array<{ trajectoryId: string; depth: number; score: number; edgeType: CausalEdge[\"edgeType\"]; edgeConfidence: number; isCounterfactual: boolean }> {\n const visited = new Set<string>([seedId]);\n const results: Array<{ trajectoryId: string; depth: number; score: number; edgeType: CausalEdge[\"edgeType\"]; edgeConfidence: number; isCounterfactual: boolean }> = [];\n\n let frontier = [seedId];\n for (let depth = 1; depth <= maxDepth; depth++) {\n const nextFrontier: string[] = [];\n\n for (const currentId of frontier) {\n const incomingEdgeIds = index.incoming[currentId] ?? [];\n\n for (const edgeId of incomingEdgeIds) {\n const edge = index.edges[edgeId];\n if (!edge) continue;\n\n const fromId = edge.fromTrajectoryId;\n if (visited.has(fromId)) continue;\n visited.add(fromId);\n\n // Check if this is a counterfactual branching point\n const outgoingFromSource = index.outgoing[fromId] ?? [];\n const isCounterfactual = outgoingFromSource.length > 1;\n\n const depthDecay = 1 / depth;\n let score = depthDecay * edge.confidence;\n if (isCounterfactual) score += counterfactualBoost;\n\n results.push({\n trajectoryId: fromId,\n depth,\n score,\n edgeType: edge.edgeType,\n edgeConfidence: edge.confidence,\n isCounterfactual,\n });\n\n nextFrontier.push(fromId);\n }\n }\n\n frontier = nextFrontier;\n if (frontier.length === 0) break;\n }\n\n return results;\n}\n\n/**\n * Walk downstream (outgoing edges) from a seed trajectory.\n * Max 2 hops downstream (less relevant than upstream context).\n */\nfunction walkDownstream(\n seedId: string,\n index: CausalChainIndex,\n maxDepth: number,\n counterfactualBoost: number,\n): Array<{ trajectoryId: string; depth: number; score: number; edgeType: CausalEdge[\"edgeType\"]; edgeConfidence: number; isCounterfactual: boolean }> {\n const downstreamMaxDepth = Math.min(maxDepth, 2);\n const visited = new Set<string>([seedId]);\n const results: Array<{ trajectoryId: string; depth: number; score: number; edgeType: CausalEdge[\"edgeType\"]; edgeConfidence: number; isCounterfactual: boolean }> = [];\n\n let frontier = [seedId];\n for (let depth = 1; depth <= downstreamMaxDepth; depth++) {\n const nextFrontier: string[] = [];\n\n for (const currentId of frontier) {\n const outgoingEdgeIds = index.outgoing[currentId] ?? [];\n\n // Counterfactual: multiple outgoing = branching point\n const isCounterfactual = outgoingEdgeIds.length > 1;\n\n for (const edgeId of outgoingEdgeIds) {\n const edge = index.edges[edgeId];\n if (!edge) continue;\n\n const toId = edge.toTrajectoryId;\n if (visited.has(toId)) continue;\n visited.add(toId);\n\n const depthDecay = 1 / (depth + 1); // downstream penalized more\n let score = depthDecay * edge.confidence;\n if (isCounterfactual) score += counterfactualBoost;\n\n results.push({\n trajectoryId: toId,\n depth,\n score,\n edgeType: edge.edgeType,\n edgeConfidence: edge.confidence,\n isCounterfactual,\n });\n\n nextFrontier.push(toId);\n }\n }\n\n frontier = nextFrontier;\n if (frontier.length === 0) break;\n }\n\n return results;\n}\n\n// ─── Section Formatting ──────────────────────────────────────────────────────\n\nfunction formatRetrievalResult(result: CausalRetrievalResult): string {\n const direction = result.direction === \"upstream\" ? \"↑\" : result.direction === \"downstream\" ? \"↓\" : \"•\";\n const counterfactual = result.isCounterfactual ? \" [branching point]\" : \"\";\n const edgeInfo = result.edgeType ? ` (${result.edgeType})` : \"\";\n return `- ${direction} ${result.summary}${edgeInfo}${counterfactual}`;\n}\n\nexport function formatCausalRetrievalSection(\n results: CausalRetrievalResult[],\n maxChars: number,\n): string | null {\n if (results.length === 0) return null;\n\n const lines: string[] = [\n \"## Causal Chain Context\",\n \"\",\n \"Related causal trajectories from connected sessions:\",\n \"\",\n ];\n\n let totalChars = lines.join(\"\\n\").length;\n\n for (const result of results) {\n const line = formatRetrievalResult(result);\n if (totalChars + line.length + 1 > maxChars) break;\n lines.push(line);\n totalChars += line.length + 1;\n }\n\n if (lines.length <= 4) return null; // only header, no content\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Retrieve causal chain context for a recall query.\n * 1. Use existing causal trajectory search for seed trajectories\n * 2. Walk upstream/downstream from seeds\n * 3. Format as recall section\n */\nexport async function retrieveCausalChains(options: {\n memoryDir: string;\n causalTrajectoryStoreDir?: string;\n query: string;\n sessionKey?: string;\n config: CausalRetrievalConfig;\n}): Promise<string | null> {\n try {\n const { memoryDir, causalTrajectoryStoreDir, query, sessionKey, config: retrievalConfig } = options;\n\n // 1. Search for seed trajectories matching the query\n const seeds = await searchCausalTrajectories({\n memoryDir,\n causalTrajectoryStoreDir,\n query,\n maxResults: 3,\n sessionKey,\n });\n\n if (seeds.length === 0) return null;\n\n // 2. Load chain index\n const chainsDir = resolveChainsDir(memoryDir, causalTrajectoryStoreDir);\n const chainIndex = await readChainIndex(chainsDir);\n\n if (Object.keys(chainIndex.edges).length === 0) return null;\n\n // 3. Walk chains from each seed\n const allResults: CausalRetrievalResult[] = [];\n\n for (const seed of seeds) {\n // Add seed itself\n allResults.push({\n trajectoryId: seed.record.trajectoryId,\n direction: \"seed\",\n depth: 0,\n score: seed.score,\n isCounterfactual: false,\n summary: `[${seed.record.outcomeKind}] ${seed.record.goal} → ${seed.record.outcomeSummary}`,\n });\n\n // Walk upstream\n const upstream = walkUpstream(\n seed.record.trajectoryId,\n chainIndex,\n retrievalConfig.maxDepth,\n retrievalConfig.counterfactualBoost,\n );\n for (const u of upstream) {\n allResults.push({\n trajectoryId: u.trajectoryId,\n direction: \"upstream\",\n depth: u.depth,\n score: u.score,\n edgeType: u.edgeType,\n edgeConfidence: u.edgeConfidence,\n isCounterfactual: u.isCounterfactual,\n summary: `Depth ${u.depth}: trajectory ${u.trajectoryId.slice(0, 12)}`,\n });\n }\n\n // Walk downstream\n const downstream = walkDownstream(\n seed.record.trajectoryId,\n chainIndex,\n retrievalConfig.maxDepth,\n retrievalConfig.counterfactualBoost,\n );\n for (const d of downstream) {\n allResults.push({\n trajectoryId: d.trajectoryId,\n direction: \"downstream\",\n depth: d.depth,\n score: d.score,\n edgeType: d.edgeType,\n edgeConfidence: d.edgeConfidence,\n isCounterfactual: d.isCounterfactual,\n summary: `Depth ${d.depth}: trajectory ${d.trajectoryId.slice(0, 12)}`,\n });\n }\n }\n\n // 4. Sort by score and format\n allResults.sort((a, b) => b.score - a.score);\n\n return formatCausalRetrievalSection(allResults, retrievalConfig.maxChars);\n } catch (error) {\n log.warn(`[cmc] causal retrieval failed (non-fatal): ${error instanceof Error ? error.message : String(error)}`);\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA2CA,SAAS,aACP,QACA,OACA,UACA,qBACoJ;AACpJ,QAAM,UAAU,oBAAI,IAAY,CAAC,MAAM,CAAC;AACxC,QAAM,UAA8J,CAAC;AAErK,MAAI,WAAW,CAAC,MAAM;AACtB,WAAS,QAAQ,GAAG,SAAS,UAAU,SAAS;AAC9C,UAAM,eAAyB,CAAC;AAEhC,eAAW,aAAa,UAAU;AAChC,YAAM,kBAAkB,MAAM,SAAS,SAAS,KAAK,CAAC;AAEtD,iBAAW,UAAU,iBAAiB;AACpC,cAAM,OAAO,MAAM,MAAM,MAAM;AAC/B,YAAI,CAAC,KAAM;AAEX,cAAM,SAAS,KAAK;AACpB,YAAI,QAAQ,IAAI,MAAM,EAAG;AACzB,gBAAQ,IAAI,MAAM;AAGlB,cAAM,qBAAqB,MAAM,SAAS,MAAM,KAAK,CAAC;AACtD,cAAM,mBAAmB,mBAAmB,SAAS;AAErD,cAAM,aAAa,IAAI;AACvB,YAAI,QAAQ,aAAa,KAAK;AAC9B,YAAI,iBAAkB,UAAS;AAE/B,gBAAQ,KAAK;AAAA,UACX,cAAc;AAAA,UACd;AAAA,UACA;AAAA,UACA,UAAU,KAAK;AAAA,UACf,gBAAgB,KAAK;AAAA,UACrB;AAAA,QACF,CAAC;AAED,qBAAa,KAAK,MAAM;AAAA,MAC1B;AAAA,IACF;AAEA,eAAW;AACX,QAAI,SAAS,WAAW,EAAG;AAAA,EAC7B;AAEA,SAAO;AACT;AAMA,SAAS,eACP,QACA,OACA,UACA,qBACoJ;AACpJ,QAAM,qBAAqB,KAAK,IAAI,UAAU,CAAC;AAC/C,QAAM,UAAU,oBAAI,IAAY,CAAC,MAAM,CAAC;AACxC,QAAM,UAA8J,CAAC;AAErK,MAAI,WAAW,CAAC,MAAM;AACtB,WAAS,QAAQ,GAAG,SAAS,oBAAoB,SAAS;AACxD,UAAM,eAAyB,CAAC;AAEhC,eAAW,aAAa,UAAU;AAChC,YAAM,kBAAkB,MAAM,SAAS,SAAS,KAAK,CAAC;AAGtD,YAAM,mBAAmB,gBAAgB,SAAS;AAElD,iBAAW,UAAU,iBAAiB;AACpC,cAAM,OAAO,MAAM,MAAM,MAAM;AAC/B,YAAI,CAAC,KAAM;AAEX,cAAM,OAAO,KAAK;AAClB,YAAI,QAAQ,IAAI,IAAI,EAAG;AACvB,gBAAQ,IAAI,IAAI;AAEhB,cAAM,aAAa,KAAK,QAAQ;AAChC,YAAI,QAAQ,aAAa,KAAK;AAC9B,YAAI,iBAAkB,UAAS;AAE/B,gBAAQ,KAAK;AAAA,UACX,cAAc;AAAA,UACd;AAAA,UACA;AAAA,UACA,UAAU,KAAK;AAAA,UACf,gBAAgB,KAAK;AAAA,UACrB;AAAA,QACF,CAAC;AAED,qBAAa,KAAK,IAAI;AAAA,MACxB;AAAA,IACF;AAEA,eAAW;AACX,QAAI,SAAS,WAAW,EAAG;AAAA,EAC7B;AAEA,SAAO;AACT;AAIA,SAAS,sBAAsB,QAAuC;AACpE,QAAM,YAAY,OAAO,cAAc,aAAa,WAAM,OAAO,cAAc,eAAe,WAAM;AACpG,QAAM,iBAAiB,OAAO,mBAAmB,uBAAuB;AACxE,QAAM,WAAW,OAAO,WAAW,KAAK,OAAO,QAAQ,MAAM;AAC7D,SAAO,KAAK,SAAS,IAAI,OAAO,OAAO,GAAG,QAAQ,GAAG,cAAc;AACrE;AAEO,SAAS,6BACd,SACA,UACe;AACf,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,aAAa,MAAM,KAAK,IAAI,EAAE;AAElC,aAAW,UAAU,SAAS;AAC5B,UAAM,OAAO,sBAAsB,MAAM;AACzC,QAAI,aAAa,KAAK,SAAS,IAAI,SAAU;AAC7C,UAAM,KAAK,IAAI;AACf,kBAAc,KAAK,SAAS;AAAA,EAC9B;AAEA,MAAI,MAAM,UAAU,EAAG,QAAO;AAC9B,QAAM,KAAK,EAAE;AACb,SAAO,MAAM,KAAK,IAAI;AACxB;AAUA,eAAsB,qBAAqB,SAMhB;AACzB,MAAI;AACF,UAAM,EAAE,WAAW,0BAA0B,OAAO,YAAY,QAAQ,gBAAgB,IAAI;AAG5F,UAAM,QAAQ,MAAM,yBAAyB;AAAA,MAC3C;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,IACF,CAAC;AAED,QAAI,MAAM,WAAW,EAAG,QAAO;AAG/B,UAAM,YAAY,iBAAiB,WAAW,wBAAwB;AACtE,UAAM,aAAa,MAAM,eAAe,SAAS;AAEjD,QAAI,OAAO,KAAK,WAAW,KAAK,EAAE,WAAW,EAAG,QAAO;AAGvD,UAAM,aAAsC,CAAC;AAE7C,eAAW,QAAQ,OAAO;AAExB,iBAAW,KAAK;AAAA,QACd,cAAc,KAAK,OAAO;AAAA,QAC1B,WAAW;AAAA,QACX,OAAO;AAAA,QACP,OAAO,KAAK;AAAA,QACZ,kBAAkB;AAAA,QAClB,SAAS,IAAI,KAAK,OAAO,WAAW,KAAK,KAAK,OAAO,IAAI,WAAM,KAAK,OAAO,cAAc;AAAA,MAC3F,CAAC;AAGD,YAAM,WAAW;AAAA,QACf,KAAK,OAAO;AAAA,QACZ;AAAA,QACA,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,MAClB;AACA,iBAAW,KAAK,UAAU;AACxB,mBAAW,KAAK;AAAA,UACd,cAAc,EAAE;AAAA,UAChB,WAAW;AAAA,UACX,OAAO,EAAE;AAAA,UACT,OAAO,EAAE;AAAA,UACT,UAAU,EAAE;AAAA,UACZ,gBAAgB,EAAE;AAAA,UAClB,kBAAkB,EAAE;AAAA,UACpB,SAAS,SAAS,EAAE,KAAK,gBAAgB,EAAE,aAAa,MAAM,GAAG,EAAE,CAAC;AAAA,QACtE,CAAC;AAAA,MACH;AAGA,YAAM,aAAa;AAAA,QACjB,KAAK,OAAO;AAAA,QACZ;AAAA,QACA,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,MAClB;AACA,iBAAW,KAAK,YAAY;AAC1B,mBAAW,KAAK;AAAA,UACd,cAAc,EAAE;AAAA,UAChB,WAAW;AAAA,UACX,OAAO,EAAE;AAAA,UACT,OAAO,EAAE;AAAA,UACT,UAAU,EAAE;AAAA,UACZ,gBAAgB,EAAE;AAAA,UAClB,kBAAkB,EAAE;AAAA,UACpB,SAAS,SAAS,EAAE,KAAK,gBAAgB,EAAE,aAAa,MAAM,GAAG,EAAE,CAAC;AAAA,QACtE,CAAC;AAAA,MACH;AAAA,IACF;AAGA,eAAW,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAE3C,WAAO,6BAA6B,YAAY,gBAAgB,QAAQ;AAAA,EAC1E,SAAS,OAAO;AACd,QAAI,KAAK,8CAA8C,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAC/G,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/causal-retrieval.ts"],"sourcesContent":["/**\n * causal-retrieval.ts — CMC Phase 3: Causal Retrieval Channel\n *\n * Walks upstream/downstream causal chains during recall to surface\n * connected trajectories. Branching points (multiple outgoing edges\n * with different outcomes) get a counterfactual boost as they represent\n * decision points worth surfacing.\n */\n\nimport type { CausalTrajectoryRecord } from \"./causal-trajectory.js\";\nimport { searchCausalTrajectories } from \"./causal-trajectory.js\";\nimport {\n readChainIndex,\n resolveChainsDir,\n type CausalChainIndex,\n type CausalEdge,\n} from \"./causal-chain.js\";\nimport { log } from \"./logger.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface CausalRetrievalConfig {\n maxDepth: number;\n maxChars: number;\n counterfactualBoost: number;\n}\n\nexport interface CausalRetrievalResult {\n trajectoryId: string;\n direction: \"upstream\" | \"downstream\" | \"seed\";\n depth: number;\n score: number;\n edgeType?: CausalEdge[\"edgeType\"];\n edgeConfidence?: number;\n isCounterfactual: boolean;\n summary: string;\n}\n\n// ─── Graph Traversal ─────────────────────────────────────────────────────────\n\n/**\n * Walk upstream (incoming edges) from a seed trajectory.\n */\nfunction walkUpstream(\n seedId: string,\n index: CausalChainIndex,\n maxDepth: number,\n counterfactualBoost: number,\n): Array<{ trajectoryId: string; depth: number; score: number; edgeType: CausalEdge[\"edgeType\"]; edgeConfidence: number; isCounterfactual: boolean }> {\n const visited = new Set<string>([seedId]);\n const results: Array<{ trajectoryId: string; depth: number; score: number; edgeType: CausalEdge[\"edgeType\"]; edgeConfidence: number; isCounterfactual: boolean }> = [];\n\n let frontier = [seedId];\n for (let depth = 1; depth <= maxDepth; depth++) {\n const nextFrontier: string[] = [];\n\n for (const currentId of frontier) {\n const incomingEdgeIds = index.incoming[currentId] ?? [];\n\n for (const edgeId of incomingEdgeIds) {\n const edge = index.edges[edgeId];\n if (!edge) continue;\n\n const fromId = edge.fromTrajectoryId;\n if (visited.has(fromId)) continue;\n visited.add(fromId);\n\n // Check if this is a counterfactual branching point\n const outgoingFromSource = index.outgoing[fromId] ?? [];\n const isCounterfactual = outgoingFromSource.length > 1;\n\n const depthDecay = 1 / depth;\n let score = depthDecay * edge.confidence;\n if (isCounterfactual) score += counterfactualBoost;\n\n results.push({\n trajectoryId: fromId,\n depth,\n score,\n edgeType: edge.edgeType,\n edgeConfidence: edge.confidence,\n isCounterfactual,\n });\n\n nextFrontier.push(fromId);\n }\n }\n\n frontier = nextFrontier;\n if (frontier.length === 0) break;\n }\n\n return results;\n}\n\n/**\n * Walk downstream (outgoing edges) from a seed trajectory.\n * Max 2 hops downstream (less relevant than upstream context).\n */\nfunction walkDownstream(\n seedId: string,\n index: CausalChainIndex,\n maxDepth: number,\n counterfactualBoost: number,\n): Array<{ trajectoryId: string; depth: number; score: number; edgeType: CausalEdge[\"edgeType\"]; edgeConfidence: number; isCounterfactual: boolean }> {\n const downstreamMaxDepth = Math.min(maxDepth, 2);\n const visited = new Set<string>([seedId]);\n const results: Array<{ trajectoryId: string; depth: number; score: number; edgeType: CausalEdge[\"edgeType\"]; edgeConfidence: number; isCounterfactual: boolean }> = [];\n\n let frontier = [seedId];\n for (let depth = 1; depth <= downstreamMaxDepth; depth++) {\n const nextFrontier: string[] = [];\n\n for (const currentId of frontier) {\n const outgoingEdgeIds = index.outgoing[currentId] ?? [];\n\n // Counterfactual: multiple outgoing = branching point\n const isCounterfactual = outgoingEdgeIds.length > 1;\n\n for (const edgeId of outgoingEdgeIds) {\n const edge = index.edges[edgeId];\n if (!edge) continue;\n\n const toId = edge.toTrajectoryId;\n if (visited.has(toId)) continue;\n visited.add(toId);\n\n const depthDecay = 1 / (depth + 1); // downstream penalized more\n let score = depthDecay * edge.confidence;\n if (isCounterfactual) score += counterfactualBoost;\n\n results.push({\n trajectoryId: toId,\n depth,\n score,\n edgeType: edge.edgeType,\n edgeConfidence: edge.confidence,\n isCounterfactual,\n });\n\n nextFrontier.push(toId);\n }\n }\n\n frontier = nextFrontier;\n if (frontier.length === 0) break;\n }\n\n return results;\n}\n\n// ─── Section Formatting ──────────────────────────────────────────────────────\n\nfunction formatRetrievalResult(result: CausalRetrievalResult): string {\n const direction = result.direction === \"upstream\" ? \"↑\" : result.direction === \"downstream\" ? \"↓\" : \"•\";\n const counterfactual = result.isCounterfactual ? \" [branching point]\" : \"\";\n const edgeInfo = result.edgeType ? ` (${result.edgeType})` : \"\";\n return `- ${direction} ${result.summary}${edgeInfo}${counterfactual}`;\n}\n\nexport function formatCausalRetrievalSection(\n results: CausalRetrievalResult[],\n maxChars: number,\n): string | null {\n if (results.length === 0) return null;\n\n const lines: string[] = [\n \"## Causal Chain Context\",\n \"\",\n \"Related causal trajectories from connected sessions:\",\n \"\",\n ];\n\n let totalChars = lines.join(\"\\n\").length;\n\n for (const result of results) {\n const line = formatRetrievalResult(result);\n if (totalChars + line.length + 1 > maxChars) break;\n lines.push(line);\n totalChars += line.length + 1;\n }\n\n if (lines.length <= 4) return null; // only header, no content\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Retrieve causal chain context for a recall query.\n * 1. Use existing causal trajectory search for seed trajectories\n * 2. Walk upstream/downstream from seeds\n * 3. Format as recall section\n */\nexport async function retrieveCausalChains(options: {\n memoryDir: string;\n causalTrajectoryStoreDir?: string;\n query: string;\n sessionKey?: string;\n config: CausalRetrievalConfig;\n}): Promise<string | null> {\n try {\n const { memoryDir, causalTrajectoryStoreDir, query, sessionKey, config: retrievalConfig } = options;\n\n // 1. Search for seed trajectories matching the query\n const seeds = await searchCausalTrajectories({\n memoryDir,\n causalTrajectoryStoreDir,\n query,\n maxResults: 3,\n sessionKey,\n });\n\n if (seeds.length === 0) return null;\n\n // 2. Load chain index\n const chainsDir = resolveChainsDir(memoryDir, causalTrajectoryStoreDir);\n const chainIndex = await readChainIndex(chainsDir);\n\n if (Object.keys(chainIndex.edges).length === 0) return null;\n\n // 3. Walk chains from each seed\n const allResults: CausalRetrievalResult[] = [];\n\n for (const seed of seeds) {\n // Add seed itself\n allResults.push({\n trajectoryId: seed.record.trajectoryId,\n direction: \"seed\",\n depth: 0,\n score: seed.score,\n isCounterfactual: false,\n summary: `[${seed.record.outcomeKind}] ${seed.record.goal} → ${seed.record.outcomeSummary}`,\n });\n\n // Walk upstream\n const upstream = walkUpstream(\n seed.record.trajectoryId,\n chainIndex,\n retrievalConfig.maxDepth,\n retrievalConfig.counterfactualBoost,\n );\n for (const u of upstream) {\n allResults.push({\n trajectoryId: u.trajectoryId,\n direction: \"upstream\",\n depth: u.depth,\n score: u.score,\n edgeType: u.edgeType,\n edgeConfidence: u.edgeConfidence,\n isCounterfactual: u.isCounterfactual,\n summary: `Depth ${u.depth}: trajectory ${u.trajectoryId.slice(0, 12)}`,\n });\n }\n\n // Walk downstream\n const downstream = walkDownstream(\n seed.record.trajectoryId,\n chainIndex,\n retrievalConfig.maxDepth,\n retrievalConfig.counterfactualBoost,\n );\n for (const d of downstream) {\n allResults.push({\n trajectoryId: d.trajectoryId,\n direction: \"downstream\",\n depth: d.depth,\n score: d.score,\n edgeType: d.edgeType,\n edgeConfidence: d.edgeConfidence,\n isCounterfactual: d.isCounterfactual,\n summary: `Depth ${d.depth}: trajectory ${d.trajectoryId.slice(0, 12)}`,\n });\n }\n }\n\n // 4. Sort by score and format\n allResults.sort((a, b) => b.score - a.score);\n\n return formatCausalRetrievalSection(allResults, retrievalConfig.maxChars);\n } catch (error) {\n log.warn(`[cmc] causal retrieval failed (non-fatal): ${error instanceof Error ? error.message : String(error)}`);\n return null;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
appendEdge
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RK2Y4XOM.js";
|
|
4
|
+
import "./chunk-2LSZVONP.js";
|
|
5
|
+
import "./chunk-WIICJPET.js";
|
|
6
|
+
import "./chunk-PZ5AY32C.js";
|
|
4
7
|
|
|
5
8
|
// src/causal-trajectory-graph.ts
|
|
6
9
|
function causalTrajectoryGraphNodeId(trajectoryId, stage) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/causal-trajectory-graph.ts"],"sourcesContent":["import { appendEdge, type GraphEdge } from \"./graph.js\";\nimport type { CausalTrajectoryRecord } from \"./causal-trajectory.js\";\n\nexport type CausalTrajectoryGraphStage = \"goal\" | \"action\" | \"observation\" | \"outcome\" | \"follow_up\";\n\nexport function causalTrajectoryGraphNodeId(trajectoryId: string, stage: CausalTrajectoryGraphStage): string {\n return `causal-trajectory/${trajectoryId}#${stage}`;\n}\n\nexport function buildCausalTrajectoryGraphEdges(record: CausalTrajectoryRecord): GraphEdge[] {\n const edges: GraphEdge[] = [\n {\n from: causalTrajectoryGraphNodeId(record.trajectoryId, \"goal\"),\n to: causalTrajectoryGraphNodeId(record.trajectoryId, \"action\"),\n type: \"causal\",\n weight: 1.0,\n label: \"goal_to_action\",\n ts: record.recordedAt,\n },\n {\n from: causalTrajectoryGraphNodeId(record.trajectoryId, \"action\"),\n to: causalTrajectoryGraphNodeId(record.trajectoryId, \"observation\"),\n type: \"causal\",\n weight: 1.0,\n label: \"action_to_observation\",\n ts: record.recordedAt,\n },\n {\n from: causalTrajectoryGraphNodeId(record.trajectoryId, \"observation\"),\n to: causalTrajectoryGraphNodeId(record.trajectoryId, \"outcome\"),\n type: \"causal\",\n weight: 1.0,\n label: `observation_to_outcome:${record.outcomeKind}`,\n ts: record.recordedAt,\n },\n ];\n\n if (record.followUpSummary) {\n edges.push({\n from: causalTrajectoryGraphNodeId(record.trajectoryId, \"outcome\"),\n to: causalTrajectoryGraphNodeId(record.trajectoryId, \"follow_up\"),\n type: \"causal\",\n weight: 1.0,\n label: \"outcome_to_follow_up\",\n ts: record.recordedAt,\n });\n }\n\n return edges;\n}\n\nexport async function appendCausalTrajectoryGraphEdges(options: {\n memoryDir: string;\n record: CausalTrajectoryRecord;\n}): Promise<void> {\n const edges = buildCausalTrajectoryGraphEdges(options.record);\n for (const edge of edges) {\n await appendEdge(options.memoryDir, edge);\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/causal-trajectory-graph.ts"],"sourcesContent":["import { appendEdge, type GraphEdge } from \"./graph.js\";\nimport type { CausalTrajectoryRecord } from \"./causal-trajectory.js\";\n\nexport type CausalTrajectoryGraphStage = \"goal\" | \"action\" | \"observation\" | \"outcome\" | \"follow_up\";\n\nexport function causalTrajectoryGraphNodeId(trajectoryId: string, stage: CausalTrajectoryGraphStage): string {\n return `causal-trajectory/${trajectoryId}#${stage}`;\n}\n\nexport function buildCausalTrajectoryGraphEdges(record: CausalTrajectoryRecord): GraphEdge[] {\n const edges: GraphEdge[] = [\n {\n from: causalTrajectoryGraphNodeId(record.trajectoryId, \"goal\"),\n to: causalTrajectoryGraphNodeId(record.trajectoryId, \"action\"),\n type: \"causal\",\n weight: 1.0,\n label: \"goal_to_action\",\n ts: record.recordedAt,\n },\n {\n from: causalTrajectoryGraphNodeId(record.trajectoryId, \"action\"),\n to: causalTrajectoryGraphNodeId(record.trajectoryId, \"observation\"),\n type: \"causal\",\n weight: 1.0,\n label: \"action_to_observation\",\n ts: record.recordedAt,\n },\n {\n from: causalTrajectoryGraphNodeId(record.trajectoryId, \"observation\"),\n to: causalTrajectoryGraphNodeId(record.trajectoryId, \"outcome\"),\n type: \"causal\",\n weight: 1.0,\n label: `observation_to_outcome:${record.outcomeKind}`,\n ts: record.recordedAt,\n },\n ];\n\n if (record.followUpSummary) {\n edges.push({\n from: causalTrajectoryGraphNodeId(record.trajectoryId, \"outcome\"),\n to: causalTrajectoryGraphNodeId(record.trajectoryId, \"follow_up\"),\n type: \"causal\",\n weight: 1.0,\n label: \"outcome_to_follow_up\",\n ts: record.recordedAt,\n });\n }\n\n return edges;\n}\n\nexport async function appendCausalTrajectoryGraphEdges(options: {\n memoryDir: string;\n record: CausalTrajectoryRecord;\n}): Promise<void> {\n const edges = buildCausalTrajectoryGraphEdges(options.record);\n for (const edge of edges) {\n await appendEdge(options.memoryDir, edge);\n }\n}\n"],"mappings":";;;;;;;;AAKO,SAAS,4BAA4B,cAAsB,OAA2C;AAC3G,SAAO,qBAAqB,YAAY,IAAI,KAAK;AACnD;AAEO,SAAS,gCAAgC,QAA6C;AAC3F,QAAM,QAAqB;AAAA,IACzB;AAAA,MACE,MAAM,4BAA4B,OAAO,cAAc,MAAM;AAAA,MAC7D,IAAI,4BAA4B,OAAO,cAAc,QAAQ;AAAA,MAC7D,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,IAAI,OAAO;AAAA,IACb;AAAA,IACA;AAAA,MACE,MAAM,4BAA4B,OAAO,cAAc,QAAQ;AAAA,MAC/D,IAAI,4BAA4B,OAAO,cAAc,aAAa;AAAA,MAClE,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,IAAI,OAAO;AAAA,IACb;AAAA,IACA;AAAA,MACE,MAAM,4BAA4B,OAAO,cAAc,aAAa;AAAA,MACpE,IAAI,4BAA4B,OAAO,cAAc,SAAS;AAAA,MAC9D,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,OAAO,0BAA0B,OAAO,WAAW;AAAA,MACnD,IAAI,OAAO;AAAA,IACb;AAAA,EACF;AAEA,MAAI,OAAO,iBAAiB;AAC1B,UAAM,KAAK;AAAA,MACT,MAAM,4BAA4B,OAAO,cAAc,SAAS;AAAA,MAChE,IAAI,4BAA4B,OAAO,cAAc,WAAW;AAAA,MAChE,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,IAAI,OAAO;AAAA,IACb,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,eAAsB,iCAAiC,SAGrC;AAChB,QAAM,QAAQ,gCAAgC,QAAQ,MAAM;AAC5D,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,QAAQ,WAAW,IAAI;AAAA,EAC1C;AACF;","names":[]}
|
|
@@ -6,10 +6,11 @@ import {
|
|
|
6
6
|
resolveCausalTrajectoryStoreDir,
|
|
7
7
|
searchCausalTrajectories,
|
|
8
8
|
validateCausalTrajectoryRecord
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-G2WADRQ3.js";
|
|
10
10
|
import "./chunk-DT5TVLJE.js";
|
|
11
11
|
import "./chunk-DGXUHMOV.js";
|
|
12
12
|
import "./chunk-LPSF4OQH.js";
|
|
13
|
+
import "./chunk-PZ5AY32C.js";
|
|
13
14
|
export {
|
|
14
15
|
filterTrajectoriesByLookbackDays,
|
|
15
16
|
getCausalTrajectoryStoreStatus,
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// src/graph-edge-reinforcement.ts
|
|
2
|
+
var DEFAULT_REINFORCE_DELTA = 0.05;
|
|
3
|
+
var CONFIDENCE_CEILING = 1;
|
|
4
|
+
var DEFAULT_DECAY_WINDOW_MS = 90 * 24 * 60 * 60 * 1e3;
|
|
5
|
+
var DEFAULT_DECAY_FLOOR = 0.1;
|
|
6
|
+
var DEFAULT_DECAY_PER_WINDOW = 0.1;
|
|
7
|
+
function readEdgeConfidence(edge) {
|
|
8
|
+
const raw = edge.confidence;
|
|
9
|
+
if (raw === void 0 || raw === null || !Number.isFinite(raw)) {
|
|
10
|
+
return CONFIDENCE_CEILING;
|
|
11
|
+
}
|
|
12
|
+
if (raw < 0) return 0;
|
|
13
|
+
if (raw > CONFIDENCE_CEILING) return CONFIDENCE_CEILING;
|
|
14
|
+
return raw;
|
|
15
|
+
}
|
|
16
|
+
function readLastReinforcedAt(edge) {
|
|
17
|
+
return edge.lastReinforcedAt ?? edge.ts;
|
|
18
|
+
}
|
|
19
|
+
function reinforceEdge(edge, now, delta = DEFAULT_REINFORCE_DELTA) {
|
|
20
|
+
const current = readEdgeConfidence(edge);
|
|
21
|
+
const safeDelta = Number.isFinite(delta) && delta >= 0 ? delta : 0;
|
|
22
|
+
const next = Math.min(CONFIDENCE_CEILING, Math.max(0, current + safeDelta));
|
|
23
|
+
return {
|
|
24
|
+
...edge,
|
|
25
|
+
confidence: next,
|
|
26
|
+
lastReinforcedAt: now
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function decayEdgeConfidence(edge, now, opts = {}) {
|
|
30
|
+
const windowMs = opts.windowMs ?? DEFAULT_DECAY_WINDOW_MS;
|
|
31
|
+
const perWindow = opts.perWindow ?? DEFAULT_DECAY_PER_WINDOW;
|
|
32
|
+
const floor = opts.floor ?? DEFAULT_DECAY_FLOOR;
|
|
33
|
+
if (!(windowMs > 0) || !Number.isFinite(perWindow) || perWindow < 0 || !Number.isFinite(floor)) {
|
|
34
|
+
return { ...edge, confidence: readEdgeConfidence(edge) };
|
|
35
|
+
}
|
|
36
|
+
const safeFloor = Math.min(CONFIDENCE_CEILING, Math.max(0, floor));
|
|
37
|
+
const nowMs = Date.parse(now);
|
|
38
|
+
const refMs = Date.parse(readLastReinforcedAt(edge));
|
|
39
|
+
if (!Number.isFinite(nowMs) || !Number.isFinite(refMs)) {
|
|
40
|
+
return { ...edge, confidence: readEdgeConfidence(edge) };
|
|
41
|
+
}
|
|
42
|
+
const age = nowMs - refMs;
|
|
43
|
+
const current = readEdgeConfidence(edge);
|
|
44
|
+
if (age <= windowMs) {
|
|
45
|
+
return { ...edge, confidence: current };
|
|
46
|
+
}
|
|
47
|
+
const windowsPast = Math.ceil((age - windowMs) / windowMs);
|
|
48
|
+
const decayed = current - perWindow * windowsPast;
|
|
49
|
+
const lowerBound = Math.min(safeFloor, current);
|
|
50
|
+
const next = Math.max(lowerBound, Math.min(current, decayed));
|
|
51
|
+
const newRefMs = refMs + windowsPast * windowMs;
|
|
52
|
+
const newRef = new Date(newRefMs).toISOString();
|
|
53
|
+
return { ...edge, confidence: next, lastReinforcedAt: newRef };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
DEFAULT_REINFORCE_DELTA,
|
|
58
|
+
CONFIDENCE_CEILING,
|
|
59
|
+
DEFAULT_DECAY_WINDOW_MS,
|
|
60
|
+
DEFAULT_DECAY_FLOOR,
|
|
61
|
+
DEFAULT_DECAY_PER_WINDOW,
|
|
62
|
+
readEdgeConfidence,
|
|
63
|
+
readLastReinforcedAt,
|
|
64
|
+
reinforceEdge,
|
|
65
|
+
decayEdgeConfidence
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=chunk-2LSZVONP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/graph-edge-reinforcement.ts"],"sourcesContent":["/**\n * Graph edge confidence + reinforcement primitives (issue #681, PR 1/3).\n *\n * Pure functions only — no I/O, no global state. The maintenance job (PR 2/3)\n * and PageRank weighting (PR 3/3) compose these helpers.\n *\n * Schema:\n * - `confidence` ∈ [0, 1]; missing on legacy edges, treated as 1.0.\n * - `lastReinforcedAt` — ISO timestamp of most recent reinforcement; missing\n * on legacy edges, treated as the original edge `ts`.\n *\n * Defaults documented here are the agreed-on starting points and may be\n * tuned later via config. They live as named constants so call sites and\n * tests share the same values.\n */\n\nimport type { GraphEdge } from \"./graph.js\";\n\n/** Default confidence bump per reinforcement event. */\nexport const DEFAULT_REINFORCE_DELTA = 0.05;\n\n/** Maximum edge confidence — confidence is capped at this on reinforcement. */\nexport const CONFIDENCE_CEILING = 1.0;\n\n/** Default decay window in milliseconds (90 days). */\nexport const DEFAULT_DECAY_WINDOW_MS = 90 * 24 * 60 * 60 * 1000;\n\n/** Default decay floor — confidence will not drop below this purely from age. */\nexport const DEFAULT_DECAY_FLOOR = 0.1;\n\n/** Default per-window decay amount (linear). */\nexport const DEFAULT_DECAY_PER_WINDOW = 0.1;\n\n/**\n * Treat a missing `confidence` on a legacy edge as 1.0.\n * Clamps to `[0, CONFIDENCE_CEILING]` so downstream math is well-behaved.\n */\nexport function readEdgeConfidence(edge: Pick<GraphEdge, \"confidence\">): number {\n const raw = edge.confidence;\n if (raw === undefined || raw === null || !Number.isFinite(raw)) {\n return CONFIDENCE_CEILING;\n }\n if (raw < 0) return 0;\n if (raw > CONFIDENCE_CEILING) return CONFIDENCE_CEILING;\n return raw;\n}\n\n/**\n * Resolve the reference timestamp for decay calculations.\n * Falls back to the edge's creation `ts` when `lastReinforcedAt` is absent\n * (legacy edges have never been reinforced).\n */\nexport function readLastReinforcedAt(\n edge: Pick<GraphEdge, \"lastReinforcedAt\" | \"ts\">,\n): string {\n return edge.lastReinforcedAt ?? edge.ts;\n}\n\n/**\n * Reinforce an edge: bump confidence by `delta` (capped at 1.0) and stamp\n * `lastReinforcedAt = now`. Pure — returns a new edge, never mutates input.\n *\n * Idempotency note: calling reinforceEdge twice with the same `now` and a\n * delta of 0 returns an edge equal to the input (modulo timestamp).\n *\n * @param edge the edge to reinforce\n * @param now ISO timestamp of the reinforcement event\n * @param delta confidence bump; defaults to DEFAULT_REINFORCE_DELTA\n */\nexport function reinforceEdge(\n edge: GraphEdge,\n now: string,\n delta: number = DEFAULT_REINFORCE_DELTA,\n): GraphEdge {\n const current = readEdgeConfidence(edge);\n // Codex P2: reinforcement must never silently decrease confidence.\n // A negative delta sneaking in through parsed config / CLI flags\n // would push strong edges toward zero on every observation. Treat\n // anything below zero as 0 (no-op besides the timestamp bump) so\n // misconfiguration is harmless rather than corrupting.\n const safeDelta =\n Number.isFinite(delta) && delta >= 0 ? delta : 0;\n const next = Math.min(CONFIDENCE_CEILING, Math.max(0, current + safeDelta));\n return {\n ...edge,\n confidence: next,\n lastReinforcedAt: now,\n };\n}\n\n/** Options for {@link decayEdgeConfidence}. */\nexport interface DecayOptions {\n /** Decay window in milliseconds. Defaults to 90 days. */\n windowMs?: number;\n /** Per-window decay amount. Defaults to 0.1. */\n perWindow?: number;\n /** Floor confidence will not decay below. Defaults to 0.1. */\n floor?: number;\n}\n\n/**\n * Apply linear decay to an edge's confidence based on time since last\n * reinforcement (or creation, for legacy edges). Pure — returns a new edge.\n *\n * Decay model:\n * age = now - lastReinforcedAt\n * if age <= windowMs: confidence unchanged\n * else: confidence -= perWindow * floor((age - windowMs) / windowMs + 1)\n * confidence is clamped to [floor, 1.0]\n *\n * Boundary semantics: `age === windowMs` is INSIDE the no-decay grace period\n * (`<=`). Decay only kicks in once age strictly exceeds the window. This\n * keeps the boundary deterministic and easy to test.\n *\n * @param edge edge to decay (confidence and lastReinforcedAt may be absent)\n * @param now ISO timestamp representing \"now\"\n * @param opts override window / per-window / floor; otherwise defaults are used\n */\nexport function decayEdgeConfidence(\n edge: GraphEdge,\n now: string,\n opts: DecayOptions = {},\n): GraphEdge {\n const windowMs = opts.windowMs ?? DEFAULT_DECAY_WINDOW_MS;\n const perWindow = opts.perWindow ?? DEFAULT_DECAY_PER_WINDOW;\n const floor = opts.floor ?? DEFAULT_DECAY_FLOOR;\n\n // Codex P2: reject negative `perWindow` so a misconfigured value\n // doesn't invert the decay equation and silently boost stale\n // edges instead of decaying them. Negative `floor` would also let\n // confidence drop below zero — clamp the floor to [0, 1] so the\n // model stays well-defined.\n if (\n !(windowMs > 0) ||\n !Number.isFinite(perWindow) ||\n perWindow < 0 ||\n !Number.isFinite(floor)\n ) {\n // Degenerate options — return a normalized copy without changing confidence.\n return { ...edge, confidence: readEdgeConfidence(edge) };\n }\n const safeFloor = Math.min(CONFIDENCE_CEILING, Math.max(0, floor));\n\n const nowMs = Date.parse(now);\n const refMs = Date.parse(readLastReinforcedAt(edge));\n if (!Number.isFinite(nowMs) || !Number.isFinite(refMs)) {\n return { ...edge, confidence: readEdgeConfidence(edge) };\n }\n\n const age = nowMs - refMs;\n const current = readEdgeConfidence(edge);\n\n if (age <= windowMs) {\n // Inside the grace period: no decay.\n return { ...edge, confidence: current };\n }\n\n // Number of full windows past the grace window.\n //\n // Codex P2: the previous formula (`Math.floor((age - windowMs) / windowMs) + 1`)\n // over-counted at exact multiples of the window. At `age === 2 * windowMs`,\n // only ONE post-grace window has elapsed (we're sitting on the boundary\n // of the second), but the old formula returned 2. Switch to a ceiling\n // count: `ceil((age - windowMs) / windowMs)` correctly returns 1 for\n // `windowMs < age <= 2*windowMs`, 2 for `2*windowMs < age <= 3*windowMs`,\n // etc. With the outer `age > windowMs` guard, this always evaluates to\n // a positive integer.\n const windowsPast = Math.ceil((age - windowMs) / windowMs);\n const decayed = current - perWindow * windowsPast;\n // Codex P2: an edge that already sits below `safeFloor` (e.g. an\n // explicit confidence: 0) must NOT be boosted up to the floor by a\n // decay pass. Decay can lower confidence or leave it unchanged — it\n // can never raise it. Cap the result at `current` and only apply\n // the floor when the pre-existing value is still above it.\n const lowerBound = Math.min(safeFloor, current);\n const next = Math.max(lowerBound, Math.min(current, decayed));\n\n // Cursor Medium round 2 + Codex P1: the anchor must advance by\n // EXACTLY the windows we just charged for — not to `now`. Resetting\n // to `now` makes every decay pass look like a fresh reinforcement\n // and re-applies the grace window on every run, under-decaying\n // stale edges when the maintenance job runs less frequently than\n // `windowMs` (codex P1). Leaving the anchor unchanged compounds\n // decay on frequent calls (cursor Medium). Advancing by\n // `windowsPast * windowMs` from the prior anchor is the right\n // middle ground: subsequent calls see a fresh grace window,\n // decay accrues at most `perWindow` per real `windowMs` regardless\n // of cadence, and historical anchor information is preserved.\n const newRefMs = refMs + windowsPast * windowMs;\n const newRef = new Date(newRefMs).toISOString();\n return { ...edge, confidence: next, lastReinforcedAt: newRef };\n}\n"],"mappings":";AAmBO,IAAM,0BAA0B;AAGhC,IAAM,qBAAqB;AAG3B,IAAM,0BAA0B,KAAK,KAAK,KAAK,KAAK;AAGpD,IAAM,sBAAsB;AAG5B,IAAM,2BAA2B;AAMjC,SAAS,mBAAmB,MAA6C;AAC9E,QAAM,MAAM,KAAK;AACjB,MAAI,QAAQ,UAAa,QAAQ,QAAQ,CAAC,OAAO,SAAS,GAAG,GAAG;AAC9D,WAAO;AAAA,EACT;AACA,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,MAAM,mBAAoB,QAAO;AACrC,SAAO;AACT;AAOO,SAAS,qBACd,MACQ;AACR,SAAO,KAAK,oBAAoB,KAAK;AACvC;AAaO,SAAS,cACd,MACA,KACA,QAAgB,yBACL;AACX,QAAM,UAAU,mBAAmB,IAAI;AAMvC,QAAM,YACJ,OAAO,SAAS,KAAK,KAAK,SAAS,IAAI,QAAQ;AACjD,QAAM,OAAO,KAAK,IAAI,oBAAoB,KAAK,IAAI,GAAG,UAAU,SAAS,CAAC;AAC1E,SAAO;AAAA,IACL,GAAG;AAAA,IACH,YAAY;AAAA,IACZ,kBAAkB;AAAA,EACpB;AACF;AA8BO,SAAS,oBACd,MACA,KACA,OAAqB,CAAC,GACX;AACX,QAAM,WAAW,KAAK,YAAY;AAClC,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,QAAQ,KAAK,SAAS;AAO5B,MACE,EAAE,WAAW,MACb,CAAC,OAAO,SAAS,SAAS,KAC1B,YAAY,KACZ,CAAC,OAAO,SAAS,KAAK,GACtB;AAEA,WAAO,EAAE,GAAG,MAAM,YAAY,mBAAmB,IAAI,EAAE;AAAA,EACzD;AACA,QAAM,YAAY,KAAK,IAAI,oBAAoB,KAAK,IAAI,GAAG,KAAK,CAAC;AAEjE,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,QAAM,QAAQ,KAAK,MAAM,qBAAqB,IAAI,CAAC;AACnD,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,OAAO,SAAS,KAAK,GAAG;AACtD,WAAO,EAAE,GAAG,MAAM,YAAY,mBAAmB,IAAI,EAAE;AAAA,EACzD;AAEA,QAAM,MAAM,QAAQ;AACpB,QAAM,UAAU,mBAAmB,IAAI;AAEvC,MAAI,OAAO,UAAU;AAEnB,WAAO,EAAE,GAAG,MAAM,YAAY,QAAQ;AAAA,EACxC;AAYA,QAAM,cAAc,KAAK,MAAM,MAAM,YAAY,QAAQ;AACzD,QAAM,UAAU,UAAU,YAAY;AAMtC,QAAM,aAAa,KAAK,IAAI,WAAW,OAAO;AAC9C,QAAM,OAAO,KAAK,IAAI,YAAY,KAAK,IAAI,SAAS,OAAO,CAAC;AAa5D,QAAM,WAAW,QAAQ,cAAc;AACvC,QAAM,SAAS,IAAI,KAAK,QAAQ,EAAE,YAAY;AAC9C,SAAO,EAAE,GAAG,MAAM,YAAY,MAAM,kBAAkB,OAAO;AAC/D;","names":[]}
|