@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
package/config.mjs CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  splitSections,
28
28
  } from "./composition.mjs";
29
29
  import { renderConfig, renderHelp } from "./config-view.mjs";
30
+ import { changePanelPreferences } from "./skills/hr-code-review/scripts/panel-preferences.mjs";
30
31
 
31
32
  const COMMANDS = ["catalog", "status", "validate", "preview", "set"];
32
33
  const TOGGLES = ["enable-modifier", "disable-modifier", "enable-skill", "disable-skill"];
@@ -41,6 +42,10 @@ function stringList(value, key) {
41
42
  if (new Set(value).size !== value.length) throw new Error(`${key} contains duplicates`);
42
43
  }
43
44
 
45
+ export const QUESTION_PRESETS = ["default", "plain", "coded", "cards"];
46
+ export const QUESTION_MODIFIERS = ["model-default-questions", "coded-offers", "question-cards"];
47
+ const BACKLOG_VIEWS = ["backlog-visual", "backlog-outline"];
48
+
44
49
  function validateStructure(config) {
45
50
  if (!object(config)) throw new Error("configuration must be a JSON object");
46
51
  for (const key of ["modifiers", "layers"]) stringList(config[key], key);
@@ -54,12 +59,26 @@ function validateSelection(config) {
54
59
  validateStructure(config);
55
60
  const known = new Set(modifierList().map((m) => m.name));
56
61
  for (const name of config.modifiers ?? []) {
57
- if (!known.has(name)) throw new Error(`unknown modifier "${name}" (see config catalog)`);
62
+ if (!known.has(name))
63
+ throw new Error(
64
+ `unknown modifier "${name}" (see config catalog); preview its removal with config set --disable-modifier <name>, then save it with config set --disable-modifier <name> --apply --expect <revision>`,
65
+ );
58
66
  }
67
+ if (BACKLOG_VIEWS.every((name) => config.modifiers?.includes(name)))
68
+ throw new Error(
69
+ `${BACKLOG_VIEWS.join(" and ")} cannot be combined; enable one, or neither for the table alone`,
70
+ );
59
71
  if (config.modifiers?.includes("question-cards") && !config.modifiers.includes("coded-offers"))
60
72
  throw new Error(
61
73
  "question-cards requires coded-offers; use --questions cards or disable question-cards",
62
74
  );
75
+ if (
76
+ config.modifiers?.includes("model-default-questions") &&
77
+ config.modifiers.some((name) => ["coded-offers", "question-cards"].includes(name))
78
+ )
79
+ throw new Error(
80
+ "model-default-questions cannot combine with coded-offers or question-cards; use --questions",
81
+ );
63
82
  }
64
83
 
65
84
  export function readConfiguration(path) {
@@ -77,7 +96,7 @@ export function readConfiguration(path) {
77
96
  try {
78
97
  if (text !== null) config = JSON.parse(text.replace(/^\uFEFF/, ""));
79
98
  } catch {
80
- throw new Error("invalid JSON in configuration");
99
+ throw new Error(`invalid JSON in ${path}`);
81
100
  }
82
101
  validateStructure(config);
83
102
  return { path, text, revision: revisionOf(text), config };
@@ -127,11 +146,13 @@ export function selectionReport(config, path) {
127
146
  unavailable,
128
147
  layers: (config.layers ?? ["."]).map((layer) => resolve(dirname(path), layer)),
129
148
  fragments: result.fragments.map((f) => ({ source: f.source, ...f.meta })),
130
- questions: selected.has("question-cards")
131
- ? "cards"
132
- : selected.has("coded-offers")
133
- ? "coded"
134
- : "plain",
149
+ questions: selected.has("model-default-questions")
150
+ ? "default"
151
+ : selected.has("question-cards")
152
+ ? "cards"
153
+ : selected.has("coded-offers")
154
+ ? "coded"
155
+ : "plain",
135
156
  warnings: result.warnings,
136
157
  composedRules: result.rules,
137
158
  hostLoading: "unverified",
@@ -165,7 +186,7 @@ export function changeSelection(config, options, path) {
165
186
  if (
166
187
  kind === "modifier" &&
167
188
  options.questions !== undefined &&
168
- ["coded-offers", "question-cards"].includes(name)
189
+ QUESTION_MODIFIERS.includes(name)
169
190
  )
170
191
  throw new Error("use --questions or explicit question modifiers, not both");
171
192
  }
@@ -182,12 +203,15 @@ export function changeSelection(config, options, path) {
182
203
  }
183
204
  }
184
205
  if (options.questions !== undefined) {
185
- if (!["plain", "coded", "cards"].includes(options.questions))
186
- throw new Error("--questions must be plain, coded or cards");
187
- if (options.questions === "plain") modifiers.delete("coded-offers");
206
+ if (!QUESTION_PRESETS.includes(options.questions))
207
+ throw new Error("--questions must be default, plain, coded or cards");
208
+ if (options.questions === "plain" || options.questions === "default")
209
+ modifiers.delete("coded-offers");
188
210
  else modifiers.add("coded-offers");
189
211
  if (options.questions === "cards") modifiers.add("question-cards");
190
212
  else modifiers.delete("question-cards");
213
+ if (options.questions === "default") modifiers.add("model-default-questions");
214
+ else modifiers.delete("model-default-questions");
191
215
  }
192
216
  if (JSON.stringify([...modifiers]) !== JSON.stringify(next.modifiers ?? []))
193
217
  next.modifiers = [...modifiers];
@@ -284,12 +308,16 @@ export function configCommand(argv) {
284
308
  questions: { type: "string" },
285
309
  apply: { type: "boolean" },
286
310
  expect: { type: "string" },
311
+ "panel-file": { type: "string" },
312
+ "expect-panel": { type: "string" },
287
313
  ...Object.fromEntries(TOGGLES.map((key) => [key, { type: "string", multiple: true }])),
288
314
  },
289
315
  });
290
316
  if (values.help) return console.log(renderHelp());
291
317
  const changing = Boolean(
292
- values.questions !== undefined || TOGGLES.some((key) => values[key]?.length),
318
+ values.questions !== undefined ||
319
+ values["panel-file"] !== undefined ||
320
+ TOGGLES.some((key) => values[key]?.length),
293
321
  );
294
322
  if (
295
323
  (changing || values.apply || values.expect !== undefined) &&
@@ -298,10 +326,31 @@ export function configCommand(argv) {
298
326
  throw new Error("selection flags belong to config set or preview");
299
327
  if (values.apply && command !== "set") throw new Error("--apply belongs to config set");
300
328
  if (values.expect !== undefined && !values.apply) throw new Error("--expect requires --apply");
329
+ if (values["expect-panel"] !== undefined && (!values.apply || values["panel-file"] === undefined))
330
+ throw new Error("--expect-panel requires --apply and --panel-file");
301
331
  if (values.rules && values.json) throw new Error("choose --rules or --json, not both");
302
332
  if (values.rules && command !== "preview") throw new Error("--rules belongs to config preview");
333
+ if (values.rules && values["panel-file"] !== undefined)
334
+ throw new Error("--panel-file requires a change report; omit --rules");
303
335
  const snapshot = readConfiguration(configurationPath(values.config));
304
- const next = changing ? changeSelection(snapshot.config, values, snapshot.path) : snapshot.config;
336
+ let next = changing ? changeSelection(snapshot.config, values, snapshot.path) : snapshot.config;
337
+ let panelRevision;
338
+ if (values["panel-file"] !== undefined) {
339
+ const path = resolve(values["panel-file"]);
340
+ if (!lstatSync(path).isFile())
341
+ throw new Error("panel input must be a regular file, not a symlink or directory");
342
+ const text = readFileSync(path, "utf8");
343
+ panelRevision = revisionOf(text);
344
+ if (values.apply && values["expect-panel"] !== panelRevision)
345
+ throw new Error("panel input changed or --expect-panel missing; preview again");
346
+ let preferences;
347
+ try {
348
+ preferences = JSON.parse(text.replace(/^\uFEFF/, ""));
349
+ } catch {
350
+ throw new Error("invalid JSON in panel input");
351
+ }
352
+ next = changePanelPreferences(next, preferences);
353
+ }
305
354
  const report = selectionReport(next, snapshot.path);
306
355
  const changes = selectionChanges(snapshot.config, next);
307
356
  const applied = values.apply ? writeConfiguration(snapshot, next, values.expect) : null;
@@ -312,6 +361,18 @@ export function configCommand(argv) {
312
361
  revision: applied?.revision ?? snapshot.revision,
313
362
  changes,
314
363
  applied,
364
+ ...(values["panel-file"] === undefined
365
+ ? {}
366
+ : {
367
+ panel: {
368
+ state: values.apply ? "configured" : "proposed",
369
+ revision: panelRevision,
370
+ before: snapshot.config.panel ?? null,
371
+ after: next.panel,
372
+ changed: JSON.stringify(snapshot.config.panel) !== JSON.stringify(next.panel),
373
+ readiness: "unverified",
374
+ },
375
+ }),
315
376
  ...report,
316
377
  };
317
378
  if (values.rules) return process.stdout.write(report.composedRules);
Binary file
@@ -19,7 +19,7 @@ or `toggle NAME`, with several choices separated by spaces. `search TEXT`,
19
19
  Excluding a skill name excludes its personal override as well as the shipped
20
20
  copy. Exclusions without a current source remain in the configuration.
21
21
 
22
- Use `questions plain|coded|cards` for question preferences; these modifiers
22
+ Use `questions default|plain|coded|cards` for question preferences; these modifiers
23
23
  are handled together rather than as individual toggles. `next` moves from
24
24
  modifiers to skills, then review. `back` keeps the draft. Only `save` on review
25
25
  writes configuration. Before a save attempt, `cancel`, end of input or Ctrl-C
@@ -86,7 +86,7 @@ validation proves what a running agent has loaded.
86
86
 
87
87
  ```bash
88
88
  node compose.mjs config set --config <config-path> \
89
- --enable-modifier swarmail --disable-skill hr-read-reddit --questions coded
89
+ --enable-modifier shared-host-load --disable-skill hr-read-reddit --questions coded
90
90
  ```
91
91
 
92
92
  `set` previews by default. It shows the selection changes, composition summary,
@@ -102,11 +102,17 @@ not add a shipped name. Disabling adds an exclusion, retaining the include list,
102
102
  unrelated exclusions and custom settings. Configs without an include list keep
103
103
  their existing selection behavior.
104
104
 
105
- | Question preset | Enabled offer modifiers |
106
- | ------------------- | ----------------------------------- |
107
- | `--questions plain` | Neither offer modifier |
108
- | `--questions coded` | `coded-offers` |
109
- | `--questions cards` | `coded-offers` and `question-cards` |
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`.
110
116
 
111
117
  Question presets preserve other modifiers. Choose a preset or explicit offer
112
118
  modifier toggles, rather than combining both in one command. Cards still depend
@@ -125,6 +131,75 @@ contradictory flags, malformed config and composition errors stop the command
125
131
  before it writes configuration. Older skill names need the
126
132
  [skill name upgrade](skill-names.md) before composition.
127
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
+
128
203
  ## Write safeguards
129
204
 
130
205
  Saving requires the revision reported by status or preview. A stale revision
@@ -144,8 +219,9 @@ another writer's lock automatically.
144
219
  ## Compose and connect
145
220
 
146
221
  Saving changes only configuration. Recompose with the existing composer or run
147
- the installer again. The installer retains previous composed skill directories;
148
- manual `--skills-out` still requires an empty or absent directory.
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.
149
225
 
150
226
  ```bash
151
227
  node compose.mjs --config <config-path> --out <rules-path> \
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bompus/house-rules",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Composable working rules and skills for AI coding agents",
5
5
  "homepage": "https://github.com/bompus/house-rules#readme",
6
6
  "license": "MIT",
@@ -23,10 +23,12 @@
23
23
  "!skills/*/test/",
24
24
  "!**/__pycache__/",
25
25
  "docs/",
26
+ "!docs/npm-release.md",
26
27
  "examples/",
27
28
  "LICENSE",
28
29
  "THIRD_PARTY_NOTICES.md",
29
- "CONTRIBUTING.md"
30
+ "CONTRIBUTING.md",
31
+ "CODE_OF_CONDUCT.md"
30
32
  ],
31
33
  "type": "module",
32
34
  "publishConfig": {