enigma-cli 1.31.2 → 1.31.4

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.31.2",
10
+ "cliVersion": "1.31.4",
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.31.2",
7
+ "cliVersion": "1.31.4",
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, API and request optimization (batching, avoiding redundant calls, skipping no-op writes), server-side caching (Redis), and Zod boundary validation.",
6
6
  "updated": "2026-07-23T04:41:39+02:00",
7
- "cliVersion": "1.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "d091e8708888d23ee14cdd6c0e71f386861f2252d95360895a31c73db090a689"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Ciphera code style conventions (formatting, naming, imports, comments, code-level anti-patterns; TypeScript-first, language-agnostic).",
6
6
  "updated": "2026-06-26T13:40:52+02:00",
7
- "cliVersion": "1.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "dc9ceb784004b05a0117c464e4bed05946835a04acea282586c0b735ee7c2284"
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-06-01T00:45:28+02:00",
7
- "cliVersion": "1.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "3d3bbe0602d5bbb4afe37648fe3c2fa39376b1bcbac5d8c441f01fad1e866ed0"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Core engineering execution policy and harness orchestration (highest-authority rules).",
6
6
  "updated": "2026-07-16T22:43:53+02:00",
7
- "cliVersion": "1.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "d132f20db08806054d95e58d3d56c2aa7ebc8e6dd24d902b0a0ed9ddfae216c5"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Senior database architecture policy: query optimization, anti-duplication/normalization, scalability, and RGPD/GDPR encryption.",
6
6
  "updated": "2026-06-03T14:19:50+02:00",
7
- "cliVersion": "1.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "2883bcecb3202683ae6f81b073c3d6a9cec9c55029e011bdd06ba7ac3537297e"
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-06-01T00:45:28+02:00",
7
- "cliVersion": "1.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "14b0064c8b33a0dc85e51464b05005cf5801c756b1101789a6924b9548420f6b"
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.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "6375d835c2aef2c9bd31ce116444dc3d796f510f9970a213aa3ac4696d7e21b9"
9
9
  }
@@ -39,7 +39,7 @@ Try to do a lot of this planning and iteration in your thinking, and only show i
39
39
 
40
40
  ## Restraint and self-critique
41
41
 
42
- Spend your boldness in one place. Let the signature element be the one memorable thing, keep everything around it quiet and disciplined, and cut any decoration that does not serve the brief. Chrome is where that discipline usually fails: a card inside a card inside a card, a border around every block, a shadow on things that are not raised. Group with spacing first, a second background tone second, and a border only where two blocks must sit flush - never more than one of the three on the same boundary, and never a second card nested in the first (frontend-policy holds the full rule). Not taking a risk can be a risk itself! Build to a quality floor without announcing it: responsive down to mobile, visible keyboard focus, reduced motion respected, and native browser chrome themed to the design rather than left as platform defaults. Default scrollbars and unstyled form controls read as templated next to a deliberate design; modern CSS brings them into the system - scrollbars via `scrollbar-width` / `scrollbar-color` (plus `::-webkit-scrollbar` on WebKit), and `<select>` and other form controls via `appearance` and accent/background/border overrides. Theme every scrollable region (code blocks, overflow panes, long lists) and every native control, not just the obvious ones. Check every interactive state for contrast: a hover/focus/active rule must never set text to the colour of its own background - a global `a:hover { color: accent }` will silently make an accent-filled button's label vanish, so hold an explicit on-accent text colour on accent surfaces. A link styled as a button is still an anchor, so it inherits the browser's default underline: a button never carries underlined text unless the design explicitly asks for it, so set `text-decoration: none` on the button class itself rather than relying on a global reset. Reserve underline for inline text links, where it signals "this is a link" inside running copy. For known services use a real icon (an SVG set reused from one place), not a text label, and make sure any logo contrasts with its background - a black mark on a dark UI must be recoloured (e.g. white) or it disappears. Every button must visibly react to a click - a control that looks identical before and after a tap reads as broken: give all of them a quick press state (a small `:active` scale or shade), and for a control that triggers an async action add a transient working/done state on the control itself - a spinner on a refresh/reload control while it refreshes, a checkmark swap on a copy control once copied - so the user knows it fired. Honour `prefers-reduced-motion` for these. Use the universal direction convention for paired data controls instead of inventing glyphs: export/download is a downward arrow (into a tray), import/upload an upward arrow (out of a tray); save is a disk/check, and the icon can either replace or sit beside the label, but the two of a pair must mirror each other. Critique your own work as you build, taking screenshots if your environment supports it - a picture is worth 1000 tokens. Consider Chanel's advice: before leaving the house, take a look in the mirror and remove one accessory. Human creators have memory and always try to do something new, so if you have a space to quickly jot down notes about what you've tried, it can help you in future passes.
42
+ Spend your boldness in one place. Let the signature element be the one memorable thing, keep everything around it quiet and disciplined, and cut any decoration that does not serve the brief. Chrome is where that discipline usually fails: a card inside a card inside a card, a border around every block, a shadow on things that are not raised. Group with spacing first, a second background tone second, and a border only where two blocks must sit flush - never more than one of the three on the same boundary, and never a second card nested in the first (frontend-policy holds the full rule). Not taking a risk can be a risk itself! Build to a quality floor without announcing it: responsive down to mobile, visible keyboard focus, reduced motion respected, and native browser chrome themed to the design rather than left as platform defaults. Default scrollbars and unstyled form controls read as templated next to a deliberate design; modern CSS brings them into the system - scrollbars via `scrollbar-width` / `scrollbar-color` (plus `::-webkit-scrollbar` on WebKit), and `<select>` and other form controls via `appearance` and accent/background/border overrides. Theme every scrollable region (code blocks, overflow panes, long lists) and every native control, not just the obvious ones. Check every interactive state for contrast: a hover/focus/active rule must never set text to the colour of its own background - a global `a:hover { color: accent }` will silently make an accent-filled button's label vanish, so hold an explicit on-accent text colour on accent surfaces. A link styled as a button is still an anchor, so it inherits the browser's default underline: a button never carries underlined text unless the design explicitly asks for it, so set `text-decoration: none` on the button class itself rather than relying on a global reset. Reserve underline for inline text links, where it signals "this is a link" inside running copy. For known services use a real icon (an SVG set reused from one place), not a text label, and make sure any logo contrasts with its background - a black mark on a dark UI must be recoloured (e.g. white) or it disappears. Treat the repeated actions in a row or card the same way: copy, edit, rename, duplicate, remove, download and refresh are the icon alone, with the wording moved into `aria-label` (naming what it acts on) plus `title` for the tooltip and `aria-hidden` on the glyph itself, since a word repeated down every row is width spent on nothing. Keep the visible label only for a primary or confirmation button, or where no conventional glyph exists (frontend-policy holds the full rule). Every button must visibly react to a click - a control that looks identical before and after a tap reads as broken: give all of them a quick press state (a small `:active` scale or shade), and for a control that triggers an async action add a transient working/done state on the control itself - a spinner on a refresh/reload control while it refreshes, a checkmark swap on a copy control once copied - so the user knows it fired. Honour `prefers-reduced-motion` for these. Use the universal direction convention for paired data controls instead of inventing glyphs: export/download is a downward arrow (into a tray), import/upload an upward arrow (out of a tray); save is a disk/check, and the icon can either replace or sit beside the label, but the two of a pair must mirror each other. Critique your own work as you build, taking screenshots if your environment supports it - a picture is worth 1000 tokens. Consider Chanel's advice: before leaving the house, take a look in the mirror and remove one accessory. Human creators have memory and always try to do something new, so if you have a space to quickly jot down notes about what you've tried, it can help you in future passes.
43
43
 
44
44
  ## More on writing in design
45
45
 
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "frontend-design",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one.",
6
- "updated": "2026-07-28T20:30:12+02:00",
7
- "cliVersion": "1.31.2",
8
- "sha": "5fbc294a4f33aba03fd93e76e0cfeeefe04389b6c8e8493043dc4036ad8f4d19"
6
+ "updated": "2026-07-29T01:18:36+02:00",
7
+ "cliVersion": "1.31.4",
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, no-op detection (skip any operation whose result equals the current state - form saves, toggles, filters, reorders - not just saves), 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 vs pagination, 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), responsive/adaptive layout (fluid units, breakpoints, no overlap or horizontal overflow, viewport meta, touch targets), 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, 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, 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 vs pagination, 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), responsive/adaptive layout (fluid units, breakpoints, no overlap or horizontal overflow, viewport meta, touch targets), 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, 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
@@ -86,6 +86,30 @@ Never apply more than one of the three to the same boundary. A block with a bord
86
86
 
87
87
  ---
88
88
 
89
+ ## Icon Actions (Words Only Where No Glyph Speaks)
90
+
91
+ Text in the chrome is the same problem as an extra border: it costs width, it repeats on every row, and it makes the screen slower to scan. An action that has a universally read glyph is an ICON button, not a word. Apply this by default, without being asked.
92
+
93
+ **Iconify the repeated actions.** Copy, edit, rename, duplicate, remove, delete, download/export, upload/import, refresh, share, open externally, expand/collapse, close: one icon, no label. These appear once per row or per card, so a word there is paid N times over. Take every glyph from the project's ONE icon set (never emoji, never a second library for one icon), and keep paired directions mirrored: export/download is a downward arrow, import/upload an upward one.
94
+
95
+ **An icon button is not done until it has a name.** Removing the visible word removes the meaning for anyone who cannot see or does not recognize the glyph, so replace it in the accessibility layer, always:
96
+
97
+ - `aria-label` naming the action AND what it acts on ("Remove account Work", not "Remove"). This is what a screen reader announces, and what makes a list of identical buttons distinguishable.
98
+ - `title` with the short action ("Remove") so pointer users get the hover tooltip.
99
+ - `aria-hidden="true"` on the inline SVG, so the icon is not announced twice. An `<img>` icon carries the same text as its `alt` instead.
100
+ - Keep the touch target at ~44px with padding even though the glyph is 15-16px, and keep the press state (Perceived Performance): an icon button gives less visible feedback than a labelled one, so it needs the `:active` shade more, not less.
101
+
102
+ **Keep the word when the word is doing the work.** This is a default, not an absolute. A written label stays when:
103
+
104
+ - No conventional glyph exists for the action ("Reuse session", "Log in", "Provider", "Inherit global"). An invented glyph is worse than a word, because a tooltip does not exist on touch.
105
+ - It is the primary action of a form, dialog or page ("Save changes", "Publish", "Send"), including the destructive confirm, which must name what it destroys ("Delete project 'Acme'").
106
+ - It reports state rather than triggering an action (an Enabled/Disabled toggle reads its own value).
107
+ - The design, the brief, or the user asks for a label. Their call wins.
108
+
109
+ The guardrail `fe-icon-action-button` blocks a button whose entire content is a bare action verb. For a deliberate exception, mark the line with an `enigma:` note or add `enigma:allow-text-actions` to the file.
110
+
111
+ ---
112
+
89
113
  ## Responsive & Adaptive Layout
90
114
 
91
115
  Build every UI to adapt to the viewport; never assume a desktop width. A layout that looks right on your screen but overlaps, overflows, or clips at another size is NOT done - responsiveness is part of the task, not a follow-up.
@@ -137,6 +161,12 @@ The general rule: before running any operation, check whether its result would e
137
161
 
138
162
  - Track the saved snapshot when the form/settings loads or after a successful save; compute dirtiness by comparing the edited values against it.
139
163
  - Example: a value goes x -> z -> back to x before saving. The net change is zero - the form is NOT dirty, and Save must send nothing to the backend.
164
+ - **Dirty means different, not touched.** Recompute the comparison on every change. Never raise a `dirty` flag from an onChange/onInput handler: a flag set by interaction stays raised after the user types a character and deletes it again, which is the exact case this rule exists for.
165
+ - **Valid is not dirty.** A Save gated only on validity ("the name is not empty", "there are no errors") still fires a no-op on a form nobody edited. Both conditions have to hold: the values differ AND they are valid.
166
+ - **Normalize before comparing**, using the same rules the field itself applies: trim surrounding whitespace, and case-fold only where the value is case-insensitive (a username usually is, a display name is not). Leading whitespace is not an edit; a different letter case may be.
167
+ - **A disabled Save must say why.** Keep it visible and disabled rather than hidden, and put the reason within reach (a `title` or one line of helper text, "No changes to save"), so the form does not read as broken. Never leave it looking enabled while it silently does nothing.
168
+ - On load the form is not dirty, so Save starts disabled; after a successful save the snapshot becomes the saved values and Save returns to disabled.
169
+ - **Autosave, blur-save and inline edits obey the same check.** On blur or after the debounce, compare against the snapshot and send nothing when the value came back to where it started.
140
170
  - When the form is not dirty, Save must never hit the network. Two acceptable UX options:
141
171
  - Preferred: disable / neutralize the Save button while the edited values equal the snapshot, so there is nothing to submit until a real change exists.
142
172
  - Or keep Save enabled but short-circuit on click: show the normal "saved" confirmation instantly and send NO request. Never open a spinner or fire a call for a no-op.
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "frontend-policy",
3
- "version": "1.18.0",
3
+ "version": "1.20.0",
4
4
  "provider": "FJRG2007/enigma",
5
- "description": "Frontend architecture: reusable components, abstraction thresholds, state management, no-op detection (skip any operation whose result equals current state, not just form saves), 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/pagination, virtualization, skeletons, progressive loading), optimistic UI with rollback, visual restraint (one card level, spacing before borders, one elevation scale), responsive/adaptive layout (fluid units, breakpoints, no overlap/overflow, viewport meta, touch targets), variable-length text (min-width:0 in flex/grid, wrap vs truncate, long unbroken strings, worst-case content checks), and AI chat/agent interfaces via Vercel's AI Elements registry instead of hand-rolled message threads.",
6
- "updated": "2026-07-28T20:30:12+02:00",
7
- "cliVersion": "1.31.2",
8
- "sha": "0bf2330162a3f62e0413496d5fa6451e39cd8f6a99985689d3126e910ef62177"
5
+ "description": "Frontend architecture: reusable components, abstraction thresholds, state management, 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/pagination, virtualization, skeletons, progressive loading), 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), variable-length text (min-width:0 in flex/grid, wrap vs truncate, long unbroken strings, worst-case content checks), and AI chat/agent interfaces via Vercel's AI Elements registry instead of hand-rolled message threads.",
6
+ "updated": "2026-07-29T01:26:14+02:00",
7
+ "cliVersion": "1.31.4",
8
+ "sha": "71ebc71510c8aa54d7925445a7dffc55dbce9eba209fb6a63bae05d119217d79"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Git & contribution policy (senior engineering standards).",
6
6
  "updated": "2026-07-16T22:44:02+02:00",
7
- "cliVersion": "1.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "e6dfbc33884000d9d25841bd9c5a84d6558ffd374882cb7b34451eb2cebc2161"
9
9
  }
@@ -7,6 +7,6 @@
7
7
  "logoColorPolicy"
8
8
  ],
9
9
  "updated": "2026-07-17T00:17:02+02:00",
10
- "cliVersion": "1.31.2",
10
+ "cliVersion": "1.31.4",
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), OWASP Top 10, transport/crypto baseline, secure logging, and agent/MCP/tool-use safety.",
6
6
  "updated": "2026-06-01T00:45:28+02:00",
7
- "cliVersion": "1.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "9971e9d9127397d0152e89d24aad3191e2935e55a8483db7fd15f5d4d7a60e7a"
9
9
  }
@@ -32,8 +32,10 @@
32
32
  .toggle .slider::before { content: ""; position: absolute; width: 18px; height: 18px; left: 3px; bottom: 3px; background: white; border-radius: 50%; transition: 0.2s; }
33
33
  .toggle input:checked + .slider { background: #d97757; }
34
34
  .toggle input:checked + .slider::before { transform: translateX(20px); }
35
- .btn-delete { background: #c44; color: white; padding: 0.3rem 0.6rem; border: none; border-radius: 4px; cursor: pointer; font-size: 0.75rem; font-family: 'Poppins', sans-serif; }
35
+ .btn-delete { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; background: #c44; color: white; padding: 0; border: none; border-radius: 4px; cursor: pointer; }
36
36
  .btn-delete:hover { background: #a33; }
37
+ .btn-delete:active { transform: scale(0.93); }
38
+ .btn-delete svg { width: 14px; height: 14px; display: block; }
37
39
  .summary { margin-top: 1rem; color: #b0aea5; font-size: 0.875rem; }
38
40
  </style>
39
41
  </head>
@@ -62,6 +64,9 @@
62
64
  <script>
63
65
  const EVAL_DATA = __EVAL_DATA_PLACEHOLDER__;
64
66
 
67
+ // Row actions are icons, not words: the label lives in title/aria-label so the row stays narrow.
68
+ const TRASH_ICON = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg>';
69
+
65
70
  let evalItems = [...EVAL_DATA];
66
71
 
67
72
  function render() {
@@ -95,7 +100,7 @@
95
100
  </label>
96
101
  <span style="margin-left:8px;font-size:0.8rem;color:#b0aea5">${item.should_trigger ? 'Yes' : 'No'}</span>
97
102
  </td>
98
- <td><button class="btn-delete" onclick="deleteRow(${idx})">Delete</button></td>
103
+ <td><button class="btn-delete" onclick="deleteRow(${idx})" title="Delete" aria-label="Delete this query">${TRASH_ICON}</button></td>
99
104
  `;
100
105
  tbody.appendChild(tr);
101
106
  });
@@ -3,7 +3,7 @@
3
3
  "version": "1.0.0",
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
- "updated": "2026-06-16T16:39:13+02:00",
7
- "cliVersion": "1.31.2",
8
- "sha": "699586cce82ec0a5458288b598ee7e5ebdddb3dfcf19db354d8bc5e85e47c1c7"
6
+ "updated": "2026-07-29T01:18:36+02:00",
7
+ "cliVersion": "1.31.4",
8
+ "sha": "13d24c217bdb6fe83fe16835d8f5c3d397a9f3338f16876c61ef96e97f34c90a"
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-07-27T17:22:17+02:00",
7
- "cliVersion": "1.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "b9046c15fd636057a8e42e199d2eeb47297477f38a0a26a07a7b0bf71d61fcb4"
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-07-28T20:30:23+02:00",
7
- "cliVersion": "1.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "a4b792103eb1f9dad93b9d70ea79dc18fe9cbbc318facf5adb47ae5907d842f9"
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.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "3bdf591057b760f674fb2b1425f63acb426cda2c4f042e1a74c5a5d3807df664"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Strict frontend + backend schema validation, schema consistency, and safe client-facing error handling.",
6
6
  "updated": "2026-07-22T01:41:06+02:00",
7
- "cliVersion": "1.31.2",
7
+ "cliVersion": "1.31.4",
8
8
  "sha": "d937df0052d1ec151728a28f6567744d9e7ca0a65d84b4d5c9a697f1e40d704f"
9
9
  }
@@ -1,6 +1,6 @@
1
1
  {
2
- "enigma-darwin-arm64": "f868bd329a528c8eed63280c32f220e0fe741987666aea5f1f3ca8af2d951269",
3
- "enigma-linux-arm64": "d2325149898a37cb13607b4ebd4e08b32d676c5ae4aa49b7f436539c8c430c2d",
4
- "enigma-linux-x64": "464c390daea135ff90d490b6e8c2b154dd50fb705270b35528c86a04ae2df772",
5
- "enigma-win32-x64.exe": "d39a5d9968903afea8795145200209612f63384d5c4d2985436ef1c2d857f876"
2
+ "enigma-darwin-arm64": "5947b36a698c19cba84bc42fd8690b1e9acabc9c288c8fdf20b1595a88f01a98",
3
+ "enigma-linux-arm64": "e13a8a57b2fbb45bc916f5c6299fa735c7093ddaa34204c96a44a22f04326385",
4
+ "enigma-linux-x64": "a821a20a6cf05c104859b7a3f4a838cce8be01dafb5da1dcf85853a21c184f79",
5
+ "enigma-win32-x64.exe": "4d84edbc1e8ab7703ed9e8a0f3f226051493ae8fa351b613da8891dd9b206b35"
6
6
  }
@@ -226,6 +226,49 @@ var BUILTIN_RULES = [
226
226
  severity: "warn",
227
227
  skill: "frontend-policy"
228
228
  },
229
+ {
230
+ id: "fe-icon-action-button",
231
+ label: "Repeated actions are icon buttons, not text labels",
232
+ files: ["*.tsx", "*.jsx", "*.vue", "*.svelte", "*.astro", "*.html", "*.htm", "*.ts", "*.js", "*.mts", "*.cts"],
233
+ // Same two-form generated/vendored excludes as ui-no-em-dash: `**/x/**` needs a leading
234
+ // segment, so it misses a root-level dist/.
235
+ excludeFiles: [
236
+ "*.test.*",
237
+ "*.spec.*",
238
+ "**/tests/**",
239
+ "**/__tests__/**",
240
+ "**/fixtures/**",
241
+ "*.min.js",
242
+ "**/dist/**",
243
+ "**/build/**",
244
+ "**/_build/**",
245
+ "**/node_modules/**",
246
+ "**/vendor/**",
247
+ "dist/**",
248
+ "build/**",
249
+ "_build/**",
250
+ "node_modules/**",
251
+ "vendor/**"
252
+ ],
253
+ scope: "file",
254
+ // A button whose ENTIRE content is one bare action verb. Three things keep this precise,
255
+ // measured over ~1100 real UI files (this repo, apps/web and references/repos): 10 hits,
256
+ // all genuine text action buttons, 0 false positives.
257
+ // (1) `[^>]*` forces the whole element onto one line with NOTHING but the word inside, so
258
+ // a button that already carries an icon (its <svg .../> contains a '>') never matches -
259
+ // icon-plus-label is not the defect, a bare word is. It still catches the string-concat
260
+ // form ('<button data-id="' + esc(id) + '">Edit</button>') because that has no '>' either.
261
+ // (2) The verb set is limited to actions with a universally understood glyph that repeat per
262
+ // row or per card. Save/Cancel/Submit/Add and any multi-word label ("Delete project") are
263
+ // deliberately absent: those are primary buttons whose job is to be read.
264
+ // (3) Case-insensitive on the tag, so a <Button> component matches too; the backreference
265
+ // keeps the closing tag paired with the opening one.
266
+ pattern: "^(?!.*enigma:).*<(button)\\b[^>]*>\\s*(?:Copy|Remove|Delete|Edit|Rename|Duplicate|Download|Share|Refresh|Reload)\\s*</\\1>",
267
+ absent: "enigma:allow-text-actions",
268
+ message: 'Action button labelled with a word. A repeated row or card action (copy, edit, rename, duplicate, remove, delete, download, share, refresh) reads faster and costs far less width as an ICON button: drop the visible word for a single icon taken from the project\'s one icon set, and keep the action reachable without sight - aria-label="<Action> <what it acts on>" for the accessible name, title="<Action>" for the hover tooltip, aria-hidden="true" on the icon itself (an <img> icon carries the same text as its alt instead). Keep a written label only where the design or the user asks for one, or on a primary/confirmation button whose whole job is to be read - then mark the line with an `enigma:` note, or add `enigma:allow-text-actions` to the file (frontend-policy).',
269
+ severity: "block",
270
+ skill: "frontend-policy"
271
+ },
229
272
  {
230
273
  id: "doc-no-file-tree",
231
274
  label: "No ASCII file-tree in the README",
@@ -293,6 +336,17 @@ var BUILTIN_RULES = [
293
336
  severity: "block",
294
337
  skill: "technical-writing-policy"
295
338
  },
339
+ // NOTE: there is deliberately no "Save button with no dirty check" rule, even though
340
+ // no-op detection is one of frontend-policy's headline rules. It has no file-local
341
+ // signature that survives measurement. The dirtiness normally lives in a parent, a store
342
+ // or a form library, so its absence from THIS file proves nothing; the policy explicitly
343
+ // allows an enabled Save that short-circuits on click, so a missing `disabled` is not
344
+ // evidence of the defect either; and the same markup is correct on a create form, which
345
+ // has nothing to compare against. Measured on the corpus: 2 save buttons in 108
346
+ // form-capable files (no signal), and the interaction-based dirty flag that WOULD be a
347
+ // precise signature (a dirty/hasChanges flag assigned a literal true) returned 0 real
348
+ // hits and 2 false ones, a CLI tracking whether it had rewritten a config file. A rule
349
+ // here would fire on correct code, so it stays guidance in frontend-policy.
296
350
  // NOTE: there is deliberately no "card inside a card" or "border with no information"
297
351
  // rule, even though both are named in frontend-policy. They are RELATIONAL defects: a
298
352
  // container is redundant only relative to the ancestor it sits in and the spacing around
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "enigma-cli",
3
- "version": "1.31.2",
3
+ "version": "1.31.4",
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": {