enigma-cli 1.30.12 → 1.31.2

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 (29) hide show
  1. package/README.md +3 -0
  2. package/assets/memory/AGENTS.md +3 -2
  3. package/assets/memory/CLAUDE.md +3 -2
  4. package/assets/skills/anti-overengineering-policy/skill.json +1 -1
  5. package/assets/skills/anti-overengineering-review/skill.json +1 -1
  6. package/assets/skills/backend-policy/skill.json +1 -1
  7. package/assets/skills/ciphera-style-policy/skill.json +1 -1
  8. package/assets/skills/code-review-policy/skill.json +1 -1
  9. package/assets/skills/core-engineering-policy/skill.json +1 -1
  10. package/assets/skills/database-expert/skill.json +1 -1
  11. package/assets/skills/debugging-policy/skill.json +1 -1
  12. package/assets/skills/dependency-policy/skill.json +1 -1
  13. package/assets/skills/frontend-design/SKILL.md +5 -5
  14. package/assets/skills/frontend-design/skill.json +4 -4
  15. package/assets/skills/frontend-policy/SKILL.md +55 -5
  16. package/assets/skills/frontend-policy/skill.json +5 -5
  17. package/assets/skills/git-policy/skill.json +1 -1
  18. package/assets/skills/logo-sourcing-policy/skill.json +1 -1
  19. package/assets/skills/security-policy/skill.json +1 -1
  20. package/assets/skills/skill-creator/skill.json +1 -1
  21. package/assets/skills/task-completion-policy/SKILL.md +5 -3
  22. package/assets/skills/task-completion-policy/skill.json +4 -4
  23. package/assets/skills/technical-writing-policy/SKILL.md +8 -1
  24. package/assets/skills/technical-writing-policy/skill.json +5 -5
  25. package/assets/skills/testing-policy/skill.json +1 -1
  26. package/assets/skills/validation-policy/skill.json +1 -1
  27. package/bin/checksums.json +4 -4
  28. package/dist/guardrails.js +122 -1
  29. package/package.json +1 -1
package/README.md CHANGED
@@ -86,6 +86,9 @@ enigma skills ... List skills and manage discards (list/discard/restore)
86
86
  enigma compress [file] Compress JSON/logs/text to fewer tokens (reversible via CCR);
87
87
  --retrieve <hash> restores, --stats shows total savings,
88
88
  --clear wipes all dashboard data (stats/history/cache)
89
+ enigma verify Check that work reported as finished actually is: scans the change for
90
+ unfinished work and runs your verification command. parity <src> <dst>
91
+ compares a codebase against a port of it. Also runs at turn end
89
92
  enigma mcp Run the context-compression MCP server over stdio
90
93
  enigma dashboard|dash Open the local dashboard (manage enigma; see savings) in your browser (http://enigma,
91
94
  or http://localhost:24282 if :80/hosts is unavailable)
@@ -43,13 +43,14 @@ Non-negotiable, language-agnostic defaults - apply them by default without being
43
43
 
44
44
  ### Task Execution (Always-On)
45
45
 
46
- - Treat correctness as mission-critical: do the work excellently, as if lives depend on it being right. Finish every part of what was asked with nothing left pending, and before claiming it is done VERIFY it actually works - exercise the exact behavior requested (run it, test it, reproduce the scenario), not merely that it compiles or typechecks. If you have not verified it, do not say it is done; state precisely what remains or is unverified.
46
+ - Treat every task as mission-critical: assume lives and irreversible consequences ride on this being genuinely correct, and that nobody will re-read your work before relying on it. A false report of success is therefore far worse than an honest failure. Finish every part of what was asked with nothing left pending, and before claiming it is done VERIFY it actually works - exercise the exact behavior requested (run it, test it, reproduce the scenario), not merely that it compiles or typechecks. If you have not verified it, do not say it is done; state precisely what remains or is unverified.
47
47
  - A message that bundles several asks, questions, or items is a MULTI-PART task - even if it is just two, three, or four things. Before doing anything, extract EVERY distinct ask into an explicit list (the runtime's todo system when it has one, else a written checklist) and treat the request as unfinished until every item on that list is addressed. Never answer the first ask and drop, summarize away, or postpone the rest. When you present a plan, execute the whole plan - do not stop after listing it.
48
48
  - For long or complex tasks - or any task you judge to warrant it - break the work into smaller, well-scoped subtasks and complete them incrementally, validating each subtask before moving to the next. Map the dependencies between subtasks first, and do only the decomposition the task genuinely needs - never over-decompose simple work.
49
49
  - For multi-item work (ports, migrations, batch changes), enumerate the FULL inventory of work units with deterministic commands before implementing, persist it as a checklist (file or todo system), and mark a unit done only after verifying it - never because a similar unit worked. This is the task-completion-policy skill; load it for any task that spans many files/items or bundles several asks.
50
50
  - "Pending", "pendiente", "TODO", "left as a follow-up", "next step: ...", or "you can do X yourself" is NOT an acceptable way to end a turn for work you are able to perform now. Do that work in this same turn. The only reasons to stop short are a genuine blocker - missing credentials or access, an irreversible or destructive choice, a business decision, or something the user explicitly approved deferring - and then you must name the blocker explicitly, never leave the item silently unfinished.
51
51
  - Do not stop early because a task is long, tedious, or the context is filling up. Keep going until every enumerated item is finished or truly blocked. If work is genuinely paused, the checklist holds the remaining items - on resume, re-read it FIRST and continue from it; never reconstruct progress from memory, that is where items get dropped.
52
- - Never declare a task complete while any item is pending, stubbed, or unverified. Before saying "done": reconcile against the checklist, build/typecheck the whole artifact, and grep for TODO/stub markers you introduced. If anything remains, say exactly what remains instead of rounding up to "done". Never silently skip or stub an item - record it with a reason and report it.
52
+ - Never declare a task complete while any item is pending, stubbed, or unverified. Before saying "done": reconcile against the checklist, build/typecheck the whole artifact, and run `enigma verify` - it checks what you actually produced for unfinished work and runs the project's verification command. For a port, clone, or migration also run `enigma verify parity <source> <target>`, which reports any module that was never carried over. If anything remains, say exactly what remains instead of rounding up to "done". Never silently skip or stub an item - record it with a reason and report it.
53
+ - Implement what was asked at the difficulty it actually has. Never quietly substitute a simplified stand-in because the real thing is tedious or hard - no regex where a real parser is required, no hardcoded special case where the general logic was asked for, no empty module, no "equivalent for now". If a faithful implementation is genuinely impossible here, say so explicitly and say why; downgrading it silently and then reporting success is the single worst outcome.
53
54
  - Never offload doable work to the user: "you can adjust/refresh X yourself" in a final report is a hidden deferral. If you can execute the action, do it before reporting; hand off only what genuinely requires the user (credentials, irreversible/destructive choices, business decisions) or what they explicitly approved deferring.
54
55
 
55
56
  <!-- enigma:parallel-subagents:start -->
@@ -43,13 +43,14 @@ Non-negotiable, language-agnostic defaults - apply them by default without being
43
43
 
44
44
  ### Task Execution (Always-On)
45
45
 
46
- - Treat correctness as mission-critical: do the work excellently, as if lives depend on it being right. Finish every part of what was asked with nothing left pending, and before claiming it is done VERIFY it actually works - exercise the exact behavior requested (run it, test it, reproduce the scenario), not merely that it compiles or typechecks. If you have not verified it, do not say it is done; state precisely what remains or is unverified.
46
+ - Treat every task as mission-critical: assume lives and irreversible consequences ride on this being genuinely correct, and that nobody will re-read your work before relying on it. A false report of success is therefore far worse than an honest failure. Finish every part of what was asked with nothing left pending, and before claiming it is done VERIFY it actually works - exercise the exact behavior requested (run it, test it, reproduce the scenario), not merely that it compiles or typechecks. If you have not verified it, do not say it is done; state precisely what remains or is unverified.
47
47
  - A message that bundles several asks, questions, or items is a MULTI-PART task - even if it is just two, three, or four things. Before doing anything, extract EVERY distinct ask into an explicit list (the runtime's todo system when it has one, else a written checklist) and treat the request as unfinished until every item on that list is addressed. Never answer the first ask and drop, summarize away, or postpone the rest. When you present a plan, execute the whole plan - do not stop after listing it.
48
48
  - For long or complex tasks - or any task you judge to warrant it - break the work into smaller, well-scoped subtasks and complete them incrementally, validating each subtask before moving to the next. Map the dependencies between subtasks first, and do only the decomposition the task genuinely needs - never over-decompose simple work.
49
49
  - For multi-item work (ports, migrations, batch changes), enumerate the FULL inventory of work units with deterministic commands before implementing, persist it as a checklist (file or todo system), and mark a unit done only after verifying it - never because a similar unit worked. This is the task-completion-policy skill; load it for any task that spans many files/items or bundles several asks.
50
50
  - "Pending", "pendiente", "TODO", "left as a follow-up", "next step: ...", or "you can do X yourself" is NOT an acceptable way to end a turn for work you are able to perform now. Do that work in this same turn. The only reasons to stop short are a genuine blocker - missing credentials or access, an irreversible or destructive choice, a business decision, or something the user explicitly approved deferring - and then you must name the blocker explicitly, never leave the item silently unfinished.
51
51
  - Do not stop early because a task is long, tedious, or the context is filling up. Keep going until every enumerated item is finished or truly blocked. If work is genuinely paused, the checklist holds the remaining items - on resume, re-read it FIRST and continue from it; never reconstruct progress from memory, that is where items get dropped.
52
- - Never declare a task complete while any item is pending, stubbed, or unverified. Before saying "done": reconcile against the checklist, build/typecheck the whole artifact, and grep for TODO/stub markers you introduced. If anything remains, say exactly what remains instead of rounding up to "done". Never silently skip or stub an item - record it with a reason and report it.
52
+ - Never declare a task complete while any item is pending, stubbed, or unverified. Before saying "done": reconcile against the checklist, build/typecheck the whole artifact, and run `enigma verify` - it checks what you actually produced for unfinished work and runs the project's verification command. For a port, clone, or migration also run `enigma verify parity <source> <target>`, which reports any module that was never carried over. If anything remains, say exactly what remains instead of rounding up to "done". Never silently skip or stub an item - record it with a reason and report it.
53
+ - Implement what was asked at the difficulty it actually has. Never quietly substitute a simplified stand-in because the real thing is tedious or hard - no regex where a real parser is required, no hardcoded special case where the general logic was asked for, no empty module, no "equivalent for now". If a faithful implementation is genuinely impossible here, say so explicitly and say why; downgrading it silently and then reporting success is the single worst outcome.
53
54
  - Never offload doable work to the user: "you can adjust/refresh X yourself" in a final report is a hidden deferral. If you can execute the action, do it before reporting; hand off only what genuinely requires the user (credentials, irreversible/destructive choices, business decisions) or what they explicitly approved deferring.
54
55
 
55
56
  <!-- enigma:parallel-subagents:start -->
@@ -7,6 +7,6 @@
7
7
  "minimalCode"
8
8
  ],
9
9
  "updated": "2026-07-17T00:17:02+02:00",
10
- "cliVersion": "1.30.12",
10
+ "cliVersion": "1.31.2",
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.30.12",
7
+ "cliVersion": "1.31.2",
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.30.12",
7
+ "cliVersion": "1.31.2",
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.30.12",
7
+ "cliVersion": "1.31.2",
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.30.12",
7
+ "cliVersion": "1.31.2",
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.30.12",
7
+ "cliVersion": "1.31.2",
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.30.12",
7
+ "cliVersion": "1.31.2",
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.30.12",
7
+ "cliVersion": "1.31.2",
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.30.12",
7
+ "cliVersion": "1.31.2",
8
8
  "sha": "6375d835c2aef2c9bd31ce116444dc3d796f510f9970a213aa3ac4696d7e21b9"
9
9
  }
@@ -9,7 +9,7 @@ Approach this as the design lead at a small studio known for giving every client
9
9
 
10
10
  ## Ground it in the subject
11
11
 
12
- If the brief does not pin down what the product or subject is, pin it yourself before designing: name one concrete subject, its audience, and the page's single job, and state your choice. If there's any information in your memory about the human's preferences, context about what they're building, or designs you've made before use that as a hint. The subject's own world, its materials, instruments, artifacts, and vernacular, is where distinctive choices come from. Build with the brief's real content and subject matter throughout.
12
+ If the brief does not pin down what the product or subject is, pin it yourself before designing: name one concrete subject, its audience, and the page's single job, and state your choice. If there's any information in your memory about the human's preferences, context about what they're building, or designs you've made before - use that as a hint. The subject's own world, its materials, instruments, artifacts, and vernacular, is where distinctive choices come from. Build with the brief's real content and subject matter throughout.
13
13
 
14
14
  ## Design principles
15
15
 
@@ -27,11 +27,11 @@ Consider written content carefully. Often a design brief may not contain real co
27
27
 
28
28
  ## Process: brainstorm, explore, plan, critique, build, critique again
29
29
 
30
- For calibration: AI-generated design right now clusters around three looks: (1) a warm cream background (near #F4F1EA) with a high-contrast serif display and a terracotta accent; (2) a near-black background with a single bright acid-green or vermilion accent; (3) a broadsheet-style layout with hairline rules, zero border-radius, and dense newspaper-like columns. All three are legitimate for some briefs, but they are defaults rather than choices, and they appear regardless of subject. Where the brief pins down a visual direction, follow it exactly the brief's own words always win, including when it asks for one of these looks. Where it leaves an axis free, don't spend that freedom on one of these defaults. Just like a human designer who's hired, there's often a careful balance between doing what you're good at and taking each project as a chance to experiment and learn.
30
+ For calibration: AI-generated design right now clusters around three looks: (1) a warm cream background (near #F4F1EA) with a high-contrast serif display and a terracotta accent; (2) a near-black background with a single bright acid-green or vermilion accent; (3) a broadsheet-style layout with hairline rules, zero border-radius, and dense newspaper-like columns. All three are legitimate for some briefs, but they are defaults rather than choices, and they appear regardless of subject. Where the brief pins down a visual direction, follow it exactly - the brief's own words always win, including when it asks for one of these looks. Where it leaves an axis free, don't spend that freedom on one of these defaults. Just like a human designer who's hired, there's often a careful balance between doing what you're good at and taking each project as a chance to experiment and learn.
31
31
 
32
- Work in two passes. First, brainstorm a short design plan based on the human's design brief: create a compact token system with color, type, layout, and signature. Color: describe the palette as 46 named hex values. Type: the typefaces for 2+ roles (a characterful display face that's used with restraint, a complementary body face, and a utility face for captions or data if needed). Layout: a layout concept, using one-sentence prose descriptions and ASCII wireframes to ideate and compare. Signature: the single unique element this page will be remembered by that embodies the brief in an appropriate way.
32
+ Work in two passes. First, brainstorm a short design plan based on the human's design brief: create a compact token system with color, type, layout, and signature. Color: describe the palette as 4-6 named hex values. Type: the typefaces for 2+ roles (a characterful display face that's used with restraint, a complementary body face, and a utility face for captions or data if needed). Layout: a layout concept, using one-sentence prose descriptions and ASCII wireframes to ideate and compare. Signature: the single unique element this page will be remembered by that embodies the brief in an appropriate way.
33
33
 
34
- Then review that plan against the brief before building: if any part of it reads like the generic default you would produce for any similar page (work through a similar prompt to see if you arrive somewhere similar) rather than a choice made for this specific brief revise that part, say what you changed and why. Only after you've confirmed the relative uniqueness of your design plan should you start to write the code, following the revised plan exactly and deriving every color and type decision from it.
34
+ Then review that plan against the brief before building: if any part of it reads like the generic default you would produce for any similar page (work through a similar prompt to see if you arrive somewhere similar) rather than a choice made for this specific brief - revise that part, say what you changed and why. Only after you've confirmed the relative uniqueness of your design plan should you start to write the code, following the revised plan exactly and deriving every color and type decision from it.
35
35
 
36
36
  When writing the code, be careful of structuring your CSS selector specificities. It's easy to generate CSS classes that cancel each other out (especially with a type-based selector like .section and a element-based selector like .cta). This can happen often with paddings/margins between sections.
37
37
 
@@ -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. 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. 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.4.0",
3
+ "version": "1.5.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-06-25T15:51:43-04:00",
7
- "cliVersion": "1.30.12",
8
- "sha": "fb78be3233bf9caa67d1f522c19831542b23f47e440b02211b5a950c898318b9"
6
+ "updated": "2026-07-28T20:30:12+02:00",
7
+ "cliVersion": "1.31.2",
8
+ "sha": "5fbc294a4f33aba03fd93e76e0cfeeefe04389b6c8e8493043dc4036ad8f4d19"
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, responsive/adaptive layout (fluid units, breakpoints, no overlap or horizontal overflow, viewport meta, touch targets), 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, 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), 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.
4
4
  ---
5
5
 
6
6
  # Frontend Architecture Policy
@@ -66,11 +66,23 @@ description: Frontend architecture - reusable components, abstraction thresholds
66
66
 
67
67
  ## Visual Hierarchy & Layout Restraint
68
68
 
69
- Keep surfaces flat and let spacing, not chrome, do the grouping.
69
+ Less is more. Chrome - borders, boxes, cards, shadows, dividers - is the most overused tool in generated UI, and every extra layer of it makes the screen harder to read, not more organized. Grouping is done with space first; a container is the last resort, not the default wrapper.
70
70
 
71
- - Do not nest a card inside another card. A card already establishes a surface; wrapping cards in cards stacks backgrounds, paddings, and shadows into visual noise. Group related content inside one card with spacing, a heading, or a light divider - not a second bordered container.
72
- - Do not add borders, boxes, or dividers that carry no information. A border is justified only when it marks a real boundary the user needs (a distinct interactive region, a table edge); otherwise prefer whitespace, type weight, and grouping over outlines, and reach for a divider only when spacing alone cannot convey the separation.
73
- - Avoid redundant containers in general: one elevation/background per surface, minimal wrapping, and consistent padding read cleaner and are easier to maintain than deeply nested boxed layouts.
71
+ **One surface level.** A card already IS a surface. Do not put a card inside a card, and never nest a third: stacked backgrounds, paddings and shadows read as visual noise and shrink the usable content width at every level. Related content inside a card is grouped with spacing, a heading, or at most a light divider - not with a second bordered box. If a block genuinely needs its own container, promote it to a sibling card rather than nesting it.
72
+
73
+ **Separate with space before you separate with lines.** There are three ways to show that two blocks are distinct, in order of preference:
74
+
75
+ 1. Spacing - more space between groups than within them. This is almost always enough, and it is what a border is usually compensating for.
76
+ 2. A second background tone - the same neutral one step lighter or darker. Use it for a genuinely different surface (a sidebar, a highlighted panel), not for every block.
77
+ 3. A border or divider - only when the two blocks must sit flush with no room for space, such as a table edge or a list of rows.
78
+
79
+ Never apply more than one of the three to the same boundary. A block with a border AND a shadow AND a background tint is three solutions to one problem.
80
+
81
+ **A border must carry information.** It is justified when it marks a real boundary the user acts on (an input, a distinct interactive region, a table edge). A border drawn around content just to make it "look contained" carries none, so remove it. The same goes for a divider between two blocks that already have space between them.
82
+
83
+ **Shadows imply one light source.** Pick a small elevation scale (two or three levels) and use it consistently, with the light always coming from the same direction - a soft shadow offset downwards, larger and softer the higher the element sits. Never ring an element with shadow on all sides, stack several shadows on one element, or use elevation decoratively on something that is not raised above the page.
84
+
85
+ **Fewer, larger, quieter.** Prefer one padded region over four nested ones; consistent padding over per-block variation; and type weight, size and colour over outlines when establishing hierarchy. If a screen looks busy, the fix is almost always to delete containers, not to restyle them.
74
86
 
75
87
  ---
76
88
 
@@ -87,6 +99,21 @@ Build every UI to adapt to the viewport; never assume a desktop width. A layout
87
99
 
88
100
  ---
89
101
 
102
+ ## Text That Does Not Fit (Variable-Length Content)
103
+
104
+ Every string is variable-length; the value on screen during development is one sample. Text escaping its card or colliding with a neighbour is the most common layout defect, it is invisible until the content changes, and it is the responsibility of whoever writes the layout - not something to be pointed out afterwards.
105
+
106
+ - Design for the extremes of each string, not the sample: the longest realistic value (an unbounded user-supplied name, a long identifier, a full path, a big formatted number) and the shortest (empty, one character). Translations run noticeably longer than English - roughly a third more for German - so a label that only just fits is already broken.
107
+ - **A flex or grid item whose overflow is visible refuses to shrink below its content** (its automatic minimum size, `min-width: auto`). This causes most "text sticks out of its card" bugs, but not where people look for it: an element that truncates has already set `overflow: hidden`, which resolves that minimum to 0, so it shrinks by itself and does NOT need `min-width: 0`. The culprit is nearly always an **ancestor** - a flex or grid item with default overflow wrapping the truncating element. Put `min-width: 0` (Tailwind `min-w-0`) on those ancestors, and use `minmax(0, 1fr)` rather than a bare `1fr` for a grid track holding text. Confirm by measuring which box actually overflows rather than scattering `min-w-0` until it looks right.
108
+ - Decide per string whether it wraps or truncates. Truncation needs `overflow: hidden` - `text-overflow: ellipsis` does nothing without it - and the full value must stay reachable via `title`, a tooltip, or an accessible label. Never truncate a value the user has no way to recover.
109
+ - Long unbroken strings (URLs, tokens, hashes, ids, file paths) have no spaces to wrap at and will push their container wide. Use `overflow-wrap: anywhere` on those. Prefer it over `word-break: break-word`: it also lowers the element's min-content width, which is what actually stops the track being forced wider.
110
+ - Content whose width changes as it updates (counters, timers, prices) reflows its row on every tick. Use tabular numerals (`font-variant-numeric: tabular-nums`) or reserve the space.
111
+ - Absolutely positioned or overlaid text is where collisions happen, because it is outside normal flow and cannot push anything away. Constrain it with a `max-width` and check it at the narrowest breakpoint.
112
+ - Do not "fix" an overflow by clipping the parent. `overflow: hidden` on the container hides the symptom, and clips focus rings, tooltips and menus with it. Fix the sizing that caused it.
113
+ - Verify with worst-case content before calling it done: render the longest value you expect and confirm nothing spills out of its box or over a neighbour. The mechanical check is `element.scrollWidth <= element.clientWidth` for the box, and comparing bounding rectangles against the container for the collision - cheaper and more reliable than eyeballing it at one window size.
114
+
115
+ ---
116
+
90
117
  ## State Management
91
118
 
92
119
  - Keep state as local as possible; lift it only when genuinely shared.
@@ -269,6 +296,29 @@ For a user-facing search box or finder over a list, use fuse.js (fuzzy search) r
269
296
 
270
297
  ---
271
298
 
299
+ ## AI Chat & Agent Interfaces
300
+
301
+ When building a chat, assistant, or agent UI in React, use **AI Elements** (Vercel, Apache-2.0 - https://elements.ai-sdk.dev/components) instead of hand-rolling the surface. Chat UI has a long tail of details that look trivial and are not: sticking the scroll to the bottom only while the user has not scrolled away, rendering markdown whose code fence is still unclosed mid-stream, message parts that arrive out of order, reasoning and tool-call panels, citation rendering, and an input that handles attachments, submit-vs-newline, and a streaming stop button. Rebuilding that per project is where the time goes, and the hand-rolled version is usually the janky part of the product.
302
+
303
+ - It is a **shadcn/ui registry, not a runtime dependency**: `npx ai-elements@latest add <component>` copies the component SOURCE into `@/components/ai-elements/`, so it is yours to edit and restyle with no version lock-in. This is the vendoring preference in dependency-policy, not a new dependency to justify.
304
+ - Prerequisites: React with Tailwind CSS in CSS-variables mode, shadcn/ui initialized (`npx shadcn@latest init`), and the AI SDK. The components are typed against AI SDK message parts and pair with `useChat`.
305
+ - Add only the components actually used. Bare `npx ai-elements@latest` installs the whole registry and drags in every peer dependency (shiki, `@xyflow/react`, media-chrome, rive, ...) - do not pull 40+ components in for one message list (anti-overengineering-policy).
306
+
307
+ ### What already exists (do not rebuild these)
308
+
309
+ - Chat shell: `conversation`, `message`, `prompt-input`, `suggestion`, `attachments`, `context`, `persona`, `panel`, `toolbar`, `controls`, `queue`, `checkpoint`, `confirmation`, `open-in-chat`.
310
+ - Model work: `reasoning`, `chain-of-thought`, `tool`, `task`, `plan`, `agent`, `artifact`, `shimmer`.
311
+ - Rendered content: `code-block`, `snippet`, `image`, `jsx-preview`, `schema-display`, `file-tree`, `terminal`, `stack-trace`, `test-results`, `web-preview`, `sandbox`, `commit`, `package-info`, `environment-variables`.
312
+ - Citations: `sources`, `inline-citation`. Voice: `speech-input`, `transcription`, `audio-player`, `mic-selector`, `voice-selector`. Models: `model-selector`. Graph: `canvas`, `node`, `edge`, `connection`.
313
+
314
+ ### Boundaries
315
+
316
+ - This is a React + Tailwind + shadcn library. If the project is Vue, Svelte, Angular, React Native, or plain HTML, or has no Tailwind/shadcn, do NOT bolt that toolchain on to get it - build natively and borrow the composition model instead (a container owning scroll-stick-to-bottom, a message that renders parts by type, a separate prompt input, streaming state held outside the bubble).
317
+ - Once installed they are ordinary project components: the Component Reuse rules above still apply - configure variants through props, and never fork a second copy per screen.
318
+ - A single static message list with no streaming does not need the library. Match the tool to the problem.
319
+
320
+ ---
321
+
272
322
  ## Accessibility & Resilience
273
323
 
274
324
  - Use semantic markup and accessible interactive elements by default.
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "frontend-policy",
3
- "version": "1.15.0",
3
+ "version": "1.18.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, and responsive/adaptive layout (fluid units, breakpoints, no overlap/overflow, viewport meta, touch targets).",
6
- "updated": "2026-07-24T01:21:27+02:00",
7
- "cliVersion": "1.30.12",
8
- "sha": "a879c95e63a6b4c4ca1f0561a6050c3ce1402e1311dfb30191f17f6c995001a3"
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"
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.30.12",
7
+ "cliVersion": "1.31.2",
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.30.12",
10
+ "cliVersion": "1.31.2",
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.30.12",
7
+ "cliVersion": "1.31.2",
8
8
  "sha": "9971e9d9127397d0152e89d24aad3191e2935e55a8483db7fd15f5d4d7a60e7a"
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-06-16T16:39:13+02:00",
7
- "cliVersion": "1.30.12",
7
+ "cliVersion": "1.31.2",
8
8
  "sha": "699586cce82ec0a5458288b598ee7e5ebdddb3dfcf19db354d8bc5e85e47c1c7"
9
9
  }
@@ -47,11 +47,13 @@ A completion claim is forbidden unless ALL of these hold:
47
47
  1. The ledger has zero `pending` and zero `blocked` units. `deferred` units require the user's explicit approval and must appear in the final report.
48
48
  2. Counts reconcile mechanically: target counts match the inventory (files ported vs source files, symbols vs symbols, endpoints vs endpoints). Run the comparison commands; never estimate.
49
49
  3. The whole artifact builds/compiles/typechecks and the test suite (or smoke run) passes - not just the last file touched.
50
- 4. A final sweep finds no incompleteness markers introduced by this task: grep the produced code for TODO, FIXME, "not implemented", placeholder/stub patterns. Every hit is fixed or explicitly reported.
51
- 5. Self-review per code-review-policy.
50
+ 4. A final sweep finds no incompleteness markers introduced by this task: run `enigma verify`, which scans exactly the code this change produced for TODO/FIXME markers, unimplemented paths and placeholders, and runs the project's configured verification command. Every hit is fixed or explicitly reported.
51
+ 5. For a port, clone, or migration, `enigma verify parity <source> <target>` reports zero absent modules. It compares the two codebases by symbol, so a module that was never carried over - the failure this phase exists to catch - cannot hide. Partially covered modules are explained or finished. Coverage matches symbol names, so it proves a counterpart exists, never that its behavior was ported faithfully; check the behavior of anything non-trivial yourself.
52
+ 6. Self-review per code-review-policy.
52
53
 
53
54
  - If any check fails, the task is NOT done: state exactly what remains and keep working (or report the blocker). Never say "everything is complete", "fully ported", or "all done" while the ledger has open units.
54
- - Words like "complete", "all", "every", and "fully" in a final report are claims that must be backed by checks 1-4.
55
+ - Words like "complete", "all", "every", and "fully" in a final report are claims that must be backed by checks 1-5.
56
+ - These checks also run automatically at turn end: when a final message claims the work is finished, enigma re-runs them and denies the stop if the evidence contradicts the claim (see the verify concept). Treat that as a backstop for accidents, never as the thing that does the checking - a claim it has to catch was one that should never have been made.
55
57
 
56
58
  ---
57
59
 
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "task-completion-policy",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Exhaustive completion discipline for long/multi-item tasks - inventory, coverage ledger, verified done.",
6
- "updated": "2026-07-21T20:25:56+02:00",
7
- "cliVersion": "1.30.12",
8
- "sha": "feaf44a9b3ab9676c8ebd3c2a799f156d28419998f5a5355250fe95a28cd5a01"
6
+ "updated": "2026-07-27T17:22:17+02:00",
7
+ "cliVersion": "1.31.2",
8
+ "sha": "b9046c15fd636057a8e42e199d2eeb47297477f38a0a26a07a7b0bf71d61fcb4"
9
9
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: technical-writing-policy
3
- description: Concise, realistic technical copy - UI microcopy, labels, descriptions, setting hints, empty/error states, and README/doc prose that informs without over-explaining, restating the obvious, or leaking implementation detail. Use whenever writing or reviewing user-facing text: a dashboard/app label or description, a settings hint, a panel intro, a button, a skill/package description, a README section, or any doc copy. Also use when the user complains that descriptions are too long, over-explained, obvious, or "cutre".
3
+ description: Concise, realistic technical copy - UI microcopy, labels, descriptions, setting hints, empty/error states, and README/doc prose that informs without over-explaining, restating the obvious, or leaking implementation detail, and that never uses an em dash. Use whenever writing or reviewing user-facing text: a dashboard/app label or description, a settings hint, a panel intro, a button, a skill/package description, a README section, or any doc copy. Also use when the user complains that descriptions are too long, over-explained, obvious, or "cutre".
4
4
  ---
5
5
 
6
6
  # Technical Writing Policy (Concise, Realistic Copy)
@@ -62,6 +62,13 @@ microcopy - the reader shouldn't have to study it.
62
62
  - READMEs: assume a competent reader. Explain what is non-obvious or load-bearing (how to
63
63
  run it, the one surprising constraint, why a choice was made) and skip what the audience
64
64
  already knows or can infer from the code. Lead with the point; cut the throat-clearing.
65
+ - Never use a typographic dash in user-facing copy. The em dash (`—`) and en dash (`–`) are
66
+ the single most recognizable tell of AI-written text in an interface, and no product's UI
67
+ needs them: use a plain hyphen "-", a comma, a colon, or two sentences, and write a range
68
+ as "5 to 10". This applies to every string a person reads - labels, hints, empty and error
69
+ states, tooltips, toasts, docs and README prose. Keep one only when the dash is the
70
+ subject (a typography guide, a punctuation rule) or when quoting text verbatim, and, as
71
+ with every rule here, when the user explicitly asks for it.
65
72
  - Do NOT volunteer a "Project Structure" section with an ASCII/box-drawing file tree and a
66
73
  folder-by-folder explanation ("src/ contains the files of the application", "public/:
67
74
  contains static files") on your own initiative. It is the hallmark of an AI-written README:
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "technical-writing-policy",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "provider": "FJRG2007/enigma",
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.",
6
- "updated": "2026-07-22T01:41:06+02:00",
7
- "cliVersion": "1.30.12",
8
- "sha": "a8c008fac91782de0d4ef1a4ae6ee77d69e3c0a506ea06b649aa86a6c988bc4f"
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
+ "updated": "2026-07-28T20:30:23+02:00",
7
+ "cliVersion": "1.31.2",
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.30.12",
7
+ "cliVersion": "1.31.2",
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.30.12",
7
+ "cliVersion": "1.31.2",
8
8
  "sha": "d937df0052d1ec151728a28f6567744d9e7ca0a65d84b4d5c9a697f1e40d704f"
9
9
  }
@@ -1,6 +1,6 @@
1
1
  {
2
- "enigma-darwin-arm64": "d6303afdc1a1a80a91fe39a34c80a876233c65efadb4da112326bf430be630ea",
3
- "enigma-linux-arm64": "ce919fe57701f464247347259ba7f5cb476855177240c77f43891f0b28f287df",
4
- "enigma-linux-x64": "46fcba8fff3bd3a6cb388f28cdc28449c2c6abbe2fd43edafc955c0d2610a806",
5
- "enigma-win32-x64.exe": "02d5c95184985e05622457c3a9d5ca2dbb1c616f2e1b35282d642efae57ea52a"
2
+ "enigma-darwin-arm64": "f868bd329a528c8eed63280c32f220e0fe741987666aea5f1f3ca8af2d951269",
3
+ "enigma-linux-arm64": "d2325149898a37cb13607b4ebd4e08b32d676c5ae4aa49b7f436539c8c430c2d",
4
+ "enigma-linux-x64": "464c390daea135ff90d490b6e8c2b154dd50fb705270b35528c86a04ae2df772",
5
+ "enigma-win32-x64.exe": "d39a5d9968903afea8795145200209612f63384d5c4d2985436ef1c2d857f876"
6
6
  }
@@ -156,6 +156,25 @@ var BUILTIN_RULES = [
156
156
  severity: "warn",
157
157
  skill: "frontend-policy"
158
158
  },
159
+ {
160
+ id: "fe-ai-elements-chat",
161
+ label: "AI chat UI via AI Elements",
162
+ files: ["*.tsx", "*.jsx"],
163
+ excludeFiles: ["*.test.*", "*.spec.*", "**/tests/**", "**/__tests__/**", "**/dist/**", "**/build/**", "**/_build/**", "**/node_modules/**"],
164
+ scope: "file",
165
+ // A JSX file branching on a message role of "assistant" is hand-rolled AI chat UI. The role
166
+ // value is what makes this precise: "user"/"admin"/"owner"/"member" are the RBAC vocabulary
167
+ // and appear far more often than chat rendering does, so matching them would false-positive
168
+ // on every permission check - "assistant" has no meaning outside an LLM conversation.
169
+ // Measured over a real multi-repo corpus: 15 matching files, all genuine chat surfaces, 0 FP.
170
+ // `absent` skips a file that already uses AI Elements or another established chat-UI kit.
171
+ pattern: `\\.role\\s*===?\\s*["']assistant["']`,
172
+ flags: "",
173
+ absent: "ai-elements|assistant-ui|@assistant-ui|copilotkit|@copilotkit|llm-ui|@nlux|nlux|@chatscope|chatscope",
174
+ message: "Hand-rolled AI chat UI. Use AI Elements (https://elements.ai-sdk.dev/components) - `npx ai-elements@latest add conversation message prompt-input` copies the source into @/components/ai-elements/, so it stays editable with no runtime dependency. It already solves streaming, scroll-stick-to-bottom, markdown with unclosed code fences mid-stream, and reasoning/tool-call/citation panels. Needs React + Tailwind + shadcn/ui; on any other stack build natively instead (frontend-policy).",
175
+ severity: "warn",
176
+ skill: "frontend-policy"
177
+ },
159
178
  {
160
179
  id: "fe-viewport-meta",
161
180
  label: "Responsive viewport meta tag",
@@ -180,6 +199,33 @@ var BUILTIN_RULES = [
180
199
  severity: "warn",
181
200
  skill: "frontend-policy"
182
201
  },
202
+ // NOTE: there is deliberately no "truncating flex item needs min-w-0" rule. It was written
203
+ // and then removed after measuring it in a browser: per CSS Flexbox 4.5 a flex item's
204
+ // automatic minimum size only applies while its computed overflow is visible, and Tailwind's
205
+ // `truncate` sets overflow:hidden - so `flex-1 truncate` already shrinks and ellipsizes, and
206
+ // the rule only ever flagged correct code. The real defect is an ANCESTOR flex/grid item with
207
+ // visible overflow wrapping the truncating element, which spans two elements and so has no
208
+ // single-line signature. It stays in frontend-policy as guidance rather than becoming a rule
209
+ // that cries wolf.
210
+ {
211
+ id: "fe-ellipsis-without-overflow",
212
+ label: "Ellipsis needs overflow hidden",
213
+ files: ["*.css", "*.scss", "*.sass", "*.less", "*.styl", "*.tsx", "*.jsx", "*.vue", "*.svelte", "*.astro", "*.html"],
214
+ excludeFiles: ["*.test.*", "*.spec.*", "**/tests/**", "**/__tests__/**", "**/dist/**", "**/build/**", "*.min.css"],
215
+ scope: "file",
216
+ // text-overflow only applies to a box that actually overflows, so ellipsis without an
217
+ // overflow value does nothing at all - the text just spills. The absent set covers the
218
+ // CSS declarations and the Tailwind utilities that provide it; note it cannot simply be
219
+ // "overflow", which would match the text-overflow property on this very line.
220
+ pattern: "text-overflow\\s*:\\s*ellipsis",
221
+ // Only things that actually PROVIDE the missing overflow value. Tailwind's `truncate`
222
+ // does (it sets overflow-hidden); `text-ellipsis` does not - it is the ellipsis
223
+ // declaration itself, so listing it would suppress the very case being flagged.
224
+ absent: "overflow(?:-x|-y)?\\s*:\\s*(?:hidden|clip|auto|scroll)|overflow-hidden|overflow-clip|\\btruncate\\b",
225
+ message: "text-overflow: ellipsis has no effect without an overflow value other than visible - the text overflows instead of being clipped. Add overflow: hidden (with white-space: nowrap for a single line), and keep the full value reachable via title or a tooltip (frontend-policy).",
226
+ severity: "warn",
227
+ skill: "frontend-policy"
228
+ },
183
229
  {
184
230
  id: "doc-no-file-tree",
185
231
  label: "No ASCII file-tree in the README",
@@ -196,6 +242,63 @@ var BUILTIN_RULES = [
196
242
  severity: "warn",
197
243
  skill: "technical-writing-policy"
198
244
  },
245
+ {
246
+ id: "ui-no-em-dash",
247
+ label: "No typographic dash in UI copy",
248
+ // Files that render text to a person: markup, components and the modules that hold
249
+ // their strings. Markdown is deliberately NOT here - prose files legitimately quote
250
+ // and vendor third-party text, so scanning them would flag content nobody wrote.
251
+ files: ["*.tsx", "*.jsx", "*.vue", "*.svelte", "*.astro", "*.html", "*.htm", "*.ts", "*.js", "*.mts", "*.cts"],
252
+ // The generated/vendored trees are listed twice: `**/x/**` needs a leading segment, so
253
+ // it does NOT match a root-level `dist/main.js` - the usual place for build output.
254
+ excludeFiles: [
255
+ "*.test.*",
256
+ "*.spec.*",
257
+ "**/tests/**",
258
+ "**/__tests__/**",
259
+ "**/fixtures/**",
260
+ "*.min.js",
261
+ "**/dist/**",
262
+ "**/build/**",
263
+ "**/_build/**",
264
+ "**/node_modules/**",
265
+ "**/vendor/**",
266
+ "dist/**",
267
+ "build/**",
268
+ "_build/**",
269
+ "node_modules/**",
270
+ "vendor/**"
271
+ ],
272
+ scope: "file",
273
+ // An em dash (U+2014) or en dash (U+2013) used as PROSE PUNCTUATION: the character
274
+ // must sit between two pieces of text ("saves time - automatically", "60-95%"). Both
275
+ // are written as regex escapes so this file never contains the characters it forbids.
276
+ // Two things keep this precise. (1) The text-on-both-sides requirement skips the
277
+ // standalone glyph - `return "-"` for an empty table cell, a `<span>-</span>`
278
+ // separator, a CLI bullet - which is a deliberate symbol, not copy, and was the only
279
+ // real false-positive class when the rule was measured over ~1100 real UI files.
280
+ // (2) The leading lookahead drops lines where the character is DATA rather than copy:
281
+ // a sanitizer (.replace / normalize), a character or entity table (mdash, ndash,
282
+ // fromCharCode, an escaped \u201x), a line the author marked with `enigma:`, or a
283
+ // line carrying a TRAILING comment - the engine only skips a line that STARTS as a
284
+ // comment, and a dash in a developer note is not user-facing text. `//` is matched
285
+ // only when it is not preceded by a colon, so a URL does not silence a line.
286
+ // `absent` gives a whole file an opt-out for genuinely quoted text.
287
+ // HTML entities (&mdash;) are deliberately not matched: to a line regex an entity
288
+ // table and an entity in copy are identical, so matching them would cost more than
289
+ // it catches.
290
+ pattern: "^(?!.*(?:enigma:|\\.replace|normali|fromCharCode|charCodeAt|mdash|ndash|\\\\u201|(?<!:)//|/\\*)).*[A-Za-z0-9)\\].,:%!?]\\s*[\\u2014\\u2013]\\s*[A-Za-z0-9(\\[\"'`]",
291
+ absent: "enigma:allow-dash",
292
+ message: 'Typographic dash in user-facing text. The em dash and en dash are the clearest tell of AI-written copy and no interface needs them: use a plain hyphen "-", a comma, a colon, or two sentences, and write a range as "5 to 10". Keep one only when the dash is the subject (a typography guide) or the text is quoted verbatim - then mark the line with an `enigma:` note or add `enigma:allow-dash` to the file (technical-writing-policy).',
293
+ severity: "block",
294
+ skill: "technical-writing-policy"
295
+ },
296
+ // NOTE: there is deliberately no "card inside a card" or "border with no information"
297
+ // rule, even though both are named in frontend-policy. They are RELATIONAL defects: a
298
+ // container is redundant only relative to the ancestor it sits in and the spacing around
299
+ // it, and a border is legitimate on an input, a table edge or a flush row list. Neither
300
+ // has a single-line signature, so a regex over `rounded-lg border` would flag correct
301
+ // markup on almost every screen. Visual density stays guidance in frontend-policy.
199
302
  {
200
303
  id: "be-no-leak-internal-error",
201
304
  label: "Do not leak internal errors to the client",
@@ -211,6 +314,21 @@ var BUILTIN_RULES = [
211
314
  message: "Leaking an internal error to the client. Never send a caught exception's .message/.stack (or a raw ORM/DB error) in a 5xx response - it exposes your schema, ORM, and internals. Log it server-side (console.error / your logger) and return a generic message with a stable code (validation-policy, security-policy).",
212
315
  severity: "warn",
213
316
  skill: "validation-policy"
317
+ },
318
+ {
319
+ id: "ctx-memory-budget",
320
+ label: "Agent memory file within its context budget",
321
+ // Basename globs, so this covers the file at any depth. Only the agent memory files:
322
+ // every other doc is read on demand and costs nothing until it is opened.
323
+ files: ["CLAUDE.md", "AGENTS.md"],
324
+ scope: "file",
325
+ // Size has no regex form, hence maxBytes. 40 KB is ~10k tokens paid on EVERY session
326
+ // in the project, relevant or not - a memory file that large is already broken, and
327
+ // the fix (an index plus on-demand docs) is mechanical, so this blocks rather than
328
+ // warns: a warn exits 0 and never reaches the model that keeps growing the file.
329
+ maxBytes: 4e4,
330
+ message: "This memory file loads into every session in the project, so its cost is paid on every task regardless of relevance. Keep it an INDEX: move each subsystem's detail into its own doc (docs/notes/<topic>.md) and leave one line here saying what the note covers and when to read it. Route new conventions by tier - a file-local syntactic signature becomes a guardrail rule, a domain-scoped rule belongs in the owning skill (loaded on demand), and only a truly universal rule stays in memory. Turn this off with `enigma guardrails disable ctx-memory-budget`.",
331
+ severity: "block"
214
332
  }
215
333
  ];
216
334
  var PROJECT_CHECKS = {
@@ -283,7 +401,10 @@ function checkFile(file, content, projectRoot) {
283
401
  if (!rule.files.some((g) => globToRegExp(g).test(norm))) continue;
284
402
  if (rule.excludeFiles?.some((g) => globToRegExp(g).test(norm))) continue;
285
403
  const base = { ruleId: rule.id, severity: rule.severity, file: norm, message: rule.message, skill: rule.skill };
286
- if (rule.scope === "file" && rule.pattern) {
404
+ if (rule.scope === "file" && rule.maxBytes) {
405
+ const bytes = Buffer.byteLength(content, "utf8");
406
+ if (bytes > rule.maxBytes) out.push({ ...base, message: `${rule.message} (${bytes} bytes, budget ${rule.maxBytes})` });
407
+ } else if (rule.scope === "file" && rule.pattern) {
287
408
  if (rule.absent) {
288
409
  try {
289
410
  if (new RegExp(rule.absent, "i").test(content)) continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "enigma-cli",
3
- "version": "1.30.12",
3
+ "version": "1.31.2",
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": {