@modusensus/dsh-mneme 0.14.0-beta.1 → 0.14.0-beta.2
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/LICENSE +21 -21
- package/README.md +830 -830
- package/assets/icon.svg +3 -3
- package/bin/cli.mjs +964 -964
- package/bin/dsh-mneme-choro.mjs +262 -262
- package/bin/dsh-mneme-mcp.mjs +510 -510
- package/bin/dsh-mneme-serve.mjs +151 -151
- package/cordis.patch.yml +21 -21
- package/docs/CONFIGURATION.md +407 -404
- package/docs/CONTINUITY.md +139 -139
- package/docs/DAEMON.md +57 -57
- package/docs/DIRECTORIES.md +114 -114
- package/docs/DISTILL.md +397 -371
- package/docs/DSH-GO.md +97 -97
- package/docs/ENTITIES.md +247 -247
- package/docs/FORGET.md +77 -77
- package/docs/KB.md +110 -110
- package/docs/LOCAL_MODEL.md +222 -222
- package/docs/SEMANTIC.md +256 -256
- package/docs/SHARE.md +552 -552
- package/docs/SLEEP.md +202 -202
- package/docs/STORAGE.md +122 -122
- package/docs/WORKFLOWS.md +366 -366
- package/lib/api-standalone.js +1007 -1007
- package/lib/api.js +3600 -3600
- package/lib/attachment-text.js +122 -122
- package/lib/bootstrap-http.js +105 -105
- package/lib/bootstrap.js +215 -215
- package/lib/candidates.js +454 -454
- package/lib/capabilities.js +819 -819
- package/lib/choro-command.js +111 -111
- package/lib/client.js +14420 -14322
- package/lib/commands.js +95 -95
- package/lib/config-keys.js +144 -144
- package/lib/config.js +1361 -1344
- package/lib/content-hash.js +54 -54
- package/lib/continuity.js +258 -258
- package/lib/date-hint.js +32 -0
- package/lib/diary/auto.js +190 -190
- package/lib/diary/compose.js +440 -440
- package/lib/diary/dir.js +59 -59
- package/lib/diary/export.js +97 -97
- package/lib/diary/index.js +26 -26
- package/lib/diary/library.js +189 -189
- package/lib/diary/qq-inbox.js +142 -142
- package/lib/diary/rollover.js +61 -61
- package/lib/diary/session-provider.js +122 -122
- package/lib/document-index.js +94 -94
- package/lib/document.js +322 -322
- package/lib/dream/clustering.js +123 -123
- package/lib/dream/decisions.js +945 -945
- package/lib/dream/narratives.js +44 -44
- package/lib/dream/sleep.js +2027 -2027
- package/lib/dream/triage.js +139 -139
- package/lib/dream.js +1879 -1879
- package/lib/dsh-go/host.js +162 -162
- package/lib/dsh-go/panel.js +2091 -2091
- package/lib/dsh-go/text.js +342 -342
- package/lib/dsh-go/views/common.js +68 -68
- package/lib/dsh-go/views/entity.js +48 -48
- package/lib/dsh-go/views/memory.js +198 -198
- package/lib/dsh-go/views/root.js +30 -30
- package/lib/dsh-go/views/settings.js +398 -398
- package/lib/dsh-go/views/status.js +51 -51
- package/lib/embedding.js +342 -342
- package/lib/entities/extractor.js +285 -285
- package/lib/fence.js +24 -24
- package/lib/graph/anchoring.js +184 -184
- package/lib/guide.js +74 -74
- package/lib/heat.js +144 -144
- package/lib/hot-memory.js +119 -119
- package/lib/image-describe.js +158 -0
- package/lib/index.js +852 -852
- package/lib/inject.js +656 -651
- package/lib/kb/index.js +309 -309
- package/lib/kb/routes.js +219 -219
- package/lib/kb/tools.js +148 -148
- package/lib/lang.js +607 -595
- package/lib/local-embedder.js +358 -358
- package/lib/maintenance.js +162 -162
- package/lib/memory-source.js +9 -9
- package/lib/mirror.js +330 -330
- package/lib/organize.js +456 -456
- package/lib/peak-hours.js +172 -172
- package/lib/pipeline-activities.js +178 -178
- package/lib/pipeline-attribution.js +165 -165
- package/lib/pipeline-command.js +279 -279
- package/lib/pipeline-confirm.js +142 -142
- package/lib/pipeline-exec.js +174 -174
- package/lib/pipeline-nudge-auto.js +129 -129
- package/lib/pipeline-nudge.js +1623 -1623
- package/lib/pipeline-observations.js +181 -181
- package/lib/pipeline-observe.js +133 -133
- package/lib/pipeline-runner.js +361 -361
- package/lib/pipeline-runs.js +442 -442
- package/lib/pipeline.js +716 -716
- package/lib/placement.js +13 -13
- package/lib/pre-inject-gate.js +354 -354
- package/lib/profile-extract.js +164 -164
- package/lib/profile-facts.js +356 -356
- package/lib/provenance-http.js +251 -251
- package/lib/quality-filter.js +162 -162
- package/lib/recall-stats.js +190 -190
- package/lib/reclaim-http.js +150 -150
- package/lib/reranker.js +269 -269
- package/lib/runtime/adopt.js +176 -176
- package/lib/runtime/closure.js +172 -172
- package/lib/runtime/download.js +247 -247
- package/lib/runtime/layout.js +265 -265
- package/lib/runtime/loader.js +252 -252
- package/lib/runtime/model-fetch.js +361 -361
- package/lib/runtime/provision.js +237 -237
- package/lib/runtime/tarball.js +130 -130
- package/lib/runtime/verify.js +223 -223
- package/lib/safe-slice.js +18 -18
- package/lib/scope-state.js +277 -277
- package/lib/scope.js +187 -187
- package/lib/search/adaptive.js +60 -60
- package/lib/search/bm25.js +96 -96
- package/lib/semantic.js +572 -572
- package/lib/sensitive-scan.js +209 -209
- package/lib/serve.js +228 -228
- package/lib/service.js +3268 -3268
- package/lib/session-gate.js +91 -91
- package/lib/session-usage.js +350 -350
- package/lib/settings.js +827 -817
- package/lib/share-http.js +281 -281
- package/lib/share-import.js +234 -234
- package/lib/share.js +335 -335
- package/lib/store.js +5895 -5895
- package/lib/summarize.js +1388 -1343
- package/lib/tools.js +1370 -1356
- package/lib/user-settings.js +230 -230
- package/lib/vector-index.js +180 -180
- package/lib/version-check.js +122 -122
- package/lib/wiki/claims.js +267 -267
- package/lib/wiki/cli-hint.js +90 -90
- package/lib/wiki/inject.js +164 -164
- package/lib/wiki/partition.js +200 -200
- package/lib/wiki/plan.js +214 -214
- package/lib/wiki/queries.js +640 -640
- package/lib/wiki/render.js +261 -261
- package/lib/wiki/scan.js +371 -371
- package/lib/wiki/t0.js +500 -500
- package/lib/wiki/t1-jobs.js +232 -232
- package/lib/wiki/t1.js +609 -609
- package/lib/write-admission.js +404 -404
- package/locale/en.json +6 -6
- package/locale/zh.json +6 -6
- package/package.json +1 -1
- package/runtime-manifest.json +526 -526
- package/scripts/benchmark-embed.js +201 -201
- package/scripts/benchmark-recall.js +249 -249
- package/scripts/benchmark-rerank.js +166 -166
- package/scripts/build-runtime-manifest.mjs +224 -224
- package/scripts/changelog-prep.mjs +91 -91
- package/scripts/check-sync.js +44 -44
- package/scripts/e2e-dsh.js +220 -220
- package/scripts/mneme-runtime.mjs +277 -277
- package/scripts/publish-gate.mjs +197 -197
- package/scripts/release-docs.mjs +210 -210
- package/scripts/release-notes.mjs +164 -164
- package/scripts/stress-dsh.js +255 -255
- package/scripts/sync-lib.js +47 -47
- package/scripts/sync-test-badge.mjs +69 -69
- package/scripts/test-count-sync.mjs +48 -48
- package/src/api-standalone.js +1007 -1007
- package/src/api.js +3600 -3600
- package/src/attachment-text.js +122 -122
- package/src/bootstrap-http.js +105 -105
- package/src/bootstrap.js +215 -215
- package/src/candidates.js +454 -454
- package/src/capabilities.js +819 -819
- package/src/choro-command.js +111 -111
- package/src/commands.js +95 -95
- package/src/config-keys.js +144 -144
- package/src/config.js +1361 -1344
- package/src/content-hash.js +54 -54
- package/src/continuity.js +258 -258
- package/src/date-hint.js +32 -0
- package/src/diary/auto.js +190 -190
- package/src/diary/compose.js +440 -440
- package/src/diary/dir.js +59 -59
- package/src/diary/export.js +97 -97
- package/src/diary/index.js +26 -26
- package/src/diary/library.js +189 -189
- package/src/diary/qq-inbox.js +142 -142
- package/src/diary/rollover.js +61 -61
- package/src/diary/session-provider.js +122 -122
- package/src/document-index.js +94 -94
- package/src/document.js +322 -322
- package/src/dream/clustering.js +123 -123
- package/src/dream/decisions.js +945 -945
- package/src/dream/narratives.js +44 -44
- package/src/dream/sleep.js +2027 -2027
- package/src/dream/triage.js +139 -139
- package/src/dream.js +1879 -1879
- package/src/dsh-go/host.js +162 -162
- package/src/dsh-go/panel.js +2091 -2091
- package/src/dsh-go/text.js +342 -342
- package/src/dsh-go/views/common.js +68 -68
- package/src/dsh-go/views/entity.js +48 -48
- package/src/dsh-go/views/memory.js +198 -198
- package/src/dsh-go/views/root.js +30 -30
- package/src/dsh-go/views/settings.js +398 -398
- package/src/dsh-go/views/status.js +51 -51
- package/src/embedding.js +342 -342
- package/src/entities/extractor.js +285 -285
- package/src/fence.js +24 -24
- package/src/graph/anchoring.js +184 -184
- package/src/guide.js +74 -74
- package/src/heat.js +144 -144
- package/src/hot-memory.js +119 -119
- package/src/image-describe.js +158 -0
- package/src/index.js +852 -852
- package/src/inject.js +656 -651
- package/src/kb/index.js +309 -309
- package/src/kb/routes.js +219 -219
- package/src/kb/tools.js +148 -148
- package/src/lang.js +607 -595
- package/src/local-embedder.js +358 -358
- package/src/maintenance.js +162 -162
- package/src/memory-source.js +9 -9
- package/src/mirror.js +330 -330
- package/src/organize.js +456 -456
- package/src/peak-hours.js +172 -172
- package/src/pipeline-activities.js +178 -178
- package/src/pipeline-attribution.js +165 -165
- package/src/pipeline-command.js +279 -279
- package/src/pipeline-confirm.js +142 -142
- package/src/pipeline-exec.js +174 -174
- package/src/pipeline-nudge-auto.js +129 -129
- package/src/pipeline-nudge.js +1623 -1623
- package/src/pipeline-observations.js +181 -181
- package/src/pipeline-observe.js +133 -133
- package/src/pipeline-runner.js +361 -361
- package/src/pipeline-runs.js +442 -442
- package/src/pipeline.js +716 -716
- package/src/placement.js +13 -13
- package/src/pre-inject-gate.js +354 -354
- package/src/profile-extract.js +164 -164
- package/src/profile-facts.js +356 -356
- package/src/provenance-http.js +251 -251
- package/src/quality-filter.js +162 -162
- package/src/recall-stats.js +190 -190
- package/src/reclaim-http.js +150 -150
- package/src/reranker.js +269 -269
- package/src/runtime/adopt.js +176 -176
- package/src/runtime/closure.js +172 -172
- package/src/runtime/download.js +247 -247
- package/src/runtime/layout.js +265 -265
- package/src/runtime/loader.js +252 -252
- package/src/runtime/model-fetch.js +361 -361
- package/src/runtime/provision.js +237 -237
- package/src/runtime/tarball.js +130 -130
- package/src/runtime/verify.js +223 -223
- package/src/safe-slice.js +18 -18
- package/src/scope-state.js +277 -277
- package/src/scope.js +187 -187
- package/src/search/adaptive.js +60 -60
- package/src/search/bm25.js +96 -96
- package/src/semantic.js +572 -572
- package/src/sensitive-scan.js +209 -209
- package/src/serve.js +228 -228
- package/src/service.js +3268 -3268
- package/src/session-gate.js +91 -91
- package/src/session-usage.js +350 -350
- package/src/settings.js +827 -817
- package/src/share-http.js +281 -281
- package/src/share-import.js +234 -234
- package/src/share.js +335 -335
- package/src/store.js +5895 -5895
- package/src/summarize.js +1388 -1343
- package/src/tools.js +1370 -1356
- package/src/user-settings.js +230 -230
- package/src/vector-index.js +180 -180
- package/src/version-check.js +122 -122
- package/src/wiki/claims.js +267 -267
- package/src/wiki/cli-hint.js +90 -90
- package/src/wiki/inject.js +164 -164
- package/src/wiki/partition.js +200 -200
- package/src/wiki/plan.js +214 -214
- package/src/wiki/queries.js +640 -640
- package/src/wiki/render.js +261 -261
- package/src/wiki/scan.js +371 -371
- package/src/wiki/t0.js +500 -500
- package/src/wiki/t1-jobs.js +232 -232
- package/src/wiki/t1.js +609 -609
- package/src/write-admission.js +404 -404
- package/test/adaptive-inject-budget.test.js +85 -85
- package/test/api-hardening.test.js +173 -173
- package/test/api-nudge-route.test.js +259 -259
- package/test/api-routes-gaps.test.js +1092 -1092
- package/test/api.test.js +3007 -2998
- package/test/attachment-text.test.js +139 -139
- package/test/audit.test.js +448 -448
- package/test/baseline-persist.test.js +248 -248
- package/test/benchmark.test.js +94 -94
- package/test/bm25-corpus-cache.test.js +145 -145
- package/test/bootstrap.test.js +228 -228
- package/test/candidates.test.js +345 -345
- package/test/capabilities.test.js +577 -577
- package/test/capacity-warning.test.js +262 -262
- package/test/changelog-prep.test.js +125 -125
- package/test/choro-command.test.js +218 -218
- package/test/cli-enums.test.js +37 -37
- package/test/cli-flag-value.test.js +86 -86
- package/test/cli-receive.test.js +390 -390
- package/test/cli-share.test.js +437 -437
- package/test/client-share.test.js +225 -225
- package/test/client.test.js +4595 -4425
- package/test/clustering.test.js +100 -100
- package/test/commands.test.js +106 -106
- package/test/config-keys-routes.test.js +233 -233
- package/test/config.test.js +153 -153
- package/test/conflict-freeze.test.js +344 -344
- package/test/conflict-ledger-enforce.test.js +452 -452
- package/test/conflict-ledger.test.js +242 -242
- package/test/conflict-reviewed.test.js +79 -79
- package/test/content-hash.test.js +204 -204
- package/test/continuity.test.js +452 -452
- package/test/contrast.test.js +432 -432
- package/test/date-hint.test.js +156 -0
- package/test/dedupe-candidate-window.test.js +180 -180
- package/test/dependency-overrides.test.js +78 -78
- package/test/diary-library.test.js +187 -187
- package/test/diary.test.js +576 -576
- package/test/differentiate-feedback.test.js +248 -248
- package/test/distill-tx-embed-gap.test.js +110 -110
- package/test/docs-config-keys.test.js +65 -65
- package/test/document-dir.test.js +233 -233
- package/test/document.test.js +703 -703
- package/test/dream-archive-guardrail.test.js +116 -116
- package/test/dream-baseline-clamp.test.js +174 -174
- package/test/dream-candidate-hybrid.test.js +281 -281
- package/test/dream-coverage-degrade.test.js +86 -86
- package/test/dream-decision-evidence.test.js +314 -314
- package/test/dream-failure-backoff.test.js +173 -173
- package/test/dream-fence.test.js +207 -207
- package/test/dream-maxtokens-fallback.test.js +132 -132
- package/test/dream-merge-guardrail.test.js +219 -219
- package/test/dream-peak-hours.test.js +194 -194
- package/test/dream.test.js +1528 -1528
- package/test/dsh-go-host.test.js +134 -134
- package/test/dsh-go-panel-actions.test.js +854 -854
- package/test/dsh-go-panel.test.js +251 -251
- package/test/embed-ready-poll.test.js +94 -94
- package/test/embed-text-reasons.test.js +112 -112
- package/test/embedding-cache-f32.test.js +276 -276
- package/test/embedding-ready.test.js +226 -226
- package/test/entities.test.js +711 -711
- package/test/entity-recall.test.js +179 -179
- package/test/epistemic.test.js +325 -325
- package/test/failure-query.test.js +147 -147
- package/test/failure-retention.test.js +105 -105
- package/test/fnew-0112.test.js +311 -311
- package/test/fnew-03.test.js +422 -422
- package/test/forget-corrections.test.js +70 -70
- package/test/graph-anchoring.test.js +184 -184
- package/test/graph-api.test.js +333 -333
- package/test/graph-boosted-relations.test.js +189 -189
- package/test/graph-inject-budget.test.js +103 -103
- package/test/graph-multipath.test.js +269 -269
- package/test/graph-passive-confirm.test.js +91 -91
- package/test/graph-weight-evolution.test.js +104 -104
- package/test/heat.test.js +175 -175
- package/test/helpers/dream-mock.js +86 -86
- package/test/helpers/peer-worker.mjs +25 -25
- package/test/helpers/runtime-source.js +60 -60
- package/test/helpers/tar-builder.js +80 -80
- package/test/helpers/write-admission-samples.js +312 -312
- package/test/hot-memory.test.js +259 -259
- package/test/image-description.test.js +271 -0
- package/test/image-memory.test.js +170 -170
- package/test/inject-content-cap.test.js +91 -91
- package/test/inject-first-round-bm25.test.js +89 -89
- package/test/inject-heat.test.js +77 -77
- package/test/inject-parent-gate.test.js +134 -109
- package/test/inject-pin-explicit.test.js +300 -300
- package/test/inject-pin-vector-crowd.test.js +225 -225
- package/test/inject-pools.test.js +195 -195
- package/test/inject-recall.test.js +172 -172
- package/test/inject-rotation.test.js +161 -161
- package/test/inject.test.js +553 -553
- package/test/issue-617-step1-query-and-fusion.test.js +361 -361
- package/test/kb-api-wiring.test.js +128 -128
- package/test/kb-collections.test.js +272 -272
- package/test/kb-routes.test.js +379 -379
- package/test/lang.test.js +98 -98
- package/test/lastrunat-persist.test.js +101 -101
- package/test/lib-smoke.test.js +116 -116
- package/test/llm-audit.test.js +815 -815
- package/test/llm-message-source.test.js +207 -207
- package/test/local-embedder.test.js +292 -292
- package/test/maintenance.test.js +501 -501
- package/test/mcp-stdio.test.js +385 -385
- package/test/mint-source.test.js +311 -311
- package/test/mirror-dirty.test.js +424 -424
- package/test/mirror-edit-digest.test.js +187 -187
- package/test/mirror-generation.test.js +499 -499
- package/test/mirror-types.test.js +208 -208
- package/test/mirror.test.js +249 -249
- package/test/narrative-bars.test.js +162 -162
- package/test/organize-tool.test.js +232 -232
- package/test/organize.test.js +418 -418
- package/test/panel-chart-scale.test.js +90 -90
- package/test/panel-tokens.test.js +245 -245
- package/test/peak-hours-observability.test.js +70 -70
- package/test/peer-blockers.test.js +193 -193
- package/test/persona-addressing.test.js +83 -83
- package/test/persona-api.test.js +172 -172
- package/test/persona-by-session.test.js +568 -568
- package/test/persona-flag.test.js +36 -36
- package/test/persona-inject.test.js +145 -145
- package/test/persona-settings.test.js +198 -198
- package/test/pipeline-activities.test.js +155 -155
- package/test/pipeline-attribution.test.js +175 -175
- package/test/pipeline-command.test.js +243 -243
- package/test/pipeline-confirm.test.js +148 -148
- package/test/pipeline-exec.test.js +172 -172
- package/test/pipeline-nudge-auto.test.js +248 -248
- package/test/pipeline-nudge.test.js +1278 -1278
- package/test/pipeline-observations.test.js +157 -157
- package/test/pipeline-observe.test.js +127 -127
- package/test/pipeline-r1r2.test.js +278 -278
- package/test/pipeline-runner.test.js +468 -468
- package/test/pipeline-runs.test.js +767 -767
- package/test/pipeline.test.js +636 -636
- package/test/placement.test.js +36 -36
- package/test/policy-epoch.test.js +259 -259
- package/test/pre-inject-gate.test.js +444 -444
- package/test/profile-extract.test.js +269 -269
- package/test/profile-facts.test.js +492 -492
- package/test/prompt-stance.test.js +128 -128
- package/test/provenance-http.test.js +367 -367
- package/test/publish-gate.test.js +272 -272
- package/test/quality-backfill.test.js +290 -290
- package/test/quality-filter.test.js +295 -295
- package/test/readme-claims.test.js +113 -113
- package/test/reasoning-effort.test.js +752 -752
- package/test/recall-anti-update.test.js +82 -82
- package/test/recall-evals.test.js +253 -253
- package/test/recall-layer.test.js +326 -326
- package/test/recall-retention.test.js +128 -128
- package/test/recall-stats.test.js +274 -274
- package/test/receipt-chain.test.js +451 -451
- package/test/reclaim-http.test.js +209 -209
- package/test/reflection-update-gate.test.js +129 -129
- package/test/reflection.test.js +226 -226
- package/test/reindex-backfill.test.js +475 -475
- package/test/reindex-scheduler.test.js +369 -369
- package/test/release-docs.test.js +156 -156
- package/test/release-notes.test.js +265 -265
- package/test/release-workflow.test.js +93 -93
- package/test/reranker-single-logit.test.js +73 -73
- package/test/reranker.test.js +197 -197
- package/test/resident-status.test.js +83 -83
- package/test/route-policy.test.js +113 -113
- package/test/runtime-adopt.test.js +206 -206
- package/test/runtime-cli.test.js +89 -89
- package/test/runtime-closure.test.js +193 -193
- package/test/runtime-download.test.js +302 -302
- package/test/runtime-layout.test.js +163 -163
- package/test/runtime-loader.test.js +255 -255
- package/test/runtime-manifest.test.js +159 -159
- package/test/runtime-model-fetch.test.js +348 -348
- package/test/runtime-provision.test.js +101 -101
- package/test/runtime-tarball.test.js +81 -81
- package/test/runtime-verify.test.js +319 -319
- package/test/scope-candidates.test.js +491 -491
- package/test/scope-distill-stamp.test.js +134 -134
- package/test/scope-explicit.test.js +452 -452
- package/test/scope-inject-soft.test.js +106 -106
- package/test/scope-optional-service.test.js +110 -110
- package/test/scope-retrieval.test.js +197 -197
- package/test/scope-state.test.js +610 -610
- package/test/scope-storage.test.js +255 -255
- package/test/scope-strict.test.js +367 -367
- package/test/search-fusion.test.js +90 -90
- package/test/security-doc.test.js +188 -188
- package/test/semantic.test.js +124 -124
- package/test/sensitive-scan.test.js +251 -251
- package/test/serve-bin.test.js +121 -121
- package/test/serve.test.js +258 -258
- package/test/service-search.test.js +174 -174
- package/test/service.test.js +410 -410
- package/test/session-gate.test.js +264 -264
- package/test/session-usage.test.js +317 -317
- package/test/settings.test.js +273 -273
- package/test/share-foreign-rows.test.js +144 -144
- package/test/share-http.test.js +144 -144
- package/test/share-import.test.js +577 -577
- package/test/share-imported-guard.test.js +311 -311
- package/test/share-imported-identity.test.js +111 -111
- package/test/share-pack.test.js +511 -511
- package/test/share-receive-http.test.js +756 -756
- package/test/share-routes.test.js +337 -337
- package/test/share-store.test.js +133 -133
- package/test/share-validate.test.js +101 -101
- package/test/skip-invalid-restore.test.js +262 -262
- package/test/sleep-action-set.test.js +441 -441
- package/test/sleep-catchup.test.js +315 -315
- package/test/sleep-failure-backoff.test.js +156 -156
- package/test/sleep-heat.test.js +174 -174
- package/test/sleep-scheduler-rearm.test.js +89 -89
- package/test/sleep.test.js +1455 -1455
- package/test/standalone-api.test.js +1344 -1344
- package/test/store-vector-cache.test.js +98 -98
- package/test/store-write-path-columns.test.js +191 -191
- package/test/store.test.js +744 -744
- package/test/stress.test.js +209 -209
- package/test/summarize-occurred-at.test.js +127 -127
- package/test/summarize-parse-diagnostics.test.js +75 -75
- package/test/summarize-reasoning-effort.test.js +189 -189
- package/test/summarize.test.js +2251 -2251
- package/test/supersede-state-tracking.test.js +394 -394
- package/test/test-count-sync.test.js +71 -71
- package/test/tool-state-ignore.test.js +65 -65
- package/test/tools-dto-schema-matrix.test.js +398 -398
- package/test/tools-memory-get-schema.test.js +65 -65
- package/test/tools.test.js +585 -585
- package/test/updated-at-semantics.test.js +113 -113
- package/test/user-settings-preview.test.js +127 -127
- package/test/user-settings-segments.test.js +527 -527
- package/test/vector-index.test.js +334 -334
- package/test/version-check.test.js +152 -152
- package/test/webServer-optional.test.js +82 -82
- package/test/wiki-api.test.js +734 -734
- package/test/wiki-claims.test.js +194 -194
- package/test/wiki-cli-hint.test.js +118 -118
- package/test/wiki-inject.test.js +265 -265
- package/test/wiki-partition.test.js +112 -112
- package/test/wiki-plan.test.js +80 -80
- package/test/wiki-provenance.test.js +202 -202
- package/test/wiki-queries.test.js +398 -398
- package/test/wiki-scan.test.js +208 -208
- package/test/wiki-store.test.js +190 -190
- package/test/wiki-t0.test.js +456 -456
- package/test/wiki-t1-jobs.test.js +125 -125
- package/test/wiki-t1.test.js +460 -460
- package/test/wiki-tools.test.js +176 -176
- package/test/workflow-guards.test.js +155 -155
- package/test/write-admission.test.js +668 -668
|
@@ -1,232 +1,232 @@
|
|
|
1
|
-
// issue #231 的第二批:把已造好的整理引擎接到 agent 的调用面上(organizeEnabled
|
|
2
|
-
// + memory_organize 工具)。src/organize.js 的本体语义由 test/organize.test.js 守,
|
|
3
|
-
// 本文件只守**出口**这一层:闸门、报告/落地的两步协议、以及 strictScope 下
|
|
4
|
-
// 「看不见的行按不存在处理」这条可信上下文。
|
|
5
|
-
import test from "node:test";
|
|
6
|
-
import assert from "node:assert/strict";
|
|
7
|
-
import { createStore } from "../src/store.js";
|
|
8
|
-
import { createService } from "../src/service.js";
|
|
9
|
-
import { createTools } from "../src/tools.js";
|
|
10
|
-
import { applyLightModePreset } from "../src/config.js";
|
|
11
|
-
|
|
12
|
-
function setup(config = {}) {
|
|
13
|
-
const store = createStore(":memory:");
|
|
14
|
-
const service = createService({ store, mirror: null, config });
|
|
15
|
-
const registered = [];
|
|
16
|
-
const ctx = {
|
|
17
|
-
tools: {
|
|
18
|
-
register(def) {
|
|
19
|
-
registered.push(def);
|
|
20
|
-
return () => {};
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
createTools(ctx, service, config, undefined);
|
|
25
|
-
const byName = Object.fromEntries(registered.map((def) => [def.name, def]));
|
|
26
|
-
return { store, service, byName, registered };
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const CANDIDATES = [
|
|
30
|
-
{ type: "project", title: "发布只在包目录内", content: "根目录发过坏包,发布必须在 dsh-mneme/ 内执行。" },
|
|
31
|
-
{ type: "project", title: "另一条", content: "第二条候选的正文。" }
|
|
32
|
-
];
|
|
33
|
-
|
|
34
|
-
test("memory_organize registers when organizeEnabled is on", async () => {
|
|
35
|
-
const { byName } = setup({ organizeEnabled: true });
|
|
36
|
-
const tool = byName.memory_organize;
|
|
37
|
-
assert.ok(tool, "organizeEnabled=true 应当注册 memory_organize");
|
|
38
|
-
const report = await tool.execute({ mode: "dryRun", candidates: CANDIDATES });
|
|
39
|
-
assert.equal(report.status, "ok");
|
|
40
|
-
assert.equal(report.counts.total, 2, "两条候选都应进报告");
|
|
41
|
-
assert.equal(report.run_id ? typeof report.run_id : "none", "string", "dryRun 必须回一个 run_id 供 apply 引用");
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// 默认关=零行为变化是仓库红线(AGENTS.md 自查清单第 1 条)。这条现在就会绿——
|
|
45
|
-
// 它防的是「以后有人把默认翻成 true」,而不是今天的缺失实现。
|
|
46
|
-
test("memory_organize stays unregistered by default", () => {
|
|
47
|
-
const { registered } = setup();
|
|
48
|
-
assert.equal(registered.some((t) => t.name === "memory_organize"), false, "organizeEnabled 缺省时不得注册");
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test("lightMode preset turns organize off, but an explicit user switch wins", () => {
|
|
52
|
-
// 轻量档那一格是**预设**,不是强制(合并顺序「用户开关 > 轻量预设 > bundle」在
|
|
53
|
-
// index.js),所以这里断言的是预设值本身——同 continuity.test.js 的
|
|
54
|
-
// continuityRescueEnabled 那条。工具侧的注册与否由上一条默认关用例守着。
|
|
55
|
-
assert.equal(applyLightModePreset({ lightMode: true }).organizeEnabled, false);
|
|
56
|
-
assert.equal(applyLightModePreset({ lightMode: true, organizeEnabled: true }).organizeEnabled, false, "预设写死 false,赢的是合并时的用户开关,不是这里");
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test("dryRun writes no memory rows but leaves one organize audit row", () => {
|
|
60
|
-
const { store, byName } = setup({ organizeEnabled: true });
|
|
61
|
-
return byName.memory_organize.execute({ mode: "dryRun", candidates: CANDIDATES }).then((report) => {
|
|
62
|
-
assert.deepEqual(store.list({ limit: null }), [], "比对是报告,不是动作:记忆表必须一行不写");
|
|
63
|
-
const runs = store.listDreamRuns({ limit: 10 });
|
|
64
|
-
assert.equal(runs.length, 1, "dryRun 只留 dream_runs 一行回执");
|
|
65
|
-
assert.equal(runs[0].run_type, "organize");
|
|
66
|
-
assert.equal(runs[0].id, report.run_id);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test("apply lands the decisions it references and reports counters", async () => {
|
|
71
|
-
const { store, byName } = setup({ organizeEnabled: true });
|
|
72
|
-
const report = await byName.memory_organize.execute({ mode: "dryRun", candidates: CANDIDATES });
|
|
73
|
-
const applied = await byName.memory_organize.execute({
|
|
74
|
-
mode: "apply",
|
|
75
|
-
run_id: report.run_id,
|
|
76
|
-
decisions: [
|
|
77
|
-
{ action: "save", index: 0 },
|
|
78
|
-
{ action: "discard", index: 1 }
|
|
79
|
-
]
|
|
80
|
-
});
|
|
81
|
-
assert.equal(applied.saved, 1, "只数新建的行");
|
|
82
|
-
assert.equal(applied.discarded, 1);
|
|
83
|
-
assert.equal(applied.status, "ok");
|
|
84
|
-
assert.equal(store.list({ limit: null }).length, 1, "一条 save、一条 discard → 库里只有一行");
|
|
85
|
-
const types = store.listDreamRuns({ limit: 10 }).map((r) => r.run_type);
|
|
86
|
-
assert.deepEqual(types, ["organize", "organize"], "报告与落地各留一行审计");
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
test("apply refuses a run_id that was never reported", async () => {
|
|
90
|
-
const { byName } = setup({ organizeEnabled: true });
|
|
91
|
-
await assert.rejects(
|
|
92
|
-
() => byName.memory_organize.execute({ mode: "apply", run_id: "no-such-run", decisions: [{ action: "discard", index: 0 }] }),
|
|
93
|
-
/unknown organize run/,
|
|
94
|
-
"没有比对过的候选一律不落库(organize 硬规则 2)"
|
|
95
|
-
);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
test("apply refuses a missing run_id", async () => {
|
|
99
|
-
const { byName } = setup({ organizeEnabled: true });
|
|
100
|
-
await assert.rejects(
|
|
101
|
-
() => byName.memory_organize.execute({ mode: "apply", decisions: [{ action: "discard", index: 0 }] }),
|
|
102
|
-
/run_id is required/,
|
|
103
|
-
"apply 必须引用一次真实 dryRun"
|
|
104
|
-
);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
// 整理接口不能成为第二条「写进库却不带 scope」的通道:memory_save 在 scopeEnabled
|
|
108
|
-
// 下按会话身份盖 auto 章,organize 落地的候选必须同源。显式参数改盖 explicit,
|
|
109
|
-
// 与 memory_save / memory_register_document 同一规则。
|
|
110
|
-
test("save lands candidates stamped with the session scope (auto), like memory_save", async () => {
|
|
111
|
-
const { store, byName } = setup({ organizeEnabled: true, scopeEnabled: true });
|
|
112
|
-
const exec = { agent: { session: { id: "s1", header: { agentPreset: "me", cwd: "D:\\p" } } } };
|
|
113
|
-
const report = await byName.memory_organize.execute({ mode: "dryRun", candidates: CANDIDATES }, exec);
|
|
114
|
-
await byName.memory_organize.execute({ mode: "apply", run_id: report.run_id, decisions: [{ action: "save", index: 0 }] }, exec);
|
|
115
|
-
const row = store.list({ limit: null })[0];
|
|
116
|
-
assert.equal(row.agent_scope, "me", "缺省吃会话身份");
|
|
117
|
-
assert.equal(row.agent_scope_source, "auto");
|
|
118
|
-
assert.equal(row.workspace_scope, "D:\\p");
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
test("explicit scope arguments stamp as explicit and win over the session label", async () => {
|
|
122
|
-
const { store, byName } = setup({ organizeEnabled: true, scopeEnabled: true });
|
|
123
|
-
const exec = { agent: { session: { id: "s1", header: { agentPreset: "me", cwd: "D:\\p" } } } };
|
|
124
|
-
const report = await byName.memory_organize.execute(
|
|
125
|
-
{ mode: "dryRun", candidates: CANDIDATES, agent_scope: "other-agent" },
|
|
126
|
-
exec
|
|
127
|
-
);
|
|
128
|
-
await byName.memory_organize.execute({ mode: "apply", run_id: report.run_id, decisions: [{ action: "save", index: 0 }] }, exec);
|
|
129
|
-
const row = store.list({ limit: null })[0];
|
|
130
|
-
assert.equal(row.agent_scope, "other-agent", "显式参数盖在会话身份之上");
|
|
131
|
-
assert.equal(row.agent_scope_source, "explicit");
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
test("unknown mode is rejected", async () => {
|
|
135
|
-
const { byName } = setup({ organizeEnabled: true });
|
|
136
|
-
await assert.rejects(() => byName.memory_organize.execute({ mode: "force" }), /unknown mode/);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
// #170 复核项 4 的口径延伸到整理接口的**两侧**:报告侧不得泄漏存在性,落地侧不得
|
|
140
|
-
// 绕过 scope 治理改库。用例形状是刻意挑的:比对键只看三列**值**(sensitivity/agent/
|
|
141
|
-
// workspace),可见性还多认一个 `explicit` 来源,所以要造出「按值该命中、但会话看不见」
|
|
142
|
-
// 那一格——匿名会话(解析不到 agentPreset)对 explicit 行 fail-closed。
|
|
143
|
-
// 报告侧少了过滤就是探测口:`agent_scope` 是模型自己给的参数,A 会话可以拿 B 的标题问
|
|
144
|
-
// 「那一档有没有这行」,拿回 id/title 就等于确认存在——memory_get 在同一条件下回「不存在」。
|
|
145
|
-
test("dryRun reports an invisible match as new, with no id or title", async () => {
|
|
146
|
-
const config = { organizeEnabled: true, scopeEnabled: true, strictScope: true };
|
|
147
|
-
const { store, byName } = setup(config);
|
|
148
|
-
store.save({
|
|
149
|
-
type: "project",
|
|
150
|
-
title: "发布只在包目录内",
|
|
151
|
-
content: "team-a 名下的旧行。",
|
|
152
|
-
agent_scope: "team-a",
|
|
153
|
-
agent_scope_source: "explicit",
|
|
154
|
-
workspace_scope: "D:\\p",
|
|
155
|
-
workspace_scope_source: "auto"
|
|
156
|
-
});
|
|
157
|
-
const exec = { agent: { session: { id: "s-anon", header: { cwd: "D:\\p" } } } };
|
|
158
|
-
const report = await byName.memory_organize.execute(
|
|
159
|
-
{
|
|
160
|
-
mode: "dryRun",
|
|
161
|
-
candidates: [{ type: "project", title: "发布只在包目录内", content: "换一种说法的同一件事。" }],
|
|
162
|
-
agent_scope: "team-a",
|
|
163
|
-
workspace_scope: "D:\\p"
|
|
164
|
-
},
|
|
165
|
-
exec
|
|
166
|
-
);
|
|
167
|
-
assert.equal(report.items[0].verdict, "new", "看不见的行按不存在处理 → 报告只能说「新条目」");
|
|
168
|
-
assert.equal(report.items[0].match, undefined, "不得带回落点 id/title/sim");
|
|
169
|
-
assert.equal(report.counts.new, 1);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// 反面对照:strictScope 是**可选**硬过滤,关掉它时那行本来就可读(A2 只降权)。少了这条,
|
|
173
|
-
// 过滤就变成「闸门关着也少召回」的第二重惩罚——修安全问题不许顺手改默认行为。
|
|
174
|
-
test("the same row is still reported as exact when strictScope is off", async () => {
|
|
175
|
-
const config = { organizeEnabled: true, scopeEnabled: true };
|
|
176
|
-
const { store, byName } = setup(config);
|
|
177
|
-
const row = store.save({
|
|
178
|
-
type: "project",
|
|
179
|
-
title: "发布只在包目录内",
|
|
180
|
-
content: "team-a 名下的旧行。",
|
|
181
|
-
agent_scope: "team-a",
|
|
182
|
-
agent_scope_source: "explicit",
|
|
183
|
-
workspace_scope: "D:\\p",
|
|
184
|
-
workspace_scope_source: "auto"
|
|
185
|
-
});
|
|
186
|
-
const exec = { agent: { session: { id: "s-anon", header: { cwd: "D:\\p" } } } };
|
|
187
|
-
const report = await byName.memory_organize.execute(
|
|
188
|
-
{
|
|
189
|
-
mode: "dryRun",
|
|
190
|
-
candidates: [{ type: "project", title: "发布只在包目录内", content: "换一种说法的同一件事。" }],
|
|
191
|
-
agent_scope: "team-a",
|
|
192
|
-
workspace_scope: "D:\\p"
|
|
193
|
-
},
|
|
194
|
-
exec
|
|
195
|
-
);
|
|
196
|
-
assert.equal(report.items[0].verdict, "exact");
|
|
197
|
-
assert.equal(report.items[0].match.id, row.id, "闸门关着时照常给出落点,否则比对报告失去意义");
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
// 落地侧:报告已按「不存在」说了,archive 也不许真的动那一行(`opts.hiddenIds` 由可信
|
|
201
|
-
// 调用层算好传入,绝不取 payload 字段——那是调用方可自选的内容,不是授权)。
|
|
202
|
-
test("archive of a row the caller cannot see is skipped as out of scope", async () => {
|
|
203
|
-
const config = { organizeEnabled: true, scopeEnabled: true, strictScope: true };
|
|
204
|
-
const { store, byName } = setup(config);
|
|
205
|
-
const teamRow = store.save({
|
|
206
|
-
type: "project",
|
|
207
|
-
title: "发布只在包目录内",
|
|
208
|
-
content: "team-a 名下的旧行。",
|
|
209
|
-
agent_scope: "team-a",
|
|
210
|
-
agent_scope_source: "explicit",
|
|
211
|
-
workspace_scope: "D:\\p",
|
|
212
|
-
workspace_scope_source: "auto"
|
|
213
|
-
});
|
|
214
|
-
const exec = { agent: { session: { id: "s-anon", header: { cwd: "D:\\p" } } } };
|
|
215
|
-
const report = await byName.memory_organize.execute(
|
|
216
|
-
{
|
|
217
|
-
mode: "dryRun",
|
|
218
|
-
candidates: [{ type: "project", title: "发布只在包目录内", content: "换一种说法的同一件事。" }],
|
|
219
|
-
agent_scope: "team-a",
|
|
220
|
-
workspace_scope: "D:\\p"
|
|
221
|
-
},
|
|
222
|
-
exec
|
|
223
|
-
);
|
|
224
|
-
const applied = await byName.memory_organize.execute(
|
|
225
|
-
{ mode: "apply", run_id: report.run_id, decisions: [{ action: "archive", id: teamRow.id }] },
|
|
226
|
-
exec
|
|
227
|
-
);
|
|
228
|
-
assert.equal(applied.archived, 0, "看不见的行按不存在处理,不得归档");
|
|
229
|
-
assert.equal(applied.skipped.length, 1);
|
|
230
|
-
assert.match(applied.skipped[0].error, /out of scope/, "文案维持「unknown, archived or out of scope」:不泄漏存在性");
|
|
231
|
-
assert.equal(store.getById(teamRow.id).archived, false, "他人的行原样未动");
|
|
232
|
-
});
|
|
1
|
+
// issue #231 的第二批:把已造好的整理引擎接到 agent 的调用面上(organizeEnabled
|
|
2
|
+
// + memory_organize 工具)。src/organize.js 的本体语义由 test/organize.test.js 守,
|
|
3
|
+
// 本文件只守**出口**这一层:闸门、报告/落地的两步协议、以及 strictScope 下
|
|
4
|
+
// 「看不见的行按不存在处理」这条可信上下文。
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { createStore } from "../src/store.js";
|
|
8
|
+
import { createService } from "../src/service.js";
|
|
9
|
+
import { createTools } from "../src/tools.js";
|
|
10
|
+
import { applyLightModePreset } from "../src/config.js";
|
|
11
|
+
|
|
12
|
+
function setup(config = {}) {
|
|
13
|
+
const store = createStore(":memory:");
|
|
14
|
+
const service = createService({ store, mirror: null, config });
|
|
15
|
+
const registered = [];
|
|
16
|
+
const ctx = {
|
|
17
|
+
tools: {
|
|
18
|
+
register(def) {
|
|
19
|
+
registered.push(def);
|
|
20
|
+
return () => {};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
createTools(ctx, service, config, undefined);
|
|
25
|
+
const byName = Object.fromEntries(registered.map((def) => [def.name, def]));
|
|
26
|
+
return { store, service, byName, registered };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const CANDIDATES = [
|
|
30
|
+
{ type: "project", title: "发布只在包目录内", content: "根目录发过坏包,发布必须在 dsh-mneme/ 内执行。" },
|
|
31
|
+
{ type: "project", title: "另一条", content: "第二条候选的正文。" }
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
test("memory_organize registers when organizeEnabled is on", async () => {
|
|
35
|
+
const { byName } = setup({ organizeEnabled: true });
|
|
36
|
+
const tool = byName.memory_organize;
|
|
37
|
+
assert.ok(tool, "organizeEnabled=true 应当注册 memory_organize");
|
|
38
|
+
const report = await tool.execute({ mode: "dryRun", candidates: CANDIDATES });
|
|
39
|
+
assert.equal(report.status, "ok");
|
|
40
|
+
assert.equal(report.counts.total, 2, "两条候选都应进报告");
|
|
41
|
+
assert.equal(report.run_id ? typeof report.run_id : "none", "string", "dryRun 必须回一个 run_id 供 apply 引用");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// 默认关=零行为变化是仓库红线(AGENTS.md 自查清单第 1 条)。这条现在就会绿——
|
|
45
|
+
// 它防的是「以后有人把默认翻成 true」,而不是今天的缺失实现。
|
|
46
|
+
test("memory_organize stays unregistered by default", () => {
|
|
47
|
+
const { registered } = setup();
|
|
48
|
+
assert.equal(registered.some((t) => t.name === "memory_organize"), false, "organizeEnabled 缺省时不得注册");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("lightMode preset turns organize off, but an explicit user switch wins", () => {
|
|
52
|
+
// 轻量档那一格是**预设**,不是强制(合并顺序「用户开关 > 轻量预设 > bundle」在
|
|
53
|
+
// index.js),所以这里断言的是预设值本身——同 continuity.test.js 的
|
|
54
|
+
// continuityRescueEnabled 那条。工具侧的注册与否由上一条默认关用例守着。
|
|
55
|
+
assert.equal(applyLightModePreset({ lightMode: true }).organizeEnabled, false);
|
|
56
|
+
assert.equal(applyLightModePreset({ lightMode: true, organizeEnabled: true }).organizeEnabled, false, "预设写死 false,赢的是合并时的用户开关,不是这里");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("dryRun writes no memory rows but leaves one organize audit row", () => {
|
|
60
|
+
const { store, byName } = setup({ organizeEnabled: true });
|
|
61
|
+
return byName.memory_organize.execute({ mode: "dryRun", candidates: CANDIDATES }).then((report) => {
|
|
62
|
+
assert.deepEqual(store.list({ limit: null }), [], "比对是报告,不是动作:记忆表必须一行不写");
|
|
63
|
+
const runs = store.listDreamRuns({ limit: 10 });
|
|
64
|
+
assert.equal(runs.length, 1, "dryRun 只留 dream_runs 一行回执");
|
|
65
|
+
assert.equal(runs[0].run_type, "organize");
|
|
66
|
+
assert.equal(runs[0].id, report.run_id);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("apply lands the decisions it references and reports counters", async () => {
|
|
71
|
+
const { store, byName } = setup({ organizeEnabled: true });
|
|
72
|
+
const report = await byName.memory_organize.execute({ mode: "dryRun", candidates: CANDIDATES });
|
|
73
|
+
const applied = await byName.memory_organize.execute({
|
|
74
|
+
mode: "apply",
|
|
75
|
+
run_id: report.run_id,
|
|
76
|
+
decisions: [
|
|
77
|
+
{ action: "save", index: 0 },
|
|
78
|
+
{ action: "discard", index: 1 }
|
|
79
|
+
]
|
|
80
|
+
});
|
|
81
|
+
assert.equal(applied.saved, 1, "只数新建的行");
|
|
82
|
+
assert.equal(applied.discarded, 1);
|
|
83
|
+
assert.equal(applied.status, "ok");
|
|
84
|
+
assert.equal(store.list({ limit: null }).length, 1, "一条 save、一条 discard → 库里只有一行");
|
|
85
|
+
const types = store.listDreamRuns({ limit: 10 }).map((r) => r.run_type);
|
|
86
|
+
assert.deepEqual(types, ["organize", "organize"], "报告与落地各留一行审计");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("apply refuses a run_id that was never reported", async () => {
|
|
90
|
+
const { byName } = setup({ organizeEnabled: true });
|
|
91
|
+
await assert.rejects(
|
|
92
|
+
() => byName.memory_organize.execute({ mode: "apply", run_id: "no-such-run", decisions: [{ action: "discard", index: 0 }] }),
|
|
93
|
+
/unknown organize run/,
|
|
94
|
+
"没有比对过的候选一律不落库(organize 硬规则 2)"
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("apply refuses a missing run_id", async () => {
|
|
99
|
+
const { byName } = setup({ organizeEnabled: true });
|
|
100
|
+
await assert.rejects(
|
|
101
|
+
() => byName.memory_organize.execute({ mode: "apply", decisions: [{ action: "discard", index: 0 }] }),
|
|
102
|
+
/run_id is required/,
|
|
103
|
+
"apply 必须引用一次真实 dryRun"
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// 整理接口不能成为第二条「写进库却不带 scope」的通道:memory_save 在 scopeEnabled
|
|
108
|
+
// 下按会话身份盖 auto 章,organize 落地的候选必须同源。显式参数改盖 explicit,
|
|
109
|
+
// 与 memory_save / memory_register_document 同一规则。
|
|
110
|
+
test("save lands candidates stamped with the session scope (auto), like memory_save", async () => {
|
|
111
|
+
const { store, byName } = setup({ organizeEnabled: true, scopeEnabled: true });
|
|
112
|
+
const exec = { agent: { session: { id: "s1", header: { agentPreset: "me", cwd: "D:\\p" } } } };
|
|
113
|
+
const report = await byName.memory_organize.execute({ mode: "dryRun", candidates: CANDIDATES }, exec);
|
|
114
|
+
await byName.memory_organize.execute({ mode: "apply", run_id: report.run_id, decisions: [{ action: "save", index: 0 }] }, exec);
|
|
115
|
+
const row = store.list({ limit: null })[0];
|
|
116
|
+
assert.equal(row.agent_scope, "me", "缺省吃会话身份");
|
|
117
|
+
assert.equal(row.agent_scope_source, "auto");
|
|
118
|
+
assert.equal(row.workspace_scope, "D:\\p");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("explicit scope arguments stamp as explicit and win over the session label", async () => {
|
|
122
|
+
const { store, byName } = setup({ organizeEnabled: true, scopeEnabled: true });
|
|
123
|
+
const exec = { agent: { session: { id: "s1", header: { agentPreset: "me", cwd: "D:\\p" } } } };
|
|
124
|
+
const report = await byName.memory_organize.execute(
|
|
125
|
+
{ mode: "dryRun", candidates: CANDIDATES, agent_scope: "other-agent" },
|
|
126
|
+
exec
|
|
127
|
+
);
|
|
128
|
+
await byName.memory_organize.execute({ mode: "apply", run_id: report.run_id, decisions: [{ action: "save", index: 0 }] }, exec);
|
|
129
|
+
const row = store.list({ limit: null })[0];
|
|
130
|
+
assert.equal(row.agent_scope, "other-agent", "显式参数盖在会话身份之上");
|
|
131
|
+
assert.equal(row.agent_scope_source, "explicit");
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("unknown mode is rejected", async () => {
|
|
135
|
+
const { byName } = setup({ organizeEnabled: true });
|
|
136
|
+
await assert.rejects(() => byName.memory_organize.execute({ mode: "force" }), /unknown mode/);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// #170 复核项 4 的口径延伸到整理接口的**两侧**:报告侧不得泄漏存在性,落地侧不得
|
|
140
|
+
// 绕过 scope 治理改库。用例形状是刻意挑的:比对键只看三列**值**(sensitivity/agent/
|
|
141
|
+
// workspace),可见性还多认一个 `explicit` 来源,所以要造出「按值该命中、但会话看不见」
|
|
142
|
+
// 那一格——匿名会话(解析不到 agentPreset)对 explicit 行 fail-closed。
|
|
143
|
+
// 报告侧少了过滤就是探测口:`agent_scope` 是模型自己给的参数,A 会话可以拿 B 的标题问
|
|
144
|
+
// 「那一档有没有这行」,拿回 id/title 就等于确认存在——memory_get 在同一条件下回「不存在」。
|
|
145
|
+
test("dryRun reports an invisible match as new, with no id or title", async () => {
|
|
146
|
+
const config = { organizeEnabled: true, scopeEnabled: true, strictScope: true };
|
|
147
|
+
const { store, byName } = setup(config);
|
|
148
|
+
store.save({
|
|
149
|
+
type: "project",
|
|
150
|
+
title: "发布只在包目录内",
|
|
151
|
+
content: "team-a 名下的旧行。",
|
|
152
|
+
agent_scope: "team-a",
|
|
153
|
+
agent_scope_source: "explicit",
|
|
154
|
+
workspace_scope: "D:\\p",
|
|
155
|
+
workspace_scope_source: "auto"
|
|
156
|
+
});
|
|
157
|
+
const exec = { agent: { session: { id: "s-anon", header: { cwd: "D:\\p" } } } };
|
|
158
|
+
const report = await byName.memory_organize.execute(
|
|
159
|
+
{
|
|
160
|
+
mode: "dryRun",
|
|
161
|
+
candidates: [{ type: "project", title: "发布只在包目录内", content: "换一种说法的同一件事。" }],
|
|
162
|
+
agent_scope: "team-a",
|
|
163
|
+
workspace_scope: "D:\\p"
|
|
164
|
+
},
|
|
165
|
+
exec
|
|
166
|
+
);
|
|
167
|
+
assert.equal(report.items[0].verdict, "new", "看不见的行按不存在处理 → 报告只能说「新条目」");
|
|
168
|
+
assert.equal(report.items[0].match, undefined, "不得带回落点 id/title/sim");
|
|
169
|
+
assert.equal(report.counts.new, 1);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// 反面对照:strictScope 是**可选**硬过滤,关掉它时那行本来就可读(A2 只降权)。少了这条,
|
|
173
|
+
// 过滤就变成「闸门关着也少召回」的第二重惩罚——修安全问题不许顺手改默认行为。
|
|
174
|
+
test("the same row is still reported as exact when strictScope is off", async () => {
|
|
175
|
+
const config = { organizeEnabled: true, scopeEnabled: true };
|
|
176
|
+
const { store, byName } = setup(config);
|
|
177
|
+
const row = store.save({
|
|
178
|
+
type: "project",
|
|
179
|
+
title: "发布只在包目录内",
|
|
180
|
+
content: "team-a 名下的旧行。",
|
|
181
|
+
agent_scope: "team-a",
|
|
182
|
+
agent_scope_source: "explicit",
|
|
183
|
+
workspace_scope: "D:\\p",
|
|
184
|
+
workspace_scope_source: "auto"
|
|
185
|
+
});
|
|
186
|
+
const exec = { agent: { session: { id: "s-anon", header: { cwd: "D:\\p" } } } };
|
|
187
|
+
const report = await byName.memory_organize.execute(
|
|
188
|
+
{
|
|
189
|
+
mode: "dryRun",
|
|
190
|
+
candidates: [{ type: "project", title: "发布只在包目录内", content: "换一种说法的同一件事。" }],
|
|
191
|
+
agent_scope: "team-a",
|
|
192
|
+
workspace_scope: "D:\\p"
|
|
193
|
+
},
|
|
194
|
+
exec
|
|
195
|
+
);
|
|
196
|
+
assert.equal(report.items[0].verdict, "exact");
|
|
197
|
+
assert.equal(report.items[0].match.id, row.id, "闸门关着时照常给出落点,否则比对报告失去意义");
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// 落地侧:报告已按「不存在」说了,archive 也不许真的动那一行(`opts.hiddenIds` 由可信
|
|
201
|
+
// 调用层算好传入,绝不取 payload 字段——那是调用方可自选的内容,不是授权)。
|
|
202
|
+
test("archive of a row the caller cannot see is skipped as out of scope", async () => {
|
|
203
|
+
const config = { organizeEnabled: true, scopeEnabled: true, strictScope: true };
|
|
204
|
+
const { store, byName } = setup(config);
|
|
205
|
+
const teamRow = store.save({
|
|
206
|
+
type: "project",
|
|
207
|
+
title: "发布只在包目录内",
|
|
208
|
+
content: "team-a 名下的旧行。",
|
|
209
|
+
agent_scope: "team-a",
|
|
210
|
+
agent_scope_source: "explicit",
|
|
211
|
+
workspace_scope: "D:\\p",
|
|
212
|
+
workspace_scope_source: "auto"
|
|
213
|
+
});
|
|
214
|
+
const exec = { agent: { session: { id: "s-anon", header: { cwd: "D:\\p" } } } };
|
|
215
|
+
const report = await byName.memory_organize.execute(
|
|
216
|
+
{
|
|
217
|
+
mode: "dryRun",
|
|
218
|
+
candidates: [{ type: "project", title: "发布只在包目录内", content: "换一种说法的同一件事。" }],
|
|
219
|
+
agent_scope: "team-a",
|
|
220
|
+
workspace_scope: "D:\\p"
|
|
221
|
+
},
|
|
222
|
+
exec
|
|
223
|
+
);
|
|
224
|
+
const applied = await byName.memory_organize.execute(
|
|
225
|
+
{ mode: "apply", run_id: report.run_id, decisions: [{ action: "archive", id: teamRow.id }] },
|
|
226
|
+
exec
|
|
227
|
+
);
|
|
228
|
+
assert.equal(applied.archived, 0, "看不见的行按不存在处理,不得归档");
|
|
229
|
+
assert.equal(applied.skipped.length, 1);
|
|
230
|
+
assert.match(applied.skipped[0].error, /out of scope/, "文案维持「unknown, archived or out of scope」:不泄漏存在性");
|
|
231
|
+
assert.equal(store.getById(teamRow.id).archived, false, "他人的行原样未动");
|
|
232
|
+
});
|