@softspark/ai-toolkit 4.8.0 → 4.10.0

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.
Files changed (47) hide show
  1. package/AGENTS.md +7 -131
  2. package/CHANGELOG.md +32 -0
  3. package/README.md +16 -16
  4. package/app/.claude-plugin/plugin.json +1 -1
  5. package/app/ARCHITECTURE.md +2 -2
  6. package/app/constitution.md +6 -2
  7. package/app/hooks/_session-paths.sh +40 -0
  8. package/app/hooks/pre-compact.sh +6 -4
  9. package/app/hooks/save-session.sh +4 -2
  10. package/app/hooks/session-end.sh +7 -6
  11. package/app/hooks/session-start.sh +3 -1
  12. package/app/hooks.json +0 -10
  13. package/app/output-styles/golden-rules.md +4 -0
  14. package/app/skills/api-patterns/SKILL.md +67 -0
  15. package/app/skills/brand-voice/SKILL.md +10 -1
  16. package/app/skills/brand-voice/modes/concise.md +3 -0
  17. package/app/skills/brand-voice/modes/strict.md +2 -0
  18. package/app/skills/deep-research/SKILL.md +97 -0
  19. package/app/skills/design-engineering/SKILL.md +73 -0
  20. package/app/skills/mcp-builder/SKILL.md +3 -0
  21. package/app/skills/mcp-patterns/SKILL.md +58 -0
  22. package/app/skills/research-mastery/SKILL.md +49 -0
  23. package/app/skills/security-patterns/SKILL.md +33 -1
  24. package/app/skills/verification-before-completion/SKILL.md +35 -0
  25. package/kb/planning/drop-cascade-hooks-after-sunset.md +91 -0
  26. package/kb/reference/architecture-overview.md +5 -5
  27. package/kb/reference/enterprise-config-guide.md +4 -4
  28. package/kb/reference/hooks-catalog.md +19 -22
  29. package/kb/reference/opencode-compatibility.md +1 -1
  30. package/kb/reference/skills-catalog.md +2 -1
  31. package/kb/reference/supported-tools-registry.md +1 -1
  32. package/kb/reference/unique-features.md +0 -1
  33. package/llms-full.txt +131 -36
  34. package/llms.txt +1 -0
  35. package/manifest.json +1 -1
  36. package/package.json +5 -5
  37. package/scripts/emission.py +11 -1
  38. package/scripts/generate_augment_hooks.py +0 -1
  39. package/scripts/generate_codex.py +5 -2
  40. package/scripts/generate_codex_hooks.py +0 -5
  41. package/scripts/generate_cursor_hooks.py +0 -1
  42. package/scripts/generate_devin_hooks.py +0 -5
  43. package/scripts/generate_gemini_hooks.py +0 -5
  44. package/scripts/generate_opencode_plugin.py +1 -2
  45. package/scripts/generate_windsurf_hooks.py +0 -3
  46. package/scripts/generator_base.py +5 -2
  47. package/app/hooks/session-context.sh +0 -63
@@ -74,6 +74,7 @@ Also loaded when a project sets `output-mode: concise` or `output-mode: strict`
74
74
  | **Active over passive** | "The function returns X" not "X is returned by the function." |
75
75
  | **Technical over casual** | Match the audience's expertise. Never dumb down for developers. |
76
76
  | **Honest over promotional** | State limitations alongside strengths. |
77
+ | **Accountable over apologetic** | Own a mistake once, fix it, move on. No repeated apology, self-abasement, or caving to pushback you can disprove. |
77
78
 
78
79
  ## Sentence-Level Rules
79
80
 
@@ -82,6 +83,13 @@ Also loaded when a project sets `output-mode: concise` or `output-mode: strict`
82
83
  - **One idea per sentence.** If a sentence has "and" linking two distinct ideas, split it.
83
84
  - **Use concrete subjects.** Bad: "It is important to note that..." Good: (delete the phrase, state the fact)
84
85
 
86
+ ## Formatting Discipline
87
+
88
+ - **Default to prose.** Use bullets, numbered lists, or headers only when (a) the user asks for a list or ranking, or (b) the content is genuinely multifaceted and a list is the clearest form. A list of one or two items is a sentence — write the sentence.
89
+ - **Every bullet carries content.** Each bullet is at least one full clause, usually one to two sentences. A one-word bullet is a sentence in disguise.
90
+ - **Match format to document type.** Reports, explanations, and narrative docs default to prose; inline enumerations read as "the steps are X, Y, and Z" without breaking into bullets. Reference material, comparisons, and option tables are where lists and tables earn their place.
91
+ - **Minimum formatting for clarity.** Reach for the lightest structure that makes the content clear. Headers, bold, and nesting are tools, not decoration.
92
+
85
93
  ## Before Publishing Checklist
86
94
 
87
95
  - [ ] No banned phrases from anti-trope list?
@@ -107,7 +115,7 @@ potential of your workflow.
107
115
  Good (direct, specific, active):
108
116
 
109
117
  ```
110
- ai-toolkit installs 99 skills and 44 agents via `npm install -g @softspark/ai-toolkit`.
118
+ ai-toolkit installs 108 skills and 44 agents via `npm install -g @softspark/ai-toolkit`.
111
119
  After install, run `ai-toolkit doctor` to verify symlinks and hooks. Typical
112
120
  install takes under 30 seconds on a local disk.
113
121
  ```
@@ -120,6 +128,7 @@ install takes under 30 seconds on a local disk.
120
128
  - **NEVER** use em dashes or en dashes in prose — they signal LLM output. Use commas, periods, or parentheses instead
121
129
  - **CRITICAL**: one idea per sentence. If you write "and" linking two distinct ideas, split the sentence
122
130
  - **MANDATORY**: technical claims include a concrete number, name, or example — never assert quality without evidence
131
+ - **NEVER** format a refusal, a "no", or a correction as bullet points — prose carries it with less abruptness
123
132
 
124
133
  ## Output Modes
125
134
 
@@ -64,4 +64,7 @@ Token ratio: 76 → 25 = 33%.
64
64
 
65
65
  - If a question genuinely needs 30 lines to answer, write 30. Don't truncate facts to hit the budget.
66
66
  - If the user asks "explain", give one solid paragraph, not a one-liner.
67
+ - A request for a long or detailed answer overrides the mode. Suspend the budget for that response and answer in full.
68
+ - Mode quality applies to prose only. Code, diffs, configs, and generated artifacts keep full quality and completeness regardless of mode — never trade correctness for brevity.
69
+ - Name the mode only if the user objects to the length or asks why responses are short. Then say it is `output-mode: concise` and that `/brand-voice default` resets it. Otherwise never mention the mode.
67
70
  - If unsure whether the user wants depth, ask. One question is cheaper than a wrong-length response.
@@ -88,4 +88,6 @@ Recommend: Postgres.
88
88
 
89
89
  - Strict mode does NOT mean wrong. If a fact requires 5 lines to be correct, write 5 lines. Cut framing, never substance.
90
90
  - Strict mode does NOT mean rude. Drop pleasantries, not respect.
91
+ - Code, diffs, configs, and generated artifacts are never abbreviated for the budget. Strict trims prose, never output the user will run or ship.
91
92
  - If the user explicitly asks for explanation, switch to concise mode for that response. Strict is the default, not a gag.
93
+ - Name the mode only if the user objects to the terseness or asks about it. Then say it is `output-mode: strict` and that `/brand-voice default` resets it. Otherwise stay silent about the mode.
@@ -0,0 +1,97 @@
1
+ ---
2
+ name: deep-research
3
+ description: "Multi-source web research methodology: retrieve-vs-answer gate, complexity-scaled search budget, query craft, primary-source preference, source-conflict skepticism, adversarial verification, attribution-without-reproduction. Triggers: deep research, multi-source, web research, synthesize sources, cross-reference, fact synthesis, source verification."
4
+ user-invocable: false
5
+ allowed-tools: Read
6
+ ---
7
+
8
+ # Deep Research
9
+
10
+ This is the web / multi-source counterpart to `research-mastery`. That skill is KB-first: it answers from the project's own knowledge base and only reaches outward when the KB comes up empty. This one governs what happens once you are already out on the open web pulling from many independent sources and have to weave them into one trustworthy answer. It is a method, not a fetcher — it does not retrieve anything by itself. You supply the search and fetch tools (built-in `WebSearch` / `WebFetch`, or the runtime `deep-research` command); this skill tells you how to spend them and how hard to doubt what comes back.
11
+
12
+ ## Retrieve-vs-Answer Gate
13
+
14
+ Run this gate before you spend a single search:
15
+
16
+ 1. **Is the answer already in the KB or your own context?** Then this is not a deep-research job — hand it to `research-mastery` (which checks RAG-MCP first) or just answer.
17
+ 2. **Is it one stable fact** with a single obvious authority (a constant, a published spec value, a definition that does not move)? One targeted lookup, confirm, done. Do not open a research campaign.
18
+ 3. **Does it need several independent sources reconciled, or is it contested, recent, or moving?** That is the case this skill exists for. Continue.
19
+
20
+ Skipping this gate is the most common failure: people fan out ten searches on a question that one source already settled, or worse, answer a contested question from memory because it "felt known."
21
+
22
+ ## Scale Effort to Complexity
23
+
24
+ Match the search budget to the question. Burning twenty searches on a lookup wastes turns; doing two searches on a contested synthesis ships a half-checked claim.
25
+
26
+ | Question shape | Plan first? | Rough search budget |
27
+ |----------------|-------------|---------------------|
28
+ | Single stable fact, clear authority | no | 1, maybe a second to confirm |
29
+ | Compare a few known options / current state of one topic | light | a handful, broaden then narrow |
30
+ | Contested, multi-faceted, or "what is the latest on…" | yes — write the plan | many, with follow-ups as conflicts surface |
31
+
32
+ For anything in the bottom two rows, write a short research plan first: name the sub-questions, the kind of source that would answer each, and what "done" looks like. The plan is for you; keep it tight. Then let conflict drive the count — if sources disagree, you have not searched enough yet.
33
+
34
+ ## Query Craft
35
+
36
+ - **Broaden, then narrow.** Open with a short, plain query to map the landscape; tighten with specific terms once you see what vocabulary the good sources actually use. Long kitchen-sink queries on the first try usually return noise.
37
+ - **Use the real current date.** Anchor "recent", "latest", "current" to today's actual date — never to your training cutoff. For 2026-06-15, "latest" means 2026, not 2024. A query that silently assumes an old year is a wrong query.
38
+ - **Vary the angle on a stubborn question.** If one phrasing returns thin or repetitive results, change the wording, the framing, or the assumed source type rather than re-running near-identical strings.
39
+
40
+ ## Source Preference and Skepticism
41
+
42
+ - **Prefer primary and original sources.** Go to the spec, the paper, the official docs, the filing, the dataset, the person who actually said it — not a blog summarizing a blog summarizing it. Each hop away from the origin adds a chance for drift.
43
+ - **A surprising-but-sourced result is usually real.** If a credible primary source says something counterintuitive, treat it as true and report it. Do not soften or discard a well-attributed fact just because it clashes with your prior.
44
+ - **The exception: low-trust topic zones.** On SEO-spam-saturated queries, conspiracy-adjacent claims, and topics with genuinely no expert consensus, raise the bar instead of lowering it. Here a surprising claim needs strong independent corroboration before you repeat it, and "many pages say it" is not corroboration when those pages copy each other.
45
+ - **Conflict means search more.** When two solid sources disagree, that is a signal to run additional searches and find a tie-breaker or the underlying primary source — not to average them, pick the one you like, or paper over the disagreement.
46
+
47
+ ## Adversarial Verification
48
+
49
+ Before you emit any synthesized claim, run this self-check. Each gate has a fix; do not just notice the problem.
50
+
51
+ | Self-check gate | If yes, do this |
52
+ |-----------------|-----------------|
53
+ | Am I mirroring one source's exact phrasing or structure? | Re-state it in your own words from the facts, not the prose. |
54
+ | Could my output stand in for reading the original — same length, same order, same examples? | Cut it back. Summarize and point to the source; do not reproduce it. |
55
+ | Have I already leaned on this one source for several claims? | Find an independent source, or flag the answer as single-sourced. |
56
+ | Is each claim independently corroborated, or is one shaky source carrying the conclusion? | Corroborate it, drop it, or label it as unconfirmed. |
57
+
58
+ For **high-stakes claims** — anything affecting money, health, legal exposure, security posture, or an irreversible decision — do not stop at one source. Confirm with a second, independent source or a different angle of approach before you state it as fact.
59
+
60
+ ## Citation Discipline
61
+
62
+ - **Paraphrase by default, and attribute to a named source.** "Per the FY2025 10-K…", "the RFC's section on retries states…". The reader should always know who is behind a claim.
63
+ - **Reserve verbatim quotes for genuinely distinctive phrasing** — a definition, a legal clause, an exact figure where the wording itself matters. Keep quotes short and clearly marked. Do not quote at length to fill space.
64
+ - **Keep any single source's paraphrased footprint small.** No one source's material should dominate your output, and the output as a whole must never substitute for reading the originals. You are pointing readers to the sources, not republishing them.
65
+ - **NEVER invent an attribution.** If you are not sure a source actually said something, leave the claim out. A fabricated citation is worse than a missing one — it launders a guess as a fact.
66
+ - **Empty retrieval is a real result.** If a search returns nothing usable, say "not found in available sources" and cite nothing. Do not backfill from memory and dress it up as retrieved.
67
+
68
+ ## Example
69
+
70
+ **Task:** "What is the current recommended approach for X, and has it changed recently?"
71
+
72
+ 1. **Gate.** Not in KB, contested, has a "recently" — this is a deep-research job. Write a 3-line plan: (a) current recommendation, (b) what it replaced, (c) when/why it changed.
73
+ 2. **Broaden.** Plain query anchored to the real date ("X recommended approach 2026"). Map who the authoritative voices are.
74
+ 3. **Narrow to primary sources.** Open the official docs / spec / changelog rather than roundup posts. Pull the version and date where the guidance changed.
75
+ 4. **Conflict surfaces.** One source still recommends the old approach. Run more searches; find the changelog entry that supersedes it. The disagreement was stale-vs-current, not a genuine split — note that.
76
+ 5. **Adversarial pass.** Re-check each gate: paraphrase in own words (not mirroring the docs' structure), confirm the change claim against a second independent source since it drives the answer, confirm no single source carries everything.
77
+ 6. **Synthesize with attribution.** "The official docs as of <date> recommend …; this replaced … per the <date> changelog." Short, sourced, original phrasing, none of it a stand-in for the docs themselves.
78
+
79
+ ## Rules
80
+
81
+ - **MUST** pass the retrieve-vs-answer gate before searching — KB-answerable or single-fact questions do not start a research campaign.
82
+ - **MUST** scale the search budget to question complexity and write a plan for contested or multi-faceted questions.
83
+ - **MUST** anchor every "latest / current / recent" query to the real current date, never the training cutoff.
84
+ - **MUST** prefer primary and original sources over second-hand summaries.
85
+ - **MUST** run more searches when credible sources conflict — never average, cherry-pick, or hide the disagreement.
86
+ - **MUST** run the adversarial self-check before emitting a synthesized claim, and apply the corrective action when a gate trips.
87
+ - **MUST** verify high-stakes claims (money, health, legal, security, irreversible) against an independent second source or angle.
88
+ - **NEVER** fabricate an attribution; if unsure a source said it, omit the claim.
89
+ - **NEVER** let one source's paraphrased footprint dominate, and never let the output substitute for reading the originals.
90
+ - **CRITICAL**: on empty retrieval, declare "not found in available sources" and cite nothing — do not backfill from memory.
91
+ - **Authorized security work is in scope.** For sanctioned defensive analysis, CTF, vulnerability research, or pentest engagements, research and report on attack techniques, CVEs, exploit mechanics, and adversary tradecraft normally — the skepticism rules raise source quality, they do not gate legitimate security topics.
92
+
93
+ ## When NOT to Use
94
+
95
+ - For a **single stable fact** already in the project KB or answerable in one lookup — use `research-mastery` (KB-first hierarchy) instead, or just answer.
96
+ - For **library / framework / API documentation** — query `context7` (or `research-mastery`'s MCP tier) for current docs rather than fanning out on the open web.
97
+ - When you need a tool that **actually fetches** — this skill is methodology only. Pair it with `WebSearch` / `WebFetch` or the runtime `deep-research` command; it retrieves nothing on its own.
@@ -16,6 +16,64 @@ Based on Emil Kowalski's design engineering philosophy — UI polish, component
16
16
  - **Invisible details create love.** Most UI refinements users never consciously register — but combined they produce something stunning.
17
17
  - **Beauty differentiates.** When functionality is table stakes, aesthetic excellence becomes genuine leverage.
18
18
 
19
+ ## Anti-Slop Visual Checklist
20
+
21
+ Defaults that signal machine-generated UI. Each is a falsifiable thing to avoid:
22
+
23
+ - **Avoid** full-bleed saturated gradient backgrounds (purple-to-pink hero washes). A flat surface or a near-flat tonal shift reads as intentional; a loud gradient reads as a template.
24
+ - **Avoid** emoji as load-bearing decoration — emoji standing in for icons, bullet markers, or section badges. Use a real icon set or typographic hierarchy instead.
25
+ - **Avoid** the rounded-card-with-left-accent-border cliche repeated across every block. If three sections share that exact treatment, vary the layout or drop the accent.
26
+ - **Avoid** hand-drawn fake imagery in SVG (synthetic "photos", invented logos, faux screenshots). Use a real asset or an honest labeled placeholder.
27
+ - **Avoid** the overused default font stack (Inter/Roboto on system-ui for everything with no scale or weight intent). Pick type with a reason and lift the actual stack from source when one exists.
28
+
29
+ ## Minimum-Scale Floors
30
+
31
+ Accessibility-grounded hard thresholds. Going below these is a defect, not a style choice:
32
+
33
+ | Context | Floor | Basis |
34
+ |---|---|---|
35
+ | Slide / presentation body text | ~24px | Readable from the back of a room |
36
+ | Print body text | ~12pt | Legible at arm's length on paper |
37
+ | Mobile touch targets | 44px × 44px | Apple HIG minimum tappable size |
38
+
39
+ Treat these as the lower bound, not the target. Captions and footnotes may approach the floor; primary content should sit comfortably above it.
40
+
41
+ ## Context-First Discipline
42
+
43
+ High-fidelity work MUST be rooted in real context before any pixels are produced. This mirrors the toolkit's verify-don't-recall ethos:
44
+
45
+ - **Read the source first.** Inspect the codebase, design tokens, UI kit, and screenshots that already exist before generating anything.
46
+ - **Lift exact values.** Copy real hex codes, the spacing scale, the font stack, and radii straight from source. Do NOT reconstruct token values from memory — recalled values drift.
47
+ - **Mock from scratch only as a last resort.** Building a screen with no reference is the fallback when no codebase, kit, or screenshot exists, not the default.
48
+
49
+ ## Question-Budget Gate
50
+
51
+ Calibrate questions to how bounded the ask is, then proceed:
52
+
53
+ - **Rich context + bounded ask** → ask nothing, build. Example: "match this card to the existing dashboard" with the repo in hand.
54
+ - **Open ask** → ask before building. Example: "prototype my onboarding" needs goals, target audience, and which dimension to diverge on (UX flow vs. visual treatment vs. copy). Resolve those three, then start.
55
+
56
+ ## Explore Many Variations
57
+
58
+ For exploratory or open work, produce **3+ atomic variations** across distinct axes, never three tweaks of one idea:
59
+
60
+ - Vary on different dimensions: layout, color, type treatment, interaction model.
61
+ - Deliberately mix safe matches with at least one novel direction — do not converge early.
62
+ - Order them basic → advanced so the reviewer can scan the gradient (the "Design It Twice" premise extended past two).
63
+
64
+ ## Match Existing Vocabulary
65
+
66
+ When editing a live UI, conform to it instead of imposing a new style:
67
+
68
+ - Reverse-engineer the palette, interactive states (hover/active/disabled), motion timing, and shadow/card/density treatment.
69
+ - Match the copy tone too — terse product UI and chatty marketing copy are different vocabularies.
70
+ - A change that introduces a foreign style is a regression even when it looks good in isolation.
71
+
72
+ ## No-Filler Content
73
+
74
+ - **Every element earns its place.** No dummy stats, decorative sections, or lorem blocks added just to fill space. If a block has no purpose, cut it.
75
+ - **Honest placeholder beats a bad fake.** A labeled placeholder ("[product screenshot]") is better than an invented icon or hand-drawn fake image. Do NOT fabricate assets — ask for the real ones.
76
+
19
77
  ## Animation Decision Framework
20
78
 
21
79
  ### Frequency determines approach
@@ -248,6 +306,13 @@ Deliberate actions stay slow (2s linear for hold-to-delete), system responses sn
248
306
  | Identical enter/exit speed | Make exit faster (e.g., 2s enter, 200ms exit) |
249
307
  | Simultaneous element appearance | Stagger 30-80ms between items |
250
308
 
309
+ ## Two-Stage Verification Handoff
310
+
311
+ Visual work ships through two passes, mirroring the toolkit's verification-before-completion and subagent two-stage review ethos:
312
+
313
+ 1. **Cheap self-check.** Load the rendered result yourself, eyeball it, and fix the obvious breaks (broken layout, wrong token, console errors) before handing off. Never claim done on output you have not opened.
314
+ 2. **Independent verifier pass.** A separate reviewer (or fresh subagent) does the deeper check — visual fidelity against source, layout under different widths, console clean. On pass it stays silent; it surfaces ONLY on failure, with the specific defect.
315
+
251
316
  ## Anti-Patterns
252
317
 
253
318
  - `transition: all` — animates unintended properties, hurts performance
@@ -265,6 +330,14 @@ Deliberate actions stay slow (2s linear for hold-to-delete), system responses sn
265
330
  - **NEVER** add motion for decorative reasons alone — every animation must serve meaning (status change, spatial relationship, progress)
266
331
  - **CRITICAL**: exit is faster than enter. A 2s linear enter (hold-to-delete) needs a 200ms ease-out exit. Symmetrical durations feel sluggish.
267
332
  - **MANDATORY**: any animation longer than 300ms for UI feedback needs an explicit justification — the user perceives >300ms as "laggy", not "smooth"
333
+ - **MUST** lift exact values (hex, spacing, font stack, radii) from the real codebase, tokens, UI kit, or screenshots before high-fidelity work — never reconstruct token values from memory; mock from scratch only when no source exists
334
+ - **MUST** keep slide body text at ~24px+, print at ~12pt+, and mobile touch targets at 44px+ — these are accessibility floors, not preferences
335
+ - **NEVER** ship the slop defaults — saturated full-bleed gradients, emoji as decoration, repeated rounded-card-with-accent-border, hand-drawn fake imagery in SVG, or the unconsidered default font stack
336
+ - **NEVER** add filler (dummy stats, decorative sections, lorem) to fill space, and never fabricate assets — an honest labeled placeholder beats an invented icon or fake image; ask for the real one
337
+ - **MUST** match the existing UI's vocabulary (palette, states, motion, shadow/density, copy tone) when editing a live surface instead of imposing a new style
338
+ - **MUST** ask about goals, audience, and which dimension to diverge on (UX vs. visuals vs. copy) before building an open-ended ask; skip questions only when context is rich and the ask is bounded
339
+ - **CARVE-OUT**: a sanctioned design audit, accessibility-failure demonstration, or authorized red-team mockup may deliberately reproduce a slop pattern or sub-floor scale to illustrate the defect — label it as such; the bans above target shipped UI, not sanctioned analysis
340
+ - **SHOULD** produce 3+ atomic variations across distinct axes (layout, color, type, interaction), ordered basic → advanced, for any exploratory or open design ask
268
341
 
269
342
  ## Gotchas
270
343
 
@@ -77,10 +77,13 @@ Example eval questions for a `github-mcp`:
77
77
  2. "Create an issue titled Y in repo Z"
78
78
  3. "Who has the most commits this month in repo X?"
79
79
 
80
+ When a tool fails an eval, the cause is almost always the description, not the schema. Score each tool against the description rubric in `mcp-patterns` (one-line purpose, WHEN TO USE, WHEN NOT TO USE, CRITICAL, self-test). A tool with an empty **WHEN NOT TO USE** is under-specified — it will misfire the moment a second tool in the same server overlaps with it, so add the boundary before re-running the eval. See `mcp-patterns` → "How to Write a Tool Description" for the full rubric and worked example.
81
+
80
82
  ## Tool Design Checklist
81
83
 
82
84
  - [ ] Name has service prefix and is verb-led
83
85
  - [ ] Description mentions when to use it and includes trigger keywords
86
+ - [ ] Description carries a non-empty **WHEN NOT TO USE** that names overlapping tools (see `mcp-patterns` rubric)
84
87
  - [ ] Input schema is strict, no free-form `object` with `additionalProperties: true`
85
88
  - [ ] Output is focused — essential fields only, with pagination cursor if applicable
86
89
  - [ ] Error responses are actionable ("API returned 403 — check `GITHUB_TOKEN` env var")
@@ -66,6 +66,64 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
66
66
 
67
67
  ---
68
68
 
69
+ ## How to Write a Tool Description
70
+
71
+ The `description` is the only signal the model uses to route a request. The schema constrains the *call*; the description decides *whether the call happens at all*. Treat it as a routing contract, not API prose. A good one has five parts, in this order:
72
+
73
+ 1. **One-line purpose** — what the tool does, in plain terms. Lead with a verb. `Search indexed knowledge-base documents and return ranked passages.` Skip the HTTP verb and endpoint; `calls GET /v2/search` tells the model nothing about intent.
74
+ 2. **WHEN TO USE** — concrete trigger phrasings the user might say, not abstract categories. List the actual shapes: *"find docs about X", "what does the KB say about Y", "look up the runbook for Z"*. Models match on surface form, so give them surface forms.
75
+ 3. **WHEN NOT TO USE** — the section that does most of the disambiguation work. Name the near-miss tools and the boundary that separates them. This is where you prevent the model from firing the wrong tool on a request that *looks* similar. Empty WHEN NOT TO USE = the tool is under-specified.
76
+ 4. **CRITICAL** — one line for the single non-obvious failure mode. The constraint a reader would not guess from the schema: a required ordering, an ID that must come from another call, a cost/irreversibility warning. One line, not a checklist.
77
+ 5. **Self-test** — close with a question the model can apply to itself to decide fit. `Ask: is the user looking up existing content, or asking me to create new content? This tool is read-only — if they want to create, stop.`
78
+
79
+ ### Why negative examples outweigh positive ones
80
+
81
+ Positive triggers tell the model when a tool *could* apply; negative ones are what stop it firing on overlapping requests. When two tools have similar purposes (`search_kb` vs `search_code`, `get_document` vs `list_documents`), the only thing keeping the model off the wrong one is each description naming the other and drawing the line. Budget more words for the boundary than the bullseye.
82
+
83
+ ### Disambiguating near-miss tools
84
+
85
+ When tools overlap, make each WHEN NOT TO USE point at its neighbour and state the discriminator explicitly:
86
+
87
+ ```text
88
+ search_kb
89
+ WHEN NOT TO USE: do not use to fetch a document you already have the id for —
90
+ that is get_document. Use search_kb only when you need to discover *which*
91
+ document, by meaning or keyword.
92
+
93
+ get_document
94
+ WHEN NOT TO USE: do not use to find a document by topic or keyword — you must
95
+ already hold an exact id (from search_kb results). For discovery, use search_kb.
96
+ ```
97
+
98
+ ### Worked example
99
+
100
+ ```text
101
+ name: cancel_workflow
102
+ description: |
103
+ Stop a running agent workflow and discard its in-flight results.
104
+
105
+ WHEN TO USE: the user says "cancel the workflow", "stop run abc123",
106
+ "kill that job", or asks to halt a workflow that get_workflow_status
107
+ reports as RUNNING.
108
+
109
+ WHEN NOT TO USE:
110
+ - To inspect progress without stopping — use get_workflow_status.
111
+ - To start a fresh run — use start_workflow.
112
+ - On a workflow already in a terminal state (COMPLETED/FAILED) — the call
113
+ is a no-op and signals the model misread the status.
114
+
115
+ CRITICAL: cancellation is irreversible and drops partial output. Confirm the
116
+ workflowId came from list_workflows or get_workflow_status — never type one
117
+ from memory.
118
+
119
+ Self-test: am I stopping work that is genuinely still RUNNING, or did I confuse
120
+ "check status" with "cancel"? If I have not seen a RUNNING status, do not call this.
121
+ ```
122
+
123
+ A description that survives this rubric routes correctly without the model reading your source. One that skips WHEN NOT TO USE will misfire the moment a second, similar tool exists in the same server.
124
+
125
+ ---
126
+
69
127
  ## Transport Patterns
70
128
 
71
129
  ### 1. stdio (Default)
@@ -43,6 +43,55 @@ You MUST search in this order. Do not skip steps.
43
43
  **Why**: Fallback for general programming concepts.
44
44
  **Rule**: Use only for generic syntax/logic, NEVER for project specifics.
45
45
 
46
+ ## 🚦 Retrieve-vs-Answer Gate
47
+
48
+ Before you reach for any tool, decide whether retrieval is even warranted. Two axes settle it:
49
+
50
+ - **Volatility** — how fast does the true answer change?
51
+ - *Timeless / slow-moving* (math, definitions, settled algorithms, language syntax): answer directly from built-in knowledge. A search adds latency and noise.
52
+ - *Current-state / volatile* (latest version, today's price, who holds a role now, "is X still the recommended way"): retrieve. Your training data is a snapshot and will lie about the present.
53
+ - **Recognition** — can you place the entity?
54
+ - If answering hinges on knowing what some named thing IS (a library, an internal project, a person, an acronym) and you cannot confidently place it, treat that as a signal to search, not to guess. An unfamiliar name is a retrieval trigger, not a hallucination prompt.
55
+
56
+ When both axes say "timeless and recognized", skip the hierarchy and answer. Otherwise, enter it at Step 1.
57
+
58
+ ## 📊 Complexity-Scaled Retrieval Budget
59
+
60
+ Match effort to the question. Over-retrieving on a one-fact lookup wastes the turn; under-retrieving on a comparison ships a half-answer.
61
+
62
+ | Question shape | Rough budget |
63
+ |---|---|
64
+ | Single discrete fact ("which version", "default port") | ~1 lookup |
65
+ | Medium question, one entity, a couple of angles | a few lookups |
66
+ | Deep comparison, multiple entities or trade-offs | more lookups, broaden then narrow |
67
+
68
+ **Escalation handoff** — when a question genuinely needs sustained fan-out (many sources, cross-checking, adversarial verification, a synthesized report), stop expanding inline. Hand off to the `deep-research` skill/agent instead of letting one turn balloon into a dozen ad-hoc searches. Inline research is for bounded lookups; deep, multi-source investigation has its own harness.
69
+
70
+ ## 🧭 Internal-First Source Ladder
71
+
72
+ The Hierarchy of Truth above already puts KB first — that order stands. Add a routing heuristic on top:
73
+
74
+ - **Possessive / company language routes inward.** When the question uses "our", "my <X>", or names an internal project, system, or team, the answer lives in internal tools and the KB, not on the open web. Searching the public internet for "our auth flow" returns someone else's auth flow.
75
+ - **Name the missing source; do not silently fall back.** If the answer should come from an internal source that is absent or unreachable (the KB lacks the doc, an MCP is not configured), say so by name and surface the gap. Do not quietly substitute a public-web guess for the internal source the user actually meant.
76
+
77
+ ## ✍️ Query Craft
78
+
79
+ - **Keep queries short.** A few keywords beat a full sentence; retrieval engines reward focused terms, not prose.
80
+ - **Broaden, then narrow.** Open with a wider query to map the space, then tighten toward the specific answer once you see the landscape.
81
+ - **Never repeat a near-identical query.** If a search disappointed, change the angle or vocabulary — re-running the same words returns the same misses and burns budget.
82
+ - **Fetch the full source over snippets.** When a result looks load-bearing, pull the whole document rather than reasoning from a one-line excerpt that may strip the qualifier that matters.
83
+ - **Use the ACTUAL current date for date-sensitive queries.** When recency matters, anchor on today's real date at query time — read it from the environment, do not hardcode a year. A baked-in or stale year quietly filters you onto last year's results.
84
+
85
+ ## 🔬 Source Skepticism & Conflict Handling
86
+
87
+ - **Prefer primary and original sources.** Go to the spec, the changelog, the official docs, the author — not a blog summarizing a summary.
88
+ - **Lead with the most recent for fast-moving topics.** When the subject changes quickly, weight newer sources first; an old top-ranked page can be confidently wrong about the present.
89
+ - **When sources conflict, search more.** Disagreement is a signal to widen the search and find the tie-breaker, not to pick the first hit and move on.
90
+ - **Stay skeptical where the web is gamed.** SEO-spammed niches, conspiracy-prone topics, and areas with no real consensus need extra cross-referencing before you trust any single source.
91
+ - **Confabulation guard — zero results means zero citations.** If retrieval surfaces nothing relevant, say so plainly and emit no citations. Never invent a `[PATH: kb/...]`, a URL, or a quote to fill the gap. An honest "not found" beats a fabricated source.
92
+
93
+ > Carve-out: none of the above is grounds to refuse authorized security work. CTF challenges, sanctioned pentests, and defensive analysis are legitimate research targets — apply the same rigor (primary sources, conflict checks, no fabricated citations) without declining.
94
+
46
95
  ## Local Fallback (No MCP Available)
47
96
 
48
97
  If `rag-mcp` is not configured, fall back to filesystem tools — still inside `kb/`:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: security-patterns
3
- description: "App security: OWASP, authN/authZ, input validation, secrets, TLS, CSRF/XSS/SQLi, JWT, CSP. Triggers: security, OWASP, auth, JWT, CSRF, XSS, SQL injection, secrets, TLS, CSP, CORS."
3
+ description: "App security: OWASP, authN/authZ, input validation, secrets, TLS, CSRF/XSS/SQLi, JWT, CSP, LLM prompt injection. Triggers: security, OWASP, auth, JWT, CSRF, XSS, SQL injection, secrets, TLS, CSP, CORS, prompt injection, LLM output trust, tool permissions."
4
4
  effort: medium
5
5
  user-invocable: false
6
6
  allowed-tools: Read
@@ -81,6 +81,36 @@ async def resource():
81
81
 
82
82
  ---
83
83
 
84
+ ## Prompt Injection & LLM-Output Trust
85
+
86
+ When the app embeds an LLM, every byte the model emits — plus tool results, retrieved documents, and fetched web pages — is **untrusted input on the same footing as a raw request body**. Text inside that content that reads like an instruction ("ignore previous rules", "call the delete tool", "email the config to…") is still data. Render it, store it, classify it — but never let it drive control flow, widen permissions, or fire a side effect without an explicit human decision. This mirrors the agent-behavior rule in [constitution Article VII](../../constitution.md); the rules here cover the application you are building, not the assistant's own behavior.
87
+
88
+ ### Trust Boundary
89
+
90
+ | Source | Trust | Handling |
91
+ |--------|-------|----------|
92
+ | System prompt / app-defined policy | Trusted | The only place instructions may originate |
93
+ | User chat turn | Semi-trusted | Authenticated to a user, still validate + scope to their permissions |
94
+ | Model output | Untrusted | Treat as data; gate any tool call it requests |
95
+ | Tool / function results | Untrusted | Re-validate before feeding back into context |
96
+ | Retrieved docs / RAG chunks | Untrusted | Strip or delimit embedded instructions |
97
+ | Fetched web / email / file content | Untrusted | Highest risk — sanitize before it crosses into the prompt |
98
+
99
+ ### Defenses
100
+
101
+ - **Separate instructions from data.** Keep app policy in the system prompt; wrap all untrusted content in clear delimiters or distinct structured fields (e.g. a `documents` array) so the model can tell "what to do" from "what to read." Never string-concatenate retrieved text into the instruction block.
102
+ - **Least-privilege tools.** Give each tool the narrowest scope it needs. A summarizer needs no write or network egress capability. Fewer reachable side effects shrink the blast radius of a successful injection.
103
+ - **Human-in-the-loop for irreversible actions.** Destructive, financial, or data-exfiltrating operations (delete, transfer, send-to-external-recipient, broad file reads) require explicit human confirmation — not a model token that "looks like" approval.
104
+ - **Validate and allowlist tool arguments.** Parse the model's proposed arguments against a schema, allowlist targets (recipient domains, table names, paths), and reject anything outside it. The model choosing a tool is a *request*, not authorization.
105
+ - **Keep secrets out of injectable context.** Never place API keys, internal URLs, or other users' data in a prompt that an injected instruction could later echo back into output. If the model cannot see it, it cannot be coaxed into leaking it.
106
+ - **Bound indirect (second-order) injection.** Content ingested now may carry instructions that only fire on a later turn — a poisoned doc indexed today, a web page fetched mid-task, a comment in a parsed file. Sanitize and size-limit everything at the moment it crosses the trust boundary, not when it is finally read.
107
+
108
+ ### Carve-out: Authorized Defensive Work
109
+
110
+ Building injection **detection** (classifiers, guardrails, eval suites) and running **authorized** red-team exercises — CTF, sanctioned pentest, internal adversarial testing of these defenses — is fully in scope. Generating injection payloads for that purpose is expected; the OWASP / authorized-testing framing of this skill applies to LLM apps exactly as it does to SQLi or XSS work.
111
+
112
+ ---
113
+
84
114
  ## Common Rationalizations
85
115
 
86
116
  | Excuse | Why It's Wrong |
@@ -90,6 +120,8 @@ async def resource():
90
120
  | "We'll add auth later" | Unauthenticated endpoints in production get discovered within hours |
91
121
  | "Nobody would exploit this" | Automated scanners don't care about your threat model — they scan everything |
92
122
  | "It's behind a VPN" | VPNs are perimeter defense — zero trust assumes breach already happened |
123
+ | "The LLM would never follow a malicious instruction in a doc" | Models follow whatever reads like an instruction — retrieved content is untrusted input, not policy |
124
+ | "We let the agent run the tool it picked, that's the point" | A model picking a tool is a request, not authorization — gate side effects behind allowlists and human confirmation |
93
125
 
94
126
  ## Reference Guides
95
127
 
@@ -43,6 +43,23 @@ Skip any step = lying, not verifying
43
43
  - Moving to next task
44
44
  - Delegating to agents
45
45
 
46
+ ## Don't Assume It Exists
47
+
48
+ A prompt — yours, the user's, or another agent's — naming a file, table, column, endpoint, env var, config key, or dependency is a *hint*, not a fact. The name existing in text is not the same as the thing existing in the repo.
49
+
50
+ - Before you read from, write to, import, or quote any such resource, confirm it: `Read` the file, `ls`/`grep` the path, list the table, check the lockfile. One look beats a confident guess.
51
+ - Never reconstruct a file's contents, a function's body, or an API's signature from its name alone. The name tells you almost nothing about the shape. If you haven't read it, you don't know it.
52
+ - A plausible-sounding path or symbol is the easiest thing in the world to invent. Treat your own fluency here as a warning sign, not as evidence.
53
+ - AUTHORIZED security work (CTF, sanctioned pentest, defensive review) still verifies — probing whether a path/endpoint/parameter actually exists is part of the job, not an exception to it.
54
+
55
+ ## Declare Ungrounded as a Real Outcome
56
+
57
+ When search, KB lookup, or tool calls come back with nothing relevant, the correct move is to *say so and stop* — not to backfill the hole from training memory and present it as established fact.
58
+
59
+ - "Not found in `<source>`" is a complete, honest answer. State which source you checked and that it came up empty.
60
+ - Do not promote a half-remembered detail to a definite claim just because the gap feels uncomfortable. An unverified recollection is a hypothesis; label it as one or leave it out.
61
+ - If the missing piece blocks the task, surface the gap and ask — do not paper over it with a guess dressed as a finding.
62
+
46
63
  ## Common Failures
47
64
 
48
65
  | Claim | Requires | Not Sufficient |
@@ -57,6 +74,9 @@ Skip any step = lying, not verifying
57
74
  | No dead code (Art. VI.1) | Grep for every removed/renamed symbol: 0 references | "I cleaned up what I touched" |
58
75
  | Behavior change covered (Art. VI.2) | Integration test for the API surface + unit test + docs updated | Unit test on the helper only |
59
76
  | Diff is clean (Art. VI.4) | Re-read full diff: no orphaned imports, no stale docs, no skipped fixes | "I only changed what I needed" |
77
+ | Resource exists (file/table/env var/endpoint/dep) | Read/list/grep it and see it | The prompt mentioned it, or the name sounds real |
78
+ | File contents / API signature | Open the file, read the actual lines | Inferring shape from the filename or symbol name |
79
+ | Answer is grounded | A source you actually read returns it | Recalling it from training memory |
60
80
 
61
81
  ## Red Flags — STOP
62
82
 
@@ -79,6 +99,21 @@ Skip any step = lying, not verifying
79
99
  | "Partial check is enough" | Partial proves nothing |
80
100
  | "Different words so rule doesn't apply" | Spirit over letter |
81
101
 
102
+ ## Pre-Completion Self-Audit
103
+
104
+ Before you type "done", run these fast yes/no gates over your own draft. Each one has a fix — if the answer is bad, do the fix, don't ship the draft.
105
+
106
+ | Self-check | If the honest answer is "no" / "yes, I did" |
107
+ |------------|---------------------------------------------|
108
+ | Did I actually run the verification command this message, or am I asserting success from memory? | Run it now. Memory is not a test result. |
109
+ | Does every factual claim trace to output or a source I actually saw? | Cite the evidence, or cut the claim. |
110
+ | Did I invent any path, filename, symbol, table, flag, or version number? | Verify it exists, or remove it. |
111
+ | Did I quote file contents or an API signature I never opened? | Open and confirm, or stop quoting. |
112
+ | Did a search/KB lookup come back empty that I then "filled in" anyway? | Replace the fill-in with "not found in `<source>`". |
113
+ | Am I about to commit/push/PR on the strength of a claim I haven't proven? | Prove it first. |
114
+
115
+ Same ethos as the rest of this skill: evidence before assertions, applied to your own output one line at a time.
116
+
82
117
  ## Key Patterns
83
118
 
84
119
  **Tests:**
@@ -0,0 +1,91 @@
1
+ ---
2
+ title: "Plan: Drop Cascade hooks after 2026-07-01 sunset"
3
+ category: planning
4
+ service: ai-toolkit
5
+ tags:
6
+ - windsurf
7
+ - devin
8
+ - cascade
9
+ - hooks
10
+ - deprecation
11
+ - cleanup
12
+ doc_type: plan
13
+ status: scheduled
14
+ created: "2026-06-10"
15
+ last_updated: "2026-06-10"
16
+ completion: "0%"
17
+ trigger_date: "2026-07-01"
18
+ description: "Scheduled cleanup: remove the deprecated Windsurf Cascade hooks generator (.windsurf/hooks.json) in the first ai-toolkit release after the 2026-07-01 Cascade sunset. The Devin CLI replacement (.devin/hooks.v1.json) shipped in v4.8.0; this plan removes the dead Cascade half once it can no longer run."
19
+ ---
20
+
21
+ # Plan: Drop Cascade hooks after 2026-07-01 sunset
22
+
23
+ ## Why this exists
24
+
25
+ Windsurf rebranded to Devin Desktop on 2026-06-02. The Cascade agent — and its
26
+ `.windsurf/hooks.json` hook surface (`agent_action_name`/`tool_info` format) — is
27
+ available **only through 2026-07-01**. Devin Local / Devin CLI do **not** read
28
+ `.windsurf/hooks.json` as a fallback.
29
+
30
+ v4.8.0 already shipped the replacement: `generate_devin_hooks.py` emits
31
+ `.devin/hooks.v1.json` in the Claude-compatible format Devin CLI uses. During the
32
+ transition **both** generators run at `profile=full` so pre-sunset Cascade users
33
+ keep working. After 2026-07-01 the Cascade half is dead code and must be removed
34
+ (Constitution Art. VI.1 — no dead code).
35
+
36
+ ## Trigger
37
+
38
+ First ai-toolkit release **on or after 2026-07-01**. Do NOT do this earlier —
39
+ removing it before the sunset breaks Cascade users who are still on the old agent.
40
+
41
+ ## Scope — remove the Cascade hooks surface
42
+
43
+ 1. **Delete the generator:** `scripts/generate_windsurf_hooks.py`.
44
+ 2. **Unwire the install step:** in `scripts/install_steps/ai_tools.py`, remove the
45
+ `_try_generator("generate_windsurf_hooks", cwd)` call (keep
46
+ `generate_devin_hooks`). Update the `profile=full` dry-run message to drop
47
+ `.windsurf/hooks.json (Cascade, deprecated)`.
48
+ 3. **Tests:** remove the windsurf-`.windsurf/hooks.json` cases from
49
+ `tests/test_hooks_per_editor.bats` (output path, valid JSON, source tag,
50
+ `$HOME` prefix, idempotence, user-preservation, `pre_write_code` coverage) and
51
+ the `profile=full` assertion in `tests/test_install_profiles.bats`
52
+ (`windsurf + full emits .windsurf/hooks.json`). Keep all `.devin/hooks.v1.json`
53
+ tests. Adjust the README test-count badge to the new total.
54
+ 4. **Registry:** in `scripts/ecosystem_tools.json` (windsurf entry), remove
55
+ `scripts/generate_windsurf_hooks.py` from `our_generators`; keep
56
+ `.windsurf/hooks.json` out of `config_paths` (it was never listed). Trim the
57
+ `status_note` hooks-migration paragraph to past tense ("Cascade hooks removed
58
+ in vX.Y.Z").
59
+ 5. **Docs:** in `kb/reference/supported-tools-registry.md` drop the
60
+ `generate_windsurf_hooks.py` row and the "drop after 2026-07-01" note; in
61
+ `kb/reference/hooks-catalog.md` remove the Cascade row from the
62
+ Per-Editor Native Hooks table and the deprecation wording, leaving the Devin CLI
63
+ section as the windsurf-family hook surface.
64
+ 6. **validate.py:** the `_HOOK_STEM_ALIAS = {"devin": "windsurf"}` mapping STAYS —
65
+ it is what keeps the `devin` hook generator counted as windsurf hooks in the
66
+ README-honesty check after the Cascade generator is gone.
67
+ 7. **CHANGELOG / version:** minor bump, `Removed` entry, regen artifacts, full
68
+ release-preparation SOP gate.
69
+
70
+ ## Verification
71
+
72
+ - `python3 scripts/validate.py --strict` — 0/0 (editor-hooks-honesty must still
73
+ report windsurf as hook-enabled via the `devin` generator alias).
74
+ - `python3 scripts/ecosystem_doctor.py --offline --check` — exit 0.
75
+ - `npm test` — 0 `not ok`; confirm no test still references
76
+ `generate_windsurf_hooks.py` or `.windsurf/hooks.json`.
77
+ - `grep -rn "generate_windsurf_hooks\|windsurf/hooks.json" scripts/ tests/ kb/ README.md`
78
+ returns nothing (Art. VI.1 orphan check).
79
+
80
+ ## Do NOT touch
81
+
82
+ - `generate_devin_hooks.py` and `.devin/hooks.v1.json` — the live replacement.
83
+ - The `.devin/`/`.windsurf/` rules + skills dual-emit (that fallback persists as
84
+ long as Devin Desktop reads legacy `.windsurf/` paths; this plan is hooks-only).
85
+
86
+ ## Related
87
+
88
+ - `kb/reference/hooks-catalog.md` — Per-Editor Native Hooks + Devin CLI section
89
+ - `kb/reference/supported-tools-registry.md` — windsurf entry, hooks-migration row
90
+ - `kb/procedures/ecosystem-sync-sop.md` — class-D deprecation workflow
91
+ - `scripts/ecosystem_tools.json` — windsurf `status_note`