mustflow 2.117.0 → 2.117.1
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/package.json +1 -1
- package/templates/default/i18n.toml +8 -2
- package/templates/default/locales/en/.mustflow/skills/INDEX.md +11 -3
- package/templates/default/locales/en/.mustflow/skills/connection-lifecycle-integrity-review/SKILL.md +302 -0
- package/templates/default/locales/en/.mustflow/skills/connection-lifecycle-integrity-review/references/connection-fault-injection-resource-lifetime-validation.md +277 -0
- package/templates/default/locales/en/.mustflow/skills/connection-lifecycle-integrity-review/references/node-stream-transport-lifecycle-checklist.md +381 -0
- package/templates/default/locales/en/.mustflow/skills/memory-lifetime-review/SKILL.md +94 -2
- package/templates/default/locales/en/.mustflow/skills/memory-lifetime-review/references/cross-runtime-memory-stream-reproduction-harness.md +289 -0
- package/templates/default/locales/en/.mustflow/skills/memory-lifetime-review/references/node-memory-resource-backpressure-diagnostics.md +369 -0
- package/templates/default/locales/en/.mustflow/skills/routes.toml +17 -0
- package/templates/default/manifest.toml +12 -1
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
mustflow_doc: skill.memory-lifetime-review
|
|
3
3
|
locale: en
|
|
4
4
|
canonical: true
|
|
5
|
-
revision:
|
|
5
|
+
revision: 5
|
|
6
6
|
lifecycle: mustflow-owned
|
|
7
7
|
authority: procedure
|
|
8
8
|
name: memory-lifetime-review
|
|
9
|
-
description: Apply this skill when code is created, changed, reviewed, or reported and object lifetime, retained references, cleanup symmetry, event listeners, timers, subscriptions, goroutines, threads, workers, streams, native handles, caches, queues, or memory/resource leak risk may matter.
|
|
9
|
+
description: Apply this skill when code is created, changed, reviewed, diagnosed, validated, or reported and object lifetime, retained references, cleanup symmetry, event listeners, timers, subscriptions, goroutines, threads, workers, streams, native handles, caches, queues, RSS, heap, external memory, ArrayBuffer or Buffer retention, allocator fragmentation, unbounded buffering, cross-runtime reproduction, backpressure, or memory/resource leak risk may matter.
|
|
10
10
|
metadata:
|
|
11
11
|
mustflow_schema: "1"
|
|
12
12
|
mustflow_kind: procedure
|
|
@@ -41,6 +41,11 @@ The question is not only "where was it allocated?" The stronger review question
|
|
|
41
41
|
- Code adds lifecycle setup such as `new`, `open`, `connect`, `subscribe`, `observe`, `addEventListener`, `setInterval`, `setTimeout`, `context.WithCancel`, `ThreadLocal.set`, `malloc`, `retain`, `shared_ptr`, `Rc`, task spawning, stream creation, or cache insertion.
|
|
42
42
|
- Code uses closures, callbacks, lambdas, async work, promises, channels, effects, refs, logging queues, metrics queues, debug arrays, maps, or registries that may capture or store large or short-lived objects.
|
|
43
43
|
- A review or final report claims that a path is leak-free, bounded, cleaned up, disposable, safe for repeated mount/unmount, safe for long-running processes, safe under retries, or safe for repeated requests.
|
|
44
|
+
- A Node.js service or streaming pipeline needs to distinguish JavaScript heap retention, external
|
|
45
|
+
buffers, native allocations, cache growth, handle leakage, allocator residency, and live
|
|
46
|
+
backpressure backlog instead of naming all RSS growth a memory leak.
|
|
47
|
+
- A Node-compatible memory or stream symptom needs a same-source Node.js, Bun, adapter, runtime
|
|
48
|
+
version, or operating-system reproduction matrix without mixing application and runtime changes.
|
|
44
49
|
|
|
45
50
|
<!-- mustflow-section: do-not-use-when -->
|
|
46
51
|
## Do Not Use When
|
|
@@ -60,7 +65,18 @@ The question is not only "where was it allocated?" The stronger review question
|
|
|
60
65
|
- Repetition path: repeated requests, screen open/close, route changes, tab switches, reconnects, retries, scheduled runs, test cases, or long-running sessions that can accumulate retained state.
|
|
61
66
|
- Error and success paths: normal completion, early return, partial read, cancellation, timeout, retry, exception, unmount, shutdown, and dependency failure behavior.
|
|
62
67
|
- Diagnostic evidence for native or low-level memory faults: first sanitizer or memory-checker report, invalid write/read address, watchpoint condition, allocator or quarantine behavior, fuzzing input, core dump, symbols, build id, shared library list, and configured or manual diagnostic boundary.
|
|
68
|
+
- Measurement classification for memory diagnosis: storage location, retention owner, terminal
|
|
69
|
+
status, post-GC or post-quiescent slope, queue-byte ledgers, process and protocol resource counts,
|
|
70
|
+
workload phases, and the statistical tolerance used for a leak or fragmentation claim.
|
|
63
71
|
- Relevant command-intent contract entries for tests, builds, docs, release checks, and mustflow validation.
|
|
72
|
+
- For Node.js RSS, heap, external-memory, Buffer, native-handle, cache, streaming, HTTP/2, HTTP/3,
|
|
73
|
+
or cross-layer backpressure diagnosis, read
|
|
74
|
+
`references/node-memory-resource-backpressure-diagnostics.md` before classifying cause or claiming
|
|
75
|
+
that a queue, leak, or allocator problem is resolved.
|
|
76
|
+
- For a Node.js or Bun cross-runtime memory, stream, socket, descriptor, handle, allocator, or
|
|
77
|
+
runtime-version reproducer, read
|
|
78
|
+
`references/cross-runtime-memory-stream-reproduction-harness.md` before designing the process
|
|
79
|
+
harness, comparator matrix, result manifest, or permanent-resolution gate.
|
|
64
80
|
|
|
65
81
|
<!-- mustflow-section: preconditions -->
|
|
66
82
|
## Preconditions
|
|
@@ -71,6 +87,12 @@ The question is not only "where was it allocated?" The stronger review question
|
|
|
71
87
|
- If authorization, secrets, personal data, telemetry, or audit records are retained, also use `security-privacy-review`.
|
|
72
88
|
- If queue, cache, retry, worker, health, or operational behavior changes, also use `backend-reliability-change`.
|
|
73
89
|
- If user-perceived latency, throughput, allocation churn, GC pressure, or memory budget is claimed, also use `performance-budget-check`.
|
|
90
|
+
- If counter, slope, denominator, benchmark, or regression-gate semantics dominate, also use
|
|
91
|
+
`performance-measurement-integrity-review`.
|
|
92
|
+
- If socket, session, request-body, FIN/RST, pool reuse, or transport shutdown semantics dominate,
|
|
93
|
+
also use `connection-lifecycle-integrity-review`.
|
|
94
|
+
- If the reported symptom does not yet have a deterministic reproduction, also use
|
|
95
|
+
`repro-first-debug` and keep exploratory runs separate from causal proof.
|
|
74
96
|
- If UI lifecycle, rendering, or browser behavior changes, also use the matching UI or framework skill.
|
|
75
97
|
|
|
76
98
|
<!-- mustflow-section: allowed-edits -->
|
|
@@ -79,6 +101,9 @@ The question is not only "where was it allocated?" The stronger review question
|
|
|
79
101
|
- Add or tighten teardown, cancellation, ownership, weak-reference, eviction, queue-bound, stream-close, worker-shutdown, and lifecycle-symmetry code tied to the task.
|
|
80
102
|
- Refactor setup and cleanup into a shared lifecycle boundary when it prevents duplicate registration or forgotten teardown.
|
|
81
103
|
- Add focused tests, fixtures, probes, or docs that prove cleanup symmetry, bounded retention, repeated lifecycle behavior, or native-resource disposal when repository evidence supports them.
|
|
104
|
+
- Add bounded owner, byte-flow, queue, post-GC, post-quiescent, handle, cache, or backpressure
|
|
105
|
+
instrumentation when it proves the changed lifetime boundary without retaining payloads or
|
|
106
|
+
sensitive context.
|
|
82
107
|
- Do not hide leak warnings by raising listener limits, disabling strict lifecycle checks, adding finalizers as primary cleanup, or weakening tests.
|
|
83
108
|
- Do not add object pools as a default leak or GC fix. Pool only heavy buffers, large arrays, native handles, or repeatedly allocated expensive objects after allocation evidence shows churn; ordinary short-lived records are often cheaper to let the generational collector reclaim.
|
|
84
109
|
- Do not use weak references as a design cover-up when the real owner and cleanup point should be explicit.
|
|
@@ -136,6 +161,53 @@ The question is not only "where was it allocated?" The stronger review question
|
|
|
136
161
|
15. Reject finalizers as the main plan. Finalizers, destructors, drop hooks, or weak callbacks can be last-resort diagnostics or safety nets, but the review should still identify deterministic cleanup for resources and reference removal.
|
|
137
162
|
16. Separate allocation churn from retained memory. High allocation rate, GC pauses, retained heap, external memory, and RSS growth point to different fixes. Prefer allocation timeline, heap snapshot, retaining-path, `--trace-gc`, sanitizer, or runtime memory evidence when configured; report unconfigured tools as manual evidence instead of guessing from RSS alone.
|
|
138
163
|
17. Add a repeated-lifecycle proof when feasible. Prefer a focused test or probe that repeats the risky lifecycle, then asserts listener count, registry size, cache size, goroutine/task completion, handle closure, queue depth, or retained object count. If heap snapshots, leak profilers, sanitizer runs, memory-checker runs, fuzzers, core dump inspection, or platform-specific diagnostics are not configured intents, report them as manual evidence gaps instead of running raw commands.
|
|
164
|
+
18. Classify memory growth on independent axes before choosing a fix.
|
|
165
|
+
- Name the storage location: managed heap, external or backing-store memory, other native
|
|
166
|
+
allocation, mapping, allocator residency, cache, application queue, or kernel buffer.
|
|
167
|
+
- Name the retaining owner: request, attempt, branch, stream, task, cache, pool, connection,
|
|
168
|
+
native operation, retry, or process service.
|
|
169
|
+
- Name the terminal state: legitimate in-flight work, bounded backlog, unbounded backlog,
|
|
170
|
+
terminal retained resource, or released allocation whose pages remain resident.
|
|
171
|
+
- Do not derive native memory by subtracting overlapping process and runtime totals.
|
|
172
|
+
19. Compare floors and slopes under controlled lifecycle phases.
|
|
173
|
+
- Fix concurrency, payload and chunk size, compression, protocol, retries, cache, branch count,
|
|
174
|
+
consumer rate, runtime, and allocator before comparison.
|
|
175
|
+
- Separate idle baseline, warmup, normal consumer, slow consumer, stopped consumer, admission
|
|
176
|
+
stop and drain, pool idle expiry, and optional isolated-GC phases.
|
|
177
|
+
- Prefer post-major-GC and post-quiescent growth per completed lifecycle with a predeclared
|
|
178
|
+
statistical tolerance over one RSS peak or literal zero-noise assertions.
|
|
179
|
+
20. Model shared and branched work as an ownership DAG.
|
|
180
|
+
- Separate process, pool, connection or session, logical request, retry or hedge attempt,
|
|
181
|
+
protocol stream, clone or tee branch, file, transform, and telemetry ownership.
|
|
182
|
+
- Require every request-owned lease and byte reservation to return once while allowing a healthy
|
|
183
|
+
shared connection, session, or bounded cache to outlive the request.
|
|
184
|
+
21. Trace backpressure from final commitment toward transport.
|
|
185
|
+
- Distinguish admitted, accepted, committed, released, cancelled, and discarded bytes at every
|
|
186
|
+
edge, keeping compressed, decoded, transformed, and durable byte domains separate.
|
|
187
|
+
- Stop the sink and identify the first edge whose queue continues to grow instead of plateauing
|
|
188
|
+
within its byte envelope; then resume and require drain and upstream progress to recover.
|
|
189
|
+
- Treat high-water marks as thresholds, not total caps, and include maximum chunk, in-flight
|
|
190
|
+
operations, side queues, branches, retries, codec expansion, protocol windows, and transport
|
|
191
|
+
buffers in the envelope.
|
|
192
|
+
22. Calibrate the diagnosis to available evidence.
|
|
193
|
+
- Call growth a terminal leak only when the owner should have ended and retained counts or bytes
|
|
194
|
+
grow with completed lifecycle repetitions.
|
|
195
|
+
- Call fragmentation only after live heap, external memory, cache, queues, handles, mappings,
|
|
196
|
+
and native allocation evidence no longer explains resident growth.
|
|
197
|
+
- Report heap snapshots, native profilers, platform handle inspection, packet capture, qlog, and
|
|
198
|
+
long-running load as manual-only or missing unless configured by the selected repository.
|
|
199
|
+
23. Design cross-runtime reproduction without changing the application and runtime together.
|
|
200
|
+
- Keep one shared compatibility-source case, a fixed observer, isolated server and client target
|
|
201
|
+
processes, explicit baseline/load/admission-stop/drain/quiescence phases, and fresh target
|
|
202
|
+
processes per measured run.
|
|
203
|
+
- Compare one factor at a time across producer rate, consumer delay, backpressure obedience,
|
|
204
|
+
finite versus continuing work, cancellation, reconnect, peer loss, concurrency, adapter,
|
|
205
|
+
runtime build, and operating-system cell. Treat ramps and multi-factor runs as exploratory.
|
|
206
|
+
- Record a versioned allowlisted manifest with configuration hash, observer identity, target
|
|
207
|
+
binary digest and build identity, environment cell, raw samples, completed work, queue and
|
|
208
|
+
resource conservation, repetitions, dispersion, and unsupported diagnostic phases.
|
|
209
|
+
- Call a newer green runtime version-localized or a fix candidate until last-bad, first-good,
|
|
210
|
+
comparable work, narrowed change, and forward or reverse change evidence establish cause.
|
|
139
211
|
|
|
140
212
|
<!-- mustflow-section: postconditions -->
|
|
141
213
|
## Postconditions
|
|
@@ -147,6 +219,13 @@ The question is not only "where was it allocated?" The stronger review question
|
|
|
147
219
|
- Async, stream, worker, goroutine, thread, and native-resource paths have deterministic cancellation, close, shutdown, or release behavior where the platform supports it.
|
|
148
220
|
- Native or low-level memory fault analysis names the first invalid access evidence or reports the missing diagnostic boundary instead of blaming the final crash line.
|
|
149
221
|
- Tests or configured verification cover the highest-risk repeated lifecycle when feasible.
|
|
222
|
+
- Memory-growth conclusions identify storage location, retention owner, terminal status, controlled
|
|
223
|
+
workload phase, and evidence level; RSS alone does not establish leak or fragmentation.
|
|
224
|
+
- Streaming and queue claims include accepted-versus-committed byte ownership, bounded plateau,
|
|
225
|
+
resume behavior, and a calculated envelope, or name the missing evidence.
|
|
226
|
+
- Cross-runtime claims preserve shared source, fixed observer, single-factor comparators, target
|
|
227
|
+
binary and environment identity, completed-work normalization, repeated samples, and causal-fix
|
|
228
|
+
boundaries, or remain exploratory or version-localized.
|
|
150
229
|
|
|
151
230
|
<!-- mustflow-section: verification -->
|
|
152
231
|
## Verification
|
|
@@ -173,6 +252,14 @@ Use the narrowest configured test, build, docs, release, or mustflow intent that
|
|
|
173
252
|
- If setup and cleanup live in separate owners, make the ownership transfer explicit or report the split as a residual leak risk.
|
|
174
253
|
- If repeated-lifecycle proof requires unconfigured heap, profiler, sanitizer, browser, device, or load-test access, report the missing manual evidence and complete the configured checks that are available.
|
|
175
254
|
- If leak reduction conflicts with product semantics, authorization, durability, observability, or retry behavior, use the relevant stronger skill and report the tradeoff.
|
|
255
|
+
- If queues drain but their maximum is unbounded, report an OOM or admission-control defect rather
|
|
256
|
+
than clearing the path merely because it is not a terminal leak.
|
|
257
|
+
- If RSS remains high after live owners fall, do not jump directly to fragmentation; report the
|
|
258
|
+
missing allocator, mapping, native-allocation, or platform evidence.
|
|
259
|
+
- If a runtime comparison changes source behavior, adapter, workload, environment, and runtime
|
|
260
|
+
together, reject causal attribution and split it into single-factor cells.
|
|
261
|
+
- If an external or attachment-linked harness file was not supplied as repository source, do not
|
|
262
|
+
claim it was implemented or executed; adapt only the observable procedure contract.
|
|
176
263
|
|
|
177
264
|
<!-- mustflow-section: output-format -->
|
|
178
265
|
## Output Format
|
|
@@ -183,6 +270,11 @@ Use the narrowest configured test, build, docs, release, or mustflow intent that
|
|
|
183
270
|
- Long-lived owners and short-lived objects checked
|
|
184
271
|
- Timers, listeners, subscriptions, streams, workers, goroutines, threads, native handles, caches, queues, registries, closures, and logs checked where relevant
|
|
185
272
|
- Weak metadata, object pooling, allocation churn, and GC diagnostics checked where relevant
|
|
273
|
+
- Storage location, retention owner, terminal status, post-GC and post-quiescent slope classification
|
|
274
|
+
- Request, attempt, branch, stream, shared-pool, cache, file, and native-operation ownership DAG
|
|
275
|
+
- Backpressure edge ledger, stopped-consumer plateau, resume behavior, and memory envelope
|
|
276
|
+
- Cross-runtime observer and target isolation, lifecycle phases, comparator matrix, result identity,
|
|
277
|
+
environment cells, completed-work normalization, and causal-fix classification
|
|
186
278
|
- First invalid access, diagnostic build axis, dangling ownership, fuzzing or core-dump evidence where relevant
|
|
187
279
|
- Cleanup symmetry changes made or recommended
|
|
188
280
|
- Repeated-lifecycle proof: configured, manual-only, missing, or not applicable
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# Cross-Runtime Memory and Stream Reproduction Harness
|
|
2
|
+
|
|
3
|
+
Use this reference when a memory, external-buffer, stream-queue, socket, file-descriptor, handle,
|
|
4
|
+
or allocator symptom must be reproduced across Node-compatible runtimes such as Node.js and Bun.
|
|
5
|
+
Use the main skill first for ownership and diagnosis. Use this reference to design the controlled
|
|
6
|
+
process harness and comparison evidence.
|
|
7
|
+
|
|
8
|
+
## Contents
|
|
9
|
+
|
|
10
|
+
1. [Freeze the comparison boundary](#1-freeze-the-comparison-boundary)
|
|
11
|
+
2. [Separate observer and target processes](#2-separate-observer-and-target-processes)
|
|
12
|
+
3. [Run explicit lifecycle phases](#3-run-explicit-lifecycle-phases)
|
|
13
|
+
4. [Collect a non-overlapping metric ledger](#4-collect-a-non-overlapping-metric-ledger)
|
|
14
|
+
5. [Change one factor per comparator](#5-change-one-factor-per-comparator)
|
|
15
|
+
6. [Make result identity reproducible](#6-make-result-identity-reproducible)
|
|
16
|
+
7. [Compare slopes, floors, and conservation](#7-compare-slopes-floors-and-conservation)
|
|
17
|
+
8. [Separate runtime, adapter, and operating-system cells](#8-separate-runtime-adapter-and-operating-system-cells)
|
|
18
|
+
9. [Narrow application versus runtime ownership](#9-narrow-application-versus-runtime-ownership)
|
|
19
|
+
10. [Require causal fix evidence](#10-require-causal-fix-evidence)
|
|
20
|
+
11. [Keep commands and artifacts bounded](#11-keep-commands-and-artifacts-bounded)
|
|
21
|
+
12. [Acceptance gate](#12-acceptance-gate)
|
|
22
|
+
|
|
23
|
+
## 1. Freeze the comparison boundary
|
|
24
|
+
|
|
25
|
+
Start with one source program that uses only the compatibility surface shared by every target
|
|
26
|
+
runtime. For a Node-compatible HTTP stream symptom, keep the request, response, Buffer,
|
|
27
|
+
EventEmitter, chunk production, consumer delay, cancellation, and accounting logic identical.
|
|
28
|
+
|
|
29
|
+
Do not replace the application API and runtime in the same comparison. If a native server adapter
|
|
30
|
+
such as `Bun.serve` is suspected, first establish the shared `node:http` comparator. Change only the
|
|
31
|
+
server adapter in the next cell. Otherwise an API difference, application rewrite, and runtime
|
|
32
|
+
difference become one confounded observation.
|
|
33
|
+
|
|
34
|
+
Freeze before measuring:
|
|
35
|
+
|
|
36
|
+
- scenario and expected terminal outcome;
|
|
37
|
+
- payload, chunk size, burst size, production rate, consumer rate, and compression;
|
|
38
|
+
- concurrency, connection reuse, retries, cancellation schedule, and total offered work;
|
|
39
|
+
- observation interval, warmup, load duration, quiescence interval, and stop deadline;
|
|
40
|
+
- runtime flags, allocator settings, container limits, CPU quota, and cache state;
|
|
41
|
+
- measurement schema, thresholds, normalization, repetitions, and statistical rule.
|
|
42
|
+
|
|
43
|
+
Treat an exploratory threshold as a trigger for a narrower experiment, not as a portable proof.
|
|
44
|
+
Queue, retained-memory, and RSS thresholds depend on chunk size, concurrency, runtime, allocator,
|
|
45
|
+
host pressure, and instrumentation overhead.
|
|
46
|
+
|
|
47
|
+
## 2. Separate observer and target processes
|
|
48
|
+
|
|
49
|
+
Use a fixed observer process to launch and sample separate server and client target processes. Keep
|
|
50
|
+
the observer runtime and implementation unchanged while target runtimes or versions vary.
|
|
51
|
+
|
|
52
|
+
The process split should preserve evidence when either target exits, crashes, is cancelled, or is
|
|
53
|
+
forcibly terminated. Use loopback or an equivalently isolated local transport unless the production
|
|
54
|
+
network path is the variable under study. Start every measured run in fresh target processes so
|
|
55
|
+
allocator and runtime state from a previous case does not contaminate the next case.
|
|
56
|
+
|
|
57
|
+
Keep three ledgers distinct:
|
|
58
|
+
|
|
59
|
+
| Ledger | Owner | Examples |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| Observer | Fixed harness process | target identity, OS samples, deadlines, result writing |
|
|
62
|
+
| Server target | Runtime under test | response queues, accepted writes, sockets, request lifecycle |
|
|
63
|
+
| Client target | Runtime under test | readable queues, consumed bytes, cancellation, client sockets |
|
|
64
|
+
|
|
65
|
+
Do not count observer timers, pipes, handles, listeners, or output buffers as target resources. Do
|
|
66
|
+
not let a killed client destroy the only copy of the server or OS evidence.
|
|
67
|
+
|
|
68
|
+
## 3. Run explicit lifecycle phases
|
|
69
|
+
|
|
70
|
+
Use the same ordered phases for every measured run:
|
|
71
|
+
|
|
72
|
+
| Phase | Required action | Evidence |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| Baseline | Start targets, complete runtime initialization, perform only configured or manual GC, then sample | Memory floors, sockets, descriptors or handles, listeners, timers |
|
|
75
|
+
| Warmup | Exercise enough work to initialize JIT, pools, parsers, and caches without entering the measured interval | Warm state and any one-time growth |
|
|
76
|
+
| Load | Run exactly one fixed case and sample at a declared cadence | Slopes, peaks, throughput, queue and request maxima |
|
|
77
|
+
| Admission stop | Stop creating new work while keeping targets alive | Closed cohort and remaining in-flight work |
|
|
78
|
+
| Drain or cancellation | Consume, cancel, disconnect, or kill according to the case | Terminal outcomes and resource-release progress |
|
|
79
|
+
| Quiescence | Wait a bounded interval for close, abort, error, native release, and pool expiry | Post-quiescent floor and unresolved owners |
|
|
80
|
+
| Post-GC observations | When supported and authorized, take at least two separated observations | Reachable heap or external retention versus delayed reclamation |
|
|
81
|
+
| Shutdown | End targets through the case-specific path and preserve the observer result | Exit status, final resource counts, incomplete cleanup |
|
|
82
|
+
|
|
83
|
+
Mark GC support per runtime and run. Exclude unsupported or failed GC phases from GC-retention claims
|
|
84
|
+
instead of treating them as zero. A forced collection is a diagnostic separator, not an application
|
|
85
|
+
cleanup mechanism.
|
|
86
|
+
|
|
87
|
+
## 4. Collect a non-overlapping metric ledger
|
|
88
|
+
|
|
89
|
+
Record runtime-internal and independent OS observations together, but preserve their semantics.
|
|
90
|
+
|
|
91
|
+
| Metric | What it supports | What it does not prove |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| Runtime RSS | Process resident growth as reported by the runtime | JavaScript leak or allocator cause |
|
|
94
|
+
| OS resident or working set | Independent process-residency observation | Live ownership or reclaimability |
|
|
95
|
+
| `heapUsed` | Managed heap currently used according to the runtime | Buffer, kernel, or all native ownership |
|
|
96
|
+
| `heapTotal` | Managed heap capacity reserved by the runtime | Live heap or leak size |
|
|
97
|
+
| `external` | Runtime-defined memory associated with managed objects | Every native allocation |
|
|
98
|
+
| `arrayBuffers` | Runtime-defined ArrayBuffer and Buffer backing-store memory | Cross-runtime identical accounting |
|
|
99
|
+
| Active socket registry | Application-observed live sockets | Kernel `TIME_WAIT` or every handle |
|
|
100
|
+
| File descriptors | Open files, sockets, pipes, and other descriptors | Exact leaked resource type without classification |
|
|
101
|
+
| Windows handle count | Open process handles across Windows object types | Socket count or Unix-FD equivalence |
|
|
102
|
+
| Active resource types | Runtime resource-type summary that may keep the event loop alive | Concrete handle identity or full OS inventory |
|
|
103
|
+
| Listener and timer ledger | Harness-known registrations and pending scheduled work | Every runtime-internal callback |
|
|
104
|
+
| Readable and writable queue lengths | Visible stream-layer queued bytes or objects | Kernel, TLS, parser, or hidden native queues |
|
|
105
|
+
| Per-request queue maximum | A single request or stream dominating memory | Whole-process memory |
|
|
106
|
+
| Open and terminal event counts | Missing lifecycle settlement or close imbalance | Cause without owner and path evidence |
|
|
107
|
+
|
|
108
|
+
For Node.js, `arrayBuffers` is included in `external`; do not add them as disjoint totals. Confirm
|
|
109
|
+
equivalent fields against the target runtime version because a Node-compatible API name does not
|
|
110
|
+
guarantee identical engine accounting. In object mode, queue lengths may count objects rather than
|
|
111
|
+
bytes; record the unit.
|
|
112
|
+
|
|
113
|
+
Track at least produced, accepted, committed or consumed, cancelled, discarded, and released bytes.
|
|
114
|
+
Keep server and client totals separate. A produced-minus-consumed gap can reside in application,
|
|
115
|
+
stream, runtime, kernel, or discarded work, so localize it with per-edge queues and terminal events.
|
|
116
|
+
|
|
117
|
+
## 5. Change one factor per comparator
|
|
118
|
+
|
|
119
|
+
Use paired cases that isolate one causal question:
|
|
120
|
+
|
|
121
|
+
| Comparator | Only changed factor | Question |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| Paced producer / fast producer | Production interval | Does producer rate trigger the symptom? |
|
|
124
|
+
| Fast consumer / slow consumer | Consumer delay | Does sink speed expose backlog? |
|
|
125
|
+
| Obey backpressure / ignore backpressure | Production admission after backpressure | Is growth application-created buffering? |
|
|
126
|
+
| Finite stream / continuing stream | Terminal production bound | Does cleanup depend on natural completion? |
|
|
127
|
+
| Graceful completion / mid-stream cancel | Cancellation schedule | Does abort cleanup release every owner? |
|
|
128
|
+
| One cancel / repeated reconnect | Lifecycle repetition | Does each completed cycle leave residue? |
|
|
129
|
+
| Graceful peer exit / forced peer loss | Peer termination mode | Does abrupt loss break finalization? |
|
|
130
|
+
| Fixed low / medium / high concurrency | Concurrency | Is cost linear, bounded, or explosive? |
|
|
131
|
+
|
|
132
|
+
A concurrency ramp is useful for finding a threshold, but it changes load continuously. Use it only
|
|
133
|
+
for exploration. Re-run fixed cells on both sides of the discovered threshold before attributing
|
|
134
|
+
cause.
|
|
135
|
+
|
|
136
|
+
The ignore-backpressure case is an intentional positive control, not a healthy implementation. It
|
|
137
|
+
should demonstrate that the harness can detect a growing visible queue. The obey-backpressure case
|
|
138
|
+
should plateau within a predeclared envelope and resume after drain.
|
|
139
|
+
|
|
140
|
+
## 6. Make result identity reproducible
|
|
141
|
+
|
|
142
|
+
Write a versioned allowlisted result manifest with:
|
|
143
|
+
|
|
144
|
+
- scenario name and configuration hash;
|
|
145
|
+
- absolute target binary identity represented safely, binary digest, runtime version, and runtime
|
|
146
|
+
revision or build identifier when available;
|
|
147
|
+
- observer build identity and result-schema version;
|
|
148
|
+
- operating-system release, architecture, CPU count, memory limit, container or cgroup boundary,
|
|
149
|
+
allocator class, and relevant runtime flags;
|
|
150
|
+
- payload, chunk, burst, production, consumer, concurrency, cancellation, and duration settings;
|
|
151
|
+
- warmup count, measured repetitions, order block, sample cadence, and GC support;
|
|
152
|
+
- terminal outcomes, throughput, queue maxima, slopes, post-quiescent floors, and evidence gaps.
|
|
153
|
+
|
|
154
|
+
Do not emit unrestricted arguments, environment variables, paths, URLs, headers, payloads, or
|
|
155
|
+
credentials. Store logical path labels or allowlisted environment fields. Treat NDJSON, heap,
|
|
156
|
+
allocation, trace, packet, and native-profile artifacts as sensitive evidence.
|
|
157
|
+
|
|
158
|
+
Reject a same-case runtime comparison when configuration hashes differ. For an intentional paired
|
|
159
|
+
case, allow the declared factor and reject every undeclared difference. A multi-factor exploratory
|
|
160
|
+
run may guide the next test but cannot prove a cause.
|
|
161
|
+
|
|
162
|
+
## 7. Compare slopes, floors, and conservation
|
|
163
|
+
|
|
164
|
+
Compare server and client separately. Use raw samples and report at least:
|
|
165
|
+
|
|
166
|
+
- runtime and OS residency slopes during the fixed load phase;
|
|
167
|
+
- managed heap, external, and ArrayBuffer slopes and post-quiescent deltas;
|
|
168
|
+
- visible stream-queue slope, maximum total queue, and maximum per-request queue;
|
|
169
|
+
- active sockets, descriptors or handles, listeners, timers, and open-minus-terminal counts;
|
|
170
|
+
- produced, accepted, committed or consumed, cancelled, discarded, and released byte differences;
|
|
171
|
+
- throughput-normalized memory growth when runtimes complete materially different work;
|
|
172
|
+
- median, dispersion, practical threshold, uncertainty decision, and rejected outliers.
|
|
173
|
+
|
|
174
|
+
Do not call a faster runtime leakier merely because it processed more bytes in the same wall time.
|
|
175
|
+
Preserve absolute memory and memory per completed unit. Likewise, a slower candidate is not fixed if
|
|
176
|
+
it merely produces fewer bytes before the deadline.
|
|
177
|
+
|
|
178
|
+
Use interleaved or randomized comparison blocks on the same machine when feasible. Avoid running
|
|
179
|
+
every old-runtime sample before every new-runtime sample because temperature, CPU boost, file cache,
|
|
180
|
+
system load, and memory pressure drift with time. Never rerun until a favorable sample appears.
|
|
181
|
+
|
|
182
|
+
Require conservation within a declared snapshot tolerance. Examples include started equals terminal
|
|
183
|
+
plus in-flight, accepted writes equal settled writes plus pending writes, and reserved bytes equal
|
|
184
|
+
current plus released or terminally discarded bytes.
|
|
185
|
+
|
|
186
|
+
## 8. Separate runtime, adapter, and operating-system cells
|
|
187
|
+
|
|
188
|
+
Build the matrix in layers:
|
|
189
|
+
|
|
190
|
+
1. Compare the same compatibility-source case on the problem runtime and a control runtime.
|
|
191
|
+
2. Compare the problem runtime with the immediately relevant prior or candidate build.
|
|
192
|
+
3. Change only the server adapter, such as compatibility HTTP versus a native server surface.
|
|
193
|
+
4. Change only the protocol layer, such as HTTP versus a raw TCP stream.
|
|
194
|
+
5. Repeat the same bad and good pair on a second representative operating-system cell.
|
|
195
|
+
|
|
196
|
+
Keep Linux glibc, Linux musl, container or cgroup Linux, macOS architectures, Windows architectures,
|
|
197
|
+
and WSL as distinct environment cells. Compare absolute RSS only within compatible OS,
|
|
198
|
+
architecture, allocator, and resource-limit boundaries. WSL is a Linux kernel environment for this
|
|
199
|
+
purpose, not a Windows IOCP cell.
|
|
200
|
+
|
|
201
|
+
Record allocator and memory-limit evidence. A stable managed heap with elevated RSS can reflect
|
|
202
|
+
allocator residency or unmeasured native ownership, but this pattern alone does not distinguish the
|
|
203
|
+
two.
|
|
204
|
+
|
|
205
|
+
## 9. Narrow application versus runtime ownership
|
|
206
|
+
|
|
207
|
+
Use the smallest next single change supported by the result:
|
|
208
|
+
|
|
209
|
+
| Observation | Next boundary |
|
|
210
|
+
|---|---|
|
|
211
|
+
| Ignore-backpressure grows on all runtimes; obey case is bounded | Application admission and queue policy |
|
|
212
|
+
| Shared compatibility source fails on only one runtime | That runtime's compatibility HTTP, stream, or socket bridge |
|
|
213
|
+
| Compatibility and native server adapters both fail | Shared stream, socket, allocator, or engine layer |
|
|
214
|
+
| Only the native server adapter fails | Native response sink, abort, and backpressure path |
|
|
215
|
+
| Raw TCP also fails | HTTP parser is below the likely boundary; inspect TCP, buffer, poller, or event loop |
|
|
216
|
+
| Raw TCP is bounded | HTTP request, response, parser, or adapter lifecycle |
|
|
217
|
+
| Fresh Buffer allocation fails but reuse is bounded | Backing-store allocation and release path |
|
|
218
|
+
| Buffer reuse also fails | Request, stream, socket, or hidden queue ownership |
|
|
219
|
+
| Descriptors or handles remain after close | Socket, poll, watcher, file, or process-resource finalization |
|
|
220
|
+
| All owned resources return but RSS remains | Allocator or unmeasured native-memory diagnostics |
|
|
221
|
+
|
|
222
|
+
Classify the owner as application, library or adapter, runtime, dependency, allocator, operating
|
|
223
|
+
system, or unresolved. A green case at one layer only removes hypotheses that the comparator
|
|
224
|
+
actually held constant.
|
|
225
|
+
|
|
226
|
+
## 10. Require causal fix evidence
|
|
227
|
+
|
|
228
|
+
A symptom disappearing in a newer runtime is a candidate signal, not root-cause proof. Large runtime
|
|
229
|
+
or engine changes can alter allocator behavior, HTTP implementation, throughput, scheduling, and
|
|
230
|
+
object lifetime together.
|
|
231
|
+
|
|
232
|
+
For a permanent-resolution claim, require where feasible:
|
|
233
|
+
|
|
234
|
+
- exact last-bad and first-good build identities and binary digests;
|
|
235
|
+
- comparable completed work and the healthy control case remaining healthy;
|
|
236
|
+
- a narrowed runtime or dependency change interval;
|
|
237
|
+
- the candidate change applied to the bad base and the symptom removed;
|
|
238
|
+
- the candidate change removed from the good base and the symptom restored;
|
|
239
|
+
- upstream cause identity for vendored engine, allocator, parser, or event-loop changes;
|
|
240
|
+
- a regression guard on bounded queues, post-quiescent ownership, and resource return rather than
|
|
241
|
+
an RSS-only literal threshold;
|
|
242
|
+
- repeated results and at least one second relevant environment cell.
|
|
243
|
+
|
|
244
|
+
If patch and revert builds are unavailable, report the result as version-localized or a fix
|
|
245
|
+
candidate. Do not upgrade the claim to causal resolution.
|
|
246
|
+
|
|
247
|
+
## 11. Keep commands and artifacts bounded
|
|
248
|
+
|
|
249
|
+
This reference does not authorize launching servers, load generators, child-process campaigns,
|
|
250
|
+
runtime downloads, profilers, packet tools, heap snapshots, dependency installs, network calls, or
|
|
251
|
+
long-running loops. Map execution to configured one-shot command intents. Mark unavailable runtime,
|
|
252
|
+
OS, profiler, or soak cells as manual-only or missing.
|
|
253
|
+
|
|
254
|
+
When authoring a durable repository harness, follow the repository's supported scripting runtime and
|
|
255
|
+
place it under the repository's declared test or tooling boundary. Give every run a hard deadline,
|
|
256
|
+
closed stdin, output cap, process-tree cleanup, isolated output directory, and maximum memory or
|
|
257
|
+
workload safety stop. Preserve the primary failure if cleanup also fails.
|
|
258
|
+
|
|
259
|
+
Do not claim an attachment-linked or external harness file exists in the repository unless its bytes
|
|
260
|
+
were supplied and admitted as a source artifact. A prose design can justify a reference contract,
|
|
261
|
+
not an executable harness implementation.
|
|
262
|
+
|
|
263
|
+
## 12. Acceptance gate
|
|
264
|
+
|
|
265
|
+
Accept the reproduction design only when:
|
|
266
|
+
|
|
267
|
+
- observer, server, client, and OS evidence owners are separated;
|
|
268
|
+
- shared-source runtime comparison changes no application behavior;
|
|
269
|
+
- lifecycle phases and closed-cohort termination are explicit;
|
|
270
|
+
- metric units do not overlap or silently change across runtimes;
|
|
271
|
+
- every paired comparator declares exactly one changed factor;
|
|
272
|
+
- result identity includes runtime build and configuration evidence;
|
|
273
|
+
- comparison uses repeated raw samples, dispersion, and completed-work normalization;
|
|
274
|
+
- environment cells are compared within compatible boundaries;
|
|
275
|
+
- application, adapter, runtime, allocator, and OS attribution remains no broader than the evidence;
|
|
276
|
+
- a newer green version is not called causal without last-bad, first-good, and forward or reverse
|
|
277
|
+
change evidence;
|
|
278
|
+
- unconfigured runtime, load, GC, profiler, packet, and OS diagnostics remain manual-only or missing;
|
|
279
|
+
- sensitive result artifacts have a versioned allowlisted schema and bounded retention.
|
|
280
|
+
|
|
281
|
+
## Primary references
|
|
282
|
+
|
|
283
|
+
- Node.js process memory and active-resource documentation
|
|
284
|
+
- Node.js stream backpressure and queue introspection documentation
|
|
285
|
+
- Bun runtime and memory-profiling documentation for the exact target version
|
|
286
|
+
- Operating-system process-memory, descriptor, and handle documentation for the tested cell
|
|
287
|
+
|
|
288
|
+
Verify version-sensitive behavior against the exact runtime build under test. A compatibility API
|
|
289
|
+
name is not evidence that two engines report memory or resource state identically.
|