Ichnus is a stigmergic ant-swarm for bug localization. Isolated LLM ants score one file each against a bug report, deposit confidence-weighted heat onto a shared board, and spread it along the import graph with hop decay.
A median-of-3 pass catches random noise. A prosecutor / judge catches confidently wrong answers. You get a HOT / WARM / COLD markdown heatmap plus a full JSON audit trail — callable from Claude Code via MCP.
uv sync
ICHNOS_MOCK=0 uv run python -m ichnos2.demo_runner /path/to/repo \
"query string drops the first parameter" ""Grepping a bug description finds similar code. Agents that read the whole repo burn tokens and still guess. Ichnus treats localization as a swarm search with a hard spend ceiling:
- Ants never talk to each other — they only write the board (O(A) cost, not O(A²))
- Heat propagates along real import edges, so neighbours of a hot file get scouted next
- Total ant spend is bounded — wave i uses
A0 / 2^i, so spend stays< 2 · A0 - Two verifiers, two failure modes — median-of-3 for random noise; prosecutor/judge for confidently wrong answers
Ant-scored heat is a measurement and never evaporates. Propagated heat is a hypothesis and does. Recruitment makes this a swarm instead of a fixed ranked list: the next wave follows the trail.
Stage 7 catches random variance. Stage 8 catches systematic error — a model that is confidently wrong every time. Median-of-3 cannot fix that; changing the question can.
Requires Python 3.11+ and uv.
git clone https://github.com/Sharann-del/Ichnus.git
cd Ichnus
uv syncuv run python -m ichnos2.demo_runner /path/to/repo \
"login fails with empty password" ""Put a key in .env (never commit it):
GEMINI_API_KEY=...
# or
OPENROUTER_API_KEY=...Then set mock mode explicitly whenever a key is present:
ICHNOS_MOCK=0 uv run python -m ichnos2.demo_runner /path/to/repo \
"bug description" "optional stack trace"| Variable | Purpose |
|---|---|
ICHNOS_MOCK |
1 offline mock · 0 real LLM calls (required when a key is set) |
ICHNOS_PROVIDER |
gemini or openrouter (else inferred from which key exists) |
ICHNOS_ANT_MODEL |
Override the default cheap scout model |
ICHNOS_STIGMERGY |
1 trail-following (default) · 0 static ranking A/B |
ICHNOS_DEBUG_ANTS |
1 print client + raw text for the first few ants |
ICHNOS_PROSECUTOR_MODEL |
Optional separate model for Stage 8 |
Gemini free tier is the practical default for multi-ant waves. OpenRouter’s free quota is easy to exhaust on a mid-size repo; Ichnus fails fast with the reset time rather than spinning on a spent daily limit.
uv run pytest tests/test_algorithm.py -v98 tests, no network required.
.mcp.json in the project root:
{
"mcpServers": {
"ichnus2": {
"type": "stdio",
"command": "uv",
"args": ["run", "python3", "-m", "ichnos2.mcp_server"],
"env": {
"ICHNOS_MOCK": "0",
"ICHNOS_PROVIDER": "gemini"
}
}
}
}Tool: locate_bug_tool(repo_path, bug_description, stack_trace="")
Returns the same markdown heatmap as the CLI. Audit JSON lands at <repo>/.ichnos2/last_audit.json.
uv run python -m ichnos2.mcp_server
# or
uv run ichnos2-mcpMarkdown heatmap — HOT / WARM / COLD bands with scores, reasons, line ranges, and verification notes.
JSON audit — full board state, ant verdicts, cache provenance, and demotion history under .ichnos2/.
The heatmap is a suggestion for where to read next, not a verdict. Keep using normal file tools after.
Wave i scouts roughly A0 / 2^i files. Across any finite number of waves:
total spend = A0 · (2 − 2^(1−n)) < 2 · A0
This is asserted in the test suite (test_total_budget_bound_proof), not just documented.
Tests and example apps are excluded from scouting by default. A path named in a stack trace is always kept.
Measured on this codebase — not invented:
| Check | Result |
|---|---|
| Test suite | 98 passed |
| Express real bug (prose symptom, no stack) | lib/request.js HOT 10.0, lines 230–241 (defect on 238) in 4/4 cold-cache Gemini runs, ~5–7s |
| Seeded Python bug via OpenRouter | Culprit HOT, defect line pinned; Stage 8 upheld |
| Mock e2e | Stage 8 overturns a planted confident decoy |
| MCP stdio | locate_bug_tool returns the heatmap end-to-end |
| Stage 1 recall (tiny synthetic sample) | 0.8 (4/5) |
- Confidence-weighted deposit — ranking uses
relevance × confidence - Hop decay —
γ^hopfrom the nearest ant-sourced HOT file; cycle-safe BFS - Bounded demotion — never below
floor × peak - Provenance-aware cache — mock and live scores never poison each other
- Rate-limit aware client — per-minute limits waited out; daily quota stops the run
- Overlapping file windows — strongest finding wins (averaging dilutes the truth)
- Accuracy is solidly shown on one real bug (Express) plus synthetics — not a broad hit-rate study
- Ants read one file at a time; they cannot run a repro or reason about whole-repo architecture
- Non-Python import edges are regex-based; only Python uses AST for authoritative contradictions
- “Embedding” similarity in Stage 1 is a bag-of-words TF cosine proxy, not a neural embedding
- Live mode sends file contents to Gemini or OpenRouter — no local-model path yet
- Free-tier quotas can make “fast” and “works” mutually exclusive
ichnos2/
locate_bug.py
candidate_filter.py
budget.py / priority.py
ants.py
board.py
reliability.py
verify.py
aggregate.py
llm_client.py
mcp_server.py
demo_runner.py
tests/
test_algorithm.py
MIT © 2026 Sharann Manojkumar