ruvnet-brain 4.3.20 → 4.3.25
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/README.md +5 -5
- package/bin/install.mjs +383 -78
- package/console/app.js +141 -9
- package/console/index.html +51 -24
- package/console/scope.css +137 -0
- package/console/scope.html +144 -0
- package/console/scope.js +209 -0
- package/console/tips.html +1 -0
- package/kb/corpus-release-identity.mjs +239 -0
- package/kb/update-storage-transaction.mjs +20 -3
- package/package.json +9 -2
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/commands/checkpoint.md +61 -0
- package/plugin/hooks/codex-hooks.json +64 -1
- package/plugin/hooks/hook-contracts.json +299 -6
- package/plugin/hooks/hooks.json +81 -1
- package/plugin/mcp/server.mjs +23 -0
- package/plugin/scripts/advocacy-catalog.mjs +245 -0
- package/plugin/scripts/advocacy-route.mjs +460 -0
- package/plugin/scripts/continuation-gate.mjs +25 -2
- package/plugin/scripts/continuation-objective.mjs +7 -1
- package/plugin/scripts/continuity-hook-policy.mjs +190 -15
- package/plugin/scripts/coverage-integrity.mjs +7 -0
- package/plugin/scripts/gates.mjs +113 -10
- package/plugin/scripts/grounding-turn-gate.mjs +167 -0
- package/plugin/scripts/grounding-turn-mark.mjs +91 -0
- package/plugin/scripts/hook-shim.mjs +14 -0
- package/plugin/scripts/host-shell-boundary.mjs +43 -0
- package/plugin/scripts/nightly-scheduler.mjs +37 -4
- package/plugin/scripts/project-progression-checkpoint.mjs +145 -0
- package/plugin/scripts/project-progression-contract.mjs +16 -0
- package/plugin/scripts/project-progression-hook.mjs +3 -0
- package/plugin/scripts/project-progression-producer.mjs +252 -0
- package/plugin/scripts/project-progression-reader.mjs +271 -0
- package/plugin/scripts/project-progression-session-start.mjs +93 -16
- package/plugin/scripts/project-progression-sources.mjs +220 -0
- package/plugin/scripts/project-progression-store.mjs +106 -13
- package/plugin/scripts/ruvnet-gate1-pattern.mjs +29 -0
- package/plugin/scripts/session-snapshot-hook.mjs +115 -7
- package/plugin/scripts/session-start-budget.mjs +59 -0
- package/plugin/scripts/session-start-core.mjs +234 -457
- package/plugin/scripts/session-start-fsutil.mjs +61 -0
- package/plugin/scripts/session-start-health.mjs +64 -0
- package/plugin/scripts/session-start-hook-description.mjs +45 -0
- package/plugin/scripts/session-start-issue-alert.mjs +77 -0
- package/plugin/scripts/session-start-repo-identity.mjs +54 -0
- package/plugin/scripts/session-start-signals.mjs +73 -0
- package/plugin/scripts/session-start-trace.mjs +86 -0
- package/plugin/scripts/session-start-update-plane.mjs +104 -0
- package/plugin/scripts/unprompted-runtime.mjs +32 -2
- package/plugin/scripts/update-apply.mjs +2 -32
- package/plugin/skills/ruvnet-brain/PLAYBOOK.md +26 -2
- package/plugin/skills/ruvnet-brain/SKILL.md +67 -2
- package/scripts/adr-072-completion.mjs +1 -1
- package/scripts/agentdb-fleet-doctor.mjs +5 -1
- package/scripts/approved-runtime.mjs +197 -0
- package/scripts/brain-novice-50.mjs +16 -1
- package/scripts/brain-score.mjs +23 -5
- package/scripts/build-bundle.mjs +971 -530
- package/scripts/build-concepts.mjs +36 -116
- package/scripts/console-engine.test.mjs +8 -7
- package/scripts/console-runtime-identity.mjs +4 -0
- package/scripts/corpus-aggregates.mjs +94 -77
- package/scripts/corpus-candidate.mjs +475 -222
- package/scripts/corpus-next-seed.mjs +225 -0
- package/scripts/corpus-promotion.mjs +58 -0
- package/scripts/corpus-reconcile.mjs +411 -105
- package/scripts/doc-currency.mjs +16 -1
- package/scripts/dual-host-deliberation.mjs +25 -2
- package/scripts/dual-host-suggest.mjs +17 -1
- package/scripts/falsify.mjs +13 -3
- package/scripts/gist-receipts.mjs +482 -87
- package/scripts/github-health-watch.mjs +12 -2
- package/scripts/handoff-asset.mjs +34 -0
- package/scripts/hook-retirement-check.mjs +8 -1
- package/scripts/host-registry.mjs +1 -1
- package/scripts/ingest-gists.mjs +74 -101
- package/scripts/job-heartbeat.sh +77 -14
- package/scripts/learning-replay-execution.mjs +10 -4
- package/scripts/nightly-gists.sh +27 -13
- package/scripts/nightly-two-run-proof.mjs +1 -1
- package/scripts/nightly-watchdog.mjs +61 -4
- package/scripts/onboarding-console.mjs +319 -27
- package/scripts/oracle/produce-questions.mjs +293 -0
- package/scripts/oracle/producer-hosts.mjs +235 -0
- package/scripts/oracle/repo-recall.mjs +448 -0
- package/scripts/oracle/retrieval-accuracy.mjs +818 -0
- package/scripts/oracle/source-tree.mjs +165 -0
- package/scripts/oracle/source-units.mjs +391 -0
- package/scripts/oracle/spike-run.mjs +98 -0
- package/scripts/oracle/unit-inventory.mjs +141 -0
- package/scripts/oracle/unit-sampling.mjs +128 -0
- package/scripts/oracle/validate-labels.mjs +250 -0
- package/scripts/private-overlay.mjs +248 -0
- package/scripts/product-integrity-contract.mjs +1 -1
- package/scripts/proxy/claude-proxied.sh +6 -0
- package/scripts/proxy/proxy-revert.sh +5 -0
- package/scripts/proxy/proxy-up.sh +6 -0
- package/scripts/proxy/proxy-verify.mjs +4 -0
- package/scripts/public-inputs.mjs +409 -0
- package/scripts/public-verification-inputs.mjs +112 -26
- package/scripts/public-verification-lane.mjs +1 -1
- package/scripts/published-surface-probe.mjs +34 -4
- package/scripts/qe/card-lane-gate.mjs +16 -1
- package/scripts/qe/session-start-gate.mjs +16 -1
- package/scripts/rebuild-gists-from-receipts.mjs +58 -78
- package/scripts/record-lesson.mjs +4 -1
- package/scripts/rehearse-corpus-pipeline.mjs +994 -0
- package/scripts/release-abort-stale.mjs +5 -1
- package/scripts/release-authority.mjs +104 -12
- package/scripts/release-channel-kind.mjs +86 -0
- package/scripts/release-convergence-watchdog.mjs +7 -2
- package/scripts/release-projection.mjs +177 -72
- package/scripts/release-transaction-provider.mjs +23 -6
- package/scripts/release.mjs +252 -17
- package/scripts/retrieval-canary.mjs +87 -0
- package/scripts/rvf-index-audit.mjs +573 -13
- package/scripts/rvf-wire.mjs +269 -0
- package/scripts/seal-gist-receipt.mjs +65 -0
- package/scripts/selfcheck.mjs +42 -21
- package/scripts/source-coverage.mjs +253 -24
- package/scripts/status-honesty.mjs +25 -0
- package/scripts/sync-census.mjs +0 -0
- package/scripts/sync-version.mjs +2 -0
- package/scripts/trismart.mjs +42 -0
- package/scripts/updater-manifest.mjs +162 -0
- package/scripts/verify-channels.mjs +17 -5
- package/scripts/wired-check.mjs +48 -10
- package/tri-smart-skill/QUICKSTART.md +37 -0
- package/tri-smart-skill/README.md +92 -0
- package/tri-smart-skill/install.cmd +14 -0
- package/tri-smart-skill/install.command +13 -0
- package/tri-smart-skill/install.mjs +51 -0
- package/tri-smart-skill/install.sh +9 -0
- package/tri-smart-skill/tri-smart/SKILL.md +90 -0
- package/tri-smart-skill/tri-smart/evals/evals.json +25 -0
- package/tri-smart-skill/tri-smart/references/protocol.md +25 -0
- package/tri-smart-skill/tri-smart/references/provider-cli.md +18 -0
- package/tri-smart-skill/tri-smart/scripts/review.mjs +154 -0
- package/tri-smart-skill/tri-smart/scripts/setup.mjs +97 -0
- package/tri-smart-skill/tri-smart/scripts/verify-access.mjs +107 -0
- package/scripts/corpus-seed-publish.mjs +0 -110
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
// advocacy-catalog.mjs — the CLOSED taxonomy of ordinary-request intents, each bound to exactly ONE
|
|
2
|
+
// RuvNet building block that serves it. Data only: no IO, no regex execution, no policy.
|
|
3
|
+
//
|
|
4
|
+
// ─────────────────────────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
// WHY THIS EXISTS AND WHY IT IS NOT A SECOND goal-match.mjs.
|
|
6
|
+
//
|
|
7
|
+
// goal-match.mjs already classifies prompts, and duplicating it would be the "hand-rolled substitute"
|
|
8
|
+
// failure this repo has a CI gate against. It is not duplicated here because the two answer different
|
|
9
|
+
// questions over disjoint inputs, and the measured evidence for that is in goal-match.mjs itself:
|
|
10
|
+
//
|
|
11
|
+
// 1. ITS TAXONOMY IS ABOUT THE ASSISTANT, NOT ABOUT THE WORK. Every GOALS entry is reverse-derived
|
|
12
|
+
// from a dormant capability's `whatItBuysYou` — "you are re-teaching me the same rule", "work is
|
|
13
|
+
// not surviving between sessions". Those are complaints about the harness. "Search these docs by
|
|
14
|
+
// meaning" is a complaint about nothing; it is a BUILD REQUEST, and goal-match has no goal for it.
|
|
15
|
+
// 2. ITS GLOBAL_VETO REJECTS EXACTLY THIS TRAFFIC. goal-match.mjs:110-113 vetoes any prompt
|
|
16
|
+
// containing `production`, `customers`, `deploy`, `api key`, `sdk` — on purpose, because those
|
|
17
|
+
// mark app work rather than harness work. Two of the six scenarios this route exists to serve
|
|
18
|
+
// ("opening this chatbot to customers next week", "our LLM bill doubled") are vetoed on their
|
|
19
|
+
// first noun. Widening that veto would break goal-match's own contract.
|
|
20
|
+
// 3. ITS `serves` NAMES MACHINE-STATE KEYS, NOT BUILDING BLOCKS. `cheap-model-routing`,
|
|
21
|
+
// `write-gates`, `session-capture` are rows in capability-registry.auditAll() — things that are
|
|
22
|
+
// installed and switched off. agentic-qe, @claude-flow/aidefence and ruvector are not rows there
|
|
23
|
+
// and are frequently not installed at all, so anticipate.sh's SILENCE RULE 1 ("only state 'off'
|
|
24
|
+
// ever speaks; 'absent' is silent — nothing to switch on") makes them unreachable BY DESIGN.
|
|
25
|
+
//
|
|
26
|
+
// So: anticipate.sh answers "what have you already got that is switched off?" and this catalogue
|
|
27
|
+
// answers "what does rUv already ship that would materially help THIS request?". Same channel, same
|
|
28
|
+
// runtime, same ledger, same dial — different question, different corpus. Nothing is re-implemented:
|
|
29
|
+
// suppression is advocacy-outcomes.mjs, delivery is unprompted-runtime.mjs, and the prose each
|
|
30
|
+
// capability is described by is the hand-written card in kb/capability-cards.md.
|
|
31
|
+
//
|
|
32
|
+
// ─────────────────────────────────────────────────────────────────────────────────────────────────
|
|
33
|
+
// THE GROUNDING RULE, MECHANICAL. Every `card` below MUST exist as a `## <card>` heading in
|
|
34
|
+
// kb/capability-cards.md, and tests/unit/advocacy-catalog.test.mjs fails if one does not. That is why
|
|
35
|
+
// this file can name a capability at all: the claim is not "I remember this package", it is "this
|
|
36
|
+
// repo's own grounded card describes it". `nextAction` and `undo` strings were verified LIVE on
|
|
37
|
+
// 2026-09-11 against the installed tools, and each carries the command that proved it:
|
|
38
|
+
//
|
|
39
|
+
// aqe --help / aqe coverage --help / aqe quality --help → coverage --gaps --risk, quality --gate,
|
|
40
|
+
// quality-gate, test schedule (flaky
|
|
41
|
+
// tracking is on unless --no-flaky)
|
|
42
|
+
// ruflo hooks --help / ruflo hooks model-route --help → "Route task to optimal Claude model
|
|
43
|
+
// (haiku/sonnet/opus) based on complexity"
|
|
44
|
+
// node -e "import('@claude-flow/aidefence')" → v3.0.3, exports createAIDefence,
|
|
45
|
+
// isSafe, checkThreats
|
|
46
|
+
// ls ~/.npm-global/lib/node_modules/@ruvector/ → rvf, rvf-node, rvf-mcp-server present
|
|
47
|
+
// agentic-flow --help → v2.1.2, `proxy`, multi-provider
|
|
48
|
+
//
|
|
49
|
+
// NOT verified and therefore NOT claimed anywhere below: "QE-Court" (no such `aqe` subcommand; the
|
|
50
|
+
// nearest verified things are `aqe arena` tournaments and the `aqe-court-referee` binary, which this
|
|
51
|
+
// file does not describe because its interface was not checked).
|
|
52
|
+
// ─────────────────────────────────────────────────────────────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* One entry per building block. Fields, and why each is required:
|
|
56
|
+
* id the ledger's finding identity suffix and the word the user says back ("use <id>")
|
|
57
|
+
* card the `## <heading>` in kb/capability-cards.md this claim is grounded in (TESTED)
|
|
58
|
+
* benefit ONE clause naming a concrete outcome for the requesting task — never a feature list
|
|
59
|
+
* nextAction a SAFE, read-only or additive first step, verified live (see the header)
|
|
60
|
+
* undo the inverse. `human-only` where no single command reverses it — never a fabricated one
|
|
61
|
+
* probe { pkgs, bins } used for a cheap, in-process availability read. Absence ⇒ 'unknown',
|
|
62
|
+
* never 'absent': we can see one npm root and a cwd, not nvm/pnpm/volta/yarn/bun.
|
|
63
|
+
*/
|
|
64
|
+
export const CAPABILITIES = Object.freeze({
|
|
65
|
+
ruvector: Object.freeze({
|
|
66
|
+
id: 'ruvector',
|
|
67
|
+
card: 'ruvector',
|
|
68
|
+
benefit: 'it indexes those docs as embeddings in one portable .rvf file and answers by meaning with HNSW nearest-neighbour search, locally, with no hosted vector database',
|
|
69
|
+
nextAction: 'npm i @ruvector/rvf, then RvfDatabase.create(...) over a sample of the docs',
|
|
70
|
+
undo: 'delete the .rvf file — nothing else is touched',
|
|
71
|
+
probe: Object.freeze({ pkgs: ['@ruvector/rvf', '@ruvector/rvf-node', 'ruvector'], bins: ['ruvector'] }),
|
|
72
|
+
}),
|
|
73
|
+
agentdb: Object.freeze({
|
|
74
|
+
id: 'agentdb',
|
|
75
|
+
card: 'agentdb',
|
|
76
|
+
benefit: 'it gives the agent durable structured memory that survives process restarts, with graph relationships and explainable recall instead of a re-read of the whole transcript',
|
|
77
|
+
nextAction: 'agentdb --help to see the store/recall surface before wiring anything',
|
|
78
|
+
undo: 'delete the store file — it is a single local database',
|
|
79
|
+
probe: Object.freeze({ pkgs: ['agentdb', '@claude-flow/memory'], bins: ['agentdb'] }),
|
|
80
|
+
}),
|
|
81
|
+
ruflo: Object.freeze({
|
|
82
|
+
id: 'ruflo',
|
|
83
|
+
card: 'ruflo',
|
|
84
|
+
benefit: 'it runs those reviewers as one coordinated swarm in parallel with shared memory, so their findings land in a single tracked place instead of four disconnected transcripts',
|
|
85
|
+
nextAction: 'ruflo swarm init --topology hierarchical, then ruflo agent spawn per reviewer',
|
|
86
|
+
undo: 'ruflo swarm shutdown',
|
|
87
|
+
probe: Object.freeze({ pkgs: ['ruflo'], bins: ['ruflo'] }),
|
|
88
|
+
}),
|
|
89
|
+
aidefence: Object.freeze({
|
|
90
|
+
id: 'aidefence',
|
|
91
|
+
card: 'aidefence',
|
|
92
|
+
benefit: 'AIMDS screens inbound prompts and outbound model output for jailbreaks, injection and PII before either reaches a customer, which is the layer a customer-facing chatbot is missing',
|
|
93
|
+
nextAction: 'npm i @claude-flow/aidefence, then createAIDefence({ enableLearning: true }) on the inbound path',
|
|
94
|
+
undo: 'remove the middleware call — it is additive and holds no state you depend on',
|
|
95
|
+
probe: Object.freeze({ pkgs: ['@claude-flow/aidefence'], bins: [] }),
|
|
96
|
+
}),
|
|
97
|
+
'agentic-qe': Object.freeze({
|
|
98
|
+
id: 'agentic-qe',
|
|
99
|
+
card: 'agentic-qe',
|
|
100
|
+
benefit: 'it reports risk-weighted coverage gaps and tracks flaky tests, and its quality gate returns a real pass/fail verdict instead of a coverage percentage nobody trusts',
|
|
101
|
+
nextAction: 'aqe coverage --gaps --risk (read-only), then aqe quality --gate',
|
|
102
|
+
undo: 'nothing to undo — both commands are read-only reports',
|
|
103
|
+
probe: Object.freeze({ pkgs: ['agentic-qe'], bins: ['aqe'] }),
|
|
104
|
+
}),
|
|
105
|
+
'agentic-flow': Object.freeze({
|
|
106
|
+
id: 'agentic-flow',
|
|
107
|
+
card: 'agentic-flow',
|
|
108
|
+
benefit: 'it routes each request to the cheapest model that can still do it, per task rather than per project, so the simple majority stops being billed at top-tier rates',
|
|
109
|
+
nextAction: 'ruflo hooks model-route -t "<a real task>" to see the haiku/sonnet/opus split before changing anything',
|
|
110
|
+
undo: 'stop calling the router — routing is advisory and changes no stored state',
|
|
111
|
+
probe: Object.freeze({ pkgs: ['agentic-flow'], bins: ['agentic-flow'] }),
|
|
112
|
+
}),
|
|
113
|
+
rulake: Object.freeze({
|
|
114
|
+
id: 'rulake',
|
|
115
|
+
card: 'rulake',
|
|
116
|
+
benefit: 'it caches vector reads in front of the store so repeated lookups return in sub-millisecond time and the hit ratio tunes itself as the query mix settles',
|
|
117
|
+
nextAction: 'query the rulake MCP tool rulake_query once against the existing index and compare latency',
|
|
118
|
+
undo: 'stop routing reads through the cache — the underlying store is unchanged',
|
|
119
|
+
probe: Object.freeze({ pkgs: ['rulake', 'rulake-mcp'], bins: ['rulake'] }),
|
|
120
|
+
}),
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* INTENTS — a closed list. Each entry binds a described need to ONE capability.
|
|
125
|
+
*
|
|
126
|
+
* WHY CLOSED, AND WHY THIS SHORT. Six of these seven exist because a real host, in a measured test on
|
|
127
|
+
* 2026-09-10, was handed that exact request and either took 15 minutes to answer or never named the
|
|
128
|
+
* capability at all. The seventh (vector-cache) is the one adjacent case whose card and MCP tool were
|
|
129
|
+
* both verifiable in the same pass. An intent nobody has been measured missing is a guess about a user,
|
|
130
|
+
* and a guess that speaks is the nag ADR-028 exists to prevent — so the list grows on evidence only.
|
|
131
|
+
*
|
|
132
|
+
* `cues` are LEXICAL and IN-PROCESS on purpose (no embedder, no child process, no network, no
|
|
133
|
+
* search_ruvnet at prompt time): an embedder's cold init alone is ~3 s against a 3 s hook timeout, so
|
|
134
|
+
* a semantic matcher here would not be a better matcher, it would be a dead one. Grounding is not
|
|
135
|
+
* skipped, it is MOVED: the model is instructed by SKILL.md to confirm with search_ruvnet before it
|
|
136
|
+
* builds, and this file's claims are pinned to kb/capability-cards.md by a test.
|
|
137
|
+
*
|
|
138
|
+
* TWO CUES, NOT ONE — the same rule goal-match.mjs sets out and for the same reason: "One cue is a
|
|
139
|
+
* coincidence. Two is a statement." A single keyword hit is how a recommender becomes a nag.
|
|
140
|
+
*/
|
|
141
|
+
export const INTENTS = Object.freeze([
|
|
142
|
+
Object.freeze({
|
|
143
|
+
id: 'semantic-search',
|
|
144
|
+
capability: 'ruvector',
|
|
145
|
+
fit: 'the request is to retrieve by meaning rather than by literal match',
|
|
146
|
+
cues: Object.freeze([
|
|
147
|
+
/\bby meaning\b/,
|
|
148
|
+
/\bsemantic(ally)?\s+(search|retriev|match|similar)/,
|
|
149
|
+
/\b(instead of|rather than|not just|beyond)\s+(an?\s+)?(exact\s+)?(keywords?|string|substring|literal|grep)/,
|
|
150
|
+
/\bvector\s+(search|database|db|store|index|embedding)/,
|
|
151
|
+
/\bembeddings?\b/,
|
|
152
|
+
/\b(nearest[- ]neighbou?r|hnsw|similarity search)\b/,
|
|
153
|
+
/\b(pinecone|qdrant|weaviate|chroma|pgvector|faiss)\b/,
|
|
154
|
+
/\b(rag|retrieval[- ]augmented)\b/,
|
|
155
|
+
/\bfind\s+\w*\s*(similar|related)\s+(docs?|documents?|passages?|chunks?|notes?)\b/,
|
|
156
|
+
]),
|
|
157
|
+
}),
|
|
158
|
+
Object.freeze({
|
|
159
|
+
id: 'agent-memory',
|
|
160
|
+
capability: 'agentdb',
|
|
161
|
+
fit: 'the request is for state that outlives a single run of the agent',
|
|
162
|
+
cues: Object.freeze([
|
|
163
|
+
/\bforg(et|ets|etting|ot)\b/,
|
|
164
|
+
/\b(durable|persistent|long[- ]term)\s+memory\b/,
|
|
165
|
+
/\b(between|across)\s+(runs?|sessions?|invocations?|restarts?|conversations?)\b/,
|
|
166
|
+
/\b(remembers?|recalls?)\s+\w*\s*(across|between|later|next time)\b/,
|
|
167
|
+
/\bagent\s+(state|memory)\b/,
|
|
168
|
+
/\bstarts?\s+(over|from scratch)\s+(each|every)\b/,
|
|
169
|
+
/\bno memory\b/,
|
|
170
|
+
]),
|
|
171
|
+
}),
|
|
172
|
+
Object.freeze({
|
|
173
|
+
id: 'multi-agent-orchestration',
|
|
174
|
+
capability: 'ruflo',
|
|
175
|
+
fit: 'the request is for several agents working at once whose output has to come back together',
|
|
176
|
+
cues: Object.freeze([
|
|
177
|
+
/\b(multiple|several|many|a team of|a fleet of|\d+)\s+(ai\s+|llm\s+)?(agents?|reviewers?|workers?|bots?|models?)\b/,
|
|
178
|
+
/\bin parallel\b/,
|
|
179
|
+
/\bswarms?\b/,
|
|
180
|
+
/\borchestrat(e|es|ing|ion)\b/,
|
|
181
|
+
/\b(coordinate|coordinating)\s+(the\s+)?(agents?|workers?|sub-?agents?|reviewers?)\b/,
|
|
182
|
+
/\bsub-?agents?\b/,
|
|
183
|
+
/\b(merge|combine|aggregate|consolidate)\s+\w*\s*(findings|results|reports|reviews|output)\b/,
|
|
184
|
+
]),
|
|
185
|
+
}),
|
|
186
|
+
Object.freeze({
|
|
187
|
+
id: 'llm-safety',
|
|
188
|
+
capability: 'aidefence',
|
|
189
|
+
fit: 'the request exposes a model to untrusted users and needs the input/output boundary defended',
|
|
190
|
+
cues: Object.freeze([
|
|
191
|
+
/\bjail[- ]?break/,
|
|
192
|
+
/\bprompt injection\b/,
|
|
193
|
+
/\bleak(s|ing|age|ed)?\b/,
|
|
194
|
+
/\b(pii|personally identifiable)\b/,
|
|
195
|
+
/\b(chat ?bot|assistant|llm|model|ai)\b[^.!?]{0,60}\b(customers?|end users?|the public|publicly)\b/,
|
|
196
|
+
/\bguard ?rails?\b/,
|
|
197
|
+
/\b(sanitis|sanitiz|filter|screen)\w*\s+(the\s+)?(prompts?|inputs?|outputs?|responses?)\b/,
|
|
198
|
+
/\bother\s+(customers?|users?|tenants?)'?s?\s+data\b/,
|
|
199
|
+
/\b(red[- ]?team|abuse|malicious)\s+(prompt|input|user)/,
|
|
200
|
+
]),
|
|
201
|
+
}),
|
|
202
|
+
Object.freeze({
|
|
203
|
+
id: 'test-quality',
|
|
204
|
+
capability: 'agentic-qe',
|
|
205
|
+
fit: 'the request is to make the test suite trustworthy rather than merely larger',
|
|
206
|
+
cues: Object.freeze([
|
|
207
|
+
/\bflak(y|iness|ey)\b/,
|
|
208
|
+
/\bun-?tested\b/,
|
|
209
|
+
/\bcoverage\b/,
|
|
210
|
+
/\bquality gates?\b/,
|
|
211
|
+
/\btest (suite|gaps?|debt)\b/,
|
|
212
|
+
/\b(generate|write|add)\s+\w*\s*tests?\b/,
|
|
213
|
+
/\bwhat'?s? (not |un)tested\b/,
|
|
214
|
+
]),
|
|
215
|
+
}),
|
|
216
|
+
Object.freeze({
|
|
217
|
+
id: 'llm-cost',
|
|
218
|
+
capability: 'agentic-flow',
|
|
219
|
+
fit: 'the request is to lower model spend without lowering output quality',
|
|
220
|
+
cues: Object.freeze([
|
|
221
|
+
/\b(llm|ai|api|token|model|inference)\s+(bill|costs?|spend(ing)?)\b/,
|
|
222
|
+
/\b(cut|reduce|lower|halve|shrink)\s+(the\s+|our\s+|my\s+)?(cost|costs|spend|spending|bill)\b/,
|
|
223
|
+
/\btoo expensive\b/,
|
|
224
|
+
/\bcheaper model\b/,
|
|
225
|
+
/\b(bill|cost|spend|spending)\s+\w*\s*(doubled|tripled|exploded|out of control)\b/,
|
|
226
|
+
/\bmost\s+(requests?|calls?|prompts?|tasks?|queries)\s+are\s+(simple|trivial|easy|basic)\b/,
|
|
227
|
+
/\bper[- ]token\b/,
|
|
228
|
+
]),
|
|
229
|
+
}),
|
|
230
|
+
Object.freeze({
|
|
231
|
+
id: 'vector-cache',
|
|
232
|
+
capability: 'rulake',
|
|
233
|
+
fit: 'the request is that repeated retrieval over an existing index is too slow',
|
|
234
|
+
cues: Object.freeze([
|
|
235
|
+
/\b(same|repeated|identical|duplicate)\s+(quer(y|ies)|lookups?|searches?|retrievals?)\b/,
|
|
236
|
+
/\bcach\w+[^.!?]{0,40}\b(vector|embedding|retrieval|search|lookup)\b/,
|
|
237
|
+
/\b(vector|embedding|semantic)\s+(search|quer(y|ies)|lookups?)[^.!?]{0,40}\b(slow|latency|expensive|costly)\b/,
|
|
238
|
+
/\bsub-?millisecond\b/,
|
|
239
|
+
/\bcache hit ?(rate|ratio)\b/,
|
|
240
|
+
]),
|
|
241
|
+
}),
|
|
242
|
+
]);
|
|
243
|
+
|
|
244
|
+
/** Two cues, never one — see the INTENTS note above. Exported so a test can pin the threshold. */
|
|
245
|
+
export const MIN_CUES = 2;
|