Bug reporting system enabling collective intelligence through automated issue collection, deduplication, and submission.
This feature provides a comprehensive bug reporting system that:
- Captures errors automatically (uncaught exceptions, unhandled rejections)
- Allows manual bug reports via command
- Collects contextual data (logs, state, navigation history)
- Deduplicates reports across users (hash-based and AI semantic)
- Submits issues to GitHub via
ghCLI - Optionally uses AI to refine reports before submission
The feedback system distributes the cognitive load of issue management:
USER COMPUTE CONTRIBUTION
─────────────────────────────────────────────────────────────►
Raw Report → AI-Refined Report → Deduplicated Report
(minimal) (user's API key) (prevents duplicates)
Design Philosophy: Users who opt into AI refinement contribute their own compute to maintain a clean issue tracker. This follows the cultural norm of "search before posting" but automates it.
src/features/feedback/
├── store/
│ └── slice.ts # FeedbackSlice - preferences, modal state, rate limiting
├── services/
│ ├── error-capture-service.ts # Console capture, error handlers, local dedup
│ ├── feedback-service.ts # Orchestration, submission, cross-user dedup
│ └── issue-formatter-service.ts # Issue markdown formatting, hash computation
├── components/
│ └── FeedbackModal.tsx # Obsidian Modal for submission
├── settings-section.ts # Feature-owned settings panel UI
├── commands.ts # Report bug + test commands
├── index.ts # Barrel export
└── README.md # This file
import {
// Store
createFeedbackSlice,
FeedbackSlice,
FeedbackState,
CapturedError,
AutoReportPreference,
// Services
errorCaptureService,
feedbackService,
issueFormatterService,
// Components
FeedbackModal,
showFeedbackModal,
// Commands
registerFeedbackCommands,
// Settings
createFeedbackSettingsSection,
} from '../features/feedback';| Command ID | Name | Description |
|---|---|---|
interbrain:report-bug |
Report a Bug | Opens the feedback modal |
interbrain:test-feedback-* |
[Test] * | Debug commands for development |
The system uses two complementary deduplication strategies:
| Strategy | Trigger | Reliability | Use Case |
|---|---|---|---|
| Hash-based | Automatic (has stack trace) | High (deterministic) | Errors with programmatic context |
| AI Semantic | Manual + AI refinement enabled | Medium (probabilistic) | User-described issues without stack trace |
For errors with stack traces, a stable hash (IB-ERR-XXXXXXXX) is computed from:
- Error message
- First meaningful stack frame (file:line:col, path-normalized)
Flow:
Error with stack trace
↓
Compute hash: IB-ERR-a1b2c3d4
↓
Search GitHub for existing issue with this hash
↓
Found? → Add comment to existing issue
Not found? → Create new issue with hash in body
Cross-user example:
- Alice hits bug → hash
IB-ERR-a1b2c3d4computed - Issue #42 created with
**Error ID:** \IB-ERR-a1b2c3d4`` in body - Bob hits same bug → same hash computed
- GitHub search finds issue #42 by hash
- Bob's report added as comment to #42
For manual reports (no stack trace), when AI refinement is enabled:
Flow:
Manual report + AI refinement enabled
↓
Step 1: Generate AI title + summary for new report
↓
Step 2: Fetch 20 recent open bug issues from GitHub
↓
Step 3: Extract title + summary from existing issues
(AI-refined issues have "**Summary:**", raw issues use description)
↓
Step 4: AI compares refined report against existing issues
↓
Duplicate? → Add comment to existing issue
Novel? → Create new issue
Key Design Decisions:
- AI refines new report first: Ensures consistent semantic representation for comparison
- Handles mixed formats: Works whether existing issues are AI-refined or raw
- Conservative matching: Only matches clearly same bug, not vaguely related
- User opt-in: Only runs when AI refinement enabled (user's API key, user's compute)
- Uses Haiku: Fast and cost-efficient for dedup checks
Separate from cross-user dedup, local deduplication prevents modal spam:
- Same error hash within 60 seconds → silently ignored (no
onErrorcallback) - Modal throttle: 30 seconds between modal appearances
| Mechanism | Cooldown | Purpose |
|---|---|---|
| Modal throttle | 30s after modal shown | Prevents error loop spam |
| Session limit | Max 10 submissions | Prevents GitHub API abuse |
| Local dedup | 60s per error hash | Prevents duplicate modals |
All limits reset on plugin reload.
| Data | Source | Purpose |
|---|---|---|
| Error stack trace | Error object | Bug location, hash computation |
| Console logs (last 50) | Ring buffer | Execution context |
| Store state snapshot | Zustand | Reproduction state |
| System info | navigator + manifest | Environment |
| Navigation history | Store | User journey |
| Error hash | Computed | Cross-user dedup |
| User description | Manual input | Intent/expectation |
| Reproduction steps | Manual input (optional) | How to reproduce |
Never included in reports:
claudeApiKey- redacted from stateradiclePassphrase- redacted from state- Absolute file paths - only vault-relative paths
- User email - not collected
Sanitized store state includes:
- Layout mode, selected node (id/name/type only)
- Copilot mode (active status, partner redacted)
- Creation/edit/search state (active status only)
- Node count (not node contents)
| Setting | Type | Default | Description |
|---|---|---|---|
| Auto-report | 'always' | 'ask' | 'never' |
'ask' |
When to show modal |
| Include logs | boolean | true |
Include console buffer |
| Include state | boolean | true |
Include sanitized store |
- Structured markdown with all collected data
- No API key required
- Fast, deterministic output
- User-provided reproduction steps included (if any)
- Claude generates concise title and summary
- Categorizes issue (Bug/UX Issue/Performance/Crash)
- Estimates complexity (Trivial/Minor/Moderate/Complex)
- Enables AI semantic deduplication
- Requires Claude API key
AI Refinement Principles:
- AI enhances, never fabricates: Raw data always preserved in collapsible section
- No invented reproduction steps: Only user-provided steps are included
- No investigation suggestions: Maintainer has codebase context, AI doesn't
- Focused output: Title, summary, category, complexity only
The feedback modal collects:
- What happened? (required) - User description textarea
- Steps to reproduce (optional) - How to reproduce the issue
- Data toggles - Console logs, app state inclusion
- Submit options - Raw or AI-refined
Error occurs (uncaught/unhandled)
↓
ErrorCaptureService.handleCapturedError()
↓
shouldIgnoreError? → (yes) → silent ignore
↓ (no)
Track hash for local dedup
↓
Call onError callback (always - let modal throttle decide)
↓
Main.ts: Check user preference
↓
'never' → log only
'always'/'ask' → Check modal throttle
↓
Throttled? → Show notice once, then silent
↓ (not throttled)
Open FeedbackModal + record modal timestamp
FeedbackModal.submitReport(useAi)
↓
FeedbackService.submitReport()
↓
Collect feedback data (logs, state, system info, hash, repro steps)
↓
Check session limit
↓
checkForDuplicateByHash() → (found) → addCommentToIssue()
↓ (not found)
useAi && !hash? → checkForDuplicateByAi() → (found) → addCommentToIssue()
↓ (not found)
useAi? → formatWithAi() : formatRaw()
↓
createIssue()
↓
Return { success, issueUrl, wasDuplicate }
checkForDuplicateByAi(data)
↓
generateAiTitleAndSummary(data) → { title, summary }
↓
Fetch 20 open bug issues from GitHub
↓
For each issue: extract title + (summary OR first 200 chars of body)
↓
Send to Claude: "Is new report same problem as any existing?"
↓
AI responds: issue number OR "NEW"
↓
Match found? → return issue URL
No match? → return null (create new issue)
| Dependency | Required | Purpose |
|---|---|---|
gh CLI |
Yes | GitHub issue creation/search |
gh auth login |
Yes | Authentication |
| Claude API key | No | AI refinement + semantic dedup |
| System | Integration |
|---|---|
| Store | FeedbackSlice in InterBrainState |
| Settings | createFeedbackSettingsSection() in settings-tab.ts |
| Main | Error handlers in initializeErrorCapture() |
| Commands | registerFeedbackCommands() in main.ts |
Development commands (always registered, useful for debugging):
| Command | Purpose |
|---|---|
[Test] Trigger Error Capture |
Throw test error |
[Test] Manual Error Capture |
Capture without throwing |
[Test] Check Rate Limit Status |
Show throttle states |
[Test] Reset Rate Limits |
Clear all throttles |
[Test] View Captured Logs |
Show log buffer |
[Test] Debug Environment Detection |
Trace system info |
AI doesn't have context about what actions trigger bugs. Only the user knows what they did. Fabricated steps add noise and waste maintainer time verifying invalid reproductions.
AI lacks codebase knowledge. Generic suggestions ("check rendering pipeline") are less useful than maintainer's domain expertise. Removed to reduce noise.
Full AI refinement includes category, complexity, formatting. For dedup comparison, we only need title + summary. Separate lightweight call is faster and cheaper.
Early adopters use AI refinement, but raw issues from before exist. System extracts "Summary:" from AI-refined issues OR falls back to body text. This ensures Bob's AI-refined report matches Alice's raw issue.
Balances context size vs. token cost. Most duplicates are recent. Older issues likely have different underlying causes even if superficially similar.
Bundled code line numbers change with every build (plugin:interbrain:5954 vs plugin:interbrain:5980). This would defeat cross-version deduplication. We strip line numbers but keep function names, which are stable.
Known limitation: If two different bugs have identical error messages AND occur in anonymous functions (like eval), they may incorrectly deduplicate. In practice, real errors usually have named functions in the stack trace that provide differentiation. This is an acceptable trade-off for version-independent deduplication.
The feedback system is designed as a foundation for broader collective intelligence:
- Contribution axis: Raw → Refined → PR → Tested PR
- Complexity axis: Bug fix → Feature → Applet → DreamNode
Current implementation covers the leftmost point (bug reports). Architecture supports organic growth toward more sophisticated collaboration patterns.