enigma-cli 1.56.1 → 1.57.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/assets/memory/AGENTS.md +1 -1
  2. package/assets/memory/CLAUDE.md +1 -1
  3. package/assets/skills/anti-overengineering-policy/skill.json +1 -1
  4. package/assets/skills/anti-overengineering-review/skill.json +1 -1
  5. package/assets/skills/backend-policy/skill.json +1 -1
  6. package/assets/skills/ciphera-style-policy/skill.json +1 -1
  7. package/assets/skills/code-review-policy/skill.json +1 -1
  8. package/assets/skills/core-engineering-policy/skill.json +1 -1
  9. package/assets/skills/database-expert/skill.json +1 -1
  10. package/assets/skills/debugging-policy/skill.json +1 -1
  11. package/assets/skills/dependency-policy/skill.json +1 -1
  12. package/assets/skills/email-policy/skill.json +1 -1
  13. package/assets/skills/frontend-design/skill.json +1 -1
  14. package/assets/skills/frontend-policy/SKILL.md +2 -0
  15. package/assets/skills/frontend-policy/skill.json +3 -3
  16. package/assets/skills/git-policy/SKILL.md +3 -2
  17. package/assets/skills/git-policy/skill.json +3 -3
  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 +7 -0
  22. package/assets/skills/task-completion-policy/skill.json +3 -3
  23. package/assets/skills/technical-writing-policy/skill.json +1 -1
  24. package/assets/skills/testing-policy/skill.json +1 -1
  25. package/assets/skills/validation-policy/SKILL.md +1 -1
  26. package/assets/skills/validation-policy/skill.json +2 -2
  27. package/bin/checksums.json +4 -4
  28. package/dist/guardrails.js +73 -0
  29. package/dist/post-edit.js +73 -0
  30. package/package.json +1 -1
@@ -53,7 +53,7 @@ Non-negotiable, language-agnostic defaults - apply them by default without being
53
53
 
54
54
  ### Task Execution (Always-On)
55
55
 
56
- - 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.
56
+ - Treat every task as mission-critical: lives and irreversible consequences ride on it and nobody re-reads your work before relying on it, so a false success is far worse than an honest failure. Finish every part with nothing pending, and before saying it works VERIFY it - run the exact behavior requested, not a compile or typecheck. A claim says no more than you observed: "fixed", "works", "deployed", "published" mean seen where the user meets it - the delivered artifact past CI and caches, their roles, locales, environments and data, the full round trip; otherwise state what you checked, where, and what stays unverified.
57
57
  - Then, before reporting, run the pass the user would otherwise force with "are you 100% sure?": review your own diff as a hostile reviewer - re-run the original failing scenario, try the edges (empty, huge, concurrent, unauthenticated, old data), check every caller of what you changed - and fix what it finds. Confidence comes from evidence you ran, never from having written the code.
58
58
  - Change safely without being told: existing behavior is preserved unless changing it IS the task. Public APIs, CLI flags, config keys, schemas, file formats and events stay backward compatible (add, deprecate, never silently rename or remove). No data loss: migrations are additive and reversible, destructive steps get a backup or dry run first, and a change applies retroactively - existing records, users and installs are migrated or backfilled, not only new ones.
59
59
  - For a new feature, an unfamiliar problem, or a design with real alternatives, research prior art first when the runtime can search: docs, GitHub issues and established OSS implementations, forums. Build on the technique that proven projects converged on and name the source in one line. Skip it for trivial or purely local edits.
@@ -53,7 +53,7 @@ Non-negotiable, language-agnostic defaults - apply them by default without being
53
53
 
54
54
  ### Task Execution (Always-On)
55
55
 
56
- - 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.
56
+ - Treat every task as mission-critical: lives and irreversible consequences ride on it and nobody re-reads your work before relying on it, so a false success is far worse than an honest failure. Finish every part with nothing pending, and before saying it works VERIFY it - run the exact behavior requested, not a compile or typecheck. A claim says no more than you observed: "fixed", "works", "deployed", "published" mean seen where the user meets it - the delivered artifact past CI and caches, their roles, locales, environments and data, the full round trip; otherwise state what you checked, where, and what stays unverified.
57
57
  - Then, before reporting, run the pass the user would otherwise force with "are you 100% sure?": review your own diff as a hostile reviewer - re-run the original failing scenario, try the edges (empty, huge, concurrent, unauthenticated, old data), check every caller of what you changed - and fix what it finds. Confidence comes from evidence you ran, never from having written the code.
58
58
  - Change safely without being told: existing behavior is preserved unless changing it IS the task. Public APIs, CLI flags, config keys, schemas, file formats and events stay backward compatible (add, deprecate, never silently rename or remove). No data loss: migrations are additive and reversible, destructive steps get a backup or dry run first, and a change applies retroactively - existing records, users and installs are migrated or backfilled, not only new ones.
59
59
  - For a new feature, an unfamiliar problem, or a design with real alternatives, research prior art first when the runtime can search: docs, GitHub issues and established OSS implementations, forums. Build on the technique that proven projects converged on and name the source in one line. Skip it for trivial or purely local edits.
@@ -7,6 +7,6 @@
7
7
  "minimalCode"
8
8
  ],
9
9
  "updated": "2026-07-17T00:17:02+02:00",
10
- "cliVersion": "1.56.1",
10
+ "cliVersion": "1.57.1",
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.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "f742a2be3f328b9ea1ff9a35a449177c2cbec35ad16e46f7054b7a873a2ab017"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Backend/API architecture: controller-service-repository layering, modern TypeScript project configuration (module resolution, strict flags, @/* path alias), API and request optimization (batching, avoiding redundant calls, skipping no-op writes), server-side caching (Redis), and Zod boundary validation.",
6
6
  "updated": "2026-08-02T19:59:01+02:00",
7
- "cliVersion": "1.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "652637f818b4ce4f4d5d83fa68fa57fe7842e32fb179523958c5496af54bb938"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Ciphera code style conventions (formatting, naming, imports incl. namespace imports for wide module surfaces, path-alias specifiers and no file extensions, comments, code-level anti-patterns; TypeScript-first, language-agnostic).",
6
6
  "updated": "2026-08-02T19:59:01+02:00",
7
- "cliVersion": "1.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "3beb0383a9cb0331ef8a579308a2517d24d57a8ba33751ad17d16d0a4f66e344"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Pre-delivery self-review gate, prioritized review dimensions, and change-quality criteria.",
6
6
  "updated": "2026-08-19T12:37:59+02:00",
7
- "cliVersion": "1.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "6b8a924cc11b61d4b45b73384aeb095ce622229359b7cc2c6ce4bb0cf3015ed7"
9
9
  }
@@ -7,6 +7,6 @@
7
7
  "codeGraph"
8
8
  ],
9
9
  "updated": "2026-08-15T20:49:24+02:00",
10
- "cliVersion": "1.56.1",
10
+ "cliVersion": "1.57.1",
11
11
  "sha": "95b7202e5659f8d9d6f11ce29e7dc5b01575ba86c78ef948bec4753ccf430155"
12
12
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Senior database architecture policy: engine selection (PostgreSQL by default, SQLite only for local-first/embedded stores), ORM selection (Prisma in TypeScript/JavaScript), query optimization, anti-duplication/normalization, scalability, and RGPD/GDPR encryption.",
6
6
  "updated": "2026-08-04T18:33:27+02:00",
7
- "cliVersion": "1.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "26fddc14caf697e830448a2cc453ddc470fe83d098d50bd67b278effba63274e"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Reproduce-isolate-fix debugging methodology with root-cause discipline and regression verification.",
6
6
  "updated": "2026-08-02T04:15:47+02:00",
7
- "cliVersion": "1.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "968876bcac9ce6e5a20be05c89ac97191b112c9e08679a8dc506d150c375fec4"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Dependency and supply-chain security: lockfiles and reproducible installs, version pinning, vulnerability auditing, vetting/minimizing packages, vendoring, and SBOM/provenance.",
6
6
  "updated": "2026-06-01T00:45:28+02:00",
7
- "cliVersion": "1.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "6375d835c2aef2c9bd31ce116444dc3d796f510f9970a213aa3ac4696d7e21b9"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Transactional email: React Email templates instead of hand-written HTML tables, server-side rendering, one send module behind the provider SDK, plain-text alternatives, idempotent background sending, link safety, and deliverability (SPF/DKIM/DMARC, bounce suppression, unsubscribe).",
6
6
  "updated": "2026-09-28T21:34:15+02:00",
7
- "cliVersion": "1.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "648c7ae3d95d5a033f4955a87613e20b40b265bfcc24d41a5732d415abe778f9"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one.",
6
6
  "updated": "2026-09-28T21:34:15+02:00",
7
- "cliVersion": "1.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "5d532c2dc467f960ff800c5cd7021db09911599347959cd04481f2054abd9baa"
9
9
  }
@@ -583,6 +583,8 @@ Render dates and timestamps as localized, auto-updating values. Do not hand-roll
583
583
  For a user-facing search box or finder over a list, use fuse.js (fuzzy search) rather than a hand-rolled `.toLowerCase().includes()` filter. Fuzzy matching tolerates typos and partial or transposed input and ranks results by relevance - which is what users expect from a search field; a raw substring filter misses "usnig" for "using" and cannot rank. Apply it by default without being asked whenever the input is a free-text search.
584
584
 
585
585
  - Configure it where the data is: `keys` naming every field the user would expect to search (a row's name AND its id, owner, tag), `threshold` around 0.3 as the starting point, and `ignoreLocation` on so a match late in a long string still counts.
586
+ - **A search must be able to say "No results".** fuse.js defaults `threshold` to 0.6, and with `ignoreLocation` on that matches nearly everything: measured over 30 settings items searched by title and description, "zebra" returned all 30. So the strict threshold is not optional, it is never raised to make results appear, `minMatchCharLength: 2` keeps one stray letter from matching, the title outweighs long description text (`keys: [{ name: "title", weight: 2 }, "description"]`), and with `includeScore` a result far worse than the best one is dropped. An empty result renders an empty state that names the query ("No results for \"zebra\""), never the full list.
587
+ - Verify a search with three queries before calling it done: an exact item (first result), a one-letter typo of it (still found), and a word that appears nowhere (nothing). The third is the one a happy-path check never runs.
586
588
  - Run it over the data already in memory, re-matching per keystroke. Debouncing belongs to the request that fetches the data, not to the match itself - an in-memory search of a loaded page is instant, and delaying it only makes the field feel broken.
587
589
  - The exception is a filter over values the user PICKS rather than types - an id, a status, a tag, a date range, a facet from a dropdown. There the exact value is the requirement and fuzzy matching would be wrong; a plain comparison is correct, and it is not the case this rule is about.
588
590
  - Server-backed search is the other half: once the list outgrows what the client holds, the query goes to the server (which does its own matching) and fuse.js narrows only what came back. Reuse the loaded list first (per Client-Side Caching) before falling back to a server query, and say which one is running, so an empty result reads as "no matches" and not as a broken field.
@@ -3,7 +3,7 @@
3
3
  "version": "1.33.0",
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Frontend architecture: reusable components, abstraction thresholds, state management, real-time form validation where an emptied or not-yet-filled field is incomplete rather than invalid (a `*` on the label and an aria-disabled submit, never \"email is not valid\" over an empty input), no-op detection (skip any operation whose result equals current state, not just form saves; dirty means different from the loaded snapshot, not touched), instant first paint (render the shell, load data async, skeletons), perceived performance (prefetch on intent, debounce/throttle, cancel stale requests, avoid waterfalls, lazy widgets), large-list rendering (infinite scroll is the preferred default, pagination the deliberate exception when the design or the user calls for it, virtualization, skeletons, progressive loading), data views that ship their own affordances by default (a log, expense, transaction or history table is not done when the rows render: fuse.js search, the filters its column kinds imply, a date range, sort, filter state in the URL, and an export of the filtered set), every reference to an entity being a way into it (a name, id, project or path in a row links to that record, reveals it in a hover card, or at minimum copies and filters by it, never inert text; machine codes get human labels and raw payloads are never dumped into a cell), optimistic UI with rollback, visual restraint (one card level, spacing before borders, one elevation scale), icon actions (repeated row/card actions are icon-only buttons with aria-label plus title, not text labels), responsive/adaptive layout (fluid units, breakpoints, no overlap/overflow, viewport meta, touch targets), form fields that declare their keyboard and casing (autocapitalize/autocomplete/inputmode per field kind, set once in the shared Input, normalized on blur), variable-length text (min-width:0 in flex/grid, wrap vs truncate, long unbroken strings, worst-case content checks), auth screens (breached-password feedback, strength meter, cookie consent before login/register), and AI chat/agent interfaces via Vercel's AI Elements registry instead of hand-rolled message threads.",
6
- "updated": "2026-09-28T22:12:26+02:00",
7
- "cliVersion": "1.56.1",
8
- "sha": "96bc75af3a5ab248f94be980cc3e2974dca105c28de7ead3a9c5b581d01e9c89"
6
+ "updated": "2026-10-02T12:11:30+02:00",
7
+ "cliVersion": "1.57.1",
8
+ "sha": "2571746934548e64ee30348bbf29b1d971d3afa0a7b32277b137150bf8803f90"
9
9
  }
@@ -91,8 +91,9 @@ When the user asks for a human co-author, the trailer is `Co-authored-by: Name <
91
91
  - Commit subjects use a leading type emoji by default: `<emoji> <type>: <short description>`.
92
92
  Example: `✨ feat: add dual-provider matching`.
93
93
  - This is the one sanctioned exception to the global no-emoji rule: it applies ONLY to the
94
- commit subject line. Commit bodies, PR text, code, comments, identifiers, and chat responses
95
- stay emoji-free. Do not add more than one emoji, and place it only at the start of the subject.
94
+ commit subject line - and to the PR title, because a squash merge turns the PR title into the
95
+ merge commit's subject. Commit bodies, PR bodies, code, comments, identifiers, and chat
96
+ responses stay emoji-free. Do not add more than one emoji, and place it only at the start of the subject.
96
97
  - Use exactly this type-to-emoji map (do not invent others):
97
98
  - ✨ feat: new features
98
99
  - 🐛 fix: bug fixes
@@ -3,7 +3,7 @@
3
3
  "version": "1.6.0",
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Git & contribution policy (senior engineering standards).",
6
- "updated": "2026-08-22T09:25:34+02:00",
7
- "cliVersion": "1.56.1",
8
- "sha": "cb320a6a5fd3279604ad7920b877c1a36e48f4f39aeead1a4c4daa89901d9ce0"
6
+ "updated": "2026-10-02T14:54:11+02:00",
7
+ "cliVersion": "1.57.1",
8
+ "sha": "c6ffef058397ac22310053af1f96d768c36eb8761336258cfef2b97cff3fb0e9"
9
9
  }
@@ -7,6 +7,6 @@
7
7
  "logoColorPolicy"
8
8
  ],
9
9
  "updated": "2026-07-17T00:17:02+02:00",
10
- "cliVersion": "1.56.1",
10
+ "cliVersion": "1.57.1",
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, object- and role-level checks), credential flows with breach-checked passwords (Have I Been Pwned), OWASP Top 10 with vetted helpers for SSRF, redirects and uploads, transport/crypto baseline, cookies and consent, secure logging, and agent/MCP/tool-use safety.",
6
6
  "updated": "2026-09-28T21:34:15+02:00",
7
- "cliVersion": "1.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "544359122f127cccedfe469232da915b04f7f4aa4795297281bd4bc9cd07d371"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Create new skills, modify and improve existing skills, and measure skill performance with evals and benchmarks.",
6
6
  "updated": "2026-08-03T00:16:54+02:00",
7
- "cliVersion": "1.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "a49f6166f57d734e0f13487332da37903e925f32257447856af0fbd6a5f1dc84"
9
9
  }
@@ -64,6 +64,13 @@ A completion claim is forbidden unless ALL of these hold:
64
64
 
65
65
  - The final report must state: total units, done, deferred (with approval), and the verification evidence (commands run and their results).
66
66
  - Anything that could not be verified is reported as unverified. Never upgrade unverified to done.
67
+ - A claim is exactly as wide as its evidence. Every success word ("fixed", "works", "deployed", "published", "tested", "arreglado", "funciona") is a statement about the user's real use, so before writing one, name what it covers and check each dimension that applies:
68
+ - **Delivery chain** - committed, merged, built (CI can skip a commit by path, type or message), released/published, deployed, and what the user's client actually loads (CDN and API caches, an installed old version). Observe the far end; a step you did not observe is not done.
69
+ - **Conditions** - the roles and permissions (not only admin/operator), locales, environments, terrains, devices, providers and existing data the user actually has. One condition passing proves that condition.
70
+ - **Whole flow** - the round trip (export then import, save then reload, send then receive), the state it leaves behind, and what it must never lose or duplicate.
71
+ - **Cause** - the evidence shows the cause you name, not only that a symptom moved. A diagnosis that was not confirmed is reported as a hypothesis, and a fact read from a doc, memory, a name or another agent's report is checked against the live system before it is relied on.
72
+ - **Neighbors** - a fix for one path says nothing about a sibling path that was not exercised (another endpoint, another device family, the mobile flow next to the desktop one).
73
+ Then write the claim to fit: "verified X by running Y in Z; not verified: W". A partial verification reported as complete is a false report, however true each observed part is.
67
74
  - Never offload doable work to the user. "You can adjust X yourself", "refresh the lockfile if you prefer", "wire the remaining seam when needed" in a final report are deferrals in disguise: if the agent can execute the action (edit the pin, refresh the freeze, run the migration, wire the seam), it does so BEFORE reporting. Hand work to the user only when it genuinely requires them - credentials or access the agent lacks, irreversible or destructive choices, or business decisions - or when the user explicitly approved deferring it.
68
75
 
69
76
  ---
@@ -3,7 +3,7 @@
3
3
  "version": "1.5.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-08-02T04:15:47+02:00",
7
- "cliVersion": "1.56.1",
8
- "sha": "4c2197954135dd3375f32d839238b82a95c0e93e976ddf5a9cbc4a0cf0146e97"
6
+ "updated": "2026-10-02T12:38:13+02:00",
7
+ "cliVersion": "1.57.1",
8
+ "sha": "ee8447d5ca9e5d77e0a338d1e762c30e1527ded4665c10ddf21f2c4c9ce3f2d5"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Concise, realistic copy for UI, landing/sales, SEO, email and docs - the user's outcome instead of the mechanism, no full enumerations or \"powered by\" lineage, none of the recognizable AI-writing tells, and never a typographic dash.",
6
6
  "updated": "2026-09-28T21:34:15+02:00",
7
- "cliVersion": "1.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "e32623f37f1bf90fa611968ca8b216e3381771254b6af7c81a953c17a8889ddb"
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.56.1",
7
+ "cliVersion": "1.57.1",
8
8
  "sha": "3bdf591057b760f674fb2b1425f63acb426cda2c4f042e1a74c5a5d3807df664"
9
9
  }
@@ -74,7 +74,7 @@ Per field kind (defaults - override only with a reason):
74
74
 
75
75
  | Field | Normalizes to |
76
76
  | --- | --- |
77
- | Email | trim, lowercase, then validate. Store it lowercased so lookups and uniqueness never miss. |
77
+ | Email | trim, lowercase, then validate with the project's existing email check or the schema library's (`z.email()`, Pydantic `EmailStr`), never a regex written for this one form - `/^[^\s@]+@[^\s@]+\.[^\s@]+$/` accepts `user@example.com,`. Store it lowercased so lookups and uniqueness never miss. |
78
78
  | Person name (full name, first, last) | trim, collapse inner spaces, uppercase the first letter of every word - and ONLY that letter, so `McDonald`, `O'Brien`, `van der Berg` and `Jean-Luc` survive. Split on spaces, hyphens and apostrophes. |
79
79
  | Username, handle, slug | trim, drop a leading `@`, lowercase when the identifier is case-insensitive, then check the allowed character set. |
80
80
  | Profile link (LinkedIn, GitHub, X, Instagram) | accept BOTH a full URL and a bare handle, canonicalize to one stored form, check the host is the expected domain, and drop query and tracking parameters. |
@@ -4,6 +4,6 @@
4
4
  "provider": "FJRG2007/enigma",
5
5
  "description": "Strict frontend + backend schema validation, normalization before validation (shared normalizers: trim, lowercase email, capitalize names, canonicalize links and handles), real-time error timing (an emptied or not-yet-filled field is incomplete, not invalid: a `*` and an aria-disabled submit instead of \"not valid\" over an empty input), schema consistency, and safe client-facing error handling.",
6
6
  "updated": "2026-08-11T17:10:56+02:00",
7
- "cliVersion": "1.56.1",
8
- "sha": "24928a4c9eed28ebede9f23f746b09a9d3d8176f8fcca61a7780a853fa5bed4e"
7
+ "cliVersion": "1.57.1",
8
+ "sha": "7b39ded6b82cb7a8424aea7b8d59a293791205d57e7272ff63d9fa558772ecb1"
9
9
  }
@@ -1,6 +1,6 @@
1
1
  {
2
- "enigma-darwin-arm64": "da4c659bd07486ef23724d838c7620a4dc80500be950fb68995d57cfc4275d06",
3
- "enigma-linux-arm64": "caab50b0cd332f01971e271d2c0a1210cb9c5ea80f54daed9d6b82a2b6a94a86",
4
- "enigma-linux-x64": "601417d5611bbf3acba4e8a0e09b192528e108b70551490ad198fc0c60512135",
5
- "enigma-win32-x64.exe": "849c8de2b6fab2b275d2f3fe459ecad77c40e057c652a8ff663bd3412a60933e"
2
+ "enigma-darwin-arm64": "2c74fd9c761017267489648159afbdecce4e089e32c87cc7e22207a09d1a9828",
3
+ "enigma-linux-arm64": "9aea53abe54a6a9823a46b7a2c4160106701a0dfc6226c93ad2032cecddf740c",
4
+ "enigma-linux-x64": "389196e5a63d0dc2df62cd2823f635d8a11c001e7bc784f2cff6705423014fa6",
5
+ "enigma-win32-x64.exe": "18b6d9fc075ff2a1a31080d098a07d48c36945b331edf3c7f68a222d3dc7b6ac"
6
6
  }
@@ -784,6 +784,79 @@ var BUILTIN_RULES = [
784
784
  severity: "block",
785
785
  skill: "frontend-policy"
786
786
  },
787
+ {
788
+ id: "fe-fuse-loose-threshold",
789
+ label: 'fuse.js tuned to say "no results"',
790
+ files: ["*.tsx", "*.jsx", "*.ts", "*.js", "*.mts", "*.cts", "*.vue", "*.svelte", "*.astro"],
791
+ excludeFiles: [
792
+ "*.test.*",
793
+ "*.spec.*",
794
+ "*.stories.*",
795
+ "**/tests/**",
796
+ "**/__tests__/**",
797
+ "**/dist/**",
798
+ "dist/**",
799
+ "**/build/**",
800
+ "build/**",
801
+ "**/node_modules/**"
802
+ ],
803
+ scope: "file",
804
+ // The other half of fe-search-fuzzy, and the failure that rule's own advice produces:
805
+ // fuse.js's default `threshold` is 0.6 (read from the shipped 7.5.0 source), and
806
+ // agents add `ignoreLocation: true` so late matches count, which together match almost
807
+ // anything. MEASURED over 30 settings-page items with title+description keys: "zebra"
808
+ // returned 30 of 30 under defaults plus ignoreLocation, where `threshold: 0.3` plus
809
+ // `minMatchCharLength: 2` returned 0 and still found "Password" for "pasword". A search
810
+ // that never says "no results" is broken in a way no test of the happy path shows.
811
+ //
812
+ // Fires on a construction in a file with no strict threshold (0.4 or below). `absent` is
813
+ // file-wide, so options defined beside the call clear it; options shared from another
814
+ // module take the escape hatch on the call line.
815
+ pattern: "\\bnew\\s+Fuse\\s*[<(]",
816
+ absent: "\\bthreshold\\s*:\\s*(?:0?\\.[0-4]|0(?![.\\d]))|enigma:allow-fuse-threshold",
817
+ // DIFF stage for the reason fe-search-fuzzy is: only a search the agent just wrote can
818
+ // fire it, never one already sitting in the repository.
819
+ stage: "diff",
820
+ message: 'fuse.js without a strict `threshold`. Its default is 0.6, and with `ignoreLocation: true` that matches nearly every item - a search for a word that is not there returns the whole list instead of "No results". Set `threshold` to about 0.3 (never raise it to make results appear), `minMatchCharLength: 2`, weighted `keys` with the title above long description text, and render an explicit empty state naming the query. Check it with a nonsense query (must return nothing) and a one-letter typo of a real item (must find it). If the options come from a shared module that sets a strict threshold, mark the call line `enigma:allow-fuse-threshold` (frontend-policy).',
821
+ severity: "block",
822
+ skill: "frontend-policy"
823
+ },
824
+ {
825
+ id: "val-email-regex-hand-rolled",
826
+ label: "Email validated by a hand-written regex",
827
+ files: ["*.tsx", "*.jsx", "*.ts", "*.js", "*.mts", "*.cts", "*.mjs", "*.vue", "*.svelte", "*.astro"],
828
+ excludeFiles: [
829
+ "*.test.*",
830
+ "*.spec.*",
831
+ "*.stories.*",
832
+ "**/tests/**",
833
+ "**/__tests__/**",
834
+ "**/dist/**",
835
+ "dist/**",
836
+ "**/build/**",
837
+ "build/**",
838
+ "**/node_modules/**"
839
+ ],
840
+ scope: "file",
841
+ // An ANCHORED regex shaped like an email (`^<class>+@<class>+\.`) is a validator, and an
842
+ // agent writes a fresh one per form instead of reusing the project's. The usual shape,
843
+ // /^[^\s@]+@[^\s@]+\.[^\s@]+$/, accepts "user@example.com," - a real report: a form
844
+ // validated its own copy while the rest of the project had a proper check. The anchor is
845
+ // what separates validation from extraction and redaction (PII masks, linkifiers, log
846
+ // scrubbers are unanchored and legitimate). MEASURED over 128669 code files of real
847
+ // repositories on the author's machine: 114 hits, every one a hand-rolled email-shaped
848
+ // validator (one project carried 20+ copies of the same line); the only non-email ones
849
+ // were email-SHAPED formats (NIP-05, Lightning addresses), which is what the marker is for.
850
+ // Git URLs, IRC prefixes and chat JIDs (`[^@/]+@github\.com`, `(\d+)@c\.us`) do not match:
851
+ // the domain part must itself be a quantified class followed by an escaped dot.
852
+ pattern: "\\^\\(?(?:\\[[^\\]\\n]*\\]|\\\\[Sw]|[^\\s\\\\])[+*]\\)?@\\(?(?:\\[[^\\]\\n]*\\]|\\\\[Sw]|[^\\s\\\\])[+*]\\)?\\\\\\.",
853
+ absent: "enigma:allow-email-regex",
854
+ // DIFF stage: the corpus is full of these, so only a validator the agent just wrote fires.
855
+ stage: "diff",
856
+ message: "Email validated with a hand-written regex. Reuse the project's existing email validation (its shared schema or helper - search for it before writing one) or the schema library's own check (`z.string().email()` / `z.email()`, Pydantic `EmailStr`), normalized first (trim, lowercase). The common shape /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/ accepts \"user@example.com,\" and a copy per form drifts from the rest. If this IS the one shared validator, or the format is only email-shaped (NIP-05, a Lightning address), mark the line `enigma:allow-email-regex` (validation-policy).",
857
+ severity: "block",
858
+ skill: "validation-policy"
859
+ },
787
860
  {
788
861
  id: "fe-skeleton-loading",
789
862
  label: "Skeletons over blank/spinner loading",
package/dist/post-edit.js CHANGED
@@ -3200,6 +3200,79 @@ var init_guardrails = __esm({
3200
3200
  severity: "block",
3201
3201
  skill: "frontend-policy"
3202
3202
  },
3203
+ {
3204
+ id: "fe-fuse-loose-threshold",
3205
+ label: 'fuse.js tuned to say "no results"',
3206
+ files: ["*.tsx", "*.jsx", "*.ts", "*.js", "*.mts", "*.cts", "*.vue", "*.svelte", "*.astro"],
3207
+ excludeFiles: [
3208
+ "*.test.*",
3209
+ "*.spec.*",
3210
+ "*.stories.*",
3211
+ "**/tests/**",
3212
+ "**/__tests__/**",
3213
+ "**/dist/**",
3214
+ "dist/**",
3215
+ "**/build/**",
3216
+ "build/**",
3217
+ "**/node_modules/**"
3218
+ ],
3219
+ scope: "file",
3220
+ // The other half of fe-search-fuzzy, and the failure that rule's own advice produces:
3221
+ // fuse.js's default `threshold` is 0.6 (read from the shipped 7.5.0 source), and
3222
+ // agents add `ignoreLocation: true` so late matches count, which together match almost
3223
+ // anything. MEASURED over 30 settings-page items with title+description keys: "zebra"
3224
+ // returned 30 of 30 under defaults plus ignoreLocation, where `threshold: 0.3` plus
3225
+ // `minMatchCharLength: 2` returned 0 and still found "Password" for "pasword". A search
3226
+ // that never says "no results" is broken in a way no test of the happy path shows.
3227
+ //
3228
+ // Fires on a construction in a file with no strict threshold (0.4 or below). `absent` is
3229
+ // file-wide, so options defined beside the call clear it; options shared from another
3230
+ // module take the escape hatch on the call line.
3231
+ pattern: "\\bnew\\s+Fuse\\s*[<(]",
3232
+ absent: "\\bthreshold\\s*:\\s*(?:0?\\.[0-4]|0(?![.\\d]))|enigma:allow-fuse-threshold",
3233
+ // DIFF stage for the reason fe-search-fuzzy is: only a search the agent just wrote can
3234
+ // fire it, never one already sitting in the repository.
3235
+ stage: "diff",
3236
+ message: 'fuse.js without a strict `threshold`. Its default is 0.6, and with `ignoreLocation: true` that matches nearly every item - a search for a word that is not there returns the whole list instead of "No results". Set `threshold` to about 0.3 (never raise it to make results appear), `minMatchCharLength: 2`, weighted `keys` with the title above long description text, and render an explicit empty state naming the query. Check it with a nonsense query (must return nothing) and a one-letter typo of a real item (must find it). If the options come from a shared module that sets a strict threshold, mark the call line `enigma:allow-fuse-threshold` (frontend-policy).',
3237
+ severity: "block",
3238
+ skill: "frontend-policy"
3239
+ },
3240
+ {
3241
+ id: "val-email-regex-hand-rolled",
3242
+ label: "Email validated by a hand-written regex",
3243
+ files: ["*.tsx", "*.jsx", "*.ts", "*.js", "*.mts", "*.cts", "*.mjs", "*.vue", "*.svelte", "*.astro"],
3244
+ excludeFiles: [
3245
+ "*.test.*",
3246
+ "*.spec.*",
3247
+ "*.stories.*",
3248
+ "**/tests/**",
3249
+ "**/__tests__/**",
3250
+ "**/dist/**",
3251
+ "dist/**",
3252
+ "**/build/**",
3253
+ "build/**",
3254
+ "**/node_modules/**"
3255
+ ],
3256
+ scope: "file",
3257
+ // An ANCHORED regex shaped like an email (`^<class>+@<class>+\.`) is a validator, and an
3258
+ // agent writes a fresh one per form instead of reusing the project's. The usual shape,
3259
+ // /^[^\s@]+@[^\s@]+\.[^\s@]+$/, accepts "user@example.com," - a real report: a form
3260
+ // validated its own copy while the rest of the project had a proper check. The anchor is
3261
+ // what separates validation from extraction and redaction (PII masks, linkifiers, log
3262
+ // scrubbers are unanchored and legitimate). MEASURED over 128669 code files of real
3263
+ // repositories on the author's machine: 114 hits, every one a hand-rolled email-shaped
3264
+ // validator (one project carried 20+ copies of the same line); the only non-email ones
3265
+ // were email-SHAPED formats (NIP-05, Lightning addresses), which is what the marker is for.
3266
+ // Git URLs, IRC prefixes and chat JIDs (`[^@/]+@github\.com`, `(\d+)@c\.us`) do not match:
3267
+ // the domain part must itself be a quantified class followed by an escaped dot.
3268
+ pattern: "\\^\\(?(?:\\[[^\\]\\n]*\\]|\\\\[Sw]|[^\\s\\\\])[+*]\\)?@\\(?(?:\\[[^\\]\\n]*\\]|\\\\[Sw]|[^\\s\\\\])[+*]\\)?\\\\\\.",
3269
+ absent: "enigma:allow-email-regex",
3270
+ // DIFF stage: the corpus is full of these, so only a validator the agent just wrote fires.
3271
+ stage: "diff",
3272
+ message: "Email validated with a hand-written regex. Reuse the project's existing email validation (its shared schema or helper - search for it before writing one) or the schema library's own check (`z.string().email()` / `z.email()`, Pydantic `EmailStr`), normalized first (trim, lowercase). The common shape /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/ accepts \"user@example.com,\" and a copy per form drifts from the rest. If this IS the one shared validator, or the format is only email-shaped (NIP-05, a Lightning address), mark the line `enigma:allow-email-regex` (validation-policy).",
3273
+ severity: "block",
3274
+ skill: "validation-policy"
3275
+ },
3203
3276
  {
3204
3277
  id: "fe-skeleton-loading",
3205
3278
  label: "Skeletons over blank/spinner loading",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "enigma-cli",
3
- "version": "1.56.1",
3
+ "version": "1.57.1",
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": {