feat: Deep research upgrade so sisyphus and the architect now have 3 possible research types: librarian standard, librarian deep, and true deep research with reflexion

This commit is contained in:
Dark-Alex-17 committed 2026-09-21 12:29:07 -06:00
1 parent 37ba25adc5
commit a8c0ec64fa
9 files changed
+171 -62

No files matched your search

+7 -3
View File
@@ -6,7 +6,7 @@ description: |
plan-conformance check (plus a black-box usage-pattern probe for consumer-facing surface), and plan-conformance check (plus a black-box usage-pattern probe for consumer-facing surface), and
finishes with ONE draft PR (CI checks watched to green) plus tracked follow-up tasks. Task state finishes with ONE draft PR (CI checks watched to green) plus tracked follow-up tasks. Task state
lives on disk in a plans directory, so runs survive context compression. lives on disk in a plans directory, so runs survive context compression.
version: 2.6.0 version: 2.8.0
agent_session: temp agent_session: temp
auto_continue: true auto_continue: true
max_auto_continues: 100 max_auto_continues: 100
@@ -18,6 +18,7 @@ spawnable_agents:
- oracle - oracle
- explore - explore
- librarian - librarian
- deep-research
- adversary - adversary
- probe - probe
- review-gauntlet - review-gauntlet
@@ -180,7 +181,9 @@ instructions: |
<label>; authoritative sources preferred; return a distilled, deduplicated checklist"), put the <label>; authoritative sources preferred; return a distilled, deduplicated checklist"), put the
returned checklist through the same accept/drop round with the user, and write the ACCEPTED returned checklist through the same accept/drop round with the user, and write the ACCEPTED
items into the plan — as measurable acceptance criteria on the relevant tasks where possible, items into the plan — as measurable acceptance criteria on the relevant tasks where possible,
otherwise as a checklist under `## Quality bar → Long-tail criteria`. otherwise as a checklist under `## Quality bar → Long-tail criteria`. Spawn checklist
librarians with `--variables {"research_depth": "deep"}` — checklist distillation is
broad-topic research and the default standard depth (3 searches / 8 fetches) starves it.
Ground the breakdown in real code: fan out `explore` agents (load `parallel-research`) across Ground the breakdown in real code: fan out `explore` agents (load `parallel-research`) across
{{project_dir}} — and `librarian` for unfamiliar external libraries — to confirm the design's {{project_dir}} — and `librarian` for unfamiliar external libraries — to confirm the design's
@@ -593,7 +596,8 @@ instructions: |
|-------|---------| |-------|---------|
| `sisyphus` | Implement ONE task's code in {{project_dir}} (its own explore/coder/verify/review loop). One per task. | | `sisyphus` | Implement ONE task's code in {{project_dir}} (its own explore/coder/verify/review loop). One per task. |
| `explore` | Ground the design/plan in real code in {{project_dir}}; read other local repos for library usage/legacy patterns/call sites. Fan out in parallel. | | `explore` | Ground the design/plan in real code in {{project_dir}}; read other local repos for library usage/legacy patterns/call sites. Fan out in parallel. |
| `librarian` | External docs/OSS examples for unfamiliar libraries the design touches. | | `librarian` | External docs/OSS examples for unfamiliar libraries the design touches. Design-time/broad topics: pass `--variables {"research_depth": "deep"}` (~3× budgets); default depth is for narrow lookups. One librarian per question beats one broad librarian — deep is for inherently broad questions. |
| `deep-research` | Open-ended/exhaustive research that should churn until its critique loop passes (plans sub-questions, deep librarian per question, credibility vetting). Spawn with `--variables {"autonomy": "autonomous"}` — MANDATORY, the supervised default blocks on a human approval gate; raise `reflexion_budget` (default 2) for longer churn. |
| `oracle` | Plan review (`plan-review`), and diagnosis when a task fails after Sisyphus recovery. | | `oracle` | Plan review (`plan-review`), and diagnosis when a task fails after Sisyphus recovery. |
| `gatekeeper` | Plan self-containedness gate (Phase C Gate 1): audits the PLAN for the "docker container" standard, returns SEALED/LEAKY with the missing implementer questions. | | `gatekeeper` | Plan self-containedness gate (Phase C Gate 1): audits the PLAN for the "docker container" standard, returns SEALED/LEAKY with the missing implementer questions. |
| `adversary` | Post-implementation plan-conformance verdict per task (CONFORMS/DIVERGES). | | `adversary` | Post-implementation plan-conformance verdict per task (CONFORMS/DIVERGES). |
+7
View File
@@ -13,6 +13,13 @@ this agent runs a fixed graph: every request goes through the same
`plan -> parallel research -> vet -> critique -> synthesize -> verify -> approve` `plan -> parallel research -> vet -> critique -> synthesize -> verify -> approve`
pipeline. pipeline.
Two variables tune a run (pass via `--variables`): `reflexion_budget`
(default 2) caps the automated critique -> re-research passes — raise it
to let the run churn until the critique passes — and
`autonomy: autonomous` skips the final human approval gate so other
agents can spawn this one autonomously. Each sub-question is researched
by a spawned `librarian` running at deep budgets.
This agent is also the **canonical reference for the Coyote graph This agent is also the **canonical reference for the Coyote graph
system**: it exercises every node type (`script`, `llm`, `rag`, `map`, system**: it exercises every node type (`script`, `llm`, `rag`, `map`,
`agent`, `input`, `approval`, `end`) and both static fan-out and `agent`, `input`, `approval`, `end`) and both static fan-out and
+40 -26
View File
@@ -7,7 +7,12 @@ description: |
delegates the final write-up to a focused sub-agent, checks that the delegates the final write-up to a focused sub-agent, checks that the
cited sources are reachable, and gates the result behind human cited sources are reachable, and gates the result behind human
approval. A reviewer's free-form feedback at the approval step feeds approval. A reviewer's free-form feedback at the approval step feeds
back into another research pass. back into another research pass. Each sub-question is researched by a
spawned librarian running at deep budgets. Tunable via --variables:
reflexion_budget (default 2) caps the automated critique->re-research
passes - raise it to let the run churn until the critique passes;
autonomy=autonomous skips the human approval gate (REQUIRED when
another agent spawns this one).
This is the canonical Coyote graph-agent reference: it exercises every This is the canonical Coyote graph-agent reference: it exercises every
node type (script, llm, rag, map, agent, input, approval, end) and node type (script, llm, rag, map, agent, input, approval, end) and
@@ -27,8 +32,16 @@ conversation_starters:
- 'How does HTTP/3 differ from HTTP/2?' - 'How does HTTP/3 differ from HTTP/2?'
- 'Summarize recent advances in solid-state battery chemistry' - 'Summarize recent advances in solid-state battery chemistry'
variables:
- name: reflexion_budget
description: "Max automated critique->re-research passes before synthesis proceeds anyway. Default 2; raise it (4-8) for exhaustive runs that should churn until the critique passes."
default: '2'
- name: autonomy
description: "supervised (default): the finished report stops at the human approval gate. autonomous: skip the gate and return the report directly - REQUIRED when another agent spawns this one (a human gate would block the run)."
default: 'supervised'
settings: settings:
max_loop_iterations: 40 max_loop_iterations: 120
log_state_snapshots: false log_state_snapshots: false
validate_before_run: true validate_before_run: true
max_concurrency: 4 max_concurrency: 4
@@ -142,23 +155,11 @@ nodes:
research_one_question: research_one_question:
id: research_one_question id: research_one_question
type: llm type: agent
instructions: | agent: librarian
You are a web research assistant. Investigate the SINGLE question # The leaf research primitive: triage -> doc+OSS search -> cited
given to you using your tools: search the web, fetch and read # synthesis. `inputs:` overlays the librarian graph's initial state,
pages, and search arXiv for academic sources. # pinning research_depth to deep for every sub-question lane.
Rules:
- Every factual claim must be backed by a real source you
actually retrieved. Never fabricate URLs, page titles,
authors, or DOIs.
- Prefer primary and authoritative sources over aggregators.
- Where sources disagree, report the disagreement rather than
papering over it.
- Put the URL (or DOI) inline next to each claim it supports.
Return organized findings in plain text. Do not include
meta-commentary about the process.
prompt: | prompt: |
Research question: {{question}} Research question: {{question}}
@@ -166,16 +167,13 @@ nodes:
{{local_context}} {{local_context}}
{{research_feedback}} {{research_feedback}}
tools: inputs:
- web_search_coyote research_depth: deep
- fetch_url_via_curl timeout: 1900
- search_arxiv
- mcp:ddg-search
max_iterations: 10
max_attempts: 2 max_attempts: 2
state_updates: state_updates:
finding: '{{output}}' finding: '{{output}}'
# On failure the engine writes "LLM node ...failed: <chain>" into `finding` # On failure the engine writes "Agent node failed: <chain>" into `finding`
# via the state_updates above BEFORE routing to the fallback. The marker # via the state_updates above BEFORE routing to the fallback. The marker
# is branch-local: a map branch's fallback must stay inside the branch. # is branch-local: a map branch's fallback must stay inside the branch.
fallback: question_fault fallback: question_fault
@@ -312,6 +310,13 @@ nodes:
id: verify_sources id: verify_sources
type: script type: script
script: scripts/verify_sources.py script: scripts/verify_sources.py
next: approval_gate
approval_gate:
id: approval_gate
type: script
description: Autonomy router - autonomous runs (spawned by another agent) skip the human approval gate and end accepted with the source check + pipeline notes attached; supervised (default) proceeds to the approval node. A crash fails forward via `next` to approve, the safe human-gated direction.
script: scripts/approval_gate.py
next: approve next: approve
approve: approve:
@@ -348,6 +353,15 @@ nodes:
type: end type: end
output: '{{report}}{{pipeline_notes}}' output: '{{report}}{{pipeline_notes}}'
end_autonomous:
id: end_autonomous
type: end
output: |
{{report}}
----
{{source_check}}{{pipeline_notes}}
end_rejected: end_rejected:
id: end_rejected id: end_rejected
type: end type: end
@@ -0,0 +1,38 @@
#!/usr/bin/env python3
"""Autonomy router for deep-research's approval gate.
Runs after verify_sources. When the `autonomy` variable is
'autonomous' (the run was spawned by another agent — architect or
sisyphus research tiers — with no human at the terminal), the report
skips the human approval node and ends accepted: the reflexion loop
already served as the quality gate, and end_autonomous carries the
source check + pipeline notes with the report so the caller sees them.
Any other value (default 'supervised') proceeds to the human approval
gate unchanged.
Routing (`_next`):
- autonomy == 'autonomous' -> end_autonomous
- anything else -> approve
Fail-safe: a crash here fails FORWARD via the node's `next` to
`approve` — the safe, human-gated direction.
"""
import json
import os
def load_state():
if path := os.environ.get("GRAPH_STATE_FILE"):
with open(path) as f:
return json.load(f)
return json.loads(os.environ.get("GRAPH_STATE", "{}"))
def main():
state = load_state()
autonomy = str(state.get("autonomy") or "supervised").strip().lower()
target = "end_autonomous" if autonomy == "autonomous" else "approve"
print(json.dumps({"_next": target}))
main()
@@ -4,10 +4,11 @@
Reached ONLY via research_one_question's `fallback:` route inside the Reached ONLY via research_one_question's `fallback:` route inside the
`research_each_question` map branch (branch-local — a map branch's fallback `research_each_question` map branch (branch-local — a map branch's fallback
must stay inside the branch subgraph). Grounded in engine behavior: on must stay inside the branch subgraph). Grounded in engine behavior: on
llm-node failure the engine writes "LLM node …failed: <chain>" into branch failure the engine writes its failure text into `finding` via the
`finding` via the node's state_updates BEFORE routing to the fallback (on node's state_updates BEFORE routing to the fallback — "Agent node failed:
success the same key holds the researched findings, which never start with <chain>" now that the branch spawns a librarian agent, "LLM node …failed:
the "LLM node" prefix). This node normalizes the failure text into a <chain>" for an llm branch (on success the same key holds the researched
findings, which never start with either prefix). This node normalizes the failure text into a
PIPELINE-FAULT finding and the chain ends here — the map collects the fault PIPELINE-FAULT finding and the chain ends here — the map collects the fault
as the lane's `finding`, so one dead research lane never sinks the whole as the lane's `finding`, so one dead research lane never sinks the whole
map. combine_findings later lifts PIPELINE-FAULT findings into map. combine_findings later lifts PIPELINE-FAULT findings into
@@ -53,7 +54,7 @@ def main():
state = load_state() state = load_state()
raw = state.get("finding") raw = state.get("finding")
detail = raw.strip().replace("\n", " ") if isinstance(raw, str) else "" detail = raw.strip().replace("\n", " ") if isinstance(raw, str) else ""
if not detail.startswith("LLM node"): if not detail.startswith(("LLM node", "Agent node")):
detail = "the research lane died without recording a failure detail" detail = "the research lane died without recording a failure detail"
if len(detail) > MAX_DETAIL_CHARS: if len(detail) > MAX_DETAIL_CHARS:
detail = detail[: MAX_DETAIL_CHARS - 1] + "…" detail = detail[: MAX_DETAIL_CHARS - 1] + "…"
@@ -2,7 +2,8 @@
"""Reflexion gate for deep-research. """Reflexion gate for deep-research.
Runs after `critique` has reviewed the current research findings. If the Runs after `critique` has reviewed the current research findings. If the
critique's verdict is REVISE and the reflexion budget is not spent, critique's verdict is REVISE and the reflexion budget (the graph's
`reflexion_budget` variable, default 2) is not spent,
loops back to `research` with the critique attached as loops back to `research` with the critique attached as
`research_feedback`, so the retry is informed rather than a blind `research_feedback`, so the retry is informed rather than a blind
re-run. Otherwise it proceeds to `synthesize`. re-run. Otherwise it proceeds to `synthesize`.
@@ -26,9 +27,11 @@ import json
import os import os
import re import re
# Automated revision passes allowed. `research` runs at most # Default automated revision passes when the `reflexion_budget` variable
# MAX_REFLEXION_REVISIONS + 1 times per user pass. Bump to allow more. # is absent or malformed. `research` runs at most budget + 1 times per
MAX_REFLEXION_REVISIONS = 2 # user pass. Callers raise it via --variables {"reflexion_budget": "6"}
# to let the run churn until the critique passes.
DEFAULT_REFLEXION_REVISIONS = 2
def load_state(): def load_state():
@@ -69,8 +72,9 @@ def main():
critique = state.get("critique") or "" critique = state.get("critique") or ""
verdict = parse_verdict(critique) verdict = parse_verdict(critique)
attempts = as_int(state.get("research_attempts")) attempts = as_int(state.get("research_attempts"))
budget = as_int(state.get("reflexion_budget"), DEFAULT_REFLEXION_REVISIONS)
if verdict == "REVISE" and attempts < MAX_REFLEXION_REVISIONS: if verdict == "REVISE" and attempts < budget:
feedback = ( feedback = (
"A reviewer judged the previous research pass incomplete. " "A reviewer judged the previous research pass incomplete. "
"Address every point in the critique below:\n\n" + critique "Address every point in the critique below:\n\n" + critique
+43 -17
View File
@@ -6,13 +6,16 @@ description: |
preamble. The "external grep" sibling of explore (which handles preamble. The "external grep" sibling of explore (which handles
internal/codebase grep). Designed to be fanned out 1-3 in parallel by internal/codebase grep). Designed to be fanned out 1-3 in parallel by
sisyphus alongside explore when unfamiliar libraries/APIs/frameworks are sisyphus alongside explore when unfamiliar libraries/APIs/frameworks are
involved. involved. Supports research_depth=deep (via --variables) for broad
design-time topics: ~3x the search/OSS/fetch budgets of the standard
quick-lookup mode.
version: '1.0' version: '1.0'
global_tools: global_tools:
- web_search_coyote.sh - web_search_coyote.sh
- fetch_url_via_curl.sh - fetch_url_via_curl.sh
- search_arxiv.sh
mcp_servers: mcp_servers:
- ddg-search - ddg-search
@@ -26,11 +29,14 @@ variables:
- name: project_dir - name: project_dir
description: Project directory for context (unused in MVP but reserved for future iterations). description: Project directory for context (unused in MVP but reserved for future iterations).
default: '.' default: '.'
- name: research_depth
description: "standard (default) = quick targeted lookup budgets. deep = design-time research: ~3x search/OSS/fetch budgets for broad topics (best-practice checklists, architecture surveys)."
default: 'standard'
settings: settings:
max_loop_iterations: 12 max_loop_iterations: 12
log_state_snapshots: true log_state_snapshots: true
timeout: 600 timeout: 1800
initial_state: initial_state:
language_ecosystem: 'general' language_ecosystem: 'general'
@@ -117,7 +123,7 @@ nodes:
search: search:
id: search id: search
type: llm type: llm
description: Identify 3-5 authoritative documentation sources via ddg-search. description: Identify authoritative documentation sources via ddg-search (3-5 standard depth, 6-12 deep).
skills_enabled: true skills_enabled: true
enabled_skills: enabled_skills:
- ai-slop-remover - ai-slop-remover
@@ -129,7 +135,10 @@ nodes:
Priority order: Priority order:
1. Official documentation - PRIORITIZE the hinted doc domains when 1. Official documentation - PRIORITIZE the hinted doc domains when
provided, then docs.X.org / readthedocs.io / MDN / vendor docs provided, then docs.X.org / readthedocs.io / MDN / vendor docs
2. Specifications (RFCs, W3C, ECMA, IEEE) 2. Specifications (RFCs, W3C, ECMA, IEEE) and academic sources -
the search_arxiv tool is available; use it when the topic is
academic/research-flavored (arXiv/DOI links count as
authoritative)
3. Credible secondary references (PEPs, official blog posts) - only 3. Credible secondary references (PEPs, official blog posts) - only
if 1-2 are sparse if 1-2 are sparse
@@ -142,14 +151,19 @@ nodes:
## Search budget and fail-fast rules ## Search budget and fail-fast rules
You have a HARD BUDGET of 3 search calls total. After 3 calls, stop Your budget is set by the `Research depth` line in the prompt:
calling tools and produce your final answer with whatever you have. - standard -> HARD BUDGET of 3 search calls total.
- deep -> HARD BUDGET of 10 search calls total; spend the extra
calls covering DISTINCT subtopics of the research topic, never
re-running near-duplicate queries.
After the budget is spent, stop calling tools and produce your final
answer with whatever you have.
If a search returns "HTTP 202 Accepted", empty results, error messages, If a search returns "HTTP 202 Accepted", empty results, error messages,
or rate-limit warnings: that counts as a used call. Do not retry the or rate-limit warnings: that counts as a used call. Do not retry the
same query - either rephrase OR give up. same query - either rephrase OR give up.
If after 3 calls you have NO usable URLs, output exactly: If after spending the budget you have NO usable URLs, output exactly:
NO_AUTHORITATIVE_SOURCES_FOUND NO_AUTHORITATIVE_SOURCES_FOUND
Reason: <one line> Reason: <one line>
@@ -168,9 +182,11 @@ nodes:
URL: <full url> URL: <full url>
... ...
Output 3-5 source blocks. No prose intro, no closing summary. Output 3-5 source blocks (standard depth) or 6-12 (deep). No prose
intro, no closing summary.
prompt: | prompt: |
Research topic: {{initial_prompt}} Research topic: {{initial_prompt}}
Research depth: {{research_depth}}
Triage hints: Triage hints:
- Language/ecosystem: {{language_ecosystem}} - Language/ecosystem: {{language_ecosystem}}
@@ -183,8 +199,9 @@ nodes:
pathlib` style queries). pathlib` style queries).
tools: tools:
- mcp:ddg-search - mcp:ddg-search
- search_arxiv
- web_search_coyote - web_search_coyote
max_iterations: 15 max_iterations: 30
state_updates: state_updates:
search_output: '{{output}}' search_output: '{{output}}'
fallback: synthesize fallback: synthesize
@@ -193,7 +210,7 @@ nodes:
search_oss: search_oss:
id: search_oss id: search_oss
type: llm type: llm
description: Find 2-3 production OSS examples relevant to the topic via the personal-github MCP. description: Find production OSS examples relevant to the topic via the personal-github MCP (2-3 standard depth, 4-8 deep).
skills_enabled: true skills_enabled: true
enabled_skills: enabled_skills:
- ai-slop-remover - ai-slop-remover
@@ -219,8 +236,12 @@ nodes:
## Search budget and fail-fast rules ## Search budget and fail-fast rules
HARD BUDGET: 8 tool calls total. After 8 calls, stop and output what Your budget is set by the `Research depth` line in the prompt:
you have - even one or two examples is fine. - standard -> HARD BUDGET of 8 tool calls total; output 2-3 blocks.
- deep -> HARD BUDGET of 20 tool calls total; output 4-8 blocks
across DIFFERENT repos/approaches, not near-duplicates.
After the budget is spent, stop and output what you have - even one or
two examples is fine.
If you find no production examples, output exactly: If you find no production examples, output exactly:
@@ -240,10 +261,12 @@ nodes:
REPO: ... REPO: ...
Output 2-3 blocks. The URL should point to a specific file that Output 2-3 blocks (standard depth) or 4-8 (deep). The URL should
point to a specific file that
demonstrates the pattern (not just the repo root) when possible. demonstrates the pattern (not just the repo root) when possible.
prompt: | prompt: |
Research topic: {{initial_prompt}} Research topic: {{initial_prompt}}
Research depth: {{research_depth}}
Triage hints: Triage hints:
- Language/ecosystem: {{language_ecosystem}} - Language/ecosystem: {{language_ecosystem}}
@@ -254,7 +277,7 @@ nodes:
Filter to {{language_ecosystem}} repositories when the API allows. Filter to {{language_ecosystem}} repositories when the API allows.
tools: tools:
- mcp:personal-github - mcp:personal-github
max_iterations: 15 max_iterations: 30
state_updates: state_updates:
oss_output: '{{output}}' oss_output: '{{output}}'
fallback: synthesize fallback: synthesize
@@ -308,8 +331,10 @@ nodes:
5. If a URL is dead, returns garbage, or is off-topic, note it 5. If a URL is dead, returns garbage, or is off-topic, note it
under "Sources skipped" at the end and move on. Do not retry. under "Sources skipped" at the end and move on. Do not retry.
Budget: max 8 fetches total (across both source lists). Skip Fetch budget, set by the `Research depth` line in the prompt:
aggressively. - standard -> max 8 fetches total (across both source lists).
- deep -> max 25 fetches total. Depth buys MORE SOURCES, never
re-fetching dead or off-topic URLs - skip aggressively either way.
## Output format ## Output format
@@ -332,6 +357,7 @@ nodes:
No flattery, no preamble. Start with `## Findings`. No flattery, no preamble. Start with `## Findings`.
prompt: | prompt: |
Research topic: {{initial_prompt}} Research topic: {{initial_prompt}}
Research depth: {{research_depth}}
Documentation sources (from doc search branch): Documentation sources (from doc search branch):
{{search_output}} {{search_output}}
@@ -340,7 +366,7 @@ nodes:
{{oss_output}} {{oss_output}}
tools: tools:
- fetch_url_via_curl - fetch_url_via_curl
max_iterations: 20 max_iterations: 45
state_updates: state_updates:
findings: '{{output}}' findings: '{{output}}'
fallback: final_format fallback: final_format
+4 -2
View File
@@ -1,6 +1,6 @@
name: sisyphus name: sisyphus
description: OpenCode-style orchestrator - classifies intent, delegates to specialists, tracks progress with todos, enforces OMO-grade verification discipline description: OpenCode-style orchestrator - classifies intent, delegates to specialists, tracks progress with todos, enforces OMO-grade verification discipline
version: 3.15.0 version: 3.17.0
agent_session: temp agent_session: temp
auto_continue: true auto_continue: true
@@ -11,6 +11,7 @@ can_spawn_agents: true
spawnable_agents: spawnable_agents:
- explore - explore
- librarian - librarian
- deep-research
- coder - coder
- oracle - oracle
- code-reviewer - code-reviewer
@@ -157,7 +158,8 @@ instructions: |
| Agent | Use For | Characteristics | | Agent | Use For | Characteristics |
|-------|---------|-----------------| |-------|---------|-----------------|
| `explore` | Find patterns in THIS codebase, understand local code | Read-only, returns findings, fan out as many as the task warrants — one per distinct search angle, module, or concern. Large codebases or cross-cutting tasks should spawn 5–15+. | | `explore` | Find patterns in THIS codebase, understand local code | Read-only, returns findings, fan out as many as the task warrants — one per distinct search angle, module, or concern. Large codebases or cross-cutting tasks should spawn 5–15+. |
| `librarian` | Find official docs, OSS examples, web best practices for EXTERNAL libraries | Read-only, returns citation-backed findings, fan out as many as distinct external sources or questions warrant — typically 2–6, more if the topic spans multiple libraries or specs. | | `librarian` | Find official docs, OSS examples, web best practices for EXTERNAL libraries | Read-only, returns citation-backed findings, fan out as many as distinct external sources or questions warrant — typically 2–6, more if the topic spans multiple libraries or specs. Default depth = quick-lookup budgets; for a BROAD topic (design research, best-practice surveys, architecture comparisons) pass `--variables {"research_depth": "deep"}` (~3× search/fetch budgets). Still prefer several narrow librarians over one giant one — deep is for questions that are inherently broad, not a substitute for fan-out. |
| `deep-research` | Open-ended investigation that must CHURN until solid — plans sub-questions, fans out a deep librarian per question, vets source credibility, runs a critique→re-research loop | Spawn with `--variables {"autonomy": "autonomous"}` — MANDATORY when spawned as a subagent (the supervised default blocks on a human approval gate). Raise `reflexion_budget` (e.g. "6", default 2) to let it churn longer. Expect hours, not minutes; one per investigation — its internal map is the fan-out. |
| `coder` | Write/edit files, implement features | Graph agent: plan → approval → implement → verify build+tests → self_review → bounded fix-loop | | `coder` | Write/edit files, implement features | Graph agent: plan → approval → implement → verify build+tests → self_review → bounded fix-loop |
| `oracle` | Architecture, complex debugging, review, plan review | Advisory, blocking — never answer the user before collecting Oracle results | | `oracle` | Architecture, complex debugging, review, plan review | Advisory, blocking — never answer the user before collecting Oracle results |
| `step-runner` | Execute ONE step of a phased plan repo (Phase 8) | Graph agent: orient → staleness check → coder → verify → handoff → user approval gate | | `step-runner` | Execute ONE step of a phased plan repo (Phase 8) | Graph agent: orient → staleness check → coder → verify → handoff → user approval gate |
+17 -4
View File
@@ -10548,7 +10548,10 @@ mod tests {
] ]
.concat(), .concat(),
), ),
("deep-research".to_string(), unreachable(&["ask_topic"])), (
"deep-research".to_string(),
unreachable(&["ask_topic", "end_autonomous"]),
),
("finding-verifier".to_string(), Vec::new()), ("finding-verifier".to_string(), Vec::new()),
("librarian".to_string(), Vec::new()), ("librarian".to_string(), Vec::new()),
("review-gauntlet".to_string(), Vec::new()), ("review-gauntlet".to_string(), Vec::new()),
@@ -12729,6 +12732,7 @@ mod tests {
[ [
"code-reviewer/review_domain", "code-reviewer/review_domain",
"code-reviewer/verify", "code-reviewer/verify",
"deep-research/research_one_question",
"deep-research/synthesize", "deep-research/synthesize",
"review-gauntlet/run_adversary", "review-gauntlet/run_adversary",
"review-gauntlet/run_code_review", "review-gauntlet/run_code_review",
@@ -17660,11 +17664,20 @@ mod tests {
assert_eq!(pf.fallback.as_deref(), Some("end_fault")); assert_eq!(pf.fallback.as_deref(), Some("end_fault"));
// research_one_question: branch-local marker; no `next` so the map // research_one_question: branch-local marker; no `next` so the map
// collects the fault as the lane's finding. // collects the fault as the lane's finding. The branch spawns a
let NodeType::Llm(question) = &graph.get_node("research_one_question").unwrap().node_type // librarian pinned to deep research budgets via graph inputs.
let NodeType::Agent(question) = &graph.get_node("research_one_question").unwrap().node_type
else { else {
panic!("research_one_question must be an llm node") panic!("research_one_question must be an agent node")
}; };
assert_eq!(question.agent, "librarian");
assert!(
question
.inputs
.as_ref()
.is_some_and(|i| i.get("research_depth").is_some_and(|v| v == "deep")),
"the librarian lane must be pinned to deep research budgets"
);
assert_eq!(question.fallback.as_deref(), Some("question_fault")); assert_eq!(question.fallback.as_deref(), Some("question_fault"));
assert!( assert!(
question question