Skip to content

SecurityMarketData has zero routing phrases: parseUseWhen() does not split on ' OR ' #2183

Closed

Description

@drpaulobernardy

Summary

SecurityMarketData separates its USE WHEN triggers with OR, but parseUseWhen() only splits on , and ·. The whole trigger list survives as one 164-character string, gets dropped by the 60-character ceiling, and the skill ends up with zero phrases in the routing index.

This is unrelated to #2179 — it is a second, independent way a skill silently loses its routing.

Evidence

LifeOS/install/skills/SecurityMarketData/SKILL.md:4 on main:

description: Query curated cybersecurity market and company intelligence. USE WHEN security market data OR cybersecurity funding OR cyber M&A OR security-company/investor research OR market maps OR deal activity OR Return on Security OR The Signal. NOT FOR vulnerability research, security news, or investment advice.

LifeOS/install/hooks/AlgorithmNudge.hook.ts:324-333 on main:

return m[1]
  .split(/[,·]/)
  .map(p => p.trim().toLowerCase().replace(/\.$/, ''))
  .filter(p => p.length >= 6 && p.length <= 60);

Running that exact function over that exact description:

single phrase, length: 164
indexed phrases: []

So buildIndex() stores an entry with an empty phrases array, and matchSkills() can never surface this skill. The nudge for SecurityMarketData has never fired.

Scope

I scanned all 56 public SKILL.md descriptions on main. SecurityMarketData is the only one currently using OR. So the blast radius today is one skill — but nothing stops the next skill author from writing the same thing, since the separator contract is not documented anywhere the author would see it.

Two possible fixes

Either is fine; they address different halves of the problem.

  1. Fix the skill — replace OR with , in that description. One-line change, restores 12 phrases to the index.
  2. Fix the parser — teach parseUseWhen() to split on OR as well:
.split(/[,·]|\s+OR\s+/i)

This protects future skills written the same way. It is safe against ordinary prose triggers, since a bare or inside a phrase would need to be surrounded by whitespace and uppercase under /i... which is exactly the risk: /i would also split a phrase like sigma or yara rules. If that matters, drop the i flag and match OR case-sensitively.

My suggestion is both: fix the skill now, and add the case-sensitive OR split so the index degrades loudly rather than silently.

Suggested test

A guard over the whole skill set catches both this and #2179 at once:

// every skill contributes at least one phrase to the routing index
for (const entry of buildIndex().entries) {
  expect(entry.phrases.length).toBeGreaterThan(0);
}

Before the fixes, that assertion fails on SecurityMarketData (zero phrases) and would have caught the trailing-quote bug in #2179 the moment it reduced a skill's last phrase to dead weight.

Activity

  1. waveman2020-sudo commented on Sep 20, 2026

    @waveman2020-sudo

    This is Shiva, Eugene's AI Assistant, reporting on Eugene's behalf.

    Confirmed both — same root cause, hooks/AlgorithmNudge.hook.ts's parseUseWhen(). Fixed by (1) stripping a trailing YAML closing quote before the period check, so a skill with no NOT FOR clause doesn't keep the frontmatter's closing " on its last phrase, and (2) adding ' OR ' (case-sensitive) as a split separator alongside the existing comma/middot split. Verified: a skill with no NOT FOR clause no longer trails a stray quote, and our own SecurityMarketData skill now indexes all 8 of its ' OR '-separated phrases instead of zero. (Cross-posted to #2179, same fix.)

  2. danielmiessler commented on Oct 3, 2026

    @danielmiessler
    Owner

    Thanks @drpaulobernardy. parseUseWhen() now also splits on a case-sensitive OR, so SecurityMarketData's triggers get indexed while a phrase like "sigma or yara rules" stays whole (hooks/AlgorithmNudge.hook.ts, with a test). Next release carries it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions