ba
SkillSearchBusiness Analyst agent. Use when starting a new feature requiring requirements elicitation BEFORE plan or cook. Asks probing questions, identifies hidden requirements, maps stakeholders, defines scope boundaries, and produces a structured Requirements Document that plan and cook consume.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the ba skill
What this skill tells your AI
The instructions your AI receives, as published by rune-kit/rune in skills/ba/SKILL.md and read by ahel’s review.
Purpose
Business Analyst agent — the ROOT FIX for "Claude works a lot but produces nothing." BA forces deep understanding of WHAT to build before any code is written. It asks probing questions, identifies hidden requirements, maps stakeholders, defines scope boundaries, and produces a structured Requirements Document.
Wrong requirements shipped correctly is the most expensive bug. BA's job is to prevent it — measure clarity (Step 2.5), measure completeness (Step 3.5), and measure cross-dimension consistency (Step 3.6) before handoff.
Goal-first (advisory, 2026). The Requirements Document is the goal spec current models want up front. Where the platform has a native goal/outcome command — Claude Code
/goal, Managed Agents Outcomes (rubric) — seed it from this document's scope boundaries + acceptance criteria so the whole run stays anchored to the agreed WHAT.
Triggers
- Called by
cookPhase 1 when task is product-oriented (not a simple bug fix) - Called by
scaffoldPhase 1 before any project generation /rune ba <requirement>— manual invocation- Auto-trigger: when user description is > 50 words OR contains business terms (users, revenue, workflow, integration)
Calls (outbound)
scout(L2): scan existing codebase for contextresearch(L3): look up similar products, APIs, integrationsplan(L2): hand off Requirements Document for implementation planningbrainstorm(L2): when multiple approaches exist for a requirementdesign(L2): when requirements include UI/UX components — hand off visual requirements
Called By (inbound)
cook(L1): before Phase 2 PLAN, when task is non-trivialscaffold(L1): Phase 1, before any project generationplan(L2): when plan receives vague requirementsbrainstorm(L2): standalone ideation that picked an approach for a new feature with no spec — hands the chosen approach tobafor requirements beforeplanmcp-builder(L2): requirements elicitation before MCP server design- User:
/rune badirect invocation
Cross-Hub Connections
ba→plan— ba produces requirements, plan produces implementation stepsba→brainstorm— ba calls brainstorm when multiple requirement approaches existba↔cook— cook calls ba for non-trivial tasks, ba feeds requirements into cook's pipelineba→scaffold— scaffold requires ba output before project generation
Executable Steps
Step 1 — Intake & Classify
Read the user's request. Classify the requirement type:
| Type | Signal | Depth |
|---|---|---|
| Feature Request | "add X", "build Y", "I want Z" | Full BA cycle (Steps 1-7) |
| Bug Fix | "broken", "error", "doesn't work" | Skip BA → direct to debug |
| Refactor | "clean up", "refactor", "restructure" | Light BA (Step 1 + Step 4 only) |
| Integration | "connect X to Y", "integrate with Z" | Full BA + API research |
| Greenfield | "new project", "build from scratch" | Full BA + market context |
If Bug Fix → skip BA, route to cook/debug directly. If Refactor → light version (Step 1 + Step 4 only). Skip Steps 2, 2.5, 3, 5, 6.
If existing codebase → invoke rune:scout for context before proceeding.
Step 1.4 — Synthesis Trigger Check
Before proceeding to elicitation, check whether the requirements are already in context. Re-asking what the user already told you is the second-most expensive bug.
Activate Synthesis Mode instead of standard elicitation if ANY of:
| Signal | Threshold |
|---|---|
| User pasted a spec / PRD / brief | > 200 words describing the feature |
| Conversation has > 1000 words on this feature | Sufficient context already gathered |
| User said "synthesize" / "I already explained" / "just write the spec" | Explicit synthesis request |
Continuation — .rune/features/<name>/requirements.md exists with prior answers | Re-elicitation would duplicate |
| Issue tracker has filled-in template (problem, story, acceptance criteria) | Source already structured |
In Synthesis Mode: extract answers from existing context, draft the Requirements Document with source citations for every section, then confirm rather than re-interview. Ask follow-ups ONLY on the 1-2 dimensions with genuine gaps. Skip steps 2, 2.5 if all 5 dimensions are filled or partial-but-acceptable.
Workflow detail + anti-patterns: references/synthesis-mode.md.
Step 1.5 — Out-of-Scope Match Check (READ)
Before any elicitation, check whether the request matches a concept previously rejected.
Glob.out-of-scope/*.md— if directory absent, skip silently.- For each file, parse YAML frontmatter (
concept,aliases). - Build a token map (lowercased, split on
-and whitespace). - Tokenize the user's request the same way.
- Compute lexical overlap per concept; keep the top match's
confidence(0.0–1.0).
Action by confidence:
| Confidence | Verdict | Action |
|---|---|---|
| ≥ 0.8 | exact-match | Surface to user: "This matches a prior rejection (.out-of-scope/<slug>.md) — closed because [body's "Why out of scope" first sentence]. Do you still feel the same way?" Pause for user response before continuing. |
| 0.5 – 0.79 | similar | Mention inline: "This is similar to a prior rejection (<slug>). Would you like to review it before we proceed?" Continue regardless of answer. |
| < 0.5 | no-match | Continue silently, no user-facing mention. |
Emit outofscope.match signal with {concept, confidence, verdict} so downstream skills (cook, plan) inherit the context.
If verdict is exact-match AND user says "yes I still want it" → record their override reason in the Requirements Document ## Risks section AND mark priority_to_revisit: high in the existing .out-of-scope/<slug>.md (do NOT delete the file). The override forces the candidate up the revisit ladder; it doesn't erase the prior decision.
If verdict is exact-match AND user accepts the prior rejection → end the BA session with a one-line summary referencing the file. No further questions.
Format reference: references/out-of-scope-format.md.
Step 1.6 — Mid-Elicitation Reject WRITE Path
If the user explicitly rejects the feature at any point during elicitation (Steps 2-3) — common phrases: "scrap it", "actually nah, don't build this", "we won't do this", "kill the feature", "drop it" — STOP elicitation and write a .out-of-scope/<slug>.md record before ending the session.
Without this WRITE path, oral rejections vanish — the next session re-asks the same questions and the user has to re-reject. Step 1.5 (READ) only catches matches against existing files; Step 1.6 (WRITE) is what produces those files in the first place.
Procedure:
-
Confirm rejection is durable, not deferral. Ask one clarifier:
"Just to record this correctly: is this out of scope (project doesn't want this), or deferred (not now but maybe later)? Out-of-scope gets recorded so we don't re-litigate; deferred goes to backlog instead."
- If deferred → route to backlog (no
.out-of-scope/write), end session with a one-line note - If out-of-scope → continue to step 2
- If deferred → route to backlog (no
-
Capture the durable reason. Ask:
"What's the reason this is out of scope? (project scope, technical constraint, strategic decision — not a temporary circumstance)"
If the user gives a temporary reason ("we're busy"), reframe: "That's a deferral — should I route to backlog instead?"
-
Generate slug (kebab-case, ≤40 chars, recognizable without opening the file).
-
Lexical-similarity check:
Glob.out-of-scope/*.md, parse each frontmatter'sconcept+aliases, compute overlap. If any existing concept has ≥0.7 overlap → APPEND to that file'sprior_requestslist and markrejected_by: bafor this round. Do NOT create a duplicate. -
Write the file using the format in
references/out-of-scope-format.md:- YAML frontmatter (
concept,aliases,decision: rejected,rejected_at,rejected_by: ba,prior_requests, optionalrevisit_if) - Markdown body: concept name, "Why out of scope" (substantive reasoning from step 2), "What would change our mind" (if user volunteered signals)
- YAML frontmatter (
-
Emit
outofscope.recordedsignal carrying{slug, rejected_by: ba, prior_requests_count}so downstream skills know a new rejection landed. -
End BA session with one-line summary:
"Recorded as out of scope in
.out-of-scope/<slug>.md. Future similar requests will surface this. Override anytime by editing the file."
When NOT to write:
- User merely defers ("not now") → backlog, not
.out-of-scope/ - User rejects a single requirement within a larger feature → adjust requirements doc Boundaries section, don't write a whole rejection file (the feature is still in scope)
- Bug rejections (already fixed, not reproducible) → not BA's job; route to incident or close the issue
- The match was already exact (≥0.8) and Step 1.5 surfaced it — user accepting the prior rejection just appends to
prior_requestsof the existing file (handled in Step 1.5 path)
Step 2.0 — Explore-First Pre-Check (HARD-GATE)
Before emitting ANY of the 5 elicitation questions, run the 4-item pre-check on each intended question:
- Is the answer in
package.json/pyproject.toml/Cargo.toml/go.mod/pom.xml? - Is the answer in
README.md/CLAUDE.md/docs/? - Is it inferable from file extensions, directory structure, or config files?
- Has the user answered it earlier in this conversation?
The gate is "tried to infer" — not "must succeed in inferring." If the file genuinely doesn't have the answer, the attempt itself is the gate.
Cache inferred answers in the requirements doc:
**Inferred from package.json**: TypeScript 5.4, Next.js 14.2, React 18.3
**Inferred from .github/workflows/**: CI runs on PRs targeting main
Worked examples + edge cases: references/explore-first.md.
Step 2 — Requirement Elicitation (the "5 Questions")
Ask exactly 5 probing questions, ONE AT A TIME (not all at once):
- WHO — "Who is the end user? What's their technical level? What are they doing right before and after using this feature?"
- WHAT — "What specific outcome do they need? What does 'done' look like from the user's perspective?"
- WHY — "Why do they need this? What problem does this solve? What happens if we don't build it?"
- BOUNDARIES — "What should this NOT do? What's explicitly out of scope?"
- CONSTRAINTS — "Any technical constraints? (existing APIs, performance requirements, security needs, deadlines)"
Question Discipline (MANDATORY)
Every question the user answers burns attention you don't get back. Protect it.
- Max 5 questions total across the whole BA session. If you find yourself wanting a 6th, the answer is in the first 5 or you're stalling — re-read, don't re-ask.
- Prefer yes/no or multiple-choice over open-ended. An open-ended question is a last resort when no reasonable option set exists.
- BAD: "What auth strategy do you want?"
- GOOD: "Auth: (a) email+password with JWT, (b) OAuth (Google/GitHub), (c) magic link, (d) I'll decide — pick one."
- Never ask what you can infer. If the answer is in the repo, the user's message, or the classification from Step 1 — don't ask it.
- Wrong stack? → read
package.json, don't ask. - Wrong audience? → check the
README, don't ask. - Wrong framework? → check config files, don't ask.
- Wrong stack? → read
- Cache the answer. Write each Q→A pair into the Requirements Document verbatim. If the user restarts the BA session on the same feature, reuse the cached answers — never re-ask what was already answered.
- Bundle yes/no questions after Q1 if the user is concise. A user who replies "y" / "n" / "skip" in 1-2 words tolerates a bundle. A user who replies with paragraphs wants the slow pace — keep one-at-a-time.
Every Q should earn its slot: removing it must leave the Requirements Document materially worse. If it wouldn't, cut the question.
Structured Elicitation Frameworks
Choose the framework that fits the requirement type. Use it to STRUCTURE the 5 Questions above, not replace them.
| Framework | When to Use | Structure |
|---|---|---|
| PICO | Clinical, research, data-driven, or A/B testing features | Population (who), Intervention (what change), Comparison (vs what), Outcome (measurable result) |
| INVEST | User stories for sprint-sized features | Independent, Negotiable, Valuable, Estimable, Small, Testable |
| Jobs-to-be-Done | Product features, user workflows | "When [situation], I want to [motivation] so I can [expected outcome]" |
PICO Example (data feature):
P: Dashboard users monitoring real-time metrics
I: Add anomaly detection alerts
C: vs. current manual threshold setting
O: 30% faster incident detection (measurable KPI)
When to apply which:
- Feature Request → INVEST (ensures stories are sprint-ready)
- Data/Analytics/Research feature → PICO (forces measurable outcome definition)
- Product/UX feature → Jobs-to-be-Done (keeps focus on user motivation)
- Integration → 5 Questions only (frameworks add noise for plumbing tasks)
Step 2.5 — Ambiguity Scoring (Execution Gate)
After each question round, compute an Ambiguity Score to determine if requirements are clear enough to proceed. This prevents premature handoff to plan with vague inputs.
Scoring Formula
Ambiguity = 1 - weighted_average(dimensions)
Dimensions (weights vary by requirement type):
Greenfield: Goal (40%) + Constraints (30%) + Success Criteria (30%)
Feature: Goal (30%) + Constraints (30%) + Success Criteria (20%) + Integration (20%)
Integration: Goal (20%) + Constraints (25%) + Success Criteria (20%) + API Contract (35%)
Dimension Scoring (0.0 – 1.0)
| Dimension | 0.0 (Unknown) | 0.5 (Partial) | 1.0 (Clear) |
|---|---|---|---|
| Goal | "Make it better" | "Improve dashboard performance" | "Dashboard loads in <2s with 10k rows" |
| Constraints | No constraints mentioned | "Use existing DB" | "PostgreSQL 15, no new deps, GDPR compliant" |
| Success Criteria | "It should work" | "Users can see their data" | "AC-1.1: GIVEN 10k rows WHEN page loads THEN render <2s" |
| Integration | "Connect to the API" | "Use REST, need auth" | "POST /api/v2/orders, OAuth2, rate limit 100/min" |
| API Contract | "It sends data somewhere" | "JSON payload to endpoint" | "OpenAPI spec provided, request/response schemas defined" |
Threshold Gate
| Ambiguity | Level | Action |
|---|---|---|
| < 15% | Crystal Clear | Proceed to Step 3 immediately |
| 15-25% | Acceptable | Proceed with noted assumptions — flag gaps in Requirements Doc |
| 25-40% | Unclear | Ask 1-2 targeted follow-up questions on weakest dimension |
| > 40% | Blocked | Do NOT proceed. Re-ask the weakest dimension question with examples |
Scoring After Each Question
After each of the 5 Questions (Step 2), update the score:
Round 1 (WHO): Goal ≈ 0.3, others = 0.0 → Ambiguity ≈ 91%
Round 2 (WHAT): Goal ≈ 0.7, Success ≈ 0.3 → Ambiguity ≈ 72%
Round 3 (WHY): Goal ≈ 0.9, Success ≈ 0.5 → Ambiguity ≈ 47%
Round 4 (BOUNDS): Constraints ≈ 0.6 → Ambiguity ≈ 30%
Round 5 (CONSTR): Constraints ≈ 0.9 → Ambiguity ≈ 12% ✅
If Ambiguity drops below 15% before all 5 questions are asked (e.g., user provides a detailed PRD), skip remaining questions and proceed. The gate is about clarity, not ceremony.
Display Format
After completing Step 2, show the user:
Clarity Score: [100 - ambiguity]%
Goal: [██████████] 0.9
Constraints: [████████░░] 0.8
Success Criteria: [██████░░░░] 0.6 ← weakest
Status: ACCEPTABLE (ambiguity 23%) — proceeding with noted gaps
Step 2.6 — CONTEXT.md Cross-Reference Gate
After elicitation, before hidden-requirement discovery, scan the user's answers for assertions about current behavior — phrasings like "the system X", "the code does X", "we already X", "right now it X".
For each such assertion:
Grepthe codebase for evidence (function names, route handlers, schema definitions matching the asserted behavior).- Compare grep results to the user's claim.
| Outcome | Action |
|---|---|
| Grep confirms claim | Proceed; record term in CONTEXT.md if domain-relevant |
| Grep contradicts claim | Surface the conflict immediately. "You said the system does X, but the code path I see does Y. Which is canonical?" Pause until resolved. |
| Grep returns nothing | Note as unverified; ask user for the file/function name; do not record in CONTEXT.md until verified |
This gate prevents the agent from silently transcribing user-asserted behavior that contradicts code — a common source of "the docs say X but the code does Y" drift.
Step 3 — Hidden Requirement Discovery
After the 5 questions, analyze for requirements the user DIDN'T mention:
Technical hidden requirements:
- Authentication/authorization needed?
- Rate limiting needed?
- Data persistence needed? (what DB, what schema)
- Error handling strategy?
- Offline/fallback behavior?
- Mobile responsiveness?
- Accessibility requirements?
- Internationalization?
Business hidden requirements:
- What happens on failure? (graceful degradation)
- What data needs to be tracked? (analytics events)
- Who else is affected? (other teams, other systems)
- What are the edge cases? (empty state, max limits, concurrent access)
- Regulatory/compliance needs? (GDPR, PCI, HIPAA)
Present discovered hidden requirements to user: "I found N additional requirements you may not have considered: [list]. Which are relevant?"
Step 3.5 — Completeness Scoring (Options & Alternatives)
When presenting options, alternatives, or scope decisions to the user, rate each with a Completeness score (X/10):
| Score | Meaning | Guidance |
|---|---|---|
| 9-10 | Complete — all edge cases, full coverage, production-ready | Always recommend |
| 7-8 | Covers happy path, skips some edges | Acceptable for MVP |
| 4-6 | Shortcut — defers significant work to later | Flag trade-off explicitly |
| 1-3 | Minimal viable, technical debt guaranteed | Only for time-critical emergencies |
Always recommend the higher-completeness option unless the delta is truly expensive. With AI-assisted coding, the marginal cost of completeness is near-zero:
| Task Type | Human Team | AI-Assisted | Compression |
|---|---|---|---|
| Boilerplate / scaffolding | 2 days | 15 min | ~100x |
| Test writing | 1 day | 15 min | ~50x |
| Feature implementation | 1 week | 30 min | ~30x |
| Bug fix + regression test | 4 hours | 15 min | ~20x |
When showing effort estimates, always show both scales: (human: ~X / AI: ~Y). The compression ratio reframes "too expensive" into "15 minutes more."
Anti-pattern: "Choose B — it covers 90% of the value with less code." → If A is only 70 lines more, choose A. The last 10% is where production bugs hide.
Step 3.6 — Logic Consistency Check
After ambiguity + completeness pass, scan for cross-dimension contradictions. Ambiguity measures CLARITY of each dimension in isolation; this step measures CONSISTENCY across dimensions. A perfectly clear requirement can still contradict itself.
Checks
Run each, label verdict 🟢 pass / 🟡 warn / 🔴 fail:
| # | Check | 🔴 Fail | 🟢 Pass |
|---|---|---|---|
| 1 | Every Acceptance Criterion traces to a User Story | AC orphaned | 1:N mapping clear |
| 1b | Every EARS FR-n (Step 4.5) traces up to a User Story AND down to an AC | FR has no AC (untested promise) or no story (orphan behavior) | FR → story + AC both present |
| 2 | Every Business Rule (Q5) is enforced in an AC or Exception Flow | Rule has no enforcement path | Rule → specific AC or exception |
| 3 | Scope IN ∩ Scope OUT = ∅ | Direct overlap in phrasing | Sets disjoint |
| 4 | Every user-story flow has a terminal state | State loop without exit condition | Terminal state explicit |
| 5 | Dependencies (Step 4) ⊂ Constraints acknowledged (Q5) | Dependency never mentioned in constraints | All deps covered |
| 6 | NFRs measurable against at least one AC | NFR has no test hook | Every NFR → testable AC |
| 7 | Hidden requirements (Step 3) resolved in/out | Silent inclusion | User confirmed inclusion or exclusion |
| 0 | Prior rejection check (Step 1.5) — exact-match resolved with explicit override or session ended | Silent re-litigation of rejected concept | User chose: override (priority bumped) OR accept prior decision (session ends) |
Output Format
Logic Consistency Report:
1. AC → User Story: 🟢 all AC trace to US-1 or US-2
1b. EARS FR → story+AC: 🟢 FR-1..FR-5 each map to a story and an AC
2. Business rule → AC: 🟡 "no duplicate emails" cited — exception flow missing
3. Scope disjoint: 🟢
4. Terminal states: 🟢
5. Deps in constraints: 🔴 "PostgreSQL 15" missing from Q5 answer
6. NFR measurable: 🟢
7. Hidden reqs resolved: 🟢
Verdict: 1 🔴, 1 🟡, 5 🟢 → BLOCK handoff until 🔴 fixed
Gate Rule
| Result | Action |
|---|---|
| 0 🔴 | Proceed to Step 4 — 🟡 warnings become "Risks" in Requirements Doc |
| 1-2 🔴 | BLOCK — ask targeted question or re-scope to resolve each 🔴 |
| 3+ 🔴 | Scrap Steps 2-3 and restart — requirements structurally incoherent |
Step 4 — Scope Definition
Based on all gathered information, produce:
In-Scope (explicitly included):
- [list of features/behaviors that WILL be built]
Out-of-Scope (explicitly excluded):
- [list of things we WON'T build — prevents scope creep]
Assumptions (things we're assuming without proof):
- [each assumption is a risk if wrong]
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 86
- Forks
- 26
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
ba- Source
- github.com/rune-kit/rune