@bompus/house-rules 0.11.0 → 0.14.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 (112) hide show
  1. package/CODE_OF_CONDUCT.md +83 -0
  2. package/README.md +102 -63
  3. package/compose.mjs +8 -2
  4. package/composition.mjs +11 -3
  5. package/config-view.mjs +18 -3
  6. package/config.mjs +74 -13
  7. package/docs/assets/overview.png +0 -0
  8. package/docs/configuration.md +85 -9
  9. package/package.json +4 -2
  10. package/rules/core.md +118 -209
  11. package/rules/modifiers/backlog-outline.md +25 -0
  12. package/rules/modifiers/backlog-visual.md +16 -0
  13. package/rules/modifiers/coded-offers.md +47 -17
  14. package/rules/modifiers/cross-session-relay.md +23 -0
  15. package/rules/modifiers/low-quota-handoff.md +4 -3
  16. package/rules/modifiers/model-default-questions.md +33 -0
  17. package/rules/modifiers/multi-agent.md +6 -2
  18. package/rules/modifiers/no-attribution.md +7 -1
  19. package/rules/modifiers/periodic-updates.md +25 -0
  20. package/rules/modifiers/plan-files.md +35 -3
  21. package/rules/modifiers/release-batching.md +4 -2
  22. package/rules/modifiers/shared-host-load.md +13 -42
  23. package/rules/modifiers/squash-landing.md +1 -1
  24. package/rules/modifiers/upstream-contributions.md +45 -0
  25. package/rules/modifiers/web-image-formats.md +35 -0
  26. package/rules/references/backlog-view.md +154 -0
  27. package/rules/references/landing.md +14 -14
  28. package/rules/references/multi-agent.md +6 -2
  29. package/rules/references/release-batching.md +37 -4
  30. package/rules/references/squash-landing.md +10 -4
  31. package/rules/references/thread-visuals.md +45 -0
  32. package/setup.mjs +87 -17
  33. package/skills/hr-agent-guidance-audit/SKILL.md +10 -5
  34. package/skills/hr-agent-guidance-audit/references/prune-workflow.md +72 -0
  35. package/skills/hr-agent-guidance-audit/references/records-and-lessons.md +1 -1
  36. package/skills/hr-agent-guidance-audit/references/retirement-verdicts.md +49 -0
  37. package/skills/hr-agent-guidance-refresh/SKILL.md +25 -57
  38. package/skills/hr-agent-guidance-refresh/references/verification.md +1 -1
  39. package/skills/hr-audit-choices/SKILL.md +1 -1
  40. package/skills/hr-benchmarking/SKILL.md +122 -159
  41. package/skills/hr-benchmarking/references/javascript.md +113 -0
  42. package/skills/hr-benchmarking/references/tools.md +62 -57
  43. package/skills/hr-better-accessibility/SKILL.md +1 -1
  44. package/skills/hr-better-accessibility/screen-readers.md +1 -0
  45. package/skills/hr-code-review/SKILL.md +19 -3
  46. package/skills/hr-code-review/agents/openai.yaml +1 -1
  47. package/skills/hr-code-review/references/acp-client.md +43 -0
  48. package/skills/{hr-change-impact/SKILL.md → hr-code-review/references/impact.md} +2 -12
  49. package/skills/hr-code-review/references/panel-adjudication.md +58 -0
  50. package/skills/hr-code-review/references/panel-plan.md +61 -0
  51. package/skills/hr-code-review/references/panel-recommendations.json +105 -0
  52. package/skills/hr-code-review/references/panel-recommendations.md +46 -0
  53. package/skills/hr-code-review/references/panel-setup.md +54 -0
  54. package/skills/hr-code-review/references/reviewer-role.md +31 -0
  55. package/skills/hr-code-review/scripts/acp-panel-client.mjs +299 -0
  56. package/skills/hr-code-review/scripts/check-receipts.mjs +263 -0
  57. package/skills/hr-code-review/scripts/panel-plan.mjs +69 -0
  58. package/skills/hr-code-review/scripts/panel-preferences.mjs +220 -0
  59. package/skills/hr-design-exploration/SKILL.md +24 -1
  60. package/skills/hr-design-exploration/agents/openai.yaml +2 -2
  61. package/skills/hr-diagnosing-bugs/SKILL.md +2 -2
  62. package/skills/hr-diagnosing-bugs/references/reporting.md +29 -4
  63. package/skills/hr-diagnosing-bugs/scripts/check-pr-offer.mjs +47 -0
  64. package/skills/hr-explain-code/SKILL.md +1 -1
  65. package/skills/hr-extract-shared-steps/SKILL.md +1 -1
  66. package/skills/hr-forgotten-work-audit/SKILL.md +130 -0
  67. package/skills/hr-forgotten-work-audit/references/brief-template.md +56 -0
  68. package/skills/hr-forgotten-work-audit/references/result-format.md +46 -0
  69. package/skills/hr-handoff/LICENSE +21 -0
  70. package/skills/hr-handoff/NOTICE.md +29 -0
  71. package/skills/hr-handoff/SKILL.md +24 -1
  72. package/skills/hr-handoff/references/reconciliation.md +25 -6
  73. package/skills/hr-handoff/references/successor-thread.md +76 -0
  74. package/skills/hr-handoff/scripts/check-reconciliation.mjs +48 -6
  75. package/skills/hr-house-rules-setup/SKILL.md +22 -8
  76. package/skills/hr-lean-plan/SKILL.md +4 -0
  77. package/skills/hr-maintainability-review/SKILL.md +14 -4
  78. package/skills/hr-maintainability-review/agents/openai.yaml +1 -1
  79. package/skills/hr-manual-qa/SKILL.md +1 -1
  80. package/skills/hr-ordering-tests/SKILL.md +1 -1
  81. package/skills/hr-plain-prose/SKILL.md +7 -4
  82. package/skills/hr-pr-followup/SKILL.md +6 -3
  83. package/skills/hr-pr-followup/references/review-helpers.md +40 -7
  84. package/skills/hr-pr-followup/scripts/check-landing.py +204 -0
  85. package/skills/hr-pr-followup/scripts/check-pr-review.ts +19 -8
  86. package/skills/hr-pr-followup/scripts/merge-pr.sh +100 -0
  87. package/skills/hr-pr-followup/scripts/verify-landed.sh +184 -0
  88. package/skills/hr-read-reddit/SKILL.md +1 -1
  89. package/skills/hr-research-shared-links/SKILL.md +103 -0
  90. package/skills/hr-sqlite/SKILL.md +174 -0
  91. package/skills/hr-sqlite/agents/openai.yaml +2 -0
  92. package/skills/hr-sqlite/references/evidence.md +94 -0
  93. package/skills/hr-sqlite/references/tool-decisions.md +39 -0
  94. package/skills/hr-sqlite/scripts/inspect-sqlite.py +245 -0
  95. package/skills/hr-stock-ui-audit/SKILL.md +1 -1
  96. package/skills/hr-test-audit/LICENSE +21 -0
  97. package/skills/hr-test-audit/NOTICE.md +67 -0
  98. package/skills/hr-usage-report/SKILL.md +90 -0
  99. package/skills/hr-usage-report/agents/openai.yaml +2 -0
  100. package/skills/hr-usage-report/assets/example-report.json +125 -0
  101. package/skills/hr-usage-report/assets/report-template.html +377 -0
  102. package/skills/hr-usage-report/scripts/render-report.ts +86 -0
  103. package/skills/hr-usage-report/scripts/usage-by-model.ts +499 -0
  104. package/skills/hr-what-next/SKILL.md +100 -10
  105. package/skills/hr-what-next/references/reporting.md +13 -22
  106. package/skills/hr-what-next/scripts/check-open-work.mjs +711 -0
  107. package/skills/hr-writing-pr/SKILL.md +29 -14
  108. package/skills/hr-writing-pr/scripts/benefit-chart.py +200 -0
  109. package/docs/npm-release.md +0 -45
  110. package/rules/modifiers/swarmail.md +0 -12
  111. package/skills/hr-benchmarking/references/priority-findings-20261006.md +0 -115
  112. package/skills/hr-change-impact/agents/openai.yaml +0 -5
@@ -1,6 +1,6 @@
1
1
  ---
2
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. Public model leaderboard research is outside this measurement workflow.
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
4
  ---
5
5
 
6
6
  # Benchmarking
@@ -21,11 +21,17 @@ configurations or capacity modes. Keep untested, invalid and unsupported
21
21
  candidates visible with reasons. A subset comparison establishes results only
22
22
  for its tested scope, not a winner across the full inventory.
23
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
+
24
29
  Before running, list the selected engines, workloads, metrics, controls and
25
30
  repetitions. Count the planned runs explicitly, including controls and stages;
26
31
  state which decision each retained dimension helps make. Choose combinations
27
32
  for that decision rather than automatically running every combination. Use a
28
- broader matrix when its required coverage is stated.
33
+ broader matrix when its required coverage is stated. State the benchmark's
34
+ expected wall-clock time, waits included, before the first run.
29
35
  Name the measurement unit: request, operation, batch or whole command. State
30
36
  whether setup, startup, compilation, input loading, retries and cleanup count.
31
37
 
@@ -54,12 +60,37 @@ Identify the limiting resource from CPU versus wall time, resource counters or
54
60
  a separate profile. Check that throughput is possible given the machine and
55
61
  input. When the generator limits the result, report that limit.
56
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
+
57
90
  ## Measure without changing the experiment
58
91
 
59
- Coordinate resource use under the host's rules. During isolated local performance
60
- measurements, the measuring session only monitors. Other sessions may do light
61
- work within the run's resource limits. Keep measured files, toolchains and
62
- services unchanged.
92
+ Keep measured files, toolchains and services unchanged, and keep other work on
93
+ the machine from competing with the run.
63
94
 
64
95
  Prefer removing competing work to raising priority. Record effective CPU and
65
96
  I/O scheduling policies and memory protections; keep them equal across arms.
@@ -69,139 +100,37 @@ rather than assuming their omission resets either. Use restricted affinity or
69
100
  changed priority only for representative deployment settings, an explicit resource
70
101
  agreement or a stated sensitivity question. Record the reason and effective values.
71
102
  Preserve frozen protocols and report constrained results within their tested scope.
72
-
73
- Treat a priority or affinity change as a separate sensitivity pilot under the host's rules, with preset variation
74
- criteria and retained raw results. Verify that the controls apply and that
75
- dependencies and monitoring still progress before adopting them for the
76
- declared experiment. Priority changes never replace admission checks, resource
77
- caps or pressure rejection. Read [scheduling controls](references/tools.md#scheduling-controls)
78
- before choosing them. When brief bursts from other sessions keep failing host-wide
79
- admission on a shared host, read the [fenced-core arm](references/tools.md#fenced-core-arm)
80
- before proposing one; it needs the user's authorization. For questions about negative, zero or positive nice values,
81
- read the [recorded priority findings](references/priority-findings-20261006.md)
82
- before proposing another experiment.
83
-
84
- Classify the timed region against the host's budget for concurrent light work.
85
- A local phase is heavy when measured or expected CPU, memory or I/O exceeds
86
- that budget. Inspect the command, its hooks, wrappers and children before calling
87
- demand
88
- unknown. Inspection can qualify bounded ordinary work within that budget;
89
- missing resource samples alone does not require a trial. When inspection leaves
90
- potentially incompatible demand unresolved, contact the active reservation owner
91
- or host coordinator. If neither is identified, ask the operator. Launch that
92
- workload only after recording agreement on a bounded trial with CPU, memory and
93
- I/O limits, or an exclusive run window. Resolve input and authorization conflicts
94
- separately; resource admission does not override them.
103
+ Read [scheduling controls](references/tools.md#scheduling-controls) before
104
+ choosing them.
95
105
 
96
106
  Apply worker limits to requested processing concurrency. Report sampled OS-thread
97
107
  counts separately; runtime background threads are not processing workers. A
98
- thread count alone does not establish CPU contention. Use CPU, memory, I/O and
99
- elapsed-time controls for the admitted resource budget. Keep thread count
100
- diagnostic unless a host limit or experiment requirement separately justifies
101
- using it to stop or reject a run.
102
-
103
- When an existing admission binds thread count, obtain revised admission before
104
- relaxing that condition. Preserve the other controls, held inputs and original
105
- run verdicts. Record the revised observer and limits before execution.
106
-
107
- For an unknown competing job, record a preset time or query limit, then inspect
108
- its process identity, actual demand and access to measured inputs. Stop at that
109
- limit. A cap, service name or active state alone does not establish incompatible
110
- work. Keep unresolved overlap or observer gaps unqualified; input mutation remains
111
- incompatible even at low demand.
112
-
113
- A retained benchmark lock does not pause other sessions or reserve every phase
114
- of their tasks. Qualified non-heavy checks, edits and coordination proceed without
115
- acquiring that lock while staying within the concurrent-work budget and preserving
116
- measured inputs. Classify actual commands and children, including hooks; reuse
117
- qualification only for comparable inputs, runtimes and worker counts. When
118
- inspection leaves demand unresolved, identify the missing evidence and arrange
119
- the bounded qualification above. Defer only the incompatible phase, naming its
120
- resource or input conflict;
121
- do not use lock ownership alone to block qualified non-heavy work. Keep repository
122
- integration and installation write locks separate from benchmark admission.
123
-
124
- Reserve the host only for heavy local phases or deliberately isolated local
125
- performance measurements. Remote model
126
- inference, light CLI/API work and remote waits need no exclusive slot; a
127
- memory cap or elapsed-time record alone does not establish heavy work. For
128
- remote agent/model evaluations, record the timing regime and concurrent local
129
- work. Apply the local admission and pressure rules below when measuring local
130
- performance, rather than treating every model call as a CPU benchmark.
131
-
132
- Before collecting results, declare required observers, their measurement interval
133
- and coverage criteria. Require successful execution and recorded coverage that
134
- meets those criteria. Preserve observer exit status, errors and missing samples;
135
- reject evidence with unexplained observer failures or insufficient coverage.
136
- Require empty stderr only when the observer's declared contract requires it;
137
- documented harmless diagnostics alone do not invalidate observation.
138
-
139
- Declare observer CPU, resident-memory and I/O budgets separately from foreign-load
140
- and pressure gates. Include every collector and reader, with process birth
141
- identities and aligned intervals. Record CPU time, average core-equivalent use,
142
- workload-relative CPU, resident peaks, logical log bytes and attributable storage
143
- I/O. Separate setup from collection; disclose missing platform counters and
144
- shared provider or writeback costs. A log-byte count is not physical disk I/O.
145
- Retain over-budget runs with an over-budget status and exclude them from accepted
146
- performance evidence. Declare any stop rule and replacement limit before
147
- execution. When automation applies a stop rule, compute it with the same code as
148
- the acceptance analysis. Record budget failures separately from foreign-load and pressure
149
- failures.
150
-
151
- Choose budgets for the host, workload duration and decision precision; there is
152
- no universal workload-relative CPU percentage. A budget permits collection but
153
- does not prove unchanged latency. Before claiming negligible observer impact or
154
- a small decisive gain, test sensitivity to observation separately with balanced
155
- controls and a preset precision criterion. Retain inconclusive controls; do not
156
- subtract observer CPU from workload wall time. Assign and record each run's
157
- protocol version before execution. A changed observer budget creates a new
158
- protocol version. Keep historical rejection verdicts with their original version.
159
-
160
- Before each arm, inspect CPU outside the measuring scope, memory headroom and
161
- pressure, swap and competing CPU, memory or I/O jobs. Use the host's admission
162
- limits; when it has none, declare the metrics and pass/fail thresholds before
163
- collecting performance results. Start only when every admission condition passes.
164
- During measurements, attribute CPU, load and resident memory to the recorded
165
- benchmark process tree or resource scope before calling them competing work.
166
- Expected benchmark utilization is not contention; total host CPU and load
167
- average include it. Collect boundary counters adjacent to the measured work,
168
- with unrelated probes outside that interval. Record sample times and observer
169
- overhead. A counter interval extending past completion cannot by itself
170
- establish overlap. Keep post-run observations diagnostic and use a fresh
171
- settled interval before the next arm.
172
-
173
- Keep uncalibrated activity counters diagnostic. Before using an activity cutoff
174
- to reject measurements, establish its relevance through separate sensitivity
175
- evidence with comparison conditions and an interference criterion set before
176
- analysis. Retain raw observations and inconclusive outcomes. Preserve declared
177
- pressure and observer checks; distinguish a conservative limit from evidence
178
- that interference occurred.
179
-
180
- Reject a run when inputs change, competing work crosses a declared contention
181
- limit, or a declared pressure condition fails. Before collecting performance
182
- results, define pressure rejection using stall duration, swap activity and
183
- memory-limit/OOM events; name any additional signals and their thresholds.
184
- Set a stall-duration budget from the experiment's timing precision. Record
185
- smaller stalls without rejecting them. Stalls exceeding the budget, swapping
186
- or memory-limit/OOM events invalidate measurements even when the benchmark
187
- causes them. Resource rejection invalidates the measurement; it alone does not
188
- establish an implementation defect. Investigate uncertain overlap and repeat
189
- affected runs within authorized retry budgets before a decisive comparison.
190
- A light session's presence alone is not rejection evidence.
191
-
192
- Declare per-case retry budgets before attempts; a budget grants no retry
193
- authority. Retain rejected attempts outside accepted samples. A later qualifying
194
- attempt neither erases a rejection nor relaxes its gates. After rejecting a case,
195
- continue other independently selected cases only when their admission passes
196
- and the failure cannot invalidate shared controls. Otherwise hold affected cases.
197
-
198
- Hold reservations during heavy local phases or declared isolated local performance
199
- measurements. Release them during remote waits, light work and reviews.
200
- Declare finite phase boundaries or stopping conditions, release at those
201
- boundaries and seek fresh admission for the next phase. While waiting, keep the
202
- blocked phase in the ledger and advance already-authorized independent light
203
- work within the active measurement's allowance. Preserve measured inputs;
204
- backlog presence does not authorize new implementation.
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.
205
134
 
206
135
  Screen correctness and quality first, then use one run per selected arm to
207
136
  explore timing and resource behavior. Preserve screened-out results and their
@@ -212,23 +141,37 @@ Before exploratory runs, define the decision-relevant signal for selecting
212
141
  comparisons for confirmation. Choose comparisons that meet that signal, plus
213
142
  decision-critical comparisons, for repeated confirmation; keep necessary controls.
214
143
  Set the confirmation plan before its runs and update the explicit run count
215
- when the scope changes. Repetition counts depend on the
216
- decision and observed variation; there is no universal minimum.
217
-
218
- For a performance claim, add alternating runs to assess run-to-run variation.
219
- Before the first run used in that claim, set a repetition count or stopping
220
- rule and a reproducible variation criterion (statistic and threshold).
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.
221
163
 
222
164
  For short or tail metrics, such as the longest stall in a run, give the
223
165
  threshold an absolute floor or use a percentile or count metric; a percentage
224
166
  of a single small maximum can fail on the workload's own variation.
225
167
  Retain every result. Keep pilots that informed the plan separate from the
226
168
  claim's sample. Capture raw results, exit status, elapsed time, CPU and memory
227
- observations. Report admission and monitoring overhead separately from the
169
+ observations. Report monitoring overhead separately from the
228
170
  measured workload; batch compatible probes when they dominate elapsed time.
229
171
  Report the selected repetition count or stopping rule, variation statistic and
230
- threshold, sample count, median and range. Apply the preset
231
- criterion and treat a gap within run-to-run variation as inconclusive. Profile
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
232
175
  separately from the runs used to claim a speed difference.
233
176
 
234
177
  When using saved evidence for a performance claim, bind archived inputs, source,
@@ -268,8 +211,8 @@ Batch latency percentiles describe batches, not individual requests.
268
211
 
269
212
  Keep the full workload, versions, conditions, repetitions, output identity,
270
213
  errors and measurement units in the measurement record. Include excluded costs,
271
- coverage limits, collector overhead, scheduling, resource caps, admission checks
272
- and rejected attempts there.
214
+ coverage limits, collector overhead, scheduling, resource caps, pre-run
215
+ machine checks and rejected attempts there.
273
216
 
274
217
  Pull requests and other change summaries show the workload, baseline and
275
218
  candidate, measured results, relevant checks and limits that affect the claim.
@@ -282,19 +225,39 @@ percent change or a times improvement. Use the metric's direction and label
282
225
  worsening, unchanged or inconclusive results. With a zero or missing baseline,
283
226
  show an absolute change or state that the benefit cannot be calculated.
284
227
 
285
- Use 3% as the default practical no-clear-change band for reported differences.
286
- This is a reporting convention, not a statistical margin of error. Use the
287
- variation statistic and threshold declared before collecting results. When that
288
- threshold, expressed as a percentage of the baseline, exceeds 3%, widen the
289
- reporting band to at least that percentage and name the statistic and threshold.
290
- If the variation criterion cannot support a percentage band, keep its result
291
- separate and label unsupported differences inconclusive. A change outside the
292
- band still needs qualified evidence and must meet the declared variation criterion. Set a different
293
- precision target before collecting results when the workload requires it;
294
- changing presentation does not change frozen acceptance or rejection gates.
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.
295
255
 
296
256
  For agent, model, rule or skill comparisons, distinguish development cases
297
- from held-out cases and report runs per case. Include a one-line instruction
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
298
261
  control when claiming an improvement from a rule or skill. Keep helper,
299
262
  setup and retry costs visible. Before collecting results, define a per-case
300
263
  contribution threshold. If a case exceeds it, report results both with and
@@ -312,5 +275,5 @@ and rework time. Keep returned usage units separate from attributable account
312
275
  charges; unknown attribution remains unknown.
313
276
 
314
277
  Record every experiment, rejected ones included, with the observed result and
315
- disposition. End with adopt, reject or inconclusive, and the evidence for that
278
+ what was decided. End with adopt, reject or inconclusive, and the evidence for that
316
279
  decision. Any implementation or publication still follows the user's scope.
@@ -15,3 +15,116 @@ startup or transformation separately when it is part of the question.
15
15
  [Node type stripping](https://nodejs.org/api/typescript.html) performs no type
16
16
  checking and ignores `tsconfig.json`. A successful direct `.ts` execution does
17
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.