mustflow 2.113.0 → 2.114.5
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/README.md +2 -0
- package/dist/cli/commands/skill.js +77 -4
- package/dist/cli/lib/command-registry.js +1 -1
- package/dist/cli/lib/external-skill-import.js +461 -7
- package/dist/core/public-json-contracts.js +9 -0
- package/package.json +3 -1
- package/schemas/README.md +4 -0
- package/schemas/skill-update-report.schema.json +256 -0
- package/templates/default/i18n.toml +12 -12
- package/templates/default/locales/en/.mustflow/skills/async-timing-boundary-review/SKILL.md +6 -1
- package/templates/default/locales/en/.mustflow/skills/client-bundle-pruning-review/SKILL.md +40 -34
- package/templates/default/locales/en/.mustflow/skills/frame-render-performance-review/SKILL.md +28 -22
- package/templates/default/locales/en/.mustflow/skills/hot-path-performance-review/SKILL.md +22 -10
- package/templates/default/locales/en/.mustflow/skills/javascript-code-change/SKILL.md +29 -11
- package/templates/default/locales/en/.mustflow/skills/memory-lifetime-review/SKILL.md +8 -2
- package/templates/default/locales/en/.mustflow/skills/node-code-change/SKILL.md +19 -5
- package/templates/default/locales/en/.mustflow/skills/performance-budget-check/SKILL.md +15 -7
- package/templates/default/locales/en/.mustflow/skills/quadratic-scan-review/SKILL.md +25 -22
- package/templates/default/locales/en/.mustflow/skills/web-render-performance-review/SKILL.md +18 -17
- package/templates/default/manifest.toml +1 -1
package/templates/default/locales/en/.mustflow/skills/frame-render-performance-review/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
mustflow_doc: skill.frame-render-performance-review
|
|
3
3
|
locale: en
|
|
4
4
|
canonical: true
|
|
5
|
-
revision:
|
|
5
|
+
revision: 2
|
|
6
6
|
lifecycle: mustflow-owned
|
|
7
7
|
authority: procedure
|
|
8
8
|
name: frame-render-performance-review
|
|
@@ -56,6 +56,7 @@ The review question is not "did we add `useMemo`?" It is "what work does the bro
|
|
|
56
56
|
|
|
57
57
|
- Interaction and frame ledger: affected interaction, route, viewport, target frame rate, user-visible symptom, expected INP or next-paint boundary, and whether the path runs during startup, scroll, input, animation, resize, or idle.
|
|
58
58
|
- DOM and layout ledger: node count, tree depth, affected subtree, list size, virtualization boundary, layout containment, geometry reads, geometry writes, reserved media slots, and layout-shift evidence.
|
|
59
|
+
- DOM update ledger: node attach count, observable mutation count, keyed update behavior, fragment or template usage, `innerHTML`, `replaceChildren`, focus, selection, scroll position, listener ownership, and event delegation.
|
|
59
60
|
- Style and CSS ledger: class or attribute toggles, selector complexity, global state classes, CSS custom property scope, runtime style injection, CSS animations, transitions, `will-change`, `contain`, `content-visibility`, and stacking or containing block side effects.
|
|
60
61
|
- Paint and compositing ledger: animated properties, repaint area, layer promotion, transform and opacity usage, canvas or SVG drawing, image/video/ad slots, shadows, filters, clipping, and expensive visual effects.
|
|
61
62
|
- Event and scheduling ledger: scroll, wheel, touch, pointer, resize, observer, timer, `requestAnimationFrame`, long task, worker, `OffscreenCanvas`, `scheduler.yield`, debounce, throttle, and cancellation behavior.
|
|
@@ -92,32 +93,37 @@ The review question is not "did we add `useMemo`?" It is "what work does the bro
|
|
|
92
93
|
8. Stop offscreen work, not only offscreen rendering. For skipped or hidden charts, maps, canvas, or media widgets, pause redraws, resize loops, observers, polling, and expensive updates while the widget is not visible.
|
|
93
94
|
9. Virtualize long lists. Large tables, chat logs, feeds, option lists, and grids should keep only the visible window plus buffer in the DOM when item count can grow.
|
|
94
95
|
10. Reduce DOM depth and breadth where it affects a hot render path. Deep wrapper chains and wide repeated structures increase style and layout propagation even when no single node looks expensive.
|
|
95
|
-
11.
|
|
96
|
-
12. Avoid
|
|
97
|
-
13.
|
|
98
|
-
14.
|
|
99
|
-
15.
|
|
100
|
-
16.
|
|
101
|
-
17.
|
|
102
|
-
18.
|
|
103
|
-
19.
|
|
104
|
-
20.
|
|
105
|
-
21.
|
|
106
|
-
22.
|
|
107
|
-
23.
|
|
108
|
-
24. Use `
|
|
109
|
-
25.
|
|
110
|
-
26.
|
|
111
|
-
27.
|
|
112
|
-
28.
|
|
113
|
-
29.
|
|
114
|
-
30.
|
|
96
|
+
11. Reduce DOM attachment and observable mutation count. `DocumentFragment` can make batch assembly cleaner, but it is not magic by itself; the win is fewer live DOM attachments, fewer layout-visible changes, and a narrower subtree to reconcile.
|
|
97
|
+
12. Avoid repeated hot-path `innerHTML` replacement. Replacing a large parent destroys node identity, focus, selection, scroll position, listener ownership, and browser reuse. Prefer keyed patching, targeted `replaceChildren`, template clones, or virtualization when only part of the subtree changed.
|
|
98
|
+
13. Use event delegation for large repeated regions. Lists, grids, tables, menus, and icon rows should usually attach one container listener and resolve the target with `closest()` instead of attaching thousands of per-node listeners.
|
|
99
|
+
14. Simplify selectors on hot or broad subtrees. Prefer simple class selectors over selectors that depend on deep descendants, complex siblings, expensive pseudo-classes, or global ancestor state.
|
|
100
|
+
15. Focus on invalidation scope, not selector folklore alone. Ask how many elements a class, attribute, CSS variable, or DOM mutation invalidates before spending time on cosmetic selector rewrites.
|
|
101
|
+
16. Avoid broad global class toggles. `body` or `html` state changes force wide style invalidation. Use the narrowest subtree root unless the state is truly global, such as theme.
|
|
102
|
+
17. Scope frequently changing CSS variables close to the affected subtree. Avoid changing `:root` custom properties on pointer move, scroll, drag, or animation. Use non-inheriting registered properties when project support and browser targets allow it.
|
|
103
|
+
18. Reserve media, ad, and embed geometry. Use width, height, `aspect-ratio`, or stable placeholders so image, video, iframe, and ad loads do not trigger layout shifts and repeated paint.
|
|
104
|
+
19. Keep LCP media and first-render discovery concerns routed to `web-render-performance-review`. In this skill, focus on whether loaded media shifts layout, repaints broad regions, or forces per-frame work.
|
|
105
|
+
20. Prefer native lazy loading for below-fold images and iframes when it covers the case. Avoid JS lazy loaders that add scroll handlers, observers, state churn, and rerenders without a project reason.
|
|
106
|
+
21. Use `IntersectionObserver` for visibility and infinite-scroll triggers. Do not calculate viewport intersection manually on every scroll event unless a browser limitation forces it.
|
|
107
|
+
22. Debounce or throttle high-frequency input only after deciding the interaction contract. Scroll, resize, pointermove, mousemove, and text input can flood async work, state updates, layout reads, and network calls; keep urgent visual feedback separate from delayed heavy work.
|
|
108
|
+
23. Use passive wheel, touch, and scroll listeners when the handler does not call `preventDefault()`. Do not mark listeners passive when the gesture intentionally cancels scrolling.
|
|
109
|
+
24. Use CSS `overscroll-behavior` before JavaScript scroll blocking for modals, drawers, and nested scroll containers. Keep JS scroll locks as the narrow fallback for focus and body-lock requirements.
|
|
110
|
+
25. Schedule visual writes with `requestAnimationFrame`. Do not use fixed `setTimeout(..., 16)` as a frame clock. Use the animation timestamp so high-refresh displays do not speed up motion.
|
|
111
|
+
26. Split long tasks. Work longer than one frame or around 50ms should yield between chunks, show urgent UI first, and move non-urgent analytics, cache cleanup, validation, or transformation out of the immediate interaction path.
|
|
112
|
+
27. Move DOM-free heavy computation off the main thread when the boundary cost is worth it. Filtering, sorting, diffing, crypto, markdown parsing, image preprocessing, and search indexing can move to a worker when data transfer and cancellation are defined.
|
|
113
|
+
28. Consider `OffscreenCanvas` for heavy canvas rendering when browser targets and architecture support it. Charts, whiteboards, maps, and image editors should not block input and paint if a worker boundary is practical.
|
|
114
|
+
29. Use `ResizeObserver` for element size changes. Avoid window resize handlers that read every card and write layout back in the same pass.
|
|
115
|
+
30. Avoid runtime CSS rule churn. Do not inject new style tags or rules during click, hover, drag, pointer move, or repeated list rendering. Use static classes and narrow CSS variables where dynamic values are needed.
|
|
116
|
+
31. Treat React `memo` as a rerender scope tool, not a cure. It fails when props are fresh objects, arrays, or functions each render. Prefer smaller component boundaries and stable primitive props.
|
|
117
|
+
32. Split React context by change frequency and audience. A fresh provider object rerenders all consumers of that context; do not put theme, auth, permissions, feature flags, and editor state into one object unless they change together.
|
|
118
|
+
33. Keep input updates urgent and heavy results deferred. Use deferred rendering or transitions for large filtered lists, charts, panels, or route changes when immediate input feedback matters more than full result freshness.
|
|
119
|
+
34. Narrow hydration. SSR can still hurt INP when the client hydrates too much at once. Hydrate only interactive islands early and defer low-priority regions by visibility, idle time, or route intent when the framework supports it.
|
|
120
|
+
35. Verify with the right evidence. Prefer DevTools Performance, paint flashing, layout shift regions, Selector Stats, Long Tasks API or `PerformanceObserver`, and INP flame evidence when configured or provided. If unavailable, report static risks and skipped measurement reasons.
|
|
115
121
|
|
|
116
122
|
<!-- mustflow-section: postconditions -->
|
|
117
123
|
## Postconditions
|
|
118
124
|
|
|
119
125
|
- The affected interaction, frame phase, DOM scope, style scope, layout reads/writes, paint or compositing cost, scheduling path, and framework render boundary are explicit where relevant.
|
|
120
|
-
- Forced synchronous layout, layout thrashing, layout-affecting animations, stale `will-change`, missing containment, unsafe `content-visibility`, offscreen background work, oversized DOM, complex selectors, broad global class toggles, root CSS variable churn, unreserved media geometry, JS scroll polling, non-passive listeners, JS scroll blocking, timer-based animation, long tasks, main-thread heavy computation, canvas main-thread cost, resize measurement loops, runtime CSS injection, ineffective memo, broad context rerenders, urgent heavy results, and full hydration cost are fixed or reported.
|
|
126
|
+
- Forced synchronous layout, layout thrashing, layout-affecting animations, stale `will-change`, missing containment, unsafe `content-visibility`, offscreen background work, oversized DOM, high mutation count, hot-path `innerHTML`, missing event delegation, complex selectors, broad style invalidation, broad global class toggles, root CSS variable churn, unreserved media geometry, JS scroll polling, high-frequency event floods, non-passive listeners, JS scroll blocking, timer-based animation, long tasks, main-thread heavy computation, canvas main-thread cost, resize measurement loops, runtime CSS injection, ineffective memo, broad context rerenders, urgent heavy results, and full hydration cost are fixed or reported.
|
|
121
127
|
- Rendering performance claims are backed by current configured evidence or labeled as static frame-risk, manual-only measurement, or missing evidence.
|
|
122
128
|
- Accessibility, focus, scroll intent, reduced motion, layout stability, privacy, and framework semantics remain intact or are reported as tradeoffs.
|
|
123
129
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
mustflow_doc: skill.hot-path-performance-review
|
|
3
3
|
locale: en
|
|
4
4
|
canonical: true
|
|
5
|
-
revision:
|
|
5
|
+
revision: 6
|
|
6
6
|
lifecycle: mustflow-owned
|
|
7
7
|
authority: procedure
|
|
8
8
|
name: hot-path-performance-review
|
|
@@ -57,6 +57,7 @@ The review question is not only "which line looks slow?" It is "how often does t
|
|
|
57
57
|
- Per-iteration cost: external calls, queries, filesystem reads, temporary arrays, object spreads, array spreads, concat copies, clones, DTO conversions, JSON parse/stringify, string splitting, logging, formatting, regex, sorting, hashing, image or crypto work, and lock hold time.
|
|
58
58
|
- Boundary ledger: DB, network, cache, filesystem, IPC, provider SDK, queue, logger, metrics sink, transaction, pool, mutex, thread, goroutine, task, or UI main thread crossed by the path.
|
|
59
59
|
- Data-size and tail-latency evidence when available: p50, p95, p99, row count, payload size, allocation count, query count, round-trip count, queue depth, pool wait, lock wait, cache hit rate, retry count, or timeout behavior.
|
|
60
|
+
- Runtime-pressure evidence when available: CPU profile, flame graph, browser DevTools Performance or Memory output, event-loop utilization, p95 or p99 event-loop delay, libuv worker-pool wait, stream backpressure, GC pause, heap growth, request-level I/O timing, or equivalent runtime metrics.
|
|
60
61
|
- Correctness boundaries: order, duplicates, idempotency, authorization, tenant isolation, consistency, partial failure, stale data, cancellation, retry semantics, and error behavior.
|
|
61
62
|
- Relevant command-intent contract entries for build, tests, docs, release checks, and mustflow validation.
|
|
62
63
|
|
|
@@ -85,18 +86,21 @@ The review question is not only "which line looks slow?" It is "how often does t
|
|
|
85
86
|
|
|
86
87
|
1. Count the path before judging it. State how many times the code can run after multiplying by requests, rows, items, retries, renders, jobs, pages, tenants, and nested loops.
|
|
87
88
|
2. Build a cost ledger with five columns: iteration count, data size, round-trip count, wait time, and copy or allocation count.
|
|
89
|
+
- For JavaScript hot paths, start from flame graph, DevTools Performance, Memory, Node CPU profile, event-loop delay, or GC evidence when it exists. Do not turn `for` versus `map` or syntax preference into the first fight while JSON parsing, sort comparators, DOM layout, GC, sync APIs, or external calls are unmeasured.
|
|
88
90
|
3. Check repeated external access first.
|
|
89
91
|
- A loop around DB, ORM, Redis, HTTP, RPC, filesystem, object storage, IPC, provider SDK, logging sink, or child process is the first suspect.
|
|
90
92
|
- ORM relation access can be a query even when it looks like a property read; treat lazy loading as guilty until query count evidence says otherwise.
|
|
91
93
|
4. Check multi-pass collection code. `map`, `filter`, `reduce`, `forEach`, LINQ, streams, iterator chains, and comprehensions can traverse data several times. Count passes and intermediate arrays before admiring the one-liner.
|
|
92
|
-
5. Check hidden quadratic lookup. A loop containing `includes`, `contains`, `find`, `indexOf`, `some`, `filter`, list membership, row-wise DataFrame work, or another linear scan is often `O(n^2)`. Prefer `Set`, `Map`, lookup tables, sorted merge, or database-side join when semantics match.
|
|
93
|
-
6. Preserve semantics when changing data structures. State order, duplicates, first or last winner, missing IDs, stable sort, tie-breakers, and authorization visibility before replacing arrays with maps or sets.
|
|
94
|
+
5. Check hidden quadratic lookup. A loop containing `includes`, `contains`, `find`, `indexOf`, `some`, `filter`, list membership, row-wise DataFrame work, or another linear scan is often `O(n^2)`. Prefer `Set`, `Map`, lookup tables, sorted merge, or database-side join when semantics match. For JavaScript, do not claim `Map` or `Set` is guaranteed O(1); treat keyed collections as average sublinear and still account for setup, memory, hashing, equality, and resize cost.
|
|
95
|
+
6. Preserve semantics when changing data structures. State order, duplicates, first or last winner, missing IDs, stable sort, tie-breakers, and authorization visibility before replacing arrays with maps or sets. Use `Set` for membership or insertion-order scalar dedupe, `Map` for key-to-latest or grouping, arrays for hard-capped ordered data, and sorted arrays for range or merge work.
|
|
94
96
|
7. Check database shape.
|
|
95
97
|
- Avoid unbounded `SELECT *`, full entity hydration, large JSON/TEXT/BLOB columns, `findAll`, row-by-row saves, and per-item relation access.
|
|
96
98
|
- Check whether predicates can use indexes. Functions around indexed columns, leading wildcard search, unselective filters, implicit casts, and mismatched sort order often defeat indexes.
|
|
97
99
|
- Treat large `OFFSET ... LIMIT ...` pages as linearly expensive unless the product truly needs arbitrary jumps. Prefer stable keyset or cursor pagination when possible.
|
|
98
100
|
8. Check transaction and lock hold time. Do not hold DB transactions, mutexes, synchronized blocks, distributed locks, or global locks across network calls, file uploads, JSON conversion, logs, long computation, or user-controlled waits.
|
|
99
101
|
9. Check async shape. Sequential `await` in a loop is still serial work. Independent I/O usually needs bounded concurrency, while `Promise.all` over thousands of items, unbounded goroutines, unbounded futures, or thread-pool bypasses can melt the shared resource.
|
|
102
|
+
- In browser and Node JavaScript, `async` does not make CPU work free. Large `response.json()` parsing, JSON stringify, diffing, markdown parsing, syntax highlighting, compression, crypto, sorting, and chart preparation still occupy the main thread or event loop unless streamed, chunked, or moved to a worker or backend.
|
|
103
|
+
- Pick a Promise aggregation strategy that matches failure behavior. `Promise.all` fails fast without cancelling siblings, so first-failure-stop behavior needs abort propagation, while partial-result workflows usually need `allSettled` or a project-specific result collector.
|
|
100
104
|
10. Reuse expensive clients and sessions. Per-request or per-item HTTP clients, DB clients, ORM clients, SDK clients, connection pools, TLS handshakes, regexes, date formatters, and thread pools are performance traps unless the API requires that lifecycle.
|
|
101
105
|
11. Check cache honesty. A cache needs a bounded key space, invalidation or TTL, max size, authorization dimensions, negative-cache policy, stale behavior, and cache stampede protection such as locking, singleflight, early refresh, or request coalescing.
|
|
102
106
|
12. Check logging and telemetry in hot paths. Repeated debug logs, eager log-string creation, whole-object serialization, high-cardinality metrics, and JSON formatting for discarded logs can dominate CPU and I/O during incidents.
|
|
@@ -105,22 +109,29 @@ The review question is not only "which line looks slow?" It is "how often does t
|
|
|
105
109
|
- Spread accumulation, `concat` in loops, repeated object spread while building indexes, and `cloneDeep` can copy growing data many times.
|
|
106
110
|
- `JSON.stringify` or `JSON.parse(JSON.stringify(...))` used for comparison, cloning, cache keys, or logging can dominate CPU and allocation while losing type semantics.
|
|
107
111
|
- Repeated `RegExp`, `Date`, `Intl`, formatter, `Set`, or `Map` construction inside hot loops should move outside the loop or become request-scoped only when ownership and memory bounds are clear.
|
|
112
|
+
- Repeated Array built-in borrowing on `arguments`, `NodeList`, `HTMLCollection`, or other array-like objects should convert once to a real array when the path repeatedly maps, filters, iterates, or indexes the same values.
|
|
113
|
+
- JavaScript hot arrays should stay dense and type-stable. Avoid holes, far-out index writes, out-of-bounds reads, mixed numeric and object values, repeated `shift()` or `unshift()`, and repeated middle `splice()` when a head index, typed array, or unordered swap-and-pop fits the semantics.
|
|
114
|
+
- Hot JavaScript objects should keep stable field order and avoid `delete`; use `Map` for dynamic keys and fixed-shape records for known fields.
|
|
115
|
+
- Object pooling is not a default allocation fix. Pool heavy buffers or large reusable arrays only after allocation evidence; ordinary short-lived objects may be cheaper for the generational collector.
|
|
108
116
|
14. Check string, JSON, DTO, and clone churn. Repeated string concatenation, `JSON.parse(JSON.stringify(...))`, `cloneDeep`, broad object spread, deep copy, repeated DTO-to-DTO conversion, and repeated serialization can move the bottleneck into "clean" mapping code.
|
|
109
117
|
15. Check large value passing and materialization. In value-copy languages or APIs, large structs, arrays, buffers, spread copies, full file reads, full JSON loads, all-pages accumulation, and eager `collect` calls can turn neat code into memory traffic.
|
|
110
118
|
16. Check regex, parsing, formatting, and locale work. Nested or ambiguous regexes, repeated date parsing, timezone conversion, numeric or locale formatting, and per-row formatter creation should be reviewed with worst-case input in mind.
|
|
119
|
+
- Check `Array.prototype.sort` comparators for repeated expensive work. `new Date`, `localeCompare` with options, normalization, derived score calculation, JSON serialization, path reads, or lookup-key construction inside a comparator can run many times per item; precompute keys before sorting when data size can grow.
|
|
111
120
|
17. Check CPU-heavy work in request or UI paths. Image resizing, compression, encryption, hashing, diffing, report generation, spreadsheet export, and search indexing may need batching, worker offload, queueing, or streaming, but only with clear backpressure and failure behavior.
|
|
112
|
-
18.
|
|
113
|
-
19.
|
|
114
|
-
20.
|
|
115
|
-
21.
|
|
116
|
-
22.
|
|
117
|
-
23.
|
|
121
|
+
18. For Node.js hot paths, separate CPU, event-loop delay, and I/O wait before prescribing workers or caches. `eventLoopUtilization` is not CPU percent; pair it with CPU profiles, p95 or p99 event-loop delay, request I/O timings, worker-pool signals, and GC evidence when available.
|
|
122
|
+
19. In Node.js, treat sync APIs, large JSON parse or stringify, REDOS-prone regexes, eager log serialization, recursive `process.nextTick()`, and whole-buffer stream handling as event-loop blockers even when the surrounding code uses `async`.
|
|
123
|
+
20. Check queues and workers. Moving work to a queue only moves the bottleneck unless consumers batch DB writes, bulk external calls where safe, bound retries, apply jitter, define poison-message handling, and expose backlog. Worker threads fit CPU-heavy JavaScript; they do not fix slow DB, HTTP, Redis, or object-storage I/O.
|
|
124
|
+
21. Check retry and timeout multiplication. A request with several calls, long timeouts, and several retries can become a tail-latency monster. Count worst-case wait and verify idempotency before adding more attempts.
|
|
125
|
+
22. Review tail behavior, not just average. p50 can look fine while p95 or p99 holds locks, connections, workers, event loops, or thread-pool slots long enough to hurt everyone else.
|
|
126
|
+
23. Add observability before large optimization when evidence is missing. Prefer query count, external-call count, payload bytes, allocation count, heap growth, GC pause, event-loop delay, cache hit rate, queue backlog, queue wait, pool wait, lock wait, retry count, and span timing over guessing.
|
|
127
|
+
24. Rank the likely payoff. Usually fix repeated external round trips, N+1 access, hidden quadratic scans, overfetching, wide transactions, lock hold time, allocation churn, unbounded fan-out, missing timeouts, and event-loop blockers before micro-optimizing arithmetic.
|
|
128
|
+
25. Label evidence honestly. If there is no configured benchmark, profile, trace, or production evidence, report the finding as static complexity or hot-path risk, not measured speedup. V8 evidence from Chrome or Node should be labeled as V8-specific until Safari, Firefox, or the project's other target runtimes are measured.
|
|
118
129
|
|
|
119
130
|
<!-- mustflow-section: postconditions -->
|
|
120
131
|
## Postconditions
|
|
121
132
|
|
|
122
133
|
- Hot path, cost multipliers, data size, round-trip count, wait points, and copy or allocation points are explicit.
|
|
123
|
-
- N+1 queries, repeated external calls, hidden quadratic scans, unbounded materialization, temporary-array chains, spread or concat copy accumulation, sequential waits, unbounded fan-out, per-item client creation, broad logging, repeated parsing or serialization, allocation churn, and lock or transaction hold time are fixed or reported.
|
|
134
|
+
- N+1 queries, repeated external calls, hidden quadratic scans, unbounded materialization, temporary-array chains, spread or concat copy accumulation, sequential waits, unbounded fan-out, large JSON parse or stringify, CPU-heavy async illusions, per-item client creation, broad logging, repeated parsing or serialization, allocation churn, event-loop blocking, worker-pool starvation, stream backpressure gaps, and lock or transaction hold time are fixed or reported.
|
|
124
135
|
- Cache, queue, retry, timeout, batching, bulk-write, concurrency, pagination, projection, index-fit, and observability behavior are explicit where relevant.
|
|
125
136
|
- Correctness, authorization, tenant isolation, ordering, duplicates, partial failure, cancellation, and stale-data behavior remain intact or are called out as tradeoffs.
|
|
126
137
|
- Performance claims are backed by configured evidence or labeled as static review risk.
|
|
@@ -157,6 +168,7 @@ Use the narrowest configured test, build, docs, release, or mustflow intent that
|
|
|
157
168
|
- Cost ledger: iteration count, data size, round trips, wait time, copy or allocation count
|
|
158
169
|
- Repeated external access, N+1, hidden quadratic scans, and multi-pass collection findings
|
|
159
170
|
- DB, pagination, index-fit, transaction, lock, async, client reuse, cache, queue, retry, timeout, logging, temporary arrays, spread or concat accumulation, serialization, clone, regex, parsing, formatting, allocation, GC, and CPU-heavy work checked where relevant
|
|
171
|
+
- Runtime pressure: CPU profile, event-loop delay, event-loop utilization, worker-pool, stream backpressure, and I/O wait checked where relevant
|
|
160
172
|
- Optimization or review recommendation
|
|
161
173
|
- Evidence level: measured, configured-test evidence, static complexity risk, manual-only, missing, or not applicable
|
|
162
174
|
- Command intents run
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
mustflow_doc: skill.javascript-code-change
|
|
3
3
|
locale: en
|
|
4
4
|
canonical: true
|
|
5
|
-
revision:
|
|
5
|
+
revision: 6
|
|
6
6
|
lifecycle: mustflow-owned
|
|
7
7
|
authority: procedure
|
|
8
8
|
name: javascript-code-change
|
|
@@ -28,7 +28,7 @@ metadata:
|
|
|
28
28
|
<!-- mustflow-section: purpose -->
|
|
29
29
|
## Purpose
|
|
30
30
|
|
|
31
|
-
Preserve JavaScript module, runtime, package entry, Promise, cleanup, dependency, and test boundaries.
|
|
31
|
+
Preserve JavaScript module, runtime, package entry, Promise, cleanup, dependency, data-shape, hot-path, and test boundaries.
|
|
32
32
|
|
|
33
33
|
<!-- mustflow-section: use-when -->
|
|
34
34
|
## Use When
|
|
@@ -48,6 +48,8 @@ Preserve JavaScript module, runtime, package entry, Promise, cleanup, dependency
|
|
|
48
48
|
- `package.json`, lockfile, engines, module `type`, package `exports`, bundler config, lint config, test config, and relevant entrypoints.
|
|
49
49
|
- Target runtime: browser, Node, worker, edge, Bun, or multi-runtime boundary.
|
|
50
50
|
- Runtime adapter files, source entrypoints, package docs examples, and build output layout when package entry or runtime support changes.
|
|
51
|
+
- Data shape and hot-path surface when collection lookup, grouping, sorting, queueing, array mutation, object shape, typed arrays, allocation, or GC pressure changes.
|
|
52
|
+
- JavaScript engine evidence when performance is claimed: Chrome or Node V8 profile, browser DevTools Performance or Memory output, Node CPU profile, event-loop delay, GC evidence, or an explicit note that Safari and Firefox behavior still needs project-specific measurement.
|
|
51
53
|
- Async ownership and cleanup surface when Promises, retries, timers, event listeners, streams, abort signals, background tasks, startup, shutdown, or external I/O change.
|
|
52
54
|
- Configured verification intents.
|
|
53
55
|
|
|
@@ -66,6 +68,7 @@ Preserve JavaScript module, runtime, package entry, Promise, cleanup, dependency
|
|
|
66
68
|
- Prefer existing dependencies and platform APIs over adding a new dependency.
|
|
67
69
|
- Keep runtime-specific APIs behind platform adapters or runtime-specific entrypoints.
|
|
68
70
|
- Keep package entry changes synchronized with declarations, docs examples, build output, and consumer smoke coverage when available.
|
|
71
|
+
- Prefer semantic data-shape changes over folklore micro-optimizations: use `Set` or `Map` for repeated lookup only when the setup cost is paid back, use objects for fixed-shape records, and keep order, duplicate, and winner semantics explicit.
|
|
69
72
|
|
|
70
73
|
<!-- mustflow-section: procedure -->
|
|
71
74
|
## Procedure
|
|
@@ -95,14 +98,27 @@ Preserve JavaScript module, runtime, package entry, Promise, cleanup, dependency
|
|
|
95
98
|
12. For package entry changes, check source entrypoints, build output layout, docs import examples, TypeScript or declaration settings, bundler config, and consumer-style tests. Report missing Node ESM, Node CJS, browser bundle, edge, Bun, or TypeScript consumer verification when those targets are claimed but no configured intent exists.
|
|
96
99
|
13. Treat build targets as syntax/output compatibility, not as permission to use a runtime API. A browser or edge build target does not make Node filesystem, process, Buffer, or native APIs safe.
|
|
97
100
|
14. Treat implicit globals as failures.
|
|
98
|
-
15. Do not
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
15. Do not treat `async`, `await`, or Promise syntax as a thread or CPU offload boundary. CPU-heavy parsing, sorting, diffing, compression, crypto, markdown rendering, syntax highlighting, chart preparation, and large JSON work still block the browser main thread or Node event loop unless moved to a real worker, backend job, streaming pipeline, or bounded chunked scheduler.
|
|
102
|
+
- When optimizing JavaScript syntax or data shape, classify the evidence by engine. V8 evidence from Chrome or Node is useful, but it does not prove Safari or Firefox behavior without measurement in the target browser/runtime.
|
|
103
|
+
16. Do not claim JavaScript `Map`, `Set`, `WeakMap`, or `WeakSet` are guaranteed O(1). Treat them as average sublinear keyed collections, then choose them only when repeated lookups, dynamic keys, object keys, or membership checks justify the setup and memory cost.
|
|
104
|
+
17. Use `Map` for dynamic, user-controlled, object-identity, or frequently added and removed keys. Use plain objects for fixed-shape records with known fields. Avoid turning hot objects into ad hoc dictionaries.
|
|
105
|
+
18. Keep hot object shapes stable. Create the same fields in the same order for the same record kind, prefer sentinel values such as `null` for optional fields, and avoid `delete` on hot objects unless dynamic-key behavior is the real requirement and a `Map` is more honest. In V8-heavy Chrome or Node paths, treat late property addition and inconsistent field order as engine-shape risks unless a profile proves they are outside the hot path.
|
|
106
|
+
19. Keep arrays dense and type-stable in hot paths. Avoid `delete array[i]`, far-out index writes, partially-filled `new Array(n)`, mixed numeric and object values, and out-of-bounds reads. Prefer `push` when values arrive sequentially, and consider `TypedArray` for numeric buffers, vectors, pixels, counters, and other fixed numeric data. Do not mix small integers, doubles, objects, holes, and sentinel values casually in arrays that execute inside render, request, parser, or worker loops.
|
|
107
|
+
20. Avoid JavaScript array operations that move or rebuild large collections in hot paths. Use a head-index queue instead of repeated `shift()` or `unshift()`, swap-with-last plus `pop()` for unordered deletes instead of repeated middle `splice()`, and avoid `filter().map().flatMap()` chains when intermediate arrays dominate allocation.
|
|
108
|
+
21. Treat sorting as ordering work, not lookup work. Use `Map` for exact repeated lookup, sorted arrays plus binary search or merge for range work, decorate-sort-undecorate when the comparator computes expensive keys, and a heap or bounded top-k structure for repeated priority extraction. Keep comparators cheap: precompute `Date`, locale, normalized string, JSON, path, or score keys instead of recalculating them for every comparison call.
|
|
109
|
+
22. Use `WeakMap` or `WeakSet` for metadata tied to object lifetime, such as DOM nodes, AST nodes, request objects, sockets, or component instances. Do not keep those objects alive in a normal `Map` unless retention is intentional and bounded.
|
|
110
|
+
23. Prefer rest parameters over `arguments` in new hot-path code. Convert `arguments`, `NodeList`, `HTMLCollection`, and other array-like objects to a real array once when repeated `map`, `filter`, `forEach`, iteration, or indexing work follows. Pool only heavy buffers, arrays, or repeatedly allocated expensive objects after allocation evidence; do not pool ordinary short-lived records just to look optimized.
|
|
111
|
+
24. Do not discard Promises. Every Promise-producing call must be awaited, returned, joined, or intentionally supervised by the project's detached-task pattern.
|
|
112
|
+
25. Do not leave `.map(async ...)` unjoined. Join with the established Promise aggregation or bounded-concurrency helper when parallel work is intended.
|
|
113
|
+
26. Do not use unbounded parallelism for large external I/O fan-out. Use the local concurrency limit pattern when the workload touches HTTP, database, filesystem, queue, AI, or other external services.
|
|
114
|
+
27. Avoid accidental serial waits over independent work. A `for...of` loop with `await` is correct for ordered dependencies, rate spacing, or shared mutable state, but independent HTTP, filesystem, database, or worker tasks should use the local bounded-concurrency pattern instead of one slow item holding the whole line hostage.
|
|
115
|
+
28. Choose Promise aggregation by failure policy. `Promise.all` fails fast but does not cancel remaining work by itself; use `allSettled` when every result matters, `any` when the first success wins, and explicit `AbortController` or local cancellation when first failure should stop underlying work.
|
|
116
|
+
29. Treat `await fetch()` and `response.json()` as two different costs. The network wait is async, but large body buffering and JSON parse can block the main thread or event loop; prefer pagination, projection, NDJSON, streaming parsers, worker parsing, or server-side shaping when payloads can grow. Cache `Intl.NumberFormat`, `Intl.DateTimeFormat`, regexes, and similar formatter/parser objects outside hot loops or render paths when ownership and locale inputs are stable.
|
|
117
|
+
30. Propagate cancellation when the operation can outlive a request, job, stream, retry loop, timeout, or user action. Accept and forward `AbortSignal` or the repository's established cancellation token when available.
|
|
118
|
+
31. Do not implement timeout as a caller-only race that leaves the real work running. Timeout behavior must cancel or abort the underlying operation when the API supports it.
|
|
119
|
+
32. Put cleanup in a deterministic path. Timers, event listeners, stream readers, Node streams, temp files, locks, transactions, subscriptions, and shutdown drains need success, failure, timeout, and cancellation cleanup coverage when touched.
|
|
120
|
+
33. Do not build package exports or dependency changes without checking consumers, tests, and docs examples.
|
|
121
|
+
34. Choose configured verification intents that cover lint, build, tests, package entry, runtime behavior, async rejection handling, cancellation, cleanup, and hot-path data-shape semantics when available.
|
|
106
122
|
|
|
107
123
|
<!-- mustflow-section: postconditions -->
|
|
108
124
|
## Postconditions
|
|
@@ -110,8 +126,9 @@ Preserve JavaScript module, runtime, package entry, Promise, cleanup, dependency
|
|
|
110
126
|
- Runtime and module boundaries are explicit.
|
|
111
127
|
- Promise failures are not hidden.
|
|
112
128
|
- Runtime-specific APIs do not leak into shared, browser, edge, or package entry code.
|
|
129
|
+
- Collection and object-shape changes preserve lookup, ordering, duplicate, lifecycle, and allocation semantics.
|
|
113
130
|
- Package entry changes are synchronized with tests or reported as unverified.
|
|
114
|
-
- Async cancellation and cleanup behavior
|
|
131
|
+
- Async cancellation, failure policy, payload parsing, CPU offload, and cleanup behavior are covered or reported as remaining risk.
|
|
115
132
|
- No unnecessary dependency was added.
|
|
116
133
|
|
|
117
134
|
<!-- mustflow-section: verification -->
|
|
@@ -145,6 +162,7 @@ Report missing browser, Node, edge, Bun, TypeScript-consumer, package-entry, asy
|
|
|
145
162
|
- Boundary checked
|
|
146
163
|
- Runtime and module notes
|
|
147
164
|
- Async and dependency notes
|
|
165
|
+
- Data-shape and hot-path notes
|
|
148
166
|
- Files changed
|
|
149
167
|
- Command intents run
|
|
150
168
|
- Skipped checks and reasons
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
mustflow_doc: skill.memory-lifetime-review
|
|
3
3
|
locale: en
|
|
4
4
|
canonical: true
|
|
5
|
-
revision:
|
|
5
|
+
revision: 3
|
|
6
6
|
lifecycle: mustflow-owned
|
|
7
7
|
authority: procedure
|
|
8
8
|
name: memory-lifetime-review
|
|
@@ -80,6 +80,7 @@ The question is not only "where was it allocated?" The stronger review question
|
|
|
80
80
|
- Refactor setup and cleanup into a shared lifecycle boundary when it prevents duplicate registration or forgotten teardown.
|
|
81
81
|
- 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.
|
|
82
82
|
- Do not hide leak warnings by raising listener limits, disabling strict lifecycle checks, adding finalizers as primary cleanup, or weakening tests.
|
|
83
|
+
- 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.
|
|
83
84
|
- Do not use weak references as a design cover-up when the real owner and cleanup point should be explicit.
|
|
84
85
|
|
|
85
86
|
<!-- mustflow-section: procedure -->
|
|
@@ -110,6 +111,8 @@ The question is not only "where was it allocated?" The stronger review question
|
|
|
110
111
|
- Producer-consumer queues need a capacity, drop or backpressure policy, timeout, and consumer shutdown path.
|
|
111
112
|
10. Check language and runtime traps where applicable.
|
|
112
113
|
- JavaScript and TypeScript: `addEventListener`, EventEmitter listeners, `setMaxListeners`, timers, intervals, unresolved promises, `AbortSignal`, React effects, ref arrays, module caches, maps, and logging queues.
|
|
114
|
+
- JavaScript metadata: use `WeakMap` or `WeakSet` for metadata attached to DOM nodes, AST nodes, request objects, sockets, or component instances when the metadata should die with the object; use a normal `Map` only when retention is intentional and bounded.
|
|
115
|
+
- JavaScript allocation and GC: avoid turning small short-lived records into long-lived pooled objects without evidence; check large temporary arrays, buffers, object graphs, array method chains, and old-generation retention before tuning `--max-old-space-size` or `--max-semi-space-size`.
|
|
113
116
|
- React and similar UI runtimes: effects that touch the outside world need cleanup that reverses setup; ref callbacks and registries must remove old nodes and survive strict double-invocation checks.
|
|
114
117
|
- Android: ViewModel or application-scope objects must not retain Activity, Fragment, View, lifecycle owner, or short-lived context; use lifecycle cleanup such as `onCleared` where appropriate.
|
|
115
118
|
- Java and Kotlin: thread pools plus `ThreadLocal`, static caches, listener registries, executors, cursors, streams, and closeable resources need explicit release.
|
|
@@ -131,7 +134,8 @@ The question is not only "where was it allocated?" The stronger review question
|
|
|
131
134
|
- Core dump, exact binary, symbols, build id, shared library list, process maps, allocator state, failing input, and deployment version can be the only evidence for a memory fault.
|
|
132
135
|
- If those artifacts are unavailable or manual-only, report that boundary instead of implying the crash was diagnosed from logs alone.
|
|
133
136
|
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.
|
|
134
|
-
16.
|
|
137
|
+
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
|
+
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.
|
|
135
139
|
|
|
136
140
|
<!-- mustflow-section: postconditions -->
|
|
137
141
|
## Postconditions
|
|
@@ -139,6 +143,7 @@ The question is not only "where was it allocated?" The stronger review question
|
|
|
139
143
|
- Every setup site has a cleanup owner, cleanup trigger, and repeated-path behavior, or the missing evidence is reported.
|
|
140
144
|
- Long-lived owners no longer retain short-lived objects beyond their intended lifecycle, or the remaining retention is intentional and bounded.
|
|
141
145
|
- Caches, queues, registries, debug stores, and logging or telemetry buffers have capacity, eviction, truncation, or copied-value boundaries where they can grow.
|
|
146
|
+
- Weak metadata, object pooling, allocation churn, GC flags, and retained-heap claims are backed by ownership or diagnostic evidence rather than folklore.
|
|
142
147
|
- Async, stream, worker, goroutine, thread, and native-resource paths have deterministic cancellation, close, shutdown, or release behavior where the platform supports it.
|
|
143
148
|
- 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.
|
|
144
149
|
- Tests or configured verification cover the highest-risk repeated lifecycle when feasible.
|
|
@@ -177,6 +182,7 @@ Use the narrowest configured test, build, docs, release, or mustflow intent that
|
|
|
177
182
|
- Retainer paths found or ruled out
|
|
178
183
|
- Long-lived owners and short-lived objects checked
|
|
179
184
|
- Timers, listeners, subscriptions, streams, workers, goroutines, threads, native handles, caches, queues, registries, closures, and logs checked where relevant
|
|
185
|
+
- Weak metadata, object pooling, allocation churn, and GC diagnostics checked where relevant
|
|
180
186
|
- First invalid access, diagnostic build axis, dangling ownership, fuzzing or core-dump evidence where relevant
|
|
181
187
|
- Cleanup symmetry changes made or recommended
|
|
182
188
|
- Repeated-lifecycle proof: configured, manual-only, missing, or not applicable
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
mustflow_doc: skill.node-code-change
|
|
3
3
|
locale: en
|
|
4
4
|
canonical: true
|
|
5
|
-
revision:
|
|
5
|
+
revision: 4
|
|
6
6
|
lifecycle: mustflow-owned
|
|
7
7
|
authority: procedure
|
|
8
8
|
name: node-code-change
|
|
9
|
-
description: Apply this skill when Node.js runtime code, package manager ownership, module format, package entry metadata, native dependencies, Node test runner behavior, TypeScript execution mode, or deployment runtime support is created or changed.
|
|
9
|
+
description: Apply this skill when Node.js runtime code, server performance behavior, event-loop blocking, libuv worker-pool use, package manager ownership, module format, package entry metadata, native dependencies, Node test runner behavior, TypeScript execution mode, or deployment runtime support is created or changed.
|
|
10
10
|
metadata:
|
|
11
11
|
mustflow_schema: "1"
|
|
12
12
|
mustflow_kind: procedure
|
|
@@ -29,12 +29,13 @@ metadata:
|
|
|
29
29
|
<!-- mustflow-section: purpose -->
|
|
30
30
|
## Purpose
|
|
31
31
|
|
|
32
|
-
Preserve the actual Node.js runtime, module, package manager, TypeScript execution, test runner, package entry, native dependency, and
|
|
32
|
+
Preserve the actual Node.js runtime, module, package manager, TypeScript execution, test runner, package entry, native dependency, deployment, event-loop, worker-pool, and server-performance boundaries.
|
|
33
33
|
|
|
34
34
|
<!-- mustflow-section: use-when -->
|
|
35
35
|
## Use When
|
|
36
36
|
|
|
37
37
|
- Node.js runtime code, `node:*` APIs, `process`, `Buffer`, streams, workers, child processes, native addons, Node permission flags, Node test runner behavior, package entry metadata, or deployment runtime support changes.
|
|
38
|
+
- Node server code, CLI code, workers, request handlers, stream handlers, serializers, parsers, regex validation, crypto, zlib, filesystem, DNS, child process, or CPU-heavy JavaScript changes can affect event-loop delay, event-loop utilization, libuv worker-pool pressure, CPU profiles, GC, or p95/p99 latency.
|
|
38
39
|
- `package.json` Node fields change, including `engines.node`, `devEngines`, `packageManager`, `type`, `main`, `exports`, `imports`, `types`, `typesVersions`, `files`, `bin`, `sideEffects`, or `workspaces`.
|
|
39
40
|
- Node version signals, CI Node setup, Docker Node base images, serverless Node runtime settings, Corepack usage, npm, pnpm, Yarn, or lockfile ownership changes.
|
|
40
41
|
- The task proposes native Node TypeScript execution, ESM/CJS conversion, conditional exports, package manager migration, or Node built-in test runner migration.
|
|
@@ -55,6 +56,7 @@ Preserve the actual Node.js runtime, module, package manager, TypeScript executi
|
|
|
55
56
|
- Module and package metadata: nearest `package.json#type`, file extensions, `main`, `module`, `exports`, `imports`, `types`, `typings`, `typesVersions`, `files`, `bin`, `sideEffects`, and documented import paths.
|
|
56
57
|
- TypeScript and loader signals: `tsconfig*.json`, `tsx`, `ts-node`, SWC, Babel, Vite, tsup, esbuild, Node native type stripping, path aliases, declaration output, and test or build transforms.
|
|
57
58
|
- Test, native, and deployment signals: package scripts, test runner config, `node:test` usage, native dependency indicators such as `.node`, `binding.gyp`, `node-gyp`, lifecycle scripts, optional dependencies, serverless or edge config, and command contract entries.
|
|
59
|
+
- Node performance signals: `perf_hooks` usage, event-loop utilization, event-loop delay histograms, CPU profile or flame graph setup, request-level I/O timings, `--trace-sync-io`, worker-thread pools, `UV_THREADPOOL_SIZE`, stream backpressure, large JSON handling, regex validation, GC or heap flags, and timeout or cancellation paths.
|
|
58
60
|
|
|
59
61
|
<!-- mustflow-section: preconditions -->
|
|
60
62
|
## Preconditions
|
|
@@ -99,7 +101,16 @@ Preserve the actual Node.js runtime, module, package manager, TypeScript executi
|
|
|
99
101
|
17. Inspect native and install-sensitive dependencies when package metadata or runtime imports touch `.node`, `binding.gyp`, `node-gyp`, `preinstall`, `install`, `postinstall`, `prepare`, optional dependencies, peer dependencies, OS, CPU, libc, or Node ABI boundaries.
|
|
100
102
|
18. Treat optional dependencies and optional peers as absent until code handles absence. Do not require optional packages directly without fallback or error handling that matches the existing project pattern.
|
|
101
103
|
19. Treat the Node permission model as a trusted-code seatbelt, not a sandbox for untrusted code. If permission flags are introduced or changed, map required filesystem, network, child process, worker, native addon, WASI, inspector, and temporary directory access explicitly.
|
|
102
|
-
20.
|
|
104
|
+
20. Separate Node performance bottlenecks before choosing a fix. Use available `perf_hooks` or configured evidence to distinguish JavaScript CPU, event-loop delay, external I/O wait, libuv worker-pool saturation, stream backpressure, and GC or allocation churn. Event-loop utilization is not CPU percent; high ELU with low CPU can still mean sync blocking.
|
|
105
|
+
21. Prefer CPU profiles or flame graphs over timing logs for CPU-heavy Node paths. Use profile or configured evidence for parsing, validation, rendering, hashing, compression, crypto, diffing, report generation, sorting, JSON work, formatter creation, or AST work; log timers alone rarely prove the hot stack.
|
|
106
|
+
22. Treat event-loop delay as a tail metric. Check p95 and p99 delay when evidence exists, not only averages. A rare 800ms block can dominate user-visible latency while average delay looks clean.
|
|
107
|
+
23. Keep server code off synchronous Node APIs after startup. `fs`, crypto, zlib, DNS, and child-process sync calls block the event loop; large `JSON.parse` or `JSON.stringify`, catastrophic regex, expensive sort comparators, repeated `Intl` or `Date` formatter construction, and eager logging serialization can do the same even without `Sync` in the name.
|
|
108
|
+
24. Use worker threads for CPU-bound JavaScript or native-bound work, not as a cure for slow DB, HTTP, Redis, or filesystem waits. Slow external I/O needs query, pool, timeout, cancellation, backpressure, batching, or provider-boundary fixes.
|
|
109
|
+
25. Treat the libuv worker pool as shared. Async `fs`, crypto, zlib, and `dns.lookup` can starve each other; `UV_THREADPOOL_SIZE` is a startup environment decision, not a runtime patch hidden inside application code.
|
|
110
|
+
26. Preserve stream backpressure. For large files, uploads, exports, compression, proxying, and generated responses, prefer pipeline-style boundaries with error handling over whole-buffer reads or unchecked writes.
|
|
111
|
+
27. Avoid `process.nextTick()` starvation. Recursive next-tick queues can prevent I/O polling; long work should be batched with event-loop yielding that lets I/O progress.
|
|
112
|
+
28. Include GC and allocation in Node CPU diagnosis. A profile dominated by V8, GC, allocation, string/Buffer copies, or JSON work usually needs allocation reduction, streaming, chunking, pagination, bounded caches, or worker offload before heap-size tuning.
|
|
113
|
+
29. Choose configured verification intents that cover lint, build, tests, package metadata, release-sensitive package output, docs examples, and mustflow contract checks when available. Report missing consumer fixture, ESM, CJS, TypeScript consumer, native dependency, deployment, permission, profiler, event-loop-delay, worker-pool, stream, or performance verification.
|
|
103
114
|
|
|
104
115
|
<!-- mustflow-section: postconditions -->
|
|
105
116
|
## Postconditions
|
|
@@ -109,6 +120,7 @@ Preserve the actual Node.js runtime, module, package manager, TypeScript executi
|
|
|
109
120
|
- Native TypeScript execution is not mistaken for typecheck, declaration emit, or a full build pipeline.
|
|
110
121
|
- Node-only APIs do not leak into browser, edge, Bun, or shared package surfaces unintentionally.
|
|
111
122
|
- Native dependency, lifecycle, optional dependency, and permission-model risks are handled or reported.
|
|
123
|
+
- Event-loop blocking, CPU profile, libuv worker-pool, stream backpressure, large JSON, regex REDOS, worker-thread fit, `process.nextTick()` starvation, and GC or allocation risks are handled or reported when touched.
|
|
112
124
|
|
|
113
125
|
<!-- mustflow-section: verification -->
|
|
114
126
|
## Verification
|
|
@@ -123,7 +135,7 @@ Use configured oneshot command intents when available:
|
|
|
123
135
|
- `test_release`
|
|
124
136
|
- `mustflow_check`
|
|
125
137
|
|
|
126
|
-
Report missing ESM/CJS consumer, declaration output, package artifact, frozen install, native dependency, deployment runtime, permission-model,
|
|
138
|
+
Report missing ESM/CJS consumer, declaration output, package artifact, frozen install, native dependency, deployment runtime, permission-model, runner-specific, CPU-profile, event-loop-delay, worker-pool, stream-backpressure, or performance verification intents when those surfaces change.
|
|
127
139
|
|
|
128
140
|
<!-- mustflow-section: failure-handling -->
|
|
129
141
|
## Failure Handling
|
|
@@ -133,6 +145,7 @@ Report missing ESM/CJS consumer, declaration output, package artifact, frozen in
|
|
|
133
145
|
- If a package entry change blocks a documented or previously supported import path, restore compatibility or report the breaking-change requirement.
|
|
134
146
|
- If native Node TypeScript execution fails, repair the build/loader boundary instead of weakening typecheck or deleting the TypeScript pipeline.
|
|
135
147
|
- If native dependency installation or optional dependency behavior is unclear, classify the change as release-sensitive and report the missing install or runtime evidence.
|
|
148
|
+
- If a Node performance claim lacks event-loop, CPU, I/O, worker-pool, stream, or GC evidence, label it as static risk or missing measurement instead of reporting a measured speedup.
|
|
136
149
|
|
|
137
150
|
<!-- mustflow-section: output-format -->
|
|
138
151
|
## Output Format
|
|
@@ -141,6 +154,7 @@ Report missing ESM/CJS consumer, declaration output, package artifact, frozen in
|
|
|
141
154
|
- Module and package entry notes
|
|
142
155
|
- TypeScript execution and test runner notes
|
|
143
156
|
- Native, lifecycle, deployment, or permission risks
|
|
157
|
+
- Event-loop, CPU, worker-pool, stream, JSON, regex, next-tick, or GC risks
|
|
144
158
|
- Files changed
|
|
145
159
|
- Command intents run
|
|
146
160
|
- Skipped checks and reasons
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
mustflow_doc: skill.performance-budget-check
|
|
3
3
|
locale: en
|
|
4
4
|
canonical: true
|
|
5
|
-
revision:
|
|
5
|
+
revision: 24
|
|
6
6
|
lifecycle: mustflow-owned
|
|
7
7
|
authority: procedure
|
|
8
8
|
name: performance-budget-check
|
|
@@ -55,6 +55,9 @@ Prefer removing unnecessary work over making unnecessary work slightly faster. A
|
|
|
55
55
|
- Performance surface: request path, command path, render path, build step, batch job, queue, cache, database path, filesystem path, IPC/RPC boundary, or test scheduler.
|
|
56
56
|
- Hot-path shape: expected call frequency, input size, growth direction, nested loops, external round trips, payload size, rendered node count, allocation rate, data layout, branch predictability, lock or pool contention, queue depth, and whether the path runs during user input or startup.
|
|
57
57
|
- Time breakdown evidence: user-visible moment, wall-time split across browser, network, application CPU, DB, cache, external API, queue, filesystem, IPC, serialization, compression, logging, and render work, plus CPU time versus wait time when available.
|
|
58
|
+
- Runtime and browser execution evidence: initial JavaScript parse, compile, evaluate, hydration, long tasks, event-loop utilization, p95 or p99 event-loop delay, CPU profile, libuv worker-pool pressure, stream backpressure, GC pause, and request-level I/O timings when relevant.
|
|
59
|
+
- JavaScript engine evidence boundary when relevant: whether claims come from Chrome or Node V8, browser DevTools Performance or Memory output, Node CPU profiles, Safari or Firefox traces, or static complexity review only.
|
|
60
|
+
- Main-thread contention evidence for browser paths: microtask pressure, large JSON parsing, DOM mutation count, forced layout, style invalidation scope, animation frame work, high-frequency event handlers, idle work, worker offload boundary, Long Tasks API entries, and Performance panel traces when available.
|
|
58
61
|
- Measurement method or evidence: configured command intent, profiler output, query count, runtime log, trace span, resource metric, benchmark, complexity analysis, or reason the metric is unavailable.
|
|
59
62
|
- Baseline and post-change result when measurable under comparable constraints, including whether the evidence reflects average, p95, p99, cold start, warm cache, realistic data size, or local-only behavior.
|
|
60
63
|
- Saturation evidence: utilization, backlog or queue depth, pool wait, lock wait, retry or error rate, tenant or data skew, and good-period versus bad-period comparison when available.
|
|
@@ -91,13 +94,16 @@ Prefer removing unnecessary work over making unnecessary work slightly faster. A
|
|
|
91
94
|
- Decompose elapsed time before touching code. Split request, render, command, or job wall time across browser, network, server routing, authorization, application CPU, DB, cache, external APIs, queue wait, filesystem, IPC, serialization, compression, logging, response download, and render. Distinguish CPU time from wait time; high wall time with low CPU means the path is waiting.
|
|
92
95
|
- Find queueing and saturation, not just high utilization. Check utilization, backlog, queue depth, pool waits, lock waits, retry or error rate, and p95/p99 latency together. Compare good periods to bad periods, affected tenants or data sizes, specific workers or replicas, and cold versus warm cache before declaring the bottleneck.
|
|
93
96
|
2. Rank the likely return on effort before choosing a technique. In typical web or service paths, first check DB/API round-trip count, slow query plans, repeated reads that could be safely cached, work that does not need to block the response, static or media delivery, response payload shape, and then CPU or allocation micro-optimizations. Escalate algorithmic or runtime work early only when the measured hot path is CPU-heavy, data-processing-heavy, render-loop-heavy, or clearly quadratic.
|
|
94
|
-
3. Do not stop at asymptotic complexity. For `O(N)`, check sequential versus pointer-chasing access, working-set size, branch predictability, per-item allocation, string or Unicode work, runtime dispatch, logging, locks, and external round trips. For `O(log N)`, check node locality, comparator cost, key size, pointer jumps, and branch behavior. For `O(1)` maps or caches, check hash cost, key equality, load factor, resize or rehash spikes, collision behavior, key mutability, cache miss path, and hot-key contention.
|
|
97
|
+
3. Do not stop at asymptotic complexity. For `O(N)`, check sequential versus pointer-chasing access, working-set size, branch predictability, per-item allocation, string or Unicode work, runtime dispatch, logging, locks, and external round trips. For `O(log N)`, check node locality, comparator cost, key size, pointer jumps, and branch behavior. For `O(1)` maps or caches, check hash cost, key equality, load factor, resize or rehash spikes, collision behavior, key mutability, cache miss path, and hot-key contention. For JavaScript, separate engine-friendly data shape from language preference: V8-friendly object and array shapes are useful for Chrome and Node, but Safari and Firefox need their own measurement before the claim becomes cross-browser.
|
|
95
98
|
4. Classify the performance surface:
|
|
96
99
|
- CPU and algorithm: nested loops, repeated lookup, sorting, parsing, formatting, validation, scoring, diffing, search, regex, JSON work, compression, crypto, image processing, context switching, event-loop blocking, runtime dispatch, or CPU throttling.
|
|
97
100
|
- I/O and external boundaries: DB, filesystem, HTTP/RPC, Redis/cache, object storage, IPC, child processes, provider SDKs, DNS, TLS, retransmits, cross-region calls, or load-balancer hot spots.
|
|
98
101
|
- Memory and allocation: object churn, deep clone, DTO conversion, large object graphs, byte/string copies, serialization, boxing, pointer chasing, cache locality, and GC pressure.
|
|
99
102
|
- UI and delivery: unstable references, broad store invalidation, large lists, layout thrashing, image or icon load, font loading, hydration cost, bundle parse or execute time, payload size, input delay, and main-thread work.
|
|
100
103
|
- Concurrency and resilience: pool exhaustion, long transactions, locks, retry storms, queue growth, backpressure, cancellation, partial failure, and shared-resource bottlenecks that autoscaling cannot remove.
|
|
104
|
+
- Frontend bundle execution: compressed bytes, decompressed bytes, initial JS parse, compile, evaluate, hydration, long tasks, route Coverage, shared vendor chunks, modulepreload, preload or prefetch priority, and chunk cache stability. Do not accept gzip-only savings as proof of faster first interaction.
|
|
105
|
+
- Browser main-thread contention: async callbacks, microtasks, JSON parsing, DOM insertion, style recalculation, forced reflow, paint, compositing, and framework rerenders compete for the same interaction budget. Do not evaluate "async optimization" and "render optimization" as separate wins unless the shared main-thread budget improved.
|
|
106
|
+
- Node.js runtime pressure: CPU profile, event-loop utilization, p95 or p99 event-loop delay, sync API use, large JSON, REDOS, libuv worker-pool saturation, stream backpressure, worker-thread fit, `process.nextTick()` starvation, and GC or allocation churn.
|
|
101
107
|
5. Look for repeated external access first. Loops around repository calls, ORM lazy fields, DB queries, network calls, Redis gets, object storage calls, filesystem stats, IPC commands, or child processes are usually higher risk than local arithmetic.
|
|
102
108
|
6. Remove N+1 and fan-out before micro-optimizing. Prefer batch loading, bulk APIs, bounded concurrency, preloading, projection, and one request that returns the data shape the caller actually needs.
|
|
103
109
|
7. Check DB and ORM reality before adding caches. Confirm query count, selected columns, lazy loading, index fit, sort or pagination shape, row estimates, rows examined versus returned, temp sorts or tables, lock waits, transaction duration, replication lag, WAL or checkpoint pressure, and connection-pool waits. Do not use a cache to hide a query shape that should be fixed first. Treat pool size as a safety valve, not a cure for slow queries, long transactions, hot rows, or N+1 access.
|
|
@@ -107,7 +113,7 @@ Prefer removing unnecessary work over making unnecessary work slightly faster. A
|
|
|
107
113
|
11. Bound reads and materialization. Avoid unbounded `SELECT *`, `findAll`, full filesystem scans, full JSON loads, full array materialization, whole response bodies, and API responses without pagination, projection, chunking, or streaming when data can grow.
|
|
108
114
|
12. Reduce payload and media work before tuning rendering internals. Send only needed fields, avoid overfetching, split late or optional data, use HTTP caching or CDN only for cacheable assets or responses, and check image dimensions, formats, lazy loading, and fixed layout dimensions before adding component memoization.
|
|
109
115
|
- Treat compression and streaming as latency tradeoffs, not free wins. Check compression CPU, content-coding negotiation, dictionary fallback, proxy buffering, buffered stream latency, flush latency, reconnect pressure, and whether p95/p99 improves for the actual client path. Do not report a false compression win when smaller bytes increase CPU, buffering, or tail latency.
|
|
110
|
-
13. Check sorting and top-k work. Do not sort entire collections when only a top subset is needed. Precompute sort keys when comparison logic parses dates, normalizes strings, computes scores, or reads paths.
|
|
116
|
+
13. Check sorting and top-k work. Do not sort entire collections when only a top subset is needed. Precompute sort keys when comparison logic parses dates, calls locale comparison, normalizes strings, computes scores, serializes data, builds lookup keys, or reads paths.
|
|
111
117
|
14. Check pagination semantics. Offset pagination can become linearly slower and can duplicate or skip items on changing data. Prefer stable keyset or cursor semantics when the product does not require arbitrary page jumps.
|
|
112
118
|
15. Move repeated pure computation out of loops and renders. Normalize queries once, precompute search blobs or numeric timestamps, reuse regexes and formatters, and avoid repeated schema validation after data crosses a trusted boundary.
|
|
113
119
|
16. Reuse expensive clients and sessions. Do not create HTTP clients, DB clients, ORM clients, SDK clients, regexes, date formatters, connection pools, or thread pools per request, per item, or per render unless the local API explicitly requires that lifecycle.
|
|
@@ -129,11 +135,13 @@ Prefer removing unnecessary work over making unnecessary work slightly faster. A
|
|
|
129
135
|
30. Check retry, timeout, and external dependency behavior. Retries need maximum attempts, exponential backoff, jitter, idempotency, and circuit-breaking or graceful degradation when an external service is slow or unavailable.
|
|
130
136
|
31. Check logging and telemetry overhead. Avoid serializing large payloads or building expensive log strings on successful hot paths. Metrics and logs also need bounded cardinality and sampling on high-frequency paths. Do not remove useful observability to make numbers look better; good traces, query counts, cache hit rates, queue backlog, pool waits, tenant or shard labels, and retry/error signals are part of the performance surface.
|
|
131
137
|
32. Run a language and runtime smell pass when applicable:
|
|
132
|
-
- TypeScript and JavaScript: repeated `includes` or `find`, unbounded `Promise.all`, `forEach(async ...)`, ORM N+1, object spread clones, JSON deep clone, repeated `new Date`, `console.log(JSON.stringify(...))`, per-request clients, large sync JSON or file work,
|
|
138
|
+
- TypeScript and JavaScript: repeated `includes` or `find`, unbounded `Promise.all`, `forEach(async ...)`, ORM N+1, object spread clones, JSON deep clone, repeated `new Date`, repeated `Intl` formatter construction, repeated Array built-in borrowing on `arguments` or `NodeList`, `console.log(JSON.stringify(...))`, per-request clients, large sync JSON or file work, CPU work on the event loop, `Map` or `Set` O(1) folklore, `shift()` queues, middle-`splice` deletes, expensive sort comparators, holey or mixed-kind arrays, hot-object `delete`, and object pooling without allocation evidence.
|
|
139
|
+
- Node.js servers and CLIs: sync `fs`, crypto, zlib, DNS, or child-process calls after startup; large `JSON.parse` or `JSON.stringify`; REDOS-prone regexes; CPU-heavy work without a profile; treating ELU as CPU percent; averages hiding p95 or p99 event-loop delay; worker threads used for slow external I/O; runtime changes to `UV_THREADPOOL_SIZE`; streams without backpressure; recursive `process.nextTick()`; and heap-size tuning before allocation evidence.
|
|
140
|
+
- Frontend JavaScript bundles: gzip-only budgets, analyzer-only claims without route Coverage, `dynamic import()` modules also statically imported by the first route, arbitrary component-level chunking, one giant vendor chunk, unsafe `sideEffects: false`, barrel files on first-route paths, old browser targets that add transforms or polyfills, asset inline thresholds that bloat JavaScript or CSS, and preload or prefetch priority inflation without Resource Timing evidence.
|
|
133
141
|
- Go: goroutine per item, missing `context` or timeout, per-call `http.Client`, `io.ReadAll` on growing input, slice growth without capacity, one mutex around a large map, and synchronous logging or formatting in hot loops.
|
|
134
142
|
- Rust: `.clone()` to silence ownership design, unnecessary `collect`, repeated `Regex::new`, `Arc<Mutex<_>>` as a default, `join_all` over unbounded futures, CPU-bound work on async executors, and missing `with_capacity` for large collections.
|
|
135
143
|
- Python: list membership in loops, sequential `requests` calls without session reuse, unbounded `asyncio.gather`, full `read()` or `json.load()` on growing files, `deepcopy`, repeated `datetime.strptime`, f-string logging at disabled levels, row-wise pandas loops, and CPU work on the event loop.
|
|
136
|
-
33. Measure when possible. Use the narrowest configured command intent that exercises the path. If measurement is unavailable, report the result as complexity evidence rather than a speed claim. Do not compare local microbenchmarks to production user experience unless data size, cache state, network, concurrency, and tail-latency conditions are comparable.
|
|
144
|
+
33. Measure when possible. Use the narrowest configured command intent that exercises the path. If measurement is unavailable, report the result as complexity evidence rather than a speed claim. Do not compare local microbenchmarks to production user experience unless data size, cache state, network, concurrency, and tail-latency conditions are comparable. Do not treat a Chrome or Node V8 profile as proof for Safari or Firefox; label it as V8-specific unless those targets were measured.
|
|
137
145
|
34. Treat deploys, restarts, migrations, rebalances, and cache warmups as performance events. A path that is fast only after warm caches, settled JIT, stable replicas, or completed compaction should report cold-start and recovery risk separately from steady-state speed.
|
|
138
146
|
35. Keep large performance architecture changes separate. Watcher refresh, bulk IPC commands, projection caches, virtualized lists, worker offload, queue introduction, cache layers, CDN behavior, sharding, and storage redesigns should be independent changes unless the repository evidence proves they must land together.
|
|
139
147
|
|
|
@@ -143,7 +151,7 @@ Prefer removing unnecessary work over making unnecessary work slightly faster. A
|
|
|
143
151
|
- The hot path, cost multiplier, and affected input scale are explicit.
|
|
144
152
|
- The optimization goal is explicit: user-perceived speed, server cost, p95 or p99 stability, failure isolation, memory headroom, or developer-loop speed.
|
|
145
153
|
- The wall-time breakdown, CPU-versus-wait classification, saturation signal, and resource bottleneck class are explicit when evidence exists.
|
|
146
|
-
- Speed, memory, bundle, payload, query-count, render, CPU locality, allocation, lock, pool, queue, or I/O claims are backed by measurement or labeled as complexity-only.
|
|
154
|
+
- Speed, memory, bundle, payload, query-count, render, CPU locality, allocation, event-loop, worker-pool, long-task, lock, pool, queue, or I/O claims are backed by measurement or labeled as complexity-only.
|
|
147
155
|
- N+1 work, hidden quadratic scans, unbounded materialization, repeated serialization, repeated allocation, client/session churn, broad rendering, and unbounded or accidentally sequential async work are removed or reported.
|
|
148
156
|
- Caches, queues, batching, concurrency, workers, streams, compression, CDN or HTTP caching, media optimization, and projections have invalidation, ordering, duplicate, partial-failure, cancellation, backpressure, capacity, stale-data, CPU, and memory behavior defined where relevant.
|
|
149
157
|
- Correctness, security, durability, privacy, and user-visible semantics remain intact or are explicitly reported as tradeoffs.
|
|
@@ -182,7 +190,7 @@ Use the narrowest configured test, build, docs, release, or mustflow intent that
|
|
|
182
190
|
- Performance evidence: measured, complexity-only, or unverified
|
|
183
191
|
- Semantics preserved: order, duplicates, IDs, consistency, partial failure, cancellation, and stale result handling
|
|
184
192
|
- Optimization applied or recommended
|
|
185
|
-
- Cache, queue, batching, concurrency, projection, UI, payload, compression, HTTP delivery, media, memory, runtime, lock, pool, stream, retry, timeout, deployment, sharding, and I/O notes where relevant
|
|
193
|
+
- Cache, queue, batching, concurrency, projection, UI, payload, compression, HTTP delivery, media, memory, runtime, Node event-loop, worker-pool, frontend initial-JS, long-task, lock, pool, stream, retry, timeout, deployment, sharding, and I/O notes where relevant
|
|
186
194
|
- Command intents run
|
|
187
195
|
- Skipped measurements and reasons
|
|
188
196
|
- Remaining performance risk
|