enigma-cli 1.38.0 → 1.40.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.
- package/assets/registry/primitives/registry.json +225 -2
- package/assets/skills/anti-overengineering-policy/skill.json +1 -1
- package/assets/skills/anti-overengineering-review/skill.json +1 -1
- package/assets/skills/backend-policy/skill.json +1 -1
- package/assets/skills/ciphera-style-policy/skill.json +1 -1
- package/assets/skills/code-review-policy/skill.json +1 -1
- package/assets/skills/core-engineering-policy/skill.json +1 -1
- package/assets/skills/database-expert/skill.json +1 -1
- package/assets/skills/debugging-policy/skill.json +1 -1
- package/assets/skills/dependency-policy/skill.json +1 -1
- package/assets/skills/email-policy/skill.json +1 -1
- package/assets/skills/frontend-design/skill.json +1 -1
- package/assets/skills/frontend-policy/SKILL.md +1 -0
- package/assets/skills/frontend-policy/skill.json +4 -4
- package/assets/skills/git-policy/skill.json +1 -1
- package/assets/skills/logo-sourcing-policy/skill.json +1 -1
- package/assets/skills/security-policy/skill.json +1 -1
- package/assets/skills/skill-creator/skill.json +1 -1
- package/assets/skills/task-completion-policy/skill.json +1 -1
- package/assets/skills/technical-writing-policy/skill.json +1 -1
- package/assets/skills/testing-policy/skill.json +1 -1
- package/assets/skills/validation-policy/skill.json +1 -1
- package/bin/checksums.json +4 -4
- package/dist/guardrails.js +93 -1
- package/package.json +1 -1
|
@@ -454,6 +454,13 @@
|
|
|
454
454
|
"react"
|
|
455
455
|
]
|
|
456
456
|
},
|
|
457
|
+
{
|
|
458
|
+
"path": "src/react/slot.tsx",
|
|
459
|
+
"dest": "button/slot.tsx",
|
|
460
|
+
"targets": [
|
|
461
|
+
"react"
|
|
462
|
+
]
|
|
463
|
+
},
|
|
457
464
|
{
|
|
458
465
|
"path": "src/react/button.tsx",
|
|
459
466
|
"dest": "button/index.tsx",
|
|
@@ -464,7 +471,8 @@
|
|
|
464
471
|
"rewrite": {
|
|
465
472
|
"@/core/button": "./button",
|
|
466
473
|
"@/react/use-button": "./use-button",
|
|
467
|
-
"@/react/link": "./link"
|
|
474
|
+
"@/react/link": "./link",
|
|
475
|
+
"@/react/slot": "./slot"
|
|
468
476
|
}
|
|
469
477
|
}
|
|
470
478
|
],
|
|
@@ -617,6 +625,13 @@
|
|
|
617
625
|
"react"
|
|
618
626
|
]
|
|
619
627
|
},
|
|
628
|
+
{
|
|
629
|
+
"path": "src/core/keys.ts",
|
|
630
|
+
"dest": "select/keys.ts",
|
|
631
|
+
"targets": [
|
|
632
|
+
"react"
|
|
633
|
+
]
|
|
634
|
+
},
|
|
620
635
|
{
|
|
621
636
|
"path": "src/core/select.ts",
|
|
622
637
|
"dest": "select/select.ts",
|
|
@@ -624,7 +639,8 @@
|
|
|
624
639
|
"react"
|
|
625
640
|
],
|
|
626
641
|
"rewrite": {
|
|
627
|
-
"@/core/search": "./search-core"
|
|
642
|
+
"@/core/search": "./search-core",
|
|
643
|
+
"@/core/keys": "./keys"
|
|
628
644
|
}
|
|
629
645
|
},
|
|
630
646
|
{
|
|
@@ -668,6 +684,7 @@
|
|
|
668
684
|
"rewrite": {
|
|
669
685
|
"@/core/select": "./select",
|
|
670
686
|
"@/core/palette": "./rows",
|
|
687
|
+
"@/core/search": "./search-core",
|
|
671
688
|
"@/react/slot": "./slot",
|
|
672
689
|
"@/react/select/styles": "./styles",
|
|
673
690
|
"@/react/select/context": "./context"
|
|
@@ -719,6 +736,212 @@
|
|
|
719
736
|
"css"
|
|
720
737
|
]
|
|
721
738
|
},
|
|
739
|
+
{
|
|
740
|
+
"name": "context-menu",
|
|
741
|
+
"title": "Context menu",
|
|
742
|
+
"description": "A right-click menu with the desktop's behaviour: submenus that open on a beat of hovering and survive a diagonal pointer, icons, a second line, shortcuts printed on the right, checkable and radio rows, separators and captions, destructive rows in red, an optional heading naming what it acts on, a filter once a level is long, a long level rendered a window at a time, and a submenu fetched on demand and cached. Opens at the pointer, on a long press, and on Shift+F10. A menu with no rows does not open at all. It brings its own theme - an unstyled popup is transparent text over the page rather than a plain-looking control.",
|
|
743
|
+
"targets": [
|
|
744
|
+
"react"
|
|
745
|
+
],
|
|
746
|
+
"entry": {
|
|
747
|
+
"react": "@enigmax/primitives/react/context-menu"
|
|
748
|
+
},
|
|
749
|
+
"exports": {
|
|
750
|
+
"react": [
|
|
751
|
+
"ContextMenu",
|
|
752
|
+
"useContextMenuContext",
|
|
753
|
+
"createContextMenu"
|
|
754
|
+
]
|
|
755
|
+
},
|
|
756
|
+
"files": [
|
|
757
|
+
{
|
|
758
|
+
"path": "src/core/search.ts",
|
|
759
|
+
"dest": "context-menu/search-core.ts",
|
|
760
|
+
"targets": [
|
|
761
|
+
"react"
|
|
762
|
+
]
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
"path": "src/core/keys.ts",
|
|
766
|
+
"dest": "context-menu/keys.ts",
|
|
767
|
+
"targets": [
|
|
768
|
+
"react"
|
|
769
|
+
]
|
|
770
|
+
},
|
|
771
|
+
{
|
|
772
|
+
"path": "src/core/context-menu.ts",
|
|
773
|
+
"dest": "context-menu/context-menu.ts",
|
|
774
|
+
"targets": [
|
|
775
|
+
"react"
|
|
776
|
+
],
|
|
777
|
+
"rewrite": {
|
|
778
|
+
"@/core/search": "./search-core",
|
|
779
|
+
"@/core/keys": "./keys"
|
|
780
|
+
}
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
"path": "src/react/slot.tsx",
|
|
784
|
+
"dest": "context-menu/slot.tsx",
|
|
785
|
+
"targets": [
|
|
786
|
+
"react"
|
|
787
|
+
]
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
"path": "src/react/context-menu/styles.ts",
|
|
791
|
+
"dest": "context-menu/styles.ts",
|
|
792
|
+
"targets": [
|
|
793
|
+
"react"
|
|
794
|
+
]
|
|
795
|
+
},
|
|
796
|
+
{
|
|
797
|
+
"path": "recipes/context-menu/styles.css",
|
|
798
|
+
"dest": "context-menu/styles.css",
|
|
799
|
+
"targets": [
|
|
800
|
+
"react"
|
|
801
|
+
],
|
|
802
|
+
"style": "css"
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
"path": "src/react/context-menu/context.ts",
|
|
806
|
+
"dest": "context-menu/context.ts",
|
|
807
|
+
"targets": [
|
|
808
|
+
"react"
|
|
809
|
+
],
|
|
810
|
+
"rewrite": {
|
|
811
|
+
"@/core/context-menu": "./context-menu"
|
|
812
|
+
}
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
"path": "src/react/context-menu/root.tsx",
|
|
816
|
+
"dest": "context-menu/root.tsx",
|
|
817
|
+
"targets": [
|
|
818
|
+
"react"
|
|
819
|
+
],
|
|
820
|
+
"rewrite": {
|
|
821
|
+
"@/core/context-menu": "./context-menu",
|
|
822
|
+
"@/core/search": "./search-core",
|
|
823
|
+
"@/core/keys": "./keys",
|
|
824
|
+
"@/react/slot": "./slot",
|
|
825
|
+
"@/react/context-menu/styles": "./styles",
|
|
826
|
+
"@/react/context-menu/context": "./context"
|
|
827
|
+
}
|
|
828
|
+
},
|
|
829
|
+
{
|
|
830
|
+
"path": "src/react/context-menu/index.tsx",
|
|
831
|
+
"dest": "context-menu/index.tsx",
|
|
832
|
+
"main": true,
|
|
833
|
+
"targets": [
|
|
834
|
+
"react"
|
|
835
|
+
],
|
|
836
|
+
"rewrite": {
|
|
837
|
+
"@/react/context-menu/root": "./root",
|
|
838
|
+
"@/react/context-menu/context": "./context",
|
|
839
|
+
"@/react/context-menu/styles": "./styles",
|
|
840
|
+
"@/core/context-menu": "./context-menu",
|
|
841
|
+
"@/core/keys": "./keys"
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
],
|
|
845
|
+
"styles": true,
|
|
846
|
+
"themeHooks": [
|
|
847
|
+
"[data-enigma-menu-trigger]",
|
|
848
|
+
"[data-enigma-menu-panel]",
|
|
849
|
+
"[data-enigma-menu-panel][data-placed]",
|
|
850
|
+
"[data-enigma-menu-title]",
|
|
851
|
+
"[data-enigma-menu-search]",
|
|
852
|
+
"[data-enigma-menu-list]",
|
|
853
|
+
"[data-enigma-menu-item]",
|
|
854
|
+
"[data-enigma-menu-item][data-active]",
|
|
855
|
+
"[data-enigma-menu-item][data-disabled]",
|
|
856
|
+
"[data-enigma-menu-item][data-destructive]",
|
|
857
|
+
"[data-enigma-menu-item][data-submenu]",
|
|
858
|
+
"[data-enigma-menu-item-label]",
|
|
859
|
+
"[data-enigma-menu-item-description]",
|
|
860
|
+
"[data-enigma-menu-icon]",
|
|
861
|
+
"[data-enigma-menu-shortcut]",
|
|
862
|
+
"[data-enigma-menu-arrow]",
|
|
863
|
+
"[data-enigma-menu-check]",
|
|
864
|
+
"[data-enigma-menu-separator]",
|
|
865
|
+
"[data-enigma-menu-label]",
|
|
866
|
+
"[data-enigma-menu-status]",
|
|
867
|
+
"[data-enigma-menu-status][data-error]"
|
|
868
|
+
],
|
|
869
|
+
"docs": "docs/notes/primitives.md#context-menu",
|
|
870
|
+
"recipes": [
|
|
871
|
+
"css"
|
|
872
|
+
]
|
|
873
|
+
},
|
|
874
|
+
{
|
|
875
|
+
"name": "selection",
|
|
876
|
+
"title": "Selection list",
|
|
877
|
+
"description": "The file-manager selection model as a headless list: a plain click replaces, Ctrl toggles, Shift takes the range from the anchor, Ctrl+Shift adds that range, Ctrl+A takes everything and Escape drops it, with a rubber band over empty space and arrow keys that move a cursor and extend with Shift. Delete, F2, Enter, copy, cut and paste are reported as commands rather than performed. Every binding can be rebound, removed one at a time, or turned off altogether, and a binding of your own is matched and reported the same way. Ships no styles: state arrives as data attributes.",
|
|
878
|
+
"targets": [
|
|
879
|
+
"react"
|
|
880
|
+
],
|
|
881
|
+
"entry": {
|
|
882
|
+
"react": "@enigmax/primitives/react/selection"
|
|
883
|
+
},
|
|
884
|
+
"exports": {
|
|
885
|
+
"react": [
|
|
886
|
+
"SelectionList",
|
|
887
|
+
"useSelection",
|
|
888
|
+
"createSelection"
|
|
889
|
+
]
|
|
890
|
+
},
|
|
891
|
+
"files": [
|
|
892
|
+
{
|
|
893
|
+
"path": "src/core/keys.ts",
|
|
894
|
+
"dest": "selection/keys.ts",
|
|
895
|
+
"targets": [
|
|
896
|
+
"react"
|
|
897
|
+
]
|
|
898
|
+
},
|
|
899
|
+
{
|
|
900
|
+
"path": "src/core/selection.ts",
|
|
901
|
+
"dest": "selection/selection.ts",
|
|
902
|
+
"targets": [
|
|
903
|
+
"react"
|
|
904
|
+
],
|
|
905
|
+
"rewrite": {
|
|
906
|
+
"@/core/keys": "./keys"
|
|
907
|
+
}
|
|
908
|
+
},
|
|
909
|
+
{
|
|
910
|
+
"path": "src/react/selection/use-selection.ts",
|
|
911
|
+
"dest": "selection/use-selection.ts",
|
|
912
|
+
"targets": [
|
|
913
|
+
"react"
|
|
914
|
+
],
|
|
915
|
+
"rewrite": {
|
|
916
|
+
"@/core/selection": "./selection"
|
|
917
|
+
}
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
"path": "src/react/selection/index.tsx",
|
|
921
|
+
"dest": "selection/index.tsx",
|
|
922
|
+
"main": true,
|
|
923
|
+
"targets": [
|
|
924
|
+
"react"
|
|
925
|
+
],
|
|
926
|
+
"rewrite": {
|
|
927
|
+
"@/react/selection/use-selection": "./use-selection",
|
|
928
|
+
"@/core/selection": "./selection",
|
|
929
|
+
"@/core/keys": "./keys"
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
],
|
|
933
|
+
"styles": false,
|
|
934
|
+
"themeHooks": [
|
|
935
|
+
"[data-enigma-selection-list]",
|
|
936
|
+
"[data-enigma-selection-item]",
|
|
937
|
+
"[data-enigma-selection-item][data-selected]",
|
|
938
|
+
"[data-enigma-selection-item][data-cursor]",
|
|
939
|
+
"[data-enigma-selection-item][data-disabled]",
|
|
940
|
+
"[data-enigma-selection-marquee]",
|
|
941
|
+
"[data-enigma-selection-empty]"
|
|
942
|
+
],
|
|
943
|
+
"docs": "docs/notes/primitives.md#selection"
|
|
944
|
+
},
|
|
722
945
|
{
|
|
723
946
|
"name": "flags",
|
|
724
947
|
"title": "Country flags",
|
|
@@ -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.
|
|
7
|
+
"cliVersion": "1.40.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.
|
|
7
|
+
"cliVersion": "1.40.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.
|
|
7
|
+
"cliVersion": "1.40.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.
|
|
7
|
+
"cliVersion": "1.40.1",
|
|
8
8
|
"sha": "6b8a924cc11b61d4b45b73384aeb095ce622229359b7cc2c6ce4bb0cf3015ed7"
|
|
9
9
|
}
|
|
@@ -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.
|
|
7
|
+
"cliVersion": "1.40.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.
|
|
7
|
+
"cliVersion": "1.40.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.
|
|
7
|
+
"cliVersion": "1.40.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-07-30T19:29:19+02:00",
|
|
7
|
-
"cliVersion": "1.
|
|
7
|
+
"cliVersion": "1.40.1",
|
|
8
8
|
"sha": "c9724fdbcdbeab99573be3fd44d4cdd97c2a394d99f3c4395f118f17356b00ed"
|
|
9
9
|
}
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one.",
|
|
6
6
|
"updated": "2026-07-29T01:18:36+02:00",
|
|
7
|
-
"cliVersion": "1.
|
|
7
|
+
"cliVersion": "1.40.1",
|
|
8
8
|
"sha": "9e30ee7d8a1a1e8c6e7f4e043857cd01841c68a427752e45bc0cad9ec5cfa279"
|
|
9
9
|
}
|
|
@@ -26,6 +26,7 @@ description: Frontend architecture - reusable components, abstraction thresholds
|
|
|
26
26
|
- Interaction logic - looping/draggable rows, momentum, focus traps, virtualized lists, dismiss timers, read caches - is BEHAVIOR, and behavior that has already been measured and tested is a dependency, not a snippet to rewrite. Check the catalogue before writing it: `enigma add` lists it and `enigma add <name>` adds it as a DEPENDENCY, which is how you use these - the package keeps getting fixes and a dependency is how they reach the project. `--copy` vendors the source and freezes it at that version; reach for it to EDIT a component, never as the normal way to add one.
|
|
27
27
|
- These primitives ship NO visual styles. They apply only what the behavior requires (overflow, touch-action, user-select, will-change, transform) and publish their state as `data-*` attributes, so the look stays entirely yours.
|
|
28
28
|
- Do not hand-roll one of them "just for this page". The hand-rolled version is where the measured bugs come back: a duration-driven marquee that accelerates as items are added, a `setPointerCapture` drag that silently stops every link in the row from opening, a hover slowdown that sticks forever after the first tap because touch never fires `pointerleave`.
|
|
29
|
+
- Two of them are worth naming because their hand-rolled versions are near-misses of behavior everyone already knows, and the `fe-context-menu-hand-rolled` and `fe-selection-hand-rolled` guardrails block both. A RIGHT-CLICK MENU (`enigma add context-menu`) is never the panel: it is the release of the opening press choosing whatever row it landed on, a submenu that closes while the pointer crosses a sibling to reach it (the way out goes over them, so closing on the first crossing makes a nested menu unreachable), a panel that opens off the edge of the window instead of flipping, no Escape, no arrows, no Shift+F10, and a menu left behind when the page scrolls - plus shortcuts printed for the reader's platform and a menu that refuses to open when it has nothing to show. A LIST SELECTION (`enigma add selection`) is Explorer's model: Shift+click measures from the ANCHOR every time (measuring from the last click leaves a trail of rows as it is dragged), Ctrl toggles instead of replacing, Ctrl+Shift adds the range, a range steps over a row it may not select, and Ctrl+A, Escape and the arrow keys exist at all - with every shortcut rebindable or removable, and delete/rename/open reported as commands rather than performed.
|
|
29
30
|
- If the catalogue has no primitive for what you need, write it as one (core + adapter + registry entry + test) rather than inline in a page, so the next screen reuses it instead of rewriting it.
|
|
30
31
|
|
|
31
32
|
## Component Reuse (Mandatory)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frontend-policy",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.31.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-
|
|
7
|
-
"cliVersion": "1.
|
|
8
|
-
"sha": "
|
|
6
|
+
"updated": "2026-09-01T21:30:38+02:00",
|
|
7
|
+
"cliVersion": "1.40.1",
|
|
8
|
+
"sha": "c18c746f8c29c591685b81cabbaada43996640bc830181c28b8560e904934bc2"
|
|
9
9
|
}
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Git & contribution policy (senior engineering standards).",
|
|
6
6
|
"updated": "2026-08-22T09:25:34+02:00",
|
|
7
|
-
"cliVersion": "1.
|
|
7
|
+
"cliVersion": "1.40.1",
|
|
8
8
|
"sha": "cb320a6a5fd3279604ad7920b877c1a36e48f4f39aeead1a4c4daa89901d9ce0"
|
|
9
9
|
}
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Application and AI-agent security: secrets, authn/authz (least privilege), credential flows with breach-checked passwords (Have I Been Pwned), OWASP Top 10, transport/crypto baseline, cookies and consent, secure logging, and agent/MCP/tool-use safety.",
|
|
6
6
|
"updated": "2026-08-19T12:37:59+02:00",
|
|
7
|
-
"cliVersion": "1.
|
|
7
|
+
"cliVersion": "1.40.1",
|
|
8
8
|
"sha": "0270c33d2b4559e831aec794c188d293d26fc17e2a8064a967d716ceb3a7bab6"
|
|
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.
|
|
7
|
+
"cliVersion": "1.40.1",
|
|
8
8
|
"sha": "a49f6166f57d734e0f13487332da37903e925f32257447856af0fbd6a5f1dc84"
|
|
9
9
|
}
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Exhaustive completion discipline for long/multi-item tasks - inventory, coverage ledger, verified done.",
|
|
6
6
|
"updated": "2026-08-02T04:15:47+02:00",
|
|
7
|
-
"cliVersion": "1.
|
|
7
|
+
"cliVersion": "1.40.1",
|
|
8
8
|
"sha": "4c2197954135dd3375f32d839238b82a95c0e93e976ddf5a9cbc4a0cf0146e97"
|
|
9
9
|
}
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Concise, realistic technical copy - UI microcopy, descriptions, hints, empty/error states, and README/doc prose that informs without over-explaining or restating the obvious, and never uses a typographic dash.",
|
|
6
6
|
"updated": "2026-08-19T12:37:59+02:00",
|
|
7
|
-
"cliVersion": "1.
|
|
7
|
+
"cliVersion": "1.40.1",
|
|
8
8
|
"sha": "a5a228a302f50d975a947b9d84676b4c2a4780f2b222f819388cc98d6a12f207"
|
|
9
9
|
}
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Test strategy, coverage gates, deterministic tests, mocking discipline, regression-first bug fixing, and test-suite organization (layout by type/domain, mirrored paths, file naming, fixture/helper placement).",
|
|
6
6
|
"updated": "2026-06-16T17:11:49+02:00",
|
|
7
|
-
"cliVersion": "1.
|
|
7
|
+
"cliVersion": "1.40.1",
|
|
8
8
|
"sha": "3bdf591057b760f674fb2b1425f63acb426cda2c4f042e1a74c5a5d3807df664"
|
|
9
9
|
}
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
"provider": "FJRG2007/enigma",
|
|
5
5
|
"description": "Strict frontend + backend schema validation, normalization before validation (shared normalizers: trim, lowercase email, capitalize names, canonicalize links and handles), real-time error timing (an emptied or not-yet-filled field is incomplete, not invalid: a `*` and an aria-disabled submit instead of \"not valid\" over an empty input), schema consistency, and safe client-facing error handling.",
|
|
6
6
|
"updated": "2026-08-11T17:10:56+02:00",
|
|
7
|
-
"cliVersion": "1.
|
|
7
|
+
"cliVersion": "1.40.1",
|
|
8
8
|
"sha": "24928a4c9eed28ebede9f23f746b09a9d3d8176f8fcca61a7780a853fa5bed4e"
|
|
9
9
|
}
|
package/bin/checksums.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"enigma-darwin-arm64": "
|
|
3
|
-
"enigma-linux-arm64": "
|
|
4
|
-
"enigma-linux-x64": "
|
|
5
|
-
"enigma-win32-x64.exe": "
|
|
2
|
+
"enigma-darwin-arm64": "d99532b31c6c8f2f3fc553be1fcb82944909a34e39aa7612aad3fc9f85da82b2",
|
|
3
|
+
"enigma-linux-arm64": "024a6a3e68814301e4aad40aafca834ab96fb386fd6b74d30bd14e4fcf5d344a",
|
|
4
|
+
"enigma-linux-x64": "6c66ee2647df7d119ef86a0ac2ea70d8de0b2d1e8c387f9a5e306a29fa60a73c",
|
|
5
|
+
"enigma-win32-x64.exe": "337ce56e7fcabaf536f71b7cf1f8b6155413d97918d3e5b1b4263a66b94d600f"
|
|
6
6
|
}
|
package/dist/guardrails.js
CHANGED
|
@@ -980,6 +980,62 @@ var BUILTIN_RULES = [
|
|
|
980
980
|
severity: "block",
|
|
981
981
|
skill: "frontend-policy"
|
|
982
982
|
},
|
|
983
|
+
{
|
|
984
|
+
id: "fe-context-menu-hand-rolled",
|
|
985
|
+
label: "Right-click menus come from the primitive",
|
|
986
|
+
files: ["*.tsx", "*.jsx", "*.vue", "*.svelte", "*.astro", "*.ts", "*.js"],
|
|
987
|
+
excludeFiles: [
|
|
988
|
+
"*.test.*",
|
|
989
|
+
"*.spec.*",
|
|
990
|
+
"**/tests/**",
|
|
991
|
+
"**/__tests__/**",
|
|
992
|
+
"**/fixtures/**",
|
|
993
|
+
"*.min.js",
|
|
994
|
+
"**/dist/**",
|
|
995
|
+
"**/build/**",
|
|
996
|
+
"**/node_modules/**",
|
|
997
|
+
"**/vendor/**",
|
|
998
|
+
"dist/**",
|
|
999
|
+
"build/**",
|
|
1000
|
+
"node_modules/**",
|
|
1001
|
+
"vendor/**"
|
|
1002
|
+
],
|
|
1003
|
+
scope: "file",
|
|
1004
|
+
// DIFF stage: a hand-rolled menu is one of the things a codebase already has, and the
|
|
1005
|
+
// rule has to name the one being written now rather than the backlog.
|
|
1006
|
+
stage: "diff",
|
|
1007
|
+
fileCheck: "fe-context-menu-hand-rolled",
|
|
1008
|
+
message: "A right-click menu written by hand. What is missing is never the panel, it is the long tail nobody writes on the first pass: the release of the press that OPENED the menu choosing whatever row it landed on, a submenu that closes while the pointer crosses a sibling to reach it (the way out of a submenu goes over them, so closing on the first crossing makes a nested menu unreachable), a panel that opens off the bottom or the right of the window instead of flipping, no Escape, no arrow keys, no Shift+F10 for anyone without a mouse, and a menu left behind when the page scrolls. `enigma add context-menu` (@enigmax/primitives) is all of that with a test each, plus shortcuts printed for the reader's platform, checkable rows, destructive rows, a filter once a level is long and submenus fetched on demand and cached - and it refuses to open at all when there is nothing to show. When the menu genuinely has to be your own, add an `enigma:allow-hand-rolled-menu` note to the file (frontend-policy).",
|
|
1009
|
+
severity: "block",
|
|
1010
|
+
skill: "frontend-policy"
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
id: "fe-selection-hand-rolled",
|
|
1014
|
+
label: "List selection comes from the primitive",
|
|
1015
|
+
files: ["*.tsx", "*.jsx", "*.vue", "*.svelte", "*.astro", "*.ts", "*.js"],
|
|
1016
|
+
excludeFiles: [
|
|
1017
|
+
"*.test.*",
|
|
1018
|
+
"*.spec.*",
|
|
1019
|
+
"**/tests/**",
|
|
1020
|
+
"**/__tests__/**",
|
|
1021
|
+
"**/fixtures/**",
|
|
1022
|
+
"*.min.js",
|
|
1023
|
+
"**/dist/**",
|
|
1024
|
+
"**/build/**",
|
|
1025
|
+
"**/node_modules/**",
|
|
1026
|
+
"**/vendor/**",
|
|
1027
|
+
"dist/**",
|
|
1028
|
+
"build/**",
|
|
1029
|
+
"node_modules/**",
|
|
1030
|
+
"vendor/**"
|
|
1031
|
+
],
|
|
1032
|
+
scope: "file",
|
|
1033
|
+
stage: "diff",
|
|
1034
|
+
fileCheck: "fe-selection-hand-rolled",
|
|
1035
|
+
message: "A file-manager selection written by hand. Everyone already knows these rules from Explorer and Finder, which is exactly why the near-miss is so visible: a Shift+click measured from the last CLICK instead of the anchor leaves a trail of rows behind as it is dragged, a Ctrl+click that replaces instead of toggling throws the selection away, a range walks straight over a row that was not selectable, and the arrow keys, Ctrl+A and Escape usually never arrive at all. `enigma add selection` (@enigmax/primitives) is the whole model - anchor and cursor, Ctrl, Shift, Ctrl+Shift, select-all, invert, a rubber band, and arrow keys that extend from the anchor - with every shortcut rebindable, removable one at a time, or off altogether, and delete/rename/open reported as commands rather than performed. It ships no styles: `[data-selected]` and `[data-cursor]` are yours. When the model genuinely has to be your own, add an `enigma:allow-hand-rolled-selection` note to the file (frontend-policy).",
|
|
1036
|
+
severity: "block",
|
|
1037
|
+
skill: "frontend-policy"
|
|
1038
|
+
},
|
|
983
1039
|
{
|
|
984
1040
|
id: "fe-icon-action-button",
|
|
985
1041
|
label: "Repeated actions are icon buttons, not text labels",
|
|
@@ -1776,7 +1832,9 @@ var FILE_CHECKS = {
|
|
|
1776
1832
|
"ts-alias-deep-relative": (content, file) => deepRelativeImports(content, file),
|
|
1777
1833
|
"ts-alias-paths": (content, file) => missingPathAlias(content, file),
|
|
1778
1834
|
"sec-operator-env-leak": (content) => operatorHomePathLeak(content),
|
|
1779
|
-
"fe-new-password-affordance-on-signin": (content) => newPasswordAffordanceOnSignIn(content)
|
|
1835
|
+
"fe-new-password-affordance-on-signin": (content) => newPasswordAffordanceOnSignIn(content),
|
|
1836
|
+
"fe-context-menu-hand-rolled": (content) => handRolledContextMenu(content),
|
|
1837
|
+
"fe-selection-hand-rolled": (content) => handRolledSelection(content)
|
|
1780
1838
|
};
|
|
1781
1839
|
var FIXERS = {
|
|
1782
1840
|
"fe-name-input-capitalize": (line, file) => {
|
|
@@ -2033,6 +2091,38 @@ function unboundedRemoteList(content) {
|
|
|
2033
2091
|
}
|
|
2034
2092
|
return out;
|
|
2035
2093
|
}
|
|
2094
|
+
var MENU_HANDLER = /onContextMenu|addEventListener\(\s*["'`]contextmenu["'`]|@contextmenu|on:contextmenu/;
|
|
2095
|
+
var MENU_POINT = /\bclient[XY]\b|\bpage[XY]\b/;
|
|
2096
|
+
var MENU_STATE = /\bset(?:ContextMenu|Menu(?:Pos|Position|Point|Anchor|Coords|Origin|At)?)\b|\bmenu(?:Pos|Position|Point|Anchor|Coords)\s*[:=]/i;
|
|
2097
|
+
var MENU_MITIGATED = /@enigmax\/primitives|createContextMenu|useContextMenuContext|<ContextMenu|ContextMenu\.|radix-ui|@headlessui|@szhsin\/react-menu|primereact|@mui\/material|antd|enigma:allow-hand-rolled-menu/;
|
|
2098
|
+
function handRolledContextMenu(content) {
|
|
2099
|
+
if (MENU_MITIGATED.test(content)) return [];
|
|
2100
|
+
if (!MENU_HANDLER.test(content) || !MENU_POINT.test(content) || !MENU_STATE.test(content)) return [];
|
|
2101
|
+
const lines = content.split("\n");
|
|
2102
|
+
for (let i = 0; i < lines.length; i++) {
|
|
2103
|
+
const line = lines[i];
|
|
2104
|
+
if (COMMENT_LINE.test(line) || /enigma:/.test(line)) continue;
|
|
2105
|
+
if (!MENU_HANDLER.test(line)) continue;
|
|
2106
|
+
return [{ line: i + 1, detail: "a contextmenu handler, pointer coordinates and the state holding them" }];
|
|
2107
|
+
}
|
|
2108
|
+
return [];
|
|
2109
|
+
}
|
|
2110
|
+
var SELECT_RANGE_KEY = /\bshiftKey\b/;
|
|
2111
|
+
var SELECT_ADD_KEY = /\bctrlKey\b|\bmetaKey\b/;
|
|
2112
|
+
var SELECT_STATE = /\bset(?:Selected|Selection|SelectedIds|SelectedRows|Checked)\b|\bselected(?:Ids|Rows|Keys|Items)\b/;
|
|
2113
|
+
var SELECT_MITIGATED = /@enigmax\/primitives|createSelection|useSelection|<SelectionList|enigma:allow-hand-rolled-selection/;
|
|
2114
|
+
function handRolledSelection(content) {
|
|
2115
|
+
if (SELECT_MITIGATED.test(content)) return [];
|
|
2116
|
+
if (!SELECT_RANGE_KEY.test(content) || !SELECT_ADD_KEY.test(content) || !SELECT_STATE.test(content)) return [];
|
|
2117
|
+
const lines = content.split("\n");
|
|
2118
|
+
for (let i = 0; i < lines.length; i++) {
|
|
2119
|
+
const line = lines[i];
|
|
2120
|
+
if (COMMENT_LINE.test(line) || /enigma:/.test(line)) continue;
|
|
2121
|
+
if (!SELECT_RANGE_KEY.test(line)) continue;
|
|
2122
|
+
return [{ line: i + 1, detail: "Shift and Ctrl over a set of selected ids" }];
|
|
2123
|
+
}
|
|
2124
|
+
return [];
|
|
2125
|
+
}
|
|
2036
2126
|
var CLIP_ONE_LINE = /\btruncate\b|\btext-ellipsis\b|text-overflow\s*:\s*ellipsis/;
|
|
2037
2127
|
var DYNAMIC_CHILD = /(?<![=!<>-])>\s*\{(?![#/:@])/;
|
|
2038
2128
|
var VALUE_REACHABLE = /\btitle\s*=|aria-label\s*=|<\s*Tooltip|TooltipTrigger|data-tooltip|hoverCard|HoverCard/i;
|
|
@@ -2610,6 +2700,8 @@ export {
|
|
|
2610
2700
|
extensionImports,
|
|
2611
2701
|
findProjectRoot,
|
|
2612
2702
|
formatFindings,
|
|
2703
|
+
handRolledContextMenu,
|
|
2704
|
+
handRolledSelection,
|
|
2613
2705
|
loadRules,
|
|
2614
2706
|
missingPathAlias,
|
|
2615
2707
|
missingWindowsHide,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "enigma-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.40.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": {
|