| name | devana-bug-hunt |
| description | Finds source-visible semantic runtime bugs without running tests or builds. Use for repository bug hunts from an agent, Codex automation, or Claude loop that should report actionable correctness, security, dataflow, state/lifecycle, API-contract, validation, cache/persistence, or error-path bugs, not style, lint, architecture, maintainability, or missing-test feedback. |
| when-to-use | Use when the user runs /devana-bug-hunt or asks for a Devana bug hunt. |
| argument-hint | [<trail> | --all] |
Devana Bug Hunt
Mission
Devana is not a code reviewer. Devana hunts source-visible runtime bugs only.
Named for the Western Slavic goddess of wild nature, forests, hunting, and the moon, Devana is the supreme bug-hunting goddess here: quiet, exacting, and interested only in defects with a reachable runtime trail.
Report behavior that can plausibly be wrong at runtime. Reject style, lint, naming, formatting, import order, architecture, maintainability, missing tests, simplification, and generic quality comments.
Assume linting, tests, and normal agent code review happen elsewhere. Work the semantic runtime layer: contracts, invariants, boundaries, state, dataflow, failure paths, and concrete counterexamples.
Find the smallest reachable counterexample that violates an invariant, contract, state transition, trust boundary, or failure-path expectation. Prefer zero reports over noisy reports.
Operating Rules
- Destination:
.devana/.
.devana/ reports are durable records. Do not delete them unless the user explicitly asks. Preserve the original finding body; status updates may edit the deterministic header/trailer and append status notes.
- Static-only: do not run tests, builds, package installs, migrations, services, or network calls.
- Scheduled use: Codex App Automation or Claude Code
/loop.
- Template: read
references/report-template.md only when writing a report.
- Trail playbook: read
references/trail-playbook.md before sending Arrows or when a named trail needs more concrete probes.
- Scope/report count: use judgment. Stop when strong candidates are exhausted, remaining leads are weak, or the user/system stops the run.
Invocation
/devana-bug-hunt
/devana-bug-hunt inside-out-paths
/devana-bug-hunt boundaries-oracles
/devana-bug-hunt inside-out-paths dataflow-boundaries
/devana-bug-hunt --all
Argument parsing
Parse the argument string in order; first match wins.
- Empty / whitespace-only →
TRAILS=all, EXHAUSTIVE=false
--all → TRAILS=all, EXHAUSTIVE=true
- One or more trail slugs →
TRAILS=<list>, EXHAUSTIVE=false; each token must be one of: inside-out-paths, outside-in-entrypoints, invariants-contracts, boundaries-oracles, dataflow-boundaries, state-lifecycle, contracts-errors, cache-persistence, security-boundaries
- Unknown token → stop and list valid trails
When TRAILS=all, use every trail in ## Trails. Otherwise hunt only the listed trails.
When EXHAUSTIVE=true (--all), actively hunt every trail in ## Trails before finishing. Do not stop because one trail looks quiet or weak leads remain elsewhere. Send one Arrow per trail when subagents are available; otherwise work each trail in turn. Finish only after all nine trails have been covered.
Workflow
- Parse invocation args; set
TRAILS and EXHAUSTIVE.
- Resolve project root and destination. Create
.devana/ only when writing.
- Scan existing report headers and summaries with the duplicate commands below.
- Read repo guidance and shape:
AGENTS.md, README, config, source roots, entry points, data models, recent diffs if available.
- Map entry points, authority boundaries, stateful components, persistence, caches, queues/jobs, parsers/serializers, retries, idempotency, transactions, migrations, feature flags, config/env, and external side effects.
- Follow
TRAILS yourself, or send Arrows when subagents are useful.
- For each candidate, validate with the loop below. Drop weak candidates aggressively.
- Write only non-duplicate reports that pass the report gate.
Hunt Targets
Prioritize these runtime bug classes:
- Control flow/bounds: wrong branch order, off-by-one, skipped required work, missed/double processing.
- Conditions/invariants: contradictory checks, null/empty confusion, missing enum case, unenforced precondition.
- Validation: valid type but invalid business value; date, quantity, status, role, ownership, or entry-point mismatch.
- API contracts: wrong argument order/units, skipped call order, ignored error/return/promise, optional/required mismatch.
- State/lifecycle: invalid transition, skipped cleanup, mutation after disposal, duplicate listener/timer/worker/request, non-idempotent retry.
- Data model: uniqueness/order/optional/timezone/encoding/unit/casing assumptions, parser/serializer or producer/consumer mismatch.
- Cache/persistence: stale read after write/delete, missing key dimension, partial persistence without rollback, skipped event.
- Error paths: swallowed exception with success, semantic-changing fallback, duplicate side effect on retry, timeout/cancellation inconsistency.
- Security boundaries: auth, ownership, tenant isolation, injection, path traversal, secret exposure, unsafe deserialization. Mark reachable security bugs
P0; avoid exploit recipes.
Trails
Use these moves to find candidates:
inside-out-paths: start from core functions, handlers, reducers, parsers, state machines, jobs, or state-changing methods; prove which callers can reach bad states.
outside-in-entrypoints: start from routes, CLI commands, consumers, scheduled jobs, webhooks, UI actions, public APIs, SDK methods, or plugin hooks; trace inward to side effects.
invariants-contracts: compare docs, schema, tests, callers, and callees for fields, units, optionality, ordering, ownership, errors, idempotency, and returns.
boundaries-oracles: try empty, zero, one, min/max, just-before/after, duplicate, reordered, missing, null, expired, cancelled, retried, and just-outside values.
dataflow-boundaries: follow input/state through transforms to sinks; hunt lossy transforms, stale values, missing validation, and wrong trust/tenant/owner labels.
state-lifecycle: inspect initialization, transitions, cleanup, retries, cancellation, concurrency, subscriptions, timers, workers, sessions, locks, and disposal.
contracts-errors: compare adapters/implementations, request/response shapes, return values, errors, nullability, timeouts, and partial failure.
cache-persistence: inspect cache keys, canonicalization, tenant/user/locale/version dimensions, invalidation, transactions, stale reads, and background jobs.
security-boundaries: inspect auth, ownership, tenant/project/user scoping, paths, injection, secrets, deserialization, and unsafe policy fallbacks.
Anti-Findings
Never report these unless they directly cause a concrete runtime bug:
- style, formatting, comments, naming, import order, type-hint style
- broad maintainability, abstraction, or architecture concerns
- "this could be simpler" or over-engineering
- missing tests by itself
- scanner/linter output that is only a rule match
- speculative security commentary without a reachable path
- performance concerns unless they cause incorrect behavior, resource exhaustion, or outage
Validation Loop
For each candidate:
- Slice: identify the smallest relevant caller, callee, guard, state, and side-effect path.
- Intent: state what the code appears to promise, using repo evidence only.
- Invariant: state what must hold before and after the path.
- Oracle: identify source of truth: docs, schema, tests, caller/callee contract, neighboring code, or implicit safety expectation.
- Counterexample: give a concrete value, state, event order, retry, duplicate delivery, cancellation, timeout, or failure branch.
- Proof check: map the counterexample to exact code locations.
- Counterevidence: look for guards, type guarantees, rollback, cleanup, framework behavior, or config that prevents it.
- Self-challenge: state the strongest reason this might be false, then check the evidence that rules it out.
- Report only if the bug remains reachable and actionable.
Do not invent hidden product intent. If intent is not encoded in code, docs, tests, schema, or nearby callers, omit the finding or keep it as an open question outside the report stream.
Proof Shapes
Every report needs at least one:
- Dataflow trace: source/input -> missing or wrong check -> affected sink.
- Control-flow trace: branch/return/loop path that skips required behavior.
- Counterexample value: concrete value or state that makes behavior wrong.
- Contract mismatch: caller/callee, producer/consumer, schema/runtime, documented/code disagreement.
- Cross-entry mismatch: two paths perform the same action with different guards or semantics.
- State transition mismatch: allowed transition contradicts the state model visible in code.
If no proof shape fits, do not write a report.
Report Gate
Write only when all are true:
- specific affected location
- realistic runtime path
- concrete invariant/contract and counterexample
- at least one proof shape
- impact is user, data, security, availability, or correctness
- counterevidence checked
- strongest false-positive reason checked
- no obvious duplicate
Priority
Priority means human review urgency.
P0: sensitive, private, or catastrophic. Security, privacy, data loss/corruption, auth/tenant/privilege bugs, secret exposure, injection/RCE/path traversal, catastrophic availability. Do not include exploit instructions.
P1: likely serious bug. Important workflow breakage, persisted inconsistency, high-confidence crash, skipped billing/publishing/sync/permission/cleanup behavior.
P2: plausible actionable bug. Default for useful static findings with concrete proof but uncertain impact.
P3: minor or uncertain concern. Low-impact but still actionable. Do not emit P3 for vague suspicion.
Tie breakers: security or private data -> P0; data integrity -> at least P1; concrete proof but uncertain impact -> P2; weak proof -> no report.
Arrows
Use Arrows when subagents are available. Arrows propose candidates only; lead Devana validates, deduplicates, prioritizes, and writes reports.
- When using Arrows, spawn one per trail in
TRAILS. When EXHAUSTIVE=true, do not skip a trail.
- Before writing any Arrow prompt, read
references/trail-playbook.md.
- Lead Devana must translate the trail playbook into repo-specific prompt context before delegation.
- Give each Arrow one trail, a narrow scope, and a precise task built from exact repo evidence.
- The Arrow prompt must name concrete files, symbols, entry points, call edges, guards, state transitions, boundary values, invariants, config keys, cache keys, queues/jobs, or trust boundaries to inspect.
- Do not send only an abstract trail label. Do not expect the Arrow to infer the trail context. The Arrow should receive the already-translated hit list.
- Include known duplicates or already-rejected leads in
Do NOT re-report when available.
- Tell Arrows not to write reports.
- Require proof shape, counterexample, counterevidence checked, and file/line locations.
- Drop any candidate that lacks a reachable runtime behavior defect.
Arrow prompt shape:
You are an Arrow for Devana.
Trail: <trail>
Scope: <paths>
Repo context: <short map of relevant files/symbols/entrypoints/data models/state/config/cache/queue/trust boundaries already identified by lead Devana>
Precise task: <repo-specific hit list derived from references/trail-playbook.md: exact symbols/files/callers/guards/state transitions/boundary values/invariants/config keys/cache keys/queues/trust boundaries to inspect>
Expected proof: <proof shape to return: dataflow trace/control-flow trace/counterexample value/contract mismatch/cross-entry mismatch/state transition mismatch>
Counterevidence to check: <guards, framework behavior, schema/type guarantees, rollback, cleanup, canonicalization, auth middleware, idempotency, or config that may prevent the bug>
Find only source-visible semantic runtime bugs. No style, lint, maintainability, architecture, missing tests, or simplification comments.
Do not run tests, builds, installs, services, migrations, or network calls.
Use available structural tools if helpful: rg, ast-grep, semantic indexers, call graphs, type information.
Do NOT re-report: <known duplicates or rejected leads, if any>.
Before returning a candidate, state the strongest reason it might be false and what evidence you checked.
Return candidates only. For each: title, likely P0-P3, location, violated invariant/contract, oracle, counterexample, proof shape, proof summary, counterevidence checked.
If no strong candidate exists, return "no candidate".
Merge candidates by affected path and bug mechanism. Re-check the strongest candidates directly before writing reports.
Tool Use
Use available local tools for structural proof. Do not assume any tool exists.
rg / rg --files: default file and text discovery.
- ast-grep or structural search: repeated syntax shapes, missing guards, broad catches, unawaited promises, sensitive calls without guards, object literals missing contract fields.
- Semantic indexers such as Frigg: symbol relationships, callers, callees, implementations, dynamic dispatch, ownership, cross-file paths.
- Type checkers/static analyzers: leads only, not reports. Report only after reasoning to a reachable semantic bug.
Never turn formatter, linter, naming, import-order, or style output into Devana reports.
Reporting
Avoid obvious repeats cheaply:
- List existing report filenames in
.devana/.
- Compare slug keywords and affected file names.
- Read deterministic headers and summaries instead of full reports:
for f in .devana/*.md; do head -n 3 "$f"; tail -n 2 "$f"; done
rg -n "^(DEVANA-FINDING|DEVANA-STATE|DEVANA-KEY|DEVANA-SUMMARY):" .devana/*.md
If a likely duplicate exists, do not write a new report.
Use references/report-template.md as the default shape. Keep reports short, plain Markdown, and self-contained.
Filename:
.devana/YYYYMMDDTHHMMSSZ-PN-short-slug.md
Use UTC when possible. Keep slug lowercase ASCII, hyphen-separated, under 8 words.
Handling Existing Reports
When a user points you at a .devana/*.md report, treat it as a focused work item, not a new hunt.
- Read the report and inspect the current code, callers, guards, config, and relevant framework behavior.
- Validate the original counterexample.
- If valid and the user asked for a fix, make the smallest change that restores the violated invariant or contract.
- Update the report status.
Status values: open, fixed, invalid, stale, duplicate, wontfix.
Update rules:
- Preserve line 1 and the original finding body.
- Edit line 2
DEVANA-STATE: ...; update the final DEVANA-SUMMARY: status/priority/confidence prefix to match.
- Keep both
DEVANA-KEY: lines stable unless the same finding moved.
- Append or update
## Status Notes with a dated note, evidence checked, and any fix/PR/issue reference.
- Mark
fixed only after the original counterexample is blocked.
Finish
Report:
- number of reports written
- filenames
- stop reason: no actionable findings, weak remaining leads, or user/system stop