@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.
Files changed (111) hide show
  1. package/CODE_OF_CONDUCT.md +83 -0
  2. package/README.md +91 -60
  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 +27 -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 +21 -0
  84. package/skills/hr-pr-followup/scripts/check-landing.py +204 -0
  85. package/skills/hr-pr-followup/scripts/merge-pr.sh +100 -0
  86. package/skills/hr-pr-followup/scripts/verify-landed.sh +184 -0
  87. package/skills/hr-read-reddit/SKILL.md +1 -1
  88. package/skills/hr-research-shared-links/SKILL.md +103 -0
  89. package/skills/hr-sqlite/SKILL.md +174 -0
  90. package/skills/hr-sqlite/agents/openai.yaml +2 -0
  91. package/skills/hr-sqlite/references/evidence.md +94 -0
  92. package/skills/hr-sqlite/references/tool-decisions.md +39 -0
  93. package/skills/hr-sqlite/scripts/inspect-sqlite.py +245 -0
  94. package/skills/hr-stock-ui-audit/SKILL.md +1 -1
  95. package/skills/hr-test-audit/LICENSE +21 -0
  96. package/skills/hr-test-audit/NOTICE.md +67 -0
  97. package/skills/hr-usage-report/SKILL.md +90 -0
  98. package/skills/hr-usage-report/agents/openai.yaml +2 -0
  99. package/skills/hr-usage-report/assets/example-report.json +125 -0
  100. package/skills/hr-usage-report/assets/report-template.html +377 -0
  101. package/skills/hr-usage-report/scripts/render-report.ts +86 -0
  102. package/skills/hr-usage-report/scripts/usage-by-model.ts +499 -0
  103. package/skills/hr-what-next/SKILL.md +100 -10
  104. package/skills/hr-what-next/references/reporting.md +13 -22
  105. package/skills/hr-what-next/scripts/check-open-work.mjs +711 -0
  106. package/skills/hr-writing-pr/SKILL.md +29 -14
  107. package/skills/hr-writing-pr/scripts/benefit-chart.py +200 -0
  108. package/docs/npm-release.md +0 -45
  109. package/rules/modifiers/swarmail.md +0 -12
  110. package/skills/hr-benchmarking/references/priority-findings-20261006.md +0 -115
  111. package/skills/hr-change-impact/agents/openai.yaml +0 -5
@@ -0,0 +1,46 @@
1
+ # Result format
2
+
3
+ ## Slice result (one file per worker)
4
+
5
+ ```markdown
6
+ # <slice name>
7
+
8
+ Coverage: <records read and range>; <N> candidates; done <n>, tracked <n>,
9
+ dropped <n>, forgotten <n>, unclear <n>.
10
+ Gaps: <records not read, filters applied, truncation>.
11
+
12
+ | # | What was asked, promised or offered | Source (agent, session, date, short quote) | Verdict | Evidence searched | Suggested disposition (do, ask, drop) |
13
+ | --- | ----------------------------------- | ------------------------------------------ | ------- | ----------------- | ------------------------------------- |
14
+
15
+ Patterns: <one paragraph on how items got lost>.
16
+ ```
17
+
18
+ The table holds every forgotten and unclear item, and tracked items with no
19
+ movement for more than seven days. Keep each cell short.
20
+
21
+ ## Consolidated report
22
+
23
+ ```markdown
24
+ # Forgotten-work audit: <project>, <start> to <end>
25
+
26
+ Scope: <repositories, record folders, transcript filter>.
27
+ Previous audit: <result path, or none>.
28
+
29
+ ## Coverage
30
+
31
+ | Slice | Range | Result file | Checked | Done | Tracked | Dropped | Forgotten | Unclear |
32
+ | ----- | ----- | ----------- | ------- | ---- | ------- | ------- | --------- | ------- |
33
+
34
+ Counts overlap between slices; the list below is deduplicated.
35
+
36
+ Gaps: <one line per source not covered, filter that dropped records, or truncation>.
37
+
38
+ ## Findings, ranked
39
+
40
+ | # | Item | State | Owner | Next (do, ask, drop) | Evidence |
41
+ | --- | ---- | ----- | ----- | -------------------- | -------- |
42
+
43
+ ## How items got lost
44
+
45
+ 1. <pattern>: <items it explains>.
46
+ ```
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aaron Queen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Source notices
2
+
3
+ This notice accompanies the hr-handoff bundle when copied on its own.
4
+
5
+ ## mattpocock/skills
6
+
7
+ Source: https://github.com/mattpocock/skills (compared at revision `d81f3a1`)
8
+
9
+ - `SKILL.md` and its supporting files: adapted from `skills/productivity/handoff/`.
10
+
11
+ Copyright (c) 2026 Matt Pocock
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
@@ -45,11 +45,34 @@ decisions and recommendations in priority order.
45
45
  For a handoff unrelated to quota, follow
46
46
  [reconciliation.md](references/reconciliation.md) to compare the current and
47
47
  preceding source transcripts, linked ledgers and Git inventory with this
48
- inventory. Save its receipt and run the offline checker. Report coverage gaps
48
+ inventory. Name each predecessor plan as a source, so every open or deferred
49
+ line in its ledger carries over as an item. Save its receipt and run the offline checker. Report coverage gaps
49
50
  and mechanical results separately from the reviewed claim that all items are
50
51
  addressed. Include owned unlanded PRs, dependency PRs and own commits without a
51
52
  PR; preserve their owners and landing authority.
52
53
 
54
+ When a handoff unrelated to quota moves work to another thread, also move what
55
+ the host binds to the outgoing thread:
56
+
57
+ 1. Inventory it: scheduled or recurring tasks, linked pull requests and PR
58
+ watches, and any agent-mail or messaging registration and its subscriptions.
59
+ Use the host's own list or status commands for each.
60
+ 2. Move or record each item. Where the host lets the receiving thread bind it,
61
+ the handoff names the exact call the receiver makes; some hosts let a thread
62
+ bind a task only to itself, so the outgoing thread cannot move it. Otherwise
63
+ record why it stays. Read each item back after the move; a move without a
64
+ read-back is unfinished. Retire the outgoing copy of a task only after the
65
+ receiver's read-back confirms its replacement, so the work neither runs twice nor is lost.
66
+ 3. Follow any thread-switch checklist the owning repository or the user's
67
+ guidance names, and list it in the handoff.
68
+ 4. Keep the outgoing registration until the user closes the old thread, then
69
+ retire it.
70
+ 5. Give each bound item a row in the receipt, with owner, state and next action.
71
+
72
+ When the new thread replaces this one as its successor, also follow
73
+ [successor-thread.md](references/successor-thread.md) for when a replacement is
74
+ warranted, its safe boundary, the title and the successor record.
75
+
53
76
  At a low-quota stop, save essential state first and record partial coverage
54
77
  when feasible. An unfinished receipt or failing check never delays that stop.
55
78
 
@@ -7,17 +7,31 @@ replace reading their content or reviewing context-only classifications.
7
7
  ## Collect independent source snapshots
8
8
 
9
9
  Review the current transcript and the preceding handoff's source transcript
10
- when available. Include linked plans, child ledgers, schedules, pending
11
- decisions and owned Git work. Use the host's existing export and session-search
12
- tools. Preserve source IDs and text rather than exporting only the items you
13
- already remembered.
10
+ when available. Include linked plans, child ledgers, pending decisions, owned
11
+ Git work and what the host binds to the outgoing thread (scheduled tasks, PR
12
+ watches, mail or messaging registration and subscriptions), as listed in the skill's
13
+ thread-move step. Use the host's existing export and session-search tools.
14
+ Preserve source IDs and text rather than exporting only the items you already
15
+ remembered.
14
16
 
15
17
  Normalize each source into a JSON object with a `records` array. Each record
16
18
  has a unique `id` and its original `text`. Record the original location and
17
19
  snapshot or range in the receipt's `snapshot` field. Name records by stable
18
20
  message IDs or ledger row IDs. Several records can map to the same item.
19
21
 
20
- When a record establishes a disposition, add an `outcome` with `item` and
22
+ A predecessor plan needs no conversion. Name its `plan.md` as the source
23
+ `file`; the checker reads each item line of its `## Ledger` section (`- [ ]`,
24
+ `- [~]`, `- [x]`, `- [-]`) as a record named `L<line>` (`L12`). Other text in
25
+ the section is not read, so turn any follow-up written there into an item line
26
+ before the handoff. Take a copy of the plan as it stood at the handoff,
27
+ because later edits renumber the lines. Each open or deferred line must map to
28
+ an item; a context-only reason such as "the rest, reopen only if asked" is
29
+ rejected. When one item absorbs several open or deferred lines, give the item
30
+ a `merges` field saying how one next action and one piece of completion evidence
31
+ satisfy every line. A ledger kept as a table is not read; normalize it to JSON
32
+ records instead.
33
+
34
+ When a record settles an item's state, add an `outcome` with `item` and
21
35
  `state`, plus `at` as a UTC ISO timestamp. States are `done`, `open` and
22
36
  `deferred`. Use the evidence's time, not the export time. A later request or
23
37
  current contradictory evidence that reopens completed work also sets
@@ -47,10 +61,15 @@ relative to the receipt; the checker reads only explicitly named snapshots.
47
61
  Add nonempty `items` containing extracted item IDs, or a `context` reason
48
62
  explaining why the record creates no candidate. Review user requests and
49
63
  assistant commitments and options before assigning context-only status.
50
- - Each `items` entry has `id`, `owner`, `state`, `evidence` and `next`.
64
+ - Each `items` entry has `id`, `owner`, `state`, `evidence` and `next`, plus
65
+ `merges` when it carries over more than one open or deferred plan line.
51
66
  Evidence references use `{ "source": "source-id", "record": "record-id" }`.
52
67
  Include the latest declared outcome. For deferred work, `next` gives its
53
68
  trigger; for done work, give its result and any separately tracked follow-up.
69
+ - Thread-bound state (scheduled or recurring tasks, PR watches, any mail or
70
+ messaging registration and subscriptions) is an `items` entry like any other. `next`
71
+ names the receiver's exact call to bind it and how to read it back, or why it
72
+ stays with the outgoing thread until the user closes it.
54
73
  - `git` records `scope`, `checkedAt` and `evidence`, plus explicit `ownedPrs`,
55
74
  `dependencyPrs` and `commitsWithoutPr` arrays. Empty arrays are checked
56
75
  results, not omitted fields. For no repository work, say so in `scope` and
@@ -0,0 +1,76 @@
1
+ # Replace a session with a successor thread
2
+
3
+ Follow this when a handoff moves work to a fresh thread that takes over from
4
+ the current one. It decides when replacing a session is warranted, when it is
5
+ safe and what the handoff and the successor record. It does not authorize
6
+ starting a thread. The house rules' § Repository work still requires the
7
+ user's direction, a standing spin-off preference or a rule that requires the
8
+ handoff. The host's own guidance owns the tool calls that create, rename and
9
+ rebind a thread.
10
+
11
+ ## When stale guidance warrants a new session
12
+
13
+ Replace a session because its injected guidance went stale only when the change
14
+ is session-critical:
15
+
16
+ - an always-on rule, or a safety rule
17
+ - the catalog entry (name and description) of a skill the session uses
18
+ - a subagent definition the session uses
19
+
20
+ A change to a skill body or a doc does not warrant a new session. The session
21
+ rereads it with `hr-agent-guidance-refresh` at its next boundary, and the body
22
+ is read when the skill runs. That skill notes that a reread does not prove the
23
+ injected context changed, so use the list above, not the reread, to decide
24
+ whether a replacement is needed.
25
+
26
+ ## Boundary
27
+
28
+ Never replace a session mid-turn, in the middle of an evaluation that fixed its
29
+ guidance, or while an external action is pending. An action is pending when it
30
+ has started without a recorded result. Replace it only when the session is
31
+ idle, nothing is running and the ledger is reconciled under the house rules'
32
+ § Finishing work.
33
+
34
+ ## Successor title
35
+
36
+ A successor keeps the base title and ends it with ` v<N>`. The first thread
37
+ counts as `v1` and is renamed at the handoff.
38
+
39
+ 1. If the title ends in ` v` followed by digits, the base is the title without
40
+ that ending and N is that number. Otherwise the base is the whole title and
41
+ N is 1.
42
+ 2. Rename the outgoing thread to `<base> v<N>` when its title does not already
43
+ end that way.
44
+ 3. Give the successor `<base> v<N+1>`, writing N+1 as a plain number without
45
+ leading zeros.
46
+
47
+ A title is a label for people. Never look a thread up by its title. Use the
48
+ registry row, the project and the thread id.
49
+
50
+ ## What the handoff records
51
+
52
+ - The outgoing thread's id and the successor's id, so each points to the other.
53
+ - Each open offer by the offer ID the ledger recorded for it, with its
54
+ question, options and recommendation. The house rules' § Offers records an ID
55
+ for every offer, including a text-only one that never displayed it. The
56
+ successor treats an offer as open only if the handoff lists it and the latest
57
+ ledger or source record still shows it open. An offer answered, completed,
58
+ deferred or superseded since the handoff was written authorizes nothing. A
59
+ bare code or `go` in the successor selects an offer only when one listed offer
60
+ is open. With several, it asks which one, as § Offers requires.
61
+ - The inventory and read-backs from the skill's thread-move step. The
62
+ receiving thread re-points to itself each item the host lets it bind:
63
+ registry rows, scheduled tasks, pull request watches and the messaging name
64
+ the work was known by. For an item it cannot bind, the handoff keeps the
65
+ recorded reason it stays with the outgoing thread. Where the host does not let
66
+ the successor take over the name, the handoff says which name the successor
67
+ registers and who needs to be told.
68
+
69
+ ## Successor record
70
+
71
+ - Mark the outgoing thread settled and record a pointer to the successor where
72
+ the host keeps such notes. Do this last, after the successor confirms it has
73
+ read the handoff.
74
+ - The successor starts by reading the handoff in full. It re-points each item
75
+ it can bind, with a read-back, and records every result in the receipt,
76
+ including the items that stay behind. Only then does it take new work.
@@ -53,6 +53,23 @@ function unique(entries, label) {
53
53
  return map;
54
54
  }
55
55
 
56
+ // A plan file (`.md`) is read as its `## Ledger` item lines, one record per item, named `L<line>`;
57
+ // other text in the section, wrapped continuation lines included, is not read.
58
+ // Open (`- [ ]`) and deferred (`- [~]`) lines are remembered: they must carry over as items.
59
+ function ledgerRecords(raw) {
60
+ const lines = raw.split(/\r?\n/);
61
+ const start = lines.findIndex((line) => /^#{1,6}\s+Ledger\s*$/i.test(line));
62
+ if (start < 0) return null;
63
+ const level = lines[start].match(/^#+/)[0].length;
64
+ const records = [];
65
+ for (let i = start + 1; i < lines.length; i++) {
66
+ if (new RegExp(`^#{1,${level}}\\s`).test(lines[i])) break;
67
+ const match = lines[i].match(/^\s*[-*]\s+\[([ x~-])\]\s+(.*)$/i);
68
+ if (match) records.push({ id: `L${i + 1}`, text: match[2], mark: match[1] });
69
+ }
70
+ return { records };
71
+ }
72
+
56
73
  function check(receipt, directory) {
57
74
  if (!object(receipt)) throw new Error("receipt: expected an object");
58
75
  if (receipt.version !== 1) errors.push("version: expected 1");
@@ -63,6 +80,7 @@ function check(receipt, directory) {
63
80
  const sources = unique(entries(receipt.sources, "sources"), "source");
64
81
  const items = unique(entries(receipt.items, "items"), "item");
65
82
  const records = new Map();
83
+ const openLines = new Set();
66
84
  const outcomes = new Map();
67
85
  if (sources.size === 0) gaps.push("no source snapshots supplied");
68
86
 
@@ -90,12 +108,19 @@ function check(receipt, directory) {
90
108
  continue;
91
109
  }
92
110
  let data;
93
- try {
94
- data = JSON.parse(raw);
95
- } catch {
96
- errors.push(`${label}: invalid snapshot JSON`);
97
- continue;
98
- }
111
+ if (source.file.endsWith(".md")) {
112
+ data = ledgerRecords(raw);
113
+ if (!data) {
114
+ errors.push(`${label}: no \`## Ledger\` section in the plan`);
115
+ continue;
116
+ }
117
+ } else
118
+ try {
119
+ data = JSON.parse(raw);
120
+ } catch {
121
+ errors.push(`${label}: invalid snapshot JSON`);
122
+ continue;
123
+ }
99
124
  if (!object(data)) {
100
125
  errors.push(`${label}: snapshot must be an object`);
101
126
  continue;
@@ -107,6 +132,8 @@ function check(receipt, directory) {
107
132
  for (const row of rows.values()) {
108
133
  requireText(row.text, `${label} record ${row.id}.text`);
109
134
  records.set(key(source.id, row.id), row);
135
+ if (source.file.endsWith(".md") && /[ ~]/.test(row.mark))
136
+ openLines.add(key(source.id, row.id));
110
137
  if (row.outcome !== undefined) {
111
138
  if (!object(row.outcome) || !states.includes(row.outcome.state)) {
112
139
  errors.push(`${label} record ${row.id}: invalid outcome`);
@@ -136,8 +163,23 @@ function check(receipt, directory) {
136
163
  for (const item of mapped) {
137
164
  if (!items.has(item)) errors.push(`${label}: unknown item ${item}`);
138
165
  }
166
+ if (openLines.has(ref) && text(row.context))
167
+ errors.push(
168
+ `${label}: an open or deferred ledger line needs an item, not a context-only reason`,
169
+ );
139
170
  accounting.set(ref, mapped);
140
171
  }
172
+ // A summary row ("the rest, reopen only if asked") that swallows many open lines loses them;
173
+ // an item fed by more than one open line must say in `merges` how one next action and one piece of evidence satisfy them all.
174
+ const absorbed = new Map();
175
+ for (const ref of openLines)
176
+ for (const item of new Set(accounting.get(ref) ?? []))
177
+ absorbed.set(item, (absorbed.get(item) ?? 0) + 1);
178
+ for (const [item, count] of absorbed)
179
+ if (count > 1 && !text(items.get(item)?.merges))
180
+ errors.push(
181
+ `item ${item}: absorbs ${count} open or deferred ledger lines; split it, or say in merges why they are one`,
182
+ );
141
183
  for (const ref of records.keys()) {
142
184
  if (!accounting.has(ref)) errors.push(`unaccounted record ${ref}`);
143
185
  }
@@ -49,14 +49,28 @@ For an agent running without a terminal, use the preview/apply workflow below.
49
49
  Personal skills override shipped ones. Keep independent names, layers,
50
50
  unrelated settings and exclusions.
51
51
 
52
- If the user wants Swarmail, offer its modifier. When its MCP tools are absent,
53
- point to https://github.com/bompus/swarmail and ask before installing it.
54
- If they want different question presentation, offer plain text, coded text,
55
- or coded text with cards using `--questions plain|coded|cards`. Cards still
56
- require a complete text offer. Explain that host, provider and model behavior
57
- varies; card availability and presentation are unverified until checked.
58
- Both text-only choices prohibit card tools. If personal rules still request
59
- cards, resolve that conflict before changing those rules or composing.
52
+ Ask how they want questions asked, in these words, unless the config
53
+ already records a choice they confirm: **Model default** (your model and host
54
+ ask their usual way; house-rules gives no instruction), **Text only** (plain
55
+ text options; no question tools are called), or **Clickable choices when
56
+ available** (complete text options plus a question card). Recommend nothing;
57
+ it is their preference. Map the answers to `--questions default`, `plain`
58
+ (or `coded`) and `cards`. For Text only, ask a separate yes/no: "Use short
59
+ reply codes like 1A, so one reply can answer several questions?" Yes is
60
+ `coded`, no is `plain`. Explain that host, provider and model behavior varies;
61
+ card availability and presentation are unverified until checked. Text only
62
+ prohibits card tools; Model default adds no instruction either way. If
63
+ personal rules still steer how questions are asked, resolve that conflict
64
+ before changing those rules or composing. Call modifiers "optional rules"
65
+ and the user's layer "your own rules" when talking to them.
66
+ Ask separately how they want a backlog or remaining-work report shown, unless
67
+ the config already records a choice they confirm: **Panel** (a dark panel
68
+ grouped by what each item waits on; `backlog-visual`), **Outline** (the same
69
+ groups as a Markdown outline that nothing renders; `backlog-outline`) or
70
+ **None** (the ranked table alone; neither modifier). Recommend nothing. Enable
71
+ one at most: the two cannot be combined. `config set` keeps modifiers it is
72
+ not told to change, so pass `--enable-modifier` for the chosen one and
73
+ `--disable-modifier` for the other, or for both when the answer is None.
60
74
  Done when the user selects relevant changes or keeps the current setup.
61
75
 
62
76
  3. Use `node compose.mjs config set --config <path>` with the selected
@@ -61,6 +61,10 @@ Look for a framing that deletes work before ordering it:
61
61
  their existing owning layer. A new layer needs a reason the current one
62
62
  cannot meet the goal.
63
63
 
64
+ Leave out steps added only in case something goes wrong. A fallback, retry,
65
+ backup path or extra check belongs in the plan when a named risk, constraint or
66
+ must-not-regress item calls for it; name which one.
67
+
64
68
  Count the moving parts the plan adds: new files, modules, services,
65
69
  dependencies, config keys, flags, migrations, background jobs and parallel
66
70
  paths. A smaller count that still meets the done-state is the better plan.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hr-maintainability-review
3
- description: "Review a diff or an entire codebase for maintainability and structure, preserving behavior. Use when explicitly requested for a strict, deep, harsh or thermo-nuclear maintainability review. Report-only; correctness, UI quality, test coverage and measured performance need separate assessments."
3
+ description: "Review a diff or an entire codebase for maintainability and structure, preserving behavior. Use when explicitly requested for a strict, deep or harsh maintainability review, or a whole-repository over-engineering or bloat audit. Report-only; correctness, UI quality, test coverage and measured performance need separate assessments."
4
4
  disable-model-invocation: true
5
5
  ---
6
6
 
@@ -45,8 +45,8 @@ change and what it owns now.
45
45
  an area assessed only after inspecting its implementation and relevant
46
46
  consumers; inventory or file counts alone do not establish coverage.
47
47
 
48
- Done when every inventoried area has an assessment or an explicit unreviewed
49
- disposition. Report gaps rather than claiming a complete audit from a sample.
48
+ Done when every inventoried area has an assessment or an explicit note that it was
49
+ not reviewed. Report gaps rather than claiming a complete audit from a sample.
50
50
 
51
51
  ## What to challenge
52
52
 
@@ -58,7 +58,10 @@ disposition. Report gaps rather than claiming a complete audit from a sample.
58
58
  before this change lands, and where the seam is.
59
59
  - **Pass-through layers.** Wrappers, adapters and services that forward calls
60
60
  with renamed arguments. Indirection must buy clarity, isolation or a real
61
- second implementation.
61
+ second implementation. Test a suspect module by imagining it deleted: if its
62
+ complexity would spread into every caller, it is earning its keep; propose
63
+ removal only when callers could use the underlying behavior directly without
64
+ duplicating or redistributing that complexity.
62
65
  - **Generic machinery over a simple shape.** Registries, plugin systems,
63
66
  builders or configurable pipelines where the data is a fixed list or a plain
64
67
  record.
@@ -75,6 +78,13 @@ disposition. Report gaps rather than claiming a complete audit from a sample.
75
78
  shape where partial state cannot exist.
76
79
  - **Modes and flags.** A boolean parameter or mode switch that splits one
77
80
  function into two behaviors sharing a name.
81
+ - **Leftover scaffolding.** Stubs and placeholders still on a live path, fixed
82
+ sample data where real data should flow, functions that report success
83
+ without doing their work, handlers that silently do nothing, "temporary"
84
+ branches that shipped, and comments describing a refactor long finished.
85
+ Propose deleting what no consumer needs. When a consumer depends on one, the
86
+ real behavior is missing: report it under **Other assessments** as a
87
+ correctness concern, without guessing at the contract the code never showed.
78
88
 
79
89
  ## Look for code that disappears
80
90
 
@@ -1,5 +1,5 @@
1
1
  interface:
2
2
  display_name: "HR: Maintainability review"
3
- short_description: "Strict maintainability review of a diff or codebase"
3
+ short_description: "Strict maintainability or bloat review of a diff or codebase"
4
4
  policy:
5
5
  allow_implicit_invocation: false
@@ -19,7 +19,7 @@ can reproduce. Follow the project's verification and domain safeguards.
19
19
  observation is needed, say so instead of inventing a checklist.
20
20
  4. Ground regression checks in the changed flow and supported surfaces. Use
21
21
  available impact findings and UI guidance. When a consequential risk needs
22
- investigation and `hr-change-impact` is available, use it for that risk;
22
+ investigation and `hr-code-review` is available, use it for that risk;
23
23
  otherwise name the uncertainty. A checklist does not require a full impact
24
24
  assessment.
25
25
  5. Present agent results first. When a manual observation remains, include a
@@ -19,7 +19,7 @@ the implementation instead of a separate model that can drift from it.
19
19
  2. **List the events.** Include each distinct write, message, restart or reset
20
20
  an actor can produce, with the variants that take different code paths:
21
21
  an older, equal and newer timestamp; a field left out; another identity
22
- (session, tenant, league); two events delivered in one batch. Aim for 6 to
22
+ (session, tenant, account); two events delivered in one batch. Aim for 6 to
23
23
  10 events, and merge variants that exercise the same path.
24
24
  3. **Enumerate.** Walk every sequence up to length N depth-first. At each node,
25
25
  restore the state its prefix left, apply one event through the real entry
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hr-plain-prose
3
- description: Revise text a person will read (commit messages, PR descriptions, docs, code comments, replies, the final report on a task) so it is plain, specific and free of AI tells, the habits that mark machine-written prose. Use when drafting or revising human-facing text, even a short message or reply, or when asked to "unslop" text or make it sound less generated.
3
+ description: Revise text a person will read (commit messages, PR descriptions, docs, code comments, replies, the final report on a task) so it is plain, specific and free of AI tells. Use when drafting or revising human-facing text, even a short message or reply, or when asked to "unslop" text or make it sound less generated.
4
4
  ---
5
5
 
6
6
  # Plain prose
@@ -179,9 +179,12 @@ self-reference ("As an AI..."). Start with the content.
179
179
  - Use active voice with a named actor: "The scheduler drops the job", not "The
180
180
  job is dropped".
181
181
  - Write replies as complete sentences about the actual work. Translate plan
182
- labels and internal shorthand into words the user already knows. Explain a
183
- needed technical term when first used. Keep exact identifiers where the
184
- reader needs them to find or verify something.
182
+ labels and internal shorthand into ordinary names before giving identifiers.
183
+ Keep technical terms and exact identifiers when the reader needs them to
184
+ understand, find or verify the work; explain an unfamiliar term when first used.
185
+ - Before each decision question, explain what would change and why it matters
186
+ to the user. Make clear what each answer authorizes, including the limits of
187
+ the work. Already-clear facts need no repeated explanation.
185
188
  - Cap sentence length. Keep a step the reader carries out near 20 words and a
186
189
  descriptive sentence near 25. A longer one usually holds two ideas. Vary the
187
190
  length below the cap.
@@ -22,7 +22,7 @@ Integrate fetched changes using the repository's history policy and preserve
22
22
  other owners' work. Ask when conflicting intent cannot be settled from the
23
23
  selected requirements.
24
24
 
25
- For each finding, record its disposition. Fix a demonstrated problem within
25
+ For each finding, record what was decided about it. Fix a demonstrated problem within
26
26
  scope, explain why an unsupported finding does not apply, or name the decision
27
27
  or evidence still needed. Include findings in review bodies outside inline
28
28
  threads. Reply and resolve threads within the selected authority; a thread
@@ -55,8 +55,11 @@ Name the exact revision, failed or unfinished gates and unresolved decisions.
55
55
  Clean CI alone is not evidence that every review finding was handled.
56
56
 
57
57
  When the repository or user selects these GitHub helper policies, use
58
- [the review gate and one-thread resolver](references/review-helpers.md).
59
- The gate does not replace other required checks or the caller's judgment.
58
+ [the CodeRabbit review gate and one-thread resolver](references/review-helpers.md).
59
+ Its review-status checks cover CodeRabbit only; its thread check covers any
60
+ reviewer and its review-body check any bot. It does not replace other required
61
+ checks or the caller's judgment. The same reference describes the landing helper scripts (`merge-pr.sh`,
62
+ `verify-landed.sh`, `check-landing.py`).
60
63
 
61
64
  Immediately before landing, re-read the head, base, checks, review bodies and
62
65
  unresolved threads. If the head or base changed, discard readiness and repeat
@@ -88,3 +88,24 @@ or changed head exits 2. Re-read the PR before deciding whether to retry.
88
88
 
89
89
  The helper shares GraphQL command/envelope validation with `check-pr-review.ts`.
90
90
  It does not clear that gate's review-body findings or change the landing workflow.
91
+
92
+ ## Landing helpers
93
+
94
+ Three scripts in `scripts/` implement the landing steps § Landing describes. They never
95
+ reset, switch or delete a checkout.
96
+
97
+ - `merge-pr.sh <pr> [--merge] [--remote <name>] [--idle-primary <path>]` squash-merges
98
+ (or merge-commits) an open pull request and deletes its remote head without
99
+ `gh pr merge --delete-branch`, which removes other sessions' linked worktrees. It
100
+ refuses while review feedback is open (`check-pr-review.ts`), while another open pull
101
+ request targets the head, and for a repository listed in `HR_PUSH_LANDED`
102
+ (space-separated `owner/repo`; those land by fast-forward push, which it prints). The
103
+ merge passes `--match-head-commit`. It lists worktrees still on the merged branch so
104
+ their owners clean up.
105
+ - `verify-landed.sh --commit <sha> [--ff [--idle-primary <path>]]` fetches, checks that
106
+ the default branch contains the commit, and checks the local default; `--ff`
107
+ fast-forwards a clean default checkout. `--preflight --ff` checks eligibility before
108
+ landing. After a blocked check, rerun this script, not `merge-pr.sh`.
109
+ - `check-landing.py [--path <checkout>] [--base <ref>]` reports whether a checkout's
110
+ work is in the base branch by content, so squash-merged branches count as landed, and
111
+ lists live processes whose working directory is inside the checkout (Linux only).