@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
package/scripts/publish-gate.mjs
CHANGED
|
@@ -1,197 +1,197 @@
|
|
|
1
|
-
// 发布闸门:publish 步之后**必须**确认这个版本真的能被 registry 看见,看不见就整轮失败。
|
|
2
|
-
//
|
|
3
|
-
// 为什么需要它:原先这一步是
|
|
4
|
-
// echo "Published: $(npm view "@modusensus/dsh-mneme@${V}" version)"
|
|
5
|
-
// 命令替换里的失败**不会**让 `set -e` 退出。v0.8.16 那次日志白纸黑字写着
|
|
6
|
-
// `npm error code E404 / 404 No match found for version 0.8.16`,step 与 job 却都是绿的。
|
|
7
|
-
// 也就是说「真发不出去」(token 失效、权限不足、npm 侧拒绝)与「发出去了」在 CI 上是同一种
|
|
8
|
-
// 颜色,只有人翻日志才看得出来 —— 闸门的意义恰恰是没人翻日志的时候。
|
|
9
|
-
//
|
|
10
|
-
// 为什么是轮询而不是一次性查询:registry 有传播延迟,v0.8.16 实测 publish 到可见约 4.5 分钟
|
|
11
|
-
// (11:15:52Z → 11:20:22Z)。一次性查询只有两种结局:忽略失败(就是现在的假绿),或者拿传播
|
|
12
|
-
// 延迟当发布失败(假红)。幂等跳过那条路径(版本已存在)**首次探测即通过**,所以只有真发新版
|
|
13
|
-
// 才付等待成本。
|
|
14
|
-
//
|
|
15
|
-
// 为什么探测走 registry 公开 HTTP 面而不是 `npm view`:不依赖 .npmrc 里的 token、不依赖 npm CLI
|
|
16
|
-
// 的 E404 语义,而且能把「还没传播」与「网络异常」分开报出来 —— 两种都重试,但日志里要能区分,
|
|
17
|
-
// 否则排障时又得靠猜。
|
|
18
|
-
//
|
|
19
|
-
// 与 scripts/changelog-prep.mjs 同一个理由:逻辑收在可注入的模块里才测得到(probe/sleep/now 全
|
|
20
|
-
// 可注入,单测零网络零等待),入口只负责读参数与决定退出码。
|
|
21
|
-
|
|
22
|
-
import { pathToFileURL } from "node:url";
|
|
23
|
-
|
|
24
|
-
export const PACKAGE_NAME = "@modusensus/dsh-mneme";
|
|
25
|
-
export const REGISTRY_ORIGIN = "https://registry.npmjs.org";
|
|
26
|
-
|
|
27
|
-
/** 默认 10 分钟:实测传播 ~4.5 分钟,留一倍余量;超时=发布失败,宁可红也不许假绿。 */
|
|
28
|
-
export const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
|
|
29
|
-
/** 默认 15 秒:一次发布最多 40 次探测,日志行数与 registry 负载都可接受。 */
|
|
30
|
-
export const DEFAULT_INTERVAL_MS = 15 * 1000;
|
|
31
|
-
/** 单次探测的 HTTP 超时:挂死的请求必须自己失败,不能吃掉整段预算。 */
|
|
32
|
-
export const DEFAULT_PROBE_TIMEOUT_MS = 15 * 1000;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* 单版本的 registry URL。scoped 包名必须整体 encodeURIComponent(`@scope/name` → `%40scope%2Fname`):
|
|
36
|
-
* 直接拼裸 `/` 会被当成路径分隔符,registry 回 404 —— 那正是「闸门自己造成的假红」。
|
|
37
|
-
*/
|
|
38
|
-
export function versionUrl(name, version, origin = REGISTRY_ORIGIN) {
|
|
39
|
-
return `${origin.replace(/\/+$/, "")}/${encodeURIComponent(name)}/${encodeURIComponent(version)}`;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* 探测一次「该版本是否已在 registry 上」。
|
|
44
|
-
*
|
|
45
|
-
* 永不抛错:任何异常都折成 `{ok:false, reason, detail}`,让上层的重试与超时逻辑保持单一形状。
|
|
46
|
-
* `reason` 取值:`missing`(404,多半是还没传播) / `network`(请求本身失败) / `http`(非 2xx/404) /
|
|
47
|
-
* `bad-json` / `mismatch`(200 但版本号对不上)。
|
|
48
|
-
*
|
|
49
|
-
* @param {string} version 如 "0.8.16"
|
|
50
|
-
* @param {{name?: string, origin?: string, fetchImpl?: typeof fetch, timeoutMs?: number}} [options]
|
|
51
|
-
* @returns {Promise<{ok: true, version: string, tarball: string} | {ok: false, reason: string, detail: string}>}
|
|
52
|
-
*/
|
|
53
|
-
export async function probeVersion(version, {
|
|
54
|
-
name = PACKAGE_NAME,
|
|
55
|
-
origin = REGISTRY_ORIGIN,
|
|
56
|
-
fetchImpl = globalThis.fetch,
|
|
57
|
-
timeoutMs = DEFAULT_PROBE_TIMEOUT_MS
|
|
58
|
-
} = {}) {
|
|
59
|
-
const url = versionUrl(name, version, origin);
|
|
60
|
-
let response;
|
|
61
|
-
try {
|
|
62
|
-
response = await fetchImpl(url, {
|
|
63
|
-
headers: { accept: "application/json" },
|
|
64
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
65
|
-
});
|
|
66
|
-
} catch (error) {
|
|
67
|
-
return { ok: false, reason: "network", detail: `请求失败:${error?.message ?? error}(${url})` };
|
|
68
|
-
}
|
|
69
|
-
if (response.status === 404) {
|
|
70
|
-
return { ok: false, reason: "missing", detail: `HTTP 404,registry 上还看不到(${url})` };
|
|
71
|
-
}
|
|
72
|
-
if (!response.ok) {
|
|
73
|
-
return { ok: false, reason: "http", detail: `HTTP ${response.status}(${url})` };
|
|
74
|
-
}
|
|
75
|
-
let body;
|
|
76
|
-
try {
|
|
77
|
-
body = await response.json();
|
|
78
|
-
} catch (error) {
|
|
79
|
-
return { ok: false, reason: "bad-json", detail: `响应不是 JSON:${error?.message ?? error}` };
|
|
80
|
-
}
|
|
81
|
-
if (body?.version !== version) {
|
|
82
|
-
return { ok: false, reason: "mismatch", detail: `registry 返回的版本是 ${body?.version ?? "(缺失)"}` };
|
|
83
|
-
}
|
|
84
|
-
return { ok: true, version, tarball: body?.dist?.tarball ?? "" };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* 轮询到版本可见为止;超时即 `{ok:false, reason:"timeout"}`。
|
|
89
|
-
*
|
|
90
|
-
* 契约(单测锁的就是这条):**看不见就绝不返回 ok:true**。任何把超时折叠成成功、或者把
|
|
91
|
-
* 「探测失败」当成「跳过校验」的改法,都等于退回 v0.8.16 那种假绿。
|
|
92
|
-
*
|
|
93
|
-
* @param {string} version
|
|
94
|
-
* @param {{name?: string, origin?: string, timeoutMs?: number, intervalMs?: number,
|
|
95
|
-
* now?: () => number, sleep?: (ms: number) => Promise<void>,
|
|
96
|
-
* probe?: () => Promise<{ok: boolean, detail?: string}>, log?: (line: string) => void}} [options]
|
|
97
|
-
*/
|
|
98
|
-
export async function waitForPublished(version, {
|
|
99
|
-
name = PACKAGE_NAME,
|
|
100
|
-
origin = REGISTRY_ORIGIN,
|
|
101
|
-
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
102
|
-
intervalMs = DEFAULT_INTERVAL_MS,
|
|
103
|
-
now = () => Date.now(),
|
|
104
|
-
sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
105
|
-
probe = () => probeVersion(version, { name, origin }),
|
|
106
|
-
log = () => {}
|
|
107
|
-
} = {}) {
|
|
108
|
-
const startedAt = now();
|
|
109
|
-
let attempts = 0;
|
|
110
|
-
let lastError = "";
|
|
111
|
-
for (;;) {
|
|
112
|
-
attempts += 1;
|
|
113
|
-
const result = await probe();
|
|
114
|
-
// 探测成功即算通过,**不再回头比期限**:预算是「等多久才放弃」,不是「多久之后就算没发布」。
|
|
115
|
-
// 单次探测自带 HTTP 超时(默认 15 秒),所以晚到的成功最多超出预算十几秒;而版本真的在
|
|
116
|
-
// registry 上就等于发布成功,因为晚到几秒把它判红才是假红——这个闸门存在的理由正是消灭
|
|
117
|
-
// 假绿,不该顺手制造另一种失真。反过来,探测失败仍严格按预算收口(见下)。
|
|
118
|
-
if (result?.ok) {
|
|
119
|
-
return { ok: true, version, attempts, waitedMs: now() - startedAt, tarball: result.tarball ?? "" };
|
|
120
|
-
}
|
|
121
|
-
lastError = result?.detail ?? "未知原因";
|
|
122
|
-
const waitedMs = now() - startedAt;
|
|
123
|
-
log(`第 ${attempts} 次探测(已等 ${Math.round(waitedMs / 1000)}s):${lastError}`);
|
|
124
|
-
if (waitedMs >= timeoutMs) {
|
|
125
|
-
return { ok: false, reason: "timeout", attempts, waitedMs, lastError };
|
|
126
|
-
}
|
|
127
|
-
// 只睡到预算耗尽为止:最后一次探测落在超时点上,不额外多睡一整轮。
|
|
128
|
-
await sleep(Math.min(intervalMs, timeoutMs - waitedMs));
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* 入口参数:位置参数是版本号,另可覆盖 `--timeout-ms` / `--interval-ms`(排障与手动跑用)。
|
|
134
|
-
* 缺版本号如实回报 `missing-version`,由入口打印用法并退出 1。
|
|
135
|
-
*/
|
|
136
|
-
export function parseArgs(argv = []) {
|
|
137
|
-
const out = { version: "", timeoutMs: DEFAULT_TIMEOUT_MS, intervalMs: DEFAULT_INTERVAL_MS };
|
|
138
|
-
const positional = [];
|
|
139
|
-
for (let i = 0; i < argv.length; i += 1) {
|
|
140
|
-
const arg = argv[i];
|
|
141
|
-
if (arg === "--timeout-ms" || arg === "--interval-ms") {
|
|
142
|
-
const key = arg === "--timeout-ms" ? "timeoutMs" : "intervalMs";
|
|
143
|
-
const value = Number(argv[i + 1]);
|
|
144
|
-
if (!Number.isFinite(value) || value <= 0) return { ok: false, reason: `${arg} 需要一个正数` };
|
|
145
|
-
out[key] = value;
|
|
146
|
-
i += 1;
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
positional.push(arg);
|
|
150
|
-
}
|
|
151
|
-
if (positional.length !== 1) return { ok: false, reason: "missing-version" };
|
|
152
|
-
out.version = positional[0];
|
|
153
|
-
return { ok: true, ...out };
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/** 入口:CI 与手动都用它;失败一律 `process.exit(1)`,绝不吞掉。 */
|
|
157
|
-
export async function main(argv = process.argv.slice(2), {
|
|
158
|
-
log = console.log,
|
|
159
|
-
error = console.error,
|
|
160
|
-
wait = waitForPublished
|
|
161
|
-
} = {}) {
|
|
162
|
-
const parsed = parseArgs(argv);
|
|
163
|
-
if (!parsed.ok) {
|
|
164
|
-
error(`用法:node scripts/publish-gate.mjs <版本号> [--timeout-ms 600000] [--interval-ms 15000]`);
|
|
165
|
-
error(`参数有误:${parsed.reason}`);
|
|
166
|
-
return 1;
|
|
167
|
-
}
|
|
168
|
-
log(`等待 ${PACKAGE_NAME}@${parsed.version} 在 registry 上可见(最多 ${parsed.timeoutMs / 1000}s)…`);
|
|
169
|
-
const result = await wait(parsed.version, {
|
|
170
|
-
timeoutMs: parsed.timeoutMs,
|
|
171
|
-
intervalMs: parsed.intervalMs,
|
|
172
|
-
log
|
|
173
|
-
});
|
|
174
|
-
if (!result.ok) {
|
|
175
|
-
error(
|
|
176
|
-
`发布闸门未通过:${PACKAGE_NAME}@${parsed.version} 在 ${Math.round(result.waitedMs / 1000)}s 内` +
|
|
177
|
-
`(${result.attempts} 次探测)始终看不到 —— 最后一次:${result.lastError}`
|
|
178
|
-
);
|
|
179
|
-
error(`publish 步很可能失败了(token 失效 / 权限不足 / npm 侧拒绝),请翻上面 publish 步的日志。`);
|
|
180
|
-
return 1;
|
|
181
|
-
}
|
|
182
|
-
const waitedSec = Math.round(result.waitedMs / 1000);
|
|
183
|
-
log(`✓ ${PACKAGE_NAME}@${result.version} 已在 registry 上可见(第 ${result.attempts} 次探测,等了 ${waitedSec}s)`);
|
|
184
|
-
if (result.tarball) log(` tarball: ${result.tarball}`);
|
|
185
|
-
return 0;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// import 即执行会让单测没法只 import 纯函数(changelog-prep.mjs 的同一教训),故用主模块判别。
|
|
189
|
-
// 比较用 pathToFileURL:手拼 `file://${argv[1]}` 在本机(Windows 盘符 + 非 ASCII 路径)拼不出合法 URL,
|
|
190
|
-
// 判别会恒假 —— 那样的失败是静默的:脚本什么也不做,还退出 0。
|
|
191
|
-
//
|
|
192
|
-
// 用 `process.exitCode` 而不是 `process.exit()`:刚做完 HTTP 请求就硬退,会在 Windows 上撞到
|
|
193
|
-
// libuv 的 `Assertion failed: !(handle->flags & UV_HANDLE_CLOSING)`(实测 0.8.16 成功路径复现),
|
|
194
|
-
// 退出码变成 0xC0000409 而不是 0 —— 一个把成功报成崩溃的退出路径,正好与本次要修的假绿同类。
|
|
195
|
-
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
196
|
-
process.exitCode = await main();
|
|
197
|
-
}
|
|
1
|
+
// 发布闸门:publish 步之后**必须**确认这个版本真的能被 registry 看见,看不见就整轮失败。
|
|
2
|
+
//
|
|
3
|
+
// 为什么需要它:原先这一步是
|
|
4
|
+
// echo "Published: $(npm view "@modusensus/dsh-mneme@${V}" version)"
|
|
5
|
+
// 命令替换里的失败**不会**让 `set -e` 退出。v0.8.16 那次日志白纸黑字写着
|
|
6
|
+
// `npm error code E404 / 404 No match found for version 0.8.16`,step 与 job 却都是绿的。
|
|
7
|
+
// 也就是说「真发不出去」(token 失效、权限不足、npm 侧拒绝)与「发出去了」在 CI 上是同一种
|
|
8
|
+
// 颜色,只有人翻日志才看得出来 —— 闸门的意义恰恰是没人翻日志的时候。
|
|
9
|
+
//
|
|
10
|
+
// 为什么是轮询而不是一次性查询:registry 有传播延迟,v0.8.16 实测 publish 到可见约 4.5 分钟
|
|
11
|
+
// (11:15:52Z → 11:20:22Z)。一次性查询只有两种结局:忽略失败(就是现在的假绿),或者拿传播
|
|
12
|
+
// 延迟当发布失败(假红)。幂等跳过那条路径(版本已存在)**首次探测即通过**,所以只有真发新版
|
|
13
|
+
// 才付等待成本。
|
|
14
|
+
//
|
|
15
|
+
// 为什么探测走 registry 公开 HTTP 面而不是 `npm view`:不依赖 .npmrc 里的 token、不依赖 npm CLI
|
|
16
|
+
// 的 E404 语义,而且能把「还没传播」与「网络异常」分开报出来 —— 两种都重试,但日志里要能区分,
|
|
17
|
+
// 否则排障时又得靠猜。
|
|
18
|
+
//
|
|
19
|
+
// 与 scripts/changelog-prep.mjs 同一个理由:逻辑收在可注入的模块里才测得到(probe/sleep/now 全
|
|
20
|
+
// 可注入,单测零网络零等待),入口只负责读参数与决定退出码。
|
|
21
|
+
|
|
22
|
+
import { pathToFileURL } from "node:url";
|
|
23
|
+
|
|
24
|
+
export const PACKAGE_NAME = "@modusensus/dsh-mneme";
|
|
25
|
+
export const REGISTRY_ORIGIN = "https://registry.npmjs.org";
|
|
26
|
+
|
|
27
|
+
/** 默认 10 分钟:实测传播 ~4.5 分钟,留一倍余量;超时=发布失败,宁可红也不许假绿。 */
|
|
28
|
+
export const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
|
|
29
|
+
/** 默认 15 秒:一次发布最多 40 次探测,日志行数与 registry 负载都可接受。 */
|
|
30
|
+
export const DEFAULT_INTERVAL_MS = 15 * 1000;
|
|
31
|
+
/** 单次探测的 HTTP 超时:挂死的请求必须自己失败,不能吃掉整段预算。 */
|
|
32
|
+
export const DEFAULT_PROBE_TIMEOUT_MS = 15 * 1000;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 单版本的 registry URL。scoped 包名必须整体 encodeURIComponent(`@scope/name` → `%40scope%2Fname`):
|
|
36
|
+
* 直接拼裸 `/` 会被当成路径分隔符,registry 回 404 —— 那正是「闸门自己造成的假红」。
|
|
37
|
+
*/
|
|
38
|
+
export function versionUrl(name, version, origin = REGISTRY_ORIGIN) {
|
|
39
|
+
return `${origin.replace(/\/+$/, "")}/${encodeURIComponent(name)}/${encodeURIComponent(version)}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 探测一次「该版本是否已在 registry 上」。
|
|
44
|
+
*
|
|
45
|
+
* 永不抛错:任何异常都折成 `{ok:false, reason, detail}`,让上层的重试与超时逻辑保持单一形状。
|
|
46
|
+
* `reason` 取值:`missing`(404,多半是还没传播) / `network`(请求本身失败) / `http`(非 2xx/404) /
|
|
47
|
+
* `bad-json` / `mismatch`(200 但版本号对不上)。
|
|
48
|
+
*
|
|
49
|
+
* @param {string} version 如 "0.8.16"
|
|
50
|
+
* @param {{name?: string, origin?: string, fetchImpl?: typeof fetch, timeoutMs?: number}} [options]
|
|
51
|
+
* @returns {Promise<{ok: true, version: string, tarball: string} | {ok: false, reason: string, detail: string}>}
|
|
52
|
+
*/
|
|
53
|
+
export async function probeVersion(version, {
|
|
54
|
+
name = PACKAGE_NAME,
|
|
55
|
+
origin = REGISTRY_ORIGIN,
|
|
56
|
+
fetchImpl = globalThis.fetch,
|
|
57
|
+
timeoutMs = DEFAULT_PROBE_TIMEOUT_MS
|
|
58
|
+
} = {}) {
|
|
59
|
+
const url = versionUrl(name, version, origin);
|
|
60
|
+
let response;
|
|
61
|
+
try {
|
|
62
|
+
response = await fetchImpl(url, {
|
|
63
|
+
headers: { accept: "application/json" },
|
|
64
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
65
|
+
});
|
|
66
|
+
} catch (error) {
|
|
67
|
+
return { ok: false, reason: "network", detail: `请求失败:${error?.message ?? error}(${url})` };
|
|
68
|
+
}
|
|
69
|
+
if (response.status === 404) {
|
|
70
|
+
return { ok: false, reason: "missing", detail: `HTTP 404,registry 上还看不到(${url})` };
|
|
71
|
+
}
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
return { ok: false, reason: "http", detail: `HTTP ${response.status}(${url})` };
|
|
74
|
+
}
|
|
75
|
+
let body;
|
|
76
|
+
try {
|
|
77
|
+
body = await response.json();
|
|
78
|
+
} catch (error) {
|
|
79
|
+
return { ok: false, reason: "bad-json", detail: `响应不是 JSON:${error?.message ?? error}` };
|
|
80
|
+
}
|
|
81
|
+
if (body?.version !== version) {
|
|
82
|
+
return { ok: false, reason: "mismatch", detail: `registry 返回的版本是 ${body?.version ?? "(缺失)"}` };
|
|
83
|
+
}
|
|
84
|
+
return { ok: true, version, tarball: body?.dist?.tarball ?? "" };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 轮询到版本可见为止;超时即 `{ok:false, reason:"timeout"}`。
|
|
89
|
+
*
|
|
90
|
+
* 契约(单测锁的就是这条):**看不见就绝不返回 ok:true**。任何把超时折叠成成功、或者把
|
|
91
|
+
* 「探测失败」当成「跳过校验」的改法,都等于退回 v0.8.16 那种假绿。
|
|
92
|
+
*
|
|
93
|
+
* @param {string} version
|
|
94
|
+
* @param {{name?: string, origin?: string, timeoutMs?: number, intervalMs?: number,
|
|
95
|
+
* now?: () => number, sleep?: (ms: number) => Promise<void>,
|
|
96
|
+
* probe?: () => Promise<{ok: boolean, detail?: string}>, log?: (line: string) => void}} [options]
|
|
97
|
+
*/
|
|
98
|
+
export async function waitForPublished(version, {
|
|
99
|
+
name = PACKAGE_NAME,
|
|
100
|
+
origin = REGISTRY_ORIGIN,
|
|
101
|
+
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
102
|
+
intervalMs = DEFAULT_INTERVAL_MS,
|
|
103
|
+
now = () => Date.now(),
|
|
104
|
+
sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
105
|
+
probe = () => probeVersion(version, { name, origin }),
|
|
106
|
+
log = () => {}
|
|
107
|
+
} = {}) {
|
|
108
|
+
const startedAt = now();
|
|
109
|
+
let attempts = 0;
|
|
110
|
+
let lastError = "";
|
|
111
|
+
for (;;) {
|
|
112
|
+
attempts += 1;
|
|
113
|
+
const result = await probe();
|
|
114
|
+
// 探测成功即算通过,**不再回头比期限**:预算是「等多久才放弃」,不是「多久之后就算没发布」。
|
|
115
|
+
// 单次探测自带 HTTP 超时(默认 15 秒),所以晚到的成功最多超出预算十几秒;而版本真的在
|
|
116
|
+
// registry 上就等于发布成功,因为晚到几秒把它判红才是假红——这个闸门存在的理由正是消灭
|
|
117
|
+
// 假绿,不该顺手制造另一种失真。反过来,探测失败仍严格按预算收口(见下)。
|
|
118
|
+
if (result?.ok) {
|
|
119
|
+
return { ok: true, version, attempts, waitedMs: now() - startedAt, tarball: result.tarball ?? "" };
|
|
120
|
+
}
|
|
121
|
+
lastError = result?.detail ?? "未知原因";
|
|
122
|
+
const waitedMs = now() - startedAt;
|
|
123
|
+
log(`第 ${attempts} 次探测(已等 ${Math.round(waitedMs / 1000)}s):${lastError}`);
|
|
124
|
+
if (waitedMs >= timeoutMs) {
|
|
125
|
+
return { ok: false, reason: "timeout", attempts, waitedMs, lastError };
|
|
126
|
+
}
|
|
127
|
+
// 只睡到预算耗尽为止:最后一次探测落在超时点上,不额外多睡一整轮。
|
|
128
|
+
await sleep(Math.min(intervalMs, timeoutMs - waitedMs));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 入口参数:位置参数是版本号,另可覆盖 `--timeout-ms` / `--interval-ms`(排障与手动跑用)。
|
|
134
|
+
* 缺版本号如实回报 `missing-version`,由入口打印用法并退出 1。
|
|
135
|
+
*/
|
|
136
|
+
export function parseArgs(argv = []) {
|
|
137
|
+
const out = { version: "", timeoutMs: DEFAULT_TIMEOUT_MS, intervalMs: DEFAULT_INTERVAL_MS };
|
|
138
|
+
const positional = [];
|
|
139
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
140
|
+
const arg = argv[i];
|
|
141
|
+
if (arg === "--timeout-ms" || arg === "--interval-ms") {
|
|
142
|
+
const key = arg === "--timeout-ms" ? "timeoutMs" : "intervalMs";
|
|
143
|
+
const value = Number(argv[i + 1]);
|
|
144
|
+
if (!Number.isFinite(value) || value <= 0) return { ok: false, reason: `${arg} 需要一个正数` };
|
|
145
|
+
out[key] = value;
|
|
146
|
+
i += 1;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
positional.push(arg);
|
|
150
|
+
}
|
|
151
|
+
if (positional.length !== 1) return { ok: false, reason: "missing-version" };
|
|
152
|
+
out.version = positional[0];
|
|
153
|
+
return { ok: true, ...out };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** 入口:CI 与手动都用它;失败一律 `process.exit(1)`,绝不吞掉。 */
|
|
157
|
+
export async function main(argv = process.argv.slice(2), {
|
|
158
|
+
log = console.log,
|
|
159
|
+
error = console.error,
|
|
160
|
+
wait = waitForPublished
|
|
161
|
+
} = {}) {
|
|
162
|
+
const parsed = parseArgs(argv);
|
|
163
|
+
if (!parsed.ok) {
|
|
164
|
+
error(`用法:node scripts/publish-gate.mjs <版本号> [--timeout-ms 600000] [--interval-ms 15000]`);
|
|
165
|
+
error(`参数有误:${parsed.reason}`);
|
|
166
|
+
return 1;
|
|
167
|
+
}
|
|
168
|
+
log(`等待 ${PACKAGE_NAME}@${parsed.version} 在 registry 上可见(最多 ${parsed.timeoutMs / 1000}s)…`);
|
|
169
|
+
const result = await wait(parsed.version, {
|
|
170
|
+
timeoutMs: parsed.timeoutMs,
|
|
171
|
+
intervalMs: parsed.intervalMs,
|
|
172
|
+
log
|
|
173
|
+
});
|
|
174
|
+
if (!result.ok) {
|
|
175
|
+
error(
|
|
176
|
+
`发布闸门未通过:${PACKAGE_NAME}@${parsed.version} 在 ${Math.round(result.waitedMs / 1000)}s 内` +
|
|
177
|
+
`(${result.attempts} 次探测)始终看不到 —— 最后一次:${result.lastError}`
|
|
178
|
+
);
|
|
179
|
+
error(`publish 步很可能失败了(token 失效 / 权限不足 / npm 侧拒绝),请翻上面 publish 步的日志。`);
|
|
180
|
+
return 1;
|
|
181
|
+
}
|
|
182
|
+
const waitedSec = Math.round(result.waitedMs / 1000);
|
|
183
|
+
log(`✓ ${PACKAGE_NAME}@${result.version} 已在 registry 上可见(第 ${result.attempts} 次探测,等了 ${waitedSec}s)`);
|
|
184
|
+
if (result.tarball) log(` tarball: ${result.tarball}`);
|
|
185
|
+
return 0;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// import 即执行会让单测没法只 import 纯函数(changelog-prep.mjs 的同一教训),故用主模块判别。
|
|
189
|
+
// 比较用 pathToFileURL:手拼 `file://${argv[1]}` 在本机(Windows 盘符 + 非 ASCII 路径)拼不出合法 URL,
|
|
190
|
+
// 判别会恒假 —— 那样的失败是静默的:脚本什么也不做,还退出 0。
|
|
191
|
+
//
|
|
192
|
+
// 用 `process.exitCode` 而不是 `process.exit()`:刚做完 HTTP 请求就硬退,会在 Windows 上撞到
|
|
193
|
+
// libuv 的 `Assertion failed: !(handle->flags & UV_HANDLE_CLOSING)`(实测 0.8.16 成功路径复现),
|
|
194
|
+
// 退出码变成 0xC0000409 而不是 0 —— 一个把成功报成崩溃的退出路径,正好与本次要修的假绿同类。
|
|
195
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
196
|
+
process.exitCode = await main();
|
|
197
|
+
}
|