cross-tab-worker-databus 0.21.35 → 0.21.36
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/CHANGELOG.md +21 -0
- package/dist/centrifuge.d.ts +4 -2
- package/dist/centrifuge.d.ts.map +1 -1
- package/dist/centrifuge.js +5 -3
- package/dist/centrifuge.js.map +2 -2
- package/dist/{chunk-EVVTH6BQ.js → chunk-AWCFYLIT.js} +2 -2
- package/dist/{chunk-EVVTH6BQ.js.map → chunk-AWCFYLIT.js.map} +2 -2
- package/dist/cjs/centrifuge.cjs +5 -3
- package/dist/cjs/centrifuge.cjs.map +2 -2
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +2 -2
- package/dist/core/trace.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/docs/README.md +1 -1
- package/docs/release-checklist.md +3 -3
- package/docs/roadmap.md +11 -3
- package/docs/zh/README.md +1 -1
- package/docs/zh/release-checklist.md +3 -3
- package/docs/zh/roadmap.md +11 -3
- package/package.json +1 -1
package/dist/core/trace.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/core/trace.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/core/trace.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
package/docs/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
| [Architecture](./architecture.md) | Worker cluster, routing, storage, migration, and degradation design |
|
|
12
12
|
| [Capabilities Matrix](./capabilities.md) | Implemented, not implemented, and planned capabilities matrix |
|
|
13
13
|
| [Roadmap](./roadmap.md) | Release-oriented priorities and verification checklist |
|
|
14
|
-
| [Benchmark trend](./benchmarks.md) | Auto-generated browser benchmark history from `bench-results
|
|
14
|
+
| [Benchmark trend](./benchmarks.md) | Auto-generated browser benchmark history from the `bench-results/browser-*.json` reports |
|
|
15
15
|
| [Release checklist](./release-checklist.md) | Local gates, tagging, publishing, and post-release verification |
|
|
16
16
|
| [../examples/demo](../examples/demo) | Runnable multi-tab browser demo |
|
|
17
17
|
| [../CHANGELOG.md](../CHANGELOG.md) | Version changelog |
|
|
@@ -22,7 +22,7 @@ Only `pnpm bench:browser` / `pnpm bench:compare` / `pnpm bench:trend` stay local
|
|
|
22
22
|
3. Gate dependency security: `pnpm audit --registry=https://registry.npmjs.org` (the configured mirror registry lacks the audit endpoint; CI runs it on the public registry in the verify job). Fail the release on any known-vulnerability advisory; `pnpm-workspace.yaml` overrides pin patched ranges.
|
|
23
23
|
4. Gate browser benchmark regressions: run `pnpm bench:browser` (twice at minimum; the gate compares the newest report against the median of the same metric in up to the five preceding archived reports, **and additionally requires the new value to exceed the highest of those samples**) and then `pnpm bench:compare --fail-above-pct 50`. The median baseline exists because the in-page hot-path metrics alternate between a fast and a slow mode on identical code — two consecutive runs of `dedup1000Ms` measured 12.7 ms then 25.6 ms, and a single noisy previous report could fail the documented ceiling with no code change at all. The second leg exists because a median over an alternating sample is only stable while the modes stay mixed: when several consecutive reports land in the same mode the median itself jumps, which is how one comment-only tree read +121% against one baseline and −56.7% against another minutes apart. A metric excused by that leg is printed under `within-baseline, not gated` rather than passing silently — measured on the current archive, `publish/dedicated/perMessageMs`, `publish/shared/perMessageMs` and `databus/publishBatch1000Ms` were all inside their own five-report range, so treat that list as the metric's real resolution, not as a clean bill. `publish/dedicated/perMessageMs` is noisy the same way: two consecutive runs of identical code measured 49.9 ms then 71.1 ms, failing the gate at +75.7% while `dedup1000Ms` and `traceAndPublish1000Ms` *improved* in the same report — that single-metric-up-everything-else-down shape is the noise signature, and the next run reported 49.4 ms and passed. Before accepting or acting on a failure, re-run and check the spread; if the change touches a hot path, size it directly (a micro-benchmark of the 0.20.95 bounded-map rewrites measured 80–86 ns/op across all three variants, i.e. inside run-to-run variance). A baseline shift (e.g. a metric becoming real instead of a no-op) is an expected one-time failure. Refresh the long-run trend doc with `pnpm bench:trend` and commit it when the tables change. **Re-running a failure can manufacture its own excuse, and that was measured.** `bench:compare`'s baseline — both the median and the maximum leg — is drawn from the most recent archived reports, and every `bench:browser` run appends to that same archive, so the samples you add while investigating a failure become the baseline that judges the next attempt. On 2026-09-24, at host load averages 7.7–15.1 with a zero non-comment `src/` diff in the tree, the first two runs measured `publish/dedicated 77.3 ms` and `publish/shared 67.7 ms` against a ~38/~34 ms fast mode and failed the 50% ceiling; five further re-runs reported **OK**, because the baseline median had slid to `70.6`. One clean run after taking those samples out of the archive showed every metric rising together (`dedicated +92.5%`, `shared +99.2%`, `dedup +43.4%`, `trace +21.0%`), which is the contention signature and the inverse of the single-metric-up shape above. So read the load average *before* re-running, and when a suspect failure occurs on a loaded host, record it as deferred with its numbers and move the off-mode samples aside instead of letting them into the baseline — and do not regenerate `docs/benchmarks.md` from them. **The standing decision, recorded at 0.21.17 (the fifth release in that state): when no quiet window exists across a cycle, defer the sample with its load numbers instead of taking it on a loaded host.** The deferral is what keeps `docs/benchmarks.md` stale, and staleness-by-recorded-opportunity is the intended outcome of this step, not a gate that passed quietly; what would not be acceptable is a loaded sample entering the archive, because that becomes the baseline the next release is judged against.
|
|
24
24
|
5. Confirm the package contains only intended files with `npm pack --dry-run --json`.
|
|
25
|
-
6. Commit on a feature branch, push that branch, and merge its green PR using squash or fast-forward (no merge commit). Fetch the merged commit, tag that exact commit, and push only the specific version tag; never push `main`/`master` directly or force-push. The workflow runs `node scripts/verify-release-version.mjs` to require `RELEASE_TAG` to equal `v` + the package version and to require exactly one non-empty CHANGELOG section. The same step compares every version heading in `CHANGELOG.md` against the registry's own `time` map and refuses a release record that names a version npm never had — but only from `0.20.85` upward, because below that floor 40 sections name versions the registry never recorded, 27 of them tagged (
|
|
25
|
+
6. Commit on a feature branch, push that branch, and merge its green PR using squash or fast-forward (no merge commit). Fetch the merged commit, tag that exact commit, and push only the specific version tag; never push `main`/`master` directly or force-push. The workflow runs `node scripts/verify-release-version.mjs` to require `RELEASE_TAG` to equal `v` + the package version and to require exactly one non-empty CHANGELOG section. The same step compares every version heading in `CHANGELOG.md` against the registry's own `time` map and refuses a release record that names a version npm never had — but only from `0.20.85` upward, because below that floor 40 sections name versions the registry never recorded, 27 of them tagged (both re-derived 2026-09-25; the command to re-derive them intersects three sets — `grep -oE '^## \[[0-9]+\.[0-9]+\.[0-9]+\]' CHANGELOG.md`, `npm view cross-tab-worker-databus time --json --registry https://registry.npmjs.org`, and `git tag -l` — because the registry read alone answers neither count, let alone the tagged half), and the gate exists to stop a new hole rather than to litigate history. The version being tagged is exempt, since it legitimately cannot be on npm yet, and a registry read that fails prints a skip warning and exits 0: refusing a good release over one transient HTTP call is the failure mode the published-consumer ceiling was sized to avoid, so only a *confirmed* absence is fatal. Note the `--registry` in that re-derive command, and that the gate passes it too: a configured **mirror** can answer successfully while 3,418 s behind. Measured while preparing `0.21.35` on a machine whose `npm` points at `registry.npmmirror.com` — its packument still reported `modified: 00:32:51Z` (the `0.21.33` publish) when the gate ran at `03:41:18Z` — 3,207 s (53 min) after npmjs had recorded `0.21.34` at `02:47:50Z`, and the mirror's own `modified` did not move until `03:44:48.778Z`, 3,418 s after the record — so the gate declared a public version "never recorded", from a read that *succeeded*. A mirror's sync lag is not HTTP caching, so `cache-control: no-cache` returns the same stale document; naming the registry is the only thing that fixes it. `verify-published-consumer.mjs` had already pinned it for both of its reads; this was the last npm-based registry read in the repository that did not.
|
|
26
26
|
|
|
27
27
|
## Security and dependency scanning
|
|
28
28
|
|
|
@@ -42,6 +42,6 @@ For a manual release (no `NPM_TOKEN` in the workflow), run `npm publish --access
|
|
|
42
42
|
2. Install the published tarball or version in a clean consumer and import the root plus every public subpath.
|
|
43
43
|
3. Record the result in the release notes. Do not advance to `1.0.0` until the public API and protocol deprecation policy are explicitly frozen.
|
|
44
44
|
|
|
45
|
-
The tagged-release workflow already ran the consumer verification above. Run `PUBLISHED_VERSION=<version> pnpm verify:published` by hand only when you need an offline repeat. The workflow's 12-minute ceiling is not padding, and the number is a sum of two measured lags. First: the registry records the publish minutes after `npm publish` returns — the ack→`time[<version>]` gap measured on 0.21.27 through 0.21.
|
|
45
|
+
The tagged-release workflow already ran the consumer verification above. Run `PUBLISHED_VERSION=<version> pnpm verify:published` by hand only when you need an offline repeat. The workflow's 12-minute ceiling is not padding, and the number is a sum of two measured lags. First: the registry records the publish minutes after `npm publish` returns — the ack→`time[<version>]` gap measured on 0.21.27 through 0.21.35 was 74.8–310.0 s, and 248.7 / 96.8 / 74.8 / 310.0 / 127.2 / 76.1 / 75.5 / 75.8 / 127.3 s in version order — nine values, counted from that enumeration (read `time[<version>]` from the packument and compare it with the `Publish to npm` step's completion time). Three consecutive releases (0.21.32–0.21.34) recorded at 76.1, 75.5 and 75.8 s, a spread of 0.6 s, and this note read that as the lag being stable; **0.21.35 then came back at 127.3 s**, so the tightness was three samples and not a property. What the nine values do support is weaker and is the only thing the ceiling needs: the record lag sits between 74.8 and 310.0 s, none has beaten the 310 s that sizes the budget, and while it ranges over a minute the *step* has consumed 304–308 s every single time across ten green runs — so the varying quantity is how long the reader stays blind to a record that already exists, which is the second lag, not this one. Second: the packument that `npm pack` resolves against is served with `cache-control: public, max-age=300`, so a copy of it anywhere in the path is allowed to be up to five minutes stale, and resolution cannot be trusted to beat one cache lifetime after a write that lands inside that window. Which copy — npm's local cache or an intermediate — served the stale views below is *not* established, and the counter-observation this note used to offer against a purely local account does not survive being read carefully, because it joins two machines: the 21:44:34Z "fresh fetch" was a `npm pack` run on a laptop, while the 1 s green at 21:47:10Z was a *new runner job*, and a new job's npm cache starts empty — which is what the local account predicts rather than what contradicts it. What a purely-local account still cannot explain is one specific reading: the runner's own `ETARGET` at 21:45:07Z — 364 s after the step that opened its first poll (21:39:03Z), so ~60 s *after* the point where a copy taken then must have gone stale (21:44:03Z, give or take the second the request actually left). The ceiling is therefore arithmetic rather than a model: worst-case ack→`time[]` gap plus one cache lifetime. That sum is not theoretical: the previous 6-minute ceiling was exhausted by a *successful* publish, the 0.21.30 tag run spending its whole 360 s budget (48 × 7.5 s) on `ETARGET` while that version's tarball HEAD and a local `npm pack` had both already succeeded, and the same step 123 s later taking 1 s. The 0.20.89 run had shown the same shape against that release's 2-minute budget. So a long retrying verify is normal propagation, not an unusually slow mirror — raise `PUBLISHED_VERIFY_ATTEMPTS` / `PUBLISHED_VERIFY_DELAY_MS` further only if the ack→`time[]` gap has itself grown. Note the asymmetry when repeating by hand: `verify-published-consumer.mjs` defaults to `6` attempts × `5_000` ms — 30 seconds, not 12 minutes — because the tag run passes the larger pair as env rather than the script owning it. So a manual repeat can report `ETARGET` on a version whose CI run was green, which reads like a failed publish and is not one; reproduce the CI budget explicitly with `PUBLISHED_VERSION=<version> PUBLISHED_VERIFY_ATTEMPTS=96 PUBLISHED_VERIFY_DELAY_MS=7500 pnpm verify:published`, or judge a manual failure against the 30 s budget you actually ran. Read the step's duration as a diagnostic rather than a mood: the five green tag runs from 0.21.25 to 0.21.29 took 307, 304, 305, 304 and 304 s, 0.21.31's took 308 s and 0.21.32's, 0.21.33's and 0.21.34's took 304 s each — nine samples in a 5-second band, which is what one 300 s cache lifetime plus a few seconds of command time predicts (take the numbers from each release run's `Verify published npm consumers` step, `steps[].started_at`/`completed_at` from the same `gh api` call). 0.21.31 through 0.21.34 are the first four releases to run under the raised 720 s ceiling, and their lags split differently, which is the useful contrast: 127.2 s of record plus ~181 s of cache for the first, 76.1 s of record plus ~228 s before the runner saw it for the next, 75.5 s plus ~229 s for the third, and 75.8 s plus ~228 s for the fourth — on 0.21.32 a `no-cache` packument read from a laptop reported the new `latest` 151 s in, while the runner's own poll kept failing until 304 s, i.e. one lifetime after *its* first fetch. So the sample that set the previous ceiling has not been beaten: if the *ack→`time[]`* figure grows past 310 s, raise `PUBLISHED_VERIFY_ATTEMPTS` again; a verify that finishes in seconds means whatever copy it read already carried the new version.
|
|
46
46
|
|
|
47
|
-
**Do not adjudicate a publish from `dist-tags.latest`.** The package document endpoint and the tarball URL are two different read paths, and their timestamps are worth more than the impression they first give. Read during the 0.21.30 release, in order: `npm publish` returned success at `21:39:03Z`; a `curl -s -H "Cache-Control: no-cache" https://registry.npmjs.org/<pkg>` at `21:43:15Z` reported `latest` still on the previous version, no `0.21.30` in `versions`, and no `time['0.21.30']`; npm's own stamp for that version is `21:44:12.987Z` and the document's `last-modified` is `21:44:14 GMT`. So the 21:43:15 read was **not** a replica refusing an artifact that already existed — the registry had not finished recording the publish, and `no-cache` could not have made it see a version that did not exist yet. Absence from `versions` and from `latest`, minutes after a green publish step, is the expected state of a successful release. The genuine read-path disagreement came 60 s later: between `21:44:14Z` and `21:44:35Z`, `curl -I …/-/<pkg>-0.21.30.tgz` returned `HTTP 200` and a local `npm pack <pkg>@0.21.30 --registry https://registry.npmjs.org` completed and wrote the tarball, while the workflow runner's own `npm pack` kept returning `ETARGET` until it exhausted its budget at `21:45:07Z`. Same version, two machines, opposite answers a minute apart. To answer "did the publish happen", HEAD the tarball URL and try the pack — those reach the artifact — and try it **from the place that is failing**, because "fetchable" is a per-machine answer; read `latest` only for the question "which version do consumers get by default", which is a different one and settles later. `npm view <pkg> version` adds a third path on top: it can be served from npm's *local* packument cache, so on a machine that queried the registry before the publish it can return the superseded version even after the global `latest` has moved (that is why this gate resolves its target from `PUBLISHED_VERSION` and refuses an inferred version that disagrees with `package.json`). Never re-push, move, or replace a tag because a metadata read looked stale; the tag is immutable once published.
|
|
47
|
+
**Do not adjudicate a publish from `dist-tags.latest`.** The package document endpoint and the tarball URL are two different read paths, and their timestamps are worth more than the impression they first give. Read during the 0.21.30 release, in order: `npm publish` returned success at `21:39:03Z`; a `curl -s -H "Cache-Control: no-cache" https://registry.npmjs.org/<pkg>` at `21:43:15Z` reported `latest` still on the previous version, no `0.21.30` in `versions`, and no `time['0.21.30']`; npm's own stamp for that version is `21:44:12.987Z` and the document's `last-modified` is `21:44:14 GMT`. So the 21:43:15 read was **not** a replica refusing an artifact that already existed — the registry had not finished recording the publish, and `no-cache` could not have made it see a version that did not exist yet. Absence from `versions` and from `latest`, minutes after a green publish step, is the expected state of a successful release from `0.20.92` on — all 42 of them measured on 2026-09-25 took at least 74.8 s to be recorded — while the five just before the window (`0.20.86`, `0.20.87`, `0.20.88`, `0.20.90`, `0.20.91`) recorded within ±0.6 s of their acks and resolved in 1 s. So the sentence describes this window and not npm; what to do when it holds is unchanged. The genuine read-path disagreement came 60 s later: between `21:44:14Z` and `21:44:35Z`, `curl -I …/-/<pkg>-0.21.30.tgz` returned `HTTP 200` and a local `npm pack <pkg>@0.21.30 --registry https://registry.npmjs.org` completed and wrote the tarball, while the workflow runner's own `npm pack` kept returning `ETARGET` until it exhausted its budget at `21:45:07Z`. Same version, two machines, opposite answers a minute apart. To answer "did the publish happen", HEAD the tarball URL and try the pack — those reach the artifact — and try it **from the place that is failing**, because "fetchable" is a per-machine answer; read `latest` only for the question "which version do consumers get by default", which is a different one and settles later. `npm view <pkg> version` adds a third path on top: it can be served from npm's *local* packument cache, so on a machine that queried the registry before the publish it can return the superseded version even after the global `latest` has moved (that is why this gate resolves its target from `PUBLISHED_VERSION` and refuses an inferred version that disagrees with `package.json`). Never re-push, move, or replace a tag because a metadata read looked stale; the tag is immutable once published.
|
package/docs/roadmap.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Roadmap
|
|
2
2
|
|
|
3
|
-
0.21.
|
|
3
|
+
0.21.36 was released on September 25, 2026. The project is intentionally continuing through reliability-focused releases before a 1.0.0 stability freeze.
|
|
4
|
+
|
|
5
|
+
## 0.21.36 delivered scope
|
|
6
|
+
|
|
7
|
+
- **Two shipped comments were contradicted by the code they describe, and both were found by counting rather than reading.** `src/centrifuge.ts`'s dispatcher doc claimed three listeners where one function is registered twice — three sources, two call sites — and the sentence ships through `dist/centrifuge.d.ts`, because a `private` member keeps its declaration doc. `src/core/trace.ts` quoted a test total that had already gone stale twice while the same sentence told the reader to re-derive it; the value is deleted, since a number written beside its own lookup is the form nobody checks. The sweep that found them counted fourteen numeric claims in `src/` against the tree and twelve held — among them `centrifuge@5.7.4`'s twelve `emit('error')` sites inside `BaseSubscription` against 23 in the whole file, where the range qualifier is exactly what makes the claim true.
|
|
8
|
+
- **`CONTRIBUTING.md` was read for the first time and carried four claims the repository contradicts.** Coverage thresholds stated below the blocking gate (85/80/90/85 against `vitest.config.ts`'s 98/96/98/99); a `pnpm check` gloss that named a test count and omitted lint; a release section instructing `npm version` plus `git push origin main --tags` — tag the local HEAD and push the protected branch, the two operations this repository prohibits; and `[Unreleased]` prescribed in four places while `CHANGELOG.md` carries zero such headings and non-release PRs open the versioned section directly. All four now point at the config and the checklist as the source of truth.
|
|
9
|
+
- **The publish-lag recipe named a parameter it never said how to choose, and the series widened from nine releases to every tag.** Reading the jobs endpoint without an attempt segment returns the *latest* attempt, so on the one re-run release the obvious short form reported −177.0 s and a 1.0 s consumer step where attempt 1 holds the real 310.0 s gap and the 364 s failure; both checklists and the workflow comment now say where to take the attempt from. Over all 48 tags from `0.20.85`: 44 non-negative ack→record gaps, maximum 310.0 s, so the 720 s propagation budget stands — and the "the registry records minutes later" premise is scoped to the `0.20.92`-onward window, because five older releases recorded within ±0.6 s, three of them before the ack returned.
|
|
10
|
+
- **`AGENTS.md`'s directory map is complete and gated.** It named 16 of the 43 files under `tests/`, so every harness, prose gate, release gate and bench file added after the block was written was invisible to the session that reads it first. It now covers every tracked `src`/`tests`/`e2e` file plus one line per code directory, and a new case enforces it with the section's *edges* pinned — because a fence extraction that slips one position makes "every name appears in the block" true of a document that merely discusses those files elsewhere. Five mutants, five distinct failures.
|
|
11
|
+
- **Two prose gates had silently wrong scopes.** The privacy gate walked `examples/` with no extension filter, so it regex-scanned 2.9 MB of gitignored bundle and sourcemap that CI never builds — a red-at-home, green-in-CI channel; its scope is now the repository's own index, pinned on fabricated input so it reads the same built or clean. `CONTRIBUTING.md` joined the citation, empty-section and relative-link sweeps, and each addition was probed on its own: two of the three fail with the array entry and pass with only that entry removed, while the citation leg has nothing in the file to fire on and is reported as preventive only.
|
|
4
12
|
|
|
5
13
|
## 0.21.35 delivered scope
|
|
6
14
|
|
|
@@ -15,7 +23,7 @@
|
|
|
15
23
|
|
|
16
24
|
## 0.21.34 delivered scope
|
|
17
25
|
|
|
18
|
-
- **A tag can now be refused because the release record names a version npm never had.** `scripts/verify-release-version.mjs` reads the packument's `time` map beside the checks it already made and fails when a CHANGELOG section at or above `firstGatedRelease = 0.20.85` has no registry record. The in-flight release is exempt, a duplicated section reports once, and a failed registry read warns and skips rather than turning a good release red — the deliberate half of the design. The floor comes from a count, not taste: 40 of the
|
|
26
|
+
- **A tag can now be refused because the release record names a version npm never had.** `scripts/verify-release-version.mjs` reads the packument's `time` map beside the checks it already made and fails when a CHANGELOG section at or above `firstGatedRelease = 0.20.85` has no registry record. The in-flight release is exempt, a duplicated section reports once, and a failed registry read warns and skips rather than turning a good release red — the deliberate half of the design. The floor comes from a count, not taste: 40 of the CHANGELOG's 165 sections (re-derive the total with `grep -c '^## \[' CHANGELOG.md`; it rises by one every release, which is why the number is not the argument) name unpublished versions (`0.9.0`, each minor's first patch from `0.12.0` to `0.18.0`, all ten `0.19.x`, `0.20.0`–`0.20.5`, `0.20.54`, `0.20.55`, `0.20.69`, `0.20.72`–`0.20.84`; 1 + 7 + 10 + 6 + 2 + 1 + 13 = 40) — 41 counting the release in flight, which is why the gate exempts it — and every one sits below it, while the 47 sections from `0.20.85` through `0.21.33` are all present (that count is this tag's own reading — it rises by one with every release, and the script prints it). Four mutants, four named tests, one failure each.
|
|
19
27
|
- **One eviction skip had no test that could see it.** `rememberTopic()` skips owned keys *and* the key being remembered; deleting the second term left all 944 tests green. It is reachable only when every older entry is owned, because a fresh `Map.set` lands at the back of the insertion-ordered Map and that is the one case where the front-scan reaches it — and there the mutant throws away the mapping the call exists to install. The new case stages 500 adopted peer SUBSCRIBE frames plus one PUBLISH and fails at `expected [ 'owned.0', …(498) ] to include 'evict.extra'`; the owned term keeps its own pre-existing case, so both skips are individually attributed. Two earlier designs are recorded in the test's comment because both were plausible and neither reached the leg: an inbound SUBSCRIBE cannot produce an unowned entry, and re-remembering a key already present cannot overflow the cap.
|
|
20
28
|
- **Three shipped sentences about caps described protections the code does not provide.** `MAX_KNOWN_TOPICS = 500` was documented as stopping a malicious peer from exhausting memory through control messages; measured, 1,200 peer `CONTROL/SUBSCRIBE` frames grew `knownTopics` and `assignedTopics` to 1,200, because each frame is adopted, adoption makes its key owned, and the loop then refuses to drop anything — one reconcile tick took both back to `0`, so the flood's bound is the sweep and the cap's bound is over unowned entries. `trace.ts` credited both of its caps with guarding "a single misbehaving topic", when `MAX_PENDING_TOPICS` is an admission gate over *distinct* topics (1,001 topics → 1,000 queues, while an admitted topic still grows to 256) and the `topics` Set carries neither cap by design, bounded by the window flush. And the identifier table in the same architecture doc still restated the eviction rule in its pre-correction form while the row beside it omitted `reconcileAssignedTopics`, the only path that ends a flood. All of it is fixed in both languages, and the `src/` comments now point at the loop and at the tests rather than restating the rule twice.
|
|
21
29
|
- **A candidate test that duplicates an existing one is deleted, not kept.** The trace caps looked unpinned because the grep used the constants' names, and the two cases that do pin them write the numbers in a comment and never mention the identifiers. Both new cases were written, then the mutation run reported that deleting the admission guard failed **two** tests — the new one and `caps the number of topics tracked for pending receives`, which uses more inputs than the new one did. They were removed; the comment cites the existing names. The release therefore adds one test (the eviction pin) and removes none.
|
|
@@ -1047,7 +1055,7 @@ The line continues the async-callback isolation audit: every fix below binds a c
|
|
|
1047
1055
|
|
|
1048
1056
|
## Release checklist
|
|
1049
1057
|
|
|
1050
|
-
-
|
|
1058
|
+
- Write the release's own `## [x.y.z] - date` section (the repository no longer keeps an `[Unreleased]` section — the versioned heading is opened in the change's own PR, and `docs/release-checklist.md` is the authoritative procedure).
|
|
1051
1059
|
- Run `pnpm check`, `pnpm lint`, `pnpm test:e2e`, `pnpm bench`, and `pnpm bench:browser`.
|
|
1052
1060
|
- Run ESM/CJS package-consumption smoke tests from the packed tarball.
|
|
1053
1061
|
- Tag the release and verify the GitHub Release and npm `latest` dist-tag.
|
package/docs/zh/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
| [架构说明](./architecture.md) | Worker 集群、路由、存储、迁移和降级设计 |
|
|
14
14
|
| [能力矩阵](./capabilities.md) | 已实现、未实现和计划待实现的能力矩阵 |
|
|
15
15
|
| [路线图](./roadmap.md) | 面向版本的优先级与验证清单 |
|
|
16
|
-
| [基准趋势](./benchmarks.md) | 基于 `bench-results
|
|
16
|
+
| [基准趋势](./benchmarks.md) | 基于 `bench-results/browser-*.json` 归档报告自动生成的浏览器基准历史 |
|
|
17
17
|
| [发布检查清单](./release-checklist.md) | 本地门禁、打 tag、发布和发布后验证 |
|
|
18
18
|
| [../../examples/demo](../../examples/demo) | 可运行的多标签浏览器演示 |
|
|
19
19
|
| [../../CHANGELOG.md](../../CHANGELOG.md) | 版本变更记录 |
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
4. 浏览器基准回归门禁:运行 `pnpm bench:browser`(至少两次;门禁将最新报告与之前最多五份归档报告中同一指标的中位数比较,**并且额外要求新值超过这些样本中的最大值**),随后执行 `pnpm bench:compare --fail-above-pct 50`。采用中位数基线是因为页内热路径指标在同一份代码上会在快/慢两档之间来回跳——`dedup1000Ms` 相邻两次实测分别为 12.7 ms 与 25.6 ms,只看"上一份报告"时,一次偶发噪声就能在无代码改动的情况下击穿既定上限。第二个条件则是因为:在两档交替的样本上,中位数只有当两档保持混合时才稳定——一旦连续几份报告落在同一档,中位数本身就会跳变,这正是同一份纯注释改动在一版基线前读出 +121%、几分钟后在另一版基线前读出 −56.7% 的原因。被该条件放过的指标会打印在 `within-baseline, not gated` 下,而不是静默通过——在当前归档上实测,`publish/dedicated/perMessageMs`、`publish/shared/perMessageMs` 与 `databus/publishBatch1000Ms` 三项都落在各自五份报告的区间内,因此应把这份清单读作该指标的真实分辨率,而不是一张合格证。`publish/dedicated/perMessageMs` 同样如此:同一份代码相邻两次实测为 49.9 ms 与 71.1 ms,令门禁以 +75.7% 失败,而同一份报告里 `dedup1000Ms` 与 `traceAndPublish1000Ms` 反而*变快*——"单指标上涨、其余下降"正是噪声的特征,第三次实测为 49.4 ms 并通过。因此在采信或处理失败前先复跑并观察离散度;若改动涉及热路径,就直接量化其开销(0.20.95 有界映射改写的微基准显示三种写法均为 80–86 ns/op,落在运行间波动之内)。基线迁移(例如某指标从空操作变为真实路径)属预期内的一次性失败。用 `pnpm bench:trend` 刷新长期趋势文档,表格变化时一并提交。**复跑失败可能亲手制造出让它通过的基线,这一点已被实测。** `bench:compare` 的基线(中位数与最大值两个条件)取自最近若干份归档报告,而每一次 `pnpm bench:browser` 都会往同一个归档里追加——于是排查失败时新增的样本,就变成了裁决下一次尝试的基线。2026-09-24:主机负载均值 7.7–15.1、待发布树的非注释 `src/` 差异为 0 行,前两次实测 `publish/dedicated 77.3 ms`、`publish/shared 67.7 ms`,相对约 38/34 ms 的快档在 50% 上限上失败;随后五次复跑报告 **OK**,因为基线中位数已经滑到 `70.6`。把这些样本移出归档后的一次干净实测显示所有指标同时上涨(`dedicated +92.5%`、`shared +99.2%`、`dedup +43.4%`、`trace +21.0%`),那是资源竞争的形态,与上文"单指标上涨、其余下降"的噪声形态相反。因此:复跑之前先看负载(`uptime`);在满载主机上遇到可疑失败,就把数字连同负载一起记为"本轮推迟",并将偏离常态的样本移出基线——也不要据它们重新生成 `docs/benchmarks.md`。
|
|
24
24
|
**这条既定决策在 0.21.17 被写下,那是处于该状态下的第五个发布周期:一个发布周期里始终没有安静的窗口时,就把这份采样连同当时的负载数字一起记为"本轮推迟",而不是在满载主机上取它。** 推迟正是 `docs/benchmarks.md` 保持陈旧的原因,而"按机会更新"的这份陈旧是本步骤期望的结果,不是一道悄悄通过的门禁;真正不可接受的,是把一个受资源竞争的样本放进归档——那会变成下一次发布用来判定回归的基线。
|
|
25
25
|
5. 用 `npm pack --dry-run --json` 确认发布包只包含预期文件。
|
|
26
|
-
6. 在功能分支提交并推送该分支,PR 验证通过后使用 squash 或 fast-forward 合入(不创建 merge commit)。获取合入后的精确提交并打 tag,只推送该版本 tag;禁止直接推送 `main`/`master` 或 force-push。工作流运行 `node scripts/verify-release-version.mjs`,要求 `RELEASE_TAG` 等于 `v` 加 package 版本,且 CHANGELOG 中恰好有一个非空的对应版本章节。同一步骤还会把 `CHANGELOG.md` 里每个版本标题与 registry 自己的 `time` 映射相对照,拒绝一份"点名了 npm 从未有过的版本"的发布记录——但只从 `0.20.85` 往上要求:在那之下有 40 个章节点名了 registry 从未记录过的版本,其中 27 个还带着 git tag
|
|
26
|
+
6. 在功能分支提交并推送该分支,PR 验证通过后使用 squash 或 fast-forward 合入(不创建 merge commit)。获取合入后的精确提交并打 tag,只推送该版本 tag;禁止直接推送 `main`/`master` 或 force-push。工作流运行 `node scripts/verify-release-version.mjs`,要求 `RELEASE_TAG` 等于 `v` 加 package 版本,且 CHANGELOG 中恰好有一个非空的对应版本章节。同一步骤还会把 `CHANGELOG.md` 里每个版本标题与 registry 自己的 `time` 映射相对照,拒绝一份"点名了 npm 从未有过的版本"的发布记录——但只从 `0.20.85` 往上要求:在那之下有 40 个章节点名了 registry 从未记录过的版本,其中 27 个还带着 git tag(两个数都在 2026-09-25 重新核过;重算的命令要把三个集合求交——`grep -oE '^## \[[0-9]+\.[0-9]+\.[0-9]+\]' CHANGELOG.md`、`npm view cross-tab-worker-databus time --json --registry https://registry.npmjs.org`、`git tag -l`——因为只读 registry 既得不出 40,更得不出其中带 tag 的 27),这道门禁要拦的是新的漏洞,不是去翻历史旧账。而 registry 读取失败时,这一半会被跳过并打印一行警告、退出 0,而不是把一次好发布判红:为一个瞬时的 HTTP 失败拒绝一次成功发布,正是已发布消费者上限当初要避免的那类失败,所以只有*确认存在*的缺失才会中止发布。请注意上面那条重算命令里的 `--registry`,也请注意门禁自己也会带上它:一台配置了**镜像**的机器可以成功应答,却落后 3,418 秒。这是准备 `0.21.35` 时在本机量到的——这台机器的 `npm` 指向 `registry.npmmirror.com`,它的 packument 仍报 `modified: 00:32:51Z`(也就是 `0.21.33` 那次发布),而门禁运行在 `03:41:18Z`——比 npmjs 在 `02:47:50Z` 记下 `0.21.34` 晚 3,207 秒(53 分钟)——镜像自己的 `modified` 直到 `03:44:48.778Z` 才动,比那条记录晚 3,418 秒,于是门禁把一个已经公开的版本判成"registry 从未记录",而这一次读取是**成功**的。镜像的同步滞后不是 HTTP 缓存,所以 `cache-control: no-cache` 拿回来的还是同一份旧文档;只有显式点名 registry 才能纠正。`verify-published-consumer.mjs` 早已为它的两次读取钉住了 registry,这里是仓库里最后一处没有钉的 npm 读取。正在打 tag 的那个版本本身被豁免,因为它此刻本来就不该在 npm 上。
|
|
27
27
|
|
|
28
28
|
## 安全与依赖扫描
|
|
29
29
|
|
|
@@ -43,6 +43,6 @@
|
|
|
43
43
|
2. 在干净消费者中安装已发布版本或 tarball,并导入主入口及所有公开子路径。
|
|
44
44
|
3. 将结果记录到发布说明。在公开 API 和协议弃用策略明确冻结前,不进入 `1.0.0`。
|
|
45
45
|
|
|
46
|
-
打 tag 的发布工作流已自动执行上述消费者验证;仅在需要离线复验时才手动运行 `PUBLISHED_VERSION=<version> pnpm verify:published`。工作流的 12 分钟上限不是凑数,而是两段实测延迟之和。第一段:`npm publish` 返回成功后,registry 还要几分钟才把这条版本记进去——0.21.27 到 0.21.
|
|
46
|
+
打 tag 的发布工作流已自动执行上述消费者验证;仅在需要离线复验时才手动运行 `PUBLISHED_VERSION=<version> pnpm verify:published`。工作流的 12 分钟上限不是凑数,而是两段实测延迟之和。第一段:`npm publish` 返回成功后,registry 还要几分钟才把这条版本记进去——0.21.27 到 0.21.35 的"发布确认 → `time[<version>]`"间隔实测为 74.8–310.0 秒,按版本顺序分别是 248.7 / 96.8 / 74.8 / 310.0 / 127.2 / 76.1 / 75.5 / 75.8 / 127.3 秒——九个值,数一遍上面那份枚举就是(自己去 packument 读 `time[<version>]`,再和工作流 `Publish to npm` 步骤的完成时刻相减)。其中连续三次(0.21.32–0.21.34)落在 76.1、75.5、75.8 秒,跨度只有 0.6 秒,本段据此写过"落库很稳";**接着 0.21.35 回到了 127.3 秒**,所以那半秒只是三个样本,不是这个量的性质。九个值真正支持的结论更弱、也更够用:落库延迟落在 74.8–310.0 秒之间,没有任何一次超过决定预算的 310 秒;而在它自己跨越一分钟的同时,那一步在十次绿色运行里每次都吃掉 304–308 秒——会变的其实是"记录已经存在之后,读者还要瞎多久",那是第二段,不是这一段。第二段:`npm pack` 用来解析版本的 packument 是以 `cache-control: public, max-age=300` 提供的,也就是说路径上任何一份副本按设计都可以旧五分钟,落在这一窗口内写入的版本,解析不太可能快过一整个缓存生命周期。究竟是哪个副本(npm 本地缓存,还是中间的 CDN)在下面提供了过期视图**并未确立**,而这段文字此前用作"反对纯本地解释"的那个观测,仔细读过之后站不住,因为它把两台机器拼成了一句话:21:44:34Z 那次"新鲜读取"是在笔记本上跑 `npm pack`,而 21:47:10Z 一秒就绿的是一次*全新的 runner 任务*,新任务的 npm 缓存本来是空的——这恰好是纯本地模型预测的结果,不是反驳它的结果。纯本地模型仍然解释不了的,只有一个读数:runner 自己在 21:45:07Z 仍然报 `ETARGET`——距离开始轮询的那一步(21:39:03Z)已经 364 秒,也就是比"那一刻抓到的副本必然已过期"的时间点(21:44:03Z,误差在请求真正发出的那一秒之内)还要晚约 60 秒。因此上限靠的是算术而不是模型:最坏情况的"确认 → `time[]`"间隔,加上一个缓存生命周期。这个和并非理论值——上一个 6 分钟上限被一次*成功*的发布排空过:0.21.30 的 tag 运行把整整 360 秒预算(48 × 7.5 秒)花在 `ETARGET` 上,而那时该版本的 tarball HEAD 和本地 `npm pack` 都已经成功;123 秒后同一步骤只用了 1 秒。0.20.89 针对它当时的 2 分钟预算也是同一形状。所以长时间的反复重试是正常的传播延迟,不是镜像异常慢——只有"确认 → `time[]`"间隔本身变长了,才需要继续调大 `PUBLISHED_VERIFY_ATTEMPTS` 和 `PUBLISHED_VERIFY_DELAY_MS`。手动复验时要注意这个不对称:`verify-published-consumer.mjs` 的默认值是 `6` 次 × `5_000` ms——30 秒而不是 12 分钟——因为更大的那一对是由 tag 工作流以 env 传入、而非脚本自带。于是手动复跑可能在一个 CI 全绿的版本上报出 `ETARGET`,这看起来像发布失败而实际不是;要对齐 CI 预算就显式执行 `PUBLISHED_VERSION=<version> PUBLISHED_VERIFY_ATTEMPTS=96 PUBLISHED_VERIFY_DELAY_MS=7500 pnpm verify:published`,否则请按你实际跑到的 30 秒预算来判断手动失败。把这个步骤的耗时当诊断读数而不是情绪指标:0.21.25 到 0.21.29 那五次*绿色* tag 运行分别用了 307、304、305、304、304 秒,0.21.31 用了 308 秒,0.21.32、0.21.33 与 0.21.34 各用了 304 秒——九个样本落在 5 秒的区间里,而这正是"一个 300 秒缓存生命周期 + 几秒命令时间"会预测出的形状(数字自己取:对每次发布运行 `gh api` 出来的 jobs 里,`Verify published npm consumers` 这一步的 `steps[].started_at`/`completed_at`)。0.21.31 到 0.21.34 是头四个跑在提高后的 720 秒上限下的发布,而它们几段延迟的切分方式不同,这个对照正是有用的地方:第一次是 127.2 秒落库 + 约 181 秒缓存;第二次是 76.1 秒落库 + 之后约 228 秒 runner 仍看不见它;第三次是 75.5 秒落库 + 约 229 秒;第四次是 75.8 秒落库 + 约 228 秒——在 0.21.32 上,笔记本在 151 秒时用 `no-cache` 读 packument 已经能看到新的 `latest`,而 runner 自己的轮询一直到 304 秒才成功,也就是从*它自己*首次抓取算起整整一个生命周期。所以当初定这个上限的那个样本至今没有被超过:如果*确认 → `time[]`*这一段自己长过了 310 秒,就再调大 `PUBLISHED_VERIFY_ATTEMPTS`;而几秒就结束的 verify 只说明它读到的那份副本已经带上了新版本。
|
|
47
47
|
|
|
48
|
-
**不要用 `dist-tags.latest` 来判断发布是否发生。** 包文档端点与 tarball URL 是两条不同的读取路径,而它们的时间戳比这两条路径给的第一手印象更值得读。0.21.30 发布期间按顺序读到:`npm publish` 在 `21:39:03Z` 返回成功;`21:43:15Z` 的一次 `curl -s -H "Cache-Control: no-cache" https://registry.npmjs.org/<pkg>` 仍报 `latest` 是上一个版本、`versions` 里没有 `0.21.30`、`time['0.21.30']` 也不存在;而 npm 自己给这个版本盖的时间戳是 `21:44:12.987Z`,文档的 `last-modified` 是 `21:44:14 GMT`。所以 21:43:15 那次读取**不是**一份副本在拒绝已经存在的产物——registry 当时确实还没把这次发布记完,`no-cache` 也不可能让它看见尚不存在的版本;在发布步骤全绿之后的几分钟里,`versions` 与 `latest`
|
|
48
|
+
**不要用 `dist-tags.latest` 来判断发布是否发生。** 包文档端点与 tarball URL 是两条不同的读取路径,而它们的时间戳比这两条路径给的第一手印象更值得读。0.21.30 发布期间按顺序读到:`npm publish` 在 `21:39:03Z` 返回成功;`21:43:15Z` 的一次 `curl -s -H "Cache-Control: no-cache" https://registry.npmjs.org/<pkg>` 仍报 `latest` 是上一个版本、`versions` 里没有 `0.21.30`、`time['0.21.30']` 也不存在;而 npm 自己给这个版本盖的时间戳是 `21:44:12.987Z`,文档的 `last-modified` 是 `21:44:14 GMT`。所以 21:43:15 那次读取**不是**一份副本在拒绝已经存在的产物——registry 当时确实还没把这次发布记完,`no-cache` 也不可能让它看见尚不存在的版本;在发布步骤全绿之后的几分钟里,`versions` 与 `latest` 里没有这个版本,对 `0.20.92` 起的每一次成功发布都是正常状态——那 42 个版本在 2026-09-25 全部量过,被记下最少也要 74.8 秒——而窗口之前的那五次(`0.20.86`、`0.20.87`、`0.20.88`、`0.20.90`、`0.20.91`)在 ack 前后 ±0.6 秒内就记录好了,1 秒即可解析。所以这句话描述的是这个窗口,而不是 npm 本身;当它成立时,该怎么判断并没有变。真正的读取路径分歧出现在 60 秒之后:`21:44:14Z` 到 `21:44:35Z` 之间,`curl -I …/-/<pkg>-0.21.30.tgz` 返回 `HTTP 200`,本地一次 `npm pack <pkg>@0.21.30 --registry https://registry.npmjs.org` 也成功写出了 tarball,而工作流 runner 自己的 `npm pack` 一直 `ETARGET` 到 `21:45:07Z` 把预算排空。同一个版本、两台机器、相隔一分钟给出相反答案。要回答"发布到底成没成",去 HEAD 那个 tarball URL 并试一次 pack——它们摸到的是产物本身——而且要从**正在失败的那台机器**上去试,因为"能取到"是一台机器才有的答案;`latest` 只回答"消费者默认拿到哪个版本",那是另一个问题,而且会更晚才稳定。`npm view <pkg> version` 在这之上还有第三条路径:它可能来自 npm 的**本地** packument 缓存,于是在发布前查过一次的机器上,即使全局 `latest` 已经前进,它仍会返回被取代的旧版本——这正是本门禁把目标版本固定取自 `PUBLISHED_VERSION`、并拒绝与 `package.json` 不一致的推断值的原因。不要因为一次元数据读取看起来过期就重推、移动或替换 tag;发布出去的 tag 是不可变的。
|
package/docs/zh/roadmap.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# 路线图
|
|
2
2
|
|
|
3
|
-
0.21.
|
|
3
|
+
0.21.36 已于 2026 年 9 月 25 日发布。项目会先持续完成可靠性发布,再进入 1.0.0 稳定性冻结。
|
|
4
|
+
|
|
5
|
+
## 0.21.36 已完成范围
|
|
6
|
+
|
|
7
|
+
- **两条已发布的注释与其描述的代码相互矛盾,而发现它们的方式是计数,不是阅读。** `src/centrifuge.ts` 的分发器注释声称有三个监听器,实际是同一个函数注册了两次——三个来源、两个调用点——而这句话会经由 `dist/centrifuge.d.ts` 发布,因为 `private` 成员会保留其声明文档。`src/core/trace.ts` 引用了一个测试总数,而它已经失效两次,同一句话却同时告诉读者如何重新推导;该数值被删除,因为写在自己查找方法旁边的数字,恰恰是没人会去核对的那一种。找到它们的这次扫描把 `src/` 中十四条数值断言逐一与代码树比对,十二条成立——其中包括 `centrifuge@5.7.4` 里 `BaseSubscription` 内的十二处 `emit('error')`(整个文件为 23 处),让这个断言成立的正是那个范围限定。
|
|
8
|
+
- **`CONTRIBUTING.md` 第一次被逐条核对,其中四条断言与仓库相互矛盾。** 覆盖率阈值低于真正的阻塞门禁(写的是 85/80/90/85,而 `vitest.config.ts` 是 98/96/98/99);`pnpm check` 的释义写了一个测试数量却漏掉 lint;发版一节要求 `npm version` 加 `git push origin main --tags`——即在本地 HEAD 上打 tag 并直接推送受保护分支,正是本仓库禁止的两个操作;`[Unreleased]` 在四处被当作约定,而 `CHANGELOG.md` 中这样的标题数为零,非发版 PR 都直接开版本号小节。四处现在都以配置文件与发版检查清单为事实来源。
|
|
9
|
+
- **发布延迟的操作方法写了一个参数却没说怎么选,同时样本序列从九个版本扩展到全部 tag。** 不带 attempt 段的 jobs 接口返回*最新*那一次,因此在那个重跑过的版本上,最直接的简写形式给出 −177.0 秒与 1.0 秒的消费者步骤,而 attempt 1 才是真实的 310.0 秒间隔与 364 秒失败;两份语言清单和 workflow 注释现在都写明 attempt 该从哪里取。在 `0.20.85` 起的全部 48 个 tag 上:44 个非负的 ack→记录间隔,最大 310.0 秒,于是 720 秒的传播预算维持不变——而“注册表在数分钟后才记录”这一前提被限定在 `0.20.92` 之后的窗口,因为更早的五个版本在 ±0.6 秒内就完成了记录,其中三个早于 ack 返回。
|
|
10
|
+
- **`AGENTS.md` 的目录地图已经完整并被门禁守住。** 它此前只列出 `tests/` 下 43 个文件中的 16 个,因此在这一块写就之后新增的测试框架、文档门禁、发版门禁与基准文件,对最先读它的会话全部不可见。如今它覆盖 `src`/`tests`/`e2e` 的每个被跟踪文件,外加每个代码目录一行,并且新的用例把这个小节的*边界*也钉住——因为围栏取位若偏移一格,“每个名字都在块里”对一份只是在别处讨论这些文件的文档同样成立。五个变异体,五次不同的失败。
|
|
11
|
+
- **两个文档门禁的作用域一直是错的。** 隐私门禁遍历 `examples/` 且没有扩展名过滤,于是每次运行都在正则扫描 2.9 MB 被 gitignore 的打包产物与 sourcemap,而 CI 从不构建它们——这是一条“本机红、CI 绿”的通道;它的作用域现在是仓库自身的索引,并用构造出来的输入钉住,因此在干净树与已构建树上读起来一致。`CONTRIBUTING.md` 进入了引用、空小节与相对链接三种扫描,而每种新增都单独探测:三种里有两种在带该数组项时失败、只去掉它时通过,而引用那一类在该文件里没有可触发的条目,因此只能算预防性覆盖。
|
|
4
12
|
|
|
5
13
|
## 0.21.35 已完成范围
|
|
6
14
|
|
|
@@ -15,7 +23,7 @@
|
|
|
15
23
|
|
|
16
24
|
## 0.21.34 已完成范围
|
|
17
25
|
|
|
18
|
-
- **发布记录里点名了一个 npm 从未有过的版本时,打 tag 现在会被拒绝。** `scripts/verify-release-version.mjs` 在原有检查旁边读入 packument 的 `time` 映射,只要 `firstGatedRelease = 0.20.85` 及以上有某段 CHANGELOG 版本在 registry 里没有记录就失败。正在发布的那个版本按必要豁免,重复的小节只报一次,而读取 registry 失败时**告警并跳过**,不去把一次好发布判红——这是设计里刻意的那一半。下限来自计数而非口味:
|
|
26
|
+
- **发布记录里点名了一个 npm 从未有过的版本时,打 tag 现在会被拒绝。** `scripts/verify-release-version.mjs` 在原有检查旁边读入 packument 的 `time` 映射,只要 `firstGatedRelease = 0.20.85` 及以上有某段 CHANGELOG 版本在 registry 里没有记录就失败。正在发布的那个版本按必要豁免,重复的小节只报一次,而读取 registry 失败时**告警并跳过**,不去把一次好发布判红——这是设计里刻意的那一半。下限来自计数而非口味:CHANGELOG 的 165 段里有 40 段点名了未发布的版本(总数自己重算:`grep -c '^## \[' CHANGELOG.md`;每发布一次就加一,所以这个总数不是论证的那一半)(`0.9.0`、`0.12.0` 到 `0.18.0` 每个 minor 的第一个 patch、`0.19.x` 全部十条、`0.20.0`–`0.20.5`、`0.20.54`、`0.20.55`、`0.20.69`、`0.20.72`–`0.20.84`;1 + 7 + 10 + 6 + 2 + 1 + 13 = 40)——把正在发布的那一条也算进去就是 41 段,而闸门豁免它正是这个原因——而它们全都在下限之下;从 `0.20.85` 一直到 `0.21.33` 的 47 条则一条不缺(这个数是本次 tag 自己的读数,每发布一次就加一,要取的是脚本打印的那一行)。四个变异体,四条具名测试,每次只红一条。
|
|
19
27
|
- **有一个淘汰跳过项没有任何测试能看见。** `rememberTopic()` 会跳过持有的 key *以及*本次正在记忆的 key;删掉后一项时 944 条测试全绿。它只在一种状态里可达:新写入的 `Map.set` 落在插入有序 Map 的**末尾**,所以只有更早的条目全部被持有时,从头扫描才会走到它——而在那里变异体丢掉的正是这次调用本要建立的映射。新用例摆出 500 条被收养的 peer SUBSCRIBE 帧加一条 PUBLISH,失败信息是 `expected [ 'owned.0', …(498) ] to include 'evict.extra'`;持有项仍由那条既有用例钉住,于是两个跳过各自有各自的击杀集。先前两种设计写不进去,原因记在用例注释里,因为它们看着合理却碰不到这条腿:入站 SUBSCRIBE 产生不出"未持有"的条目,而重复记忆一个已在表里的 key 撑不爆上限。
|
|
20
28
|
- **三句关于上限的既定文字,描述的是代码并不提供的保护。** `MAX_KNOWN_TOPICS = 500` 曾被写成"防止恶意 peer 借控制消息耗尽内存";实测 1,200 条 peer `CONTROL/SUBSCRIBE` 让 `knownTopics` 和 `assignedTopics` 一起涨到 1,200——每个帧都会被收养,收养使它的 key 变为持有,而扫描随即拒绝删除任何东西;一轮 reconcile 把两者带回 `0`,所以洪水的界是清扫,上限的界只覆盖未持有的条目。`trace.ts` 把它的两个上限都说成在防"单个失控 topic",而 `MAX_PENDING_TOPICS` 其实是对*不同* topic 的准入闸门(1,001 个 topic 得到 1,000 条队列,而一个已准入的 topic 仍会长到 256),`topics` 这张集合两个上限都不加,是刻意为之,由窗口刷新增界。同一份架构文档里的标识符表仍按修正前的说法复述淘汰规则,而它旁边那行漏掉了 `reconcileAssignedTopics`——唯一真正结束洪水的通路。两种语言全部改正,`src/` 的注释改为指向那个循环和那些测试,而不是把规则复述两遍。
|
|
21
29
|
- **与既有用例重复的候选测试应当删掉,而不是留下。** trace 的两个上限看起来没人钉,是因为检索用的是常量名,而那两条真正钉住它们的用例把数字写在注释里、通篇没提这两个标识符。两条新用例都写好了,随后变异检测报告:删掉准入守卫会红**两**条——新写的那条,以及输入规模更大的 `caps the number of topics tracked for pending receives`。于是新用例被删除,注释改为引用既有用例的名字。本次发布因此只新增一条测试(淘汰跳过项),不删除任何测试。
|
|
@@ -993,7 +1001,7 @@ DataBus 生命周期审计还固定了 initial `transport.start()` 被 `stop()`
|
|
|
993
1001
|
|
|
994
1002
|
## 发版检查清单
|
|
995
1003
|
|
|
996
|
-
-
|
|
1004
|
+
- 写好本次发布自己的 `## [x.y.z] - 日期` 一节(仓库已不再维护 `[Unreleased]` 段——版本标题在变更自身的 PR 里开出,权威流程见 `docs/zh/release-checklist.md`);
|
|
997
1005
|
- 执行 `pnpm check`、`pnpm lint`、`pnpm test:e2e`、`pnpm bench`、`pnpm bench:browser`;
|
|
998
1006
|
- 从打包 tarball 做 ESM/CJS 消费冒烟验证;
|
|
999
1007
|
- 推送 tag 后核验 GitHub Release 与 npm `latest` dist-tag。
|
package/package.json
CHANGED