@remnic/core 9.65.1 → 9.65.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-admin-ops-surface.d.ts +44 -44
- package/dist/access-admin-ops-surface.js +36 -35
- package/dist/access-authorization-probe.d.ts +39 -40
- package/dist/access-authorization-probe.js +37 -36
- package/dist/access-boundary.d.ts +41 -185
- package/dist/access-boundary.js +36 -35
- package/dist/access-cli.js +110 -107
- package/dist/access-cli.js.map +1 -1
- package/dist/access-coding-context-resolution.d.ts +3 -1
- package/dist/access-extraction-force-flush.d.ts +25 -25
- package/dist/access-extraction-force-flush.js +36 -35
- package/dist/access-health-types.d.ts +3 -1
- package/dist/access-http-lcm-compaction.d.ts +39 -39
- package/dist/access-http-lifecycle-flush.d.ts +40 -41
- package/dist/access-http-offline-stream.d.ts +25 -25
- package/dist/access-http-query.d.ts +4 -2
- package/dist/access-http-query.js +38 -37
- package/dist/access-http.d.ts +51 -44
- package/dist/access-http.js +57 -56
- package/dist/access-identity-continuity-surface.d.ts +12 -12
- package/dist/access-identity-continuity-surface.js +36 -35
- package/dist/access-lcm-surface.d.ts +27 -27
- package/dist/access-lcm-surface.js +36 -35
- package/dist/access-mcp-admin-tools.d.ts +9 -1
- package/dist/access-mcp-admin-tools.js +3 -1
- package/dist/access-mcp-output-schemas.js +1 -1
- package/dist/access-mcp.d.ts +39 -39
- package/dist/access-mcp.js +50 -47
- package/dist/access-memory-search-fanout.d.ts +4 -2
- package/dist/{access-namespace-preflight-BKUnKsBv.d.ts → access-namespace-preflight-B7Usyz-K.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +5 -3
- package/dist/access-namespace-preflight.js +36 -35
- package/dist/access-observe-write-surface.d.ts +39 -39
- package/dist/access-observe-write-surface.js +36 -35
- package/dist/access-offline-manifest.d.ts +12 -12
- package/dist/access-offline-manifest.js +5 -5
- package/dist/access-operations-batch.js +41 -40
- package/dist/access-operations.d.ts +46 -47
- package/dist/access-operations.js +44 -43
- package/dist/access-recall-concurrency.d.ts +40 -40
- package/dist/access-recall-concurrency.js +36 -35
- package/dist/access-recall-response.d.ts +24 -24
- package/dist/access-recall-response.js +36 -35
- package/dist/access-recall-surface.d.ts +24 -24
- package/dist/access-recall-surface.js +36 -35
- package/dist/access-schema.d.ts +139 -139
- package/dist/access-schema.js +3 -3
- package/dist/{access-service-B1Lbb-nQ.d.ts → access-service-DkaIG3n8.d.ts} +688 -140
- package/dist/access-service-helpers.d.ts +40 -40
- package/dist/access-service.d.ts +47 -47
- package/dist/access-service.js +36 -35
- package/dist/access-surface-catalog.d.ts +41 -42
- package/dist/access-surface-catalog.js +44 -37
- 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-recall.d.ts +3 -1
- package/dist/active-recall.js +11 -1
- package/dist/active-recall.js.map +1 -1
- package/dist/adapters/index.js +4 -4
- 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-5L7EUZ27.js → auto-sync-H64ZCNIR.js} +13 -5
- package/dist/{auto-sync-5L7EUZ27.js.map → auto-sync-H64ZCNIR.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 -12
- package/dist/briefing-window.d.ts +4 -2
- package/dist/briefing.d.ts +4 -2
- package/dist/briefing.js +16 -15
- 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 +4 -4
- package/dist/bulk-import/index.d.ts +5 -3
- package/dist/calibration.d.ts +3 -1
- package/dist/calibration.js +1 -1
- package/dist/capabilities.d.ts +3 -1
- package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
- package/dist/{catalog-DjVhJoRM.d.ts → catalog-CX2BZEJh.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +3 -1
- package/dist/causal-consolidation.js +20 -19
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-MIBKEW7A.js → chunk-2VXWFYJE.js} +3 -3
- package/dist/{chunk-3YTTAGPB.js → chunk-3DVBKTSO.js} +2 -2
- package/dist/{chunk-EIR5VLIH.js → chunk-4K7IW3F7.js} +2 -2
- package/dist/chunk-4K7IW3F7.js.map +1 -0
- package/dist/{chunk-JTSVMJHV.js → chunk-4XDGYCZI.js} +3 -3
- package/dist/chunk-573TEZCD.js +88 -0
- package/dist/chunk-573TEZCD.js.map +1 -0
- package/dist/{chunk-HQSBYI5X.js → chunk-57HVIG5U.js} +2 -2
- package/dist/{chunk-PMVPCZJZ.js → chunk-6433HV72.js} +2 -2
- package/dist/{chunk-N6TRHP72.js → chunk-6TAX66IA.js} +2 -2
- package/dist/{chunk-AGKIG3YA.js → chunk-6VALIZKG.js} +2 -2
- package/dist/{chunk-YQ3CBLL4.js → chunk-76PL4XLG.js} +512 -8
- package/dist/chunk-76PL4XLG.js.map +1 -0
- package/dist/{chunk-4NZHHGVL.js → chunk-7BDZTALN.js} +4 -1
- package/dist/chunk-7BDZTALN.js.map +1 -0
- package/dist/{chunk-NS5ETDYD.js → chunk-7BEPVIH3.js} +3 -3
- package/dist/{chunk-JG22O53B.js → chunk-7CBKAQIG.js} +2 -1
- package/dist/chunk-7CBKAQIG.js.map +1 -0
- package/dist/{chunk-LYIZXQYY.js → chunk-7KFIMGMP.js} +2 -2
- package/dist/{chunk-LWVO2QZV.js → chunk-7QOO4LGC.js} +56 -56
- package/dist/chunk-AAXJNINV.js +55 -0
- package/dist/chunk-AAXJNINV.js.map +1 -0
- package/dist/{chunk-56BSXSHC.js → chunk-AB3A7EFH.js} +31 -2
- package/dist/{chunk-56BSXSHC.js.map → chunk-AB3A7EFH.js.map} +1 -1
- package/dist/{chunk-CCTVAVTT.js → chunk-AUO2LJ3K.js} +2 -2
- package/dist/{chunk-ALCJRQ72.js → chunk-AYDDB3XI.js} +2 -2
- package/dist/{chunk-3TMYV3LP.js → chunk-AYYGRVRP.js} +5 -5
- package/dist/{chunk-W6TSGWYS.js → chunk-AZAA5DNP.js} +2 -2
- package/dist/{chunk-WTOE7CW4.js → chunk-BKYPJUQL.js} +122 -16
- package/dist/chunk-BKYPJUQL.js.map +1 -0
- package/dist/{chunk-6JJT5AKI.js → chunk-BQUEAVNW.js} +2 -2
- package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
- package/dist/{chunk-CEH2AFXG.js → chunk-C24UZSFW.js} +6 -6
- package/dist/{chunk-ZPN7W3OP.js → chunk-CDUUDBWJ.js} +3 -3
- package/dist/{chunk-35NN3ZFA.js → chunk-CTVWELNK.js} +21 -3
- package/dist/chunk-CTVWELNK.js.map +1 -0
- package/dist/{chunk-Y23B2QXP.js → chunk-D27J626P.js} +2 -2
- package/dist/{chunk-2572MRP2.js → chunk-DHTQP334.js} +2 -2
- package/dist/{chunk-HJQZQUPC.js → chunk-DJZWNKFO.js} +5 -5
- package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
- package/dist/{chunk-VJ6ECBIP.js → chunk-E4MVQQVX.js} +2 -2
- package/dist/{chunk-SYJ6EKKE.js → chunk-EIVIB73I.js} +2 -2
- package/dist/{chunk-HUNSEO5U.js → chunk-EV3YFLCB.js} +2 -2
- package/dist/{chunk-GEULB2VI.js → chunk-FC7TIRFS.js} +21 -1
- package/dist/chunk-FC7TIRFS.js.map +1 -0
- package/dist/{chunk-VPGRXEAB.js → chunk-G57LQRP6.js} +2 -2
- package/dist/{chunk-BC4QD3FM.js → chunk-GN55KU2P.js} +2 -2
- package/dist/{chunk-4W6INNXO.js → chunk-GUXS322H.js} +2 -2
- package/dist/{chunk-DBXZZIDU.js → chunk-H5FW4S5Q.js} +434 -693
- package/dist/chunk-H5FW4S5Q.js.map +1 -0
- package/dist/chunk-I32NKXE2.js +879 -0
- package/dist/chunk-I32NKXE2.js.map +1 -0
- package/dist/{chunk-3MADV4YC.js → chunk-IQSC3V2E.js} +2 -2
- package/dist/{chunk-UYCIS6V5.js → chunk-JCWY73FK.js} +2 -2
- package/dist/{chunk-T42L3S6A.js → chunk-LBWQ65SX.js} +4 -4
- package/dist/{chunk-MSTNSVXI.js → chunk-LDBFXD4F.js} +2 -1
- package/dist/chunk-LDBFXD4F.js.map +1 -0
- package/dist/{chunk-CEQF6L5K.js → chunk-LUNJ3WFO.js} +9 -7
- package/dist/chunk-LUNJ3WFO.js.map +1 -0
- package/dist/{chunk-256FBCVX.js → chunk-M4AHBM72.js} +7 -7
- package/dist/{chunk-YEQEGSJA.js → chunk-MBDJJTAT.js} +3 -3
- package/dist/{chunk-IAY7YBXS.js → chunk-MRTUN665.js} +2 -2
- package/dist/{chunk-JFJ3MHGV.js → chunk-NXKJHSDN.js} +1 -1
- package/dist/chunk-NXKJHSDN.js.map +1 -0
- package/dist/{chunk-R3AAOKR2.js → chunk-NZWEEALH.js} +2 -2
- package/dist/{chunk-I2HTKOOP.js → chunk-ODZG724P.js} +2 -2
- package/dist/{chunk-7QFBLYFP.js → chunk-OJD4WS2E.js} +3 -3
- package/dist/{chunk-CUS6S7PN.js → chunk-OLWTCWQ2.js} +9 -9
- package/dist/chunk-OLWTCWQ2.js.map +1 -0
- package/dist/{chunk-53ENM6F6.js → chunk-P4DHENRE.js} +2 -2
- package/dist/{chunk-DEFI2QBT.js → chunk-PAYGC3BD.js} +52 -22
- package/dist/chunk-PAYGC3BD.js.map +1 -0
- package/dist/{chunk-KPBLJCCV.js → chunk-PDVQ5JU3.js} +2 -2
- package/dist/{chunk-7BY7V4YX.js → chunk-Q4WONDMJ.js} +4 -3
- package/dist/{chunk-7BY7V4YX.js.map → chunk-Q4WONDMJ.js.map} +1 -1
- package/dist/{chunk-ESCQ6LY7.js → chunk-QFMO32TO.js} +3 -3
- package/dist/{chunk-HQSPXTQO.js → chunk-QXIQPCCN.js} +1 -1
- package/dist/{chunk-CFRBTATE.js → chunk-R47WINCY.js} +3 -3
- package/dist/{chunk-G72IPMR7.js → chunk-R4OCGPSH.js} +2 -2
- package/dist/{chunk-LCU5R6TQ.js → chunk-RAIUTAZZ.js} +22 -3
- package/dist/chunk-RAIUTAZZ.js.map +1 -0
- package/dist/chunk-RIAM7DND.js +167 -0
- package/dist/chunk-RIAM7DND.js.map +1 -0
- package/dist/{chunk-VZVP2W4O.js → chunk-RK4WXUI2.js} +2 -2
- package/dist/{chunk-JBPKEARU.js → chunk-RKNJBZ55.js} +4 -4
- package/dist/{chunk-6L27N6YI.js → chunk-S7Q5CM7E.js} +2 -2
- package/dist/{chunk-CTQRPANJ.js → chunk-SVSRPG6M.js} +2 -2
- package/dist/{chunk-GXWDWOWP.js → chunk-TDKSCV62.js} +2 -2
- package/dist/{chunk-S2VBSTTA.js → chunk-THG4GYIE.js} +2 -2
- package/dist/{chunk-IXRC7EQG.js → chunk-TR7DGXGI.js} +2 -2
- package/dist/{chunk-63FHSH7E.js → chunk-TYUS5TLG.js} +4 -4
- package/dist/{chunk-7PWWGYGO.js → chunk-URHCUXKI.js} +2 -2
- package/dist/{chunk-Z54TXZ2F.js → chunk-VA5KMSAE.js} +16 -7
- package/dist/chunk-VA5KMSAE.js.map +1 -0
- package/dist/{chunk-KQAFEZQX.js → chunk-VDX2J7OX.js} +2 -2
- package/dist/{chunk-MUJ4QFUQ.js → chunk-W4BMEGQA.js} +4 -4
- package/dist/{chunk-5HK3CJAR.js → chunk-W675UJCZ.js} +2 -2
- package/dist/{chunk-3PXVYJMC.js → chunk-WN5FSGLE.js} +2077 -215
- package/dist/chunk-WN5FSGLE.js.map +1 -0
- package/dist/{chunk-3RHFGGI5.js → chunk-YF6UHWOV.js} +30 -10
- package/dist/chunk-YF6UHWOV.js.map +1 -0
- package/dist/{chunk-X5SDZMO7.js → chunk-YHCBJULX.js} +2 -2
- package/dist/{chunk-5UYSCYR7.js → chunk-Z4RPXHJH.js} +4 -4
- package/dist/{cli-Pulnz-qm.d.ts → cli-ChKeYMZv.d.ts} +5 -5
- package/dist/cli.d.ts +25 -25
- package/dist/cli.js +81 -78
- package/dist/coding/pre-action-gate.d.ts +2 -60
- package/dist/compounding/engine.d.ts +4 -2
- package/dist/compounding/engine.js +17 -16
- 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 +11 -1
- package/dist/connectors/codex-materialize-runner.d.ts +3 -1
- package/dist/connectors/codex-materialize-runner.js +16 -15
- package/dist/connectors/codex-materialize.d.ts +3 -1
- package/dist/connectors/index.d.ts +3 -1
- package/dist/connectors/index.js +16 -15
- package/dist/consolidation-provenance-check.d.ts +4 -2
- package/dist/consolidation-undo.d.ts +4 -2
- package/dist/contradiction/index.d.ts +10 -270
- package/dist/contradiction/index.js +20 -7
- package/dist/{contradiction-review-QKJH5DKD.js → contradiction-review-WRVLRWHS.js} +6 -2
- package/dist/{contradiction-scan-VOTQRRSX.js → contradiction-scan-AKUWPX5N.js} +5 -3
- package/dist/converge-config.d.ts +3 -1
- package/dist/convergence-refresh.d.ts +4 -2
- package/dist/convergence-refresh.js +18 -17
- package/dist/conversation-index/backend.d.ts +3 -1
- package/dist/conversation-index/chunker.d.ts +3 -1
- package/dist/conversation-index/faiss-adapter.d.ts +3 -1
- 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 +18 -17
- package/dist/cross-lingual-recall.d.ts +3 -1
- package/dist/day-summary.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-Co17gxYb.d.ts → dependency-propagation-delivery-B8ZMBBCY.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 +16 -15
- package/dist/entity-schema.d.ts +3 -1
- package/dist/episodic-context.d.ts +3 -1
- package/dist/explicit-capture.d.ts +12 -12
- package/dist/explicit-capture.js +7 -6
- package/dist/external-wiki-access.d.ts +41 -42
- package/dist/external-wiki-access.js +37 -36
- 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 +40 -40
- package/dist/extraction-error-classification.d.ts +3 -1
- package/dist/extraction-faithfulness.d.ts +3 -1
- 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 +2 -2
- package/dist/extraction-liveness.d.ts +3 -1
- package/dist/extraction-normalization.d.ts +3 -1
- package/dist/extraction-normalization.js +2 -2
- package/dist/extraction-prompt.d.ts +4 -2
- package/dist/extraction-prompt.js +1 -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 +22 -21
- package/dist/fallback-llm.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-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 +1 -1
- package/dist/importance.d.ts +3 -1
- package/dist/importers/index.d.ts +3 -1
- package/dist/in-flight-reads.d.ts +3 -1
- package/dist/index-CexDrJzC.d.ts +284 -0
- package/dist/index.d.ts +946 -707
- package/dist/index.js +253 -151
- package/dist/intent.d.ts +3 -1
- package/dist/lcm/engine.d.ts +3 -1
- package/dist/lcm/engine.js +3 -3
- package/dist/lcm/index.d.ts +3 -1
- package/dist/lcm/index.js +6 -6
- 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.d.ts +3 -1
- package/dist/local-model-endpoint.d.ts +3 -1
- package/dist/maintenance/memory-governance.d.ts +3 -1
- package/dist/maintenance/memory-governance.js +16 -15
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +4 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +16 -15
- package/dist/maintenance/rebuild-memory-projection.d.ts +4 -2
- package/dist/maintenance/rebuild-memory-projection.js +17 -16
- package/dist/{maintenance-DiSLtVN7.d.ts → maintenance-nkdtSrVr.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +37 -37
- package/dist/mcp-read-only-tools.js +1 -1
- package/dist/memory-action-policy.d.ts +3 -1
- package/dist/memory-cache.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 +177 -0
- package/dist/memory-subject-cli.js +16 -0
- package/dist/memory-subject.d.ts +128 -0
- package/dist/memory-subject.js +44 -0
- package/dist/memory-subject.js.map +1 -0
- package/dist/memory-worth-outcomes.d.ts +7 -4
- package/dist/memory-worth-outcomes.js +1 -1
- package/dist/models-json.d.ts +3 -1
- package/dist/namespaces/migrate.d.ts +5 -3
- package/dist/namespaces/migrate.js +17 -16
- package/dist/namespaces/principal.d.ts +3 -1
- package/dist/namespaces/search.d.ts +3 -1
- package/dist/namespaces/search.js +6 -6
- package/dist/namespaces/storage.d.ts +5 -3
- package/dist/namespaces/storage.js +16 -15
- package/dist/native-knowledge.d.ts +3 -1
- package/dist/offline-sync-impression-drain.d.ts +3 -1
- package/dist/operator-doctor-corpus.d.ts +3 -1
- package/dist/operator-doctor-corpus.js +19 -18
- package/dist/operator-doctor-replica.d.ts +3 -1
- package/dist/operator-toolkit.d.ts +5 -3
- package/dist/operator-toolkit.js +29 -24
- package/dist/orchestration/compression-guideline-coordinator.d.ts +4 -2
- package/dist/orchestration/maintenance.d.ts +6 -4
- package/dist/orchestration/maintenance.js +22 -21
- package/dist/{orchestrator-DzCaxNS4.d.ts → orchestrator-Bvq1-RQs.d.ts} +23 -9
- package/dist/orchestrator.d.ts +12 -12
- package/dist/orchestrator.js +111 -108
- package/dist/patterns-cli.d.ts +3 -1
- package/dist/{pipeline-HJ8DKbFl.d.ts → pipeline-C8vfIiTX.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-DwXauTX3.d.ts → public-http-Cy0aYbys.d.ts} +1 -1
- package/dist/{qmd-BzxluoLt.d.ts → qmd-B9p1SZTZ.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 +4 -4
- 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-planner-llm.d.ts +3 -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 +3 -1
- package/dist/recall-xray.js +2 -2
- package/dist/reconcile/cursor.d.ts +3 -1
- package/dist/reconcile/manifest.d.ts +3 -1
- package/dist/reconcile/manifest.js +3 -3
- 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-4552BNRV.js +36 -0
- package/dist/resolution-4552BNRV.js.map +1 -0
- package/dist/resolve-auth-token.d.ts +3 -1
- package/dist/resume-bundles.js +9 -2
- 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/salvage-envelope.d.ts +3 -1
- package/dist/salvage-envelope.js +10 -2
- package/dist/schemas.d.ts +130 -116
- package/dist/schemas.js +1 -1
- package/dist/{scope-profiles-CEMZz0t5.d.ts → scope-profiles-DLrRxFWR.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 +5 -5
- package/dist/search/index.d.ts +3 -1
- package/dist/search/index.js +9 -9
- 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-TddhF0y7.d.ts → semantic-BalR6EXU.d.ts} +1 -1
- package/dist/{semantic-consolidation-D9dYj6vu.d.ts → semantic-consolidation-DlN6xe20.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +4 -2
- package/dist/semantic-consolidation.js +17 -16
- package/dist/semantic-rule-promotion.js +16 -15
- package/dist/semantic-rule-verifier.d.ts +3 -1
- package/dist/semantic-rule-verifier.js +16 -15
- package/dist/{service-_qgST_0y.d.ts → service-GkYyVfm9.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 +13 -11
- package/dist/signal.d.ts +3 -1
- package/dist/source-agent-qualifier.d.ts +3 -1
- package/dist/source-agent-qualifier.js +18 -17
- package/dist/{storage-B9lbNTYE.d.ts → storage-BIDzuKIn.d.ts} +3 -2
- package/dist/storage.d.ts +4 -2
- package/dist/storage.js +18 -17
- package/dist/subject-config.d.ts +40 -0
- package/dist/subject-config.js +20 -0
- package/dist/subject-config.js.map +1 -0
- package/dist/summarizer.d.ts +3 -1
- package/dist/summary-snapshot.d.ts +3 -1
- package/dist/support-passport/index.d.ts +43 -43
- package/dist/support-passport/index.js +39 -38
- 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/topics.d.ts +3 -1
- package/dist/transcript.d.ts +3 -1
- package/dist/transfer/backup.js +2 -2
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +2 -2
- package/dist/transfer/types.d.ts +86 -86
- package/dist/trust-score-stage.d.ts +3 -1
- package/dist/trust-score.d.ts +3 -1
- package/dist/{types-BrEzuxPA.d.ts → types-BxAcOl5Q.d.ts} +360 -32
- 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 +16 -15
- package/dist/who-knows-cli.d.ts +40 -40
- package/dist/who-knows-cli.js +17 -16
- package/dist/who-knows.d.ts +42 -42
- package/dist/who-knows.js +16 -15
- package/dist/write-envelope.d.ts +7 -2
- package/dist/write-envelope.js +10 -1
- package/package.json +2 -2
- package/scripts/build-with-heap.mjs +1 -1
- package/src/access-boundary.ts +6 -0
- package/src/access-http.ts +6 -5
- package/src/access-mcp-admin-tools.ts +38 -0
- package/src/access-mcp-output-schemas.ts +20 -0
- package/src/access-mcp.ts +8 -8
- package/src/access-operations-batch.ts +13 -0
- package/src/access-service.ts +112 -0
- package/src/access-surface-catalog.test.ts +24 -0
- package/src/access-surface-catalog.ts +6 -0
- package/src/coding/action-gate.test.ts +341 -0
- package/src/coding/action-gate.ts +556 -0
- package/src/config.ts +15 -17
- package/src/contradiction/contradiction-review.ts +50 -4
- package/src/contradiction/contradiction-scan.ts +14 -3
- package/src/contradiction/resolution.ts +50 -2
- package/src/extraction-prompt.ts +1 -0
- package/src/extraction.ts +4 -1
- package/src/index.ts +9 -9
- package/src/mcp-read-only-tools.ts +1 -0
- package/src/memory-subject-cli.ts +135 -0
- package/src/memory-subject.test.ts +48 -0
- package/src/memory-subject.ts +314 -0
- package/src/memory-worth-outcomes.test.ts +6 -2
- package/src/memory-worth-outcomes.ts +11 -7
- package/src/operator-toolkit.ts +1 -1
- package/src/orchestration/extraction-persist.ts +48 -48
- package/src/orchestration/recall-internal.ts +6 -5
- package/src/orchestration/recall-rerank-coordinator.ts +123 -4
- package/src/orchestration/recall-result-formatter.ts +6 -2
- package/src/orchestration/recall-search-pipeline.ts +14 -1
- package/src/preferences/drift-config.ts +118 -0
- package/src/preferences/drift-recall.ts +133 -0
- package/src/preferences/drift-types.ts +87 -0
- package/src/preferences/index.ts +12 -0
- package/src/preferences/preference-drift.test.ts +690 -0
- package/src/preferences/preference-drift.ts +724 -0
- package/src/procedural/library-maintenance.test.ts +582 -0
- package/src/procedural/library-maintenance.ts +546 -0
- package/src/procedural/maintenance-config.ts +78 -0
- package/src/procedural/procedure-recall.ts +29 -1
- package/src/procedural/procedure-stats.ts +20 -0
- package/src/review/review-deck-access.test.ts +325 -0
- package/src/review/review-deck-http-base.ts +133 -0
- package/src/review/review-deck-mutation.test.ts +417 -0
- package/src/review/review-deck-mutation.ts +677 -0
- package/src/review/review-deck-snapshot.ts +196 -0
- package/src/review/review-deck-surface.ts +117 -0
- package/src/review/review-deck.test.ts +347 -0
- package/src/review/review-deck.ts +311 -0
- package/src/schemas.ts +7 -0
- package/src/spaces/index.ts +38 -2
- package/src/storage.ts +10 -8
- package/src/subject-config.ts +80 -0
- package/src/types.ts +33 -32
- package/src/write-envelope.test.ts +14 -0
- package/src/write-envelope.ts +24 -3
- package/dist/chunk-35NN3ZFA.js.map +0 -1
- package/dist/chunk-3PXVYJMC.js.map +0 -1
- package/dist/chunk-3RHFGGI5.js.map +0 -1
- package/dist/chunk-4NZHHGVL.js.map +0 -1
- package/dist/chunk-CEQF6L5K.js.map +0 -1
- package/dist/chunk-CUS6S7PN.js.map +0 -1
- package/dist/chunk-DBXZZIDU.js.map +0 -1
- package/dist/chunk-DEFI2QBT.js.map +0 -1
- package/dist/chunk-EIR5VLIH.js.map +0 -1
- package/dist/chunk-GEULB2VI.js.map +0 -1
- package/dist/chunk-JFJ3MHGV.js.map +0 -1
- package/dist/chunk-JG22O53B.js.map +0 -1
- package/dist/chunk-LCU5R6TQ.js.map +0 -1
- package/dist/chunk-MDVBCPOS.js +0 -402
- package/dist/chunk-MDVBCPOS.js.map +0 -1
- package/dist/chunk-MSTNSVXI.js.map +0 -1
- package/dist/chunk-WTOE7CW4.js.map +0 -1
- package/dist/chunk-YQ3CBLL4.js.map +0 -1
- package/dist/chunk-Z54TXZ2F.js.map +0 -1
- package/dist/resolution-DKMBPXHI.js +0 -18
- /package/dist/{capsule-crypto-7FJQINUR.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
- /package/dist/{chunk-MIBKEW7A.js.map → chunk-2VXWFYJE.js.map} +0 -0
- /package/dist/{chunk-3YTTAGPB.js.map → chunk-3DVBKTSO.js.map} +0 -0
- /package/dist/{chunk-JTSVMJHV.js.map → chunk-4XDGYCZI.js.map} +0 -0
- /package/dist/{chunk-HQSBYI5X.js.map → chunk-57HVIG5U.js.map} +0 -0
- /package/dist/{chunk-PMVPCZJZ.js.map → chunk-6433HV72.js.map} +0 -0
- /package/dist/{chunk-N6TRHP72.js.map → chunk-6TAX66IA.js.map} +0 -0
- /package/dist/{chunk-AGKIG3YA.js.map → chunk-6VALIZKG.js.map} +0 -0
- /package/dist/{chunk-NS5ETDYD.js.map → chunk-7BEPVIH3.js.map} +0 -0
- /package/dist/{chunk-LYIZXQYY.js.map → chunk-7KFIMGMP.js.map} +0 -0
- /package/dist/{chunk-LWVO2QZV.js.map → chunk-7QOO4LGC.js.map} +0 -0
- /package/dist/{chunk-CCTVAVTT.js.map → chunk-AUO2LJ3K.js.map} +0 -0
- /package/dist/{chunk-ALCJRQ72.js.map → chunk-AYDDB3XI.js.map} +0 -0
- /package/dist/{chunk-3TMYV3LP.js.map → chunk-AYYGRVRP.js.map} +0 -0
- /package/dist/{chunk-W6TSGWYS.js.map → chunk-AZAA5DNP.js.map} +0 -0
- /package/dist/{chunk-6JJT5AKI.js.map → chunk-BQUEAVNW.js.map} +0 -0
- /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
- /package/dist/{chunk-CEH2AFXG.js.map → chunk-C24UZSFW.js.map} +0 -0
- /package/dist/{chunk-ZPN7W3OP.js.map → chunk-CDUUDBWJ.js.map} +0 -0
- /package/dist/{chunk-Y23B2QXP.js.map → chunk-D27J626P.js.map} +0 -0
- /package/dist/{chunk-2572MRP2.js.map → chunk-DHTQP334.js.map} +0 -0
- /package/dist/{chunk-HJQZQUPC.js.map → chunk-DJZWNKFO.js.map} +0 -0
- /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
- /package/dist/{chunk-VJ6ECBIP.js.map → chunk-E4MVQQVX.js.map} +0 -0
- /package/dist/{chunk-SYJ6EKKE.js.map → chunk-EIVIB73I.js.map} +0 -0
- /package/dist/{chunk-HUNSEO5U.js.map → chunk-EV3YFLCB.js.map} +0 -0
- /package/dist/{chunk-VPGRXEAB.js.map → chunk-G57LQRP6.js.map} +0 -0
- /package/dist/{chunk-BC4QD3FM.js.map → chunk-GN55KU2P.js.map} +0 -0
- /package/dist/{chunk-4W6INNXO.js.map → chunk-GUXS322H.js.map} +0 -0
- /package/dist/{chunk-3MADV4YC.js.map → chunk-IQSC3V2E.js.map} +0 -0
- /package/dist/{chunk-UYCIS6V5.js.map → chunk-JCWY73FK.js.map} +0 -0
- /package/dist/{chunk-T42L3S6A.js.map → chunk-LBWQ65SX.js.map} +0 -0
- /package/dist/{chunk-256FBCVX.js.map → chunk-M4AHBM72.js.map} +0 -0
- /package/dist/{chunk-YEQEGSJA.js.map → chunk-MBDJJTAT.js.map} +0 -0
- /package/dist/{chunk-IAY7YBXS.js.map → chunk-MRTUN665.js.map} +0 -0
- /package/dist/{chunk-R3AAOKR2.js.map → chunk-NZWEEALH.js.map} +0 -0
- /package/dist/{chunk-I2HTKOOP.js.map → chunk-ODZG724P.js.map} +0 -0
- /package/dist/{chunk-7QFBLYFP.js.map → chunk-OJD4WS2E.js.map} +0 -0
- /package/dist/{chunk-53ENM6F6.js.map → chunk-P4DHENRE.js.map} +0 -0
- /package/dist/{chunk-KPBLJCCV.js.map → chunk-PDVQ5JU3.js.map} +0 -0
- /package/dist/{chunk-ESCQ6LY7.js.map → chunk-QFMO32TO.js.map} +0 -0
- /package/dist/{chunk-HQSPXTQO.js.map → chunk-QXIQPCCN.js.map} +0 -0
- /package/dist/{chunk-CFRBTATE.js.map → chunk-R47WINCY.js.map} +0 -0
- /package/dist/{chunk-G72IPMR7.js.map → chunk-R4OCGPSH.js.map} +0 -0
- /package/dist/{chunk-VZVP2W4O.js.map → chunk-RK4WXUI2.js.map} +0 -0
- /package/dist/{chunk-JBPKEARU.js.map → chunk-RKNJBZ55.js.map} +0 -0
- /package/dist/{chunk-6L27N6YI.js.map → chunk-S7Q5CM7E.js.map} +0 -0
- /package/dist/{chunk-CTQRPANJ.js.map → chunk-SVSRPG6M.js.map} +0 -0
- /package/dist/{chunk-GXWDWOWP.js.map → chunk-TDKSCV62.js.map} +0 -0
- /package/dist/{chunk-S2VBSTTA.js.map → chunk-THG4GYIE.js.map} +0 -0
- /package/dist/{chunk-IXRC7EQG.js.map → chunk-TR7DGXGI.js.map} +0 -0
- /package/dist/{chunk-63FHSH7E.js.map → chunk-TYUS5TLG.js.map} +0 -0
- /package/dist/{chunk-7PWWGYGO.js.map → chunk-URHCUXKI.js.map} +0 -0
- /package/dist/{chunk-KQAFEZQX.js.map → chunk-VDX2J7OX.js.map} +0 -0
- /package/dist/{chunk-MUJ4QFUQ.js.map → chunk-W4BMEGQA.js.map} +0 -0
- /package/dist/{chunk-5HK3CJAR.js.map → chunk-W675UJCZ.js.map} +0 -0
- /package/dist/{chunk-X5SDZMO7.js.map → chunk-YHCBJULX.js.map} +0 -0
- /package/dist/{chunk-5UYSCYR7.js.map → chunk-Z4RPXHJH.js.map} +0 -0
- /package/dist/{contradiction-review-QKJH5DKD.js.map → contradiction-review-WRVLRWHS.js.map} +0 -0
- /package/dist/{contradiction-scan-VOTQRRSX.js.map → contradiction-scan-AKUWPX5N.js.map} +0 -0
- /package/dist/{resolution-DKMBPXHI.js.map → memory-subject-cli.js.map} +0 -0
|
@@ -8,20 +8,20 @@ import {
|
|
|
8
8
|
} from "./chunk-GDB4J2H3.js";
|
|
9
9
|
import {
|
|
10
10
|
importCapsule
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-6433HV72.js";
|
|
12
12
|
import {
|
|
13
13
|
buildCodingGraphInstallHint,
|
|
14
14
|
tryLoadCodingGraphModule
|
|
15
15
|
} from "./chunk-VQ7B2Q6M.js";
|
|
16
|
-
import {
|
|
17
|
-
WriteQuarantineStore
|
|
18
|
-
} from "./chunk-PJSK6OJM.js";
|
|
19
16
|
import {
|
|
20
17
|
WHO_KNOWS_DEFAULT_LIMIT,
|
|
21
18
|
computeWhoKnows,
|
|
22
19
|
loadWhoKnowsEntities,
|
|
23
20
|
validateWhoKnowsInput
|
|
24
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-NZWEEALH.js";
|
|
22
|
+
import {
|
|
23
|
+
WriteQuarantineStore
|
|
24
|
+
} from "./chunk-PJSK6OJM.js";
|
|
25
25
|
import {
|
|
26
26
|
trustResultFor
|
|
27
27
|
} from "./chunk-GNVZQ5JN.js";
|
|
@@ -45,25 +45,25 @@ import {
|
|
|
45
45
|
} from "./chunk-H7XKCNR6.js";
|
|
46
46
|
import {
|
|
47
47
|
toRecallExplainJson
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-AZAA5DNP.js";
|
|
49
49
|
import {
|
|
50
50
|
estimateRecallTokens
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-G57LQRP6.js";
|
|
52
52
|
import {
|
|
53
53
|
readAggregateExtractionWatermark
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-GUXS322H.js";
|
|
55
|
+
import {
|
|
56
|
+
ReplicaDivergenceMonitor
|
|
57
|
+
} from "./chunk-CVILPI77.js";
|
|
55
58
|
import {
|
|
56
59
|
recordObjectiveStateSnapshotsFromObservedMessages
|
|
57
60
|
} from "./chunk-2HIJHXB3.js";
|
|
58
61
|
import {
|
|
59
62
|
objectiveStateStoreOverrideForNamespace
|
|
60
63
|
} from "./chunk-HTP6XRUI.js";
|
|
61
|
-
import {
|
|
62
|
-
ReplicaDivergenceMonitor
|
|
63
|
-
} from "./chunk-CVILPI77.js";
|
|
64
64
|
import {
|
|
65
65
|
recordMemoryOutcome
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-4K7IW3F7.js";
|
|
67
67
|
import {
|
|
68
68
|
coerceIncludedMemories
|
|
69
69
|
} from "./chunk-2YA5N2BY.js";
|
|
@@ -90,13 +90,14 @@ import {
|
|
|
90
90
|
} from "./chunk-IVKIODHO.js";
|
|
91
91
|
import {
|
|
92
92
|
buildProcedurePersistBody,
|
|
93
|
-
normalizeProcedureSteps
|
|
93
|
+
normalizeProcedureSteps,
|
|
94
|
+
parseProcedureStepsFromBody
|
|
94
95
|
} from "./chunk-QDW3E4RD.js";
|
|
95
96
|
import {
|
|
96
97
|
persistExplicitCapture,
|
|
97
98
|
queueExplicitCaptureForReview,
|
|
98
99
|
validateExplicitCaptureInput
|
|
99
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-7BEPVIH3.js";
|
|
100
101
|
import {
|
|
101
102
|
boundRecallContextComposition,
|
|
102
103
|
composeRecallContext,
|
|
@@ -116,46 +117,42 @@ import {
|
|
|
116
117
|
listMemoryGovernanceRuns,
|
|
117
118
|
readMemoryGovernanceRunArtifact,
|
|
118
119
|
runMemoryGovernance
|
|
119
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-EIVIB73I.js";
|
|
120
121
|
import {
|
|
121
122
|
CorpusWatermarkCache,
|
|
122
123
|
computeServiceCorpusCensus
|
|
123
|
-
} from "./chunk-
|
|
124
|
+
} from "./chunk-P4DHENRE.js";
|
|
124
125
|
import {
|
|
125
126
|
ExtractionDeadlineError,
|
|
126
127
|
isActivityDigestPath,
|
|
127
128
|
isArtifactMemoryPath,
|
|
128
129
|
isLocationDayPath,
|
|
129
130
|
isMeetingRecordPath
|
|
130
|
-
} from "./chunk-
|
|
131
|
+
} from "./chunk-THG4GYIE.js";
|
|
131
132
|
import {
|
|
132
133
|
defaultCapsulesDir
|
|
133
134
|
} from "./chunk-ZY2MNJR6.js";
|
|
134
|
-
import {
|
|
135
|
-
filterTrajectoriesByLookbackDays,
|
|
136
|
-
readCausalTrajectoryRecords
|
|
137
|
-
} from "./chunk-PP7R754B.js";
|
|
138
135
|
import {
|
|
139
136
|
FileCalendarSource,
|
|
140
137
|
buildBriefing,
|
|
141
138
|
enqueuePassiveCorrectionNotification,
|
|
142
139
|
parseBriefingFocus,
|
|
143
140
|
parseBriefingWindow
|
|
144
|
-
} from "./chunk-
|
|
141
|
+
} from "./chunk-AYYGRVRP.js";
|
|
145
142
|
import {
|
|
146
143
|
parseEntityFile,
|
|
147
144
|
parseFrontmatter,
|
|
148
145
|
qmdCollectionPathParts,
|
|
149
146
|
qmdResultPathCandidates,
|
|
150
147
|
selfDeps
|
|
151
|
-
} from "./chunk-
|
|
148
|
+
} from "./chunk-PAYGC3BD.js";
|
|
152
149
|
import {
|
|
153
150
|
namespaceCollectionName
|
|
154
|
-
} from "./chunk-
|
|
151
|
+
} from "./chunk-YHCBJULX.js";
|
|
155
152
|
import {
|
|
156
153
|
DEFAULT_RECALL_DISCLOSURE,
|
|
157
154
|
isRecallDisclosure
|
|
158
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-NXKJHSDN.js";
|
|
159
156
|
import {
|
|
160
157
|
normalizeProjectionPreview,
|
|
161
158
|
normalizeProjectionTags
|
|
@@ -166,15 +163,26 @@ import {
|
|
|
166
163
|
buildObserveRequestFingerprint,
|
|
167
164
|
composeMemoryEnvelope,
|
|
168
165
|
isMemoryCategory
|
|
169
|
-
} from "./chunk-
|
|
166
|
+
} from "./chunk-RAIUTAZZ.js";
|
|
170
167
|
import {
|
|
171
168
|
applyTagFilter,
|
|
172
169
|
normalizeTags,
|
|
173
170
|
parseTagMatch
|
|
174
171
|
} from "./chunk-BT7NVCML.js";
|
|
175
172
|
import {
|
|
176
|
-
createVersion
|
|
173
|
+
createVersion,
|
|
174
|
+
getVersion,
|
|
175
|
+
revertToVersion
|
|
177
176
|
} from "./chunk-UFKPQBXH.js";
|
|
177
|
+
import {
|
|
178
|
+
MEMORY_CORPUS_VERSION_SENTINEL,
|
|
179
|
+
bumpMemoryCorpusVersionForDir
|
|
180
|
+
} from "./chunk-XCB6QDL6.js";
|
|
181
|
+
import {
|
|
182
|
+
HistoricalEntityCanonicalIdCache,
|
|
183
|
+
canonicalizeEntityRefFrontmatter,
|
|
184
|
+
repairContentAfterJournalMoveSync
|
|
185
|
+
} from "./chunk-ZVPVTPGI.js";
|
|
178
186
|
import {
|
|
179
187
|
supersessionKeysForFact
|
|
180
188
|
} from "./chunk-5WITETWU.js";
|
|
@@ -194,9 +202,16 @@ import {
|
|
|
194
202
|
import {
|
|
195
203
|
isExternalWikiCollectionName
|
|
196
204
|
} from "./chunk-JV3C2MNQ.js";
|
|
205
|
+
import {
|
|
206
|
+
filterTrajectoriesByLookbackDays,
|
|
207
|
+
readCausalTrajectoryRecords
|
|
208
|
+
} from "./chunk-PP7R754B.js";
|
|
209
|
+
import {
|
|
210
|
+
computePromotionCandidates
|
|
211
|
+
} from "./chunk-RIAM7DND.js";
|
|
197
212
|
import {
|
|
198
213
|
exportCapsule
|
|
199
|
-
} from "./chunk-
|
|
214
|
+
} from "./chunk-VDX2J7OX.js";
|
|
200
215
|
import {
|
|
201
216
|
evaluateActionConfidence
|
|
202
217
|
} from "./chunk-Z2YFLXHU.js";
|
|
@@ -225,7 +240,7 @@ import {
|
|
|
225
240
|
} from "./chunk-LNEWDF2A.js";
|
|
226
241
|
import {
|
|
227
242
|
createOfflineSyncManifestStream
|
|
228
|
-
} from "./chunk-
|
|
243
|
+
} from "./chunk-ODZG724P.js";
|
|
229
244
|
import {
|
|
230
245
|
offlineSyncStorageForSnapshot
|
|
231
246
|
} from "./chunk-HZNYJN77.js";
|
|
@@ -243,6 +258,7 @@ import {
|
|
|
243
258
|
} from "./chunk-KCT36JAW.js";
|
|
244
259
|
import {
|
|
245
260
|
inferMemoryStatus,
|
|
261
|
+
isActiveMemoryStatus,
|
|
246
262
|
toMemoryPathRel
|
|
247
263
|
} from "./chunk-7RJUVTVF.js";
|
|
248
264
|
import {
|
|
@@ -251,13 +267,6 @@ import {
|
|
|
251
267
|
import {
|
|
252
268
|
displayErrorDetail
|
|
253
269
|
} from "./chunk-RL6NEVXT.js";
|
|
254
|
-
import {
|
|
255
|
-
computeContentHash
|
|
256
|
-
} from "./chunk-5FVVY2EB.js";
|
|
257
|
-
import {
|
|
258
|
-
serializeMutations,
|
|
259
|
-
withHeldFileLock
|
|
260
|
-
} from "./chunk-FFAZ2XFU.js";
|
|
261
270
|
import {
|
|
262
271
|
SUPPORT_PASSPORT_ATTRIBUTE_KEYS,
|
|
263
272
|
SUPPORT_PASSPORT_CARD_TAG,
|
|
@@ -284,6 +293,13 @@ import {
|
|
|
284
293
|
import {
|
|
285
294
|
stripAttributesSuffix
|
|
286
295
|
} from "./chunk-JDSVLVCG.js";
|
|
296
|
+
import {
|
|
297
|
+
computeContentHash
|
|
298
|
+
} from "./chunk-5FVVY2EB.js";
|
|
299
|
+
import {
|
|
300
|
+
serializeMutations,
|
|
301
|
+
withHeldFileLock
|
|
302
|
+
} from "./chunk-FFAZ2XFU.js";
|
|
287
303
|
import {
|
|
288
304
|
sanitizeMemoryContent
|
|
289
305
|
} from "./chunk-5GKPFL3S.js";
|
|
@@ -374,6 +390,10 @@ import {
|
|
|
374
390
|
raceAbort,
|
|
375
391
|
throwIfAborted
|
|
376
392
|
} from "./chunk-BTTPKDIL.js";
|
|
393
|
+
import {
|
|
394
|
+
readJsonFile,
|
|
395
|
+
writeJsonFileAtomic
|
|
396
|
+
} from "./chunk-P77QX3ID.js";
|
|
377
397
|
import {
|
|
378
398
|
AccessAuditAdapter
|
|
379
399
|
} from "./chunk-TVVEYCNW.js";
|
|
@@ -387,7 +407,8 @@ import {
|
|
|
387
407
|
SecureStoreLockedError
|
|
388
408
|
} from "./chunk-XQ3HXAQH.js";
|
|
389
409
|
import {
|
|
390
|
-
ALL_CATEGORY_DIRS
|
|
410
|
+
ALL_CATEGORY_DIRS,
|
|
411
|
+
getCategoryDir
|
|
391
412
|
} from "./chunk-VS2IYZRU.js";
|
|
392
413
|
import {
|
|
393
414
|
recordCitationUsage
|
|
@@ -397,7 +418,7 @@ import {
|
|
|
397
418
|
} from "./chunk-3WCASNQZ.js";
|
|
398
419
|
|
|
399
420
|
// src/access-service.ts
|
|
400
|
-
import { createHash as
|
|
421
|
+
import { createHash as createHash13 } from "crypto";
|
|
401
422
|
import { constants as fsConstants2 } from "fs";
|
|
402
423
|
import { readdirSync, unlinkSync } from "fs";
|
|
403
424
|
import { stat as stat3 } from "fs/promises";
|
|
@@ -5367,6 +5388,7 @@ var OPERATION_NAMES = [
|
|
|
5367
5388
|
"recall_tier_explain",
|
|
5368
5389
|
"recall_xray",
|
|
5369
5390
|
"who_knows",
|
|
5391
|
+
"promotion_candidates",
|
|
5370
5392
|
"namespace_writable",
|
|
5371
5393
|
"wearables_status",
|
|
5372
5394
|
"wearables_sync",
|
|
@@ -5387,6 +5409,7 @@ var OPERATION_NAMES = [
|
|
|
5387
5409
|
"procedure_mining_run",
|
|
5388
5410
|
"pattern_reinforcement_run",
|
|
5389
5411
|
"procedural_stats",
|
|
5412
|
+
"procedure_library_maintenance",
|
|
5390
5413
|
"memory_timeline",
|
|
5391
5414
|
"suggestion_submit",
|
|
5392
5415
|
"entity_get",
|
|
@@ -5437,6 +5460,7 @@ var OPERATION_NAMES = [
|
|
|
5437
5460
|
"review_list",
|
|
5438
5461
|
"review_resolve",
|
|
5439
5462
|
"contradiction_scan_run",
|
|
5463
|
+
"preference_drift_scan",
|
|
5440
5464
|
"memory_summarize_hourly",
|
|
5441
5465
|
"conversation_index_update",
|
|
5442
5466
|
"profiling_report",
|
|
@@ -5481,6 +5505,9 @@ var OPERATION_NAMES = [
|
|
|
5481
5505
|
"trust_zones_status",
|
|
5482
5506
|
"trust_zones_records",
|
|
5483
5507
|
"review_disposition",
|
|
5508
|
+
"review_deck_list",
|
|
5509
|
+
"review_deck_action",
|
|
5510
|
+
"review_deck_undo",
|
|
5484
5511
|
"trust_zones_promote",
|
|
5485
5512
|
"trust_zones_demo_seed",
|
|
5486
5513
|
"citations_observed",
|
|
@@ -5558,10 +5585,10 @@ function formatZodIssues(error) {
|
|
|
5558
5585
|
const parts = [];
|
|
5559
5586
|
for (const issue of error.issues) {
|
|
5560
5587
|
const hasNumeric = issue.path.some((p) => typeof p === "number");
|
|
5561
|
-
const
|
|
5588
|
+
const path20 = hasNumeric ? issue.path.filter((p) => typeof p === "string").join(".") || "(root)" : issue.path.length > 0 ? issue.path.join(".") : "(root)";
|
|
5562
5589
|
const options = enumOptionsFromIssue(issue);
|
|
5563
5590
|
const suffix = options ? `. Valid: ${options.join(", ")}` : "";
|
|
5564
|
-
parts.push(`${
|
|
5591
|
+
parts.push(`${path20}: ${issue.message}${suffix}`);
|
|
5565
5592
|
}
|
|
5566
5593
|
return parts.length > 0 ? `request validation failed: ${parts.join("; ")}` : "request validation failed";
|
|
5567
5594
|
}
|
|
@@ -6114,6 +6141,343 @@ async function promoteMemory(options) {
|
|
|
6114
6141
|
};
|
|
6115
6142
|
}
|
|
6116
6143
|
|
|
6144
|
+
// src/procedural/library-maintenance.ts
|
|
6145
|
+
import path10 from "path";
|
|
6146
|
+
var MAINTENANCE_ACTOR = "procedure-library-maintenance";
|
|
6147
|
+
var MAINTENANCE_RULE_VERSION = "procedure-library-maintenance:1";
|
|
6148
|
+
function maintenanceMarkerPath(memoryDir) {
|
|
6149
|
+
return path10.join(memoryDir, "state", "procedure-maintenance.json");
|
|
6150
|
+
}
|
|
6151
|
+
async function readProcedureMaintenanceMarker(memoryDir) {
|
|
6152
|
+
try {
|
|
6153
|
+
const raw = await readJsonFile(maintenanceMarkerPath(memoryDir));
|
|
6154
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
6155
|
+
const m = raw;
|
|
6156
|
+
if (typeof m.lastRunAt !== "string") return null;
|
|
6157
|
+
return {
|
|
6158
|
+
schemaVersion: 1,
|
|
6159
|
+
lastRunAt: m.lastRunAt,
|
|
6160
|
+
lastApplyAt: typeof m.lastApplyAt === "string" ? m.lastApplyAt : null,
|
|
6161
|
+
appliedCount: typeof m.appliedCount === "number" ? m.appliedCount : 0
|
|
6162
|
+
};
|
|
6163
|
+
} catch {
|
|
6164
|
+
return null;
|
|
6165
|
+
}
|
|
6166
|
+
}
|
|
6167
|
+
function evidenceFor(m) {
|
|
6168
|
+
return {
|
|
6169
|
+
memoryId: m.frontmatter.id,
|
|
6170
|
+
mwSuccess: m.frontmatter.mw_success ?? 0,
|
|
6171
|
+
mwFail: m.frontmatter.mw_fail ?? 0,
|
|
6172
|
+
lastAccessed: m.frontmatter.lastAccessed ?? null,
|
|
6173
|
+
updated: m.frontmatter.updated ?? null
|
|
6174
|
+
};
|
|
6175
|
+
}
|
|
6176
|
+
function tsMs(value) {
|
|
6177
|
+
if (typeof value !== "string") return null;
|
|
6178
|
+
const ms = Date.parse(value);
|
|
6179
|
+
return Number.isFinite(ms) ? ms : null;
|
|
6180
|
+
}
|
|
6181
|
+
function procedureTitle(content) {
|
|
6182
|
+
const text = content.replace(/\r\n/g, "\n").trim();
|
|
6183
|
+
const idx = text.search(/^##\s+Step\s+\d+\s*$/im);
|
|
6184
|
+
return (idx === -1 ? text : text.slice(0, idx)).trim();
|
|
6185
|
+
}
|
|
6186
|
+
function normalizePhrase(s) {
|
|
6187
|
+
return s.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
6188
|
+
}
|
|
6189
|
+
function stepSignature(steps) {
|
|
6190
|
+
if (steps === null) return "<unparsed>";
|
|
6191
|
+
return steps.map(
|
|
6192
|
+
(s) => `${s.order}|${normalizePhrase(s.intent)}|${s.toolCall?.kind ?? ""}|${s.toolCall?.signature ?? ""}`
|
|
6193
|
+
).join(";;");
|
|
6194
|
+
}
|
|
6195
|
+
function isUserEditedProcedure(content) {
|
|
6196
|
+
const steps = parseProcedureStepsFromBody(content);
|
|
6197
|
+
if (steps === null) return true;
|
|
6198
|
+
const rebuilt = buildProcedurePersistBody(procedureTitle(content), steps);
|
|
6199
|
+
return rebuilt.trim() !== content.replace(/\r\n/g, "\n").trim();
|
|
6200
|
+
}
|
|
6201
|
+
function compareCanonical(a, b) {
|
|
6202
|
+
const aMs = tsMs(a.frontmatter.updated) ?? tsMs(a.frontmatter.created) ?? 0;
|
|
6203
|
+
const bMs = tsMs(b.frontmatter.updated) ?? tsMs(b.frontmatter.created) ?? 0;
|
|
6204
|
+
if (aMs !== bMs) return aMs > bMs ? -1 : 1;
|
|
6205
|
+
const aId = a.frontmatter.id ?? "";
|
|
6206
|
+
const bId = b.frontmatter.id ?? "";
|
|
6207
|
+
if (aId !== bId) return aId < bId ? -1 : 1;
|
|
6208
|
+
return 0;
|
|
6209
|
+
}
|
|
6210
|
+
function recentTrajectoryToolText(trajectories) {
|
|
6211
|
+
return trajectories.map((r) => r.actionSummary).join("\n").toLowerCase();
|
|
6212
|
+
}
|
|
6213
|
+
async function runProcedureLibraryMaintenance(options) {
|
|
6214
|
+
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
6215
|
+
const nowIso = now.toISOString();
|
|
6216
|
+
const mode = options.apply === true ? "apply" : "shadow";
|
|
6217
|
+
const cfg = options.config.procedural;
|
|
6218
|
+
if (cfg?.enabled !== true || cfg.maintenance?.enabled !== true) {
|
|
6219
|
+
return {
|
|
6220
|
+
schemaVersion: 1,
|
|
6221
|
+
generatedAt: nowIso,
|
|
6222
|
+
mode,
|
|
6223
|
+
scannedProcedures: 0,
|
|
6224
|
+
proposed: [],
|
|
6225
|
+
applied: [],
|
|
6226
|
+
appliedCount: 0,
|
|
6227
|
+
skippedReason: cfg?.enabled !== true ? "procedural_disabled" : "maintenance_disabled"
|
|
6228
|
+
};
|
|
6229
|
+
}
|
|
6230
|
+
const maintenance = cfg.maintenance;
|
|
6231
|
+
const all = await options.storage.readAllMemories();
|
|
6232
|
+
const byId = /* @__PURE__ */ new Map();
|
|
6233
|
+
for (const m of all) {
|
|
6234
|
+
if (m.frontmatter.category !== "procedure") continue;
|
|
6235
|
+
if (!isActiveMemoryStatus(m.frontmatter.status)) continue;
|
|
6236
|
+
if (typeof m.frontmatter.id === "string" && m.frontmatter.id.length > 0) {
|
|
6237
|
+
byId.set(m.frontmatter.id, m);
|
|
6238
|
+
}
|
|
6239
|
+
}
|
|
6240
|
+
const activeProcedures = [...byId.values()];
|
|
6241
|
+
const report = {
|
|
6242
|
+
schemaVersion: 1,
|
|
6243
|
+
generatedAt: nowIso,
|
|
6244
|
+
mode,
|
|
6245
|
+
scannedProcedures: activeProcedures.length,
|
|
6246
|
+
proposed: [],
|
|
6247
|
+
applied: [],
|
|
6248
|
+
appliedCount: 0
|
|
6249
|
+
};
|
|
6250
|
+
if (activeProcedures.length === 0 && mode === "shadow") return report;
|
|
6251
|
+
const mergeConsumed = /* @__PURE__ */ new Set();
|
|
6252
|
+
if (maintenance.mergeEnabled) {
|
|
6253
|
+
const clusters = /* @__PURE__ */ new Map();
|
|
6254
|
+
for (const m of activeProcedures) {
|
|
6255
|
+
const steps = parseProcedureStepsFromBody(m.content);
|
|
6256
|
+
const key = `${normalizePhrase(procedureTitle(m.content))}
|
|
6257
|
+
@@
|
|
6258
|
+
${stepSignature(steps)}`;
|
|
6259
|
+
const bucket = clusters.get(key);
|
|
6260
|
+
if (bucket) bucket.push(m);
|
|
6261
|
+
else clusters.set(key, [m]);
|
|
6262
|
+
}
|
|
6263
|
+
for (const cluster of clusters.values()) {
|
|
6264
|
+
if (cluster.length < 2) continue;
|
|
6265
|
+
const sortedCluster = [...cluster].sort(compareCanonical);
|
|
6266
|
+
const userEdited = sortedCluster.filter((m) => isUserEditedProcedure(m.content));
|
|
6267
|
+
if (userEdited.length > 0) {
|
|
6268
|
+
report.proposed.push({
|
|
6269
|
+
action: "flag_user_edited",
|
|
6270
|
+
reasonCode: "user_edited_protected",
|
|
6271
|
+
memoryIds: sortedCluster.map((m) => m.frontmatter.id),
|
|
6272
|
+
reason: "duplicate-signature cluster contains user-edited bodies; merge skipped for manual review",
|
|
6273
|
+
evidence: sortedCluster.map(evidenceFor)
|
|
6274
|
+
});
|
|
6275
|
+
continue;
|
|
6276
|
+
}
|
|
6277
|
+
const canonical = sortedCluster[0];
|
|
6278
|
+
const duplicates = sortedCluster.slice(1);
|
|
6279
|
+
for (const m of sortedCluster) mergeConsumed.add(m.frontmatter.id);
|
|
6280
|
+
report.proposed.push({
|
|
6281
|
+
action: "merge",
|
|
6282
|
+
reasonCode: "merge_duplicate_signature",
|
|
6283
|
+
memoryIds: [canonical.frontmatter.id, ...duplicates.map((m) => m.frontmatter.id)],
|
|
6284
|
+
canonicalId: canonical.frontmatter.id,
|
|
6285
|
+
reason: `near-identical trigger phrase + step signature across ${sortedCluster.length} active procedures`,
|
|
6286
|
+
evidence: sortedCluster.map(evidenceFor)
|
|
6287
|
+
});
|
|
6288
|
+
}
|
|
6289
|
+
}
|
|
6290
|
+
const trajectoryDir = typeof options.config.causalTrajectoryStoreDir === "string" && options.config.causalTrajectoryStoreDir.trim().length > 0 ? options.config.causalTrajectoryStoreDir.trim() : void 0;
|
|
6291
|
+
const { trajectories } = await readCausalTrajectoryRecords({
|
|
6292
|
+
memoryDir: options.memoryDir,
|
|
6293
|
+
causalTrajectoryStoreDir: trajectoryDir
|
|
6294
|
+
});
|
|
6295
|
+
const recentTrajectories = filterTrajectoriesByLookbackDays(
|
|
6296
|
+
trajectories,
|
|
6297
|
+
cfg.lookbackDays,
|
|
6298
|
+
now.getTime()
|
|
6299
|
+
);
|
|
6300
|
+
const repairFlags = [];
|
|
6301
|
+
const staleToolsByProcedure = /* @__PURE__ */ new Map();
|
|
6302
|
+
if (recentTrajectories.length > 0) {
|
|
6303
|
+
const toolText = recentTrajectoryToolText(recentTrajectories);
|
|
6304
|
+
for (const m of activeProcedures) {
|
|
6305
|
+
if (mergeConsumed.has(m.frontmatter.id)) continue;
|
|
6306
|
+
const steps = parseProcedureStepsFromBody(m.content);
|
|
6307
|
+
if (steps === null) continue;
|
|
6308
|
+
const tools = [
|
|
6309
|
+
...new Set(
|
|
6310
|
+
steps.map((s) => s.toolCall?.kind).filter((t) => typeof t === "string" && t.length > 0)
|
|
6311
|
+
)
|
|
6312
|
+
];
|
|
6313
|
+
if (tools.length === 0) continue;
|
|
6314
|
+
const stale = tools.filter((t) => !toolText.includes(t.toLowerCase()));
|
|
6315
|
+
if (stale.length === 0) continue;
|
|
6316
|
+
staleToolsByProcedure.set(m.frontmatter.id, stale);
|
|
6317
|
+
repairFlags.push({
|
|
6318
|
+
action: "flag_repair",
|
|
6319
|
+
reasonCode: "needs_repair_stale_tools",
|
|
6320
|
+
memoryIds: [m.frontmatter.id],
|
|
6321
|
+
reason: `tools absent from last ${cfg.lookbackDays}d of trajectories: ${stale.join(", ")}`,
|
|
6322
|
+
evidence: [evidenceFor(m)]
|
|
6323
|
+
});
|
|
6324
|
+
}
|
|
6325
|
+
}
|
|
6326
|
+
const retireActions = [];
|
|
6327
|
+
const retireIds = /* @__PURE__ */ new Set();
|
|
6328
|
+
const idleMs = maintenance.retireIdleDays * 24 * 60 * 60 * 1e3;
|
|
6329
|
+
for (const m of activeProcedures) {
|
|
6330
|
+
if (mergeConsumed.has(m.frontmatter.id)) continue;
|
|
6331
|
+
const mwSuccess = m.frontmatter.mw_success ?? 0;
|
|
6332
|
+
const mwFail = m.frontmatter.mw_fail ?? 0;
|
|
6333
|
+
const failureDominant = mwFail >= maintenance.retireMinOutcomes && mwFail > mwSuccess * maintenance.retireFailRatio;
|
|
6334
|
+
const lastSignalMs = tsMs(m.frontmatter.lastAccessed) ?? tsMs(m.frontmatter.updated);
|
|
6335
|
+
const idle = maintenance.retireIdleDays > 0 && mwSuccess + mwFail === 0 && lastSignalMs !== null && lastSignalMs < now.getTime() - idleMs;
|
|
6336
|
+
const reasonCode = failureDominant ? "retire_failure_dominant" : idle ? "retire_idle" : null;
|
|
6337
|
+
if (reasonCode === null) continue;
|
|
6338
|
+
if (isUserEditedProcedure(m.content)) {
|
|
6339
|
+
report.proposed.push({
|
|
6340
|
+
action: "flag_user_edited",
|
|
6341
|
+
reasonCode: "user_edited_protected",
|
|
6342
|
+
memoryIds: [m.frontmatter.id],
|
|
6343
|
+
reason: `user-edited body exempt from automatic retirement (${reasonCode} waived)`,
|
|
6344
|
+
evidence: [evidenceFor(m)]
|
|
6345
|
+
});
|
|
6346
|
+
continue;
|
|
6347
|
+
}
|
|
6348
|
+
retireIds.add(m.frontmatter.id);
|
|
6349
|
+
retireActions.push({
|
|
6350
|
+
action: "retire",
|
|
6351
|
+
reasonCode,
|
|
6352
|
+
memoryIds: [m.frontmatter.id],
|
|
6353
|
+
reason: reasonCode === "retire_failure_dominant" ? `mw_fail ${mwFail} >= ${maintenance.retireMinOutcomes} and > mw_success ${mwSuccess} * ${maintenance.retireFailRatio}` : `no access signal for ${maintenance.retireIdleDays}d and zero recorded outcomes`,
|
|
6354
|
+
evidence: [evidenceFor(m)]
|
|
6355
|
+
});
|
|
6356
|
+
}
|
|
6357
|
+
for (const flag of repairFlags) {
|
|
6358
|
+
if (retireIds.has(flag.memoryIds[0])) continue;
|
|
6359
|
+
report.proposed.push(flag);
|
|
6360
|
+
}
|
|
6361
|
+
report.proposed.push(...retireActions);
|
|
6362
|
+
if (mode === "shadow") return report;
|
|
6363
|
+
const applied = report.proposed;
|
|
6364
|
+
let writes = 0;
|
|
6365
|
+
for (const action of applied) {
|
|
6366
|
+
try {
|
|
6367
|
+
if (action.action === "merge") {
|
|
6368
|
+
const canonicalId = action.canonicalId;
|
|
6369
|
+
const canonical = canonicalId !== void 0 ? byId.get(canonicalId) : void 0;
|
|
6370
|
+
if (!canonical || canonicalId === void 0) continue;
|
|
6371
|
+
const memberIds = [...action.memoryIds].sort();
|
|
6372
|
+
const previousCount = canonical.frontmatter.reinforcement_count ?? 0;
|
|
6373
|
+
const newCount = Math.max(previousCount, memberIds.length);
|
|
6374
|
+
if (newCount !== canonical.frontmatter.reinforcement_count || canonical.frontmatter.derived_via !== "pattern-reinforcement") {
|
|
6375
|
+
await options.storage.writeMemoryFrontmatter(
|
|
6376
|
+
canonical,
|
|
6377
|
+
{
|
|
6378
|
+
reinforcement_count: newCount,
|
|
6379
|
+
last_reinforced_at: nowIso,
|
|
6380
|
+
derived_via: "pattern-reinforcement",
|
|
6381
|
+
derived_from: memberIds,
|
|
6382
|
+
updated: nowIso
|
|
6383
|
+
},
|
|
6384
|
+
{
|
|
6385
|
+
actor: MAINTENANCE_ACTOR,
|
|
6386
|
+
reasonCode: action.reasonCode,
|
|
6387
|
+
ruleVersion: MAINTENANCE_RULE_VERSION,
|
|
6388
|
+
relatedMemoryIds: memberIds
|
|
6389
|
+
}
|
|
6390
|
+
);
|
|
6391
|
+
writes += 1;
|
|
6392
|
+
}
|
|
6393
|
+
for (const memberId of action.memoryIds) {
|
|
6394
|
+
if (memberId === canonicalId) continue;
|
|
6395
|
+
const member = byId.get(memberId);
|
|
6396
|
+
if (!member) continue;
|
|
6397
|
+
await options.storage.writeMemoryFrontmatter(
|
|
6398
|
+
member,
|
|
6399
|
+
{
|
|
6400
|
+
status: "superseded",
|
|
6401
|
+
supersededBy: canonicalId,
|
|
6402
|
+
supersededAt: nowIso,
|
|
6403
|
+
updated: nowIso
|
|
6404
|
+
},
|
|
6405
|
+
{
|
|
6406
|
+
actor: MAINTENANCE_ACTOR,
|
|
6407
|
+
reasonCode: action.reasonCode,
|
|
6408
|
+
ruleVersion: MAINTENANCE_RULE_VERSION,
|
|
6409
|
+
relatedMemoryIds: [canonicalId]
|
|
6410
|
+
}
|
|
6411
|
+
);
|
|
6412
|
+
writes += 1;
|
|
6413
|
+
}
|
|
6414
|
+
} else if (action.action === "retire") {
|
|
6415
|
+
const memory = byId.get(action.memoryIds[0]);
|
|
6416
|
+
if (!memory) continue;
|
|
6417
|
+
const archivedPath = await options.storage.archiveMemory(memory, {
|
|
6418
|
+
at: now,
|
|
6419
|
+
actor: `${MAINTENANCE_ACTOR}.apply`,
|
|
6420
|
+
reasonCode: action.reasonCode,
|
|
6421
|
+
ruleVersion: MAINTENANCE_RULE_VERSION,
|
|
6422
|
+
relatedMemoryIds: []
|
|
6423
|
+
});
|
|
6424
|
+
if (archivedPath !== null) writes += 1;
|
|
6425
|
+
} else if (action.action === "flag_repair") {
|
|
6426
|
+
const memory = byId.get(action.memoryIds[0]);
|
|
6427
|
+
if (!memory) continue;
|
|
6428
|
+
const existing = memory.frontmatter.structuredAttributes ?? {};
|
|
6429
|
+
const prior = existing.needsRepair;
|
|
6430
|
+
let priorReason = null;
|
|
6431
|
+
if (typeof prior === "string") {
|
|
6432
|
+
try {
|
|
6433
|
+
const parsed = JSON.parse(prior);
|
|
6434
|
+
if (typeof parsed.reason === "string") priorReason = parsed.reason;
|
|
6435
|
+
} catch {
|
|
6436
|
+
priorReason = prior;
|
|
6437
|
+
}
|
|
6438
|
+
}
|
|
6439
|
+
if (priorReason === action.reason) continue;
|
|
6440
|
+
const stamp = JSON.stringify({ reason: action.reason, detectedAt: nowIso });
|
|
6441
|
+
await options.storage.writeMemoryFrontmatter(
|
|
6442
|
+
memory,
|
|
6443
|
+
{
|
|
6444
|
+
structuredAttributes: { ...existing, needsRepair: stamp },
|
|
6445
|
+
updated: nowIso
|
|
6446
|
+
},
|
|
6447
|
+
{
|
|
6448
|
+
actor: MAINTENANCE_ACTOR,
|
|
6449
|
+
reasonCode: action.reasonCode,
|
|
6450
|
+
ruleVersion: MAINTENANCE_RULE_VERSION
|
|
6451
|
+
}
|
|
6452
|
+
);
|
|
6453
|
+
writes += 1;
|
|
6454
|
+
}
|
|
6455
|
+
report.applied.push(action);
|
|
6456
|
+
} catch (err) {
|
|
6457
|
+
log.warn(
|
|
6458
|
+
`procedure-library-maintenance: action ${action.reasonCode} on ${action.memoryIds.join(",")} failed: ${err instanceof Error ? err.message : String(err)}`
|
|
6459
|
+
);
|
|
6460
|
+
}
|
|
6461
|
+
}
|
|
6462
|
+
report.appliedCount = report.applied.length;
|
|
6463
|
+
if (writes > 0) {
|
|
6464
|
+
bumpMemoryCorpusVersionForDir(options.memoryDir);
|
|
6465
|
+
}
|
|
6466
|
+
try {
|
|
6467
|
+
await writeJsonFileAtomic(maintenanceMarkerPath(options.memoryDir), {
|
|
6468
|
+
schemaVersion: 1,
|
|
6469
|
+
lastRunAt: nowIso,
|
|
6470
|
+
lastApplyAt: nowIso,
|
|
6471
|
+
appliedCount: report.appliedCount
|
|
6472
|
+
});
|
|
6473
|
+
} catch (err) {
|
|
6474
|
+
log.warn(
|
|
6475
|
+
`procedure-library-maintenance: failed to persist run marker: ${err instanceof Error ? err.message : String(err)}`
|
|
6476
|
+
);
|
|
6477
|
+
}
|
|
6478
|
+
return report;
|
|
6479
|
+
}
|
|
6480
|
+
|
|
6117
6481
|
// src/procedural/procedure-stats.ts
|
|
6118
6482
|
function snapshotConfig(config) {
|
|
6119
6483
|
const p = config.procedural;
|
|
@@ -6127,7 +6491,7 @@ function snapshotConfig(config) {
|
|
|
6127
6491
|
recallMaxProcedures: typeof p?.recallMaxProcedures === "number" ? p.recallMaxProcedures : 0
|
|
6128
6492
|
};
|
|
6129
6493
|
}
|
|
6130
|
-
function
|
|
6494
|
+
function tsMs2(value) {
|
|
6131
6495
|
if (typeof value !== "string") return null;
|
|
6132
6496
|
const ms = Date.parse(value);
|
|
6133
6497
|
return Number.isFinite(ms) ? ms : null;
|
|
@@ -6149,6 +6513,7 @@ async function computeProcedureStats(options) {
|
|
|
6149
6513
|
let lastWriteMs = null;
|
|
6150
6514
|
let writesLast7Days = 0;
|
|
6151
6515
|
let minerSourced = 0;
|
|
6516
|
+
let needsRepairFlags = 0;
|
|
6152
6517
|
const known = [
|
|
6153
6518
|
"active",
|
|
6154
6519
|
"pending_review",
|
|
@@ -6172,8 +6537,8 @@ async function computeProcedureStats(options) {
|
|
|
6172
6537
|
} else {
|
|
6173
6538
|
counts.other += 1;
|
|
6174
6539
|
}
|
|
6175
|
-
const createdMs =
|
|
6176
|
-
const updatedMs =
|
|
6540
|
+
const createdMs = tsMs2(m.frontmatter.created);
|
|
6541
|
+
const updatedMs = tsMs2(m.frontmatter.updated);
|
|
6177
6542
|
const latestMs = createdMs !== null && updatedMs !== null ? Math.max(createdMs, updatedMs) : updatedMs ?? createdMs;
|
|
6178
6543
|
if (latestMs !== null) {
|
|
6179
6544
|
if (lastWriteMs === null || latestMs > lastWriteMs) {
|
|
@@ -6186,7 +6551,11 @@ async function computeProcedureStats(options) {
|
|
|
6186
6551
|
if (m.frontmatter.source === "procedure-miner") {
|
|
6187
6552
|
minerSourced += 1;
|
|
6188
6553
|
}
|
|
6554
|
+
if (m.frontmatter.structuredAttributes?.needsRepair !== void 0 && isActiveMemoryStatus(m.frontmatter.status)) {
|
|
6555
|
+
needsRepairFlags += 1;
|
|
6556
|
+
}
|
|
6189
6557
|
}
|
|
6558
|
+
const maintenanceMarker = await readProcedureMaintenanceMarker(storage.dir);
|
|
6190
6559
|
return {
|
|
6191
6560
|
schemaVersion: 1,
|
|
6192
6561
|
generatedAt: new Date(nowMs).toISOString(),
|
|
@@ -6196,7 +6565,9 @@ async function computeProcedureStats(options) {
|
|
|
6196
6565
|
writesLast7Days,
|
|
6197
6566
|
minerSourced
|
|
6198
6567
|
},
|
|
6199
|
-
config: snapshotConfig(config)
|
|
6568
|
+
config: snapshotConfig(config),
|
|
6569
|
+
lastMaintenanceAt: maintenanceMarker?.lastRunAt ?? null,
|
|
6570
|
+
needsRepairFlags
|
|
6200
6571
|
};
|
|
6201
6572
|
}
|
|
6202
6573
|
function formatProcedureStatsText(report) {
|
|
@@ -6231,6 +6602,10 @@ function formatProcedureStatsText(report) {
|
|
|
6231
6602
|
lines.push(` lastWriteAt: ${recent.lastWriteAt ?? "(none)"}`);
|
|
6232
6603
|
lines.push(` writesLast7Days: ${recent.writesLast7Days}`);
|
|
6233
6604
|
lines.push(` minerSourced: ${recent.minerSourced}`);
|
|
6605
|
+
lines.push("");
|
|
6606
|
+
lines.push(` maintenance:`);
|
|
6607
|
+
lines.push(` lastMaintenanceAt: ${report.lastMaintenanceAt ?? "(never)"}`);
|
|
6608
|
+
lines.push(` needsRepairFlags: ${report.needsRepairFlags}`);
|
|
6234
6609
|
return lines.join("\n") + "\n";
|
|
6235
6610
|
}
|
|
6236
6611
|
|
|
@@ -8691,7 +9066,7 @@ import { createHash as createHash5 } from "crypto";
|
|
|
8691
9066
|
import * as nodePath2 from "path";
|
|
8692
9067
|
|
|
8693
9068
|
// src/orchestration/recall-result-formatter.ts
|
|
8694
|
-
import
|
|
9069
|
+
import path11 from "path";
|
|
8695
9070
|
function renderConnectorLabel(connector) {
|
|
8696
9071
|
if (!isValidConnectorId(connector)) return null;
|
|
8697
9072
|
return connector.length <= CONNECTOR_LABEL_MAX_LENGTH ? connector : `${connector.slice(0, CONNECTOR_LABEL_MAX_LENGTH - 1)}\u2026`;
|
|
@@ -8713,15 +9088,15 @@ function resolveEffectiveIdentityInjectionMode(options) {
|
|
|
8713
9088
|
return { mode: options.configuredMode, shouldInject: true };
|
|
8714
9089
|
}
|
|
8715
9090
|
function displayResultPath(resultPath, memoryDir, namespace) {
|
|
8716
|
-
if (!
|
|
8717
|
-
const root =
|
|
8718
|
-
const nsRoot =
|
|
8719
|
-
if (namespace && (resultPath === nsRoot || resultPath.startsWith(nsRoot +
|
|
8720
|
-
const afterNs =
|
|
9091
|
+
if (!path11.isAbsolute(resultPath)) return resultPath;
|
|
9092
|
+
const root = path11.resolve(memoryDir);
|
|
9093
|
+
const nsRoot = path11.join(root, "namespaces");
|
|
9094
|
+
if (namespace && (resultPath === nsRoot || resultPath.startsWith(nsRoot + path11.sep))) {
|
|
9095
|
+
const afterNs = path11.relative(nsRoot, resultPath).split(path11.sep).slice(1).join("/");
|
|
8721
9096
|
if (afterNs) return `${namespace}/${afterNs}`;
|
|
8722
9097
|
}
|
|
8723
|
-
const rel =
|
|
8724
|
-
return rel && !rel.startsWith("..") && !
|
|
9098
|
+
const rel = path11.relative(root, resultPath);
|
|
9099
|
+
return rel && !rel.startsWith("..") && !path11.isAbsolute(rel) ? rel.split(path11.sep).join("/") : resultPath;
|
|
8725
9100
|
}
|
|
8726
9101
|
function displaySafeRecallSnapshot(snapshot, memoryDir) {
|
|
8727
9102
|
const includedMemories = coerceIncludedMemories(snapshot).map((memory) => ({
|
|
@@ -8789,14 +9164,15 @@ ${snippet}`;
|
|
|
8789
9164
|
const withHandle = handle ? `${head.trimEnd()} ${handle}` : head.trimEnd();
|
|
8790
9165
|
const connectorLabel = renderConnectorLabel(r.sourceConnector);
|
|
8791
9166
|
const withConnector = connectorLabel ? `${withHandle} [agent: ${connectorLabel}]` : withHandle;
|
|
9167
|
+
const withDrift = r.driftNote ? `${withConnector} ${r.driftNote}` : withConnector;
|
|
8792
9168
|
if (hedgeMap) {
|
|
8793
9169
|
const item = trustResultFor(hedgeMap, r);
|
|
8794
9170
|
if (item) {
|
|
8795
9171
|
const hedge = renderEpistemicHedge(item.trust);
|
|
8796
|
-
if (hedge.length > 0) return `${
|
|
9172
|
+
if (hedge.length > 0) return `${withDrift} ${hedge}`;
|
|
8797
9173
|
}
|
|
8798
9174
|
}
|
|
8799
|
-
return
|
|
9175
|
+
return withDrift;
|
|
8800
9176
|
});
|
|
8801
9177
|
return { heading: `## ${title}`, entries };
|
|
8802
9178
|
}
|
|
@@ -9989,102 +10365,1497 @@ var AccessRecallSurface = class {
|
|
|
9989
10365
|
}
|
|
9990
10366
|
};
|
|
9991
10367
|
|
|
9992
|
-
// src/
|
|
9993
|
-
import {
|
|
10368
|
+
// src/review/review-deck-surface.ts
|
|
10369
|
+
import { createHash as createHash8 } from "crypto";
|
|
9994
10370
|
|
|
9995
|
-
// src/
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
constructor(code, message, status) {
|
|
10371
|
+
// src/review/review-deck.ts
|
|
10372
|
+
import { createHash as createHash6 } from "crypto";
|
|
10373
|
+
var ReviewDeckCursorError = class extends Error {
|
|
10374
|
+
constructor(message = "Invalid review deck cursor") {
|
|
10000
10375
|
super(message);
|
|
10001
|
-
this.name = "
|
|
10002
|
-
this.code = code;
|
|
10003
|
-
this.status = status;
|
|
10376
|
+
this.name = "ReviewDeckCursorError";
|
|
10004
10377
|
}
|
|
10005
10378
|
};
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
10009
|
-
|
|
10379
|
+
var ALLOWED_CHOICES = ["keep", "prepare_fix", "not_true"];
|
|
10380
|
+
var REVERSIBLE_RISK = {
|
|
10381
|
+
keep: "reversible",
|
|
10382
|
+
prepare_fix: "reversible",
|
|
10383
|
+
not_true: "reversible"
|
|
10384
|
+
};
|
|
10385
|
+
var REVIEW_REASON_LABELS = {
|
|
10386
|
+
low_confidence: "Low confidence",
|
|
10387
|
+
suggestion: "Suggested memory",
|
|
10388
|
+
tombstone_blocked: "Blocked by a deletion",
|
|
10389
|
+
contradiction: "Conflicts with another memory",
|
|
10390
|
+
duplicate: "Possible duplicate"
|
|
10391
|
+
};
|
|
10392
|
+
var EXCERPT_LIMIT = 240;
|
|
10393
|
+
function computeReviewItemRevision(fileContent) {
|
|
10394
|
+
return `rv1:${createHash6("sha256").update(fileContent).digest("hex")}`;
|
|
10010
10395
|
}
|
|
10011
|
-
function
|
|
10012
|
-
|
|
10396
|
+
function projectReviewDeckItem(row, namespace) {
|
|
10397
|
+
const provenance = provenanceFromRow(row);
|
|
10398
|
+
return {
|
|
10399
|
+
schemaVersion: 1,
|
|
10400
|
+
itemId: row.itemId,
|
|
10401
|
+
source: "review",
|
|
10402
|
+
sourceId: row.itemId,
|
|
10403
|
+
memoryId: row.itemId,
|
|
10404
|
+
content: row.content,
|
|
10405
|
+
...row.category !== void 0 ? { category: row.category } : {},
|
|
10406
|
+
...row.lifecycleState !== void 0 ? { lifecycleState: row.lifecycleState } : {},
|
|
10407
|
+
...row.confidence !== void 0 ? { confidence: row.confidence } : {},
|
|
10408
|
+
...row.confidenceTier !== void 0 ? { confidenceTier: row.confidenceTier } : {},
|
|
10409
|
+
reviewReason: row.reviewReason,
|
|
10410
|
+
reviewReasonLabel: reviewReasonLabel(row.reviewReason),
|
|
10411
|
+
supportCount: provenance.filter((entry) => entry.relation === "supports").length,
|
|
10412
|
+
provenance,
|
|
10413
|
+
allowedChoices: ALLOWED_CHOICES,
|
|
10414
|
+
choiceRisk: REVERSIBLE_RISK,
|
|
10415
|
+
namespace,
|
|
10416
|
+
revision: row.revision
|
|
10417
|
+
};
|
|
10013
10418
|
}
|
|
10014
|
-
function
|
|
10015
|
-
|
|
10016
|
-
|
|
10017
|
-
|
|
10018
|
-
|
|
10019
|
-
|
|
10419
|
+
function compareReviewDeckRows(a, b) {
|
|
10420
|
+
const aBlocked = a.blockedBy && a.blockedBy.length > 0 ? 0 : 1;
|
|
10421
|
+
const bBlocked = b.blockedBy && b.blockedBy.length > 0 ? 0 : 1;
|
|
10422
|
+
if (aBlocked !== bBlocked) return aBlocked - bBlocked;
|
|
10423
|
+
const aConfidence = a.confidence ?? 0.5;
|
|
10424
|
+
const bConfidence = b.confidence ?? 0.5;
|
|
10425
|
+
if (aConfidence !== bConfidence) return aConfidence < bConfidence ? -1 : 1;
|
|
10426
|
+
if (a.created !== b.created) return a.created < b.created ? -1 : 1;
|
|
10427
|
+
if (a.itemId !== b.itemId) return a.itemId < b.itemId ? -1 : 1;
|
|
10428
|
+
return 0;
|
|
10429
|
+
}
|
|
10430
|
+
function encodeReviewDeckCursor(scope, lastSortKey) {
|
|
10431
|
+
return Buffer.from(
|
|
10432
|
+
JSON.stringify({
|
|
10433
|
+
v: 1,
|
|
10434
|
+
p: scope.principalDigest,
|
|
10435
|
+
n: scope.namespace,
|
|
10436
|
+
f: scope.filterDigest,
|
|
10437
|
+
c: scope.corpusVersion,
|
|
10438
|
+
k: lastSortKey
|
|
10439
|
+
}),
|
|
10440
|
+
"utf8"
|
|
10441
|
+
).toString("base64url");
|
|
10442
|
+
}
|
|
10443
|
+
function decodeReviewDeckCursor(cursor, scope) {
|
|
10444
|
+
const payload = parseCursorPayload(cursor);
|
|
10445
|
+
if (payload.p !== scope.principalDigest || payload.n !== scope.namespace || payload.f !== scope.filterDigest || payload.c !== scope.corpusVersion) {
|
|
10446
|
+
throw new ReviewDeckCursorError("Review deck cursor scope mismatch");
|
|
10447
|
+
}
|
|
10448
|
+
return payload.k;
|
|
10449
|
+
}
|
|
10450
|
+
function buildReviewDeckPage(rows, opts) {
|
|
10451
|
+
const sorted = [...rows].sort(compareReviewDeckRows);
|
|
10452
|
+
const limit = Math.max(0, opts.limit);
|
|
10453
|
+
let start = 0;
|
|
10454
|
+
if (opts.cursor !== void 0) {
|
|
10455
|
+
const lastSortKey = decodeReviewDeckCursor(opts.cursor, opts.scope);
|
|
10456
|
+
start = sorted.findIndex((row) => reviewDeckSortKey(row) > lastSortKey);
|
|
10457
|
+
if (start < 0) start = sorted.length;
|
|
10458
|
+
}
|
|
10459
|
+
const pageRows = limit === 0 ? [] : sorted.slice(start, start + limit);
|
|
10460
|
+
const items = pageRows.map((row) => projectReviewDeckItem(row, opts.scope.namespace));
|
|
10461
|
+
const consumed = start + pageRows.length;
|
|
10462
|
+
const nextCursor = pageRows.length > 0 && consumed < sorted.length ? encodeReviewDeckCursor(opts.scope, reviewDeckSortKey(pageRows[pageRows.length - 1])) : void 0;
|
|
10463
|
+
return {
|
|
10464
|
+
schemaVersion: 1,
|
|
10465
|
+
items,
|
|
10466
|
+
total: sorted.length,
|
|
10467
|
+
...nextCursor !== void 0 ? { nextCursor } : {}
|
|
10020
10468
|
};
|
|
10021
10469
|
}
|
|
10022
|
-
function
|
|
10023
|
-
const
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
|
|
10027
|
-
|
|
10470
|
+
function reviewDeckSortKey(row) {
|
|
10471
|
+
const blocked = row.blockedBy && row.blockedBy.length > 0 ? "0" : "1";
|
|
10472
|
+
return `${blocked} ${(row.confidence ?? 0.5).toFixed(6)} ${row.created} ${row.itemId}`;
|
|
10473
|
+
}
|
|
10474
|
+
function reviewReasonLabel(reason) {
|
|
10475
|
+
const known = REVIEW_REASON_LABELS[reason];
|
|
10476
|
+
if (known) return known;
|
|
10477
|
+
const words = reason.split("_").filter((part) => part.length > 0);
|
|
10478
|
+
if (words.length === 0) return "Review";
|
|
10479
|
+
return words.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
10480
|
+
}
|
|
10481
|
+
function provenanceFromRow(row) {
|
|
10482
|
+
const fm = parseFrontmatterFields(row.fileContent);
|
|
10483
|
+
const source = nonempty(row.source) ?? nonempty(fm.source);
|
|
10484
|
+
const context = nonempty(row.context) ?? nonempty(fm.context);
|
|
10485
|
+
const created = nonempty(row.created) ?? nonempty(fm.created);
|
|
10486
|
+
const supportIds = idList(fm.supports);
|
|
10487
|
+
const conflictIds = [...idList(fm.conflicts), ...idList(fm.contradicts)];
|
|
10488
|
+
const relatedIds = idList(fm.relatedMemoryIds);
|
|
10489
|
+
const relatedRelation = row.reviewReason === "contradiction" ? "conflicts" : "supports";
|
|
10490
|
+
const provenance = [];
|
|
10491
|
+
if (source !== void 0 || context !== void 0) {
|
|
10492
|
+
provenance.push({
|
|
10493
|
+
relation: "origin",
|
|
10494
|
+
...created !== void 0 ? { sourceDate: created } : {},
|
|
10495
|
+
excerpt: truncateExcerpt(context ?? source ?? "")
|
|
10496
|
+
});
|
|
10028
10497
|
}
|
|
10029
|
-
|
|
10030
|
-
}
|
|
10031
|
-
|
|
10032
|
-
|
|
10033
|
-
|
|
10034
|
-
|
|
10035
|
-
|
|
10036
|
-
|
|
10037
|
-
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
updatedAt,
|
|
10041
|
-
reviewBy: card.reviewBy
|
|
10042
|
-
});
|
|
10498
|
+
for (const sourceMemoryId of supportIds) {
|
|
10499
|
+
provenance.push({ relation: "supports", sourceMemoryId });
|
|
10500
|
+
}
|
|
10501
|
+
for (const sourceMemoryId of conflictIds) {
|
|
10502
|
+
provenance.push({ relation: "conflicts", sourceMemoryId });
|
|
10503
|
+
}
|
|
10504
|
+
for (const sourceMemoryId of relatedIds) {
|
|
10505
|
+
if (supportIds.includes(sourceMemoryId) || conflictIds.includes(sourceMemoryId)) continue;
|
|
10506
|
+
provenance.push({ relation: relatedRelation, sourceMemoryId });
|
|
10507
|
+
}
|
|
10508
|
+
return provenance;
|
|
10043
10509
|
}
|
|
10044
|
-
function
|
|
10045
|
-
|
|
10046
|
-
|
|
10047
|
-
if (
|
|
10048
|
-
|
|
10510
|
+
function parseFrontmatterFields(content) {
|
|
10511
|
+
if (!content.startsWith("---\n")) return {};
|
|
10512
|
+
const end = content.indexOf("\n---", 4);
|
|
10513
|
+
if (end === -1) return {};
|
|
10514
|
+
const fields = {};
|
|
10515
|
+
for (const line of content.slice(4, end).split("\n")) {
|
|
10516
|
+
const colonIdx = line.indexOf(":");
|
|
10517
|
+
if (colonIdx === -1) continue;
|
|
10518
|
+
fields[line.slice(0, colonIdx).trim()] = line.slice(colonIdx + 1).trim();
|
|
10049
10519
|
}
|
|
10050
|
-
return
|
|
10520
|
+
return fields;
|
|
10051
10521
|
}
|
|
10052
|
-
function
|
|
10053
|
-
|
|
10054
|
-
return
|
|
10522
|
+
function idList(value) {
|
|
10523
|
+
if (value === void 0 || value.length === 0) return [];
|
|
10524
|
+
return value.replace(/^\[|\]$/g, "").split(",").map((part) => part.trim().replace(/^["']|["']$/g, "")).filter((part) => part.length > 0);
|
|
10055
10525
|
}
|
|
10056
|
-
function
|
|
10057
|
-
|
|
10058
|
-
return
|
|
10526
|
+
function nonempty(value) {
|
|
10527
|
+
if (value === void 0) return void 0;
|
|
10528
|
+
return value.trim().length > 0 ? value : void 0;
|
|
10059
10529
|
}
|
|
10060
|
-
function
|
|
10061
|
-
|
|
10062
|
-
|
|
10530
|
+
function truncateExcerpt(value) {
|
|
10531
|
+
return value.length <= EXCERPT_LIMIT ? value : value.slice(0, EXCERPT_LIMIT);
|
|
10532
|
+
}
|
|
10533
|
+
function parseCursorPayload(cursor) {
|
|
10534
|
+
if (cursor.length === 0) throw new ReviewDeckCursorError("Malformed review deck cursor");
|
|
10535
|
+
let parsed;
|
|
10536
|
+
try {
|
|
10537
|
+
parsed = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
|
|
10538
|
+
} catch {
|
|
10539
|
+
throw new ReviewDeckCursorError("Malformed review deck cursor");
|
|
10540
|
+
}
|
|
10541
|
+
if (!parsed || typeof parsed !== "object") throw new ReviewDeckCursorError("Malformed review deck cursor");
|
|
10542
|
+
const record = parsed;
|
|
10543
|
+
if (record.v !== 1) throw new ReviewDeckCursorError("Unsupported review deck cursor schema");
|
|
10544
|
+
if (typeof record.p !== "string" || typeof record.n !== "string" || typeof record.f !== "string" || typeof record.c !== "string" || typeof record.k !== "string" || record.k.length === 0) {
|
|
10545
|
+
throw new ReviewDeckCursorError("Malformed review deck cursor");
|
|
10063
10546
|
}
|
|
10547
|
+
return { v: 1, p: record.p, n: record.n, f: record.f, c: record.c, k: record.k };
|
|
10064
10548
|
}
|
|
10065
|
-
|
|
10066
|
-
|
|
10067
|
-
|
|
10549
|
+
|
|
10550
|
+
// src/review/review-deck-mutation.ts
|
|
10551
|
+
import { createHash as createHash7, randomUUID } from "crypto";
|
|
10552
|
+
import fs3 from "fs";
|
|
10553
|
+
import path14 from "path";
|
|
10554
|
+
|
|
10555
|
+
// src/review/index.ts
|
|
10556
|
+
import fs from "fs";
|
|
10557
|
+
import path12 from "path";
|
|
10558
|
+
var historicalIdCache = new HistoricalEntityCanonicalIdCache();
|
|
10559
|
+
function writeReviewFileCanonicalized(memoryDir, filePath, content) {
|
|
10560
|
+
const stateDir = path12.join(memoryDir, "state");
|
|
10561
|
+
const idsAtWrite = historicalIdCache.get(stateDir);
|
|
10562
|
+
let originalBytes = null;
|
|
10563
|
+
try {
|
|
10564
|
+
originalBytes = fs.readFileSync(filePath, "utf8");
|
|
10565
|
+
} catch {
|
|
10566
|
+
originalBytes = null;
|
|
10567
|
+
}
|
|
10568
|
+
const written = canonicalizeEntityRefFrontmatter(content, idsAtWrite);
|
|
10569
|
+
fs.writeFileSync(filePath, written, "utf8");
|
|
10570
|
+
try {
|
|
10571
|
+
repairContentAfterJournalMoveSync({
|
|
10572
|
+
stateDir,
|
|
10573
|
+
cache: historicalIdCache,
|
|
10574
|
+
idsAtWrite,
|
|
10575
|
+
rawContent: content,
|
|
10576
|
+
lastWritten: written,
|
|
10577
|
+
rewrite: (next) => fs.writeFileSync(filePath, next, "utf8")
|
|
10578
|
+
});
|
|
10579
|
+
} catch (err) {
|
|
10580
|
+
try {
|
|
10581
|
+
if (originalBytes === null) {
|
|
10582
|
+
fs.unlinkSync(filePath);
|
|
10583
|
+
} else {
|
|
10584
|
+
fs.writeFileSync(filePath, originalBytes, "utf8");
|
|
10585
|
+
}
|
|
10586
|
+
} catch {
|
|
10587
|
+
}
|
|
10588
|
+
throw err;
|
|
10068
10589
|
}
|
|
10069
10590
|
}
|
|
10070
|
-
|
|
10071
|
-
|
|
10072
|
-
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
|
|
10076
|
-
|
|
10077
|
-
|
|
10078
|
-
|
|
10079
|
-
(item) => item.card.status !== "active" || !cardsWithPendingReplacements.has(item.card.cardId)
|
|
10080
|
-
);
|
|
10591
|
+
var DEFAULT_CONFIDENCE_THRESHOLD = 0.7;
|
|
10592
|
+
function realMemoryRoot(memoryDir) {
|
|
10593
|
+
try {
|
|
10594
|
+
const stat4 = fs.lstatSync(memoryDir);
|
|
10595
|
+
if (!stat4.isDirectory() || stat4.isSymbolicLink()) return null;
|
|
10596
|
+
return fs.realpathSync(memoryDir);
|
|
10597
|
+
} catch {
|
|
10598
|
+
return null;
|
|
10599
|
+
}
|
|
10081
10600
|
}
|
|
10082
|
-
function
|
|
10083
|
-
const
|
|
10084
|
-
|
|
10085
|
-
|
|
10086
|
-
|
|
10087
|
-
|
|
10601
|
+
function isPathInside(rootReal, candidateReal) {
|
|
10602
|
+
const relative2 = path12.relative(rootReal, candidateReal);
|
|
10603
|
+
return relative2 === "" || !!relative2 && !relative2.startsWith("..") && !path12.isAbsolute(relative2);
|
|
10604
|
+
}
|
|
10605
|
+
function isSafeDirectory(rootReal, dir) {
|
|
10606
|
+
try {
|
|
10607
|
+
const stat4 = fs.lstatSync(dir);
|
|
10608
|
+
if (!stat4.isDirectory() || stat4.isSymbolicLink()) return false;
|
|
10609
|
+
return isPathInside(rootReal, fs.realpathSync(dir));
|
|
10610
|
+
} catch {
|
|
10611
|
+
return false;
|
|
10612
|
+
}
|
|
10613
|
+
}
|
|
10614
|
+
function ensureSafeDirectory(rootReal, dir) {
|
|
10615
|
+
if (fs.existsSync(dir)) {
|
|
10616
|
+
if (!isSafeDirectory(rootReal, dir)) {
|
|
10617
|
+
throw new Error(`Refusing to write through unsafe review path: ${dir}`);
|
|
10618
|
+
}
|
|
10619
|
+
return;
|
|
10620
|
+
}
|
|
10621
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
10622
|
+
if (!isSafeDirectory(rootReal, dir)) {
|
|
10623
|
+
throw new Error(`Refusing to write through unsafe review path: ${dir}`);
|
|
10624
|
+
}
|
|
10625
|
+
}
|
|
10626
|
+
function listReviewItems(options) {
|
|
10627
|
+
const startTime = Date.now();
|
|
10628
|
+
const {
|
|
10629
|
+
memoryDir,
|
|
10630
|
+
reason: filterReason,
|
|
10631
|
+
limit = 50,
|
|
10632
|
+
confidenceThreshold = DEFAULT_CONFIDENCE_THRESHOLD
|
|
10633
|
+
} = options;
|
|
10634
|
+
const maxItems = Math.max(0, limit);
|
|
10635
|
+
const rootReal = realMemoryRoot(memoryDir);
|
|
10636
|
+
if (!rootReal || maxItems === 0) {
|
|
10637
|
+
return { items: [], total: 0, durationMs: Date.now() - startTime };
|
|
10638
|
+
}
|
|
10639
|
+
const items = [];
|
|
10640
|
+
const isLimitReached = () => items.length >= maxItems;
|
|
10641
|
+
const addItem = (item) => {
|
|
10642
|
+
if (isLimitReached()) return;
|
|
10643
|
+
if (filterReason && item.reviewReason !== filterReason) return;
|
|
10644
|
+
items.push(item);
|
|
10645
|
+
};
|
|
10646
|
+
const suggestionsDir = path12.join(memoryDir, "suggestions");
|
|
10647
|
+
if (!isLimitReached() && fs.existsSync(suggestionsDir) && isSafeDirectory(rootReal, suggestionsDir)) {
|
|
10648
|
+
walkMd(rootReal, suggestionsDir, (filePath, content) => {
|
|
10649
|
+
if (isLimitReached()) return true;
|
|
10650
|
+
const fm = parseFrontmatter2(content);
|
|
10651
|
+
const body = extractBody(content);
|
|
10652
|
+
if (!fm?.id) return false;
|
|
10653
|
+
addItem({
|
|
10654
|
+
id: fm.id,
|
|
10655
|
+
content: body,
|
|
10656
|
+
category: fm.category ?? "suggestion",
|
|
10657
|
+
confidence: parseConfidence(fm.confidence, 0.5),
|
|
10658
|
+
confidenceTier: fm.confidenceTier ?? "low",
|
|
10659
|
+
source: fm.source ?? "unknown",
|
|
10660
|
+
filePath,
|
|
10661
|
+
created: fm.created ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
10662
|
+
reviewReason: "suggestion"
|
|
10663
|
+
});
|
|
10664
|
+
return isLimitReached();
|
|
10665
|
+
});
|
|
10666
|
+
}
|
|
10667
|
+
const reviewDir = path12.join(memoryDir, "review");
|
|
10668
|
+
if (!isLimitReached() && fs.existsSync(reviewDir) && isSafeDirectory(rootReal, reviewDir)) {
|
|
10669
|
+
walkMd(rootReal, reviewDir, (filePath, content) => {
|
|
10670
|
+
if (isLimitReached()) return true;
|
|
10671
|
+
const fm = parseFrontmatter2(content);
|
|
10672
|
+
const body = extractBody(content);
|
|
10673
|
+
if (!fm?.id) return false;
|
|
10674
|
+
addItem({
|
|
10675
|
+
id: fm.id,
|
|
10676
|
+
content: body,
|
|
10677
|
+
category: fm.category ?? "review",
|
|
10678
|
+
confidence: parseConfidence(fm.confidence, 0.5),
|
|
10679
|
+
confidenceTier: fm.confidenceTier ?? "low",
|
|
10680
|
+
source: fm.source ?? "unknown",
|
|
10681
|
+
filePath,
|
|
10682
|
+
created: fm.created ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
10683
|
+
reviewReason: fm.reviewReason ?? "low_confidence",
|
|
10684
|
+
context: fm.context
|
|
10685
|
+
});
|
|
10686
|
+
return isLimitReached();
|
|
10687
|
+
});
|
|
10688
|
+
}
|
|
10689
|
+
const categories = ALL_CATEGORY_DIRS;
|
|
10690
|
+
for (const category of categories) {
|
|
10691
|
+
if (isLimitReached()) break;
|
|
10692
|
+
const dir = path12.join(memoryDir, category);
|
|
10693
|
+
if (!fs.existsSync(dir) || !isSafeDirectory(rootReal, dir)) continue;
|
|
10694
|
+
walkMd(rootReal, dir, (filePath, content) => {
|
|
10695
|
+
if (isLimitReached()) return true;
|
|
10696
|
+
const fm = parseFrontmatter2(content);
|
|
10697
|
+
const body = extractBody(content);
|
|
10698
|
+
if (!fm?.id) return false;
|
|
10699
|
+
const confidence = parseConfidence(fm.confidence, 1);
|
|
10700
|
+
if (confidence >= confidenceThreshold && !(typeof fm.blockedBy === "string" && fm.blockedBy.length > 0)) return false;
|
|
10701
|
+
if (parseBoolean(fm.reviewDismissed)) return false;
|
|
10702
|
+
if (items.some((i) => i.id === fm.id)) return false;
|
|
10703
|
+
addItem({
|
|
10704
|
+
id: fm.id,
|
|
10705
|
+
content: body,
|
|
10706
|
+
category: fm.category ?? category.slice(0, -1),
|
|
10707
|
+
confidence,
|
|
10708
|
+
confidenceTier: fm.confidenceTier ?? "low",
|
|
10709
|
+
source: fm.source ?? "unknown",
|
|
10710
|
+
filePath,
|
|
10711
|
+
created: fm.created ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
10712
|
+
reviewReason: typeof fm.blockedBy === "string" && fm.blockedBy.length > 0 ? "tombstone_blocked" : "low_confidence"
|
|
10713
|
+
});
|
|
10714
|
+
return isLimitReached();
|
|
10715
|
+
});
|
|
10716
|
+
}
|
|
10717
|
+
return {
|
|
10718
|
+
items,
|
|
10719
|
+
total: items.length,
|
|
10720
|
+
durationMs: Date.now() - startTime
|
|
10721
|
+
};
|
|
10722
|
+
}
|
|
10723
|
+
function performReview(memoryDir, itemId, action, options = {}) {
|
|
10724
|
+
const result = action === "approve" ? approveItem(memoryDir, itemId, options) : action === "dismiss" ? dismissItem(memoryDir, itemId, options) : flagItem(memoryDir, itemId, options);
|
|
10725
|
+
if (result.updatedPath !== void 0) bumpMemoryCorpusVersionForDir(memoryDir);
|
|
10726
|
+
return result;
|
|
10727
|
+
}
|
|
10728
|
+
function approveItem(memoryDir, itemId, options) {
|
|
10729
|
+
const rootReal = realMemoryRoot(memoryDir);
|
|
10730
|
+
if (!rootReal) return { itemId, action: "approve", message: "Item not found" };
|
|
10731
|
+
const found = findReviewFileById(memoryDir, itemId, options);
|
|
10732
|
+
if (!found) {
|
|
10733
|
+
return { itemId, action: "approve", message: "Item not found" };
|
|
10734
|
+
}
|
|
10735
|
+
const content = fs.readFileSync(found.filePath, "utf8");
|
|
10736
|
+
const fm = parseFrontmatter2(content);
|
|
10737
|
+
if (!fm) return { itemId, action: "approve", message: "Could not parse frontmatter" };
|
|
10738
|
+
const blockedBy = typeof fm.blockedBy === "string" ? fm.blockedBy : null;
|
|
10739
|
+
const fireBlockedRevocation = () => {
|
|
10740
|
+
if (!blockedBy || !options.onApproveBlockedMemory) return;
|
|
10741
|
+
try {
|
|
10742
|
+
const maybe = options.onApproveBlockedMemory(blockedBy, itemId);
|
|
10743
|
+
if (maybe && typeof maybe.then === "function") {
|
|
10744
|
+
void maybe.catch(() => void 0);
|
|
10745
|
+
}
|
|
10746
|
+
} catch {
|
|
10747
|
+
}
|
|
10748
|
+
};
|
|
10749
|
+
const updatedContent = updateFrontmatterFields(content, {
|
|
10750
|
+
confidence: "0.9",
|
|
10751
|
+
confidenceTier: "high",
|
|
10752
|
+
reviewDismissed: null,
|
|
10753
|
+
// Clear the tombstone-block markers so the promoted memory is active.
|
|
10754
|
+
// Clear the tombstone-block markers AND restore active status so the
|
|
10755
|
+
// promoted memory is fully active in recall + provenance (issue #1579
|
|
10756
|
+
// review: leaving status: pending_review kept it invisible to recall).
|
|
10757
|
+
...blockedBy ? { blockedBy: null, tombstoneBlockTier: null, status: "active" } : {}
|
|
10758
|
+
});
|
|
10759
|
+
if (found.location === "category") {
|
|
10760
|
+
writeReviewFileCanonicalized(memoryDir, found.filePath, updatedContent);
|
|
10761
|
+
fireBlockedRevocation();
|
|
10762
|
+
return {
|
|
10763
|
+
itemId,
|
|
10764
|
+
action: "approve",
|
|
10765
|
+
updatedPath: found.filePath,
|
|
10766
|
+
message: "Approved low-confidence memory in place with confidence 0.9",
|
|
10767
|
+
...blockedBy ? { clearedTombstoneId: blockedBy } : {}
|
|
10768
|
+
};
|
|
10769
|
+
}
|
|
10770
|
+
const category = fm.category ?? "fact";
|
|
10771
|
+
const targetDir = getCategoryDir(memoryDir, category);
|
|
10772
|
+
const dateDir = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
10773
|
+
ensureSafeDirectory(rootReal, targetDir);
|
|
10774
|
+
const outputPath = path12.join(targetDir, dateDir, path12.basename(found.filePath));
|
|
10775
|
+
ensureSafeDirectory(rootReal, path12.dirname(outputPath));
|
|
10776
|
+
const reviewStateDir = path12.join(memoryDir, "state");
|
|
10777
|
+
const idsAtWrite = historicalIdCache.get(reviewStateDir);
|
|
10778
|
+
const promotedWritten = canonicalizeEntityRefFrontmatter(updatedContent, idsAtWrite);
|
|
10779
|
+
const promotedPath = writeFileWithoutClobber(outputPath, promotedWritten, itemId);
|
|
10780
|
+
try {
|
|
10781
|
+
repairContentAfterJournalMoveSync({
|
|
10782
|
+
stateDir: reviewStateDir,
|
|
10783
|
+
cache: historicalIdCache,
|
|
10784
|
+
idsAtWrite,
|
|
10785
|
+
rawContent: updatedContent,
|
|
10786
|
+
lastWritten: promotedWritten,
|
|
10787
|
+
rewrite: (next) => fs.writeFileSync(promotedPath, next, "utf8")
|
|
10788
|
+
});
|
|
10789
|
+
} catch (err) {
|
|
10790
|
+
try {
|
|
10791
|
+
fs.unlinkSync(promotedPath);
|
|
10792
|
+
} catch {
|
|
10793
|
+
}
|
|
10794
|
+
throw err;
|
|
10795
|
+
}
|
|
10796
|
+
fs.unlinkSync(found.filePath);
|
|
10797
|
+
fireBlockedRevocation();
|
|
10798
|
+
return {
|
|
10799
|
+
itemId,
|
|
10800
|
+
action: "approve",
|
|
10801
|
+
updatedPath: promotedPath,
|
|
10802
|
+
message: `Promoted to ${category} with confidence 0.9`,
|
|
10803
|
+
...blockedBy ? { clearedTombstoneId: blockedBy } : {}
|
|
10804
|
+
};
|
|
10805
|
+
}
|
|
10806
|
+
function dismissItem(memoryDir, itemId, options) {
|
|
10807
|
+
const found = findReviewFileById(memoryDir, itemId, options);
|
|
10808
|
+
if (!found) {
|
|
10809
|
+
return { itemId, action: "dismiss", message: "Item not found" };
|
|
10810
|
+
}
|
|
10811
|
+
if (found.location === "queue") {
|
|
10812
|
+
fs.unlinkSync(found.filePath);
|
|
10813
|
+
return { itemId, action: "dismiss", message: "Dismissed and removed" };
|
|
10814
|
+
}
|
|
10815
|
+
const content = fs.readFileSync(found.filePath, "utf8");
|
|
10816
|
+
writeReviewFileCanonicalized(
|
|
10817
|
+
memoryDir,
|
|
10818
|
+
found.filePath,
|
|
10819
|
+
updateFrontmatterFields(content, {
|
|
10820
|
+
reviewDismissed: "true",
|
|
10821
|
+
reviewDismissedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10822
|
+
})
|
|
10823
|
+
);
|
|
10824
|
+
return {
|
|
10825
|
+
itemId,
|
|
10826
|
+
action: "dismiss",
|
|
10827
|
+
updatedPath: found.filePath,
|
|
10828
|
+
message: "Dismissed low-confidence memory in place"
|
|
10829
|
+
};
|
|
10830
|
+
}
|
|
10831
|
+
function flagItem(memoryDir, itemId, options) {
|
|
10832
|
+
const found = findReviewFileById(memoryDir, itemId, options);
|
|
10833
|
+
if (!found) {
|
|
10834
|
+
return { itemId, action: "flag", message: "Item not found" };
|
|
10835
|
+
}
|
|
10836
|
+
const content = fs.readFileSync(found.filePath, "utf8");
|
|
10837
|
+
const fixed = updateFrontmatterFields(content, {
|
|
10838
|
+
flagged: "true",
|
|
10839
|
+
flaggedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10840
|
+
});
|
|
10841
|
+
writeReviewFileCanonicalized(memoryDir, found.filePath, fixed);
|
|
10842
|
+
return {
|
|
10843
|
+
itemId,
|
|
10844
|
+
action: "flag",
|
|
10845
|
+
updatedPath: found.filePath,
|
|
10846
|
+
message: "Flagged for further review"
|
|
10847
|
+
};
|
|
10848
|
+
}
|
|
10849
|
+
function findReviewFileById(memoryDir, id, options = {}) {
|
|
10850
|
+
const rootReal = realMemoryRoot(memoryDir);
|
|
10851
|
+
if (!rootReal) return null;
|
|
10852
|
+
for (const loc of ["suggestions", "review"]) {
|
|
10853
|
+
const dir = path12.join(memoryDir, loc);
|
|
10854
|
+
if (!fs.existsSync(dir) || !isSafeDirectory(rootReal, dir)) continue;
|
|
10855
|
+
const found = findFileById(rootReal, dir, id);
|
|
10856
|
+
if (found) return { filePath: found, location: "queue" };
|
|
10857
|
+
}
|
|
10858
|
+
for (const category of ALL_CATEGORY_DIRS) {
|
|
10859
|
+
const dir = path12.join(memoryDir, category);
|
|
10860
|
+
if (!fs.existsSync(dir) || !isSafeDirectory(rootReal, dir)) continue;
|
|
10861
|
+
const found = findFileById(rootReal, dir, id, (fm) => isLowConfidenceReviewCandidate(fm, options));
|
|
10862
|
+
if (found) return { filePath: found, location: "category" };
|
|
10863
|
+
}
|
|
10864
|
+
return null;
|
|
10865
|
+
}
|
|
10866
|
+
function findFileById(rootReal, dir, id, include) {
|
|
10867
|
+
const files = walkMdPaths(rootReal, dir);
|
|
10868
|
+
for (const filePath of files) {
|
|
10869
|
+
const content = readFileSafe(filePath);
|
|
10870
|
+
if (!content) continue;
|
|
10871
|
+
const fm = parseFrontmatter2(content);
|
|
10872
|
+
if (fm?.id === id && (!include || include(fm))) return filePath;
|
|
10873
|
+
}
|
|
10874
|
+
return null;
|
|
10875
|
+
}
|
|
10876
|
+
function isLowConfidenceReviewCandidate(fm, options) {
|
|
10877
|
+
const threshold = options.confidenceThreshold ?? DEFAULT_CONFIDENCE_THRESHOLD;
|
|
10878
|
+
if (typeof fm.blockedBy === "string" && fm.blockedBy.length > 0) {
|
|
10879
|
+
return !parseBoolean(fm.reviewDismissed);
|
|
10880
|
+
}
|
|
10881
|
+
return parseConfidence(fm.confidence, 1) < threshold && !parseBoolean(fm.reviewDismissed);
|
|
10882
|
+
}
|
|
10883
|
+
function parseBoolean(value) {
|
|
10884
|
+
if (typeof value === "boolean") return value;
|
|
10885
|
+
if (typeof value !== "string") return false;
|
|
10886
|
+
const normalized = value.trim().toLowerCase();
|
|
10887
|
+
return normalized === "true" || normalized === "1" || normalized === "yes";
|
|
10888
|
+
}
|
|
10889
|
+
function parseConfidence(value, fallback) {
|
|
10890
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : fallback;
|
|
10891
|
+
if (typeof value === "string") {
|
|
10892
|
+
const n = parseFloat(value);
|
|
10893
|
+
return Number.isFinite(n) ? n : fallback;
|
|
10894
|
+
}
|
|
10895
|
+
return fallback;
|
|
10896
|
+
}
|
|
10897
|
+
function updateFrontmatterFields(content, fields) {
|
|
10898
|
+
const match = content.match(/^(---\n)([\s\S]*?)(\n---(?:\n|$))/);
|
|
10899
|
+
if (!match) return content;
|
|
10900
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10901
|
+
const lines = match[2].split("\n");
|
|
10902
|
+
const nextLines = [];
|
|
10903
|
+
for (const line of lines) {
|
|
10904
|
+
const colonIdx = line.indexOf(":");
|
|
10905
|
+
if (colonIdx === -1) {
|
|
10906
|
+
nextLines.push(line);
|
|
10907
|
+
continue;
|
|
10908
|
+
}
|
|
10909
|
+
const key = line.slice(0, colonIdx).trim();
|
|
10910
|
+
if (!Object.prototype.hasOwnProperty.call(fields, key)) {
|
|
10911
|
+
nextLines.push(line);
|
|
10912
|
+
continue;
|
|
10913
|
+
}
|
|
10914
|
+
seen.add(key);
|
|
10915
|
+
const value = fields[key];
|
|
10916
|
+
if (value !== null) {
|
|
10917
|
+
nextLines.push(`${key}: ${value}`);
|
|
10918
|
+
}
|
|
10919
|
+
}
|
|
10920
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
10921
|
+
if (value !== null && !seen.has(key)) {
|
|
10922
|
+
nextLines.push(`${key}: ${value}`);
|
|
10923
|
+
}
|
|
10924
|
+
}
|
|
10925
|
+
return `${match[1]}${nextLines.join("\n")}${match[3]}${content.slice(match[0].length)}`;
|
|
10926
|
+
}
|
|
10927
|
+
function readFileSafe(filePath) {
|
|
10928
|
+
try {
|
|
10929
|
+
return fs.readFileSync(filePath, "utf8");
|
|
10930
|
+
} catch {
|
|
10931
|
+
return null;
|
|
10932
|
+
}
|
|
10933
|
+
}
|
|
10934
|
+
function writeFileWithoutClobber(basePath, content, discriminator) {
|
|
10935
|
+
const parsed = path12.parse(basePath);
|
|
10936
|
+
const safeDiscriminator = sanitizeFilePart(discriminator);
|
|
10937
|
+
for (let attempt = 0; attempt < 1e3; attempt++) {
|
|
10938
|
+
const candidate = attempt === 0 ? basePath : path12.join(
|
|
10939
|
+
parsed.dir,
|
|
10940
|
+
`${parsed.name}-${safeDiscriminator}${attempt === 1 ? "" : `-${attempt}`}${parsed.ext || ".md"}`
|
|
10941
|
+
);
|
|
10942
|
+
try {
|
|
10943
|
+
fs.writeFileSync(candidate, content, { encoding: "utf8", flag: "wx" });
|
|
10944
|
+
return candidate;
|
|
10945
|
+
} catch (error) {
|
|
10946
|
+
if (error.code === "EEXIST") continue;
|
|
10947
|
+
throw error;
|
|
10948
|
+
}
|
|
10949
|
+
}
|
|
10950
|
+
throw new Error(`Could not find a free review promotion path for ${basePath}`);
|
|
10951
|
+
}
|
|
10952
|
+
function sanitizeFilePart(value) {
|
|
10953
|
+
const chars = [];
|
|
10954
|
+
let previousWasDash = false;
|
|
10955
|
+
for (const char of value) {
|
|
10956
|
+
const next = isSafeFilePartChar(char) ? char : "-";
|
|
10957
|
+
if (next === "-" && previousWasDash) continue;
|
|
10958
|
+
chars.push(next);
|
|
10959
|
+
previousWasDash = next === "-";
|
|
10960
|
+
if (chars.length >= 64) break;
|
|
10961
|
+
}
|
|
10962
|
+
let start = 0;
|
|
10963
|
+
let end = chars.length;
|
|
10964
|
+
while (start < end && chars[start] === "-") start++;
|
|
10965
|
+
while (end > start && chars[end - 1] === "-") end--;
|
|
10966
|
+
const sanitized = chars.slice(start, end).join("");
|
|
10967
|
+
return sanitized || "review-item";
|
|
10968
|
+
}
|
|
10969
|
+
function isSafeFilePartChar(value) {
|
|
10970
|
+
if (value.length !== 1) return false;
|
|
10971
|
+
const code = value.charCodeAt(0);
|
|
10972
|
+
return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || value === "." || value === "_" || value === "-";
|
|
10973
|
+
}
|
|
10974
|
+
function parseFrontmatter2(content) {
|
|
10975
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
10976
|
+
if (!match) return null;
|
|
10977
|
+
const fm = {};
|
|
10978
|
+
for (const line of match[1].split("\n")) {
|
|
10979
|
+
const colonIdx = line.indexOf(":");
|
|
10980
|
+
if (colonIdx === -1) continue;
|
|
10981
|
+
const key = line.slice(0, colonIdx).trim();
|
|
10982
|
+
const value = line.slice(colonIdx + 1).trim();
|
|
10983
|
+
fm[key] = value;
|
|
10984
|
+
}
|
|
10985
|
+
return fm;
|
|
10986
|
+
}
|
|
10987
|
+
function extractBody(content) {
|
|
10988
|
+
const match = content.match(/^---\n[\s\S]*?\n---\n([\s\S]*)/);
|
|
10989
|
+
return match ? match[1].trim() : content.trim();
|
|
10990
|
+
}
|
|
10991
|
+
function walkMd(rootReal, dir, callback) {
|
|
10992
|
+
if (!isSafeDirectory(rootReal, dir)) return false;
|
|
10993
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
10994
|
+
const fullPath = path12.join(dir, entry.name);
|
|
10995
|
+
if (entry.isSymbolicLink()) continue;
|
|
10996
|
+
if (entry.isDirectory()) {
|
|
10997
|
+
if (walkMd(rootReal, fullPath, callback)) return true;
|
|
10998
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
10999
|
+
const content = readFileSafe(fullPath);
|
|
11000
|
+
if (content && callback(fullPath, content) === true) return true;
|
|
11001
|
+
}
|
|
11002
|
+
}
|
|
11003
|
+
return false;
|
|
11004
|
+
}
|
|
11005
|
+
function walkMdPaths(rootReal, dir) {
|
|
11006
|
+
const results = [];
|
|
11007
|
+
if (!isSafeDirectory(rootReal, dir)) return results;
|
|
11008
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
11009
|
+
const fullPath = path12.join(dir, entry.name);
|
|
11010
|
+
if (entry.isSymbolicLink()) continue;
|
|
11011
|
+
if (entry.isDirectory()) {
|
|
11012
|
+
results.push(...walkMdPaths(rootReal, fullPath));
|
|
11013
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
11014
|
+
results.push(fullPath);
|
|
11015
|
+
}
|
|
11016
|
+
}
|
|
11017
|
+
return results;
|
|
11018
|
+
}
|
|
11019
|
+
|
|
11020
|
+
// src/review/review-deck-snapshot.ts
|
|
11021
|
+
import fs2 from "fs";
|
|
11022
|
+
import path13 from "path";
|
|
11023
|
+
var QUEUE_DIRS = ["suggestions", "review"];
|
|
11024
|
+
function readReviewDeckSnapshot(opts) {
|
|
11025
|
+
const corpusVersion = readCorpusVersion(opts.memoryDir);
|
|
11026
|
+
const rootReal = realMemoryRoot2(opts.memoryDir);
|
|
11027
|
+
if (!rootReal) return { corpusVersion, total: 0, rows: [] };
|
|
11028
|
+
const rows = [];
|
|
11029
|
+
for (const location of QUEUE_DIRS) {
|
|
11030
|
+
const dir = path13.join(opts.memoryDir, location);
|
|
11031
|
+
if (!fs2.existsSync(dir) || !isSafeDirectory2(rootReal, dir)) continue;
|
|
11032
|
+
walkMd2(rootReal, dir, (filePath, content) => {
|
|
11033
|
+
const row = rowFromQueueFile(filePath, content, location);
|
|
11034
|
+
if (row) rows.push(row);
|
|
11035
|
+
});
|
|
11036
|
+
}
|
|
11037
|
+
return { corpusVersion, total: rows.length, rows };
|
|
11038
|
+
}
|
|
11039
|
+
function readReviewDeckRow(opts) {
|
|
11040
|
+
const rootReal = realMemoryRoot2(opts.memoryDir);
|
|
11041
|
+
if (!rootReal) return null;
|
|
11042
|
+
for (const location of QUEUE_DIRS) {
|
|
11043
|
+
const dir = path13.join(opts.memoryDir, location);
|
|
11044
|
+
if (!fs2.existsSync(dir) || !isSafeDirectory2(rootReal, dir)) continue;
|
|
11045
|
+
let found = null;
|
|
11046
|
+
walkMd2(rootReal, dir, (filePath, content) => {
|
|
11047
|
+
const row = rowFromQueueFile(filePath, content, location);
|
|
11048
|
+
if (row?.itemId === opts.itemId) {
|
|
11049
|
+
found = row;
|
|
11050
|
+
return true;
|
|
11051
|
+
}
|
|
11052
|
+
});
|
|
11053
|
+
if (found) return found;
|
|
11054
|
+
}
|
|
11055
|
+
return null;
|
|
11056
|
+
}
|
|
11057
|
+
function readCorpusVersion(memoryDir) {
|
|
11058
|
+
try {
|
|
11059
|
+
return String(fs2.statSync(path13.join(memoryDir, "state", MEMORY_CORPUS_VERSION_SENTINEL)).size);
|
|
11060
|
+
} catch {
|
|
11061
|
+
return "0";
|
|
11062
|
+
}
|
|
11063
|
+
}
|
|
11064
|
+
function rowFromQueueFile(filePath, content, location) {
|
|
11065
|
+
const fm = parseFrontmatter3(content);
|
|
11066
|
+
const itemId = optionalString(fm?.id);
|
|
11067
|
+
if (!fm || !itemId || !isPendingQueueRow(fm)) return null;
|
|
11068
|
+
const blockedBy = optionalString(fm.blockedBy);
|
|
11069
|
+
const confidence = parseOptionalConfidence(fm.confidence);
|
|
11070
|
+
const category = optionalString(fm.category);
|
|
11071
|
+
const confidenceTier = optionalString(fm.confidenceTier);
|
|
11072
|
+
const source = optionalString(fm.source);
|
|
11073
|
+
const context = optionalString(fm.context);
|
|
11074
|
+
const lifecycleState = optionalString(fm.lifecycleState) ?? optionalString(fm.status);
|
|
11075
|
+
const created = optionalString(fm.created) ?? "";
|
|
11076
|
+
const explicitReason = optionalString(fm.reviewReason);
|
|
11077
|
+
return {
|
|
11078
|
+
itemId,
|
|
11079
|
+
filePath,
|
|
11080
|
+
fileContent: content,
|
|
11081
|
+
revision: computeReviewItemRevision(content),
|
|
11082
|
+
content: extractBody2(content),
|
|
11083
|
+
reviewReason: explicitReason ?? (blockedBy ? "tombstone_blocked" : location === "suggestions" ? "suggestion" : "low_confidence"),
|
|
11084
|
+
created,
|
|
11085
|
+
...category ? { category } : {},
|
|
11086
|
+
...confidence !== void 0 ? { confidence } : {},
|
|
11087
|
+
...confidenceTier ? { confidenceTier } : {},
|
|
11088
|
+
...source ? { source } : {},
|
|
11089
|
+
...blockedBy ? { blockedBy } : {},
|
|
11090
|
+
...lifecycleState ? { lifecycleState } : {},
|
|
11091
|
+
...context ? { context } : {}
|
|
11092
|
+
};
|
|
11093
|
+
}
|
|
11094
|
+
function isPendingQueueRow(fm) {
|
|
11095
|
+
if (parseBoolean2(fm.reviewDismissed)) return false;
|
|
11096
|
+
const status = optionalString(fm.status);
|
|
11097
|
+
return status === void 0 || status === "pending_review";
|
|
11098
|
+
}
|
|
11099
|
+
function realMemoryRoot2(memoryDir) {
|
|
11100
|
+
try {
|
|
11101
|
+
const stat4 = fs2.lstatSync(memoryDir);
|
|
11102
|
+
if (!stat4.isDirectory() || stat4.isSymbolicLink()) return null;
|
|
11103
|
+
return fs2.realpathSync(memoryDir);
|
|
11104
|
+
} catch {
|
|
11105
|
+
return null;
|
|
11106
|
+
}
|
|
11107
|
+
}
|
|
11108
|
+
function isPathInside2(rootReal, candidateReal) {
|
|
11109
|
+
const relative2 = path13.relative(rootReal, candidateReal);
|
|
11110
|
+
return relative2 === "" || !!relative2 && !relative2.startsWith("..") && !path13.isAbsolute(relative2);
|
|
11111
|
+
}
|
|
11112
|
+
function isSafeDirectory2(rootReal, dir) {
|
|
11113
|
+
try {
|
|
11114
|
+
const stat4 = fs2.lstatSync(dir);
|
|
11115
|
+
if (!stat4.isDirectory() || stat4.isSymbolicLink()) return false;
|
|
11116
|
+
return isPathInside2(rootReal, fs2.realpathSync(dir));
|
|
11117
|
+
} catch {
|
|
11118
|
+
return false;
|
|
11119
|
+
}
|
|
11120
|
+
}
|
|
11121
|
+
function walkMd2(rootReal, dir, callback) {
|
|
11122
|
+
if (!isSafeDirectory2(rootReal, dir)) return false;
|
|
11123
|
+
for (const entry of fs2.readdirSync(dir, { withFileTypes: true })) {
|
|
11124
|
+
const fullPath = path13.join(dir, entry.name);
|
|
11125
|
+
if (entry.isSymbolicLink()) continue;
|
|
11126
|
+
if (entry.isDirectory()) {
|
|
11127
|
+
if (walkMd2(rootReal, fullPath, callback)) return true;
|
|
11128
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
11129
|
+
const content = readFileSafe2(fullPath);
|
|
11130
|
+
if (content && callback(fullPath, content) === true) return true;
|
|
11131
|
+
}
|
|
11132
|
+
}
|
|
11133
|
+
return false;
|
|
11134
|
+
}
|
|
11135
|
+
function readFileSafe2(filePath) {
|
|
11136
|
+
try {
|
|
11137
|
+
return fs2.readFileSync(filePath, "utf8");
|
|
11138
|
+
} catch {
|
|
11139
|
+
return null;
|
|
11140
|
+
}
|
|
11141
|
+
}
|
|
11142
|
+
function splitFrontmatter(content) {
|
|
11143
|
+
if (!content.startsWith("---\n")) return null;
|
|
11144
|
+
const end = content.indexOf("\n---", 4);
|
|
11145
|
+
if (end === -1) return null;
|
|
11146
|
+
const after = end + "\n---".length;
|
|
11147
|
+
const body = content.startsWith("\n", after) ? content.slice(after + 1) : content.slice(after);
|
|
11148
|
+
return { fields: content.slice(4, end), body };
|
|
11149
|
+
}
|
|
11150
|
+
function parseFrontmatter3(content) {
|
|
11151
|
+
const split = splitFrontmatter(content);
|
|
11152
|
+
if (!split) return null;
|
|
11153
|
+
const fm = {};
|
|
11154
|
+
for (const line of split.fields.split("\n")) {
|
|
11155
|
+
const colonIdx = line.indexOf(":");
|
|
11156
|
+
if (colonIdx === -1) continue;
|
|
11157
|
+
fm[line.slice(0, colonIdx).trim()] = line.slice(colonIdx + 1).trim();
|
|
11158
|
+
}
|
|
11159
|
+
return fm;
|
|
11160
|
+
}
|
|
11161
|
+
function extractBody2(content) {
|
|
11162
|
+
const split = splitFrontmatter(content);
|
|
11163
|
+
return split ? split.body.trim() : content.trim();
|
|
11164
|
+
}
|
|
11165
|
+
function parseBoolean2(value) {
|
|
11166
|
+
if (typeof value === "boolean") return value;
|
|
11167
|
+
if (typeof value !== "string") return false;
|
|
11168
|
+
const normalized = value.trim().toLowerCase();
|
|
11169
|
+
return normalized === "true" || normalized === "1" || normalized === "yes";
|
|
11170
|
+
}
|
|
11171
|
+
function optionalString(value) {
|
|
11172
|
+
if (typeof value !== "string") return void 0;
|
|
11173
|
+
const trimmed = value.trim();
|
|
11174
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
11175
|
+
}
|
|
11176
|
+
function parseOptionalConfidence(value) {
|
|
11177
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
|
|
11178
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
11179
|
+
const parsed = Number.parseFloat(value);
|
|
11180
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
11181
|
+
}
|
|
11182
|
+
return void 0;
|
|
11183
|
+
}
|
|
11184
|
+
|
|
11185
|
+
// src/review/review-deck-mutation.ts
|
|
11186
|
+
var ACTOR = "admin-console.review-deck";
|
|
11187
|
+
var RULE_VERSION = "admin-console.review-deck.v1";
|
|
11188
|
+
var DECK_VERSIONING = {
|
|
11189
|
+
enabled: true,
|
|
11190
|
+
maxVersionsPerPage: 20,
|
|
11191
|
+
sidecarDir: ".versions"
|
|
11192
|
+
};
|
|
11193
|
+
var KEEP_EFFECT = "Kept: this memory can now be recalled.";
|
|
11194
|
+
var NOT_TRUE_EFFECT = "Marked untrue: removed from the review queue.";
|
|
11195
|
+
var PLANNED_EFFECT = "Prepared a correction plan.";
|
|
11196
|
+
var PLAN_FAILED_EFFECT = "Could not prepare a correction plan.";
|
|
11197
|
+
var MISSING_EFFECT = "This review item is no longer available.";
|
|
11198
|
+
var CONFLICT_EFFECT = "This memory changed. Review it again.";
|
|
11199
|
+
var UNDO_EFFECT = "Undid the last review decision.";
|
|
11200
|
+
var UNDO_CONFLICT_EFFECT = "Another change happened first. Nothing was undone.";
|
|
11201
|
+
var UNDO_FAILED_EFFECT = "This action cannot be undone.";
|
|
11202
|
+
var ReviewDeckIdempotencyError = class extends Error {
|
|
11203
|
+
name = "ReviewDeckIdempotencyError";
|
|
11204
|
+
constructor(message = "Idempotency key was reused with a different review request.") {
|
|
11205
|
+
super(message);
|
|
11206
|
+
}
|
|
11207
|
+
};
|
|
11208
|
+
var ReviewDeckInputError = class extends Error {
|
|
11209
|
+
name = "ReviewDeckInputError";
|
|
11210
|
+
constructor(message) {
|
|
11211
|
+
super(message);
|
|
11212
|
+
}
|
|
11213
|
+
};
|
|
11214
|
+
var LEDGER_ACTION = {
|
|
11215
|
+
keep: "approve",
|
|
11216
|
+
not_true: "dismiss",
|
|
11217
|
+
undo: "undo"
|
|
11218
|
+
};
|
|
11219
|
+
var EVENT_TYPE = {
|
|
11220
|
+
keep: "promoted",
|
|
11221
|
+
not_true: "rejected",
|
|
11222
|
+
undo: "restored"
|
|
11223
|
+
};
|
|
11224
|
+
function sha256Hex(value) {
|
|
11225
|
+
return createHash7("sha256").update(value, "utf8").digest("hex");
|
|
11226
|
+
}
|
|
11227
|
+
function computeReceiptId(namespace, principalDigest, idempotencyKey) {
|
|
11228
|
+
return `rcp1:${sha256Hex(`${namespace}\0${principalDigest}\0${idempotencyKey}`)}`;
|
|
11229
|
+
}
|
|
11230
|
+
function computeRequestFingerprint(parts) {
|
|
11231
|
+
return `rfp1:${sha256Hex(parts.join("\0"))}`;
|
|
11232
|
+
}
|
|
11233
|
+
function actionFingerprint(ctx, itemId, action, expectedRevision, correctionText) {
|
|
11234
|
+
const parts = [ctx.principalDigest, ctx.namespace, itemId, action, expectedRevision];
|
|
11235
|
+
if (correctionText !== void 0) parts.push(correctionText);
|
|
11236
|
+
return computeRequestFingerprint(parts);
|
|
11237
|
+
}
|
|
11238
|
+
function isNonEmptyString(value) {
|
|
11239
|
+
return typeof value === "string" && value.length > 0;
|
|
11240
|
+
}
|
|
11241
|
+
function isReceiptAction(value) {
|
|
11242
|
+
return value === "approve" || value === "dismiss" || value === "undo";
|
|
11243
|
+
}
|
|
11244
|
+
function parseReviewLifecycleReceipt(value) {
|
|
11245
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
|
|
11246
|
+
const rec = value;
|
|
11247
|
+
if (rec.schemaVersion !== 1) return null;
|
|
11248
|
+
if (!isNonEmptyString(rec.receiptId)) return null;
|
|
11249
|
+
if (!isNonEmptyString(rec.requestFingerprint)) return null;
|
|
11250
|
+
if (!isNonEmptyString(rec.principalDigest)) return null;
|
|
11251
|
+
if (!isNonEmptyString(rec.itemId)) return null;
|
|
11252
|
+
if (!isReceiptAction(rec.action)) return null;
|
|
11253
|
+
if (typeof rec.beforeRevision !== "string") return null;
|
|
11254
|
+
if (typeof rec.afterRevision !== "string") return null;
|
|
11255
|
+
if (!isNonEmptyString(rec.sourcePath) || path14.isAbsolute(rec.sourcePath)) return null;
|
|
11256
|
+
if (rec.revisionArtifact !== void 0 && typeof rec.revisionArtifact !== "string") return null;
|
|
11257
|
+
if (rec.undoOfReceiptId !== void 0 && typeof rec.undoOfReceiptId !== "string") return null;
|
|
11258
|
+
const parsed = {
|
|
11259
|
+
schemaVersion: 1,
|
|
11260
|
+
receiptId: rec.receiptId,
|
|
11261
|
+
requestFingerprint: rec.requestFingerprint,
|
|
11262
|
+
principalDigest: rec.principalDigest,
|
|
11263
|
+
itemId: rec.itemId,
|
|
11264
|
+
action: rec.action,
|
|
11265
|
+
beforeRevision: rec.beforeRevision,
|
|
11266
|
+
afterRevision: rec.afterRevision,
|
|
11267
|
+
sourcePath: rec.sourcePath
|
|
11268
|
+
};
|
|
11269
|
+
if (typeof rec.revisionArtifact === "string") parsed.revisionArtifact = rec.revisionArtifact;
|
|
11270
|
+
if (typeof rec.undoOfReceiptId === "string") parsed.undoOfReceiptId = rec.undoOfReceiptId;
|
|
11271
|
+
return parsed;
|
|
11272
|
+
}
|
|
11273
|
+
function asStoredEvent(value) {
|
|
11274
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
|
|
11275
|
+
return value;
|
|
11276
|
+
}
|
|
11277
|
+
function findStoredReceipt(events, receiptId) {
|
|
11278
|
+
for (const raw of events) {
|
|
11279
|
+
const event = asStoredEvent(raw);
|
|
11280
|
+
if (!event) continue;
|
|
11281
|
+
const receipt = parseReviewLifecycleReceipt(event.reviewReceipt);
|
|
11282
|
+
if (receipt && receipt.receiptId === receiptId) return { event, receipt };
|
|
11283
|
+
}
|
|
11284
|
+
return null;
|
|
11285
|
+
}
|
|
11286
|
+
function resolveInside(memoryDir, rel) {
|
|
11287
|
+
if (!rel || path14.isAbsolute(rel)) return null;
|
|
11288
|
+
const root = path14.resolve(memoryDir);
|
|
11289
|
+
const abs = path14.resolve(root, rel.split("/").join(path14.sep));
|
|
11290
|
+
const next = path14.relative(root, abs);
|
|
11291
|
+
if (next.startsWith("..") || path14.isAbsolute(next)) return null;
|
|
11292
|
+
return abs;
|
|
11293
|
+
}
|
|
11294
|
+
function currentRevision(absPath) {
|
|
11295
|
+
try {
|
|
11296
|
+
return computeReviewItemRevision(fs3.readFileSync(absPath, "utf8"));
|
|
11297
|
+
} catch {
|
|
11298
|
+
return "";
|
|
11299
|
+
}
|
|
11300
|
+
}
|
|
11301
|
+
function publicReceipt(input) {
|
|
11302
|
+
return {
|
|
11303
|
+
schemaVersion: 1,
|
|
11304
|
+
receiptId: input.receiptId,
|
|
11305
|
+
itemId: input.itemId,
|
|
11306
|
+
action: input.action,
|
|
11307
|
+
outcome: input.outcome,
|
|
11308
|
+
effect: input.effect,
|
|
11309
|
+
undoAvailable: input.undoAvailable,
|
|
11310
|
+
...input.appliedRevision !== void 0 ? { appliedRevision: input.appliedRevision } : {},
|
|
11311
|
+
...input.correctionPlanId !== void 0 ? { correctionPlanId: input.correctionPlanId } : {},
|
|
11312
|
+
...input.correctionPreview !== void 0 ? { correctionPreview: input.correctionPreview } : {}
|
|
11313
|
+
};
|
|
11314
|
+
}
|
|
11315
|
+
async function snapshotForUndo(filePath, memoryDir) {
|
|
11316
|
+
try {
|
|
11317
|
+
const content = fs3.readFileSync(filePath, "utf8");
|
|
11318
|
+
const version = await createVersion(
|
|
11319
|
+
filePath,
|
|
11320
|
+
content,
|
|
11321
|
+
"manual",
|
|
11322
|
+
DECK_VERSIONING,
|
|
11323
|
+
void 0,
|
|
11324
|
+
void 0,
|
|
11325
|
+
memoryDir
|
|
11326
|
+
);
|
|
11327
|
+
return version.versionId;
|
|
11328
|
+
} catch {
|
|
11329
|
+
return void 0;
|
|
11330
|
+
}
|
|
11331
|
+
}
|
|
11332
|
+
async function artifactReadable(filePath, versionId, memoryDir) {
|
|
11333
|
+
try {
|
|
11334
|
+
await getVersion(filePath, versionId, DECK_VERSIONING, memoryDir);
|
|
11335
|
+
return true;
|
|
11336
|
+
} catch {
|
|
11337
|
+
return false;
|
|
11338
|
+
}
|
|
11339
|
+
}
|
|
11340
|
+
function undoTargetRevision(receipt, createdRel) {
|
|
11341
|
+
const created = createdRel && createdRel !== receipt.sourcePath ? createdRel : void 0;
|
|
11342
|
+
if (receipt.action === "approve" && created) return created;
|
|
11343
|
+
return receipt.sourcePath;
|
|
11344
|
+
}
|
|
11345
|
+
async function honestUndoAvailable(ctx, receipt, createdRel) {
|
|
11346
|
+
if (!receipt.revisionArtifact || receipt.action === "undo") return false;
|
|
11347
|
+
const sourceAbs = resolveInside(ctx.memoryDir, receipt.sourcePath);
|
|
11348
|
+
if (!sourceAbs) return false;
|
|
11349
|
+
if (!await artifactReadable(sourceAbs, receipt.revisionArtifact, ctx.memoryDir)) return false;
|
|
11350
|
+
const targetRel = undoTargetRevision(receipt, createdRel);
|
|
11351
|
+
const targetAbs = resolveInside(ctx.memoryDir, targetRel);
|
|
11352
|
+
if (!targetAbs) return false;
|
|
11353
|
+
return currentRevision(targetAbs) === receipt.afterRevision;
|
|
11354
|
+
}
|
|
11355
|
+
async function replayReceipt(ctx, hit, action) {
|
|
11356
|
+
const stored = hit.event.reviewDeckReceipt;
|
|
11357
|
+
const undoAvailable = await honestUndoAvailable(ctx, hit.receipt, hit.event.reviewCreatedPath);
|
|
11358
|
+
if (stored && stored.schemaVersion === 1 && stored.receiptId === hit.receipt.receiptId) {
|
|
11359
|
+
return {
|
|
11360
|
+
...stored,
|
|
11361
|
+
undoAvailable,
|
|
11362
|
+
appliedRevision: stored.appliedRevision ?? hit.receipt.afterRevision
|
|
11363
|
+
};
|
|
11364
|
+
}
|
|
11365
|
+
return publicReceipt({
|
|
11366
|
+
receiptId: hit.receipt.receiptId,
|
|
11367
|
+
itemId: hit.receipt.itemId,
|
|
11368
|
+
action,
|
|
11369
|
+
outcome: "applied",
|
|
11370
|
+
effect: action === "keep" ? KEEP_EFFECT : action === "not_true" ? NOT_TRUE_EFFECT : UNDO_EFFECT,
|
|
11371
|
+
undoAvailable,
|
|
11372
|
+
appliedRevision: hit.receipt.afterRevision
|
|
11373
|
+
});
|
|
11374
|
+
}
|
|
11375
|
+
function applyKeepOrNotTrueSync(input) {
|
|
11376
|
+
let current;
|
|
11377
|
+
try {
|
|
11378
|
+
current = fs3.readFileSync(input.filePath, "utf8");
|
|
11379
|
+
} catch {
|
|
11380
|
+
return { kind: "failed" };
|
|
11381
|
+
}
|
|
11382
|
+
const currentRev = computeReviewItemRevision(current);
|
|
11383
|
+
if (currentRev !== input.expectedRevision) {
|
|
11384
|
+
return { kind: "conflict", current: currentRev };
|
|
11385
|
+
}
|
|
11386
|
+
const result = performReview(
|
|
11387
|
+
input.memoryDir,
|
|
11388
|
+
input.itemId,
|
|
11389
|
+
input.action === "keep" ? "approve" : "dismiss",
|
|
11390
|
+
{ onApproveBlockedMemory: input.onApproveBlockedMemory }
|
|
11391
|
+
);
|
|
11392
|
+
if (result.message === "Item not found" || result.message === "Could not parse frontmatter") {
|
|
11393
|
+
return { kind: "failed" };
|
|
11394
|
+
}
|
|
11395
|
+
if (result.updatedPath && fs3.existsSync(result.updatedPath)) {
|
|
11396
|
+
return {
|
|
11397
|
+
kind: "applied",
|
|
11398
|
+
afterRevision: computeReviewItemRevision(fs3.readFileSync(result.updatedPath, "utf8")),
|
|
11399
|
+
createdAbs: result.updatedPath
|
|
11400
|
+
};
|
|
11401
|
+
}
|
|
11402
|
+
return { kind: "applied", afterRevision: "" };
|
|
11403
|
+
}
|
|
11404
|
+
async function appendAppliedEvent(ctx, input) {
|
|
11405
|
+
const event = {
|
|
11406
|
+
eventId: `mle-${randomUUID()}`,
|
|
11407
|
+
memoryId: input.itemId,
|
|
11408
|
+
eventType: EVENT_TYPE[input.action],
|
|
11409
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11410
|
+
actor: ACTOR,
|
|
11411
|
+
ruleVersion: RULE_VERSION,
|
|
11412
|
+
reviewReceipt: input.receipt,
|
|
11413
|
+
reviewNamespace: ctx.namespace,
|
|
11414
|
+
reviewDeckReceipt: input.publicReceipt,
|
|
11415
|
+
before: { path: input.receipt.sourcePath },
|
|
11416
|
+
...input.createdRel ? { after: { path: input.createdRel }, reviewCreatedPath: input.createdRel } : {},
|
|
11417
|
+
...input.undoOfReceiptId ? { relatedMemoryIds: [input.itemId] } : {}
|
|
11418
|
+
};
|
|
11419
|
+
await ctx.appendLifecycleEvents([event]);
|
|
11420
|
+
}
|
|
11421
|
+
async function executeReviewDeckAction(ctx, req) {
|
|
11422
|
+
throwIfAborted(ctx.signal);
|
|
11423
|
+
if (req.schemaVersion !== 1) throw new ReviewDeckInputError("schemaVersion must be 1");
|
|
11424
|
+
if (!isNonEmptyString(req.itemId)) throw new ReviewDeckInputError("itemId is required");
|
|
11425
|
+
if (!isNonEmptyString(req.revision)) throw new ReviewDeckInputError("revision is required");
|
|
11426
|
+
if (!isNonEmptyString(req.idempotencyKey)) throw new ReviewDeckInputError("idempotencyKey is required");
|
|
11427
|
+
const receiptId = computeReceiptId(ctx.namespace, ctx.principalDigest, req.idempotencyKey);
|
|
11428
|
+
if (req.action === "prepare_fix") {
|
|
11429
|
+
const correctionText = req.correctionText;
|
|
11430
|
+
if (typeof correctionText !== "string" || correctionText.trim() === "") {
|
|
11431
|
+
throw new ReviewDeckInputError("correctionText is required");
|
|
11432
|
+
}
|
|
11433
|
+
if (!ctx.planCorrection) {
|
|
11434
|
+
return publicReceipt({
|
|
11435
|
+
receiptId,
|
|
11436
|
+
itemId: req.itemId,
|
|
11437
|
+
action: "prepare_fix",
|
|
11438
|
+
outcome: "failed",
|
|
11439
|
+
effect: PLAN_FAILED_EFFECT,
|
|
11440
|
+
undoAvailable: false
|
|
11441
|
+
});
|
|
11442
|
+
}
|
|
11443
|
+
const planned = await ctx.planCorrection({ itemId: req.itemId, correctionText });
|
|
11444
|
+
if (!planned.planId) {
|
|
11445
|
+
return publicReceipt({
|
|
11446
|
+
receiptId,
|
|
11447
|
+
itemId: req.itemId,
|
|
11448
|
+
action: "prepare_fix",
|
|
11449
|
+
outcome: "failed",
|
|
11450
|
+
effect: planned.message?.trim() || PLAN_FAILED_EFFECT,
|
|
11451
|
+
undoAvailable: false
|
|
11452
|
+
});
|
|
11453
|
+
}
|
|
11454
|
+
return publicReceipt({
|
|
11455
|
+
receiptId,
|
|
11456
|
+
itemId: req.itemId,
|
|
11457
|
+
action: "prepare_fix",
|
|
11458
|
+
outcome: "planned",
|
|
11459
|
+
effect: PLANNED_EFFECT,
|
|
11460
|
+
undoAvailable: false,
|
|
11461
|
+
correctionPlanId: planned.planId,
|
|
11462
|
+
correctionPreview: planned.preview
|
|
11463
|
+
});
|
|
11464
|
+
}
|
|
11465
|
+
if (req.action !== "keep" && req.action !== "not_true") {
|
|
11466
|
+
throw new ReviewDeckInputError("unsupported review deck action");
|
|
11467
|
+
}
|
|
11468
|
+
const fingerprint = actionFingerprint(ctx, req.itemId, req.action, req.revision);
|
|
11469
|
+
const existing = findStoredReceipt(await ctx.readLifecycleEvents(), receiptId);
|
|
11470
|
+
if (existing) {
|
|
11471
|
+
if (existing.receipt.requestFingerprint !== fingerprint) throw new ReviewDeckIdempotencyError();
|
|
11472
|
+
return replayReceipt(ctx, existing, req.action);
|
|
11473
|
+
}
|
|
11474
|
+
const row = readReviewDeckRow({ memoryDir: ctx.memoryDir, itemId: req.itemId });
|
|
11475
|
+
if (!row) {
|
|
11476
|
+
return publicReceipt({
|
|
11477
|
+
receiptId,
|
|
11478
|
+
itemId: req.itemId,
|
|
11479
|
+
action: req.action,
|
|
11480
|
+
outcome: "failed",
|
|
11481
|
+
effect: MISSING_EFFECT,
|
|
11482
|
+
undoAvailable: false
|
|
11483
|
+
});
|
|
11484
|
+
}
|
|
11485
|
+
throwIfAborted(ctx.signal);
|
|
11486
|
+
const revisionArtifact = await snapshotForUndo(row.filePath, ctx.memoryDir);
|
|
11487
|
+
throwIfAborted(ctx.signal);
|
|
11488
|
+
const applied = applyKeepOrNotTrueSync({
|
|
11489
|
+
memoryDir: ctx.memoryDir,
|
|
11490
|
+
itemId: req.itemId,
|
|
11491
|
+
filePath: row.filePath,
|
|
11492
|
+
expectedRevision: req.revision,
|
|
11493
|
+
action: req.action,
|
|
11494
|
+
onApproveBlockedMemory: ctx.onApproveBlockedMemory
|
|
11495
|
+
});
|
|
11496
|
+
if (applied.kind === "conflict") {
|
|
11497
|
+
return publicReceipt({
|
|
11498
|
+
receiptId,
|
|
11499
|
+
itemId: req.itemId,
|
|
11500
|
+
action: req.action,
|
|
11501
|
+
outcome: "conflict",
|
|
11502
|
+
effect: CONFLICT_EFFECT,
|
|
11503
|
+
undoAvailable: false,
|
|
11504
|
+
appliedRevision: applied.current
|
|
11505
|
+
});
|
|
11506
|
+
}
|
|
11507
|
+
if (applied.kind === "failed") {
|
|
11508
|
+
return publicReceipt({
|
|
11509
|
+
receiptId,
|
|
11510
|
+
itemId: req.itemId,
|
|
11511
|
+
action: req.action,
|
|
11512
|
+
outcome: "failed",
|
|
11513
|
+
effect: MISSING_EFFECT,
|
|
11514
|
+
undoAvailable: false
|
|
11515
|
+
});
|
|
11516
|
+
}
|
|
11517
|
+
const sourcePath = toMemoryPathRel(ctx.memoryDir, row.filePath);
|
|
11518
|
+
const createdRel = applied.createdAbs ? toMemoryPathRel(ctx.memoryDir, applied.createdAbs) : void 0;
|
|
11519
|
+
const ledgerReceipt = {
|
|
11520
|
+
schemaVersion: 1,
|
|
11521
|
+
receiptId,
|
|
11522
|
+
requestFingerprint: fingerprint,
|
|
11523
|
+
principalDigest: ctx.principalDigest,
|
|
11524
|
+
itemId: req.itemId,
|
|
11525
|
+
action: LEDGER_ACTION[req.action],
|
|
11526
|
+
beforeRevision: req.revision,
|
|
11527
|
+
afterRevision: applied.afterRevision,
|
|
11528
|
+
sourcePath,
|
|
11529
|
+
...revisionArtifact ? { revisionArtifact } : {}
|
|
11530
|
+
};
|
|
11531
|
+
const undoAvailable = Boolean(revisionArtifact);
|
|
11532
|
+
const published = publicReceipt({
|
|
11533
|
+
receiptId,
|
|
11534
|
+
itemId: req.itemId,
|
|
11535
|
+
action: req.action,
|
|
11536
|
+
outcome: "applied",
|
|
11537
|
+
effect: req.action === "keep" ? KEEP_EFFECT : NOT_TRUE_EFFECT,
|
|
11538
|
+
undoAvailable,
|
|
11539
|
+
appliedRevision: applied.afterRevision
|
|
11540
|
+
});
|
|
11541
|
+
await appendAppliedEvent(ctx, {
|
|
11542
|
+
itemId: req.itemId,
|
|
11543
|
+
action: req.action,
|
|
11544
|
+
receipt: ledgerReceipt,
|
|
11545
|
+
createdRel,
|
|
11546
|
+
publicReceipt: published
|
|
11547
|
+
});
|
|
11548
|
+
return published;
|
|
11549
|
+
}
|
|
11550
|
+
async function executeReviewDeckUndo(ctx, req) {
|
|
11551
|
+
throwIfAborted(ctx.signal);
|
|
11552
|
+
if (req.schemaVersion !== 1) throw new ReviewDeckInputError("schemaVersion must be 1");
|
|
11553
|
+
if (!isNonEmptyString(req.receiptId)) throw new ReviewDeckInputError("receiptId is required");
|
|
11554
|
+
if (typeof req.expectedRevision !== "string") throw new ReviewDeckInputError("expectedRevision is required");
|
|
11555
|
+
if (!isNonEmptyString(req.idempotencyKey)) throw new ReviewDeckInputError("idempotencyKey is required");
|
|
11556
|
+
const undoReceiptId = computeReceiptId(ctx.namespace, ctx.principalDigest, req.idempotencyKey);
|
|
11557
|
+
const events = await ctx.readLifecycleEvents();
|
|
11558
|
+
const original = findStoredReceipt(events, req.receiptId);
|
|
11559
|
+
if (!original) {
|
|
11560
|
+
return publicReceipt({
|
|
11561
|
+
receiptId: undoReceiptId,
|
|
11562
|
+
itemId: "",
|
|
11563
|
+
action: "undo",
|
|
11564
|
+
outcome: "failed",
|
|
11565
|
+
effect: UNDO_FAILED_EFFECT,
|
|
11566
|
+
undoAvailable: false
|
|
11567
|
+
});
|
|
11568
|
+
}
|
|
11569
|
+
const scopeOk = original.receipt.principalDigest === ctx.principalDigest && original.event.reviewNamespace === ctx.namespace;
|
|
11570
|
+
if (!scopeOk) {
|
|
11571
|
+
return publicReceipt({
|
|
11572
|
+
receiptId: undoReceiptId,
|
|
11573
|
+
itemId: "",
|
|
11574
|
+
action: "undo",
|
|
11575
|
+
outcome: "failed",
|
|
11576
|
+
effect: UNDO_FAILED_EFFECT,
|
|
11577
|
+
undoAvailable: false
|
|
11578
|
+
});
|
|
11579
|
+
}
|
|
11580
|
+
const fingerprint = actionFingerprint(
|
|
11581
|
+
ctx,
|
|
11582
|
+
original.receipt.itemId,
|
|
11583
|
+
"undo",
|
|
11584
|
+
req.expectedRevision
|
|
11585
|
+
);
|
|
11586
|
+
const priorUndo = findStoredReceipt(events, undoReceiptId);
|
|
11587
|
+
if (priorUndo) {
|
|
11588
|
+
if (priorUndo.receipt.requestFingerprint !== fingerprint) throw new ReviewDeckIdempotencyError();
|
|
11589
|
+
return replayReceipt(ctx, priorUndo, "undo");
|
|
11590
|
+
}
|
|
11591
|
+
if (req.expectedRevision !== original.receipt.afterRevision) {
|
|
11592
|
+
return publicReceipt({
|
|
11593
|
+
receiptId: undoReceiptId,
|
|
11594
|
+
itemId: original.receipt.itemId,
|
|
11595
|
+
action: "undo",
|
|
11596
|
+
outcome: "conflict",
|
|
11597
|
+
effect: UNDO_CONFLICT_EFFECT,
|
|
11598
|
+
undoAvailable: false
|
|
11599
|
+
});
|
|
11600
|
+
}
|
|
11601
|
+
const createdRel = original.event.reviewCreatedPath;
|
|
11602
|
+
const targetRel = undoTargetRevision(original.receipt, createdRel);
|
|
11603
|
+
const targetAbs = resolveInside(ctx.memoryDir, targetRel);
|
|
11604
|
+
const sourceAbs = resolveInside(ctx.memoryDir, original.receipt.sourcePath);
|
|
11605
|
+
if (!targetAbs || !sourceAbs) {
|
|
11606
|
+
return publicReceipt({
|
|
11607
|
+
receiptId: undoReceiptId,
|
|
11608
|
+
itemId: original.receipt.itemId,
|
|
11609
|
+
action: "undo",
|
|
11610
|
+
outcome: "failed",
|
|
11611
|
+
effect: UNDO_FAILED_EFFECT,
|
|
11612
|
+
undoAvailable: false
|
|
11613
|
+
});
|
|
11614
|
+
}
|
|
11615
|
+
if (currentRevision(targetAbs) !== original.receipt.afterRevision) {
|
|
11616
|
+
return publicReceipt({
|
|
11617
|
+
receiptId: undoReceiptId,
|
|
11618
|
+
itemId: original.receipt.itemId,
|
|
11619
|
+
action: "undo",
|
|
11620
|
+
outcome: "conflict",
|
|
11621
|
+
effect: UNDO_CONFLICT_EFFECT,
|
|
11622
|
+
undoAvailable: false,
|
|
11623
|
+
appliedRevision: currentRevision(targetAbs)
|
|
11624
|
+
});
|
|
11625
|
+
}
|
|
11626
|
+
if (!original.receipt.revisionArtifact) {
|
|
11627
|
+
return publicReceipt({
|
|
11628
|
+
receiptId: undoReceiptId,
|
|
11629
|
+
itemId: original.receipt.itemId,
|
|
11630
|
+
action: "undo",
|
|
11631
|
+
outcome: "failed",
|
|
11632
|
+
effect: UNDO_FAILED_EFFECT,
|
|
11633
|
+
undoAvailable: false
|
|
11634
|
+
});
|
|
11635
|
+
}
|
|
11636
|
+
throwIfAborted(ctx.signal);
|
|
11637
|
+
try {
|
|
11638
|
+
await revertToVersion(
|
|
11639
|
+
sourceAbs,
|
|
11640
|
+
original.receipt.revisionArtifact,
|
|
11641
|
+
DECK_VERSIONING,
|
|
11642
|
+
void 0,
|
|
11643
|
+
ctx.memoryDir
|
|
11644
|
+
);
|
|
11645
|
+
} catch {
|
|
11646
|
+
return publicReceipt({
|
|
11647
|
+
receiptId: undoReceiptId,
|
|
11648
|
+
itemId: original.receipt.itemId,
|
|
11649
|
+
action: "undo",
|
|
11650
|
+
outcome: "failed",
|
|
11651
|
+
effect: UNDO_FAILED_EFFECT,
|
|
11652
|
+
undoAvailable: false
|
|
11653
|
+
});
|
|
11654
|
+
}
|
|
11655
|
+
if (createdRel && createdRel !== original.receipt.sourcePath) {
|
|
11656
|
+
const createdAbs = resolveInside(ctx.memoryDir, createdRel);
|
|
11657
|
+
if (createdAbs && createdAbs !== sourceAbs && fs3.existsSync(createdAbs)) {
|
|
11658
|
+
fs3.unlinkSync(createdAbs);
|
|
11659
|
+
}
|
|
11660
|
+
}
|
|
11661
|
+
bumpMemoryCorpusVersionForDir(ctx.memoryDir);
|
|
11662
|
+
const afterRevision = currentRevision(sourceAbs);
|
|
11663
|
+
const ledgerReceipt = {
|
|
11664
|
+
schemaVersion: 1,
|
|
11665
|
+
receiptId: undoReceiptId,
|
|
11666
|
+
requestFingerprint: fingerprint,
|
|
11667
|
+
principalDigest: ctx.principalDigest,
|
|
11668
|
+
itemId: original.receipt.itemId,
|
|
11669
|
+
action: "undo",
|
|
11670
|
+
beforeRevision: original.receipt.afterRevision,
|
|
11671
|
+
afterRevision,
|
|
11672
|
+
sourcePath: original.receipt.sourcePath,
|
|
11673
|
+
undoOfReceiptId: original.receipt.receiptId
|
|
11674
|
+
};
|
|
11675
|
+
const published = publicReceipt({
|
|
11676
|
+
receiptId: undoReceiptId,
|
|
11677
|
+
itemId: original.receipt.itemId,
|
|
11678
|
+
action: "undo",
|
|
11679
|
+
outcome: "applied",
|
|
11680
|
+
effect: UNDO_EFFECT,
|
|
11681
|
+
undoAvailable: false,
|
|
11682
|
+
appliedRevision: afterRevision
|
|
11683
|
+
});
|
|
11684
|
+
await appendAppliedEvent(ctx, {
|
|
11685
|
+
itemId: original.receipt.itemId,
|
|
11686
|
+
action: "undo",
|
|
11687
|
+
receipt: ledgerReceipt,
|
|
11688
|
+
publicReceipt: published,
|
|
11689
|
+
undoOfReceiptId: original.receipt.receiptId
|
|
11690
|
+
});
|
|
11691
|
+
return published;
|
|
11692
|
+
}
|
|
11693
|
+
|
|
11694
|
+
// src/review/review-deck-surface.ts
|
|
11695
|
+
function digest(value) {
|
|
11696
|
+
return createHash8("sha256").update(value).digest("hex");
|
|
11697
|
+
}
|
|
11698
|
+
var ReviewDeckSurface = class {
|
|
11699
|
+
constructor(deps) {
|
|
11700
|
+
this.deps = deps;
|
|
11701
|
+
}
|
|
11702
|
+
deps;
|
|
11703
|
+
async list(opts) {
|
|
11704
|
+
const namespace = this.deps.resolveReadableNamespace(opts.namespace, opts.principal);
|
|
11705
|
+
const storage = await this.deps.orchestrator.getStorage(namespace);
|
|
11706
|
+
const snapshot = readReviewDeckSnapshot({ memoryDir: storage.dir, namespace });
|
|
11707
|
+
try {
|
|
11708
|
+
return buildReviewDeckPage(snapshot.rows, {
|
|
11709
|
+
scope: {
|
|
11710
|
+
principalDigest: digest(opts.principal ?? ""),
|
|
11711
|
+
namespace,
|
|
11712
|
+
filterDigest: digest(""),
|
|
11713
|
+
corpusVersion: snapshot.corpusVersion
|
|
11714
|
+
},
|
|
11715
|
+
cursor: opts.cursor,
|
|
11716
|
+
limit: opts.limit
|
|
11717
|
+
});
|
|
11718
|
+
} catch (error) {
|
|
11719
|
+
if (error instanceof ReviewDeckCursorError) {
|
|
11720
|
+
throw new EngramAccessInputError(error.message);
|
|
11721
|
+
}
|
|
11722
|
+
throw error;
|
|
11723
|
+
}
|
|
11724
|
+
}
|
|
11725
|
+
async action(req, opts) {
|
|
11726
|
+
return executeReviewDeckAction(await this.mutationContext(opts), req);
|
|
11727
|
+
}
|
|
11728
|
+
async undo(req, opts) {
|
|
11729
|
+
return executeReviewDeckUndo(await this.mutationContext(opts), req);
|
|
11730
|
+
}
|
|
11731
|
+
async mutationContext(opts) {
|
|
11732
|
+
const namespace = this.deps.writableNamespaceFor(opts.namespace, void 0, opts.principal);
|
|
11733
|
+
this.deps.resolveReadableNamespace(namespace, opts.principal);
|
|
11734
|
+
const storage = await this.deps.orchestrator.getStorage(namespace);
|
|
11735
|
+
return {
|
|
11736
|
+
memoryDir: storage.dir,
|
|
11737
|
+
namespace,
|
|
11738
|
+
principalDigest: digest(opts.principal ?? ""),
|
|
11739
|
+
appendLifecycleEvents: async (events) => {
|
|
11740
|
+
await storage.appendMemoryLifecycleEvents(events);
|
|
11741
|
+
},
|
|
11742
|
+
readLifecycleEvents: (memoryId) => memoryId ? storage.getMemoryTimeline(memoryId) : storage.readMemoryLifecycleEvents(),
|
|
11743
|
+
onApproveBlockedMemory: (tombstoneId) => {
|
|
11744
|
+
void storage.revokeTombstone(tombstoneId, "user_correction").catch(() => void 0);
|
|
11745
|
+
},
|
|
11746
|
+
planCorrection: async ({ itemId, correctionText }) => {
|
|
11747
|
+
const plan = await this.deps.correctionPlan(
|
|
11748
|
+
{
|
|
11749
|
+
text: correctionText,
|
|
11750
|
+
targetIds: [itemId],
|
|
11751
|
+
principal: opts.principal,
|
|
11752
|
+
namespace
|
|
11753
|
+
},
|
|
11754
|
+
opts.signal ? { abortSignal: opts.signal } : void 0
|
|
11755
|
+
);
|
|
11756
|
+
return { planId: plan.planId, preview: plan };
|
|
11757
|
+
},
|
|
11758
|
+
signal: opts.signal
|
|
11759
|
+
};
|
|
11760
|
+
}
|
|
11761
|
+
};
|
|
11762
|
+
|
|
11763
|
+
// src/support-passport/card-service.ts
|
|
11764
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
11765
|
+
|
|
11766
|
+
// src/support-passport/errors.ts
|
|
11767
|
+
var SupportPassportError = class extends Error {
|
|
11768
|
+
code;
|
|
11769
|
+
status;
|
|
11770
|
+
constructor(code, message, status) {
|
|
11771
|
+
super(message);
|
|
11772
|
+
this.name = "SupportPassportError";
|
|
11773
|
+
this.code = code;
|
|
11774
|
+
this.status = status;
|
|
11775
|
+
}
|
|
11776
|
+
};
|
|
11777
|
+
|
|
11778
|
+
// src/support-passport/card-state.ts
|
|
11779
|
+
function invalidInput() {
|
|
11780
|
+
return new SupportPassportError("invalid_input", "The support card request is invalid.", 400);
|
|
11781
|
+
}
|
|
11782
|
+
function isStorageConflict(error) {
|
|
11783
|
+
return error instanceof SupportPassportError && error.code === "storage_conflict";
|
|
11784
|
+
}
|
|
11785
|
+
function once(callback) {
|
|
11786
|
+
let called = false;
|
|
11787
|
+
return () => {
|
|
11788
|
+
if (called) return;
|
|
11789
|
+
called = true;
|
|
11790
|
+
callback?.();
|
|
11791
|
+
};
|
|
11792
|
+
}
|
|
11793
|
+
function validateOwnerScope(owner, principal) {
|
|
11794
|
+
const requestedPrincipal = SupportPassportListCardsInputSchema.safeParse({ principal });
|
|
11795
|
+
const namespace = SupportPassportNamespaceSchema.safeParse(owner.namespace);
|
|
11796
|
+
const ownerPrincipal = SupportPassportListCardsInputSchema.safeParse({ principal: owner.principal });
|
|
11797
|
+
if (!requestedPrincipal.success || !namespace.success || !ownerPrincipal.success || ownerPrincipal.data.principal !== requestedPrincipal.data.principal) {
|
|
11798
|
+
throw new SupportPassportError("card_data_invalid", "The support passport owner scope is invalid.", 500);
|
|
11799
|
+
}
|
|
11800
|
+
return { ...owner, principal: ownerPrincipal.data.principal, namespace: namespace.data };
|
|
11801
|
+
}
|
|
11802
|
+
var MAX_OWNER_VISIBLE_CARDS = 100;
|
|
11803
|
+
var OWNER_VISIBLE_STATUSES = /* @__PURE__ */ new Set(["pending_review", "active"]);
|
|
11804
|
+
function revisionFor(card, status, updatedAt) {
|
|
11805
|
+
return computeSupportPassportCardRevision({
|
|
11806
|
+
cardId: card.cardId,
|
|
11807
|
+
title: card.title,
|
|
11808
|
+
statement: card.statement,
|
|
11809
|
+
category: card.category,
|
|
11810
|
+
status,
|
|
11811
|
+
updatedAt,
|
|
11812
|
+
reviewBy: card.reviewBy
|
|
11813
|
+
});
|
|
11814
|
+
}
|
|
11815
|
+
function projectRequiredCard(memory, namespace, principal) {
|
|
11816
|
+
const card = projectSupportPassportCard(memory);
|
|
11817
|
+
if (!card) throw new SupportPassportError("card_data_invalid", "The support card data is invalid.", 500);
|
|
11818
|
+
if (card.namespace !== namespace || card.owner !== computeSupportPassportOwnerKey(principal)) {
|
|
11819
|
+
throw new SupportPassportError("card_not_found", "The support card was not found.", 404);
|
|
11820
|
+
}
|
|
11821
|
+
return card;
|
|
11822
|
+
}
|
|
11823
|
+
function projectOwnedCard(memory, namespace, principal) {
|
|
11824
|
+
const card = projectSupportPassportCard(memory);
|
|
11825
|
+
return card?.namespace === namespace && card.owner === computeSupportPassportOwnerKey(principal) ? card : null;
|
|
11826
|
+
}
|
|
11827
|
+
function ownsMemory(memory, namespace, principal) {
|
|
11828
|
+
const attributes = memory.frontmatter.structuredAttributes;
|
|
11829
|
+
return attributes !== void 0 && decodeSupportPassportNamespaceAttributes(attributes) === namespace && attributes[SUPPORT_PASSPORT_ATTRIBUTE_KEYS.owner] === computeSupportPassportOwnerKey(principal);
|
|
11830
|
+
}
|
|
11831
|
+
function requireRevision(card, expectedRevision) {
|
|
11832
|
+
if (card.card.revision !== expectedRevision) {
|
|
11833
|
+
throw new SupportPassportError("revision_conflict", "The support card changed after it was loaded.", 409);
|
|
11834
|
+
}
|
|
11835
|
+
}
|
|
11836
|
+
function requireStatus(card, status) {
|
|
11837
|
+
if (card.card.status !== status) {
|
|
11838
|
+
throw new SupportPassportError("invalid_card_status", `The support card must have status ${status}.`, 409);
|
|
11839
|
+
}
|
|
11840
|
+
}
|
|
11841
|
+
function ownerVisibleCards(storedCards) {
|
|
11842
|
+
const visibleCards = storedCards.filter(
|
|
11843
|
+
(item) => OWNER_VISIBLE_STATUSES.has(item.card.status) && !item.draftReplacementPrepared
|
|
11844
|
+
);
|
|
11845
|
+
if (visibleCards.length <= MAX_OWNER_VISIBLE_CARDS) return visibleCards;
|
|
11846
|
+
const cardsWithPendingReplacements = new Set(
|
|
11847
|
+
visibleCards.filter((item) => item.card.status === "pending_review").map((item) => item.memory.frontmatter.supersedes).filter((cardId) => typeof cardId === "string")
|
|
11848
|
+
);
|
|
11849
|
+
return visibleCards.filter(
|
|
11850
|
+
(item) => item.card.status !== "active" || !cardsWithPendingReplacements.has(item.card.cardId)
|
|
11851
|
+
);
|
|
11852
|
+
}
|
|
11853
|
+
function ownerListCards(storedCards) {
|
|
11854
|
+
const visibleCards = ownerVisibleCards(storedCards);
|
|
11855
|
+
const byId = new Map(storedCards.map((item) => [item.card.cardId, item]));
|
|
11856
|
+
const activeReplacementPredecessors = activeSupportPassportReplacementPredecessorIds(visibleCards);
|
|
11857
|
+
const replacedDraftIds = new Set(
|
|
11858
|
+
visibleCards.filter(
|
|
10088
11859
|
(item) => item.card.status === "pending_review" && item.replacesDraftId !== void 0 && byId.get(item.replacesDraftId)?.card.status === "pending_review"
|
|
10089
11860
|
).map((item) => item.replacesDraftId)
|
|
10090
11861
|
);
|
|
@@ -10180,14 +11951,14 @@ async function completeSupportPassportReplacementPrior(input) {
|
|
|
10180
11951
|
}
|
|
10181
11952
|
|
|
10182
11953
|
// src/support-passport/generated-batch.ts
|
|
10183
|
-
import
|
|
11954
|
+
import path16 from "path";
|
|
10184
11955
|
import { z as z2 } from "zod";
|
|
10185
11956
|
|
|
10186
11957
|
// src/support-passport/private-file.ts
|
|
10187
|
-
import { randomUUID } from "crypto";
|
|
11958
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
10188
11959
|
import { constants as fsConstants } from "fs";
|
|
10189
11960
|
import { lstat as lstat3, mkdir as mkdir3, open, rename as rename2, rm as rm2, stat as stat2 } from "fs/promises";
|
|
10190
|
-
import
|
|
11961
|
+
import path15 from "path";
|
|
10191
11962
|
var UNSUPPORTED_DIRECTORY_SYNC_ERRORS = /* @__PURE__ */ new Set(["EINVAL", "ENOSYS", "ENOTSUP", "EOPNOTSUPP"]);
|
|
10192
11963
|
var NON_WRITABLE_ANCESTOR_SYNC_ERRORS = /* @__PURE__ */ new Set(["EROFS", "EPERM", "EACCES"]);
|
|
10193
11964
|
function assertStableDirectory(before, opened, after, errorMessage) {
|
|
@@ -10213,8 +11984,8 @@ function openFlags(...flags) {
|
|
|
10213
11984
|
return combined;
|
|
10214
11985
|
}
|
|
10215
11986
|
function assertContainedPath(trustedRoot, directory, errorMessage) {
|
|
10216
|
-
const relative2 =
|
|
10217
|
-
if (relative2 === ".." || relative2.startsWith(`..${
|
|
11987
|
+
const relative2 = path15.relative(path15.resolve(trustedRoot), path15.resolve(directory));
|
|
11988
|
+
if (relative2 === ".." || relative2.startsWith(`..${path15.sep}`) || path15.isAbsolute(relative2)) {
|
|
10218
11989
|
throw new Error(errorMessage);
|
|
10219
11990
|
}
|
|
10220
11991
|
}
|
|
@@ -10247,7 +12018,7 @@ async function syncDirectoryHandle(handle) {
|
|
|
10247
12018
|
}
|
|
10248
12019
|
async function resolvePrivateDirectoryPath(directory, handle, opened, errorMessage, platform = process.platform) {
|
|
10249
12020
|
const descriptorRoot = requirePrivateFileDescriptorRoot(platform, errorMessage);
|
|
10250
|
-
const pinnedPath =
|
|
12021
|
+
const pinnedPath = path15.join(descriptorRoot, String(handle.fd));
|
|
10251
12022
|
const metadata = await stat2(pinnedPath);
|
|
10252
12023
|
if (!metadata.isDirectory() || metadata.dev !== opened.dev || metadata.ino !== opened.ino) {
|
|
10253
12024
|
throw new Error(errorMessage);
|
|
@@ -10263,12 +12034,12 @@ function requirePrivateFileDescriptorRoot(platform, errorMessage) {
|
|
|
10263
12034
|
throw new Error(errorMessage);
|
|
10264
12035
|
}
|
|
10265
12036
|
async function openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform = process.platform) {
|
|
10266
|
-
const root =
|
|
10267
|
-
const target =
|
|
12037
|
+
const root = path15.resolve(trustedRoot);
|
|
12038
|
+
const target = path15.resolve(directory);
|
|
10268
12039
|
assertContainedPath(root, target, errorMessage);
|
|
10269
12040
|
requirePrivateFileDescriptorRoot(platform, errorMessage);
|
|
10270
|
-
const relative2 =
|
|
10271
|
-
const components = relative2 === "" ? [] : relative2.split(
|
|
12041
|
+
const relative2 = path15.relative(root, target);
|
|
12042
|
+
const components = relative2 === "" ? [] : relative2.split(path15.sep);
|
|
10272
12043
|
const handles = [];
|
|
10273
12044
|
let currentPath = root;
|
|
10274
12045
|
try {
|
|
@@ -10276,10 +12047,10 @@ async function openStableDirectoryFromRoot(trustedRoot, directory, errorMessage,
|
|
|
10276
12047
|
handles.push(current.handle);
|
|
10277
12048
|
for (const component of components) {
|
|
10278
12049
|
const pinnedParent = await resolvePrivateDirectoryPath(currentPath, current.handle, current.opened, errorMessage);
|
|
10279
|
-
const child = await openDirectoryNoFollow(
|
|
12050
|
+
const child = await openDirectoryNoFollow(path15.join(pinnedParent, component), errorMessage);
|
|
10280
12051
|
handles.push(child.handle);
|
|
10281
12052
|
assertStableDirectory(current.before, current.opened, await lstat3(currentPath), errorMessage);
|
|
10282
|
-
currentPath =
|
|
12053
|
+
currentPath = path15.join(currentPath, component);
|
|
10283
12054
|
current = child;
|
|
10284
12055
|
}
|
|
10285
12056
|
assertStableDirectory(current.before, current.opened, await lstat3(target), errorMessage);
|
|
@@ -10300,12 +12071,12 @@ async function openStableDirectoryFromRoot(trustedRoot, directory, errorMessage,
|
|
|
10300
12071
|
}
|
|
10301
12072
|
}
|
|
10302
12073
|
async function ensurePrivateDirectoryNoFollow(trustedRoot, directory, errorMessage, syncVerifiedParent = syncDirectoryHandle, hardenExistingChildren = true, platform = process.platform) {
|
|
10303
|
-
const root =
|
|
10304
|
-
const target =
|
|
12074
|
+
const root = path15.resolve(trustedRoot);
|
|
12075
|
+
const target = path15.resolve(directory);
|
|
10305
12076
|
assertContainedPath(root, target, errorMessage);
|
|
10306
|
-
const relative2 =
|
|
12077
|
+
const relative2 = path15.relative(root, target);
|
|
10307
12078
|
requirePrivateFileDescriptorRoot(platform, errorMessage);
|
|
10308
|
-
const components = relative2 === "" ? [] : relative2.split(
|
|
12079
|
+
const components = relative2 === "" ? [] : relative2.split(path15.sep);
|
|
10309
12080
|
const handles = [];
|
|
10310
12081
|
let currentPath = root;
|
|
10311
12082
|
try {
|
|
@@ -10313,7 +12084,7 @@ async function ensurePrivateDirectoryNoFollow(trustedRoot, directory, errorMessa
|
|
|
10313
12084
|
handles.push(current.handle);
|
|
10314
12085
|
for (const component of components) {
|
|
10315
12086
|
const pinnedParent = await resolvePrivateDirectoryPath(currentPath, current.handle, current.opened, errorMessage);
|
|
10316
|
-
const childPath =
|
|
12087
|
+
const childPath = path15.join(pinnedParent, component);
|
|
10317
12088
|
let created = false;
|
|
10318
12089
|
try {
|
|
10319
12090
|
await mkdir3(childPath, { mode: 448 });
|
|
@@ -10328,7 +12099,7 @@ async function ensurePrivateDirectoryNoFollow(trustedRoot, directory, errorMessa
|
|
|
10328
12099
|
await child.handle.chmod(448);
|
|
10329
12100
|
}
|
|
10330
12101
|
assertStableDirectory(current.before, current.opened, await lstat3(currentPath), errorMessage);
|
|
10331
|
-
currentPath =
|
|
12102
|
+
currentPath = path15.join(currentPath, component);
|
|
10332
12103
|
current = child;
|
|
10333
12104
|
}
|
|
10334
12105
|
assertStableDirectory(current.before, current.opened, await lstat3(target), errorMessage);
|
|
@@ -10337,8 +12108,8 @@ async function ensurePrivateDirectoryNoFollow(trustedRoot, directory, errorMessa
|
|
|
10337
12108
|
}
|
|
10338
12109
|
}
|
|
10339
12110
|
async function ensurePrivateDirectoryTreeNoFollow(directory, errorMessage, syncVerifiedParent = syncDirectoryHandle, platform = process.platform) {
|
|
10340
|
-
const target =
|
|
10341
|
-
const filesystemRoot =
|
|
12111
|
+
const target = path15.resolve(directory);
|
|
12112
|
+
const filesystemRoot = path15.parse(target).root;
|
|
10342
12113
|
const rootMetadata = await stat2(filesystemRoot);
|
|
10343
12114
|
await ensurePrivateDirectoryNoFollow(
|
|
10344
12115
|
filesystemRoot,
|
|
@@ -10373,15 +12144,15 @@ async function withPrivateDirectoryNoFollow(trustedRoot, directory, errorMessage
|
|
|
10373
12144
|
}
|
|
10374
12145
|
}
|
|
10375
12146
|
async function readPrivateFileNoFollow(directory, filePath, errorMessage, trustedRoot = directory, platform = process.platform) {
|
|
10376
|
-
if (
|
|
10377
|
-
const targetName =
|
|
12147
|
+
if (path15.dirname(filePath) !== path15.resolve(directory)) throw new Error(errorMessage);
|
|
12148
|
+
const targetName = path15.basename(filePath);
|
|
10378
12149
|
let directoryHandles = [];
|
|
10379
12150
|
let fileHandle;
|
|
10380
12151
|
try {
|
|
10381
12152
|
const stableDirectory = await openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform);
|
|
10382
12153
|
directoryHandles = stableDirectory.handles;
|
|
10383
12154
|
const pinnedDirectory = stableDirectory.pinnedDirectory;
|
|
10384
|
-
const targetPath =
|
|
12155
|
+
const targetPath = path15.join(pinnedDirectory, targetName);
|
|
10385
12156
|
const before = await lstat3(targetPath);
|
|
10386
12157
|
if (before.isSymbolicLink() || !before.isFile()) throw new Error(errorMessage);
|
|
10387
12158
|
try {
|
|
@@ -10400,10 +12171,10 @@ async function readPrivateFileNoFollow(directory, filePath, errorMessage, truste
|
|
|
10400
12171
|
}
|
|
10401
12172
|
}
|
|
10402
12173
|
async function appendPrivateFileAtPinnedDirectory(pinnedDirectory, targetName, content, errorMessage, directoryHandle, openFile) {
|
|
10403
|
-
if (targetName.length === 0 || targetName === "." || targetName === ".." ||
|
|
12174
|
+
if (targetName.length === 0 || targetName === "." || targetName === ".." || path15.basename(targetName) !== targetName) {
|
|
10404
12175
|
throw new Error(errorMessage);
|
|
10405
12176
|
}
|
|
10406
|
-
const targetPath =
|
|
12177
|
+
const targetPath = path15.join(pinnedDirectory, targetName);
|
|
10407
12178
|
let fileHandle;
|
|
10408
12179
|
try {
|
|
10409
12180
|
try {
|
|
@@ -10439,8 +12210,8 @@ async function appendPrivateFileAtPinnedDirectory(pinnedDirectory, targetName, c
|
|
|
10439
12210
|
}
|
|
10440
12211
|
async function appendPrivateFileInPinnedDirectory(pinnedDirectory, fileName, content, errorMessage, platform = process.platform) {
|
|
10441
12212
|
const descriptorRoot = requirePrivateFileDescriptorRoot(platform, errorMessage);
|
|
10442
|
-
const resolvedDirectory =
|
|
10443
|
-
const descriptor =
|
|
12213
|
+
const resolvedDirectory = path15.resolve(pinnedDirectory);
|
|
12214
|
+
const descriptor = path15.relative(descriptorRoot, resolvedDirectory);
|
|
10444
12215
|
if (!/^\d+$/.test(descriptor)) throw new Error(errorMessage);
|
|
10445
12216
|
const before = await stat2(resolvedDirectory);
|
|
10446
12217
|
if (!before.isDirectory()) throw new Error(errorMessage);
|
|
@@ -10456,9 +12227,9 @@ async function appendPrivateFileInPinnedDirectory(pinnedDirectory, fileName, con
|
|
|
10456
12227
|
}
|
|
10457
12228
|
}
|
|
10458
12229
|
async function writePrivateFileAtomicallyNoFollow(directory, filePath, content, errorMessage, trustedRoot = directory, platform = process.platform, syncVerifiedDirectory = syncDirectoryHandle) {
|
|
10459
|
-
if (
|
|
10460
|
-
const targetName =
|
|
10461
|
-
const tempName = `.${targetName}.${
|
|
12230
|
+
if (path15.dirname(filePath) !== path15.resolve(directory)) throw new Error(errorMessage);
|
|
12231
|
+
const targetName = path15.basename(filePath);
|
|
12232
|
+
const tempName = `.${targetName}.${randomUUID2()}.tmp`;
|
|
10462
12233
|
let tempPath;
|
|
10463
12234
|
let directoryHandles = [];
|
|
10464
12235
|
let fileHandle;
|
|
@@ -10466,8 +12237,8 @@ async function writePrivateFileAtomicallyNoFollow(directory, filePath, content,
|
|
|
10466
12237
|
const stableDirectory = await openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform);
|
|
10467
12238
|
directoryHandles = stableDirectory.handles;
|
|
10468
12239
|
const pinnedDirectory = stableDirectory.pinnedDirectory;
|
|
10469
|
-
tempPath =
|
|
10470
|
-
const targetPath =
|
|
12240
|
+
tempPath = path15.join(pinnedDirectory, tempName);
|
|
12241
|
+
const targetPath = path15.join(pinnedDirectory, targetName);
|
|
10471
12242
|
try {
|
|
10472
12243
|
fileHandle = await open(
|
|
10473
12244
|
tempPath,
|
|
@@ -10504,7 +12275,7 @@ async function writePrivateFileAtomicallyNoFollow(directory, filePath, content,
|
|
|
10504
12275
|
}
|
|
10505
12276
|
async function removePrivateFilesNoFollow(directory, fileNames, errorMessage, trustedRoot = directory, platform = process.platform) {
|
|
10506
12277
|
if (fileNames.some(
|
|
10507
|
-
(fileName) => fileName.length === 0 || fileName === "." || fileName === ".." ||
|
|
12278
|
+
(fileName) => fileName.length === 0 || fileName === "." || fileName === ".." || path15.basename(fileName) !== fileName
|
|
10508
12279
|
)) {
|
|
10509
12280
|
throw new Error(errorMessage);
|
|
10510
12281
|
}
|
|
@@ -10514,7 +12285,7 @@ async function removePrivateFilesNoFollow(directory, fileNames, errorMessage, tr
|
|
|
10514
12285
|
directoryHandles = stableDirectory.handles;
|
|
10515
12286
|
const pinnedDirectory = stableDirectory.pinnedDirectory;
|
|
10516
12287
|
for (const fileName of fileNames) {
|
|
10517
|
-
await rm2(
|
|
12288
|
+
await rm2(path15.join(pinnedDirectory, fileName), { force: true });
|
|
10518
12289
|
}
|
|
10519
12290
|
assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat3(directory), errorMessage);
|
|
10520
12291
|
if (stableDirectory.handle) await syncDirectoryHandle(stableDirectory.handle);
|
|
@@ -10535,13 +12306,13 @@ var GeneratedBatchMarkerSchema = z2.object({
|
|
|
10535
12306
|
}).strict();
|
|
10536
12307
|
var BATCH_ERROR = "The generated draft batch state is not safe.";
|
|
10537
12308
|
function batchDirectory(storage) {
|
|
10538
|
-
return
|
|
12309
|
+
return path16.join(storage.dir, "state", "support-passport", "generated-batches");
|
|
10539
12310
|
}
|
|
10540
12311
|
function batchFileName(batchId) {
|
|
10541
12312
|
return `${BatchIdSchema.parse(batchId)}.json`;
|
|
10542
12313
|
}
|
|
10543
12314
|
function batchPath(storage, batchId) {
|
|
10544
|
-
return
|
|
12315
|
+
return path16.join(batchDirectory(storage), batchFileName(batchId));
|
|
10545
12316
|
}
|
|
10546
12317
|
function markerFor(context, batchId, size, complete) {
|
|
10547
12318
|
return GeneratedBatchMarkerSchema.parse({
|
|
@@ -10965,19 +12736,19 @@ var SupportPassportAnswerModelInputSchema = z4.object({
|
|
|
10965
12736
|
}).strict();
|
|
10966
12737
|
|
|
10967
12738
|
// src/support-passport/owner-lock.ts
|
|
10968
|
-
import { createHash as
|
|
10969
|
-
import
|
|
12739
|
+
import { createHash as createHash9 } from "crypto";
|
|
12740
|
+
import path17 from "path";
|
|
10970
12741
|
var CARD_MUTATION_LOCK_STALE_MS = 6e4;
|
|
10971
12742
|
var CARD_MUTATION_LOCK_MAX_WAIT_MS = 3e4;
|
|
10972
12743
|
function computeSupportPassportOwnerLockKey(namespace, principal) {
|
|
10973
|
-
return
|
|
12744
|
+
return createHash9("sha256").update(JSON.stringify([namespace, principal])).digest("hex");
|
|
10974
12745
|
}
|
|
10975
12746
|
function supportPassportOwnerLockPath(storage, scope) {
|
|
10976
12747
|
const ownerLockKey = scope.ownerKey ?? computeSupportPassportOwnerLockKey(scope.namespace, scope.principal);
|
|
10977
12748
|
if (!/^[a-f0-9]{64}$/.test(ownerLockKey)) {
|
|
10978
12749
|
throw new SupportPassportError("card_data_invalid", "The support passport owner scope is invalid.", 500);
|
|
10979
12750
|
}
|
|
10980
|
-
return
|
|
12751
|
+
return path17.join(storage.dir, "state", `support-passport-cards-${ownerLockKey}.lock`);
|
|
10981
12752
|
}
|
|
10982
12753
|
async function withSupportPassportOwnerLock(storage, scope, task) {
|
|
10983
12754
|
const lockPath = supportPassportOwnerLockPath(storage, scope);
|
|
@@ -11085,7 +12856,7 @@ var SupportPassportCardService = class {
|
|
|
11085
12856
|
const onCommitted = once(input.onCommitted);
|
|
11086
12857
|
return await withSupportPassportOwnerLock(storage, { namespace, principal }, async (lock) => {
|
|
11087
12858
|
const batchContext = this.generatedBatchContext(storage, lock, principal, namespace, onCommitted);
|
|
11088
|
-
const batchId =
|
|
12859
|
+
const batchId = randomUUID3();
|
|
11089
12860
|
const created = [];
|
|
11090
12861
|
const createdIds = [];
|
|
11091
12862
|
const createdRecords = [];
|
|
@@ -11873,9 +13644,9 @@ var SupportPassportCardService = class {
|
|
|
11873
13644
|
};
|
|
11874
13645
|
|
|
11875
13646
|
// src/support-passport/grant-store.ts
|
|
11876
|
-
import { createHash as
|
|
13647
|
+
import { createHash as createHash10, randomBytes, randomUUID as randomUUID4, timingSafeEqual } from "crypto";
|
|
11877
13648
|
import { lstat as lstat4, open as open2, readdir as readdir4 } from "fs/promises";
|
|
11878
|
-
import
|
|
13649
|
+
import path18 from "path";
|
|
11879
13650
|
var GRANT_LOCK_STALE_MS = 3e4;
|
|
11880
13651
|
var GRANT_LOCK_WAIT_MS = 5e3;
|
|
11881
13652
|
var GRANT_LOCK_HEARTBEAT_MS = 1e4;
|
|
@@ -11898,7 +13669,7 @@ var MalformedGrantStateError = class extends Error {
|
|
|
11898
13669
|
}
|
|
11899
13670
|
};
|
|
11900
13671
|
function sha256(domain, value) {
|
|
11901
|
-
return
|
|
13672
|
+
return createHash10("sha256").update(domain).update("\0").update(value).digest("hex");
|
|
11902
13673
|
}
|
|
11903
13674
|
function hashesMatch(left, right) {
|
|
11904
13675
|
const leftBytes = Buffer.from(left, "hex");
|
|
@@ -11967,12 +13738,12 @@ var SupportPassportGrantStore = class {
|
|
|
11967
13738
|
runWithHeldFileLock;
|
|
11968
13739
|
syncDirectory;
|
|
11969
13740
|
constructor(options) {
|
|
11970
|
-
this.memoryDir =
|
|
11971
|
-
this.grantsDir =
|
|
11972
|
-
this.ownerIndexesDir =
|
|
13741
|
+
this.memoryDir = path18.resolve(expandTildePath(options.memoryDir));
|
|
13742
|
+
this.grantsDir = path18.join(this.memoryDir, "state", "support-passport", "grants");
|
|
13743
|
+
this.ownerIndexesDir = path18.join(this.grantsDir, "owners");
|
|
11973
13744
|
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
11974
13745
|
this.makeSecret = options.makeSecret ?? (() => randomBytes(32));
|
|
11975
|
-
this.makeGrantId = options.makeGrantId ??
|
|
13746
|
+
this.makeGrantId = options.makeGrantId ?? randomUUID4;
|
|
11976
13747
|
this.runWithHeldFileLock = options.withHeldFileLock ?? withHeldFileLock;
|
|
11977
13748
|
this.syncDirectory = options.syncDirectory ?? syncDirectoryForDurability;
|
|
11978
13749
|
}
|
|
@@ -12182,11 +13953,11 @@ var SupportPassportGrantStore = class {
|
|
|
12182
13953
|
}
|
|
12183
13954
|
filePath(grantId) {
|
|
12184
13955
|
const normalizedGrantId = normalizeGrantId(grantId);
|
|
12185
|
-
return
|
|
13956
|
+
return path18.join(this.grantsDir, `${normalizedGrantId}.json`);
|
|
12186
13957
|
}
|
|
12187
13958
|
ownerIndexPath(ownerHash) {
|
|
12188
13959
|
if (!SAFE_OWNER_INDEX_HASH.test(ownerHash)) throw new Error("support passport owner index hash is invalid");
|
|
12189
|
-
return
|
|
13960
|
+
return path18.join(this.ownerIndexesDir, `${ownerHash}.json`);
|
|
12190
13961
|
}
|
|
12191
13962
|
ownerHash(namespace, principalHash) {
|
|
12192
13963
|
return sha256("support-passport-owner-index:v1", `${namespace}\0${principalHash}`);
|
|
@@ -12242,12 +14013,12 @@ var SupportPassportGrantStore = class {
|
|
|
12242
14013
|
this.grantsDir,
|
|
12243
14014
|
grantIds.map((grantId) => `${grantId}.json`),
|
|
12244
14015
|
"support passport grant files must be regular files in a stable directory",
|
|
12245
|
-
|
|
14016
|
+
path18.parse(this.memoryDir).root
|
|
12246
14017
|
);
|
|
12247
14018
|
}
|
|
12248
14019
|
ownerMembershipDirectory(ownerHash) {
|
|
12249
14020
|
if (!SAFE_OWNER_INDEX_HASH.test(ownerHash)) throw new Error("support passport owner index hash is invalid");
|
|
12250
|
-
return
|
|
14021
|
+
return path18.join(this.ownerIndexesDir, ownerHash);
|
|
12251
14022
|
}
|
|
12252
14023
|
async ensureOwnerMembershipDirectory(ownerHash) {
|
|
12253
14024
|
const directory = this.ownerMembershipDirectory(ownerHash);
|
|
@@ -12262,11 +14033,11 @@ var SupportPassportGrantStore = class {
|
|
|
12262
14033
|
const directory = await this.ensureOwnerMembershipDirectory(ownerHash);
|
|
12263
14034
|
await writePrivateFileAtomicallyNoFollow(
|
|
12264
14035
|
directory,
|
|
12265
|
-
|
|
14036
|
+
path18.join(directory, `${state.grantId}.json`),
|
|
12266
14037
|
`${JSON.stringify({ schemaVersion: 1, grantId: state.grantId })}
|
|
12267
14038
|
`,
|
|
12268
14039
|
"support passport owner membership must be regular files in a stable directory",
|
|
12269
|
-
|
|
14040
|
+
path18.parse(this.memoryDir).root
|
|
12270
14041
|
);
|
|
12271
14042
|
}
|
|
12272
14043
|
async removeOwnerMembership(state) {
|
|
@@ -12276,7 +14047,7 @@ var SupportPassportGrantStore = class {
|
|
|
12276
14047
|
directory,
|
|
12277
14048
|
[`${state.grantId}.json`],
|
|
12278
14049
|
"support passport owner membership must be regular files in a stable directory",
|
|
12279
|
-
|
|
14050
|
+
path18.parse(this.memoryDir).root
|
|
12280
14051
|
);
|
|
12281
14052
|
}
|
|
12282
14053
|
async removeStoredGrant(state) {
|
|
@@ -12377,7 +14148,7 @@ var SupportPassportGrantStore = class {
|
|
|
12377
14148
|
const ownerHash = this.ownerHash(namespace, principalHash);
|
|
12378
14149
|
const directory = await this.ensureOwnerMembershipDirectory(ownerHash);
|
|
12379
14150
|
const grantIds = await withPrivateDirectoryNoFollow(
|
|
12380
|
-
|
|
14151
|
+
path18.parse(this.memoryDir).root,
|
|
12381
14152
|
directory,
|
|
12382
14153
|
"support passport owner membership must be regular files in a stable directory",
|
|
12383
14154
|
async (pinnedDirectory) => {
|
|
@@ -12408,7 +14179,7 @@ var SupportPassportGrantStore = class {
|
|
|
12408
14179
|
this.ownerIndexesDir,
|
|
12409
14180
|
filePath,
|
|
12410
14181
|
"support passport owner indexes must be regular files in a stable directory",
|
|
12411
|
-
|
|
14182
|
+
path18.parse(this.memoryDir).root
|
|
12412
14183
|
);
|
|
12413
14184
|
} catch (error) {
|
|
12414
14185
|
if (error.code === "ENOENT") return [];
|
|
@@ -12448,7 +14219,7 @@ var SupportPassportGrantStore = class {
|
|
|
12448
14219
|
`${JSON.stringify({ schemaVersion: 1, ownerHash, grantIds }, null, 2)}
|
|
12449
14220
|
`,
|
|
12450
14221
|
"support passport owner indexes must be regular files in a stable directory",
|
|
12451
|
-
|
|
14222
|
+
path18.parse(this.memoryDir).root
|
|
12452
14223
|
);
|
|
12453
14224
|
}
|
|
12454
14225
|
async readState(grantId) {
|
|
@@ -12458,7 +14229,7 @@ var SupportPassportGrantStore = class {
|
|
|
12458
14229
|
this.grantsDir,
|
|
12459
14230
|
filePath,
|
|
12460
14231
|
"support passport grant files must be regular files in a stable directory",
|
|
12461
|
-
|
|
14232
|
+
path18.parse(this.memoryDir).root
|
|
12462
14233
|
);
|
|
12463
14234
|
try {
|
|
12464
14235
|
const state = SupportPassportGrantStateSchema.parse(JSON.parse(content));
|
|
@@ -12492,7 +14263,7 @@ var SupportPassportGrantStore = class {
|
|
|
12492
14263
|
`${JSON.stringify(state, null, 2)}
|
|
12493
14264
|
`,
|
|
12494
14265
|
"support passport grant files must be regular files in a stable directory",
|
|
12495
|
-
|
|
14266
|
+
path18.parse(this.memoryDir).root
|
|
12496
14267
|
);
|
|
12497
14268
|
}
|
|
12498
14269
|
async ensureSafeDirectories() {
|
|
@@ -12526,8 +14297,8 @@ var SupportPassportGrantStore = class {
|
|
|
12526
14297
|
void 0
|
|
12527
14298
|
);
|
|
12528
14299
|
this.memoryDir = configuredMemoryDir;
|
|
12529
|
-
this.grantsDir =
|
|
12530
|
-
this.ownerIndexesDir =
|
|
14300
|
+
this.grantsDir = path18.join(configuredMemoryDir, "state", "support-passport", "grants");
|
|
14301
|
+
this.ownerIndexesDir = path18.join(this.grantsDir, "owners");
|
|
12531
14302
|
})();
|
|
12532
14303
|
}
|
|
12533
14304
|
const currentAttempt = this.memoryRootReady;
|
|
@@ -12541,12 +14312,12 @@ var SupportPassportGrantStore = class {
|
|
|
12541
14312
|
async withMutationLock(task) {
|
|
12542
14313
|
await this.ensureSafeDirectories();
|
|
12543
14314
|
return await withPrivateDirectoryNoFollow(
|
|
12544
|
-
|
|
14315
|
+
path18.parse(this.memoryDir).root,
|
|
12545
14316
|
this.grantsDir,
|
|
12546
14317
|
"support passport grant lock directory must remain inside the memory directory",
|
|
12547
14318
|
async (pinnedDirectory) => await this.withExclusiveLock(
|
|
12548
14319
|
`support-passport-grants:${this.grantsDir}`,
|
|
12549
|
-
|
|
14320
|
+
path18.join(pinnedDirectory, ".grants.lock"),
|
|
12550
14321
|
task
|
|
12551
14322
|
)
|
|
12552
14323
|
);
|
|
@@ -12555,12 +14326,12 @@ var SupportPassportGrantStore = class {
|
|
|
12555
14326
|
const normalizedGrantId = normalizeGrantId(grantId);
|
|
12556
14327
|
await this.ensureSafeDirectories();
|
|
12557
14328
|
return await withPrivateDirectoryNoFollow(
|
|
12558
|
-
|
|
14329
|
+
path18.parse(this.memoryDir).root,
|
|
12559
14330
|
this.grantsDir,
|
|
12560
14331
|
"support passport grant lock directory must remain inside the memory directory",
|
|
12561
14332
|
async (pinnedDirectory) => await this.withExclusiveLock(
|
|
12562
14333
|
`support-passport-grant:${this.grantsDir}:${normalizedGrantId}`,
|
|
12563
|
-
|
|
14334
|
+
path18.join(pinnedDirectory, `.${normalizedGrantId}.lock`),
|
|
12564
14335
|
task
|
|
12565
14336
|
)
|
|
12566
14337
|
);
|
|
@@ -12568,12 +14339,12 @@ var SupportPassportGrantStore = class {
|
|
|
12568
14339
|
async withOwnerIndexLock(ownerHash, task) {
|
|
12569
14340
|
await this.ensureSafeDirectories();
|
|
12570
14341
|
return await withPrivateDirectoryNoFollow(
|
|
12571
|
-
|
|
14342
|
+
path18.parse(this.memoryDir).root,
|
|
12572
14343
|
this.ownerIndexesDir,
|
|
12573
14344
|
"support passport owner lock directory must remain inside the memory directory",
|
|
12574
14345
|
async (pinnedDirectory) => await this.withExclusiveLock(
|
|
12575
14346
|
`support-passport-owner:${this.ownerIndexesDir}:${ownerHash}`,
|
|
12576
|
-
|
|
14347
|
+
path18.join(pinnedDirectory, `.${ownerHash}.lock`),
|
|
12577
14348
|
task
|
|
12578
14349
|
)
|
|
12579
14350
|
);
|
|
@@ -13410,8 +15181,8 @@ var SupportPassportModelAdapter = class {
|
|
|
13410
15181
|
};
|
|
13411
15182
|
|
|
13412
15183
|
// src/support-passport/model-audit.ts
|
|
13413
|
-
import { createHash as
|
|
13414
|
-
import
|
|
15184
|
+
import { createHash as createHash11 } from "crypto";
|
|
15185
|
+
import path19 from "path";
|
|
13415
15186
|
import { z as z5 } from "zod";
|
|
13416
15187
|
var HashSchema = z5.string().regex(/^[a-f0-9]{64}$/);
|
|
13417
15188
|
var SupportPassportModelAuditRecordSchema = z5.object({
|
|
@@ -13448,7 +15219,7 @@ var SupportPassportModelAuditRecordSchema = z5.object({
|
|
|
13448
15219
|
}
|
|
13449
15220
|
});
|
|
13450
15221
|
function hashSupportPassportAuditValues(domain, values) {
|
|
13451
|
-
return
|
|
15222
|
+
return createHash11("sha256").update(`support-passport-audit:${domain}:v1`).update("\0").update([...values].sort().join("\0")).digest("hex");
|
|
13452
15223
|
}
|
|
13453
15224
|
var SupportPassportModelAuditStore = class {
|
|
13454
15225
|
memoryDir;
|
|
@@ -13456,15 +15227,15 @@ var SupportPassportModelAuditStore = class {
|
|
|
13456
15227
|
memoryRootReady;
|
|
13457
15228
|
runWithHeldFileLock;
|
|
13458
15229
|
constructor(options) {
|
|
13459
|
-
this.memoryDir =
|
|
13460
|
-
this.auditDir =
|
|
15230
|
+
this.memoryDir = path19.resolve(expandTildePath(options.memoryDir));
|
|
15231
|
+
this.auditDir = path19.join(this.memoryDir, "state", "support-passport", "audit");
|
|
13461
15232
|
this.runWithHeldFileLock = options.withHeldFileLock ?? withHeldFileLock;
|
|
13462
15233
|
}
|
|
13463
15234
|
async record(input) {
|
|
13464
15235
|
const record = SupportPassportModelAuditRecordSchema.parse(input);
|
|
13465
15236
|
await this.ensureSafeDirectories();
|
|
13466
15237
|
const day = record.occurredAt.slice(0, 10);
|
|
13467
|
-
const filePath =
|
|
15238
|
+
const filePath = path19.join(this.auditDir, `${day}.jsonl`);
|
|
13468
15239
|
await serializeMutations(
|
|
13469
15240
|
`support-passport-audit:${filePath}`,
|
|
13470
15241
|
() => withPrivateDirectoryNoFollow(
|
|
@@ -13472,7 +15243,7 @@ var SupportPassportModelAuditStore = class {
|
|
|
13472
15243
|
this.auditDir,
|
|
13473
15244
|
"support passport audit directory must remain inside the memory directory",
|
|
13474
15245
|
async (pinnedDirectory) => await this.runWithHeldFileLock(
|
|
13475
|
-
|
|
15246
|
+
path19.join(pinnedDirectory, `.${day}.lock`),
|
|
13476
15247
|
{
|
|
13477
15248
|
staleMs: 3e4,
|
|
13478
15249
|
maxWaitMs: 5e3,
|
|
@@ -13509,7 +15280,7 @@ var SupportPassportModelAuditStore = class {
|
|
|
13509
15280
|
"support passport memory directory must be a stable directory"
|
|
13510
15281
|
);
|
|
13511
15282
|
this.memoryDir = configuredMemoryDir;
|
|
13512
|
-
this.auditDir =
|
|
15283
|
+
this.auditDir = path19.join(configuredMemoryDir, "state", "support-passport", "audit");
|
|
13513
15284
|
})();
|
|
13514
15285
|
}
|
|
13515
15286
|
const currentAttempt = this.memoryRootReady;
|
|
@@ -13523,7 +15294,7 @@ var SupportPassportModelAuditStore = class {
|
|
|
13523
15294
|
};
|
|
13524
15295
|
|
|
13525
15296
|
// src/support-passport/model-service.ts
|
|
13526
|
-
import { createHash as
|
|
15297
|
+
import { createHash as createHash12 } from "crypto";
|
|
13527
15298
|
import { z as z6 } from "zod";
|
|
13528
15299
|
var DraftServiceInputSchema = z6.object({
|
|
13529
15300
|
principal: z6.string().trim().min(1).max(512),
|
|
@@ -13559,7 +15330,7 @@ function supportPassportSourceContent(memory) {
|
|
|
13559
15330
|
return hasStructuredAttributes(memory.frontmatter.structuredAttributes) ? stripAttributesSuffix(memory.content) : memory.content;
|
|
13560
15331
|
}
|
|
13561
15332
|
function computeSupportPassportSourceRevision(content, structuredAttributes) {
|
|
13562
|
-
return
|
|
15333
|
+
return createHash12("sha256").update("support-passport-source:v1\0").update(hasStructuredAttributes(structuredAttributes) ? stripAttributesSuffix(content) : content).digest("hex");
|
|
13563
15334
|
}
|
|
13564
15335
|
function isSupportPassportSourceEligible(memory) {
|
|
13565
15336
|
const status = memory.frontmatter.status ?? "active";
|
|
@@ -14195,6 +15966,7 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
14195
15966
|
this.idempotency = new AccessIdempotencyStore(orchestrator.config.memoryDir);
|
|
14196
15967
|
this.replicaDivergenceMonitor = new ReplicaDivergenceMonitor({ resolveSecretRef: options.resolveSecretRef });
|
|
14197
15968
|
this.injectedSupportPassportGatewayRoute = options.supportPassportGatewayRoute ?? null;
|
|
15969
|
+
this.reviewDeckEnabled = options.reviewDeckEnabled === true;
|
|
14198
15970
|
const accessCaps = resolveAccessSetupCapabilities(orchestrator.config);
|
|
14199
15971
|
this.budget = new CrossNamespaceBudget({
|
|
14200
15972
|
enabled: accessCaps.recallCrossNamespaceBudget,
|
|
@@ -14234,6 +16006,7 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
14234
16006
|
corpusWatermarkCache = new CorpusWatermarkCache();
|
|
14235
16007
|
replicaDivergenceMonitor;
|
|
14236
16008
|
injectedSupportPassportGatewayRoute;
|
|
16009
|
+
reviewDeckEnabled;
|
|
14237
16010
|
/** AccessObserveWriteSurface (access-service decomposition). Lazy; selfDeps live wiring. */
|
|
14238
16011
|
_accessObserveWriteSurface;
|
|
14239
16012
|
get accessObserveWriteSurface() {
|
|
@@ -14262,6 +16035,15 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
14262
16035
|
}
|
|
14263
16036
|
return this._accessAdminOpsSurface;
|
|
14264
16037
|
}
|
|
16038
|
+
_reviewDeckSurface;
|
|
16039
|
+
get reviewDeckSurface() {
|
|
16040
|
+
if (!this._reviewDeckSurface) {
|
|
16041
|
+
this._reviewDeckSurface = new ReviewDeckSurface(
|
|
16042
|
+
selfDeps(this)
|
|
16043
|
+
);
|
|
16044
|
+
}
|
|
16045
|
+
return this._reviewDeckSurface;
|
|
16046
|
+
}
|
|
14265
16047
|
/** AccessRecallSurface (access-service decomposition). Lazy; selfDeps live wiring. */
|
|
14266
16048
|
_accessRecallSurface;
|
|
14267
16049
|
get accessRecallSurface() {
|
|
@@ -15223,6 +17005,36 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
15223
17005
|
]);
|
|
15224
17006
|
return computeWhoKnows({ topic, limit, memories, entities });
|
|
15225
17007
|
}
|
|
17008
|
+
/**
|
|
17009
|
+
* Read-only promotion-candidate surfacing (issue #2372): agent-subject,
|
|
17010
|
+
* active, reuse-signaled memories in the caller's namespace with no
|
|
17011
|
+
* equivalent in the target layer. No auto-promotion — callers use the
|
|
17012
|
+
* existing promotion commands.
|
|
17013
|
+
*/
|
|
17014
|
+
async promotionCandidates(request) {
|
|
17015
|
+
const limit = request.limit ?? 20;
|
|
17016
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
|
|
17017
|
+
throw new EngramAccessInputError(
|
|
17018
|
+
`promotion_candidates: limit expects an integer in [1, 100] (got ${String(request.limit)})`
|
|
17019
|
+
);
|
|
17020
|
+
}
|
|
17021
|
+
const resolvedNamespace = this.resolveReadableNamespace(request.namespace, request.authenticatedPrincipal);
|
|
17022
|
+
const resolvedTarget = this.resolveReadableNamespace(
|
|
17023
|
+
request.targetNamespace ?? this.orchestrator.config.sharedNamespace,
|
|
17024
|
+
request.authenticatedPrincipal
|
|
17025
|
+
);
|
|
17026
|
+
const minAccessCount = this.orchestrator.config.promotionCandidates.minAccessCount;
|
|
17027
|
+
const [memories, targetMemories] = await Promise.all([
|
|
17028
|
+
(await this.orchestrator.getStorage(resolvedNamespace)).readAllMemories(),
|
|
17029
|
+
(await this.orchestrator.getStorage(resolvedTarget)).readAllMemories()
|
|
17030
|
+
]);
|
|
17031
|
+
return {
|
|
17032
|
+
namespace: resolvedNamespace,
|
|
17033
|
+
targetNamespace: resolvedTarget,
|
|
17034
|
+
minAccessCount,
|
|
17035
|
+
candidates: computePromotionCandidates({ memories, targetMemories, minAccessCount, limit })
|
|
17036
|
+
};
|
|
17037
|
+
}
|
|
15226
17038
|
async memoryStore(request, hooks) {
|
|
15227
17039
|
return this.accessObserveWriteSurface.memoryStore(request, hooks);
|
|
15228
17040
|
}
|
|
@@ -15863,6 +17675,35 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
15863
17675
|
});
|
|
15864
17676
|
return { namespace: resolvedNamespace, ...report };
|
|
15865
17677
|
}
|
|
17678
|
+
/**
|
|
17679
|
+
* Procedure library health maintenance (issue #2370). Shadow-first: the
|
|
17680
|
+
* gate is checked BEFORE any storage read, so `maintenance.enabled=false`
|
|
17681
|
+
* returns `{ enabled: false }` having touched nothing but config. Apply
|
|
17682
|
+
* mode additionally requires `apply: true`; `dryRun: true` forces shadow.
|
|
17683
|
+
*
|
|
17684
|
+
* The authenticated principal (never a client-supplied actor) drives the
|
|
17685
|
+
* namespace via the same writable resolver `procedureMiningRun` uses, so
|
|
17686
|
+
* cross-tenant writes are impossible.
|
|
17687
|
+
*/
|
|
17688
|
+
async procedureLibraryMaintenance(request, principal) {
|
|
17689
|
+
const procedural = this.orchestrator.config.procedural;
|
|
17690
|
+
if (procedural?.enabled !== true || procedural.maintenance?.enabled !== true) {
|
|
17691
|
+
return { enabled: false };
|
|
17692
|
+
}
|
|
17693
|
+
const resolvedNamespace = this.writableNamespaceFor(
|
|
17694
|
+
request.namespace,
|
|
17695
|
+
void 0,
|
|
17696
|
+
request.authenticatedPrincipal ?? principal
|
|
17697
|
+
);
|
|
17698
|
+
const storage = await this.orchestrator.getStorage(resolvedNamespace);
|
|
17699
|
+
const report = await runProcedureLibraryMaintenance({
|
|
17700
|
+
memoryDir: storage.dir,
|
|
17701
|
+
storage,
|
|
17702
|
+
config: this.orchestrator.config,
|
|
17703
|
+
apply: request.apply === true && request.dryRun !== true
|
|
17704
|
+
});
|
|
17705
|
+
return { enabled: true, namespace: resolvedNamespace, report };
|
|
17706
|
+
}
|
|
15866
17707
|
async memorySummarizeHourly() {
|
|
15867
17708
|
await this.orchestrator.summarizer.runHourly();
|
|
15868
17709
|
return {
|
|
@@ -16986,8 +18827,8 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
16986
18827
|
async offlineSyncSnapshot(options = {}) {
|
|
16987
18828
|
const resolvedNamespace = this.resolveReadableNamespace(options.namespace, options.principal);
|
|
16988
18829
|
const storage = await offlineSyncStorageForSnapshot(this.orchestrator, resolvedNamespace);
|
|
16989
|
-
const storageHash =
|
|
16990
|
-
const deletions = [...await storage.readDeletionRevisions()].map(([
|
|
18830
|
+
const storageHash = createHash13("sha256").update(storage.dir).digest("hex").slice(0, 16);
|
|
18831
|
+
const deletions = [...await storage.readDeletionRevisions()].map(([path20, mtimeMs]) => ({ path: path20, mtimeMs }));
|
|
16991
18832
|
const snapshotBuilder = options.includeContent === false && options.baseFiles && options.baseFiles.length > 0 ? buildOfflineSyncSnapshotFromBase : buildOfflineSyncSnapshot;
|
|
16992
18833
|
const snapshot = await snapshotBuilder({
|
|
16993
18834
|
root: storage.dir,
|
|
@@ -17010,10 +18851,10 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
17010
18851
|
async offlineSyncSnapshotStream(options = {}) {
|
|
17011
18852
|
const resolvedNamespace = this.resolveReadableNamespace(options.namespace, options.principal);
|
|
17012
18853
|
const storage = await offlineSyncStorageForSnapshot(this.orchestrator, resolvedNamespace);
|
|
17013
|
-
const storageHash =
|
|
18854
|
+
const storageHash = createHash13("sha256").update(storage.dir).digest("hex").slice(0, 16);
|
|
17014
18855
|
const deletions = await filterOfflineSyncDeletionRevisions({
|
|
17015
18856
|
root: storage.dir,
|
|
17016
|
-
deletions: [...await storage.readDeletionRevisions()].map(([
|
|
18857
|
+
deletions: [...await storage.readDeletionRevisions()].map(([path20, mtimeMs]) => ({ path: path20, mtimeMs })),
|
|
17017
18858
|
includeTranscripts: options.includeTranscripts !== false,
|
|
17018
18859
|
userExcludeRegexps: this.offlineSyncUserExcludes
|
|
17019
18860
|
});
|
|
@@ -17050,7 +18891,7 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
17050
18891
|
async offlineSyncFiles(options) {
|
|
17051
18892
|
const resolvedNamespace = this.resolveReadableNamespace(options.namespace, options.principal);
|
|
17052
18893
|
const storage = await offlineSyncStorageForSnapshot(this.orchestrator, resolvedNamespace);
|
|
17053
|
-
const storageHash =
|
|
18894
|
+
const storageHash = createHash13("sha256").update(storage.dir).digest("hex").slice(0, 16);
|
|
17054
18895
|
try {
|
|
17055
18896
|
const snapshot = await buildOfflineSyncSnapshotForPaths({
|
|
17056
18897
|
root: storage.dir,
|
|
@@ -17289,6 +19130,15 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
17289
19130
|
async adminPromoteMemory(request) {
|
|
17290
19131
|
return this.accessAdminOpsSurface.adminPromoteMemory(request);
|
|
17291
19132
|
}
|
|
19133
|
+
async reviewDeckList(opts) {
|
|
19134
|
+
return this.reviewDeckSurface.list(opts);
|
|
19135
|
+
}
|
|
19136
|
+
async reviewDeckAction(...args) {
|
|
19137
|
+
return this.reviewDeckSurface.action(...args);
|
|
19138
|
+
}
|
|
19139
|
+
async reviewDeckUndo(...args) {
|
|
19140
|
+
return this.reviewDeckSurface.undo(...args);
|
|
19141
|
+
}
|
|
17292
19142
|
};
|
|
17293
19143
|
|
|
17294
19144
|
// src/access-recall-concurrency.ts
|
|
@@ -17647,6 +19497,7 @@ export {
|
|
|
17647
19497
|
resolveNamespaceWritablePreflight,
|
|
17648
19498
|
resolveAuthorizedNamespaceWritablePreflight,
|
|
17649
19499
|
resolveQueryNamespaceWritablePreflight,
|
|
19500
|
+
runProcedureLibraryMaintenance,
|
|
17650
19501
|
computeProcedureStats,
|
|
17651
19502
|
formatProcedureStatsText,
|
|
17652
19503
|
AccessIdentityContinuitySurface,
|
|
@@ -17659,6 +19510,17 @@ export {
|
|
|
17659
19510
|
RecallResultFormatter,
|
|
17660
19511
|
assembleRecallResponse,
|
|
17661
19512
|
AccessRecallSurface,
|
|
19513
|
+
ReviewDeckCursorError,
|
|
19514
|
+
computeReviewItemRevision,
|
|
19515
|
+
projectReviewDeckItem,
|
|
19516
|
+
compareReviewDeckRows,
|
|
19517
|
+
encodeReviewDeckCursor,
|
|
19518
|
+
decodeReviewDeckCursor,
|
|
19519
|
+
buildReviewDeckPage,
|
|
19520
|
+
listReviewItems,
|
|
19521
|
+
performReview,
|
|
19522
|
+
readReviewDeckSnapshot,
|
|
19523
|
+
readReviewDeckRow,
|
|
17662
19524
|
SupportPassportError,
|
|
17663
19525
|
SupportPassportGrantCardRefSchema,
|
|
17664
19526
|
SupportPassportGrantStateSchema,
|
|
@@ -17705,4 +19567,4 @@ export {
|
|
|
17705
19567
|
EngramAccessService,
|
|
17706
19568
|
AccessAdminOpsSurface
|
|
17707
19569
|
};
|
|
17708
|
-
//# sourceMappingURL=chunk-
|
|
19570
|
+
//# sourceMappingURL=chunk-WN5FSGLE.js.map
|