@remnic/core 9.69.33 → 9.69.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-admin-ops-surface.d.ts +14 -11
- package/dist/access-admin-ops-surface.js +65 -60
- package/dist/access-audit.js +2 -2
- package/dist/access-authorization-probe.d.ts +14 -11
- package/dist/access-authorization-probe.js +66 -61
- package/dist/access-boundary.d.ts +14 -11
- package/dist/access-boundary.js +65 -60
- package/dist/access-cli.js +137 -133
- package/dist/access-cli.js.map +1 -1
- package/dist/access-coding-context-resolution.d.ts +3 -1
- package/dist/access-coding-context-resolution.js +3 -3
- package/dist/access-extraction-force-flush.d.ts +14 -11
- package/dist/access-extraction-force-flush.js +65 -60
- package/dist/access-health-types.d.ts +3 -1
- package/dist/access-http-briefing.d.ts +14 -11
- package/dist/access-http-briefing.js +66 -61
- package/dist/access-http-lcm-compaction.d.ts +14 -11
- package/dist/access-http-lifecycle-flush.d.ts +14 -11
- package/dist/access-http-offline-stream.d.ts +14 -11
- package/dist/access-http-query.d.ts +4 -2
- package/dist/access-http-query.js +67 -62
- package/dist/access-http.d.ts +15 -12
- package/dist/access-http.js +86 -82
- package/dist/access-identity-continuity-surface.d.ts +12 -9
- package/dist/access-identity-continuity-surface.js +65 -60
- package/dist/access-lcm-surface.d.ts +14 -11
- package/dist/access-lcm-surface.js +65 -60
- package/dist/access-mcp.d.ts +14 -11
- package/dist/access-mcp.js +74 -70
- package/dist/access-memory-search-fanout.d.ts +4 -2
- package/dist/{access-namespace-preflight-DMR-jOMS.d.ts → access-namespace-preflight-D8qri11P.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +5 -3
- package/dist/access-namespace-preflight.js +65 -60
- package/dist/access-observe-transcript.d.ts +12 -9
- package/dist/access-observe-transcript.js +3 -3
- package/dist/access-observe-write-surface.d.ts +16 -13
- package/dist/access-observe-write-surface.js +65 -60
- package/dist/access-offline-manifest.d.ts +48 -11
- package/dist/access-offline-manifest.js +18 -16
- package/dist/access-operations-batch.js +68 -64
- package/dist/access-operations.d.ts +15 -12
- package/dist/access-operations.js +73 -69
- package/dist/access-recall-concurrency.d.ts +14 -11
- package/dist/access-recall-concurrency.js +65 -60
- package/dist/access-recall-response.d.ts +14 -11
- package/dist/access-recall-response.js +65 -60
- package/dist/access-recall-surface.d.ts +14 -11
- package/dist/access-recall-surface.js +65 -60
- package/dist/access-schema.d.ts +56 -13
- package/dist/access-schema.js +15 -1
- package/dist/{access-service-CJQoQvRa.d.ts → access-service-CKu5ixg9.d.ts} +52 -50
- package/dist/access-service-helpers.d.ts +14 -11
- package/dist/access-service.d.ts +14 -11
- package/dist/access-service.js +65 -60
- package/dist/access-surface-catalog.d.ts +14 -11
- package/dist/access-surface-catalog.js +67 -62
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/access-wearables-meetings-surface.d.ts +5 -3
- package/dist/action-confidence.d.ts +3 -1
- package/dist/active-memory-bridge.d.ts +3 -1
- package/dist/active-memory-bridge.js +2 -2
- package/dist/active-recall.d.ts +3 -1
- package/dist/active-recall.js +12 -10
- package/dist/active-recall.js.map +1 -1
- package/dist/activity/digest.d.ts +3 -1
- package/dist/adapters/index.d.ts +46 -1
- package/dist/adapters/index.js +10 -6
- package/dist/adapters/registry.js +2 -2
- package/dist/ambient-provenance.d.ts +3 -1
- package/dist/artifact-search.d.ts +3 -1
- package/dist/{auto-sync-NSHLUAQI.js → auto-sync-4YFATLFQ.js} +10 -9
- package/dist/{auto-sync-NSHLUAQI.js.map → auto-sync-4YFATLFQ.js.map} +1 -1
- package/dist/behavior-learner.d.ts +3 -1
- package/dist/behavior-signals.d.ts +3 -1
- package/dist/bootstrap.d.ts +12 -9
- package/dist/briefing-window.d.ts +4 -2
- package/dist/briefing.d.ts +4 -2
- package/dist/briefing.js +26 -25
- package/dist/buffer-surprise-report.d.ts +3 -1
- package/dist/buffer-turn-helpers.d.ts +3 -1
- package/dist/buffer.d.ts +4 -2
- package/dist/buffer.js +11 -10
- package/dist/bulk-import/index.d.ts +5 -3
- package/dist/calibration.d.ts +3 -1
- package/dist/calibration.js +3 -2
- package/dist/calibration.js.map +1 -1
- package/dist/capabilities.d.ts +3 -1
- package/dist/{capsule-merge-IPG4IOFP.js → capsule-merge-ZCXUPLNJ.js} +2 -2
- package/dist/{catalog-8O9KY9eA.d.ts → catalog-Bq1AxZwF.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +3 -1
- package/dist/causal-consolidation.d.ts +3 -1
- package/dist/causal-consolidation.js +27 -26
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-trajectory-graph.d.ts +3 -1
- package/dist/{chunk-CDKHKZL5.js → chunk-2524MOWK.js} +2 -2
- package/dist/{chunk-HVAEXYPL.js → chunk-255PC37A.js} +47 -25
- package/dist/chunk-255PC37A.js.map +1 -0
- package/dist/{chunk-2C3S7J2S.js → chunk-2BQ4ZIWC.js} +741 -28
- package/dist/chunk-2BQ4ZIWC.js.map +1 -0
- package/dist/{chunk-RKBLRTNT.js → chunk-2YLMUME2.js} +2 -2
- package/dist/{chunk-QOIOACIE.js → chunk-326KUXIR.js} +15 -648
- package/dist/chunk-326KUXIR.js.map +1 -0
- package/dist/{chunk-DBQWVT2H.js → chunk-3CBI2ZSA.js} +2 -2
- package/dist/{chunk-MWFGUESQ.js → chunk-3FJKJ5UZ.js} +2 -2
- package/dist/{chunk-NZXEK3UF.js → chunk-3Q3N35W7.js} +2 -2
- package/dist/{chunk-YYGZJPOK.js → chunk-42DJ235G.js} +2 -2
- package/dist/{chunk-SO7SV523.js → chunk-4MDKNUV4.js} +1 -1
- package/dist/chunk-4MDKNUV4.js.map +1 -0
- package/dist/chunk-5HYUUFMQ.js +1280 -0
- package/dist/chunk-5HYUUFMQ.js.map +1 -0
- package/dist/{chunk-2JVJ7UHC.js → chunk-5JG5EBVL.js} +4 -2
- package/dist/chunk-5JG5EBVL.js.map +1 -0
- package/dist/{chunk-HV7OY4DM.js → chunk-5VAF4ID4.js} +643 -202
- package/dist/chunk-5VAF4ID4.js.map +1 -0
- package/dist/{chunk-N7RWREIQ.js → chunk-65RENJGB.js} +6 -1
- package/dist/chunk-65RENJGB.js.map +1 -0
- package/dist/{chunk-JTH2SE6B.js → chunk-6J6K3STG.js} +8 -8
- package/dist/{chunk-H4VH5VIB.js → chunk-776GVKL7.js} +2 -2
- package/dist/{chunk-BUTCAMJM.js → chunk-A2YQL2FF.js} +5 -5
- package/dist/chunk-A5UQ52YQ.js +211 -0
- package/dist/chunk-A5UQ52YQ.js.map +1 -0
- package/dist/{chunk-X2NFFBTO.js → chunk-A7GQBJP5.js} +4 -4
- package/dist/{chunk-CGC5UQCF.js → chunk-AKE4GGQ3.js} +2 -2
- package/dist/{chunk-B325AGLK.js → chunk-AZSKROVQ.js} +2 -2
- package/dist/{chunk-I5DZ3WGR.js → chunk-BJETIR53.js} +3 -3
- package/dist/{chunk-JT3EB7ZL.js → chunk-BNGHPYZU.js} +5 -5
- package/dist/chunk-BRZWWUCJ.js +13 -0
- package/dist/{chunk-FYDW33ZB.js.map → chunk-BRZWWUCJ.js.map} +1 -1
- package/dist/{chunk-3JVLGJCY.js → chunk-C6KRO3SU.js} +2 -2
- package/dist/{chunk-5NANRSCD.js → chunk-CNV2A557.js} +5 -5
- package/dist/{chunk-PBGVVDLY.js → chunk-DK4X5B6I.js} +2 -2
- package/dist/{chunk-MFDTVQJX.js → chunk-DVOBLPSQ.js} +22 -7
- package/dist/chunk-DVOBLPSQ.js.map +1 -0
- package/dist/{chunk-N2ZNPHA3.js → chunk-ECKG5WSI.js} +2 -2
- package/dist/{chunk-PYLL63BF.js → chunk-EEBQFG5E.js} +9 -9
- package/dist/{chunk-ET356KSB.js → chunk-F4TWWUMP.js} +2 -2
- package/dist/{chunk-RHQMKJFG.js → chunk-F6IVBYFS.js} +55 -51
- package/dist/{chunk-RHQMKJFG.js.map → chunk-F6IVBYFS.js.map} +1 -1
- package/dist/{chunk-CLLPJ6QT.js → chunk-FQXJAC3T.js} +2 -2
- package/dist/{chunk-JGHXXQ2G.js → chunk-FVJ4D6L7.js} +2 -2
- package/dist/{chunk-DD5JFCWM.js → chunk-GCBIXUPT.js} +2 -2
- package/dist/{chunk-MN3LK3KN.js → chunk-GLZH5VEN.js} +2 -2
- package/dist/{chunk-S7T2TY65.js → chunk-HC4GFLMQ.js} +3 -3
- package/dist/{chunk-EQHDH4C2.js → chunk-HUT2JR6I.js} +3 -3
- package/dist/{chunk-UUQG7HAD.js → chunk-HXSAWV3A.js} +4 -4
- package/dist/{chunk-XXIHX75O.js → chunk-J7PB5UQ4.js} +3 -3
- package/dist/{chunk-UGPUYIET.js → chunk-JHZCXUQI.js} +221 -400
- package/dist/chunk-JHZCXUQI.js.map +1 -0
- package/dist/{chunk-LTIZHLV7.js → chunk-JR6H5CYS.js} +2 -2
- package/dist/{chunk-FCSZ4K2X.js → chunk-JR6PP7UM.js} +3 -3
- package/dist/{chunk-TCUKRAMK.js → chunk-JRWW7GM6.js} +10 -10
- package/dist/{chunk-Q726HSJO.js → chunk-JSRVXI6E.js} +16 -15
- package/dist/chunk-JSRVXI6E.js.map +1 -0
- package/dist/{chunk-DB5TGMLZ.js → chunk-JZ2CHRLB.js} +6 -4
- package/dist/{chunk-DB5TGMLZ.js.map → chunk-JZ2CHRLB.js.map} +1 -1
- package/dist/{chunk-JEIXTYVG.js → chunk-L2QLDZJC.js} +46 -17
- package/dist/chunk-L2QLDZJC.js.map +1 -0
- package/dist/{chunk-PL7FYKHT.js → chunk-L2WQVSKP.js} +2 -2
- package/dist/{chunk-JSN44KIB.js → chunk-LEMD7WZJ.js} +9 -9
- package/dist/{chunk-VZWXFXLX.js → chunk-LMCD5W5B.js} +2 -2
- package/dist/{chunk-7BMXZCOT.js → chunk-LNDLXMH6.js} +3 -3
- package/dist/{chunk-3QQTXYZ6.js → chunk-LSLCFCCQ.js} +2 -1
- package/dist/chunk-LSLCFCCQ.js.map +1 -0
- package/dist/{chunk-EONF76DT.js → chunk-LYDJRF45.js} +2 -2
- package/dist/{chunk-MKD3OMPS.js → chunk-M3MYMWXG.js} +2 -2
- package/dist/{chunk-VGXM5B4H.js → chunk-MNIPH6LD.js} +2 -2
- package/dist/{chunk-A7XEPMQ6.js → chunk-MVAQ2WM3.js} +6 -6
- package/dist/chunk-MVAQ2WM3.js.map +1 -0
- package/dist/{chunk-6N3TQFZU.js → chunk-NN4JEFON.js} +3 -3
- package/dist/chunk-NPNSKE76.js +220 -0
- package/dist/chunk-NPNSKE76.js.map +1 -0
- package/dist/{chunk-MOZXTRC2.js → chunk-OQ7SSRXP.js} +19 -19
- package/dist/{chunk-XU6OEECT.js → chunk-OQQXGYMX.js} +3 -3
- package/dist/{chunk-4MHYKEOM.js → chunk-OS2AT2JU.js} +10 -10
- package/dist/{chunk-N57A4KPV.js → chunk-P3ONDDIJ.js} +2 -2
- package/dist/chunk-PCEYGOSL.js +66 -0
- package/dist/chunk-PCEYGOSL.js.map +1 -0
- package/dist/{chunk-R3HKWWUB.js → chunk-PHP3MUGF.js} +2 -2
- package/dist/{chunk-EEOUMG3J.js → chunk-PWPIERBM.js} +38 -6
- package/dist/chunk-PWPIERBM.js.map +1 -0
- package/dist/chunk-Q4AUIFUA.js +111 -0
- package/dist/chunk-Q4AUIFUA.js.map +1 -0
- package/dist/{chunk-P3SB5BNT.js → chunk-QATYVTP7.js} +2 -2
- package/dist/{chunk-LSYDG6MJ.js → chunk-QBLDCI6E.js} +2 -2
- package/dist/{chunk-KCB7F4J7.js → chunk-QURNMKME.js} +2 -2
- package/dist/{chunk-XOVKXJEP.js → chunk-R3TLVTWW.js} +3 -3
- package/dist/{chunk-XXE5P6HJ.js → chunk-RRZKTSFG.js} +2 -2
- package/dist/{chunk-44T3Y7SZ.js → chunk-RUXPVSML.js} +5 -5
- package/dist/{chunk-DCJ3YFIC.js → chunk-S2ULTQZR.js} +2 -2
- package/dist/{chunk-H272ZPQ3.js → chunk-SHEHQBCG.js} +124 -23
- package/dist/chunk-SHEHQBCG.js.map +1 -0
- package/dist/{chunk-EEC4PCG5.js → chunk-SZDLX763.js} +2 -2
- package/dist/{chunk-E2ZHGBAK.js → chunk-T2JSUEH6.js} +2 -2
- package/dist/{chunk-227UFSEQ.js → chunk-TFA6HPOA.js} +2 -2
- package/dist/{chunk-BA6WOZOT.js → chunk-TK4FHQRN.js} +4 -4
- package/dist/{chunk-W27OW7AB.js → chunk-TKFSXDOB.js} +2 -2
- package/dist/chunk-TLHNF6GA.js +647 -0
- package/dist/chunk-TLHNF6GA.js.map +1 -0
- package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
- package/dist/{chunk-FDLDOEO6.js → chunk-UBG4GAEP.js} +51 -6
- package/dist/chunk-UBG4GAEP.js.map +1 -0
- package/dist/{chunk-CETXNLEX.js → chunk-UDZYNIDJ.js} +2 -2
- package/dist/{chunk-H5AFCNGA.js → chunk-UJX4I26O.js} +2 -2
- package/dist/{chunk-E6TDQRF6.js → chunk-UYUCCQ46.js} +2 -2
- package/dist/{chunk-BLUYQFRH.js → chunk-VELCIWJZ.js} +15 -11
- package/dist/chunk-VELCIWJZ.js.map +1 -0
- package/dist/{chunk-OQDPBRQ6.js → chunk-VYXDUPYE.js} +2 -2
- package/dist/{chunk-ZG74PWRW.js → chunk-VZAKYDMJ.js} +2 -2
- package/dist/chunk-W6IJMWTZ.js +72 -0
- package/dist/chunk-W6IJMWTZ.js.map +1 -0
- package/dist/{chunk-NB5BCFUY.js → chunk-WHHEPAO3.js} +4 -4
- package/dist/{chunk-H3TKENU4.js → chunk-WIKO4SCR.js} +5 -5
- package/dist/{chunk-TX2UTLXC.js → chunk-WPDKBUWX.js} +2 -2
- package/dist/{chunk-YFLLGRXO.js → chunk-X2QPKLPL.js} +2 -2
- package/dist/{chunk-PFFZWDPE.js → chunk-XCOV45MO.js} +3 -3
- package/dist/{chunk-5BCNEBEN.js → chunk-XPJNT6PI.js} +4 -4
- package/dist/chunk-XW2T4QAW.js +1 -0
- package/dist/{chunk-J7HFPA6O.js → chunk-Y63ZFP4X.js} +2 -2
- package/dist/{chunk-D223ZDQV.js → chunk-YEDVOYL2.js} +2 -2
- package/dist/{chunk-TLPZ6MKZ.js → chunk-YEN4TREG.js} +541 -5
- package/dist/chunk-YEN4TREG.js.map +1 -0
- package/dist/{chunk-22FVR2KE.js → chunk-YJ6VCDMZ.js} +6 -2
- package/dist/chunk-YJ6VCDMZ.js.map +1 -0
- package/dist/{chunk-RC5DXXWC.js → chunk-YM7YN37H.js} +2 -2
- package/dist/{chunk-BPJNF7J2.js → chunk-YNN26CIZ.js} +2 -2
- package/dist/{chunk-VLXBE57O.js → chunk-YVGXH72Y.js} +2 -2
- package/dist/{chunk-YQAXP5AC.js → chunk-YXLUTALO.js} +5 -5
- package/dist/{chunk-DGGB65KC.js → chunk-Z7ACR6MJ.js} +3 -3
- package/dist/{chunk-X35W4S3L.js → chunk-ZBEGS7OB.js} +4 -4
- package/dist/{chunk-O75CRYGF.js → chunk-ZEFVK7XC.js} +1 -1
- package/dist/chunk-ZEFVK7XC.js.map +1 -0
- package/dist/{chunk-XUE46UYW.js → chunk-ZLN7AROH.js} +6 -6
- package/dist/{chunk-E6JA6XWY.js → chunk-ZTG4P7NZ.js} +1013 -1317
- package/dist/chunk-ZTG4P7NZ.js.map +1 -0
- package/dist/{chunk-HK32G473.js → chunk-ZWEZXVYH.js} +2 -2
- package/dist/{cli-D57e2Mqt.d.ts → cli-Bk7Ctql4.d.ts} +5 -5
- package/dist/cli-fallback.d.ts +11 -4
- package/dist/cli-fallback.js +5 -1
- package/dist/cli.d.ts +16 -13
- package/dist/cli.js +107 -103
- package/dist/coding/export-okf-codegraph.d.ts +3 -1
- package/dist/coding/export-okf-codegraph.js +32 -30
- package/dist/coding/export-okf-codegraph.js.map +1 -1
- package/dist/coding/pre-action-gate.d.ts +3 -1
- package/dist/compat/checks.js +2 -2
- package/dist/compat/codex-cli-fallback.d.ts +1 -1
- package/dist/compat/codex-cli-fallback.js +5 -1
- package/dist/compat/codex-cli-fallback.js.map +1 -1
- package/dist/compounding/engine.d.ts +4 -2
- package/dist/compounding/engine.js +27 -26
- package/dist/compounding/preference-consolidator.d.ts +3 -1
- package/dist/compression-optimizer.d.ts +3 -1
- package/dist/config.d.ts +3 -1
- package/dist/config.js +12 -10
- package/dist/connectors/codex-materialize-runner.d.ts +3 -1
- package/dist/connectors/codex-materialize-runner.js +26 -25
- package/dist/connectors/codex-materialize.d.ts +3 -1
- package/dist/connectors/index.d.ts +3 -1
- package/dist/connectors/index.js +28 -27
- package/dist/consolidation-provenance-check.d.ts +4 -2
- package/dist/consolidation-undo.d.ts +4 -2
- package/dist/contradiction/index.d.ts +5 -3
- package/dist/contradiction/index.js +5 -5
- package/dist/{contradiction-scan-NOYMFG66.js → contradiction-scan-GVD4JJ7B.js} +3 -3
- package/dist/converge-config.d.ts +3 -1
- package/dist/convergence-refresh.d.ts +4 -2
- package/dist/convergence-refresh.js +28 -27
- package/dist/conversation-index/backend.d.ts +3 -1
- package/dist/conversation-index/backend.js +3 -3
- package/dist/conversation-index/chunker.d.ts +3 -1
- package/dist/conversation-index/faiss-adapter.d.ts +3 -1
- package/dist/conversation-index/faiss-adapter.js +2 -2
- package/dist/conversation-index/indexer.d.ts +3 -1
- package/dist/conversation-index/search.d.ts +3 -1
- package/dist/corpus-watermark.d.ts +3 -1
- package/dist/corpus-watermark.js +29 -28
- package/dist/cross-lingual-recall.d.ts +3 -1
- package/dist/day-summary.d.ts +3 -1
- package/dist/deep-recall-http-glue.d.ts +14 -11
- package/dist/deep-recall-http-glue.js +12 -2
- package/dist/deep-recall-mcp-tools.d.ts +14 -11
- package/dist/deep-recall-policy-llm.d.ts +3 -1
- package/dist/deep-recall-policy-llm.js +4 -3
- package/dist/deep-recall-seeds.d.ts +3 -1
- package/dist/delinearize.d.ts +3 -1
- package/dist/dependency-propagation-config.d.ts +3 -1
- package/dist/{dependency-propagation-delivery-CmniEsUK.d.ts → dependency-propagation-delivery-DLiAtj25.d.ts} +1 -1
- package/dist/direct-answer-wiring.d.ts +3 -1
- package/dist/direct-answer.d.ts +3 -1
- package/dist/embedding-fallback.d.ts +3 -1
- package/dist/enrichment/index.d.ts +3 -1
- package/dist/entity-origin-fields.d.ts +3 -1
- package/dist/entity-retrieval.d.ts +4 -2
- package/dist/entity-retrieval.js +26 -25
- package/dist/entity-schema.d.ts +3 -1
- package/dist/episodic-context.d.ts +3 -1
- package/dist/eval-trajectory-contracts.d.ts +3 -1
- package/dist/eval-trajectory-store.d.ts +3 -1
- package/dist/eval-trajectory.d.ts +3 -1
- package/dist/explicit-capture.d.ts +12 -9
- package/dist/explicit-capture.js +6 -6
- package/dist/external-wiki-access.d.ts +14 -11
- package/dist/external-wiki-access.js +66 -61
- package/dist/external-wiki-collection-registration.d.ts +3 -1
- package/dist/external-wiki-collection.d.ts +3 -1
- package/dist/external-wiki-mcp-tools.d.ts +14 -11
- package/dist/extraction-error-classification.d.ts +3 -1
- package/dist/extraction-faithfulness.d.ts +3 -1
- package/dist/extraction-faithfulness.js +4 -3
- package/dist/extraction-judge-telemetry.d.ts +3 -1
- package/dist/extraction-judge-training.d.ts +3 -1
- package/dist/extraction-judge.d.ts +3 -1
- package/dist/extraction-judge.js +5 -4
- package/dist/extraction-liveness.d.ts +3 -1
- package/dist/extraction-normalization.d.ts +3 -1
- package/dist/extraction-prompt.d.ts +3 -1
- package/dist/extraction-source-grounding-rules.d.ts +3 -1
- package/dist/extraction-source-grounding.d.ts +3 -1
- package/dist/extraction.d.ts +3 -1
- package/dist/extraction.js +38 -36
- package/dist/fallback-llm.d.ts +3 -1
- package/dist/fallback-llm.js +3 -2
- package/dist/{first-start-migration-RC345GPL.js → first-start-migration-L3UFX5CU.js} +3 -3
- package/dist/generic-recall-paths-DbitKJI5.d.ts +23 -0
- package/dist/graph-append-error.d.ts +3 -1
- package/dist/graph-dashboard-diff.d.ts +3 -1
- package/dist/graph-dashboard-key.d.ts +3 -1
- package/dist/graph-dashboard-parser.d.ts +3 -1
- package/dist/graph-edge-reinforcement.d.ts +3 -1
- package/dist/graph-jsonl.d.ts +3 -1
- package/dist/graph-path-reconstruction.d.ts +3 -1
- package/dist/graph-path-scoring.d.ts +3 -1
- package/dist/graph-snapshot.d.ts +3 -1
- package/dist/graph.d.ts +3 -1
- package/dist/harmonic-retrieval.js +2 -2
- package/dist/importance.d.ts +3 -1
- package/dist/importers/index.d.ts +3 -1
- package/dist/importers/test-utils.d.ts +3 -1
- package/dist/in-flight-reads.d.ts +3 -1
- package/dist/{index-BTAsSkPG.d.ts → index-BINUgPFo.d.ts} +2 -2
- package/dist/index.d.ts +303 -245
- package/dist/index.js +316 -214
- package/dist/intent.d.ts +3 -1
- package/dist/lcm/engine.d.ts +3 -1
- package/dist/lcm/engine.js +2 -2
- package/dist/lcm/index.d.ts +3 -1
- package/dist/lcm/index.js +7 -7
- package/dist/lcm/tools.d.ts +3 -1
- package/dist/lifecycle.d.ts +3 -1
- package/dist/live-connectors-runner.d.ts +3 -1
- package/dist/local-llm-config.d.ts +26 -0
- package/dist/local-llm-config.js +1 -0
- package/dist/local-llm.d.ts +5 -1
- package/dist/local-llm.js +3 -3
- package/dist/local-model-endpoint.d.ts +3 -1
- package/dist/location/index.d.ts +5 -3
- package/dist/location/index.js +29 -28
- package/dist/maintenance/memory-governance.d.ts +3 -1
- package/dist/maintenance/memory-governance.js +26 -25
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +4 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +26 -25
- package/dist/maintenance/rebuild-memory-projection.d.ts +4 -2
- package/dist/maintenance/rebuild-memory-projection.js +27 -26
- package/dist/{maintenance-DCvQGTzL.d.ts → maintenance-ag1gYztC.d.ts} +378 -4
- package/dist/mcp-memory-inspector-app.d.ts +14 -11
- package/dist/memory-action-policy.d.ts +3 -1
- package/dist/memory-cache.d.ts +3 -1
- package/dist/memory-controller.d.ts +3 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +3 -1
- package/dist/memory-projection-store.d.ts +3 -1
- package/dist/memory-provenance.d.ts +3 -1
- package/dist/memory-snapshot.d.ts +3 -1
- package/dist/memory-subject-cli.d.ts +14 -11
- package/dist/memory-subject.d.ts +14 -11
- package/dist/memory-worth-outcomes.d.ts +4 -2
- package/dist/migrate/from-engram.js +2 -2
- package/dist/models-json.d.ts +3 -1
- package/dist/namespaces/migrate.d.ts +5 -3
- package/dist/namespaces/migrate.js +27 -26
- package/dist/namespaces/principal.d.ts +3 -1
- package/dist/namespaces/search.d.ts +3 -1
- package/dist/namespaces/search.js +8 -8
- package/dist/namespaces/storage.d.ts +5 -3
- package/dist/namespaces/storage.js +26 -25
- package/dist/native-knowledge.d.ts +3 -1
- package/dist/network/tailscale.js +2 -2
- package/dist/offline-sync-impression-drain.d.ts +3 -1
- package/dist/offline-sync-impression-drain.js +6 -6
- package/dist/operator-doctor-corpus.d.ts +3 -1
- package/dist/operator-doctor-corpus.js +30 -29
- package/dist/operator-doctor-replica.d.ts +3 -1
- package/dist/operator-toolkit.d.ts +5 -3
- package/dist/operator-toolkit.js +44 -42
- package/dist/orchestration/compression-guideline-coordinator.d.ts +4 -2
- package/dist/orchestration/maintenance.d.ts +6 -4
- package/dist/orchestration/maintenance.js +44 -39
- package/dist/{orchestrator-CvCsp1tz.d.ts → orchestrator-Cf3G-3Ed.d.ts} +17 -29
- package/dist/orchestrator.d.ts +12 -9
- package/dist/orchestrator.js +141 -135
- package/dist/patterns-cli.d.ts +3 -1
- package/dist/{pipeline-JAdwKBS7.d.ts → pipeline-AwB03fw_.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +3 -1
- package/dist/proactive-contention.d.ts +3 -1
- package/dist/provenance.d.ts +3 -1
- package/dist/{public-http-h-yWu9rj.d.ts → public-http-BetSQn7q.d.ts} +1 -1
- package/dist/{qmd-Cvw9RWKr.d.ts → qmd-Bfaydrfm.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +4 -2
- package/dist/qmd-recall-cache.d.ts +3 -1
- package/dist/qmd.d.ts +4 -2
- package/dist/qmd.js +2 -2
- package/dist/recall-concurrency-config.d.ts +3 -1
- package/dist/recall-disclosure-escalation.d.ts +3 -1
- package/dist/recall-explain-renderer.d.ts +3 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-memory-map.d.ts +3 -1
- package/dist/recall-navigate-access.d.ts +3 -1
- package/dist/recall-navigate-access.js +2 -2
- package/dist/recall-navigate-disclosure.d.ts +3 -1
- package/dist/recall-navigate-disclosure.js +1 -1
- package/dist/recall-navigate.d.ts +3 -1
- package/dist/recall-navigate.js +2 -2
- package/dist/recall-planner-llm.d.ts +3 -1
- package/dist/recall-planner-llm.js +3 -2
- package/dist/recall-planner-llm.js.map +1 -1
- package/dist/recall-state-view-admission.d.ts +57 -0
- package/dist/recall-state-view-admission.js +39 -0
- package/dist/recall-state-view-admission.js.map +1 -0
- package/dist/recall-state-view-inject.js +2 -2
- package/dist/recall-state-view-render.js +2 -2
- package/dist/recall-state-view-widen.d.ts +18 -1
- package/dist/recall-state-view-widen.js +2 -2
- package/dist/recall-state-view-wire.d.ts +1 -1
- package/dist/recall-state-view-wire.js +3 -3
- package/dist/recall-state-view.d.ts +1 -0
- package/dist/recall-state-view.js +1 -1
- package/dist/recall-state.d.ts +3 -1
- package/dist/recall-tag-filter.d.ts +3 -1
- package/dist/recall-timings.d.ts +3 -1
- package/dist/recall-xray-cli.d.ts +3 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +3 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +10 -1
- package/dist/recall-xray.js +2 -2
- package/dist/reconcile/cursor.d.ts +12 -2
- package/dist/reconcile/cursor.js +6 -4
- package/dist/reconcile/cursor.js.map +1 -1
- package/dist/reconcile/manifest.d.ts +38 -2
- package/dist/reconcile/manifest.js +15 -5
- package/dist/reconcile/plan.d.ts +3 -1
- package/dist/replay/normalizers/chatgpt.d.ts +3 -1
- package/dist/replay/normalizers/claude.d.ts +3 -1
- package/dist/replay/normalizers/openclaw.d.ts +3 -1
- package/dist/replay/normalizers/shared.d.ts +3 -1
- package/dist/replay/runner.d.ts +3 -1
- package/dist/replay/types.d.ts +3 -1
- package/dist/replica-divergence.d.ts +3 -1
- package/dist/replica-peers-config.d.ts +3 -1
- package/dist/{resolution-VKATP2HT.js → resolution-OHJZG45O.js} +6 -6
- package/dist/resolution-OHJZG45O.js.map +1 -0
- package/dist/resolve-auth-token.d.ts +3 -1
- package/dist/resume-bundles.js +13 -11
- package/dist/retrieval-agents.d.ts +4 -2
- package/dist/retrieval-tiers.d.ts +3 -1
- package/dist/routing/engine.d.ts +3 -1
- package/dist/routing/store.d.ts +3 -1
- package/dist/runtime/child-process.d.ts +1 -1
- package/dist/runtime/child-process.js +1 -1
- package/dist/salvage-envelope.d.ts +3 -1
- package/dist/salvage-envelope.js +2 -2
- package/dist/{scope-profiles-BShpTPeV.d.ts → scope-profiles-nxTKvjE-.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +3 -1
- package/dist/search/factory.d.ts +3 -1
- package/dist/search/factory.js +7 -7
- package/dist/search/index.d.ts +3 -1
- package/dist/search/index.js +11 -11
- package/dist/search/lancedb-backend.d.ts +3 -1
- package/dist/search/meilisearch-backend.d.ts +3 -1
- package/dist/search/noop-backend.d.ts +3 -1
- package/dist/search/orama-backend.d.ts +3 -1
- package/dist/search/port.d.ts +3 -1
- package/dist/search/remote-backend.d.ts +3 -1
- package/dist/{semantic-consolidation-CusOpe9F.d.ts → semantic-consolidation-C83DVakV.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +4 -2
- package/dist/semantic-consolidation.js +27 -26
- package/dist/semantic-rule-promotion.js +26 -25
- package/dist/semantic-rule-verifier.d.ts +3 -1
- package/dist/semantic-rule-verifier.js +26 -25
- package/dist/{service-BbuVh1eS.d.ts → service-q-xtOoAr.d.ts} +2 -2
- package/dist/session-observer-bands.d.ts +3 -1
- package/dist/session-observer-state.d.ts +3 -1
- package/dist/shared-context/manager.d.ts +3 -1
- package/dist/signal.d.ts +3 -1
- package/dist/source-agent-qualifier.d.ts +3 -1
- package/dist/source-agent-qualifier.js +35 -33
- package/dist/standup/build.js +26 -25
- package/dist/{storage-BBLLuVTF.d.ts → storage-Ca0MbTfm.d.ts} +67 -6
- package/dist/storage.d.ts +5 -3
- package/dist/storage.js +25 -24
- package/dist/subject-config.d.ts +3 -1
- package/dist/subject-config.js +2 -2
- package/dist/summarizer.d.ts +3 -1
- package/dist/summarizer.js +6 -6
- package/dist/summary-snapshot.d.ts +3 -1
- package/dist/support-passport/index.d.ts +50 -15
- package/dist/support-passport/index.js +73 -64
- package/dist/temporal-supersession.d.ts +4 -2
- package/dist/temporal-timeline-recall.d.ts +3 -1
- package/dist/temporal-validity.d.ts +3 -1
- package/dist/threading.d.ts +3 -1
- package/dist/tier-migration.d.ts +4 -2
- package/dist/tier-routing.d.ts +3 -1
- package/dist/tier-routing.js +2 -2
- package/dist/{tier-stats-KA6OZX2C.js → tier-stats-VK5PCO2L.js} +3 -3
- package/dist/topics.d.ts +3 -1
- package/dist/transcript.d.ts +3 -1
- package/dist/transfer/capsule-import.js +1 -1
- package/dist/transfer/export-okf.d.ts +3 -1
- package/dist/transfer/export-okf.js +27 -26
- package/dist/transfer/types.d.ts +24 -24
- package/dist/trust-score-stage.d.ts +3 -1
- package/dist/trust-score.d.ts +3 -1
- package/dist/{types-igV4-sbB.d.ts → types-yDgWDkrJ.d.ts} +60 -34
- package/dist/types.d.ts +3 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +3 -1
- package/dist/verified-recall.js +26 -25
- package/dist/who-knows-cli.d.ts +14 -11
- package/dist/who-knows-cli.js +27 -26
- package/dist/who-knows.d.ts +14 -11
- package/dist/who-knows.js +26 -25
- package/dist/write-envelope.d.ts +5 -2
- package/dist/write-envelope.js +3 -1
- package/package.json +2 -2
- package/src/access-category-alias.test.ts +216 -0
- package/src/access-mcp.test.ts +73 -0
- package/src/access-mcp.ts +6 -6
- package/src/access-observe-write-surface.ts +19 -4
- package/src/access-offline-manifest.ts +297 -16
- package/src/access-recall-surface.ts +5 -5
- package/src/access-schema.ts +76 -7
- package/src/access-service.ts +11 -2
- package/src/activity/config.test.ts +124 -1
- package/src/activity/config.ts +150 -18
- package/src/activity/index.ts +3 -0
- package/src/activity/journal-extract-storage.test.ts +129 -0
- package/src/activity/journal-extract.test.ts +314 -0
- package/src/activity/journal-extract.ts +247 -0
- package/src/activity/journal-heading.test.ts +24 -1
- package/src/activity/journal-heading.ts +36 -0
- package/src/activity/journal-read.test.ts +242 -0
- package/src/activity/journal-read.ts +183 -0
- package/src/activity/journal-source.test.ts +15 -15
- package/src/activity/journal-source.ts +21 -14
- package/src/activity/journal-state.lock-worker.ts +30 -0
- package/src/activity/journal-state.test.ts +144 -0
- package/src/activity/journal-state.ts +107 -0
- package/src/activity/journal-strip.test.ts +106 -52
- package/src/activity/journal-strip.ts +35 -10
- package/src/activity/journal-vault-integration.test.ts +230 -0
- package/src/activity/journal-vault-provenance.test.ts +9 -7
- package/src/activity/journal-vault-provenance.ts +4 -10
- package/src/activity/journal-vault-read.test.ts +3 -2
- package/src/activity/journal-vault-read.ts +9 -139
- package/src/activity/journal.test.ts +74 -23
- package/src/activity/runner.test.ts +116 -1
- package/src/activity/runner.ts +25 -0
- package/src/activity/scheduler.ts +4 -0
- package/src/activity/store.test.ts +18 -0
- package/src/activity/store.ts +14 -0
- package/src/activity/sync-registration.ts +4 -0
- package/src/activity/timeline/analysis-metadata.ts +2 -0
- package/src/activity/timeline/analysis-provider.ts +140 -0
- package/src/activity/timeline/analysis-run.test.ts +419 -0
- package/src/activity/timeline/analysis-run.ts +106 -0
- package/src/activity/timeline/analysis.ts +66 -37
- package/src/activity/timeline/corrections.ts +9 -0
- package/src/activity/timeline/index.ts +3 -0
- package/src/activity/timeline/query.test.ts +71 -0
- package/src/activity/timeline/query.ts +57 -8
- package/src/activity/timeline/regenerate.test.ts +505 -0
- package/src/activity/timeline/regenerate.ts +373 -0
- package/src/activity/types.ts +40 -5
- package/src/adapters/grok-opencode.test.ts +146 -0
- package/src/adapters/grok.ts +53 -0
- package/src/adapters/index.ts +2 -0
- package/src/adapters/opencode.ts +52 -0
- package/src/adapters/registry.ts +4 -0
- package/src/cli-fallback.ts +13 -4
- package/src/config.test.ts +27 -1
- package/src/config.ts +17 -1
- package/src/dedup/merge.test.ts +732 -25
- package/src/fallback-llm.test.ts +53 -0
- package/src/fallback-llm.ts +12 -0
- package/src/index.ts +2 -0
- package/src/local-llm-config.ts +25 -0
- package/src/local-llm.ts +3 -1
- package/src/orchestration/dependency-propagation-recovery-replay.ts +1 -1
- package/src/orchestration/extraction-persist-deps.ts +9 -0
- package/src/orchestration/extraction-persist-promotion.test.ts +265 -6
- package/src/orchestration/extraction-persist-promotion.ts +42 -3
- package/src/orchestration/extraction-persist.ts +3 -3
- package/src/orchestration/harmonic-construction-persist.test.ts +115 -4
- package/src/orchestration/harmonic-construction-persist.ts +34 -6
- package/src/orchestration/maintenance.ts +1 -0
- package/src/orchestration/orchestrator-helpers.ts +6 -0
- package/src/orchestration/recall-entry.ts +16 -0
- package/src/orchestration/recall-internal-deps.ts +14 -0
- package/src/orchestration/recall-internal.ts +41 -58
- package/src/orchestration/recall-result-formatter.ts +11 -1
- package/src/orchestration/recall-search-pipeline.ts +121 -11
- package/src/orchestration/recall-state-view-pipeline.test.ts +211 -0
- package/src/orchestration/semantic-merge-commit-effects.ts +76 -17
- package/src/orchestration/semantic-merge-persist.ts +121 -16
- package/src/orchestration/semantic-merge-promotion-payload.ts +133 -54
- package/src/orchestrator.ts +7 -35
- package/src/providers/codex-subscription.test.ts +666 -0
- package/src/providers/codex-subscription.ts +743 -0
- package/src/recall-disclosure.test.ts +20 -0
- package/src/recall-state-view-admission.ts +114 -0
- package/src/recall-state-view-asof.test.ts +176 -0
- package/src/recall-state-view-call.test.ts +175 -0
- package/src/recall-state-view-config.test.ts +16 -0
- package/src/recall-state-view-widen.test.ts +70 -0
- package/src/recall-state-view-widen.ts +28 -7
- package/src/recall-state-view-wire.ts +3 -1
- package/src/recall-state-view-zero-diff.test.ts +20 -11
- package/src/recall-state-view.test.ts +142 -0
- package/src/recall-state-view.ts +72 -24
- package/src/recall-xray-renderer.test.ts +27 -0
- package/src/recall-xray-renderer.ts +4 -0
- package/src/recall-xray.ts +13 -0
- package/src/reconcile/cursor.ts +23 -33
- package/src/reconcile/manifest.ts +96 -11
- package/src/reconcile-identity-cache.test.ts +378 -0
- package/src/runtime/child-process.ts +1 -1
- package/src/storage/cas-revision-host.ts +75 -0
- package/src/storage/cas-revision-store.test.ts +459 -0
- package/src/storage/cas-revision-store.ts +661 -0
- package/src/storage/deletion-revision-store.ts +80 -6
- package/src/storage/tombstone-blocked-capture-index.ts +15 -0
- package/src/storage/tombstone-blocked-capture-mutation.ts +67 -7
- package/src/storage/tombstone-blocked-capture-sync.ts +55 -20
- package/src/storage-contract/failure-semantics.test.ts +1 -1
- package/src/storage-frontmatter-cas.test.ts +698 -1
- package/src/storage-replay.test.ts +166 -3
- package/src/storage.ts +41 -41
- package/src/support-passport/card-projection.ts +82 -33
- package/src/temporal-supersession.test.ts +10 -10
- package/src/types.ts +10 -29
- package/src/write-envelope.ts +1 -1
- package/dist/chunk-22FVR2KE.js.map +0 -1
- package/dist/chunk-2C3S7J2S.js.map +0 -1
- package/dist/chunk-2JVJ7UHC.js.map +0 -1
- package/dist/chunk-2QSZNTDO.js +0 -56
- package/dist/chunk-2QSZNTDO.js.map +0 -1
- package/dist/chunk-3QQTXYZ6.js.map +0 -1
- package/dist/chunk-5VCDKQWQ.js +0 -560
- package/dist/chunk-5VCDKQWQ.js.map +0 -1
- package/dist/chunk-A7XEPMQ6.js.map +0 -1
- package/dist/chunk-BLUYQFRH.js.map +0 -1
- package/dist/chunk-E6JA6XWY.js.map +0 -1
- package/dist/chunk-EEOUMG3J.js.map +0 -1
- package/dist/chunk-FDLDOEO6.js.map +0 -1
- package/dist/chunk-FYDW33ZB.js +0 -13
- package/dist/chunk-H272ZPQ3.js.map +0 -1
- package/dist/chunk-HV7OY4DM.js.map +0 -1
- package/dist/chunk-HVAEXYPL.js.map +0 -1
- package/dist/chunk-JEIXTYVG.js.map +0 -1
- package/dist/chunk-LRICZIGN.js +0 -52
- package/dist/chunk-LRICZIGN.js.map +0 -1
- package/dist/chunk-MFDTVQJX.js.map +0 -1
- package/dist/chunk-N7RWREIQ.js.map +0 -1
- package/dist/chunk-O75CRYGF.js.map +0 -1
- package/dist/chunk-Q726HSJO.js.map +0 -1
- package/dist/chunk-QOIOACIE.js.map +0 -1
- package/dist/chunk-SEDEKFYQ.js +0 -1
- package/dist/chunk-SO7SV523.js.map +0 -1
- package/dist/chunk-TLPZ6MKZ.js.map +0 -1
- package/dist/chunk-UGPUYIET.js.map +0 -1
- package/src/activity/journal-mode.test.ts +0 -32
- package/src/activity/journal-mode.ts +0 -20
- /package/dist/{capsule-merge-IPG4IOFP.js.map → capsule-merge-ZCXUPLNJ.js.map} +0 -0
- /package/dist/{chunk-CDKHKZL5.js.map → chunk-2524MOWK.js.map} +0 -0
- /package/dist/{chunk-RKBLRTNT.js.map → chunk-2YLMUME2.js.map} +0 -0
- /package/dist/{chunk-DBQWVT2H.js.map → chunk-3CBI2ZSA.js.map} +0 -0
- /package/dist/{chunk-MWFGUESQ.js.map → chunk-3FJKJ5UZ.js.map} +0 -0
- /package/dist/{chunk-NZXEK3UF.js.map → chunk-3Q3N35W7.js.map} +0 -0
- /package/dist/{chunk-YYGZJPOK.js.map → chunk-42DJ235G.js.map} +0 -0
- /package/dist/{chunk-JTH2SE6B.js.map → chunk-6J6K3STG.js.map} +0 -0
- /package/dist/{chunk-H4VH5VIB.js.map → chunk-776GVKL7.js.map} +0 -0
- /package/dist/{chunk-BUTCAMJM.js.map → chunk-A2YQL2FF.js.map} +0 -0
- /package/dist/{chunk-X2NFFBTO.js.map → chunk-A7GQBJP5.js.map} +0 -0
- /package/dist/{chunk-CGC5UQCF.js.map → chunk-AKE4GGQ3.js.map} +0 -0
- /package/dist/{chunk-B325AGLK.js.map → chunk-AZSKROVQ.js.map} +0 -0
- /package/dist/{chunk-I5DZ3WGR.js.map → chunk-BJETIR53.js.map} +0 -0
- /package/dist/{chunk-JT3EB7ZL.js.map → chunk-BNGHPYZU.js.map} +0 -0
- /package/dist/{chunk-3JVLGJCY.js.map → chunk-C6KRO3SU.js.map} +0 -0
- /package/dist/{chunk-5NANRSCD.js.map → chunk-CNV2A557.js.map} +0 -0
- /package/dist/{chunk-PBGVVDLY.js.map → chunk-DK4X5B6I.js.map} +0 -0
- /package/dist/{chunk-N2ZNPHA3.js.map → chunk-ECKG5WSI.js.map} +0 -0
- /package/dist/{chunk-PYLL63BF.js.map → chunk-EEBQFG5E.js.map} +0 -0
- /package/dist/{chunk-ET356KSB.js.map → chunk-F4TWWUMP.js.map} +0 -0
- /package/dist/{chunk-CLLPJ6QT.js.map → chunk-FQXJAC3T.js.map} +0 -0
- /package/dist/{chunk-JGHXXQ2G.js.map → chunk-FVJ4D6L7.js.map} +0 -0
- /package/dist/{chunk-DD5JFCWM.js.map → chunk-GCBIXUPT.js.map} +0 -0
- /package/dist/{chunk-MN3LK3KN.js.map → chunk-GLZH5VEN.js.map} +0 -0
- /package/dist/{chunk-S7T2TY65.js.map → chunk-HC4GFLMQ.js.map} +0 -0
- /package/dist/{chunk-EQHDH4C2.js.map → chunk-HUT2JR6I.js.map} +0 -0
- /package/dist/{chunk-UUQG7HAD.js.map → chunk-HXSAWV3A.js.map} +0 -0
- /package/dist/{chunk-XXIHX75O.js.map → chunk-J7PB5UQ4.js.map} +0 -0
- /package/dist/{chunk-LTIZHLV7.js.map → chunk-JR6H5CYS.js.map} +0 -0
- /package/dist/{chunk-FCSZ4K2X.js.map → chunk-JR6PP7UM.js.map} +0 -0
- /package/dist/{chunk-TCUKRAMK.js.map → chunk-JRWW7GM6.js.map} +0 -0
- /package/dist/{chunk-PL7FYKHT.js.map → chunk-L2WQVSKP.js.map} +0 -0
- /package/dist/{chunk-JSN44KIB.js.map → chunk-LEMD7WZJ.js.map} +0 -0
- /package/dist/{chunk-VZWXFXLX.js.map → chunk-LMCD5W5B.js.map} +0 -0
- /package/dist/{chunk-7BMXZCOT.js.map → chunk-LNDLXMH6.js.map} +0 -0
- /package/dist/{chunk-EONF76DT.js.map → chunk-LYDJRF45.js.map} +0 -0
- /package/dist/{chunk-MKD3OMPS.js.map → chunk-M3MYMWXG.js.map} +0 -0
- /package/dist/{chunk-VGXM5B4H.js.map → chunk-MNIPH6LD.js.map} +0 -0
- /package/dist/{chunk-6N3TQFZU.js.map → chunk-NN4JEFON.js.map} +0 -0
- /package/dist/{chunk-MOZXTRC2.js.map → chunk-OQ7SSRXP.js.map} +0 -0
- /package/dist/{chunk-XU6OEECT.js.map → chunk-OQQXGYMX.js.map} +0 -0
- /package/dist/{chunk-4MHYKEOM.js.map → chunk-OS2AT2JU.js.map} +0 -0
- /package/dist/{chunk-N57A4KPV.js.map → chunk-P3ONDDIJ.js.map} +0 -0
- /package/dist/{chunk-R3HKWWUB.js.map → chunk-PHP3MUGF.js.map} +0 -0
- /package/dist/{chunk-P3SB5BNT.js.map → chunk-QATYVTP7.js.map} +0 -0
- /package/dist/{chunk-LSYDG6MJ.js.map → chunk-QBLDCI6E.js.map} +0 -0
- /package/dist/{chunk-KCB7F4J7.js.map → chunk-QURNMKME.js.map} +0 -0
- /package/dist/{chunk-XOVKXJEP.js.map → chunk-R3TLVTWW.js.map} +0 -0
- /package/dist/{chunk-XXE5P6HJ.js.map → chunk-RRZKTSFG.js.map} +0 -0
- /package/dist/{chunk-44T3Y7SZ.js.map → chunk-RUXPVSML.js.map} +0 -0
- /package/dist/{chunk-DCJ3YFIC.js.map → chunk-S2ULTQZR.js.map} +0 -0
- /package/dist/{chunk-EEC4PCG5.js.map → chunk-SZDLX763.js.map} +0 -0
- /package/dist/{chunk-E2ZHGBAK.js.map → chunk-T2JSUEH6.js.map} +0 -0
- /package/dist/{chunk-227UFSEQ.js.map → chunk-TFA6HPOA.js.map} +0 -0
- /package/dist/{chunk-BA6WOZOT.js.map → chunk-TK4FHQRN.js.map} +0 -0
- /package/dist/{chunk-W27OW7AB.js.map → chunk-TKFSXDOB.js.map} +0 -0
- /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
- /package/dist/{chunk-CETXNLEX.js.map → chunk-UDZYNIDJ.js.map} +0 -0
- /package/dist/{chunk-H5AFCNGA.js.map → chunk-UJX4I26O.js.map} +0 -0
- /package/dist/{chunk-E6TDQRF6.js.map → chunk-UYUCCQ46.js.map} +0 -0
- /package/dist/{chunk-OQDPBRQ6.js.map → chunk-VYXDUPYE.js.map} +0 -0
- /package/dist/{chunk-ZG74PWRW.js.map → chunk-VZAKYDMJ.js.map} +0 -0
- /package/dist/{chunk-NB5BCFUY.js.map → chunk-WHHEPAO3.js.map} +0 -0
- /package/dist/{chunk-H3TKENU4.js.map → chunk-WIKO4SCR.js.map} +0 -0
- /package/dist/{chunk-TX2UTLXC.js.map → chunk-WPDKBUWX.js.map} +0 -0
- /package/dist/{chunk-YFLLGRXO.js.map → chunk-X2QPKLPL.js.map} +0 -0
- /package/dist/{chunk-PFFZWDPE.js.map → chunk-XCOV45MO.js.map} +0 -0
- /package/dist/{chunk-5BCNEBEN.js.map → chunk-XPJNT6PI.js.map} +0 -0
- /package/dist/{chunk-SEDEKFYQ.js.map → chunk-XW2T4QAW.js.map} +0 -0
- /package/dist/{chunk-J7HFPA6O.js.map → chunk-Y63ZFP4X.js.map} +0 -0
- /package/dist/{chunk-D223ZDQV.js.map → chunk-YEDVOYL2.js.map} +0 -0
- /package/dist/{chunk-RC5DXXWC.js.map → chunk-YM7YN37H.js.map} +0 -0
- /package/dist/{chunk-BPJNF7J2.js.map → chunk-YNN26CIZ.js.map} +0 -0
- /package/dist/{chunk-VLXBE57O.js.map → chunk-YVGXH72Y.js.map} +0 -0
- /package/dist/{chunk-YQAXP5AC.js.map → chunk-YXLUTALO.js.map} +0 -0
- /package/dist/{chunk-DGGB65KC.js.map → chunk-Z7ACR6MJ.js.map} +0 -0
- /package/dist/{chunk-X35W4S3L.js.map → chunk-ZBEGS7OB.js.map} +0 -0
- /package/dist/{chunk-XUE46UYW.js.map → chunk-ZLN7AROH.js.map} +0 -0
- /package/dist/{chunk-HK32G473.js.map → chunk-ZWEZXVYH.js.map} +0 -0
- /package/dist/{contradiction-scan-NOYMFG66.js.map → contradiction-scan-GVD4JJ7B.js.map} +0 -0
- /package/dist/{first-start-migration-RC345GPL.js.map → first-start-migration-L3UFX5CU.js.map} +0 -0
- /package/dist/{resolution-VKATP2HT.js.map → local-llm-config.js.map} +0 -0
- /package/dist/{tier-stats-KA6OZX2C.js.map → tier-stats-VK5PCO2L.js.map} +0 -0
package/src/dedup/merge.test.ts
CHANGED
|
@@ -47,7 +47,8 @@ import {
|
|
|
47
47
|
type MergeJudgeRawVerdict,
|
|
48
48
|
} from "./merge.js";
|
|
49
49
|
import type { SemanticDedupHit } from "./semantic.js";
|
|
50
|
-
import { invalidationCommitFingerprint } from "../storage/deletion-revision-store.js";
|
|
50
|
+
import { invalidationCommitFingerprint, isSemanticFrontmatterChange, markCasCommittedRevision, nextCasRevisionIso } from "../storage/deletion-revision-store.js";
|
|
51
|
+
import type { CasRevisionReadStatus } from "../storage/cas-revision-store.js";
|
|
51
52
|
|
|
52
53
|
// The merge snapshot trigger must stay a literal union: a widened
|
|
53
54
|
// `VersionTrigger` (e.g. annotated `readonly string[]`) would let an unknown
|
|
@@ -455,7 +456,7 @@ interface MergeHarness {
|
|
|
455
456
|
storage: StorageManager;
|
|
456
457
|
target: MemoryFile;
|
|
457
458
|
/** Simulate another writer committing a new body to the target. */
|
|
458
|
-
setTargetContent: (content: string) => Promise<
|
|
459
|
+
setTargetContent: (content: string, revision?: string) => Promise<string>;
|
|
459
460
|
calls: {
|
|
460
461
|
contentUpdates: Array<{ id: string; content: string; actor?: string }>;
|
|
461
462
|
frontmatterPatches: Array<{ id: string; patch: Partial<MemoryFrontmatter>; actor?: string }>;
|
|
@@ -464,6 +465,8 @@ interface MergeHarness {
|
|
|
464
465
|
hashRegistrations: Array<{ id: string; hash: string }>;
|
|
465
466
|
reindexed: string[];
|
|
466
467
|
lookupStorages: string[];
|
|
468
|
+
/** Every revision `commit()` stamped, in order — [0] is the content CAS's receipt. */
|
|
469
|
+
commitRevisions: string[];
|
|
467
470
|
};
|
|
468
471
|
}
|
|
469
472
|
|
|
@@ -506,6 +509,15 @@ async function harness(
|
|
|
506
509
|
targetMemoryKind?: MemoryFrontmatter["memoryKind"];
|
|
507
510
|
/** Stamp stale intent routing fields on the target's frontmatter (round N+3 A). */
|
|
508
511
|
targetIntent?: { goal: string; actionType: string; entityTypes: string[] };
|
|
512
|
+
/** Seed `updated` on the target's frontmatter (receipt-clock tests). */
|
|
513
|
+
targetUpdated?: string;
|
|
514
|
+
/**
|
|
515
|
+
* Model what StorageManager.writeMemoryFrontmatter does on success: the
|
|
516
|
+
* accepted patch becomes the standing record's frontmatter — INCLUDING
|
|
517
|
+
* `updated` — so a patch that regresses the revision below an issued CAS
|
|
518
|
+
* receipt is observable (#2813 P1, round 3).
|
|
519
|
+
*/
|
|
520
|
+
applyFrontmatterPatches?: boolean;
|
|
509
521
|
/** Top-level parseConfig overrides (citation enablement, round N+2 C). */
|
|
510
522
|
topLevelConfig?: Record<string, unknown>;
|
|
511
523
|
lookupHits?: SemanticDedupHit[];
|
|
@@ -516,10 +528,34 @@ async function harness(
|
|
|
516
528
|
* open.
|
|
517
529
|
*/
|
|
518
530
|
mutateAtPatch?: string;
|
|
531
|
+
/**
|
|
532
|
+
* #2807 (P1 exception round): a concurrent correction retirement inside
|
|
533
|
+
* the patch window — a SEMANTIC frontmatter mutation whose patch omits
|
|
534
|
+
* `updated` (retireMemoryFn). Routed through the production
|
|
535
|
+
* `frontmatterWriteRevision` so the test exercises the real revision
|
|
536
|
+
* decision, not the stub's opinion.
|
|
537
|
+
*/
|
|
538
|
+
retireAtPatch?: boolean;
|
|
519
539
|
/** Force the frontmatter patch to fail after the content update commits. */
|
|
520
540
|
frontmatterFails?: boolean;
|
|
521
541
|
/** Force the automatic rollback of that committed content to fail. */
|
|
522
542
|
rollbackFails?: boolean;
|
|
543
|
+
/**
|
|
544
|
+
* #2807: force `updateMemoryIfUnchanged` itself to THROW on the
|
|
545
|
+
* semantic-merge actor — "before" fails at lock acquisition (target
|
|
546
|
+
* untouched), "after" commits the merged body and then throws (lock
|
|
547
|
+
* release failure past the write; storage stamps the commit receipt),
|
|
548
|
+
* "concurrent" (#2813 P1) has another writer commit the IDENTICAL
|
|
549
|
+
* deterministic merged body before this writer's lock acquisition
|
|
550
|
+
* fails, so the throw carries no receipt.
|
|
551
|
+
*/
|
|
552
|
+
contentCasThrows?: "before" | "after" | "concurrent" | "after-concurrent";
|
|
553
|
+
/**
|
|
554
|
+
* #2813 (P1 B): force the three-way receipt read inside the rollback's
|
|
555
|
+
* ownership check — "unavailable" simulates a transiently unreadable
|
|
556
|
+
* sidecar, "absent" a sidecar that corroborates neither writer.
|
|
557
|
+
*/
|
|
558
|
+
receiptStatus?: "unavailable" | "absent";
|
|
523
559
|
} = {},
|
|
524
560
|
): Promise<MergeHarness> {
|
|
525
561
|
const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-merge-"));
|
|
@@ -546,6 +582,7 @@ async function harness(
|
|
|
546
582
|
...(overrides.targetValidAt ? { valid_at: overrides.targetValidAt } : {}),
|
|
547
583
|
...(overrides.targetInvalidAt ? { invalid_at: overrides.targetInvalidAt } : {}),
|
|
548
584
|
...(overrides.targetMemoryKind ? { memoryKind: overrides.targetMemoryKind } : {}),
|
|
585
|
+
...(overrides.targetUpdated ? { updated: overrides.targetUpdated } : {}),
|
|
549
586
|
...(overrides.targetIntent
|
|
550
587
|
? {
|
|
551
588
|
intentGoal: overrides.targetIntent.goal,
|
|
@@ -560,6 +597,10 @@ async function harness(
|
|
|
560
597
|
// Live state: the CAS compares against what is on disk NOW, so a stub that
|
|
561
598
|
// returned the original snapshot forever could never fail a compare.
|
|
562
599
|
let state: MemoryFile = { ...target };
|
|
600
|
+
// #2807: the dedicated CAS receipt identity — a sidecar simulation,
|
|
601
|
+
// exactly like StorageManager's CasRevisionStore. Public
|
|
602
|
+
// `frontmatter.updated` is business time and never carries it.
|
|
603
|
+
let casRevision: string | undefined;
|
|
563
604
|
|
|
564
605
|
const calls: MergeHarness["calls"] = {
|
|
565
606
|
contentUpdates: [],
|
|
@@ -569,10 +610,27 @@ async function harness(
|
|
|
569
610
|
hashRegistrations: [],
|
|
570
611
|
reindexed: [],
|
|
571
612
|
lookupStorages: [],
|
|
613
|
+
commitRevisions: [],
|
|
572
614
|
};
|
|
573
|
-
const commit = async (content: string): Promise<
|
|
574
|
-
|
|
615
|
+
const commit = async (content: string, revision?: string): Promise<string> => {
|
|
616
|
+
// Signature-faithful to updateMemoryFromCurrent (#2807): the durable
|
|
617
|
+
// write stamps public `updated` with the wall clock (business time,
|
|
618
|
+
// monotonic within the fake so two same-millisecond commits stay
|
|
619
|
+
// fingerprint-distinct, as real milliseconds are) and mints the receipt
|
|
620
|
+
// from the per-target sidecar token (nextCasRevisionIso) — unique per
|
|
621
|
+
// commit even inside one millisecond.
|
|
622
|
+
casRevision = revision ?? nextCasRevisionIso(casRevision);
|
|
623
|
+
calls.commitRevisions.push(casRevision);
|
|
624
|
+
state = {
|
|
625
|
+
...state,
|
|
626
|
+
content,
|
|
627
|
+
frontmatter: {
|
|
628
|
+
...state.frontmatter,
|
|
629
|
+
updated: nextCasRevisionIso(state.frontmatter.updated),
|
|
630
|
+
},
|
|
631
|
+
};
|
|
575
632
|
await writeFile(targetPath, `---\nid: fact-target\ncategory: fact\n---\n\n${content}\n`, "utf8");
|
|
633
|
+
return casRevision;
|
|
576
634
|
};
|
|
577
635
|
// Live state: reads come off the file, so a stub can neither invent a
|
|
578
636
|
// restore that never touched storage nor compare a snapshot against itself.
|
|
@@ -615,13 +673,49 @@ async function harness(
|
|
|
615
673
|
options?: { actor?: string },
|
|
616
674
|
) => {
|
|
617
675
|
if (overrides.rollbackFails && options?.actor === "semantic-merge-rollback") return false;
|
|
676
|
+
if (overrides.contentCasThrows === "before" && options?.actor === "semantic-merge") {
|
|
677
|
+
throw new Error("storage lock acquisition timed out");
|
|
678
|
+
}
|
|
679
|
+
if (overrides.contentCasThrows === "concurrent" && options?.actor === "semantic-merge") {
|
|
680
|
+
// #2813 (P1): a concurrent writer wins the lock and commits the
|
|
681
|
+
// IDENTICAL deterministic merged body; this writer's CAS then throws
|
|
682
|
+
// before its own mutation — no commit receipt is stamped.
|
|
683
|
+
calls.contentUpdates.push({ id: expected.frontmatter.id, content, actor: "other-writer" });
|
|
684
|
+
await commit(content);
|
|
685
|
+
throw new Error("storage lock acquisition timed out");
|
|
686
|
+
}
|
|
618
687
|
if (overrides.mutateOnWrite !== undefined && options?.actor === "semantic-merge") {
|
|
619
688
|
await commit(overrides.mutateOnWrite);
|
|
620
689
|
}
|
|
690
|
+
if (overrides.contentCasThrows === "after" && options?.actor === "semantic-merge") {
|
|
691
|
+
calls.contentUpdates.push({ id: expected.frontmatter.id, content, actor: options?.actor });
|
|
692
|
+
const revision = await commit(content);
|
|
693
|
+
// Signature-faithful to the real CAS: the durable write landed, so
|
|
694
|
+
// storage stamps the post-commit throw with the commit receipt.
|
|
695
|
+
const err = new Error("lock release failed after the content write committed");
|
|
696
|
+
markCasCommittedRevision(err, revision);
|
|
697
|
+
throw err;
|
|
698
|
+
}
|
|
699
|
+
if (overrides.contentCasThrows === "after-concurrent" && options?.actor === "semantic-merge") {
|
|
700
|
+
// #2813 (P1, round 2): THIS writer's CAS commits the merged body and
|
|
701
|
+
// its post-commit work throws with the commit receipt stamped — then
|
|
702
|
+
// a concurrent writer commits the IDENTICAL deterministic merged body
|
|
703
|
+
// after the lock is released, before this writer's catch path
|
|
704
|
+
// performs its rollback. Fix B: both commits land inside the SAME
|
|
705
|
+
// millisecond; only the monotonic revision stamp tells them apart.
|
|
706
|
+
calls.contentUpdates.push({ id: expected.frontmatter.id, content, actor: options?.actor });
|
|
707
|
+
const revision = await commit(content);
|
|
708
|
+
calls.contentUpdates.push({ id: expected.frontmatter.id, content, actor: "other-writer" });
|
|
709
|
+
const foreign = await commit(content);
|
|
710
|
+
assert.notEqual(foreign, revision, "same-millisecond identical commits must carry distinct receipts");
|
|
711
|
+
const err = new Error("lock release failed after the content write committed");
|
|
712
|
+
markCasCommittedRevision(err, revision);
|
|
713
|
+
throw err;
|
|
714
|
+
}
|
|
621
715
|
if (!(await unchanged(expected))) return false;
|
|
622
716
|
calls.contentUpdates.push({ id: expected.frontmatter.id, content, actor: options?.actor });
|
|
623
|
-
|
|
624
|
-
return
|
|
717
|
+
// Signature-faithful: a successful CAS returns its commit receipt.
|
|
718
|
+
return await commit(content);
|
|
625
719
|
},
|
|
626
720
|
// Signature-faithful to StorageManager.writeMemoryFrontmatterIfUnchanged.
|
|
627
721
|
writeMemoryFrontmatterIfUnchanged: async (
|
|
@@ -632,8 +726,37 @@ async function harness(
|
|
|
632
726
|
// A concurrent writer inside the patch window: after the caller's
|
|
633
727
|
// verifying read, before storage takes its own lock.
|
|
634
728
|
if (overrides.mutateAtPatch !== undefined) await commit(overrides.mutateAtPatch);
|
|
729
|
+
// #2807 (P1 exception round): a concurrent correction retirement in
|
|
730
|
+
// the same window — status flip with NO proposed revision, stamped
|
|
731
|
+
// through the production boundary exactly as
|
|
732
|
+
// StorageManager.writeMemoryFrontmatter stamps it.
|
|
733
|
+
if (overrides.retireAtPatch) {
|
|
734
|
+
// #2807: the patch applies VERBATIM (business time untouched — no
|
|
735
|
+
// `updated` rewrite) and, being semantic, mints the next sidecar
|
|
736
|
+
// token exactly as StorageManager.writeMemoryFrontmatter's
|
|
737
|
+
// chokepoint does.
|
|
738
|
+
const retired: MemoryFrontmatter = {
|
|
739
|
+
...state.frontmatter,
|
|
740
|
+
status: "superseded",
|
|
741
|
+
supersededBy: "fact-replacement",
|
|
742
|
+
};
|
|
743
|
+
if (isSemanticFrontmatterChange(state.frontmatter, retired)) {
|
|
744
|
+
casRevision = nextCasRevisionIso(casRevision);
|
|
745
|
+
}
|
|
746
|
+
state = { ...state, frontmatter: retired };
|
|
747
|
+
}
|
|
635
748
|
if (!(await unchanged(expected))) return false;
|
|
636
749
|
calls.frontmatterPatches.push({ id: expected.frontmatter.id, patch, actor: options?.actor });
|
|
750
|
+
// #2807: the accepted patch becomes the standing record's frontmatter
|
|
751
|
+
// VERBATIM (including caller `updated`), and a semantic change mints
|
|
752
|
+
// the next sidecar token — mirroring StorageManager.writeMemoryFrontmatter.
|
|
753
|
+
if (overrides.applyFrontmatterPatches) {
|
|
754
|
+
const merged = { ...state.frontmatter, ...patch };
|
|
755
|
+
if (isSemanticFrontmatterChange(state.frontmatter, merged)) {
|
|
756
|
+
casRevision = nextCasRevisionIso(casRevision);
|
|
757
|
+
}
|
|
758
|
+
state = { ...state, frontmatter: merged };
|
|
759
|
+
}
|
|
637
760
|
return overrides.frontmatterFails !== true;
|
|
638
761
|
},
|
|
639
762
|
removeFactContentHashesForMemories: async (memories: MemoryFile[]) => {
|
|
@@ -645,6 +768,15 @@ async function harness(
|
|
|
645
768
|
registerFactContentHash: async (id: string, hash: string, _expectedContent: string) => {
|
|
646
769
|
calls.hashRegistrations.push({ id, hash });
|
|
647
770
|
},
|
|
771
|
+
readCasRevision: async (p: string) => (p === targetPath ? casRevision : undefined),
|
|
772
|
+
readCasRevisionStatus: async (p: string): Promise<CasRevisionReadStatus> => {
|
|
773
|
+
if (p !== targetPath) return { status: "absent" };
|
|
774
|
+
if (overrides.receiptStatus === "unavailable") {
|
|
775
|
+
return { status: "unavailable", reason: "simulated transient sidecar read failure" };
|
|
776
|
+
}
|
|
777
|
+
if (overrides.receiptStatus === "absent") return { status: "absent" };
|
|
778
|
+
return casRevision === undefined ? { status: "absent" } : { status: "present", revision: casRevision };
|
|
779
|
+
},
|
|
648
780
|
} as unknown as StorageManager;
|
|
649
781
|
|
|
650
782
|
const config = parseConfig({
|
|
@@ -1171,10 +1303,7 @@ test("registerFactContentHash: exact dedup finds the degraded record's merged bo
|
|
|
1171
1303
|
// compare-and-swapped to the merged text while the frontmatter keeps the
|
|
1172
1304
|
// old identity (updateMemoryIfUnchanged preserves contentHash).
|
|
1173
1305
|
const before = (await storage.readAllMemories()).find((m) => m.frontmatter.id === id)!;
|
|
1174
|
-
assert.
|
|
1175
|
-
await storage.updateMemoryIfUnchanged(before, MERGED, { actor: "semantic-merge" }),
|
|
1176
|
-
true,
|
|
1177
|
-
);
|
|
1306
|
+
assert.ok(await storage.updateMemoryIfUnchanged(before, MERGED, { actor: "semantic-merge" }));
|
|
1178
1307
|
const degraded = (await storage.readAllMemories()).find((m) => m.frontmatter.id === id)!;
|
|
1179
1308
|
const staleHash = degraded.frontmatter.contentHash;
|
|
1180
1309
|
const mergedHash = ContentHashIndex.computeHash(sanitizeMemoryContent(MERGED).text);
|
|
@@ -1252,7 +1381,7 @@ test("persistRepairedContentHash: the repaired hash survives a restart's corpus
|
|
|
1252
1381
|
// compare-and-swapped to the merged text while the frontmatter keeps the
|
|
1253
1382
|
// old identity (updateMemoryIfUnchanged preserves contentHash).
|
|
1254
1383
|
const before = (await storage.readAllMemories()).find((m) => m.frontmatter.id === id)!;
|
|
1255
|
-
assert.
|
|
1384
|
+
assert.ok(await storage.updateMemoryIfUnchanged(before, MERGED, { actor: "semantic-merge" }));
|
|
1256
1385
|
const mergedHash = ContentHashIndex.computeHash(sanitizeMemoryContent(MERGED).text);
|
|
1257
1386
|
// The N+16 C repair alone (process-local registration).
|
|
1258
1387
|
await storage.registerFactContentHash(id, mergedHash, MERGED);
|
|
@@ -2358,7 +2487,7 @@ test("applySemanticMergeAtPersist: the committed merged record carries the lower
|
|
|
2358
2487
|
assert.equal(committed?.frontmatter.confidenceTier, "inferred");
|
|
2359
2488
|
// The committed record is the promotion payload's sole source, so the
|
|
2360
2489
|
// shared/profile copy stamps the downgraded value too.
|
|
2361
|
-
const payload = await buildMergedTargetPromotionPayload(storage, {
|
|
2490
|
+
const { payload } = await buildMergedTargetPromotionPayload(storage, {
|
|
2362
2491
|
targetId: created.id,
|
|
2363
2492
|
mergedContent: MERGED,
|
|
2364
2493
|
provenancePatched: true,
|
|
@@ -2414,7 +2543,7 @@ test("buildMergedTargetPromotionPayload: never promotes from an inactive committ
|
|
|
2414
2543
|
// reread: the multi-writer interleaving, simulated directly.
|
|
2415
2544
|
const snapshot = await storage.getMemoryByIdIncludingArchived(created.id);
|
|
2416
2545
|
assert.ok(snapshot);
|
|
2417
|
-
assert.
|
|
2546
|
+
assert.ok(await storage.updateMemoryIfUnchanged(snapshot, MERGED));
|
|
2418
2547
|
for (const status of ["superseded", "archived"] as const) {
|
|
2419
2548
|
assert.equal(
|
|
2420
2549
|
await storage.updateMemoryFrontmatter(created.id, { status }),
|
|
@@ -2424,11 +2553,11 @@ test("buildMergedTargetPromotionPayload: never promotes from an inactive committ
|
|
|
2424
2553
|
// Null, never a payload: the caller skips promoteMemoryToShared, so no
|
|
2425
2554
|
// new active copy resurrects what the lifecycle operation retired.
|
|
2426
2555
|
assert.equal(
|
|
2427
|
-
await buildMergedTargetPromotionPayload(storage, {
|
|
2556
|
+
(await buildMergedTargetPromotionPayload(storage, {
|
|
2428
2557
|
targetId: created.id,
|
|
2429
2558
|
mergedContent: MERGED,
|
|
2430
2559
|
provenancePatched: true,
|
|
2431
|
-
}),
|
|
2560
|
+
})).payload,
|
|
2432
2561
|
null,
|
|
2433
2562
|
status,
|
|
2434
2563
|
);
|
|
@@ -2438,7 +2567,7 @@ test("buildMergedTargetPromotionPayload: never promotes from an inactive committ
|
|
|
2438
2567
|
await storage.updateMemoryFrontmatter(created.id, { status: "active" }),
|
|
2439
2568
|
true,
|
|
2440
2569
|
);
|
|
2441
|
-
const payload = await buildMergedTargetPromotionPayload(storage, {
|
|
2570
|
+
const { payload } = await buildMergedTargetPromotionPayload(storage, {
|
|
2442
2571
|
targetId: created.id,
|
|
2443
2572
|
mergedContent: MERGED,
|
|
2444
2573
|
provenancePatched: true,
|
|
@@ -2489,7 +2618,7 @@ test("buildMergedTargetPromotionPayload: carries the committed tool-scope marker
|
|
|
2489
2618
|
},
|
|
2490
2619
|
);
|
|
2491
2620
|
assert.equal(outcome.action, "merged");
|
|
2492
|
-
const payload = await buildMergedTargetPromotionPayload(storage, {
|
|
2621
|
+
const { payload } = await buildMergedTargetPromotionPayload(storage, {
|
|
2493
2622
|
targetId: created.id,
|
|
2494
2623
|
mergedContent: MERGED,
|
|
2495
2624
|
provenancePatched: true,
|
|
@@ -2523,7 +2652,7 @@ test("buildMergedTargetPromotionPayload: an unscoped target promotes a payload w
|
|
|
2523
2652
|
judgeCall: (options) => acceptingJudge(options),
|
|
2524
2653
|
});
|
|
2525
2654
|
assert.equal(outcome.action, "merged");
|
|
2526
|
-
const payload = await buildMergedTargetPromotionPayload(storage, {
|
|
2655
|
+
const { payload } = await buildMergedTargetPromotionPayload(storage, {
|
|
2527
2656
|
targetId: created.id,
|
|
2528
2657
|
mergedContent: MERGED,
|
|
2529
2658
|
provenancePatched: true,
|
|
@@ -2883,7 +3012,7 @@ test("buildMergedTargetPromotionPayload: a degraded merge never yields a promoti
|
|
|
2883
3012
|
if (degraded.action !== "merged") return;
|
|
2884
3013
|
assert.equal(degraded.provenancePatched, false);
|
|
2885
3014
|
assert.equal(
|
|
2886
|
-
await buildMergedTargetPromotionPayload(h.storage, degraded),
|
|
3015
|
+
(await buildMergedTargetPromotionPayload(h.storage, degraded)).payload,
|
|
2887
3016
|
null,
|
|
2888
3017
|
"no shared/profile copy may be built from an unpatched provenance record",
|
|
2889
3018
|
);
|
|
@@ -2899,7 +3028,7 @@ test("buildMergedTargetPromotionPayload: a degraded merge never yields a promoti
|
|
|
2899
3028
|
assert.equal(patched.action, "merged");
|
|
2900
3029
|
if (patched.action !== "merged") return;
|
|
2901
3030
|
assert.equal(patched.provenancePatched, true);
|
|
2902
|
-
const payload = await buildMergedTargetPromotionPayload(ok.storage, patched);
|
|
3031
|
+
const { payload } = await buildMergedTargetPromotionPayload(ok.storage, patched);
|
|
2903
3032
|
assert.ok(payload);
|
|
2904
3033
|
assert.equal(payload?.sourceMemoryId, "fact-target");
|
|
2905
3034
|
});
|
|
@@ -2925,12 +3054,13 @@ test("buildMergedTargetPromotionPayload: a failed post-commit reread fails open
|
|
|
2925
3054
|
throw new Error("secure store locked");
|
|
2926
3055
|
},
|
|
2927
3056
|
} as unknown as StorageManager;
|
|
2928
|
-
const payload = await buildMergedTargetPromotionPayload(lockedStore, {
|
|
3057
|
+
const { payload, readFailed } = await buildMergedTargetPromotionPayload(lockedStore, {
|
|
2929
3058
|
targetId: "fact-target",
|
|
2930
3059
|
mergedContent: "merged body",
|
|
2931
3060
|
provenancePatched: true,
|
|
2932
3061
|
});
|
|
2933
3062
|
assert.equal(payload, null, "a reread failure must resolve to null, not a rejection");
|
|
3063
|
+
assert.equal(readFailed, true, "#2807: the null must be identifiable as a read failure, not a refusal");
|
|
2934
3064
|
const line = entries.find(
|
|
2935
3065
|
(e) => e.level === "warn" && e.message.includes("semantic-merge") && e.message.includes("fact-target"),
|
|
2936
3066
|
)?.message;
|
|
@@ -3045,6 +3175,9 @@ async function postEffectsHarness(options: {
|
|
|
3045
3175
|
content: MERGED,
|
|
3046
3176
|
}
|
|
3047
3177
|
: null,
|
|
3178
|
+
// #2807: static token — these fixtures drive the rollback paths, not
|
|
3179
|
+
// ownership attribution.
|
|
3180
|
+
readCasRevision: async () => "2026-08-20T00:00:00.000Z",
|
|
3048
3181
|
} as unknown as StorageManager;
|
|
3049
3182
|
const deps = {
|
|
3050
3183
|
config: parseConfig({ memoryDir: dir }),
|
|
@@ -3375,14 +3508,17 @@ test("runMergedTargetPostEffects: a stale writer's rollback preserves the newer
|
|
|
3375
3508
|
id,
|
|
3376
3509
|
category: "fact",
|
|
3377
3510
|
entityRef: "entity-billing-service",
|
|
3378
|
-
// B's commit flips
|
|
3379
|
-
//
|
|
3380
|
-
//
|
|
3381
|
-
...(buildStarted ? { updated: "2026-08-22T01:00:00.000Z" } : {}),
|
|
3511
|
+
// B's commit flips the body once A's rebuild has begun: the
|
|
3512
|
+
// initial committed-body check sees A's state, everything from
|
|
3513
|
+
// the build onward sees B's.
|
|
3382
3514
|
},
|
|
3383
3515
|
content: buildStarted ? NEWER_BODY : MERGED,
|
|
3384
3516
|
}
|
|
3385
3517
|
: null,
|
|
3518
|
+
// #2807: B's mid-rebuild commit mints a NEW token — the identity the
|
|
3519
|
+
// revision guard compares (public `updated` no longer carries it).
|
|
3520
|
+
readCasRevision: async () =>
|
|
3521
|
+
buildStarted ? "2026-08-22T01:00:00.001Z" : "2026-08-20T00:00:00.000Z",
|
|
3386
3522
|
} as unknown as StorageManager;
|
|
3387
3523
|
const graphConfig = parseConfig({ memoryDir: h.dir });
|
|
3388
3524
|
const graphIndex = new GraphIndex(h.dir, graphConfig);
|
|
@@ -3514,6 +3650,503 @@ test("runMergedTargetPostEffects: a THROWING build's rollback preserves the newe
|
|
|
3514
3650
|
}
|
|
3515
3651
|
});
|
|
3516
3652
|
|
|
3653
|
+
|
|
3654
|
+
// ── #2807: deferred P2 follow-ups from the #2771 round cap ──────────────────
|
|
3655
|
+
|
|
3656
|
+
test("applySemanticMergeAtPersist: a content CAS that throws before changing the target discards the staged snapshot (#2807)", async () => {
|
|
3657
|
+
// Scenario A — the CAS throws at lock acquisition: the target was never
|
|
3658
|
+
// touched, yet the old catch left the staged snapshot `pending` forever
|
|
3659
|
+
// (pruneExcessVersions excludes pending entries), so repeated contention
|
|
3660
|
+
// grew version history past maxVersionsPerPage with duplicates of an
|
|
3661
|
+
// unchanged body. The reread confirms the pre-merge body → discard.
|
|
3662
|
+
const before = await harness({ contentCasThrows: "before" });
|
|
3663
|
+
const outcomeA = await applySemanticMergeAtPersist(before.deps, {
|
|
3664
|
+
storage: before.storage,
|
|
3665
|
+
content: INCOMING,
|
|
3666
|
+
category: "fact",
|
|
3667
|
+
judgeCall: (options) => acceptingJudge(options),
|
|
3668
|
+
});
|
|
3669
|
+
assert.deepEqual(outcomeA, { action: "created", reason: "update_failed" });
|
|
3670
|
+
const bodyA = await before.storage.getMemoryByIdIncludingArchived("fact-target");
|
|
3671
|
+
assert.equal(bodyA?.content, EXISTING, "the throw preceded the write — the target is untouched");
|
|
3672
|
+
assert.equal(
|
|
3673
|
+
(
|
|
3674
|
+
await listVersions(
|
|
3675
|
+
before.target.path,
|
|
3676
|
+
{ enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
|
|
3677
|
+
before.storage.dir,
|
|
3678
|
+
)
|
|
3679
|
+
).versions.length,
|
|
3680
|
+
0,
|
|
3681
|
+
"a snapshot of a body that never changed must not survive the aborted attempt",
|
|
3682
|
+
);
|
|
3683
|
+
|
|
3684
|
+
// Scenario B — the CAS commits the merged body and THEN throws (lock
|
|
3685
|
+
// release past the write): `contentCommitted` never flipped, so the old
|
|
3686
|
+
// code both stranded the snapshot AND reported `created` while storage
|
|
3687
|
+
// held the unprovenanced merged body (the duplicate-fact hazard the
|
|
3688
|
+
// catch's own contract forbids). The reread must see the landed body,
|
|
3689
|
+
// revert it, and drop the now-duplicate snapshot.
|
|
3690
|
+
const after = await harness({ contentCasThrows: "after" });
|
|
3691
|
+
const outcomeB = await applySemanticMergeAtPersist(after.deps, {
|
|
3692
|
+
storage: after.storage,
|
|
3693
|
+
content: INCOMING,
|
|
3694
|
+
category: "fact",
|
|
3695
|
+
judgeCall: (options) => acceptingJudge(options),
|
|
3696
|
+
});
|
|
3697
|
+
assert.deepEqual(outcomeB, { action: "created", reason: "update_failed" });
|
|
3698
|
+
const bodyB = await after.storage.getMemoryByIdIncludingArchived("fact-target");
|
|
3699
|
+
assert.equal(bodyB?.content, EXISTING, "the landed merged body is rolled back before `created` is honest");
|
|
3700
|
+
assert.deepEqual(
|
|
3701
|
+
after.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
|
|
3702
|
+
[
|
|
3703
|
+
{ content: MERGED, actor: "semantic-merge" },
|
|
3704
|
+
{ content: EXISTING, actor: "semantic-merge-rollback" },
|
|
3705
|
+
],
|
|
3706
|
+
);
|
|
3707
|
+
assert.equal(
|
|
3708
|
+
(
|
|
3709
|
+
await listVersions(
|
|
3710
|
+
after.target.path,
|
|
3711
|
+
{ enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
|
|
3712
|
+
after.storage.dir,
|
|
3713
|
+
)
|
|
3714
|
+
).versions.length,
|
|
3715
|
+
0,
|
|
3716
|
+
"the reverted attempt leaves no snapshot: the recovery point would hold the body storage already returned to",
|
|
3717
|
+
);
|
|
3718
|
+
});
|
|
3719
|
+
|
|
3720
|
+
test("applySemanticMergeAtPersist: a concurrent identical commit is never claimed as this writer's (#2813 P1)", async () => {
|
|
3721
|
+
// The P1 hole — body-equality ownership. This writer's CAS throws before
|
|
3722
|
+
// mutating anything, but a concurrent writer commits the IDENTICAL
|
|
3723
|
+
// deterministic merged body. The old reread saw "the merged body
|
|
3724
|
+
// standing" and claimed the commit as ours, so revertMergedContent
|
|
3725
|
+
// CAS-replaced the other writer's valid merge with the pre-merge body
|
|
3726
|
+
// while their patched provenance stood. Ownership now comes from the CAS
|
|
3727
|
+
// commit receipt: absent → the standing body is theirs. This writer
|
|
3728
|
+
// discards only its own staged duplicate snapshot and reports the
|
|
3729
|
+
// degraded merged outcome (never `created` — storage already holds
|
|
3730
|
+
// these claims, so writing the fact again would duplicate them).
|
|
3731
|
+
const h = await harness({ contentCasThrows: "concurrent" });
|
|
3732
|
+
const outcome = await applySemanticMergeAtPersist(h.deps, {
|
|
3733
|
+
storage: h.storage,
|
|
3734
|
+
content: INCOMING,
|
|
3735
|
+
category: "fact",
|
|
3736
|
+
judgeCall: (options) => acceptingJudge(options),
|
|
3737
|
+
});
|
|
3738
|
+
assert.deepEqual(outcome, {
|
|
3739
|
+
action: "merged",
|
|
3740
|
+
targetId: "fact-target",
|
|
3741
|
+
mergedContent: MERGED,
|
|
3742
|
+
provenancePatched: false,
|
|
3743
|
+
});
|
|
3744
|
+
const body = await h.storage.getMemoryByIdIncludingArchived("fact-target");
|
|
3745
|
+
assert.equal(body?.content, MERGED, "the concurrent writer's commit stands — never reverted");
|
|
3746
|
+
assert.deepEqual(
|
|
3747
|
+
h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
|
|
3748
|
+
[{ content: MERGED, actor: "other-writer" }],
|
|
3749
|
+
"neither a semantic-merge write nor a semantic-merge-rollback ran — the concurrent commit's state is untouched",
|
|
3750
|
+
);
|
|
3751
|
+
assert.equal(
|
|
3752
|
+
(
|
|
3753
|
+
await listVersions(
|
|
3754
|
+
h.target.path,
|
|
3755
|
+
{ enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
|
|
3756
|
+
h.storage.dir,
|
|
3757
|
+
)
|
|
3758
|
+
).versions.length,
|
|
3759
|
+
0,
|
|
3760
|
+
"this writer's staged duplicate snapshot is cleaned up, not finalized into history",
|
|
3761
|
+
);
|
|
3762
|
+
});
|
|
3763
|
+
|
|
3764
|
+
test("applySemanticMergeAtPersist: a rollback never reverts a concurrent identical commit that landed after this writer's receipt (#2813 P1)", async () => {
|
|
3765
|
+
// The round-2 P1 hole — the receipt used only as a boolean. This writer's
|
|
3766
|
+
// CAS COMMITS the merged body and its post-commit work throws with the
|
|
3767
|
+
// commit receipt stamped; before the catch path runs its rollback, a
|
|
3768
|
+
// concurrent writer commits the IDENTICAL deterministic merged body under a
|
|
3769
|
+
// later revision. Body equality cannot tell the two commits apart, so the
|
|
3770
|
+
// old rollback reread "the merged body standing", CAS-restored the
|
|
3771
|
+
// pre-merge body over the concurrent writer's valid merge, and discarded
|
|
3772
|
+
// the snapshot while their provenance update may already have landed. The
|
|
3773
|
+
// rollback now compares the standing record's revision with the receipt:
|
|
3774
|
+
// equal → ours, safe to revert; advanced → theirs — the other-writer
|
|
3775
|
+
// handling from the previous fix (discard our staged duplicate, repair
|
|
3776
|
+
// indexes for the standing body, report the degraded merge; never revert
|
|
3777
|
+
// theirs).
|
|
3778
|
+
const h = await harness({ contentCasThrows: "after-concurrent" });
|
|
3779
|
+
const outcome = await applySemanticMergeAtPersist(h.deps, {
|
|
3780
|
+
storage: h.storage,
|
|
3781
|
+
content: INCOMING,
|
|
3782
|
+
category: "fact",
|
|
3783
|
+
judgeCall: (options) => acceptingJudge(options),
|
|
3784
|
+
});
|
|
3785
|
+
assert.deepEqual(outcome, {
|
|
3786
|
+
action: "merged",
|
|
3787
|
+
targetId: "fact-target",
|
|
3788
|
+
mergedContent: MERGED,
|
|
3789
|
+
provenancePatched: false,
|
|
3790
|
+
});
|
|
3791
|
+
const body = await h.storage.getMemoryByIdIncludingArchived("fact-target");
|
|
3792
|
+
assert.equal(
|
|
3793
|
+
body?.content,
|
|
3794
|
+
MERGED,
|
|
3795
|
+
"the concurrent writer's identical commit stands — never reverted to the pre-merge body",
|
|
3796
|
+
);
|
|
3797
|
+
assert.deepEqual(
|
|
3798
|
+
h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
|
|
3799
|
+
[
|
|
3800
|
+
{ content: MERGED, actor: "semantic-merge" },
|
|
3801
|
+
{ content: MERGED, actor: "other-writer" },
|
|
3802
|
+
],
|
|
3803
|
+
"no semantic-merge-rollback write runs — the pre-merge restore must never fire against another writer's commit",
|
|
3804
|
+
);
|
|
3805
|
+
assert.equal(
|
|
3806
|
+
h.calls.hashRegistrations.length,
|
|
3807
|
+
1,
|
|
3808
|
+
"the degraded path repairs the hash indexes for the standing merged body",
|
|
3809
|
+
);
|
|
3810
|
+
assert.equal(
|
|
3811
|
+
(
|
|
3812
|
+
await listVersions(
|
|
3813
|
+
h.target.path,
|
|
3814
|
+
{ enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
|
|
3815
|
+
h.storage.dir,
|
|
3816
|
+
)
|
|
3817
|
+
).versions.length,
|
|
3818
|
+
0,
|
|
3819
|
+
"this writer's staged duplicate snapshot is discarded, not finalized into history",
|
|
3820
|
+
);
|
|
3821
|
+
});
|
|
3822
|
+
|
|
3823
|
+
test("applySemanticMergeAtPersist: a successful content CAS retains its receipt, so a same-millisecond identical commit survives a failed provenance patch (#2813 P1)", async () => {
|
|
3824
|
+
// Fix A — the receipt was captured only from the THROWING CAS
|
|
3825
|
+
// (casCommittedRevisionOf). When the content CAS SUCCEEDED and a later
|
|
3826
|
+
// step threw (provenance patch rejected), the catch rolled back with NO
|
|
3827
|
+
// revision: revertMergedContent skipped its ownership comparison, body
|
|
3828
|
+
// equality attributed the standing record to this writer, and the
|
|
3829
|
+
// pre-merge restore deleted the concurrent writer's valid identical merge
|
|
3830
|
+
// (here committed inside the patch window, the SAME millisecond — fix B's
|
|
3831
|
+
// wall-clock collision). The success path now retains the landed revision,
|
|
3832
|
+
// the monotonic stamp keeps the two same-ms commits distinct, and the
|
|
3833
|
+
// rollback classifies the standing body as superseded — never reverted.
|
|
3834
|
+
const h = await harness({ mutateAtPatch: MERGED });
|
|
3835
|
+
const outcome = await applySemanticMergeAtPersist(h.deps, {
|
|
3836
|
+
storage: h.storage,
|
|
3837
|
+
content: INCOMING,
|
|
3838
|
+
category: "fact",
|
|
3839
|
+
judgeCall: (options) => acceptingJudge(options),
|
|
3840
|
+
});
|
|
3841
|
+
assert.deepEqual(outcome, {
|
|
3842
|
+
action: "merged",
|
|
3843
|
+
targetId: "fact-target",
|
|
3844
|
+
mergedContent: MERGED,
|
|
3845
|
+
provenancePatched: false,
|
|
3846
|
+
});
|
|
3847
|
+
const body = await h.storage.getMemoryByIdIncludingArchived("fact-target");
|
|
3848
|
+
assert.equal(
|
|
3849
|
+
body?.content,
|
|
3850
|
+
MERGED,
|
|
3851
|
+
"the concurrent writer's identical commit stands — never reverted to the pre-merge body",
|
|
3852
|
+
);
|
|
3853
|
+
assert.deepEqual(
|
|
3854
|
+
h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
|
|
3855
|
+
[{ content: MERGED, actor: "semantic-merge" }],
|
|
3856
|
+
"no semantic-merge-rollback write runs — the pre-merge restore must never fire against another writer's commit",
|
|
3857
|
+
);
|
|
3858
|
+
assert.equal(
|
|
3859
|
+
h.calls.hashRegistrations.length,
|
|
3860
|
+
1,
|
|
3861
|
+
"the degraded path repairs the hash indexes for the standing merged body",
|
|
3862
|
+
);
|
|
3863
|
+
assert.equal(
|
|
3864
|
+
(
|
|
3865
|
+
await listVersions(
|
|
3866
|
+
h.target.path,
|
|
3867
|
+
{ enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
|
|
3868
|
+
h.storage.dir,
|
|
3869
|
+
)
|
|
3870
|
+
).versions.length,
|
|
3871
|
+
0,
|
|
3872
|
+
"this writer's staged duplicate snapshot is discarded, not finalized into history",
|
|
3873
|
+
);
|
|
3874
|
+
});
|
|
3875
|
+
|
|
3876
|
+
test("applySemanticMergeAtPersist: a timestamp-less retirement between the content CAS and the provenance patch is never rolled back over (#2807 P1)", async () => {
|
|
3877
|
+
// The exception-round P1 hole — the PRESERVED revision. This writer's
|
|
3878
|
+
// content CAS commits the merged body (receipt T+1) and, before the
|
|
3879
|
+
// provenance patch takes its lock, a concurrent correction retirement
|
|
3880
|
+
// lands: a semantic frontmatter mutation whose patch omits `updated`
|
|
3881
|
+
// (retireMemoryFn). The status flip makes the provenance patch's
|
|
3882
|
+
// fingerprint compare reject it, so the catch path rolls back holding the
|
|
3883
|
+
// content CAS's receipt. Pre-fix, the timestamp-less write PRESERVED the
|
|
3884
|
+
// standing revision, so the retired record still carried this writer's
|
|
3885
|
+
// receipt — the rollback claimed the foreign record as its own and
|
|
3886
|
+
// CAS-restored the pre-merge body, leaving the retirement metadata
|
|
3887
|
+
// (superseded/supersededBy) attached to content it never described. The
|
|
3888
|
+
// boundary fix advances the revision on EVERY semantic frontmatter
|
|
3889
|
+
// mutation, so the failure handler detects the foreign revision and the
|
|
3890
|
+
// retired record is never touched.
|
|
3891
|
+
const h = await harness({ retireAtPatch: true });
|
|
3892
|
+
const outcome = await applySemanticMergeAtPersist(h.deps, {
|
|
3893
|
+
storage: h.storage,
|
|
3894
|
+
content: INCOMING,
|
|
3895
|
+
category: "fact",
|
|
3896
|
+
judgeCall: (options) => acceptingJudge(options),
|
|
3897
|
+
});
|
|
3898
|
+
assert.deepEqual(outcome, {
|
|
3899
|
+
action: "merged",
|
|
3900
|
+
targetId: "fact-target",
|
|
3901
|
+
mergedContent: MERGED,
|
|
3902
|
+
provenancePatched: false,
|
|
3903
|
+
});
|
|
3904
|
+
const body = await h.storage.getMemoryByIdIncludingArchived("fact-target");
|
|
3905
|
+
assert.ok(body);
|
|
3906
|
+
assert.equal(body.content, MERGED, "the merged body is never rolled back over the concurrent retirement");
|
|
3907
|
+
assert.equal(body.frontmatter.status, "superseded", "the retirement metadata survives untouched");
|
|
3908
|
+
assert.equal(body.frontmatter.supersededBy, "fact-replacement");
|
|
3909
|
+
// The failure handler detected the FOREIGN revision: the standing
|
|
3910
|
+
// revision advanced strictly past the content CAS's receipt — the
|
|
3911
|
+
// identity the rollback compares.
|
|
3912
|
+
const receipt = h.calls.commitRevisions[0];
|
|
3913
|
+
assert.ok(receipt, "the content CAS stamped a receipt");
|
|
3914
|
+
const standingToken = await h.storage.readCasRevision(h.target.path);
|
|
3915
|
+
assert.ok(standingToken, "the retirement minted a new token");
|
|
3916
|
+
assert.notEqual(standingToken, receipt, "the timestamp-less retirement retired the CAS's receipt token");
|
|
3917
|
+
assert.ok(
|
|
3918
|
+
new Date(standingToken).getTime() > new Date(receipt).getTime(),
|
|
3919
|
+
"the timestamp-less retirement advanced the token strictly past the CAS receipt",
|
|
3920
|
+
);
|
|
3921
|
+
assert.deepEqual(
|
|
3922
|
+
h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
|
|
3923
|
+
[{ content: MERGED, actor: "semantic-merge" }],
|
|
3924
|
+
"no semantic-merge-rollback write runs — the retired record is another writer's",
|
|
3925
|
+
);
|
|
3926
|
+
assert.equal(
|
|
3927
|
+
h.calls.hashRegistrations.length,
|
|
3928
|
+
1,
|
|
3929
|
+
"the degraded path repairs the hash indexes for the standing merged body",
|
|
3930
|
+
);
|
|
3931
|
+
assert.equal(
|
|
3932
|
+
(
|
|
3933
|
+
await listVersions(
|
|
3934
|
+
h.target.path,
|
|
3935
|
+
{ enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
|
|
3936
|
+
h.storage.dir,
|
|
3937
|
+
)
|
|
3938
|
+
).versions.length,
|
|
3939
|
+
0,
|
|
3940
|
+
"this writer's staged duplicate snapshot is discarded, not finalized into history",
|
|
3941
|
+
);
|
|
3942
|
+
});
|
|
3943
|
+
|
|
3944
|
+
test("applySemanticMergeAtPersist: the monotonic receipt survives the metadata patch — three same-millisecond merges, A's rollback never restores over C's commit (#2813 P1)", async () => {
|
|
3945
|
+
// Round-3 P1 hole — the receipt was monotonic only until the metadata
|
|
3946
|
+
// patch. The patch stamped the PRE-CAS wall clock (mergePatch.updated), so
|
|
3947
|
+
// a successful writer REGRESSED frontmatter.updated below the receipt its
|
|
3948
|
+
// own CAS had just issued. Three writers merging into the same target
|
|
3949
|
+
// inside one millisecond (target seeded at T, every writer's clock T):
|
|
3950
|
+
// The seed sits AHEAD of the real wall clock on purpose: the fake's commit
|
|
3951
|
+
// stamps via nextCasRevisionIso against the real clock, so a future seed
|
|
3952
|
+
// forces every stamp into the +1ms monotonic branch — the sequence is
|
|
3953
|
+
// pinned to T+n exactly as inside the finding's single millisecond.
|
|
3954
|
+
// #2807: the patch now stamps business time (mergePatch.updated) verbatim;
|
|
3955
|
+
// monotonicity lives in the sidecar token, minted by storage's write
|
|
3956
|
+
// chokepoint — never in `frontmatter.updated`. C's token lands past every
|
|
3957
|
+
// prior receipt, A classifies the standing record as superseded, and C's
|
|
3958
|
+
// commit survives A's failure.
|
|
3959
|
+
const T = new Date(Date.now() + 60_000);
|
|
3960
|
+
const h = await harness({
|
|
3961
|
+
targetUpdated: T.toISOString(),
|
|
3962
|
+
applyFrontmatterPatches: true,
|
|
3963
|
+
});
|
|
3964
|
+
const realPatch = h.storage.writeMemoryFrontmatterIfUnchanged.bind(h.storage);
|
|
3965
|
+
let patchCalls = 0;
|
|
3966
|
+
let releaseC!: () => void;
|
|
3967
|
+
const cGate = new Promise<void>((resolve) => {
|
|
3968
|
+
releaseC = resolve;
|
|
3969
|
+
});
|
|
3970
|
+
let cArrived!: () => void;
|
|
3971
|
+
const cArrivedGate = new Promise<void>((resolve) => {
|
|
3972
|
+
cArrived = resolve;
|
|
3973
|
+
});
|
|
3974
|
+
let cMerge: Promise<{ action: string }> | undefined;
|
|
3975
|
+
h.storage.writeMemoryFrontmatterIfUnchanged = (async (
|
|
3976
|
+
expected: MemoryFile,
|
|
3977
|
+
patch: Partial<MemoryFrontmatter>,
|
|
3978
|
+
options?: { actor?: string },
|
|
3979
|
+
) => {
|
|
3980
|
+
if (options?.actor !== "semantic-merge") {
|
|
3981
|
+
return await realPatch(expected, patch, options);
|
|
3982
|
+
}
|
|
3983
|
+
patchCalls += 1;
|
|
3984
|
+
if (patchCalls === 1) {
|
|
3985
|
+
// A's patch: B commits fully (CAS + patch) while A's post-commit work
|
|
3986
|
+
// is failing; C commits its CAS and suspends INSIDE its own patch —
|
|
3987
|
+
// exactly the finding's window, where C's commit stands at the reused
|
|
3988
|
+
// receipt and its patch has not landed.
|
|
3989
|
+
const bOutcome = await applySemanticMergeAtPersist(h.deps, {
|
|
3990
|
+
storage: h.storage,
|
|
3991
|
+
content: INCOMING,
|
|
3992
|
+
category: "fact",
|
|
3993
|
+
judgeCall: (options) => acceptingJudge(options),
|
|
3994
|
+
now: () => T,
|
|
3995
|
+
});
|
|
3996
|
+
assert.equal(bOutcome.action, "merged", "B's merge commits fully");
|
|
3997
|
+
cMerge = applySemanticMergeAtPersist(h.deps, {
|
|
3998
|
+
storage: h.storage,
|
|
3999
|
+
content: INCOMING,
|
|
4000
|
+
category: "fact",
|
|
4001
|
+
judgeCall: (options) => acceptingJudge(options),
|
|
4002
|
+
now: () => T,
|
|
4003
|
+
});
|
|
4004
|
+
await cArrivedGate;
|
|
4005
|
+
return false; // A's patch is rejected — A enters its post-commit failure path
|
|
4006
|
+
}
|
|
4007
|
+
if (patchCalls === 3) {
|
|
4008
|
+
// C's patch: suspended until A's rollback has compared the standing
|
|
4009
|
+
// record, so A's classification runs against C's bare CAS commit.
|
|
4010
|
+
cArrived();
|
|
4011
|
+
await cGate;
|
|
4012
|
+
}
|
|
4013
|
+
return await realPatch(expected, patch, options);
|
|
4014
|
+
}) as StorageManager["writeMemoryFrontmatterIfUnchanged"];
|
|
4015
|
+
|
|
4016
|
+
const aOutcome = await applySemanticMergeAtPersist(h.deps, {
|
|
4017
|
+
storage: h.storage,
|
|
4018
|
+
content: INCOMING,
|
|
4019
|
+
category: "fact",
|
|
4020
|
+
judgeCall: (options) => acceptingJudge(options),
|
|
4021
|
+
now: () => T,
|
|
4022
|
+
});
|
|
4023
|
+
releaseC();
|
|
4024
|
+
const cOutcome = await cMerge!;
|
|
4025
|
+
|
|
4026
|
+
assert.deepEqual(aOutcome, {
|
|
4027
|
+
action: "merged",
|
|
4028
|
+
targetId: "fact-target",
|
|
4029
|
+
mergedContent: MERGED,
|
|
4030
|
+
provenancePatched: false,
|
|
4031
|
+
});
|
|
4032
|
+
assert.deepEqual(cOutcome, { action: "merged", targetId: "fact-target", mergedContent: MERGED, provenancePatched: true });
|
|
4033
|
+
const body = await h.storage.getMemoryByIdIncludingArchived("fact-target");
|
|
4034
|
+
assert.equal(
|
|
4035
|
+
body?.content,
|
|
4036
|
+
MERGED,
|
|
4037
|
+
"C's commit stands — A's rollback must not restore the pre-merge body over it",
|
|
4038
|
+
);
|
|
4039
|
+
assert.equal(
|
|
4040
|
+
body?.frontmatter.updated,
|
|
4041
|
+
T.toISOString(),
|
|
4042
|
+
"#2807: the metadata patch stamps business time (mergePatch.updated) verbatim — never a revision",
|
|
4043
|
+
);
|
|
4044
|
+
const standingToken = await h.storage.readCasRevision(h.target.path);
|
|
4045
|
+
const [aReceipt, bReceipt, cReceipt2] = h.calls.commitRevisions;
|
|
4046
|
+
assert.ok(aReceipt && bReceipt && cReceipt2);
|
|
4047
|
+
assert.ok(aReceipt < bReceipt && bReceipt < cReceipt2, "A, B, C receipts are unique and strictly increasing");
|
|
4048
|
+
assert.ok(
|
|
4049
|
+
standingToken !== undefined && standingToken > cReceipt2,
|
|
4050
|
+
"the standing token advanced past every issued CAS receipt through the metadata patches",
|
|
4051
|
+
);
|
|
4052
|
+
assert.notEqual(standingToken, aReceipt, "A's retired receipt no longer matches the standing token");
|
|
4053
|
+
assert.deepEqual(
|
|
4054
|
+
h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
|
|
4055
|
+
[
|
|
4056
|
+
{ content: MERGED, actor: "semantic-merge" },
|
|
4057
|
+
{ content: MERGED, actor: "semantic-merge" },
|
|
4058
|
+
{ content: MERGED, actor: "semantic-merge" },
|
|
4059
|
+
],
|
|
4060
|
+
"exactly the three CAS commits — no semantic-merge-rollback write ever fires",
|
|
4061
|
+
);
|
|
4062
|
+
});
|
|
4063
|
+
|
|
4064
|
+
test("runMergedTargetPostEffects: a rolled-back edge rewrite invalidates the graph edge cache (#2807)", async () => {
|
|
4065
|
+
// The warm-cache hole: the target had no prior generated rows (the
|
|
4066
|
+
// removal is a disk no-op, so the cache baseline survives), the build's
|
|
4067
|
+
// onMemoryWritten incrementally pushes the appended rows into
|
|
4068
|
+
// GraphIndex.edgeCache, and a writer that advanced the target past the
|
|
4069
|
+
// revision check triggers the rollback — which repairs only the JSONL
|
|
4070
|
+
// files. Without invalidating the owning index, spreadingActivation kept
|
|
4071
|
+
// serving the rolled-back edges for the full five-minute TTL.
|
|
4072
|
+
const h = await postEffectsHarness();
|
|
4073
|
+
const OTHER = "facts/2026-08-19/other.md";
|
|
4074
|
+
const UNRELATED_FROM = "facts/2026-08-18/unrelated-a.md";
|
|
4075
|
+
const UNRELATED_TO = "facts/2026-08-18/unrelated-b.md";
|
|
4076
|
+
const unrelated: GraphEdge = {
|
|
4077
|
+
from: UNRELATED_FROM, to: UNRELATED_TO, type: "entity", weight: 1,
|
|
4078
|
+
label: "entity-unrelated", ts: "2026-08-18T00:00:00.000Z",
|
|
4079
|
+
};
|
|
4080
|
+
await seedGraphFile(h.dir, "entity", [unrelated]);
|
|
4081
|
+
const NEWER_BODY = "Billing service deploys run on Tuesdays at 09:00 UTC, paging the on-call engineer.";
|
|
4082
|
+
const targetPath = path.join(h.dir, h.targetRelPath);
|
|
4083
|
+
let buildStarted = false;
|
|
4084
|
+
const storage = {
|
|
4085
|
+
dir: h.dir,
|
|
4086
|
+
getMemoryByIdIncludingArchived: async (id: string) =>
|
|
4087
|
+
id === "fact-target"
|
|
4088
|
+
? {
|
|
4089
|
+
path: targetPath,
|
|
4090
|
+
frontmatter: {
|
|
4091
|
+
id,
|
|
4092
|
+
category: "fact",
|
|
4093
|
+
entityRef: "entity-billing-service",
|
|
4094
|
+
...(buildStarted ? { updated: "2026-08-22T01:00:00.000Z" } : {}),
|
|
4095
|
+
},
|
|
4096
|
+
content: buildStarted ? NEWER_BODY : MERGED,
|
|
4097
|
+
}
|
|
4098
|
+
: null,
|
|
4099
|
+
} as unknown as StorageManager;
|
|
4100
|
+
const graphConfig = parseConfig({ memoryDir: h.dir, multiGraphMemoryEnabled: true });
|
|
4101
|
+
const graphIndex = new GraphIndex(h.dir, graphConfig);
|
|
4102
|
+
const coordinator = new PersistenceIndexCoordinator({
|
|
4103
|
+
config: graphConfig,
|
|
4104
|
+
graphIndexFor: () => graphIndex,
|
|
4105
|
+
} as unknown as ConstructorParameters<typeof PersistenceIndexCoordinator>[0]);
|
|
4106
|
+
// Warm the cache from the seeded file BEFORE the rewrite runs.
|
|
4107
|
+
await graphIndex.spreadingActivation([UNRELATED_FROM]);
|
|
4108
|
+
const realBuild = coordinator.buildGraphEdge.bind(coordinator);
|
|
4109
|
+
const sibling = {
|
|
4110
|
+
path: path.join(h.dir, OTHER),
|
|
4111
|
+
frontmatter: { id: "mem-sibling", category: "fact", entityRef: "entity-billing-service" },
|
|
4112
|
+
content: "Sibling fact sharing the billing entity.",
|
|
4113
|
+
} as unknown as MemoryFile;
|
|
4114
|
+
const deps = {
|
|
4115
|
+
...h.deps,
|
|
4116
|
+
buildGraphEdge: async (...args: Parameters<typeof realBuild>) => {
|
|
4117
|
+
buildStarted = true;
|
|
4118
|
+
return realBuild(...args);
|
|
4119
|
+
},
|
|
4120
|
+
invalidateGraphEdgeCache: () => graphIndex.invalidateEdgeCache(),
|
|
4121
|
+
} as unknown as ExtractionPersistDeps;
|
|
4122
|
+
await runMergedTargetPostEffects(
|
|
4123
|
+
deps,
|
|
4124
|
+
storage,
|
|
4125
|
+
{ targetId: "fact-target", mergedContent: MERGED },
|
|
4126
|
+
{
|
|
4127
|
+
category: "fact",
|
|
4128
|
+
incomingContent: INCOMING,
|
|
4129
|
+
incomingConfidence: 0.9,
|
|
4130
|
+
namespace: "default",
|
|
4131
|
+
graphCaps: { entityGraph: true, timeGraph: false, causalGraph: false, multiGraphMemory: true, graphWriteSessionAdjacency: false },
|
|
4132
|
+
graphContext: { allMemsForGraph: [sibling], memoryPathById: new Map() },
|
|
4133
|
+
threadIdForEdge: undefined,
|
|
4134
|
+
threadEpisodeIdsForGraph: undefined,
|
|
4135
|
+
},
|
|
4136
|
+
);
|
|
4137
|
+
assert.deepEqual(
|
|
4138
|
+
await readGraphFile(h.dir, "entity"),
|
|
4139
|
+
[unrelated],
|
|
4140
|
+
"the superseded rewrite's rows are rolled back out of the entity file",
|
|
4141
|
+
);
|
|
4142
|
+
const served = await graphIndex.spreadingActivation([h.targetRelPath]);
|
|
4143
|
+
assert.equal(
|
|
4144
|
+
served.filter((result) => result.path === OTHER).length,
|
|
4145
|
+
0,
|
|
4146
|
+
`the cache must not serve the rolled-back target→sibling edge after the rollback (served: ${JSON.stringify(served)})`,
|
|
4147
|
+
);
|
|
4148
|
+
});
|
|
4149
|
+
|
|
3517
4150
|
test("persistMergedTargetThreadEpisode: a re-merge moves an existing earlier target to the durable thread tail (round N+12 D)", async () => {
|
|
3518
4151
|
const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-merge-thread-"));
|
|
3519
4152
|
try {
|
|
@@ -3540,3 +4173,77 @@ test("persistMergedTargetThreadEpisode: a re-merge moves an existing earlier tar
|
|
|
3540
4173
|
await rm(dir, { recursive: true, force: true });
|
|
3541
4174
|
}
|
|
3542
4175
|
});
|
|
4176
|
+
|
|
4177
|
+
test("applySemanticMergeAtPersist: a transiently unreadable receipt preserves the recovery snapshot instead of discarding it (#2813 P1 B)", async () => {
|
|
4178
|
+
// The P1 B hole: the content CAS COMMITTED, the provenance patch failed,
|
|
4179
|
+
// and the rollback's ownership check hit a sidecar it could not read. The
|
|
4180
|
+
// fail-open read returned undefined, which classified the standing merged
|
|
4181
|
+
// body as superseded and DISCARDED the staged recovery snapshot on
|
|
4182
|
+
// unproven grounds — the degraded state lost its recovery point. The
|
|
4183
|
+
// three-way status keeps every unproven branch keep-side: the rollback
|
|
4184
|
+
// refuses, the snapshot is preserved as the recovery point, and the
|
|
4185
|
+
// outcome stays the degraded merged report.
|
|
4186
|
+
const h = await harness({ frontmatterFails: true, receiptStatus: "unavailable" });
|
|
4187
|
+
const outcome = await applySemanticMergeAtPersist(h.deps, {
|
|
4188
|
+
storage: h.storage,
|
|
4189
|
+
content: INCOMING,
|
|
4190
|
+
category: "fact",
|
|
4191
|
+
judgeCall: (options) => acceptingJudge(options),
|
|
4192
|
+
});
|
|
4193
|
+
assert.deepEqual(outcome, {
|
|
4194
|
+
action: "merged",
|
|
4195
|
+
targetId: "fact-target",
|
|
4196
|
+
mergedContent: MERGED,
|
|
4197
|
+
provenancePatched: false,
|
|
4198
|
+
});
|
|
4199
|
+
assert.deepEqual(
|
|
4200
|
+
h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
|
|
4201
|
+
[{ content: MERGED, actor: "semantic-merge" }],
|
|
4202
|
+
"no semantic-merge-rollback runs while receipt identity is unavailable",
|
|
4203
|
+
);
|
|
4204
|
+
assert.equal(
|
|
4205
|
+
(
|
|
4206
|
+
await listVersions(
|
|
4207
|
+
h.target.path,
|
|
4208
|
+
{ enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
|
|
4209
|
+
h.storage.dir,
|
|
4210
|
+
)
|
|
4211
|
+
).versions.length,
|
|
4212
|
+
1,
|
|
4213
|
+
"the recovery snapshot is preserved — an unreadable receipt never proves supersession",
|
|
4214
|
+
);
|
|
4215
|
+
});
|
|
4216
|
+
|
|
4217
|
+
test("applySemanticMergeAtPersist: an absent receipt while this writer holds a commit receipt is keep-side (#2813 P1 B)", async () => {
|
|
4218
|
+
// Absent-with-receipt-in-hand corroborates NEITHER writer, so it takes
|
|
4219
|
+
// the same keep-side handling as unavailable: never the superseded
|
|
4220
|
+
// branch, never the discard it licenses.
|
|
4221
|
+
const h = await harness({ frontmatterFails: true, receiptStatus: "absent" });
|
|
4222
|
+
const outcome = await applySemanticMergeAtPersist(h.deps, {
|
|
4223
|
+
storage: h.storage,
|
|
4224
|
+
content: INCOMING,
|
|
4225
|
+
category: "fact",
|
|
4226
|
+
judgeCall: (options) => acceptingJudge(options),
|
|
4227
|
+
});
|
|
4228
|
+
assert.deepEqual(outcome, {
|
|
4229
|
+
action: "merged",
|
|
4230
|
+
targetId: "fact-target",
|
|
4231
|
+
mergedContent: MERGED,
|
|
4232
|
+
provenancePatched: false,
|
|
4233
|
+
});
|
|
4234
|
+
assert.deepEqual(
|
|
4235
|
+
h.calls.contentUpdates.map((c) => ({ content: c.content, actor: c.actor })),
|
|
4236
|
+
[{ content: MERGED, actor: "semantic-merge" }],
|
|
4237
|
+
);
|
|
4238
|
+
assert.equal(
|
|
4239
|
+
(
|
|
4240
|
+
await listVersions(
|
|
4241
|
+
h.target.path,
|
|
4242
|
+
{ enabled: true, maxVersionsPerPage: 20, sidecarDir: ".versions" },
|
|
4243
|
+
h.storage.dir,
|
|
4244
|
+
)
|
|
4245
|
+
).versions.length,
|
|
4246
|
+
1,
|
|
4247
|
+
"the recovery snapshot is preserved when the sidecar corroborates neither writer",
|
|
4248
|
+
);
|
|
4249
|
+
});
|