@bompus/house-rules 0.11.0 → 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.
- package/CODE_OF_CONDUCT.md +83 -0
- package/README.md +91 -60
- package/compose.mjs +8 -2
- package/composition.mjs +11 -3
- package/config-view.mjs +18 -3
- package/config.mjs +74 -13
- package/docs/assets/overview.png +0 -0
- package/docs/configuration.md +85 -9
- package/package.json +4 -2
- package/rules/core.md +118 -209
- package/rules/modifiers/backlog-outline.md +25 -0
- package/rules/modifiers/backlog-visual.md +16 -0
- package/rules/modifiers/coded-offers.md +47 -17
- package/rules/modifiers/cross-session-relay.md +23 -0
- package/rules/modifiers/low-quota-handoff.md +4 -3
- package/rules/modifiers/model-default-questions.md +33 -0
- package/rules/modifiers/multi-agent.md +6 -2
- package/rules/modifiers/no-attribution.md +7 -1
- package/rules/modifiers/periodic-updates.md +25 -0
- package/rules/modifiers/plan-files.md +35 -3
- package/rules/modifiers/release-batching.md +4 -2
- package/rules/modifiers/shared-host-load.md +13 -42
- package/rules/modifiers/squash-landing.md +1 -1
- package/rules/modifiers/upstream-contributions.md +45 -0
- package/rules/modifiers/web-image-formats.md +35 -0
- package/rules/references/backlog-view.md +154 -0
- package/rules/references/landing.md +14 -14
- package/rules/references/multi-agent.md +6 -2
- package/rules/references/release-batching.md +27 -4
- package/rules/references/squash-landing.md +10 -4
- package/rules/references/thread-visuals.md +45 -0
- package/setup.mjs +87 -17
- package/skills/hr-agent-guidance-audit/SKILL.md +10 -5
- package/skills/hr-agent-guidance-audit/references/prune-workflow.md +72 -0
- package/skills/hr-agent-guidance-audit/references/records-and-lessons.md +1 -1
- package/skills/hr-agent-guidance-audit/references/retirement-verdicts.md +49 -0
- package/skills/hr-agent-guidance-refresh/SKILL.md +25 -57
- package/skills/hr-agent-guidance-refresh/references/verification.md +1 -1
- package/skills/hr-audit-choices/SKILL.md +1 -1
- package/skills/hr-benchmarking/SKILL.md +122 -159
- package/skills/hr-benchmarking/references/javascript.md +113 -0
- package/skills/hr-benchmarking/references/tools.md +62 -57
- package/skills/hr-better-accessibility/SKILL.md +1 -1
- package/skills/hr-better-accessibility/screen-readers.md +1 -0
- package/skills/hr-code-review/SKILL.md +19 -3
- package/skills/hr-code-review/agents/openai.yaml +1 -1
- package/skills/hr-code-review/references/acp-client.md +43 -0
- package/skills/{hr-change-impact/SKILL.md → hr-code-review/references/impact.md} +2 -12
- package/skills/hr-code-review/references/panel-adjudication.md +58 -0
- package/skills/hr-code-review/references/panel-plan.md +61 -0
- package/skills/hr-code-review/references/panel-recommendations.json +105 -0
- package/skills/hr-code-review/references/panel-recommendations.md +46 -0
- package/skills/hr-code-review/references/panel-setup.md +54 -0
- package/skills/hr-code-review/references/reviewer-role.md +31 -0
- package/skills/hr-code-review/scripts/acp-panel-client.mjs +299 -0
- package/skills/hr-code-review/scripts/check-receipts.mjs +263 -0
- package/skills/hr-code-review/scripts/panel-plan.mjs +69 -0
- package/skills/hr-code-review/scripts/panel-preferences.mjs +220 -0
- package/skills/hr-design-exploration/SKILL.md +24 -1
- package/skills/hr-design-exploration/agents/openai.yaml +2 -2
- package/skills/hr-diagnosing-bugs/SKILL.md +2 -2
- package/skills/hr-diagnosing-bugs/references/reporting.md +29 -4
- package/skills/hr-diagnosing-bugs/scripts/check-pr-offer.mjs +47 -0
- package/skills/hr-explain-code/SKILL.md +1 -1
- package/skills/hr-extract-shared-steps/SKILL.md +1 -1
- package/skills/hr-forgotten-work-audit/SKILL.md +130 -0
- package/skills/hr-forgotten-work-audit/references/brief-template.md +56 -0
- package/skills/hr-forgotten-work-audit/references/result-format.md +46 -0
- package/skills/hr-handoff/LICENSE +21 -0
- package/skills/hr-handoff/NOTICE.md +29 -0
- package/skills/hr-handoff/SKILL.md +24 -1
- package/skills/hr-handoff/references/reconciliation.md +25 -6
- package/skills/hr-handoff/references/successor-thread.md +76 -0
- package/skills/hr-handoff/scripts/check-reconciliation.mjs +48 -6
- package/skills/hr-house-rules-setup/SKILL.md +22 -8
- package/skills/hr-lean-plan/SKILL.md +4 -0
- package/skills/hr-maintainability-review/SKILL.md +14 -4
- package/skills/hr-maintainability-review/agents/openai.yaml +1 -1
- package/skills/hr-manual-qa/SKILL.md +1 -1
- package/skills/hr-ordering-tests/SKILL.md +1 -1
- package/skills/hr-plain-prose/SKILL.md +7 -4
- package/skills/hr-pr-followup/SKILL.md +6 -3
- package/skills/hr-pr-followup/references/review-helpers.md +21 -0
- package/skills/hr-pr-followup/scripts/check-landing.py +204 -0
- package/skills/hr-pr-followup/scripts/merge-pr.sh +100 -0
- package/skills/hr-pr-followup/scripts/verify-landed.sh +184 -0
- package/skills/hr-read-reddit/SKILL.md +1 -1
- package/skills/hr-research-shared-links/SKILL.md +103 -0
- package/skills/hr-sqlite/SKILL.md +174 -0
- package/skills/hr-sqlite/agents/openai.yaml +2 -0
- package/skills/hr-sqlite/references/evidence.md +94 -0
- package/skills/hr-sqlite/references/tool-decisions.md +39 -0
- package/skills/hr-sqlite/scripts/inspect-sqlite.py +245 -0
- package/skills/hr-stock-ui-audit/SKILL.md +1 -1
- package/skills/hr-test-audit/LICENSE +21 -0
- package/skills/hr-test-audit/NOTICE.md +67 -0
- package/skills/hr-usage-report/SKILL.md +90 -0
- package/skills/hr-usage-report/agents/openai.yaml +2 -0
- package/skills/hr-usage-report/assets/example-report.json +125 -0
- package/skills/hr-usage-report/assets/report-template.html +377 -0
- package/skills/hr-usage-report/scripts/render-report.ts +86 -0
- package/skills/hr-usage-report/scripts/usage-by-model.ts +499 -0
- package/skills/hr-what-next/SKILL.md +100 -10
- package/skills/hr-what-next/references/reporting.md +13 -22
- package/skills/hr-what-next/scripts/check-open-work.mjs +711 -0
- package/skills/hr-writing-pr/SKILL.md +29 -14
- package/skills/hr-writing-pr/scripts/benefit-chart.py +200 -0
- package/docs/npm-release.md +0 -45
- package/rules/modifiers/swarmail.md +0 -12
- package/skills/hr-benchmarking/references/priority-findings-20261006.md +0 -115
- package/skills/hr-change-impact/agents/openai.yaml +0 -5
|
@@ -42,21 +42,27 @@ Resolve mismatches between the description and the implementation before calling
|
|
|
42
42
|
|
|
43
43
|
## Title and body
|
|
44
44
|
|
|
45
|
-
Write a title naming the resulting behavior or fixed failure
|
|
45
|
+
Write a title naming the resulting behavior or fixed failure, in the words of the person who feels it ("fork threads open faster"), not the mechanism ("skip hidden ancestor payloads"). Use the repository's title convention when it has one. When the PR title becomes the squash commit line, keep a measured speedup out of it, because the figure goes stale there. A repository whose convention asks for the figure keeps it. Put the qualified result, with the workload it holds for, in the body's opening sentence.
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
Check the title's type and scope against the diff's dominant change. A `docs:` title on a diff that adds an executable installer misfiles the squash commit. When no PR template exists, the title convention is the only template; default to Conventional Commits `type(scope):` unless the repository's recent history uses another style. Flag a mixed diff as a possible split into separate PRs (the `hr-split-to-prs` skill, where installed) instead of stretching the title to cover it.
|
|
48
|
+
|
|
49
|
+
Open the body with one sentence that states the benefit, before any problem detail. For a measured change it carries the qualified figure and its workload ("Clean Android builds finish 32% faster, 67.7 s to 46.2 s on a warm Gradle cache"). For a bug fix it says who hit the bug and what now works ("Cursor title generation no longer leaks a SQLite file handle on every call"). The problem and resulting behavior follow. A small change may need only a paragraph and a validation sentence. Expand only where the reviewer needs more context:
|
|
48
50
|
|
|
49
51
|
- **Bug fix:** trigger, previous behavior, corrected behavior, and regression proof.
|
|
50
52
|
- **Feature:** observable capability, a small usage example, and supported limits.
|
|
51
53
|
- **Refactor:** motivation, the structural change, and evidence that required behavior is preserved.
|
|
52
54
|
|
|
53
|
-
Explain implementation details only when they clarify a decision or help assess correctness. Include compatibility, dependency, migration, or documentation implications when the diff creates them. When the change has a hard-to-reverse surface (host-level effects such as `sudo install-deps`, migrations, destructive actions), say so in one sentence; never a fixed risk section, and nothing on purely additive changes.
|
|
55
|
+
Explain implementation details only when they clarify a decision or help assess correctness. Include compatibility, dependency, migration, or documentation implications when the diff creates them. When the change has a hard-to-reverse surface (host-level effects such as `sudo install-deps`, migrations, destructive actions), say so in one sentence; never a fixed risk section, and nothing on purely additive changes.
|
|
56
|
+
|
|
57
|
+
For a change too large to read in the diff's file order, give a reading order. Use a short numbered list where each step says what it accomplishes ("the contract, then the service that implements it, then its callers"), and anchor load-bearing claims with `path:line`. Put mechanical files in a last step that says what you checked and the pattern that holds ("same rename in all nine drivers"). Add a "Decisions for you" list only when the reviewer has a call that tests cannot make: a tradeoff, a compatibility promise, a product or scope choice, or an accepted risk. Leave bugs, missing tests and nits out of it, and omit the list when there is no such call. Name adjacent work you left out on purpose in a "Not covered" line.
|
|
58
|
+
|
|
59
|
+
In a stack, open with the parent ("Stacked on #123.") and describe only this layer, measured from its parent; that layer is its final combined change. When the body attributes behavior to another layer or describes a dependency on it, name that layer by number ("added in #123", "wired into the UI in #125"). Do not describe or judge its code.
|
|
54
60
|
|
|
55
|
-
Describe the final combined change. Leave out intermediate attempts, commit reshuffling, conversational history, and file inventories already visible in the diff. Write for the reviewer in plain language: no unexplained jargon, and no narrative about how the change was produced. Review panels, models consulted, harnesses, and agent process never appear in titles, bodies, or PR comments; that detail lives in plan files and session records. For routine clarifications, update the title and body. Material scope changes follow the replacement rule above.
|
|
61
|
+
Describe the final combined change. Leave out intermediate attempts, commit reshuffling, conversational history, and file inventories already visible in the diff. Write for the reviewer in plain language: no unexplained jargon, and no narrative about how the change was produced. Review panels, models consulted, harnesses, and agent process never appear in titles, bodies, or PR comments, except for a disclosure the repository's contribution guidelines or PR template ask for, which is given as asked and no further; that detail otherwise lives in plan files and session records. For routine clarifications, update the title and body. Material scope changes follow the replacement rule above.
|
|
56
62
|
|
|
57
63
|
## Evidence that earns its space
|
|
58
64
|
|
|
59
|
-
Report relevant checks and their actual outcomes, including material failures and unverified behavior. Name the tests or commands run and their scope; a suite-wide pass count alone is not evidence for the changed behavior. When generated files dominate the diff, give the authored line count alongside the headline number so the size does not mislead review. Distinguish newly introduced failures from established baseline failures only when a comparison supports that claim. Keep detailed logs in a linked artifact when the short result is sufficient.
|
|
65
|
+
Report relevant checks and their actual outcomes, including material failures and unverified behavior. Name the tests or commands run and their scope, and the head commit they ran against; a suite-wide pass count alone is not evidence for the changed behavior. When generated files dominate the diff, give the authored line count alongside the headline number so the size does not mislead review. Distinguish newly introduced failures from established baseline failures only when a comparison supports that claim. Keep detailed logs in a linked artifact when the short result is sufficient.
|
|
60
66
|
|
|
61
67
|
Use a small code example when it makes behavior concrete. For visual changes, use comparable before/after images when available. When the change replaces an existing procedure, state the prior and new procedure in one line each. For measured performance claims, follow the installed `hr-benchmarking` skill's
|
|
62
68
|
"Report and decide" guidance for benefit columns, variability and claim limits.
|
|
@@ -85,20 +91,29 @@ outcomes visible; collapse long commands or supporting detail when useful.
|
|
|
85
91
|
Required scope or approval sections stay, with only the justification and links
|
|
86
92
|
the reviewer needs.
|
|
87
93
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
A qualified measured change outside the declared variation criterion, with
|
|
95
|
+
identical outputs, gets a
|
|
96
|
+
headline chart directly under the opening sentence, beside the exact result
|
|
97
|
+
table. Render it with `scripts/benefit-chart.py` in this skill's directory. It reads
|
|
98
|
+
a JSON spec and writes a dark PNG with labeled units, zero-based bars and a
|
|
99
|
+
benefit badge per row. Skip the chart only when every row is no clear change,
|
|
100
|
+
or the one row moved by less than 10%. Set the spec's top-level `band`
|
|
101
|
+
(required) to the declared variation criterion as a fraction of the baseline,
|
|
102
|
+
and name it beside the chart. If the criterion cannot be a fraction of the
|
|
103
|
+
baseline, skip the chart and label the result inconclusive.
|
|
104
|
+
|
|
105
|
+
Show the workload and material limits beside it; a synthetic benchmark is not a
|
|
106
|
+
production or UI speedup. Preview a chart in a different style with the user
|
|
107
|
+
before publishing it. The image is never the only place a value or caveat
|
|
108
|
+
appears. The opening sentence and the result table carry every figure, and `--table`
|
|
109
|
+
prints that table from the chart's spec. The alt text the script prints carries
|
|
110
|
+
them too. An agent or screen reader that cannot read the image loses nothing. Keep the table or equivalent text accessible, and
|
|
96
111
|
attach PR-only graphics without committing them to the product repository.
|
|
97
112
|
|
|
98
113
|
Scale structure to the change. Omit empty optional sections, placeholder text, guessed risk scores or review times, and coverage percentages that were not measured. Complete a required checklist with this PR's specifics rather than omitting it, and mark non-applicable items N/A with a reason. Preserve required template sections and mark unavailable evidence honestly.
|
|
99
114
|
|
|
100
115
|
## Completion check
|
|
101
116
|
|
|
102
|
-
Every factual claim must be supported by inspected code, the originating request, or observed results. The opening explains what changes and why; the remaining text helps review it. Deliver the title and body in the form requested. Apply them to a remote PR only within the user's authorized scope. When the user's rules turn attribution off, include no `Made with` or other host attribution. After `gh pr create` or `gh pr edit`, reread the published body and strip any footer a harness appended.
|
|
117
|
+
Every factual claim must be supported by inspected code, the originating request, or observed results. The opening explains what changes and why; the remaining text helps review it. Deliver the title and body in the form requested. Apply them to a remote PR only within the user's authorized scope. When the user's rules turn attribution off, include no `Made with` or other host attribution beyond a disclosure the repository asks for. After `gh pr create` or `gh pr edit`, reread the published body and strip any footer a harness appended.
|
|
103
118
|
|
|
104
119
|
Relevant validation stays in the description; extensive templates and review automation are outside this skill.
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Render a before/after benefit chart as a PNG for a pull request, issue or discussion.
|
|
3
|
+
|
|
4
|
+
Usage: benefit-chart.py <spec.json> <out.png> [--table]
|
|
5
|
+
|
|
6
|
+
The spec holds a headline, a workload line and one row per measured metric:
|
|
7
|
+
|
|
8
|
+
{
|
|
9
|
+
"headline": "Sidebar search: typing one letter takes 319 ms, was 1,136 ms",
|
|
10
|
+
"workload": "1,300 threads, 1,057 matches, dev build; median of 3 runs",
|
|
11
|
+
"arms": ["Before", "After"],
|
|
12
|
+
"band": 0.03,
|
|
13
|
+
"note": "Lower is better.",
|
|
14
|
+
"rows": [
|
|
15
|
+
{"label": "Type one letter", "before": 1136, "after": 319, "unit": "ms"},
|
|
16
|
+
{"label": "Renders", "before": 36950, "after": 7693, "unit": "",
|
|
17
|
+
"words": ["fewer", "more"]}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
Row fields: label, before, after, unit (text after the value), lower_is_better
|
|
22
|
+
(default true), words (the two words after the percentage, for a good and a bad
|
|
23
|
+
change; default "lower"/"higher", or "higher"/"lower" when lower_is_better is false), and
|
|
24
|
+
note (extra text under the label). band is required: the variation criterion
|
|
25
|
+
declared before the first run, as a fraction of the baseline. A change at or
|
|
26
|
+
inside it is labeled "no clear change". Bars start at zero and share a scale per row.
|
|
27
|
+
|
|
28
|
+
Values must be non-negative. Prints the alt text for the image on stdout. With --table it
|
|
29
|
+
also prints a Markdown table of the same values, the text version of the chart
|
|
30
|
+
for readers and agents that cannot parse the image. Requires matplotlib.
|
|
31
|
+
"""
|
|
32
|
+
import json
|
|
33
|
+
import math
|
|
34
|
+
import sys
|
|
35
|
+
import textwrap
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
import matplotlib
|
|
39
|
+
|
|
40
|
+
matplotlib.use("Agg")
|
|
41
|
+
import matplotlib.pyplot as plt
|
|
42
|
+
from matplotlib.patches import FancyBboxPatch
|
|
43
|
+
except ImportError:
|
|
44
|
+
sys.exit("benefit-chart.py needs matplotlib (pip install matplotlib).")
|
|
45
|
+
|
|
46
|
+
BACKGROUND = "#0d1117"
|
|
47
|
+
TEXT = "#e6edf3"
|
|
48
|
+
MUTED = "#9da7b3"
|
|
49
|
+
BEFORE = "#6e7681"
|
|
50
|
+
GOOD = "#3fb950"
|
|
51
|
+
BAD = "#f85149"
|
|
52
|
+
NEUTRAL = "#8b949e"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def fmt(value):
|
|
56
|
+
magnitude = abs(value)
|
|
57
|
+
if float(value).is_integer():
|
|
58
|
+
return f"{value:,.0f}"
|
|
59
|
+
if magnitude >= 100:
|
|
60
|
+
return f"{value:,.0f}"
|
|
61
|
+
if magnitude >= 10:
|
|
62
|
+
return f"{value:,.1f}"
|
|
63
|
+
if magnitude >= 1:
|
|
64
|
+
return f"{value:,.2f}"
|
|
65
|
+
return f"{value:,.3f}"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def band_of(spec):
|
|
69
|
+
if "band" not in spec:
|
|
70
|
+
sys.exit('spec needs a top-level "band": the declared variation criterion as a fraction '
|
|
71
|
+
"of the baseline, such as 0.04.")
|
|
72
|
+
try:
|
|
73
|
+
if isinstance(spec["band"], bool):
|
|
74
|
+
raise TypeError
|
|
75
|
+
band = float(spec["band"])
|
|
76
|
+
except (TypeError, ValueError):
|
|
77
|
+
band = float("nan")
|
|
78
|
+
if not math.isfinite(band) or band < 0:
|
|
79
|
+
sys.exit('spec "band" must be a finite non-negative number.')
|
|
80
|
+
return band
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def judge(row, band):
|
|
84
|
+
before, after = float(row["before"]), float(row["after"])
|
|
85
|
+
lower_is_better = row.get("lower_is_better", True)
|
|
86
|
+
if before == 0:
|
|
87
|
+
return NEUTRAL, "no baseline to compare", "no baseline to compare"
|
|
88
|
+
change = (after - before) / before
|
|
89
|
+
if abs(change) <= band:
|
|
90
|
+
return NEUTRAL, "no clear change", "no clear change"
|
|
91
|
+
improved = change < 0 if lower_is_better else change > 0
|
|
92
|
+
default_words = ("lower", "higher") if lower_is_better else ("higher", "lower")
|
|
93
|
+
words = row.get("words") or default_words
|
|
94
|
+
word = words[0] if improved else words[1]
|
|
95
|
+
percent = abs(change) * 100
|
|
96
|
+
if 99 <= percent < 100:
|
|
97
|
+
percent_text = f"{int(percent * 10) / 10:.1f}%" # never rounds up to "100%"
|
|
98
|
+
else:
|
|
99
|
+
percent_text = f"{percent:,.0f}%" if percent >= 10 else f"{percent:,.1f}%"
|
|
100
|
+
ratio = max(before, after) / min(before, after) if min(before, after) > 0 else None
|
|
101
|
+
times = f" ({ratio:,.1f}×)" if ratio and ratio >= 1.5 else ""
|
|
102
|
+
text = f"{percent_text} {word}{times}"
|
|
103
|
+
return (GOOD if improved else BAD), text, text
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def render(spec, out_path):
|
|
107
|
+
rows = spec["rows"]
|
|
108
|
+
for row in rows:
|
|
109
|
+
if float(row["before"]) < 0 or float(row["after"]) < 0:
|
|
110
|
+
sys.exit(f"row {row['label']!r}: negative values are not supported (bars start at zero).")
|
|
111
|
+
band = band_of(spec)
|
|
112
|
+
arms = spec.get("arms", ["Before", "After"])
|
|
113
|
+
count = len(rows)
|
|
114
|
+
headline_lines = textwrap.wrap(spec["headline"], 54)
|
|
115
|
+
head = 0.75 + 0.45 * len(headline_lines)
|
|
116
|
+
height = head + 0.6 + 1.25 * count + (0.5 if spec.get("note") else 0.2)
|
|
117
|
+
fig = plt.figure(figsize=(10, height), dpi=160, facecolor=BACKGROUND)
|
|
118
|
+
ax = fig.add_axes([0, 0, 1, 1])
|
|
119
|
+
ax.set_xlim(0, 10)
|
|
120
|
+
ax.set_ylim(0, height)
|
|
121
|
+
ax.axis("off")
|
|
122
|
+
ax.set_facecolor(BACKGROUND)
|
|
123
|
+
|
|
124
|
+
top = height - 0.3
|
|
125
|
+
ax.text(0.4, top, "\n".join(headline_lines), color=TEXT, fontsize=19, fontweight="bold",
|
|
126
|
+
va="top", linespacing=1.25)
|
|
127
|
+
ax.text(0.4, top - 0.4 * len(headline_lines) - 0.2, spec.get("workload", ""), color=MUTED,
|
|
128
|
+
fontsize=10.5, va="top")
|
|
129
|
+
|
|
130
|
+
arm_right, bar_left, bar_span = 1.35, 1.5, 5.6
|
|
131
|
+
y = height - head - 0.45
|
|
132
|
+
alts = []
|
|
133
|
+
for row in rows:
|
|
134
|
+
before, after = float(row["before"]), float(row["after"])
|
|
135
|
+
unit = row.get("unit", "")
|
|
136
|
+
suffix = f" {unit}" if unit else ""
|
|
137
|
+
color, badge, alt_badge = judge(row, band)
|
|
138
|
+
top_value = max(before, after) or 1.0
|
|
139
|
+
ax.text(0.4, y, row["label"], color=TEXT, fontsize=12.5, fontweight="bold", va="center")
|
|
140
|
+
ax.text(9.6, y, badge, color=color, fontsize=15, fontweight="bold", va="center", ha="right")
|
|
141
|
+
if row.get("note"):
|
|
142
|
+
ax.text(0.4, y - 0.24, row["note"], color=MUTED, fontsize=9, va="center")
|
|
143
|
+
bars = ((arms[0], before, BEFORE), (arms[1], after, color))
|
|
144
|
+
for index, (arm, value, bar_color) in enumerate(bars):
|
|
145
|
+
bar_y = y - 0.5 - index * 0.32
|
|
146
|
+
width = max(bar_span * value / top_value, 0.03)
|
|
147
|
+
ax.add_patch(FancyBboxPatch((bar_left, bar_y - 0.11), width, 0.22,
|
|
148
|
+
boxstyle="round,pad=0,rounding_size=0.04",
|
|
149
|
+
linewidth=0, facecolor=bar_color))
|
|
150
|
+
ax.text(arm_right, bar_y, arm, color=MUTED, fontsize=9.5, va="center", ha="right")
|
|
151
|
+
ax.text(bar_left + width + 0.12, bar_y, f"{fmt(value)}{suffix}", color=TEXT,
|
|
152
|
+
fontsize=10.5, va="center")
|
|
153
|
+
row_alt = f"{row['label']}: {fmt(before)}{suffix} to {fmt(after)}{suffix}, {alt_badge}"
|
|
154
|
+
if row.get("note"):
|
|
155
|
+
row_alt += f" ({row['note']})"
|
|
156
|
+
alts.append(row_alt)
|
|
157
|
+
y -= 1.25
|
|
158
|
+
|
|
159
|
+
if spec.get("note"):
|
|
160
|
+
ax.text(0.4, 0.3, spec["note"], color=MUTED, fontsize=9.5, va="center")
|
|
161
|
+
fig.savefig(out_path, facecolor=BACKGROUND)
|
|
162
|
+
plt.close(fig)
|
|
163
|
+
lead = spec["headline"] + (f". {spec['note']}" if spec.get("note") else "")
|
|
164
|
+
if spec.get("workload"):
|
|
165
|
+
lead += f". Workload: {spec['workload']}"
|
|
166
|
+
return f"{lead}. " + "; ".join(alts) + "."
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def table(spec):
|
|
170
|
+
band = band_of(spec)
|
|
171
|
+
arms = spec.get("arms", ["Before", "After"])
|
|
172
|
+
lines = [f"| Metric | {arms[0]} | {arms[1]} | Change |", "| --- | ---: | ---: | --- |"]
|
|
173
|
+
for row in spec["rows"]:
|
|
174
|
+
suffix = f" {row['unit']}" if row.get("unit") else ""
|
|
175
|
+
change = judge(row, band)[2]
|
|
176
|
+
label = row["label"].replace("|", "\\|")
|
|
177
|
+
lines.append(f"| {label} | {fmt(float(row['before']))}{suffix} | "
|
|
178
|
+
f"{fmt(float(row['after']))}{suffix} | {change} |")
|
|
179
|
+
notes = [f"Workload: {spec['workload']}"] if spec.get("workload") else []
|
|
180
|
+
notes += [spec["note"]] if spec.get("note") else []
|
|
181
|
+
notes += [f"{row['label']}: {row['note']}" for row in spec["rows"] if row.get("note")]
|
|
182
|
+
if notes:
|
|
183
|
+
lines += ["", *notes]
|
|
184
|
+
return "\n".join(lines)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def main():
|
|
188
|
+
args = [a for a in sys.argv[1:] if a != "--table"]
|
|
189
|
+
if len(args) != 2:
|
|
190
|
+
sys.exit(__doc__)
|
|
191
|
+
with open(args[0]) as handle:
|
|
192
|
+
spec = json.load(handle)
|
|
193
|
+
print(render(spec, args[1]))
|
|
194
|
+
if "--table" in sys.argv[1:]:
|
|
195
|
+
print()
|
|
196
|
+
print(table(spec))
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
if __name__ == "__main__":
|
|
200
|
+
main()
|
package/docs/npm-release.md
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# npm release setup
|
|
2
|
-
|
|
3
|
-
The package name is `@bompus/house-rules`; the executable is `house-rules`.
|
|
4
|
-
It has no runtime dependencies or install hooks. Installing the package does
|
|
5
|
-
not install skills into an agent host. Composition writes the requested rules
|
|
6
|
-
file, its `house-rules-references/` directory when the rules include reference
|
|
7
|
-
procedures, and any `--skills-out` directory.
|
|
8
|
-
|
|
9
|
-
Keep the `package.json` version, changelog version and `v<version>` tag
|
|
10
|
-
identical.
|
|
11
|
-
|
|
12
|
-
## First publication
|
|
13
|
-
|
|
14
|
-
This one-time setup applies to 0.11.0, the first published version. The first publication requires an npm account that owns the `bompus` scope.
|
|
15
|
-
An earlier publication of another package does not establish current login or
|
|
16
|
-
scope access. Authenticate using npm's web login and complete its 2FA approval.
|
|
17
|
-
Do not put credentials into the repository or workflow.
|
|
18
|
-
|
|
19
|
-
On the selected release commit, run `npm run check:package -- --out <directory>`.
|
|
20
|
-
Publish that verified `house-rules.tgz` with `npm publish <tarball> --access public`.
|
|
21
|
-
Then configure its trusted publisher on npm for GitHub user `bompus`, repository
|
|
22
|
-
`house-rules`, workflow filename `npm-publish.yml`. Enable direct `npm publish`.
|
|
23
|
-
The default staged-publication permission alone does not permit this workflow.
|
|
24
|
-
|
|
25
|
-
The first GitHub release workflow checks the published tarball integrity and
|
|
26
|
-
skips an identical existing version. Different bytes at the same version fail
|
|
27
|
-
the workflow. Subsequent versions publish automatically after trusted publisher
|
|
28
|
-
setup. Do not create another release solely to test authentication.
|
|
29
|
-
|
|
30
|
-
## Subsequent releases
|
|
31
|
-
|
|
32
|
-
Publishing a stable GitHub release triggers `.github/workflows/npm-publish.yml`.
|
|
33
|
-
It verifies that the tagged commit belongs to `main`, checks the package version
|
|
34
|
-
and dated changelog entry, and checks the packed CLI and skill resources before
|
|
35
|
-
publishing the same tarball. Prereleases are excluded.
|
|
36
|
-
|
|
37
|
-
The workflow uses a GitHub-hosted runner and npm's OIDC trusted publishing.
|
|
38
|
-
It stores no npm token. npm requires Node 22.14 or newer and npm 11.5.1 or newer;
|
|
39
|
-
the workflow uses Node 26. npm automatically supplies provenance for this public
|
|
40
|
-
repository and package. See the [official trusted publishing documentation](https://docs.npmjs.com/trusted-publishers/).
|
|
41
|
-
|
|
42
|
-
CI runs `npm run check:package -- --bun`. It installs the actual local tarball
|
|
43
|
-
into isolated scratch with lifecycle scripts disabled, exercises the CLI under
|
|
44
|
-
Node and Bun, and compares composed skills and resources with the source.
|
|
45
|
-
Scratch honors `HOUSE_RULES_TEST_TMP` and is removed when the check exits normally.
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Locate Swarmail-owned instructions and tool contracts for local session coordination.
|
|
3
|
-
after: Coordination and isolation
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
## Swarmail coordination
|
|
7
|
-
|
|
8
|
-
When Swarmail is connected, read its server instructions and tool contracts
|
|
9
|
-
before using it. If those instructions are unavailable or omit a needed detail,
|
|
10
|
-
read `swarmail --help` and `README.md` in its owning checkout at the installed
|
|
11
|
-
or host-approved revision. If available sources do not establish that detail,
|
|
12
|
-
report it as unverified rather than guessing the product's operations.
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
# CPU priority findings: 2026-10-06
|
|
2
|
-
|
|
3
|
-
Read this record before answering whether negative, zero or positive nice values
|
|
4
|
-
improved the tested workload. Reuse these results for the same question; a new
|
|
5
|
-
experiment needs a materially different workload, contention regime or hypothesis.
|
|
6
|
-
Follow the host's authorization rules before changing priority or measuring again.
|
|
7
|
-
|
|
8
|
-
## Result and scope
|
|
9
|
-
|
|
10
|
-
Negative nice did not establish a timing or memory benefit in this small WSL
|
|
11
|
-
allocation experiment. Verified effective nice 0 was the only setting that met
|
|
12
|
-
the preset variation criterion for both runtimes. It is a baseline candidate for
|
|
13
|
-
comparable isolated measurements, not a universal priority policy.
|
|
14
|
-
|
|
15
|
-
The workload performed 16,384 warmup and 65,536 measured `Buffer.alloc(size, 1)`
|
|
16
|
-
operations, cycling 1,000, 16,000, 128,000 and 1,000,000-byte buffers and retaining
|
|
17
|
-
at most 128 references. Timing and CPU cover the measured loop; peak RSS covers
|
|
18
|
-
the whole process. This allocation case is also reported in
|
|
19
|
-
[Bun issue 44661](https://github.com/oven-sh/bun/issues/44661).
|
|
20
|
-
This is a priority sensitivity comparison, not a general Bun-versus-Node ranking,
|
|
21
|
-
a contention-resistance test or an explanation of that issue's root cause.
|
|
22
|
-
|
|
23
|
-
## Recorded experiment
|
|
24
|
-
|
|
25
|
-
The measured interval was 2026-10-06 23:42:55Z–23:45:40Z. Bun 1.4.2 and
|
|
26
|
-
Node 26.10.0 used unchanged sources and binaries. Three independent processes
|
|
27
|
-
per runtime/priority cell ran in counterbalanced order, for 24 processes total.
|
|
28
|
-
All passed correctness, effective-control and quiet-host admission checks;
|
|
29
|
-
none was rejected. The preset criterion was `(maximum - minimum) / median <= 10%`.
|
|
30
|
-
|
|
31
|
-
Controls were Windows-hosted WSL, Linux kernel 7.2.8 with an unverified custom
|
|
32
|
-
scheduler implementation, ordinary fair scheduling, unprivileged workload UID
|
|
33
|
-
1000, CPU affinity 0–7 and identical 704 MiB `memory.high`/`memory.max` limits.
|
|
34
|
-
No CPU quota was present at inspected cgroup ancestors. The launcher set absolute
|
|
35
|
-
priority before dropping privileges and verified it afterward; the workload did
|
|
36
|
-
not run as root. Main-thread scheduler wait included warmup and cannot establish
|
|
37
|
-
timed-region or all-GC-thread scheduling effects.
|
|
38
|
-
|
|
39
|
-
| Runtime | Nice | Median wall ms | Wall range ms | Span | Median CPU ms | Median peak RSS MiB | Variation passes |
|
|
40
|
-
| ------- | ---: | -------------: | ------------: | -----: | ------------: | ------------------: | ---------------- |
|
|
41
|
-
| bun | +10 | 1445.9 | 1195.6–1467.9 | 18.83% | 1812.3 | 191.5 | no |
|
|
42
|
-
| bun | +0 | 1356.4 | 1326.5–1412.4 | 6.34% | 1778.9 | 191.3 | yes |
|
|
43
|
-
| bun | -10 | 1416.1 | 1291.2–1468.1 | 12.49% | 1781.2 | 189.2 | no |
|
|
44
|
-
| bun | -20 | 1346.1 | 1287.4–1497.2 | 15.58% | 1691.4 | 190.1 | no |
|
|
45
|
-
| node | +10 | 1196.5 | 1083.8–1231.8 | 12.37% | 1849.8 | 193.5 | no |
|
|
46
|
-
| node | +0 | 1136.2 | 1133.3–1138.5 | 0.46% | 1735.8 | 192.1 | yes |
|
|
47
|
-
| node | -10 | 1148.1 | 1097.3–1152.7 | 4.82% | 1747.0 | 191.9 | yes |
|
|
48
|
-
| node | -20 | 1191.7 | 1189.9–1277.3 | 7.33% | 1825.9 | 192.7 | yes |
|
|
49
|
-
|
|
50
|
-
Bun +10, -10 and -20 failed the variation criterion. Node -10 overlapped nice 0;
|
|
51
|
-
Node -20 was slower. These three-process samples support no confirmed negative
|
|
52
|
-
priority gain. The small quiet-host cohort does not predict behavior under
|
|
53
|
-
contention or on another scheduler. The per-process measurement values below
|
|
54
|
-
make the reported aggregates auditable; their scope limits still apply.
|
|
55
|
-
|
|
56
|
-
## Per-process measurement values
|
|
57
|
-
|
|
58
|
-
These are the 24 retained output measurements used above, with path and process
|
|
59
|
-
identity fields omitted. Repetition numbers identify each process within its
|
|
60
|
-
runtime/priority cell; they are not execution order. CPU is in microseconds and
|
|
61
|
-
peak RSS in KiB to retain the source units. Wall values retain nine decimal
|
|
62
|
-
places for aggregate recalculation, not a claim of clock accuracy.
|
|
63
|
-
|
|
64
|
-
Recalculation from these samples matches every aggregate before display rounding.
|
|
65
|
-
Each source output passed correctness and effective-control checks before and
|
|
66
|
-
after the workload. No process was rejected. The broader host-admission receipts
|
|
67
|
-
remain outside this bundle; this table provides sample-level auditability for
|
|
68
|
-
the reported wall, CPU, RSS and variation values, not complete host reproduction.
|
|
69
|
-
|
|
70
|
-
| Runtime | Nice | Repetition | Wall ms | CPU us | Peak RSS KiB |
|
|
71
|
-
| ------- | ---: | ---------: | -------------: | ------: | -----------: |
|
|
72
|
-
| bun | +10 | 1 | 1195.596419000 | 1505936 | 196116 |
|
|
73
|
-
| bun | +10 | 2 | 1445.887323000 | 1812345 | 190948 |
|
|
74
|
-
| bun | +10 | 3 | 1467.863081000 | 1852217 | 197132 |
|
|
75
|
-
| bun | +0 | 1 | 1326.456355000 | 1659644 | 195900 |
|
|
76
|
-
| bun | +0 | 2 | 1412.394017000 | 1778913 | 189540 |
|
|
77
|
-
| bun | +0 | 3 | 1356.414170000 | 1779749 | 199772 |
|
|
78
|
-
| bun | -10 | 1 | 1291.186539000 | 1638686 | 190644 |
|
|
79
|
-
| bun | -10 | 2 | 1468.095042000 | 1847875 | 195332 |
|
|
80
|
-
| bun | -10 | 3 | 1416.096128000 | 1781215 | 193692 |
|
|
81
|
-
| bun | -20 | 1 | 1287.427399000 | 1628746 | 194676 |
|
|
82
|
-
| bun | -20 | 2 | 1497.167736000 | 1893806 | 191196 |
|
|
83
|
-
| bun | -20 | 3 | 1346.090557000 | 1691437 | 195036 |
|
|
84
|
-
| node | +10 | 1 | 1083.811791000 | 1655921 | 200988 |
|
|
85
|
-
| node | +10 | 2 | 1196.507378000 | 1849814 | 198100 |
|
|
86
|
-
| node | +10 | 3 | 1231.812016000 | 1913550 | 197184 |
|
|
87
|
-
| node | +0 | 1 | 1138.547173000 | 1717254 | 196524 |
|
|
88
|
-
| node | +0 | 2 | 1136.151985000 | 1735839 | 197480 |
|
|
89
|
-
| node | +0 | 3 | 1133.265512000 | 1736305 | 196716 |
|
|
90
|
-
| node | -10 | 1 | 1097.328563000 | 1684817 | 196008 |
|
|
91
|
-
| node | -10 | 2 | 1152.692612000 | 1789165 | 197780 |
|
|
92
|
-
| node | -10 | 3 | 1148.141853000 | 1746972 | 196516 |
|
|
93
|
-
| node | -20 | 1 | 1277.348138000 | 1994581 | 196600 |
|
|
94
|
-
| node | -20 | 2 | 1191.670413000 | 1825925 | 197344 |
|
|
95
|
-
| node | -20 | 3 | 1189.945316000 | 1821113 | 198976 |
|
|
96
|
-
|
|
97
|
-
## Omitting nice versus requesting zero
|
|
98
|
-
|
|
99
|
-
A child inherits its parent's nice value, and `exec` preserves it. Omitting
|
|
100
|
-
`nice` therefore yields zero only when the parent already has effective nice 0.
|
|
101
|
-
GNU `nice -n 0 COMMAND` adds zero to the inherited value; it does not reset +10
|
|
102
|
-
to zero. Bare `nice COMMAND` applies the default +10 adjustment. `setpriority`
|
|
103
|
-
sets an absolute value, subject to permissions; verify the effective value
|
|
104
|
-
rather than treating the requested command as proof.
|
|
105
|
-
|
|
106
|
-
Positive nice lowers CPU scheduling priority; negative nice raises it. Neither
|
|
107
|
-
reserves a core or replaces host admission and resource controls. Keep effective
|
|
108
|
-
values equal across ordinary comparison arms. General +10 background/build
|
|
109
|
-
policies serve responsiveness and are separate from this experiment; these
|
|
110
|
-
results do not authorize removing them or changing installed settings.
|
|
111
|
-
|
|
112
|
-
Sources: [Linux getpriority/setpriority](https://man7.org/linux/man-pages/man2/setpriority.2.html)
|
|
113
|
-
for inheritance, absolute values and permissions; [GNU nice](https://www.gnu.org/software/coreutils/manual/html_node/nice-invocation.html)
|
|
114
|
-
for relative adjustment. GNU online retrieval was unavailable during verification;
|
|
115
|
-
the installed command's help confirmed the adjustment and default +10.
|