mustflow 2.116.4 → 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 +152 -8
- package/templates/default/locales/en/.mustflow/skills/INDEX.md +131 -13
- package/templates/default/locales/en/.mustflow/skills/agent-eval-integrity-review/SKILL.md +62 -34
- package/templates/default/locales/en/.mustflow/skills/agent-execution-control-review/SKILL.md +102 -31
- package/templates/default/locales/en/.mustflow/skills/agent-memory-context-governance-review/SKILL.md +163 -0
- package/templates/default/locales/en/.mustflow/skills/agent-planning-recovery-review/SKILL.md +180 -0
- package/templates/default/locales/en/.mustflow/skills/agent-release-bundle-rollout-review/SKILL.md +181 -0
- package/templates/default/locales/en/.mustflow/skills/agent-runtime-isolation-review/SKILL.md +196 -0
- package/templates/default/locales/en/.mustflow/skills/agent-runtime-multi-worker-review/SKILL.md +180 -0
- package/templates/default/locales/en/.mustflow/skills/automation-investment-case-review/SKILL.md +173 -0
- package/templates/default/locales/en/.mustflow/skills/client-platform-strategy-review/SKILL.md +236 -0
- 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/credit-ledger-integrity-review/SKILL.md +8 -4
- package/templates/default/locales/en/.mustflow/skills/credit-monetization-integrity-review/SKILL.md +283 -0
- package/templates/default/locales/en/.mustflow/skills/desktop-commercial-distribution-review/SKILL.md +225 -0
- package/templates/default/locales/en/.mustflow/skills/external-prompt-injection-defense/SKILL.md +49 -3
- package/templates/default/locales/en/.mustflow/skills/freemium-ad-monetization-review/SKILL.md +196 -0
- package/templates/default/locales/en/.mustflow/skills/game-economy-monetization-review/SKILL.md +208 -0
- package/templates/default/locales/en/.mustflow/skills/game-liveops-commerce-integrity-review/SKILL.md +237 -0
- package/templates/default/locales/en/.mustflow/skills/growth-distribution-integrity-review/SKILL.md +247 -0
- package/templates/default/locales/en/.mustflow/skills/idempotency-integrity-review/SKILL.md +20 -2
- package/templates/default/locales/en/.mustflow/skills/llm-model-routing-integrity-review/SKILL.md +183 -0
- package/templates/default/locales/en/.mustflow/skills/llm-product-monetization-review/SKILL.md +311 -0
- package/templates/default/locales/en/.mustflow/skills/llm-token-cost-control-review/SKILL.md +15 -1
- package/templates/default/locales/en/.mustflow/skills/localization-market-expansion-review/SKILL.md +224 -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/multi-agent-work-coordination/SKILL.md +7 -2
- package/templates/default/locales/en/.mustflow/skills/pricing-model-integrity-review/SKILL.md +288 -0
- package/templates/default/locales/en/.mustflow/skills/product-engagement-retention-review/SKILL.md +234 -0
- package/templates/default/locales/en/.mustflow/skills/product-onboarding-activation-review/SKILL.md +269 -0
- package/templates/default/locales/en/.mustflow/skills/product-portfolio-integrity-review/SKILL.md +233 -0
- package/templates/default/locales/en/.mustflow/skills/prompt-contract-quality-review/SKILL.md +1 -0
- package/templates/default/locales/en/.mustflow/skills/referral-incentive-integrity-review/SKILL.md +206 -0
- package/templates/default/locales/en/.mustflow/skills/retry-policy-integrity-review/SKILL.md +45 -2
- package/templates/default/locales/en/.mustflow/skills/routes.toml +346 -7
- package/templates/default/locales/en/.mustflow/skills/service-portfolio-capital-allocation-review/SKILL.md +245 -0
- package/templates/default/locales/en/.mustflow/skills/subscription-retention-profit-review/SKILL.md +217 -0
- package/templates/default/manifest.toml +97 -1
|
@@ -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.
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
# Node Memory, Resource, and Backpressure Diagnostics
|
|
2
|
+
|
|
3
|
+
Use this reference when a Node.js process shows growing RSS, heap, external memory, buffers,
|
|
4
|
+
descriptors, sockets, native handles, cache residency, or streaming queues, especially when slow
|
|
5
|
+
consumers, retries, clones, transforms, HTTP/2, or HTTP/3 can blur ownership.
|
|
6
|
+
|
|
7
|
+
Do not force one exclusive root-cause label onto evidence that describes different dimensions. A
|
|
8
|
+
single incident can combine unbounded buffering, external-memory growth, allocator fragmentation,
|
|
9
|
+
and a missed transport close.
|
|
10
|
+
|
|
11
|
+
## Contents
|
|
12
|
+
|
|
13
|
+
1. [Classify three independent axes](#1-classify-three-independent-axes)
|
|
14
|
+
2. [Build one synchronized measurement ledger](#2-build-one-synchronized-measurement-ledger)
|
|
15
|
+
3. [Control the reproduction and compare floors](#3-control-the-reproduction-and-compare-floors)
|
|
16
|
+
4. [Distinguish common growth classes](#4-distinguish-common-growth-classes)
|
|
17
|
+
5. [Model request ownership as a DAG](#5-model-request-ownership-as-a-dag)
|
|
18
|
+
6. [Enforce terminal resource invariants](#6-enforce-terminal-resource-invariants)
|
|
19
|
+
7. [Trace backpressure from the final sink](#7-trace-backpressure-from-the-final-sink)
|
|
20
|
+
8. [Check each pipeline boundary](#8-check-each-pipeline-boundary)
|
|
21
|
+
9. [Run stop, plateau, and resume experiments](#9-run-stop-plateau-and-resume-experiments)
|
|
22
|
+
10. [Calculate the memory envelope](#10-calculate-the-memory-envelope)
|
|
23
|
+
11. [Infer the broken boundary](#11-infer-the-broken-boundary)
|
|
24
|
+
12. [Diagnostic acceptance gate](#12-diagnostic-acceptance-gate)
|
|
25
|
+
13. [Primary references](#13-primary-references)
|
|
26
|
+
|
|
27
|
+
## 1. Classify three independent axes
|
|
28
|
+
|
|
29
|
+
Classify every observation on all three axes:
|
|
30
|
+
|
|
31
|
+
| Axis | Question |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| Storage location | Are the bytes in the V8 heap, ArrayBuffer or Buffer backing stores, other native allocations, memory mappings, allocator residency, or kernel buffers? |
|
|
34
|
+
| Retention cause | Does a request, pending task, stream queue, cache, pool, native operation, retry, branch, or telemetry queue still own the bytes? |
|
|
35
|
+
| Terminal status | Is the owner still performing valid work, stuck in unbounded backlog, terminal but retained, or released while RSS remains resident? |
|
|
36
|
+
|
|
37
|
+
Call growth a leak only when the expected terminal condition has occurred, an owner or native
|
|
38
|
+
allocation remains live, and retained count or bytes grow with completed lifecycle repetitions under
|
|
39
|
+
comparable load. A queue that drains completely after a live request is not a strict leak, but an
|
|
40
|
+
unbounded queue is still an OOM defect and must not be reported as safe.
|
|
41
|
+
|
|
42
|
+
One common mixed sequence is:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
slow consumer
|
|
46
|
+
-> ignored writable backpressure
|
|
47
|
+
-> unbounded Buffer queue
|
|
48
|
+
-> external and array-buffer growth
|
|
49
|
+
-> queue release
|
|
50
|
+
-> allocator pages remain resident
|
|
51
|
+
-> external falls while RSS stays high
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Do not infer native memory as `rss - heapTotal - external`. The measurements use different
|
|
55
|
+
inclusion, reservation, and residency semantics. In Node, `arrayBuffers` is part of `external`, not
|
|
56
|
+
an independent addend.
|
|
57
|
+
|
|
58
|
+
## 2. Build one synchronized measurement ledger
|
|
59
|
+
|
|
60
|
+
Collect comparable samples from the same process and clock domain:
|
|
61
|
+
|
|
62
|
+
| Layer | Required evidence | Useful expansion |
|
|
63
|
+
| --- | --- | --- |
|
|
64
|
+
| V8 heap | `heapUsed`, `heapTotal`, post-major-GC floor | old space, large-object space, native and detached contexts, global handles |
|
|
65
|
+
| External memory | `external`, `arrayBuffers` | Buffer count, backing-store bytes, parser, codec, crypto, and TLS buffers |
|
|
66
|
+
| Process memory | RSS plus private or committed memory | anonymous, file-backed, shared mappings, PSS, thread stacks, code pages |
|
|
67
|
+
| Resources | descriptor, socket, or Windows handle counts by type | socket state, pool busy/idle/queued, TLS session cache, active resource categories |
|
|
68
|
+
| Application | started, completed, aborted, failed, retried, in-flight | logical request, attempt, branch, and owner counts |
|
|
69
|
+
| Data flow | admitted, accepted, committed, released, cancelled, and discarded bytes per edge | peak queue bytes, chunk size, transform expansion, sink durability boundary |
|
|
70
|
+
| Protocol | TCP queues, HTTP/2 windows and outbound queue, QUIC credit | reset, window update, blocked-frame, cancel, and session or stream counts |
|
|
71
|
+
|
|
72
|
+
Use V8 heap-space statistics to distinguish live-space growth from reserved capacity. A growing
|
|
73
|
+
native or detached context count is a retention lead, not a complete diagnosis.
|
|
74
|
+
|
|
75
|
+
On Linux, mapping summaries can separate anonymous, file-backed, and shared residency. On Windows,
|
|
76
|
+
pair Working Set with Private Bytes or Commit and handle counts by type. Treat mapping inspection,
|
|
77
|
+
native heap profilers, heap snapshots, packet capture, and platform handle tools as configured or
|
|
78
|
+
manual-only diagnostics; this reference does not authorize raw commands.
|
|
79
|
+
|
|
80
|
+
`process.getActiveResourcesInfo()` reports resource types keeping the event loop alive. It is not an
|
|
81
|
+
enumeration of every reference, descriptor, allocation, or leak. Pair it with ownership and
|
|
82
|
+
platform evidence.
|
|
83
|
+
|
|
84
|
+
## 3. Control the reproduction and compare floors
|
|
85
|
+
|
|
86
|
+
Fix more than request rate. Record concurrency, body and chunk sizes, compression, protocol,
|
|
87
|
+
retries, cache state, branch count, consumer rate, origin cardinality, runtime build, and allocator.
|
|
88
|
+
|
|
89
|
+
Run phases in this order:
|
|
90
|
+
|
|
91
|
+
1. idle baseline;
|
|
92
|
+
2. bounded warmup with fixed origins, keys, and connections;
|
|
93
|
+
3. normal consumer faster than producer;
|
|
94
|
+
4. slow consumer below producer rate;
|
|
95
|
+
5. fully stopped consumer;
|
|
96
|
+
6. admission stop followed by complete drain;
|
|
97
|
+
7. idle wait beyond pool and keep-alive deadlines; and
|
|
98
|
+
8. optional forced GC only in an isolated staging or canary process.
|
|
99
|
+
|
|
100
|
+
Do not take a production heap snapshot casually. Snapshot generation can block the event loop and
|
|
101
|
+
require substantial extra memory. Use an isolated process or removed-from-traffic instance and
|
|
102
|
+
record the diagnostic impact.
|
|
103
|
+
|
|
104
|
+
Compare floors and slopes rather than one peak:
|
|
105
|
+
|
|
106
|
+
```text
|
|
107
|
+
post_gc_slope
|
|
108
|
+
= change(post-major-GC heapUsed) / change(completed lifecycles)
|
|
109
|
+
|
|
110
|
+
post_quiescent_slope
|
|
111
|
+
= change(resource amount after admission stop, drain, and idle expiry)
|
|
112
|
+
/ change(completed lifecycles)
|
|
113
|
+
|
|
114
|
+
Q_edge(t)
|
|
115
|
+
= admitted_bytes_edge(t) - released_bytes_edge(t)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Define release as the moment that edge no longer owns the bytes, not the moment it hands them to
|
|
119
|
+
another queue. Keep compressed, decompressed, transformed, and committed byte domains separate.
|
|
120
|
+
Use a predeclared statistical tolerance rather than demanding literal zero from noisy process
|
|
121
|
+
measurements.
|
|
122
|
+
|
|
123
|
+
## 4. Distinguish common growth classes
|
|
124
|
+
|
|
125
|
+
| Class | Decisive evidence | Common false conclusion |
|
|
126
|
+
| --- | --- | --- |
|
|
127
|
+
| JavaScript heap retention | Post-GC and post-quiescent live heap grows with completed work; repeated dominator paths lead to a long-lived map, cache, listener, promise continuation, closure, or context | Treating `heapTotal`, warmup, or a bounded cache as live-object growth |
|
|
128
|
+
| Native leak | JavaScript heap, external memory, queues, and handles are stable while still-live native allocation stacks grow | Calling JIT code, mappings, thread stacks, pools, or fragmentation a native leak |
|
|
129
|
+
| External buffer retention | Small wrappers or views retain large backing stores and `arrayBuffers` moves with owned queue bytes | Treating all `external` as Buffer memory or continuing to call it a Buffer leak after external falls |
|
|
130
|
+
| Unbounded buffering | Growth appears under a slow or stopped consumer near producer-minus-consumer rate and drains after consumption resumes | Calling it safe because it eventually drains, or calling it a terminal leak before the request ends |
|
|
131
|
+
| Descriptor, socket, or handle leak | After admission stop, terminal settlement, and pool idle expiry, owned resources fail to return to baseline, often one per abort or error | Counting a bounded warm pool or kernel `TIME_WAIT` as a process-owned leak |
|
|
132
|
+
| Cache growth | A named cache root owns the bytes and growth follows key, origin, tenant, or SNI cardinality; eviction or flush releases them | Assuming TTL alone is a byte bound or limiting entries while values remain unbounded |
|
|
133
|
+
| Allocator fragmentation or residency | Live heap, external memory, queues, and live native allocations stabilize or fall while allocator active-to-resident gap remains high | Declaring fragmentation merely because RSS did not fall immediately after release |
|
|
134
|
+
|
|
135
|
+
Persistent `CLOSE_WAIT` plus an owned descriptor is a stronger local-close signal than `TIME_WAIT`.
|
|
136
|
+
Confirm the owning process and lifecycle before assigning cause.
|
|
137
|
+
|
|
138
|
+
## 5. Model request ownership as a DAG
|
|
139
|
+
|
|
140
|
+
A strict tree is wrong when pools and multiplexed sessions are shared, retries or hedges create
|
|
141
|
+
multiple attempts, and `clone()` or `tee()` creates multiple body branches.
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
process
|
|
145
|
+
-> process caches and telemetry queues
|
|
146
|
+
-> pool
|
|
147
|
+
-> connection or session
|
|
148
|
+
-> protocol stream leased by request attempt
|
|
149
|
+
-> logical request
|
|
150
|
+
-> root cancellation and context
|
|
151
|
+
-> attempt 1
|
|
152
|
+
-> attempt 2 or hedge
|
|
153
|
+
-> output branch A
|
|
154
|
+
-> output branch B
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Track at least:
|
|
158
|
+
|
|
159
|
+
```text
|
|
160
|
+
resource_id
|
|
161
|
+
resource_type
|
|
162
|
+
scope: process | pool | connection | request | attempt | branch | stream
|
|
163
|
+
owner_id
|
|
164
|
+
parent_id
|
|
165
|
+
leased_by_request_ids
|
|
166
|
+
created_at
|
|
167
|
+
created_stack_hash
|
|
168
|
+
state: CREATED | ACTIVE | CLOSING | CLOSED | FAILED
|
|
169
|
+
current_bytes
|
|
170
|
+
close_action
|
|
171
|
+
terminal_reason
|
|
172
|
+
closed_at
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Separate logical request, attempt, branch, protocol stream, shared connection, and process cache
|
|
176
|
+
ownership. A request normally returns a lease instead of closing a healthy shared connection.
|
|
177
|
+
Cancelling one HTTP/2 or HTTP/3 request normally resets its stream, not the whole session or
|
|
178
|
+
connection.
|
|
179
|
+
|
|
180
|
+
Track terminal reasons such as success, client abort, deadline, DNS, connect, TLS, upstream
|
|
181
|
+
headers, upstream body, transform, downstream, retry-superseded, and shutdown. Do not let the
|
|
182
|
+
success path be the only path with balanced counters.
|
|
183
|
+
|
|
184
|
+
## 6. Enforce terminal resource invariants
|
|
185
|
+
|
|
186
|
+
For every supported terminal reason, require the applicable invariants:
|
|
187
|
+
|
|
188
|
+
| Scope | Terminal invariant |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| Request | Registry, async context, listeners, timers, and request references from cancellation state are zero |
|
|
191
|
+
| Attempt | Fetch or provider task, retry or hedge task, body, parser, and timeout are terminal |
|
|
192
|
+
| Branch | Every clone or tee branch is consumed, cancelled, or errored |
|
|
193
|
+
| Stream | Reader and writer locks are released, pipe tasks settle, and both transform sides reach a terminal state |
|
|
194
|
+
| File | File handle, stream, temporary file, and quota reservation are released |
|
|
195
|
+
| Protocol | HTTP/1 exchange or HTTP/2/3 request stream is terminal |
|
|
196
|
+
| Shared resource | Request lease and reference count decrement exactly once; a healthy shared socket or session need not close |
|
|
197
|
+
| Memory | Request-owned queue bytes reach zero; shared pools and caches remain within declared byte and cardinality limits |
|
|
198
|
+
| Observation | Terminal reason records once and close actions are idempotent |
|
|
199
|
+
|
|
200
|
+
A useful cleanup order is: atomically select terminal state, abort the root scope, stop producers and
|
|
201
|
+
retries, cancel or abort sources and sinks, await task settlement, release locks, remove timers and
|
|
202
|
+
listeners, close files, return shared leases, and remove the registry entry. A finalizer or GC hook
|
|
203
|
+
is a safety net, not the normal protocol.
|
|
204
|
+
|
|
205
|
+
Promises require separate treatment from their work. A settled promise does not prove the socket,
|
|
206
|
+
file, fetch, codec, or native operation ended. A pending promise is not automatically a leak unless
|
|
207
|
+
a longer-lived owner retains it or its underlying operation past the intended boundary.
|
|
208
|
+
|
|
209
|
+
## 7. Trace backpressure from the final sink
|
|
210
|
+
|
|
211
|
+
Backpressure is a chain of local capacity translations, not one signal travelling unchanged through
|
|
212
|
+
the stack:
|
|
213
|
+
|
|
214
|
+
```text
|
|
215
|
+
final sink capacity falls
|
|
216
|
+
-> Web writer readiness blocks or Node write returns false
|
|
217
|
+
-> transform readable queue fills
|
|
218
|
+
-> transform writable pressure rises
|
|
219
|
+
-> body pull or read stops
|
|
220
|
+
-> parser and body ingress slow
|
|
221
|
+
-> HTTP/1 socket reading slows
|
|
222
|
+
or HTTP/2 flow-control credit stops increasing
|
|
223
|
+
or QUIC stream and connection credit stops increasing
|
|
224
|
+
-> remote producer rate falls
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Instrument each request, attempt, and branch with compatible byte domains:
|
|
228
|
+
|
|
229
|
+
```text
|
|
230
|
+
wire_encoded_received
|
|
231
|
+
fetch_ingress_encoded
|
|
232
|
+
body_decoded_enqueued
|
|
233
|
+
body_delivered
|
|
234
|
+
transform_input
|
|
235
|
+
transform_output_enqueued
|
|
236
|
+
sink_accepted
|
|
237
|
+
sink_committed
|
|
238
|
+
sink_released
|
|
239
|
+
cancelled_bytes
|
|
240
|
+
discarded_bytes
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Keep accepted, committed, and released distinct. A sink that resolves `write()` after copying into
|
|
244
|
+
an internal array has accepted bytes but has not necessarily committed or released them. Compression
|
|
245
|
+
and expansion require separate encoded and decoded ledgers.
|
|
246
|
+
|
|
247
|
+
## 8. Check each pipeline boundary
|
|
248
|
+
|
|
249
|
+
| Boundary | Healthy pressure evidence | Failure pattern |
|
|
250
|
+
| --- | --- | --- |
|
|
251
|
+
| Final writable | Web writer readiness remains pending or Node `write()` returns false until drain; local queue plateaus | Adapter resolves before real capacity, ignores false, or grows a background queue |
|
|
252
|
+
| Transform | Transform invocation and output enqueue stop when readable capacity is exhausted; async transform returns its work promise | Background work or side arrays bypass the stream queues; count-based HWM hides huge chunks |
|
|
253
|
+
| Response body and manual pump | New reads stop when the sink blocks; early exit cancels; every write is awaited | Read loop accumulates promises or chunks, releases only a lock, or leaves a clone branch unread |
|
|
254
|
+
| Fetch or client bridge | Body ingress stops after bounded overshoot when delivery stops | Parser, decoder, or bridge continues consuming into user-space storage |
|
|
255
|
+
| HTTP/1 | Application delivery and socket reads stop after bounded transport and parser overshoot | User-space keeps draining the kernel while application Buffers grow; low kernel Recv-Q is misread as health |
|
|
256
|
+
| HTTP/2 | Stream credit stops increasing while connection control frames and healthy sibling streams still progress | Credit is returned when bytes enter an unbounded application queue, or the entire TCP socket is paused and siblings deadlock |
|
|
257
|
+
| HTTP/3 and QUIC | Stream and connection credit stop increasing; blocked telemetry appears; cancellation closes the narrow stream directions | QUIC returns credit before application consumption or one-direction cancellation leaves reassembly state retained |
|
|
258
|
+
| Transport | TCP receive window or QUIC flow control eventually stalls the sender after bounded in-flight bytes | Continued application reads keep transport open while downstream storage grows |
|
|
259
|
+
|
|
260
|
+
Treat high-water marks as pressure thresholds, not hard byte caps. Use a byte-length queuing strategy
|
|
261
|
+
for byte payloads and include maximum chunk, in-flight operations, protocol windows, and hidden side
|
|
262
|
+
queues in the budget.
|
|
263
|
+
|
|
264
|
+
Do not pause an entire HTTP/2 transport merely to slow one stream. Continue processing connection
|
|
265
|
+
control frames and healthy siblings; express pressure through stream and connection flow-control
|
|
266
|
+
accounting. Verify runtime-specific behavior against the target version and client implementation.
|
|
267
|
+
|
|
268
|
+
## 9. Run stop, plateau, and resume experiments
|
|
269
|
+
|
|
270
|
+
Start with HTTP/1, no compression, no retry or hedge, no cache, no clone or tee, concurrency one,
|
|
271
|
+
fixed incompressible chunks, and an origin faster than the sink. Add one variable at a time only
|
|
272
|
+
after the base experiment passes.
|
|
273
|
+
|
|
274
|
+
During normal consumption, queues should oscillate within a low bounded range. During slow
|
|
275
|
+
consumption, buffers may fill, but upstream rate should converge toward sink rate. During a full
|
|
276
|
+
stop, require the applicable observations after bounded overshoot:
|
|
277
|
+
|
|
278
|
+
- writer readiness blocks or Node write returns false;
|
|
279
|
+
- local writable and transform queues plateau;
|
|
280
|
+
- transform invocations and response reads stop;
|
|
281
|
+
- client body ingress stops;
|
|
282
|
+
- HTTP/2 window updates or QUIC credit increases stop for the affected stream; and
|
|
283
|
+
- remote sender throughput stops after in-flight transport data is exhausted.
|
|
284
|
+
|
|
285
|
+
On resume, require queue drain, writer readiness or drain, transform and body reads, protocol credit,
|
|
286
|
+
and remote sending to resume. A pipeline that stops but never resumes is deadlocked or cancelled,
|
|
287
|
+
not backpressure-correct.
|
|
288
|
+
|
|
289
|
+
Then add, one at a time: concurrency, HTTP/2, HTTP/3, gzip or Brotli expansion, output-expanding
|
|
290
|
+
transforms, retries, hedges, clones, tees, slow and fast branches, downstream abort, upstream reset,
|
|
291
|
+
transform failure, and graceful shutdown.
|
|
292
|
+
|
|
293
|
+
## 10. Calculate the memory envelope
|
|
294
|
+
|
|
295
|
+
Use an explicit envelope such as:
|
|
296
|
+
|
|
297
|
+
```text
|
|
298
|
+
pipeline_memory_bound
|
|
299
|
+
~= concurrency
|
|
300
|
+
* sum(
|
|
301
|
+
queue_high_water_mark_bytes
|
|
302
|
+
+ maximum_chunk_bytes
|
|
303
|
+
+ in_flight_operation_bytes
|
|
304
|
+
+ bounded_side_queue_bytes
|
|
305
|
+
)
|
|
306
|
+
+ protocol_receive_windows
|
|
307
|
+
+ protocol_send_windows
|
|
308
|
+
+ kernel_and_userspace_transport_buffers
|
|
309
|
+
+ clone_branch_multiplier
|
|
310
|
+
+ retry_or_hedge_multiplier
|
|
311
|
+
+ codec_expansion_working_set
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
The equation is a budgeting model, not proof of allocator RSS. Validate each term from current
|
|
315
|
+
implementation and workload evidence. A count HWM of one permits one arbitrarily large chunk; it is
|
|
316
|
+
not a one-byte budget.
|
|
317
|
+
|
|
318
|
+
## 11. Infer the broken boundary
|
|
319
|
+
|
|
320
|
+
| Observation | Likely broken boundary |
|
|
321
|
+
| --- | --- |
|
|
322
|
+
| `sinkCommitted` stops while `sinkAccepted` grows | Sink adapter resolves before durable or capacity-limited commit |
|
|
323
|
+
| `sinkAccepted` stops while transform output grows | Transform ignores readable pressure or uses a side queue |
|
|
324
|
+
| Transform input stops while body delivery grows | Manual pump is not serializing read and write |
|
|
325
|
+
| Body delivery stops while client ingress grows | Parser, decoder, or response bridge is over-reading |
|
|
326
|
+
| Application delivery stops while HTTP/2 DATA and credit continue | Credit is returned at intermediate copy instead of final consumption |
|
|
327
|
+
| Application delivery stops while QUIC credit continues | QUIC integration returns credit before application consumption |
|
|
328
|
+
| Application body stops while socket bytes rise and kernel receive queue stays low | HTTP/1 or client bridge continues draining into user-space buffers |
|
|
329
|
+
| Queues and array buffers fall while RSS remains high | Allocator residency, slabs, pools, or fragmentation, after excluding live native allocation |
|
|
330
|
+
| Bytes stabilize while descriptors or handles rise | Independent lifecycle leak |
|
|
331
|
+
| Descriptors stabilize while live native allocation stacks rise | Native memory leak |
|
|
332
|
+
| Live memory stabilizes while cache bytes rise | Cache policy or cardinality failure |
|
|
333
|
+
| Post-GC heap rises even with normal consumers | JavaScript retention unrelated to backpressure |
|
|
334
|
+
|
|
335
|
+
## 12. Diagnostic acceptance gate
|
|
336
|
+
|
|
337
|
+
Call the diagnosis complete only to the evidence level actually established:
|
|
338
|
+
|
|
339
|
+
- locate growth in at least one measurable storage class;
|
|
340
|
+
- identify the owner or bounded queue responsible for retaining it;
|
|
341
|
+
- prove request, attempt, branch, stream, file, and protocol terminal invariants for every supported
|
|
342
|
+
success, abort, timeout, retry, error, and shutdown path;
|
|
343
|
+
- show stopped-consumer queues plateau within a precomputed envelope and upstream rate eventually
|
|
344
|
+
stops;
|
|
345
|
+
- show resume restores drain, protocol credit, and upstream progress;
|
|
346
|
+
- show request-owned descriptors and handles return within predeclared tolerance after pool idle
|
|
347
|
+
expiry while shared pools remain within their limits;
|
|
348
|
+
- show post-GC or post-quiescent slopes remain within predeclared statistical tolerance; and
|
|
349
|
+
- distinguish fragmentation only after live heap, external, cache, queue, handle, mapping, and native
|
|
350
|
+
allocation evidence no longer explains resident growth.
|
|
351
|
+
|
|
352
|
+
If snapshots, native profilers, platform handle inspection, packet capture, qlog, or long-running
|
|
353
|
+
load are not configured, report them as manual-only or missing. RSS growth alone is an observation,
|
|
354
|
+
not a completed diagnosis.
|
|
355
|
+
|
|
356
|
+
## 13. Primary references
|
|
357
|
+
|
|
358
|
+
- [Node.js process memory and active resource APIs](https://nodejs.org/api/process.html)
|
|
359
|
+
- [Node.js V8 heap statistics and heap snapshots](https://nodejs.org/api/v8.html)
|
|
360
|
+
- [Node.js Buffer ownership and views](https://nodejs.org/api/buffer.html)
|
|
361
|
+
- [Node.js stream backpressure and high-water marks](https://nodejs.org/api/stream.html)
|
|
362
|
+
- [Node.js HTTP/2 state and flow control](https://nodejs.org/api/http2.html)
|
|
363
|
+
- [WHATWG Streams Standard](https://streams.spec.whatwg.org/)
|
|
364
|
+
- [RFC 9113: HTTP/2](https://www.rfc-editor.org/rfc/rfc9113.html)
|
|
365
|
+
- [RFC 9000: QUIC](https://www.rfc-editor.org/rfc/rfc9000.html)
|
|
366
|
+
|
|
367
|
+
Use documentation for the target runtime and client version. The current Node documentation and
|
|
368
|
+
standards establish API and protocol semantics; they do not prove a particular library build,
|
|
369
|
+
allocator, kernel, proxy, or application implements the lifecycle correctly.
|