@olegkoval/agent-skills 1.44.0 → 1.45.1

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 (45) hide show
  1. package/adapters/claude/olko-github-pr/skills/lekker-review/SKILL.md +28 -2
  2. package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/fix-verifier.md +56 -2
  3. package/adapters/claude/olko-github-pr/skills/lekker-review/references/fix-mode.md +19 -1
  4. package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-consistency.md +76 -0
  5. package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-conventions.md +20 -20
  6. package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-implementation.md +12 -12
  7. package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-quality.md +7 -7
  8. package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-simplification.md +9 -9
  9. package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-test-quality.md +18 -18
  10. package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/phase4-comparison.md +0 -2
  11. package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/profile.md +59 -41
  12. package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/profiles/lekker-deep.md +13 -12
  13. package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/profiles/lekker-medium.md +13 -12
  14. package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/fixtures/house-rules.md +5 -5
  15. package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/fixtures/revmux-report.json +1 -1
  16. package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/revmux-engine.sh +1 -0
  17. package/package.json +1 -1
  18. package/plugins/olko-apple-kit/.claude-plugin/plugin.json +1 -1
  19. package/plugins/olko-creative/.claude-plugin/plugin.json +1 -1
  20. package/plugins/olko-garmin-kit/.claude-plugin/plugin.json +1 -1
  21. package/plugins/olko-git-tools/.claude-plugin/plugin.json +1 -1
  22. package/plugins/olko-github-pr/.claude-plugin/plugin.json +1 -1
  23. package/plugins/olko-github-pr/skills/lekker-review/SKILL.md +28 -2
  24. package/plugins/olko-github-pr/skills/lekker-review/fix-workflow.js +89 -7
  25. package/plugins/olko-github-pr/skills/lekker-review/references/agents/fix-verifier.md +56 -2
  26. package/plugins/olko-github-pr/skills/lekker-review/references/fix-mode.md +19 -1
  27. package/plugins/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-consistency.md +76 -0
  28. package/plugins/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-conventions.md +20 -20
  29. package/plugins/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-implementation.md +12 -12
  30. package/plugins/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-quality.md +7 -7
  31. package/plugins/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-simplification.md +9 -9
  32. package/plugins/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-test-quality.md +18 -18
  33. package/plugins/olko-github-pr/skills/lekker-review/references/revmux/phase4-comparison.md +0 -2
  34. package/plugins/olko-github-pr/skills/lekker-review/references/revmux/profile.md +59 -41
  35. package/plugins/olko-github-pr/skills/lekker-review/references/revmux/profiles/lekker-deep.md +13 -12
  36. package/plugins/olko-github-pr/skills/lekker-review/references/revmux/profiles/lekker-medium.md +13 -12
  37. package/plugins/olko-github-pr/skills/lekker-review/scripts/fixtures/house-rules.md +5 -5
  38. package/plugins/olko-github-pr/skills/lekker-review/scripts/fixtures/revmux-report.json +1 -1
  39. package/plugins/olko-github-pr/skills/lekker-review/scripts/revmux-engine.sh +1 -0
  40. package/plugins/olko-obsidian/.claude-plugin/plugin.json +1 -1
  41. package/plugins/olko-product/.claude-plugin/plugin.json +1 -1
  42. package/plugins/olko-reflection/.claude-plugin/plugin.json +1 -1
  43. package/plugins/olko-release/.claude-plugin/plugin.json +1 -1
  44. package/plugins/olko-skill-meta/.claude-plugin/plugin.json +1 -1
  45. package/plugins/olko-web-ops/.claude-plugin/plugin.json +1 -1
@@ -1,18 +1,18 @@
1
1
  ---
2
- description: whether tests actually catch bugs — mutation-slip analysis, mock smell, Teifi test conventions
2
+ description: whether tests actually catch bugs - mutation-slip analysis, mock smell, Teifi test conventions
3
3
  ---
4
4
  ## Lens: lekker-test-quality
5
5
 
6
6
  Review the change with a strict focus on test quality. This is NOT about
7
- coverage numbers — it is about whether the tests actually catch bugs.
7
+ coverage numbers - it is about whether the tests actually catch bugs.
8
8
 
9
- Step 1 — Inventory the tests. Read the diff at `{{SCOPE}}`. List every test
9
+ Step 1 - Inventory the tests. Read the diff at `{{SCOPE}}`. List every test
10
10
  file/spec added or modified. If no test files are in the diff, note that and
11
11
  continue to axis (f) below.
12
12
 
13
- Step 2 — For each changed test file, read the full file from `{{WORKDIR}}`.
13
+ Step 2 - For each changed test file, read the full file from `{{WORKDIR}}`.
14
14
 
15
- Step 3 — Evaluate each of these axes:
15
+ Step 3 - Evaluate each of these axes:
16
16
 
17
17
  a) Meaningful assertions vs. smoke tests
18
18
  - Does the test verify a specific outcome, or just that no exception was
@@ -60,7 +60,7 @@ e) Test isolation and reliability
60
60
  (a beforeEach that does not clean up)?
61
61
  - Are there tests that depend on execution order or global singletons?
62
62
  - Could a test make a real network/DB call in CI (flaky)? The fix is a
63
- simple injected fake at the boundary, not blanket module mocking — see
63
+ simple injected fake at the boundary, not blanket module mocking - see
64
64
  axis (g).
65
65
  - Are async tests properly awaited? (floating promises, missing `await` on
66
66
  `expect().resolves`, unhandled rejections)
@@ -75,12 +75,12 @@ f) Test-to-code ratio signal
75
75
  ```
76
76
  Report whether existing coverage closes the gap or not.
77
77
 
78
- g) Mock smell — test the behavior, not the way it's built
79
- (House standard: Notion "To mock or not to mock" —
78
+ g) Mock smell - test the behavior, not the way it's built
79
+ (House standard: Notion "To mock or not to mock" -
80
80
  https://app.notion.com/p/teifi/To-mock-or-not-to-mock-36ff8ed0f7db80f09495d174e3b86cd6)
81
81
  Flag tests coupled to *how* the code is built rather than *what* it does for
82
82
  the user. For each smell, do NOT just criticize: give the concrete no-mock
83
- refactor. The default fix is almost always the same shape — pull the logic
83
+ refactor. The default fix is almost always the same shape - pull the logic
84
84
  into a pure function (functional core) and test that directly, leaving a thin
85
85
  shell covered by a few real integration tests.
86
86
 
@@ -96,7 +96,7 @@ g) Mock smell — test the behavior, not the way it's built
96
96
  fetch-and-wire once with a real integration test. For streaming/paging
97
97
  code specifically: a shared `collect()`/reassembly helper should be a
98
98
  pure function of `AsyncGenerator<T[]> → Promise<T[]>` (or similar) fed a
99
- plain fake generator in its own test — never a mocked client — and any
99
+ plain fake generator in its own test - never a mocked client - and any
100
100
  call-site logic that combines multiple streams (parallel joins, chunked
101
101
  batching) should be its own pure function tested the same way.
102
102
  - Spying on calls / asserting call shape: `toHaveBeenCalledWith`,
@@ -110,7 +110,7 @@ g) Mock smell — test the behavior, not the way it's built
110
110
  attributes, then asserting on them): the assertions are about the mock, and
111
111
  break on a component swap or prop rename that changes nothing a user sees.
112
112
  → Pull the logic (pagination, display state) into a pure function over
113
- plain values — e.g. `paginate(items, page, pageSize)` — and assert the
113
+ plain values - e.g. `paginate(items, page, pageSize)` - and assert the
114
114
  value it returns.
115
115
  - Mocking a query hook (`useQuery` / a `use-X` hook) to hand a component
116
116
  canned data: re-tests React Query's own plumbing and couples to the hook's
@@ -135,7 +135,7 @@ h) Teifi test conventions
135
135
  Read `{{PROFILE}}` and apply its §4 (test conventions) to every test file in
136
136
  the diff: `__tests__/` placement beside the source, `.test.ts` vs
137
137
  `.test.tsx`, English-sentence test names, `describe` nesting <= 2,
138
- `afterEach(cleanup)`, `retry: false` on the test QueryClient (major — its
138
+ `afterEach(cleanup)`, `retry: false` on the test QueryClient (major - its
139
139
  absence hangs the suite on a failing query), the getByRole → getByLabelText
140
140
  → getByText → getByTestId priority, module-boundary mocking, `safeParse` for
141
141
  Zod schemas, and the typed `it.each` matrix with AC tags plus the
@@ -145,17 +145,17 @@ h) Teifi test conventions
145
145
  test passes against the real module. Quote the line, give the relative path
146
146
  as the fix.
147
147
  A comment explaining WHY a test exists (a captured past bug, a subtle
148
- contract) is sanctioned — never flag it as over-commenting.
148
+ contract) is sanctioned - never flag it as over-commenting.
149
149
 
150
150
  Report each per-line issue as:
151
- `test-file:line — <concise description of the gap or weakness>`
151
+ `test-file:line - <concise description of the gap or weakness>`
152
152
 
153
153
  For every mock-smell finding from axis (g), append the no-mock fix on the next
154
154
  line as `→ Fix: <pure-function / simple-fake refactor in one line>`. A
155
155
  criticism without a fix is incomplete.
156
156
 
157
157
  Report the mutation-slip analysis as a single paragraph under a
158
- "**Mutation-slip risk:**" heading — not as line items.
158
+ "**Mutation-slip risk:**" heading - not as line items.
159
159
 
160
160
  Rules:
161
161
  - Every per-line finding must trace to test code in the diff, OR to business
@@ -163,10 +163,10 @@ Rules:
163
163
  - Report problems only. No praise for tests that meet the bar.
164
164
  - If no test files are changed AND no existing tests cover the new code paths,
165
165
  report: "No test coverage for new code paths."
166
- - Quote the verbatim offending line(s) — never paraphrased, never reconstructed
166
+ - Quote the verbatim offending line(s) - never paraphrased, never reconstructed
167
167
  from memory. When the finding IS the absence of a test, there is no test line
168
168
  to quote: quote the untested production line(s) from the diff instead, and
169
169
  give the test that should exist as the fix. Never drop a "no coverage"
170
- finding just because nothing bad is written down — absence is the finding.
170
+ finding just because nothing bad is written down - absence is the finding.
171
171
  - A finding you cannot quote and cannot fix (outside the no-coverage case
172
- above) is a finding you have not proven — drop it instead.
172
+ above) is a finding you have not proven - drop it instead.
@@ -37,6 +37,4 @@ worktree; "merged" means two revmux findings described one mechanism.
37
37
  ## Still open
38
38
 
39
39
  - Same PRs through the default `workflow` engine for a side-by-side (Oleg-driven).
40
- - Read-only enforcement: revmux default `--tools` includes Bash; prompt-enforced
41
- only. `--tools=Read,Grep,Glob,WebFetch,WebSearch` override not yet applied.
42
40
  - Adapter: price synth + verify once revmux reports a per-model split.
@@ -12,29 +12,29 @@ and lekker-deep review profiles. It concatenates the two files lekker-review its
12
12
 
13
13
  These rules are non-negotiable. Violations are always **Critical** findings regardless of depth or other filters. Apply them when developing a feature or bugfix, not only during review.
14
14
 
15
- ### TS-1 — Type safety (TypeScript only)
15
+ ### TS-1 - Type safety (TypeScript only)
16
16
 
17
- - No type casting (`as X`, `<X>expr`) — ask them if they are Harry Potter for casting spells.
18
- - No `any` — except in test files where types are genuinely hard to express; even there, blatantly omitted types (e.g. `any[]` on a known shaped list) must be flagged.
17
+ - No type casting (`as X`, `<X>expr`) - ask them if they are Harry Potter for casting spells.
18
+ - No `any` - except in test files where types are genuinely hard to express; even there, blatantly omitted types (e.g. `any[]` on a known shaped list) must be flagged.
19
19
  - Every finding: quote the cast/`any`, explain the correct type, show the fix.
20
20
 
21
- ### TS-2 — No JavaScript files
21
+ ### TS-2 - No JavaScript files
22
22
 
23
23
  - No `.js` files may be added to any Teifi integrations repo.
24
24
  - Exception: Liquid themes (Online Store 2.0 Shopify themes) may contain `.js`.
25
25
  - If the PR adds a `.js` file to a non-theme repo, flag it as Critical: must be converted to `.ts`.
26
26
 
27
- ### GQL-1 — GraphQL NodesConnection pagination
27
+ ### GQL-1 - GraphQL NodesConnection pagination
28
28
 
29
29
  - Every query that uses a nodes connection (`nodes { ... }`) **must** include `pageInfo { hasNextPage endCursor }` alongside the nodes.
30
- - All remaining pages **must** be fetched — a single-page fetch with no loop/recursion is a bug.
30
+ - All remaining pages **must** be fetched - a single-page fetch with no loop/recursion is a bug.
31
31
  - The page size **must** be `250` (Shopify max). If any other value is used, a code comment explaining why is required; if no comment exists, flag it.
32
32
 
33
- ### PR-1 — PR title must be prefixed with Linear ticket(s)
33
+ ### PR-1 - PR title must be prefixed with Linear ticket(s)
34
34
 
35
35
  - PR title must start with `[GIC-123]` (or the relevant project prefix) in square brackets.
36
36
  - Go through the commit history: if merged PRs or commits reference Linear tickets in square brackets (`[GIC-123]`), all of them must appear comma-separated in the current PR title (e.g. `[GIC-123,GIC-124]`).
37
- - This is a **blocking** finding: display a prominent `⛔ CANNOT MERGE` warning and recommend the correct title prefix. Confidence score is not affected — this is a process rule, not a code quality signal.
37
+ - This is a **blocking** finding: display a prominent `⛔ CANNOT MERGE` warning and recommend the correct title prefix. Confidence score is not affected - this is a process rule, not a code quality signal.
38
38
 
39
39
  ### 1g. Repo placement check (Teifi multi-repo projects only)
40
40
 
@@ -49,7 +49,7 @@ belongs in *this* repo and not a sibling repo.
49
49
  | `*-integrations` (e.g. `evi-integrations`; see the GIC exception below) | Backend ERP sync: cron jobs, orchestrator, BC/Sage/Jitterbit/ROI API clients |
50
50
  | `teifi-digital` / shared libs | Cross-project utilities, shared types |
51
51
 
52
- **Note:** `gic-integrations` has an `extensions/` folder containing legacy/reference extensions (e.g. `link-account-customer`), but **new customer account extensions for GIC should target `gic-live`** per project specs. Always check the Linear/Notion ticket for explicit repo path — don't infer from existing repo contents alone.
52
+ **Note:** `gic-integrations` has an `extensions/` folder containing legacy/reference extensions (e.g. `link-account-customer`), but **new customer account extensions for GIC should target `gic-live`** per project specs. Always check the Linear/Notion ticket for explicit repo path - don't infer from existing repo contents alone.
53
53
 
54
54
  **Action:** If the diff adds a new Shopify extension and the PR targets `*-integrations`, check the Linear/Notion spec for the explicit target directory. If the spec names `*-live`, flag it as a **Critical** placement error (`## 🏠 Wrong Repo`).
55
55
 
@@ -64,12 +64,12 @@ Include: spec quote with correct path, which repo to target, and the risk (wrong
64
64
  | TS-1 | No type casts (`as X`), no `any` | Critical; test files lenient on genuine unknowns only |
65
65
  | TS-2 | No `.js` files in integrations repos | Critical; Liquid themes exempt |
66
66
  | GQL-1 | nodes connections need `pageInfo`, all pages fetched, size=250 | Critical if pageInfo/pagination missing; Important if size≠250 without comment |
67
- | PR-1 | PR title must start with `[TICKET-NNN]`; include all commit-referenced tickets | Blocking — ⛔ CANNOT MERGE warning |
67
+ | PR-1 | PR title must start with `[TICKET-NNN]`; include all commit-referenced tickets | Blocking - ⛔ CANNOT MERGE warning |
68
68
  | FLAG-1 | Reflag repos only: risky change should ship behind a feature flag | Non-blocking; `important` at most, usually `observation`. Never a `rule:` tag |
69
69
 
70
- These apply equally when you are writing a feature or bugfix — not only in review.
70
+ These apply equally when you are writing a feature or bugfix - not only in review.
71
71
 
72
- ### FLAG-1 — Ship behind a feature flag (Reflag repos only)
72
+ ### FLAG-1 - Ship behind a feature flag (Reflag repos only)
73
73
 
74
74
  Applies ONLY where a `package.json` (any depth, excluding `node_modules`) depends on
75
75
  `@reflag/node-sdk` or `@teifi-digital/reflag-client`. Elsewhere there is no flag client,
@@ -90,12 +90,30 @@ Yes → ship it. No → flag it.
90
90
 
91
91
  Deliberately NOT blocking, unlike TS-1/GQL-1/PR-1: whether something needs a flag is a
92
92
  rollout judgement, not a correctness violation, and a blocking comment on every
93
- borderline diff trains people to ignore the signal. Never invent a concrete flag key —
93
+ borderline diff trains people to ignore the signal. Never invent a concrete flag key -
94
94
  keys must be confirmed against Reflag, so say a flag is needed without naming one.
95
95
 
96
96
  Related: a diff that BOTH adds a column/table AND changes what is read or written must
97
97
  be split into expand / migrate / read-switch / contract PRs (`important`, name the split).
98
98
 
99
+ ### CONS-1 — One rule, two implementations, must agree
100
+
101
+ When a change enforces the same business rule in two places that can both run
102
+ for the same input — a client-side guard and the server-side validator behind
103
+ it, a UI filter and its query, a webhook handler and the cron that backfills the
104
+ same state — the two must make the same decision for every input class.
105
+
106
+ Build both decision tables and compare them row by row, including the
107
+ missing/undefined input, the not-applicable actor, the flag-off case and the
108
+ error path. The server-side, unbypassable layer is authoritative; the advisory
109
+ layer must match it. A client layer that is STRICTER than the server is a bug,
110
+ not extra safety: it blocks work the system allows.
111
+
112
+ Severity: critical when the divergence blocks a legitimate action or admits one
113
+ that should be blocked; major when the authoritative layer is still right and
114
+ only the message is wrong. Detail and the reporting format live in the
115
+ `lekker-consistency` lens.
116
+
99
117
  ### Stack context to inform the review:
100
118
 
101
119
  - **Backend:** TypeScript, Node.js, Express, Prisma, pgtyped, PostgreSQL
@@ -103,20 +121,20 @@ be split into expand / migrate / read-switch / contract PRs (`important`, name t
103
121
  - **Shopify:** REST Admin + GraphQL Admin, Webhooks, Shopify Functions, genql
104
122
  - **External APIs:** Business Central (OAuth2, rate-limited), Salesforce GraphQL, ROI
105
123
  - **Infra:** Docker Compose locally; environment-var–driven cron syncs via `orchestrator.ts`
106
- - **Type gen pipeline:** pgtyped (SQL→TS), genql (GraphQL→TS), json2ts (schemas→TS) —
124
+ - **Type gen pipeline:** pgtyped (SQL→TS), genql (GraphQL→TS), json2ts (schemas→TS) -
107
125
  check that generated files are regenerated when their sources change
108
126
  - **MCPs available:** Linear, Slack, Notion, Shopify Dev docs, Harvest, Sentry
109
127
 
110
128
  ### Repo taxonomy (for Step 1g placement check)
111
129
 
112
- **Per-project repo structure varies — always verify before flagging.**
130
+ **Per-project repo structure varies - always verify before flagging.**
113
131
 
114
132
  - For **EVI project**: `evi-integrations` = backend ERP sync only; `evi-live` = Shopify app (extensions, Polaris UI).
115
133
  - For **GIC project**: `gic-integrations` owns the ERP backend sync and retains
116
134
  legacy/reference Shopify extensions. New GIC customer account extensions belong
117
135
  in `gic-live`; do not treat the legacy `extensions/` folder as placement precedent.
118
136
  - For other projects (`rsl-*`, `elmt-*`, etc.): check the repo's `extensions/` folder
119
- presence before assuming a split — do not assume the `*-integrations` pattern always
137
+ presence before assuming a split - do not assume the `*-integrations` pattern always
120
138
  means backend-only.
121
139
 
122
140
  **Step 1g action**: Before flagging a placement mismatch, run:
@@ -136,7 +154,7 @@ that alone is not precedent for new GIC extensions. Flag when the repo has no
136
154
  # Teifi soft conventions (styling, naming, comments, tests, hygiene)
137
155
 
138
156
  Companion to `teifi-rules.md`. Those are the four HARD rules (TS-1, TS-2,
139
- GQL-1, PR-1) — always Critical. This file is the house style the Teifi
157
+ GQL-1, PR-1) - always Critical. This file is the house style the Teifi
140
158
  plugin skills enforce during development (`teifi-dev:code-review`,
141
159
  `rename-pass`, `comment-stripper`, `unit-test-best-practices`). A review that
142
160
  misses them lets the same nits come back from the human reviewer.
@@ -150,7 +168,7 @@ inflate a style deviation into Critical.
150
168
  ## 1. Naming matrix (source: `teifi-dev` rename-pass agent)
151
169
 
152
170
  Flag a name the diff INTRODUCES that breaks a row. Renaming is cheap in the
153
- diff, expensive later — but a rename is still a cost, so leave conforming
171
+ diff, expensive later - but a rename is still a cost, so leave conforming
154
172
  names alone.
155
173
 
156
174
  ### Values
@@ -166,7 +184,7 @@ names alone.
166
184
  | count | `Count` suffix | `lineCount` |
167
185
  | casing | camelCase values · PascalCase types/components · `CONSTANT_CASE` constants | |
168
186
 
169
- ### Verbs — one per job, chosen by cost + purity
187
+ ### Verbs - one per job, chosen by cost + purity
170
188
 
171
189
  `get` cheap/sync · `fetch` async I/O · `create` new persisted entity ·
172
190
  `build` assembles in memory (pure) · `derive` pure value from existing state ·
@@ -177,14 +195,14 @@ idempotently makes state hold.
177
195
  A `getX` that does network I/O is a finding (`fetchX`). A `createX` that
178
196
  mutates an existing row is a finding (`updateX`).
179
197
 
180
- ### Effect affixes — put the surprise in the name
198
+ ### Effect affixes - put the surprise in the name
181
199
 
182
200
  `…OrThrow` · `…OrDefault` · `upsert` · `…ForUpdate` (row lock) ·
183
201
  `…SkipLocked` · `try…` (returns result, doesn't throw) · `with…`
184
202
  (acquire→run→release) · `…Sync` · `…Cached` · `unsafe…`.
185
203
 
186
204
  A function that takes a row lock, throws on miss, or returns a cached value
187
- without saying so in its name is a finding — that surprise is exactly what the
205
+ without saying so in its name is a finding - that surprise is exactly what the
188
206
  next caller will miss.
189
207
 
190
208
  ### React & types
@@ -201,7 +219,7 @@ next caller will miss.
201
219
  `line`, `item`, `node`, `record`, `entry`, `group`, `row`, `value`, `key` are
202
220
  findings when the surrounding domain has two or more qualified variants in
203
221
  scope (arrival line vs receipt line; source node vs target node). Qualify with
204
- the domain role — variables, params, fields, type aliases, **type params**
222
+ the domain role - variables, params, fields, type aliases, **type params**
205
223
  (`TLine` → `TReceiptLine`), and the functions built on the noun.
206
224
 
207
225
  ### NEVER flag a rename at a boundary
@@ -210,7 +228,7 @@ DB table/column names (and any `Row`/`Dto` mirroring them), GraphQL / oRPC /
210
228
  OpenAPI contract fields, enum string values, route strings, wire/JSON keys.
211
229
  Something outside the diff reads them. The app-layer alias may be renamed
212
230
  (`createdAt @map("created_at")`); the boundary name may not. A "rename this
213
- column" finding is a false positive — say the boundary name is bad and leave
231
+ column" finding is a false positive - say the boundary name is bad and leave
214
232
  it to a human if it matters.
215
233
 
216
234
  ---
@@ -220,25 +238,25 @@ it to a human if it matters.
220
238
  **Default: a comment should not exist.** It earns its place only by saying
221
239
  something the code *cannot*, and then in as few words as possible. Flag each
222
240
  offending comment the diff ADDED as its own `idiomatic` finding with the
223
- deletion as the `fix` — never a vague "too many comments". Pre-existing
241
+ deletion as the `fix` - never a vague "too many comments". Pre-existing
224
242
  comments are out of scope.
225
243
 
226
244
  Flag a comment that:
227
245
 
228
246
  - restates the next line (`// increment counter` over `counter += 1`);
229
247
  - narrates a step or captions a block ("first we fetch, then we map…");
230
- - **narrates a whole function or type** — JSDoc restating a well-named
248
+ - **narrates a whole function or type** - JSDoc restating a well-named
231
249
  signature, its params, or its return shape. A doc comment earns its place
232
250
  only for a non-obvious *contract*;
233
251
  - explains obvious syntax or a well-known API;
234
252
  - repeats a rationale stated elsewhere in the diff (keep ONE canonical place);
235
- - is changelog/AI noise — ticket IDs (`EVI-123`), person names, multi-paragraph
253
+ - is changelog/AI noise - ticket IDs (`EVI-123`), person names, multi-paragraph
236
254
  "why we chose X" essays. A single `@see EVI-123` JSDoc tag is fine;
237
- - **references what the reader cannot see** — a removed line or a prior
255
+ - **references what the reader cannot see** - a removed line or a prior
238
256
  approach ("no longer using the old Y"). Source shows what the code *is*;
239
- - **documents invisible coupling** — "ordered this way because some other code
257
+ - **documents invisible coupling** - "ordered this way because some other code
240
258
  does X". The fix is clearer structure, not a comment enshrining it;
241
- - **says what a name or type could say** — then the code should carry it (this
259
+ - **says what a name or type could say** - then the code should carry it (this
242
260
  is a naming finding per §1, not a comment to keep).
243
261
 
244
262
  KEEP (do not flag): an external-system quirk, an ordering/concurrency
@@ -251,7 +269,7 @@ gotcha, is noise. Code is type-checked; prose is not.
251
269
 
252
270
  ---
253
271
 
254
- ## 3. Hygiene & debug artifacts — severity is fixed, do not soften
272
+ ## 3. Hygiene & debug artifacts - severity is fixed, do not soften
255
273
 
256
274
  Scan `+` lines only (added by this diff; pre-existing occurrences are out of
257
275
  scope).
@@ -260,7 +278,7 @@ scope).
260
278
  |---|---|
261
279
  | `console.log(` / `console.debug(` added to non-CLI production code | important |
262
280
  | `debugger;` | critical |
263
- | `.only` on a test (`it.only`, `describe.only`, `fit(`, `fdescribe(`) — silently skips the rest of the suite | critical |
281
+ | `.only` on a test (`it.only`, `describe.only`, `fit(`, `fdescribe(`) - silently skips the rest of the suite | critical |
264
282
  | new `TODO:` / `FIXME:` / `HACK:` / `XXX:` with no ticket reference | idiomatic |
265
283
  | commented-out code block > 3 lines | idiomatic |
266
284
  | hardcoded URL / endpoint that belongs in an env var | important |
@@ -268,7 +286,7 @@ scope).
268
286
  | unreachable code after `return`/`throw` | important |
269
287
 
270
288
  `console.error`/`console.warn` on a real error path is not a finding unless the
271
- repo has a logger idiom — then cite it.
289
+ repo has a logger idiom - then cite it.
272
290
 
273
291
  ---
274
292
 
@@ -287,13 +305,13 @@ does. Each is an `idiomatic` finding with the corrected code as the `fix`.
287
305
  - **`afterEach(cleanup)`** in every RTL test file.
288
306
  - **`new QueryClient({ defaultOptions: { queries: { retry: false } } })`** in
289
307
  every hook/component test wrapper. Missing `retry: false` silently hangs the
290
- test on a failing query — flag it as `important`, not idiomatic.
308
+ test on a failing query - flag it as `important`, not idiomatic.
291
309
  - **Query priority:** `getByRole` → `getByLabelText` → `getByText` →
292
310
  `getByTestId` (last resort only). A `getByTestId` where a role query works is
293
311
  a finding.
294
312
  - **Mock paths are RELATIVE, never the `@lib/common` alias.** The alias
295
313
  resolves only from `web/`; inside `common/` it is silently ignored and the
296
- mock has no effect — the test then passes against the real module. Flag any
314
+ mock has no effect - the test then passes against the real module. Flag any
297
315
  `vi.mock('@lib/common/…')` inside `common/` as `important`.
298
316
  - **Mock at the module boundary,** not `vi.spyOn(mod, '_internal')`.
299
317
  - **Zod schemas:** test via `safeParse` and assert `result.success`, not
@@ -304,28 +322,28 @@ does. Each is an `idiomatic` finding with the corrected code as the `fix`.
304
322
  (`expect(matrix).toHaveLength(N * M * K)`). A hand-picked subset of a
305
323
  combinatorial space is a coverage-gap finding.
306
324
  - **Comment the non-obvious scenario:** a test capturing a past bug explains
307
- *why* (this is a sanctioned comment — never flag it under §2).
325
+ *why* (this is a sanctioned comment - never flag it under §2).
308
326
 
309
327
  ---
310
328
 
311
329
  ## 5. Commit & PR hygiene
312
330
 
313
- Beyond PR-1 (hard rule). All `idiomatic` — a squash fixes them and they never
331
+ Beyond PR-1 (hard rule). All `idiomatic` - a squash fixes them and they never
314
332
  block.
315
333
 
316
334
  - Conventional commits: `<type>(<scope>): <description>` with type in
317
335
  `feat|fix|refactor|test|docs|chore|style|perf|build|ci`; description
318
336
  lowercase, imperative, no trailing period.
319
- - Vague subjects (`fix`, `update`, `wip`, `changes`, `stuff`) — flag, recommend
337
+ - Vague subjects (`fix`, `update`, `wip`, `changes`, `stuff`) - flag, recommend
320
338
  a rewrite.
321
- - Many WIP commits — recommend a squash before merge, in one line, once.
339
+ - Many WIP commits - recommend a squash before merge, in one line, once.
322
340
  - Never mention Claude Code / the assistant in commit or PR text; a
323
341
  `Co-Authored-By: Claude` trailer or "Generated with Claude Code" footer in
324
342
  the commit log is a finding.
325
343
 
326
344
  ---
327
345
 
328
- ## 6. Generated code — check the source, not the artifact
346
+ ## 6. Generated code - check the source, not the artifact
329
347
 
330
348
  The Teifi type-gen pipeline means several files must move together. When a
331
349
  source changes and its generated artifact does not (or vice-versa), that is an
@@ -338,10 +356,10 @@ source changes and its generated artifact does not (or vice-versa), that is an
338
356
  | `schemas/*.json` | `schemas/generated/` (json2ts) |
339
357
  | `prisma/schema.prisma` | a migration in `prisma/migrations/` + Prisma client |
340
358
 
341
- Never review the *content* of a generated file as if it were hand-written — no
359
+ Never review the *content* of a generated file as if it were hand-written - no
342
360
  naming, comment, or complexity findings inside `generated/`. Review the source.
343
361
 
344
362
  Related hard convention (project CLAUDE.md): Shopify Admin API calls go through
345
- the genql client (`gql.<file>.<query>.run(graphql, vars)`) — a hand-rolled
363
+ the genql client (`gql.<file>.<query>.run(graphql, vars)`) - a hand-rolled
346
364
  `fetch` to `/admin/api/…/graphql.json` is an `important` finding even for a
347
365
  one-off probe.
@@ -1,16 +1,17 @@
1
1
  ---
2
- description: Teifi deep review — lekker-medium plus revmux's own bugs+impl second opinion, claude-only
2
+ description: Teifi deep review: lekker-medium (incl. cross-layer consistency) plus revmux's own bugs+impl second opinion, claude-only
3
3
  model: claude/sonnet:medium
4
4
  agents:
5
5
  - {name: quality+impl, lenses: [lekker-quality, lekker-implementation], color: cyan}
6
6
  - {name: simpl+conventions, lenses: [lekker-simplification, lekker-conventions], color: magenta}
7
7
  - {name: tests, lenses: [lekker-test-quality, tests], color: green}
8
+ - {name: consistency, lenses: [lekker-consistency], color: white}
8
9
  - {name: adversarial, lenses: [adversarial], model: claude/sonnet:high, color: yellow}
9
10
  - {name: bugs+impl, lenses: [bugs, impl], color: blue}
10
11
  stages: {synthesis: claude/opus:medium, verify: claude/sonnet:high}
11
12
  ---
12
13
  You are one reviewer on a panel. Other reviewers are working the same change in parallel with
13
- different lenses. You never see their findings and must not guess at them — report what your own
14
+ different lenses. You never see their findings and must not guess at them; report what your own
14
15
  lenses find.
15
16
 
16
17
  This review is **read-only**. You may read files and run read-only commands such as `git diff`,
@@ -22,15 +23,15 @@ Do not run tests, builds or the linter - all of that was done before the review
22
23
 
23
24
  Every item below is a **path**, not the text it names. Read the file or directory before you start.
24
25
 
25
- - `{{SCOPE}}` — what is under review and the command that produces the diff. Read this first and run
26
+ - `{{SCOPE}}`: what is under review and the command that produces the diff. Read this first and run
26
27
  that command yourself.
27
- - `{{GOAL}}` — what the change is trying to achieve.
28
- - `{{PROFILE}}` — Teifi's own rules and conventions. Where they disagree with your general taste,
28
+ - `{{GOAL}}`: what the change is trying to achieve.
29
+ - `{{PROFILE}}`: Teifi's own rules and conventions. Where they disagree with your general taste,
29
30
  they win. This is also where the hard-rule text (TS-1, TS-2, GQL-1, PR-1) and the Teifi
30
31
  conventions (naming matrix, comment policy, hygiene severities, test conventions) live in full.
31
- - `{{CONTEXT}}` — a directory of supporting material: ticket text, design notes, spec excerpts, CI
32
+ - `{{CONTEXT}}`: a directory of supporting material: ticket text, design notes, spec excerpts, CI
32
33
  status, Sentry signals, existing review comments.
33
- - `{{WORKDIR}}` — run every command from here.
34
+ - `{{WORKDIR}}`: run every command from here.
34
35
 
35
36
  Any of these may read `none provided`. That is not an error and not something to work around: the
36
37
  caller supplied nothing for it, so calibrate severity generically to that extent rather than
@@ -41,18 +42,18 @@ inventing the missing context.
41
42
  No nitpicking. Critical and major findings are reserved for things that could cause bugs, outages,
42
43
  data loss, security incidents, or real performance problems at scale.
43
44
 
44
- - **critical** — a bug, an outage, data loss, a security hole, or a real performance problem at scale.
45
- - **major** — wrong behavior, or a broken contract a caller executes against.
46
- - **minor** — a real, contained defect.
45
+ - **critical**: a bug, an outage, data loss, a security hole, or a real performance problem at scale.
46
+ - **major**: wrong behavior, or a broken contract a caller executes against.
47
+ - **minor**: a real, contained defect.
47
48
 
48
49
  Style preference and taste alone are never a finding. Anything you cannot place on that bar is not
49
- a finding — leave it out.
50
+ a finding; leave it out.
50
51
 
51
52
  ## Hard-rule findings are policy, not a runtime question
52
53
 
53
54
  Findings titled `[TS-1]`, `[TS-2]`, `[GQL-1]`, or `[PR-1]` are Teifi's own policy violations,
54
55
  defined in full in `{{PROFILE}}`. Confirm one when the quoted code shows the pattern the rule
55
- names — a cast, an `any`, a `.js` file outside a theme repo, a missing `pageInfo`/pagination, a PR
56
+ names: a cast, an `any`, a `.js` file outside a theme repo, a missing `pageInfo`/pagination, a PR
56
57
  title missing its ticket prefix. Never rate a hard-rule finding by its runtime impact and never mark
57
58
  it immaterial for lack of one: the rule itself is the standard, and violating it is always critical,
58
59
  independent of whether it happens to fail at runtime today.
@@ -1,15 +1,16 @@
1
1
  ---
2
- description: Teifi medium-depth review — four claude agents, adversarial second pass, claude-only
2
+ description: Teifi medium-depth review: five claude agents incl. cross-layer consistency, adversarial second pass, claude-only
3
3
  model: claude/sonnet:medium
4
4
  agents:
5
5
  - {name: quality+impl, lenses: [lekker-quality, lekker-implementation], color: cyan}
6
6
  - {name: simpl+conventions, lenses: [lekker-simplification, lekker-conventions], color: magenta}
7
7
  - {name: tests, lenses: [lekker-test-quality, tests], color: green}
8
+ - {name: consistency, lenses: [lekker-consistency], color: white}
8
9
  - {name: adversarial, lenses: [adversarial], model: claude/sonnet:high, color: yellow}
9
10
  stages: {synthesis: claude/sonnet:medium, verify: claude/sonnet:medium}
10
11
  ---
11
12
  You are one reviewer on a panel. Other reviewers are working the same change in parallel with
12
- different lenses. You never see their findings and must not guess at them — report what your own
13
+ different lenses. You never see their findings and must not guess at them; report what your own
13
14
  lenses find.
14
15
 
15
16
  This review is **read-only**. You may read files and run read-only commands such as `git diff`,
@@ -21,15 +22,15 @@ Do not run tests, builds or the linter - all of that was done before the review
21
22
 
22
23
  Every item below is a **path**, not the text it names. Read the file or directory before you start.
23
24
 
24
- - `{{SCOPE}}` — what is under review and the command that produces the diff. Read this first and run
25
+ - `{{SCOPE}}`: what is under review and the command that produces the diff. Read this first and run
25
26
  that command yourself.
26
- - `{{GOAL}}` — what the change is trying to achieve.
27
- - `{{PROFILE}}` — Teifi's own rules and conventions. Where they disagree with your general taste,
27
+ - `{{GOAL}}`: what the change is trying to achieve.
28
+ - `{{PROFILE}}`: Teifi's own rules and conventions. Where they disagree with your general taste,
28
29
  they win. This is also where the hard-rule text (TS-1, TS-2, GQL-1, PR-1) and the Teifi
29
30
  conventions (naming matrix, comment policy, hygiene severities, test conventions) live in full.
30
- - `{{CONTEXT}}` — a directory of supporting material: ticket text, design notes, spec excerpts, CI
31
+ - `{{CONTEXT}}`: a directory of supporting material: ticket text, design notes, spec excerpts, CI
31
32
  status, Sentry signals, existing review comments.
32
- - `{{WORKDIR}}` — run every command from here.
33
+ - `{{WORKDIR}}`: run every command from here.
33
34
 
34
35
  Any of these may read `none provided`. That is not an error and not something to work around: the
35
36
  caller supplied nothing for it, so calibrate severity generically to that extent rather than
@@ -40,18 +41,18 @@ inventing the missing context.
40
41
  No nitpicking. Critical and major findings are reserved for things that could cause bugs, outages,
41
42
  data loss, security incidents, or real performance problems at scale.
42
43
 
43
- - **critical** — a bug, an outage, data loss, a security hole, or a real performance problem at scale.
44
- - **major** — wrong behavior, or a broken contract a caller executes against.
45
- - **minor** — a real, contained defect.
44
+ - **critical**: a bug, an outage, data loss, a security hole, or a real performance problem at scale.
45
+ - **major**: wrong behavior, or a broken contract a caller executes against.
46
+ - **minor**: a real, contained defect.
46
47
 
47
48
  Style preference and taste alone are never a finding. Anything you cannot place on that bar is not
48
- a finding — leave it out.
49
+ a finding; leave it out.
49
50
 
50
51
  ## Hard-rule findings are policy, not a runtime question
51
52
 
52
53
  Findings titled `[TS-1]`, `[TS-2]`, `[GQL-1]`, or `[PR-1]` are Teifi's own policy violations,
53
54
  defined in full in `{{PROFILE}}`. Confirm one when the quoted code shows the pattern the rule
54
- names — a cast, an `any`, a `.js` file outside a theme repo, a missing `pageInfo`/pagination, a PR
55
+ names: a cast, an `any`, a `.js` file outside a theme repo, a missing `pageInfo`/pagination, a PR
55
56
  title missing its ticket prefix. Never rate a hard-rule finding by its runtime impact and never mark
56
57
  it immaterial for lack of one: the rule itself is the standard, and violating it is always critical,
57
58
  independent of whether it happens to fail at runtime today.
@@ -1,11 +1,11 @@
1
1
  # Fixture house rules
2
2
 
3
- ### TS-1 — Type safety
3
+ ### TS-1 - Type safety
4
4
 
5
- ### TS-2 — No JavaScript files
5
+ ### TS-2 - No JavaScript files
6
6
 
7
- ### GQL-1 — Complete pagination
7
+ ### GQL-1 - Complete pagination
8
8
 
9
- ### PR-1 — Ticket-prefixed titles
9
+ ### PR-1 - Ticket-prefixed titles
10
10
 
11
- ### SEC-7 — Never log session tokens
11
+ ### SEC-7 - Never log session tokens
@@ -11,7 +11,7 @@
11
11
  "body": "Two concurrent writers can both pass the guard and insert a fulfillment row.",
12
12
  "fix": "Take a row lock on the order before the check-then-insert.",
13
13
  "sources": ["quality+impl"],
14
- "lenses": ["lekker-quality"],
14
+ "lenses": ["lekker-quality", "lekker-implementation"],
15
15
  "verdict": "confirmed"
16
16
  },
17
17
  {
@@ -143,6 +143,7 @@ REVMUX_OUT="$OUT"
143
143
  set +e
144
144
  revmux --task "$TASK" --run "$RUN" --profile "$PROFILE_NAME" \
145
145
  --workdir "$WORKDIR" --tasks-dir "$TASKS_DIR" --config-dir "$CONFIG_DIR" \
146
+ --tools=Read,Grep,Glob,WebFetch,WebSearch \
146
147
  --no-tui > "$REVMUX_OUT"
147
148
  CODE=$?
148
149
  set -e
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-obsidian",
3
3
  "description": "Keep an Obsidian vault in sync with work: PR sync, task rollover, morning routine.",
4
- "version": "1.44.0",
4
+ "version": "1.45.1",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-product",
3
3
  "description": "Take a product idea to a shippable build: MVP passes, full-stack scaffolds, launch plans.",
4
- "version": "1.44.0",
4
+ "version": "1.45.1",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-reflection",
3
3
  "description": "Look back and improve: self-critique, retrospectives, performance review, rapid learning.",
4
- "version": "1.44.0",
4
+ "version": "1.45.1",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-release",
3
3
  "description": "Ship a release: semantic-release setup, changelogs, store listing copy, release-day routine.",
4
- "version": "1.44.0",
4
+ "version": "1.45.1",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-skill-meta",
3
3
  "description": "Author and maintain agent skills and the AI toolchain itself.",
4
- "version": "1.44.0",
4
+ "version": "1.45.1",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },