Skip to content

fix: inline regex flags ((?i)) silently killed 50 of 57 instincts - #35

Open
juanparisma wants to merge 1 commit into
Luispitik:mainfrom
juanparisma:fix/inline-regex-flags-kill-instincts
Open

fix: inline regex flags ((?i)) silently killed 50 of 57 instincts#35
juanparisma wants to merge 1 commit into
Luispitik:mainfrom
juanparisma:fix/inline-regex-flags-kill-instincts

Conversation

@juanparisma

Copy link
Copy Markdown
Contributor

The bug

(?i) is Python/PCRE syntax. JavaScript has no inline flags:

new RegExp("(?i)foo", "i")   // SyntaxError: Invalid regular expression: Invalid group

Both activators compile trigger patterns inside a try/catch whose handler is a
bare continue:

// core/_instinct-activator.sh:118
if (!new RegExp(tp, "i").test(context)) continue;
} catch(e) { continue; }          // ← the instinct disappears, and nothing says so

So an instinct written with (?i) is dropped in total silence. It stays in the
index looking perfectly healthy — valid JSON, right level, sensible inject — and
never fires once for the rest of its life.

Why it went unnoticed

Nothing surfaced it. The index was valid, /dream reported only the generic
invalid_regex, and the occurrence counter stayed at 0 — which is exactly what an
instinct whose trigger simply never came up also looks like.

Trigger patterns are authored by the model when an instinct is created, and (?i) is
the reflex spelling for anyone used to grep or Python. So it accumulates quietly, one
instinct at a time.

On the index that surfaced this, 50 of 57 instincts were dead. Sorting by
occurrences made it unmistakable:

occurrences pattern instinct
2213 no (?i) env-vars-never-hardcode
642 no (?i) error-handling-explicit
552 no (?i) git-push-rebase-shared-repo
548 no (?i) git-commit-conventional
390 no (?i) memory-md-index-only
249 no (?i) verify-numbers-at-source
0 has (?i) …the other fifty

The survivors were simply the ones nobody had prefixed.

There is a second-order hazard worth flagging: because everything looked
never_activated, /dream's staleness module marked ~50 instincts as
archive_candidate. Following that advice would have archived a knowledge base whose
only problem was a syntax error.

The fixes

  • Both activators normalise inline flag groups before compiling. Stripping (?i)
    is lossless here — they already pass the "i" flag, so it was redundant on top of
    being fatal. Other groups map to real flags where JS has an equivalent and are
    dropped otherwise, which still beats losing the whole instinct. This revives
    existing indexes in place
    , without asking anyone to edit their data.
  • A pattern that genuinely cannot compile is logged as BAD_PATTERN with the
    instinct id and the engine's message. Silence is what let this run for months.
  • /dream distinguishes inline_flag_group from invalid_regex and carries a
    Detail column, so the report names the cause instead of a category.
  • commands/analyze-session.md tells the author not to write inline flags, so new
    instincts stop arriving broken.

_passive-activator.sh gets the same treatment. The shipped rules are clean today,
but they are hand-written like the instincts — the next one is one (?i) away from
vanishing the same way.

Verification

tests/test-inline-regex-flags.sh pins all of it: that JS really does reject the
syntax, that a (?i) instinct fires, that an uncompilable pattern is logged, and that
/dream separates the two causes.

  • 4 of 5 fail against the unpatched activators, 5 of 5 pass with them — checked by
    stashing the fix, so the tests are not passing for their own reasons.
  • All 17 suites green locally on a clean clone at a038b50 (16 existing + the new
    one, which is wired into .github/workflows/tests.yml).

Scope

6 files. No data migration: users' indexes keep their existing patterns and start
working again on the next tool use.

`(?i)` is Python/PCRE syntax. JavaScript has no inline flags, so
`new RegExp("(?i)foo")` throws "Invalid group" -- and both activators compiled
patterns inside a try/catch whose handler was a bare `continue`. An instinct
written that way was dropped in total silence: valid JSON, right level, sensible
inject, and it never fired once for the rest of its life.

Nothing surfaced it. The index looked healthy, /dream reported the pattern only
as the generic "invalid_regex", and the occurrence counter simply stayed at zero
-- which is indistinguishable from an instinct whose trigger just never came up.

The patterns are authored by the model when an instinct is created, and `(?i)`
is the reflex spelling for anyone used to grep or Python, so this accumulates
quietly. On the index that surfaced it, 50 of 57 instincts were dead this way;
the seven survivors were simply the ones nobody had prefixed. Sorting by
occurrences made it unmistakable -- every instinct with real activity lacked the
prefix, every prefixed one sat at zero or held a count from before it was added.

Fixes, in the order they matter:

- Both activators normalise inline flag groups before compiling. Stripping `(?i)`
  is lossless here because they already pass the "i" flag -- it was redundant on
  top of being fatal. Other groups map to real flags where JS has an equivalent
  and are dropped otherwise, which still beats losing the whole instinct. This
  revives existing indexes without asking anyone to edit their data.
- A pattern that genuinely cannot compile is now logged as BAD_PATTERN with the
  instinct id and the engine's message, instead of vanishing. Silence is what let
  this run for months.
- /dream distinguishes "inline_flag_group" from "invalid_regex" and carries a
  Detail column, so the report points at the cause instead of a category.
- commands/analyze-session.md says not to write inline flags when authoring a
  trigger, so new instincts stop arriving broken.

tests/test-inline-regex-flags.sh pins all of it: that JS really does reject the
syntax, that a `(?i)` instinct fires, that an uncompilable one is logged, and
that /dream separates the two causes. Verified to fail 4/5 against the unpatched
activators and pass 5/5 with them, so the tests are not passing for their own
reasons.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant