@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.
- package/CODE_OF_CONDUCT.md +83 -0
- package/CONTRIBUTING.md +54 -0
- package/LICENSE +21 -0
- package/README.md +378 -2
- package/THIRD_PARTY_NOTICES.md +188 -0
- package/compose.mjs +125 -0
- package/composition.mjs +361 -0
- package/config-view.mjs +209 -0
- package/config.mjs +381 -0
- package/docs/assets/banner-dark.png +0 -0
- package/docs/assets/banner-light.png +0 -0
- package/docs/assets/overview.png +0 -0
- package/docs/configuration.md +269 -0
- package/docs/skill-names.md +50 -0
- package/examples/person/house-rules.json +15 -0
- package/examples/person/rules/10-tooling.md +8 -0
- package/examples/person/rules/20-reporting.md +9 -0
- package/examples/project/AGENTS.md +18 -0
- package/package.json +42 -4
- package/rule-references.mjs +91 -0
- package/rules/core.md +340 -0
- package/rules/modifiers/backlog-outline.md +25 -0
- package/rules/modifiers/backlog-visual.md +16 -0
- package/rules/modifiers/coded-offers.md +70 -0
- package/rules/modifiers/cross-session-relay.md +23 -0
- package/rules/modifiers/effort-estimates.md +41 -0
- package/rules/modifiers/land-when-done.md +12 -0
- package/rules/modifiers/low-quota-handoff.md +20 -0
- package/rules/modifiers/model-default-questions.md +33 -0
- package/rules/modifiers/multi-agent.md +38 -0
- package/rules/modifiers/no-attribution.md +16 -0
- package/rules/modifiers/periodic-updates.md +25 -0
- package/rules/modifiers/plan-files.md +82 -0
- package/rules/modifiers/question-cards.md +48 -0
- package/rules/modifiers/release-batching.md +15 -0
- package/rules/modifiers/scratch-on-disk.md +15 -0
- package/rules/modifiers/shared-host-load.md +19 -0
- package/rules/modifiers/solo-operator.md +13 -0
- package/rules/modifiers/squash-landing.md +22 -0
- 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/github-actions.md +45 -0
- package/rules/references/landing.md +39 -0
- package/rules/references/multi-agent.md +51 -0
- package/rules/references/release-batching.md +66 -0
- package/rules/references/squash-landing.md +50 -0
- package/rules/references/thread-visuals.md +45 -0
- package/setup.mjs +445 -0
- package/skills/hr-agent-guidance-audit/LICENSE +21 -0
- package/skills/hr-agent-guidance-audit/SKILL.md +91 -0
- package/skills/hr-agent-guidance-audit/agents/openai.yaml +2 -0
- package/skills/hr-agent-guidance-audit/references/prune-workflow.md +72 -0
- package/skills/hr-agent-guidance-audit/references/records-and-lessons.md +60 -0
- package/skills/hr-agent-guidance-audit/references/retirement-verdicts.md +49 -0
- package/skills/hr-agent-guidance-refresh/LICENSE +21 -0
- package/skills/hr-agent-guidance-refresh/SKILL.md +36 -0
- package/skills/hr-agent-guidance-refresh/agents/openai.yaml +2 -0
- package/skills/hr-agent-guidance-refresh/references/verification.md +47 -0
- package/skills/hr-api-exposure-check/SKILL.md +159 -0
- package/skills/hr-api-exposure-check/agents/openai.yaml +3 -0
- package/skills/hr-audit-choices/SKILL.md +67 -0
- package/skills/hr-audit-choices/agents/openai.yaml +2 -0
- package/skills/hr-benchmarking/NOTICE.md +36 -0
- package/skills/hr-benchmarking/SKILL.md +279 -0
- package/skills/hr-benchmarking/agents/openai.yaml +2 -0
- package/skills/hr-benchmarking/references/javascript.md +130 -0
- package/skills/hr-benchmarking/references/tools.md +165 -0
- package/skills/hr-benchmarking/scripts/process-attribution.ps1 +20 -0
- package/skills/hr-benchmarking/scripts/process-attribution.py +107 -0
- package/skills/hr-better-accessibility/LICENSE +22 -0
- package/skills/hr-better-accessibility/NOTICE.md +46 -0
- package/skills/hr-better-accessibility/SKILL.md +119 -0
- package/skills/hr-better-accessibility/agents/openai.yaml +3 -0
- package/skills/hr-better-accessibility/focus-and-keyboard.md +130 -0
- package/skills/hr-better-accessibility/forms.md +82 -0
- package/skills/hr-better-accessibility/hit-areas.md +98 -0
- package/skills/hr-better-accessibility/motion-and-zoom.md +81 -0
- package/skills/hr-better-accessibility/screen-readers.md +102 -0
- package/skills/hr-better-accessibility/semantics-and-aria.md +84 -0
- package/skills/hr-better-colors/LICENSE +21 -0
- package/skills/hr-better-colors/NOTICE.md +37 -0
- package/skills/hr-better-colors/SKILL.md +114 -0
- package/skills/hr-better-colors/agents/openai.yaml +3 -0
- package/skills/hr-better-colors/color-formats.md +90 -0
- package/skills/hr-better-colors/color-usage.md +140 -0
- package/skills/hr-better-colors/contrast.md +80 -0
- package/skills/hr-better-colors/palette-generation.md +104 -0
- package/skills/hr-better-colors/palette-structure.md +76 -0
- package/skills/hr-better-colors/token-naming.md +97 -0
- package/skills/hr-better-layout/LICENSE +22 -0
- package/skills/hr-better-layout/NOTICE.md +48 -0
- package/skills/hr-better-layout/SKILL.md +92 -0
- package/skills/hr-better-layout/agents/openai.yaml +3 -0
- package/skills/hr-better-layout/grouping-and-alignment.md +144 -0
- package/skills/hr-better-layout/spacing-and-adaptivity.md +215 -0
- package/skills/hr-better-typography/LICENSE +22 -0
- package/skills/hr-better-typography/NOTICE.md +46 -0
- package/skills/hr-better-typography/SKILL.md +172 -0
- package/skills/hr-better-typography/agents/openai.yaml +3 -0
- package/skills/hr-better-typography/choosing-fonts.md +69 -0
- package/skills/hr-better-typography/css-cheat-sheet.md +65 -0
- package/skills/hr-better-typography/details-and-accessibility.md +119 -0
- package/skills/hr-better-typography/spacing-and-sizing.md +131 -0
- package/skills/hr-better-typography/variable-fonts-and-opentype.md +105 -0
- package/skills/hr-better-typography/wrapping-and-punctuation.md +57 -0
- package/skills/hr-better-writing/LICENSE +22 -0
- package/skills/hr-better-writing/NOTICE.md +46 -0
- package/skills/hr-better-writing/SKILL.md +122 -0
- package/skills/hr-better-writing/agents/openai.yaml +3 -0
- package/skills/hr-code-review/LICENSE +21 -0
- package/skills/hr-code-review/NOTICE.md +26 -0
- package/skills/hr-code-review/SKILL.md +163 -0
- package/skills/hr-code-review/agents/openai.yaml +3 -0
- package/skills/hr-code-review/references/acp-client.md +43 -0
- package/skills/hr-code-review/references/evidence.md +57 -0
- package/skills/hr-code-review/references/impact.md +103 -0
- 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 +105 -0
- package/skills/hr-design-exploration/agents/openai.yaml +4 -0
- package/skills/hr-diagnosing-bugs/NOTICE.md +45 -0
- package/skills/hr-diagnosing-bugs/SKILL.md +108 -0
- package/skills/hr-diagnosing-bugs/agents/openai.yaml +3 -0
- package/skills/hr-diagnosing-bugs/references/reporting.md +97 -0
- package/skills/hr-diagnosing-bugs/scripts/check-pr-offer.mjs +47 -0
- package/skills/hr-explain-code/NOTICE.md +37 -0
- package/skills/hr-explain-code/SKILL.md +110 -0
- package/skills/hr-explain-code/agents/openai.yaml +5 -0
- package/skills/hr-explain-code/references/helper-brief.md +39 -0
- package/skills/hr-extract-shared-steps/SKILL.md +134 -0
- package/skills/hr-extract-shared-steps/agents/openai.yaml +3 -0
- 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 +114 -0
- package/skills/hr-handoff/agents/openai.yaml +5 -0
- package/skills/hr-handoff/assets/ledger.example.json +10 -0
- package/skills/hr-handoff/assets/receipt.example.json +76 -0
- package/skills/hr-handoff/assets/source.example.json +20 -0
- package/skills/hr-handoff/references/reconciliation.md +124 -0
- package/skills/hr-handoff/references/successor-thread.md +76 -0
- package/skills/hr-handoff/scripts/check-reconciliation.mjs +324 -0
- package/skills/hr-house-rules-setup/SKILL.md +114 -0
- package/skills/hr-house-rules-setup/agents/openai.yaml +5 -0
- package/skills/hr-issue-tracker-setup/SKILL.md +49 -0
- package/skills/hr-issue-tracker-setup/agents/openai.yaml +5 -0
- package/skills/hr-lean-plan/SKILL.md +146 -0
- package/skills/hr-lean-plan/agents/openai.yaml +5 -0
- package/skills/hr-maintainability-review/SKILL.md +186 -0
- package/skills/hr-maintainability-review/agents/openai.yaml +5 -0
- package/skills/hr-manual-qa/NOTICE.md +36 -0
- package/skills/hr-manual-qa/SKILL.md +37 -0
- package/skills/hr-manual-qa/agents/openai.yaml +3 -0
- package/skills/hr-navigation-retro/LICENSE +21 -0
- package/skills/hr-navigation-retro/NOTICE.md +5 -0
- package/skills/hr-navigation-retro/SKILL.md +86 -0
- package/skills/hr-navigation-retro/agents/openai.yaml +4 -0
- package/skills/hr-navigation-retro/references/inputs.md +67 -0
- package/skills/hr-navigation-retro/scripts/retro.py +552 -0
- package/skills/hr-navigation-retro/scripts/transcripts.py +205 -0
- package/skills/hr-ordering-tests/SKILL.md +51 -0
- package/skills/hr-ordering-tests/agents/openai.yaml +2 -0
- package/skills/hr-plain-prose/SKILL.md +264 -0
- package/skills/hr-plain-prose/agents/openai.yaml +3 -0
- package/skills/hr-plain-prose/scripts/check.mjs +331 -0
- package/skills/hr-pr-followup/LICENSE +21 -0
- package/skills/hr-pr-followup/NOTICE.md +9 -0
- package/skills/hr-pr-followup/SKILL.md +74 -0
- package/skills/hr-pr-followup/agents/openai.yaml +2 -0
- package/skills/hr-pr-followup/references/review-helpers.md +111 -0
- package/skills/hr-pr-followup/scripts/check-landing.py +204 -0
- package/skills/hr-pr-followup/scripts/check-pr-review.ts +510 -0
- package/skills/hr-pr-followup/scripts/merge-pr.sh +100 -0
- package/skills/hr-pr-followup/scripts/resolve-pr-thread.ts +219 -0
- package/skills/hr-pr-followup/scripts/verify-landed.sh +184 -0
- package/skills/hr-progress-report/SKILL.md +49 -0
- package/skills/hr-progress-report/agents/openai.yaml +5 -0
- package/skills/hr-read-reddit/SKILL.md +44 -0
- package/skills/hr-read-reddit/agents/openai.yaml +2 -0
- package/skills/hr-read-reddit/scripts/reddit.ts +252 -0
- package/skills/hr-read-x-links/SKILL.md +42 -0
- package/skills/hr-read-x-links/agents/openai.yaml +2 -0
- package/skills/hr-read-x-links/scripts/x-post.ts +264 -0
- package/skills/hr-research-shared-links/SKILL.md +103 -0
- package/skills/hr-split-to-prs/LICENSE +21 -0
- package/skills/hr-split-to-prs/NOTICE.md +9 -0
- package/skills/hr-split-to-prs/SKILL.md +61 -0
- package/skills/hr-split-to-prs/agents/openai.yaml +2 -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 +132 -0
- package/skills/hr-stock-ui-audit/agents/openai.yaml +3 -0
- package/skills/hr-stock-ui-audit/scripts/scan.mjs +619 -0
- package/skills/hr-tdd/LICENSE +21 -0
- package/skills/hr-tdd/NOTICE.md +10 -0
- package/skills/hr-tdd/SKILL.md +40 -0
- package/skills/hr-tdd/agents/openai.yaml +3 -0
- package/skills/hr-tdd/mocking.md +39 -0
- package/skills/hr-tdd/tests.md +77 -0
- package/skills/hr-test-audit/LICENSE +21 -0
- package/skills/hr-test-audit/NOTICE.md +67 -0
- package/skills/hr-test-audit/SKILL.md +146 -0
- package/skills/hr-test-audit/agents/openai.yaml +3 -0
- package/skills/hr-test-audit/scripts/floor-guard.ts +137 -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 +151 -0
- package/skills/hr-what-next/agents/openai.yaml +4 -0
- package/skills/hr-what-next/references/reporting.md +59 -0
- package/skills/hr-what-next/scripts/check-open-work.mjs +711 -0
- package/skills/hr-writing-for-agents/NOTICE.md +46 -0
- package/skills/hr-writing-for-agents/SKILL-MECHANICS.md +83 -0
- package/skills/hr-writing-for-agents/SKILL.md +108 -0
- package/skills/hr-writing-for-agents/agents/openai.yaml +3 -0
- package/skills/hr-writing-pr/NOTICE.md +48 -0
- package/skills/hr-writing-pr/SKILL.md +119 -0
- package/skills/hr-writing-pr/agents/openai.yaml +2 -0
- package/skills/hr-writing-pr/scripts/benefit-chart.py +200 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# Configure house rules
|
|
2
|
+
|
|
3
|
+
Use `node compose.mjs config help` to see the commands. Bun supports the same
|
|
4
|
+
interface. The CLI manages the existing `house-rules.json`; it keeps personal
|
|
5
|
+
layers, independent skill names and unrelated settings.
|
|
6
|
+
|
|
7
|
+
## Guided selection
|
|
8
|
+
|
|
9
|
+
Run `node compose.mjs setup --config <config-path>` in a terminal. Bun supports
|
|
10
|
+
the same command. The numbered flow uses ordinary line input; `--plain` selects
|
|
11
|
+
the same flow. Both input and output must be terminals. Redirected input or
|
|
12
|
+
output prints scripting instructions and exits 2 without saving. Use
|
|
13
|
+
`setup --json` for the existing read-only `config status --json` report.
|
|
14
|
+
|
|
15
|
+
Modifiers and skills have stable row numbers while searching. Use `toggle N`
|
|
16
|
+
or `toggle NAME`, with several choices separated by spaces. `search TEXT`,
|
|
17
|
+
`clear search`, `show selected` and `show all` change visibility only.
|
|
18
|
+
`help N` shows the full description, source and invocation policy.
|
|
19
|
+
Excluding a skill name excludes its personal override as well as the shipped
|
|
20
|
+
copy. Exclusions without a current source remain in the configuration.
|
|
21
|
+
|
|
22
|
+
Use `questions default|plain|coded|cards` for question preferences; these modifiers
|
|
23
|
+
are handled together rather than as individual toggles. `next` moves from
|
|
24
|
+
modifiers to skills, then review. `back` keeps the draft. Only `save` on review
|
|
25
|
+
writes configuration. Before a save attempt, `cancel`, end of input or Ctrl-C
|
|
26
|
+
leaves it unchanged.
|
|
27
|
+
A new config with no selection changes is not created.
|
|
28
|
+
|
|
29
|
+
Review includes personal rule origins and an equivalent `config set` command.
|
|
30
|
+
The command uses POSIX quoting on Unix and PowerShell quoting on Windows.
|
|
31
|
+
Personal prose can override the selected preferences; setup does not interpret
|
|
32
|
+
or edit it. Existing composition errors still block saving. Unknown stored
|
|
33
|
+
modifiers can be removed, and a question preset can repair its prerequisite.
|
|
34
|
+
Malformed configuration, legacy skill names and invalid layers require repair
|
|
35
|
+
outside setup.
|
|
36
|
+
|
|
37
|
+
If another writer changes configuration before save, setup preserves the
|
|
38
|
+
draft intent and refuses the stale write. Use `refresh` to compare that intent
|
|
39
|
+
with the fresh configuration, then explicitly save again. It never saves a
|
|
40
|
+
fresh comparison automatically. Saving preserves custom keys and their meaning;
|
|
41
|
+
the writer formats JSON, so existing whitespace is not preserved.
|
|
42
|
+
|
|
43
|
+
If verification fails after saving, configuration may already have changed.
|
|
44
|
+
Inspect `config status` or use `refresh` before another save. Cancelling ends
|
|
45
|
+
the session without undoing an earlier save attempt.
|
|
46
|
+
|
|
47
|
+
Setup saves selections only. Recompose output separately, then connect the
|
|
48
|
+
chosen hosts. It does not install, update, repair or remove managed output.
|
|
49
|
+
|
|
50
|
+
## Browse and inspect
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
node compose.mjs config catalog --config <config-path>
|
|
54
|
+
node compose.mjs config status --config <config-path>
|
|
55
|
+
node compose.mjs config validate --config <config-path>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`setup` initially shows current selections. Search for relevant additions or
|
|
59
|
+
use `show all` to browse the complete catalog. Review and saving do not require
|
|
60
|
+
a catalog-wide decision.
|
|
61
|
+
|
|
62
|
+
`catalog` shows modifiers, skills and rule sections. `status` shows enabled
|
|
63
|
+
selections and effective personal sources. Both use aligned tables, with color
|
|
64
|
+
in a terminal and stacked rows on narrow screens. `NO_COLOR` disables color.
|
|
65
|
+
Use `--json` for structured output without terminal styling.
|
|
66
|
+
|
|
67
|
+
A missing config is treated as an empty selection without creating files.
|
|
68
|
+
Modifiers are opt-in. Fresh installers copy the sample config with eight skills
|
|
69
|
+
and no modifiers. A missing config or an existing config without `skills.include`
|
|
70
|
+
keeps the full shipped set. The default config path is the same as the composer
|
|
71
|
+
uses. Pass `--config` to choose another.
|
|
72
|
+
|
|
73
|
+
`skills.include` is an optional list of shipped skill names. An empty list selects
|
|
74
|
+
no shipped skills; later shipped additions stay off unless listed. Unknown names,
|
|
75
|
+
malformed lists and duplicates are errors. Personal layer skills still load and
|
|
76
|
+
override shipped skills, even when the shipped name is absent from the list.
|
|
77
|
+
`skills.exclude` takes precedence across every layer. Existing independent names,
|
|
78
|
+
layers and custom settings retain their behavior. The catalog remains complete
|
|
79
|
+
so you can discover additions without enabling them.
|
|
80
|
+
|
|
81
|
+
Status distinguishes configured question preferences from effective rule
|
|
82
|
+
sources. Personal rules can override those preferences. Neither status nor
|
|
83
|
+
validation proves what a running agent has loaded.
|
|
84
|
+
|
|
85
|
+
## Preview and save
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
node compose.mjs config set --config <config-path> \
|
|
89
|
+
--enable-modifier shared-host-load --disable-skill hr-read-reddit --questions coded
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`set` previews by default. It shows the selection changes, composition summary,
|
|
93
|
+
personal rule overrides and current revision. Repeat the exact command with
|
|
94
|
+
`--apply --expect <revision>` to save the reviewed change. Read the new revision
|
|
95
|
+
from the result before another write.
|
|
96
|
+
|
|
97
|
+
Toggle flags can repeat. Enable or disable modifiers with `--enable-modifier`
|
|
98
|
+
and `--disable-modifier`; skills use `--enable-skill` and `--disable-skill`.
|
|
99
|
+
Enabling a skill removes its exclusion. When `skills.include` exists, enabling
|
|
100
|
+
a shipped skill also adds it to that list. Enabling a personal-only skill does
|
|
101
|
+
not add a shipped name. Disabling adds an exclusion, retaining the include list,
|
|
102
|
+
unrelated exclusions and custom settings. Configs without an include list keep
|
|
103
|
+
their existing selection behavior.
|
|
104
|
+
|
|
105
|
+
| Question preset | What you get | Enabled offer modifiers |
|
|
106
|
+
| --------------------- | --------------------------------- | ----------------------------------- |
|
|
107
|
+
| `--questions default` | Model default | `model-default-questions` |
|
|
108
|
+
| `--questions plain` | Text only | Neither offer modifier |
|
|
109
|
+
| `--questions coded` | Text only, with short reply codes | `coded-offers` |
|
|
110
|
+
| `--questions cards` | Clickable choices when available | `coded-offers` and `question-cards` |
|
|
111
|
+
|
|
112
|
+
`default` adds no instruction about how to ask: the model and host ask
|
|
113
|
+
questions their usual way, which on some hosts means clickable choices and on
|
|
114
|
+
others plain text. Core rules, without a preset, keep text only. `default`
|
|
115
|
+
cannot combine with `coded-offers` or `question-cards`.
|
|
116
|
+
|
|
117
|
+
Question presets preserve other modifiers. Choose a preset or explicit offer
|
|
118
|
+
modifier toggles, rather than combining both in one command. Cards still depend
|
|
119
|
+
on the agent host, provider and model. Review any personal Offers override
|
|
120
|
+
before saving; the CLI does not rewrite personal prose.
|
|
121
|
+
|
|
122
|
+
To repair invalid modifier selections, preview changes that produce a valid
|
|
123
|
+
selection. `--questions` can repair the offer dependency; `--disable-modifier`
|
|
124
|
+
can remove an unknown modifier already stored in the config. Malformed config
|
|
125
|
+
structure, unknown enables and unknown disables absent from the config remain
|
|
126
|
+
errors.
|
|
127
|
+
|
|
128
|
+
`preview` accepts the same selection flags without saving. Add `--rules` to
|
|
129
|
+
print the composed rules, or `--json` for the full report. Unknown choices,
|
|
130
|
+
contradictory flags, malformed config and composition errors stop the command
|
|
131
|
+
before it writes configuration. Older skill names need the
|
|
132
|
+
[skill name upgrade](skill-names.md) before composition.
|
|
133
|
+
|
|
134
|
+
## Optional panel preferences
|
|
135
|
+
|
|
136
|
+
Use `--panel-file <json>` with `config preview` or `config set` to replace only
|
|
137
|
+
the configuration's `panel` section. The input contains the complete preferences
|
|
138
|
+
object, without a surrounding `panel` key. It must be a regular JSON file.
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"version": 1,
|
|
143
|
+
"profile": "balanced",
|
|
144
|
+
"roles": [
|
|
145
|
+
{ "id": "correctness", "candidates": ["review-primary", "review-alternative"] },
|
|
146
|
+
{ "id": "contrarian", "candidates": ["challenge-primary"] }
|
|
147
|
+
],
|
|
148
|
+
"policy": {
|
|
149
|
+
"fallback": "approved-only",
|
|
150
|
+
"roundLimit": 1,
|
|
151
|
+
"meteredRoutes": "explicit-approval-required",
|
|
152
|
+
"distinctFamilies": true,
|
|
153
|
+
"excludeAuthorFamily": true,
|
|
154
|
+
"allowReducedPanel": false
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
node compose.mjs config preview --config <config-path> --panel-file <panel-json>
|
|
161
|
+
node compose.mjs config set --config <config-path> --panel-file <panel-json> \
|
|
162
|
+
--apply --expect <reviewed-config-revision> --expect-panel <reviewed-input-revision>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Preview shows the entire previous and proposed panel section, including ordered
|
|
166
|
+
alternatives. Explicit apply replaces that section; it does not merge role lists.
|
|
167
|
+
Normal selection flags can accompany a panel replacement, with both changes
|
|
168
|
+
covered by the same revision guard. `--rules` cannot accompany `--panel-file`
|
|
169
|
+
because rule output would hide the panel replacement preview.
|
|
170
|
+
Panel input has its own SHA-256 revision. Apply requires `--expect-panel` from
|
|
171
|
+
the preview as well as the config revision, so an edited input file cannot
|
|
172
|
+
silently replace reviewed preferences. A changed input requires another preview.
|
|
173
|
+
|
|
174
|
+
Version 1 requires `version`, a non-empty ordered `roles` array and `policy`.
|
|
175
|
+
Each role has a unique `id` and a non-empty ordered `candidates` array without
|
|
176
|
+
duplicates. Role IDs and candidate aliases start with a lowercase letter, use
|
|
177
|
+
only lowercase letters, digits and hyphens, and contain at most 64 characters.
|
|
178
|
+
Aliases refer to future local bindings; they are not provider/model identifiers.
|
|
179
|
+
The optional `profile` is `quick`, `balanced` or `deep`. It records a preference,
|
|
180
|
+
not a measured performance tier or a seat-count default.
|
|
181
|
+
|
|
182
|
+
Policy requires `fallback` (`none` or `approved-only`), a positive safe-integer
|
|
183
|
+
`roundLimit`, and `meteredRoutes` (`included-only` or
|
|
184
|
+
`explicit-approval-required`). Optional `distinctFamilies`, `excludeAuthorFamily`
|
|
185
|
+
and `allowReducedPanel` are booleans. An omitted policy option is unspecified,
|
|
186
|
+
not permission to bypass a host or project limit. Unknown fields and unsupported
|
|
187
|
+
versions fail an explicit panel operation before configuration writes.
|
|
188
|
+
|
|
189
|
+
The preview reports `proposed`; an explicit save reports `configured`.
|
|
190
|
+
Both report readiness as `unverified`. This feature stores preferences only.
|
|
191
|
+
It does not discover or resolve providers, verify quota or effective effort,
|
|
192
|
+
enforce policy at runtime, enable a skill, change subscriptions or invoke models.
|
|
193
|
+
Exact routes and effort choices belong to local bindings, outside this portable
|
|
194
|
+
schema; the `hr-code-review` skill's `panel-plan.mjs` resolves preferences and
|
|
195
|
+
bindings into seats without calling a model ([contract](../skills/hr-code-review/references/panel-plan.md)). To choose or change seats with the agent, ask it to set up or change your review panel; the skill's [setup procedure](../skills/hr-code-review/references/panel-setup.md) suggests seats from dated recommendations and saves nothing until you confirm. Saving preferences does not authorize spending or waive review gates.
|
|
196
|
+
|
|
197
|
+
Ordinary setup, composition and selection operations preserve existing `panel`
|
|
198
|
+
data without adopting or validating it, including older unrelated uses of that
|
|
199
|
+
key. Before replacing such data, review the full preview. Other selections and
|
|
200
|
+
custom keys are retained. Credentials and provider configuration do not belong
|
|
201
|
+
in the panel input. Input validation checks structure, not secret detection.
|
|
202
|
+
|
|
203
|
+
## Write safeguards
|
|
204
|
+
|
|
205
|
+
Saving requires the revision reported by status or preview. A stale revision
|
|
206
|
+
fails without overwriting a newer config. Cooperating CLI writers share an
|
|
207
|
+
exclusive `<config-path>.lock` file; a competing writer fails immediately.
|
|
208
|
+
The CLI writes a sibling temporary file, then replaces the config atomically.
|
|
209
|
+
Repeated requests leave an unchanged config's bytes and modification time alone.
|
|
210
|
+
A missing config is created only by explicit apply.
|
|
211
|
+
|
|
212
|
+
Manual editors do not share the lock. Avoid editing the config while a CLI
|
|
213
|
+
write runs. The CLI checks again before replacement, but cannot exclude a
|
|
214
|
+
manual write racing that final replacement. It refuses symlink config files.
|
|
215
|
+
If an interrupted writer leaves a lock, inspect its recorded process ID and
|
|
216
|
+
confirm that writer has ended before removing the lock. The CLI never removes
|
|
217
|
+
another writer's lock automatically.
|
|
218
|
+
|
|
219
|
+
## Compose and connect
|
|
220
|
+
|
|
221
|
+
Saving changes only configuration. Recompose with the existing composer or run
|
|
222
|
+
the installer again. When the composed skills changed, the installer keeps the
|
|
223
|
+
previous composed skills directory under a dated name; when they match, it keeps
|
|
224
|
+
nothing extra. Manual `--skills-out` still requires an empty or absent directory.
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
node compose.mjs --config <config-path> --out <rules-path> \
|
|
228
|
+
--skills-out <new-skills-directory>
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Connecting or copying that output to agent hosts remains a separate setup
|
|
232
|
+
step. Use `hr-house-rules-setup` for the guided workflow. Custom rule prose
|
|
233
|
+
still belongs in layer fragments; the protected completion sections stay
|
|
234
|
+
required.
|
|
235
|
+
|
|
236
|
+
## Reference output
|
|
237
|
+
|
|
238
|
+
`--out rules.md` writes selected procedure references to a sibling
|
|
239
|
+
`house-rules-references/` directory. Keep that directory beside the rules file
|
|
240
|
+
when copying it to a host. References do not depend on `skills.include` or
|
|
241
|
+
`skills.exclude`. Core Landing and Reporting always contribute their references; enabled modifiers
|
|
242
|
+
contribute theirs. Reporting is also bundled with `hr-what-next` for standalone
|
|
243
|
+
skill use. Excluding that skill does not remove the core reference. A personal replacement suppresses the resource it replaces.
|
|
244
|
+
|
|
245
|
+
The `multi-agent` modifier exports its complete agent-work procedure when enabled,
|
|
246
|
+
including review follow-ups and cleanup qualification. It remains independent
|
|
247
|
+
of selected skills; enabling reference output does not enable the modifier.
|
|
248
|
+
|
|
249
|
+
Use `--references-out <directory>` with `--out` to choose another destination;
|
|
250
|
+
links are rendered relative to the rules file. Keep both locations available.
|
|
251
|
+
Stdout and ordinary composition/configuration API calls retain full inline
|
|
252
|
+
procedures, so existing preview and copy-only workflows need no bundle.
|
|
253
|
+
|
|
254
|
+
A hash manifest permits repeat exports and updates to previously generated
|
|
255
|
+
files. Modified, missing or unrecognized files in that directory stop generation
|
|
256
|
+
before output writes. Reconcile them explicitly; generation never removes old
|
|
257
|
+
procedure files or unrelated files. Output directories must not overlap.
|
|
258
|
+
|
|
259
|
+
Core rule frontmatter may name one `reference` or a comma-separated `references`
|
|
260
|
+
list relative to `rules/core.md`. Use only one form; list paths and section headings
|
|
261
|
+
must be distinct and non-empty. Each target must be a regular file within the
|
|
262
|
+
source layer, with one level-2 heading matching the core section holding its
|
|
263
|
+
mandatory link. Default composition expands that section;
|
|
264
|
+
linked output retains its safety boundaries and reading trigger. Modifier
|
|
265
|
+
references use the same validation and output inventory.
|
|
266
|
+
|
|
267
|
+
For low-level `compose(coreText, fragments)`, use `loadFragments` for personal
|
|
268
|
+
layers so reference paths retain their source ownership. Directly parsed shipped
|
|
269
|
+
modifiers are recognized only when their label and body match the shipped file.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Upgrading skill names
|
|
2
|
+
|
|
3
|
+
Every skill shipped by house-rules uses the `hr-` prefix. For example,
|
|
4
|
+
`handoff` becomes `hr-handoff`. Rule headings, modifier names and the
|
|
5
|
+
`house-rules` command stay the same. Skills from other sources keep their names.
|
|
6
|
+
|
|
7
|
+
## Before updating
|
|
8
|
+
|
|
9
|
+
1. In `house-rules.json`, replace each shipped skill name in `skills.exclude`
|
|
10
|
+
with its `hr-` name.
|
|
11
|
+
2. For each personal override of a shipped skill, rename its directory and
|
|
12
|
+
its frontmatter `name:` to the matching `hr-` name.
|
|
13
|
+
3. Update your skill invocations, rules, links and host settings to use the
|
|
14
|
+
new names.
|
|
15
|
+
|
|
16
|
+
Composition refuses unresolved old exclusion names, ambiguous old personal
|
|
17
|
+
folders and legacy frontmatter names in prefixed overrides before writing output. The error names the replacement. Fix the
|
|
18
|
+
config or layer, then compose again. The installer keeps the previous composed
|
|
19
|
+
skills until composition succeeds.
|
|
20
|
+
|
|
21
|
+
A personal override named `hr-handoff` replaces the shipped `hr-handoff`.
|
|
22
|
+
If your generic `handoff` is a separate skill you intend to keep alongside it,
|
|
23
|
+
record that decision in your config:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"skills": {
|
|
28
|
+
"independent": ["handoff"],
|
|
29
|
+
"exclude": ["hr-read-reddit"]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`skills.independent` lets the listed personal skills keep names that match old
|
|
35
|
+
house-rules names. It does not create an alias or replace the prefixed skill.
|
|
36
|
+
`skills.exclude` uses the new names for shipped skills. An old name listed in
|
|
37
|
+
`skills.independent` refers to the independent personal skill and can be excluded
|
|
38
|
+
without excluding its prefixed counterpart. Unrelated personal
|
|
39
|
+
names need no entry in `skills.independent`.
|
|
40
|
+
|
|
41
|
+
## Connect hosts after composing
|
|
42
|
+
|
|
43
|
+
If a host reads the whole composed directory, point it at the new composed set.
|
|
44
|
+
If it has individual skill links or copied folders, replace its old house-rules
|
|
45
|
+
entries with the matching prefixed entries. Preserve unrelated skills.
|
|
46
|
+
Restart or reload the host and check that it discovers the new names.
|
|
47
|
+
|
|
48
|
+
The composer and installer do not edit host files or remove old host entries.
|
|
49
|
+
Do not keep both the old and new house-rules copies active. Historical skill
|
|
50
|
+
invocations need the new names; there are no compatibility aliases.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Example project
|
|
2
|
+
|
|
3
|
+
## Session
|
|
4
|
+
|
|
5
|
+
Before your first reply in a session, read § End of every reply and § Offers in
|
|
6
|
+
your user-level house rules in full. They apply here unchanged; this file only
|
|
7
|
+
adds to them and never removes the offer.
|
|
8
|
+
|
|
9
|
+
## Landing
|
|
10
|
+
|
|
11
|
+
This repository lands by direct push to `main` after `npm test` passes; that
|
|
12
|
+
is the landing path § Landing asks the repository to name. Never force-push
|
|
13
|
+
`main`.
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
- Install: `npm ci`
|
|
18
|
+
- Test: `npm test`
|
package/package.json
CHANGED
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bompus/house-rules",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.13.0",
|
|
4
|
+
"description": "Composable working rules and skills for AI coding agents",
|
|
5
|
+
"homepage": "https://github.com/bompus/house-rules#readme",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/bompus/house-rules.git"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"house-rules": "compose.mjs"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"compose.mjs",
|
|
16
|
+
"composition.mjs",
|
|
17
|
+
"rule-references.mjs",
|
|
18
|
+
"config.mjs",
|
|
19
|
+
"config-view.mjs",
|
|
20
|
+
"setup.mjs",
|
|
21
|
+
"rules/",
|
|
22
|
+
"skills/",
|
|
23
|
+
"!skills/*/test/",
|
|
24
|
+
"!**/__pycache__/",
|
|
25
|
+
"docs/",
|
|
26
|
+
"!docs/npm-release.md",
|
|
27
|
+
"examples/",
|
|
28
|
+
"LICENSE",
|
|
29
|
+
"THIRD_PARTY_NOTICES.md",
|
|
30
|
+
"CONTRIBUTING.md",
|
|
31
|
+
"CODE_OF_CONDUCT.md"
|
|
32
|
+
],
|
|
33
|
+
"type": "module",
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public",
|
|
36
|
+
"registry": "https://registry.npmjs.org/"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"check:package": "node scripts/check-package.mjs"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=22"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Plan reference writes before changing output; retain owned older files, never delete them.
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import {
|
|
4
|
+
existsSync,
|
|
5
|
+
lstatSync,
|
|
6
|
+
mkdirSync,
|
|
7
|
+
readFileSync,
|
|
8
|
+
readdirSync,
|
|
9
|
+
writeFileSync,
|
|
10
|
+
} from "node:fs";
|
|
11
|
+
import { dirname, join, resolve } from "node:path";
|
|
12
|
+
|
|
13
|
+
const hash = (text) => createHash("sha256").update(text).digest("hex");
|
|
14
|
+
const safeName = (name) => /^[a-z0-9][a-z0-9-]*\.md$/.test(name);
|
|
15
|
+
|
|
16
|
+
export function checkOutputPath(path, directory = false) {
|
|
17
|
+
path = resolve(path);
|
|
18
|
+
for (let current = path; ; current = dirname(current)) {
|
|
19
|
+
let stat;
|
|
20
|
+
try {
|
|
21
|
+
stat = lstatSync(current);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
if (error.code !== "ENOENT") throw error;
|
|
24
|
+
}
|
|
25
|
+
if (stat) {
|
|
26
|
+
if (
|
|
27
|
+
stat.isSymbolicLink() ||
|
|
28
|
+
(current === path && !directory ? !stat.isFile() : !stat.isDirectory())
|
|
29
|
+
)
|
|
30
|
+
throw new Error(`Unsafe output path: ${current}`);
|
|
31
|
+
}
|
|
32
|
+
if (dirname(current) === current) break;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function planReferenceOutput(directory, references) {
|
|
37
|
+
checkOutputPath(directory, true);
|
|
38
|
+
const manifestPath = join(directory, "manifest.json");
|
|
39
|
+
let files = {};
|
|
40
|
+
if (existsSync(directory) && readdirSync(directory).length) {
|
|
41
|
+
if (!existsSync(manifestPath) || !lstatSync(manifestPath).isFile())
|
|
42
|
+
throw new Error(`Unmanaged reference directory: ${directory}`);
|
|
43
|
+
const content = readFileSync(manifestPath, "utf8");
|
|
44
|
+
let manifest;
|
|
45
|
+
try {
|
|
46
|
+
manifest = JSON.parse(content);
|
|
47
|
+
} catch {
|
|
48
|
+
throw new Error(`Invalid reference manifest: ${manifestPath}; reconcile it first`);
|
|
49
|
+
}
|
|
50
|
+
if (
|
|
51
|
+
manifest?.format !== 1 ||
|
|
52
|
+
!manifest.files ||
|
|
53
|
+
typeof manifest.files !== "object" ||
|
|
54
|
+
Array.isArray(manifest.files)
|
|
55
|
+
)
|
|
56
|
+
throw new Error(`Invalid reference manifest: ${manifestPath}`);
|
|
57
|
+
files = manifest.files;
|
|
58
|
+
for (const [name, sha] of Object.entries(files)) {
|
|
59
|
+
if (!safeName(name) || typeof sha !== "string" || !/^[a-f0-9]{64}$/.test(sha))
|
|
60
|
+
throw new Error(`Invalid reference manifest: ${manifestPath}`);
|
|
61
|
+
const path = join(directory, name);
|
|
62
|
+
if (!existsSync(path) || !lstatSync(path).isFile() || hash(readFileSync(path)) !== sha)
|
|
63
|
+
throw new Error(`Modified or missing reference; reconcile it first: ${path}`);
|
|
64
|
+
}
|
|
65
|
+
for (const name of readdirSync(directory)) {
|
|
66
|
+
const path = join(directory, name);
|
|
67
|
+
if (
|
|
68
|
+
lstatSync(path).isSymbolicLink() ||
|
|
69
|
+
(name !== "manifest.json" && !Object.hasOwn(files, name))
|
|
70
|
+
)
|
|
71
|
+
throw new Error(`Unrecognized reference file; reconcile it first: ${path}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const writes = [];
|
|
75
|
+
for (const [name, text] of references) {
|
|
76
|
+
if (!safeName(name) || typeof text !== "string") throw new Error("Invalid reference output");
|
|
77
|
+
if (files[name] !== hash(text)) writes.push({ path: join(directory, name), text });
|
|
78
|
+
files[name] = hash(text);
|
|
79
|
+
}
|
|
80
|
+
const text = JSON.stringify({ format: 1, files }, null, 2) + "\n";
|
|
81
|
+
if (!existsSync(manifestPath) || readFileSync(manifestPath, "utf8") !== text)
|
|
82
|
+
writes.push({ path: manifestPath, text });
|
|
83
|
+
return writes;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function writeReferenceOutput(writes) {
|
|
87
|
+
for (const { path, text } of writes) {
|
|
88
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
89
|
+
writeFileSync(path, text);
|
|
90
|
+
}
|
|
91
|
+
}
|