@remnic/core 9.66.1 → 9.66.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-admin-ops-surface.js +30 -30
- package/dist/access-authorization-probe.js +31 -31
- package/dist/access-boundary.js +30 -30
- package/dist/access-cli.js +96 -94
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.js +30 -30
- package/dist/access-http-query.js +32 -32
- package/dist/access-http.js +45 -45
- package/dist/access-identity-continuity-surface.js +30 -30
- package/dist/access-lcm-surface.js +30 -30
- package/dist/access-mcp.js +38 -38
- package/dist/access-namespace-preflight.js +30 -30
- package/dist/access-observe-write-surface.js +30 -30
- package/dist/access-operations-batch.js +33 -33
- package/dist/access-operations.js +37 -37
- package/dist/access-recall-concurrency.js +30 -30
- package/dist/access-recall-response.js +30 -30
- package/dist/access-recall-surface.js +30 -30
- package/dist/access-schema.js +3 -3
- package/dist/access-service.js +30 -30
- package/dist/access-surface-catalog.js +32 -32
- package/dist/active-recall.js +3 -3
- package/dist/briefing.js +13 -13
- package/dist/buffer.js +4 -4
- package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
- package/dist/causal-behavior.js +2 -2
- package/dist/causal-chain.js +2 -2
- package/dist/causal-consolidation.js +16 -16
- package/dist/causal-retrieval.js +2 -2
- package/dist/causal-trajectory-graph.js +2 -2
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-XKNHFDTT.js → chunk-3A2Z4OOS.js} +2 -2
- package/dist/{chunk-CHGG74CY.js → chunk-3HHTN5X7.js} +2 -2
- package/dist/{chunk-TCF4MU7L.js → chunk-3PO35HUU.js} +1218 -104
- package/dist/chunk-3PO35HUU.js.map +1 -0
- package/dist/{chunk-XOHYGIWF.js → chunk-3Z4SFJA5.js} +2 -2
- package/dist/{chunk-RDGKVH6T.js → chunk-4NKIGSJM.js} +2 -2
- package/dist/{chunk-GPFZFCRN.js → chunk-4PTTMTTQ.js} +1 -1
- package/dist/{chunk-VG4SSPAW.js → chunk-4XESAT4V.js} +2 -2
- package/dist/{chunk-S4CDUXQY.js → chunk-5KGLNBUB.js} +2 -2
- package/dist/{chunk-2X6BGKQL.js → chunk-5XRZANCW.js} +10 -10
- package/dist/{chunk-TCQRIIIN.js → chunk-6DODJYBY.js} +2 -2
- package/dist/{chunk-KWIGDKM2.js → chunk-73CAEYI3.js} +2 -2
- package/dist/{chunk-J2R275FN.js → chunk-7DXW5V2W.js} +2 -2
- package/dist/{chunk-LYUUA6QB.js → chunk-7JJHIVMG.js} +2 -2
- package/dist/{chunk-2FA7U5XY.js → chunk-7NNMRMLZ.js} +2 -2
- package/dist/{chunk-227UFSEQ.js → chunk-7RZJWZ46.js} +5 -5
- package/dist/{chunk-EWKVYCFP.js → chunk-B2OKCCXX.js} +1 -1
- package/dist/{chunk-NSTNGMSS.js → chunk-B7AGLMGP.js} +7 -7
- package/dist/chunk-BLUYQFRH.js +36 -0
- package/dist/chunk-BLUYQFRH.js.map +1 -0
- package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
- package/dist/{chunk-CEH2AFXG.js → chunk-C24UZSFW.js} +6 -6
- package/dist/{chunk-LTBKKSCX.js → chunk-C2JCVZWX.js} +2 -2
- package/dist/{chunk-65JOGLIS.js → chunk-D4R3OUZA.js} +2 -2
- package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
- package/dist/chunk-E4X2YX2F.js +22 -0
- package/dist/chunk-E4X2YX2F.js.map +1 -0
- package/dist/{chunk-IGZCAHFL.js → chunk-EGGNFLAT.js} +2 -2
- package/dist/{chunk-H2IRSXZN.js → chunk-ESDOAP7W.js} +3 -3
- package/dist/{chunk-D3UXGE5D.js → chunk-EZWIEFYD.js} +8 -8
- package/dist/{chunk-ZPS724LT.js → chunk-F5H5QINZ.js} +2 -2
- package/dist/{chunk-S4Z2OBTX.js → chunk-FPSOXMLK.js} +3 -3
- package/dist/chunk-FYDW33ZB.js +13 -0
- package/dist/chunk-FYDW33ZB.js.map +1 -0
- package/dist/{chunk-CX4OLNIH.js → chunk-G5UKF2GJ.js} +2 -2
- package/dist/{chunk-OJUEUQDJ.js → chunk-GGY2747C.js} +2 -2
- package/dist/{chunk-TNGH4ZYI.js → chunk-GNWLTCKC.js} +2 -2
- package/dist/{chunk-YWPLOJ7T.js → chunk-GZPGI45F.js} +2 -2
- package/dist/{chunk-NFP4KPTA.js → chunk-IDEPEHUG.js} +2 -2
- package/dist/{chunk-LJABGXC4.js → chunk-IN5EUWCA.js} +3 -3
- package/dist/{chunk-U6NGKS32.js → chunk-JJAOVJ3E.js} +9 -9
- package/dist/{chunk-RPIS5FQ7.js → chunk-JWCS3VYQ.js} +50 -50
- package/dist/{chunk-U65VJSCJ.js → chunk-KE23ZIEW.js} +13 -13
- package/dist/{chunk-NACLNNFQ.js → chunk-KSZKQTZS.js} +2 -2
- package/dist/{chunk-KJXCD7VR.js → chunk-KWJNEWTM.js} +5 -5
- package/dist/chunk-MAG6M3B6.js +51 -0
- package/dist/chunk-MAG6M3B6.js.map +1 -0
- package/dist/chunk-MKD3OMPS.js +20 -0
- package/dist/chunk-MKD3OMPS.js.map +1 -0
- package/dist/{chunk-UW4RYPWC.js → chunk-MLTGALDY.js} +2 -2
- package/dist/{chunk-MUEGIKKY.js → chunk-OKGQDI4Y.js} +17 -16
- package/dist/chunk-OKGQDI4Y.js.map +1 -0
- package/dist/{chunk-YMOPYG3K.js → chunk-OLT3YTDH.js} +4 -4
- package/dist/{chunk-2PSX5BJU.js → chunk-OPQKVVYG.js} +2 -2
- package/dist/{chunk-D6Q5EPOV.js → chunk-PGD3DXZP.js} +2 -2
- package/dist/chunk-Q3SHEAXR.js +80 -0
- package/dist/chunk-Q3SHEAXR.js.map +1 -0
- package/dist/{chunk-GBEOUCBB.js → chunk-Q6LC3ZD5.js} +2 -2
- package/dist/{chunk-QBNE55VA.js → chunk-QELYSDAU.js} +2 -2
- package/dist/{chunk-INUBU6I5.js → chunk-S6PRJGQL.js} +2 -2
- package/dist/{chunk-B4AOWRYF.js → chunk-TCJO7LOG.js} +5 -5
- package/dist/{chunk-SZMYGDSM.js → chunk-TO5U47YK.js} +2 -2
- package/dist/{chunk-GAJK3DQ5.js → chunk-U3L6GRUX.js} +2 -2
- package/dist/{chunk-4XLTUR6R.js → chunk-U4RGSLI4.js} +3 -3
- package/dist/{chunk-M5ERTI4I.js → chunk-UH53XVQ3.js} +2 -2
- package/dist/{chunk-NUF7VSEX.js → chunk-UXERIBOJ.js} +2 -2
- package/dist/{chunk-FFUMTH27.js → chunk-VA2CSIPC.js} +2 -2
- package/dist/{chunk-KQAFEZQX.js → chunk-VDX2J7OX.js} +2 -2
- package/dist/{chunk-AF5H7TKI.js → chunk-VPJNGE2R.js} +2 -2
- package/dist/{chunk-OMX6TKXH.js → chunk-VTJZSLDR.js} +2 -2
- package/dist/{chunk-TBCDF556.js → chunk-WHFFAS4A.js} +4 -4
- package/dist/{chunk-7UOXCCCI.js → chunk-WVNETF4Q.js} +2 -2
- package/dist/{chunk-EH65UV2Z.js → chunk-XSTMPZMY.js} +2 -2
- package/dist/{chunk-PD66CVSD.js → chunk-Z3SQEEB6.js} +2 -2
- package/dist/{chunk-JKTV3JNX.js → chunk-ZBYOXIIF.js} +3 -3
- package/dist/{chunk-2ITZ74A6.js → chunk-ZC5IHL5X.js} +11 -11
- package/dist/{chunk-KI64TTBL.js → chunk-ZDMTCO7N.js} +2 -2
- package/dist/{chunk-C5IUOBCN.js → chunk-ZET6A3OF.js} +2 -2
- package/dist/{chunk-ZZZWEDF4.js → chunk-ZVAKRZZD.js} +2 -2
- package/dist/cli.js +67 -67
- package/dist/coding/export-okf-codegraph.js +13 -13
- package/dist/coding/pre-action-gate.js +2 -2
- package/dist/compounding/engine.js +13 -13
- package/dist/config.js +3 -3
- package/dist/connectors/codex-materialize-runner.js +13 -13
- package/dist/connectors/index.js +13 -13
- package/dist/convergence-refresh.js +15 -15
- package/dist/conversation-index/backend.js +2 -2
- package/dist/corpus-watermark.js +15 -15
- package/dist/entity-retrieval.js +13 -13
- package/dist/external-wiki-access.js +31 -31
- package/dist/extraction-span-bench.d.ts +14 -0
- package/dist/extraction-span-bench.js +17 -0
- package/dist/extraction-span-bench.js.map +1 -0
- package/dist/extraction-span-clip.d.ts +22 -0
- package/dist/extraction-span-clip.js +19 -0
- package/dist/extraction-span-clip.js.map +1 -0
- package/dist/extraction-span-contains.d.ts +12 -0
- package/dist/extraction-span-contains.js +17 -0
- package/dist/extraction-span-contains.js.map +1 -0
- package/dist/extraction-span-join.d.ts +23 -0
- package/dist/extraction-span-join.js +19 -0
- package/dist/extraction-span-join.js.map +1 -0
- package/dist/extraction-span-length.d.ts +11 -0
- package/dist/extraction-span-length.js +17 -0
- package/dist/extraction-span-length.js.map +1 -0
- package/dist/extraction-span-overlap.d.ts +14 -0
- package/dist/extraction-span-overlap.js +16 -0
- package/dist/extraction-span-overlap.js.map +1 -0
- package/dist/extraction-span-shift.d.ts +15 -0
- package/dist/extraction-span-shift.js +17 -0
- package/dist/extraction-span-shift.js.map +1 -0
- package/dist/extraction-span-slice.d.ts +12 -0
- package/dist/extraction-span-slice.js +17 -0
- package/dist/extraction-span-slice.js.map +1 -0
- package/dist/extraction-span-validate.d.ts +20 -0
- package/dist/extraction-span-validate.js +20 -0
- package/dist/extraction-span-validate.js.map +1 -0
- package/dist/extraction-span-wire.d.ts +17 -0
- package/dist/extraction-span-wire.js +13 -0
- package/dist/extraction-span-wire.js.map +1 -0
- package/dist/extraction-span.d.ts +17 -0
- package/dist/extraction-span.js +8 -0
- package/dist/extraction.js +16 -16
- package/dist/{graph-edge-decay-A4SDFMMS.js → graph-edge-decay-DGTBFALQ.js} +4 -4
- package/dist/graph-edge-decay-DGTBFALQ.js.map +1 -0
- package/dist/graph-snapshot.js +3 -3
- package/dist/graph.js +2 -2
- package/dist/harmonic-retrieval.js +1 -1
- package/dist/index.d.ts +387 -1
- package/dist/index.js +203 -122
- package/dist/lcm/engine.js +3 -3
- package/dist/lcm/index.js +9 -9
- package/dist/location/index.js +15 -15
- package/dist/maintenance/memory-governance.js +13 -13
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +13 -13
- package/dist/maintenance/rebuild-memory-projection.js +14 -14
- package/dist/namespaces/migrate.js +14 -14
- package/dist/namespaces/search.js +9 -9
- package/dist/namespaces/storage.js +13 -13
- package/dist/operator-doctor-corpus.js +16 -16
- package/dist/operator-toolkit.js +26 -26
- package/dist/orchestration/maintenance.js +21 -21
- package/dist/orchestrator.js +98 -96
- package/dist/qmd.js +4 -4
- package/dist/recall-deep-access.d.ts +30 -0
- package/dist/recall-deep-access.js +50 -0
- package/dist/recall-deep-access.js.map +1 -0
- package/dist/recall-deep-budget-left.d.ts +8 -0
- package/dist/recall-deep-budget-left.js +15 -0
- package/dist/recall-deep-budget-left.js.map +1 -0
- package/dist/recall-deep-budget.d.ts +9 -0
- package/dist/recall-deep-budget.js +15 -0
- package/dist/recall-deep-budget.js.map +1 -0
- package/dist/recall-deep-expand.d.ts +12 -0
- package/dist/recall-deep-expand.js +17 -0
- package/dist/recall-deep-expand.js.map +1 -0
- package/dist/recall-deep-policy.d.ts +17 -0
- package/dist/recall-deep-policy.js +18 -0
- package/dist/recall-deep-policy.js.map +1 -0
- package/dist/recall-deep-query.d.ts +15 -0
- package/dist/recall-deep-query.js +12 -0
- package/dist/recall-deep-query.js.map +1 -0
- package/dist/recall-deep-refine.d.ts +12 -0
- package/dist/recall-deep-refine.js +17 -0
- package/dist/recall-deep-refine.js.map +1 -0
- package/dist/recall-deep-render.d.ts +11 -0
- package/dist/recall-deep-render.js +28 -0
- package/dist/recall-deep-render.js.map +1 -0
- package/dist/recall-deep-step-count.d.ts +8 -0
- package/dist/recall-deep-step-count.js +15 -0
- package/dist/recall-deep-step-count.js.map +1 -0
- package/dist/recall-deep-stop-reason.d.ts +17 -0
- package/dist/recall-deep-stop-reason.js +23 -0
- package/dist/recall-deep-stop-reason.js.map +1 -0
- package/dist/recall-deep-stop.d.ts +17 -0
- package/dist/recall-deep-stop.js +23 -0
- package/dist/recall-deep-stop.js.map +1 -0
- package/dist/recall-deep-working-set.d.ts +9 -0
- package/dist/recall-deep-working-set.js +14 -0
- package/dist/recall-deep-working-set.js.map +1 -0
- package/dist/recall-deep.js +6 -73
- package/dist/recall-deep.js.map +1 -1
- package/dist/recall-navigate-access.d.ts +39 -0
- package/dist/recall-navigate-access.js +31 -0
- package/dist/recall-navigate-access.js.map +1 -0
- package/dist/recall-navigate-action.d.ts +17 -0
- package/dist/recall-navigate-action.js +14 -0
- package/dist/recall-navigate-action.js.map +1 -0
- package/dist/recall-navigate-budget.d.ts +16 -0
- package/dist/recall-navigate-budget.js +18 -0
- package/dist/recall-navigate-budget.js.map +1 -0
- package/dist/recall-navigate-cost.d.ts +8 -0
- package/dist/recall-navigate-cost.js +15 -0
- package/dist/recall-navigate-cost.js.map +1 -0
- package/dist/recall-navigate-depth.d.ts +8 -0
- package/dist/recall-navigate-depth.js +15 -0
- package/dist/recall-navigate-depth.js.map +1 -0
- package/dist/recall-navigate-link.d.ts +17 -0
- package/dist/recall-navigate-link.js +20 -0
- package/dist/recall-navigate-link.js.map +1 -0
- package/dist/recall-navigate-max-children.d.ts +8 -0
- package/dist/recall-navigate-max-children.js +15 -0
- package/dist/recall-navigate-max-children.js.map +1 -0
- package/dist/recall-navigate-node.d.ts +15 -0
- package/dist/recall-navigate-node.js +13 -0
- package/dist/recall-navigate-node.js.map +1 -0
- package/dist/recall-navigate-path.d.ts +9 -0
- package/dist/recall-navigate-path.js +14 -0
- package/dist/recall-navigate-path.js.map +1 -0
- package/dist/recall-navigate-render.d.ts +15 -0
- package/dist/recall-navigate-render.js +23 -0
- package/dist/recall-navigate-render.js.map +1 -0
- package/dist/recall-navigate.js +6 -42
- package/dist/recall-navigate.js.map +1 -1
- package/dist/recall-state-view-current.d.ts +18 -0
- package/dist/recall-state-view-current.js +14 -0
- package/dist/recall-state-view-current.js.map +1 -0
- package/dist/recall-state-view-inject.d.ts +15 -0
- package/dist/recall-state-view-inject.js +16 -0
- package/dist/recall-state-view-inject.js.map +1 -0
- package/dist/recall-state-view-kind.d.ts +17 -0
- package/dist/recall-state-view-kind.js +14 -0
- package/dist/recall-state-view-kind.js.map +1 -0
- package/dist/recall-state-view-label.d.ts +17 -0
- package/dist/recall-state-view-label.js +16 -0
- package/dist/recall-state-view-label.js.map +1 -0
- package/dist/recall-state-view-render.d.ts +18 -0
- package/dist/recall-state-view-render.js +11 -0
- package/dist/recall-state-view-render.js.map +1 -0
- package/dist/recall-state-view-successor.d.ts +15 -0
- package/dist/recall-state-view-successor.js +13 -0
- package/dist/recall-state-view-successor.js.map +1 -0
- package/dist/recall-state-view-superseded.d.ts +15 -0
- package/dist/recall-state-view-superseded.js +14 -0
- package/dist/recall-state-view-superseded.js.map +1 -0
- package/dist/recall-state-view-transition.d.ts +18 -0
- package/dist/recall-state-view-transition.js +14 -0
- package/dist/recall-state-view-transition.js.map +1 -0
- package/dist/recall-state-view-widen.d.ts +13 -0
- package/dist/recall-state-view-widen.js +11 -0
- package/dist/recall-state-view-widen.js.map +1 -0
- package/dist/recall-state-view-wire.d.ts +3 -4
- package/dist/recall-state-view-wire.js +2 -1
- package/dist/resume-bundles.js +4 -4
- package/dist/search/factory.js +8 -8
- package/dist/search/index.js +14 -14
- package/dist/semantic-consolidation.js +14 -14
- package/dist/semantic-rule-promotion.js +13 -13
- package/dist/semantic-rule-verifier.js +13 -13
- package/dist/source-agent-qualifier.js +15 -15
- package/dist/storage.js +12 -12
- package/dist/support-passport/index.js +33 -33
- package/dist/transfer/backup.js +2 -2
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +2 -2
- package/dist/transfer/export-okf.js +14 -14
- package/dist/verified-recall.js +13 -13
- package/dist/who-knows-cli.js +14 -14
- package/dist/who-knows.js +13 -13
- package/package.json +2 -2
- package/src/activity/dwell.test.ts +28 -0
- package/src/activity/dwell.ts +22 -0
- package/src/activity/from-ms.test.ts +25 -0
- package/src/activity/from-ms.ts +13 -0
- package/src/activity/heading-level.test.ts +23 -0
- package/src/activity/heading-level.ts +21 -0
- package/src/activity/heading-title.test.ts +21 -0
- package/src/activity/heading-title.ts +26 -0
- package/src/activity/index.ts +9 -0
- package/src/activity/journal-heading.test.ts +22 -0
- package/src/activity/journal-heading.ts +18 -0
- package/src/activity/journal-mode.test.ts +32 -0
- package/src/activity/journal-mode.ts +20 -0
- package/src/activity/journal-path.test.ts +25 -0
- package/src/activity/journal-path.ts +27 -0
- package/src/activity/journal-section.test.ts +37 -0
- package/src/activity/journal-section.ts +75 -0
- package/src/activity/journal-source.test.ts +37 -0
- package/src/activity/journal-source.ts +23 -0
- package/src/activity/journal-vault-read.test.ts +153 -0
- package/src/activity/journal-vault-read.ts +214 -0
- package/src/activity/journal.ts +1 -1
- package/src/activity/privacy-enabled.test.ts +30 -0
- package/src/activity/privacy-enabled.ts +33 -0
- package/src/activity/privacy-keys.test.ts +22 -0
- package/src/activity/privacy-keys.ts +12 -0
- package/src/activity/privacy-redact.test.ts +25 -0
- package/src/activity/privacy-redact.ts +23 -0
- package/src/activity/privacy-window.test.ts +49 -0
- package/src/activity/privacy-window.ts +32 -0
- package/src/activity/retain-days.test.ts +20 -0
- package/src/activity/retain-days.ts +14 -0
- package/src/activity/timeline/analysis-batch.test.ts +56 -0
- package/src/activity/timeline/analysis-batch.ts +45 -0
- package/src/activity/timeline/analysis-claim.test.ts +33 -0
- package/src/activity/timeline/analysis-claim.ts +16 -0
- package/src/activity/timeline/analysis-dup.test.ts +28 -0
- package/src/activity/timeline/analysis-dup.ts +10 -0
- package/src/activity/timeline/analysis-empty.test.ts +21 -0
- package/src/activity/timeline/analysis-empty.ts +14 -0
- package/src/activity/timeline/analysis-evidence.test.ts +32 -0
- package/src/activity/timeline/analysis-evidence.ts +20 -0
- package/src/activity/timeline/analysis-max.test.ts +26 -0
- package/src/activity/timeline/analysis-max.ts +14 -0
- package/src/activity/timeline/analysis-order.test.ts +28 -0
- package/src/activity/timeline/analysis-order.ts +10 -0
- package/src/activity/timeline/analysis-prompt.test.ts +50 -0
- package/src/activity/timeline/analysis-prompt.ts +24 -0
- package/src/activity/timeline/analysis.test.ts +413 -0
- package/src/activity/timeline/analysis.ts +362 -0
- package/src/activity/timeline/index.ts +13 -0
- package/src/activity/timeline/journal-recap-persist.test.ts +148 -0
- package/src/activity/timeline/journal-recap-persist.ts +37 -0
- package/src/activity/timeline/recap-card-id.test.ts +21 -0
- package/src/activity/timeline/recap-card-id.ts +16 -0
- package/src/activity/timeline/recap-date.test.ts +21 -0
- package/src/activity/timeline/recap-date.ts +19 -0
- package/src/activity/timeline/recap-empty.test.ts +21 -0
- package/src/activity/timeline/recap-empty.ts +14 -0
- package/src/activity/timeline/recap-export.test.ts +78 -0
- package/src/activity/timeline/recap-export.ts +41 -0
- package/src/activity/timeline/recap-id.test.ts +28 -0
- package/src/activity/timeline/recap-id.ts +10 -0
- package/src/activity/timeline/recap-markdown.test.ts +56 -0
- package/src/activity/timeline/recap-markdown.ts +26 -0
- package/src/activity/timeline/recap-sort-key.test.ts +18 -0
- package/src/activity/timeline/recap-sort-key.ts +14 -0
- package/src/activity/timeline/recap-tz.test.ts +35 -0
- package/src/activity/timeline/recap-tz.ts +19 -0
- package/src/activity/timeline/week-count.test.ts +19 -0
- package/src/activity/timeline/week-count.ts +13 -0
- package/src/activity/timeline/week-days.test.ts +26 -0
- package/src/activity/timeline/week-days.ts +23 -0
- package/src/activity/timeline/week-export.test.ts +59 -0
- package/src/activity/timeline/week-export.ts +44 -0
- package/src/activity/timeline/week-iso.test.ts +29 -0
- package/src/activity/timeline/week-iso.ts +20 -0
- package/src/activity/timeline/week-monday.test.ts +17 -0
- package/src/activity/timeline/week-monday.ts +12 -0
- package/src/activity/timeline/week-range.test.ts +23 -0
- package/src/activity/timeline/week-range.ts +26 -0
- package/src/activity/timeline/week-snapshot.test.ts +66 -0
- package/src/activity/timeline/week-snapshot.ts +40 -0
- package/src/activity/timeline/week-sunday.test.ts +17 -0
- package/src/activity/timeline/week-sunday.ts +12 -0
- package/src/activity/timeline/weekly-persist.test.ts +121 -0
- package/src/activity/timeline/weekly-persist.ts +103 -0
- package/src/activity/to-ms.test.ts +25 -0
- package/src/activity/to-ms.ts +13 -0
- package/src/activity/vault-begin.test.ts +20 -0
- package/src/activity/vault-begin.ts +13 -0
- package/src/activity/vault-end.test.ts +20 -0
- package/src/activity/vault-end.ts +13 -0
- package/src/activity/vault-frontmatter.test.ts +28 -0
- package/src/activity/vault-frontmatter.ts +39 -0
- package/src/activity/vault-join.test.ts +21 -0
- package/src/activity/vault-join.ts +31 -0
- package/src/activity/vault-marker.test.ts +23 -0
- package/src/activity/vault-marker.ts +27 -0
- package/src/activity/vault-name-trim.test.ts +22 -0
- package/src/activity/vault-name-trim.ts +16 -0
- package/src/activity/vault-path.test.ts +38 -0
- package/src/activity/vault-path.ts +59 -0
- package/src/activity/vault-publish.test.ts +102 -0
- package/src/activity/vault-publish.ts +92 -13
- package/src/activity/vault-region-pair.test.ts +26 -0
- package/src/activity/vault-region-pair.ts +24 -0
- package/src/activity/vault-region.test.ts +24 -0
- package/src/activity/vault-region.ts +24 -0
- package/src/activity/vault-suffix.test.ts +20 -0
- package/src/activity/vault-suffix.ts +12 -0
- package/src/activity/vault-wikilink.test.ts +27 -0
- package/src/activity/vault-wikilink.ts +28 -0
- package/src/activity/window-order.test.ts +27 -0
- package/src/activity/window-order.ts +24 -0
- package/src/dedup/merge-count.test.ts +19 -0
- package/src/dedup/merge-count.ts +13 -0
- package/src/dedup/merge-dup.test.ts +21 -0
- package/src/dedup/merge-dup.ts +16 -0
- package/src/dedup/merge-empty.test.ts +22 -0
- package/src/dedup/merge-empty.ts +18 -0
- package/src/dedup/merge-id.test.ts +18 -0
- package/src/dedup/merge-id.ts +14 -0
- package/src/dedup/merge-min-score.test.ts +37 -0
- package/src/dedup/merge-min-score.ts +22 -0
- package/src/dedup/merge-on-write-wire.test.ts +101 -0
- package/src/dedup/merge-on-write-wire.ts +34 -0
- package/src/dedup/merge-pair.test.ts +19 -0
- package/src/dedup/merge-pair.ts +13 -0
- package/src/dedup/merge-score.test.ts +20 -0
- package/src/dedup/merge-score.ts +14 -0
- package/src/dedup/merge-self.test.ts +19 -0
- package/src/dedup/merge-self.ts +17 -0
- package/src/dedup/merge-threshold.test.ts +46 -0
- package/src/dedup/merge-threshold.ts +26 -0
- package/src/dedup/merge-tie.test.ts +22 -0
- package/src/dedup/merge-tie.ts +13 -0
- package/src/extraction-span-bench.test.ts +27 -0
- package/src/extraction-span-bench.ts +28 -0
- package/src/extraction-span-clip.test.ts +71 -0
- package/src/extraction-span-clip.ts +26 -0
- package/src/extraction-span-contains.test.ts +30 -0
- package/src/extraction-span-contains.ts +20 -0
- package/src/extraction-span-join.test.ts +50 -0
- package/src/extraction-span-join.ts +30 -0
- package/src/extraction-span-length.test.ts +25 -0
- package/src/extraction-span-length.ts +16 -0
- package/src/extraction-span-overlap.test.ts +34 -0
- package/src/extraction-span-overlap.ts +23 -0
- package/src/extraction-span-shift.test.ts +25 -0
- package/src/extraction-span-shift.ts +20 -0
- package/src/extraction-span-slice.test.ts +32 -0
- package/src/extraction-span-slice.ts +20 -0
- package/src/extraction-span-validate.test.ts +42 -0
- package/src/extraction-span-validate.ts +27 -0
- package/src/extraction-span-wire.test.ts +20 -0
- package/src/extraction-span-wire.ts +17 -0
- package/src/extraction-span.test.ts +59 -0
- package/src/extraction-span.ts +39 -0
- package/src/index.ts +1 -0
- package/src/recall-deep-access.test.ts +58 -0
- package/src/recall-deep-access.ts +71 -0
- package/src/recall-deep-budget-left.test.ts +20 -0
- package/src/recall-deep-budget-left.ts +13 -0
- package/src/recall-deep-budget.test.ts +19 -0
- package/src/recall-deep-budget.ts +14 -0
- package/src/recall-deep-expand.test.ts +23 -0
- package/src/recall-deep-expand.ts +19 -0
- package/src/recall-deep-policy.test.ts +32 -0
- package/src/recall-deep-policy.ts +22 -0
- package/src/recall-deep-query.test.ts +23 -0
- package/src/recall-deep-query.ts +15 -0
- package/src/recall-deep-refine.test.ts +23 -0
- package/src/recall-deep-refine.ts +19 -0
- package/src/recall-deep-render.test.ts +68 -0
- package/src/recall-deep-render.ts +32 -0
- package/src/recall-deep-step-count.test.ts +20 -0
- package/src/recall-deep-step-count.ts +13 -0
- package/src/recall-deep-stop-reason.test.ts +46 -0
- package/src/recall-deep-stop-reason.ts +27 -0
- package/src/recall-deep-stop.test.ts +34 -0
- package/src/recall-deep-stop.ts +31 -0
- package/src/recall-deep-working-set.test.ts +21 -0
- package/src/recall-deep-working-set.ts +14 -0
- package/src/recall-navigate-access.test.ts +73 -0
- package/src/recall-navigate-access.ts +48 -0
- package/src/recall-navigate-action.test.ts +32 -0
- package/src/recall-navigate-action.ts +20 -0
- package/src/recall-navigate-budget.test.ts +23 -0
- package/src/recall-navigate-budget.ts +22 -0
- package/src/recall-navigate-cost.test.ts +20 -0
- package/src/recall-navigate-cost.ts +13 -0
- package/src/recall-navigate-depth.test.ts +20 -0
- package/src/recall-navigate-depth.ts +13 -0
- package/src/recall-navigate-link.test.ts +19 -0
- package/src/recall-navigate-link.ts +26 -0
- package/src/recall-navigate-max-children.test.ts +20 -0
- package/src/recall-navigate-max-children.ts +13 -0
- package/src/recall-navigate-node.test.ts +21 -0
- package/src/recall-navigate-node.ts +16 -0
- package/src/recall-navigate-path.test.ts +21 -0
- package/src/recall-navigate-path.ts +14 -0
- package/src/recall-navigate-render.test.ts +63 -0
- package/src/recall-navigate-render.ts +31 -0
- package/src/recall-state-view-current.test.ts +23 -0
- package/src/recall-state-view-current.ts +24 -0
- package/src/recall-state-view-inject.test.ts +32 -0
- package/src/recall-state-view-inject.ts +14 -0
- package/src/recall-state-view-kind.test.ts +19 -0
- package/src/recall-state-view-kind.ts +20 -0
- package/src/recall-state-view-label.test.ts +36 -0
- package/src/recall-state-view-label.ts +22 -0
- package/src/recall-state-view-render.test.ts +94 -0
- package/src/recall-state-view-render.ts +24 -0
- package/src/recall-state-view-successor.test.ts +21 -0
- package/src/recall-state-view-successor.ts +16 -0
- package/src/recall-state-view-superseded.test.ts +20 -0
- package/src/recall-state-view-superseded.ts +17 -0
- package/src/recall-state-view-transition.test.ts +30 -0
- package/src/recall-state-view-transition.ts +24 -0
- package/src/recall-state-view-widen.test.ts +66 -0
- package/src/recall-state-view-widen.ts +49 -0
- package/src/recall-state-view-wire.ts +6 -16
- package/src/shared-context/authority.test.ts +35 -0
- package/src/shared-context/authority.ts +25 -0
- package/src/shared-context/claim-key.test.ts +21 -0
- package/src/shared-context/claim-key.ts +16 -0
- package/src/shared-context/contradictions.test.ts +39 -0
- package/src/shared-context/contradictions.ts +32 -0
- package/src/shared-context/envelope-actor.test.ts +21 -0
- package/src/shared-context/envelope-actor.ts +16 -0
- package/src/shared-context/envelope-at.test.ts +19 -0
- package/src/shared-context/envelope-at.ts +17 -0
- package/src/shared-context/envelope-id.test.ts +21 -0
- package/src/shared-context/envelope-id.ts +16 -0
- package/src/shared-context/envelope-required.test.ts +24 -0
- package/src/shared-context/envelope-required.ts +15 -0
- package/src/shared-context/envelope-ttl.test.ts +29 -0
- package/src/shared-context/envelope-ttl.ts +35 -0
- package/src/shared-context/provenance.test.ts +35 -0
- package/src/shared-context/provenance.ts +68 -0
- package/src/shared-context/staleness.test.ts +36 -0
- package/src/shared-context/staleness.ts +38 -0
- package/src/shared-context/trajectories.test.ts +77 -0
- package/src/shared-context/trajectories.ts +49 -0
- package/dist/chunk-MUEGIKKY.js.map +0 -1
- package/dist/chunk-TCF4MU7L.js.map +0 -1
- package/dist/chunk-WFCWP4XU.js +0 -17
- package/dist/chunk-WFCWP4XU.js.map +0 -1
- /package/dist/{capsule-crypto-7FJQINUR.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
- /package/dist/{chunk-XKNHFDTT.js.map → chunk-3A2Z4OOS.js.map} +0 -0
- /package/dist/{chunk-CHGG74CY.js.map → chunk-3HHTN5X7.js.map} +0 -0
- /package/dist/{chunk-XOHYGIWF.js.map → chunk-3Z4SFJA5.js.map} +0 -0
- /package/dist/{chunk-RDGKVH6T.js.map → chunk-4NKIGSJM.js.map} +0 -0
- /package/dist/{chunk-GPFZFCRN.js.map → chunk-4PTTMTTQ.js.map} +0 -0
- /package/dist/{chunk-VG4SSPAW.js.map → chunk-4XESAT4V.js.map} +0 -0
- /package/dist/{chunk-S4CDUXQY.js.map → chunk-5KGLNBUB.js.map} +0 -0
- /package/dist/{chunk-2X6BGKQL.js.map → chunk-5XRZANCW.js.map} +0 -0
- /package/dist/{chunk-TCQRIIIN.js.map → chunk-6DODJYBY.js.map} +0 -0
- /package/dist/{chunk-KWIGDKM2.js.map → chunk-73CAEYI3.js.map} +0 -0
- /package/dist/{chunk-J2R275FN.js.map → chunk-7DXW5V2W.js.map} +0 -0
- /package/dist/{chunk-LYUUA6QB.js.map → chunk-7JJHIVMG.js.map} +0 -0
- /package/dist/{chunk-2FA7U5XY.js.map → chunk-7NNMRMLZ.js.map} +0 -0
- /package/dist/{chunk-227UFSEQ.js.map → chunk-7RZJWZ46.js.map} +0 -0
- /package/dist/{chunk-EWKVYCFP.js.map → chunk-B2OKCCXX.js.map} +0 -0
- /package/dist/{chunk-NSTNGMSS.js.map → chunk-B7AGLMGP.js.map} +0 -0
- /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
- /package/dist/{chunk-CEH2AFXG.js.map → chunk-C24UZSFW.js.map} +0 -0
- /package/dist/{chunk-LTBKKSCX.js.map → chunk-C2JCVZWX.js.map} +0 -0
- /package/dist/{chunk-65JOGLIS.js.map → chunk-D4R3OUZA.js.map} +0 -0
- /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
- /package/dist/{chunk-IGZCAHFL.js.map → chunk-EGGNFLAT.js.map} +0 -0
- /package/dist/{chunk-H2IRSXZN.js.map → chunk-ESDOAP7W.js.map} +0 -0
- /package/dist/{chunk-D3UXGE5D.js.map → chunk-EZWIEFYD.js.map} +0 -0
- /package/dist/{chunk-ZPS724LT.js.map → chunk-F5H5QINZ.js.map} +0 -0
- /package/dist/{chunk-S4Z2OBTX.js.map → chunk-FPSOXMLK.js.map} +0 -0
- /package/dist/{chunk-CX4OLNIH.js.map → chunk-G5UKF2GJ.js.map} +0 -0
- /package/dist/{chunk-OJUEUQDJ.js.map → chunk-GGY2747C.js.map} +0 -0
- /package/dist/{chunk-TNGH4ZYI.js.map → chunk-GNWLTCKC.js.map} +0 -0
- /package/dist/{chunk-YWPLOJ7T.js.map → chunk-GZPGI45F.js.map} +0 -0
- /package/dist/{chunk-NFP4KPTA.js.map → chunk-IDEPEHUG.js.map} +0 -0
- /package/dist/{chunk-LJABGXC4.js.map → chunk-IN5EUWCA.js.map} +0 -0
- /package/dist/{chunk-U6NGKS32.js.map → chunk-JJAOVJ3E.js.map} +0 -0
- /package/dist/{chunk-RPIS5FQ7.js.map → chunk-JWCS3VYQ.js.map} +0 -0
- /package/dist/{chunk-U65VJSCJ.js.map → chunk-KE23ZIEW.js.map} +0 -0
- /package/dist/{chunk-NACLNNFQ.js.map → chunk-KSZKQTZS.js.map} +0 -0
- /package/dist/{chunk-KJXCD7VR.js.map → chunk-KWJNEWTM.js.map} +0 -0
- /package/dist/{chunk-UW4RYPWC.js.map → chunk-MLTGALDY.js.map} +0 -0
- /package/dist/{chunk-YMOPYG3K.js.map → chunk-OLT3YTDH.js.map} +0 -0
- /package/dist/{chunk-2PSX5BJU.js.map → chunk-OPQKVVYG.js.map} +0 -0
- /package/dist/{chunk-D6Q5EPOV.js.map → chunk-PGD3DXZP.js.map} +0 -0
- /package/dist/{chunk-GBEOUCBB.js.map → chunk-Q6LC3ZD5.js.map} +0 -0
- /package/dist/{chunk-QBNE55VA.js.map → chunk-QELYSDAU.js.map} +0 -0
- /package/dist/{chunk-INUBU6I5.js.map → chunk-S6PRJGQL.js.map} +0 -0
- /package/dist/{chunk-B4AOWRYF.js.map → chunk-TCJO7LOG.js.map} +0 -0
- /package/dist/{chunk-SZMYGDSM.js.map → chunk-TO5U47YK.js.map} +0 -0
- /package/dist/{chunk-GAJK3DQ5.js.map → chunk-U3L6GRUX.js.map} +0 -0
- /package/dist/{chunk-4XLTUR6R.js.map → chunk-U4RGSLI4.js.map} +0 -0
- /package/dist/{chunk-M5ERTI4I.js.map → chunk-UH53XVQ3.js.map} +0 -0
- /package/dist/{chunk-NUF7VSEX.js.map → chunk-UXERIBOJ.js.map} +0 -0
- /package/dist/{chunk-FFUMTH27.js.map → chunk-VA2CSIPC.js.map} +0 -0
- /package/dist/{chunk-KQAFEZQX.js.map → chunk-VDX2J7OX.js.map} +0 -0
- /package/dist/{chunk-AF5H7TKI.js.map → chunk-VPJNGE2R.js.map} +0 -0
- /package/dist/{chunk-OMX6TKXH.js.map → chunk-VTJZSLDR.js.map} +0 -0
- /package/dist/{chunk-TBCDF556.js.map → chunk-WHFFAS4A.js.map} +0 -0
- /package/dist/{chunk-7UOXCCCI.js.map → chunk-WVNETF4Q.js.map} +0 -0
- /package/dist/{chunk-EH65UV2Z.js.map → chunk-XSTMPZMY.js.map} +0 -0
- /package/dist/{chunk-PD66CVSD.js.map → chunk-Z3SQEEB6.js.map} +0 -0
- /package/dist/{chunk-JKTV3JNX.js.map → chunk-ZBYOXIIF.js.map} +0 -0
- /package/dist/{chunk-2ITZ74A6.js.map → chunk-ZC5IHL5X.js.map} +0 -0
- /package/dist/{chunk-KI64TTBL.js.map → chunk-ZDMTCO7N.js.map} +0 -0
- /package/dist/{chunk-C5IUOBCN.js.map → chunk-ZET6A3OF.js.map} +0 -0
- /package/dist/{chunk-ZZZWEDF4.js.map → chunk-ZVAKRZZD.js.map} +0 -0
- /package/dist/{graph-edge-decay-A4SDFMMS.js.map → extraction-span.js.map} +0 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named-policy access facade for the deep-recall stepper (issue #2332 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Not the hot path. Surfaces and parseConfig wait. Policy names are
|
|
5
|
+
* allow-listed. Budget 0 returns a tagged refusal without a policy call.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { runDeepRecall, type DeepRecallResult, type DeepRecallState } from "./recall-deep.js";
|
|
9
|
+
|
|
10
|
+
export const DEEP_RECALL_ACCESS_POLICIES = ["stop", "expand-once"] as const;
|
|
11
|
+
|
|
12
|
+
export type DeepRecallAccessPolicyName = (typeof DEEP_RECALL_ACCESS_POLICIES)[number];
|
|
13
|
+
|
|
14
|
+
export interface DeepRecallAccessInput {
|
|
15
|
+
query: string;
|
|
16
|
+
budget: number;
|
|
17
|
+
policyName: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface DeepRecallAccessRefusal {
|
|
21
|
+
tag: "budget_exhausted";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface DeepRecallAccessResult {
|
|
25
|
+
ok: boolean;
|
|
26
|
+
refusal?: DeepRecallAccessRefusal;
|
|
27
|
+
state: DeepRecallState;
|
|
28
|
+
trace: DeepRecallResult["trace"];
|
|
29
|
+
traceJson: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function isDeepRecallAccessPolicyName(value: unknown): value is DeepRecallAccessPolicyName {
|
|
33
|
+
return typeof value === "string" && (DEEP_RECALL_ACCESS_POLICIES as readonly string[]).includes(value);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function runDeepRecallAccess(input: DeepRecallAccessInput): DeepRecallAccessResult {
|
|
37
|
+
if (!isDeepRecallAccessPolicyName(input.policyName)) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`unknown deep recall access policy: ${JSON.stringify(input.policyName)}. Valid: ${DEEP_RECALL_ACCESS_POLICIES.join(", ")}`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const start: DeepRecallState = { query: input.query, workingSet: [], frontier: [], budget: input.budget };
|
|
44
|
+
if (!Number.isFinite(input.budget) || input.budget <= 0) {
|
|
45
|
+
const result = runDeepRecall(start, () => {
|
|
46
|
+
throw new Error("policy must not run when budget is 0");
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
ok: false,
|
|
50
|
+
refusal: { tag: "budget_exhausted" },
|
|
51
|
+
state: result.state,
|
|
52
|
+
trace: result.trace,
|
|
53
|
+
traceJson: JSON.stringify(result.trace),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let expanded = false;
|
|
58
|
+
const result = runDeepRecall(start, () => {
|
|
59
|
+
if (input.policyName === "expand-once" && !expanded) {
|
|
60
|
+
expanded = true;
|
|
61
|
+
return "expand";
|
|
62
|
+
}
|
|
63
|
+
return "stop";
|
|
64
|
+
});
|
|
65
|
+
return {
|
|
66
|
+
ok: true,
|
|
67
|
+
state: result.state,
|
|
68
|
+
trace: result.trace,
|
|
69
|
+
traceJson: JSON.stringify(result.trace),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { parseBudgetLeft } from "./recall-deep-budget-left.js";
|
|
5
|
+
|
|
6
|
+
test("budget left 0 is allowed", () => {
|
|
7
|
+
assert.equal(parseBudgetLeft(0), 0);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("budget left 4 is returned", () => {
|
|
11
|
+
assert.equal(parseBudgetLeft(4), 4);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("negative budget left throws", () => {
|
|
15
|
+
assert.throws(() => parseBudgetLeft(-1), /non-negative integer/);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("float budget left throws", () => {
|
|
19
|
+
assert.throws(() => parseBudgetLeft(1.5), /non-negative integer/);
|
|
20
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-recall remaining-budget parse (issue #2332 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Pure. Surfaces wait. 0 is allowed. Negative or non-integer throws.
|
|
5
|
+
*/
|
|
6
|
+
export function parseBudgetLeft(value: unknown): number {
|
|
7
|
+
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value) || value < 0) {
|
|
8
|
+
throw new Error(
|
|
9
|
+
`deep recall budget left must be a non-negative integer; got ${JSON.stringify(value)}`,
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { clampDeepRecallBudget } from "./recall-deep-budget.js";
|
|
5
|
+
|
|
6
|
+
test("budget 0 stays 0", () => {
|
|
7
|
+
assert.equal(clampDeepRecallBudget(0), 0);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("budget 3 stays 3", () => {
|
|
11
|
+
assert.equal(clampDeepRecallBudget(3), 3);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("invalid budget throws", () => {
|
|
15
|
+
assert.throws(() => clampDeepRecallBudget(-1), /non-negative integer/);
|
|
16
|
+
assert.throws(() => clampDeepRecallBudget(1.5), /non-negative integer/);
|
|
17
|
+
assert.throws(() => clampDeepRecallBudget(Number.NaN), /non-negative integer/);
|
|
18
|
+
assert.throws(() => clampDeepRecallBudget(Number.POSITIVE_INFINITY), /non-negative integer/);
|
|
19
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-recall budget clamp (issue #2332 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Pure. Surfaces wait. 0 stays 0. Positive integers pass through.
|
|
5
|
+
* Negative, non-finite, and non-integer values throw.
|
|
6
|
+
*/
|
|
7
|
+
export function clampDeepRecallBudget(n: number): number {
|
|
8
|
+
if (!Number.isFinite(n) || !Number.isInteger(n) || n < 0) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
`deep recall budget must be a non-negative integer; got ${JSON.stringify(n)}`,
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
return n;
|
|
14
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { mayExpandOnce } from "./recall-deep-expand.js";
|
|
5
|
+
|
|
6
|
+
test("already expanded is false", () => {
|
|
7
|
+
assert.equal(mayExpandOnce({ alreadyExpanded: true, budgetLeft: 3 }), false);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("budget 0 is false", () => {
|
|
11
|
+
assert.equal(mayExpandOnce({ alreadyExpanded: false, budgetLeft: 0 }), false);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("ok is true", () => {
|
|
15
|
+
assert.equal(mayExpandOnce({ alreadyExpanded: false, budgetLeft: 3 }), true);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("negative budget throws", () => {
|
|
19
|
+
assert.throws(
|
|
20
|
+
() => mayExpandOnce({ alreadyExpanded: false, budgetLeft: -1 }),
|
|
21
|
+
/negative/,
|
|
22
|
+
);
|
|
23
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-recall one-shot expand gate (issue #2332 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Pure. Surfaces wait. Already expanded or budget 0 refuse.
|
|
5
|
+
* Negative budget throws.
|
|
6
|
+
*/
|
|
7
|
+
export function mayExpandOnce(input: {
|
|
8
|
+
alreadyExpanded: boolean;
|
|
9
|
+
budgetLeft: number;
|
|
10
|
+
}): boolean {
|
|
11
|
+
if (input.budgetLeft < 0) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
`deep recall expand budget must not be negative; got ${JSON.stringify(input.budgetLeft)}`,
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
if (input.alreadyExpanded) return false;
|
|
17
|
+
if (input.budgetLeft === 0) return false;
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { parseDeepPolicyName } from "./recall-deep-policy.js";
|
|
5
|
+
|
|
6
|
+
test("stop is allowed", () => {
|
|
7
|
+
assert.deepEqual(parseDeepPolicyName("stop"), {
|
|
8
|
+
ok: true,
|
|
9
|
+
policy: "stop",
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("expand-once is allowed", () => {
|
|
14
|
+
assert.deepEqual(parseDeepPolicyName("expand-once"), {
|
|
15
|
+
ok: true,
|
|
16
|
+
policy: "expand-once",
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("unknown policy is unknown_policy", () => {
|
|
21
|
+
assert.deepEqual(parseDeepPolicyName("refine-twice"), {
|
|
22
|
+
ok: false,
|
|
23
|
+
error: "unknown_policy",
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("empty policy is unknown_policy", () => {
|
|
28
|
+
assert.deepEqual(parseDeepPolicyName(""), {
|
|
29
|
+
ok: false,
|
|
30
|
+
error: "unknown_policy",
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a deep-recall policy name (issue #2332 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Pure. Surfaces wait. Unknown or empty values fail closed.
|
|
5
|
+
*/
|
|
6
|
+
export const DEEP_POLICY_NAMES = ["stop", "expand-once"] as const;
|
|
7
|
+
|
|
8
|
+
export type DeepPolicyName = (typeof DEEP_POLICY_NAMES)[number];
|
|
9
|
+
|
|
10
|
+
export type ParseDeepPolicyNameResult =
|
|
11
|
+
| { ok: true; policy: DeepPolicyName }
|
|
12
|
+
| { ok: false; error: "unknown_policy" };
|
|
13
|
+
|
|
14
|
+
export function parseDeepPolicyName(value: unknown): ParseDeepPolicyNameResult {
|
|
15
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
16
|
+
return { ok: false, error: "unknown_policy" };
|
|
17
|
+
}
|
|
18
|
+
if (!(DEEP_POLICY_NAMES as readonly string[]).includes(value)) {
|
|
19
|
+
return { ok: false, error: "unknown_policy" };
|
|
20
|
+
}
|
|
21
|
+
return { ok: true, policy: value as DeepPolicyName };
|
|
22
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { parseDeepQuery } from "./recall-deep-query.js";
|
|
5
|
+
|
|
6
|
+
test("query is returned", () => {
|
|
7
|
+
assert.deepEqual(parseDeepQuery("what happened"), {
|
|
8
|
+
ok: true,
|
|
9
|
+
query: "what happened",
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("empty query is empty_query", () => {
|
|
14
|
+
assert.deepEqual(parseDeepQuery(""), { ok: false, error: "empty_query" });
|
|
15
|
+
assert.deepEqual(parseDeepQuery(" "), { ok: false, error: "empty_query" });
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("query is trimmed", () => {
|
|
19
|
+
assert.deepEqual(parseDeepQuery(" what happened "), {
|
|
20
|
+
ok: true,
|
|
21
|
+
query: "what happened",
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a deep-recall query (issue #2332 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Pure. Surfaces wait. Trim. Empty is empty_query.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export type ParseDeepQueryResult =
|
|
8
|
+
| { ok: true; query: string }
|
|
9
|
+
| { ok: false; error: "empty_query" };
|
|
10
|
+
|
|
11
|
+
export function parseDeepQuery(value: string): ParseDeepQueryResult {
|
|
12
|
+
const query = value.trim();
|
|
13
|
+
if (query.length === 0) return { ok: false, error: "empty_query" };
|
|
14
|
+
return { ok: true, query };
|
|
15
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { mayRefine } from "./recall-deep-refine.js";
|
|
5
|
+
|
|
6
|
+
test("refined is false", () => {
|
|
7
|
+
assert.equal(mayRefine({ refined: true, budgetLeft: 3 }), false);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("budget 0 is false", () => {
|
|
11
|
+
assert.equal(mayRefine({ refined: false, budgetLeft: 0 }), false);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("ok is true", () => {
|
|
15
|
+
assert.equal(mayRefine({ refined: false, budgetLeft: 3 }), true);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("negative budget throws", () => {
|
|
19
|
+
assert.throws(
|
|
20
|
+
() => mayRefine({ refined: false, budgetLeft: -1 }),
|
|
21
|
+
/negative/,
|
|
22
|
+
);
|
|
23
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-recall one-shot refine gate (issue #2332 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Pure. Surfaces wait. Already refined or budget 0 refuse.
|
|
5
|
+
* Negative budget throws.
|
|
6
|
+
*/
|
|
7
|
+
export function mayRefine(input: {
|
|
8
|
+
refined: boolean;
|
|
9
|
+
budgetLeft: number;
|
|
10
|
+
}): boolean {
|
|
11
|
+
if (input.budgetLeft < 0) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
`deep recall refine budget must not be negative; got ${JSON.stringify(input.budgetLeft)}`,
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
if (input.refined) return false;
|
|
17
|
+
if (input.budgetLeft === 0) return false;
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
runDeepRecall,
|
|
6
|
+
type DeepRecallState,
|
|
7
|
+
} from "./recall-deep.js";
|
|
8
|
+
import { renderDeepRecallTrace } from "./recall-deep-render.js";
|
|
9
|
+
|
|
10
|
+
function seed(extra: Partial<DeepRecallState> = {}): DeepRecallState {
|
|
11
|
+
return {
|
|
12
|
+
query: "who met at the cafe",
|
|
13
|
+
workingSet: [],
|
|
14
|
+
frontier: ["m-b", "m-c"],
|
|
15
|
+
budget: 2,
|
|
16
|
+
...extra,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
test("empty working set prints (empty)", () => {
|
|
21
|
+
const result = runDeepRecall(seed({ budget: 0 }), () => {
|
|
22
|
+
throw new Error("policy must not run when budget is 0");
|
|
23
|
+
});
|
|
24
|
+
assert.equal(
|
|
25
|
+
renderDeepRecallTrace(result),
|
|
26
|
+
[
|
|
27
|
+
"# Deep recall",
|
|
28
|
+
"",
|
|
29
|
+
"- query: who met at the cafe",
|
|
30
|
+
"- budget: 0",
|
|
31
|
+
"- stop: budget exhausted",
|
|
32
|
+
"",
|
|
33
|
+
"## Steps",
|
|
34
|
+
"",
|
|
35
|
+
"1. stop budget=0 workingSet=(empty) frontier=m-b, m-c",
|
|
36
|
+
"",
|
|
37
|
+
].join("\n"),
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("expand then stop snapshot", () => {
|
|
42
|
+
const result = runDeepRecall(seed({ workingSet: ["m-seed"], budget: 2 }), (state) =>
|
|
43
|
+
state.workingSet.includes("m-b") ? "stop" : "expand",
|
|
44
|
+
);
|
|
45
|
+
assert.equal(
|
|
46
|
+
renderDeepRecallTrace(result),
|
|
47
|
+
[
|
|
48
|
+
"# Deep recall",
|
|
49
|
+
"",
|
|
50
|
+
"- query: who met at the cafe",
|
|
51
|
+
"- budget: 1",
|
|
52
|
+
"- stop: stop",
|
|
53
|
+
"",
|
|
54
|
+
"## Steps",
|
|
55
|
+
"",
|
|
56
|
+
"1. expand budget=1 workingSet=m-seed, m-b frontier=m-c",
|
|
57
|
+
"2. stop budget=1 workingSet=m-seed, m-b frontier=m-c",
|
|
58
|
+
"",
|
|
59
|
+
].join("\n"),
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("same result renders the same bytes", () => {
|
|
64
|
+
const policy = () => "stop";
|
|
65
|
+
const first = renderDeepRecallTrace(runDeepRecall(seed({ budget: 3 }), policy));
|
|
66
|
+
const second = renderDeepRecallTrace(runDeepRecall(seed({ budget: 3 }), policy));
|
|
67
|
+
assert.equal(first, second);
|
|
68
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown renderer for a deep-recall trace (issue #2332 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Deterministic. Surfaces wait. Empty working set prints (empty).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { DeepRecallResult } from "./recall-deep.js";
|
|
8
|
+
|
|
9
|
+
export function renderDeepRecallTrace(result: DeepRecallResult): string {
|
|
10
|
+
const last = result.trace[result.trace.length - 1];
|
|
11
|
+
const stop = !last ? "none" : last.budget <= 0 ? "budget exhausted" : last.action;
|
|
12
|
+
const steps =
|
|
13
|
+
result.trace.length === 0
|
|
14
|
+
? ["(empty)"]
|
|
15
|
+
: result.trace.map((step, index) => {
|
|
16
|
+
const workingSet = step.workingSet.length === 0 ? "(empty)" : step.workingSet.join(", ");
|
|
17
|
+
const frontier = step.frontier.length === 0 ? "(empty)" : step.frontier.join(", ");
|
|
18
|
+
return `${index + 1}. ${step.action} budget=${step.budget} workingSet=${workingSet} frontier=${frontier}`;
|
|
19
|
+
});
|
|
20
|
+
return [
|
|
21
|
+
"# Deep recall",
|
|
22
|
+
"",
|
|
23
|
+
`- query: ${result.state.query}`,
|
|
24
|
+
`- budget: ${result.state.budget}`,
|
|
25
|
+
`- stop: ${stop}`,
|
|
26
|
+
"",
|
|
27
|
+
"## Steps",
|
|
28
|
+
"",
|
|
29
|
+
...steps,
|
|
30
|
+
"",
|
|
31
|
+
].join("\n");
|
|
32
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { parseStepCount } from "./recall-deep-step-count.js";
|
|
5
|
+
|
|
6
|
+
test("step count 0 is allowed", () => {
|
|
7
|
+
assert.equal(parseStepCount(0), 0);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("step count 5 is returned", () => {
|
|
11
|
+
assert.equal(parseStepCount(5), 5);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("negative step count throws", () => {
|
|
15
|
+
assert.throws(() => parseStepCount(-1), /non-negative integer/);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("float step count throws", () => {
|
|
19
|
+
assert.throws(() => parseStepCount(1.5), /non-negative integer/);
|
|
20
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-recall step-count parse (issue #2332 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Pure. Surfaces wait. 0 is allowed. Negative or non-integer throws.
|
|
5
|
+
*/
|
|
6
|
+
export function parseStepCount(value: unknown): number {
|
|
7
|
+
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value) || value < 0) {
|
|
8
|
+
throw new Error(
|
|
9
|
+
`deep recall step count must be a non-negative integer; got ${JSON.stringify(value)}`,
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { parseDeepStopReason } from "./recall-deep-stop-reason.js";
|
|
5
|
+
|
|
6
|
+
test("budget_exhausted is allowed", () => {
|
|
7
|
+
assert.deepEqual(parseDeepStopReason("budget_exhausted"), {
|
|
8
|
+
ok: true,
|
|
9
|
+
reason: "budget_exhausted",
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("policy_stop is allowed", () => {
|
|
14
|
+
assert.deepEqual(parseDeepStopReason("policy_stop"), {
|
|
15
|
+
ok: true,
|
|
16
|
+
reason: "policy_stop",
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("expand_once is allowed", () => {
|
|
21
|
+
assert.deepEqual(parseDeepStopReason("expand_once"), {
|
|
22
|
+
ok: true,
|
|
23
|
+
reason: "expand_once",
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("refine_done is allowed", () => {
|
|
28
|
+
assert.deepEqual(parseDeepStopReason("refine_done"), {
|
|
29
|
+
ok: true,
|
|
30
|
+
reason: "refine_done",
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("unknown reason is unknown_reason", () => {
|
|
35
|
+
assert.deepEqual(parseDeepStopReason("stop"), {
|
|
36
|
+
ok: false,
|
|
37
|
+
error: "unknown_reason",
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("empty reason is unknown_reason", () => {
|
|
42
|
+
assert.deepEqual(parseDeepStopReason(""), {
|
|
43
|
+
ok: false,
|
|
44
|
+
error: "unknown_reason",
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a deep-recall stop reason (issue #2332 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Pure. Surfaces wait. Unknown or empty values fail closed.
|
|
5
|
+
*/
|
|
6
|
+
export const DEEP_STOP_REASONS = [
|
|
7
|
+
"budget_exhausted",
|
|
8
|
+
"policy_stop",
|
|
9
|
+
"expand_once",
|
|
10
|
+
"refine_done",
|
|
11
|
+
] as const;
|
|
12
|
+
|
|
13
|
+
export type DeepStopReason = (typeof DEEP_STOP_REASONS)[number];
|
|
14
|
+
|
|
15
|
+
export type ParseDeepStopReasonResult =
|
|
16
|
+
| { ok: true; reason: DeepStopReason }
|
|
17
|
+
| { ok: false; error: "unknown_reason" };
|
|
18
|
+
|
|
19
|
+
export function parseDeepStopReason(value: unknown): ParseDeepStopReasonResult {
|
|
20
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
21
|
+
return { ok: false, error: "unknown_reason" };
|
|
22
|
+
}
|
|
23
|
+
if (!(DEEP_STOP_REASONS as readonly string[]).includes(value)) {
|
|
24
|
+
return { ok: false, error: "unknown_reason" };
|
|
25
|
+
}
|
|
26
|
+
return { ok: true, reason: value as DeepStopReason };
|
|
27
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { shouldStopDeepRecall } from "./recall-deep-stop.js";
|
|
5
|
+
|
|
6
|
+
test("budgetLeft 0 stops", () => {
|
|
7
|
+
assert.equal(shouldStopDeepRecall({ budgetLeft: 0, policy: "expand-once" }), true);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("stop policy stops", () => {
|
|
11
|
+
assert.equal(shouldStopDeepRecall({ budgetLeft: 3, policy: "stop" }), true);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("expand-once stops only after one expansion", () => {
|
|
15
|
+
assert.equal(
|
|
16
|
+
shouldStopDeepRecall({ budgetLeft: 3, policy: "expand-once", alreadyExpanded: false }),
|
|
17
|
+
false,
|
|
18
|
+
);
|
|
19
|
+
assert.equal(
|
|
20
|
+
shouldStopDeepRecall({ budgetLeft: 3, policy: "expand-once", alreadyExpanded: true }),
|
|
21
|
+
true,
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("unknown policy throws", () => {
|
|
26
|
+
assert.throws(
|
|
27
|
+
() => shouldStopDeepRecall({ budgetLeft: 3, policy: "refine-twice" }),
|
|
28
|
+
/unknown deep recall stop policy/,
|
|
29
|
+
);
|
|
30
|
+
assert.throws(
|
|
31
|
+
() => shouldStopDeepRecall({ budgetLeft: 3, policy: "refine-twice" }),
|
|
32
|
+
/stop, expand-once/,
|
|
33
|
+
);
|
|
34
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-recall stop predicate (issue #2332 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Pure. Surfaces wait. Budget 0, stop policy, and expand-once after
|
|
5
|
+
* one expansion halt. Unknown policy throws.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const DEEP_RECALL_STOP_POLICIES = ["stop", "expand-once"] as const;
|
|
9
|
+
|
|
10
|
+
export type DeepRecallStopPolicy = (typeof DEEP_RECALL_STOP_POLICIES)[number];
|
|
11
|
+
|
|
12
|
+
export interface DeepRecallStopInput {
|
|
13
|
+
budgetLeft: number;
|
|
14
|
+
policy: string;
|
|
15
|
+
alreadyExpanded?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function isDeepRecallStopPolicy(value: unknown): value is DeepRecallStopPolicy {
|
|
19
|
+
return typeof value === "string" && (DEEP_RECALL_STOP_POLICIES as readonly string[]).includes(value);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function shouldStopDeepRecall(input: DeepRecallStopInput): boolean {
|
|
23
|
+
if (!isDeepRecallStopPolicy(input.policy)) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
`unknown deep recall stop policy: ${JSON.stringify(input.policy)}. Valid: ${DEEP_RECALL_STOP_POLICIES.join(", ")}`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
if (input.budgetLeft <= 0) return true;
|
|
29
|
+
if (input.policy === "stop") return true;
|
|
30
|
+
return input.alreadyExpanded === true;
|
|
31
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { isEmptyWorkingSet } from "./recall-deep-working-set.js";
|
|
5
|
+
|
|
6
|
+
test("null, undefined, and empty array are empty", () => {
|
|
7
|
+
assert.equal(isEmptyWorkingSet(null), true);
|
|
8
|
+
assert.equal(isEmptyWorkingSet(undefined), true);
|
|
9
|
+
assert.equal(isEmptyWorkingSet([]), true);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("a non-empty array is not empty", () => {
|
|
13
|
+
assert.equal(isEmptyWorkingSet([{ id: 1 }]), false);
|
|
14
|
+
assert.equal(isEmptyWorkingSet([0]), false);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("a non-array throws", () => {
|
|
18
|
+
assert.throws(() => isEmptyWorkingSet({}), TypeError);
|
|
19
|
+
assert.throws(() => isEmptyWorkingSet("items"), TypeError);
|
|
20
|
+
assert.throws(() => isEmptyWorkingSet(1), TypeError);
|
|
21
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Empty-set guard for a deep-recall working set (issue #2332 leftover).
|
|
3
|
+
*
|
|
4
|
+
* null, undefined, and [] are empty. A non-array throws. Any other array is not empty.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** True when the working set is absent or has no items. */
|
|
8
|
+
export function isEmptyWorkingSet(items: unknown): boolean {
|
|
9
|
+
if (items == null) return true;
|
|
10
|
+
if (!Array.isArray(items)) {
|
|
11
|
+
throw new TypeError("items must be an array");
|
|
12
|
+
}
|
|
13
|
+
return items.length === 0;
|
|
14
|
+
}
|