@iceinvein/agent-skills 0.1.37 → 0.1.39

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 (79) hide show
  1. package/package.json +1 -1
  2. package/skills/bounded-context-auditor/SKILL.md +15 -3
  3. package/skills/bounded-context-auditor/skill.json +1 -1
  4. package/skills/codebase-architecture/SKILL.md +4 -4
  5. package/skills/codebase-architecture/skill.json +1 -1
  6. package/skills/cognitive-load-auditor/SKILL.md +11 -9
  7. package/skills/cognitive-load-auditor/skill.json +1 -1
  8. package/skills/cohesion-analyzer/SKILL.md +1 -1
  9. package/skills/cohesion-analyzer/skill.json +1 -1
  10. package/skills/composability-auditor/SKILL.md +5 -5
  11. package/skills/composability-auditor/skill.json +1 -1
  12. package/skills/contract-enforcer/SKILL.md +5 -5
  13. package/skills/contract-enforcer/skill.json +1 -1
  14. package/skills/coupling-auditor/SKILL.md +2 -2
  15. package/skills/coupling-auditor/skill.json +1 -1
  16. package/skills/cover-letter/SKILL.md +18 -20
  17. package/skills/cover-letter/skill.json +7 -2
  18. package/skills/cover-letter-audit/SKILL.md +20 -20
  19. package/skills/cover-letter-audit/skill.json +7 -2
  20. package/skills/cover-letter-persona/SKILL.md +13 -13
  21. package/skills/cover-letter-persona/skill.json +7 -2
  22. package/skills/cover-letter-rewrite/SKILL.md +18 -16
  23. package/skills/cover-letter-rewrite/skill.json +7 -2
  24. package/skills/cover-letter-write/SKILL.md +25 -20
  25. package/skills/cover-letter-write/skill.json +7 -2
  26. package/skills/cqs-auditor/SKILL.md +19 -47
  27. package/skills/cqs-auditor/skill.json +1 -1
  28. package/skills/demeter-enforcer/SKILL.md +5 -5
  29. package/skills/demeter-enforcer/skill.json +1 -1
  30. package/skills/dependency-direction-auditor/SKILL.md +1 -1
  31. package/skills/dependency-direction-auditor/skill.json +1 -1
  32. package/skills/design-review/SKILL.md +6 -2
  33. package/skills/design-review/skill.json +1 -1
  34. package/skills/error-strategist/SKILL.md +3 -3
  35. package/skills/error-strategist/skill.json +1 -1
  36. package/skills/event-design-reviewer/SKILL.md +3 -3
  37. package/skills/event-design-reviewer/skill.json +1 -1
  38. package/skills/evolution-analyzer/SKILL.md +4 -3
  39. package/skills/evolution-analyzer/skill.json +1 -1
  40. package/skills/gestalt-reviewer/SKILL.md +8 -4
  41. package/skills/gestalt-reviewer/skill.json +1 -1
  42. package/skills/idempotency-guardian/SKILL.md +6 -6
  43. package/skills/idempotency-guardian/skill.json +1 -1
  44. package/skills/improve-my-codebase/CATALOGUE-FIELDS.md +2 -2
  45. package/skills/improve-my-codebase/SKILL.md +68 -27
  46. package/skills/improve-my-codebase/skill.json +1 -1
  47. package/skills/index.json +33 -33
  48. package/skills/integration-pattern-auditor/SKILL.md +2 -2
  49. package/skills/integration-pattern-auditor/skill.json +1 -1
  50. package/skills/magpie/README.md +3 -5
  51. package/skills/magpie/SKILL.md +39 -536
  52. package/skills/magpie/package.json +1 -1
  53. package/skills/magpie/references/critic.md +58 -0
  54. package/skills/magpie/references/peer-review.md +84 -0
  55. package/skills/magpie/references/specialists.md +391 -0
  56. package/skills/magpie/scripts/__tests__/helper.test.ts +40 -0
  57. package/skills/magpie/scripts/__tests__/skill-lint.test.ts +116 -28
  58. package/skills/magpie/scripts/__tests__/status-cmd.test.ts +13 -0
  59. package/skills/magpie/scripts/helper.js +24 -13
  60. package/skills/magpie/scripts/status-cmd.ts +10 -1
  61. package/skills/magpie/skill.json +2 -1
  62. package/skills/module-secret-auditor/SKILL.md +8 -5
  63. package/skills/module-secret-auditor/skill.json +1 -1
  64. package/skills/port-adapter-auditor/SKILL.md +3 -3
  65. package/skills/port-adapter-auditor/skill.json +1 -1
  66. package/skills/rams-design-audit/SKILL.md +4 -2
  67. package/skills/rams-design-audit/skill.json +1 -1
  68. package/skills/seam-finder/SKILL.md +2 -2
  69. package/skills/seam-finder/skill.json +1 -1
  70. package/skills/simplicity-razor/SKILL.md +4 -4
  71. package/skills/simplicity-razor/skill.json +1 -1
  72. package/skills/temporal-coupling-detector/SKILL.md +2 -2
  73. package/skills/temporal-coupling-detector/skill.json +1 -1
  74. package/skills/terse/SKILL.md +12 -7
  75. package/skills/terse/skill.json +1 -1
  76. package/skills/type-driven-designer/SKILL.md +8 -8
  77. package/skills/type-driven-designer/skill.json +1 -1
  78. package/skills/unidirectional-flow-enforcer/SKILL.md +2 -2
  79. package/skills/unidirectional-flow-enforcer/skill.json +1 -1
@@ -1,15 +1,13 @@
1
1
  ---
2
2
  name: cover-letter-rewrite
3
3
  description: >
4
- Revise an existing cover letter by auditing it first, then applying targeted
5
- fixes: humanize AI-sounding prose, align claims with the resume, tighten
6
- structure, adjust tone to match an active persona, or improve job-description
7
- coverage. Preserves the applicant's voice where it's already working. Supports
8
- focused passes with --focus humanize|align|tighten|structure|tone. Produces
9
- markdown, DOCX, and PDF outputs. Use when the user says "rewrite cover letter",
10
- "improve cover letter", "humanize cover letter", "fix cover letter", "tighten
11
- cover letter", "this cover letter sounds AI", "make this less generic", "make
12
- this more specific", or shares a letter and asks for edits.
4
+ Use when the user asks to rewrite, improve, humanize, fix, or tighten an
5
+ existing cover letter ("this sounds AI", "make it less generic"), or shares
6
+ a letter asking for edits. Audit-driven targeted revision that preserves the
7
+ applicant's voice where it works; focus passes via --focus
8
+ humanize|align|tighten|structure|tone. Emits markdown, DOCX, and PDF. NOT
9
+ for writing from scratch (cover-letter-write) or score-only feedback
10
+ (cover-letter-audit).
13
11
  argument-hint: "<letter-file> [--resume <file>] [--jd <file|url|text>] [--focus humanize|align|tighten|structure|tone] [--length short|standard|long] [--out <dir>]"
14
12
  ---
15
13
 
@@ -24,11 +22,12 @@ targeting the weakest category (or the user's --focus).
24
22
  - **Rewrite**: user has a draft they like the bones of. Keep their voice,
25
23
  fix specific issues.
26
24
  - **Write**: user has resume + JD and nothing else, or the existing letter is
27
- so generic it would be easier to start fresh (audit score below 50 with
28
- multiple critical issues).
25
+ so generic it would be easier to start fresh (audit score below 60, the
26
+ "Rewrite" band in cover-letter-audit's rating table, with multiple critical
27
+ issues).
29
28
 
30
29
  If the user asks to "improve" or "fix" a letter, default to rewrite. If the
31
- letter scores below 50 with fabrication or complete topic drift, suggest a
30
+ letter scores below 60 with fabrication or complete topic drift, suggest a
32
31
  fresh `/cover-letter write` instead.
33
32
 
34
33
  ## Inputs
@@ -50,6 +49,7 @@ Flags:
50
49
  - `--out <dir>` (default `./cover-letters/`).
51
50
  - `--preserve-voice` (stricter; forbid changes outside the flagged issues).
52
51
  - `--diff` (emit a unified diff between original and rewrite alongside files).
52
+ - `--show-audit` (print the full before/after audit reports instead of the one-line score summaries).
53
53
 
54
54
  If resume or JD is missing and would be needed for the requested focus,
55
55
  either ask for it or proceed with a caveat (for example, `--focus humanize`
@@ -149,8 +149,9 @@ Actions:
149
149
  delivering results" becomes "Shipped three products to production in the
150
150
  last two years" (or similar; use real resume content).
151
151
  - Remove em-dashes; replace with period or comma or parentheses.
152
- - Add burstiness: introduce at least one short sentence (under 10 words) per
153
- paragraph, and ensure at least one long sentence (over 20 words) per letter.
152
+ - Add burstiness to the level the audit scores for: at least one short
153
+ sentence (under 10 words) AND one long sentence (over 20 words) per
154
+ paragraph, with sentence-length standard deviation >= 5.
154
155
  - Raise TTR: replace repeated nouns and verbs with synonyms the applicant
155
156
  would actually use.
156
157
  - Cut hedging and throat-clearing ("I would like to", "I believe", "it is
@@ -229,8 +230,9 @@ Actions:
229
230
  ### align focus
230
231
 
231
232
  The JD lists "experience with Kafka" as a must-have. The original letter
232
- doesn't mention it. The resume lists "migrated order service to Kafka-backed
233
- event sourcing (2M events/day)". Rewrite adds a single clause:
233
+ doesn't mention it. The resume lists, under the Shopify role, "migrated order
234
+ service to Kafka-backed event sourcing (2M events/day)". Rewrite adds a single
235
+ clause (every fact in it, including the employer, traces to the resume):
234
236
 
235
237
  **Before:**
236
238
 
@@ -1,10 +1,15 @@
1
1
  {
2
2
  "name": "cover-letter-rewrite",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Audit-driven targeted rewrite of an existing cover letter. Focus modes: humanize, align, tighten, structure, tone; preserves voice where it already works",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",
7
- "tools": ["claude", "cursor", "codex", "gemini"],
7
+ "tools": [
8
+ "claude",
9
+ "cursor",
10
+ "codex",
11
+ "gemini"
12
+ ],
8
13
  "files": {
9
14
  "prompt": "SKILL.md"
10
15
  },
@@ -1,16 +1,13 @@
1
1
  ---
2
2
  name: cover-letter-write
3
3
  description: >
4
- Generate a cover letter from a resume and a job description. Accepts resume and
5
- JD as PDF, DOCX, markdown/MDX, URL, or pasted text. Produces markdown, DOCX, and
6
- PDF outputs. Enforces human-sounding prose (varied sentence length, concrete
7
- verbs, no filler openers), aligns every claim to a resume bullet, and covers the
8
- top job-description requirements without keyword stuffing. Respects active
9
- writing persona if one is set via /cover-letter persona use. Use when the user
10
- says "write cover letter", "draft cover letter", "generate cover letter", "new
11
- cover letter", "cover letter for <role>", or shares a resume and job description
12
- together. Even if the user phrases it as "make me a cover letter" or "help me
13
- apply to X", trigger this skill.
4
+ Use when the user asks to write, draft, or generate a cover letter ("write
5
+ cover letter", "cover letter for <role>", "make me a cover letter"), or
6
+ shares a resume and job description together wanting an application letter.
7
+ Generates a letter from resume + JD (each as PDF, DOCX, markdown/MDX, URL, or
8
+ pasted text), aligned to resume evidence and human-sounding, emitting
9
+ markdown, DOCX, and PDF. NOT for scoring an existing letter
10
+ (cover-letter-audit) or revising one (cover-letter-rewrite).
14
11
  argument-hint: "--resume <file> --jd <file|url|text> [--length short|standard|long] [--out <dir>]"
15
12
  ---
16
13
 
@@ -122,7 +119,8 @@ For each gap (must-have with no resume evidence), decide:
122
119
  Check `~/.config/cover-letter/active-persona`. If a persona is active and the
123
120
  user did not override with `--tone`, load that persona JSON.
124
121
 
125
- Without a persona, use these defaults:
122
+ Without a persona, use these defaults (these mirror the "Mid / default"
123
+ values in cover-letter-persona's schema; that file is the source of truth):
126
124
 
127
125
  | Setting | Default |
128
126
  |---------|---------|
@@ -133,7 +131,7 @@ Without a persona, use these defaults:
133
131
  | Passive voice cap | 10% |
134
132
  | Readability | Flesch grade 8-10 |
135
133
 
136
- If the JD signals a clear tone (a startup posting that uses "ya'll" and
134
+ If the JD signals a clear tone (a startup posting that uses "y'all" and
137
135
  emoji wants casual; a law firm posting that uses "the Firm" and
138
136
  "heretofore" wants formal), nudge the defaults one step toward that tone
139
137
  unless a persona explicitly locks them.
@@ -187,8 +185,8 @@ Writing rules the draft must follow:
187
185
 
188
186
  Before writing files, run the audit checks inline:
189
187
 
190
- 1. Word count within target band (default 250-400)
191
- 2. No AI phrases from the list in `cover-letter-audit` (50+ phrases)
188
+ 1. Word count within the declared target band (default 250-400; `--length short|standard|long` = 180/300/420 targets — tell the audit which band applies)
189
+ 2. No AI phrases from the list in `cover-letter-audit` (50+ phrases). If cover-letter-audit is not installed alongside this skill, at minimum reject the filler openers from Writing principle 6 and generic AI verbs ("leveraged", "spearheaded", "delve", "resonated")
192
190
  3. Sentence length std dev >= 5 (burstiness proxy)
193
191
  4. Passive voice <= persona cap (default 10%)
194
192
  5. Every claim traceable to a resume bullet
@@ -201,14 +199,20 @@ revisions in one line.
201
199
 
202
200
  ### Step 7: Emit outputs
203
201
 
204
- Write markdown first. Derive DOCX and PDF from it.
202
+ Write markdown first. Derive DOCX and PDF from it. Name the files with the
203
+ suite's slug convention: `<company>-<role>-<YYYY-MM-DD>.<ext>` (lowercase,
204
+ hyphenated), in `./cover-letters/` unless `--out` overrides.
205
205
 
206
206
  ```bash
207
- # from cwd or --out dir
208
- pandoc cover-letter.md -o cover-letter.docx
209
- pandoc cover-letter.md -o cover-letter.pdf --pdf-engine=weasyprint
207
+ # from --out dir (default ./cover-letters/)
208
+ pandoc acme-platform-engineer-2026-07-18.md -o acme-platform-engineer-2026-07-18.docx
209
+ pandoc acme-platform-engineer-2026-07-18.md -o acme-platform-engineer-2026-07-18.pdf --pdf-engine=weasyprint
210
210
  ```
211
211
 
212
+ After emitting, write `~/.config/cover-letter/last-run.json` with
213
+ `{resume, jd, letter_path, persona, length_band, date}` so audit/rewrite can
214
+ resolve inputs when the user gives no paths.
215
+
212
216
  PDF engine fallback order:
213
217
 
214
218
  1. `weasyprint` (best typography out of the box)
@@ -222,8 +226,9 @@ install (`brew install weasyprint` on macOS) would unlock the PDF.
222
226
  ### Step 8: Report
223
227
 
224
228
  One terse summary: file paths, self-audit score, any acknowledged gaps. If the
225
- self-audit score is below 85, suggest `/cover-letter rewrite <file> --focus
226
- humanize` (or whichever category scored lowest).
229
+ self-audit score is below 80 (under Strong per cover-letter-audit's rating
230
+ table), suggest `/cover-letter rewrite <file> --focus humanize` (or whichever
231
+ category scored lowest).
227
232
 
228
233
  ## Handling edge cases
229
234
 
@@ -1,10 +1,15 @@
1
1
  {
2
2
  "name": "cover-letter-write",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Generates a cover letter from a resume and job description. Outputs markdown, DOCX, and PDF; enforces human prose, maps every claim to a resume bullet, and covers top JD requirements without keyword stuffing",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",
7
- "tools": ["claude", "cursor", "codex", "gemini"],
7
+ "tools": [
8
+ "claude",
9
+ "cursor",
10
+ "codex",
11
+ "gemini"
12
+ ],
8
13
  "files": {
9
14
  "prompt": "SKILL.md"
10
15
  },
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: cqs-auditor
3
- description: Use when functions both mutate state and return values, when calling a "getter" has hidden side effects, when it's unclear whether calling a function is safe to retry or cache, or when testing requires complex setup to verify both return value and state change. Trigger on "is it safe to call this twice?", "why does reading this value change the system?", or when designing read/write boundaries. NOT for stack/queue pop() where mutation+return is inherent, iterator next(), or builder methods that return this.
3
+ description: Use when functions both mutate state and return values, when calling a "getter" has hidden side effects, when it's unclear whether a call is safe to retry or cache, or when tests must verify both a return value and a state change. Trigger on "is it safe to call this twice?", "why does reading this value change the system?", or when designing read/write boundaries. NOT for stack/queue pop(), iterator next(), or builder methods returning this.
4
4
  ---
5
5
 
6
6
  # CQS Auditor
@@ -72,7 +72,7 @@ function logMetric(name: string, value: number): void {
72
72
  - Unsafe to retry (second call will have different effect)
73
73
  - Unsafe to cache (what changes between calls?)
74
74
  - Testing must verify both aspects, making tests complex
75
- - Examples: `getOrCreateUser(email)`, `popFromStack()`, `processAndReturn()`
75
+ - Examples: `getOrCreateUser(email)`, `saveAndReturnId()`, `processAndReturn()` (note: `pop()` and `next()` are the accepted exceptions, see Guard Rails)
76
76
 
77
77
  ```typescript
78
78
  // ❌ Mixed — mutation + return (violation)
@@ -101,14 +101,14 @@ Mark functions as violations if they:
101
101
 
102
102
  - **Return a value AND mutate state** — the caller can't tell if they're calling for the return or the effect
103
103
  - **Hide mutations in getters** — a function named `getValue()` shouldn't call `emit()` or `increment()` or `write to cache`
104
- - **Return error codes instead of throwing** — if the return type is carrying both data and error signal (a code smell of mixed concern)
104
+ - **Return domain data from a command** — a bare success/failure signal from a command is acceptable (see Guard Rails), but returning domain data means callers now depend on the mutation for reads
105
105
  - **Accumulate side effects scattered across the call** — side effect happens in database, side effect in cache, side effect in event bus, all in one function
106
106
 
107
107
  ### 3. Classify Violation Severity
108
108
 
109
109
  Not all violations are equally bad. Rank them:
110
110
 
111
- **Concealed query** (most dangerous)
111
+ **Concealed command** (most dangerous: a command disguised as a query)
112
112
  - Function looks like a getter (named `get*()`, `fetch*()`, `compute*()`)
113
113
  - Caller expects only a return value, no side effects
114
114
  - But the function has hidden mutations (logs, caches, increments, notifies)
@@ -116,7 +116,7 @@ Not all violations are equally bad. Rank them:
116
116
  - Example: `getNextSequenceId()` increments the database counter
117
117
 
118
118
  ```typescript
119
- // ❌ Concealed query — looks like a getter, has a side effect
119
+ // ❌ Concealed command — looks like a getter, has a side effect
120
120
  function getNextOrderId(): string {
121
121
  const id = database.incrementAndFetch("order_seq"); // ← hidden mutation
122
122
  return id;
@@ -170,20 +170,9 @@ function getUser(id: string): User {
170
170
 
171
171
  For each violation, extract it into separate query and command functions:
172
172
 
173
- #### Example 1: Concealed Query
173
+ #### Example 1: Concealed Command
174
174
 
175
- **Before:**
176
- ```typescript
177
- // ❌ Concealed query — looks safe, has hidden side effect
178
- function getNextOrderId(): string {
179
- const id = database.incrementAndFetch("order_seq");
180
- return id;
181
- }
182
-
183
- // Caller thinks it's safe to cache:
184
- const id = getNextOrderId(); // Returns "ORD001"
185
- const id2 = getNextOrderId(); // Caller expects same? Nope, now "ORD002"
186
- ```
175
+ **Before:** the `getNextOrderId()` snippet from Section 3: a getter that silently increments the sequence.
187
176
 
188
177
  **After:**
189
178
  ```typescript
@@ -204,24 +193,7 @@ const latest = getLatestOrderId(); // Just reads
204
193
 
205
194
  #### Example 2: Bundled Command-Query
206
195
 
207
- **Before:**
208
- ```typescript
209
- // ⚠️ Mixed — returns user, also creates if missing
210
- function getOrCreateUser(email: string): User {
211
- let user = database.findByEmail(email);
212
- if (!user) {
213
- user = { email, id: generateId(), createdAt: now() };
214
- database.insert(user);
215
- eventBus.emit("user.created", { email });
216
- }
217
- return user;
218
- }
219
-
220
- // Caller:
221
- const user = getOrCreateUser("alice@example.com");
222
- // Is alice new or existing? Function doesn't say.
223
- // Testing: must mock database.insert, eventBus.emit, and verify return.
224
- ```
196
+ **Before:** the `getOrCreateUser()` snippet from Section 3: find, create-if-missing, and return in one call. The caller can't tell whether the user is new or existing, and tests must mock the insert, the event emit, and verify the return.
225
197
 
226
198
  **After:**
227
199
  ```typescript
@@ -246,12 +218,12 @@ if (!user) {
246
218
 
247
219
  // Or with a single operation at a higher level:
248
220
  function ensureUserExists(email: string): { user: User; isNew: boolean } {
249
- let user = getUserByEmail(email);
250
- if (user) {
251
- return { user, isNew: false };
221
+ const existing = getUserByEmail(email);
222
+ if (existing) {
223
+ return { user: existing, isNew: false };
252
224
  }
253
- user = createUser(email);
254
- return { user, isNew: true };
225
+ createUser(email);
226
+ return { user: getUserByEmail(email)!, isNew: true };
255
227
  }
256
228
  ```
257
229
 
@@ -264,19 +236,19 @@ For each violation found:
264
236
  ```
265
237
  CQS: [function name]
266
238
  Location: [file:line]
267
- Type: [concealed query / bundled command-query / incidental side effect]
239
+ Type: [concealed command / bundled command-query / incidental side effect]
268
240
  Mutation: [what state changes]
269
241
  Return: [what it returns]
270
242
  Risk: [caching implications / retry implications / testing complexity]
271
243
  Fix: [specific split into query + command, or rename to be honest]
272
244
  ```
273
245
 
274
- Example 1: Concealed Query
246
+ Example 1: Concealed Command
275
247
 
276
248
  ```
277
249
  CQS: getNextOrderId
278
250
  Location: src/orders/service.ts:42
279
- Type: concealed query
251
+ Type: concealed command
280
252
  Mutation: database sequence "order_seq" incremented
281
253
  Return: next sequence ID (string)
282
254
  Risk: caller caches result thinking it's side-effect-free; second call gets different ID; caching breaks
@@ -292,7 +264,7 @@ CQS: getOrCreateUser
292
264
  Mutation: database insert (if user doesn't exist), eventBus.emit("user.created")
293
265
  Return: User object (existing or newly created)
294
266
  Risk: testing must verify both database state and return value; retry semantics unclear (idempotent on read, not on create)
295
- Fix: split into getUserByEmail(email): User | null (query) and createUser(email): User (command); caller composes them
267
+ Fix: split into getUserByEmail(email): User | null (query) and createUser(email): void (command); caller composes them
296
268
  ```
297
269
 
298
270
  Example 3: Incidental Side Effect
@@ -309,7 +281,7 @@ CQS: getUser
309
281
 
310
282
  ## Interaction Model
311
283
 
312
- Decision engine. When reviewing code, the agent classifies functions as queries, commands, or mixed. It prioritizes concealed queries (most dangerous), then bundled command-queries, then incidental side effects. For each violation, it recommends a specific split or honest renaming. It provides before/after examples showing how to separate the concerns. It doesn't refactor entire codebases — it focuses on public interfaces and functions that cross module boundaries.
284
+ Decision engine. When reviewing code, the agent classifies functions as queries, commands, or mixed. It prioritizes concealed commands (most dangerous), then bundled command-queries, then incidental side effects. For each violation, it recommends a specific split or honest renaming. It provides before/after examples showing how to separate the concerns. It doesn't refactor entire codebases — it focuses on public interfaces and functions that cross module boundaries.
313
285
 
314
286
  ## CQS at System Level: CQRS
315
287
 
@@ -350,7 +322,7 @@ CQRS is useful at architectural scale (multiple services, expensive infrastructu
350
322
  | Splitting but sharing mutable state | Splitting `getOrCreateUser` into `getUser` + `createUser` is good. But if both functions mutate a shared cache, you've only moved the problem. Ensure each function's mutations are isolated. |
351
323
  | Applying CQS to every private method | Focus on public boundaries. Private helpers can be more pragmatic. |
352
324
  | Treating CQRS as a prerequisite for CQS | CQRS is an architectural pattern for large systems. CQS is a function-level principle. Apply CQS first; CQRS only if your system needs it. |
353
- | Ignoring concealed queries | A function named `getBalance()` that increments a counter is a bug waiting to happen. Concealed queries are the most dangerous violation. |
325
+ | Ignoring concealed commands | A function named `getBalance()` that increments a counter is a bug waiting to happen. Concealed commands are the most dangerous violation. |
354
326
  | Returning void from commands that fail | If a command can fail, return an error code or throw an exception. Don't return `void` and hide the failure in a side effect (writing to a log that no one checks). |
355
327
 
356
328
  ## Cross-References
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cqs-auditor",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Meyer-inspired Command-Query Separation: classify functions as commands or queries, detect mixed violations, separate side effects from return values",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",
@@ -121,8 +121,8 @@ DEMETER: OrderProcessor.calculateShipping()
121
121
  Chain: order.getShippingAddress().getCountry().getTaxRate()
122
122
  Depth: 3 hops
123
123
  Location: src/orders/processor.ts:142
124
- Fix: Tell, Don't Ask — call order.getShippingTaxRate() instead; move logic to Order class
125
- Trade-off: Order class grows; OrderProcessor loses context of *why* it needs tax rate (name is important: getShippingTaxRate, not getCountryTaxRate)
124
+ Fix: Tell, Don't Ask — move the shipping calculation into Order: order.calculateShipping() reaches its own address internally, so OrderProcessor stops traversing. (Not order.getShippingTaxRate() — a wrapper getter that traverses internally is the Hidden Traversal anti-pattern, see Guard Rails.)
125
+ Trade-off: Order takes on shipping logic and grows; if shipping rules vary by carrier or channel, prefer parameter narrowing (pass shippingCountry) instead
126
126
  ```
127
127
 
128
128
  ```
@@ -140,7 +140,7 @@ Decision engine. The agent analyzes method calls in code it writes or reviews, i
140
140
 
141
141
  ## The Law of Demeter Reference
142
142
 
143
- Karl Lieberherr's formal statement of the Law of Demeter consists of five rules:
143
+ The law is commonly glossed as informal rules like these (Lieberherr's formal statement is the permitted-receiver constraint below, not this list):
144
144
 
145
145
  1. **Each unit should have only limited knowledge of other units:** Only units that are directly related to the current unit.
146
146
  2. **Each unit should only talk to its friends:** Don't talk to strangers (objects you don't know directly).
@@ -148,7 +148,7 @@ Karl Lieberherr's formal statement of the Law of Demeter consists of five rules:
148
148
  4. **Don't climb the object tree:** Don't chain method calls to navigate through intermediate objects.
149
149
  5. **The recipient of a message should not be the result of another message sent to a different object:** Avoid a.b().c(); instead, call a.getC() or ask a to do the work.
150
150
 
151
- The Law was formalized as a graph constraint: from object O, you can only call methods on objects that are:
151
+ Lieberherr's formal statement is this permitted-receiver constraint: from object O, you can only call methods on objects that are:
152
152
  - O itself
153
153
  - Formal parameters of the method
154
154
  - Instance variables of O
@@ -159,7 +159,7 @@ The Law was formalized as a graph constraint: from object O, you can only call m
159
159
 
160
160
  **Don't count dots mechanically.** Some multi-dot expressions are fine. `LocalDate.of(2024, 4, 11).atTime(10, 30)` is a fluent API designed for chaining. The law is about reducing *coupling and fragility*, not eliminating all dots.
161
161
 
162
- **Aggregates and entities are exceptions.** If Customer owns Address (they're a single aggregate), then `customer.address.street` is fine—it's internal navigation, not a violation. Demeter applies to module boundaries, not within cohesive entities.
162
+ **Aggregates and entities are exceptions.** If Customer owns Address (they're a single aggregate), then `customer.address.street` is fine—it's internal navigation, not a violation. This is a deliberate relaxation of the strict law (which permits no calls on accessor results, even within an aggregate); this skill applies Demeter to module boundaries, not within cohesive entities.
163
163
 
164
164
  **Don't wrap chains in facade methods.** Creating `order.getShippingCountry()` that internally chains `this.shippingAddress.country` doesn't solve the problem; it hides it. The fragility is still there.
165
165
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "demeter-enforcer",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Lieberherr-inspired Law of Demeter analysis: detect chain violations, parameter drilling, and hidden traversal; fix with tell-don't-ask or parameter narrowing",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",
@@ -18,7 +18,7 @@ A structural analysis framework based on Robert C. Martin's *Clean Architecture*
18
18
  - "Why do I need a database to test this business rule?"
19
19
  - "Why does changing the API response format require modifying domain entities?"
20
20
 
21
- **Not for:** Dependencies *within* a single layer (that's cohesion — see `cohesion-analyzer`). Framework-internal wiring (e.g., how Express middleware chains — that's the framework's design). Coupling *strength* between modules at the same layer (→ `coupling-auditor`).
21
+ **Not for:** Dependencies *within* a single layer, and coupling *strength* between same-layer modules (both → `coupling-auditor`; a single module doing too many unrelated things → `cohesion-analyzer`). Framework-internal wiring (e.g., how Express middleware chains — that's the framework's design). Designing the port/adapter boundary itself (→ `port-adapter-auditor`; this skill checks which way dependencies point across layers).
22
22
 
23
23
  ## The Process
24
24
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dependency-direction-auditor",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Martin-inspired dependency direction analysis: trace imports across layers, classify violations by severity, recommend inversion",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",
@@ -1,9 +1,11 @@
1
1
  ---
2
2
  name: design-review
3
- description: Use when reviewing, evaluating, or giving feedback on a design document, technical spec, architecture doc, system design, product spec, API design, or database schema — especially after AI helped write or brainstorm it. Always use this skill when the user shares a design and asks you to review it, check if it holds together, or help scope it down. Trigger on phrases like "review my design", "does this design make sense", "can you look at this spec", "not sure what to cut", "scope this down", "feels like too much", "check if this holds together", "design review", or any request to evaluate a design document. Also trigger when the user describes a design that sounds like a feature list without a unifying idea, mentions AI helped create it, or expresses uncertainty about whether the design is coherent.
3
+ description: Use when reviewing a design document, technical spec, architecture doc, API design, or database schema, especially one AI helped write. Trigger on "review my design", "does this design make sense", "scope this down", "feels like too much", "check if this holds together", or a design that reads as a feature list without a unifying idea. NOT for UI/visual review (rams-design-audit, gestalt-reviewer, cognitive-load-auditor) or an existing codebase (codebase-architecture).
4
4
  ---
5
5
 
6
- # Design Integrity Review
6
+ # Design Review
7
+
8
+ A design-integrity review.
7
9
 
8
10
  ## Overview
9
11
 
@@ -30,6 +32,8 @@ You are a thoughtful, experienced design partner. Not an adversary — but you a
30
32
 
31
33
  **IMPORTANT:** This is an interactive interview, not a checklist. Ask ONE question at a time. Listen to the answer. Follow up based on what was actually said, not what you planned to ask next.
32
34
 
35
+ **Non-interactive fallback:** if the user asks for a straight review without an interview ("just review it, don't quiz me"), or no human is in the loop, run the same phases against the document itself: answer each phase's questions from the text where possible, record the ones the document cannot answer as open risks, and emit the Synthesis. Say explicitly that the interview was skipped.
36
+
33
37
  ### Phase 1: The One-Sentence Test
34
38
 
35
39
  Start here. Always.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "design-review",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Brooks-inspired design integrity review: tests conceptual integrity, constraint exploitation, removal discipline, and scope control",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",
@@ -33,7 +33,7 @@ Before writing any error handling, classify the error using Duffy's taxonomy:
33
33
  - In production: Use process supervisors, crash recovery, and monitoring. The process restarts clean. This is safer than continuing with corrupted state.
34
34
 
35
35
  **Recoverable error** (expected operational failure)
36
- - Examples: network timeout, file not found, authentication rejected, rate limited, validation failure, external service unavailable
36
+ - Examples: network timeout, file not found, authentication rejected, rate limited, runtime validation failure of external data (precondition *design* belongs to `contract-enforcer`), external service unavailable
37
37
  - Correct response: **Surface to the caller as a typed result.** The caller decides the recovery strategy — retry, fallback, surface to user, queue for later.
38
38
  - Why: These aren't bugs — they're part of normal operation. The system should handle them explicitly, not treat them as exceptional. The caller has context for recovery that the failing function doesn't.
39
39
  - Implementation: Use result types (`Result<T, E>`), error unions, or typed exceptions — never string messages or generic error classes.
@@ -157,7 +157,7 @@ Error *classification* is technical. Error *recovery strategy* is often a produc
157
157
 
158
158
  ## The Duffy Classification (Reference)
159
159
 
160
- From Joe Duffy's Midori error model:
160
+ Adapted from Joe Duffy's Midori error model (Midori's split is two-way: bugs and fatal conditions both end in abandonment; the three-way taxonomy this skill uses separates fatal for practical triage):
161
161
 
162
162
  1. **Bugs are not recoverable at runtime.** They indicate programmer mistakes. The correct response is to fail fast, gather diagnostics, and fix the code. Trying to recover from bugs leads to undefined behavior.
163
163
 
@@ -167,7 +167,7 @@ From Joe Duffy's Midori error model:
167
167
 
168
168
  4. **The boundary between bug and recoverable depends on context.** A "file not found" error is recoverable if the user might have mistyped a path. It's a bug if the file is a configuration file that was validated at startup and should always exist.
169
169
 
170
- 5. **Error handling and normal code should use the same control flow.** Recoverable errors should flow through return values, not through exceptions. Exceptions should be reserved for bugs and fatal conditions that abort the current operation entirely.
170
+ 5. **Recoverable errors are visible in the type system; bugs are never catchable.** In Midori, recoverable errors flow through declared, typed channels (results or checked/typed exceptions the caller must acknowledge), while bugs never throw anything catchable; they trigger abandonment (fail-fast process termination). Whatever your language, keep the two channels distinct: recoverable errors in signatures, bugs to fail-fast.
171
171
 
172
172
  ## Abrahams' Exception Safety Guarantees (Reference)
173
173
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "error-strategist",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Duffy & Abrahams-inspired error handling: classify errors (bug/recoverable/fatal), assign safety guarantees, design recovery boundaries",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: event-design-reviewer
3
- description: Use when designing domain events, naming events, defining event payloads, or reviewing event-driven communication between bounded contexts or services. Trigger on "what should this event be called?", "what data should the event carry?", "should this be an event or a command?", or when events are named after implementation details instead of domain concepts. NOT for UI event handlers (onClick, onChange) or framework-level events.
3
+ description: Use when designing domain events, naming events, defining event payloads, or reviewing event-driven communication between bounded contexts. Trigger on "what should this event be called?", "what data should the event carry?", "should this be an event or a command?", or events named after implementation details. NOT for UI event handlers (onClick), framework-level events, or channel topology and delivery guarantees (integration-pattern-auditor).
4
4
  ---
5
5
 
6
6
  # Event Design Reviewer
@@ -155,7 +155,7 @@ Example:
155
155
  EVENT DESIGN: UserUpdated
156
156
  Type: event (correct — it's a fact about something that happened)
157
157
  Domain test: FAIL — "updated" is meaningless. Updated how? A domain expert would ask "what changed?"
158
- Naming: wrong — present-tense-ish, generic CRUD name, doesn't describe the domain action
158
+ Naming: wrong — past tense (good) but a generic CRUD name that doesn't describe the domain action
159
159
  Payload: thin — only carries { userId }, forcing consumers to query user service
160
160
  Envelope: missing correlationId and version field
161
161
  Smells: CRUD naming, thin payload creates temporal coupling, no schema versioning
@@ -190,7 +190,7 @@ Event naming is a domain decision. The agent enforces the principles but the hum
190
190
 
191
191
  **Vernon (2013):** Domain events are raised within the aggregate that owns the state change. The aggregate guarantees consistency; the event communicates the fact.
192
192
 
193
- **Dahan (2009):** Domain events vs. integration events. Domain events are internal to a bounded context (can carry rich domain types). Integration events cross boundaries (must use a shared, stable schema).
193
+ **Dahan:** Udi Dahan's domain-events pattern (2009) underpins the now-standard domain-event vs. integration-event split, later popularized by microservices guidance. Domain events are internal to a bounded context (can carry rich domain types). Integration events cross boundaries (must use a shared, stable schema).
194
194
 
195
195
  | Concept | Domain Event | Integration Event |
196
196
  |---------|-------------|-------------------|
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "event-design-reviewer",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Evans/Vernon/Dahan-inspired event design: domain-meaningful naming, fat payloads, schema evolution, and the domain expert test",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",
@@ -41,17 +41,17 @@ Evaluate the change against the laws most relevant to the situation:
41
41
  - Massive rewrites almost always fail because they fight the system's natural evolution rate.
42
42
  - Incremental, well-directed changes succeed because they work with the system's grain.
43
43
 
44
- **IV. Conservation of Familiarity** — The rate of effective change is limited by the team's ability to absorb novelty.
44
+ **V. Conservation of Familiarity** — The rate of effective change is limited by the team's ability to absorb novelty. (Law IV, Conservation of Organizational Stability, is skipped here: it concerns process, not individual changes — see the Complete Reference below.)
45
45
  - How much novelty does this change introduce? New patterns, new abstractions, new conventions?
46
46
  - Will the team still recognize this area of the codebase after the change?
47
47
  - Changes that exceed the team's absorption rate create unknown unknowns — the team no longer fully understands what they have.
48
48
 
49
- **V. Continuing Growth** — Functional content must continually increase to maintain user satisfaction.
49
+ **VI. Continuing Growth** — Functional content must continually increase to maintain user satisfaction.
50
50
  - Is the system's *structure* keeping pace with its *functionality*?
51
51
  - Growth without structural investment creates fragility: the system can do more but is harder to extend.
52
52
  - Structural investment without growth is gold-plating: the architecture is beautiful but doesn't serve more users.
53
53
 
54
- **VI. Declining Quality** — Unless rigorously adapted to account for environmental changes, system quality will appear to decline.
54
+ **VII. Declining Quality** — Unless rigorously adapted to account for environmental changes, system quality will appear to decline.
55
55
  - Is the environment (dependencies, platforms, security requirements, user expectations) evolving in ways this code isn't keeping up with?
56
56
  - A codebase that was excellent in 2020 may be declining in 2026 — not because it got worse, but because the world moved on.
57
57
 
@@ -61,6 +61,7 @@ Look at the area of code being changed:
61
61
 
62
62
  **Churn analysis:**
63
63
  - How often has this area been modified recently? High churn signals evolution pressure — this area is under active adaptation or struggling with accumulated debt.
64
+ - Measure it: `git log --since="6 months ago" --name-only --pretty=format: -- <path> | sort | uniq -c | sort -rn | head -20` ranks the hotspots; `git log --oneline --since="6 months ago" -- <path> | wc -l` counts commits touching the area. As a rough heuristic, a file in the repo's top decile of commit counts is high-churn.
64
65
  - Is each successive change *smaller and easier* (debt being paid down) or *larger and harder* (debt compounding)?
65
66
  - Are changes concentrated in a few files (hotspots) or spread evenly?
66
67
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evolution-analyzer",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Lehman-inspired software evolution analysis: trajectory assessment, debt visibility, and change impact on system health",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",