enigma-cli 1.44.0 → 1.45.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.
@@ -7,6 +7,6 @@
7
7
  "minimalCode"
8
8
  ],
9
9
  "updated": "2026-07-17T00:17:02+02:00",
10
- "cliVersion": "1.44.0",
10
+ "cliVersion": "1.45.0",
11
11
  "sha": "3f0dcc28341bb0407860534f7ce9314cfc91b5e673f8f3d13b89d61851ed75f6"
12
12
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "On-demand over-engineering review - diff review, whole-repo audit, and enigma: debt-marker ledger (tags delete/stdlib/native/yagni/shrink, line/dep scoring); lists cuts, applies nothing.",
6
6
  "updated": "2026-06-16T11:24:30+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "f742a2be3f328b9ea1ff9a35a449177c2cbec35ad16e46f7054b7a873a2ab017"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Backend/API architecture: controller-service-repository layering, modern TypeScript project configuration (module resolution, strict flags, @/* path alias), API and request optimization (batching, avoiding redundant calls, skipping no-op writes), server-side caching (Redis), and Zod boundary validation.",
6
6
  "updated": "2026-08-02T19:59:01+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "652637f818b4ce4f4d5d83fa68fa57fe7842e32fb179523958c5496af54bb938"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Ciphera code style conventions (formatting, naming, imports incl. namespace imports for wide module surfaces, path-alias specifiers and no file extensions, comments, code-level anti-patterns; TypeScript-first, language-agnostic).",
6
6
  "updated": "2026-08-02T19:59:01+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "3beb0383a9cb0331ef8a579308a2517d24d57a8ba33751ad17d16d0a4f66e344"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Pre-delivery self-review gate, prioritized review dimensions, and change-quality criteria.",
6
6
  "updated": "2026-08-19T12:37:59+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "6b8a924cc11b61d4b45b73384aeb095ce622229359b7cc2c6ce4bb0cf3015ed7"
9
9
  }
@@ -7,6 +7,6 @@
7
7
  "codeGraph"
8
8
  ],
9
9
  "updated": "2026-08-15T20:49:24+02:00",
10
- "cliVersion": "1.44.0",
10
+ "cliVersion": "1.45.0",
11
11
  "sha": "95b7202e5659f8d9d6f11ce29e7dc5b01575ba86c78ef948bec4753ccf430155"
12
12
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Senior database architecture policy: engine selection (PostgreSQL by default, SQLite only for local-first/embedded stores), ORM selection (Prisma in TypeScript/JavaScript), query optimization, anti-duplication/normalization, scalability, and RGPD/GDPR encryption.",
6
6
  "updated": "2026-08-04T18:33:27+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "26fddc14caf697e830448a2cc453ddc470fe83d098d50bd67b278effba63274e"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Reproduce-isolate-fix debugging methodology with root-cause discipline and regression verification.",
6
6
  "updated": "2026-08-02T04:15:47+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "968876bcac9ce6e5a20be05c89ac97191b112c9e08679a8dc506d150c375fec4"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Dependency and supply-chain security: lockfiles and reproducible installs, version pinning, vulnerability auditing, vetting/minimizing packages, vendoring, and SBOM/provenance.",
6
6
  "updated": "2026-06-01T00:45:28+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "6375d835c2aef2c9bd31ce116444dc3d796f510f9970a213aa3ac4696d7e21b9"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Transactional email: React Email templates instead of hand-written HTML tables, server-side rendering, one send module behind the provider SDK, plain-text alternatives, idempotent background sending, link safety, and deliverability (SPF/DKIM/DMARC, bounce suppression, unsubscribe).",
6
6
  "updated": "2026-07-30T19:29:19+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "c9724fdbcdbeab99573be3fd44d4cdd97c2a394d99f3c4395f118f17356b00ed"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one.",
6
6
  "updated": "2026-07-29T01:18:36+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "9e30ee7d8a1a1e8c6e7f4e043857cd01841c68a427752e45bc0cad9ec5cfa279"
9
9
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: frontend-policy
3
- description: Frontend architecture - reusable components, abstraction thresholds, state management, real-time form validation where an emptied or not-yet-filled field is incomplete rather than invalid (a `*` on the label and an aria-disabled submit, never "email is not valid" over an empty input), no-op detection (skip any operation whose result equals the current state - form saves, toggles, filters, reorders - not just saves; dirty means the values DIFFER from the loaded snapshot, not that the user touched the field, so a value edited and put back leaves Save disabled), client-side caching (localStorage/sessionStorage to avoid redundant server calls and survive rate limits), instant first paint (render the shell immediately, load data async via the API, show skeletons - never block render on data), perceived performance and responsiveness (instant interaction feedback, prefetch on intent, debounce/throttle, cancel stale requests, avoid request waterfalls, lazy-load heavy widgets), large-list rendering (virtualized infinite scroll as the preferred default with pagination as the deliberate exception when the design or the user calls for it, skeletons, progressive/parallel loading, short-TTL caching), optimistic UI with rollback, visual restraint (never a card inside a card, borders only where they carry information, spacing and background tone before chrome), icon actions (repeated row/card actions like copy, edit, rename, remove, download, refresh are icon-only buttons carrying aria-label plus title, never a text label), navigation that is iconified and grouped into labelled sections once it outgrows a flat list, a Cmd/Ctrl+K command palette with fuse.js fuzzy search over the loaded data once the app has enough destinations and records to hunt through, data views that ship their own affordances by default (a log, expense, transaction or history table is not done when the rows render - it needs the search, the filters its column kinds imply, a date range, sort, filter state kept in the URL, and an export of the filtered set), every reference to an entity being a way into it (a name, id, project or path in a row links to that record, reveals it in a hover card, or at minimum copies and filters by it - never inert text, with machine codes given human labels and raw payloads never dumped into a cell), responsive/adaptive layout (fluid units, breakpoints, no overlap or horizontal overflow, viewport meta, touch targets, and items with a fixed intrinsic size - icons, avatars, badges - pinned with flex-shrink so long text squashes the text and never the glyph), form fields that declare their keyboard and casing (autocapitalize/autocomplete/inputmode/spellcheck per field kind, set once in the shared Input, normalized on blur rather than on every keystroke, with an inline error on every field that has a rule), auth screens (breached-password feedback, strength meter, cookie consent answered before login/register, and a fixed-length 2FA or emailed code that verifies itself when the last digit lands, once per distinct value and never re-firing into the attempt cap), AI chat/assistant/agent interfaces (use Vercel's AI Elements registry for message threads, streaming, reasoning and tool-call panels, prompt inputs - never hand-roll chat UI in React), and periodic React code-health audits (react-doctor). Use when building or changing UI components, client state, forms/save flows, data fetching/caching, lists that show lots of data, a log/activity/expenses/transactions/history table, loading states, dashboards/panels, layout/responsiveness, making the UI feel fast, building a chat/AI/agent/LLM interface, or any frontend structure.
3
+ description: Frontend architecture - reusable components, abstraction thresholds, state management, real-time form validation where an emptied or not-yet-filled field is incomplete rather than invalid (a `*` on the label and an aria-disabled submit, never "email is not valid" over an empty input), no-op detection (skip any operation whose result equals the current state - form saves, toggles, filters, reorders - not just saves; dirty means the values DIFFER from the loaded snapshot, not that the user touched the field, so a value edited and put back leaves Save disabled), client-side caching (localStorage/sessionStorage to avoid redundant server calls and survive rate limits), instant first paint (render the shell immediately, load data async via the API, show skeletons - never block render on data), perceived performance and responsiveness (instant interaction feedback, prefetch on intent, debounce/throttle, cancel stale requests, avoid request waterfalls, lazy-load heavy widgets), large-list rendering (virtualized infinite scroll as the preferred default with pagination as the deliberate exception when the design or the user calls for it, skeletons, progressive/parallel loading, short-TTL caching), optimistic UI with rollback, visual restraint (never a card inside a card, borders only where they carry information, spacing and background tone before chrome), icon actions (repeated row/card actions like copy, edit, rename, remove, download, refresh are icon-only buttons carrying aria-label plus title, never a text label), independent scroll regions (a list beside a record has two scrollers, not one - the shell owns the viewport height, each pane carries min-height: 0 and overscroll-behavior: contain, and reaching the end of one never scrolls the other), navigation that is iconified and grouped into labelled sections once it outgrows a flat list, a Cmd/Ctrl+K command palette with fuse.js fuzzy search over the loaded data once the app has enough destinations and records to hunt through, data views that ship their own affordances by default (a log, expense, transaction or history table is not done when the rows render - it needs the search, the filters its column kinds imply, a date range, sort, filter state kept in the URL, and an export of the filtered set), every reference to an entity being a way into it (a name, id, project or path in a row links to that record, reveals it in a hover card, or at minimum copies and filters by it - never inert text, with machine codes given human labels and raw payloads never dumped into a cell), responsive/adaptive layout (fluid units, breakpoints, no overlap or horizontal overflow, viewport meta, touch targets, and items with a fixed intrinsic size - icons, avatars, badges - pinned with flex-shrink so long text squashes the text and never the glyph), form fields that declare their keyboard and casing (autocapitalize/autocomplete/inputmode/spellcheck per field kind, set once in the shared Input, normalized on blur rather than on every keystroke, with an inline error on every field that has a rule), auth screens (breached-password feedback, strength meter, cookie consent answered before login/register, and a fixed-length 2FA or emailed code that verifies itself when the last digit lands, once per distinct value and never re-firing into the attempt cap), AI chat/assistant/agent interfaces (use Vercel's AI Elements registry for message threads, streaming, reasoning and tool-call panels, prompt inputs - never hand-roll chat UI in React), and periodic React code-health audits (react-doctor). Use when building or changing UI components, a layout with more than one scrollable region (list + detail, tree + editor, chat + thread), client state, forms/save flows, data fetching/caching, lists that show lots of data, a log/activity/expenses/transactions/history table, loading states, dashboards/panels, layout/responsiveness, making the UI feel fast, building a chat/AI/agent/LLM interface, or any frontend structure.
4
4
  ---
5
5
 
6
6
  # Frontend Architecture Policy
@@ -162,6 +162,26 @@ A sidebar keeps its desktop width only while there is a desktop to put it in. On
162
162
 
163
163
  ---
164
164
 
165
+ ## Two Panes Means Two Scrolls (Independent Scroll Regions)
166
+
167
+ A view with a list on one side and a record on the other has TWO scrollable regions, and they are independent: scrolling the open email moves the email, and the list of emails stays exactly where it was. The same holds for a file tree beside an editor, a thread beside a conversation list, a table beside a details drawer, a chat beside its transcript.
168
+
169
+ The defect is scroll CHAINING, and it is the most-missed part of any multi-pane layout: the wheel over the reading pane scrolls it to its end and then keeps going into whatever is behind it, so the list jumps, or the whole page moves, or both panes travel together as if they were one document. It looks fine until content is long enough to reach an end, which is why it survives review.
170
+
171
+ Three things make a pane scroll on its own. All three are required, and the second is the one usually missing:
172
+
173
+ - **The page does not scroll; the shell is the viewport.** The outer container is `height: 100dvh` (`h-dvh`) with `overflow: hidden`, and the panes inside it own every scrollbar on screen. If the page itself can scroll, nothing below matters - the chain has somewhere to go.
174
+ - **Each pane declares `min-height: 0`** (`min-w-0` for a horizontal one). A flex or grid child defaults to `min-height: auto`, which is its CONTENT's height, so the pane grows to fit instead of scrolling and pushes the scrollbar out to the page. This is the same trap as the `min-width: 0` one that makes text refuse to truncate, and it produces no error, no warning and no visual clue except that the wrong thing scrolls.
175
+ - **Each pane sets `overscroll-behavior: contain`** (`overscroll-contain`). That is what actually stops the chain: reaching the end of the email does not hand the rest of the gesture to the list behind it. Use `none` only where the browser's own overscroll effect must go too (pull-to-refresh, rubber-banding).
176
+
177
+ Then the state that goes with them:
178
+
179
+ - **Each pane's scroll position is its own.** Opening a different record resets the reading pane to the top (`ref.scrollTo({ top: 0 })` on the id changing, not on every render) and must not touch the list's position. Coming back to the list finds it where it was left - restoring a list to the top after a back navigation is the same defect seen from the other side.
180
+ - **A pane that scrolls must be reachable from the keyboard.** A `div` with `overflow-y: auto` is not focusable, so Page Down scrolls the page instead of the pane the reader is looking at. Give it `tabindex="0"` and an accessible name (`role="region"` plus `aria-label`), or put a focusable element inside it.
181
+ - **On a phone the two panes are two screens**, not two scrollers side by side: the list navigates to the record and back. Two independent scroll boxes stacked in one viewport is the shape nobody can use.
182
+
183
+ Verify it mechanically rather than by eye, because eyeballing is what let it through: scroll the inner pane to its end, keep scrolling, and assert the OUTER container's `scrollTop` is unchanged. `pane.scrollTop === pane.scrollHeight - pane.clientHeight && outer.scrollTop === before` is the whole check.
184
+
165
185
  ## Navigation Is Structured, Not A Growing List
166
186
 
167
187
  A sidebar gets one more entry per feature and nobody ever goes back to reorganize it, so it ends as a flat column of a dozen similar words that has to be read top to bottom every time. Structure it as it grows, by default and without being asked: the icons, the grouping and the ordering below are part of building the nav, not a redesign to propose afterwards.
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Frontend architecture: reusable components, abstraction thresholds, state management, real-time form validation where an emptied or not-yet-filled field is incomplete rather than invalid (a `*` on the label and an aria-disabled submit, never \"email is not valid\" over an empty input), no-op detection (skip any operation whose result equals current state, not just form saves; dirty means different from the loaded snapshot, not touched), instant first paint (render the shell, load data async, skeletons), perceived performance (prefetch on intent, debounce/throttle, cancel stale requests, avoid waterfalls, lazy widgets), large-list rendering (infinite scroll is the preferred default, pagination the deliberate exception when the design or the user calls for it, virtualization, skeletons, progressive loading), data views that ship their own affordances by default (a log, expense, transaction or history table is not done when the rows render: fuse.js search, the filters its column kinds imply, a date range, sort, filter state in the URL, and an export of the filtered set), every reference to an entity being a way into it (a name, id, project or path in a row links to that record, reveals it in a hover card, or at minimum copies and filters by it, never inert text; machine codes get human labels and raw payloads are never dumped into a cell), optimistic UI with rollback, visual restraint (one card level, spacing before borders, one elevation scale), icon actions (repeated row/card actions are icon-only buttons with aria-label plus title, not text labels), responsive/adaptive layout (fluid units, breakpoints, no overlap/overflow, viewport meta, touch targets), form fields that declare their keyboard and casing (autocapitalize/autocomplete/inputmode per field kind, set once in the shared Input, normalized on blur), variable-length text (min-width:0 in flex/grid, wrap vs truncate, long unbroken strings, worst-case content checks), auth screens (breached-password feedback, strength meter, cookie consent before login/register), and AI chat/agent interfaces via Vercel's AI Elements registry instead of hand-rolled message threads.",
6
6
  "updated": "2026-09-05T02:46:46+02:00",
7
- "cliVersion": "1.44.0",
8
- "sha": "d0085206565523d2a54d3c74ccb670fe5c9c43a64cef2b31c15b22156d1b8131"
7
+ "cliVersion": "1.45.0",
8
+ "sha": "8bfd675f3a66dbdcaa7e670bc40246adb0c470b93c1d8677338b4092dfa9ada4"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Git & contribution policy (senior engineering standards).",
6
6
  "updated": "2026-08-22T09:25:34+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "cb320a6a5fd3279604ad7920b877c1a36e48f4f39aeead1a4c4daa89901d9ce0"
9
9
  }
@@ -7,6 +7,6 @@
7
7
  "logoColorPolicy"
8
8
  ],
9
9
  "updated": "2026-07-17T00:17:02+02:00",
10
- "cliVersion": "1.44.0",
10
+ "cliVersion": "1.45.0",
11
11
  "sha": "09cdbefd98625b02a7d03685e5deed128238ff8454a83fe22279610fe3ef8ddf"
12
12
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Application and AI-agent security: secrets, authn/authz (least privilege), credential flows with breach-checked passwords (Have I Been Pwned), OWASP Top 10, transport/crypto baseline, cookies and consent, secure logging, and agent/MCP/tool-use safety.",
6
6
  "updated": "2026-09-05T02:46:46+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "d64fe3a4a54f27a71e3066875ee949500f170d04da5c548ef605268a12102afb"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Create new skills, modify and improve existing skills, and measure skill performance with evals and benchmarks.",
6
6
  "updated": "2026-08-03T00:16:54+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "a49f6166f57d734e0f13487332da37903e925f32257447856af0fbd6a5f1dc84"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Exhaustive completion discipline for long/multi-item tasks - inventory, coverage ledger, verified done.",
6
6
  "updated": "2026-08-02T04:15:47+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "4c2197954135dd3375f32d839238b82a95c0e93e976ddf5a9cbc4a0cf0146e97"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Concise, realistic technical copy - UI microcopy, descriptions, hints, empty/error states, and README/doc prose that informs without over-explaining or restating the obvious, and never uses a typographic dash.",
6
6
  "updated": "2026-08-19T12:37:59+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "a5a228a302f50d975a947b9d84676b4c2a4780f2b222f819388cc98d6a12f207"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Test strategy, coverage gates, deterministic tests, mocking discipline, regression-first bug fixing, and test-suite organization (layout by type/domain, mirrored paths, file naming, fixture/helper placement).",
6
6
  "updated": "2026-06-16T17:11:49+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "3bdf591057b760f674fb2b1425f63acb426cda2c4f042e1a74c5a5d3807df664"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Strict frontend + backend schema validation, normalization before validation (shared normalizers: trim, lowercase email, capitalize names, canonicalize links and handles), real-time error timing (an emptied or not-yet-filled field is incomplete, not invalid: a `*` and an aria-disabled submit instead of \"not valid\" over an empty input), schema consistency, and safe client-facing error handling.",
6
6
  "updated": "2026-08-11T17:10:56+02:00",
7
- "cliVersion": "1.44.0",
7
+ "cliVersion": "1.45.0",
8
8
  "sha": "24928a4c9eed28ebede9f23f746b09a9d3d8176f8fcca61a7780a853fa5bed4e"
9
9
  }
@@ -1,6 +1,6 @@
1
1
  {
2
- "enigma-darwin-arm64": "9d77f2f48a3b09655b5c0387dc2434308842af579dbe7c4c35ccf354981736ea",
3
- "enigma-linux-arm64": "b791c070374b50f1eee59ce1d6f924d882915534bf0986e616cb35fb9647f9a5",
4
- "enigma-linux-x64": "eda9a4c6a66a3f2c220f5b4d47eb61711513c49aabffb901f894c8207469f983",
5
- "enigma-win32-x64.exe": "8b3426ebb8acb03cfec9f988db0e090995c0c40218e1cd19873c1f21a8e43627"
2
+ "enigma-darwin-arm64": "092a175e099189d7cc55b7cec7444dfd6e94fc6b2149d88c244b0cbef40193d1",
3
+ "enigma-linux-arm64": "1795639328fe7d841db589a589855784fc991893d0f81ac7b7040d61163cfde6",
4
+ "enigma-linux-x64": "c53c1d59617ae14ad901b34e41e907f746f9b4a1ab94778f333965a0510d9d5b",
5
+ "enigma-win32-x64.exe": "547f70fbb3b7c7c50ddb8d67049aaba99647d1143c32e2f1c6bdfdae168e4542"
6
6
  }
@@ -177,6 +177,42 @@ var BUILTIN_RULES = [
177
177
  severity: "warn",
178
178
  skill: "frontend-policy"
179
179
  },
180
+ {
181
+ id: "fe-scroll-chaining",
182
+ label: "A scroll region contains its own scroll",
183
+ files: ["*.css", "*.scss", "*.less", "*.tsx", "*.jsx", "*.astro", "*.vue", "*.svelte"],
184
+ excludeFiles: [
185
+ "*.test.*",
186
+ "*.spec.*",
187
+ "*.stories.*",
188
+ "*.min.js",
189
+ "*.min.css",
190
+ "**/tests/**",
191
+ "tests/**",
192
+ "**/__tests__/**",
193
+ "__tests__/**",
194
+ "**/dist/**",
195
+ "dist/**",
196
+ "**/build/**",
197
+ "build/**",
198
+ "**/node_modules/**",
199
+ "node_modules/**",
200
+ "**/vendor/**",
201
+ "vendor/**"
202
+ ],
203
+ scope: "file",
204
+ stage: "diff",
205
+ // A VERTICAL scroll container, in CSS or in Tailwind. `overflow-x` is left alone: a wide
206
+ // table scrolling sideways chains into nothing anybody notices, and including it doubled
207
+ // the rule's noise for no defect.
208
+ pattern: "overflow(-y)?\\s*:\\s*(auto|scroll)|\\boverflow-y-(auto|scroll)\\b",
209
+ // Any mention anywhere in the file, in either spelling, and the file has clearly thought
210
+ // about it - one declaration usually covers the pane the rule is about.
211
+ absent: "overscroll-behavior|\\boverscroll-(y-)?(contain|none|auto)\\b|enigma:allow-scroll-chaining",
212
+ message: "This file makes something scroll but never mentions overscroll-behavior, so its scroll CHAINS: the wheel reaches the end of this box and keeps going into whatever is behind it. In a two-pane view - a list beside the record, a tree beside the editor, a thread beside the conversation - that is the reading pane dragging the list along with it, which is the single most-missed part of a multi-pane layout because it only shows up once content is long enough to reach an end. Add `overscroll-behavior: contain` (Tailwind `overscroll-contain`) to the scroll container, and check the other two halves while you are there: the shell is the viewport (`height: 100dvh; overflow: hidden`) and each pane carries `min-height: 0`, or the pane grows instead of scrolling and the page scrolls in its place. Deliberate - a page-level scroller, or an effect that must reach the browser - mark it `enigma:allow-scroll-chaining` (frontend-policy).",
213
+ severity: "warn",
214
+ skill: "frontend-policy"
215
+ },
180
216
  {
181
217
  id: "fe-pointer-capture-drag",
182
218
  label: "Drag bound to window, not setPointerCapture",
package/dist/post-edit.js CHANGED
@@ -1637,6 +1637,42 @@ var init_guardrails = __esm({
1637
1637
  severity: "warn",
1638
1638
  skill: "frontend-policy"
1639
1639
  },
1640
+ {
1641
+ id: "fe-scroll-chaining",
1642
+ label: "A scroll region contains its own scroll",
1643
+ files: ["*.css", "*.scss", "*.less", "*.tsx", "*.jsx", "*.astro", "*.vue", "*.svelte"],
1644
+ excludeFiles: [
1645
+ "*.test.*",
1646
+ "*.spec.*",
1647
+ "*.stories.*",
1648
+ "*.min.js",
1649
+ "*.min.css",
1650
+ "**/tests/**",
1651
+ "tests/**",
1652
+ "**/__tests__/**",
1653
+ "__tests__/**",
1654
+ "**/dist/**",
1655
+ "dist/**",
1656
+ "**/build/**",
1657
+ "build/**",
1658
+ "**/node_modules/**",
1659
+ "node_modules/**",
1660
+ "**/vendor/**",
1661
+ "vendor/**"
1662
+ ],
1663
+ scope: "file",
1664
+ stage: "diff",
1665
+ // A VERTICAL scroll container, in CSS or in Tailwind. `overflow-x` is left alone: a wide
1666
+ // table scrolling sideways chains into nothing anybody notices, and including it doubled
1667
+ // the rule's noise for no defect.
1668
+ pattern: "overflow(-y)?\\s*:\\s*(auto|scroll)|\\boverflow-y-(auto|scroll)\\b",
1669
+ // Any mention anywhere in the file, in either spelling, and the file has clearly thought
1670
+ // about it - one declaration usually covers the pane the rule is about.
1671
+ absent: "overscroll-behavior|\\boverscroll-(y-)?(contain|none|auto)\\b|enigma:allow-scroll-chaining",
1672
+ message: "This file makes something scroll but never mentions overscroll-behavior, so its scroll CHAINS: the wheel reaches the end of this box and keeps going into whatever is behind it. In a two-pane view - a list beside the record, a tree beside the editor, a thread beside the conversation - that is the reading pane dragging the list along with it, which is the single most-missed part of a multi-pane layout because it only shows up once content is long enough to reach an end. Add `overscroll-behavior: contain` (Tailwind `overscroll-contain`) to the scroll container, and check the other two halves while you are there: the shell is the viewport (`height: 100dvh; overflow: hidden`) and each pane carries `min-height: 0`, or the pane grows instead of scrolling and the page scrolls in its place. Deliberate - a page-level scroller, or an effect that must reach the browser - mark it `enigma:allow-scroll-chaining` (frontend-policy).",
1673
+ severity: "warn",
1674
+ skill: "frontend-policy"
1675
+ },
1640
1676
  {
1641
1677
  id: "fe-pointer-capture-drag",
1642
1678
  label: "Drag bound to window, not setPointerCapture",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "enigma-cli",
3
- "version": "1.44.0",
3
+ "version": "1.45.0",
4
4
  "description": "Everything you need to work with a coding agent: install shared policy skills for Claude Code, OpenAI Codex and opencode, and set up portable git security hooks.",
5
5
  "type": "module",
6
6
  "bin": {