@bompus/house-rules 0.0.0-stage → 0.13.0

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.
Files changed (236) hide show
  1. package/CODE_OF_CONDUCT.md +83 -0
  2. package/CONTRIBUTING.md +54 -0
  3. package/LICENSE +21 -0
  4. package/README.md +378 -2
  5. package/THIRD_PARTY_NOTICES.md +188 -0
  6. package/compose.mjs +125 -0
  7. package/composition.mjs +361 -0
  8. package/config-view.mjs +209 -0
  9. package/config.mjs +381 -0
  10. package/docs/assets/banner-dark.png +0 -0
  11. package/docs/assets/banner-light.png +0 -0
  12. package/docs/assets/overview.png +0 -0
  13. package/docs/configuration.md +269 -0
  14. package/docs/skill-names.md +50 -0
  15. package/examples/person/house-rules.json +15 -0
  16. package/examples/person/rules/10-tooling.md +8 -0
  17. package/examples/person/rules/20-reporting.md +9 -0
  18. package/examples/project/AGENTS.md +18 -0
  19. package/package.json +42 -4
  20. package/rule-references.mjs +91 -0
  21. package/rules/core.md +340 -0
  22. package/rules/modifiers/backlog-outline.md +25 -0
  23. package/rules/modifiers/backlog-visual.md +16 -0
  24. package/rules/modifiers/coded-offers.md +70 -0
  25. package/rules/modifiers/cross-session-relay.md +23 -0
  26. package/rules/modifiers/effort-estimates.md +41 -0
  27. package/rules/modifiers/land-when-done.md +12 -0
  28. package/rules/modifiers/low-quota-handoff.md +20 -0
  29. package/rules/modifiers/model-default-questions.md +33 -0
  30. package/rules/modifiers/multi-agent.md +38 -0
  31. package/rules/modifiers/no-attribution.md +16 -0
  32. package/rules/modifiers/periodic-updates.md +25 -0
  33. package/rules/modifiers/plan-files.md +82 -0
  34. package/rules/modifiers/question-cards.md +48 -0
  35. package/rules/modifiers/release-batching.md +15 -0
  36. package/rules/modifiers/scratch-on-disk.md +15 -0
  37. package/rules/modifiers/shared-host-load.md +19 -0
  38. package/rules/modifiers/solo-operator.md +13 -0
  39. package/rules/modifiers/squash-landing.md +22 -0
  40. package/rules/modifiers/upstream-contributions.md +45 -0
  41. package/rules/modifiers/web-image-formats.md +35 -0
  42. package/rules/references/backlog-view.md +154 -0
  43. package/rules/references/github-actions.md +45 -0
  44. package/rules/references/landing.md +39 -0
  45. package/rules/references/multi-agent.md +51 -0
  46. package/rules/references/release-batching.md +66 -0
  47. package/rules/references/squash-landing.md +50 -0
  48. package/rules/references/thread-visuals.md +45 -0
  49. package/setup.mjs +445 -0
  50. package/skills/hr-agent-guidance-audit/LICENSE +21 -0
  51. package/skills/hr-agent-guidance-audit/SKILL.md +91 -0
  52. package/skills/hr-agent-guidance-audit/agents/openai.yaml +2 -0
  53. package/skills/hr-agent-guidance-audit/references/prune-workflow.md +72 -0
  54. package/skills/hr-agent-guidance-audit/references/records-and-lessons.md +60 -0
  55. package/skills/hr-agent-guidance-audit/references/retirement-verdicts.md +49 -0
  56. package/skills/hr-agent-guidance-refresh/LICENSE +21 -0
  57. package/skills/hr-agent-guidance-refresh/SKILL.md +36 -0
  58. package/skills/hr-agent-guidance-refresh/agents/openai.yaml +2 -0
  59. package/skills/hr-agent-guidance-refresh/references/verification.md +47 -0
  60. package/skills/hr-api-exposure-check/SKILL.md +159 -0
  61. package/skills/hr-api-exposure-check/agents/openai.yaml +3 -0
  62. package/skills/hr-audit-choices/SKILL.md +67 -0
  63. package/skills/hr-audit-choices/agents/openai.yaml +2 -0
  64. package/skills/hr-benchmarking/NOTICE.md +36 -0
  65. package/skills/hr-benchmarking/SKILL.md +279 -0
  66. package/skills/hr-benchmarking/agents/openai.yaml +2 -0
  67. package/skills/hr-benchmarking/references/javascript.md +130 -0
  68. package/skills/hr-benchmarking/references/tools.md +165 -0
  69. package/skills/hr-benchmarking/scripts/process-attribution.ps1 +20 -0
  70. package/skills/hr-benchmarking/scripts/process-attribution.py +107 -0
  71. package/skills/hr-better-accessibility/LICENSE +22 -0
  72. package/skills/hr-better-accessibility/NOTICE.md +46 -0
  73. package/skills/hr-better-accessibility/SKILL.md +119 -0
  74. package/skills/hr-better-accessibility/agents/openai.yaml +3 -0
  75. package/skills/hr-better-accessibility/focus-and-keyboard.md +130 -0
  76. package/skills/hr-better-accessibility/forms.md +82 -0
  77. package/skills/hr-better-accessibility/hit-areas.md +98 -0
  78. package/skills/hr-better-accessibility/motion-and-zoom.md +81 -0
  79. package/skills/hr-better-accessibility/screen-readers.md +102 -0
  80. package/skills/hr-better-accessibility/semantics-and-aria.md +84 -0
  81. package/skills/hr-better-colors/LICENSE +21 -0
  82. package/skills/hr-better-colors/NOTICE.md +37 -0
  83. package/skills/hr-better-colors/SKILL.md +114 -0
  84. package/skills/hr-better-colors/agents/openai.yaml +3 -0
  85. package/skills/hr-better-colors/color-formats.md +90 -0
  86. package/skills/hr-better-colors/color-usage.md +140 -0
  87. package/skills/hr-better-colors/contrast.md +80 -0
  88. package/skills/hr-better-colors/palette-generation.md +104 -0
  89. package/skills/hr-better-colors/palette-structure.md +76 -0
  90. package/skills/hr-better-colors/token-naming.md +97 -0
  91. package/skills/hr-better-layout/LICENSE +22 -0
  92. package/skills/hr-better-layout/NOTICE.md +48 -0
  93. package/skills/hr-better-layout/SKILL.md +92 -0
  94. package/skills/hr-better-layout/agents/openai.yaml +3 -0
  95. package/skills/hr-better-layout/grouping-and-alignment.md +144 -0
  96. package/skills/hr-better-layout/spacing-and-adaptivity.md +215 -0
  97. package/skills/hr-better-typography/LICENSE +22 -0
  98. package/skills/hr-better-typography/NOTICE.md +46 -0
  99. package/skills/hr-better-typography/SKILL.md +172 -0
  100. package/skills/hr-better-typography/agents/openai.yaml +3 -0
  101. package/skills/hr-better-typography/choosing-fonts.md +69 -0
  102. package/skills/hr-better-typography/css-cheat-sheet.md +65 -0
  103. package/skills/hr-better-typography/details-and-accessibility.md +119 -0
  104. package/skills/hr-better-typography/spacing-and-sizing.md +131 -0
  105. package/skills/hr-better-typography/variable-fonts-and-opentype.md +105 -0
  106. package/skills/hr-better-typography/wrapping-and-punctuation.md +57 -0
  107. package/skills/hr-better-writing/LICENSE +22 -0
  108. package/skills/hr-better-writing/NOTICE.md +46 -0
  109. package/skills/hr-better-writing/SKILL.md +122 -0
  110. package/skills/hr-better-writing/agents/openai.yaml +3 -0
  111. package/skills/hr-code-review/LICENSE +21 -0
  112. package/skills/hr-code-review/NOTICE.md +26 -0
  113. package/skills/hr-code-review/SKILL.md +163 -0
  114. package/skills/hr-code-review/agents/openai.yaml +3 -0
  115. package/skills/hr-code-review/references/acp-client.md +43 -0
  116. package/skills/hr-code-review/references/evidence.md +57 -0
  117. package/skills/hr-code-review/references/impact.md +103 -0
  118. package/skills/hr-code-review/references/panel-adjudication.md +58 -0
  119. package/skills/hr-code-review/references/panel-plan.md +61 -0
  120. package/skills/hr-code-review/references/panel-recommendations.json +105 -0
  121. package/skills/hr-code-review/references/panel-recommendations.md +46 -0
  122. package/skills/hr-code-review/references/panel-setup.md +54 -0
  123. package/skills/hr-code-review/references/reviewer-role.md +31 -0
  124. package/skills/hr-code-review/scripts/acp-panel-client.mjs +299 -0
  125. package/skills/hr-code-review/scripts/check-receipts.mjs +263 -0
  126. package/skills/hr-code-review/scripts/panel-plan.mjs +69 -0
  127. package/skills/hr-code-review/scripts/panel-preferences.mjs +220 -0
  128. package/skills/hr-design-exploration/SKILL.md +105 -0
  129. package/skills/hr-design-exploration/agents/openai.yaml +4 -0
  130. package/skills/hr-diagnosing-bugs/NOTICE.md +45 -0
  131. package/skills/hr-diagnosing-bugs/SKILL.md +108 -0
  132. package/skills/hr-diagnosing-bugs/agents/openai.yaml +3 -0
  133. package/skills/hr-diagnosing-bugs/references/reporting.md +97 -0
  134. package/skills/hr-diagnosing-bugs/scripts/check-pr-offer.mjs +47 -0
  135. package/skills/hr-explain-code/NOTICE.md +37 -0
  136. package/skills/hr-explain-code/SKILL.md +110 -0
  137. package/skills/hr-explain-code/agents/openai.yaml +5 -0
  138. package/skills/hr-explain-code/references/helper-brief.md +39 -0
  139. package/skills/hr-extract-shared-steps/SKILL.md +134 -0
  140. package/skills/hr-extract-shared-steps/agents/openai.yaml +3 -0
  141. package/skills/hr-forgotten-work-audit/SKILL.md +130 -0
  142. package/skills/hr-forgotten-work-audit/references/brief-template.md +56 -0
  143. package/skills/hr-forgotten-work-audit/references/result-format.md +46 -0
  144. package/skills/hr-handoff/LICENSE +21 -0
  145. package/skills/hr-handoff/NOTICE.md +29 -0
  146. package/skills/hr-handoff/SKILL.md +114 -0
  147. package/skills/hr-handoff/agents/openai.yaml +5 -0
  148. package/skills/hr-handoff/assets/ledger.example.json +10 -0
  149. package/skills/hr-handoff/assets/receipt.example.json +76 -0
  150. package/skills/hr-handoff/assets/source.example.json +20 -0
  151. package/skills/hr-handoff/references/reconciliation.md +124 -0
  152. package/skills/hr-handoff/references/successor-thread.md +76 -0
  153. package/skills/hr-handoff/scripts/check-reconciliation.mjs +324 -0
  154. package/skills/hr-house-rules-setup/SKILL.md +114 -0
  155. package/skills/hr-house-rules-setup/agents/openai.yaml +5 -0
  156. package/skills/hr-issue-tracker-setup/SKILL.md +49 -0
  157. package/skills/hr-issue-tracker-setup/agents/openai.yaml +5 -0
  158. package/skills/hr-lean-plan/SKILL.md +146 -0
  159. package/skills/hr-lean-plan/agents/openai.yaml +5 -0
  160. package/skills/hr-maintainability-review/SKILL.md +186 -0
  161. package/skills/hr-maintainability-review/agents/openai.yaml +5 -0
  162. package/skills/hr-manual-qa/NOTICE.md +36 -0
  163. package/skills/hr-manual-qa/SKILL.md +37 -0
  164. package/skills/hr-manual-qa/agents/openai.yaml +3 -0
  165. package/skills/hr-navigation-retro/LICENSE +21 -0
  166. package/skills/hr-navigation-retro/NOTICE.md +5 -0
  167. package/skills/hr-navigation-retro/SKILL.md +86 -0
  168. package/skills/hr-navigation-retro/agents/openai.yaml +4 -0
  169. package/skills/hr-navigation-retro/references/inputs.md +67 -0
  170. package/skills/hr-navigation-retro/scripts/retro.py +552 -0
  171. package/skills/hr-navigation-retro/scripts/transcripts.py +205 -0
  172. package/skills/hr-ordering-tests/SKILL.md +51 -0
  173. package/skills/hr-ordering-tests/agents/openai.yaml +2 -0
  174. package/skills/hr-plain-prose/SKILL.md +264 -0
  175. package/skills/hr-plain-prose/agents/openai.yaml +3 -0
  176. package/skills/hr-plain-prose/scripts/check.mjs +331 -0
  177. package/skills/hr-pr-followup/LICENSE +21 -0
  178. package/skills/hr-pr-followup/NOTICE.md +9 -0
  179. package/skills/hr-pr-followup/SKILL.md +74 -0
  180. package/skills/hr-pr-followup/agents/openai.yaml +2 -0
  181. package/skills/hr-pr-followup/references/review-helpers.md +111 -0
  182. package/skills/hr-pr-followup/scripts/check-landing.py +204 -0
  183. package/skills/hr-pr-followup/scripts/check-pr-review.ts +510 -0
  184. package/skills/hr-pr-followup/scripts/merge-pr.sh +100 -0
  185. package/skills/hr-pr-followup/scripts/resolve-pr-thread.ts +219 -0
  186. package/skills/hr-pr-followup/scripts/verify-landed.sh +184 -0
  187. package/skills/hr-progress-report/SKILL.md +49 -0
  188. package/skills/hr-progress-report/agents/openai.yaml +5 -0
  189. package/skills/hr-read-reddit/SKILL.md +44 -0
  190. package/skills/hr-read-reddit/agents/openai.yaml +2 -0
  191. package/skills/hr-read-reddit/scripts/reddit.ts +252 -0
  192. package/skills/hr-read-x-links/SKILL.md +42 -0
  193. package/skills/hr-read-x-links/agents/openai.yaml +2 -0
  194. package/skills/hr-read-x-links/scripts/x-post.ts +264 -0
  195. package/skills/hr-research-shared-links/SKILL.md +103 -0
  196. package/skills/hr-split-to-prs/LICENSE +21 -0
  197. package/skills/hr-split-to-prs/NOTICE.md +9 -0
  198. package/skills/hr-split-to-prs/SKILL.md +61 -0
  199. package/skills/hr-split-to-prs/agents/openai.yaml +2 -0
  200. package/skills/hr-sqlite/SKILL.md +174 -0
  201. package/skills/hr-sqlite/agents/openai.yaml +2 -0
  202. package/skills/hr-sqlite/references/evidence.md +94 -0
  203. package/skills/hr-sqlite/references/tool-decisions.md +39 -0
  204. package/skills/hr-sqlite/scripts/inspect-sqlite.py +245 -0
  205. package/skills/hr-stock-ui-audit/SKILL.md +132 -0
  206. package/skills/hr-stock-ui-audit/agents/openai.yaml +3 -0
  207. package/skills/hr-stock-ui-audit/scripts/scan.mjs +619 -0
  208. package/skills/hr-tdd/LICENSE +21 -0
  209. package/skills/hr-tdd/NOTICE.md +10 -0
  210. package/skills/hr-tdd/SKILL.md +40 -0
  211. package/skills/hr-tdd/agents/openai.yaml +3 -0
  212. package/skills/hr-tdd/mocking.md +39 -0
  213. package/skills/hr-tdd/tests.md +77 -0
  214. package/skills/hr-test-audit/LICENSE +21 -0
  215. package/skills/hr-test-audit/NOTICE.md +67 -0
  216. package/skills/hr-test-audit/SKILL.md +146 -0
  217. package/skills/hr-test-audit/agents/openai.yaml +3 -0
  218. package/skills/hr-test-audit/scripts/floor-guard.ts +137 -0
  219. package/skills/hr-usage-report/SKILL.md +90 -0
  220. package/skills/hr-usage-report/agents/openai.yaml +2 -0
  221. package/skills/hr-usage-report/assets/example-report.json +125 -0
  222. package/skills/hr-usage-report/assets/report-template.html +377 -0
  223. package/skills/hr-usage-report/scripts/render-report.ts +86 -0
  224. package/skills/hr-usage-report/scripts/usage-by-model.ts +499 -0
  225. package/skills/hr-what-next/SKILL.md +151 -0
  226. package/skills/hr-what-next/agents/openai.yaml +4 -0
  227. package/skills/hr-what-next/references/reporting.md +59 -0
  228. package/skills/hr-what-next/scripts/check-open-work.mjs +711 -0
  229. package/skills/hr-writing-for-agents/NOTICE.md +46 -0
  230. package/skills/hr-writing-for-agents/SKILL-MECHANICS.md +83 -0
  231. package/skills/hr-writing-for-agents/SKILL.md +108 -0
  232. package/skills/hr-writing-for-agents/agents/openai.yaml +3 -0
  233. package/skills/hr-writing-pr/NOTICE.md +48 -0
  234. package/skills/hr-writing-pr/SKILL.md +119 -0
  235. package/skills/hr-writing-pr/agents/openai.yaml +2 -0
  236. package/skills/hr-writing-pr/scripts/benefit-chart.py +200 -0
@@ -0,0 +1,36 @@
1
+ # Source notices
2
+
3
+ This notice accompanies the hr-benchmarking bundle when copied on its own.
4
+
5
+ ## cursor/plugins (pstack)
6
+
7
+ Source: https://github.com/cursor/plugins (compared at revision `e43c7ee`)
8
+
9
+ - `skills/hr-benchmarking/SKILL.md`: the validity checks are adapted from
10
+ `pstack/skills/benchmark-checklist/`.
11
+
12
+ Copyright (c) 2026 Lauren Tan
13
+
14
+ ## house-rules and MIT permission notice
15
+
16
+ MIT License
17
+
18
+ Copyright (c) 2026 Aaron Queen
19
+
20
+ Permission is hereby granted, free of charge, to any person obtaining a copy
21
+ of this software and associated documentation files (the "Software"), to deal
22
+ in the Software without restriction, including without limitation the rights
23
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24
+ copies of the Software, and to permit persons to whom the Software is
25
+ furnished to do so, subject to the following conditions:
26
+
27
+ The above copyright notice and this permission notice shall be included in all
28
+ copies or substantial portions of the Software.
29
+
30
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36
+ SOFTWARE.
@@ -0,0 +1,279 @@
1
+ ---
2
+ name: hr-benchmarking
3
+ description: Benchmark equivalent work with repeated timing, CPU and memory measurements under stated inputs and controls, and check whether saved results support a performance claim. Use when asked to benchmark, to measure which option is faster or uses less memory, or to time agent or model runs. Not for public model leaderboard research.
4
+ ---
5
+
6
+ # Benchmarking
7
+
8
+ Follow the repository and host's commands, resource limits, authorization and
9
+ landing rules. Reuse an existing workload and runner before building a harness.
10
+ Read [the tool reference](references/tools.md) when selecting a benchmark,
11
+ profiler or correctness check, or interpreting its measurements.
12
+
13
+ ## Define the comparison
14
+
15
+ State the question, baseline, candidate, representative input and timed region.
16
+ Exercise ordinary supported inputs and cases that disable an optimization.
17
+ State any restrictions behind a performance claim.
18
+
19
+ For a requested candidate set, record its inventory and distinguish
20
+ configurations or capacity modes. Keep untested, invalid and unsupported
21
+ candidates visible with reasons. A subset comparison establishes results only
22
+ for its tested scope, not a winner across the full inventory.
23
+
24
+ Test the newest stable release of each candidate. When the version installed
25
+ or deployed differs, say so in the results, and ask which to test if the
26
+ request does not settle it. When told to use an older version, use it and
27
+ offer the newest as an alternative.
28
+
29
+ Before running, list the selected engines, workloads, metrics, controls and
30
+ repetitions. Count the planned runs explicitly, including controls and stages;
31
+ state which decision each retained dimension helps make. Choose combinations
32
+ for that decision rather than automatically running every combination. Use a
33
+ broader matrix when its required coverage is stated. State the benchmark's
34
+ expected wall-clock time, waits included, before the first run.
35
+ Name the measurement unit: request, operation, batch or whole command. State
36
+ whether setup, startup, compilation, input loading, retries and cleanup count.
37
+
38
+ Record exact runtime, compiler, dependency and runner versions, build flags,
39
+ input identity and source revisions. Freeze copied quality and control artifacts;
40
+ record their hashes and the executed artifact's identity. Agreement across
41
+ runtimes alone does not verify the intended artifact. Keep these fixed across
42
+ repeated arms; reject mixed versions when resuming a checkpoint.
43
+
44
+ Compare runtime knobs within the same build. Use equivalent outputs, release
45
+ settings and comparable tuning. An untuned arm compares configurations rather
46
+ than implementations.
47
+
48
+ Keep warm and cold conditions explicit. Reset state or use fresh processes
49
+ where the question requires independence. Record warmup and cache conditions.
50
+ A reused service needs equivalent state across arms, not an arbitrary restart.
51
+
52
+ ## Confirm the work
53
+
54
+ Validate outputs, consumed results and error counts outside the timed region
55
+ where practical. Confirm requests arrived and asynchronous work was awaited.
56
+ Include failures, timeouts and unresolved attempts in both arms' denominators.
57
+ A faster wrong result or skipped operation is not a performance improvement.
58
+
59
+ Identify the limiting resource from CPU versus wall time, resource counters or
60
+ a separate profile. Check that throughput is possible given the machine and
61
+ input. When the generator limits the result, report that limit.
62
+
63
+ Before changing a component to remove a suspected cost, attribute time to that
64
+ component in the real workload with a profile or a counter. For fast feedback,
65
+ benchmark each changed piece through its actual production entry point with
66
+ representative fixed inputs and equivalent consumed outputs. Do not benchmark a
67
+ copied implementation or stub out work material to the comparison.
68
+
69
+ Compare each piece before and after against its immediate predecessor. Before
70
+ running, declare integration milestones when changed pieces enter the consuming
71
+ workload. Keep that workload before any piece changes as the original baseline.
72
+ At those milestones, compare the integrated workload with both its immediate
73
+ predecessor and the original baseline to track cumulative effects. Plan applicable
74
+ caller and integration checks for copying, serialization, startup and orchestration
75
+ costs that isolation excludes. Run those checks at the milestones and report
76
+ results or specific coverage limits. Re-time the change in the workload that uses
77
+ it at those milestones; a full-application run is not required after every piece.
78
+ An isolated gain does not establish an end-to-end gain. A setting that ran 7.6
79
+ times faster in isolation changed a 33 s indexing run by 0.1 s.
80
+
81
+ Select metrics for the question and limiting resource: wall time or latency,
82
+ memory, disk I/O, CPU, throughput, errors and output size as relevant. State each
83
+ metric's unit, process scope and interval; distinguish peak process memory from
84
+ retained memory, logical bytes from physical storage I/O, and warm from cold cache
85
+ state. Cache hits and delayed writeback can hide storage costs; record unavailable
86
+ counters and attribution limits rather than inferring physical I/O from logical
87
+ bytes. Do not require irrelevant additional counters; retain the CPU and memory
88
+ observations required below.
89
+
90
+ ## Measure without changing the experiment
91
+
92
+ Keep measured files, toolchains and services unchanged, and keep other work on
93
+ the machine from competing with the run.
94
+
95
+ Prefer removing competing work to raising priority. Record effective CPU and
96
+ I/O scheduling policies and memory protections; keep them equal across arms.
97
+ Use normal scheduling and all available CPUs for ordinary measurements. Omit
98
+ automatic `nice` and `taskset` wrappers; verify inherited priority and affinity
99
+ rather than assuming their omission resets either. Use restricted affinity or
100
+ changed priority only for representative deployment settings, an explicit resource
101
+ agreement or a stated sensitivity question. Record the reason and effective values.
102
+ Preserve frozen protocols and report constrained results within their tested scope.
103
+ Read [scheduling controls](references/tools.md#scheduling-controls) before
104
+ choosing them.
105
+
106
+ Apply worker limits to requested processing concurrency. Report sampled OS-thread
107
+ counts separately; runtime background threads are not processing workers. A
108
+ thread count alone does not establish CPU contention; keep it diagnostic unless
109
+ the experiment separately justifies using it to reject a run.
110
+
111
+ Before collecting results, set the criteria for rejecting a run: competing
112
+ load, swapping and memory-limit or OOM events, each with its metric and
113
+ threshold. Check the machine against them before each arm and watch them
114
+ throughout the measured interval. A run that fails them, or whose inputs change, is rejected even when the benchmark caused the
115
+ failure. A rejection invalidates that measurement; it does not by itself show
116
+ an implementation defect. Keep rejected runs outside the accepted sample and
117
+ report them; a later passing run neither erases a rejection nor loosens the
118
+ criteria.
119
+
120
+ Attribute CPU, load and resident memory to the recorded benchmark process tree
121
+ or resource scope before calling them competing work. Expected benchmark
122
+ utilization is not contention, and total host CPU and load average include it.
123
+ Keep an activity counter diagnostic until separate evidence shows its cutoff
124
+ matters. Collect boundary counters adjacent to the measured work, with
125
+ unrelated probes outside that interval, and record sample times. A counter
126
+ interval extending past completion cannot by itself establish overlap; keep
127
+ post-run observations diagnostic and let the machine settle before the next arm.
128
+
129
+ Before claiming negligible observer impact or a small decisive gain, test
130
+ sensitivity to observation separately with balanced controls and a preset
131
+ precision criterion. Retain inconclusive controls; do not subtract observer CPU
132
+ from workload wall time. For remote agent or model evaluations, record the
133
+ timing regime and concurrent local work.
134
+
135
+ Screen correctness and quality first, then use one run per selected arm to
136
+ explore timing and resource behavior. Preserve screened-out results and their
137
+ reasons. Label screening exploratory; one run does not support a performance
138
+ claim. A correctness-only check can use one candidate run; report its coverage.
139
+
140
+ Before exploratory runs, define the decision-relevant signal for selecting
141
+ comparisons for confirmation. Choose comparisons that meet that signal, plus
142
+ decision-critical comparisons, for repeated confirmation; keep necessary controls.
143
+ Set the confirmation plan before its runs and update the explicit run count
144
+ when the scope changes.
145
+
146
+ The default stopping rule for a performance claim is 3 runs per arm. Add 2 more
147
+ per arm only when the arms' ranges overlap or the effect is near the noise,
148
+ meaning the gap is within the variation criterion set below. 5 per arm is the
149
+ cap. If 5 runs per arm leave the comparison unresolved, report it as
150
+ inconclusive rather than adding runs. Use another count only when the user asks
151
+ for it or a run is too long to repeat 3 times, and declare it before the first
152
+ run, with the reason. Alternate the arms in every run so drift reaches each arm.
153
+
154
+ For a performance claim, assess run-to-run variation from those alternating runs.
155
+ Treat variation as already known only when earlier repeated runs of the
156
+ same variant, build and input used the same workload, host, run conditions and
157
+ variation statistic, and met the repetition count or stopping rule declared for
158
+ this claim. Otherwise include an A/A arm,
159
+ which runs the same variant twice in the same alternation. Its spread is that
160
+ comparison's own noise floor, and it can supply the preset variation statistic.
161
+ Before the first run used in that claim, set a reproducible variation criterion
162
+ (statistic and threshold), and the stopping rule if it differs from the default.
163
+
164
+ For short or tail metrics, such as the longest stall in a run, give the
165
+ threshold an absolute floor or use a percentile or count metric; a percentage
166
+ of a single small maximum can fail on the workload's own variation.
167
+ Retain every result. Keep pilots that informed the plan separate from the
168
+ claim's sample. Capture raw results, exit status, elapsed time, CPU and memory
169
+ observations. Report monitoring overhead separately from the
170
+ measured workload; batch compatible probes when they dominate elapsed time.
171
+ Report the selected repetition count or stopping rule, variation statistic and
172
+ threshold, sample count, median and range. Always give the run count and the
173
+ range with any central value, never a bare average. Apply the preset
174
+ criterion and report a gap within run-to-run variation as no clear change. Profile
175
+ separately from the runs used to claim a speed difference.
176
+
177
+ When using saved evidence for a performance claim, bind archived inputs, source,
178
+ cohort and results to their recorded identities and artifact hashes. Validate
179
+ historical reports against that frozen archive; later changes in the live
180
+ checkout alone do not invalidate historical evidence. Verify run identities and
181
+ stages against the declared plan.
182
+
183
+ Recompute qualification from recorded raw counters and preset limits; an accepted
184
+ summary or changed label is insufficient. Reject missing, duplicate or
185
+ misclassified required observations. When an evidence reader exists, put these
186
+ checks and focused corruption regressions there. After a rebase or merge
187
+ touches the reader or a check it imports, run the integrated reader over the
188
+ saved archive before landing, and compare its accepted and excluded records
189
+ with the frozen reader's. A shared check changed on the base branch can reject
190
+ records that the frozen reader accepted.
191
+
192
+ Record memory by what it measures. Whole-process peak RSS includes startup,
193
+ inputs and dependencies. Heap snapshots describe retained objects; allocation
194
+ profiles describe allocation activity. Forced-GC probes are separate from
195
+ ordinary latency measurements. Match retention semantics and payloads when
196
+ comparing caches; equal requested capacities need not mean equal memory use.
197
+ For cache-retention probes, keep the cache owner reachable through the final
198
+ observation; otherwise collection of the owner can be mistaken for release by
199
+ the cache operation.
200
+
201
+ For WeakRef-based retention probes, use bounded allocation batches and calibrated
202
+ collection boundaries after creating or dereferencing targets. Avoid observer
203
+ arrays or locals that keep measured values strongly reachable; preserve the
204
+ intended owner lifetime. Report live payload, cache occupancy and process RSS
205
+ separately. Keep this collection protocol outside ordinary latency runs; yielding
206
+ or forced collection alone does not guarantee that a target is reclaimed.
207
+
208
+ Batch latency percentiles describe batches, not individual requests.
209
+
210
+ ## Report and decide
211
+
212
+ Keep the full workload, versions, conditions, repetitions, output identity,
213
+ errors and measurement units in the measurement record. Include excluded costs,
214
+ coverage limits, collector overhead, scheduling, resource caps, pre-run
215
+ machine checks and rejected attempts there.
216
+
217
+ Pull requests and other change summaries show the workload, baseline and
218
+ candidate, measured results, relevant checks and limits that affect the claim.
219
+ Omit operational measurement details unless the reader needs them to interpret
220
+ the result or asks for them. A claimed difference with unknown limits, unequal
221
+ work or missing repetitions is unverified or inconclusive.
222
+
223
+ Show numeric before/after results in a table with a benefit column containing
224
+ percent change or a times improvement. Use the metric's direction and label
225
+ worsening, unchanged or inconclusive results. With a zero or missing baseline,
226
+ show an absolute change or state that the benefit cannot be calculated.
227
+
228
+ There is no minimum gain size. A favorable difference counts as a gain when it
229
+ lies outside the variation criterion declared before the first run (the comparison's
230
+ own run-to-run spread, from its A/A arm or already-known variation, as a
231
+ percentage of the baseline) and the outputs are identical. Report a gap inside
232
+ that criterion as no clear change, and name the statistic and threshold beside
233
+ it. An unfavorable difference outside it is a regression; label it worsening.
234
+ Report memory and CPU costs beside the gain. If the variation criterion cannot support a percentage, keep its result
235
+ separate and label unsupported differences inconclusive. Changing presentation
236
+ does not change frozen acceptance or rejection gates.
237
+
238
+ Show a comparison of three or more variants or conditions as a chart beside the
239
+ before/after table, unless every row is no clear change. Choose the chart for the
240
+ question:
241
+
242
+ | Question | Chart |
243
+ | -------------------------------- | ------------------------------------------ |
244
+ | Repeated runs of each variant | Dot plot of every run, mean marked |
245
+ | Conditions crossed with variants | Grouped bars, baseline as a reference line |
246
+ | Ranking of options | Sorted horizontal bars |
247
+ | Resource cost (CPU, memory) | Bars per variant, one panel per resource |
248
+ | Change with load or time | Line chart |
249
+
250
+ Put units and run counts on the axes, start bars at zero, mark a gap inside the
251
+ variation criterion as no clear change, and give the chart an explicit background colour so
252
+ it reads the same on a light or a dark page.
253
+ In a pull request, the headline chart and when it may be skipped come from
254
+ `hr-writing-pr`; this table applies to any other chart.
255
+
256
+ For agent, model, rule or skill comparisons, distinguish development cases
257
+ from held-out cases and report runs per case. Check each case for a ceiling: a
258
+ case every arm already passes cannot show a pass-rate improvement. Report it
259
+ apart from the cases that could, and report any metric the case does not
260
+ saturate (time, cost, graded quality) on its own. Include a one-line instruction
261
+ control when claiming an improvement from a rule or skill. Keep helper,
262
+ setup and retry costs visible. Before collecting results, define a per-case
263
+ contribution threshold. If a case exceeds it, report results both with and
264
+ without that case.
265
+
266
+ For bug-review evaluations, freeze the supported input contract and label
267
+ procedure before calls. A passing reference suite does not certify a clean
268
+ control. Adjudicate additional findings against that contract. A confirmed extra
269
+ defect makes the affected specificity estimate unavailable; retain earlier
270
+ receipts and introduce a new control version. Leave disputed domains unresolved.
271
+
272
+ Report provider completion, output-format compliance and independently checked
273
+ artifact acceptance separately. Distinguish observed call time from verification
274
+ and rework time. Keep returned usage units separate from attributable account
275
+ charges; unknown attribution remains unknown.
276
+
277
+ Record every experiment, rejected ones included, with the observed result and
278
+ what was decided. End with adopt, reject or inconclusive, and the evidence for that
279
+ decision. Any implementation or publication still follows the user's scope.
@@ -0,0 +1,2 @@
1
+ interface:
2
+ display_name: "HR: Benchmarking"
@@ -0,0 +1,130 @@
1
+ # JavaScript and TypeScript measurement
2
+
3
+ Use built-in runtime profilers and oha from [the tool reference](tools.md).
4
+ TypeScript applications execute through a runtime; compiler timing and
5
+ application timing answer different questions.
6
+
7
+ ## TypeScript measurement
8
+
9
+ Use [compiler diagnostics](https://www.typescriptlang.org/tsconfig/extendedDiagnostics.html)
10
+ for compiler phases and repeated whole-command timing for builds. For application
11
+ performance, record the executed artifact, build target, module format and source
12
+ maps. Use the same compiled JS artifact for an engine-only comparison; report
13
+ startup or transformation separately when it is part of the question.
14
+
15
+ [Node type stripping](https://nodejs.org/api/typescript.html) performs no type
16
+ checking and ignores `tsconfig.json`. A successful direct `.ts` execution does
17
+ not establish TypeScript correctness.
18
+
19
+ ## Running under Bun versus Node
20
+
21
+ Confirm the runtime before comparing: print `process.execPath` or
22
+ `process.versions.bun` from inside the code under test, in worker threads too.
23
+ Verified on Bun 1.4.x:
24
+
25
+ - `bun x vitest` is not Bun. `bun x` honors the tool's `#!/usr/bin/env node`
26
+ shebang and runs the whole suite under Node. Use `bun --bun x vitest run`.
27
+ - `node` can resolve to Bun. On Bun 1.4.3, a package script that calls `node` printed Bun's
28
+ version under `bun --bun run` and Node's under plain `bun run`; a `Bun.spawnSync(['node', …])`
29
+ reached real Node in both modes. The shim depends on Bun's `run.bun` setting, which defaults
30
+ on only when `node` is absent from `PATH`. Check `process.versions.bun` in the spawned process,
31
+ and filter `PATH` entries matching `/bun/i` when you need real Node.
32
+ - With no `node_modules` up the tree, `require.resolve` falls back to Bun's global
33
+ install cache ([oven-sh/bun#42893](https://github.com/oven-sh/bun/issues/42893)).
34
+ Pass `--no-install` for a hermetic "not installed" result.
35
+ - File-path and `{ eval: true }` workers both run under Bun, and `node:sqlite` and
36
+ NAPI `.node` addons load.
37
+ - Many busy, allocating workers wait on each other's parallel GC marking
38
+ ([oven-sh/bun#44186](https://github.com/oven-sh/bun/issues/44186)); with 8
39
+ workers `BUN_JSC_numberOfGCMarkers=1` roughly halved wall time. Attribute with a
40
+ profiler before concluding anything about worker scaling.
41
+ - Node 26.11 renamed its synchronous SQLite classes to `Database` and `Statement`
42
+ (`DatabaseSync` and `StatementSync` stay as aliases) and caches common property
43
+ keys in its SQLite bindings. Record the exact Node version beside SQLite
44
+ results; an older baseline does not establish the gap on the new runtime.
45
+
46
+ ## Choosing what to hunt
47
+
48
+ Start with something a user waits for. Use a representative workload and data size, then count the work before timing individual functions.
49
+
50
+ - Count messages and bytes per action, SQL statements, subprocesses, React commits, queue depth and oldest-item age. Measure idle CPU, event-loop delay and utilization. Use a CPU profile to attribute expensive work; delay alone does not identify its cause.
51
+ - Check repeated work first: whole-state rebuilds after small updates, serialization per subscriber, repeated parsing or validation, N+1 queries and per-row transactions. Check for backpressure when producers outrun consumers.
52
+ - Vary one input size while holding the rest fixed. Look for quadratic growth, large linear costs, and fixed costs paid too often. A high count alone does not establish a bottleneck.
53
+ - Check work that survives its owner: listeners, timers, caches, pending requests and reconnect loops. Measure repeated open/close cycles and hidden, idle and disconnected states separately.
54
+ - Profile startup imports, rendering and layout, compression, logging and tracing when they appear in the user-visible path. Investigate engine-specific tuning only when a profile identifies the relevant hot loop.
55
+
56
+ Record null results and their tested conditions. Stop a candidate when its measured benefit is within the declared variation criterion, or when it cannot materially improve the chosen user-visible outcome. Do not use a universal percentage cutoff.
57
+
58
+ ### Deciding whether to move synchronous work
59
+
60
+ Prioritize hot paths, then inspect less frequent paths for long individual stalls. A rare operation can still delay unrelated requests.
61
+
62
+ Measure the longest blocked interval and the average blocked milliseconds per call multiplied by calls per second. The product is milliseconds blocked per second; divide by 1,000 to estimate the duty-cycle fraction. This average does not describe burst latency. Compare against the application's actual response and frame budgets. A 60 Hz frame is about 16.7 ms; higher refresh rates leave less time.
63
+
64
+ Reduce unnecessary work first. Consider reuse, bounded caching, batching and yielding between chunks when their correctness requirements fit. A promise or `async` wrapper does not make CPU work leave the event loop.
65
+
66
+ Use the runtime's asynchronous APIs for supported I/O. They add scheduling and completion overhead and can contend for a shared thread pool. For CPU work, compare chunked yielding with a reused [worker or worker pool](https://nodejs.org/api/worker_threads.html). Include worker startup, message and clone or transfer costs, queueing, memory, cancellation and shutdown. Do not create a new worker for every small call by default.
67
+
68
+ Compare equal completed work under representative concurrency. Report wall time, CPU, memory and unrelated-request latency beside the longest stall. Offloading may improve responsiveness while costing more total CPU; state that tradeoff. A saturated worker queue can erase the improvement. There is no universal payload size or duration at which async or a worker wins.
69
+
70
+ ### Runtime checks
71
+
72
+ - **Cloudflare Workers:** [deployed timers](https://developers.cloudflare.com/workers/runtime-apis/performance/) such as `Date.now()` and `performance.now()` advance after I/O, so they cannot time an uninterrupted CPU section. Local Wrangler uses workerd and permits advancing timers; use it for attribution and confirm deployed behavior with platform CPU metrics. Check current platform limits. A Durable Object runs JavaScript on one thread, but requests can interleave across awaits; distinguish synchronous blocking from storage gates and explicit concurrency controls.
73
+ - **Bun:** JavaScriptCore and V8 can have different hot paths. Verify the runtime and use its profiler; remeasure relevant changes on each supported runtime.
74
+ - **Electron:** attribute renderer and main-process work separately. Synchronous IPC blocks the caller; expensive main-thread work can delay all windows.
75
+ - **React Native and web:** use production builds. Count commits per actual streamed update or action, not per estimated token. Separate JavaScript work from layout, paint and native UI work. Record visibility and observer overhead.
76
+
77
+ ## Event-loop and server-code measurement
78
+
79
+ Each event-loop thread of a Node or Bun server runs request handling, timers and
80
+ synchronous database calls. A slow call matters when it holds that thread, so
81
+ measure the hold, not only the duration. (M) marks a result measured on one
82
+ workload and host, not a benchmark.
83
+
84
+ - **Measure the longest stall, not wall time.** Run a 1 ms `setInterval` that
85
+ records the largest gap between ticks while the call runs, after letting the
86
+ loop settle first. Report it beside wall time. They differ: a snapshot read took
87
+ 79 ms of wall time and held the loop for 12.6 ms because the runtime yielded
88
+ between steps (M). `perf_hooks.monitorEventLoopDelay` has a resolution of at
89
+ least 1 ms, so use it for coarse trends, not for claims of a few ms. State the
90
+ probe interval beside any figure near it.
91
+ - **Time the real function, not a copy.** A copied string-appending coalescer
92
+ looked quadratic; the real one showed equal CPU and equal longest stall within
93
+ noise, because V8 joins repeated concatenation lazily (M). A replica that leaves
94
+ out framework overhead is only a lower bound. Run server code inside the
95
+ project's own test runner with its in-memory test layer, write results to a file
96
+ because runners often swallow `console.log`, and delete the temporary test
97
+ afterwards.
98
+ - **Count volume when volume is the cost.** For code that emits events or
99
+ messages, feed a fixed synthetic input through the real component and count the
100
+ events and serialized bytes at several sizes. Counts are deterministic, so they
101
+ need no repetitions; stall and wall time still do. One adapter emitted three
102
+ events per streamed chunk, two of them carrying the whole reply so far: 15,003
103
+ events (three per chunk plus one closing update of each) and 263.6 MB for 5,000
104
+ chunks of 10 characters (about 125 MB for each of
105
+ the two full-text copies), growing about 3.3 to 3.6 times per doubling, with a
106
+ longest stall under 6 ms (M). That is a volume problem, not
107
+ a stall.
108
+ - **Separate loop time from child-process time.** Work done by an asynchronously
109
+ spawned process uses CPU but does not hold the loop. Count such a spawn as loop
110
+ cost only for its spawning and parsing. `spawnSync`, `execSync` and `execFileSync` block the
111
+ loop for the child's whole lifetime, so count that time as a stall.
112
+ - **Prove that work left the loop with a test that cannot pass otherwise.** Hold
113
+ the main connection or thread busy (blocked on a latch) and
114
+ assert the moved work still completes. A speed measurement alone cannot show
115
+ where the work ran. Moving one read off the loop took the longest stall from a
116
+ median 165 ms to 2.5 ms over 12 runs per arm, with no clear change in wall time, measured with a 2 ms probe (M).
117
+ - **Measure retention with forced garbage collection.** Run N synthetic sessions
118
+ or turns, force a collection, and compare heap deltas with the suspect field
119
+ kept and dropped, keeping the owner reachable to the end. One researcher's run, not
120
+ repeated, kept only the two fields that were read and went from 61.45 MiB to
121
+ 2.10 MiB over 30 sessions of 10 turns of 200 KiB.
122
+ - **Time startup on the built artifact, interleaved.** Alternate arms on
123
+ one build, using the default run count in [the skill](../SKILL.md). An
124
+ environment variable can stand in for an API
125
+ call, but note what it changes (it also reaches child processes). A V8 compile
126
+ cache took a CLI's `--help` from a 554 ms median to 381 ms over 11 runs (M).
127
+ - **Treat another researcher's numbers as leads.** Of three top candidates from a
128
+ model's blind read-only pass, re-measuring left one refuted, one mostly covered
129
+ by existing work and one real but small. Re-run a lead with the real function
130
+ and the stall probe before acting on it.
@@ -0,0 +1,165 @@
1
+ # Benchmarking and investigation tools
2
+
3
+ These defaults come from tools used in our work. Prefer a suitable runner
4
+ already used by the project. Check the official version's documentation before
5
+ relying on flags or interpreting output.
6
+
7
+ ## Timing and resource measurement
8
+
9
+ | Task | Default and reason | Limits to record |
10
+ | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
11
+ | Whole CLI commands | [Hyperfine](https://github.com/sharkdp/hyperfine): repeated runs with wall time, CPU time and peak memory, warmup/preparation and JSON output. | Works across Linux, macOS and Windows. Declare warm/cold conditions. Since 2.0 commands run without a shell unless `-S` or `--shell` is given; 1.x needs `-N` for that. Peak memory and `--metrics` hardware counters are measured on Linux and macOS only; on Windows use another tool for memory. Check `schema_version` before reading exported JSON; 2.0 changed its layout. |
12
+ | JavaScript operations | [Tinybench](https://github.com/tinylibs/tinybench), directly or through the project's benchmark runner: warmup and task latency/throughput statistics. | The unit is a task invocation. For 1,000-operation batches, batch p99 divided by 1,000 is the p99 of batch-average costs, not mean operation cost or individual-operation p99. |
13
+ | HTTP load, including JS/TS servers | [oha](https://github.com/hatoo/oha): a native load generator with concurrency/rate controls, latency distributions and JSON output. | Declare protocol, connections, rate, deadlines, keepalive and error handling. Check generator CPU/network limits. For fixed-rate load, `--latency-correction` corrects coordinated omission; it is ignored unless `-q` is set. |
14
+ | Command CPU and memory | [GNU time](https://www.gnu.org/software/time/manual/time.html), commonly `/usr/bin/time -v`: wall time, CPU and maximum RSS. | GNU options differ from shell `time` and BSD/macOS tools. RSS is a lifetime high-water mark for the observed process; it does not isolate retained cache memory. |
15
+ | Host or process contention | Linux [mpstat/pidstat](https://github.com/sysstat/sysstat): processor utilization and process CPU, memory and I/O observations. | Sampling can miss short bursts; some counters need kernel support. These explain interference, not application latency. |
16
+
17
+ On Linux with compressed swap enabled, observe compressed-swap activity as
18
+ well as disk swap I/O. Unchanged `pswpin`/`pswpout` counters do not establish
19
+ absence of swapping. For [zswap](https://www.kernel.org/doc/html/latest/admin-guide/mm/zswap.html),
20
+ record available `zswpin`/`zswpout`/`zswpwb` deltas from the benchmark cgroup's
21
+ `memory.stat` over the measured interval. Label host-wide deltas as system-wide;
22
+ they cannot attribute activity to the workload.
23
+
24
+ Use [cgroup swap and zswap accounting](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html)
25
+ (`memory.swap.current`, `memory.zswap.current`) to distinguish the workload
26
+ from other jobs. These occupancy values do not measure activity by themselves.
27
+ Record missing counters and preserve the run plan's declared pressure criteria.
28
+
29
+ ## Process attribution
30
+
31
+ Prefer `pidstat -u -r -d -p ALL 1 20` for the standard Linux process view.
32
+ For receipts that retain PID birth identity, use the bundled collector:
33
+
34
+ ```sh
35
+ python3 scripts/process-attribution.py --seconds 20 --output /disk/path/receipt.json
36
+ ```
37
+
38
+ Run from the skill directory. Linux receipts contain raw one-second snapshots
39
+ and CPU deltas ranked by busy cores, with process name, parent PID, birth ticks,
40
+ RSS pages and unmatched boundary counts. They omit command arguments.
41
+
42
+ Each row also reports `reapedChildCores`: CPU of children the process reaped
43
+ during the interval, attributed to that parent. It shows which process ran
44
+ commands too short-lived to appear in a snapshot, not the commands themselves,
45
+ and can include CPU the children used before the interval started.
46
+
47
+ Each interval reports `cpuBusyCores` per logical CPU. Busy CPU excludes idle,
48
+ iowait and steal time. A CPU brought online or offline during the interval
49
+ reports `null`.
50
+ The collector uses its own `/proc/self/status` `VmHWM` for peak RSS;
51
+ `ru_maxrss` can retain a launcher's inherited high-water mark.
52
+ It records observer CPU and scan duration. Report those costs beside the results; no
53
+ negligible-impact claim follows from successful collection.
54
+
55
+ On Windows, `scripts/process-attribution.ps1` accepts mandatory `OutputPath`
56
+ and `StopPath` arguments. It saves process PID, start time, name and cumulative
57
+ CPU, plus host activity and observer CPU/working set. Match PID and start time
58
+ before computing deltas. It stops when the stop file exists or after 120 samples;
59
+ choose a fresh stop path. Use the host's approved PowerShell invocation without
60
+ changing execution policy.
61
+
62
+ Neither collector stops jobs or changes any setting. Boundary samples
63
+ miss processes that start and exit between them; unreadable processes are counted
64
+ as missing. CPU contributors explain observed activity, not whether it changed
65
+ application latency.
66
+
67
+ ## Scheduling controls
68
+
69
+ These Linux controls change resource allocation under competition; they do not
70
+ establish isolation. Check support for the actual kernel, controller and I/O
71
+ path. Record effective values and unavailable controls for every arm; requesting
72
+ a setting does not prove it took effect.
73
+
74
+ | Control | Effect and limit |
75
+ | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
76
+ | [Nice level](https://man7.org/linux/man-pages/man2/nice.2.html) | Lower numeric values raise fair CPU scheduling priority. Permissions and autogroup policy affect the result. This does not reserve a core. |
77
+ | CPU affinity (`taskset`) | Restricts available CPUs and can affect worker counts and parallelism. It does not reserve exclusive cores. Use it for a declared CPU configuration, not automatic noise reduction. |
78
+ | [CPU and I/O cgroup weights](https://docs.kernel.org/admin-guide/cgroup-v2.html) | Adjust relative shares among active sibling groups. Parent limits and controller/device support still apply; a higher weight is not a capacity guarantee. |
79
+ | [Process I/O priority](https://man7.org/linux/man-pages/man2/ioprio_set.2.html) | Depends on the supporting I/O scheduler and path. Process-specific priority does not cover asynchronous writes. |
80
+ | [Memory protection](https://docs.kernel.org/admin-guide/cgroup-v2.html) | `memory.low` and `memory.min` protect against reclaim, not memory-bandwidth competition. Excessive hard protection can cause OOM. Memory caps remain limits, not reservations. |
81
+
82
+ In a virtual machine, guest affinity does not reserve host cores; host
83
+ activity, shared cache, memory bandwidth and power limits still apply.
84
+
85
+ Avoid realtime [CPU](https://man7.org/linux/man-pages/man7/sched.7.html) or
86
+ [I/O](https://man7.org/linux/man-pages/man1/ionice.1.html) classes for generic
87
+ benchmark noise reduction; they can starve dependencies or monitoring.
88
+ Preserve the host's scheduling policy unless it authorizes a different regime.
89
+
90
+ ## Profiling and debugging
91
+
92
+ Use a separate diagnostic run; instrumentation changes the work it observes.
93
+
94
+ | Question | Tool and reason | Limits to record |
95
+ | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
96
+ | Where does JavaScript CPU time go? | Runtime CPU profiler: [Node](https://nodejs.org/api/cli.html#--cpu-prof) or [Bun](https://bun.com/docs/project/benchmarking#cpu-profiling). | Match runtime/version and profile settings. Samples locate hotspots; verify improvements with unprofiled runs. |
97
+ | Which JS objects are allocated or retained? | Runtime allocation profiles and heap snapshots: [Node](https://nodejs.org/api/cli.html#--heap-prof), [Bun](https://bun.com/docs/project/benchmarking#heap-profiling). | Matching flags do not guarantee matching metrics; see the distinction below. |
98
+ | Where does native/kernel CPU work go? | Linux [perf stat](https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/perf-stat.txt) and [perf record](https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/perf-record.txt): counters, samples and call graphs. | Permissions, hardware/kernel support, symbols and stack unwinding affect evidence. Frame-pointer unwinding needs compatible binaries. |
99
+ | Which system calls fail or wait? | Linux [strace](https://github.com/strace/strace/blob/master/doc/strace.1.in): syscall results, errors and ordering. | Interception changes execution; summaries are not ordinary throughput. Traces may contain sensitive paths or payloads. |
100
+ | Which native allocations churn? | Linux [heaptrack](https://github.com/KDE/heaptrack): allocation counts, temporary allocations and allocation stacks. | Symbols improve attribution. Pool allocators need annotations; native allocation traces do not identify individual GC-managed JS objects. |
101
+
102
+ ### Native and JavaScript CPU profiles
103
+
104
+ Keep native symbols in the diagnostic build. For a Rust release build, use
105
+ `CARGO_PROFILE_RELEASE_DEBUG=line-tables-only CARGO_PROFILE_RELEASE_STRIP=none`.
106
+ For Node JIT frames under `perf`, add `--perf-basic-prof`. A runtime CPU profile
107
+ may attribute a native addon's work to its JavaScript caller; use native samples
108
+ to see inside that call. Node `--cpu-prof` writes separate files for worker threads;
109
+ retain them alongside the main-thread profile.
110
+
111
+ If `perf report` stalls while expanding a large binary's inline frames, try
112
+ `perf report --stdio --no-inline`. This omits inline-call expansion, so record
113
+ that limit when attributing samples.
114
+
115
+ ### Viewing profiles
116
+
117
+ [speedscope](https://github.com/jlfwong/speedscope) opens profiles locally as
118
+ interactive flame graphs, including Node CPU profiles and Linux `perf` captures.
119
+ It has been used to inspect JavaScript and native stacks across worker threads.
120
+ To import a `perf` capture, write `perf script > profile.perf` without a custom
121
+ `-F` field list; a partially recognized format can display one stack without an
122
+ import error. Check that the expected threads and stacks appear.
123
+
124
+ The npm CLI opens the default browser with `speedscope <profile>`. When using a
125
+ controlled browser, serve its packaged `dist/release/` directory and the profile
126
+ over loopback HTTP, then open `index.html#profileURL=<URL-encoded-profile-url>`.
127
+ Use `encodeURIComponent(profileUrl)` for the value so query parameters remain
128
+ part of the profile URL. Choose a free port and keep private captures on the
129
+ local host. Follow the host's browser rules.
130
+
131
+ ### Allocation and waiting-time limits
132
+
133
+ `heaptrack` unwinds a stack on each native allocation. Start with a small input:
134
+ millions of allocations can make instrumentation dominate runtime. Treat that
135
+ runtime as diagnostic overhead, and verify improvements with uninstrumented runs.
136
+
137
+ On-CPU profiles omit time spent off CPU. Use a separate
138
+ [bpftrace](https://bpftrace.org/docs) scheduler trace when a thread's wall time
139
+ greatly exceeds its CPU time. Track the target and its descendants, and aggregate
140
+ time between switch-out and switch-in. Off-CPU time includes both blocked time
141
+ and time runnable threads wait for a CPU; sums across threads can exceed wall time.
142
+ Kernel tracepoints, PID namespaces and privileges affect attribution, so verify
143
+ the target's identity and that probes attached before starting it.
144
+
145
+ Node `--heap-prof` samples allocation activity. Bun's documentation describes
146
+ a full V8-format heap snapshot at exit, not the same sampled allocation history;
147
+ its accepted interval flag does not add allocation sampling. Record which kind
148
+ of artifact was captured and verify semantics for the version used.
149
+
150
+ For a concrete crash, hang or event-tracing question, use the available
151
+ [debugger](https://www.sourceware.org/gdb/documentation/) or
152
+ [system tracing tool](https://bpftrace.org/docs). They are optional diagnostic
153
+ tools, not benchmark prerequisites; platform and permissions affect availability.
154
+
155
+ For TypeScript compiler versus application timing, and for Bun-versus-Node pitfalls, read [the language reference](javascript.md).
156
+
157
+ ## Correctness and audit evidence
158
+
159
+ Use the repository's lint, type checks, focused tests and relevant static or
160
+ security analysis. These establish intended behavior and detect defects; passing
161
+ them does not establish speed or memory use. State their coverage limits.
162
+
163
+ Add a tool after using it successfully on a real task. Record the question it
164
+ answered, why it helped, its platform and measurement limits, and the official
165
+ documentation. Keep untried candidates in research notes until then.