Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Apply safe error-pattern matching rules for agentic engines.
.claude/skills/github-error-pattern-safety/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 66% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 29% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 22% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 7% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 19% | 0% |
Use these regex safety rules in agentic engines to prevent JavaScript infinite loops.
With the JavaScript global flag (/pattern/g), zero-width matches can cause infinite loops because:
regex.exec() with the g flag uses lastIndex to track positionlastIndex doesn't advance❌ NEVER USE THESE PATTERNS:
javascript// Pure .* - matches everything including empty string at end /.*/g // Single character with * - matches zero or more (including zero) /a*/g // Patterns that can match empty string /(x|y)*/g
✅ ALWAYS USE PATTERNS LIKE THESE:
javascript// Required prefix before .* /error.*/gi /error.*permission.*denied/gi // Specific structure with required content /\[(\d{4}-\d{2}-\d{2})\]\s+(ERROR):\s+(.+)/g // Required characters throughout /access denied.*user.*not authorized/gi
.+ instead of .* when you need "something".* as the entire patternerror.*.* or .*?javascript const regex = /your-pattern/g; if (regex.test("")) { throw new Error("Pattern matches empty string - DANGEROUS!"); }
^error.*.*error$\berror\bAll error patterns must pass the same safety checks used by the repo’s unit suite:
go// Test that pattern doesn't match empty string func TestPatternSafety(t *testing.T) { pattern := "your-pattern" regex := regexp.MustCompile(pattern) if regex.MatchString("") { t.Error("Pattern matches empty string!") } }
Run the relevant package tests with make test-unit.
javascripttest("should not match empty string", () => { const regex = new RegExp("your-pattern", "g"); expect(regex.test("")).toBe(false); });
Use the relevant *.test.cjs suite under actions/setup/js/ or pkg/workflow/js/ for the area you changed, or run the repo’s JavaScript checks via make test-js.
The repo’s validation helpers include built-in protections for dangerous regex patterns:
javascriptif (regex.lastIndex === lastIndex) { core.error(`Infinite loop detected! Pattern: ${pattern.pattern}`); break; }
When adding new error patterns to engines:
go { Pattern: (?i)error.permission.denied, LevelGroup: 0, MessageGroup: 0, Description: "Permission denied error", }
make test-unitTestAllEnginePatternsSafePatterns are converted from Go to JavaScript:
go// Go pattern (case-insensitive flag) Pattern: `(?i)error.*permission.*denied` // Converted to JavaScript new RegExp("error.*permission.*denied", "gi")
The (?i) prefix is removed because JavaScript uses the i flag instead.
go// Requires "error" prefix Pattern: `(?i)error.*permission.*denied` // Requires specific timestamp format Pattern: `(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z)\s+\[(ERROR)\]\s+(.+)` // Requires "access denied" prefix Pattern: `(?i)access denied.*user.*not authorized`
If you find a pattern that matches empty string:
Before (unsafe):
goPattern: `.*error.*` // Can match empty at start/end
After (safe):
goPattern: `error.*` // Requires "error" at start // OR Pattern: `.*error.+` // Requires "error" and at least one char after // OR Pattern: `\berror\b.*` // Requires word "error"
Before committing pattern changes:
make test-unitmake test-js or the targeted Vitest suitemake test-unit and make test-js| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-12 | fail→fail | 21,260 | 17,192 | -19% | 1 | 1 | 0% | 2,823 | 3,604 | +28% | 0 | 0 | — |
case-01 | fail→pass | 21,161 | 24,287 | +15% | 1 | 1 | 0% | 2,780 | 4,614 | +66% | 0 | 0 | — |
case-02 | fail→pass | 21,943 | 17,278 | -21% | 1 | 1 | 0% | 2,722 | 3,524 | +29% | 0 | 0 | — |
case-03 | pass→pass | 15,296 | 14,274 | -7% | 1 | 1 | 0% | 2,026 | 3,028 | +49% | 0 | 0 | — |
case-04 | pass→pass | 9,891 | 10,999 | +11% | 1 | 1 | 0% | 854 | 2,554 | +199% | 0 | 0 | — |
case-05 | pass→pass | 8,192 | 7,521 | -8% | 1 | 1 | 0% | 547 | 1,881 | +244% | 0 | 0 | — |
case-06 | fail→pass | 17,992 | 6,453 | -64% | 1 | 1 | 0% | 2,126 | 2,592 | +22% | 0 | 0 | — |
case-07 | pass→pass | 18,944 | 13,114 | -31% | 1 | 1 | 0% | 2,321 | 2,808 | +21% | 0 | 0 | — |
case-08 | fail→pass | 20,072 | 11,665 | -42% | 1 | 1 | 0% | 2,467 | 2,631 | +7% | 0 | 0 | — |
case-09 | pass→pass | 12,631 | 9,476 | -25% | 1 | 1 | 0% | 1,356 | 2,151 | +59% | 0 | 0 | — |
case-10 | fail→pass | 22,168 | 17,261 | -22% | 1 | 1 | 0% | 3,129 | 3,728 | +19% | 0 | 0 | — |
case-11 | pass→pass | 18,073 | 12,004 | -34% | 1 | 1 | 0% | 1,994 | 2,610 | +31% | 0 | 0 | — |
case-13 | fail→pass | 21,945 | 14,533 | -34% | 1 | 1 | 0% | 2,850 | 3,017 | +6% | 0 | 0 | — |
case-14 | pass→pass | 16,654 | 10,250 | -38% | 1 | 1 | 0% | 1,927 | 2,310 | +20% | 0 | 0 | — |
case-15 | fail→pass | 18,666 | 7,870 | -58% | 1 | 1 | 0% | 2,308 | 1,902 | -18% | 0 | 0 | — |
case-16 | pass→pass | 23,870 | 17,006 | -29% | 1 | 1 | 0% | 2,827 | 3,239 | +15% | 0 | 0 | — |
case-17 | pass→pass | 22,592 | 22,048 | -2% | 1 | 1 | 0% | 2,817 | 4,072 | +45% | 0 | 0 | — |
case-18 | pass→pass | 23,223 | 15,189 | -35% | 1 | 1 | 0% | 2,648 | 3,185 | +20% | 0 | 0 | — |
case-19 | pass→pass | 21,657 | 19,204 | -11% | 1 | 1 | 0% | 2,715 | 3,930 | +45% | 0 | 0 | — |
case-20 | fail→fail | 18,829 | 9,153 | -51% | 1 | 1 | 0% | 2,002 | 2,135 | +7% | 0 | 0 | — |
case-21 | fail→pass | 22,375 | 13,409 | -40% | 1 | 1 | 0% | 2,661 | 2,743 | +3% | 0 | 0 | — |
case-22 | fail→pass | 21,714 | 8,752 | -60% | 1 | 1 | 0% | 2,461 | 2,026 | -18% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +41 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/9/2026 | +27% |
Other measured skills in the registry, with their headline benchmark lift.