返回 DeepSeek-Reasonix
2026-06-29-autoresearch-runtime-design.md
根目录 / docs / superpowers / specs / 2026-06-29-autoresearch-runtime-design.md
1 # AutoResearch Runtime Design
2
3 > Superseded: the active AutoResearch runtime was removed when Goal became the
4 > sole runtime. This document is retained as historical design context only;
5 > new Goal runs do not create or mutate `.reasonix/autoresearch/` state.
6
7 ## Context
8
9 Reasonix already has Goal mode and AutoResearch instructions. When a goal looks
10 long-running, `activeGoalBlock` injects an AutoResearch protocol that asks the
11 model to create `.reasonix/autoresearch/<task-id>/` and maintain files such as
12 `task_spec.json`, `progress.json`, `findings.jsonl`, `directions_tried.json`, and
13 `heartbeat.jsonl`.
14
15 The current behavior is useful, but the durable state is mostly prompt-driven.
16 The host does not create the task directory, validate schemas, compute
17 `stale_count`, require pivots, expose a structured status API, or provide a real
18 resume mechanism. This design upgrades AutoResearch from a prompt convention to
19 a host-managed runtime.
20
21 ## Goals
22
23 - Host creates and owns the AutoResearch task id and directory layout.
24 - Host validates task state with typed schemas.
25 - Host records heartbeat, progress, findings, directions tried, and iteration log.
26 - Host computes stale and pivot pressure from accepted evidence and direction
27 repetition.
28 - Goal completion is blocked until required success criteria have evidence.
29 - Existing AutoResearch task ids can be resumed by the controller.
30 - The desktop/API layer can query AutoResearch status without parsing prompt text.
31
32 ## Non-Goals
33
34 - No large desktop panel in the first implementation.
35 - No autonomous background daemon. AutoResearch advances only through normal Goal
36 turns.
37 - No parallel writable sub-agent redesign in this feature.
38 - No network, publish, payment, credential, or destructive-operation bypass.
39 Existing Reasonix gates still apply.
40
41 ## Proposed Architecture
42
43 Add a new package:
44
45 ```text
46 internal/autoresearch/
47 task.go
48 store.go
49 schema.go
50 summary.go
51 readiness.go
52 ```
53
54 The package is responsible for all filesystem state under:
55
56 ```text
57 .reasonix/autoresearch/<task-id>/
58 state/
59 task_spec.json
60 progress.json
61 directions_tried.json
62 findings.jsonl
63 iteration_log.jsonl
64 logs/
65 heartbeat.jsonl
66 ```
67
68 The controller remains the owner of Goal lifecycle. AutoResearch state is a
69 durable sidecar attached to a running Goal when research mode is on or auto
70 research is triggered.
71
72 ## Core Types
73
74 `TaskSpec`:
75
76 ```json
77 {
78 "task_id": "20260629-153000-debug-lag",
79 "goal": "Find the root cause of UI event-loop lag and verify the fix",
80 "scope": ["desktop/frontend", "desktop"],
81 "non_goals": [],
82 "allowed_operations": {
83 "write": true,
84 "network": false,
85 "publish": false
86 },
87 "success_criteria": [
88 {
89 "id": "root_cause",
90 "description": "A reproducible root cause is identified",
91 "required": true,
92 "evidence_ids": []
93 }
94 ]
95 }
96 ```
97
98 `Progress`:
99
100 ```json
101 {
102 "status": "running",
103 "iteration": 4,
104 "current_direction": "profile markdown rendering",
105 "stale_count": 1,
106 "pivot_count": 0,
107 "blocked_reason": "",
108 "updated_at": "2026-06-29T15:30:00Z"
109 }
110 ```
111
112 `Finding` JSONL entries:
113
114 ```json
115 {
116 "id": "f1",
117 "kind": "test",
118 "summary": "A markdown render benchmark reproduces the lag",
119 "source": "command",
120 "command": "pnpm --dir desktop/frontend test",
121 "paths": ["desktop/frontend/src/components/MarkdownRenderer.tsx"],
122 "accepted": true,
123 "created_at": "2026-06-29T15:30:00Z"
124 }
125 ```
126
127 `DirectionTried` entries record normalized direction fingerprints so the host can
128 detect repeated work:
129
130 ```json
131 {
132 "fingerprint": "profile-markdown-rendering",
133 "summary": "Profile markdown rendering",
134 "first_seen_iteration": 2,
135 "last_seen_iteration": 4,
136 "count": 2
137 }
138 ```
139
140 ## Store API
141
142 The first implementation should expose a small host API:
143
144 ```go
145 type Store struct { /* workspace root + autoresearch root */ }
146
147 func (s *Store) CreateTask(goal string, opts CreateOptions) (*Task, error)
148 func (s *Store) LoadTask(taskID string) (*Task, error)
149 func (s *Store) ResumeFromGoalText(goal string) (*Task, bool, error)
150 func (s *Store) AppendHeartbeat(taskID string, h Heartbeat) error
151 func (s *Store) AppendFinding(taskID string, f Finding) error
152 func (s *Store) RecordDirection(taskID string, d Direction) (*Progress, error)
153 func (s *Store) UpdateProgress(taskID string, patch ProgressPatch) (*Progress, error)
154 func (s *Store) ValidateTask(taskID string) (*ValidationReport, error)
155 func (s *Store) Readiness(taskID string) (*ReadinessReport, error)
156 func (s *Store) Summary(taskID string) (*Summary, error)
157 ```
158
159 All writes should be atomic: write to a temp file in the same directory, fsync
160 where practical, then rename. JSONL appends should validate each entry before
161 writing.
162
163 ## Controller Integration
164
165 When Goal mode starts:
166
167 1. If research mode is off, behavior is unchanged.
168 2. If AutoResearch is on, the controller creates a task unless the goal contains
169 an explicit `.reasonix/autoresearch/<task-id>/` path.
170 3. If an explicit task path exists, the controller loads and validates that task.
171 4. The active goal state stores `AutoResearchTaskID`.
172
173 Before each AutoResearch turn:
174
175 - The controller appends a heartbeat with `status=starting_turn`.
176 - The composed user input includes a concise host-generated summary:
177 task id, status, iteration, current direction, stale count, pivot count,
178 blockers, open success criteria, and next required runtime action.
179 - The static prompt still explains the protocol, but host state is authoritative.
180
181 After each turn:
182
183 - The controller appends a heartbeat with `status=turn_done`.
184 - If tools ran, it records basic iteration metadata.
185 - If no accepted evidence was recorded, or the same direction repeated, the host
186 increments `stale_count`.
187 - At `stale_count >= 2`, the next turn summary requires a structural pivot.
188 - At `stale_count >= 4`, the goal is blocked unless the agent asks for the
189 smallest external input needed.
190
191 The model may still write detailed notes, but host-owned JSON files are the
192 source of truth.
193
194 ## Completion Gate
195
196 When the model emits `[goal:complete]`, the controller runs AutoResearch
197 readiness before normal Goal completion:
198
199 - `task_spec.json` and `progress.json` must exist and validate.
200 - Every required success criterion must have at least one accepted evidence id.
201 - Evidence ids must resolve to entries in `findings.jsonl`.
202 - If code was changed, there must be accepted verification evidence or an
203 explicit accepted reason why verification could not run.
204 - If `progress.status` is blocked, completion is rejected.
205 - If `stale_count > 0`, completion is allowed only when the final iteration added
206 accepted evidence that addresses the stale direction.
207
208 Failure returns a concrete intercept message to the model listing missing
209 criteria and required next actions.
210
211 ## Resume Behavior
212
213 AutoResearch resume has two paths:
214
215 - Explicit: a goal or prompt includes `.reasonix/autoresearch/<task-id>/`.
216 - Session-sidecar: the persisted Goal state contains `AutoResearchTaskID`.
217
218 On resume, the host validates the task. If state is corrupt, it blocks execution
219 with a repair message instead of silently asking the model to infer state.
220
221 ## Desktop/API Surface
222
223 The first UI implementation should make AutoResearch visible without turning the
224 chat surface into a project-management app. It should use the existing desktop
225 layout patterns: status bar for compact state, side panels for inspectable
226 details, and transcript cards for turn-local events.
227
228 Host methods:
229
230 - `AutoResearchStatus(taskID string)`
231 - `AutoResearchList()`
232 - `AutoResearchCurrent()`
233 - `AutoResearchFindings(taskID string, limit int)`
234 - `AutoResearchOpenTask(taskID string)`
235
236 The status payload should include:
237
238 - task id
239 - goal
240 - status
241 - iteration
242 - current direction
243 - stale count
244 - pivot count
245 - last heartbeat
246 - finding count
247 - open success criteria
248 - blocker
249
250 `AutoResearchOpenTask` opens `.reasonix/autoresearch/<task-id>/` in the
251 workspace panel or OS file browser, matching existing workspace reveal behavior.
252
253 ## Deferred Desktop UI Design
254
255 The runtime PR exposes the desktop API and compact tab metadata first. The
256 default frontend tool/status surface intentionally stays unchanged until the UI
257 entry points below are implemented and reviewed as a separate product decision.
258
259 ### Entry Points
260
261 AutoResearch should appear in three places:
262
263 1. Status bar chip: a compact always-visible indicator when the active tab has a
264 running or resumable AutoResearch task.
265 2. Context/side panel section: an inspectable task summary for the active tab.
266 3. Transcript event cards: lightweight markers for task creation, pivot required,
267 blocked, resumed, and completed.
268
269 This keeps the primary chat workflow intact while making durable research state
270 visible and recoverable.
271
272 ### Status Bar Chip
273
274 Add an `autoresearch` status item to the existing status bar item system. It is
275 hidden when no AutoResearch task is active for the current tab.
276
277 Display states:
278
279 - `Research 4` for running iteration 4.
280 - `Pivot` when `pivot_required` is true.
281 - `Blocked` when status is blocked.
282 - `Done` briefly after completion.
283
284 The chip should include an icon, short label, and tooltip. The tooltip contains:
285
286 - task id
287 - current direction
288 - stale count
289 - open criteria count
290 - last heartbeat age
291
292 Clicking the chip opens the AutoResearch detail panel.
293
294 ### Detail Panel
295
296 Add a compact AutoResearch section to the right-side context/workspace area. The
297 panel should be dense and operational, not decorative.
298
299 Header:
300
301 - task id
302 - status
303 - iteration
304 - last heartbeat
305 - open task folder button
306
307 Summary rows:
308
309 - goal
310 - current direction
311 - stale count
312 - pivot count
313 - blocker
314
315 Success criteria list:
316
317 - criterion description
318 - required/optional marker
319 - evidence count
320 - status: open, satisfied, blocked
321
322 Findings list:
323
324 - newest accepted findings first
325 - kind badge: command, file, test, benchmark, manual, review, verification
326 - summary
327 - source command/path if present
328 - created time
329
330 Controls:
331
332 - Resume: starts or continues `/goal --research .reasonix/autoresearch/<task-id>/`
333 for the active tab when not running.
334 - Pause: clears active Goal continuation without deleting task state.
335 - Open Folder: reveals the task directory.
336 - Copy Task ID: copies the task id.
337
338 The first implementation can omit inline editing of task spec fields. Task state
339 is owned by the host and model workflow; UI edits would need validation and a
340 separate audit path.
341
342 ### Transcript Cards
343
344 Emit lightweight notices or typed events for important AutoResearch lifecycle
345 changes:
346
347 - task created
348 - task resumed
349 - heartbeat failed
350 - pivot required
351 - readiness blocked completion
352 - task completed
353 - task blocked
354
355 The transcript should not render the full runtime summary every turn. It should
356 show only meaningful lifecycle changes, because the full summary is already
357 available in the detail panel and injecting it visually every turn would add
358 noise.
359
360 ### Frontend State Flow
361
362 Extend bridge/types with:
363
364 ```ts
365 interface AutoResearchStatusView {
366 taskId: string;
367 goal: string;
368 status: "running" | "blocked" | "complete" | "stopped" | "invalid";
369 iteration: number;
370 currentDirection: string;
371 staleCount: number;
372 pivotCount: number;
373 pivotRequired: boolean;
374 lastHeartbeatAt: string;
375 findingCount: number;
376 openCriteria: AutoResearchCriterionView[];
377 blocker: string;
378 taskPath: string;
379 }
380 ```
381
382 `MetaForTab` should include only the small active-task summary needed to render
383 the status chip. The heavier findings list should be loaded on demand through
384 `AutoResearchFindings`, so normal chat turns do not pull large JSONL data into
385 frontend state.
386
387 Refresh strategy:
388
389 - Refresh current AutoResearch status after `turn_done`.
390 - Refresh when switching tabs.
391 - Refresh when receiving an AutoResearch lifecycle event.
392 - Do not poll every second. The heartbeat is persisted for durability, not for a
393 live dashboard animation.
394
395 ### Empty and Error States
396
397 - No active task: hide the chip and show no panel section by default.
398 - Invalid state: show an `Invalid` status with the exact validation error and an
399 Open Folder action.
400 - Missing task folder on resume: show a blocked state and keep the Goal from
401 silently continuing.
402 - Stale state: show the pivot requirement prominently but do not mark it as an
403 error.
404
405 ### Accessibility and Layout
406
407 - Use existing button, tooltip, panel, and status bar patterns.
408 - Keep the status chip width stable so the status bar does not shift during
409 streaming.
410 - Long goals and directions should wrap in the panel but truncate in the chip
411 tooltip label.
412 - Findings should be keyboard navigable and copyable.
413 - Use icons only where the existing design system already uses them; avoid a
414 marketing-style card layout.
415
416 ## Error Handling
417
418 - Missing task directory: create only when starting a new task; otherwise return
419 a clear resume error.
420 - Corrupt JSON: block AutoResearch continuation and surface the exact file.
421 - Schema mismatch: return validation errors with paths and fields.
422 - Failed heartbeat write: warn and continue for non-critical writes, but block
423 completion if state cannot be validated.
424 - Concurrent writes: serialize per task id inside the store.
425
426 ## Testing
427
428 Unit tests:
429
430 - task id generation is stable in shape and collision-safe
431 - store creates the expected directory layout
432 - schema validation rejects missing required fields
433 - JSONL append rejects invalid entries
434 - direction repetition increments stale count
435 - pivot threshold produces a pivot requirement
436 - readiness blocks missing evidence
437 - readiness accepts complete criteria with accepted findings
438 - resume loads explicit task id from goal text
439
440 Controller tests:
441
442 - AutoResearch goal creates task state
443 - active goal block includes host-generated summary
444 - every turn appends heartbeat
445 - `[goal:complete]` is intercepted when readiness fails
446 - explicit `.reasonix/autoresearch/<task-id>/` resumes existing state
447
448 Desktop/API tests:
449
450 - app method returns current AutoResearch status for the active tab
451 - tab metadata includes only compact AutoResearch summary
452 - findings are loaded on demand and capped by limit
453 - status chip hides when no task is active
454 - status chip opens the detail panel
455 - detail panel renders running, pivot, blocked, invalid, and complete states
456 - Open Folder calls the existing reveal/open path behavior
457 - tab switch refreshes the visible AutoResearch summary
458
459 ## Rollout
460
461 Phase 1: implement `internal/autoresearch` store, schemas, summary, readiness,
462 and tests.
463
464 Phase 2: integrate with Goal controller create/resume/heartbeat/summary and
465 completion intercept.
466
467 Phase 3: add desktop/API status methods, status bar chip, detail panel, transcript
468 lifecycle cards, and frontend tests.
469
470 Phase 4: optionally let tools or a dedicated host tool record structured
471 findings directly, reducing reliance on model-authored JSON.
472
473 ## Compatibility and Cache Impact
474
475 This design should not change provider-visible tool schemas in phase 1. The
476 active goal prompt changes only when AutoResearch is active. Cache impact is
477 therefore low for ordinary sessions and medium for AutoResearch sessions because
478 the injected runtime summary changes each turn.
479
480 No existing `.reasonix/autoresearch` task should be deleted or rewritten without
481 validation and explicit migration logic.
482
482 lines MARKDOWN