@remnic/core 9.65.2 → 9.65.4
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 +21 -19
- package/dist/access-authorization-probe.d.ts +38 -38
- package/dist/access-authorization-probe.js +22 -20
- package/dist/access-boundary.d.ts +40 -40
- package/dist/access-boundary.js +21 -19
- package/dist/access-cli.js +62 -60
- 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 +21 -19
- 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 +39 -39
- 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 +23 -21
- package/dist/access-http.d.ts +51 -44
- package/dist/access-http.js +37 -35
- package/dist/access-identity-continuity-surface.d.ts +12 -12
- package/dist/access-identity-continuity-surface.js +21 -19
- package/dist/access-lcm-surface.d.ts +27 -27
- package/dist/access-lcm-surface.js +21 -19
- 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 +31 -29
- package/dist/access-memory-search-fanout.d.ts +4 -2
- package/dist/{access-namespace-preflight-Dhvcl-T0.d.ts → access-namespace-preflight-D_6mo8ms.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +5 -3
- package/dist/access-namespace-preflight.js +21 -19
- package/dist/access-observe-write-surface.d.ts +39 -39
- package/dist/access-observe-write-surface.js +21 -19
- package/dist/access-offline-manifest.d.ts +12 -12
- package/dist/access-offline-manifest.js +3 -3
- package/dist/access-operations-batch.js +25 -23
- package/dist/access-operations.d.ts +40 -40
- package/dist/access-operations.js +28 -26
- package/dist/access-recall-concurrency.d.ts +40 -40
- package/dist/access-recall-concurrency.js +21 -19
- package/dist/access-recall-response.d.ts +24 -24
- package/dist/access-recall-response.js +21 -19
- package/dist/access-recall-surface.d.ts +24 -24
- package/dist/access-recall-surface.js +21 -19
- package/dist/access-schema.d.ts +45 -45
- package/dist/{access-service-Bke1alZO.d.ts → access-service-DqPa3hy4.d.ts} +219 -75
- package/dist/access-service-helpers.d.ts +40 -40
- package/dist/access-service.d.ts +47 -47
- package/dist/access-service.js +21 -19
- package/dist/access-surface-catalog.d.ts +40 -40
- package/dist/access-surface-catalog.js +27 -21
- 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 +10 -1
- package/dist/active-recall.js.map +1 -1
- package/dist/ambient-provenance.d.ts +3 -1
- package/dist/artifact-search.d.ts +3 -1
- package/dist/{auto-sync-H64ZCNIR.js → auto-sync-XVMLL2RH.js} +5 -5
- 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 +4 -4
- 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/bulk-import/index.d.ts +5 -3
- package/dist/calibration.d.ts +3 -1
- package/dist/capabilities.d.ts +3 -1
- package/dist/{catalog-DV6qnbr7.d.ts → catalog-DO_7zfkv.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 +12 -9
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/chunk-236PXYG7.js +232 -0
- package/dist/chunk-236PXYG7.js.map +1 -0
- package/dist/{chunk-YB42WZCY.js → chunk-2IXQSGCU.js} +2 -2
- package/dist/{chunk-PE255F4T.js → chunk-2MVTAIL3.js} +2 -2
- package/dist/{chunk-LGO6A7GJ.js → chunk-3JZBPTLD.js} +338 -80
- package/dist/chunk-3JZBPTLD.js.map +1 -0
- package/dist/{chunk-GDFVPUJ5.js → chunk-3NH3VP3U.js} +2 -2
- package/dist/{chunk-TBOJ76ER.js → chunk-AB3A7EFH.js} +18 -2
- package/dist/{chunk-TBOJ76ER.js.map → chunk-AB3A7EFH.js.map} +1 -1
- package/dist/{chunk-GNCCUR6K.js → chunk-AXGFOFNY.js} +2 -2
- package/dist/{chunk-SB7D4BT7.js → chunk-AZLLH6YA.js} +1554 -114
- package/dist/chunk-AZLLH6YA.js.map +1 -0
- package/dist/{chunk-5YQ63T4B.js → chunk-BK5G2MHO.js} +2 -2
- package/dist/{chunk-LZH5FR2W.js → chunk-CQBIN77D.js} +2 -2
- package/dist/{chunk-35NN3ZFA.js → chunk-CTVWELNK.js} +21 -3
- package/dist/chunk-CTVWELNK.js.map +1 -0
- package/dist/{chunk-NKKD4ZAU.js → chunk-DORFF5N5.js} +2 -2
- package/dist/{chunk-BWLRUMOG.js → chunk-DPNXADEI.js} +441 -2
- package/dist/chunk-DPNXADEI.js.map +1 -0
- package/dist/{chunk-SQI57UCJ.js → chunk-DUEDOYZD.js} +2 -2
- package/dist/{chunk-5NM4OH4P.js → chunk-DUZARALI.js} +3 -3
- package/dist/{chunk-2E36UXVW.js → chunk-ECLJ4LA2.js} +2 -2
- package/dist/{chunk-TZNQUNKL.js → chunk-FC7TIRFS.js} +15 -1
- package/dist/chunk-FC7TIRFS.js.map +1 -0
- package/dist/{chunk-IID2CMUU.js → chunk-GHD2LLG4.js} +2 -2
- package/dist/{chunk-ZQHI2BZB.js → chunk-HF5BUTI6.js} +2 -2
- package/dist/{chunk-3DVBKTSO.js → chunk-HSZMX3ZJ.js} +4 -4
- package/dist/{chunk-S2DPMJXH.js → chunk-I23ZHYSL.js} +2 -2
- package/dist/{chunk-ODZG724P.js → chunk-I2HTKOOP.js} +2 -2
- package/dist/chunk-I32NKXE2.js +879 -0
- package/dist/chunk-I32NKXE2.js.map +1 -0
- package/dist/{chunk-NTWN6HB2.js → chunk-IURMJBGP.js} +2 -2
- package/dist/{chunk-OCZIYAE5.js → chunk-IWKGOCL6.js} +3 -3
- package/dist/{chunk-UXO5IMBK.js → chunk-J3ATBB7M.js} +2 -2
- package/dist/{chunk-Y7DK7HHJ.js → chunk-JPAKBNTM.js} +2 -2
- package/dist/{chunk-SPUJNJJC.js → chunk-KFIOPZ25.js} +2 -2
- package/dist/{chunk-JYYBA7TF.js → chunk-KOO37E4Y.js} +2 -2
- package/dist/{chunk-OTHZWLUD.js → chunk-KPB2QHJZ.js} +2 -2
- package/dist/{chunk-SBDCZ2AX.js → chunk-LBFFNDFM.js} +1 -1
- package/dist/chunk-LBFFNDFM.js.map +1 -0
- package/dist/{chunk-CT56C22C.js → chunk-LYBIHM4N.js} +4 -4
- package/dist/{chunk-3I7ASZN3.js → chunk-MFOSZUIT.js} +2 -2
- package/dist/{chunk-DZUJ46DO.js → chunk-NLEH4RTB.js} +2 -2
- package/dist/{chunk-ZO6AXLEH.js → chunk-OCCHUEZB.js} +2 -2
- package/dist/{chunk-EILZG5VC.js → chunk-OU34IQXV.js} +2 -2
- package/dist/{chunk-2XDWWPTN.js → chunk-OZDFB22S.js} +2 -2
- package/dist/{chunk-UIN2BWDD.js → chunk-PTZQYCJ4.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-Z7PBQPJ4.js → chunk-QJW4MZSW.js} +2 -2
- package/dist/{chunk-R7JAM2XF.js → chunk-R2MZCYA6.js} +3 -3
- package/dist/{chunk-TF77C7SV.js → chunk-SR5LNI6Q.js} +7 -5
- package/dist/chunk-SR5LNI6Q.js.map +1 -0
- package/dist/{chunk-LBWQ65SX.js → chunk-T42L3S6A.js} +4 -4
- package/dist/{chunk-J275IYMG.js → chunk-THVI4Y7X.js} +34 -7
- package/dist/chunk-THVI4Y7X.js.map +1 -0
- package/dist/{chunk-QOS5LBZN.js → chunk-TJFI3K2O.js} +15 -3
- package/dist/chunk-TJFI3K2O.js.map +1 -0
- package/dist/{chunk-2YI72KM3.js → chunk-UCKG36HO.js} +2 -2
- package/dist/{chunk-SIHSCCUQ.js → chunk-UFR6HX7A.js} +1 -1
- package/dist/{chunk-CDUUDBWJ.js → chunk-VFYRYFLL.js} +2 -2
- package/dist/{chunk-XRYZRW54.js → chunk-WDXD6ITO.js} +2 -2
- package/dist/{chunk-4KYOLI6M.js → chunk-XGM3VQWG.js} +120 -14
- package/dist/chunk-XGM3VQWG.js.map +1 -0
- package/dist/{chunk-MN4KB2A4.js → chunk-YDKF4MSJ.js} +3 -3
- package/dist/{chunk-YLDXWCZP.js → chunk-YHGCT462.js} +14 -9
- package/dist/chunk-YHGCT462.js.map +1 -0
- package/dist/{chunk-7YQ4IYS2.js → chunk-YOXVZJFM.js} +2 -2
- package/dist/{chunk-ZWXJBFZU.js → chunk-YZJM6CLF.js} +8 -8
- package/dist/chunk-ZCUTSMR2.js +61 -0
- package/dist/chunk-ZCUTSMR2.js.map +1 -0
- package/dist/{chunk-LUNJ3WFO.js → chunk-ZK4BFABK.js} +4 -4
- package/dist/{chunk-V3MXUL3D.js → chunk-ZPOHEB5Z.js} +329 -653
- package/dist/chunk-ZPOHEB5Z.js.map +1 -0
- package/dist/{chunk-RDFF2NAU.js → chunk-ZXBTTMGZ.js} +184 -88
- package/dist/chunk-ZXBTTMGZ.js.map +1 -0
- package/dist/{cli-cShQ13XG.d.ts → cli-DO3i14pM.d.ts} +5 -5
- package/dist/cli.d.ts +25 -25
- package/dist/cli.js +51 -48
- package/dist/coding/pre-action-gate.d.ts +2 -60
- package/dist/compounding/engine.d.ts +4 -2
- package/dist/compounding/engine.js +4 -4
- 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 +10 -1
- package/dist/connectors/codex-materialize-runner.d.ts +3 -1
- package/dist/connectors/codex-materialize-runner.js +8 -5
- package/dist/connectors/codex-materialize.d.ts +16 -1
- package/dist/connectors/codex-materialize.js +10 -1
- package/dist/connectors/index.d.ts +3 -1
- package/dist/connectors/index.js +8 -5
- 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 +12 -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 +6 -6
- 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 +6 -6
- 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-CsGg-VwS.d.ts → dependency-propagation-delivery-D23_x-s5.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 +4 -4
- 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 +1 -1
- package/dist/external-wiki-access.d.ts +40 -40
- package/dist/external-wiki-access.js +22 -20
- 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-prompt.d.ts +3 -1
- package/dist/extraction-source-grounding-rules.d.ts +3 -1
- package/dist/extraction-source-grounding.d.ts +3 -1
- package/dist/extraction.d.ts +3 -1
- package/dist/extraction.js +9 -7
- 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--QhGIXF2.d.ts +284 -0
- package/dist/index.d.ts +314 -45
- package/dist/index.js +163 -88
- package/dist/intent.d.ts +3 -1
- package/dist/lcm/engine.d.ts +3 -1
- package/dist/lcm/index.d.ts +3 -1
- 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 +4 -4
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +4 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +4 -4
- package/dist/maintenance/rebuild-memory-projection.d.ts +4 -2
- package/dist/maintenance/rebuild-memory-projection.js +5 -5
- package/dist/{maintenance-jhMpeGne.d.ts → maintenance-PFvY1Pw_.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +37 -37
- 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 +40 -40
- package/dist/memory-subject.d.ts +42 -42
- package/dist/memory-worth-outcomes.d.ts +4 -2
- package/dist/models-json.d.ts +3 -1
- package/dist/namespaces/migrate.d.ts +5 -3
- package/dist/namespaces/migrate.js +5 -5
- package/dist/namespaces/principal.d.ts +3 -1
- package/dist/namespaces/search.d.ts +3 -1
- package/dist/namespaces/storage.d.ts +5 -3
- package/dist/namespaces/storage.js +4 -4
- 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 +7 -7
- package/dist/operator-doctor-replica.d.ts +3 -1
- package/dist/operator-toolkit.d.ts +5 -3
- package/dist/operator-toolkit.js +19 -13
- package/dist/orchestration/compression-guideline-coordinator.d.ts +4 -2
- package/dist/orchestration/maintenance.d.ts +6 -4
- package/dist/orchestration/maintenance.js +10 -10
- package/dist/{orchestrator-DyGUC7re.d.ts → orchestrator-4wzJrPVm.d.ts} +23 -9
- package/dist/orchestrator.d.ts +12 -12
- package/dist/orchestrator.js +62 -60
- package/dist/patterns-cli.d.ts +3 -1
- package/dist/{pipeline-C25Oxtp1.d.ts → pipeline-CgXgdIrF.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-CMe7NQzj.d.ts → public-http-DhIXYBYI.d.ts} +1 -1
- package/dist/{qmd-DkDVCbgF.d.ts → qmd-BppGGxsi.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/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 +2 -2
- 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-MFY72STR.js → resolution-4552BNRV.js} +14 -4
- package/dist/resolve-auth-token.d.ts +3 -1
- package/dist/resume-bundles.js +8 -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 +1 -1
- package/dist/schemas.d.ts +44 -44
- package/dist/{scope-profiles-B9xMoFO-.d.ts → scope-profiles-ChZUtxDU.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +3 -1
- package/dist/search/factory.d.ts +3 -1
- package/dist/search/index.d.ts +3 -1
- 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-C4uykW84.d.ts → semantic-consolidation-mSPwQSmF.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +4 -2
- package/dist/semantic-consolidation.js +9 -6
- package/dist/semantic-rule-promotion.js +4 -4
- package/dist/semantic-rule-verifier.d.ts +3 -1
- package/dist/semantic-rule-verifier.js +4 -4
- package/dist/{service-DCZDZNcV.d.ts → service-BICWLwSP.d.ts} +2 -2
- package/dist/session-observer-bands.d.ts +3 -1
- package/dist/session-observer-state.d.ts +3 -1
- package/dist/shared-context/manager.d.ts +3 -1
- package/dist/signal.d.ts +3 -1
- package/dist/skills-registry.js +4 -56
- package/dist/skills-registry.js.map +1 -1
- package/dist/source-agent-qualifier.d.ts +3 -1
- package/dist/source-agent-qualifier.js +8 -5
- package/dist/{storage-CcKmEjL8.d.ts → storage-B7urx1K3.d.ts} +1 -1
- package/dist/storage.d.ts +4 -2
- package/dist/storage.js +6 -6
- package/dist/subject-config.d.ts +3 -1
- 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 +24 -22
- 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/types.d.ts +20 -20
- package/dist/trust-score-stage.d.ts +3 -1
- package/dist/trust-score.d.ts +3 -1
- package/dist/{types-Pi0lfaEt.d.ts → types-ETU5N6nB.d.ts} +433 -7
- 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 +4 -4
- package/dist/who-knows-cli.d.ts +40 -40
- package/dist/who-knows-cli.js +5 -5
- package/dist/who-knows.d.ts +42 -42
- package/dist/who-knows.js +4 -4
- package/dist/write-envelope.d.ts +3 -1
- package/dist/write-envelope.js +1 -1
- package/package.json +2 -2
- package/src/access-boundary.ts +4 -0
- package/src/access-http.ts +6 -5
- package/src/access-mcp-admin-tools.ts +24 -0
- package/src/access-mcp-output-schemas.ts +14 -0
- package/src/access-mcp.ts +2 -2
- package/src/access-operations-batch.ts +5 -0
- package/src/access-service.ts +27 -0
- package/src/access-surface-catalog.test.ts +24 -0
- package/src/access-surface-catalog.ts +4 -0
- package/src/cli/skills-commands.ts +150 -0
- package/src/cli.ts +4 -2
- package/src/coding/action-gate.test.ts +341 -0
- package/src/coding/action-gate.ts +556 -0
- package/src/config.ts +9 -2
- package/src/connectors/codex-materialize-runner.ts +16 -0
- package/src/connectors/codex-materialize-skills.test.ts +141 -0
- package/src/connectors/codex-materialize.ts +58 -40
- package/src/connectors/materialize-paths.ts +50 -0
- package/src/connectors/materialize-skills.ts +127 -0
- 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/index.ts +9 -13
- 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/skill-io.test.ts +190 -0
- package/src/procedural/skill-io.ts +220 -0
- package/src/procedural/skill-projection.test.ts +214 -0
- package/src/procedural/skill-projection.ts +356 -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/storage.ts +4 -6
- package/src/types.ts +9 -6
- package/dist/chunk-35NN3ZFA.js.map +0 -1
- package/dist/chunk-4KYOLI6M.js.map +0 -1
- package/dist/chunk-BWLRUMOG.js.map +0 -1
- package/dist/chunk-J275IYMG.js.map +0 -1
- package/dist/chunk-LGO6A7GJ.js.map +0 -1
- package/dist/chunk-QOS5LBZN.js.map +0 -1
- package/dist/chunk-RDFF2NAU.js.map +0 -1
- package/dist/chunk-SB7D4BT7.js.map +0 -1
- package/dist/chunk-SBDCZ2AX.js.map +0 -1
- package/dist/chunk-TF77C7SV.js.map +0 -1
- package/dist/chunk-TZNQUNKL.js.map +0 -1
- package/dist/chunk-V3MXUL3D.js.map +0 -1
- package/dist/chunk-XCTXS7VY.js +0 -402
- package/dist/chunk-XCTXS7VY.js.map +0 -1
- package/dist/chunk-YLDXWCZP.js.map +0 -1
- /package/dist/{auto-sync-H64ZCNIR.js.map → auto-sync-XVMLL2RH.js.map} +0 -0
- /package/dist/{chunk-YB42WZCY.js.map → chunk-2IXQSGCU.js.map} +0 -0
- /package/dist/{chunk-PE255F4T.js.map → chunk-2MVTAIL3.js.map} +0 -0
- /package/dist/{chunk-GDFVPUJ5.js.map → chunk-3NH3VP3U.js.map} +0 -0
- /package/dist/{chunk-GNCCUR6K.js.map → chunk-AXGFOFNY.js.map} +0 -0
- /package/dist/{chunk-5YQ63T4B.js.map → chunk-BK5G2MHO.js.map} +0 -0
- /package/dist/{chunk-LZH5FR2W.js.map → chunk-CQBIN77D.js.map} +0 -0
- /package/dist/{chunk-NKKD4ZAU.js.map → chunk-DORFF5N5.js.map} +0 -0
- /package/dist/{chunk-SQI57UCJ.js.map → chunk-DUEDOYZD.js.map} +0 -0
- /package/dist/{chunk-5NM4OH4P.js.map → chunk-DUZARALI.js.map} +0 -0
- /package/dist/{chunk-2E36UXVW.js.map → chunk-ECLJ4LA2.js.map} +0 -0
- /package/dist/{chunk-IID2CMUU.js.map → chunk-GHD2LLG4.js.map} +0 -0
- /package/dist/{chunk-ZQHI2BZB.js.map → chunk-HF5BUTI6.js.map} +0 -0
- /package/dist/{chunk-3DVBKTSO.js.map → chunk-HSZMX3ZJ.js.map} +0 -0
- /package/dist/{chunk-S2DPMJXH.js.map → chunk-I23ZHYSL.js.map} +0 -0
- /package/dist/{chunk-ODZG724P.js.map → chunk-I2HTKOOP.js.map} +0 -0
- /package/dist/{chunk-NTWN6HB2.js.map → chunk-IURMJBGP.js.map} +0 -0
- /package/dist/{chunk-OCZIYAE5.js.map → chunk-IWKGOCL6.js.map} +0 -0
- /package/dist/{chunk-UXO5IMBK.js.map → chunk-J3ATBB7M.js.map} +0 -0
- /package/dist/{chunk-Y7DK7HHJ.js.map → chunk-JPAKBNTM.js.map} +0 -0
- /package/dist/{chunk-SPUJNJJC.js.map → chunk-KFIOPZ25.js.map} +0 -0
- /package/dist/{chunk-JYYBA7TF.js.map → chunk-KOO37E4Y.js.map} +0 -0
- /package/dist/{chunk-OTHZWLUD.js.map → chunk-KPB2QHJZ.js.map} +0 -0
- /package/dist/{chunk-CT56C22C.js.map → chunk-LYBIHM4N.js.map} +0 -0
- /package/dist/{chunk-3I7ASZN3.js.map → chunk-MFOSZUIT.js.map} +0 -0
- /package/dist/{chunk-DZUJ46DO.js.map → chunk-NLEH4RTB.js.map} +0 -0
- /package/dist/{chunk-ZO6AXLEH.js.map → chunk-OCCHUEZB.js.map} +0 -0
- /package/dist/{chunk-EILZG5VC.js.map → chunk-OU34IQXV.js.map} +0 -0
- /package/dist/{chunk-2XDWWPTN.js.map → chunk-OZDFB22S.js.map} +0 -0
- /package/dist/{chunk-UIN2BWDD.js.map → chunk-PTZQYCJ4.js.map} +0 -0
- /package/dist/{chunk-Z7PBQPJ4.js.map → chunk-QJW4MZSW.js.map} +0 -0
- /package/dist/{chunk-R7JAM2XF.js.map → chunk-R2MZCYA6.js.map} +0 -0
- /package/dist/{chunk-LBWQ65SX.js.map → chunk-T42L3S6A.js.map} +0 -0
- /package/dist/{chunk-2YI72KM3.js.map → chunk-UCKG36HO.js.map} +0 -0
- /package/dist/{chunk-SIHSCCUQ.js.map → chunk-UFR6HX7A.js.map} +0 -0
- /package/dist/{chunk-CDUUDBWJ.js.map → chunk-VFYRYFLL.js.map} +0 -0
- /package/dist/{chunk-XRYZRW54.js.map → chunk-WDXD6ITO.js.map} +0 -0
- /package/dist/{chunk-MN4KB2A4.js.map → chunk-YDKF4MSJ.js.map} +0 -0
- /package/dist/{chunk-7YQ4IYS2.js.map → chunk-YOXVZJFM.js.map} +0 -0
- /package/dist/{chunk-ZWXJBFZU.js.map → chunk-YZJM6CLF.js.map} +0 -0
- /package/dist/{chunk-LUNJ3WFO.js.map → chunk-ZK4BFABK.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-MFY72STR.js.map → resolution-4552BNRV.js.map} +0 -0
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
computeWhoKnows,
|
|
19
19
|
loadWhoKnowsEntities,
|
|
20
20
|
validateWhoKnowsInput
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-KFIOPZ25.js";
|
|
22
22
|
import {
|
|
23
23
|
WriteQuarantineStore
|
|
24
24
|
} from "./chunk-PJSK6OJM.js";
|
|
@@ -45,13 +45,13 @@ import {
|
|
|
45
45
|
} from "./chunk-H7XKCNR6.js";
|
|
46
46
|
import {
|
|
47
47
|
toRecallExplainJson
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-YOXVZJFM.js";
|
|
49
49
|
import {
|
|
50
50
|
estimateRecallTokens
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-MFOSZUIT.js";
|
|
52
52
|
import {
|
|
53
53
|
readAggregateExtractionWatermark
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-2MVTAIL3.js";
|
|
55
55
|
import {
|
|
56
56
|
ReplicaDivergenceMonitor
|
|
57
57
|
} from "./chunk-CVILPI77.js";
|
|
@@ -88,11 +88,6 @@ import {
|
|
|
88
88
|
import {
|
|
89
89
|
LocalLlmClient
|
|
90
90
|
} from "./chunk-IVKIODHO.js";
|
|
91
|
-
import {
|
|
92
|
-
buildProcedurePersistBody,
|
|
93
|
-
normalizeProcedureSteps,
|
|
94
|
-
parseProcedureStepsFromBody
|
|
95
|
-
} from "./chunk-QDW3E4RD.js";
|
|
96
91
|
import {
|
|
97
92
|
persistExplicitCapture,
|
|
98
93
|
queueExplicitCaptureForReview,
|
|
@@ -117,11 +112,11 @@ import {
|
|
|
117
112
|
listMemoryGovernanceRuns,
|
|
118
113
|
readMemoryGovernanceRunArtifact,
|
|
119
114
|
runMemoryGovernance
|
|
120
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-KOO37E4Y.js";
|
|
121
116
|
import {
|
|
122
117
|
CorpusWatermarkCache,
|
|
123
118
|
computeServiceCorpusCensus
|
|
124
|
-
} from "./chunk-
|
|
119
|
+
} from "./chunk-WDXD6ITO.js";
|
|
125
120
|
import {
|
|
126
121
|
ExtractionDeadlineError,
|
|
127
122
|
isActivityDigestPath,
|
|
@@ -132,31 +127,27 @@ import {
|
|
|
132
127
|
import {
|
|
133
128
|
defaultCapsulesDir
|
|
134
129
|
} from "./chunk-ZY2MNJR6.js";
|
|
135
|
-
import {
|
|
136
|
-
filterTrajectoriesByLookbackDays,
|
|
137
|
-
readCausalTrajectoryRecords
|
|
138
|
-
} from "./chunk-PP7R754B.js";
|
|
139
130
|
import {
|
|
140
131
|
FileCalendarSource,
|
|
141
132
|
buildBriefing,
|
|
142
133
|
enqueuePassiveCorrectionNotification,
|
|
143
134
|
parseBriefingFocus,
|
|
144
135
|
parseBriefingWindow
|
|
145
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-IURMJBGP.js";
|
|
146
137
|
import {
|
|
147
138
|
parseEntityFile,
|
|
148
139
|
parseFrontmatter,
|
|
149
140
|
qmdCollectionPathParts,
|
|
150
141
|
qmdResultPathCandidates,
|
|
151
142
|
selfDeps
|
|
152
|
-
} from "./chunk-
|
|
143
|
+
} from "./chunk-THVI4Y7X.js";
|
|
153
144
|
import {
|
|
154
145
|
namespaceCollectionName
|
|
155
146
|
} from "./chunk-YHCBJULX.js";
|
|
156
147
|
import {
|
|
157
148
|
DEFAULT_RECALL_DISCLOSURE,
|
|
158
149
|
isRecallDisclosure
|
|
159
|
-
} from "./chunk-
|
|
150
|
+
} from "./chunk-LBFFNDFM.js";
|
|
160
151
|
import {
|
|
161
152
|
normalizeProjectionPreview,
|
|
162
153
|
normalizeProjectionTags
|
|
@@ -174,11 +165,19 @@ import {
|
|
|
174
165
|
parseTagMatch
|
|
175
166
|
} from "./chunk-BT7NVCML.js";
|
|
176
167
|
import {
|
|
177
|
-
createVersion
|
|
168
|
+
createVersion,
|
|
169
|
+
getVersion,
|
|
170
|
+
revertToVersion
|
|
178
171
|
} from "./chunk-UFKPQBXH.js";
|
|
179
172
|
import {
|
|
173
|
+
MEMORY_CORPUS_VERSION_SENTINEL,
|
|
180
174
|
bumpMemoryCorpusVersionForDir
|
|
181
175
|
} from "./chunk-XCB6QDL6.js";
|
|
176
|
+
import {
|
|
177
|
+
HistoricalEntityCanonicalIdCache,
|
|
178
|
+
canonicalizeEntityRefFrontmatter,
|
|
179
|
+
repairContentAfterJournalMoveSync
|
|
180
|
+
} from "./chunk-ZVPVTPGI.js";
|
|
182
181
|
import {
|
|
183
182
|
supersessionKeysForFact
|
|
184
183
|
} from "./chunk-5WITETWU.js";
|
|
@@ -198,6 +197,15 @@ import {
|
|
|
198
197
|
import {
|
|
199
198
|
isExternalWikiCollectionName
|
|
200
199
|
} from "./chunk-JV3C2MNQ.js";
|
|
200
|
+
import {
|
|
201
|
+
buildProcedurePersistBody,
|
|
202
|
+
normalizeProcedureSteps,
|
|
203
|
+
parseProcedureStepsFromBody
|
|
204
|
+
} from "./chunk-QDW3E4RD.js";
|
|
205
|
+
import {
|
|
206
|
+
filterTrajectoriesByLookbackDays,
|
|
207
|
+
readCausalTrajectoryRecords
|
|
208
|
+
} from "./chunk-PP7R754B.js";
|
|
201
209
|
import {
|
|
202
210
|
computePromotionCandidates
|
|
203
211
|
} from "./chunk-RIAM7DND.js";
|
|
@@ -232,7 +240,7 @@ import {
|
|
|
232
240
|
} from "./chunk-LNEWDF2A.js";
|
|
233
241
|
import {
|
|
234
242
|
createOfflineSyncManifestStream
|
|
235
|
-
} from "./chunk-
|
|
243
|
+
} from "./chunk-I2HTKOOP.js";
|
|
236
244
|
import {
|
|
237
245
|
offlineSyncStorageForSnapshot
|
|
238
246
|
} from "./chunk-HZNYJN77.js";
|
|
@@ -282,9 +290,6 @@ import {
|
|
|
282
290
|
isSupportPassportPrivateMemory,
|
|
283
291
|
projectSupportPassportCard
|
|
284
292
|
} from "./chunk-XDL5CYZN.js";
|
|
285
|
-
import {
|
|
286
|
-
stripAttributesSuffix
|
|
287
|
-
} from "./chunk-JDSVLVCG.js";
|
|
288
293
|
import {
|
|
289
294
|
computeContentHash
|
|
290
295
|
} from "./chunk-5FVVY2EB.js";
|
|
@@ -292,6 +297,9 @@ import {
|
|
|
292
297
|
serializeMutations,
|
|
293
298
|
withHeldFileLock
|
|
294
299
|
} from "./chunk-FFAZ2XFU.js";
|
|
300
|
+
import {
|
|
301
|
+
stripAttributesSuffix
|
|
302
|
+
} from "./chunk-JDSVLVCG.js";
|
|
295
303
|
import {
|
|
296
304
|
sanitizeMemoryContent
|
|
297
305
|
} from "./chunk-5GKPFL3S.js";
|
|
@@ -399,7 +407,8 @@ import {
|
|
|
399
407
|
SecureStoreLockedError
|
|
400
408
|
} from "./chunk-XQ3HXAQH.js";
|
|
401
409
|
import {
|
|
402
|
-
ALL_CATEGORY_DIRS
|
|
410
|
+
ALL_CATEGORY_DIRS,
|
|
411
|
+
getCategoryDir
|
|
403
412
|
} from "./chunk-VS2IYZRU.js";
|
|
404
413
|
import {
|
|
405
414
|
recordCitationUsage
|
|
@@ -409,7 +418,7 @@ import {
|
|
|
409
418
|
} from "./chunk-3WCASNQZ.js";
|
|
410
419
|
|
|
411
420
|
// src/access-service.ts
|
|
412
|
-
import { createHash as
|
|
421
|
+
import { createHash as createHash13 } from "crypto";
|
|
413
422
|
import { constants as fsConstants2 } from "fs";
|
|
414
423
|
import { readdirSync, unlinkSync } from "fs";
|
|
415
424
|
import { stat as stat3 } from "fs/promises";
|
|
@@ -5451,6 +5460,7 @@ var OPERATION_NAMES = [
|
|
|
5451
5460
|
"review_list",
|
|
5452
5461
|
"review_resolve",
|
|
5453
5462
|
"contradiction_scan_run",
|
|
5463
|
+
"preference_drift_scan",
|
|
5454
5464
|
"memory_summarize_hourly",
|
|
5455
5465
|
"conversation_index_update",
|
|
5456
5466
|
"profiling_report",
|
|
@@ -5495,6 +5505,9 @@ var OPERATION_NAMES = [
|
|
|
5495
5505
|
"trust_zones_status",
|
|
5496
5506
|
"trust_zones_records",
|
|
5497
5507
|
"review_disposition",
|
|
5508
|
+
"review_deck_list",
|
|
5509
|
+
"review_deck_action",
|
|
5510
|
+
"review_deck_undo",
|
|
5498
5511
|
"trust_zones_promote",
|
|
5499
5512
|
"trust_zones_demo_seed",
|
|
5500
5513
|
"citations_observed",
|
|
@@ -5572,10 +5585,10 @@ function formatZodIssues(error) {
|
|
|
5572
5585
|
const parts = [];
|
|
5573
5586
|
for (const issue of error.issues) {
|
|
5574
5587
|
const hasNumeric = issue.path.some((p) => typeof p === "number");
|
|
5575
|
-
const
|
|
5588
|
+
const path20 = hasNumeric ? issue.path.filter((p) => typeof p === "string").join(".") || "(root)" : issue.path.length > 0 ? issue.path.join(".") : "(root)";
|
|
5576
5589
|
const options = enumOptionsFromIssue(issue);
|
|
5577
5590
|
const suffix = options ? `. Valid: ${options.join(", ")}` : "";
|
|
5578
|
-
parts.push(`${
|
|
5591
|
+
parts.push(`${path20}: ${issue.message}${suffix}`);
|
|
5579
5592
|
}
|
|
5580
5593
|
return parts.length > 0 ? `request validation failed: ${parts.join("; ")}` : "request validation failed";
|
|
5581
5594
|
}
|
|
@@ -9151,14 +9164,15 @@ ${snippet}`;
|
|
|
9151
9164
|
const withHandle = handle ? `${head.trimEnd()} ${handle}` : head.trimEnd();
|
|
9152
9165
|
const connectorLabel = renderConnectorLabel(r.sourceConnector);
|
|
9153
9166
|
const withConnector = connectorLabel ? `${withHandle} [agent: ${connectorLabel}]` : withHandle;
|
|
9167
|
+
const withDrift = r.driftNote ? `${withConnector} ${r.driftNote}` : withConnector;
|
|
9154
9168
|
if (hedgeMap) {
|
|
9155
9169
|
const item = trustResultFor(hedgeMap, r);
|
|
9156
9170
|
if (item) {
|
|
9157
9171
|
const hedge = renderEpistemicHedge(item.trust);
|
|
9158
|
-
if (hedge.length > 0) return `${
|
|
9172
|
+
if (hedge.length > 0) return `${withDrift} ${hedge}`;
|
|
9159
9173
|
}
|
|
9160
9174
|
}
|
|
9161
|
-
return
|
|
9175
|
+
return withDrift;
|
|
9162
9176
|
});
|
|
9163
9177
|
return { heading: `## ${title}`, entries };
|
|
9164
9178
|
}
|
|
@@ -10351,8 +10365,1403 @@ var AccessRecallSurface = class {
|
|
|
10351
10365
|
}
|
|
10352
10366
|
};
|
|
10353
10367
|
|
|
10368
|
+
// src/review/review-deck-surface.ts
|
|
10369
|
+
import { createHash as createHash8 } from "crypto";
|
|
10370
|
+
|
|
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") {
|
|
10375
|
+
super(message);
|
|
10376
|
+
this.name = "ReviewDeckCursorError";
|
|
10377
|
+
}
|
|
10378
|
+
};
|
|
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")}`;
|
|
10395
|
+
}
|
|
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
|
+
};
|
|
10418
|
+
}
|
|
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 } : {}
|
|
10468
|
+
};
|
|
10469
|
+
}
|
|
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
|
+
});
|
|
10497
|
+
}
|
|
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;
|
|
10509
|
+
}
|
|
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();
|
|
10519
|
+
}
|
|
10520
|
+
return fields;
|
|
10521
|
+
}
|
|
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);
|
|
10525
|
+
}
|
|
10526
|
+
function nonempty(value) {
|
|
10527
|
+
if (value === void 0) return void 0;
|
|
10528
|
+
return value.trim().length > 0 ? value : void 0;
|
|
10529
|
+
}
|
|
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");
|
|
10546
|
+
}
|
|
10547
|
+
return { v: 1, p: record.p, n: record.n, f: record.f, c: record.c, k: record.k };
|
|
10548
|
+
}
|
|
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;
|
|
10589
|
+
}
|
|
10590
|
+
}
|
|
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
|
+
}
|
|
10600
|
+
}
|
|
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
|
+
|
|
10354
11763
|
// src/support-passport/card-service.ts
|
|
10355
|
-
import { randomUUID as
|
|
11764
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
10356
11765
|
|
|
10357
11766
|
// src/support-passport/errors.ts
|
|
10358
11767
|
var SupportPassportError = class extends Error {
|
|
@@ -10542,14 +11951,14 @@ async function completeSupportPassportReplacementPrior(input) {
|
|
|
10542
11951
|
}
|
|
10543
11952
|
|
|
10544
11953
|
// src/support-passport/generated-batch.ts
|
|
10545
|
-
import
|
|
11954
|
+
import path16 from "path";
|
|
10546
11955
|
import { z as z2 } from "zod";
|
|
10547
11956
|
|
|
10548
11957
|
// src/support-passport/private-file.ts
|
|
10549
|
-
import { randomUUID } from "crypto";
|
|
11958
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
10550
11959
|
import { constants as fsConstants } from "fs";
|
|
10551
11960
|
import { lstat as lstat3, mkdir as mkdir3, open, rename as rename2, rm as rm2, stat as stat2 } from "fs/promises";
|
|
10552
|
-
import
|
|
11961
|
+
import path15 from "path";
|
|
10553
11962
|
var UNSUPPORTED_DIRECTORY_SYNC_ERRORS = /* @__PURE__ */ new Set(["EINVAL", "ENOSYS", "ENOTSUP", "EOPNOTSUPP"]);
|
|
10554
11963
|
var NON_WRITABLE_ANCESTOR_SYNC_ERRORS = /* @__PURE__ */ new Set(["EROFS", "EPERM", "EACCES"]);
|
|
10555
11964
|
function assertStableDirectory(before, opened, after, errorMessage) {
|
|
@@ -10575,8 +11984,8 @@ function openFlags(...flags) {
|
|
|
10575
11984
|
return combined;
|
|
10576
11985
|
}
|
|
10577
11986
|
function assertContainedPath(trustedRoot, directory, errorMessage) {
|
|
10578
|
-
const relative2 =
|
|
10579
|
-
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)) {
|
|
10580
11989
|
throw new Error(errorMessage);
|
|
10581
11990
|
}
|
|
10582
11991
|
}
|
|
@@ -10609,7 +12018,7 @@ async function syncDirectoryHandle(handle) {
|
|
|
10609
12018
|
}
|
|
10610
12019
|
async function resolvePrivateDirectoryPath(directory, handle, opened, errorMessage, platform = process.platform) {
|
|
10611
12020
|
const descriptorRoot = requirePrivateFileDescriptorRoot(platform, errorMessage);
|
|
10612
|
-
const pinnedPath =
|
|
12021
|
+
const pinnedPath = path15.join(descriptorRoot, String(handle.fd));
|
|
10613
12022
|
const metadata = await stat2(pinnedPath);
|
|
10614
12023
|
if (!metadata.isDirectory() || metadata.dev !== opened.dev || metadata.ino !== opened.ino) {
|
|
10615
12024
|
throw new Error(errorMessage);
|
|
@@ -10625,12 +12034,12 @@ function requirePrivateFileDescriptorRoot(platform, errorMessage) {
|
|
|
10625
12034
|
throw new Error(errorMessage);
|
|
10626
12035
|
}
|
|
10627
12036
|
async function openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform = process.platform) {
|
|
10628
|
-
const root =
|
|
10629
|
-
const target =
|
|
12037
|
+
const root = path15.resolve(trustedRoot);
|
|
12038
|
+
const target = path15.resolve(directory);
|
|
10630
12039
|
assertContainedPath(root, target, errorMessage);
|
|
10631
12040
|
requirePrivateFileDescriptorRoot(platform, errorMessage);
|
|
10632
|
-
const relative2 =
|
|
10633
|
-
const components = relative2 === "" ? [] : relative2.split(
|
|
12041
|
+
const relative2 = path15.relative(root, target);
|
|
12042
|
+
const components = relative2 === "" ? [] : relative2.split(path15.sep);
|
|
10634
12043
|
const handles = [];
|
|
10635
12044
|
let currentPath = root;
|
|
10636
12045
|
try {
|
|
@@ -10638,10 +12047,10 @@ async function openStableDirectoryFromRoot(trustedRoot, directory, errorMessage,
|
|
|
10638
12047
|
handles.push(current.handle);
|
|
10639
12048
|
for (const component of components) {
|
|
10640
12049
|
const pinnedParent = await resolvePrivateDirectoryPath(currentPath, current.handle, current.opened, errorMessage);
|
|
10641
|
-
const child = await openDirectoryNoFollow(
|
|
12050
|
+
const child = await openDirectoryNoFollow(path15.join(pinnedParent, component), errorMessage);
|
|
10642
12051
|
handles.push(child.handle);
|
|
10643
12052
|
assertStableDirectory(current.before, current.opened, await lstat3(currentPath), errorMessage);
|
|
10644
|
-
currentPath =
|
|
12053
|
+
currentPath = path15.join(currentPath, component);
|
|
10645
12054
|
current = child;
|
|
10646
12055
|
}
|
|
10647
12056
|
assertStableDirectory(current.before, current.opened, await lstat3(target), errorMessage);
|
|
@@ -10662,12 +12071,12 @@ async function openStableDirectoryFromRoot(trustedRoot, directory, errorMessage,
|
|
|
10662
12071
|
}
|
|
10663
12072
|
}
|
|
10664
12073
|
async function ensurePrivateDirectoryNoFollow(trustedRoot, directory, errorMessage, syncVerifiedParent = syncDirectoryHandle, hardenExistingChildren = true, platform = process.platform) {
|
|
10665
|
-
const root =
|
|
10666
|
-
const target =
|
|
12074
|
+
const root = path15.resolve(trustedRoot);
|
|
12075
|
+
const target = path15.resolve(directory);
|
|
10667
12076
|
assertContainedPath(root, target, errorMessage);
|
|
10668
|
-
const relative2 =
|
|
12077
|
+
const relative2 = path15.relative(root, target);
|
|
10669
12078
|
requirePrivateFileDescriptorRoot(platform, errorMessage);
|
|
10670
|
-
const components = relative2 === "" ? [] : relative2.split(
|
|
12079
|
+
const components = relative2 === "" ? [] : relative2.split(path15.sep);
|
|
10671
12080
|
const handles = [];
|
|
10672
12081
|
let currentPath = root;
|
|
10673
12082
|
try {
|
|
@@ -10675,7 +12084,7 @@ async function ensurePrivateDirectoryNoFollow(trustedRoot, directory, errorMessa
|
|
|
10675
12084
|
handles.push(current.handle);
|
|
10676
12085
|
for (const component of components) {
|
|
10677
12086
|
const pinnedParent = await resolvePrivateDirectoryPath(currentPath, current.handle, current.opened, errorMessage);
|
|
10678
|
-
const childPath =
|
|
12087
|
+
const childPath = path15.join(pinnedParent, component);
|
|
10679
12088
|
let created = false;
|
|
10680
12089
|
try {
|
|
10681
12090
|
await mkdir3(childPath, { mode: 448 });
|
|
@@ -10690,7 +12099,7 @@ async function ensurePrivateDirectoryNoFollow(trustedRoot, directory, errorMessa
|
|
|
10690
12099
|
await child.handle.chmod(448);
|
|
10691
12100
|
}
|
|
10692
12101
|
assertStableDirectory(current.before, current.opened, await lstat3(currentPath), errorMessage);
|
|
10693
|
-
currentPath =
|
|
12102
|
+
currentPath = path15.join(currentPath, component);
|
|
10694
12103
|
current = child;
|
|
10695
12104
|
}
|
|
10696
12105
|
assertStableDirectory(current.before, current.opened, await lstat3(target), errorMessage);
|
|
@@ -10699,8 +12108,8 @@ async function ensurePrivateDirectoryNoFollow(trustedRoot, directory, errorMessa
|
|
|
10699
12108
|
}
|
|
10700
12109
|
}
|
|
10701
12110
|
async function ensurePrivateDirectoryTreeNoFollow(directory, errorMessage, syncVerifiedParent = syncDirectoryHandle, platform = process.platform) {
|
|
10702
|
-
const target =
|
|
10703
|
-
const filesystemRoot =
|
|
12111
|
+
const target = path15.resolve(directory);
|
|
12112
|
+
const filesystemRoot = path15.parse(target).root;
|
|
10704
12113
|
const rootMetadata = await stat2(filesystemRoot);
|
|
10705
12114
|
await ensurePrivateDirectoryNoFollow(
|
|
10706
12115
|
filesystemRoot,
|
|
@@ -10735,15 +12144,15 @@ async function withPrivateDirectoryNoFollow(trustedRoot, directory, errorMessage
|
|
|
10735
12144
|
}
|
|
10736
12145
|
}
|
|
10737
12146
|
async function readPrivateFileNoFollow(directory, filePath, errorMessage, trustedRoot = directory, platform = process.platform) {
|
|
10738
|
-
if (
|
|
10739
|
-
const targetName =
|
|
12147
|
+
if (path15.dirname(filePath) !== path15.resolve(directory)) throw new Error(errorMessage);
|
|
12148
|
+
const targetName = path15.basename(filePath);
|
|
10740
12149
|
let directoryHandles = [];
|
|
10741
12150
|
let fileHandle;
|
|
10742
12151
|
try {
|
|
10743
12152
|
const stableDirectory = await openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform);
|
|
10744
12153
|
directoryHandles = stableDirectory.handles;
|
|
10745
12154
|
const pinnedDirectory = stableDirectory.pinnedDirectory;
|
|
10746
|
-
const targetPath =
|
|
12155
|
+
const targetPath = path15.join(pinnedDirectory, targetName);
|
|
10747
12156
|
const before = await lstat3(targetPath);
|
|
10748
12157
|
if (before.isSymbolicLink() || !before.isFile()) throw new Error(errorMessage);
|
|
10749
12158
|
try {
|
|
@@ -10762,10 +12171,10 @@ async function readPrivateFileNoFollow(directory, filePath, errorMessage, truste
|
|
|
10762
12171
|
}
|
|
10763
12172
|
}
|
|
10764
12173
|
async function appendPrivateFileAtPinnedDirectory(pinnedDirectory, targetName, content, errorMessage, directoryHandle, openFile) {
|
|
10765
|
-
if (targetName.length === 0 || targetName === "." || targetName === ".." ||
|
|
12174
|
+
if (targetName.length === 0 || targetName === "." || targetName === ".." || path15.basename(targetName) !== targetName) {
|
|
10766
12175
|
throw new Error(errorMessage);
|
|
10767
12176
|
}
|
|
10768
|
-
const targetPath =
|
|
12177
|
+
const targetPath = path15.join(pinnedDirectory, targetName);
|
|
10769
12178
|
let fileHandle;
|
|
10770
12179
|
try {
|
|
10771
12180
|
try {
|
|
@@ -10801,8 +12210,8 @@ async function appendPrivateFileAtPinnedDirectory(pinnedDirectory, targetName, c
|
|
|
10801
12210
|
}
|
|
10802
12211
|
async function appendPrivateFileInPinnedDirectory(pinnedDirectory, fileName, content, errorMessage, platform = process.platform) {
|
|
10803
12212
|
const descriptorRoot = requirePrivateFileDescriptorRoot(platform, errorMessage);
|
|
10804
|
-
const resolvedDirectory =
|
|
10805
|
-
const descriptor =
|
|
12213
|
+
const resolvedDirectory = path15.resolve(pinnedDirectory);
|
|
12214
|
+
const descriptor = path15.relative(descriptorRoot, resolvedDirectory);
|
|
10806
12215
|
if (!/^\d+$/.test(descriptor)) throw new Error(errorMessage);
|
|
10807
12216
|
const before = await stat2(resolvedDirectory);
|
|
10808
12217
|
if (!before.isDirectory()) throw new Error(errorMessage);
|
|
@@ -10818,9 +12227,9 @@ async function appendPrivateFileInPinnedDirectory(pinnedDirectory, fileName, con
|
|
|
10818
12227
|
}
|
|
10819
12228
|
}
|
|
10820
12229
|
async function writePrivateFileAtomicallyNoFollow(directory, filePath, content, errorMessage, trustedRoot = directory, platform = process.platform, syncVerifiedDirectory = syncDirectoryHandle) {
|
|
10821
|
-
if (
|
|
10822
|
-
const targetName =
|
|
10823
|
-
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`;
|
|
10824
12233
|
let tempPath;
|
|
10825
12234
|
let directoryHandles = [];
|
|
10826
12235
|
let fileHandle;
|
|
@@ -10828,8 +12237,8 @@ async function writePrivateFileAtomicallyNoFollow(directory, filePath, content,
|
|
|
10828
12237
|
const stableDirectory = await openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform);
|
|
10829
12238
|
directoryHandles = stableDirectory.handles;
|
|
10830
12239
|
const pinnedDirectory = stableDirectory.pinnedDirectory;
|
|
10831
|
-
tempPath =
|
|
10832
|
-
const targetPath =
|
|
12240
|
+
tempPath = path15.join(pinnedDirectory, tempName);
|
|
12241
|
+
const targetPath = path15.join(pinnedDirectory, targetName);
|
|
10833
12242
|
try {
|
|
10834
12243
|
fileHandle = await open(
|
|
10835
12244
|
tempPath,
|
|
@@ -10866,7 +12275,7 @@ async function writePrivateFileAtomicallyNoFollow(directory, filePath, content,
|
|
|
10866
12275
|
}
|
|
10867
12276
|
async function removePrivateFilesNoFollow(directory, fileNames, errorMessage, trustedRoot = directory, platform = process.platform) {
|
|
10868
12277
|
if (fileNames.some(
|
|
10869
|
-
(fileName) => fileName.length === 0 || fileName === "." || fileName === ".." ||
|
|
12278
|
+
(fileName) => fileName.length === 0 || fileName === "." || fileName === ".." || path15.basename(fileName) !== fileName
|
|
10870
12279
|
)) {
|
|
10871
12280
|
throw new Error(errorMessage);
|
|
10872
12281
|
}
|
|
@@ -10876,7 +12285,7 @@ async function removePrivateFilesNoFollow(directory, fileNames, errorMessage, tr
|
|
|
10876
12285
|
directoryHandles = stableDirectory.handles;
|
|
10877
12286
|
const pinnedDirectory = stableDirectory.pinnedDirectory;
|
|
10878
12287
|
for (const fileName of fileNames) {
|
|
10879
|
-
await rm2(
|
|
12288
|
+
await rm2(path15.join(pinnedDirectory, fileName), { force: true });
|
|
10880
12289
|
}
|
|
10881
12290
|
assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat3(directory), errorMessage);
|
|
10882
12291
|
if (stableDirectory.handle) await syncDirectoryHandle(stableDirectory.handle);
|
|
@@ -10897,13 +12306,13 @@ var GeneratedBatchMarkerSchema = z2.object({
|
|
|
10897
12306
|
}).strict();
|
|
10898
12307
|
var BATCH_ERROR = "The generated draft batch state is not safe.";
|
|
10899
12308
|
function batchDirectory(storage) {
|
|
10900
|
-
return
|
|
12309
|
+
return path16.join(storage.dir, "state", "support-passport", "generated-batches");
|
|
10901
12310
|
}
|
|
10902
12311
|
function batchFileName(batchId) {
|
|
10903
12312
|
return `${BatchIdSchema.parse(batchId)}.json`;
|
|
10904
12313
|
}
|
|
10905
12314
|
function batchPath(storage, batchId) {
|
|
10906
|
-
return
|
|
12315
|
+
return path16.join(batchDirectory(storage), batchFileName(batchId));
|
|
10907
12316
|
}
|
|
10908
12317
|
function markerFor(context, batchId, size, complete) {
|
|
10909
12318
|
return GeneratedBatchMarkerSchema.parse({
|
|
@@ -11327,19 +12736,19 @@ var SupportPassportAnswerModelInputSchema = z4.object({
|
|
|
11327
12736
|
}).strict();
|
|
11328
12737
|
|
|
11329
12738
|
// src/support-passport/owner-lock.ts
|
|
11330
|
-
import { createHash as
|
|
11331
|
-
import
|
|
12739
|
+
import { createHash as createHash9 } from "crypto";
|
|
12740
|
+
import path17 from "path";
|
|
11332
12741
|
var CARD_MUTATION_LOCK_STALE_MS = 6e4;
|
|
11333
12742
|
var CARD_MUTATION_LOCK_MAX_WAIT_MS = 3e4;
|
|
11334
12743
|
function computeSupportPassportOwnerLockKey(namespace, principal) {
|
|
11335
|
-
return
|
|
12744
|
+
return createHash9("sha256").update(JSON.stringify([namespace, principal])).digest("hex");
|
|
11336
12745
|
}
|
|
11337
12746
|
function supportPassportOwnerLockPath(storage, scope) {
|
|
11338
12747
|
const ownerLockKey = scope.ownerKey ?? computeSupportPassportOwnerLockKey(scope.namespace, scope.principal);
|
|
11339
12748
|
if (!/^[a-f0-9]{64}$/.test(ownerLockKey)) {
|
|
11340
12749
|
throw new SupportPassportError("card_data_invalid", "The support passport owner scope is invalid.", 500);
|
|
11341
12750
|
}
|
|
11342
|
-
return
|
|
12751
|
+
return path17.join(storage.dir, "state", `support-passport-cards-${ownerLockKey}.lock`);
|
|
11343
12752
|
}
|
|
11344
12753
|
async function withSupportPassportOwnerLock(storage, scope, task) {
|
|
11345
12754
|
const lockPath = supportPassportOwnerLockPath(storage, scope);
|
|
@@ -11447,7 +12856,7 @@ var SupportPassportCardService = class {
|
|
|
11447
12856
|
const onCommitted = once(input.onCommitted);
|
|
11448
12857
|
return await withSupportPassportOwnerLock(storage, { namespace, principal }, async (lock) => {
|
|
11449
12858
|
const batchContext = this.generatedBatchContext(storage, lock, principal, namespace, onCommitted);
|
|
11450
|
-
const batchId =
|
|
12859
|
+
const batchId = randomUUID3();
|
|
11451
12860
|
const created = [];
|
|
11452
12861
|
const createdIds = [];
|
|
11453
12862
|
const createdRecords = [];
|
|
@@ -12235,9 +13644,9 @@ var SupportPassportCardService = class {
|
|
|
12235
13644
|
};
|
|
12236
13645
|
|
|
12237
13646
|
// src/support-passport/grant-store.ts
|
|
12238
|
-
import { createHash as
|
|
13647
|
+
import { createHash as createHash10, randomBytes, randomUUID as randomUUID4, timingSafeEqual } from "crypto";
|
|
12239
13648
|
import { lstat as lstat4, open as open2, readdir as readdir4 } from "fs/promises";
|
|
12240
|
-
import
|
|
13649
|
+
import path18 from "path";
|
|
12241
13650
|
var GRANT_LOCK_STALE_MS = 3e4;
|
|
12242
13651
|
var GRANT_LOCK_WAIT_MS = 5e3;
|
|
12243
13652
|
var GRANT_LOCK_HEARTBEAT_MS = 1e4;
|
|
@@ -12260,7 +13669,7 @@ var MalformedGrantStateError = class extends Error {
|
|
|
12260
13669
|
}
|
|
12261
13670
|
};
|
|
12262
13671
|
function sha256(domain, value) {
|
|
12263
|
-
return
|
|
13672
|
+
return createHash10("sha256").update(domain).update("\0").update(value).digest("hex");
|
|
12264
13673
|
}
|
|
12265
13674
|
function hashesMatch(left, right) {
|
|
12266
13675
|
const leftBytes = Buffer.from(left, "hex");
|
|
@@ -12329,12 +13738,12 @@ var SupportPassportGrantStore = class {
|
|
|
12329
13738
|
runWithHeldFileLock;
|
|
12330
13739
|
syncDirectory;
|
|
12331
13740
|
constructor(options) {
|
|
12332
|
-
this.memoryDir =
|
|
12333
|
-
this.grantsDir =
|
|
12334
|
-
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");
|
|
12335
13744
|
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
12336
13745
|
this.makeSecret = options.makeSecret ?? (() => randomBytes(32));
|
|
12337
|
-
this.makeGrantId = options.makeGrantId ??
|
|
13746
|
+
this.makeGrantId = options.makeGrantId ?? randomUUID4;
|
|
12338
13747
|
this.runWithHeldFileLock = options.withHeldFileLock ?? withHeldFileLock;
|
|
12339
13748
|
this.syncDirectory = options.syncDirectory ?? syncDirectoryForDurability;
|
|
12340
13749
|
}
|
|
@@ -12544,11 +13953,11 @@ var SupportPassportGrantStore = class {
|
|
|
12544
13953
|
}
|
|
12545
13954
|
filePath(grantId) {
|
|
12546
13955
|
const normalizedGrantId = normalizeGrantId(grantId);
|
|
12547
|
-
return
|
|
13956
|
+
return path18.join(this.grantsDir, `${normalizedGrantId}.json`);
|
|
12548
13957
|
}
|
|
12549
13958
|
ownerIndexPath(ownerHash) {
|
|
12550
13959
|
if (!SAFE_OWNER_INDEX_HASH.test(ownerHash)) throw new Error("support passport owner index hash is invalid");
|
|
12551
|
-
return
|
|
13960
|
+
return path18.join(this.ownerIndexesDir, `${ownerHash}.json`);
|
|
12552
13961
|
}
|
|
12553
13962
|
ownerHash(namespace, principalHash) {
|
|
12554
13963
|
return sha256("support-passport-owner-index:v1", `${namespace}\0${principalHash}`);
|
|
@@ -12604,12 +14013,12 @@ var SupportPassportGrantStore = class {
|
|
|
12604
14013
|
this.grantsDir,
|
|
12605
14014
|
grantIds.map((grantId) => `${grantId}.json`),
|
|
12606
14015
|
"support passport grant files must be regular files in a stable directory",
|
|
12607
|
-
|
|
14016
|
+
path18.parse(this.memoryDir).root
|
|
12608
14017
|
);
|
|
12609
14018
|
}
|
|
12610
14019
|
ownerMembershipDirectory(ownerHash) {
|
|
12611
14020
|
if (!SAFE_OWNER_INDEX_HASH.test(ownerHash)) throw new Error("support passport owner index hash is invalid");
|
|
12612
|
-
return
|
|
14021
|
+
return path18.join(this.ownerIndexesDir, ownerHash);
|
|
12613
14022
|
}
|
|
12614
14023
|
async ensureOwnerMembershipDirectory(ownerHash) {
|
|
12615
14024
|
const directory = this.ownerMembershipDirectory(ownerHash);
|
|
@@ -12624,11 +14033,11 @@ var SupportPassportGrantStore = class {
|
|
|
12624
14033
|
const directory = await this.ensureOwnerMembershipDirectory(ownerHash);
|
|
12625
14034
|
await writePrivateFileAtomicallyNoFollow(
|
|
12626
14035
|
directory,
|
|
12627
|
-
|
|
14036
|
+
path18.join(directory, `${state.grantId}.json`),
|
|
12628
14037
|
`${JSON.stringify({ schemaVersion: 1, grantId: state.grantId })}
|
|
12629
14038
|
`,
|
|
12630
14039
|
"support passport owner membership must be regular files in a stable directory",
|
|
12631
|
-
|
|
14040
|
+
path18.parse(this.memoryDir).root
|
|
12632
14041
|
);
|
|
12633
14042
|
}
|
|
12634
14043
|
async removeOwnerMembership(state) {
|
|
@@ -12638,7 +14047,7 @@ var SupportPassportGrantStore = class {
|
|
|
12638
14047
|
directory,
|
|
12639
14048
|
[`${state.grantId}.json`],
|
|
12640
14049
|
"support passport owner membership must be regular files in a stable directory",
|
|
12641
|
-
|
|
14050
|
+
path18.parse(this.memoryDir).root
|
|
12642
14051
|
);
|
|
12643
14052
|
}
|
|
12644
14053
|
async removeStoredGrant(state) {
|
|
@@ -12739,7 +14148,7 @@ var SupportPassportGrantStore = class {
|
|
|
12739
14148
|
const ownerHash = this.ownerHash(namespace, principalHash);
|
|
12740
14149
|
const directory = await this.ensureOwnerMembershipDirectory(ownerHash);
|
|
12741
14150
|
const grantIds = await withPrivateDirectoryNoFollow(
|
|
12742
|
-
|
|
14151
|
+
path18.parse(this.memoryDir).root,
|
|
12743
14152
|
directory,
|
|
12744
14153
|
"support passport owner membership must be regular files in a stable directory",
|
|
12745
14154
|
async (pinnedDirectory) => {
|
|
@@ -12770,7 +14179,7 @@ var SupportPassportGrantStore = class {
|
|
|
12770
14179
|
this.ownerIndexesDir,
|
|
12771
14180
|
filePath,
|
|
12772
14181
|
"support passport owner indexes must be regular files in a stable directory",
|
|
12773
|
-
|
|
14182
|
+
path18.parse(this.memoryDir).root
|
|
12774
14183
|
);
|
|
12775
14184
|
} catch (error) {
|
|
12776
14185
|
if (error.code === "ENOENT") return [];
|
|
@@ -12810,7 +14219,7 @@ var SupportPassportGrantStore = class {
|
|
|
12810
14219
|
`${JSON.stringify({ schemaVersion: 1, ownerHash, grantIds }, null, 2)}
|
|
12811
14220
|
`,
|
|
12812
14221
|
"support passport owner indexes must be regular files in a stable directory",
|
|
12813
|
-
|
|
14222
|
+
path18.parse(this.memoryDir).root
|
|
12814
14223
|
);
|
|
12815
14224
|
}
|
|
12816
14225
|
async readState(grantId) {
|
|
@@ -12820,7 +14229,7 @@ var SupportPassportGrantStore = class {
|
|
|
12820
14229
|
this.grantsDir,
|
|
12821
14230
|
filePath,
|
|
12822
14231
|
"support passport grant files must be regular files in a stable directory",
|
|
12823
|
-
|
|
14232
|
+
path18.parse(this.memoryDir).root
|
|
12824
14233
|
);
|
|
12825
14234
|
try {
|
|
12826
14235
|
const state = SupportPassportGrantStateSchema.parse(JSON.parse(content));
|
|
@@ -12854,7 +14263,7 @@ var SupportPassportGrantStore = class {
|
|
|
12854
14263
|
`${JSON.stringify(state, null, 2)}
|
|
12855
14264
|
`,
|
|
12856
14265
|
"support passport grant files must be regular files in a stable directory",
|
|
12857
|
-
|
|
14266
|
+
path18.parse(this.memoryDir).root
|
|
12858
14267
|
);
|
|
12859
14268
|
}
|
|
12860
14269
|
async ensureSafeDirectories() {
|
|
@@ -12888,8 +14297,8 @@ var SupportPassportGrantStore = class {
|
|
|
12888
14297
|
void 0
|
|
12889
14298
|
);
|
|
12890
14299
|
this.memoryDir = configuredMemoryDir;
|
|
12891
|
-
this.grantsDir =
|
|
12892
|
-
this.ownerIndexesDir =
|
|
14300
|
+
this.grantsDir = path18.join(configuredMemoryDir, "state", "support-passport", "grants");
|
|
14301
|
+
this.ownerIndexesDir = path18.join(this.grantsDir, "owners");
|
|
12893
14302
|
})();
|
|
12894
14303
|
}
|
|
12895
14304
|
const currentAttempt = this.memoryRootReady;
|
|
@@ -12903,12 +14312,12 @@ var SupportPassportGrantStore = class {
|
|
|
12903
14312
|
async withMutationLock(task) {
|
|
12904
14313
|
await this.ensureSafeDirectories();
|
|
12905
14314
|
return await withPrivateDirectoryNoFollow(
|
|
12906
|
-
|
|
14315
|
+
path18.parse(this.memoryDir).root,
|
|
12907
14316
|
this.grantsDir,
|
|
12908
14317
|
"support passport grant lock directory must remain inside the memory directory",
|
|
12909
14318
|
async (pinnedDirectory) => await this.withExclusiveLock(
|
|
12910
14319
|
`support-passport-grants:${this.grantsDir}`,
|
|
12911
|
-
|
|
14320
|
+
path18.join(pinnedDirectory, ".grants.lock"),
|
|
12912
14321
|
task
|
|
12913
14322
|
)
|
|
12914
14323
|
);
|
|
@@ -12917,12 +14326,12 @@ var SupportPassportGrantStore = class {
|
|
|
12917
14326
|
const normalizedGrantId = normalizeGrantId(grantId);
|
|
12918
14327
|
await this.ensureSafeDirectories();
|
|
12919
14328
|
return await withPrivateDirectoryNoFollow(
|
|
12920
|
-
|
|
14329
|
+
path18.parse(this.memoryDir).root,
|
|
12921
14330
|
this.grantsDir,
|
|
12922
14331
|
"support passport grant lock directory must remain inside the memory directory",
|
|
12923
14332
|
async (pinnedDirectory) => await this.withExclusiveLock(
|
|
12924
14333
|
`support-passport-grant:${this.grantsDir}:${normalizedGrantId}`,
|
|
12925
|
-
|
|
14334
|
+
path18.join(pinnedDirectory, `.${normalizedGrantId}.lock`),
|
|
12926
14335
|
task
|
|
12927
14336
|
)
|
|
12928
14337
|
);
|
|
@@ -12930,12 +14339,12 @@ var SupportPassportGrantStore = class {
|
|
|
12930
14339
|
async withOwnerIndexLock(ownerHash, task) {
|
|
12931
14340
|
await this.ensureSafeDirectories();
|
|
12932
14341
|
return await withPrivateDirectoryNoFollow(
|
|
12933
|
-
|
|
14342
|
+
path18.parse(this.memoryDir).root,
|
|
12934
14343
|
this.ownerIndexesDir,
|
|
12935
14344
|
"support passport owner lock directory must remain inside the memory directory",
|
|
12936
14345
|
async (pinnedDirectory) => await this.withExclusiveLock(
|
|
12937
14346
|
`support-passport-owner:${this.ownerIndexesDir}:${ownerHash}`,
|
|
12938
|
-
|
|
14347
|
+
path18.join(pinnedDirectory, `.${ownerHash}.lock`),
|
|
12939
14348
|
task
|
|
12940
14349
|
)
|
|
12941
14350
|
);
|
|
@@ -13772,8 +15181,8 @@ var SupportPassportModelAdapter = class {
|
|
|
13772
15181
|
};
|
|
13773
15182
|
|
|
13774
15183
|
// src/support-passport/model-audit.ts
|
|
13775
|
-
import { createHash as
|
|
13776
|
-
import
|
|
15184
|
+
import { createHash as createHash11 } from "crypto";
|
|
15185
|
+
import path19 from "path";
|
|
13777
15186
|
import { z as z5 } from "zod";
|
|
13778
15187
|
var HashSchema = z5.string().regex(/^[a-f0-9]{64}$/);
|
|
13779
15188
|
var SupportPassportModelAuditRecordSchema = z5.object({
|
|
@@ -13810,7 +15219,7 @@ var SupportPassportModelAuditRecordSchema = z5.object({
|
|
|
13810
15219
|
}
|
|
13811
15220
|
});
|
|
13812
15221
|
function hashSupportPassportAuditValues(domain, values) {
|
|
13813
|
-
return
|
|
15222
|
+
return createHash11("sha256").update(`support-passport-audit:${domain}:v1`).update("\0").update([...values].sort().join("\0")).digest("hex");
|
|
13814
15223
|
}
|
|
13815
15224
|
var SupportPassportModelAuditStore = class {
|
|
13816
15225
|
memoryDir;
|
|
@@ -13818,15 +15227,15 @@ var SupportPassportModelAuditStore = class {
|
|
|
13818
15227
|
memoryRootReady;
|
|
13819
15228
|
runWithHeldFileLock;
|
|
13820
15229
|
constructor(options) {
|
|
13821
|
-
this.memoryDir =
|
|
13822
|
-
this.auditDir =
|
|
15230
|
+
this.memoryDir = path19.resolve(expandTildePath(options.memoryDir));
|
|
15231
|
+
this.auditDir = path19.join(this.memoryDir, "state", "support-passport", "audit");
|
|
13823
15232
|
this.runWithHeldFileLock = options.withHeldFileLock ?? withHeldFileLock;
|
|
13824
15233
|
}
|
|
13825
15234
|
async record(input) {
|
|
13826
15235
|
const record = SupportPassportModelAuditRecordSchema.parse(input);
|
|
13827
15236
|
await this.ensureSafeDirectories();
|
|
13828
15237
|
const day = record.occurredAt.slice(0, 10);
|
|
13829
|
-
const filePath =
|
|
15238
|
+
const filePath = path19.join(this.auditDir, `${day}.jsonl`);
|
|
13830
15239
|
await serializeMutations(
|
|
13831
15240
|
`support-passport-audit:${filePath}`,
|
|
13832
15241
|
() => withPrivateDirectoryNoFollow(
|
|
@@ -13834,7 +15243,7 @@ var SupportPassportModelAuditStore = class {
|
|
|
13834
15243
|
this.auditDir,
|
|
13835
15244
|
"support passport audit directory must remain inside the memory directory",
|
|
13836
15245
|
async (pinnedDirectory) => await this.runWithHeldFileLock(
|
|
13837
|
-
|
|
15246
|
+
path19.join(pinnedDirectory, `.${day}.lock`),
|
|
13838
15247
|
{
|
|
13839
15248
|
staleMs: 3e4,
|
|
13840
15249
|
maxWaitMs: 5e3,
|
|
@@ -13871,7 +15280,7 @@ var SupportPassportModelAuditStore = class {
|
|
|
13871
15280
|
"support passport memory directory must be a stable directory"
|
|
13872
15281
|
);
|
|
13873
15282
|
this.memoryDir = configuredMemoryDir;
|
|
13874
|
-
this.auditDir =
|
|
15283
|
+
this.auditDir = path19.join(configuredMemoryDir, "state", "support-passport", "audit");
|
|
13875
15284
|
})();
|
|
13876
15285
|
}
|
|
13877
15286
|
const currentAttempt = this.memoryRootReady;
|
|
@@ -13885,7 +15294,7 @@ var SupportPassportModelAuditStore = class {
|
|
|
13885
15294
|
};
|
|
13886
15295
|
|
|
13887
15296
|
// src/support-passport/model-service.ts
|
|
13888
|
-
import { createHash as
|
|
15297
|
+
import { createHash as createHash12 } from "crypto";
|
|
13889
15298
|
import { z as z6 } from "zod";
|
|
13890
15299
|
var DraftServiceInputSchema = z6.object({
|
|
13891
15300
|
principal: z6.string().trim().min(1).max(512),
|
|
@@ -13921,7 +15330,7 @@ function supportPassportSourceContent(memory) {
|
|
|
13921
15330
|
return hasStructuredAttributes(memory.frontmatter.structuredAttributes) ? stripAttributesSuffix(memory.content) : memory.content;
|
|
13922
15331
|
}
|
|
13923
15332
|
function computeSupportPassportSourceRevision(content, structuredAttributes) {
|
|
13924
|
-
return
|
|
15333
|
+
return createHash12("sha256").update("support-passport-source:v1\0").update(hasStructuredAttributes(structuredAttributes) ? stripAttributesSuffix(content) : content).digest("hex");
|
|
13925
15334
|
}
|
|
13926
15335
|
function isSupportPassportSourceEligible(memory) {
|
|
13927
15336
|
const status = memory.frontmatter.status ?? "active";
|
|
@@ -14557,6 +15966,7 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
14557
15966
|
this.idempotency = new AccessIdempotencyStore(orchestrator.config.memoryDir);
|
|
14558
15967
|
this.replicaDivergenceMonitor = new ReplicaDivergenceMonitor({ resolveSecretRef: options.resolveSecretRef });
|
|
14559
15968
|
this.injectedSupportPassportGatewayRoute = options.supportPassportGatewayRoute ?? null;
|
|
15969
|
+
this.reviewDeckEnabled = options.reviewDeckEnabled === true;
|
|
14560
15970
|
const accessCaps = resolveAccessSetupCapabilities(orchestrator.config);
|
|
14561
15971
|
this.budget = new CrossNamespaceBudget({
|
|
14562
15972
|
enabled: accessCaps.recallCrossNamespaceBudget,
|
|
@@ -14596,6 +16006,7 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
14596
16006
|
corpusWatermarkCache = new CorpusWatermarkCache();
|
|
14597
16007
|
replicaDivergenceMonitor;
|
|
14598
16008
|
injectedSupportPassportGatewayRoute;
|
|
16009
|
+
reviewDeckEnabled;
|
|
14599
16010
|
/** AccessObserveWriteSurface (access-service decomposition). Lazy; selfDeps live wiring. */
|
|
14600
16011
|
_accessObserveWriteSurface;
|
|
14601
16012
|
get accessObserveWriteSurface() {
|
|
@@ -14624,6 +16035,15 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
14624
16035
|
}
|
|
14625
16036
|
return this._accessAdminOpsSurface;
|
|
14626
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
|
+
}
|
|
14627
16047
|
/** AccessRecallSurface (access-service decomposition). Lazy; selfDeps live wiring. */
|
|
14628
16048
|
_accessRecallSurface;
|
|
14629
16049
|
get accessRecallSurface() {
|
|
@@ -17407,8 +18827,8 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
17407
18827
|
async offlineSyncSnapshot(options = {}) {
|
|
17408
18828
|
const resolvedNamespace = this.resolveReadableNamespace(options.namespace, options.principal);
|
|
17409
18829
|
const storage = await offlineSyncStorageForSnapshot(this.orchestrator, resolvedNamespace);
|
|
17410
|
-
const storageHash =
|
|
17411
|
-
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 }));
|
|
17412
18832
|
const snapshotBuilder = options.includeContent === false && options.baseFiles && options.baseFiles.length > 0 ? buildOfflineSyncSnapshotFromBase : buildOfflineSyncSnapshot;
|
|
17413
18833
|
const snapshot = await snapshotBuilder({
|
|
17414
18834
|
root: storage.dir,
|
|
@@ -17431,10 +18851,10 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
17431
18851
|
async offlineSyncSnapshotStream(options = {}) {
|
|
17432
18852
|
const resolvedNamespace = this.resolveReadableNamespace(options.namespace, options.principal);
|
|
17433
18853
|
const storage = await offlineSyncStorageForSnapshot(this.orchestrator, resolvedNamespace);
|
|
17434
|
-
const storageHash =
|
|
18854
|
+
const storageHash = createHash13("sha256").update(storage.dir).digest("hex").slice(0, 16);
|
|
17435
18855
|
const deletions = await filterOfflineSyncDeletionRevisions({
|
|
17436
18856
|
root: storage.dir,
|
|
17437
|
-
deletions: [...await storage.readDeletionRevisions()].map(([
|
|
18857
|
+
deletions: [...await storage.readDeletionRevisions()].map(([path20, mtimeMs]) => ({ path: path20, mtimeMs })),
|
|
17438
18858
|
includeTranscripts: options.includeTranscripts !== false,
|
|
17439
18859
|
userExcludeRegexps: this.offlineSyncUserExcludes
|
|
17440
18860
|
});
|
|
@@ -17471,7 +18891,7 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
17471
18891
|
async offlineSyncFiles(options) {
|
|
17472
18892
|
const resolvedNamespace = this.resolveReadableNamespace(options.namespace, options.principal);
|
|
17473
18893
|
const storage = await offlineSyncStorageForSnapshot(this.orchestrator, resolvedNamespace);
|
|
17474
|
-
const storageHash =
|
|
18894
|
+
const storageHash = createHash13("sha256").update(storage.dir).digest("hex").slice(0, 16);
|
|
17475
18895
|
try {
|
|
17476
18896
|
const snapshot = await buildOfflineSyncSnapshotForPaths({
|
|
17477
18897
|
root: storage.dir,
|
|
@@ -17710,6 +19130,15 @@ var EngramAccessService = class extends SupportPassportAccessServiceBase {
|
|
|
17710
19130
|
async adminPromoteMemory(request) {
|
|
17711
19131
|
return this.accessAdminOpsSurface.adminPromoteMemory(request);
|
|
17712
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
|
+
}
|
|
17713
19142
|
};
|
|
17714
19143
|
|
|
17715
19144
|
// src/access-recall-concurrency.ts
|
|
@@ -18081,6 +19510,17 @@ export {
|
|
|
18081
19510
|
RecallResultFormatter,
|
|
18082
19511
|
assembleRecallResponse,
|
|
18083
19512
|
AccessRecallSurface,
|
|
19513
|
+
ReviewDeckCursorError,
|
|
19514
|
+
computeReviewItemRevision,
|
|
19515
|
+
projectReviewDeckItem,
|
|
19516
|
+
compareReviewDeckRows,
|
|
19517
|
+
encodeReviewDeckCursor,
|
|
19518
|
+
decodeReviewDeckCursor,
|
|
19519
|
+
buildReviewDeckPage,
|
|
19520
|
+
listReviewItems,
|
|
19521
|
+
performReview,
|
|
19522
|
+
readReviewDeckSnapshot,
|
|
19523
|
+
readReviewDeckRow,
|
|
18084
19524
|
SupportPassportError,
|
|
18085
19525
|
SupportPassportGrantCardRefSchema,
|
|
18086
19526
|
SupportPassportGrantStateSchema,
|
|
@@ -18127,4 +19567,4 @@ export {
|
|
|
18127
19567
|
EngramAccessService,
|
|
18128
19568
|
AccessAdminOpsSurface
|
|
18129
19569
|
};
|
|
18130
|
-
//# sourceMappingURL=chunk-
|
|
19570
|
+
//# sourceMappingURL=chunk-AZLLH6YA.js.map
|