@remnic/core 10.0.4 → 10.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-admin-ops-surface.js +46 -46
- package/dist/access-authorization-probe.js +47 -47
- package/dist/access-boundary.js +46 -46
- package/dist/access-cli.d.ts.map +1 -1
- package/dist/access-cli.js +117 -112
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.js +46 -46
- package/dist/access-http-briefing.js +47 -47
- package/dist/access-http-query.js +48 -48
- package/dist/access-http.d.ts.map +1 -1
- package/dist/access-http.js +69 -68
- package/dist/access-identity-continuity-surface.js +46 -46
- package/dist/access-lcm-surface.js +46 -46
- package/dist/access-mcp-correction-tools.d.ts +10 -0
- package/dist/access-mcp-correction-tools.d.ts.map +1 -0
- package/dist/access-mcp-correction-tools.js +8 -0
- package/dist/access-mcp.d.ts.map +1 -1
- package/dist/access-mcp.js +60 -59
- package/dist/access-namespace-preflight.js +46 -46
- package/dist/access-observe-write-category.js +3 -3
- package/dist/access-observe-write-surface.js +46 -46
- package/dist/access-offline-manifest.js +5 -5
- package/dist/access-operations-batch.js +49 -49
- package/dist/access-operations.d.ts +1 -0
- package/dist/access-operations.d.ts.map +1 -1
- package/dist/access-operations.js +56 -56
- package/dist/access-recall-concurrency.js +46 -46
- package/dist/access-recall-diagnostics.js +2 -2
- package/dist/access-recall-response.js +46 -46
- package/dist/access-recall-surface.js +46 -46
- package/dist/access-service.d.ts.map +1 -1
- package/dist/access-service.js +46 -46
- package/dist/access-surface-catalog.js +48 -48
- package/dist/active-recall.js +22 -22
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/auto-sync-FN7E3OTO.js +2 -2
- package/dist/briefing.js +18 -18
- package/dist/buffer.js +1 -1
- package/dist/causal-consolidation.js +18 -18
- package/dist/{chunk-5YDWSWBU.js → chunk-2CP577K6.js} +2 -2
- package/dist/{chunk-ABET5LA5.js → chunk-37HCPM56.js} +23 -23
- package/dist/{chunk-5QHTQMRL.js → chunk-4CWUZBPF.js} +8 -6
- package/dist/chunk-4CWUZBPF.js.map +1 -0
- package/dist/{chunk-H6FA36LC.js → chunk-4K2H4KTR.js} +5 -5
- package/dist/{chunk-TSEUVMJL.js → chunk-52CQKST6.js} +39 -39
- package/dist/{chunk-H7BZBSP6.js → chunk-52II7PB6.js} +4 -4
- package/dist/{chunk-RH6MQ5NG.js → chunk-5BPXMAUP.js} +17 -68
- package/dist/chunk-5BPXMAUP.js.map +1 -0
- package/dist/{chunk-WLC6XA6C.js → chunk-5BY3IA2U.js} +16 -53
- package/dist/chunk-5BY3IA2U.js.map +1 -0
- package/dist/{chunk-ABDTBGI2.js → chunk-5CQO6LVM.js} +2 -2
- package/dist/{chunk-HSZBALHV.js → chunk-5LNPW7NE.js} +2 -2
- package/dist/{chunk-U3LVARGV.js → chunk-5X4ZJESN.js} +2 -2
- package/dist/{chunk-SNGNGH53.js → chunk-63UNVGZW.js} +4 -4
- package/dist/{chunk-2KB7TTAP.js → chunk-64S6X4IU.js} +4 -4
- package/dist/{chunk-3QAIX7TV.js → chunk-6KHF6PAB.js} +2 -2
- package/dist/{chunk-MYBCB4AT.js → chunk-6T42L5FI.js} +2 -2
- package/dist/{chunk-R6EOFKZG.js → chunk-7LYRFI5A.js} +2 -2
- package/dist/{chunk-4NFRYOHT.js → chunk-ANZXWOYD.js} +2 -2
- package/dist/{chunk-QDKABMUE.js → chunk-AXC7UTLM.js} +2 -2
- package/dist/{chunk-5XXTZ4Y7.js → chunk-B657ZGDH.js} +2 -2
- package/dist/{chunk-NSQ3GUVO.js → chunk-CYEK6Z3P.js} +4 -4
- package/dist/{chunk-IRYKRBEX.js → chunk-DJMVSUPK.js} +3 -3
- package/dist/{chunk-GLS3A4SQ.js → chunk-DST7HRSG.js} +2 -2
- package/dist/{chunk-UCCB7RKF.js → chunk-EMVJU7WC.js} +2 -2
- package/dist/{chunk-IY7ZISXV.js → chunk-ENNC3RZ6.js} +2 -2
- package/dist/{chunk-QLK3SL7Q.js → chunk-ETSJD5IV.js} +131 -12
- package/dist/chunk-ETSJD5IV.js.map +1 -0
- package/dist/{chunk-PTFL3INS.js → chunk-FC6RCOIU.js} +2 -2
- package/dist/{chunk-CQQTEDHS.js → chunk-FLV7M7CT.js} +2 -2
- package/dist/{chunk-IXF7TRMQ.js → chunk-FRH2UC7Q.js} +2 -2
- package/dist/{chunk-3SL52JKD.js → chunk-FZVROZKC.js} +5 -5
- package/dist/{chunk-Z2EVKNZR.js → chunk-GEGUBU3D.js} +2 -2
- package/dist/{chunk-LIGP5M2C.js → chunk-GF4H3B3R.js} +8 -8
- package/dist/{chunk-7OOW72QA.js → chunk-GVUW5XK5.js} +305 -136
- package/dist/chunk-GVUW5XK5.js.map +1 -0
- package/dist/{chunk-XTWF5XR6.js → chunk-HPAOMYKM.js} +67 -67
- package/dist/{chunk-ZOGZMAGI.js → chunk-I25RINZK.js} +2 -2
- package/dist/{chunk-FMIVV5SV.js → chunk-I56MTWE7.js} +2 -2
- package/dist/{chunk-EUL3S3LE.js → chunk-J5WI4QRP.js} +4 -4
- package/dist/{chunk-436IRJUD.js → chunk-JA54KIYD.js} +2 -2
- package/dist/{chunk-QWNBQ2T5.js → chunk-JMF5Q4JY.js} +10 -10
- package/dist/{chunk-IDSSDL4W.js → chunk-JXSYWTFK.js} +21 -4
- package/dist/{chunk-IDSSDL4W.js.map → chunk-JXSYWTFK.js.map} +1 -1
- package/dist/chunk-KIUVEMBI.js +49 -0
- package/dist/chunk-KIUVEMBI.js.map +1 -0
- package/dist/{chunk-IINXHPCV.js → chunk-KQI2PKYP.js} +2 -2
- package/dist/{chunk-RGPPNNDJ.js → chunk-KSUOM3YU.js} +9 -9
- package/dist/{chunk-CXG2T7BJ.js → chunk-KZEMFD6E.js} +3 -3
- package/dist/{chunk-O57VUN4U.js → chunk-L2VS27PZ.js} +2 -2
- package/dist/{chunk-IVGJXS5F.js → chunk-L34W4W4I.js} +2 -2
- package/dist/{chunk-MEP3POVW.js → chunk-L3PWXD73.js} +2 -2
- package/dist/{chunk-NQHSXHJP.js → chunk-L6GNS5GB.js} +2 -2
- package/dist/{chunk-YMXCJ7SE.js → chunk-M47Q6566.js} +2 -2
- package/dist/{chunk-DQJCQHII.js → chunk-MQNOIH2C.js} +6 -6
- package/dist/{chunk-IDSZNHIP.js → chunk-MULNBSPP.js} +4 -4
- package/dist/{chunk-4DXVWBDB.js → chunk-NBQIFCJE.js} +2 -2
- package/dist/{chunk-H2XCCUOT.js → chunk-NHSVW7UT.js} +15 -15
- package/dist/{chunk-BDHWKFGM.js → chunk-OFEHITAZ.js} +2 -2
- package/dist/{chunk-RYN4AIRM.js → chunk-OZABSIOV.js} +4 -4
- package/dist/{chunk-Y7CXM7UM.js → chunk-QMFKW4OU.js} +3 -3
- package/dist/{chunk-Z63GU5NN.js → chunk-QWWMS4AE.js} +1 -1
- package/dist/chunk-QWWMS4AE.js.map +1 -0
- package/dist/{chunk-R4O2G6ML.js → chunk-RSMIRLKM.js} +2 -2
- package/dist/{chunk-6AH2DDHI.js → chunk-S5TGRZWY.js} +2 -2
- package/dist/{chunk-TYOBAFCY.js → chunk-SNXBXYUE.js} +3 -3
- package/dist/{chunk-MEMH5NKJ.js → chunk-SUAX5JWY.js} +2 -2
- package/dist/{chunk-IHIP7TJ3.js → chunk-SWRN6U7Q.js} +2 -2
- package/dist/{chunk-DBA2W6VV.js → chunk-SZXPKUMN.js} +6 -6
- package/dist/{chunk-WQUGCOKF.js → chunk-TFA6HPOA.js} +4 -4
- package/dist/{chunk-VWCFR4NR.js → chunk-U6OXJQEH.js} +5 -5
- package/dist/{chunk-DYRXRQHV.js → chunk-V32NHP2R.js} +2 -2
- package/dist/{chunk-ORAL4HJC.js → chunk-WG4TMZJ2.js} +2 -2
- package/dist/{chunk-QVBB2CLG.js → chunk-WRICYGYG.js} +27 -26
- package/dist/chunk-WRICYGYG.js.map +1 -0
- package/dist/{chunk-CV5AMCPX.js → chunk-XPRAOTJY.js} +2 -2
- package/dist/{chunk-RZCRXCLI.js → chunk-XQSJXNWC.js} +2 -2
- package/dist/{chunk-P22M3DX3.js → chunk-YJAOYEWI.js} +2 -2
- package/dist/{chunk-OAFRMLL4.js → chunk-YJEUHGZZ.js} +2 -2
- package/dist/cli.js +89 -88
- package/dist/coding/export-okf-codegraph.js +16 -16
- package/dist/compounding/engine.js +17 -17
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +22 -22
- package/dist/connectors/codex-materialize-runner.js +17 -17
- package/dist/connectors/index.js +17 -17
- package/dist/consolidation-provenance-check.js +2 -2
- package/dist/contradiction/index.js +7 -7
- package/dist/convergence-refresh.js +19 -19
- package/dist/conversation-index/backend.js +2 -2
- package/dist/corpus-watermark.js +19 -19
- package/dist/correction/correction-access-wiring.d.ts +6 -6
- package/dist/correction/correction-access-wiring.d.ts.map +1 -1
- package/dist/correction/correction-classify.d.ts +25 -0
- package/dist/correction/correction-classify.d.ts.map +1 -0
- package/dist/correction/correction-config.d.ts +11 -0
- package/dist/correction/correction-config.d.ts.map +1 -0
- package/dist/correction/correction-contract.d.ts +13 -1
- package/dist/correction/correction-contract.d.ts.map +1 -1
- package/dist/correction/correction-executor.d.ts +2 -0
- package/dist/correction/correction-executor.d.ts.map +1 -1
- package/dist/correction/correction-planner.d.ts +24 -3
- package/dist/correction/correction-planner.d.ts.map +1 -1
- package/dist/entity-retrieval.js +17 -17
- package/dist/event-order-recall.js +2 -2
- package/dist/explicit-capture.js +2 -2
- package/dist/external-wiki-access.js +47 -47
- package/dist/extraction-span-materialize.js +2 -2
- package/dist/extraction.js +22 -22
- package/dist/harmonic-retrieval.js +17 -17
- package/dist/index.js +189 -188
- package/dist/lcm/index.js +3 -3
- package/dist/local-llm.d.ts.map +1 -1
- package/dist/local-llm.js +1 -1
- package/dist/location/index.js +19 -19
- package/dist/maintenance/memory-governance.js +17 -17
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +17 -17
- package/dist/maintenance/rebuild-memory-projection-runner.js +19 -19
- package/dist/maintenance/rebuild-memory-projection.js +18 -18
- package/dist/memory-browse-operations.js +47 -47
- package/dist/memory-browse.js +1 -1
- package/dist/memory-subject.js +1 -1
- package/dist/namespaces/migrate.js +18 -18
- package/dist/namespaces/search.js +6 -6
- package/dist/namespaces/storage.js +17 -17
- package/dist/operator-doctor-corpus.js +20 -20
- package/dist/operator-toolkit.js +32 -32
- package/dist/orchestration/maintenance.js +28 -28
- package/dist/orchestration/session-context.d.ts.map +1 -1
- package/dist/orchestrator.js +113 -112
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-navigate-access.js +2 -2
- package/dist/recall-navigate-disclosure.js +2 -2
- package/dist/recall-navigate.js +2 -2
- package/dist/recall-navigation-operations.js +47 -47
- package/dist/recall-navigation.js +46 -46
- package/dist/recall-why-service.js +2 -2
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.js +2 -2
- package/dist/reconcile/manifest.js +3 -3
- package/dist/{resolution-RSG4HZTL.js → resolution-TV3F7ZTH.js} +7 -7
- package/dist/resolution-TV3F7ZTH.js.map +1 -0
- package/dist/resume-bundles.js +23 -23
- package/dist/salvage-envelope.js +1 -1
- package/dist/search/factory.js +5 -5
- package/dist/search/index.js +9 -9
- package/dist/semantic-consolidation.js +23 -23
- package/dist/semantic-rule-promotion.js +17 -17
- package/dist/semantic-rule-verifier.js +17 -17
- package/dist/source-agent-qualifier.js +17 -17
- package/dist/standup/build.js +17 -17
- package/dist/storage.js +16 -16
- package/dist/subject-config.js +1 -1
- package/dist/summarizer.js +3 -3
- package/dist/support-passport/index.js +63 -63
- package/dist/transfer/export-okf.js +17 -17
- package/dist/types.d.ts +6 -23
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/verified-recall.js +17 -17
- package/dist/who-knows-cli.js +18 -18
- package/dist/who-knows.js +17 -17
- package/dist/write-envelope.js +1 -1
- package/package.json +2 -2
- package/src/access-cli.ts +4 -0
- package/src/access-http.ts +1 -0
- package/src/access-mcp-correction-tools.ts +56 -0
- package/src/access-mcp.ts +4 -49
- package/src/access-operations.ts +3 -0
- package/src/access-service.ts +12 -21
- package/src/config.test.ts +26 -0
- package/src/config.ts +4 -60
- package/src/correction/correction-access-wiring.ts +56 -16
- package/src/correction/correction-classify.test.ts +185 -0
- package/src/correction/correction-classify.ts +157 -0
- package/src/correction/correction-config.ts +93 -0
- package/src/correction/correction-contract.ts +61 -14
- package/src/correction/correction-executor.test.ts +102 -2
- package/src/correction/correction-executor.ts +19 -1
- package/src/correction/correction-planner.test.ts +141 -0
- package/src/correction/correction-planner.ts +117 -11
- package/src/correction/correction-surfaces.test.ts +22 -1
- package/src/local-llm-qos.test.ts +36 -0
- package/src/local-llm.ts +20 -3
- package/src/orchestration/session-context.ts +0 -15
- package/src/recall-handles-wiring.test.ts +24 -0
- package/src/types.ts +6 -23
- package/dist/chunk-5QHTQMRL.js.map +0 -1
- package/dist/chunk-7OOW72QA.js.map +0 -1
- package/dist/chunk-QLK3SL7Q.js.map +0 -1
- package/dist/chunk-QVBB2CLG.js.map +0 -1
- package/dist/chunk-RH6MQ5NG.js.map +0 -1
- package/dist/chunk-WLC6XA6C.js.map +0 -1
- package/dist/chunk-Z63GU5NN.js.map +0 -1
- /package/dist/{resolution-RSG4HZTL.js.map → access-mcp-correction-tools.js.map} +0 -0
- /package/dist/{chunk-5YDWSWBU.js.map → chunk-2CP577K6.js.map} +0 -0
- /package/dist/{chunk-ABET5LA5.js.map → chunk-37HCPM56.js.map} +0 -0
- /package/dist/{chunk-H6FA36LC.js.map → chunk-4K2H4KTR.js.map} +0 -0
- /package/dist/{chunk-TSEUVMJL.js.map → chunk-52CQKST6.js.map} +0 -0
- /package/dist/{chunk-H7BZBSP6.js.map → chunk-52II7PB6.js.map} +0 -0
- /package/dist/{chunk-ABDTBGI2.js.map → chunk-5CQO6LVM.js.map} +0 -0
- /package/dist/{chunk-HSZBALHV.js.map → chunk-5LNPW7NE.js.map} +0 -0
- /package/dist/{chunk-U3LVARGV.js.map → chunk-5X4ZJESN.js.map} +0 -0
- /package/dist/{chunk-SNGNGH53.js.map → chunk-63UNVGZW.js.map} +0 -0
- /package/dist/{chunk-2KB7TTAP.js.map → chunk-64S6X4IU.js.map} +0 -0
- /package/dist/{chunk-3QAIX7TV.js.map → chunk-6KHF6PAB.js.map} +0 -0
- /package/dist/{chunk-MYBCB4AT.js.map → chunk-6T42L5FI.js.map} +0 -0
- /package/dist/{chunk-R6EOFKZG.js.map → chunk-7LYRFI5A.js.map} +0 -0
- /package/dist/{chunk-4NFRYOHT.js.map → chunk-ANZXWOYD.js.map} +0 -0
- /package/dist/{chunk-QDKABMUE.js.map → chunk-AXC7UTLM.js.map} +0 -0
- /package/dist/{chunk-5XXTZ4Y7.js.map → chunk-B657ZGDH.js.map} +0 -0
- /package/dist/{chunk-NSQ3GUVO.js.map → chunk-CYEK6Z3P.js.map} +0 -0
- /package/dist/{chunk-IRYKRBEX.js.map → chunk-DJMVSUPK.js.map} +0 -0
- /package/dist/{chunk-GLS3A4SQ.js.map → chunk-DST7HRSG.js.map} +0 -0
- /package/dist/{chunk-UCCB7RKF.js.map → chunk-EMVJU7WC.js.map} +0 -0
- /package/dist/{chunk-IY7ZISXV.js.map → chunk-ENNC3RZ6.js.map} +0 -0
- /package/dist/{chunk-PTFL3INS.js.map → chunk-FC6RCOIU.js.map} +0 -0
- /package/dist/{chunk-CQQTEDHS.js.map → chunk-FLV7M7CT.js.map} +0 -0
- /package/dist/{chunk-IXF7TRMQ.js.map → chunk-FRH2UC7Q.js.map} +0 -0
- /package/dist/{chunk-3SL52JKD.js.map → chunk-FZVROZKC.js.map} +0 -0
- /package/dist/{chunk-Z2EVKNZR.js.map → chunk-GEGUBU3D.js.map} +0 -0
- /package/dist/{chunk-LIGP5M2C.js.map → chunk-GF4H3B3R.js.map} +0 -0
- /package/dist/{chunk-XTWF5XR6.js.map → chunk-HPAOMYKM.js.map} +0 -0
- /package/dist/{chunk-ZOGZMAGI.js.map → chunk-I25RINZK.js.map} +0 -0
- /package/dist/{chunk-FMIVV5SV.js.map → chunk-I56MTWE7.js.map} +0 -0
- /package/dist/{chunk-EUL3S3LE.js.map → chunk-J5WI4QRP.js.map} +0 -0
- /package/dist/{chunk-436IRJUD.js.map → chunk-JA54KIYD.js.map} +0 -0
- /package/dist/{chunk-QWNBQ2T5.js.map → chunk-JMF5Q4JY.js.map} +0 -0
- /package/dist/{chunk-IINXHPCV.js.map → chunk-KQI2PKYP.js.map} +0 -0
- /package/dist/{chunk-RGPPNNDJ.js.map → chunk-KSUOM3YU.js.map} +0 -0
- /package/dist/{chunk-CXG2T7BJ.js.map → chunk-KZEMFD6E.js.map} +0 -0
- /package/dist/{chunk-O57VUN4U.js.map → chunk-L2VS27PZ.js.map} +0 -0
- /package/dist/{chunk-IVGJXS5F.js.map → chunk-L34W4W4I.js.map} +0 -0
- /package/dist/{chunk-MEP3POVW.js.map → chunk-L3PWXD73.js.map} +0 -0
- /package/dist/{chunk-NQHSXHJP.js.map → chunk-L6GNS5GB.js.map} +0 -0
- /package/dist/{chunk-YMXCJ7SE.js.map → chunk-M47Q6566.js.map} +0 -0
- /package/dist/{chunk-DQJCQHII.js.map → chunk-MQNOIH2C.js.map} +0 -0
- /package/dist/{chunk-IDSZNHIP.js.map → chunk-MULNBSPP.js.map} +0 -0
- /package/dist/{chunk-4DXVWBDB.js.map → chunk-NBQIFCJE.js.map} +0 -0
- /package/dist/{chunk-H2XCCUOT.js.map → chunk-NHSVW7UT.js.map} +0 -0
- /package/dist/{chunk-BDHWKFGM.js.map → chunk-OFEHITAZ.js.map} +0 -0
- /package/dist/{chunk-RYN4AIRM.js.map → chunk-OZABSIOV.js.map} +0 -0
- /package/dist/{chunk-Y7CXM7UM.js.map → chunk-QMFKW4OU.js.map} +0 -0
- /package/dist/{chunk-R4O2G6ML.js.map → chunk-RSMIRLKM.js.map} +0 -0
- /package/dist/{chunk-6AH2DDHI.js.map → chunk-S5TGRZWY.js.map} +0 -0
- /package/dist/{chunk-TYOBAFCY.js.map → chunk-SNXBXYUE.js.map} +0 -0
- /package/dist/{chunk-MEMH5NKJ.js.map → chunk-SUAX5JWY.js.map} +0 -0
- /package/dist/{chunk-IHIP7TJ3.js.map → chunk-SWRN6U7Q.js.map} +0 -0
- /package/dist/{chunk-DBA2W6VV.js.map → chunk-SZXPKUMN.js.map} +0 -0
- /package/dist/{chunk-WQUGCOKF.js.map → chunk-TFA6HPOA.js.map} +0 -0
- /package/dist/{chunk-VWCFR4NR.js.map → chunk-U6OXJQEH.js.map} +0 -0
- /package/dist/{chunk-DYRXRQHV.js.map → chunk-V32NHP2R.js.map} +0 -0
- /package/dist/{chunk-ORAL4HJC.js.map → chunk-WG4TMZJ2.js.map} +0 -0
- /package/dist/{chunk-CV5AMCPX.js.map → chunk-XPRAOTJY.js.map} +0 -0
- /package/dist/{chunk-RZCRXCLI.js.map → chunk-XQSJXNWC.js.map} +0 -0
- /package/dist/{chunk-P22M3DX3.js.map → chunk-YJAOYEWI.js.map} +0 -0
- /package/dist/{chunk-OAFRMLL4.js.map → chunk-YJEUHGZZ.js.map} +0 -0
package/src/access-cli.ts
CHANGED
|
@@ -207,6 +207,7 @@ function usage(): string {
|
|
|
207
207
|
"Correct options (issue #1580 — one plan/apply pipeline for all corrections):",
|
|
208
208
|
" --text \"<correction>\" plan a correction from natural language",
|
|
209
209
|
" --id <memoryId> (repeatable) explicit target memory ids",
|
|
210
|
+
" --duplicate-of <memoryId> winner id; requires exactly one --id (skips the classifier)",
|
|
210
211
|
" --apply apply a pending plan (requires --plan-id + --confirm)",
|
|
211
212
|
" --plan-id <id> the plan to apply or discard",
|
|
212
213
|
" --confirm confirm the apply (safety guard, rule 48)",
|
|
@@ -297,6 +298,7 @@ const COMMAND_SPECS: Record<CommandName, CommandSpec> = {
|
|
|
297
298
|
valueOptions: new Set([
|
|
298
299
|
"text",
|
|
299
300
|
"id",
|
|
301
|
+
"duplicate-of",
|
|
300
302
|
"plan-id",
|
|
301
303
|
"namespace",
|
|
302
304
|
"session-key",
|
|
@@ -830,6 +832,7 @@ async function runCorrect(args: ParsedArgs, preferredId?: string): Promise<void>
|
|
|
830
832
|
// so schema validation + namespace policy reach this path (same as MCP/HTTP).
|
|
831
833
|
const text = requireOption(args, "text");
|
|
832
834
|
const targetIds = getAllOptions(args, "id");
|
|
835
|
+
const duplicateOf = getLastOption(args, "duplicate-of");
|
|
833
836
|
const planOp = getOperation("memory_correct_plan");
|
|
834
837
|
if (!planOp) {
|
|
835
838
|
throw new Error("access-boundary: operation not registered: memory_correct_plan");
|
|
@@ -838,6 +841,7 @@ async function runCorrect(args: ParsedArgs, preferredId?: string): Promise<void>
|
|
|
838
841
|
{
|
|
839
842
|
text,
|
|
840
843
|
...(targetIds.length > 0 ? { targetIds } : {}),
|
|
844
|
+
...(duplicateOf ? { duplicateOf } : {}),
|
|
841
845
|
...(sessionKey ? { sessionKey } : {}),
|
|
842
846
|
...(namespace ? { namespace } : {}),
|
|
843
847
|
},
|
package/src/access-http.ts
CHANGED
|
@@ -1999,6 +1999,7 @@ export class EngramAccessHttpServer extends ReviewDeckAccessHttpBase {
|
|
|
1999
1999
|
const output = (await op.run(this.gatedBodyNamespace(req, body), {
|
|
2000
2000
|
service: this.service,
|
|
2001
2001
|
authenticatedPrincipal: this.resolveRequestPrincipal(req),
|
|
2002
|
+
...(abortSignal ? { abortSignal } : {}),
|
|
2002
2003
|
})) as { result: unknown };
|
|
2003
2004
|
this.recordWriteRateLimitHit(req);
|
|
2004
2005
|
this.respondJson(res, 200, output.result);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Correction MCP tool descriptors.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from access-mcp.ts (over its fileSizeGrandfather ceiling) so
|
|
5
|
+
* `duplicateOf` can land without growing that file. Aliases are applied by
|
|
6
|
+
* the caller via withToolAliases.
|
|
7
|
+
*/
|
|
8
|
+
import type { McpTool } from "./access-mcp.js";
|
|
9
|
+
|
|
10
|
+
export const correctionMcpTools: McpTool[] = [
|
|
11
|
+
{
|
|
12
|
+
name: "engram.memory_correct_plan",
|
|
13
|
+
description:
|
|
14
|
+
"Plan a memory correction from a plain-language statement. Returns a CorrectionPlan with a diff preview; apply via memory_correct_apply. Pass duplicateOf plus one targetIds entry to supersede that duplicate without calling the classifier.",
|
|
15
|
+
inputSchema: {
|
|
16
|
+
type: "object",
|
|
17
|
+
properties: {
|
|
18
|
+
text: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: 'The natural-language correction (e.g. "we migrated to MySQL in March").',
|
|
21
|
+
},
|
|
22
|
+
targetIds: {
|
|
23
|
+
type: "array",
|
|
24
|
+
items: { type: "string" },
|
|
25
|
+
description:
|
|
26
|
+
"Optional explicit target memory ids. When omitted, the planner searches. With duplicateOf, pass exactly the duplicate id.",
|
|
27
|
+
},
|
|
28
|
+
duplicateOf: {
|
|
29
|
+
type: "string",
|
|
30
|
+
description:
|
|
31
|
+
"Optional winner memory id. Requires targetIds to be exactly the duplicate. Skips classification and drafts one recoverable supersede (no hard delete) linking the duplicate to this id.",
|
|
32
|
+
},
|
|
33
|
+
sessionKey: { type: "string", description: "Session identifier for namespace resolution." },
|
|
34
|
+
namespace: { type: "string", description: "Optional explicit namespace (validated by policy)." },
|
|
35
|
+
},
|
|
36
|
+
required: ["text"],
|
|
37
|
+
additionalProperties: false,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "engram.memory_correct_apply",
|
|
42
|
+
description:
|
|
43
|
+
"Apply a planned memory correction by planId. Requires confirm: true when correction.applyRequiresConfirm is on (default).",
|
|
44
|
+
inputSchema: {
|
|
45
|
+
type: "object",
|
|
46
|
+
properties: {
|
|
47
|
+
planId: { type: "string", description: "The plan id returned by memory_correct_plan." },
|
|
48
|
+
confirm: { type: "boolean", description: "Must be true to apply (safety guard)." },
|
|
49
|
+
sessionKey: { type: "string", description: "Session identifier for namespace resolution." },
|
|
50
|
+
namespace: { type: "string", description: "Optional explicit namespace (validated by policy)." },
|
|
51
|
+
},
|
|
52
|
+
required: ["planId"],
|
|
53
|
+
additionalProperties: false,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
];
|
package/src/access-mcp.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { sharedContextMcpTools } from "./access-mcp-shared-context-tools.js";
|
|
2
|
+
import { correctionMcpTools } from "./access-mcp-correction-tools.js";
|
|
2
3
|
import { randomUUID } from "node:crypto";
|
|
3
4
|
import {
|
|
4
5
|
MCP_ADMIN_OPS_MIGRATED_OPERATIONS,
|
|
@@ -2133,56 +2134,10 @@ export class EngramMcpServer {
|
|
|
2133
2134
|
this.tools = [...this.tools, ...deltaTools];
|
|
2134
2135
|
}
|
|
2135
2136
|
if (this.correctionVisible) {
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
// (memory_correct_plan / memory_correct_apply) which delegate to the
|
|
2139
|
-
// CorrectionService.
|
|
2140
|
-
const planTool = withToolAliases(
|
|
2141
|
-
{
|
|
2142
|
-
name: "engram.memory_correct_plan",
|
|
2143
|
-
description:
|
|
2144
|
-
"Plan a memory correction from a plain-language statement (issue #1580). Returns a CorrectionPlan with a diff preview; apply via memory_correct_apply.",
|
|
2145
|
-
inputSchema: {
|
|
2146
|
-
type: "object",
|
|
2147
|
-
properties: {
|
|
2148
|
-
text: {
|
|
2149
|
-
type: "string",
|
|
2150
|
-
description: 'The natural-language correction (e.g. "we migrated to MySQL in March").',
|
|
2151
|
-
},
|
|
2152
|
-
targetIds: {
|
|
2153
|
-
type: "array",
|
|
2154
|
-
items: { type: "string" },
|
|
2155
|
-
description: "Optional explicit target memory ids. When omitted, the planner searches.",
|
|
2156
|
-
},
|
|
2157
|
-
sessionKey: { type: "string", description: "Session identifier for namespace resolution." },
|
|
2158
|
-
namespace: { type: "string", description: "Optional explicit namespace (validated by policy)." },
|
|
2159
|
-
},
|
|
2160
|
-
required: ["text"],
|
|
2161
|
-
additionalProperties: false,
|
|
2162
|
-
},
|
|
2163
|
-
},
|
|
2164
|
-
this.emitLegacyTools
|
|
2165
|
-
);
|
|
2166
|
-
const applyTool = withToolAliases(
|
|
2167
|
-
{
|
|
2168
|
-
name: "engram.memory_correct_apply",
|
|
2169
|
-
description:
|
|
2170
|
-
"Apply a planned memory correction by planId (issue #1580). Requires confirm: true when correction.applyRequiresConfirm is on (default).",
|
|
2171
|
-
inputSchema: {
|
|
2172
|
-
type: "object",
|
|
2173
|
-
properties: {
|
|
2174
|
-
planId: { type: "string", description: "The plan id returned by memory_correct_plan." },
|
|
2175
|
-
confirm: { type: "boolean", description: "Must be true to apply (safety guard, rule 48)." },
|
|
2176
|
-
sessionKey: { type: "string", description: "Session identifier for namespace resolution." },
|
|
2177
|
-
namespace: { type: "string", description: "Optional explicit namespace (validated by policy)." },
|
|
2178
|
-
},
|
|
2179
|
-
required: ["planId"],
|
|
2180
|
-
additionalProperties: false,
|
|
2181
|
-
},
|
|
2182
|
-
},
|
|
2183
|
-
this.emitLegacyTools
|
|
2137
|
+
const correctionTools = correctionMcpTools.flatMap((tool) =>
|
|
2138
|
+
withToolAliases(tool, this.emitLegacyTools),
|
|
2184
2139
|
);
|
|
2185
|
-
this.tools = [...this.tools, ...
|
|
2140
|
+
this.tools = [...this.tools, ...correctionTools];
|
|
2186
2141
|
}
|
|
2187
2142
|
if (this.chatVisible) {
|
|
2188
2143
|
const chatTools = withToolAliases(
|
package/src/access-operations.ts
CHANGED
|
@@ -384,6 +384,7 @@ const memoryCorrectPlanSchema = z.preprocess(
|
|
|
384
384
|
z.object({
|
|
385
385
|
text: z.string().trim().min(1).max(10_000),
|
|
386
386
|
targetIds: z.array(z.string().trim().min(1).max(512)).optional(),
|
|
387
|
+
duplicateOf: z.string().trim().min(1).max(512).optional(),
|
|
387
388
|
sessionKey: z.string().trim().max(512).optional(),
|
|
388
389
|
namespace: z.string().trim().max(256).optional(),
|
|
389
390
|
}),
|
|
@@ -392,6 +393,7 @@ const memoryCorrectPlanSchema = z.preprocess(
|
|
|
392
393
|
export interface MemoryCorrectPlanInput {
|
|
393
394
|
text: string;
|
|
394
395
|
targetIds?: string[];
|
|
396
|
+
duplicateOf?: string;
|
|
395
397
|
sessionKey?: string;
|
|
396
398
|
namespace?: string;
|
|
397
399
|
}
|
|
@@ -414,6 +416,7 @@ export const memoryCorrectPlanOperation = defineOperation<
|
|
|
414
416
|
{
|
|
415
417
|
text: input.text,
|
|
416
418
|
...(input.targetIds ? { targetIds: input.targetIds } : {}),
|
|
419
|
+
...(input.duplicateOf ? { duplicateOf: input.duplicateOf } : {}),
|
|
417
420
|
...(input.sessionKey ? { sessionKey: input.sessionKey } : {}),
|
|
418
421
|
...(input.namespace ? { namespace: input.namespace } : {}),
|
|
419
422
|
...(ctx.authenticatedPrincipal ? { principal: ctx.authenticatedPrincipal } : {}),
|
package/src/access-service.ts
CHANGED
|
@@ -3349,24 +3349,6 @@ export class EngramAccessService extends SupportPassportAccessServiceBase {
|
|
|
3349
3349
|
return Promise.resolve(false);
|
|
3350
3350
|
}
|
|
3351
3351
|
},
|
|
3352
|
-
// Wire the orchestrator's extraction LLM so classify+draft actually
|
|
3353
|
-
// drafts actions instead of always hitting the deterministic fallback
|
|
3354
|
-
// (review thread PG5). The planner's classifyAndDraft already falls back
|
|
3355
|
-
// on any LLM outage, so returning null (LLM disabled/cooldown) or a
|
|
3356
|
-
// thrown error both degrade safely to the deterministic path (rule 13).
|
|
3357
|
-
llmComplete: async ({ system, user }) => {
|
|
3358
|
-
const result = await this.orchestrator.localLlm.chatCompletion(
|
|
3359
|
-
[
|
|
3360
|
-
{ role: "system", content: system },
|
|
3361
|
-
{ role: "user", content: user },
|
|
3362
|
-
],
|
|
3363
|
-
{ operation: "correction-classify", priority: "background" }
|
|
3364
|
-
);
|
|
3365
|
-
if (!result) {
|
|
3366
|
-
throw new Error("correction classify+draft: local LLM unavailable (disabled or in cooldown)");
|
|
3367
|
-
}
|
|
3368
|
-
return result.content;
|
|
3369
|
-
},
|
|
3370
3352
|
});
|
|
3371
3353
|
this._correctionService = service;
|
|
3372
3354
|
return service;
|
|
@@ -3389,11 +3371,20 @@ export class EngramAccessService extends SupportPassportAccessServiceBase {
|
|
|
3389
3371
|
}
|
|
3390
3372
|
|
|
3391
3373
|
async correctionPlan(request: CorrectionRequest, opts?: { abortSignal?: AbortSignal }): Promise<CorrectionPlan> {
|
|
3374
|
+
let next = request;
|
|
3392
3375
|
if (request.targetIds?.some((id) => isHandleToken(id))) {
|
|
3393
|
-
|
|
3394
|
-
|
|
3376
|
+
next = {
|
|
3377
|
+
...next,
|
|
3378
|
+
targetIds: request.targetIds.map((id) => this.resolveMemoryIdOrHandleInput(id, request.sessionKey)),
|
|
3379
|
+
};
|
|
3380
|
+
}
|
|
3381
|
+
if (request.duplicateOf && isHandleToken(request.duplicateOf)) {
|
|
3382
|
+
next = {
|
|
3383
|
+
...next,
|
|
3384
|
+
duplicateOf: this.resolveMemoryIdOrHandleInput(request.duplicateOf, request.sessionKey),
|
|
3385
|
+
};
|
|
3395
3386
|
}
|
|
3396
|
-
return this.correctionService().plan(
|
|
3387
|
+
return this.correctionService().plan(next, opts);
|
|
3397
3388
|
}
|
|
3398
3389
|
|
|
3399
3390
|
async correctionApply(
|
package/src/config.test.ts
CHANGED
|
@@ -2463,6 +2463,32 @@ test("parseConfig rejects invalid correction.planTtlHours instead of silently de
|
|
|
2463
2463
|
assert.equal(parseConfig({}).correctionPlanTtlHours, 24, "absent → documented default");
|
|
2464
2464
|
});
|
|
2465
2465
|
|
|
2466
|
+
test("parseConfig correction.classifyTimeoutMs defaults to 45000 and rejects invalid values", () => {
|
|
2467
|
+
assert.equal(parseConfig({}).correctionClassifyTimeoutMs, 45_000);
|
|
2468
|
+
assert.equal(parseConfig({ correction: { classifyTimeoutMs: 12000 } }).correctionClassifyTimeoutMs, 12_000);
|
|
2469
|
+
assert.equal(
|
|
2470
|
+
parseConfig({
|
|
2471
|
+
correction: { classifyTimeoutMs: 8000 },
|
|
2472
|
+
correctionClassifyTimeoutMs: 1000,
|
|
2473
|
+
}).correctionClassifyTimeoutMs,
|
|
2474
|
+
8000,
|
|
2475
|
+
"nested correction.classifyTimeoutMs wins",
|
|
2476
|
+
);
|
|
2477
|
+
assert.equal(parseConfig({ correctionClassifyTimeoutMs: 15000 }).correctionClassifyTimeoutMs, 15_000);
|
|
2478
|
+
for (const value of [0, -1, 3.7, "abc", 300_001, true]) {
|
|
2479
|
+
assert.throws(
|
|
2480
|
+
() => parseConfig({ correctionClassifyTimeoutMs: value } as Record<string, unknown>),
|
|
2481
|
+
/Invalid correction\.classifyTimeoutMs/,
|
|
2482
|
+
`correctionClassifyTimeoutMs=${JSON.stringify(value)} should throw`,
|
|
2483
|
+
);
|
|
2484
|
+
assert.throws(
|
|
2485
|
+
() => parseConfig({ correction: { classifyTimeoutMs: value } } as Record<string, unknown>),
|
|
2486
|
+
/Invalid correction\.classifyTimeoutMs/,
|
|
2487
|
+
`nested classifyTimeoutMs=${JSON.stringify(value)} should throw`,
|
|
2488
|
+
);
|
|
2489
|
+
}
|
|
2490
|
+
});
|
|
2491
|
+
|
|
2466
2492
|
test("parseConfig correction.maxAffected rejects non-integers (Number.isInteger, #1678)", () => {
|
|
2467
2493
|
// The error message says "integer" — 3.7 must be rejected, not silently floored to 3.
|
|
2468
2494
|
for (const value of [3.7, 2.5, "1.5", 0.99]) {
|
package/src/config.ts
CHANGED
|
@@ -28,6 +28,7 @@ import type {
|
|
|
28
28
|
import { parseBackgroundGeneration } from "./background-generation-config.js";
|
|
29
29
|
import { parseSearchBackend } from "./config-search-backend.js";
|
|
30
30
|
import { parseLocalLlmConfig } from "./local-llm-config.js";
|
|
31
|
+
import { parseCorrectionConfig } from "./correction/correction-config.js";
|
|
31
32
|
import { parseConvergeConfig } from "./converge-config.js";
|
|
32
33
|
import { parseExternalWikiRecallGuard } from "./external-wiki-guard.js";
|
|
33
34
|
import { log } from "./logger.js";
|
|
@@ -1855,66 +1856,9 @@ export function parseConfig(
|
|
|
1855
1856
|
// (docs kept honest — review: wire resolver before exposing the gate).
|
|
1856
1857
|
temporalBiTemporal: coerceBool(cfg.temporalBiTemporal) ?? false,
|
|
1857
1858
|
temporalExpiredInInjection: coerceBool(cfg.temporalExpiredInInjection) ?? false,
|
|
1858
|
-
// Correction Contract (
|
|
1859
|
-
//
|
|
1860
|
-
|
|
1861
|
-
// flat legacy keys are dropped and the runtime always sees defaults. Nested
|
|
1862
|
-
// `correction.<key>` wins; flat `correction<Key>` is the legacy fallback.
|
|
1863
|
-
correctionEnabled: (() => {
|
|
1864
|
-
const nested = (cfg.correction as Record<string, unknown> | undefined)?.enabled;
|
|
1865
|
-
const raw = nested !== undefined ? nested : cfg.correctionEnabled;
|
|
1866
|
-
if (raw === undefined || raw === null) return true;
|
|
1867
|
-
const v = coerceBool(raw);
|
|
1868
|
-
if (v === undefined) {
|
|
1869
|
-
throw new Error(`Invalid correction.enabled: expected a boolean, got ${JSON.stringify(raw)}`);
|
|
1870
|
-
}
|
|
1871
|
-
return v;
|
|
1872
|
-
})(),
|
|
1873
|
-
correctionApplyRequiresConfirm: (() => {
|
|
1874
|
-
const nested = (cfg.correction as Record<string, unknown> | undefined)?.applyRequiresConfirm;
|
|
1875
|
-
const raw = nested !== undefined ? nested : cfg.correctionApplyRequiresConfirm;
|
|
1876
|
-
if (raw === undefined || raw === null) return true;
|
|
1877
|
-
const v = coerceBool(raw);
|
|
1878
|
-
if (v === undefined) {
|
|
1879
|
-
throw new Error(`Invalid correction.applyRequiresConfirm: expected a boolean, got ${JSON.stringify(raw)}`);
|
|
1880
|
-
}
|
|
1881
|
-
return v;
|
|
1882
|
-
})(),
|
|
1883
|
-
correctionMaxAffected: (() => {
|
|
1884
|
-
const rawNested = (cfg.correction as Record<string, unknown> | undefined)?.maxAffected;
|
|
1885
|
-
const raw = rawNested !== undefined ? rawNested : cfg.correctionMaxAffected;
|
|
1886
|
-
if (raw === undefined || raw === null) return 10;
|
|
1887
|
-
const n = coerceNumber(raw);
|
|
1888
|
-
// #1678 (thread Oiup6): the error message says "integer" — enforce it
|
|
1889
|
-
// with Number.isInteger so 3.7 is rejected rather than silently floored.
|
|
1890
|
-
if (n === undefined || !Number.isFinite(n) || n < 1 || !Number.isInteger(n)) {
|
|
1891
|
-
throw new Error(`Invalid correction.maxAffected: expected an integer >= 1, got ${JSON.stringify(raw)}`);
|
|
1892
|
-
}
|
|
1893
|
-
return n;
|
|
1894
|
-
})(),
|
|
1895
|
-
correctionPlanTtlHours: (() => {
|
|
1896
|
-
const nested = (cfg.correction as Record<string, unknown> | undefined)?.planTtlHours;
|
|
1897
|
-
const fromNested = nested !== undefined ? coerceNumber(nested) : undefined;
|
|
1898
|
-
if (fromNested !== undefined && fromNested >= 1) return fromNested;
|
|
1899
|
-
// #1678 (threads Ohtvi/Ohyvf): reject invalid (0/negative/non-numeric)
|
|
1900
|
-
// instead of silently defaulting to 24h — completes the config-reject
|
|
1901
|
-
// class already enforced for enabled/applyRequiresConfirm/maxAffected.
|
|
1902
|
-
if (nested !== undefined && fromNested === undefined) {
|
|
1903
|
-
throw new Error(`Invalid correction.planTtlHours: expected a number >= 1, got ${JSON.stringify(nested)}`);
|
|
1904
|
-
}
|
|
1905
|
-
if (fromNested !== undefined && fromNested < 1) {
|
|
1906
|
-
throw new Error(`Invalid correction.planTtlHours: expected a number >= 1, got ${JSON.stringify(nested)}`);
|
|
1907
|
-
}
|
|
1908
|
-
const fromFlat = coerceNumber(cfg.correctionPlanTtlHours);
|
|
1909
|
-
if (fromFlat !== undefined && fromFlat >= 1) return fromFlat;
|
|
1910
|
-
if (cfg.correctionPlanTtlHours !== undefined && fromFlat === undefined) {
|
|
1911
|
-
throw new Error(`Invalid correction.planTtlHours: expected a number >= 1, got ${JSON.stringify(cfg.correctionPlanTtlHours)}`);
|
|
1912
|
-
}
|
|
1913
|
-
if (fromFlat !== undefined && fromFlat < 1) {
|
|
1914
|
-
throw new Error(`Invalid correction.planTtlHours: expected a number >= 1, got ${JSON.stringify(cfg.correctionPlanTtlHours)}`);
|
|
1915
|
-
}
|
|
1916
|
-
return 24;
|
|
1917
|
-
})(),
|
|
1859
|
+
// Correction Contract (#1580). Nested `correction.<key>` wins over flat
|
|
1860
|
+
// `correction<Key>`. Parser lives in correction/correction-config.ts.
|
|
1861
|
+
...parseCorrectionConfig(cfg),
|
|
1918
1862
|
// Passive correction capture (issue #1581). Parsed from
|
|
1919
1863
|
// `correctionCapture.<key>` (nested) or flat legacy keys. Default "off" —
|
|
1920
1864
|
// operators opt in (rule 48). Invalid mode → rejected listing options (rule 51).
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
import path from "node:path";
|
|
24
|
-
import { throwIfAborted } from "../abort-error.js";
|
|
24
|
+
import { abortError, isAbortError, throwIfAborted } from "../abort-error.js";
|
|
25
25
|
import { composeMemoryEnvelope, isMemoryCategory } from "../write-envelope.js";
|
|
26
26
|
import { log } from "../logger.js";
|
|
27
27
|
import { createHash } from "node:crypto";
|
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
} from "./correction-planner.js";
|
|
49
49
|
import { type ExecutorDeps, type ExecutorMemory } from "./correction-executor.js";
|
|
50
50
|
import { CorrectionService, type CorrectionServiceDeps } from "./correction-service.js";
|
|
51
|
+
import { completeCorrectionClassify } from "./correction-classify.js";
|
|
51
52
|
import { resolveRecallAuxiliaryCapabilities } from "../capabilities.js";
|
|
52
53
|
import { isSupportPassportPrivateMemory } from "../support-passport/card-projection.js";
|
|
53
54
|
|
|
@@ -81,15 +82,15 @@ export interface CorrectionAccessWiring {
|
|
|
81
82
|
principal?: string;
|
|
82
83
|
}): Promise<boolean>;
|
|
83
84
|
/**
|
|
84
|
-
* Optional
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* ships with the safe fallback.
|
|
85
|
+
* Optional test override for classify+draft. Production leaves this unset
|
|
86
|
+
* and uses completeCorrectionClassify: a short per-attempt timeout, caller
|
|
87
|
+
* abort, then the gateway/fallback model. A caller abort propagates; every
|
|
88
|
+
* other failure becomes the deterministic empty-action plan.
|
|
89
89
|
*/
|
|
90
90
|
llmComplete?(request: {
|
|
91
91
|
system: string;
|
|
92
92
|
user: string;
|
|
93
|
+
abortSignal?: AbortSignal;
|
|
93
94
|
}): Promise<string>;
|
|
94
95
|
}
|
|
95
96
|
|
|
@@ -144,10 +145,12 @@ function makePlannerDeps(
|
|
|
144
145
|
searchMemories(wiring, text, namespaces, limit),
|
|
145
146
|
resolveTargets: async ({ targetIds, namespaces }) =>
|
|
146
147
|
resolveTargetMemories(wiring, targetIds, namespaces),
|
|
148
|
+
inspectMemory: async ({ memoryId, namespaces }) =>
|
|
149
|
+
inspectCorrectionMemory(wiring, memoryId, namespaces),
|
|
147
150
|
expandNeighbors: async ({ seedIds, namespaces, limit }) =>
|
|
148
151
|
expandEntityNeighbors(wiring, seedIds, namespaces, limit),
|
|
149
|
-
classifyAndDraft: async ({ text, candidates }) =>
|
|
150
|
-
classifyAndDraft(wiring, text, candidates),
|
|
152
|
+
classifyAndDraft: async ({ text, candidates, abortSignal }) =>
|
|
153
|
+
classifyAndDraft(wiring, text, candidates, abortSignal),
|
|
151
154
|
renderDiff: async ({ candidates, actions }) =>
|
|
152
155
|
renderCorrectionDiff(wiring, candidates, actions),
|
|
153
156
|
storageDir: async (namespace) => (await wiring.orchestrator.getStorage(namespace)).dir,
|
|
@@ -294,22 +297,54 @@ async function classifyAndDraft(
|
|
|
294
297
|
wiring: CorrectionAccessWiring,
|
|
295
298
|
text: string,
|
|
296
299
|
candidates: PlannerCandidate[],
|
|
300
|
+
abortSignal?: AbortSignal,
|
|
297
301
|
): Promise<LlmClassificationResult> {
|
|
298
|
-
//
|
|
299
|
-
//
|
|
300
|
-
//
|
|
302
|
+
// Injected llmComplete stays as a test override. Production uses
|
|
303
|
+
// completeCorrectionClassify: short timeout, caller abort, gateway fallback.
|
|
304
|
+
// Abort throws. Every other failure is the deterministic empty-action plan.
|
|
301
305
|
try {
|
|
302
|
-
|
|
303
|
-
return fallbackClassification(candidates, "no LLM client available");
|
|
304
|
-
}
|
|
306
|
+
throwIfAborted(abortSignal, "correction classify aborted");
|
|
305
307
|
const user = buildClassifyPrompt(text, candidates);
|
|
306
|
-
const raw =
|
|
308
|
+
const raw = wiring.llmComplete
|
|
309
|
+
? await wiring.llmComplete({ system: CLASSIFY_SYSTEM_PROMPT, user, abortSignal })
|
|
310
|
+
: await completeCorrectionClassify(
|
|
311
|
+
[
|
|
312
|
+
{ role: "system", content: CLASSIFY_SYSTEM_PROMPT },
|
|
313
|
+
{ role: "user", content: user },
|
|
314
|
+
],
|
|
315
|
+
{ config: wiring.orchestrator.config, localLlm: wiring.orchestrator.localLlm },
|
|
316
|
+
abortSignal,
|
|
317
|
+
);
|
|
318
|
+
if (raw == null) return fallbackClassification(candidates, "correction classify unavailable");
|
|
319
|
+
throwIfAborted(abortSignal, "correction classify aborted");
|
|
307
320
|
return parseClassifyResponse(raw, candidates);
|
|
308
321
|
} catch (err) {
|
|
322
|
+
if (isAbortError(err) || abortSignal?.aborted) {
|
|
323
|
+
throw isAbortError(err) ? err : abortError("correction classify aborted");
|
|
324
|
+
}
|
|
309
325
|
return fallbackClassification(candidates, `LLM unavailable: ${errMsg(err)}`);
|
|
310
326
|
}
|
|
311
327
|
}
|
|
312
328
|
|
|
329
|
+
async function inspectCorrectionMemory(
|
|
330
|
+
wiring: CorrectionAccessWiring,
|
|
331
|
+
memoryId: string,
|
|
332
|
+
namespaces: readonly string[],
|
|
333
|
+
): Promise<{ candidate: PlannerCandidate; status: string } | null> {
|
|
334
|
+
for (const ns of namespaces) {
|
|
335
|
+
const storage = await wiring.orchestrator.getStorage(ns);
|
|
336
|
+
const memory = await storage.getMemoryByIdIncludingArchived(memoryId);
|
|
337
|
+
if (!memory || memory.frontmatter.id !== memoryId) continue;
|
|
338
|
+
const candidate = toCandidate(memory, ns, 1);
|
|
339
|
+
if (isSupportPassportPrivateMemory(memory)) return { candidate, status: "ineligible" };
|
|
340
|
+
if (typeof memory.frontmatter.archivedAt === "string" && memory.frontmatter.archivedAt.length > 0) {
|
|
341
|
+
return { candidate, status: "archived" };
|
|
342
|
+
}
|
|
343
|
+
return { candidate, status: memory.frontmatter.status ?? "active" };
|
|
344
|
+
}
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
|
|
313
348
|
async function renderCorrectionDiff(
|
|
314
349
|
_wiring: CorrectionAccessWiring,
|
|
315
350
|
candidates: PlannerCandidate[],
|
|
@@ -339,7 +374,10 @@ async function renderCorrectionDiff(
|
|
|
339
374
|
function describeAfterState(action: CorrectionAction): string {
|
|
340
375
|
switch (action.kind) {
|
|
341
376
|
case "supersede":
|
|
342
|
-
return action.replacement?.content
|
|
377
|
+
return action.replacement?.content
|
|
378
|
+
?? (action.winnerId
|
|
379
|
+
? `(superseded by ${action.winnerId}; recoverable)`
|
|
380
|
+
: "(superseded without replacement)");
|
|
343
381
|
case "edit":
|
|
344
382
|
return action.patch;
|
|
345
383
|
case "retract":
|
|
@@ -899,6 +937,7 @@ function toExecutorMemory(m: MemoryFile): ExecutorMemory {
|
|
|
899
937
|
...(typeof fm.contentHash === "string" && fm.contentHash.length > 0
|
|
900
938
|
? { contentHash: fm.contentHash }
|
|
901
939
|
: {}),
|
|
940
|
+
status: fm.status ?? "active",
|
|
902
941
|
} satisfies ExecutorMemory;
|
|
903
942
|
}
|
|
904
943
|
|
|
@@ -987,6 +1026,7 @@ Given a correction statement and candidate memories, respond with a JSON object:
|
|
|
987
1026
|
|
|
988
1027
|
Action shapes:
|
|
989
1028
|
- {"kind":"supersede","loserId":"<id>","replacement":{"content":"<new fact>"}}
|
|
1029
|
+
- {"kind":"supersede","loserId":"<id>","winnerId":"<existing id>"}
|
|
990
1030
|
- {"kind":"edit","memoryId":"<id>","patch":"<new full content>"}
|
|
991
1031
|
- {"kind":"retract","memoryId":"<id>"}
|
|
992
1032
|
- {"kind":"rescope","memoryId":"<id>","toNamespace":"<ns>"}
|