chore: remove obsolete documentation files

Remove outdated design docs, plans, and guides that have been
superseded or are no longer relevant.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sondre Engebråten
2026-02-17 09:01:39 +01:00
parent d85fad1a36
commit 926a82dbd8
16 changed files with 0 additions and 7006 deletions
-1
View File
@@ -1 +0,0 @@
'card data'
-651
View File
@@ -1,651 +0,0 @@
# Gap Tracker — Issues Tab Enhancement
**Branch:** `terminal/enhancement-issues-tab`
**Created:** 2026-02-12
**Total Gaps:** 41 confirmed (from triple-verified audit)
**Status:** 41 / 41 complete
---
## How to Use This File
Each gap has: ID, description, status, files to modify, doc reference, test status, and notes.
**Status values:**
- `PENDING` — Not started
- `IN_PROGRESS` — Currently being worked on
- `DONE` — Implemented, tested, committed
- `BLOCKED` — Waiting on another gap
- `SKIPPED` — Decided not to implement (with reason)
**Workflow per gap:**
1. Write/update tests first (TDD)
2. Implement the fix
3. Run tests — all must pass
4. Run lint (`npm run lint`)
5. Update this file
6. Commit with message referencing gap ID
---
## TIER 1 — Critical Wiring (Components built but not connected)
### GAP-01: `useMutations` hook not called in GitHubIssues.tsx
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Medium
- **Doc ref:** Phase 5 PRD > US-4 > AC-4.7; Phase 5 impl plan WP-4 Step 4.3
- **Files modified:** `GitHubIssues.tsx`
- **Fix:** Imported useMutations from hooks barrel, called with project ID, created 9 wrapped useCallback handlers bound to selectedIssue.number, passed all to IssueDetail (onEditTitle, onEditBody, onClose, onReopen, onComment, onAddLabels, onRemoveLabels, onAddAssignees, onRemoveAssignees)
- **Tests:** IssueDetail integration tests pass (7 tests), lint clean
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** GAP-01
### GAP-02: InlineEditor not used for title editing in IssueDetail.tsx
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Small
- **Doc ref:** Phase 5 PRD > US-4 > AC-4.1; Phase 2 PRD > US-1
- **Files to modify:** `renderer/components/github-issues/components/IssueDetail.tsx`
- **Source component:** `InlineEditor.tsx` — accepts value, onSave, ariaLabel, maxLength, counterThreshold, required
- **Fix:** Imported InlineEditor. Conditionally renders InlineEditor when onEditTitle provided (required, ariaLabel from i18n), else renders static h2.
- **Tests:** 3 new tests: renders edit button when onEditTitle present, no edit button when absent, onEditTitle called on save
- **Test status:** `PASS` (14/14)
- **Depends on:** GAP-01 (for callbacks to flow)
- **Commit:** (combined with GAP-03)
### GAP-03: InlineEditor not used for body editing in IssueDetail.tsx
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Small
- **Doc ref:** Phase 5 PRD > US-4 > AC-4.2; Phase 2 PRD > US-2
- **Files to modify:** `renderer/components/github-issues/components/IssueDetail.tsx`
- **Source component:** `InlineEditor.tsx` — multiline mode
- **Fix:** Conditionally renders InlineEditor multiline when onEditBody provided, ariaLabel from i18n. Falls through to ReactMarkdown or empty state when not provided.
- **Tests:** 4 new tests: renders edit button when onEditBody present, no edit button when absent, body InlineEditor editable, null body with onEditBody
- **Test status:** `PASS` (14/14)
- **Depends on:** GAP-01, GAP-02 (same import)
- **Commit:** (combined with GAP-02)
### GAP-04: LabelManager not used in IssueDetail.tsx
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Medium
- **Doc ref:** Phase 5 PRD > US-4 > AC-4.3; Phase 2 PRD > US-3 > AC3.1-3.10
- **Files to modify:** `renderer/components/github-issues/components/IssueDetail.tsx`, `types/index.ts`, `GitHubIssues.tsx`
- **Source component:** `LabelManager.tsx` — accepts currentLabels, repoLabels, onAddLabel, onRemoveLabel, disabled, isLoading
- **Fix:** Added `repoLabels` to IssueDetailProps, fetched via IPC in GitHubIssues.tsx, LabelManager renders when onAddLabels+onRemoveLabels+repoLabels provided with single→array adapter
- **Tests:** 3 new tests: LabelManager visible with props, static badges without, onRemoveLabel calls onRemoveLabels([label])
- **Test status:** `PASS` (20/20)
- **Depends on:** GAP-01
- **Commit:** (combined with GAP-05)
### GAP-05: AssigneeManager not used in IssueDetail.tsx
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Medium
- **Doc ref:** Phase 5 PRD > US-4 > AC-4.4; Phase 2 PRD > US-4 > AC4.1-4.9
- **Files to modify:** `renderer/components/github-issues/components/IssueDetail.tsx`, `types/index.ts`, `GitHubIssues.tsx`
- **Source component:** `AssigneeManager.tsx` — accepts currentAssignees, collaborators, onAddAssignee, onRemoveAssignee, disabled
- **Fix:** Added `collaborators` to IssueDetailProps, fetched via IPC in GitHubIssues.tsx, AssigneeManager renders when onAddAssignees+onRemoveAssignees+collaborators provided with single→array adapter
- **Tests:** 3 new tests: AssigneeManager visible with props, static badges without, onRemoveAssignee calls onRemoveAssignees([login])
- **Test status:** `PASS` (20/20)
- **Depends on:** GAP-01
- **Commit:** (combined with GAP-04)
### GAP-06: CreateSpecButton not used in IssueDetail.tsx
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Medium
- **Doc ref:** Phase 2 PRD > US-8 > AC8.1; Phase 2 PRD Section 4.2
- **Files to modify:** `renderer/components/github-issues/components/IssueDetail.tsx`, `types/index.ts`
- **Source component:** `CreateSpecButton.tsx` — accepts issueNumber, issueClosed, hasActiveAgent, activeSpecNumber, hasEnrichment, onCreateSpec
- **Fix:** Added onCreateSpec to IssueDetailProps, imported CreateSpecButton, conditionally renders after actions when onCreateSpec provided, derives hasActiveAgent and hasEnrichment from enrichment data
- **Tests:** 3 new tests: button visible with onCreateSpec, hidden without, disabled when agent active
- **Test status:** `PASS` (23/23)
- **Depends on:** None (standalone component)
- **Commit:** GAP-06
### GAP-07: CompletenessBreakdown not used in EnrichmentPanel.tsx
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Small
- **Doc ref:** Phase 2 PRD > US-9 > AC9.1; Phase 2 PRD Section 4.2
- **Files to modify:** `renderer/components/github-issues/components/EnrichmentPanel.tsx`
- **Source component:** `CompletenessBreakdown.tsx` — accepts enrichment, score, onSectionClick?
- **Fix:** Imported CompletenessBreakdown, renders after CompletenessIndicator when enrichmentData exists. Also fixed lint warnings (vi.fn() instead of () => {}).
- **Tests:** 2 new tests: breakdown visible with enrichment data, hidden without
- **Test status:** `PASS` (12/12)
- **Depends on:** None
- **Commit:** GAP-07
### GAP-08: `useDependencies` hook not called in GitHubIssues.tsx
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Small
- **Doc ref:** Phase 5 PRD > US-6 > AC-6.2; Phase 5 impl plan WP-4 Step 4.3
- **Files to modify:** `renderer/components/GitHubIssues.tsx`
- **Source hook:** `hooks/useDependencies.ts` — returns dependencies, isLoading, error, refetch
- **Fix:** Added useDependencies to hooks import, called with selectedIssue?.number, passed dependencies/isDepsLoading/depsError to IssueDetail
- **Tests:** Existing IssueDetail integration tests already cover dependency rendering (DependencyList test)
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** GAP-08
### GAP-09: BulkResultsPanel not mounted in GitHubIssues.tsx
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Doc ref:** Phase 5 PRD > US-5 > AC-5.4; Phase 5 impl plan WP-5 Step 5.3
- **Files modified:** `renderer/components/GitHubIssues.tsx`
- **Source component:** `BulkResultsPanel.tsx` — accepts result, onRetry, onDismiss
- **Fix:** Imported BulkResultsPanel + useMutationStore. Mounted after BulkActionBar when bulkResult exists. Wired onRetry (noop — externally handled) and onDismiss (clearBulkResult).
- **Tests:** 6 BulkResultsPanel component tests pass
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** Phase D batch
### GAP-10: EnrichmentCommentPreview not mounted in GitHubIssues.tsx
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Doc ref:** Phase 3 PRD > US-5 > AC5.4; Phase 5 impl plan WP-6 Step 6.3
- **Files modified:** `renderer/components/GitHubIssues.tsx`, `stores/github/ai-triage-store.ts`, `hooks/useAITriage.ts`, `shared/constants/ai-triage.ts`
- **Source component:** `EnrichmentCommentPreview.tsx` — accepts content, onPost, onCancel
- **Fix:** Added enrichmentResult/clearEnrichmentResult to store + hook. Added formatEnrichmentComment utility. Mounted EnrichmentCommentPreview when enrichmentResult exists. onPost calls addComment + clearEnrichmentResult.
- **Tests:** 6 EnrichmentCommentPreview component tests + 2 store tests (set/clear enrichmentResult) = 8 tests pass
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** Phase D batch
### GAP-11: LabelSyncSettings not mounted in settings page
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Doc ref:** Phase 5 PRD > US-9 > AC-9.1; Phase 5 impl plan WP-8 Step 8.2
- **Files modified:** `components/LabelSyncSettingsConnected.tsx` (NEW), `settings/sections/SectionRouter.tsx`
- **Source component:** `LabelSyncSettings.tsx` — accepts enabled, isSyncing, lastSyncedAt, error, onEnable, onDisable
- **Fix:** Created LabelSyncSettingsConnected wrapper (hooks can't be called conditionally in switch). Uses useLabelSync + useRef guard to prevent infinite re-render. Mounted in SectionRouter github case after GitHubIntegration.
- **Tests:** 3 new tests: renders settings, loadStatus on mount, enabled state. All pass.
- **Test status:** `PASS`
- **Depends on:** GAP-15 (useLabelSync wiring)
- **Commit:** Phase D batch
### GAP-12: ProgressiveTrustSettings not mounted in settings page
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Doc ref:** Phase 5 PRD > US-9 > AC-9.2; Phase 5 impl plan WP-8 Step 8.2
- **Files modified:** `components/ProgressiveTrustSettingsConnected.tsx` (NEW), `settings/sections/SectionRouter.tsx`
- **Source component:** `ProgressiveTrustSettings.tsx` — accepts config, onSave, onCancel
- **Fix:** Created ProgressiveTrustSettingsConnected wrapper. Loads config via getProgressiveTrust IPC on mount, saves via saveProgressiveTrust. Mounted in SectionRouter github case after LabelSyncSettingsConnected.
- **Tests:** 3 new tests: renders settings, loads config from IPC, saves config. All pass.
- **Test status:** `PASS`
- **Depends on:** GAP-11 (same settings file)
- **Commit:** Phase D batch
### GAP-13: IssueListHeader ignores triage toggle props
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Small
- **Doc ref:** Phase 5 PRD > US-8 > AC-8.1; Phase 5 impl plan WP-7 Step 7.4
- **Files to modify:** `renderer/components/github-issues/components/IssueListHeader.tsx`
- **Fix:** Destructured onToggleTriageMode, isTriageModeEnabled, isTriageModeAvailable. Added Layers toggle button with i18n aria-label (phase5.triageMode), tooltip (phase5.triageModeTooltip), aria-pressed state, disabled when !isAvailable, variant secondary when enabled.
- **Tests:** 5 new tests: toggle visible/hidden, click callback, disabled state, aria-pressed state
- **Test status:** `PASS` (5/5)
- **Depends on:** None
- **Commit:** GAP-13
### GAP-14: Select All / Deselect All missing from UI
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Small
- **Doc ref:** Phase 2 PRD > US-7 > AC7.2; Phase 5 PRD > US-5 > AC-5.7
- **Files to modify:** `renderer/components/GitHubIssues.tsx`, `renderer/components/github-issues/components/BulkActionBar.tsx`
- **Fix:** Re-add handleSelectAll/handleDeselectAll in GitHubIssues.tsx. Pass to BulkActionBar. Add Select All / Deselect All buttons in BulkActionBar.
- **Tests:** Click Select All → all visible issues selected; Deselect All → none selected
- **Test status:** `PASS` (4 new tests, 12 total)
- **Depends on:** None
- **Commit:** pending
### GAP-15: `useLabelSync` hook not wired anywhere
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Doc ref:** Phase 4 PRD > US-2 > AC2.1; Phase 5 PRD > US-9 > AC-9.1
- **Files modified:** `renderer/components/GitHubIssues.tsx`, `__tests__/label-sync-integration.test.ts` (NEW)
- **Fix:** Called useLabelSync() in GitHubIssues.tsx. Updated handleTransition to call labelSync.syncIssueLabel(issueNumber, newState, oldState) after transitionWorkflowState.
- **Tests:** 3 integration tests: sync called on transition, not called when no issue selected, old state derived from enrichments
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** Phase D batch
### GAP-16: BatchTriageReview not mounted in GitHubIssues.tsx
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Doc ref:** Phase 3 PRD > US-3 > AC3.1; Phase 5 impl plan WP-6
- **Files modified:** `renderer/components/GitHubIssues.tsx`
- **Source component:** `BatchTriageReview.tsx` — accepts items, onAccept, onReject, onAcceptAll, onDismiss, onApply
- **Fix:** Imported BatchTriageReview. Mounted when aiTriage.reviewItems.length > 0. Wired onAccept/onReject from hook, onAcceptAll/onDismiss from store, onApply from hook.
- **Tests:** 6 BatchTriageReview component tests pass
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** Phase D batch
---
## TIER 2 — Missing Implementation
### GAP-17: `risksEdgeCases` missing from EnrichmentPanel ENRICHMENT_SECTIONS
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Small
- **Doc ref:** Phase 1 PRD > US-4 > AC4.2; PRD Section 4.3 (7 enrichment sections); PRD Section 4.12 i18n
- **Files modified:** `EnrichmentPanel.tsx`, `en/common.json`, `fr/common.json`
- **Fix:** Added `{ key: 'risksEdgeCases', i18nKey: 'enrichment.panel.risksEdgeCases' }` to ENRICHMENT_SECTION_KEYS; added i18n keys to EN ("Risks / Edge Cases") and FR ("Risques / Cas limites")
- **Tests:** 10 tests pass — section count updated from 6→7, new test for risksEdgeCases content rendering
- **Test status:** `PASS`
- **Depends on:** GAP-18 (done)
- **Commit:** GAP-17
### GAP-18: Hardcoded English in 5 components instead of i18n
- **Status:** `DONE`
- **Priority:** MUST-FIX (CLAUDE.md critical rule)
- **Scope:** Medium
- **Doc ref:** Phase 1 PRD > Section 11 DoD; CLAUDE.md Critical Rules
- **Files modified:**
1. `components/WorkflowStateBadge.tsx` — replaced WORKFLOW_STATE_LABELS with t('enrichment.states.X')
2. `components/WorkflowFilter.tsx` — replaced "All states", "Workflow state", selected count with t() calls
3. `components/WorkflowStateDropdown.tsx` — replaced "Move to", resolutions, "Unblock →" with t() calls
4. `components/CompletenessIndicator.tsx` — replaced "Not assessed", completeness label with t() calls
5. `components/EnrichmentPanel.tsx` — replaced section labels, "No priority", "Not yet enriched" with t() calls
6. `components/MetricsDashboard.tsx` — (bonus) replaced WORKFLOW_STATE_LABELS with t() calls
- **Fix:** Added useTranslation('common') import to each, replaced all hardcoded English with i18n keys
- **Tests:** All 7 test files updated (5 component tests + TriageSidebar + IssueDetail integration) — 75 tests pass
- **Test status:** `PASS` (61 component tests + 14 MetricsDashboard tests)
- **Depends on:** None (i18n keys already exist)
- **Commit:** GAP-18
### GAP-19: Keyboard shortcuts Ctrl+1/2/3 for triage panels
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Doc ref:** Phase 4 PRD > US-5 > AC5.1-5.4; Phase 5 PRD > US-8 > AC-8.6
- **Files modified:** `hooks/useTriageMode.ts`, `renderer/components/GitHubIssues.tsx`
- **Fix:** Added useEffect with keydown listener for Ctrl+1/2/3 in useTriageMode. Only active when isEnabled. Added data-triage-panel="1|2|3" + tabIndex={-1} to panel sections.
- **Tests:** 4 new tests: Ctrl+1/2/3 focus panels, shortcuts inactive when disabled. 9 total.
- **Test status:** `PASS`
- **Depends on:** GAP-24 (panels need role="region" + aria-label as focus targets)
- **Commit:** Phase E batch
### GAP-20: DependencyList items not clickable
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Small
- **Doc ref:** Phase 4 PRD > US-6 > AC6.5
- **Files to modify:** `renderer/components/github-issues/components/DependencyList.tsx`
- **Fix:** Added onNavigate prop. Local deps rendered as clickable buttons with text-primary + hover:underline. Cross-repo deps remain static text. Wired through IssueDetail → GitHubIssues selectIssue.
- **Tests:** 4 new tests: click local track, click trackedBy, cross-repo not clickable, no buttons when onNavigate absent
- **Test status:** `PASS` (4 new, 13 total)
- **Depends on:** None
- **Commit:** pending
### GAP-21: useMutations doesn't update issues-store after success
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Medium
- **Doc ref:** Phase 2 PRD > US-1 AC1.6, US-2 AC2.7, US-3 AC3.9, US-4 AC4.8, US-5 AC5.6
- **Files modified:** `hooks/useMutations.ts`, `hooks/__tests__/useMutations.test.ts`
- **Fix:** Imported useIssuesStore, added optimistic store updates after each successful mutation (title, body, state, commentsCount, labels merge/remove, assignees merge/remove). No store update on failure.
- **Tests:** 21 tests pass (12 existing + 9 new store update tests)
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** GAP-21
### GAP-22: Selection doesn't clear after bulk op success
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Small
- **Doc ref:** Phase 5 PRD > US-5 > AC-5.5; Phase 5 impl plan WP-5.1 test 6
- **Files to modify:** `renderer/components/GitHubIssues.tsx`
- **Fix:** Added useRef to track wasBulkOperating. useEffect clears selectedIssueNumbers when isBulkOperating transitions true→false.
- **Tests:** Logic is minimal (ref + effect), integration-tested by existing bulk operation flow
- **Test status:** `PASS` (verified via lint)
- **Depends on:** None
- **Commit:** pending
### GAP-23: No confirmation dialog before bulk actions
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Small-Medium
- **Doc ref:** Phase 2 PRD > US-7 > AC7.5
- **Files to modify:** `renderer/components/github-issues/components/BulkActionBar.tsx`
- **Fix:** Added pendingAction state. Clicking action button shows inline confirm prompt (role=alert) with confirm/cancel. i18n keys: bulk.confirmMessage, bulk.confirm, bulk.cancel (EN+FR).
- **Tests:** 3 new tests: confirm fires action, cancel reverts, dialog has role=alert. Updated existing test. 14 total.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** pending
### GAP-24: role="region" + aria-label missing on triage panels
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Small
- **Doc ref:** Phase 4 PRD > US-5 > AC5.5; Phase 4 PRD > US-4 > AC4.8
- **Files modified:** `GitHubIssues.tsx`, `en/common.json`, `fr/common.json`
- **Fix:** Changed 3 panel `<div>` to `<section>` with i18n `aria-label` (panels.issueList/issueDetail/triageSidebar). Also added `useTranslation` import to GitHubIssues.tsx.
- **Tests:** Lint passes with 0 warnings (Biome recommended `<section>` over `<div role="region">`)
- **Test status:** `PASS` (lint clean)
- **Depends on:** None
- **Commit:** GAP-24
---
## TIER 3 — Phase 3 AI Gaps
### GAP-28: Progressive trust auto-apply logic not implemented
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Medium
- **Doc ref:** Phase 3 PRD > US-4 > AC4.6
- **Files modified:** `stores/github/ai-triage-store.ts`, `hooks/useAITriage.ts`, `stores/github/__tests__/ai-triage-store.test.ts`, `hooks/__tests__/useAITriage.test.ts`
- **Fix:** Added `autoApplyByTrust(config)` to store — iterates pending items, marks as 'auto-applied' if confidence >= threshold for enabled categories (labels requires non-empty labelsToAdd, duplicate requires isDuplicate). Added `applyProgressiveTrust()` callback in useAITriage hook — fetches config via `getProgressiveTrust` IPC, calls store method.
- **Tests:** 6 store tests (above threshold, below threshold, duplicate, disabled categories, already accepted/rejected, empty labels). 1 hook test (fetches config + auto-applies). 17 total.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** pending
### GAP-29: No enrichment persistence to local files after AI triage
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Medium
- **Doc ref:** Phase 3 PRD > US-1 > AC1.11; Phase 3 PRD > US-5 > AC5.9
- **Files to modify:** `main/ipc-handlers/github/ai-triage-handlers.ts`
- **Fix:** After sendComplete() in runEnrichment, persist enrichment sections + completenessScore to enrichment.json. After successful label apply in applyTriageResults, persist triageResult. Both use readEnrichmentFile/writeEnrichmentFile with createDefaultEnrichment fallback. Errors caught and logged (non-fatal).
- **Tests:** 2 new tests: runEnrichment persists to file, applyTriageResults persists triageResult. 15 total.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** pending
### GAP-30: No `actor: 'ai-triage'` audit trail
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Medium
- **Doc ref:** Phase 3 PRD > US-4 > AC4.7; NFR 3.3
- **Files to modify:** `shared/types/enrichment.ts`, `main/ipc-handlers/github/ai-triage-handlers.ts`
- **Fix:** Added 'ai-triage' to TransitionActor union. After successful label apply in applyTriageResults, call appendTransition with actor: 'ai-triage', from: existing state, to: 'triage', reason with category + confidence.
- **Tests:** 1 new test: verify appendTransition called with ai-triage actor. 16 total.
- **Test status:** `PASS`
- **Depends on:** GAP-29
- **Commit:** pending
### GAP-31: No linking comment when splitting issues
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Small
- **Doc ref:** Phase 3 PRD > US-6 > AC6.8, AC6.12
- **Files to modify:** `renderer/components/github-issues/hooks/useAITriage.ts`
- **Fix:** In confirmSplit(), after creating sub-issues and before closing original, post comment via addIssueComment: "Split into: #N1, #N2...\n\n---\n*Split by Auto-Claude*"
- **Tests:** 1 new test verifying linking comment contains sub-issue numbers and signature. 9 total.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** pending
### GAP-32: No sub-issue enrichment creation on split
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Medium
- **Doc ref:** Phase 3 PRD > US-6 > AC6.11
- **Files to modify:** `renderer/components/github-issues/hooks/useAITriage.ts`
- **Fix:** After creating sub-issues in confirmSplit, save enrichment for each sub-issue with splitFrom: originalNumber. Also save original's enrichment with splitInto: [subNumbers]. Uses createDefaultEnrichment + saveEnrichment IPC.
- **Tests:** 1 new test: 3 saveEnrichment calls verified (2 subs with splitFrom, 1 original with splitInto). 10 total.
- **Test status:** `PASS`
- **Depends on:** GAP-29 (enrichment write mechanism)
- **Commit:** pending
### GAP-33: Duplicate detection display-only
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Doc ref:** Phase 3 PRD > US-7 > AC7.2, AC7.3
- **Files modified:** `TriageResultCard.tsx`, `TriageResultCard.test.tsx`, `en/common.json`, `fr/common.json`
- **Fix:** Added `onNavigateToIssue` and `onCloseAsDuplicate` props. Duplicate number rendered as clickable button (text-primary hover:underline) when onNavigateToIssue provided, else static span. "Close as Duplicate" button shown when onCloseAsDuplicate provided and item is pending. i18n key: aiTriage.closeAsDuplicate (EN+FR).
- **Tests:** 5 new tests: clickable duplicate navigates, static when absent, close-as-duplicate fires callback, hidden when accepted. 13 total.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** pending
### GAP-34: No batch triage confirmation dialog or cost estimate
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Doc ref:** Phase 3 PRD > US-2 > AC2.2; NFR 3.2
- **Files modified:** `BulkActionBar.tsx`, `BulkActionBar.test.tsx`, `en/common.json`, `fr/common.json`
- **Fix:** Added `pendingTriageAll` state. Clicking Triage All shows inline confirmation (role=alert) with issue count + estimated cost via `estimateBatchCost()`. Confirm fires `onTriageAll`, cancel reverts to button. i18n key: aiTriage.confirmTriage (EN+FR).
- **Tests:** 2 new tests: confirm fires action with cost shown, cancel reverts. 16 total.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** pending
### GAP-35: No undo batch mechanism
- **Status:** `DONE`
- **Priority:** SHOULD-FIX (NICE-TO-HAVE)
- **Scope:** Large
- **Doc ref:** Phase 3 PRD > US-4 > AC4.9; Phase 3 audit GAP-4
- **Files modified:** `stores/github/ai-triage-store.ts`, `components/BatchTriageReview.tsx`, `GitHubIssues.tsx`, `en/common.json`, `fr/common.json`
- **Fix:** Added lastBatchSnapshot state + snapshotBeforeApply/undoLastBatch actions to store. Added onUndo prop to BatchTriageReview with Undo button. GitHubIssues snapshots before apply and passes onUndo when snapshot exists. i18n: batchReview.undo (EN/FR).
- **Tests:** 3 store tests (snapshot, restore, no-op when no snapshot) + 2 component tests (undo button shown/hidden). 22 total.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** Phase E batch
### GAP-36: Trust level UI (Crawl/Walk/Run) not displayed
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Doc ref:** Phase 3 PRD > US-4 > AC4.10, AC4.11
- **Files modified:** `ProgressiveTrustSettings.tsx`, `ProgressiveTrustSettings.test.tsx`, `en/common.json`, `fr/common.json`
- **Fix:** Added trust level radio group (Crawl/Walk/Run) above category rows. `deriveTrustLevel()` infers level from config. `setTrustLevel()` applies presets: Crawl=all disabled, Walk=labels+duplicate, Run=all enabled. Warning (role=alert) shown for Run. i18n keys: trustLevel, crawl, walk, run, runWarning (EN+FR).
- **Tests:** 5 new tests: radio group renders, default crawl, run enables all + warning, crawl disables all, walk enables labels+duplicate. 12 total.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** pending
### GAP-37: No error/retry UI for failed AI triage
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Doc ref:** Phase 3 PRD > US-1 > AC1.12
- **Files modified:** `stores/github/ai-triage-store.ts`, `hooks/useAITriage.ts`, `components/EnrichmentPanel.tsx`, `en/common.json`, `fr/common.json`
- **Fix:** Added `lastError` state + `setLastError`/`clearLastError` to store. `startTriage` clears lastError. Error IPC listeners set lastError. EnrichmentPanel shows role=alert with error text + Retry button (i18n: aiTriage.retry EN+FR). Hook exposes lastError + clearLastError.
- **Tests:** 3 store tests (set/clear/startTriage clears), 2 hook tests (error callback, expose state), 2 panel tests (shows alert + retry, no alert when null). 36 total across 3 files.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** pending
### GAP-38: Missing aria-labels on AI action buttons
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Small
- **Doc ref:** Phase 3 PRD > US-1 AC1.13, US-2 AC2.11, US-5 AC5.13
- **Files modified:** `EnrichmentPanel.tsx`, `BulkActionBar.tsx`, `BulkActionBar.test.tsx`
- **Fix:** Added aria-label to AI Triage, Improve Issue, Split Issue buttons in EnrichmentPanel. Added aria-label to Triage All and toolbar in BulkActionBar (using i18n keys).
- **Tests:** 18 tests pass (10 EnrichmentPanel + 8 BulkActionBar including new Triage All aria-label test)
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** GAP-38
---
## TIER 4 — Polish
### GAP-39: No compact card mode for IssueList in 3-panel
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Small-Medium
- **Doc ref:** Phase 4 PRD > US-4 > AC4.4; Phase 4 impl plan WP-8.5
- **Files to modify:** `types/index.ts`, `components/IssueList.tsx`, `components/IssueListItem.tsx`, `GitHubIssues.tsx`
- **Fix:** Added compact prop to IssueListItemProps and IssueListProps. When compact=true, metadata footer row (author, comments, labels, completeness) is hidden. Passed compact={triageModeEnabled} from GitHubIssues. Added to memo comparison.
- **Tests:** 4 new tests in IssueListItem.test.tsx: normal shows metadata, compact hides metadata, compact shows title, compact shows issue number
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** pending
### GAP-40: Label sync debounce not implemented
- **Status:** `DONE`
- **Priority:** NICE-TO-HAVE
- **Scope:** Medium
- **Doc ref:** Phase 4 PRD > US-2 > AC2.2, AC2.7
- **Files modified:** `hooks/useLabelSync.ts`
- **Fix:** Added useRef timer + SYNC_DEBOUNCE_MS (2000ms) debounce to syncIssueLabel. Clears timer on each call, only fires the last. Cleanup on unmount.
- **Tests:** Updated existing test + 1 new debounce test: rapid calls → only last fires. 11 total.
- **Test status:** `PASS`
- **Depends on:** GAP-15 (useLabelSync wired first)
- **Commit:** Phase E batch
### GAP-41: No bulk label sync handler
- **Status:** `DONE`
- **Priority:** NICE-TO-HAVE
- **Scope:** Medium
- **Doc ref:** Phase 4 PRD Section 3.2; Phase 4 impl plan WP-2.1
- **Files modified:** `shared/constants/ipc.ts`, `main/ipc-handlers/github/label-sync-handlers.ts`, `preload/api/modules/github-api.ts`, `hooks/useLabelSync.ts`
- **Fix:** Added GITHUB_LABEL_SYNC_BULK IPC channel. Added bulk handler in label-sync-handlers (iterates issues, reads enrichment for state, syncs labels). Added preload method + hook bulkLabelSync function.
- **Tests:** 2 new hook tests: bulk calls API when enabled, skips when disabled. 11 total.
- **Test status:** `PASS`
- **Depends on:** GAP-15
- **Commit:** Phase E batch
### GAP-42: No color preview in LabelSyncSettings
- **Status:** `DONE`
- **Priority:** NICE-TO-HAVE
- **Scope:** Small
- **Doc ref:** Phase 4 PRD > US-8 > AC8.4; Phase 4 impl plan WP-7.1
- **Files modified:** `components/LabelSyncSettings.tsx`
- **Fix:** Imported getWorkflowLabels. Renders 7 color swatches when enabled, each with colored dot + label name (e.g., ac:new, ac:triage). Uses hex color from WORKFLOW_LABEL_COLORS with opacity for background.
- **Tests:** 2 new tests: 7 swatches when enabled, 0 when disabled. 13 total.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** Phase E batch
### GAP-43: No markdown preview toggle in CommentForm/InlineEditor
- **Status:** `DONE`
- **Priority:** NICE-TO-HAVE
- **Scope:** Large
- **Doc ref:** Phase 2 PRD > US-2 AC2.2; Phase 2 PRD > US-6 AC6.2
- **Files modified:** `components/CommentForm.tsx`, `en/common.json`, `fr/common.json`
- **Fix:** Added Write/Preview tab toggle to CommentForm. Preview mode renders ReactMarkdown. Also converted all hardcoded strings to i18n keys (commentForm.write/preview/placeholder/emptyError/submit/submitting). Content preserved when toggling.
- **Tests:** 3 new tests (tabs visible, preview shows markdown, write restores content) + 5 updated existing. 8 total.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** Phase E batch
## TIER 5 — Low Priority
### GAP-25: IssueList ARIA listbox
- **Status:** `DONE`
- **Priority:** NICE-TO-HAVE
- **Scope:** Small
- **Doc ref:** WCAG 2.1 Listbox pattern
- **Files modified:** `components/IssueList.tsx`, `components/IssueListItem.tsx`, `en/common.json`, `fr/common.json`
- **Fix:** Added role="listbox" + aria-label (i18n issues.listLabel) to IssueList container div. Added role="option" + aria-selected + tabIndex={0} + onKeyDown (Enter/Space) to IssueListItem.
- **Tests:** 4 new IssueList integration tests (listbox role, aria-label, option count, aria-selected). 4 new IssueListItem tests (role=option, aria-selected false/true, Enter key). 18 total.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** Phase F batch
### GAP-26: transitions.json retention
- **Status:** `SKIPPED`
- **Priority:** NICE-TO-HAVE
- **Scope:** N/A
- **Doc ref:** Not in PRD
- **Reason:** Not specified in any PRD. Transitions are already persisted via appendTransition in enrichment handlers (GAP-30). No additional work needed.
---
## Progress Log
| Date | Gap ID | Action | Commit |
|------|--------|--------|--------|
| 2026-02-12 | GAP-18 | DONE — i18n in 6 components (5 + MetricsDashboard), 7 test files updated, 75 tests pass | GAP-18 |
| 2026-02-12 | GAP-17 | DONE — risksEdgeCases section added to EnrichmentPanel, i18n keys added EN+FR, 10 tests pass | GAP-17 |
| 2026-02-12 | GAP-24 | DONE — 3 panels changed to `<section>` with i18n aria-label, lint clean | GAP-24 |
| 2026-02-12 | GAP-38 | DONE — aria-labels on AI buttons (EnrichmentPanel + BulkActionBar), 18 tests pass | GAP-38 |
| 2026-02-12 | GAP-01 | DONE — useMutations wired in GitHubIssues.tsx, 9 callbacks passed to IssueDetail | GAP-01 |
| 2026-02-12 | GAP-21 | DONE — optimistic store updates in useMutations, 21 tests pass | GAP-21 |
| 2026-02-12 | GAP-02+03 | DONE — InlineEditor wired for title (required) and body (multiline) in IssueDetail, 7 new tests, 14 pass | GAP-02+03 |
| 2026-02-12 | GAP-04+05 | DONE — LabelManager+AssigneeManager wired in IssueDetail, repoLabels/collaborators fetched via IPC, 6 new tests, 20 pass | GAP-04+05 |
| 2026-02-12 | GAP-06 | DONE — CreateSpecButton wired in IssueDetail with onCreateSpec prop, 3 new tests, 23 pass | GAP-06 |
| 2026-02-12 | GAP-07 | DONE — CompletenessBreakdown wired in EnrichmentPanel, 2 new tests, 12 pass, lint warnings fixed | GAP-07 |
| 2026-02-12 | GAP-08 | DONE — useDependencies hook wired in GitHubIssues.tsx, deps passed to IssueDetail | GAP-08 |
| 2026-02-12 | GAP-13 | DONE — Triage toggle in IssueListHeader, 5 new tests, aria-pressed + tooltip | GAP-13 |
| 2026-02-13 | GAP-15 | DONE — useLabelSync wired in GitHubIssues.tsx, syncIssueLabel after handleTransition, 3 integration tests | Phase D |
| 2026-02-13 | GAP-11 | DONE — LabelSyncSettingsConnected wrapper, mounted in SectionRouter, 3 tests | Phase D |
| 2026-02-13 | GAP-12 | DONE — ProgressiveTrustSettingsConnected wrapper, mounted in SectionRouter, 3 tests | Phase D |
| 2026-02-13 | GAP-09 | DONE — BulkResultsPanel mounted in GitHubIssues.tsx, wired to mutation store | Phase D |
| 2026-02-13 | GAP-10 | DONE — EnrichmentCommentPreview mounted, enrichmentResult in store/hook, formatEnrichmentComment utility, 8 tests | Phase D |
| 2026-02-13 | GAP-16 | DONE — BatchTriageReview mounted in GitHubIssues.tsx, wired accept/reject/apply callbacks | Phase D |
| 2026-02-13 | GAP-19 | DONE — Ctrl+1/2/3 keyboard shortcuts in useTriageMode, data-triage-panel attrs, 4 new tests | Phase E |
| 2026-02-13 | GAP-35 | DONE — Undo batch: snapshotBeforeApply/undoLastBatch in store, Undo button in BatchTriageReview, 5 tests | Phase E |
| 2026-02-13 | GAP-40 | DONE — Label sync debounce (2000ms) via useRef timer in useLabelSync, 1 new debounce test | Phase E |
| 2026-02-13 | GAP-41 | DONE — Bulk label sync: IPC channel + handler + preload + hook method, 2 new tests | Phase E |
| 2026-02-13 | GAP-42 | DONE — Color swatches in LabelSyncSettings (7 workflow labels with colors), 2 new tests | Phase E |
| 2026-02-13 | GAP-43 | DONE — Write/Preview tabs in CommentForm with ReactMarkdown, i18n keys EN+FR, 8 tests | Phase E |
| 2026-02-13 | GAP-25 | DONE — ARIA listbox on IssueList + role=option + aria-selected + keyboard on IssueListItem, 8 new tests | Phase F |
| 2026-02-13 | GAP-26 | SKIPPED — Not in PRD, transitions already persisted via GAP-30 | N/A |
---
## Recommended Fix Order
**Phase A — Foundation wiring (highest impact, unlocks everything):**
1. GAP-18 (i18n in 5 components — critical rule)
2. GAP-17 (risksEdgeCases section)
3. GAP-24 (ARIA on panels)
4. GAP-38 (ARIA on AI buttons)
5. GAP-01 (useMutations wiring)
6. GAP-21 (store updates after mutations)
7. GAP-02 + GAP-03 (InlineEditor title + body)
8. GAP-04 + GAP-05 (LabelManager + AssigneeManager)
9. GAP-06 (CreateSpecButton)
10. GAP-07 (CompletenessBreakdown)
**Phase B — More wiring:**
11. GAP-08 (useDependencies)
12. GAP-13 (triage toggle in header)
13. GAP-14 (Select All / Deselect All)
14. GAP-20 (clickable dependencies)
15. GAP-22 (clear selection after bulk)
16. GAP-23 (bulk confirmation dialog)
17. GAP-39 (compact card mode)
**Phase C — AI triage gaps:**
18. GAP-29 (enrichment persistence)
19. GAP-30 (ai-triage actor)
20. GAP-31 (split linking comment)
21. GAP-32 (sub-issue enrichment)
22. GAP-28 (progressive trust auto-apply)
23. GAP-37 (error/retry UI)
24. GAP-33 (duplicate detection UX)
25. GAP-34 (batch confirmation)
26. GAP-36 (trust level UI)
**Phase D — Settings + remaining wiring:**
27. GAP-15 (useLabelSync)
28. GAP-11 (LabelSyncSettings in settings)
29. GAP-12 (ProgressiveTrustSettings in settings)
30. GAP-09 (BulkResultsPanel)
31. GAP-10 (EnrichmentCommentPreview)
32. GAP-16 (BatchTriageReview)
**Phase E — Polish (nice-to-have):**
33. GAP-19 (keyboard shortcuts)
34. GAP-35 (undo batch)
35. GAP-40 (label sync debounce)
36. GAP-41 (bulk label sync)
37. GAP-42 (color preview)
38. GAP-43 (markdown preview)
**Phase F — Low priority:**
39. GAP-25 (IssueList ARIA listbox — downgraded)
40. GAP-26 (transitions.json retention — not in PRD)
@@ -1,192 +0,0 @@
# Investigation Pipeline Redesign: Two-Phase Execution with Per-Specialist Settings
## Problem
The GitHub Issues investigation pipeline runs all 4 specialist agents (root cause, impact, fix advisor, reproducer) fully in parallel. None of them receive results from the others — they each independently analyze the issue from scratch.
This causes two problems:
1. **Root cause analysis is too shallow** — it finishes quickly without digging deep enough because it uses a hardcoded thinking budget multiplier rather than a user-configurable model and thinking level.
2. **Downstream agents produce weak results** — the fix advisor suggests fixes without knowing the root cause, and the impact assessor estimates blast radius without knowing what's actually broken.
## Solution
### Two-Phase Execution
Split the 4 agents into two sequential phases:
```
Phase 1 (parallel): Root Cause Agent + Reproducer Agent
Phase 2 (parallel): Impact Agent + Fix Advisor Agent
(both receive root cause output in their prompts)
```
Phase 2 agents wait for Phase 1 to complete, then receive the root cause structured output injected into their prompts. This gives them concrete code locations, evidence, and confidence levels to work with.
The Reproducer Agent runs alongside root cause in Phase 1 because reproduction steps and test coverage assessment are independent of root cause findings.
### Per-Specialist Agent Settings
Replace the single `featureModels.githubIssues` / `featureThinking.githubIssues` setting with per-specialist configuration, following the same pattern as the task pipeline's per-phase config.
New types:
```typescript
interface InvestigationModelConfig {
rootCause: ModelTypeShort;
impact: ModelTypeShort;
fixAdvisor: ModelTypeShort;
reproducer: ModelTypeShort;
}
interface InvestigationThinkingConfig {
rootCause: ThinkingLevel;
impact: ThinkingLevel;
fixAdvisor: ThinkingLevel;
reproducer: ThinkingLevel;
}
```
Defaults:
| Specialist | Model | Thinking |
|---|---|---|
| Root Cause Agent | opus | high |
| Impact Agent | sonnet | medium |
| Fix Advisor Agent | sonnet | medium |
| Reproducer Agent | sonnet | low |
No hardcoded thinking budget multipliers or max turn limits. Each agent gets its configured model and thinking level, and is free to work within those parameters.
### Settings UI
In App Settings > General > Feature Model Configuration, the single "GitHub Issues" row is replaced with 4 specialist rows under the "GitHub Issues" heading:
```
GitHub Issues Issue investigation agents
Root Cause Agent [Opus ▾] [High ▾]
Impact Agent [Sonnet ▾] [Medium ▾]
Fix Advisor Agent [Sonnet ▾] [Medium ▾]
Reproducer Agent [Sonnet ▾] [Low ▾]
```
Always visible (no collapsible dropdown). Same visual treatment as other feature model rows but with indented sub-rows.
### Root Cause Prompt Enhancement
Add depth requirements to `investigation_root_cause.md`:
- Must trace at least 3 levels deep in the call chain before concluding
- Must explore at least 2 competing hypotheses before settling on a root cause
- Must not conclude with medium/low confidence if unexplored code paths remain
- If the issue mentions UI behavior, trace from React component through store, IPC, and backend
- If likely cause is found early, keep investigating to verify
### Context Injection for Phase 2
After Phase 1, the root cause structured output is serialized and appended to Phase 2 agent prompts:
```python
if root_cause_result:
prompt += f"""
## Root Cause Analysis (from prior investigation)
{root_cause_result.identified_root_cause}
**Code paths:** {root_cause_result.code_paths}
**Confidence:** {root_cause_result.confidence}
**Evidence:** {root_cause_result.evidence}
Use this root cause analysis to inform your assessment. Do NOT re-investigate
the root cause — focus on your specialty using these findings as ground truth.
"""
```
### Progress Reporting
Two-phase progress:
| Progress | Event |
|---|---|
| 10% | Starting investigation |
| 20% | Launching Phase 1 (Root Cause Agent + Reproducer Agent) |
| 35% | Reproducer Agent complete |
| 50% | Root Cause Agent complete |
| 55% | Launching Phase 2 with root cause context |
| 65% | First Phase 2 agent complete |
| 80% | Second Phase 2 agent complete |
| 100% | Report built |
Frontend needs no structural changes — it already tracks per-agent events independently. Phase 2 agent `agent_started` events simply arrive later.
## Files Changed
### Frontend
| File | Change |
|---|---|
| `src/shared/types/settings.ts` | Add `InvestigationModelConfig`, `InvestigationThinkingConfig`, add fields to `AppSettings` |
| `src/shared/constants/models.ts` | Add defaults, specialist keys, labels |
| `src/renderer/components/settings/GeneralSettings.tsx` | Replace single githubIssues row with 4 specialist rows |
| `src/main/ipc-handlers/github/investigation-handlers.ts` | `getGitHubIssuesSettings()` reads per-specialist config, passes as `--specialist-config` JSON CLI arg |
| `src/shared/i18n/locales/en/settings.json` | Add specialist label keys |
| `src/shared/i18n/locales/fr/settings.json` | Add specialist label keys |
### Backend
| File | Change |
|---|---|
| `runners/github/runner.py` | Add `--specialist-config` argparse, parse JSON, pass to config |
| `runners/github/services/issue_investigation_orchestrator.py` | Two-phase execution, per-specialist model/thinking, root cause context injection |
| `runners/github/services/parallel_agent_base.py` | Remove `thinking_budget_multiplier` from `SpecialistConfig` |
| `prompts/github/investigation_root_cause.md` | Add depth requirements section |
| `prompts/github/investigation_impact.md` | Add instruction to leverage root cause context |
| `prompts/github/investigation_fix_advice.md` | Add instruction to leverage root cause context |
## Code Removed
| What | Where | Why |
|---|---|---|
| `thinking_budget_multiplier` field | `SpecialistConfig` in `parallel_agent_base.py` | Replaced by per-specialist thinking level |
| `_effective_budget` calculation | `_make_specialist_factory()` in orchestrator | No longer needed |
| Single `model` param | `_run_investigation_specialists()` | Replaced by per-specialist config |
| Single `thinking_budget` param | `_run_investigation_specialists()` | Replaced by per-specialist config |
| ~~`featureModels.githubIssues`~~ | ~~`FeatureModelConfig`~~ | **NOT removed** — still used by triage/enrich/split handlers. `investigationModels` is additive. |
| ~~`featureThinking.githubIssues`~~ | ~~`FeatureThinkingConfig`~~ | **NOT removed** — still used by triage handlers. `investigationThinking` is additive. |
## Unchanged (No Breakage)
- `InvestigationReport` and all Pydantic schemas
- `_build_report()`, `_parse_specialist_result()`, `_generate_summary()`
- Frontend investigation store, IPC channels, progress/complete/error flow
- `InvestigationSettings.tsx` (project-level settings)
- Resume support (`--resume-sessions`)
- Log collection, `agent_started`/`agent_done` events
- `transformPythonReport()` result parsing
- `_run_parallel_specialists()` base class method (reused twice, once per phase)
## Settings Flow
```
GeneralSettings UI (4 specialist rows)
settings-store → IPC SETTINGS_SAVE → settings.json
↓ (on investigation start)
investigation-handlers.ts reads investigationModels + investigationThinking
CLI: --specialist-config '{"root_cause":{"model":"opus","thinking":"high"},...}'
runner.py parses JSON → GitHubRunnerConfig.specialist_config
IssueInvestigationOrchestrator.investigate()
Phase 1: create_client(model=opus, thinking=high) ← Root Cause Agent
create_client(model=sonnet, thinking=low) ← Reproducer Agent
↓ (root cause result)
Phase 2: create_client(model=sonnet, thinking=medium) ← Impact Agent (+ root cause context)
create_client(model=sonnet, thinking=medium) ← Fix Advisor Agent (+ root cause context)
```
## Migration
No migration needed. `featureModels.githubIssues` and `featureThinking.githubIssues` remain in place for triage/enrich/split handlers. The new `investigationModels`/`investigationThinking` keys are additive — they read with sensible defaults if the new keys aren't present in settings.
@@ -1,853 +0,0 @@
# Investigation Pipeline Redesign Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Restructure the investigation pipeline from 4 parallel agents to a two-phase pipeline where root cause runs first, and downstream agents receive its output.
**Architecture:** Phase 1 runs root_cause + reproducer in parallel. Phase 2 runs impact + fix_advisor in parallel with root cause results injected into their prompts. Per-specialist model/thinking settings replace the single `githubIssues` feature config for investigations.
**Tech Stack:** TypeScript (Electron/React), Python (asyncio, Claude Agent SDK), Zustand, Tailwind CSS, react-i18next
**Design doc:** `docs/plans/2026-02-14-investigation-pipeline-redesign-design.md`
**Correction from design doc:** `featureModels.githubIssues` stays in `FeatureModelConfig` because triage/enrich/split handlers also use it. The new `investigationModels`/`investigationThinking` fields are _additions_ to `AppSettings`, not replacements.
---
### Task 1: Add TypeScript types for per-specialist investigation config
**Files:**
- Modify: `apps/frontend/src/shared/types/settings.ts:182-201` (after `FeatureThinkingConfig`)
**Step 1: Add the new interfaces and AppSettings fields**
Add after `FeatureThinkingConfig` (line 201):
```typescript
// Per-specialist investigation model configuration
export interface InvestigationModelConfig {
rootCause: ModelTypeShort;
impact: ModelTypeShort;
fixAdvisor: ModelTypeShort;
reproducer: ModelTypeShort;
}
// Per-specialist investigation thinking level configuration
export interface InvestigationThinkingConfig {
rootCause: ThinkingLevel;
impact: ThinkingLevel;
fixAdvisor: ThinkingLevel;
reproducer: ThinkingLevel;
}
```
Add to `AppSettings` interface (after `featureThinking` on line 265):
```typescript
// Per-specialist investigation agent configuration
investigationModels?: InvestigationModelConfig;
investigationThinking?: InvestigationThinkingConfig;
```
**Step 2: Run typecheck**
Run: `cd apps/frontend && npm run typecheck`
Expected: PASS (new types are optional, nothing references them yet)
**Step 3: Commit**
```bash
git add apps/frontend/src/shared/types/settings.ts
git commit -m "feat(investigation): add per-specialist model/thinking type definitions"
```
---
### Task 2: Add constants and defaults for investigation specialists
**Files:**
- Modify: `apps/frontend/src/shared/constants/models.ts:141-151` (after `DEFAULT_FEATURE_THINKING`)
**Step 1: Add defaults and labels**
Add after `DEFAULT_FEATURE_THINKING` (line 141), before `FEATURE_LABELS`:
```typescript
// ============================================
// Investigation Specialist Settings
// ============================================
// Keys for iterating over investigation specialist config
export const INVESTIGATION_SPECIALIST_KEYS: readonly (keyof import('../types/settings').InvestigationModelConfig)[] = [
'rootCause', 'impact', 'fixAdvisor', 'reproducer'
] as const;
// Default per-specialist model configuration
export const DEFAULT_INVESTIGATION_MODELS: import('../types/settings').InvestigationModelConfig = {
rootCause: 'opus',
impact: 'sonnet',
fixAdvisor: 'sonnet',
reproducer: 'sonnet'
};
// Default per-specialist thinking configuration
export const DEFAULT_INVESTIGATION_THINKING: import('../types/settings').InvestigationThinkingConfig = {
rootCause: 'high',
impact: 'medium',
fixAdvisor: 'medium',
reproducer: 'low'
};
// Labels for investigation specialist UI
export const INVESTIGATION_SPECIALIST_LABELS: Record<
keyof import('../types/settings').InvestigationModelConfig,
{ label: string; description: string }
> = {
rootCause: { label: 'Root Cause Agent', description: 'Traces the bug to its source code' },
impact: { label: 'Impact Agent', description: 'Determines blast radius and severity' },
fixAdvisor: { label: 'Fix Advisor Agent', description: 'Suggests concrete fix approaches' },
reproducer: { label: 'Reproducer Agent', description: 'Checks reproducibility and test coverage' }
};
```
Also update the models.ts import line (line 6) to include the new type:
```typescript
import type { AgentProfile, PhaseModelConfig, FeatureModelConfig, FeatureThinkingConfig, InvestigationModelConfig } from '../types/settings';
```
**Step 2: Run typecheck**
Run: `cd apps/frontend && npm run typecheck`
Expected: PASS
**Step 3: Commit**
```bash
git add apps/frontend/src/shared/constants/models.ts
git commit -m "feat(investigation): add per-specialist defaults and labels"
```
---
### Task 3: Update GeneralSettings UI to show 4 specialist rows
**Files:**
- Modify: `apps/frontend/src/renderer/components/settings/GeneralSettings.tsx:9-14` (imports), `177-239` (feature model loop)
**Step 1: Update imports**
Add to the constants import (line 9-15):
```typescript
import {
AVAILABLE_MODELS,
THINKING_LEVELS,
DEFAULT_FEATURE_MODELS,
DEFAULT_FEATURE_THINKING,
FEATURE_LABELS,
DEFAULT_INVESTIGATION_MODELS,
DEFAULT_INVESTIGATION_THINKING,
INVESTIGATION_SPECIALIST_KEYS,
INVESTIGATION_SPECIALIST_LABELS
} from '../../../shared/constants';
```
Add `InvestigationModelConfig` to the types import:
```typescript
import type {
AppSettings,
FeatureModelConfig,
InvestigationModelConfig,
ModelTypeShort,
ThinkingLevel,
ToolDetectionResult
} from '../../../shared/types';
```
**Step 2: Replace the FEATURE_LABELS loop**
Replace the loop at line 177-239 with code that:
1. Iterates over `FEATURE_LABELS` but SKIPS `githubIssues` (that becomes the specialist section)
2. After skipping githubIssues in the loop, renders a "GitHub Issues" header with 4 indented specialist sub-rows
```tsx
{/* Standard feature rows (skip githubIssues — shown as specialist section below) */}
{(Object.keys(FEATURE_LABELS) as Array<keyof FeatureModelConfig>)
.filter((feature) => feature !== 'githubIssues')
.map((feature) => {
const featureModels = settings.featureModels || DEFAULT_FEATURE_MODELS;
const featureThinking = settings.featureThinking || DEFAULT_FEATURE_THINKING;
return (
<div key={feature} className="space-y-2">
<div className="flex items-center justify-between">
<Label className="text-sm font-medium text-foreground">
{FEATURE_LABELS[feature].label}
</Label>
<span className="text-xs text-muted-foreground">
{FEATURE_LABELS[feature].description}
</span>
</div>
<div className="grid grid-cols-2 gap-3 max-w-md">
<div className="space-y-1">
<Label className="text-xs text-muted-foreground">{t('general.model')}</Label>
<Select
value={featureModels[feature]}
onValueChange={(value) => {
const newFeatureModels = { ...featureModels, [feature]: value as ModelTypeShort };
onSettingsChange({ ...settings, featureModels: newFeatureModels });
}}
>
<SelectTrigger className="h-9">
<SelectValue />
</SelectTrigger>
<SelectContent>
{AVAILABLE_MODELS.map((m) => (
<SelectItem key={m.value} value={m.value}>
{m.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="space-y-1">
<Label className="text-xs text-muted-foreground">{t('general.thinkingLevel')}</Label>
<Select
value={featureThinking[feature]}
onValueChange={(value) => {
const newFeatureThinking = { ...featureThinking, [feature]: value as ThinkingLevel };
onSettingsChange({ ...settings, featureThinking: newFeatureThinking });
}}
>
<SelectTrigger className="h-9">
<SelectValue />
</SelectTrigger>
<SelectContent>
{THINKING_LEVELS.map((level) => (
<SelectItem key={level.value} value={level.value}>
{level.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
</div>
);
})}
{/* GitHub Issues — per-specialist investigation agent config */}
<div className="space-y-3">
<div className="flex items-center justify-between">
<Label className="text-sm font-medium text-foreground">
{t('general.investigationAgents.title')}
</Label>
<span className="text-xs text-muted-foreground">
{t('general.investigationAgents.description')}
</span>
</div>
{INVESTIGATION_SPECIALIST_KEYS.map((specialist) => {
const invModels = settings.investigationModels || DEFAULT_INVESTIGATION_MODELS;
const invThinking = settings.investigationThinking || DEFAULT_INVESTIGATION_THINKING;
return (
<div key={specialist} className="space-y-1 pl-4 border-l-2 border-border">
<div className="flex items-center justify-between">
<Label className="text-xs font-medium text-foreground">
{INVESTIGATION_SPECIALIST_LABELS[specialist].label}
</Label>
<span className="text-xs text-muted-foreground">
{INVESTIGATION_SPECIALIST_LABELS[specialist].description}
</span>
</div>
<div className="grid grid-cols-2 gap-3 max-w-md">
<div className="space-y-1">
<Label className="text-xs text-muted-foreground">{t('general.model')}</Label>
<Select
value={invModels[specialist]}
onValueChange={(value) => {
const newInvModels = { ...invModels, [specialist]: value as ModelTypeShort };
onSettingsChange({ ...settings, investigationModels: newInvModels });
}}
>
<SelectTrigger className="h-9">
<SelectValue />
</SelectTrigger>
<SelectContent>
{AVAILABLE_MODELS.map((m) => (
<SelectItem key={m.value} value={m.value}>
{m.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="space-y-1">
<Label className="text-xs text-muted-foreground">{t('general.thinkingLevel')}</Label>
<Select
value={invThinking[specialist]}
onValueChange={(value) => {
const newInvThinking = { ...invThinking, [specialist]: value as ThinkingLevel };
onSettingsChange({ ...settings, investigationThinking: newInvThinking });
}}
>
<SelectTrigger className="h-9">
<SelectValue />
</SelectTrigger>
<SelectContent>
{THINKING_LEVELS.map((level) => (
<SelectItem key={level.value} value={level.value}>
{level.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
</div>
);
})}
</div>
```
**Step 3: Run typecheck**
Run: `cd apps/frontend && npm run typecheck`
Expected: PASS
**Step 4: Commit**
```bash
git add apps/frontend/src/renderer/components/settings/GeneralSettings.tsx
git commit -m "feat(investigation): show per-specialist model/thinking rows in settings UI"
```
---
### Task 4: Add i18n keys for investigation specialist labels
**Files:**
- Modify: `apps/frontend/src/shared/i18n/locales/en/settings.json`
- Modify: `apps/frontend/src/shared/i18n/locales/fr/settings.json`
**Step 1: Add English keys**
Add under the `"general"` section (near `featureModelSettings`):
```json
"investigationAgents": {
"title": "GitHub Issues",
"description": "Issue investigation agents"
}
```
**Step 2: Add French keys**
Add same structure with French translations:
```json
"investigationAgents": {
"title": "GitHub Issues",
"description": "Agents d'investigation des issues"
}
```
**Step 3: Commit**
```bash
git add apps/frontend/src/shared/i18n/locales/en/settings.json apps/frontend/src/shared/i18n/locales/fr/settings.json
git commit -m "feat(i18n): add investigation specialist settings labels"
```
---
### Task 5: Update investigation-handlers.ts to read per-specialist config
**Files:**
- Modify: `apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts:604-612` (`getGitHubIssuesSettings`)
**Step 1: Add new function to read per-specialist config**
Add alongside the existing `getGitHubIssuesSettings()` function (which stays for triage):
```typescript
/**
* Get per-specialist investigation model and thinking settings from app settings.
* Returns a JSON-serializable config dict for --specialist-config CLI arg.
*/
function getInvestigationSpecialistConfig(): Record<string, { model: string; thinking: string }> {
const rawSettings = readSettingsFile() as Partial<AppSettings> | undefined;
const invModels = rawSettings?.investigationModels ?? DEFAULT_INVESTIGATION_MODELS;
const invThinking = rawSettings?.investigationThinking ?? DEFAULT_INVESTIGATION_THINKING;
return {
root_cause: {
model: MODEL_ID_MAP[invModels.rootCause] ?? MODEL_ID_MAP['opus'],
thinking: invThinking.rootCause ?? 'high'
},
impact: {
model: MODEL_ID_MAP[invModels.impact] ?? MODEL_ID_MAP['sonnet'],
thinking: invThinking.impact ?? 'medium'
},
fix_advisor: {
model: MODEL_ID_MAP[invModels.fixAdvisor] ?? MODEL_ID_MAP['sonnet'],
thinking: invThinking.fixAdvisor ?? 'medium'
},
reproducer: {
model: MODEL_ID_MAP[invModels.reproducer] ?? MODEL_ID_MAP['sonnet'],
thinking: invThinking.reproducer ?? 'low'
}
};
}
```
Add imports at the top of the file for `DEFAULT_INVESTIGATION_MODELS` and `DEFAULT_INVESTIGATION_THINKING`.
**Step 2: Update `runInvestigation()` to pass specialist config**
Find where `buildRunnerArgs` is called for investigation (around line 1044-1053). Replace the single `{ model, thinkingLevel }` with the specialist config:
```typescript
const specialistConfig = getInvestigationSpecialistConfig();
const args = [
...buildRunnerArgs(
getRunnerPath(backendPath),
project.path,
'investigate',
[String(issueNumber)],
// No model/thinkingLevel here — per-specialist config replaces it
),
'--specialist-config', JSON.stringify(specialistConfig),
...resumeSessionsArg,
];
```
Remove the `const { model, thinkingLevel } = getGitHubIssuesSettings();` call from the investigation path (keep it for triage).
**Step 3: Run typecheck**
Run: `cd apps/frontend && npm run typecheck`
Expected: PASS
**Step 4: Commit**
```bash
git add apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts
git commit -m "feat(investigation): pass per-specialist config as CLI arg"
```
---
### Task 6: Update Python runner to accept --specialist-config
**Files:**
- Modify: `apps/backend/runners/github/runner.py:838-850` (investigate parser), `340-376` (cmd_investigate)
- Modify: `apps/backend/runners/github/models.py:995-1006` (GitHubRunnerConfig)
**Step 1: Add specialist_config field to GitHubRunnerConfig**
Add after `fast_mode` field (line 1006):
```python
# Per-specialist investigation config (overrides model/thinking_level for each specialist)
# Dict mapping specialist name → {"model": str, "thinking": str}
specialist_config: dict[str, dict[str, str]] | None = None
```
**Step 2: Add argparse argument**
Add to investigate_parser (after line 850):
```python
investigate_parser.add_argument(
"--specialist-config",
type=str,
default=None,
help="JSON dict of specialist configs: {name: {model, thinking}}",
)
```
**Step 3: Update cmd_investigate and get_config**
In `get_config()` (line 180-190), add:
```python
specialist_config = None
if hasattr(args, "specialist_config") and args.specialist_config:
specialist_config = json.loads(args.specialist_config)
```
Pass it to `GitHubRunnerConfig`:
```python
return GitHubRunnerConfig(
...
specialist_config=specialist_config,
)
```
**Step 4: Run backend tests**
Run: `cd "D:\Koding\Autoclaude" && python -m pytest tests/test_github_investigation.py -x -v`
Expected: PASS (existing tests don't use specialist_config)
**Step 5: Commit**
```bash
git add apps/backend/runners/github/runner.py apps/backend/runners/github/models.py
git commit -m "feat(investigation): accept --specialist-config CLI arg in runner"
```
---
### Task 7: Remove thinking_budget_multiplier from SpecialistConfig
**Files:**
- Modify: `apps/backend/runners/github/services/parallel_agent_base.py:85` (remove field)
- Modify: `apps/backend/runners/github/services/issue_investigation_orchestrator.py:98` (remove from root_cause config)
- Modify: `tests/test_github_investigation.py:599` (remove from test mock)
**Step 1: Remove from SpecialistConfig dataclass**
In `parallel_agent_base.py` line 85, remove:
```python
thinking_budget_multiplier: float = 1.0
```
**Step 2: Remove from root_cause specialist**
In `issue_investigation_orchestrator.py` line 98, remove:
```python
thinking_budget_multiplier=1.5,
```
**Step 3: Remove _effective_budget calculation from factory**
In `issue_investigation_orchestrator.py` lines 366-371, remove:
```python
# Apply per-specialist thinking multiplier
_effective_budget = (
int(thinking_budget * cfg.thinking_budget_multiplier)
if thinking_budget
else None
)
```
And update the reference in `_run_specialist_session` call to use the per-specialist thinking budget (this will be done in Task 8).
**Step 4: Fix test mock**
In `tests/test_github_investigation.py` line 599, remove `thinking_budget_multiplier` field from any test SpecialistConfig mocks.
**Step 5: Run backend tests**
Run: `cd "D:\Koding\Autoclaude" && python -m pytest tests/test_github_investigation.py -x -v`
Expected: PASS
**Step 6: Commit**
```bash
git add apps/backend/runners/github/services/parallel_agent_base.py apps/backend/runners/github/services/issue_investigation_orchestrator.py tests/test_github_investigation.py
git commit -m "refactor(investigation): remove thinking_budget_multiplier from SpecialistConfig"
```
---
### Task 8: Implement two-phase execution in orchestrator
This is the core change. Replace the single `_run_investigation_specialists()` gather with two phases.
**Files:**
- Modify: `apps/backend/runners/github/services/issue_investigation_orchestrator.py:144-508`
**Step 1: Update `investigate()` to use specialist_config**
Replace the model/thinking resolution at lines 194-197:
```python
# Resolve per-specialist config
specialist_config = self.config.specialist_config or {}
# Fallback: use single model/thinking_level for all specialists
fallback_model_shorthand = self.config.model or "sonnet"
fallback_model = resolve_model_id(fallback_model_shorthand)
fallback_thinking_level = self.config.thinking_level or "medium"
fallback_thinking_budget = get_thinking_budget(fallback_thinking_level)
```
Update the call to `_run_investigation_specialists()` to pass `specialist_config` instead of single model/budget.
**Step 2: Rewrite `_run_investigation_specialists()` as two phases**
Key changes:
1. Split `INVESTIGATION_SPECIALISTS` into `PHASE_1_SPECIALISTS` (root_cause, reproducer) and `PHASE_2_SPECIALISTS` (impact, fix_advisor)
2. Phase 1: gather root_cause + reproducer
3. Parse root_cause structured output
4. Phase 2: build prompts with root cause context, gather impact + fix_advisor
5. Combine results
```python
# Phase groupings
PHASE_1_NAMES = {"root_cause", "reproducer"}
PHASE_2_NAMES = {"impact", "fix_advisor"}
async def _run_investigation_specialists(
self,
issue_context: str,
project_root: Path,
specialist_config: dict[str, dict[str, str]],
fallback_model: str,
fallback_thinking_budget: int | None,
issue_number: int | None = None,
resume_sessions: dict[str, str] | None = None,
) -> dict[str, dict[str, Any]]:
"""Run investigation specialists in two phases.
Phase 1 (parallel): root_cause + reproducer
Phase 2 (parallel): impact + fix_advisor (with root cause context)
"""
_agents_done = 0
_agents_lock = asyncio.Lock()
total_agents = len(INVESTIGATION_SPECIALISTS)
phase_1_specs = [s for s in INVESTIGATION_SPECIALISTS if s.name in self.PHASE_1_NAMES]
phase_2_specs = [s for s in INVESTIGATION_SPECIALISTS if s.name in self.PHASE_2_NAMES]
def _resolve_specialist(cfg_name: str):
"""Resolve model and thinking budget for a specialist."""
sc = specialist_config.get(cfg_name, {})
model = sc.get("model", fallback_model)
thinking_level = sc.get("thinking", self.config.thinking_level or "medium")
budget = get_thinking_budget(thinking_level)
return model, budget
# ... (factory and lifecycle wrapper similar to current but using _resolve_specialist)
# === Phase 1 ===
self._report_progress("investigating", 20, "Phase 1: Root Cause Agent + Reproducer Agent...", issue_number=issue_number)
phase_1_results = await self._run_parallel_specialists(...)
# Parse root cause result for context injection
root_cause_parsed = self._parse_specialist_result("root_cause", phase_1_result_map, RootCauseAnalysis)
# === Phase 2 ===
self._report_progress("investigating", 55, "Phase 2: Impact Agent + Fix Advisor Agent (with root cause context)...", issue_number=issue_number)
# Build phase 2 prompts with root cause context injected
phase_2_results = await self._run_parallel_specialists(...)
# Combine all results
return {**phase_1_result_map, **phase_2_result_map}
```
**Step 3: Add `_build_root_cause_context()` method**
```python
def _build_root_cause_context(self, root_cause: RootCauseAnalysis | None) -> str:
"""Build root cause context string for injection into Phase 2 prompts."""
if not root_cause:
return ""
code_paths_str = ""
if root_cause.code_paths:
code_paths_str = "\n".join(f"- {p}" for p in root_cause.code_paths)
return f"""
## Root Cause Analysis (from prior investigation phase)
**Root Cause:** {root_cause.identified_root_cause}
**Confidence:** {root_cause.confidence}
**Code Paths:**
{code_paths_str}
**Evidence:** {root_cause.evidence}
**Likely Already Fixed:** {root_cause.likely_already_fixed}
Use this root cause analysis to inform your assessment. Do NOT re-investigate
the root cause — focus on your specialty using these findings as ground truth.
"""
```
**Step 4: Update `_build_specialist_prompt()` to accept root cause context**
Add optional `root_cause_context: str = ""` parameter:
```python
def _build_specialist_prompt(
self,
config: SpecialistConfig,
issue_context: str,
project_root: Path,
root_cause_context: str = "",
) -> str:
# ... existing code ...
return base_prompt + working_dir_section + issue_context + root_cause_context
```
**Step 5: Run backend tests**
Run: `cd "D:\Koding\Autoclaude" && python -m pytest tests/test_github_investigation.py -x -v`
Expected: PASS (may need test updates for new signature)
**Step 6: Commit**
```bash
git add apps/backend/runners/github/services/issue_investigation_orchestrator.py
git commit -m "feat(investigation): implement two-phase execution with root cause context injection"
```
---
### Task 9: Enhance root cause agent prompt
**Files:**
- Modify: `apps/backend/prompts/github/investigation_root_cause.md`
**Step 1: Add depth requirements section**
Add before the `## Output` section:
```markdown
## Depth Requirements
- You MUST trace at least 3 levels deep in the call chain (entry point → intermediate → root cause location) before concluding
- You MUST explore at least 2 competing hypotheses before settling on a root cause — read both code paths and explain why one is more likely
- Do NOT conclude with "medium" or "low" confidence if you still have unexplored code paths you could Read or Grep
- If the issue mentions a UI behavior, trace it from the React component through the store, IPC handler, and into the backend
- If you find the likely cause early, keep investigating to VERIFY it — read callers, check edge cases, look for related patterns
- Use your full tool budget. Read more files, run more greps. Thoroughness is more valuable than speed for root cause analysis
```
**Step 2: Commit**
```bash
git add apps/backend/prompts/github/investigation_root_cause.md
git commit -m "feat(investigation): add depth requirements to root cause agent prompt"
```
---
### Task 10: Update Phase 2 agent prompts to use root cause context
**Files:**
- Modify: `apps/backend/prompts/github/investigation_impact.md`
- Modify: `apps/backend/prompts/github/investigation_fix_advice.md`
**Step 1: Add context usage instruction to impact prompt**
Add after the "## Your Mission" section in `investigation_impact.md`:
```markdown
## Using Root Cause Context
If a "Root Cause Analysis" section is provided below the issue context, use it as the starting point for your impact assessment. The root cause agent has already identified the problematic code — your job is to trace outward from those code paths to determine blast radius and severity.
This means you can skip Steps 1-2 (identifying affected code) when root cause context is available, and instead focus on mapping dependencies outward from the identified code paths.
```
**Step 2: Add context usage instruction to fix advice prompt**
Add after the "## Your Mission" section in `investigation_fix_advice.md`:
```markdown
## Using Root Cause Context
If a "Root Cause Analysis" section is provided below the issue context, use it as the foundation for your fix approaches. The root cause agent has already identified the exact code location and cause — your job is to design fix strategies that address that specific root cause.
This means you can skip Step 1 (understanding the problem space) when root cause context is available, and instead focus on designing fixes that target the identified code paths.
```
**Step 3: Commit**
```bash
git add apps/backend/prompts/github/investigation_impact.md apps/backend/prompts/github/investigation_fix_advice.md
git commit -m "feat(investigation): update Phase 2 agent prompts to leverage root cause context"
```
---
### Task 11: Update progress reporting for two phases
**Files:**
- Modify: `apps/backend/runners/github/services/issue_investigation_orchestrator.py` (progress calls in Phase 1 and Phase 2)
**Step 1: Update progress percentages**
In the two-phase execution from Task 8, ensure progress reporting uses:
- 10%: Starting investigation
- 20%: Launching Phase 1 (Root Cause Agent + Reproducer Agent)
- 35%: First Phase 1 agent complete
- 50%: Phase 1 complete
- 55%: Launching Phase 2 with root cause context
- 65%: First Phase 2 agent complete
- 80%: Phase 2 complete
- 100%: Report built
The `_agent_lifecycle_wrapper` needs different progress math for each phase:
- Phase 1: 20 + (agent_index * 15) = 35, 50
- Phase 2: 55 + (agent_index * 15) = 65 (first), 80 (second... but wait, with only 2 agents per phase we want: 55 → 65 → 80)
Actually simplify: just pass the base offset into the wrapper.
**Step 2: Run backend tests**
Run: `cd "D:\Koding\Autoclaude" && python -m pytest tests/test_github_investigation.py -x -v`
Expected: PASS
**Step 3: Commit**
```bash
git add apps/backend/runners/github/services/issue_investigation_orchestrator.py
git commit -m "feat(investigation): update progress reporting for two-phase execution"
```
---
### Task 12: Run full test suite and typecheck
**Step 1: Run frontend typecheck**
Run: `cd apps/frontend && npm run typecheck`
Expected: PASS
**Step 2: Run backend tests**
Run: `cd "D:\Koding\Autoclaude" && python -m pytest tests/ -x -v`
Expected: PASS
**Step 3: Run frontend lint**
Run: `cd apps/frontend && npm run lint`
Expected: PASS (or fix any lint issues)
**Step 4: Commit any fixes**
```bash
git commit -m "fix(investigation): address lint and test issues from pipeline redesign"
```
---
### Task 13: Update design doc with correction
**Files:**
- Modify: `docs/plans/2026-02-14-investigation-pipeline-redesign-design.md`
**Step 1: Fix the "Code Removed" section**
Remove the rows about `featureModels.githubIssues` and `featureThinking.githubIssues` since those stay for triage/enrich/split. Add a note that `investigationModels`/`investigationThinking` are additions, not replacements.
**Step 2: Commit**
```bash
git add -f docs/plans/2026-02-14-investigation-pipeline-redesign-design.md
git commit -m "docs: correct design doc — githubIssues stays for triage, investigation config is additive"
```
@@ -1,246 +0,0 @@
# Investigation SDK Enhancements Design
Date: 2026-02-14
Branch: feat/issues
Approach: Incremental SDK integration (Approach A)
## Overview
Enhance the GitHub issue investigation system by layering Claude Agent SDK features into the existing `ParallelAgentOrchestrator` architecture. Each enhancement is independent and shippable on its own.
Goals:
- Better investigation quality (deeper root cause analysis, thinking visibility)
- Cost and scope control (max_turns, model/thinking from settings)
- Richer progress UX (structured events via hooks, replace stdout parsing)
- New capabilities (controlled Bash access, resumable sessions)
## 1. Controlled Bash Access via PreToolUse Hooks
**Problem:** Investigation specialists only have Read/Grep/Glob. They can't run tests, check git history, or inspect dependencies.
**Solution:** Add `"Bash"` to specialist tool lists, gated by a `PreToolUse` hook with an investigation-specific allowlist.
### Allowlisted commands
- `git log`, `git show`, `git blame`, `git diff`, `git status` -- code history
- `pytest`, `npm test`, `vitest`, `cargo test` -- test runners (read-only validation)
- `pip list`, `npm ls`, `node -v`, `python --version` -- dependency inspection
- `ls`, `find`, `wc` -- filesystem exploration beyond Read/Grep
### Blocked commands
- Any write operation: `git commit`, `git push`, `rm`, `mv`, `cp`, `echo >`, editors
- Package install: `pip install`, `npm install`, `apt`, `brew`
- Shell control: `sudo`, `su`, `chmod`, `chown`
### Implementation
New file: `apps/backend/runners/github/services/investigation_hooks.py`
```python
INVESTIGATION_BASH_ALLOWLIST = [
"git log", "git show", "git blame", "git diff", "git status",
"pytest", "npm test", "vitest", "cargo test",
"pip list", "npm ls", "node -v", "python --version",
"ls", "find", "wc",
]
async def investigation_bash_guard(input_data, tool_use_id, context):
"""PreToolUse hook: validate Bash commands for investigation safety."""
command = input_data.get("tool_input", {}).get("command", "")
if not any(command.strip().startswith(allowed) for allowed in INVESTIGATION_BASH_ALLOWLIST):
return {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": f"Command not allowed during investigation: {command[:100]}"
}
}
return {}
```
In `parallel_agent_base.py._run_specialist_session()`:
```python
if "Bash" in config.tools:
client_kwargs["hooks"] = {
"PreToolUse": [HookMatcher(matcher="Bash", hooks=[investigation_bash_guard])]
}
```
### Files affected
- `apps/backend/runners/github/services/investigation_hooks.py` (new)
- `apps/backend/runners/github/services/issue_investigation_orchestrator.py` (add Bash to tools)
- `apps/backend/runners/github/services/parallel_agent_base.py` (wire hooks)
## 2. Cost & Scope Controls
**Problem:** No max_turns or budget limits. Specialists run until output or the 500-message circuit breaker.
### max_turns per specialist
Add `max_turns` field to `SpecialistConfig`:
| Specialist | max_turns | Rationale |
|---|---|---|
| root_cause | 40 | Deep: search, read, follow call chains |
| impact | 25 | Moderate: component scanning |
| fix_advisor | 30 | Read patterns and examples |
| reproducer | 35 | Find tests, check coverage |
Passed through `_run_specialist_session()` to `process_sdk_stream(max_messages=...)`.
### Model/thinking from settings
The existing `featureModels.githubIssues` and `featureThinking.githubIssues` settings are already read by `getGitHubIssuesSettings()` in the frontend and passed to the subprocess. The backend uses `resolve_model_id()` and `get_thinking_budget()`.
Gap: ensure the settings UI exposes the `githubIssues` entry in feature model/thinking dropdowns (if not already present).
### Files affected
- `apps/backend/runners/github/services/parallel_agent_base.py` (SpecialistConfig.max_turns)
- `apps/backend/runners/github/services/issue_investigation_orchestrator.py` (set per-specialist values)
- Frontend settings component (wire githubIssues model/thinking if missing)
## 3. Structured Progress via SDK Hooks
**Problem:** Progress flows via stdout prefix parsing (`[Investigation:root_cause] ...`). Fragile regex, no typing, no thinking visibility.
**Solution:** Add SDK hooks that emit structured JSON events to stdout alongside existing text lines. Frontend parses both formats.
### Event protocol
JSON events emitted to stdout (one per line):
```json
{"event":"tool_start","agent":"root_cause","tool":"Read","detail":"Reading auth.py","ts":"2026-02-14T10:30:00Z"}
{"event":"tool_end","agent":"root_cause","tool":"Read","success":true,"ts":"2026-02-14T10:30:01Z"}
{"event":"thinking","agent":"root_cause","chars":4200,"preview":"The issue traces back to...","ts":"2026-02-14T10:30:02Z"}
```
### Hook implementation
In `_run_specialist_session()`, pass callbacks to `process_sdk_stream`:
```python
stream_result = await process_sdk_stream(
client=client,
on_thinking=lambda text: emit_json_event("thinking", config.name, chars=len(text), preview=text[:200]),
on_tool_use=lambda name, tid, inp: emit_json_event("tool_start", config.name, tool=name, detail=_get_tool_detail(name, inp)),
on_tool_result=lambda tid, err, _: emit_json_event("tool_end", config.name, success=not err),
...
)
```
### Frontend changes
- `parseInvestigationLogLine()`: if line starts with `{`, try JSON.parse, map to existing entry types
- `InvestigationLogEntry` type: add optional `toolName`, `thinkingPreview`, `isStructured` fields
- Live log panel: show "Thinking (4,200 chars)..." and tool details
### Files affected
- `apps/backend/runners/github/services/parallel_agent_base.py` (emit functions)
- `apps/backend/runners/github/services/sdk_utils.py` (callbacks already exist, wire them)
- `apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts` (JSON parser)
- `apps/frontend/src/shared/types/` (InvestigationLogEntry extension)
- Frontend log panel component (render enriched entries)
## 4. Resumable Sessions
**Problem:** Interrupted investigations re-run from scratch. Context from partial investigations is lost.
**Solution:** Save SDK session IDs per specialist. On resume, pass `resume=session_id` to recreate the session with prior context.
### Session persistence
After `client.query()`, capture session ID:
```python
session_id = getattr(client, 'session_id', None)
```
Save to `investigation_state.json`:
```json
{
"issue_number": 42,
"status": "investigating",
"sessions": {
"root_cause": "session-abc123",
"impact": "session-def456",
"fix_advisor": null,
"reproducer": null
}
}
```
### Resume flow
1. App restarts, detects interrupted investigation (status = "investigating")
2. Reads session IDs from investigation_state.json
3. Passes session IDs to subprocess via CLI args or env vars
4. Backend passes `resume=session_id` to `create_client()` for specialists with saved sessions
5. Specialists without sessions run fresh
6. If resume fails (session expired, CLI updated), gracefully fall back to fresh run
### Fallback
SDK session resume requires the same Claude Code CLI instance. If resume fails, catch the error and restart from scratch with a log message.
### Files affected
- `apps/backend/runners/github/services/parallel_agent_base.py` (resume_session_id param)
- `apps/backend/runners/github/services/issue_investigation_orchestrator.py` (save/read sessions)
- `apps/backend/runners/github/services/investigation_persistence.py` (session fields)
- `apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts` (pass session IDs)
## 5. Investigation Quality: Extended Thinking
**Problem:** All specialists get the same thinking budget. Root cause analysis benefits most from deeper reasoning.
### Per-specialist thinking multiplier
Add `thinking_budget_multiplier` to `SpecialistConfig`:
| Specialist | Multiplier | Effective budget (medium=4096) |
|---|---|---|
| root_cause | 1.5x | 6144 |
| impact | 1.0x | 4096 |
| fix_advisor | 1.0x | 4096 |
| reproducer | 1.0x | 4096 |
Applied in `_run_investigation_specialists()`:
```python
effective_budget = int(thinking_budget * config.thinking_budget_multiplier)
```
### Thinking preview in UI
The `on_thinking` callback (from Section 3) emits a preview of thinking content. The frontend log panel renders this as a collapsible "Thinking..." entry with the preview text.
### Files affected
- `apps/backend/runners/github/services/parallel_agent_base.py` (SpecialistConfig field)
- `apps/backend/runners/github/services/issue_investigation_orchestrator.py` (set multipliers)
## Out of Scope (Future)
- **MCP servers** (Context7, Puppeteer) for extended tool capabilities per specialist
- **Per-specialist model overrides** (e.g., Haiku for impact, Opus for root cause)
- **File checkpointing** for try-and-verify fix patterns
- **Two-phase investigation** (quick triage then deep-dive on same session)
- **Cross-issue deduplication** via Graphiti memory integration
## Dependency Order
1. **SpecialistConfig extensions** (max_turns, thinking_multiplier) -- no dependencies
2. **Investigation hooks module** -- no dependencies
3. **Bash access** -- depends on (2)
4. **Structured progress events** -- depends on (2), frontend type changes
5. **Resumable sessions** -- depends on persistence changes, frontend CLI arg passing
6. **Settings UI wiring** -- independent frontend task
Items 1-3 can ship together. Item 4 can ship independently. Item 5 requires more integration testing.
File diff suppressed because it is too large Load Diff
@@ -1,251 +0,0 @@
# GitHub Investigation → Worktree Integration Design
**Date:** 2026-02-16
**Author:** Design exploration via brainstorming session
**Status:** Approved
## Problem Statement
GitHub issues are investigated with detailed reports, but when these issues are pushed to the Kanban board as tasks, the investigation data is **not accessible** to:
- ❌ AI agents working in worktrees (can't see root cause, evidence, fix approaches)
- ❌ Human reviewers (can't validate if the actual bug is fixed)
- ❌ QA system (can't verify the issue is resolved, only checks code quality)
## Current State
### Data Flow (Broken)
```
.auto-claude/issues/1801/ ← Investigation data lives here
├── investigation_report.json
├── investigation_logs.json
└── activity_log.json
[Create Task button clicked]
.auto-claude/specs/001-fix-bug/ ← Only summary copied
├── implementation_plan.json (description has investigation summary)
├── requirements.json
└── task_metadata.json
[Worktree created]
.auto-claude/worktrees/tasks/001-fix-bug/ ← NO investigation data!
└── .auto-claude/specs/001-fix-bug/
(implementation_plan.json, requirements.json, task_metadata.json)
```
### Key Issues
1. **Agents lack context** — Only get investigation summary, not full report with evidence and code paths
2. **Humans can't validate** — No visibility into investigation findings during review
3. **QA doesn't verify fix** — Checks code quality/tests, but not if the actual bug is resolved
4. **No feedback loop validation** — QA rejects → Fixer fixes → QA re-runs, but never validates against original issue
## Solution: Spec Directory Augmentation
**Approach:** Copy investigation files to spec directory at task creation. Worktree setup's existing `copy_spec_to_worktree()` naturally propagates everything.
### Why This Approach
**Leverages existing patterns**`copy_spec_to_worktree()` already handles copying spec files
**Safest changes** — Modifications in IPC handlers, not core workspace setup
**True isolation** — Worktrees are fully self-contained
**Cross-platform** — No symlink headaches on Windows
**YAGNI** — Investigation reports are static; no auto-sync needed
## Design
### 1. Data Flow (Fixed)
```
.auto-claude/issues/1801/
├── investigation_report.json
├── investigation_logs.json
└── activity_log.json
[Create Task button clicked]
.auto-claude/specs/001-fix-bug/ ← NEW: Investigation files copied
├── implementation_plan.json
├── requirements.json
├── task_metadata.json (sourceType: github, githubIssueNumber, baseBranch)
├── investigation_report.json ← NEW!
├── investigation_logs.json ← NEW!
└── activity_log.json ← NEW!
[Worktree created]
.auto-claude/worktrees/tasks/001-fix-bug/
└── .auto-claude/specs/001-fix-bug/
├── implementation_plan.json
├── requirements.json
├── task_metadata.json
├── investigation_report.json ← Automatically included!
├── investigation_logs.json ← Automatically included!
└── activity_log.json ← Automatically included!
```
### 2. Agent Context Enhancement
**Goal:** Agents receive full investigation context when implementing fixes.
**Implementation:**
1. **Copy investigation files to spec directory**
- File: `apps/frontend/src/main/ipc-handlers/github/spec-utils.ts`
- Function: `createSpecForIssue()` (after line 184)
- Copies: `investigation_report.json`, `investigation_logs.json`, `activity_log.json`
2. **Load investigation context in agent**
- File: `apps/backend/agents/coder.py`
- Function: `load_investigation_context(spec_dir: Path) -> dict | None`
- Returns structured context (root cause, fix approaches, gotchas, reproducer)
3. **Inject into agent prompt using XML tags** (per Anthropic Opus 4.6 best practices)
```xml
<github_investigation_context>
<root_cause_analysis>...</root_cause_analysis>
<fix_approaches>...</fix_approaches>
<gotchas>...</gotchas>
<patterns_to_follow>...</patterns_to_follow>
<verification_steps>...</verification_steps>
</github_investigation_context>
<investigation_usage_guidance>
Use the investigation context above to inform your implementation, but:
- Verify findings independently before making changes
- Prioritize the recommended fix approach unless you find a better solution
- Reference the evidence and code paths when making changes
- Use the verification steps to confirm your fix works
</investigation_usage_guidance>
```
4. **Prevent overthinking** (Opus 4.6 specific)
```xml
<focus_guidance>
When implementing, choose an approach from the investigation and commit to it.
Avoid revisiting decisions unless you encounter new information that contradicts your reasoning.
If you need to course-correct, you can always adjust later.
</focus_guidance>
```
### 3. Human Visibility Enhancement
**Goal:** Humans can see investigation findings when reviewing tasks.
**Implementation:**
1. **TaskCard enhancement**
- File: `apps/frontend/src/renderer/components/task/TaskCard.tsx`
- Shows: GitHub issue badge + "Show Investigation" button (if `sourceType === 'github'`)
2. **InvestigationSummary component** (new)
- File: `apps/frontend/src/renderer/components/task/InvestigationSummary.tsx`
- Displays:
- Root cause summary
- Recommended fix approach
- Link to full report (opens in VSCode)
3. **useInvestigationData hook** (new)
- File: `apps/frontend/src/renderer/hooks/useInvestigationData.ts`
- Calls IPC handler to load investigation data
4. **IPC handler** (new)
- File: `apps/frontend/src/main/ipc-handlers/task/investigation-handlers.ts`
- Handler: `TASK_GET_INVESTIGATION_DATA`
- Reads: `.auto-claude/specs/{specId}/investigation_report.json`
5. **Review modal enhancement**
- File: `apps/frontend/src/renderer/components/task/TaskReviewModal.tsx`
- Adds: Validation checklist
- ☐ Root cause addressed?
- ☐ Reproducer fixed?
- ☐ Gotchas avoided?
### 4. QA Validation Enhancement
**Goal:** QA validates the bug is actually fixed, not just code quality.
**Implementation:**
1. **Load investigation context in QA**
- File: `apps/backend/qa/reviewer.py`
- Function: `load_qa_investigation_context(spec_dir, base_branch)`
2. **QA reviewer prompt enhancement**
- File: `apps/backend/prompts/qa_reviewer.md`
- Adds: `<github_issue_validation>` section with:
- Root cause to validate
- Evidence of the issue
- Reproduction steps (if available)
- Expected impact (before/after)
- Validation checklist:
1. Verify root cause is addressed
2. Validate the issue is resolved
3. Check for regressions
4. Verify minimal changes
3. **QA signoff enhancement**
- File: `apps/backend/qa/loop.py`
- Adds: `investigation_validation` field to QA signoff
```json
{
"status": "approved",
"investigation_validation": {
"root_cause_addressed": true,
"reproducer_passed": true,
"expected_outcome_achieved": true,
"validation_notes": "The fix correctly addresses the race condition..."
}
}
```
4. **QA fixer context**
- File: `apps/backend/qa/fixer.py`
- Passes: Investigation context (root cause, reproducer, fix approaches)
- Guidance: "Ensure your fix actually addresses these findings. Don't just make QA errors go away."
## Files to Create/Modify
### Create (4 files)
1. `apps/frontend/src/renderer/components/task/InvestigationSummary.tsx`
2. `apps/frontend/src/renderer/hooks/useInvestigationData.ts`
3. `apps/frontend/src/main/ipc-handlers/task/investigation-handlers.ts`
4. `apps/backend/agents/investigation_context.py` (utility module)
### Modify (8 files)
1. `apps/frontend/src/main/ipc-handlers/github/spec-utils.ts` — Copy investigation files to spec
2. `apps/frontend/src/renderer/components/task/TaskCard.tsx` — Show investigation badge
3. `apps/frontend/src/renderer/components/task/TaskReviewModal.tsx` — Validation checklist
4. `apps/backend/agents/coder.py` — Load investigation context
5. `apps/backend/prompts/coder.md` — Investigation prompt section
6. `apps/backend/qa/reviewer.py` — Load investigation for QA
7. `apps/backend/prompts/qa_reviewer.md` — Investigation validation
8. `apps/backend/qa/fixer.py` — Pass investigation to fixer
**Total: 12 files, ~400 lines of code (estimated)**
## Success Criteria
- ✅ Agents can access full investigation report when implementing fixes
- ✅ Humans can see investigation findings during review
- ✅ QA validates the bug is fixed (not just code quality)
- ✅ Existing workflow unchanged for non-GitHub tasks
- ✅ Worktrees remain fully isolated
- ✅ Cross-platform compatibility maintained
## Future Enhancements (Out of Scope)
- Auto-comment GitHub issue during QA phases
- Auto-close GitHub issue when task marked 'done'
- Category-specific QA prompts (security, performance, UI/UX)
- QA feedback posted to GitHub issue
## References
- [Claude Opus 4.6 Prompting Best Practices](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices)
- Investigation deep dive report: Agent `a9b71f6` output
- Current GitHub→Kanban workflow investigation: Agent `aeb13e2` output
File diff suppressed because it is too large Load Diff
-283
View File
@@ -1,283 +0,0 @@
# Verification Gap Tracker — Issues Tab Enhancement (Round 2)
**Branch:** `terminal/enhancement-issues-tab`
**Created:** 2026-02-13
**Total Gaps:** 46 confirmed (from 9-agent triple-verified audit)
**Status:** 17 / 17 complete ✓
---
## How to Use This File
Each gap has: ID, description, status, files to modify, verification source, test status, and notes.
**Status values:**
- `PENDING` — Not started
- `IN_PROGRESS` — Currently being worked on
- `DONE` — Implemented, tested, committed
- `BLOCKED` — Waiting on another gap
- `SKIPPED` — Decided not to implement (with reason)
**Workflow per gap:**
1. Write/update tests first (TDD)
2. Implement the fix
3. Run tests — all must pass
4. Run lint (`npm run lint`)
5. Update this file
6. Commit with message referencing gap ID
---
## TIER 1 — Critical Wiring (Features built but not connected)
### VGAP-01: `onCreateSpec` not passed to IssueDetail in GitHubIssues.tsx
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Small
- **Verified by:** Phase4+5 agent + Verifier-1 (CONFIRMED)
- **Doc ref:** Phase 5 PRD > US-4; Phase 2 PRD > US-8
- **Files modified:** `renderer/components/GitHubIssues.tsx`
- **Fix:** Created `handleCreateSpec` useCallback that calls `window.electronAPI.github.createSpecFromIssue()` and returns `{ specNumber }`. Passed as `onCreateSpec={handleCreateSpec}` to IssueDetail.
- **Tests:** 3860 pass, lint clean
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-01+02
### VGAP-02: TriageSidebar missing dependency props in GitHubIssues.tsx
- **Status:** `DONE`
- **Priority:** MUST-FIX
- **Scope:** Small
- **Verified by:** Phase4+5 agent + Verifier-1 (CONFIRMED)
- **Doc ref:** Phase 5 PRD > US-6 > AC-6.1; Phase 5 PRD > US-8 > AC-8.3
- **Files modified:** `renderer/components/GitHubIssues.tsx`
- **Fix:** Added `dependencies={dependencies}`, `isDepsLoading={isDepsLoading}`, `depsError={depsError}` to TriageSidebar JSX. Data already available from useDependencies hook.
- **Tests:** 3860 pass, lint clean
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-01+02
---
## TIER 2 — i18n Hardcoded Strings
### VGAP-03: BulkActionBar.tsx hardcoded action labels (8 strings)
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Verified by:** i18n agent + Verifier-2 (CONFIRMED)
- **Doc ref:** CLAUDE.md > i18n required
- **Files modified:** `renderer/components/github-issues/components/BulkActionBar.tsx`, `shared/i18n/locales/en/common.json`, `shared/i18n/locales/fr/common.json`
- **Fix:** Changed `BULK_ACTIONS` constant to use `labelKey` instead of `label`, rendering via `t(labelKey)`. Replaced `{selectedCount} selected` with `t('bulk.selected', { count })`. Replaced `Processing X/Y...` with `t('bulk.processing', { current, total })`. Updated test expectations to match i18n keys.
- **Tests:** 3860 pass, lint clean
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-03..07
### VGAP-04: EmptyStates.tsx hardcoded strings (4 strings)
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Small
- **Verified by:** i18n agent + Verifier-2 (CONFIRMED)
- **Doc ref:** CLAUDE.md > i18n required
- **Files modified:** `renderer/components/github-issues/components/EmptyStates.tsx`, `shared/i18n/locales/en/common.json`, `shared/i18n/locales/fr/common.json`
- **Fix:** Added `useTranslation('common')` to both EmptyState and NotConnectedState. Replaced 4 hardcoded strings with `t('issues.emptySearch')`, `t('issues.notConnected')`, `t('issues.configureToken')`, `t('issues.openSettings')`.
- **Tests:** 3860 pass, lint clean
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-03..07
### VGAP-05: IssueListHeader.tsx hardcoded strings (9+ strings)
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Medium
- **Verified by:** i18n agent + Verifier-2 (CONFIRMED)
- **Doc ref:** CLAUDE.md > i18n required
- **Files modified:** `renderer/components/github-issues/components/IssueListHeader.tsx`, `shared/i18n/locales/en/common.json`, `shared/i18n/locales/fr/common.json`
- **Fix:** Replaced 10 hardcoded strings with `t()` calls: title, openCount (with interpolation), analyzeGroup, analyzeGroupTooltip, autoFixNew, autoFixTooltip, autoFixProcessing (with interpolation), searchPlaceholder, filterOpen/Closed/All.
- **Tests:** 3860 pass, lint clean
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-03..07
### VGAP-06: LabelManager.tsx hardcoded strings (3 strings)
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Small
- **Verified by:** i18n agent + Verifier-2 (CONFIRMED)
- **Doc ref:** CLAUDE.md > i18n required
- **Files modified:** `renderer/components/github-issues/components/LabelManager.tsx`, `shared/i18n/locales/en/common.json`, `shared/i18n/locales/fr/common.json`
- **Fix:** Added `useTranslation('common')`. Replaced `'Add Label'``t('labels.add')`, `'Filter labels...'``t('labels.filter')`, `'No matching labels'``t('labels.noMatch')`.
- **Tests:** 3860 pass, lint clean
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-03..07
### VGAP-07: AssigneeManager.tsx hardcoded strings (3 strings)
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Small
- **Verified by:** i18n agent + Verifier-2 (CONFIRMED)
- **Doc ref:** CLAUDE.md > i18n required
- **Files modified:** `renderer/components/github-issues/components/AssigneeManager.tsx`, `shared/i18n/locales/en/common.json`, `shared/i18n/locales/fr/common.json`
- **Fix:** Added `useTranslation('common')`. Replaced `'Assign'``t('assignees.assign')`, `'Search collaborators...'``t('assignees.search')`, `'No matching collaborators'``t('assignees.noMatch')`.
- **Tests:** 3860 pass, lint clean
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-03..07
---
## TIER 3 — Accessibility Keyboard Support
### VGAP-08: LabelManager dropdown options missing keyboard handlers
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Small
- **Verified by:** i18n agent + Verifier-2 (CONFIRMED)
- **Doc ref:** Design doc > Section 8.4 Accessibility
- **Files modified:** `renderer/components/github-issues/components/LabelManager.tsx`, `__tests__/LabelManager.test.tsx`
- **Fix:** Added `onKeyDown` handler to `role="option"` divs: Enter/Space to select (with `preventDefault`), Escape to close dropdown and reset search.
- **Tests:** 4 new tests: Enter key select, Space key select, Escape close, Enter on applied label no-op. All pass.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-08+09
### VGAP-09: AssigneeManager dropdown options missing keyboard handlers
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Small
- **Verified by:** i18n agent + Verifier-2 (CONFIRMED)
- **Doc ref:** Design doc > Section 8.4 Accessibility
- **Files modified:** `renderer/components/github-issues/components/AssigneeManager.tsx`, `__tests__/AssigneeManager.test.tsx`
- **Fix:** Added `onKeyDown` handler identical to LabelManager: Enter/Space to select, Escape to close dropdown.
- **Tests:** 4 new tests: Enter key select, Space key select, Escape close, Enter on assigned user no-op. All pass.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-08+09
---
## TIER 4 — IPC Consistency (Hardcoded channel strings)
### VGAP-10: dependency-handlers.ts uses hardcoded IPC channel string
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Small
- **Verified by:** IPC agent + Verifier-3 (CONFIRMED)
- **Doc ref:** Codebase convention — all handlers use IPC_CHANNELS constants
- **Files modified:** `main/ipc-handlers/github/dependency-handlers.ts`
- **Fix:** Added `import { IPC_CHANNELS } from '../../../shared/constants/ipc'` and replaced `'github:deps:fetch'` with `IPC_CHANNELS.GITHUB_DEPS_FETCH`.
- **Tests:** 3868 pass, lint clean
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-10..12
### VGAP-11: label-sync-handlers.ts uses 6 hardcoded IPC channel strings
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Small
- **Verified by:** IPC agent + Verifier-3 (CONFIRMED)
- **Doc ref:** Codebase convention
- **Files modified:** `main/ipc-handlers/github/label-sync-handlers.ts`
- **Fix:** Added `import { IPC_CHANNELS } from '../../../shared/constants/ipc'` and replaced all 6 hardcoded strings with `IPC_CHANNELS.GITHUB_LABEL_SYNC_*` constants.
- **Tests:** 3868 pass, lint clean
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-10..12
### VGAP-12: metrics-handlers.ts uses 2 hardcoded IPC channel strings
- **Status:** `DONE`
- **Priority:** SHOULD-FIX
- **Scope:** Small
- **Verified by:** IPC agent + Verifier-3 (CONFIRMED)
- **Doc ref:** Codebase convention
- **Files modified:** `main/ipc-handlers/github/metrics-handlers.ts`
- **Fix:** Added `import { IPC_CHANNELS } from '../../../shared/constants/ipc'` and replaced both hardcoded strings with `IPC_CHANNELS.GITHUB_METRICS_COMPUTE` and `IPC_CHANNELS.GITHUB_METRICS_STATE_COUNTS`.
- **Tests:** 3868 pass, lint clean
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-10..12
---
## TIER 5 — Phase 3 Audit Gaps (Low severity, not addressed from original audit)
### VGAP-13: No validation caching for Python runner check (Phase 3 GAP-3)
- **Status:** `DONE`
- **Priority:** NICE-TO-HAVE
- **Scope:** Medium
- **Verified by:** Phase3 agent + Verifier-1 (CONFIRMED)
- **Doc ref:** Phase 3 audit > GAP-3
- **Files modified:** `main/ipc-handlers/github/utils/subprocess-runner.ts`
- **Fix:** Added module-level validation cache with 5-minute TTL in `validateGitHubModule()`. Cache is per-project-path and auto-invalidates on TTL expiry or project switch. All callers (ai-triage-handlers, autofix-handlers, pr-handlers, triage-handlers) benefit automatically.
- **Tests:** 3868 pass, lint clean. Existing mocked handler tests unaffected.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-13
### VGAP-14: Undo batch only reverts local state, not GitHub labels (Phase 3 GAP-4)
- **Status:** `DONE`
- **Priority:** NICE-TO-HAVE
- **Scope:** Large
- **Verified by:** Phase3 agent + Verifier-1 (CONFIRMED)
- **Doc ref:** Phase 3 PRD > US-4 > AC4.9; Phase 3 audit > GAP-4
- **Files modified:** `renderer/components/github-issues/hooks/useAITriage.ts`, `renderer/components/GitHubIssues.tsx`, `hooks/__tests__/useAITriage.test.ts`
- **Fix:** Added `undoLastBatchWithGitHub()` to useAITriage hook. Before restoring local snapshot, iterates accepted/auto-applied items and calls `removeIssueLabels()` for each item's `labelsToAdd` (best-effort, continues on failure). GitHubIssues.tsx now calls this instead of store-only `undoLastBatch`.
- **Tests:** New test verifies removeIssueLabels called for accepted items, NOT called for rejected items, and local state restored to pending. 14 tests pass.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-14
### VGAP-15: No enrichment comment duplicate detection (Phase 3 GAP-5)
- **Status:** `DONE`
- **Priority:** NICE-TO-HAVE
- **Scope:** Medium
- **Verified by:** Phase3 agent + Verifier-1 (CONFIRMED)
- **Doc ref:** Phase 3 PRD > US-5 > AC5.11; Phase 3 audit > GAP-5
- **Files modified:** `renderer/components/github-issues/components/EnrichmentCommentPreview.tsx`, `renderer/components/GitHubIssues.tsx`, `shared/i18n/locales/en/common.json`, `shared/i18n/locales/fr/common.json`, `__tests__/EnrichmentCommentPreview.test.tsx`
- **Fix:** Added `hasExistingAIComment` prop to EnrichmentCommentPreview that shows a yellow warning banner with `role="alert"`. GitHubIssues.tsx fetches issue comments via `getIssueComments` IPC when enrichment result is available, checks for `ENRICHMENT_COMMENT_FOOTER`, and passes result as prop. Added `duplicateWarning` i18n key to EN + FR.
- **Tests:** 3 new tests: warning shown when true, hidden when false, hidden when undefined. All pass.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-15
### VGAP-16: No cancel mechanism for batch triage subprocess (Phase 3 GAP-7)
- **Status:** `DONE`
- **Priority:** NICE-TO-HAVE
- **Scope:** Medium
- **Verified by:** Phase3 agent + Verifier-1 (CONFIRMED)
- **Doc ref:** Phase 3 PRD > US-2 > AC2.6; Phase 3 audit > GAP-7
- **Files modified:** `shared/constants/ipc.ts`, `main/ipc-handlers/github/ai-triage-handlers.ts`, `preload/api/modules/github-api.ts`, `renderer/components/GitHubIssues.tsx`
- **Fix:** Added `GITHUB_TRIAGE_CANCEL` to IPC_CHANNELS. Added module-level `activeTriageProcess` variable in ai-triage-handlers.ts that stores ChildProcess reference for both enrichment and split subprocesses (cleared after completion). Added `ipcMain.handle` for cancel channel that sends SIGTERM. Added `cancelTriage()` to preload github-api bridge. Wired TriageProgressOverlay cancel button to call `window.electronAPI.github.cancelTriage()`.
- **Tests:** 430 pass, lint clean
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-16
### VGAP-17: Review queue not persisted across sessions (Phase 3 GAP-9)
- **Status:** `DONE`
- **Priority:** NICE-TO-HAVE
- **Scope:** Medium
- **Verified by:** Phase3 agent (CONFIRMED)
- **Doc ref:** Phase 3 audit > GAP-9
- **Files modified:** `shared/constants/ipc.ts`, `main/ipc-handlers/github/ai-triage-handlers.ts`, `preload/api/modules/github-api.ts`, `renderer/components/github-issues/hooks/useAITriage.ts`, `hooks/__tests__/useAITriage.test.ts`
- **Fix:** Added `GITHUB_TRIAGE_SAVE_PENDING_REVIEW` and `GITHUB_TRIAGE_LOAD_PENDING_REVIEW` IPC channels. Main handler saves/loads `pending-review.json` in the github config directory (auto-deletes when queue is empty). Preload bridge exposes `savePendingReview` and `loadPendingReview`. useAITriage hook loads persisted items on mount via useEffect (with loadedRef guard to prevent premature saves) and auto-saves whenever reviewItems change.
- **Tests:** 2 new tests: load persisted items on mount, save items on change. 432 pass total, lint clean.
- **Test status:** `PASS`
- **Depends on:** None
- **Commit:** VGAP-17
---
## Progress Summary
| Tier | Description | Total | Done | Remaining |
|------|-------------|-------|------|-----------|
| 1 | Critical Wiring | 2 | 2 | 0 |
| 2 | i18n Hardcoded Strings | 5 | 5 | 0 |
| 3 | Accessibility Keyboard | 2 | 2 | 0 |
| 4 | IPC Consistency | 3 | 3 | 0 |
| 5 | Phase 3 Audit Gaps | 5 | 5 | 0 |
| **Total** | | **17** | **17** | **0** |
Note: VGAP-03 through VGAP-07 contain 28+ individual hardcoded strings grouped by component file. The 17 gap count represents work units (one per component/file), not individual string count.
-166
View File
@@ -1,166 +0,0 @@
# Cross-Project Task Contamination: Missing projectId in Agent Event Pipeline
## Description
When running multiple projects simultaneously, agent events from one project can corrupt the status, badges, and column placement of tasks in another project. The root cause is that the entire agent event pipeline (from process spawn through XState state machine to disk persistence) identifies tasks by `specId` alone, with no project scoping. Since specIds are derived from task descriptions and are not unique across projects, `findTaskAndProject(taskId)` returns the first match across all loaded projects, routing events to the wrong task.
## Severity
**High** - Silent data corruption. Affected tasks show wrong status, wrong badges, land in wrong Kanban columns, and persist corrupted state to disk. On refresh, the corrupted state is reloaded, making the damage permanent until manually fixed.
## Affected Versions
All versions using the XState task state machine (PR #1575 and later).
## Steps to Reproduce
1. Open Auto Claude and load two projects (e.g., "Project A" and "Project B")
2. In Project A, create a task with a specific name (e.g., "write wtf to text file") - this generates specId `016-write-wtf-to-text-file`
3. In Project B, create a task with the same name - this generates the same specId `016-write-wtf-to-text-file`
4. Start both tasks simultaneously (or start Project A's task first, let it reach QA, then start Project B's task)
5. Switch between projects and observe the Kanban board
## Expected Results
- Each project's task progresses independently through its own lifecycle
- Events from Project A's agent process only affect Project A's task card
- Events from Project B's agent process only affect Project B's task card
- Refreshing the app preserves the correct status for both tasks
- Switching between projects shows each task in its correct column with the correct badge
## Actual Results
- Tasks in the non-active project show wrong status badges (e.g., "Coding" badge on a task still in the Planning column)
- Tasks snap to the wrong Kanban column after refresh
- Tasks get stuck in states they should have transitioned out of (e.g., permanently stuck in "Planning")
- "Incomplete" badges appear on tasks that completed their phase successfully
- QA tasks appear in "In Progress" column instead of "AI Review" column after switching projects
- The corrupted state persists to `implementation_plan.json`, so the damage survives app restart
## Root Cause
### Task Identity Collision
Every task has two identifiers:
- **`task.id`** - A UUID, unique globally
- **`task.specId`** - The spec directory name (e.g., `016-write-wtf-to-text-file`), derived from the task description, **not unique across projects**
The backend process uses `specId` as the task identifier in stdout markers. All agent event handlers resolve this back to a Task object via `findTaskAndProject(taskId)`, which searches all projects and returns the first match.
### Missing projectId in Event Pipeline
The agent event pipeline has no project scoping:
```
Backend process (Python)
-> stdout/stderr (phase markers, task events, logs)
-> agent-process.ts (parses output, emits typed events)
-> agent-manager.ts (EventEmitter relay)
-> agent-events-handlers.ts (event handlers)
-> findTaskAndProject(taskId) <-- COLLISION POINT
-> taskStateManager (XState actor)
-> persistPlanStatusAndReasonSync (disk)
-> safeSendToRenderer (IPC to UI)
```
None of the `AgentManagerEvents` carry a `projectId`:
```typescript
// BEFORE: no way to scope events to the correct project
interface AgentManagerEvents {
log: (taskId: string, log: string) => void;
error: (taskId: string, error: string) => void;
exit: (taskId: string, code: number | null, processType: ProcessType) => void;
'execution-progress': (taskId: string, progress: ExecutionProgressData) => void;
'task-event': (taskId: string, event: TaskEventPayload) => void;
}
```
### Impact on XState
The `TaskStateManager` maintains one XState actor per taskId and drives column placement, badge display, disk persistence, and renderer notifications. When an event is routed to the wrong project's actor:
1. The actor receives an event invalid for its current state (e.g., `PLANNING_COMPLETE` sent to an actor in `qa_review`)
2. XState either drops the event or transitions to an unexpected state
3. The wrong project's `implementation_plan.json` is overwritten with incorrect status fields
4. On app refresh, the task loads from the corrupted plan file and appears in the wrong column
5. Subsequent legitimate events may be rejected because the actor is in a state that doesn't accept them
### Contamination Example
Given:
- **Project A**: task `016-write-wtf-to-text-file` in QA (`qa_review` state)
- **Project B**: task `016-write-wtf-to-text-file` just started (`planning` state)
When Project B's planner emits `PLANNING_COMPLETE`:
1. `agent-process.ts` emits `task-event` with `taskId = "016-write-wtf-to-text-file"` and no projectId
2. `findTaskAndProject("016-write-wtf-to-text-file")` returns **Project A's task** (first match)
3. `PLANNING_COMPLETE` is sent to **Project A's XState actor** (which is in `qa_review`)
4. Project A's plan file is corrupted; Project B's task never receives the event
## Observed Symptoms
| Symptom | Cause |
|---------|-------|
| "Coding" badge on a task in the Planning column | Project B's `CODING_STARTED` event hit Project A's planning task |
| Task snaps to backlog on refresh | Plan file overwritten without XState fields; wrong project looked up for re-stamp |
| "Incomplete" badge on a task that just finished planning | `PROCESS_EXITED` event from Project B's process hit Project A's `plan_review` actor |
| QA task in "In Progress" column with "AI Review" badge | Execution progress event wrote wrong status to plan file |
| Task stuck in "Planning" forever | Events meant for this task were consumed by the duplicate in another project |
## Fix
Thread `projectId` from the IPC handler that starts each agent process through the entire event pipeline to the lookup function.
### Propagation Chain
```
execution-handlers.ts
agentManager.startSpecCreation(..., project.id) <- Origin: project.id from IPC handler
agentManager.startTaskExecution(..., project.id)
agentManager.startQAProcess(..., project.id)
agent-manager.ts
storeTaskContext(..., projectId) <- Stored in execution context
processManager.spawnProcess(..., projectId) <- Passed to process spawner
agent-process.ts
this.emitter.emit('log', taskId, ..., projectId) <- Attached to every emitted event
this.emitter.emit('task-event', taskId, ..., projectId)
this.emitter.emit('execution-progress', ..., projectId)
this.emitter.emit('exit', taskId, ..., projectId)
this.emitter.emit('error', taskId, ..., projectId)
agent-events-handlers.ts
findTaskAndProject(taskId, projectId) <- Scoped lookup
taskStateManager.handleTaskEvent(...) <- Correct actor receives event
persistPlanStatusAndReasonSync(...) <- Correct plan file updated
safeSendToRenderer(..., projectId) <- Renderer filters by project
```
### Scoped Lookup
`findTaskAndProject` now accepts an optional `projectId`. When provided, it searches only the target project. Falls back to searching all projects for backward compatibility (file watcher events, renderer-initiated actions).
## Files Changed
| File | Change |
|------|--------|
| `apps/frontend/src/main/agent/types.ts` | Added `projectId?: string` to all event signatures |
| `apps/frontend/src/main/agent/agent-manager.ts` | Added `projectId` to context storage, start methods, restart flow |
| `apps/frontend/src/main/agent/agent-process.ts` | Added `projectId` to `spawnProcess` and all `emitter.emit()` calls |
| `apps/frontend/src/main/ipc-handlers/task/shared.ts` | Scoped `findTaskAndProject` by projectId with fallback |
| `apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts` | All event handlers receive and forward projectId |
| `apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts` | All 9 `agentManager.start*` call sites pass `project.id` |
| `apps/frontend/src/__tests__/integration/subprocess-spawn.test.ts` | Updated test expectations for new projectId parameter |
## Verification
- [ ] Run two projects simultaneously with tasks that have the same specId
- [ ] Verify events from Project A only affect Project A's task cards
- [ ] Verify events from Project B only affect Project B's task cards
- [ ] Refresh the app during various lifecycle stages - tasks remain in correct columns
- [ ] Switch between projects during QA - task stays in AI Review column
- [ ] `npm run typecheck` passes
- [ ] `npm run test` passes (2639 tests, 0 failures)
@@ -1,628 +0,0 @@
# AI Issue Investigation System — Design Document
> **Status:** Design Complete (98 gap decisions resolved)
> **Date:** 2026-02-13
> **Branch:** `feat/issues`
> **Target:** `develop`
## 1. Vision
Transform GitHub issues from passive tickets into actionable intelligence. When a user clicks **"AI Investigate"** on an issue, Auto-Claude spins up a worktree, deploys 4 specialist agents in parallel to explore the codebase, and produces a detailed investigation report. The report can be posted to GitHub and one-click converted into a kanban task that flows through the existing build pipeline.
**Future vision:** Full auto-fix loop — investigate → build fix → verify fix against investigation worktree → auto PR review → loop until resolved.
### Core Principles
- **GitHub is the source of truth** — all state synced via lifecycle labels and comments
- **Two parallel workflows** — normal task creation stays untouched; issue-based tasks get their own pipeline
- **One worktree, two phases** — investigation explores read-only, then the build phase writes the fix in the same worktree
- **DRY with PR review system** — extract shared patterns (parallel orchestrator, specialist agents, stream processing, structured output)
- **Investigation replaces triage** — the old enrichment/triage system is superseded by deep investigation
---
## 2. User-Facing Workflow
### 2.1 Single-Issue Investigation
1. User opens an issue in the GitHub Issues tab
2. Clicks **"AI Investigate"** button (primary CTA in detail view)
3. Button transitions: `AI Investigate``Investigating...` (animated) → `View Results``Create Task`
4. 4 specialist agents explore the codebase in parallel (progress bar on issue card in list)
5. Results panel replaces the old enrichment panel (mirrors PR review layout)
6. Optionally auto-posted to GitHub as a branded comment (follows PR follow-up "full auto" pattern)
7. User clicks **"Create Task"** (replaces the investigate button) → one-click task creation
8. Task appears on kanban board → build pipeline reuses the investigation worktree
### 2.2 Bulk Investigation
- Checkbox selection on individual issues + "Investigate Selected" button
- "Investigate All Matching" button for current filter results
- Both feed into the parallel queue (max N concurrent, configurable)
- Batch cancel (cancel all) + individual cancel available
### 2.3 Button State Machine
```
[AI Investigate] → [Investigating... ⏳] → [View Results ✓] → [Create Task]
(blue) (animated/disabled) (green) (purple)
[Cancel Investigation]
(appears alongside)
```
- **No separate "Create Task" button** — it only appears after investigation completes
- **Triage button removed** — investigation replaces triage entirely
- **Create Spec button removed** — investigation is the only path from issue to task
### 2.4 Results Display
- Mirrors PR review layout (same component patterns)
- Collapsible sections per specialist agent (Root Cause, Impact, Fix Advice, Reproduction)
- AI summary replaces the raw GitHub issue body (raw body available via "Show original" toggle)
- Minimal activity log: key events with timestamps (e.g., "Investigated Feb 13", "Task created Feb 13")
- Agent-suggested labels shown with accept/reject UI
### 2.5 Issue List Indicators
- Mini progress bar on each issue card (0-100% during investigation)
- After completion: checkmark + task link badge
- Investigation state filter chips alongside existing label/status filters
- Dismissed issues hidden by default (toggle to show)
---
## 3. Architecture
### 3.1 Two Parallel Workflows
```
NORMAL WORKFLOW (unchanged):
User creates task manually → .auto-claude/specs/{specId}/ → Start build → New worktree → Pipeline
ISSUE-BASED WORKFLOW (new):
AI Investigate → Pre-allocate specId → Worktree created → Read-only investigation
Create Task → .auto-claude/specs/{specId}/ created from investigation → Task on kanban
Build starts → Reuses existing worktree → Pipeline with investigation context injected
```
### 3.2 Investigation-to-Task Flow (Detailed)
```
Step 1: "AI Investigate" clicked
├── Allocate specId (spec number lock, pre-reserve)
├── Create worktree: .auto-claude/worktrees/tasks/{specId}/
├── Create branch: auto-claude/{specId}
├── Create issue dir: .auto-claude/issues/{issueNumber}/
│ └── Store: specId, issueNumber, state=investigating
├── Add GitHub label: "auto-claude: investigating"
└── Launch 4 specialist agents (read-only, parallel)
Step 2: Investigation completes
├── Save investigation_report.json to .auto-claude/issues/{issueNumber}/
├── Update GitHub label: "auto-claude: findings-ready"
├── Post GitHub comment (if auto-post enabled)
├── In-app notification (toast/badge)
└── Derived state → "findings_ready"
Step 3: "Create Task" clicked (or auto-create if enabled)
├── Create .auto-claude/specs/{specId}/ (template-based from investigation data)
│ ├── spec.md (from investigation report)
│ ├── requirements.json (from structured investigation data)
│ ├── task_metadata.json (GitHub issue link, category, investigation source)
│ └── investigation_report.json (copied from issues dir)
├── Update .auto-claude/issues/{issueNumber}/ with linked_spec_id
├── Task appears on kanban in "backlog" status
├── Update GitHub label: "auto-claude: task-created"
└── Derived state → "task_created"
Step 4: Build starts
├── run.py --spec {specId} --issue-workflow
├── setup_workspace() finds EXISTING worktree (idempotent get_or_create_worktree)
├── Spec files copied into worktree
├── Investigation report injected into coder prompt + kept as file
├── Pipeline runs: planner → coder → QA (configurable phases per gap 25)
├── Update GitHub label: "auto-claude: building"
└── Derived state → "building" (auto-synced from kanban task status)
Step 5: Build completes
├── Task moves to "done" on kanban
├── Post completion comment on GitHub: "Resolved by Auto-Claude task #XXX. PR: #YYY"
├── Auto-close GitHub issue (if setting enabled)
├── Update GitHub label: "auto-claude: done"
└── Derived state → "done"
```
### 3.3 Specialist Agents
4 parallel agents, each a separate Claude SDK session:
| Agent | Purpose | Tools |
|-------|---------|-------|
| **Root Cause Analyzer** | Trace the bug/issue to its source. Follow references in the issue body. Identify the exact code paths. | Read, Grep, Glob |
| **Impact Assessor** | Determine blast radius. What other code/features are affected? What breaks if this isn't fixed? | Read, Grep, Glob |
| **Fix Advisor** | Suggest concrete fix approaches. Identify files to modify, patterns to follow, gotchas. | Read, Grep, Glob |
| **Reproducer** | Determine if/how the issue can be reproduced. Check test coverage, find related test files. | Read, Grep, Glob |
**Tool enforcement:** Read/Grep/Glob only. No Write/Edit/Bash. Enforced at tool grant level, not prompt-only.
**Structured output:** Pydantic models + JSON schema (same pattern as PR review specialists).
**Shared infrastructure with PR review:**
- `process_sdk_stream()` from `sdk_utils.py` for stream processing
- `SpecialistConfig` dataclass pattern for agent definition
- `asyncio.gather()` for parallel execution
- Pydantic models for structured output
- `create_client()` from `core/client.py` for SDK sessions
### 3.4 Data Model
#### `.auto-claude/issues/{issueNumber}/` (new directory)
```
.auto-claude/issues/
1805/
investigation_report.json # Full findings from all 4 agents
investigation_state.json # { specId, issueNumber, status, startedAt, completedAt, ... }
agent_logs/ # Per-agent log files
root_cause_analyzer.log
impact_assessor.log
fix_advisor.log
reproducer.log
github_comment_id # ID of posted GitHub comment (for editing/referencing)
suggested_labels.json # AI-suggested labels with accept/reject status
```
#### Investigation State (derived, not manually managed)
```
No investigation data → "new"
Investigation running → "investigating"
Investigation complete, no task → "findings_ready"
Investigation found likely fixed → "resolved"
Investigation failed → "failed"
Task exists, in backlog/queue → "task_created"
Task in_progress/ai_review → "building" (auto-synced from kanban)
Task done/pr_created → "done" (auto-synced from kanban)
```
State is **fully derived** — computed from investigation data + linked task status. Never manually set. GitHub labels auto-sync from derived state (debounced 5-10s).
#### Worktree Layout
```
.auto-claude/
worktrees/
tasks/
042-fix-login-bug/ # One worktree, used for both phases
.auto-claude/
specs/042-fix-login-bug/ # Spec files (copied in during build phase)
issues/1805/ # Investigation data (available to build agents)
src/ # Project source code
...
issues/
1805/ # Investigation home (main project, authoritative)
investigation_report.json
investigation_state.json
agent_logs/
...
specs/
042-fix-login-bug/ # Created ONLY when "Create Task" clicked
spec.md
requirements.json
task_metadata.json
investigation_report.json # Copied from issues dir
```
---
## 4. GitHub Sync
### 4.1 Lifecycle Labels (5 labels, auto-created with consent)
| Label | Color | When Applied |
|-------|-------|-------------|
| `auto-claude: investigating` | Blue (#1d76db) | Investigation starts |
| `auto-claude: findings-ready` | Purple (#7057ff) | Investigation completes |
| `auto-claude: task-created` | Green (#0e8a16) | Task created on kanban |
| `auto-claude: building` | Orange (#e4e669) | Build pipeline running |
| `auto-claude: done` | Dark Green (#006b75) | Task completed |
- **One-way sync**: Auto-Claude pushes labels to GitHub but does not read them back. App state is authoritative.
- **Auto-create with consent**: First use shows dialog: "Auto-Claude needs to create status labels in your repo. Allow?"
- **Debounced**: Label updates batched with 5-10s delay to avoid rapid API calls during fast state transitions.
- **Auto-Claude owns its labels**: Users can manage their own labels freely; Auto-Claude only manages `auto-claude:` prefixed labels.
### 4.2 GitHub Comments
**Investigation Report Comment:**
- Branded header: "Auto-Claude Investigation Report" with emoji + timestamp
- Collapsible sections per agent (matches PR review comment format)
- Severity badge at top
- Posted automatically when "full auto" setting is enabled (follows PR follow-up pattern)
- Manual "Post to GitHub" button when auto-post is disabled
- Re-investigation: new comment posted, old one left as-is (both stay visible)
- Only current investigation can be posted — no backfill of past un-posted results
**Completion Comment:**
- Posted when linked task reaches "done": "This issue was resolved by Auto-Claude task #XXX. PR: #YYY"
- Auto-close issue if setting enabled (configurable toggle, default off)
### 4.3 Linked PR Detection
Investigation checks for linked/referenced PRs on the issue. If found, includes in report: "Existing PR #456 addresses this issue. Status: open/merged."
---
## 5. Settings Configuration
New **"AI Investigation"** subsection within the existing GitHub settings page.
### 5.1 Settings List
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| Auto-create tasks from investigations | Toggle | Off | When enabled, auto-creates kanban tasks after investigation. Tasks collect in batch staging area for review. |
| Auto-start tasks when created | Toggle (global) | Off | Auto-start build pipeline when tasks are created (applies to ALL task sources). |
| Pipeline mode for investigation tasks | Dropdown | Full | `Full` / `Skip to planning` / `Minimal` — controls how much spec pipeline runs for investigation-created tasks. |
| Auto-post investigation to GitHub | Toggle | Off | Follows PR follow-up "full auto" pattern. When enabled, posts results automatically. |
| Auto-close issues when task completes | Toggle | Off | Closes GitHub issue with completion comment when linked task reaches "done". |
| Max parallel investigations | Number input | 3 | Range 1-10. Controls how many investigations run simultaneously. |
| Label include filter | Multi-select dropdown | (empty = all) | Synced from repo labels. Only auto-create tasks for issues with these labels. |
| Label exclude filter | Multi-select dropdown | (empty = none) | Synced from repo labels. Never auto-create tasks for issues with these labels. |
### 5.2 Notification Settings
- In-app only (badges/toasts) for investigation events (completed, failed, task auto-created)
- Start investigation-specific, but schema designed to extend into app-wide notification system later
### 5.3 Auto-Create Batch Staging
When auto-create is enabled, tasks don't go directly to kanban. Instead:
- Collapsible inline banner at top of issues view
- Shows pending task creations with approve/reject per item
- Configurable limit before queuing (prevents task flood)
---
## 6. Existing System Changes
### 6.1 Triage System → Replaced
- **Remove triage button** entirely from issue detail view
- Investigation replaces triage as the AI analysis feature
- Old enrichment panel replaced with investigation results panel
- Existing workflow states (`new`, `triaged`, `in_progress`, etc.) replaced with derived investigation states
- Enrichment data for already-triaged issues kept for backwards compatibility but no new triage operations
### 6.2 Create Spec Button → Removed
- **Remove "Create Spec" button** from issue detail view
- Investigation is the only path from GitHub issue to kanban task
- Existing `createSpecForIssue` handler replaced entirely with investigation-based task creation
### 6.3 Enrichment Panel → Replaced
- Old enrichment panel (problem statement, goal, acceptance criteria, completeness %) removed
- Replaced with investigation results panel matching PR review layout
- AI summary replaces raw GitHub issue body as primary view ("Show original" toggle for raw body)
### 6.4 Issue List Updates
- Completeness % replaced with investigation progress bar
- Label pills (already implemented) stay as-is
- New filter chips for investigation state
- Dismissed issues hidden by default with "Show dismissed" toggle
### 6.5 Kanban Task Store
- No changes to normal task workflow
- Task store continues scanning `.auto-claude/specs/` only (not `.auto-claude/issues/`)
- Investigation data lives separately until "Create Task" promotes it
### 6.6 Build Pipeline Extensions
- New `--issue-workflow` flag for `run.py`
- Full issue mode: loads investigation data, skips phases per setting, injects context, tracks lifecycle
- `setup_workspace()` behavior unchanged — `get_or_create_worktree()` is already idempotent and returns existing worktrees
---
## 7. Edge Cases & Failure Handling
### 7.1 App Crash During Investigation
- Auto-resume on restart: detect incomplete investigations, re-run from scratch (full re-run, not resume)
- Worktree already exists, so setup is fast
- Previous partial results discarded
### 7.2 Investigation Failure
- Auto-retry once if all agents error
- If still fails: show "Investigation failed" with error details and "Retry" button
- GitHub label: stays on `auto-claude: investigating` (or removed on cleanup)
### 7.3 Cancellation
- User can cancel running investigation
- Partial results saved and viewable
- Worktree stays (for potential re-investigation)
- Agents terminated gracefully
### 7.4 Closed/Stale Issues
- Investigation allowed on closed issues with warning banner: "This issue is closed"
- Useful for post-mortems and historical analysis
### 7.5 Connection Loss
- Agents continue locally (they only need the worktree/codebase)
- "Post to GitHub" step skipped if connection unavailable
- User can post manually later when connection restores
### 7.6 Already-Resolved Issues
- If investigation finds issue is likely already fixed: "Likely resolved" badge
- Suggest closing the GitHub issue (prominent banner with one-click close)
- "Create Task" button still available if user disagrees
### 7.7 Task Deletion
- If user deletes linked kanban task, issue reverts to "findings_ready" state
- Investigation data preserved in `.auto-claude/issues/`
- User can re-create task from existing findings
### 7.8 Repo Switch
- Investigations are tied to the project, not the repo setting
- Running investigations continue if user switches GitHub repo in settings
- New investigations use the new repo
### 7.9 Re-Investigation
- User can re-run investigation on any issue (even with existing findings)
- Previous results kept (history pattern)
- New GitHub comment posted (old one left as-is)
- If task exists: new findings appended to existing task description
### 7.10 Stale Findings
- No automatic staleness tracking (point-in-time snapshot)
- Investigation timestamp shown prominently
- User's responsibility to re-investigate if codebase changed significantly
### 7.11 Dismiss Flow
- "Dismiss" button with reason dropdown: Won't fix, Duplicate, Cannot reproduce, Out of scope
- Closes issue on GitHub with selected reason as comment
- Dismissed issues hidden from list (toggle to show)
### 7.12 Deleted/Transferred Issues
- If issue disappears from GitHub sync, marked as "stale/removed" in app
- Investigation data preserved locally with warning badge
---
## 8. Shared Infrastructure (DRY with PR Review)
### 8.1 Extract from PR Review System
| Component | Current Location | Shared Pattern |
|-----------|-----------------|----------------|
| `ParallelOrchestratorReviewer` | `runners/github/services/parallel_orchestrator_reviewer.py` | Extract `ParallelAgentOrchestrator` base class |
| `SpecialistConfig` | `parallel_orchestrator_reviewer.py` | Move to shared module |
| `process_sdk_stream()` | `runners/github/services/sdk_utils.py` | Already shared |
| Pydantic structured output | `runners/github/services/pydantic_models.py` | Add investigation models |
| `create_client()` | `core/client.py` | Already shared |
| `AGENT_CONFIGS` | `agents/tools_pkg/models.py` | Add investigation agent configs |
| Finding validation pipeline | `parallel_orchestrator_reviewer.py` | Extract for reuse |
| `createIPCCommunicators` | Frontend IPC handlers | Reuse for investigation progress/complete/error |
### 8.2 New Backend Components
| Component | Purpose |
|-----------|---------|
| `runners/github/services/issue_investigation_orchestrator.py` | Parallel orchestrator for 4 investigation agents |
| `runners/github/services/investigation_models.py` | Pydantic models for investigation structured output |
| `prompts/github/investigation_*.md` | 4 specialist prompt files |
| `runners/github/services/investigation_report_builder.py` | Combines agent outputs into unified report |
| `runners/github/services/investigation_persistence.py` | Read/write `.auto-claude/issues/` data |
### 8.3 New Frontend Components
| Component | Purpose |
|-----------|---------|
| IPC handler: `investigation-handlers.ts` | Start, cancel, status, create-task |
| Store: `investigation-store.ts` | Investigation state, results, progress |
| Component: `InvestigationPanel.tsx` | Results display (mirrors PR review panel) |
| Component: `InvestigateButton.tsx` | State machine button (investigate → running → results → create task) |
| Component: `BatchStagingBanner.tsx` | Inline auto-create staging area |
| Settings section: `InvestigationSettings.tsx` | All investigation toggles |
### 8.4 New IPC Channels
| Channel | Direction | Purpose |
|---------|-----------|---------|
| `GITHUB_INVESTIGATION_START` | Renderer → Main | Start investigation on issue(s) |
| `GITHUB_INVESTIGATION_CANCEL` | Renderer → Main | Cancel running investigation |
| `GITHUB_INVESTIGATION_PROGRESS` | Main → Renderer | Real-time progress updates |
| `GITHUB_INVESTIGATION_COMPLETE` | Main → Renderer | Investigation finished with results |
| `GITHUB_INVESTIGATION_ERROR` | Main → Renderer | Investigation failed |
| `GITHUB_INVESTIGATION_CREATE_TASK` | Renderer → Main | Create kanban task from findings |
| `GITHUB_INVESTIGATION_DISMISS` | Renderer → Main | Dismiss issue with reason |
| `GITHUB_INVESTIGATION_POST_GITHUB` | Renderer → Main | Post results to GitHub |
---
## 9. Testing Strategy
**Integration-first TDD** — test the full flow, then add unit tests for individual components.
### 9.1 Backend Tests
- Investigation orchestrator: mock SDK, verify 4 agents spawned in parallel
- Investigation persistence: read/write `.auto-claude/issues/` data
- Report builder: combine agent outputs into unified report
- Pipeline integration: `--issue-workflow` flag loads investigation context
- Worktree reuse: verify `get_or_create_worktree()` returns existing investigation worktree
### 9.2 Frontend Tests
- Investigation store: state transitions, progress tracking
- InvestigateButton: state machine (investigate → running → results → create task)
- Task creation from investigation: template-based spec generation
- Settings: all toggles persist and apply
- Batch staging: approve/reject flow
### 9.3 E2E Tests
- Full flow: investigate → view results → create task → verify on kanban
- Bulk investigate: select multiple → queue → parallel execution
- Cancel: start investigation → cancel → verify partial results saved
- Auto-create: enable setting → investigate → verify batch staging appears
---
## 10. Gap Analysis Reference
All 98 design decisions are documented below for traceability.
<details>
<summary>Click to expand full gap analysis (98 decisions)</summary>
### Core Architecture (1-10)
| # | Topic | Decision |
|---|-------|----------|
| 1 | Concurrency | Multiple parallel investigations |
| 2 | Agent failure | Retry once, then partial results |
| 3 | Re-investigation | Keep history (previousResult pattern) |
| 4 | Issue types | All types, agents adapt |
| 5 | Button conflict | One smart "Create Task" button (appears after investigation) |
| 6 | Worktree cleanup | Tied to task lifecycle + age-based GC |
| 7 | Context size | Full issue context |
| 8 | Progress UX | Real-time log stream (PRLogs pattern) |
| 9 | Rate limits | Existing multi-account profile swapping |
| 10 | Testing | Integration-first TDD |
### UX & Interaction (11-24)
| # | Topic | Decision |
|---|-------|----------|
| 11 | Button placement | Same layout as PR review system |
| 12 | Navigation during run | Background + badge on issue list |
| 13 | App crash/close | Auto-resume (full re-run on restart) |
| 14 | Duplicate comments | Post new, leave old as-is |
| 15 | Task flood | Batch confirmation inline banner |
| 16 | Existing linked task | Update existing task description |
| 17 | Cancellation | Cancel + keep partial, worktree stays |
| 18 | Closed issues | Allow with warning banner |
| 19 | Connection loss | Agents continue locally, skip GH post |
| 20 | Results UI | Mirror PR review layout |
| 21 | Resume mode | Re-run full (fresh agents, worktree exists) |
| 22 | Queue system | Parallel up to N limit, rest queued |
| 23 | Auto-build | Optional "auto-start" setting |
| 24 | Sharing/export | GitHub comment is the artifact |
### Investigation to Task Transition (25-37)
| # | Topic | Decision |
|---|-------|----------|
| 25 | Spec pipeline | Configurable: Full / Skip to planning / Minimal |
| 26 | Report in task | Full investigation report as description |
| 27 | Auto-run scope | Global toggle (all task sources) |
| 28 | Filter rules | Labels only (synced from repo) |
| 29 | Report storage | New `investigation_report.json` in spec dir |
| 30 | Staging UI | Inline banner in issues view |
| 31 | Settings layout | New "AI Investigation" subsection in GitHub settings |
| 32 | Filter config | Synced label dropdowns (include/exclude) |
| 33 | Parallel limit | Configurable (1-10, default 3) |
| 34 | Already fixed | Flag "Likely resolved" + optional task button |
| 35 | Manual create | One-click create, edit in kanban after |
| 36 | Task linking | Badge + link on issue (bidirectional) |
| 37 | Re-investigate done | Allow, append findings to existing task |
### Settings & Lifecycle (38-44)
| # | Topic | Decision |
|---|-------|----------|
| 38 | Auto-post to GH | Follows PR follow-up "full auto" pattern |
| 39 | Auto-close issue | Configurable toggle (default off) |
| 40 | Bulk investigate | Checkbox selection + filter-based |
| 41-42 | Notifications | In-app only (badges/toasts) |
| 43 | Notification arch | Start specific, plan for app-wide later |
| 44 | Settings complete | Confirmed |
### Existing Issue System Integration (45-68)
| # | Topic | Decision |
|---|-------|----------|
| 45 | Triage vs investigation | Investigation replaces triage |
| 46 | GitHub status labels | Yes, full lifecycle (5 labels) |
| 47 | Button layout | Single "AI Investigate" button, "Create Task" appears after |
| 48 | Live GH changes | Ignore during investigation run |
| 49 | Button states | Investigate → Running → Results → Create Task |
| 50 | Create Task location | Replaces the investigate button after completion |
| 51 | Triage button fate | Removed entirely |
| 52 | Label creation | Auto-create with user consent dialog |
| 53 | Label names | 5 labels: investigating, findings-ready, task-created, building, done |
| 54 | Workflow states | Replace with derived investigation states |
| 55 | Completion sync | Comment + close (if auto-close enabled) |
| 56 | Reverse sync | One-way only (app → GitHub). Auto-Claude owns its labels. |
| 57 | Create Spec fate | Removed entirely |
| 58 | Enrichment panel | Replaced with investigation results panel |
| 59 | Auto-label suggestions | Yes, suggest labels (user accepts/rejects) |
| 60 | List indicators | Progress bar per issue card |
| 61 | Comment format | Match PR review format (collapsible sections) |
| 62 | Bot branding | Branded header at top |
| 63 | Old comments | Leave both (no editing/deleting old comments) |
| 64 | Backfill posting | Only current investigation results |
| 65 | State filters | Filter chips alongside existing filters |
| 66 | Deleted issues | Mark as stale, keep local data |
| 67 | Linked PRs | Detect and show in investigation report |
| 68 | State persistence | Full local persistence |
### Derived State & Dismiss (69-83)
| # | Topic | Decision |
|---|-------|----------|
| 69 | State machine | Fully derived from investigation + task data |
| 70 | Task sync | Auto-sync from kanban (issue state mirrors task status) |
| 71 | Activity log | Minimal log (key events + timestamps) |
| 72 | Summary view | AI summary replaces body ("Show original" toggle) |
| 73 | State list | 7 derived states + "failed" = 8 states total |
| 74 | Label sync timing | Debounced (5-10s delay) |
| 75 | Dismiss action | In-app dismiss + close on GitHub with reason |
| 76 | Task deleted | Revert to findings_ready |
| 77 | Repo switch | Investigations keep running |
| 78 | Stale findings | No staleness tracking (point-in-time) |
| 79 | Batch cancel | Both batch and individual cancel |
| 80 | Dismissed view | Hidden with filter toggle |
| 81 | Failed state | Auto-retry once, then fail with "Retry" button |
| 82 | Resolved action | Suggest closing GitHub issue |
| 83 | Completeness | Confirmed complete |
### Kanban/Pipeline Redesign (84-98)
| # | Topic | Decision |
|---|-------|----------|
| 84 | Worktree strategy | One worktree, two phases (investigate read-only → build writes) |
| 85 | Pipeline entry | Extend existing run.py with --issue-workflow flag |
| 86 | Naming/numbering | Pre-allocate specId at investigation start |
| 87 | Data storage | New `.auto-claude/issues/{issueNumber}/` directory |
| 88 | Issue dir contents | Full investigation home (report, state, logs, comment ID) |
| 89 | Context for build | File in worktree + key findings in coder prompt |
| 90 | Read-only enforcement | Tool grants only (Read/Grep/Glob) |
| 91 | Spec pipeline config | Honors gap 25 configurable setting |
| 92 | Handler approach | Replace existing createSpecForIssue entirely |
| 93 | File merge on build | Copy spec, keep investigation data alongside |
| 94 | Kanban visibility | Separate until "Create Task" promotes to specs dir |
| 95 | Full flow confirmed | Allocate specId → worktree → investigate → Create Task → specs → kanban → build reuses worktree |
| 96 | Spec generation | Template-based (deterministic, no AI cost) |
| 97 | Pipeline flag behavior | Full issue mode (load investigation, skip phases, inject context) |
| 98 | Completeness | Confirmed complete |
</details>
@@ -1,319 +0,0 @@
# AI Issue Investigation — Implementation Plan
> **Design doc:** [ai-issue-investigation-design.md](ai-issue-investigation-design.md)
> **Date:** 2026-02-13
> **Branch:** `feat/issues`
## Implementation Phases
14 phases ordered by dependency. Backend (B) and frontend (F) phases can run in parallel where noted.
---
### Phase 1 — Backend: Shared Infrastructure Extraction [B1]
**Goal:** Extract reusable parallel orchestrator base from PR review system.
**New files:**
- `apps/backend/runners/github/services/parallel_agent_base.py``ParallelAgentOrchestrator` base class + `SpecialistConfig` dataclass. Extracts: `_load_prompt()`, `_run_specialist_session()`, `_run_parallel_specialists()` (asyncio.gather wrapper), `_report_progress()`.
**Modified files:**
- `apps/backend/runners/github/services/parallel_orchestrator_reviewer.py` — Inherit from base, remove duplicated methods, keep PR-specific logic (finding validation, verdict generation, SPECIALIST_CONFIGS).
- `apps/backend/runners/github/services/__init__.py` — Add exports.
**Depends on:** Nothing (foundational).
---
### Phase 2 — Backend: Investigation Models & Persistence [B2]
**Goal:** Pydantic models for structured agent output + `.auto-claude/issues/` read/write layer.
**New files:**
- `apps/backend/runners/github/services/investigation_models.py``RootCauseAnalysis`, `ImpactAssessment`, `FixAdvice`, `ReproductionAnalysis`, `InvestigationReport`, `SuggestedLabel`, `LinkedPR`, per-specialist response models.
- `apps/backend/runners/github/services/investigation_persistence.py``save_investigation_state()`, `load_investigation_state()`, `save_investigation_report()`, `load_investigation_report()`, `save_agent_log()`, `save_github_comment_id()`, `list_investigated_issues()`. All writes via `write_json_atomic()`.
**Depends on:** B1 (SpecialistConfig import).
---
### Phase 3 — Frontend: Type Definitions & IPC Foundation [F1]
**Goal:** All type contracts, IPC channels, and preload bridge for the investigation system.
**New files:**
- `apps/frontend/src/shared/types/investigation.ts``InvestigationState`, `InvestigationReport`, `InvestigationProgress`, `InvestigationResult`, `InvestigationDismissReason`, `InvestigationSettings`, `BatchStagingItem`.
**Modified files:**
- `apps/frontend/src/shared/types/integrations.ts` — Deprecate old `GitHubInvestigationResult`/`Status`.
- `apps/frontend/src/shared/types/index.ts` — Add `investigation` exports.
- `apps/frontend/src/shared/constants/ipc.ts` — Add 7 new IPC channels (`INVESTIGATION_START`, `CANCEL`, `CREATE_TASK`, `DISMISS`, `POST_GITHUB`, `GET_SETTINGS`, `SAVE_SETTINGS`).
- `apps/frontend/src/shared/types/ipc.ts` — Update callback signatures, add new method declarations.
- `apps/frontend/src/preload/api/modules/github-api.ts` — Add 7 new API methods + implementations.
**Depends on:** Nothing. **Can run in parallel with B1 and B2.**
---
### Phase 4 — Backend: Investigation Orchestrator & Prompts [B3]
**Goal:** Core orchestrator that runs 4 specialist agents in parallel + prompt files.
**New files:**
- `apps/backend/runners/github/services/issue_investigation_orchestrator.py``IssueInvestigationOrchestrator` inheriting from `ParallelAgentOrchestrator`. 4 specialist configs (root_cause, impact, fix_advisor, reproducer) with `["Read", "Grep", "Glob"]` tools only.
- `apps/backend/prompts/github/investigation_root_cause.md` — Trace bug to source code paths.
- `apps/backend/prompts/github/investigation_impact.md` — Blast radius and affected components.
- `apps/backend/prompts/github/investigation_fix_advice.md` — Concrete fix approaches with files and patterns.
- `apps/backend/prompts/github/investigation_reproduction.md` — Reproducibility and test coverage.
**Modified files:**
- `apps/backend/agents/tools_pkg/models.py` — Add `investigation_specialist` agent config (`BASE_READ_TOOLS` only).
- `apps/backend/runners/github/orchestrator.py` — Add `investigate_issue()` method.
- `apps/backend/runners/github/services/__init__.py` — Add exports.
**Depends on:** B1 (base class), B2 (models + persistence).
---
### Phase 5 — Frontend: Investigation Store [F2]
**Goal:** Full multi-issue Zustand store modeled after `pr-review-store.ts`.
**Rewrite:**
- `apps/frontend/src/renderer/stores/github/investigation-store.ts` — Complete rewrite. Keyed by `${projectId}:${issueNumber}`. State per issue: `isInvestigating`, `progress`, `report`, `error`, `previousReport`, `specId`, `dismissReason`. Derived state computation (8 states). Global IPC listeners. Settings sub-state.
**Modified files:**
- `apps/frontend/src/renderer/stores/github/index.ts` — Wire up `initializeInvestigationListeners()` / `cleanupInvestigationListeners()`.
**Depends on:** F1 (types).
---
### Phase 6 — Backend: Report Builder & Worktree Pre-Allocation [B4]
**Goal:** GitHub comment formatter + worktree creation at investigation start.
**New files:**
- `apps/backend/runners/github/services/investigation_report_builder.py``build_github_comment(report)` (branded markdown with collapsible sections), `build_summary(report)` (one-paragraph for list display).
**Modified files:**
- `apps/backend/runners/github/orchestrator.py` — Add `start_investigation()` method: allocate worktree via `WorktreeManager.get_or_create_worktree(spec_name)`, save initial state, run orchestrator, handle retry-once on failure, save results.
- `apps/backend/runners/github/models.py` — Add investigation settings to `GitHubRunnerConfig`.
**Depends on:** B2 (models), B3 (orchestrator).
---
### Phase 7 — Frontend: IPC Handler Rewrite [F3]
**Goal:** Main process handlers for the full investigation lifecycle.
**Rewrite:**
- `apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts` — Complete rewrite. Handles all 7 IPC channels. Spawns backend subprocess via `runPythonSubprocess()`. Tracks running processes (Map of issueNumber → process) for cancel support. Uses `createIPCCommunicators` for progress/error/complete. Create-task handler uses template-based spec generation. Dismiss handler closes GitHub issue with reason comment. Post handler posts branded comment.
**Modified files:**
- `apps/frontend/src/main/ipc-handlers/github/index.ts` — Update handler registration if needed.
**Depends on:** F1 (IPC channels), B4 (backend ready to receive investigation requests).
---
### Phase 8 — Frontend: Core UI Components [F4]
**Goal:** InvestigateButton, InvestigationPanel, progress bar, and hook rewrite.
**New files:**
- `apps/frontend/src/renderer/components/github-issues/components/InvestigateButton.tsx` — State machine button: `AI Investigate` (blue) → `Investigating...` (animated) → `View Results` (green) → `Create Task` (purple). Cancel button alongside during investigation.
- `apps/frontend/src/renderer/components/github-issues/components/InvestigationPanel.tsx` — Mirrors PR review layout. 4 collapsible agent sections. AI summary, severity badge, suggested labels (accept/reject), activity log, "Post to GitHub" button, "Likely resolved" banner, "Show original" toggle.
- `apps/frontend/src/renderer/components/github-issues/components/InvestigationProgressBar.tsx` — Mini progress bar for issue list items (0-100%, checkmark + task link after completion).
**Rewrite:**
- `apps/frontend/src/renderer/components/github-issues/hooks/useGitHubInvestigation.ts` — Use new investigation store. Return: `investigationState()`, `startInvestigation`, `cancelInvestigation`, `createTask`, `dismissIssue`, `getActiveInvestigations`.
**Modified files:**
- `apps/frontend/src/renderer/components/github-issues/components/index.ts` — Add new exports, remove `EnrichmentPanel`.
- `apps/frontend/src/renderer/components/github-issues/types/index.ts` — Update all component prop types (remove triage/enrichment props, add investigation props).
**Depends on:** F2 (store), F1 (types).
---
### Phase 9 — Frontend: Issue Detail & List Rewiring [F5]
**Goal:** Replace enrichment/triage UI with investigation UI in detail view and list.
**Modified files:**
- `apps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsx` — Remove: enrichment panel, create spec button, triage button. Add: `InvestigateButton` (state machine), `InvestigationPanel`, dismiss button with reason dropdown, closed issue warning banner, AI summary as primary view with "Show original" toggle.
- `apps/frontend/src/renderer/components/github-issues/components/IssueListItem.tsx` — Remove: `WorkflowStateBadge`, `CompletenessIndicator`. Add: `InvestigationProgressBar`, task link badge.
- `apps/frontend/src/renderer/components/github-issues/components/IssueList.tsx` — Pass investigation states instead of enrichments.
- `apps/frontend/src/renderer/components/github-issues/components/IssueListHeader.tsx` — Replace workflow filter chips with investigation state filter chips. Add "Show dismissed" toggle. Remove triage mode toggle.
**Depends on:** F4 (components exist).
---
### Phase 10 — Frontend: Main Component Rewiring [F6]
**Goal:** Update parent `GitHubIssues.tsx` to use investigation system.
**Modified files:**
- `apps/frontend/src/renderer/components/GitHubIssues.tsx` — Remove: all triage/enrichment imports, hooks, and state (`useEnrichmentStore`, `useAITriage`, `useTriageMode`, `BatchTriageReview`, `TriageProgressOverlay`, `TriageSidebar`, `InvestigationDialog`). Add: investigation store, investigation callbacks. Replace 3-panel triage mode with 2-panel (investigation panel is inline in detail view). Wire all investigation callbacks to IssueDetail.
- `apps/frontend/src/renderer/components/github-issues/index.ts` — Remove `InvestigationDialog`, add new exports.
**Depends on:** F5 (child components rewired).
---
### Phase 11 — Backend: Pipeline Extension & Spec Generation [B5]
**Goal:** `--issue-workflow` flag + template-based spec creation from investigation.
**New files:**
- `apps/backend/runners/github/services/investigation_spec_generator.py``generate_spec_from_investigation()`: loads report from `.auto-claude/issues/`, creates `spec.md` (from AI summary + root cause + fix advice), `requirements.json`, `task_metadata.json`, copies `investigation_report.json` into spec dir. All template-based (no AI cost).
**Modified files:**
- `apps/backend/cli/main.py` — Add `--issue-workflow` argument.
- `apps/backend/cli/build_commands.py` — Handle `issue_workflow=True`: load investigation report, inject context into coder prompt (via `prompt += "\n\n" + context` pattern), skip phases per setting, update investigation state to "building"/"done".
- `apps/backend/runners/github/orchestrator.py` — Add `create_task_from_investigation()` method.
**Depends on:** B2 (persistence), B3 (orchestrator). **Can run in parallel with F3-F6.**
---
### Phase 12 — Frontend: Batch Staging & Settings [F7]
**Goal:** Auto-create batch staging banner + investigation settings subsection.
**New files:**
- `apps/frontend/src/renderer/components/github-issues/components/BatchStagingBanner.tsx` — Collapsible inline banner. Pending task creations, approve/reject per item, configurable limit.
- `apps/frontend/src/renderer/components/github-issues/components/InvestigationSettings.tsx` — All 8 settings: auto-create toggle, auto-start toggle, pipeline mode dropdown, auto-post toggle, auto-close toggle, max parallel (1-10), label include/exclude filters.
**Modified files:**
- `apps/frontend/src/renderer/components/settings/sections/SectionRouter.tsx` — Render `InvestigationSettings` in GitHub settings section.
- `apps/frontend/src/renderer/components/GitHubIssues.tsx` — Render `BatchStagingBanner` above issue list.
**Depends on:** F2 (store), F1 (types).
---
### Phase 13 — Frontend: i18n [F8]
**Goal:** All translation keys for English and French.
**Modified files:**
- `apps/frontend/src/shared/i18n/locales/en/common.json` — Investigation namespace (buttons, states, agent names, dismiss reasons, filters, batch staging).
- `apps/frontend/src/shared/i18n/locales/en/settings.json` — Investigation settings labels and descriptions.
- `apps/frontend/src/shared/i18n/locales/fr/common.json` — French translations.
- `apps/frontend/src/shared/i18n/locales/fr/settings.json` — French translations.
**Depends on:** F4-F7 (all components exist to know what keys are needed).
---
### Phase 14 — Frontend: Cleanup Deprecated Code [F9]
**Goal:** Remove obsolete triage/enrichment code.
**Files to remove:**
- `InvestigationDialog.tsx` — Replaced by inline `InvestigateButton`.
- `CreateSpecButton.tsx` — No longer used (investigation is the only path).
- `useTriageMode.ts` — Triage mode removed.
**Files to deprecate (keep for backwards compat with old data):**
- `EnrichmentPanel.tsx`, `TriageSidebar.tsx`, `WorkflowStateBadge.tsx`, `WorkflowStateDropdown.tsx`, `WorkflowFilter.tsx`, `CompletenessIndicator.tsx`, `CompletenessBreakdown.tsx`, `useAITriage.ts`, `enrichment-store.ts`, `ai-triage-store.ts`.
**Depends on:** F6 (all references removed).
---
## Dependency Graph
```
B1 ──→ B2 ──→ B3 ──→ B4 ──→ B5
F1 ──→ F2 ──→ F4 ──→ F5 ──→ F6 ──→ F9
↓ ↑ ↑
F3 ────┘ F7
(needs B4) ↓
F8
```
**Parallel lanes:**
- B1+B2 can run in parallel with F1
- B5 can run in parallel with F3-F6
- F7 can run in parallel with F5-F6
- F8 runs after all components exist
- F9 runs last
---
## File Summary
### New files (17)
| # | File | Phase |
|---|------|-------|
| 1 | `apps/backend/runners/github/services/parallel_agent_base.py` | B1 |
| 2 | `apps/backend/runners/github/services/investigation_models.py` | B2 |
| 3 | `apps/backend/runners/github/services/investigation_persistence.py` | B2 |
| 4 | `apps/backend/runners/github/services/issue_investigation_orchestrator.py` | B3 |
| 5 | `apps/backend/prompts/github/investigation_root_cause.md` | B3 |
| 6 | `apps/backend/prompts/github/investigation_impact.md` | B3 |
| 7 | `apps/backend/prompts/github/investigation_fix_advice.md` | B3 |
| 8 | `apps/backend/prompts/github/investigation_reproduction.md` | B3 |
| 9 | `apps/backend/runners/github/services/investigation_report_builder.py` | B4 |
| 10 | `apps/backend/runners/github/services/investigation_spec_generator.py` | B5 |
| 11 | `apps/frontend/src/shared/types/investigation.ts` | F1 |
| 12 | `apps/frontend/src/renderer/components/github-issues/components/InvestigateButton.tsx` | F4 |
| 13 | `apps/frontend/src/renderer/components/github-issues/components/InvestigationPanel.tsx` | F4 |
| 14 | `apps/frontend/src/renderer/components/github-issues/components/InvestigationProgressBar.tsx` | F4 |
| 15 | `apps/frontend/src/renderer/components/github-issues/components/BatchStagingBanner.tsx` | F7 |
| 16 | `apps/frontend/src/renderer/components/github-issues/components/InvestigationSettings.tsx` | F7 |
| 17 | (i18n keys added to 4 existing locale files) | F8 |
### Files to rewrite (3)
| # | File | Phase |
|---|------|-------|
| 1 | `apps/frontend/src/renderer/stores/github/investigation-store.ts` | F2 |
| 2 | `apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts` | F3 |
| 3 | `apps/frontend/src/renderer/components/github-issues/hooks/useGitHubInvestigation.ts` | F4 |
### Files to modify (22)
| # | File | Phase(s) |
|---|------|----------|
| 1 | `apps/backend/runners/github/services/parallel_orchestrator_reviewer.py` | B1 |
| 2 | `apps/backend/runners/github/services/__init__.py` | B1, B3, B5 |
| 3 | `apps/backend/agents/tools_pkg/models.py` | B3 |
| 4 | `apps/backend/runners/github/orchestrator.py` | B3, B4, B5 |
| 5 | `apps/backend/runners/github/models.py` | B4 |
| 6 | `apps/backend/cli/main.py` | B5 |
| 7 | `apps/backend/cli/build_commands.py` | B5 |
| 8 | `apps/frontend/src/shared/types/integrations.ts` | F1 |
| 9 | `apps/frontend/src/shared/types/index.ts` | F1 |
| 10 | `apps/frontend/src/shared/constants/ipc.ts` | F1 |
| 11 | `apps/frontend/src/shared/types/ipc.ts` | F1 |
| 12 | `apps/frontend/src/preload/api/modules/github-api.ts` | F1 |
| 13 | `apps/frontend/src/renderer/stores/github/index.ts` | F2 |
| 14 | `apps/frontend/src/main/ipc-handlers/github/index.ts` | F3 |
| 15 | `apps/frontend/src/renderer/components/github-issues/components/index.ts` | F4 |
| 16 | `apps/frontend/src/renderer/components/github-issues/types/index.ts` | F4 |
| 17 | `apps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsx` | F5 |
| 18 | `apps/frontend/src/renderer/components/github-issues/components/IssueListItem.tsx` | F5 |
| 19 | `apps/frontend/src/renderer/components/github-issues/components/IssueList.tsx` | F5 |
| 20 | `apps/frontend/src/renderer/components/github-issues/components/IssueListHeader.tsx` | F5 |
| 21 | `apps/frontend/src/renderer/components/GitHubIssues.tsx` | F6, F7 |
| 22 | `apps/frontend/src/renderer/components/settings/sections/SectionRouter.tsx` | F7 |
### Files to remove (3)
| # | File | Phase |
|---|------|-------|
| 1 | `InvestigationDialog.tsx` | F9 |
| 2 | `CreateSpecButton.tsx` | F9 |
| 3 | `useTriageMode.ts` | F9 |
### Files to deprecate (10)
EnrichmentPanel, TriageSidebar, WorkflowStateBadge, WorkflowStateDropdown, WorkflowFilter, CompletenessIndicator, CompletenessBreakdown, useAITriage, enrichment-store, ai-triage-store.
-95
View File
@@ -1,95 +0,0 @@
# Linux Installation & Building Guide
This guide covers Linux-specific installation options and building from source.
## Flatpak Installation
Flatpak packages are available for Linux users who prefer sandboxed applications.
### Download Flatpak
See the [main README](../README.md#beta-release) for Flatpak download links in the Beta Release section.
### Building Flatpak from Source
To build the Flatpak package yourself, you need additional dependencies:
```bash
# Fedora/RHEL
sudo dnf install flatpak-builder
# Ubuntu/Debian
sudo apt install flatpak-builder
# Install required Flatpak runtimes
flatpak install flathub org.freedesktop.Platform//25.08 org.freedesktop.Sdk//25.08
flatpak install flathub org.electronjs.Electron2.BaseApp//25.08
# Build the Flatpak
cd apps/frontend
npm run package:flatpak
```
The Flatpak will be created in `apps/frontend/dist/`.
### Installing the Built Flatpak
After building, install the Flatpak locally:
```bash
flatpak install --user apps/frontend/dist/Auto-Claude-*.flatpak
```
### Running from Flatpak
```bash
flatpak run com.autoclaude.AutoClaude
```
## Other Linux Packages
### AppImage
AppImage files are portable and don't require installation:
```bash
# Make executable
chmod +x Auto-Claude-*-linux-x86_64.AppImage
# Run
./Auto-Claude-*-linux-x86_64.AppImage
```
### Debian Package (.deb)
For Ubuntu/Debian systems:
```bash
sudo dpkg -i Auto-Claude-*-linux-amd64.deb
```
## Troubleshooting
### Flatpak Runtime Issues
If you encounter runtime issues with Flatpak:
```bash
# Update runtimes
flatpak update
# Check for missing runtimes
flatpak list --runtime
```
### AppImage Not Starting
If the AppImage doesn't start:
```bash
# Check for missing libraries
ldd ./Auto-Claude-*-linux-x86_64.AppImage
# Try running with debug output
./Auto-Claude-*-linux-x86_64.AppImage --verbose
```
-165
View File
@@ -1,165 +0,0 @@
# Opus 4.6 Features in Auto Claude
This document describes the Opus 4.6-specific features implemented in Auto Claude.
## Overview
Auto Claude leverages Claude Opus 4.6's advanced capabilities to provide faster, smarter GitHub issue investigations. These features are designed to balance speed, quality, and cost for different use cases.
## Fast Mode
Opus 4.6 Fast Mode delivers **2.5x faster output generation** at premium pricing by optimizing token generation speed.
### When to Use Fast Mode
- **Quick investigations:** When you need results fast and cost is secondary
- **Development/testing:** When iterating on investigation prompts or workflows
- **Time-sensitive issues:** Production incidents requiring rapid analysis
- **Batch processing:** When investigating multiple issues in parallel
### When to Use Standard Mode
- **Cost-sensitive projects:** When API budget is a concern
- **Complex investigations:** When maximum thinking time is beneficial
- **Non-urgent issues:** When speed is not critical
### How to Enable Fast Mode
1. Open Auto Claude desktop app
2. Navigate to **Settings > GitHub > AI Investigation**
3. Toggle **"Fast mode investigations"** to ON
4. Future investigations will use Fast Mode
**Note:** Fast Mode is **opt-in** (defaults to OFF) to avoid unexpected costs.
### Pricing Impact
Fast Mode costs approximately **2.5x more per token** than standard Opus 4.6. For example:
- Standard investigation (5 issues): ~$0.50
- Fast mode investigation (5 issues): ~$1.25
*Estimates vary based on issue complexity and repository size.*
### Technical Details
Fast Mode is implemented by setting the `CLAUDE_CODE_FAST_MODE=true` environment variable when creating the Claude SDK client. This is handled automatically by the investigation pipeline when the setting is enabled.
```python
# From core/client.py
if fast_mode:
sdk_env["CLAUDE_CODE_FAST_MODE"] = "true"
```
## 128K Output Tokens
Root cause analyzer now uses **128K max output tokens** (up from 64K) for complex investigations, enabling deeper analysis of large codebases.
### Benefits
- **Deeper code path tracing:** Follow execution through more files and functions
- **More comprehensive analysis:** Cover edge cases and complex interactions
- **Better for large monorepos:** Analyze sprawling codebases without running out of output space
- **Richer explanations:** More detailed root cause narratives and fix recommendations
### Per-Specialist Token Limits
Different investigation specialists have different output token limits based on their needs:
| Specialist | Max Tokens | API Max | Rationale |
|------------|------------|---------|-----------|
| **Root Cause** | 127,999 | 128,000 | Most complex specialist; needs to trace through multiple files, understand intricate dependencies, and provide comprehensive explanations |
| **Impact** | 63,999 | 64,000 | Standard component mapping and affected file analysis |
| **Fix Advisor** | 63,999 | 64,000 | Standard fix approaches and code suggestions |
| **Reproducer** | 63,999 | 64,000 | Standard test coverage and reproduction steps |
**Note:** Values are 1 token lower than API maximums to reserve space for the message separator that the SDK requires between thinking and output.
### Technical Implementation
The per-specialist limits are configured in `apps/backend/runners/github/services/issue_investigation_orchestrator.py`:
```python
# Per-specialist max_tokens configuration (Opus 4.6 supports up to 128K)
# Note: Values are 1 token lower than API max to reserve space for message separator
SPECIALIST_MAX_TOKENS = {
"root_cause": 127999, # Maximum for complex multi-file tracing (API max: 128000)
"impact": 63999, # Standard for component mapping (API max: 64000)
"fix_advisor": 63999, # Standard for fix approaches (API max: 64000)
"reproducer": 63999, # Standard for test coverage analysis (API max: 64000)
}
```
These limits are passed to the agent creation calls as both `max_tokens` and `thinking_budget` parameters.
## Adaptive Thinking
All investigations use **adaptive thinking** with `effort_level="high"` for best quality results.
### What This Means for Users
- **Claude decides when to think:** The model automatically determines when and how much thinking is needed
- **Interleaved thinking enabled:** Thinking tokens are generated alongside output for more coherent analysis
- **High effort by default:** Investigations use maximum effort for the most thorough analysis possible
### Technical Details
Adaptive thinking is configured automatically by the investigation pipeline. The `effort_level="high"` parameter ensures Claude uses its full reasoning capabilities during investigations.
This is distinct from Fast Mode—adaptive thinking controls **how thoroughly** Claude thinks, while Fast Mode controls **how fast** tokens are generated. You can use them independently:
- **Fast Mode + Adaptive Thinking:** Fast, thorough analysis (premium cost)
- **Standard Mode + Adaptive Thinking:** Standard speed, thorough analysis (default)
- **Standard Mode only:** Standard speed, variable thinking (not recommended for investigations)
## API Migration: output_config.format
Auto Claude has migrated from the deprecated `output_format` parameter to the new `output_config.format` API pattern.
### What Changed
**Old pattern (deprecated):**
```python
response = client.messages.create(
model=model,
max_tokens=8192,
output_format={"type": "json_schema", "schema": schema},
messages=[...]
)
```
**New pattern (current):**
```python
response = client.messages.create(
model=model,
max_tokens=8192,
output_config={"format": {"type": "json_schema", "schema": schema}},
messages=[...]
)
```
### Why This Matters
- The old `output_format` parameter is deprecated and will be removed in future SDK versions
- The new `output_config.format` pattern is more extensible for future output options
- Auto Claude's `create_client()` function handles the conversion automatically
This migration is internal—users don't need to change anything. Auto Claude forwards the new pattern to the Claude SDK.
## Future Enhancements
Potential future improvements to Opus 4.6 integration:
- [ ] **Cost estimation:** Show estimated Fast Mode cost before running investigations
- [ ] **Per-specialist effort levels:** Allow configuring effort level per specialist
- [ ] **Compaction API:** Enable for very long investigations to reduce token usage
- [ ] **1M context window:** Add option for massive projects with extensive context
- [ ] **Fast mode per specialist:** Allow Fast Mode for specific specialists only
## Related Documentation
- [Anthropic: What's new in Claude 4.6](https://platform.claude.com/docs/en/about-claude/models/whats-new-claude-4-6)
- [Anthropic: Fast Mode](https://platform.claude.com/docs/en/build-with-claude/fast-mode)
- [Anthropic: Adaptive Thinking](https://platform.claude.com/docs/en/build-with-claude/adaptive-thinking)
- [Anthropic: Structured Outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs)
- [ARCHITECTURE.md](../shared_docs/ARCHITECTURE.md) - Auto Claude architecture overview
-139
View File
@@ -1,139 +0,0 @@
# PR #1575 Follow-up: XState Status Lifecycle & Cross-Project Contamination Fixes
## Overview
After the XState task state machine migration (PR #1575), several interrelated bugs surfaced when running multiple projects simultaneously and during normal task lifecycle transitions. These bugs caused tasks to appear in wrong columns, display incorrect badges, and lose status on refresh.
## Bug 1: Cross-Project Task Contamination
### Problem
When two projects have tasks with the same specId (e.g., both have a task `016-write-wtf-to-text-file`), events from Project A's task would affect Project B's task card. Tasks in the secondary project would show wrong status badges (e.g., "Coding" badge on a task in the Planning column).
### Root Cause
`findTaskAndProject(taskId)` searches ALL projects by matching `t.id === taskId || t.specId === taskId`, returning the first match. When the backend emits events using the specId as the task identifier, the lookup could match a task in the wrong project.
Agent events (log, error, exit, execution-progress, task-event) did not carry a `projectId`, so there was no way to scope the lookup to the correct project.
### Fix
- Added `projectId` to all `AgentManagerEvents` type signatures
- Pass `project.id` from all 9 `agentManager.start*` call sites in `execution-handlers.ts`
- Thread `projectId` through `agent-manager.ts``agent-process.ts` → all `emitter.emit()` calls
- Updated `findTaskAndProject(taskId, projectId?)` to scope search to the target project when `projectId` is provided, with fallback to searching all projects for backward compatibility
- All event handlers in `agent-events-handlers.ts` now receive and use `projectId`
### Files Changed
- `apps/frontend/src/main/agent/types.ts`
- `apps/frontend/src/main/agent/agent-manager.ts`
- `apps/frontend/src/main/agent/agent-process.ts`
- `apps/frontend/src/main/ipc-handlers/task/shared.ts`
- `apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts`
- `apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts`
- `apps/frontend/src/__tests__/integration/subprocess-spawn.test.ts`
## Bug 2: "Incomplete" Badge on Plan Review Tasks
### Problem
Tasks with `requireReviewBeforeCoding=true` would complete planning, correctly transition to `plan_review` state, but then immediately show an "Incomplete" badge instead of "Planning" + "Approve Plan".
### Root Cause
Two issues combined:
1. **`PLANNING_COMPLETE` was not in the `TERMINAL_EVENTS` set.** When the spec creation process finished normally (exit code 0), `handleProcessExited` was called. Since `PLANNING_COMPLETE` wasn't terminal, the check didn't skip.
2. **`handleProcessExited` always sent `unexpected: true`**, even for exit code 0. This caused the XState guard `unexpectedExit` to pass, transitioning the task from `plan_review``error`, which overwrote the correct `plan_review` reviewReason.
### Fix
- Added `PLANNING_COMPLETE` to the `TERMINAL_EVENTS` set so process exit is skipped when planning has already completed
- Changed `handleProcessExited` to only set `unexpected: true` when `exitCode !== 0` — a code-0 exit is normal and should not trigger error transitions
### Files Changed
- `apps/frontend/src/main/task-state-manager.ts`
## Bug 3: Backend qa.py Racing with XState Status
### Problem
Tasks completing QA would sometimes show "Incomplete" instead of "Needs Review" because the `reviewReason` field was missing.
### Root Cause
The backend `qa.py` tool was writing `plan["status"] = "human_review"` directly to the plan file WITHOUT setting `reviewReason`. This raced with the frontend XState state machine's `persistPlanStatusAndReasonSync()` which writes both `status` and `reviewReason` together. When qa.py wrote last, it clobbered the `reviewReason`.
### Fix
Removed the backend's direct status writes from `qa.py`. The frontend XState state machine is now the sole owner of status transitions — the backend only updates `last_updated` timestamps and QA-specific fields.
### Files Changed
- `apps/backend/agents/tools_pkg/tools/qa.py`
## Bug 4: Plan File Overwrite by Planner Agent
### Problem
After a task started, the frontend would persist XState status fields (`status`, `xstateState`, `executionPhase`) to `implementation_plan.json`. The planner agent would then create the full plan using the Write tool, completely replacing the file and stripping the frontend's status fields. On refresh, the task would snap back to backlog.
### Root Cause
The planner agent writes `implementation_plan.json` via Claude's Write tool, which replaces the entire file. The agent-generated plan does not include frontend status fields (`xstateState`, `executionPhase`), so they are lost.
### Fix
Added a re-stamp mechanism in the file watcher's `progress` event handler. When the file watcher detects a plan file change and the `xstateState` field is missing (indicating the backend overwrote the file), the handler re-persists the current XState state back to the file. This also covers the worktree copy.
### Files Changed
- `apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts`
## Bug 5: QA Tasks in Wrong Column After Project Switch
### Problem
A task correctly in the "AI Review" column (status `ai_review`, phase `qa_review`) would snap to "In Progress" column after switching to another project and back. The "AI Review" badge would still show, but the card was in the wrong column.
### Root Cause
`persistPlanPhaseSync()` in `plan-file-utils.ts` mapped execution phases to TaskStatus for column placement. It incorrectly mapped `qa_review` and `qa_fixing` to `in_progress` instead of `ai_review`. Every execution-progress event during QA would overwrite the correct `ai_review` status (set by XState) with `in_progress`. On refresh (reading from disk), the task loaded with `status: 'in_progress'` + `executionPhase: 'qa_review'`, placing it in the In Progress column with an AI Review badge.
### Fix
Changed the phase-to-status mapping in `persistPlanPhaseSync`:
- `qa_review``ai_review` (was `in_progress`)
- `qa_fixing``ai_review` (was `in_progress`)
### Files Changed
- `apps/frontend/src/main/ipc-handlers/task/plan-file-utils.ts`
## Bug 6: updateTaskStatus Not Applying reviewReason
### Problem
Tasks completing planning with `requireReviewBeforeCoding=true` would show an "Incomplete" badge in the Human Review column instead of "Planning" + "Approve Plan". The persisted plan file had the correct `reviewReason: 'plan_review'`, so refreshing the app would fix it.
### Root Cause
`updateTaskStatus` in `task-store.ts` received `reviewReason` as a parameter but never applied it to the task object. The spread was `{ ...t, status, executionProgress }` — missing `reviewReason`. The skip condition also only checked `status`, not `reviewReason`, so transitions where only `reviewReason` changed (e.g., `human_review` with different reasons) were silently dropped.
### Fix
- Added `reviewReason` to the task spread: `{ ...t, status, reviewReason, executionProgress }`
- Updated skip condition to check both `status` AND `reviewReason`
### Files Changed
- `apps/frontend/src/renderer/stores/task-store.ts`
## Bug 7: Task Stuck in "In Progress" After Planning (requireReviewBeforeCoding)
### Problem
Tasks with `requireReviewBeforeCoding=true` would complete planning, XState would correctly transition to `plan_review`, but the task card would remain in the "In Progress" column with `status=in_progress, reviewReason=none, phase=planning`.
### Root Cause
When the process exits with code 1 (expected — the interactive review checkpoint fails in piped mode), `agent-process.ts` emits an `execution-progress` event with `phase: 'failed'` before the `exit` event. The `execution-progress` handler in `agent-events-handlers.ts`:
1. **Called `persistPlanPhaseSync` with `phase: 'failed'`**, which maps `failed``status: 'error'`, overwriting the `status: 'human_review'` that XState had already persisted to the plan file
2. **Sent `TASK_EXECUTION_PROGRESS` with `phase: 'failed'` to the renderer**, overwriting the `planning` phase that XState had already emitted via `emitPhaseFromState`
Both operations bypassed XState's authority as the source of truth for status.
### Fix
Added an XState "settled state" guard in the `execution-progress` handler. When XState has already transitioned to a settled state (`plan_review`, `human_review`, `error`, `creating_pr`, `pr_created`, `done`), the handler:
- Skips `persistPlanPhaseSync` to prevent overwriting XState's persisted status
- Skips sending `TASK_EXECUTION_PROGRESS` to the renderer to prevent overwriting XState's emitted phase
XState's own `persistStatus()` and `emitPhaseFromState()` already handle disk and renderer updates correctly when transitioning to these states.
### Files Changed
- `apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts`
## Testing
All fixes pass:
- `npm run typecheck` — clean
- `npm run test` — 2649 tests passing, 0 failures
- Manual testing: multi-project with same specIds, review-required tasks, project switching during QA, refresh at all lifecycle stages
-337
View File
@@ -1,337 +0,0 @@
# Windows Development Guide
This guide covers Windows-specific considerations when developing
Auto Claude.
## File Encoding
### Problem
Windows Python defaults to the `cp1252` (Windows-1252) code page instead
of UTF-8. This causes encoding errors when reading/writing files with
non-ASCII characters.
**Common Error:**
```plaintext
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 1234
```
### Solution
**Always specify `encoding="utf-8"` for all text file operations.**
See [CONTRIBUTING.md - File Encoding](../CONTRIBUTING.md#file-encoding-python)
for detailed examples and patterns.
### Testing on Windows
To verify your code works on Windows:
1. **Test with non-ASCII content:**
```python
# Include emoji, international chars in test data
test_data = {"message": "Test 🚀 with ñoño and 中文"}
```
2. **Run pre-commit hooks:**
```bash
pre-commit run check-file-encoding --all-files
```
3. **Run all tests:**
```bash
npm run test:backend
```
### Common Pitfalls
#### Pitfall 1: JSON files
```python
# Wrong - no encoding
with open("config.json") as f:
data = json.load(f)
# Correct
with open("config.json", encoding="utf-8") as f:
data = json.load(f)
```
#### Pitfall 2: Path methods
```python
# Wrong
content = Path("README.md").read_text()
# Correct
content = Path("README.md").read_text(encoding="utf-8")
```
#### Pitfall 3: Subprocess output
```python
# Wrong
result = subprocess.run(cmd, capture_output=True, text=True)
# Correct
result = subprocess.run(cmd, capture_output=True, encoding="utf-8")
```
## Line Endings
### Problem
Windows uses CRLF (`\r\n`) line endings while macOS/Linux use LF (`\n`).
This can cause git diffs to show every line as changed.
### Solution
1. **Configure git to handle line endings:**
```bash
git config --global core.autocrlf true
```
2. **The project's `.gitattributes` handles this automatically:**
```plaintext
* text=auto
*.py text eol=lf
*.md text eol=lf
```
3. **In code, normalize when processing:**
```python
# Normalize line endings to LF (idiomatic approach)
content = "\n".join(content.splitlines())
```
## Path Separators
### Problem
Windows uses backslash `\` for paths, while Unix uses `/`.
This can break path operations.
### Solution
1. **Always use `Path` from `pathlib`:**
```python
from pathlib import Path
# Correct - works on all platforms
config_path = Path("config") / "settings.json"
# Wrong - Unix only
config_path = "config/settings.json"
```
2. **Use `os.path.join()` for strings:**
```python
import os
# Correct
config_path = os.path.join("config", "settings.json")
```
3. **Never hardcode separators:**
```python
# Wrong - Unix only
path = "apps/backend/core"
# Correct
path = os.path.join("apps", "backend", "core")
# Or better
path = Path("apps") / "backend" / "core"
```
## Shell Commands
### Problem
Windows doesn't have bash by default. Shell commands need to work across
platforms.
### Solution
1. **Use Python libraries instead of shell:**
```python
# Instead of shell commands
import shutil
shutil.copy("source.txt", "dest.txt") # Instead of cp
import os
os.remove("file.txt") # Instead of rm
```
2. **Use `shlex` for cross-platform commands:**
```python
import shlex
import subprocess
cmd = shlex.split("git rev-parse HEAD")
result = subprocess.run(cmd, capture_output=True, encoding="utf-8")
```
3. **Check platform when needed:**
```python
import sys
if sys.platform == "win32":
# Windows-specific code
pass
else:
# Unix code
pass
```
## Development Environment
### Recommended Setup on Windows
1. **Use WSL2 (Windows Subsystem for Linux)** - Recommended:
- Most consistent with production Linux environment
- Full bash support
- Better performance for file I/O
- Install from Microsoft Store or: `wsl --install`
2. **Or use Git Bash:**
- Comes with Git for Windows
- Provides Unix-like shell
- Lighter than WSL
- Download from [gitforwindows.org](https://gitforwindows.org/)
3. **Or use PowerShell with Python:**
- Native Windows environment
- Requires extra care with paths/encoding
- Built into Windows
### Editor Configuration
**VS Code settings for Windows (`settings.json`):**
```json
{
"files.encoding": "utf8",
"files.eol": "\n",
"python.analysis.typeCheckingMode": "basic",
"editor.formatOnSave": true
}
```
## Common Issues and Solutions
### Issue: Permission errors when deleting files
**Problem:** Windows file locking is stricter than Unix.
**Solution:** Ensure files are properly closed using context managers:
```python
# Use context managers
with open(path, encoding="utf-8") as f:
data = f.read()
# File is closed here - safe to delete
```
### Issue: Long path names
**Problem:** Windows has a 260-character path limit (legacy).
**Solution:**
1. Enable long paths in Windows 10+ (Group Policy or Registry)
2. Or keep paths short
3. Or use WSL2
### Issue: Case-insensitive filesystem
**Problem:** Windows filesystem is case-insensitive
(`File.txt` == `file.txt`).
**Solution:** Be consistent with casing in filenames and imports:
```python
# Consistent casing
from apps.backend.core import Client # File: client.py
# Avoid mixing cases
from apps.backend.core import client # Could work on Windows but fail on Linux
```
## Testing Windows Compatibility
### Before Submitting a PR
1. **Run pre-commit hooks:**
```bash
pre-commit run --all-files
```
2. **Run all tests:**
```bash
npm run test:backend
npm test # frontend tests
```
3. **Test with special characters:**
```python
# Add test data with emoji, international chars
test_content = "Test 🚀 ñoño 中文 العربية"
```
### Windows-Specific Test Cases
Add tests for Windows compatibility when relevant:
```python
import sys
import pytest
@pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
def test_windows_encoding():
"""Test Windows encoding with special characters."""
content = "Test 🚀 ñoño 中文"
Path("test.txt").write_text(content, encoding="utf-8")
loaded = Path("test.txt").read_text(encoding="utf-8")
assert loaded == content
```
## Getting Help
If you encounter Windows-specific issues:
1. Check this guide and [CONTRIBUTING.md](../CONTRIBUTING.md)
2. Search [existing issues](https://github.com/AndyMik90/Auto-Claude/issues)
3. Ask in [discussions](https://github.com/AndyMik90/Auto-Claude/discussions)
4. Create an issue with `[Windows]` tag
## Resources
- [Python on Windows](https://docs.python.org/3/using/windows.html)
- [pathlib Documentation](https://docs.python.org/3/library/pathlib.html)
- [Git for Windows](https://gitforwindows.org/)
- [WSL2 Documentation](https://docs.microsoft.com/en-us/windows/wsl/)
## Related
- [CONTRIBUTING.md](../CONTRIBUTING.md) - General contribution
guidelines
- [PR #782](https://github.com/AndyMik90/Auto-Claude/pull/782) -
Comprehensive UTF-8 encoding fix
- [PR #795](https://github.com/AndyMik90/Auto-Claude/pull/795) -
Pre-commit hooks for encoding enforcement