@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,178 +1,178 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 把 shell 观察压成**人能扫的「业务动作」清单**。
|
|
3
|
-
*
|
|
4
|
-
* ## 为什么需要这一层(三组实测逼出来的)
|
|
5
|
-
*
|
|
6
|
-
* 1. 拿单条命令去匹配手写步骤表,命中率只有 14.2~15.2%(非发版会话 4.4%,
|
|
7
|
-
* 区分力仅 3 倍)→ **拿清单套行为这条路走不通**。
|
|
8
|
-
* 2. 想用「整段命令」当分组键:每个会话中位 **539 组**、最多 7373 组
|
|
9
|
-
* → 文献那套「聚类 + 人命名」直接照搬也不成立(网页活动本来只有几十个页面)。
|
|
10
|
-
* 3. 换「动词」当键:密度最高的全是 **PowerShell 管道语法**
|
|
11
|
-
* (`write-output` 10619、`select-object` 10422、`}` 4864…)
|
|
12
|
-
* → **「命令 ≈ 动作」这个预设是错的**:大部分"命令"不是活动,是句子成分。
|
|
13
|
-
* 4. 只留业务命令(git/gh/npm/node/docker…)后:业务段占 **6.5%**,
|
|
14
|
-
* 不同动词 **8 个**、不同前两词组 **1010 个** —— 这才是人能扫的量级。
|
|
15
|
-
*
|
|
16
|
-
* ## 这个模块的产出:一份「本次窗口观察到什么」清单
|
|
17
|
-
*
|
|
18
|
-
* 形态:`git status ×12`、`gh pr ×5`、`npm test ×3`。
|
|
19
|
-
* **不猜它对应哪一步**——那件事交给人(见 mneme-research 的 09 号文档)。
|
|
20
|
-
*
|
|
21
|
-
* ## 🔴 隐私:为什么只输出「动词 + 子命令」
|
|
22
|
-
*
|
|
23
|
-
* 完整命令行里**几乎必然含绝对路径**,而路径里含本机用户名。例如实测里真实出现过
|
|
24
|
-
* `set-location "c:\users\<用户名>\desktop\..."`。这条回执是要显示在界面上、
|
|
25
|
-
* 可能被截图的那一面——所以本模块有一条硬规则:
|
|
26
|
-
*
|
|
27
|
-
* > **位置参数一律丢弃,只保留动词、子命令与 `-` 开头的旗标。**
|
|
28
|
-
*
|
|
29
|
-
* 旗标是语义(`--rebase` / `--force` / `-m`),位置参数是数据(路径、文件名、id)。
|
|
30
|
-
* 只留前者,清单既表意又不泄露。这不是"顺手过滤",是这一层存在的第二个理由。
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* 业务命令的动词白名单。
|
|
35
|
-
*
|
|
36
|
-
* 判据不是"常见",而是"**它的执行会构成工作流的一步**"——即它有语义
|
|
37
|
-
* (改仓库状态、发版、跑测试),而不是在组装文本(`write-output`、`foreach-object`)。
|
|
38
|
-
*
|
|
39
|
-
* 这张名单是**拍的**(实测里 6.5% 的段落在名单内),未验证覆盖率:
|
|
40
|
-
* 可能有业务动作用了别的工具(`python`、`curl`、`cargo`)。认不出来不产清单项,
|
|
41
|
-
* 是安全的方向——它只会让清单更短,不会让它更假。
|
|
42
|
-
*/
|
|
43
|
-
const BUSINESS_VERBS = new Set([
|
|
44
|
-
// 实测 21723 次调用里,真正命中的只有这四个:git / gh / npm / node。
|
|
45
|
-
// 其余先不收——认不出来只会让清单更短,不会让它更假;
|
|
46
|
-
// 等真有项目用上了再加(这一版刻意不做"猜未来会用到"的预留)。
|
|
47
|
-
"git", "gh", "npm", "npx", "node", "docker"
|
|
48
|
-
]);
|
|
49
|
-
|
|
50
|
-
/** 命令分隔符:与 pipeline-attribution 同一口径(只认两侧带空白的)。 */
|
|
51
|
-
const SEPARATOR_RE = /\s*(?:;|&&|\|\||\|)\s*|\n/u;
|
|
52
|
-
|
|
53
|
-
/** 重定向尾巴(`2>&1`、`> file`、`2>nul`):不是命令的一部分。 */
|
|
54
|
-
const REDIRECT_RE = /\s*\d?>\s*&?\s*\S+/gu;
|
|
55
|
-
|
|
56
|
-
/** `cd <路径>`:前导定位语句,不是活动。 */
|
|
57
|
-
const CD_RE = /^cd\s/iu;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* 这个 token 像不像一个**子命令**。
|
|
61
|
-
*
|
|
62
|
-
* 必须做这道校验,否则三件事都会发生(都是端到端实测抓到的):
|
|
63
|
-
* 1. `node d:\dsh\...\probe.mjs` → 把**脚本路径**当成 sub,路径里的用户名被带出去;
|
|
64
|
-
* 2. `git -C $(Join-Path ...) log --oneline` → 把 `$(Join-Path` 当成 sub,清单里出现
|
|
65
|
-
* `git (join-path -C --oneline` 这种读不懂的东西;
|
|
66
|
-
* 3. `node x.test.js` → **带点的文件名**被当成 sub(`x.test.js` 完全符合"小写字母起头
|
|
67
|
-
* 的短词")。这条是加完前两条修复后复验时才冒出来的。
|
|
68
|
-
*
|
|
69
|
-
* 所以除了字符集,还要**排除含点的 token**:子命令带点是极罕见的
|
|
70
|
-
* (`git log` / `gh pr` / `npm test` / `kubectl get` 都不带),而文件名几乎都带。
|
|
71
|
-
* 宁可漏认一个,不可把文件名当子命令——后者会出现在给人看的清单里。
|
|
72
|
-
*/
|
|
73
|
-
function looksLikeSubcommand(token) {
|
|
74
|
-
if (typeof token !== "string") return false;
|
|
75
|
-
const t = token.replace(/^["']|["']$/gu, "");
|
|
76
|
-
// 一个正则同时挡住四类坏值:旗标(`-` 开头)、含点的文件名、`$(…)` 这类
|
|
77
|
-
// shell 片段、以及超长的东西。上一版写成五道 if,等价但更啰嗦。
|
|
78
|
-
return /^[a-z0-9][a-z0-9_-]{0,19}$/u.test(t);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* 一条命令 → 一个业务动作。
|
|
83
|
-
*
|
|
84
|
-
* 返回 `{ verb, sub, flags }` 或 `null`(不是业务命令,或抽不出动词)。
|
|
85
|
-
* - `verb`:白名单里的动词(小写)
|
|
86
|
-
* - `sub`:**扫描出的第一个像子命令的 token**(不是"第一个非旗标 token"——那个
|
|
87
|
-
* 可能是路径或参数,见 `looksLikeSubcommand`)。找不到就是空串
|
|
88
|
-
* - `flags`:`-` 开头的旗标。**位置参数一律丢弃**(理由见文件头隐私一节)
|
|
89
|
-
*/
|
|
90
|
-
export function businessCommandOf(command) {
|
|
91
|
-
if (typeof command !== "string") return null;
|
|
92
|
-
const cleaned = command.replace(REDIRECT_RE, " ").trim();
|
|
93
|
-
if (cleaned === "" || CD_RE.test(cleaned)) return null;
|
|
94
|
-
|
|
95
|
-
const tokens = cleaned.split(/\s+/u).filter((t) => t !== "");
|
|
96
|
-
if (tokens.length === 0) return null;
|
|
97
|
-
|
|
98
|
-
const verb = tokens[0].toLowerCase().replace(/^["']|["']$/gu, "");
|
|
99
|
-
if (!BUSINESS_VERBS.has(verb)) return null;
|
|
100
|
-
|
|
101
|
-
// **扫描**而不是取第一个非旗标:`git -C <path> log` 的子命令在 `-C <值>` 之后。
|
|
102
|
-
let sub = "";
|
|
103
|
-
for (let i = 1; i < tokens.length; i += 1) {
|
|
104
|
-
if (looksLikeSubcommand(tokens[i])) {
|
|
105
|
-
sub = tokens[i].replace(/^["']|["']$/gu, "").toLowerCase();
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// 旗标:只留 `-` 开头的、短的、不含路径分隔符的(`--base=<path>` 这类直接丢)。
|
|
111
|
-
const flags = [];
|
|
112
|
-
for (const raw of tokens.slice(1)) {
|
|
113
|
-
const t = raw.replace(/^["']|["']$/gu, "");
|
|
114
|
-
if (t.startsWith("-") && t.length > 1 && t.length <= 24 && !/[/\\=]/u.test(t)) flags.push(t);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return { verb, sub, flags: [...new Set(flags)].slice(0, 4) };
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* 分组的键。
|
|
122
|
-
*
|
|
123
|
-
* 优先用子命令(`git status`)。**没有子命令时退而用第一个旗标**——因为对
|
|
124
|
-
* `node` / `npm` 这类工具,真正区分语义的常常就是旗标:`node --test`(跑测试)与
|
|
125
|
-
* `node --check`(查语法)是两件事,若键里只有 `node`,它们会被合并成一行,
|
|
126
|
-
* 清单就读不出差别了。这条是端到端实测里发现的(16 次 node 调用被并成一条)。
|
|
127
|
-
*
|
|
128
|
-
* **旗标仍然只是"补充",不是主体**:`git status -C --porcelain` 的键是 `git status`,
|
|
129
|
-
* `-C`(它后面本来跟着一个被丢弃的路径)不该挤进键里。
|
|
130
|
-
*/
|
|
131
|
-
export function activityKey(activity) {
|
|
132
|
-
if (!activity) return "";
|
|
133
|
-
const tail = activity.sub || (Array.isArray(activity.flags) ? activity.flags[0] : "") || "";
|
|
134
|
-
return tail ? `${activity.verb} ${tail}` : activity.verb;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* 一批观察 → 业务动作清单(按出现次数降序)。
|
|
139
|
-
*
|
|
140
|
-
* 每条:`{ key, verb, sub, count, flags }`;`flags` 是出现过的旗标并集(截断)。
|
|
141
|
-
* **不含任何位置参数**,因此不含路径与用户名。
|
|
142
|
-
*/
|
|
143
|
-
export function tallyActivities(observations) {
|
|
144
|
-
const groups = new Map();
|
|
145
|
-
let shellNoise = 0;
|
|
146
|
-
let totalSegments = 0;
|
|
147
|
-
|
|
148
|
-
for (const observation of observations || []) {
|
|
149
|
-
const command = observation?.command;
|
|
150
|
-
if (typeof command !== "string" || command.trim() === "") continue;
|
|
151
|
-
for (const raw of command.split(SEPARATOR_RE)) {
|
|
152
|
-
if (raw.trim() === "") continue;
|
|
153
|
-
totalSegments += 1;
|
|
154
|
-
const activity = businessCommandOf(raw);
|
|
155
|
-
if (!activity) {
|
|
156
|
-
shellNoise += 1;
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
const key = activityKey(activity);
|
|
160
|
-
const cur = groups.get(key) || { key, verb: activity.verb, sub: activity.sub, count: 0, flags: new Set() };
|
|
161
|
-
cur.count += 1;
|
|
162
|
-
for (const f of activity.flags) cur.flags.add(f);
|
|
163
|
-
groups.set(key, cur);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const activities = [...groups.values()]
|
|
168
|
-
.map((g) => ({ key: g.key, verb: g.verb, sub: g.sub, count: g.count, flags: [...g.flags].slice(0, 6) }))
|
|
169
|
-
.sort((a, b) => (b.count === a.count ? a.key.localeCompare(b.key) : b.count - a.count));
|
|
170
|
-
|
|
171
|
-
return {
|
|
172
|
-
activities,
|
|
173
|
-
// 两个数分开报:「业务动作很少」与「这条命令根本不是动作」是两件事。
|
|
174
|
-
businessSegments: activities.reduce((n, a) => n + a.count, 0),
|
|
175
|
-
shellNoise,
|
|
176
|
-
totalSegments
|
|
177
|
-
};
|
|
178
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 把 shell 观察压成**人能扫的「业务动作」清单**。
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么需要这一层(三组实测逼出来的)
|
|
5
|
+
*
|
|
6
|
+
* 1. 拿单条命令去匹配手写步骤表,命中率只有 14.2~15.2%(非发版会话 4.4%,
|
|
7
|
+
* 区分力仅 3 倍)→ **拿清单套行为这条路走不通**。
|
|
8
|
+
* 2. 想用「整段命令」当分组键:每个会话中位 **539 组**、最多 7373 组
|
|
9
|
+
* → 文献那套「聚类 + 人命名」直接照搬也不成立(网页活动本来只有几十个页面)。
|
|
10
|
+
* 3. 换「动词」当键:密度最高的全是 **PowerShell 管道语法**
|
|
11
|
+
* (`write-output` 10619、`select-object` 10422、`}` 4864…)
|
|
12
|
+
* → **「命令 ≈ 动作」这个预设是错的**:大部分"命令"不是活动,是句子成分。
|
|
13
|
+
* 4. 只留业务命令(git/gh/npm/node/docker…)后:业务段占 **6.5%**,
|
|
14
|
+
* 不同动词 **8 个**、不同前两词组 **1010 个** —— 这才是人能扫的量级。
|
|
15
|
+
*
|
|
16
|
+
* ## 这个模块的产出:一份「本次窗口观察到什么」清单
|
|
17
|
+
*
|
|
18
|
+
* 形态:`git status ×12`、`gh pr ×5`、`npm test ×3`。
|
|
19
|
+
* **不猜它对应哪一步**——那件事交给人(见 mneme-research 的 09 号文档)。
|
|
20
|
+
*
|
|
21
|
+
* ## 🔴 隐私:为什么只输出「动词 + 子命令」
|
|
22
|
+
*
|
|
23
|
+
* 完整命令行里**几乎必然含绝对路径**,而路径里含本机用户名。例如实测里真实出现过
|
|
24
|
+
* `set-location "c:\users\<用户名>\desktop\..."`。这条回执是要显示在界面上、
|
|
25
|
+
* 可能被截图的那一面——所以本模块有一条硬规则:
|
|
26
|
+
*
|
|
27
|
+
* > **位置参数一律丢弃,只保留动词、子命令与 `-` 开头的旗标。**
|
|
28
|
+
*
|
|
29
|
+
* 旗标是语义(`--rebase` / `--force` / `-m`),位置参数是数据(路径、文件名、id)。
|
|
30
|
+
* 只留前者,清单既表意又不泄露。这不是"顺手过滤",是这一层存在的第二个理由。
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 业务命令的动词白名单。
|
|
35
|
+
*
|
|
36
|
+
* 判据不是"常见",而是"**它的执行会构成工作流的一步**"——即它有语义
|
|
37
|
+
* (改仓库状态、发版、跑测试),而不是在组装文本(`write-output`、`foreach-object`)。
|
|
38
|
+
*
|
|
39
|
+
* 这张名单是**拍的**(实测里 6.5% 的段落在名单内),未验证覆盖率:
|
|
40
|
+
* 可能有业务动作用了别的工具(`python`、`curl`、`cargo`)。认不出来不产清单项,
|
|
41
|
+
* 是安全的方向——它只会让清单更短,不会让它更假。
|
|
42
|
+
*/
|
|
43
|
+
const BUSINESS_VERBS = new Set([
|
|
44
|
+
// 实测 21723 次调用里,真正命中的只有这四个:git / gh / npm / node。
|
|
45
|
+
// 其余先不收——认不出来只会让清单更短,不会让它更假;
|
|
46
|
+
// 等真有项目用上了再加(这一版刻意不做"猜未来会用到"的预留)。
|
|
47
|
+
"git", "gh", "npm", "npx", "node", "docker"
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
/** 命令分隔符:与 pipeline-attribution 同一口径(只认两侧带空白的)。 */
|
|
51
|
+
const SEPARATOR_RE = /\s*(?:;|&&|\|\||\|)\s*|\n/u;
|
|
52
|
+
|
|
53
|
+
/** 重定向尾巴(`2>&1`、`> file`、`2>nul`):不是命令的一部分。 */
|
|
54
|
+
const REDIRECT_RE = /\s*\d?>\s*&?\s*\S+/gu;
|
|
55
|
+
|
|
56
|
+
/** `cd <路径>`:前导定位语句,不是活动。 */
|
|
57
|
+
const CD_RE = /^cd\s/iu;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 这个 token 像不像一个**子命令**。
|
|
61
|
+
*
|
|
62
|
+
* 必须做这道校验,否则三件事都会发生(都是端到端实测抓到的):
|
|
63
|
+
* 1. `node d:\dsh\...\probe.mjs` → 把**脚本路径**当成 sub,路径里的用户名被带出去;
|
|
64
|
+
* 2. `git -C $(Join-Path ...) log --oneline` → 把 `$(Join-Path` 当成 sub,清单里出现
|
|
65
|
+
* `git (join-path -C --oneline` 这种读不懂的东西;
|
|
66
|
+
* 3. `node x.test.js` → **带点的文件名**被当成 sub(`x.test.js` 完全符合"小写字母起头
|
|
67
|
+
* 的短词")。这条是加完前两条修复后复验时才冒出来的。
|
|
68
|
+
*
|
|
69
|
+
* 所以除了字符集,还要**排除含点的 token**:子命令带点是极罕见的
|
|
70
|
+
* (`git log` / `gh pr` / `npm test` / `kubectl get` 都不带),而文件名几乎都带。
|
|
71
|
+
* 宁可漏认一个,不可把文件名当子命令——后者会出现在给人看的清单里。
|
|
72
|
+
*/
|
|
73
|
+
function looksLikeSubcommand(token) {
|
|
74
|
+
if (typeof token !== "string") return false;
|
|
75
|
+
const t = token.replace(/^["']|["']$/gu, "");
|
|
76
|
+
// 一个正则同时挡住四类坏值:旗标(`-` 开头)、含点的文件名、`$(…)` 这类
|
|
77
|
+
// shell 片段、以及超长的东西。上一版写成五道 if,等价但更啰嗦。
|
|
78
|
+
return /^[a-z0-9][a-z0-9_-]{0,19}$/u.test(t);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* 一条命令 → 一个业务动作。
|
|
83
|
+
*
|
|
84
|
+
* 返回 `{ verb, sub, flags }` 或 `null`(不是业务命令,或抽不出动词)。
|
|
85
|
+
* - `verb`:白名单里的动词(小写)
|
|
86
|
+
* - `sub`:**扫描出的第一个像子命令的 token**(不是"第一个非旗标 token"——那个
|
|
87
|
+
* 可能是路径或参数,见 `looksLikeSubcommand`)。找不到就是空串
|
|
88
|
+
* - `flags`:`-` 开头的旗标。**位置参数一律丢弃**(理由见文件头隐私一节)
|
|
89
|
+
*/
|
|
90
|
+
export function businessCommandOf(command) {
|
|
91
|
+
if (typeof command !== "string") return null;
|
|
92
|
+
const cleaned = command.replace(REDIRECT_RE, " ").trim();
|
|
93
|
+
if (cleaned === "" || CD_RE.test(cleaned)) return null;
|
|
94
|
+
|
|
95
|
+
const tokens = cleaned.split(/\s+/u).filter((t) => t !== "");
|
|
96
|
+
if (tokens.length === 0) return null;
|
|
97
|
+
|
|
98
|
+
const verb = tokens[0].toLowerCase().replace(/^["']|["']$/gu, "");
|
|
99
|
+
if (!BUSINESS_VERBS.has(verb)) return null;
|
|
100
|
+
|
|
101
|
+
// **扫描**而不是取第一个非旗标:`git -C <path> log` 的子命令在 `-C <值>` 之后。
|
|
102
|
+
let sub = "";
|
|
103
|
+
for (let i = 1; i < tokens.length; i += 1) {
|
|
104
|
+
if (looksLikeSubcommand(tokens[i])) {
|
|
105
|
+
sub = tokens[i].replace(/^["']|["']$/gu, "").toLowerCase();
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 旗标:只留 `-` 开头的、短的、不含路径分隔符的(`--base=<path>` 这类直接丢)。
|
|
111
|
+
const flags = [];
|
|
112
|
+
for (const raw of tokens.slice(1)) {
|
|
113
|
+
const t = raw.replace(/^["']|["']$/gu, "");
|
|
114
|
+
if (t.startsWith("-") && t.length > 1 && t.length <= 24 && !/[/\\=]/u.test(t)) flags.push(t);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return { verb, sub, flags: [...new Set(flags)].slice(0, 4) };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 分组的键。
|
|
122
|
+
*
|
|
123
|
+
* 优先用子命令(`git status`)。**没有子命令时退而用第一个旗标**——因为对
|
|
124
|
+
* `node` / `npm` 这类工具,真正区分语义的常常就是旗标:`node --test`(跑测试)与
|
|
125
|
+
* `node --check`(查语法)是两件事,若键里只有 `node`,它们会被合并成一行,
|
|
126
|
+
* 清单就读不出差别了。这条是端到端实测里发现的(16 次 node 调用被并成一条)。
|
|
127
|
+
*
|
|
128
|
+
* **旗标仍然只是"补充",不是主体**:`git status -C --porcelain` 的键是 `git status`,
|
|
129
|
+
* `-C`(它后面本来跟着一个被丢弃的路径)不该挤进键里。
|
|
130
|
+
*/
|
|
131
|
+
export function activityKey(activity) {
|
|
132
|
+
if (!activity) return "";
|
|
133
|
+
const tail = activity.sub || (Array.isArray(activity.flags) ? activity.flags[0] : "") || "";
|
|
134
|
+
return tail ? `${activity.verb} ${tail}` : activity.verb;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 一批观察 → 业务动作清单(按出现次数降序)。
|
|
139
|
+
*
|
|
140
|
+
* 每条:`{ key, verb, sub, count, flags }`;`flags` 是出现过的旗标并集(截断)。
|
|
141
|
+
* **不含任何位置参数**,因此不含路径与用户名。
|
|
142
|
+
*/
|
|
143
|
+
export function tallyActivities(observations) {
|
|
144
|
+
const groups = new Map();
|
|
145
|
+
let shellNoise = 0;
|
|
146
|
+
let totalSegments = 0;
|
|
147
|
+
|
|
148
|
+
for (const observation of observations || []) {
|
|
149
|
+
const command = observation?.command;
|
|
150
|
+
if (typeof command !== "string" || command.trim() === "") continue;
|
|
151
|
+
for (const raw of command.split(SEPARATOR_RE)) {
|
|
152
|
+
if (raw.trim() === "") continue;
|
|
153
|
+
totalSegments += 1;
|
|
154
|
+
const activity = businessCommandOf(raw);
|
|
155
|
+
if (!activity) {
|
|
156
|
+
shellNoise += 1;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const key = activityKey(activity);
|
|
160
|
+
const cur = groups.get(key) || { key, verb: activity.verb, sub: activity.sub, count: 0, flags: new Set() };
|
|
161
|
+
cur.count += 1;
|
|
162
|
+
for (const f of activity.flags) cur.flags.add(f);
|
|
163
|
+
groups.set(key, cur);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const activities = [...groups.values()]
|
|
168
|
+
.map((g) => ({ key: g.key, verb: g.verb, sub: g.sub, count: g.count, flags: [...g.flags].slice(0, 6) }))
|
|
169
|
+
.sort((a, b) => (b.count === a.count ? a.key.localeCompare(b.key) : b.count - a.count));
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
activities,
|
|
173
|
+
// 两个数分开报:「业务动作很少」与「这条命令根本不是动作」是两件事。
|
|
174
|
+
businessSegments: activities.reduce((n, a) => n + a.count, 0),
|
|
175
|
+
shellNoise,
|
|
176
|
+
totalSegments
|
|
177
|
+
};
|
|
178
|
+
}
|