@modusensus/dsh-mneme 0.13.0 → 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 -828
- package/assets/icon.svg +3 -3
- package/bin/cli.mjs +964 -964
- package/bin/dsh-mneme-choro.mjs +262 -254
- 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 -402
- 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 -3394
- 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 -13436
- package/lib/commands.js +95 -95
- package/lib/config-keys.js +144 -144
- package/lib/config.js +1361 -1317
- 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 -907
- package/lib/dream/narratives.js +44 -44
- package/lib/dream/sleep.js +2027 -1887
- package/lib/dream/triage.js +139 -0
- package/lib/dream.js +1879 -1764
- 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 -107
- package/lib/image-describe.js +158 -0
- package/lib/index.js +852 -822
- package/lib/inject.js +656 -639
- 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 -584
- 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 -3196
- package/lib/session-gate.js +91 -91
- package/lib/session-usage.js +350 -350
- package/lib/settings.js +827 -802
- 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 -5662
- 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 -0
- 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 -474
- package/lib/wiki/render.js +261 -187
- package/lib/wiki/scan.js +371 -371
- package/lib/wiki/t0.js +500 -463
- package/lib/wiki/t1-jobs.js +232 -232
- package/lib/wiki/t1.js +609 -502
- package/lib/write-admission.js +404 -404
- package/locale/en.json +6 -6
- package/locale/zh.json +6 -6
- package/package.json +15 -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 -204
- package/scripts/release-notes.mjs +164 -161
- 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 -3394
- 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 -1317
- 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 -907
- package/src/dream/narratives.js +44 -44
- package/src/dream/sleep.js +2027 -1887
- package/src/dream/triage.js +139 -0
- package/src/dream.js +1879 -1764
- 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 -107
- package/src/image-describe.js +158 -0
- package/src/index.js +852 -822
- package/src/inject.js +656 -639
- 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 -584
- 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 -3196
- package/src/session-gate.js +91 -91
- package/src/session-usage.js +350 -350
- package/src/settings.js +827 -802
- 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 -5662
- 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 -0
- 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 -474
- package/src/wiki/render.js +261 -187
- package/src/wiki/scan.js +371 -371
- package/src/wiki/t0.js +500 -463
- package/src/wiki/t1-jobs.js +232 -232
- package/src/wiki/t1.js +609 -502
- 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 -2988
- 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 -4184
- 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 -0
- package/test/conflict-ledger.test.js +242 -0
- 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 -320
- 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 -0
- 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 -209
- 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 -211
- 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 -106
- 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 -494
- 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 -0
- package/test/panel-tokens.test.js +245 -0
- 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 -136
- package/test/release-notes.test.js +265 -240
- 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 -178
- 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 -1418
- 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 -627
- package/test/wiki-claims.test.js +194 -0
- 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 -0
- package/test/wiki-queries.test.js +398 -277
- package/test/wiki-scan.test.js +208 -208
- package/test/wiki-store.test.js +190 -190
- package/test/wiki-t0.test.js +456 -380
- package/test/wiki-t1-jobs.test.js +125 -125
- package/test/wiki-t1.test.js +460 -235
- package/test/wiki-tools.test.js +176 -176
- package/test/workflow-guards.test.js +155 -155
- package/test/write-admission.test.js +668 -668
package/test/mint-source.test.js
CHANGED
|
@@ -1,311 +1,311 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { createStore } from "../src/store.js";
|
|
4
|
-
import { createService } from "../src/service.js";
|
|
5
|
-
import { applyDecisions, validateDecisions } from "../src/dream/decisions.js";
|
|
6
|
-
import { runSleep } from "../src/dream/sleep.js";
|
|
7
|
-
import { createDreamScheduler } from "../src/dream.js";
|
|
8
|
-
|
|
9
|
-
// 机器 mint 的记忆必须带真 source。
|
|
10
|
-
//
|
|
11
|
-
// 背景(现场实测,2026-10-14):pattern 表的 144 行 source 全是 "manual",
|
|
12
|
-
// 而按 dream_runs 的 patterns.applied 逐轮求和恰好也是 144——它们全是 sleep 的
|
|
13
|
-
// phasePatterns mint 的,那个 "manual" 只是 saveWithDedupe 没拿到 source 时的
|
|
14
|
-
// 兜底值。于是「这类条目从哪来」在数据面上不可读,靠它做的判断(service.js 里
|
|
15
|
-
// 那条「pattern 只由手工写入」)也就跟着错了。
|
|
16
|
-
//
|
|
17
|
-
// 这组用例锁两件事:① 三条 mint 管道各自声明自己的来源;② 来源只能由调用方给,
|
|
18
|
-
// 模型写在决策对象上的 source 一律不算数——validateDecisions 不剥离未知字段,
|
|
19
|
-
// 若 applyCreate 信了 d.source,模型就能给自己的输出盖「人写的」戳。
|
|
20
|
-
|
|
21
|
-
function setup() {
|
|
22
|
-
const store = createStore(":memory:");
|
|
23
|
-
const service = createService({ store, mirror: null, config: {} });
|
|
24
|
-
return { store, service };
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function mint(service, extra = {}) {
|
|
28
|
-
return service
|
|
29
|
-
.saveWithDedupe({ type: "project", title: `铺垫${Math.random()}`, content: "给扫描窗垫一条普通记忆", importance: 3 })
|
|
30
|
-
.memory;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// ---------------------------------------------------------------- applyDecisions
|
|
34
|
-
|
|
35
|
-
test("mint source: applyDecisions stamps the caller's mintSource on create", () => {
|
|
36
|
-
const { store, service } = setup();
|
|
37
|
-
const { applied } = applyDecisions(
|
|
38
|
-
[{ action: "create", type: "pattern", title: "真模式", content: "从重复里抽出来的规律", importance: 3 }],
|
|
39
|
-
service,
|
|
40
|
-
null,
|
|
41
|
-
null,
|
|
42
|
-
{ mintSource: "sleep" }
|
|
43
|
-
);
|
|
44
|
-
assert.equal(applied, 1);
|
|
45
|
-
const row = service.all().find((m) => m.type === "pattern");
|
|
46
|
-
assert.equal(row.source, "sleep", "minted row carries the pipeline provenance");
|
|
47
|
-
store.close();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test("mint source: dream pipeline stamps 'dream'", () => {
|
|
51
|
-
const { store, service } = setup();
|
|
52
|
-
applyDecisions(
|
|
53
|
-
[{ action: "create", type: "pattern", title: "真模式", content: "规律", importance: 3 }],
|
|
54
|
-
service,
|
|
55
|
-
null,
|
|
56
|
-
null,
|
|
57
|
-
{ mintSource: "dream" }
|
|
58
|
-
);
|
|
59
|
-
const row = service.all().find((m) => m.type === "pattern");
|
|
60
|
-
assert.equal(row.source, "dream");
|
|
61
|
-
store.close();
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// 对抗条:来源取自调用方,不取自决策对象。模型自报的 source 必须被忽略——
|
|
65
|
-
// 否则「机器写的不冒充人写的」这条防线就形同虚设。
|
|
66
|
-
test("mint source: a source on the decision object is ignored, pipeline wins", () => {
|
|
67
|
-
const { store, service } = setup();
|
|
68
|
-
const decisions = [
|
|
69
|
-
{ action: "create", type: "pattern", title: "真模式", content: "规律", importance: 3, source: "manual" }
|
|
70
|
-
];
|
|
71
|
-
// 先证明威胁真实存在:这类决策能整个通过校验走到 applyCreate(校验不剥离未知
|
|
72
|
-
// 字段)。若哪天真加了剥离,这条会红——那时下面的对抗断言也就不再承重了。
|
|
73
|
-
const { ok } = validateDecisions(decisions, new Map(), { maxCreatePerRun: 3 });
|
|
74
|
-
assert.equal(ok, true, "a create carrying its own source still validates — that is the threat");
|
|
75
|
-
|
|
76
|
-
applyDecisions(decisions, service, null, null, { mintSource: "sleep" });
|
|
77
|
-
const row = service.all().find((m) => m.type === "pattern");
|
|
78
|
-
assert.equal(row.source, "sleep", "the model-authored source must not win");
|
|
79
|
-
store.close();
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// 反向:模型自报 source 而没有管道来源时,也不许它自己说了算——回落到兜底,
|
|
83
|
-
// 而不是让模型指哪打哪。
|
|
84
|
-
test("mint source: without a pipeline source the model-authored one still does not win", () => {
|
|
85
|
-
const { store, service } = setup();
|
|
86
|
-
applyDecisions(
|
|
87
|
-
[{ action: "create", type: "pattern", title: "真模式", content: "规律", importance: 3, source: "human" }],
|
|
88
|
-
service
|
|
89
|
-
);
|
|
90
|
-
const row = service.all().find((m) => m.type === "pattern");
|
|
91
|
-
assert.equal(row.source, "manual", "falls back to the existing default, not the model's claim");
|
|
92
|
-
store.close();
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
// 不传 mintSource 时行为与改前逐字一致(不放大行为面)。
|
|
96
|
-
test("mint source: absent mintSource keeps the previous fallback", () => {
|
|
97
|
-
const { store, service } = setup();
|
|
98
|
-
applyDecisions([{ action: "create", type: "pattern", title: "真模式", content: "规律", importance: 3 }], service);
|
|
99
|
-
const row = service.all().find((m) => m.type === "pattern");
|
|
100
|
-
assert.equal(row.source, "manual");
|
|
101
|
-
store.close();
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// 空白串按「没给」处理,不能写出 source="" 这种假装有来源的空值。
|
|
105
|
-
test("mint source: blank mintSource is treated as absent", () => {
|
|
106
|
-
const { store, service } = setup();
|
|
107
|
-
applyDecisions(
|
|
108
|
-
[{ action: "create", type: "pattern", title: "真模式", content: "规律", importance: 3 }],
|
|
109
|
-
service,
|
|
110
|
-
null,
|
|
111
|
-
null,
|
|
112
|
-
{ mintSource: " " }
|
|
113
|
-
);
|
|
114
|
-
const row = service.all().find((m) => m.type === "pattern");
|
|
115
|
-
assert.equal(row.source, "manual");
|
|
116
|
-
store.close();
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// ------------------------------------------------------------------ end to end
|
|
120
|
-
|
|
121
|
-
// sleep 的 pattern 相位(唯一的真实 mint 路径)端到端:断言落库行的 source。
|
|
122
|
-
// 不能靠等下一次做梦验收(要调度 + LLM 路由),所以在这里驱动相位。
|
|
123
|
-
function sleepCtx(decisionsJson) {
|
|
124
|
-
return {
|
|
125
|
-
logger: { warn: () => {}, info: () => {} },
|
|
126
|
-
agentDefaultModel: { currentSelection: () => ({ provider: "mock", model: "sleep-model" }) },
|
|
127
|
-
llm: {
|
|
128
|
-
async *stream(options) {
|
|
129
|
-
const userText = options.messages.find((m) => m.role === "user")?.content?.[0]?.text ?? "";
|
|
130
|
-
yield { type: "text-delta", index: 0, text: userText.includes("| type=") ? decisionsJson : "[]" };
|
|
131
|
-
yield { type: "finish", reason: { kind: "stop" } };
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
test("mint source: sleep pattern phase mints with source=sleep", async () => {
|
|
138
|
-
const { store, service } = setup();
|
|
139
|
-
mint(service);
|
|
140
|
-
mint(service);
|
|
141
|
-
const ctx = sleepCtx(
|
|
142
|
-
JSON.stringify([{ action: "create", type: "pattern", title: "真模式", content: "从 a 和 b 提取", importance: 3 }])
|
|
143
|
-
);
|
|
144
|
-
const config = {
|
|
145
|
-
sleepModeEnabled: true,
|
|
146
|
-
sleepPatternMinMemories: 10,
|
|
147
|
-
sleepMaxPatternPerRun: 3
|
|
148
|
-
};
|
|
149
|
-
const result = await runSleep(ctx, service, config, ctx.logger, null, null);
|
|
150
|
-
assert.equal(result.phases.patterns.status, "ok", "pattern phase minted");
|
|
151
|
-
|
|
152
|
-
const row = service.all().find((m) => m.type === "pattern");
|
|
153
|
-
assert.ok(row, "pattern minted");
|
|
154
|
-
assert.equal(row.source, "sleep", "the sleep phase declares its own provenance");
|
|
155
|
-
store.close();
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test("mint source: dream main chain mints with source=dream", async () => {
|
|
159
|
-
const { store, service } = setup();
|
|
160
|
-
const seed = service.saveWithDedupe({ type: "project", title: "旧条目", content: "第一段内容", importance: 3 }).memory;
|
|
161
|
-
let call = 0;
|
|
162
|
-
const ctx = {
|
|
163
|
-
logger: { warn: () => {}, info: () => {} },
|
|
164
|
-
agentDefaultModel: { currentSelection: () => ({ provider: "mock", model: "mock-model" }) },
|
|
165
|
-
llm: {
|
|
166
|
-
async *stream(options) {
|
|
167
|
-
call++;
|
|
168
|
-
const userText = options.messages.find((m) => m.role === "user")?.content?.[0]?.text ?? "";
|
|
169
|
-
const text = call === 1
|
|
170
|
-
? JSON.stringify([
|
|
171
|
-
{ action: "keep", ids: [seed.id] },
|
|
172
|
-
{ action: "create", type: "pattern", title: "主链路模式", content: "巩固时发现的规律", importance: 3 }
|
|
173
|
-
])
|
|
174
|
-
: "记忆库总览摘要文本";
|
|
175
|
-
void userText;
|
|
176
|
-
yield { type: "text-delta", text };
|
|
177
|
-
yield { type: "finish", reason: { kind: "ok" } };
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
const dream = createDreamScheduler({ thresholdCount: 1, thresholdChars: 0, delayMs: 0 });
|
|
182
|
-
const result = await dream.runDream(ctx, service, { dreamProvider: "mock", dreamModel: "mock-model" });
|
|
183
|
-
assert.equal(result.ok, true);
|
|
184
|
-
|
|
185
|
-
const row = service.all().find((m) => m.type === "pattern");
|
|
186
|
-
assert.ok(row, "the create decision minted a row");
|
|
187
|
-
assert.equal(row.source, "dream");
|
|
188
|
-
store.close();
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
// 验收口径本身:全表分组统计随之可读——同一次运行 mint 的条目能按来源数出来。
|
|
192
|
-
test("mint source: rows are countable by source after minting", () => {
|
|
193
|
-
const { store, service } = setup();
|
|
194
|
-
applyDecisions([{ action: "create", type: "pattern", title: "甲", content: "规律甲", importance: 3 }], service, null, null, { mintSource: "sleep" });
|
|
195
|
-
applyDecisions([{ action: "create", type: "pattern", title: "乙", content: "规律乙", importance: 3 }], service, null, null, { mintSource: "dream" });
|
|
196
|
-
const bySource = new Map();
|
|
197
|
-
for (const m of service.all()) bySource.set(m.source, (bySource.get(m.source) ?? 0) + 1);
|
|
198
|
-
assert.equal(bySource.get("sleep"), 1);
|
|
199
|
-
assert.equal(bySource.get("dream"), 1);
|
|
200
|
-
assert.equal(bySource.get("manual"), undefined, "nothing minted here fell back to the default");
|
|
201
|
-
store.close();
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
// ── Issue #512:铸造出来的记忆要能追到「哪一轮」 ──
|
|
205
|
-
//
|
|
206
|
-
// source 只说「哪条管道」,不说「哪一次运行」。同一管道跑过几百轮之后,
|
|
207
|
-
// 「这条 pattern 是哪一轮抽出来的」在数据面上仍然不可读——这正是 #512 要补的。
|
|
208
|
-
// 归因落在 memory_mints:dream/sleep 铸造的记忆没有会话区间(session/seq 都不存在),
|
|
209
|
-
// 硬塞合成区间就是编的,所以窗口级归因(memory_provenance)与行级归因(本表)分层。
|
|
210
|
-
|
|
211
|
-
test("issue#512: a created row remembers which run minted it", () => {
|
|
212
|
-
const { store, service } = setup();
|
|
213
|
-
applyDecisions(
|
|
214
|
-
[{ action: "create", type: "pattern", title: "真模式", content: "规律", importance: 3 }],
|
|
215
|
-
service,
|
|
216
|
-
null,
|
|
217
|
-
null,
|
|
218
|
-
{ mintSource: "dream", runId: "run-abc" }
|
|
219
|
-
);
|
|
220
|
-
const row = service.all().find((m) => m.type === "pattern");
|
|
221
|
-
assert.ok(row, "pattern minted");
|
|
222
|
-
const mints = store.mintsFor(row.id);
|
|
223
|
-
assert.equal(mints.length, 1, "one created row = one mint record");
|
|
224
|
-
assert.equal(mints[0].run_id, "run-abc");
|
|
225
|
-
assert.equal(mints[0].run_type, "dream");
|
|
226
|
-
assert.equal(mints[0].trigger_source, "autoDream");
|
|
227
|
-
store.close();
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
// 没有 run id 时什么都不写。旧装配(或直接调 applyDecisions 的调用方)没有 run 概念,
|
|
231
|
-
// 这时候编一个 id 出来比留空更坏:它会让「能追到」变成一句谎话。
|
|
232
|
-
test("issue#512: without a run id no mint record is fabricated", () => {
|
|
233
|
-
const { store, service } = setup();
|
|
234
|
-
applyDecisions(
|
|
235
|
-
[{ action: "create", type: "pattern", title: "无轮模式", content: "规律", importance: 3 }],
|
|
236
|
-
service,
|
|
237
|
-
null,
|
|
238
|
-
null,
|
|
239
|
-
{ mintSource: "dream" }
|
|
240
|
-
);
|
|
241
|
-
const row = service.all().find((m) => m.type === "pattern");
|
|
242
|
-
assert.ok(row, "pattern still minted — 记账缺失不该拦铸造");
|
|
243
|
-
assert.deepEqual(store.mintsFor(row.id), []);
|
|
244
|
-
store.close();
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
// 只记 create。merge/conflict/update/supersede 动的是既有行,receipt_chain 已按
|
|
248
|
-
// (run_id, record_id) 记过一遍;再造一份就是第二套账,两边迟早对不上。
|
|
249
|
-
test("issue#512: only creation is recorded — edits to existing rows stay in receipt_chain", () => {
|
|
250
|
-
const { store, service } = setup();
|
|
251
|
-
const existing = service.saveWithDedupe({ type: "project", title: "既有行", content: "旧内容", importance: 3 }).memory;
|
|
252
|
-
applyDecisions(
|
|
253
|
-
[{ action: "update", ids: [existing.id], content: "新内容", importance: 4 }],
|
|
254
|
-
service,
|
|
255
|
-
null,
|
|
256
|
-
null,
|
|
257
|
-
{ mintSource: "dream", runId: "run-upd" }
|
|
258
|
-
);
|
|
259
|
-
assert.deepEqual(store.mintsFor(existing.id), [], "update 不是铸造,不进 memory_mints");
|
|
260
|
-
store.close();
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
// #619 / Ephor 第七轮 ③:原地刷新不是出生。同一个 pattern 跑两轮,第一轮真铸了、
|
|
264
|
-
// 第二轮只是把同一行重写;memory_mints 的语义是「这条记忆出生自哪一轮」,第二行
|
|
265
|
-
// 就是「同一条记忆出生过两次」——面板上会显示两条出生记录(mintsFor 由
|
|
266
|
-
// provenance-http.js 读)。live 库当时还没显形,因为同题刷新刚上线。
|
|
267
|
-
test("issue#619r: a refreshed pattern does not record a second birth", () => {
|
|
268
|
-
const { store, service } = setup();
|
|
269
|
-
const decision = [{ action: "create", type: "pattern", title: "同题规律", content: "第一轮", importance: 3 }];
|
|
270
|
-
const first = applyDecisions(decision, service, null, null, { mintSource: "sleep", runId: "run-a" });
|
|
271
|
-
assert.equal(first.applied, 1, "第一轮真铸了");
|
|
272
|
-
const row = service.all().find((m) => m.type === "pattern");
|
|
273
|
-
assert.equal(store.mintsFor(row.id).length, 1);
|
|
274
|
-
|
|
275
|
-
const second = applyDecisions(
|
|
276
|
-
[{ action: "create", type: "pattern", title: "同题规律", content: "第二轮", importance: 3 }],
|
|
277
|
-
service,
|
|
278
|
-
null,
|
|
279
|
-
null,
|
|
280
|
-
{ mintSource: "sleep", runId: "run-b" }
|
|
281
|
-
);
|
|
282
|
-
assert.equal(second.applied, 0, "第二轮没有新铸");
|
|
283
|
-
assert.equal(second.merged, 1, "它刷新了一条");
|
|
284
|
-
assert.equal(second.committed[0].action, "create_merged");
|
|
285
|
-
assert.equal(store.mintsFor(row.id).length, 1, "刷新不算再一次出生");
|
|
286
|
-
store.close();
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
// 端到端:sleep 真的跑一轮,铸造出来的行要指回那一轮的 runId(不是随便一个 id)。
|
|
290
|
-
test("issue#512: sleep mints point back at the run that produced them", async () => {
|
|
291
|
-
const { store, service } = setup();
|
|
292
|
-
mint(service);
|
|
293
|
-
mint(service);
|
|
294
|
-
const ctx = sleepCtx(
|
|
295
|
-
JSON.stringify([{ action: "create", type: "pattern", title: "真模式", content: "从 a 和 b 提取", importance: 3 }])
|
|
296
|
-
);
|
|
297
|
-
const config = { sleepModeEnabled: true, sleepPatternMinMemories: 10, sleepMaxPatternPerRun: 3 };
|
|
298
|
-
const result = await runSleep(ctx, service, config, ctx.logger, null, null);
|
|
299
|
-
assert.equal(result.phases.patterns.status, "ok", "pattern phase minted");
|
|
300
|
-
|
|
301
|
-
const row = service.all().find((m) => m.type === "pattern");
|
|
302
|
-
assert.ok(row, "pattern minted");
|
|
303
|
-
const mints = store.mintsFor(row.id);
|
|
304
|
-
assert.equal(mints.length, 1);
|
|
305
|
-
assert.equal(mints[0].run_id, result.runId, "归因要指回这一轮的 runId,不是另编一个");
|
|
306
|
-
assert.equal(mints[0].run_type, "sleep");
|
|
307
|
-
assert.equal(mints[0].trigger_source, "sleep");
|
|
308
|
-
// 那一轮 run 台账本身也在:两边能对上,归因才成立。
|
|
309
|
-
assert.equal(store.getDreamRun(result.runId).run_type, "sleep");
|
|
310
|
-
store.close();
|
|
311
|
-
});
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { createStore } from "../src/store.js";
|
|
4
|
+
import { createService } from "../src/service.js";
|
|
5
|
+
import { applyDecisions, validateDecisions } from "../src/dream/decisions.js";
|
|
6
|
+
import { runSleep } from "../src/dream/sleep.js";
|
|
7
|
+
import { createDreamScheduler } from "../src/dream.js";
|
|
8
|
+
|
|
9
|
+
// 机器 mint 的记忆必须带真 source。
|
|
10
|
+
//
|
|
11
|
+
// 背景(现场实测,2026-10-14):pattern 表的 144 行 source 全是 "manual",
|
|
12
|
+
// 而按 dream_runs 的 patterns.applied 逐轮求和恰好也是 144——它们全是 sleep 的
|
|
13
|
+
// phasePatterns mint 的,那个 "manual" 只是 saveWithDedupe 没拿到 source 时的
|
|
14
|
+
// 兜底值。于是「这类条目从哪来」在数据面上不可读,靠它做的判断(service.js 里
|
|
15
|
+
// 那条「pattern 只由手工写入」)也就跟着错了。
|
|
16
|
+
//
|
|
17
|
+
// 这组用例锁两件事:① 三条 mint 管道各自声明自己的来源;② 来源只能由调用方给,
|
|
18
|
+
// 模型写在决策对象上的 source 一律不算数——validateDecisions 不剥离未知字段,
|
|
19
|
+
// 若 applyCreate 信了 d.source,模型就能给自己的输出盖「人写的」戳。
|
|
20
|
+
|
|
21
|
+
function setup() {
|
|
22
|
+
const store = createStore(":memory:");
|
|
23
|
+
const service = createService({ store, mirror: null, config: {} });
|
|
24
|
+
return { store, service };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function mint(service, extra = {}) {
|
|
28
|
+
return service
|
|
29
|
+
.saveWithDedupe({ type: "project", title: `铺垫${Math.random()}`, content: "给扫描窗垫一条普通记忆", importance: 3 })
|
|
30
|
+
.memory;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ---------------------------------------------------------------- applyDecisions
|
|
34
|
+
|
|
35
|
+
test("mint source: applyDecisions stamps the caller's mintSource on create", () => {
|
|
36
|
+
const { store, service } = setup();
|
|
37
|
+
const { applied } = applyDecisions(
|
|
38
|
+
[{ action: "create", type: "pattern", title: "真模式", content: "从重复里抽出来的规律", importance: 3 }],
|
|
39
|
+
service,
|
|
40
|
+
null,
|
|
41
|
+
null,
|
|
42
|
+
{ mintSource: "sleep" }
|
|
43
|
+
);
|
|
44
|
+
assert.equal(applied, 1);
|
|
45
|
+
const row = service.all().find((m) => m.type === "pattern");
|
|
46
|
+
assert.equal(row.source, "sleep", "minted row carries the pipeline provenance");
|
|
47
|
+
store.close();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("mint source: dream pipeline stamps 'dream'", () => {
|
|
51
|
+
const { store, service } = setup();
|
|
52
|
+
applyDecisions(
|
|
53
|
+
[{ action: "create", type: "pattern", title: "真模式", content: "规律", importance: 3 }],
|
|
54
|
+
service,
|
|
55
|
+
null,
|
|
56
|
+
null,
|
|
57
|
+
{ mintSource: "dream" }
|
|
58
|
+
);
|
|
59
|
+
const row = service.all().find((m) => m.type === "pattern");
|
|
60
|
+
assert.equal(row.source, "dream");
|
|
61
|
+
store.close();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// 对抗条:来源取自调用方,不取自决策对象。模型自报的 source 必须被忽略——
|
|
65
|
+
// 否则「机器写的不冒充人写的」这条防线就形同虚设。
|
|
66
|
+
test("mint source: a source on the decision object is ignored, pipeline wins", () => {
|
|
67
|
+
const { store, service } = setup();
|
|
68
|
+
const decisions = [
|
|
69
|
+
{ action: "create", type: "pattern", title: "真模式", content: "规律", importance: 3, source: "manual" }
|
|
70
|
+
];
|
|
71
|
+
// 先证明威胁真实存在:这类决策能整个通过校验走到 applyCreate(校验不剥离未知
|
|
72
|
+
// 字段)。若哪天真加了剥离,这条会红——那时下面的对抗断言也就不再承重了。
|
|
73
|
+
const { ok } = validateDecisions(decisions, new Map(), { maxCreatePerRun: 3 });
|
|
74
|
+
assert.equal(ok, true, "a create carrying its own source still validates — that is the threat");
|
|
75
|
+
|
|
76
|
+
applyDecisions(decisions, service, null, null, { mintSource: "sleep" });
|
|
77
|
+
const row = service.all().find((m) => m.type === "pattern");
|
|
78
|
+
assert.equal(row.source, "sleep", "the model-authored source must not win");
|
|
79
|
+
store.close();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// 反向:模型自报 source 而没有管道来源时,也不许它自己说了算——回落到兜底,
|
|
83
|
+
// 而不是让模型指哪打哪。
|
|
84
|
+
test("mint source: without a pipeline source the model-authored one still does not win", () => {
|
|
85
|
+
const { store, service } = setup();
|
|
86
|
+
applyDecisions(
|
|
87
|
+
[{ action: "create", type: "pattern", title: "真模式", content: "规律", importance: 3, source: "human" }],
|
|
88
|
+
service
|
|
89
|
+
);
|
|
90
|
+
const row = service.all().find((m) => m.type === "pattern");
|
|
91
|
+
assert.equal(row.source, "manual", "falls back to the existing default, not the model's claim");
|
|
92
|
+
store.close();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// 不传 mintSource 时行为与改前逐字一致(不放大行为面)。
|
|
96
|
+
test("mint source: absent mintSource keeps the previous fallback", () => {
|
|
97
|
+
const { store, service } = setup();
|
|
98
|
+
applyDecisions([{ action: "create", type: "pattern", title: "真模式", content: "规律", importance: 3 }], service);
|
|
99
|
+
const row = service.all().find((m) => m.type === "pattern");
|
|
100
|
+
assert.equal(row.source, "manual");
|
|
101
|
+
store.close();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// 空白串按「没给」处理,不能写出 source="" 这种假装有来源的空值。
|
|
105
|
+
test("mint source: blank mintSource is treated as absent", () => {
|
|
106
|
+
const { store, service } = setup();
|
|
107
|
+
applyDecisions(
|
|
108
|
+
[{ action: "create", type: "pattern", title: "真模式", content: "规律", importance: 3 }],
|
|
109
|
+
service,
|
|
110
|
+
null,
|
|
111
|
+
null,
|
|
112
|
+
{ mintSource: " " }
|
|
113
|
+
);
|
|
114
|
+
const row = service.all().find((m) => m.type === "pattern");
|
|
115
|
+
assert.equal(row.source, "manual");
|
|
116
|
+
store.close();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// ------------------------------------------------------------------ end to end
|
|
120
|
+
|
|
121
|
+
// sleep 的 pattern 相位(唯一的真实 mint 路径)端到端:断言落库行的 source。
|
|
122
|
+
// 不能靠等下一次做梦验收(要调度 + LLM 路由),所以在这里驱动相位。
|
|
123
|
+
function sleepCtx(decisionsJson) {
|
|
124
|
+
return {
|
|
125
|
+
logger: { warn: () => {}, info: () => {} },
|
|
126
|
+
agentDefaultModel: { currentSelection: () => ({ provider: "mock", model: "sleep-model" }) },
|
|
127
|
+
llm: {
|
|
128
|
+
async *stream(options) {
|
|
129
|
+
const userText = options.messages.find((m) => m.role === "user")?.content?.[0]?.text ?? "";
|
|
130
|
+
yield { type: "text-delta", index: 0, text: userText.includes("| type=") ? decisionsJson : "[]" };
|
|
131
|
+
yield { type: "finish", reason: { kind: "stop" } };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
test("mint source: sleep pattern phase mints with source=sleep", async () => {
|
|
138
|
+
const { store, service } = setup();
|
|
139
|
+
mint(service);
|
|
140
|
+
mint(service);
|
|
141
|
+
const ctx = sleepCtx(
|
|
142
|
+
JSON.stringify([{ action: "create", type: "pattern", title: "真模式", content: "从 a 和 b 提取", importance: 3 }])
|
|
143
|
+
);
|
|
144
|
+
const config = {
|
|
145
|
+
sleepModeEnabled: true,
|
|
146
|
+
sleepPatternMinMemories: 10,
|
|
147
|
+
sleepMaxPatternPerRun: 3
|
|
148
|
+
};
|
|
149
|
+
const result = await runSleep(ctx, service, config, ctx.logger, null, null);
|
|
150
|
+
assert.equal(result.phases.patterns.status, "ok", "pattern phase minted");
|
|
151
|
+
|
|
152
|
+
const row = service.all().find((m) => m.type === "pattern");
|
|
153
|
+
assert.ok(row, "pattern minted");
|
|
154
|
+
assert.equal(row.source, "sleep", "the sleep phase declares its own provenance");
|
|
155
|
+
store.close();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("mint source: dream main chain mints with source=dream", async () => {
|
|
159
|
+
const { store, service } = setup();
|
|
160
|
+
const seed = service.saveWithDedupe({ type: "project", title: "旧条目", content: "第一段内容", importance: 3 }).memory;
|
|
161
|
+
let call = 0;
|
|
162
|
+
const ctx = {
|
|
163
|
+
logger: { warn: () => {}, info: () => {} },
|
|
164
|
+
agentDefaultModel: { currentSelection: () => ({ provider: "mock", model: "mock-model" }) },
|
|
165
|
+
llm: {
|
|
166
|
+
async *stream(options) {
|
|
167
|
+
call++;
|
|
168
|
+
const userText = options.messages.find((m) => m.role === "user")?.content?.[0]?.text ?? "";
|
|
169
|
+
const text = call === 1
|
|
170
|
+
? JSON.stringify([
|
|
171
|
+
{ action: "keep", ids: [seed.id] },
|
|
172
|
+
{ action: "create", type: "pattern", title: "主链路模式", content: "巩固时发现的规律", importance: 3 }
|
|
173
|
+
])
|
|
174
|
+
: "记忆库总览摘要文本";
|
|
175
|
+
void userText;
|
|
176
|
+
yield { type: "text-delta", text };
|
|
177
|
+
yield { type: "finish", reason: { kind: "ok" } };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
const dream = createDreamScheduler({ thresholdCount: 1, thresholdChars: 0, delayMs: 0 });
|
|
182
|
+
const result = await dream.runDream(ctx, service, { dreamProvider: "mock", dreamModel: "mock-model" });
|
|
183
|
+
assert.equal(result.ok, true);
|
|
184
|
+
|
|
185
|
+
const row = service.all().find((m) => m.type === "pattern");
|
|
186
|
+
assert.ok(row, "the create decision minted a row");
|
|
187
|
+
assert.equal(row.source, "dream");
|
|
188
|
+
store.close();
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// 验收口径本身:全表分组统计随之可读——同一次运行 mint 的条目能按来源数出来。
|
|
192
|
+
test("mint source: rows are countable by source after minting", () => {
|
|
193
|
+
const { store, service } = setup();
|
|
194
|
+
applyDecisions([{ action: "create", type: "pattern", title: "甲", content: "规律甲", importance: 3 }], service, null, null, { mintSource: "sleep" });
|
|
195
|
+
applyDecisions([{ action: "create", type: "pattern", title: "乙", content: "规律乙", importance: 3 }], service, null, null, { mintSource: "dream" });
|
|
196
|
+
const bySource = new Map();
|
|
197
|
+
for (const m of service.all()) bySource.set(m.source, (bySource.get(m.source) ?? 0) + 1);
|
|
198
|
+
assert.equal(bySource.get("sleep"), 1);
|
|
199
|
+
assert.equal(bySource.get("dream"), 1);
|
|
200
|
+
assert.equal(bySource.get("manual"), undefined, "nothing minted here fell back to the default");
|
|
201
|
+
store.close();
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// ── Issue #512:铸造出来的记忆要能追到「哪一轮」 ──
|
|
205
|
+
//
|
|
206
|
+
// source 只说「哪条管道」,不说「哪一次运行」。同一管道跑过几百轮之后,
|
|
207
|
+
// 「这条 pattern 是哪一轮抽出来的」在数据面上仍然不可读——这正是 #512 要补的。
|
|
208
|
+
// 归因落在 memory_mints:dream/sleep 铸造的记忆没有会话区间(session/seq 都不存在),
|
|
209
|
+
// 硬塞合成区间就是编的,所以窗口级归因(memory_provenance)与行级归因(本表)分层。
|
|
210
|
+
|
|
211
|
+
test("issue#512: a created row remembers which run minted it", () => {
|
|
212
|
+
const { store, service } = setup();
|
|
213
|
+
applyDecisions(
|
|
214
|
+
[{ action: "create", type: "pattern", title: "真模式", content: "规律", importance: 3 }],
|
|
215
|
+
service,
|
|
216
|
+
null,
|
|
217
|
+
null,
|
|
218
|
+
{ mintSource: "dream", runId: "run-abc" }
|
|
219
|
+
);
|
|
220
|
+
const row = service.all().find((m) => m.type === "pattern");
|
|
221
|
+
assert.ok(row, "pattern minted");
|
|
222
|
+
const mints = store.mintsFor(row.id);
|
|
223
|
+
assert.equal(mints.length, 1, "one created row = one mint record");
|
|
224
|
+
assert.equal(mints[0].run_id, "run-abc");
|
|
225
|
+
assert.equal(mints[0].run_type, "dream");
|
|
226
|
+
assert.equal(mints[0].trigger_source, "autoDream");
|
|
227
|
+
store.close();
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// 没有 run id 时什么都不写。旧装配(或直接调 applyDecisions 的调用方)没有 run 概念,
|
|
231
|
+
// 这时候编一个 id 出来比留空更坏:它会让「能追到」变成一句谎话。
|
|
232
|
+
test("issue#512: without a run id no mint record is fabricated", () => {
|
|
233
|
+
const { store, service } = setup();
|
|
234
|
+
applyDecisions(
|
|
235
|
+
[{ action: "create", type: "pattern", title: "无轮模式", content: "规律", importance: 3 }],
|
|
236
|
+
service,
|
|
237
|
+
null,
|
|
238
|
+
null,
|
|
239
|
+
{ mintSource: "dream" }
|
|
240
|
+
);
|
|
241
|
+
const row = service.all().find((m) => m.type === "pattern");
|
|
242
|
+
assert.ok(row, "pattern still minted — 记账缺失不该拦铸造");
|
|
243
|
+
assert.deepEqual(store.mintsFor(row.id), []);
|
|
244
|
+
store.close();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// 只记 create。merge/conflict/update/supersede 动的是既有行,receipt_chain 已按
|
|
248
|
+
// (run_id, record_id) 记过一遍;再造一份就是第二套账,两边迟早对不上。
|
|
249
|
+
test("issue#512: only creation is recorded — edits to existing rows stay in receipt_chain", () => {
|
|
250
|
+
const { store, service } = setup();
|
|
251
|
+
const existing = service.saveWithDedupe({ type: "project", title: "既有行", content: "旧内容", importance: 3 }).memory;
|
|
252
|
+
applyDecisions(
|
|
253
|
+
[{ action: "update", ids: [existing.id], content: "新内容", importance: 4 }],
|
|
254
|
+
service,
|
|
255
|
+
null,
|
|
256
|
+
null,
|
|
257
|
+
{ mintSource: "dream", runId: "run-upd" }
|
|
258
|
+
);
|
|
259
|
+
assert.deepEqual(store.mintsFor(existing.id), [], "update 不是铸造,不进 memory_mints");
|
|
260
|
+
store.close();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// #619 / Ephor 第七轮 ③:原地刷新不是出生。同一个 pattern 跑两轮,第一轮真铸了、
|
|
264
|
+
// 第二轮只是把同一行重写;memory_mints 的语义是「这条记忆出生自哪一轮」,第二行
|
|
265
|
+
// 就是「同一条记忆出生过两次」——面板上会显示两条出生记录(mintsFor 由
|
|
266
|
+
// provenance-http.js 读)。live 库当时还没显形,因为同题刷新刚上线。
|
|
267
|
+
test("issue#619r: a refreshed pattern does not record a second birth", () => {
|
|
268
|
+
const { store, service } = setup();
|
|
269
|
+
const decision = [{ action: "create", type: "pattern", title: "同题规律", content: "第一轮", importance: 3 }];
|
|
270
|
+
const first = applyDecisions(decision, service, null, null, { mintSource: "sleep", runId: "run-a" });
|
|
271
|
+
assert.equal(first.applied, 1, "第一轮真铸了");
|
|
272
|
+
const row = service.all().find((m) => m.type === "pattern");
|
|
273
|
+
assert.equal(store.mintsFor(row.id).length, 1);
|
|
274
|
+
|
|
275
|
+
const second = applyDecisions(
|
|
276
|
+
[{ action: "create", type: "pattern", title: "同题规律", content: "第二轮", importance: 3 }],
|
|
277
|
+
service,
|
|
278
|
+
null,
|
|
279
|
+
null,
|
|
280
|
+
{ mintSource: "sleep", runId: "run-b" }
|
|
281
|
+
);
|
|
282
|
+
assert.equal(second.applied, 0, "第二轮没有新铸");
|
|
283
|
+
assert.equal(second.merged, 1, "它刷新了一条");
|
|
284
|
+
assert.equal(second.committed[0].action, "create_merged");
|
|
285
|
+
assert.equal(store.mintsFor(row.id).length, 1, "刷新不算再一次出生");
|
|
286
|
+
store.close();
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// 端到端:sleep 真的跑一轮,铸造出来的行要指回那一轮的 runId(不是随便一个 id)。
|
|
290
|
+
test("issue#512: sleep mints point back at the run that produced them", async () => {
|
|
291
|
+
const { store, service } = setup();
|
|
292
|
+
mint(service);
|
|
293
|
+
mint(service);
|
|
294
|
+
const ctx = sleepCtx(
|
|
295
|
+
JSON.stringify([{ action: "create", type: "pattern", title: "真模式", content: "从 a 和 b 提取", importance: 3 }])
|
|
296
|
+
);
|
|
297
|
+
const config = { sleepModeEnabled: true, sleepPatternMinMemories: 10, sleepMaxPatternPerRun: 3 };
|
|
298
|
+
const result = await runSleep(ctx, service, config, ctx.logger, null, null);
|
|
299
|
+
assert.equal(result.phases.patterns.status, "ok", "pattern phase minted");
|
|
300
|
+
|
|
301
|
+
const row = service.all().find((m) => m.type === "pattern");
|
|
302
|
+
assert.ok(row, "pattern minted");
|
|
303
|
+
const mints = store.mintsFor(row.id);
|
|
304
|
+
assert.equal(mints.length, 1);
|
|
305
|
+
assert.equal(mints[0].run_id, result.runId, "归因要指回这一轮的 runId,不是另编一个");
|
|
306
|
+
assert.equal(mints[0].run_type, "sleep");
|
|
307
|
+
assert.equal(mints[0].trigger_source, "sleep");
|
|
308
|
+
// 那一轮 run 台账本身也在:两边能对上,归因才成立。
|
|
309
|
+
assert.equal(store.getDreamRun(result.runId).run_type, "sleep");
|
|
310
|
+
store.close();
|
|
311
|
+
});
|