- Status:
Open| Priority:P1| Labels:Stability,Bug - Created: 2026-04-10
- Description: Models (especially larger ones like Qwen 3.5) occasionally return the JSON schema definition or a malformed object instead of just the values.
- Example:
Raw: {"type":"object","properties":{...}}instead of the expected result object. - Root Cause: The system prompt instructions for
json_objectmode are being misinterpreted by some models as a request to echo the schema.
- Status:
Open| Priority:P1| Labels:Reliability,Bug - Created: 2026-04-10
- Description: When RAG is enabled, the total request time can exceed 60-90 seconds, causing the connection to drop or the cloud provider to return an empty body.
- Proposed Fix: Implement an auto-retry logic in
enrichBlockClientor move the timeout handling to the server-side proxy.
- Status:
Open| Priority:P2| Labels:RAG,Feature - Created: 2026-04-10
- Description: Currently, the entire
userMessage(including XML tags and page context) is sent to the search engine. - Proposed Fix: Use a fast model to distill the note text into 1-3 crisp search queries before calling
/api/web_search.
- Status:
Closed| Resolved: 2026-05-12 | Priority:P3| Labels:UI,Tech-Debt - Created: 2026-04-10
- Summary: Fixed. Root cause was
useModKey()inlib/utils.tsinitializing as'⌘'on the server but correcting to'Ctrl'on non-Mac clients after mount — React flagged this on every page load on Windows. Thefdprocessedidattributes from browser extensions were a red herring; React reported them as the mismatch location but they were not the cause. Also fixeduseElapsed()insynthesis-progress-panel.tsxwhich initialized state withDate.now(), always producing different values on server vs client. - Fix: Added
suppressHydrationWarningto the keyboard hint elements invim-input.tsx,tiling-area.tsx,kanban-area.tsx, andgraph-area.tsx. ChangeduseElapsedinitial state fromDate.now()to0.
- Status:
Open| Priority:P1| Labels:Feature,Multi-modal - Created: 2026-04-12
- Description: Enable the AI to process images and videos alongside text notes. This transforms nodepad into a perceptual extension, allowing for visual anchors in spatial memory, OCR for handouts/math, and vision-based reasoning (e.g., analyzing D&D maps or physics diagrams).
- Status:
Open| Priority:P2| Labels:Architecture,Storage - Created: 2026-04-12
- Description: Transition from
localStoragetoIndexedDBfor storing large media assets (images/videos). This is necessary to avoid hitting the 5MB browser storage limit when implementing multi-modal support.
- Status:
Open| Priority:P1| Labels:Feature,UX,AI - Created: 2026-04-12
- Description: A top-down synthesis engine that allows users to query their entire workspace (all 100+ nodes) rather than just recent context.
- Proposed Implementation:
- Command-Based: Use
/askor/draftin the command bar to trigger operations. - Query Panel: A dedicated sidebar (extending the Synthesis Panel) for long-form responses, outlines, and summaries.
- Spatial Grounding: Interactive citations in AI output that dim the canvas and highlight the specific source nodes when hovered/clicked.
- Note Conversion: "Pin to Canvas" button to turn an AI response into a permanent #thesis node.
- Command-Based: Use
- Design Philosophy: Must avoid the "Chatbot" anti-pattern. The AI remains a partner that operates on the spatial map, not a conversational agent.
- Open Question: Should a spatial canvas do more than just pin notes? Is a "query" function the right path, or should the AI interact more directly with the spatial arrangement (e.g., semantic clustering or "lenses" as an answer)?
- Status:
Open| Priority:P3| Labels:UX,Core - Created: 2026-04-12
- Description: Allow the AI to interact with the UI via natural language commands (e.g., "Highlight all notes related to Thermodynamics" or "Group all task nodes in the top right"). This reduces the manual labor of organizing large canvases.
- Status:
Closed| Resolved: 2026-05-07 - Labels:
Security,Tech-Debt,Windows - Summary: Resolved the Node.js deprecation warning (DEP0190) related to spawning child processes with
shell: trueand multiple arguments. - Technical Highlights:
- Safe Command Construction: Implemented manual escaping and quoting for CLI arguments.
- Single-String Spawning: Refactored
spawncalls to pass a single command string, satisfying Node.js 22+ security requirements while maintaining Windows compatibility for.ps1scripts.
- Status:
Closed| Resolved: 2026-05-07 - Labels:
UI,UX,Gemini-CLI - Summary: Improved the UI integration and configuration model for the Gemini CLI provider.
- Technical Highlights:
- Model Label Visibility: Fixed a bug where the model name was hidden in the status bar due to the absence of an API key.
- Gemini Auto Selection: Simplified the configuration to a single "Gemini Auto" model, reflecting the CLI's internal model optimization.
- Consistency: Ensured "Gemini Auto" is correctly reflected in both the Settings panel and the Status Bar.
- Status:
Closed| Resolved: 2026-04-10 - Labels:
Core,Feature,Architecture - Summary: Integrated Ollama as a hybrid provider. Implemented intelligent routing that automatically detects if a model is Local or Cloud (via
remote_hostmetadata) and routes requests to the correct host (ollama.comvslocalhost) dynamically.
- Status:
Closed| Resolved: 2026-04-10 - Labels:
Architecture,Security,API - Summary: Built
app/api/ai/route.tswith dual functionality: aGEThandler for dynamic model discovery (zero-config) and aPOSThandler to bypass browser CSP/CORS blocks. Implemented discovery persistence vialocalStorageto ensure dynamic metadata is available to core application logic.
- Status:
Closed| Resolved: 2026-04-10 - Labels:
RAG,Feature - Summary: Built a hybrid RAG pipeline: Live search via Ollama Cloud API -> Local vectorization via
embeddinggemma-> Cloud-based response generation.
- Status:
Closed| Resolved: 2026-04-10 - Labels:
Performance,Optimization - Summary: Switched from sequential embedding calls to Batch Embedding via
/api/embed, reducing RAG processing time by over 60%.
- Status:
Closed| Resolved: 2026-04-10 - Labels:
DX,Logging - Summary: Added structured terminal logs with nanosecond-precision timing (extracted from Ollama
total_duration) to track internal model time vs. wall-clock overhead.
- Status:
Closed| Resolved: 2026-04-10 - Labels:
UI,UX,Safety - Summary: Integrated the RAG toggle for Ollama with a model dependency check. If
embeddinggemmais missing locally, the toggle is disabled with a prompt to runollama pull embeddinggemma. Improved UI by removing redundant model icons and adding a loading state for discovery.
- Status:
Closed| Resolved: 2026-04-11 - Labels:
Security,Architecture - Summary: Merged security best practices from community PRs (#16, #20). Implemented an Auth Guard (stripping keys for localhost), SSRF Protection (port/protocol allowlisting), and Same-Origin Enforcement. Fixed a 403 error in discovery by standardizing the same-origin validation logic.
- Status:
Closed| Resolved: 2026-05-06 - Labels:
Bug,UI,UX - Summary: Fixed a race condition in the settings sidebar where background Ollama model discovery would overwrite the user's active provider selection. Modified
ProjectSidebar.tsxto only synchronize the local draft state when the settings panel is first opened.
- Status:
Closed| Resolved: 2026-05-06 - Labels:
Core,Feature,Architecture - Summary: Integrated Gemini CLI as a premium AI provider, enabling access to Gemini 3 Pro and Flash models without external API keys.
- Technical Highlights:
- Stdin Piping: Bypassed Windows shell character limits by streaming high-context prompts directly to
stdin. - Pure LLM Mode: Optimized for performance and capacity by disabling agentic behavior via the
--policy simpleflag. - Structured Output: Implemented robust JSON extraction from CLI response wrappers.
- UI Enhancements: Added automated keyless authentication UI logic and real-time terminal logging.
- Stdin Piping: Bypassed Windows shell character limits by streaming high-context prompts directly to
- Status:
Closed| Resolved: 2026-05-06 - Labels:
RAG,Feature,Automation - Summary: Implemented a context-aware, two-stage web-grounding pipeline leveraging Gemini CLI's native tool-use capabilities (
google_web_search,web_fetch). - Technical Highlights:
- Autonomous Two-Stage Pipeline:
- Stage 1 (Research): Uses the model's native agentic tools with the full nodespace context to perform deep research and synthesize a factual report.
- Stage 2 (Enrichment): Injects the research into the prompt as verified context and generates the final structured JSON using a restricted
simplepolicy.
- Model Autonomy: Removed explicit model selection flags, allowing the CLI to optimize between Pro and Flash models based on capacity.
- High-Signal Logging: Implemented JSON parsing of CLI stats to provide clean, Ollama-style terminal logs for tool usage.
- Robust Windows Handling: Increased timeouts to 8 minutes and implemented non-blocking cleanup to prevent
EBUSYresource locks. - UI Integration: Added a dedicated web-grounding toggle and descriptive feedback in the sidebar settings.
- Autonomous Two-Stage Pipeline:
- Status:
Closed| Resolved: 2026-05-11 - Labels:
Feature,Obsidian,Architecture - Summary: Ported the nodepad React UI into Obsidian as a first-class plugin using the
TextFileViewAPI..nodepadfiles live directly in the vault and auto-save on every state change. All three view modes (Tiling, Kanban, Graph) render inside an Obsidian leaf, themed via Obsidian's own CSS variables. - Technical Highlights:
plugin/src/main.ts— registers.nodepadextension, ribbon icon, command palette entry, folder right-click menuplugin/src/view.tsx— mounts React into the Obsidian leaf, reads/writes vault file viarequestSave()plugin/src/styles.css— maps Tailwind tokens to Obsidian CSS variables; SVG and button!importantoverrides for Obsidian CSS cascade conflictsplugin/esbuild.config.mjs— CJS bundle of all sharedlib/andcomponents/from the local fork via path aliases- Component patches —
isPluginmode inVimInput(hides Projects nav), portal scoping inStatusBar,AboutPanel,Sheet; transparent SVG<rect>fix for graph pan/zoom; minimap inline padding override
- Status:
Closed| Resolved: 2026-05-11 - Labels:
Feature,Obsidian,UX - Summary: Implemented an in-Obsidian settings tab (Settings → Nodepad) for all five AI providers. Settings stored in
.obsidian/plugins/nodepad/data.json, local to the vault. - Technical Highlights:
- Provider dropdown (OpenRouter, OpenAI, Z.ai, Ollama, Gemini CLI) with per-provider key persistence via
providerKeysrecord - API key field with eye icon toggle (hidden for keyless providers); Ollama model auto-discovery on switch
- Web-grounding toggle with provider-specific descriptions for all applicable providers
- Provider dropdown (OpenRouter, OpenAI, Z.ai, Ollama, Gemini CLI) with per-provider key persistence via
- Status:
Closed| Resolved: 2026-05-11 - Labels:
Feature,Obsidian,Architecture - Summary: Generic
spawnCLI()subprocess helper inplugin/src/ai-adapter.tsthat enables CLI tools (Gemini CLI, future Claude Code) to be invoked directly from Obsidian's Electron environment. - Technical Highlights:
- Stdin piping for high-context prompts (bypasses Windows argument length limits)
- JSON wrapper extraction from CLI response formats
- 8-minute timeout with non-blocking cleanup to prevent
EBUSYresource locks on Windows
- Status:
Closed| Resolved: 2026-05-11 - Labels:
Feature,Obsidian,Ollama - Summary: Enabled Ollama (local and Cloud) with Hybrid RAG in the Obsidian plugin.
requestUrl()in Obsidian's Electron bypasses CORS, so local Ollama works directly without a proxy. - Technical Highlights:
- Local vs Cloud routing; dynamic model discovery via
/api/tags - Hybrid RAG pipeline (web search →
embeddinggemmavectorization → cosine similarity → top-5 injection) ported from web app server route to plugin adapter getProviderHeaders()for correctAuthorizationhandling per routing mode
- Local vs Cloud routing; dynamic model discovery via
- Status:
Closed| Resolved: 2026-05-11 - Labels:
Feature,Obsidian,Gemini-CLI - Summary: Enabled Gemini CLI as a provider inside Obsidian via the
child_processbridge. Web grounding runs natively inside the CLI (no separate RAG pass needed). - Technical Highlights:
- Two-stage pipeline (Stage 1: agentic web research; Stage 2:
--policy simplestructured JSON enrichment) - Keyless auth detection in settings UI; graceful error if
geminibinary not on PATH - JSON stats parsing for Ollama-style terminal logs (tool usage, model selection)
- Two-stage pipeline (Stage 1: agentic web research; Stage 2:
- Status:
Closed| Resolved: 2026-05-12 | Labels:Bug,Stability - Summary:
confidenceBar()inlib/export.tstreated confidence as a[0, 1]decimal, but the codebase stores it as an integer percentage[0–100]. Exporting any project with an AI-enriched claim block crashed withRangeError: Invalid count valueonString.repeat(). Only reproducible with larger workspaces because the confidence bar is only rendered forclaim-typed blocks, which are more likely to be AI-enriched in bigger projects. - Fix: Corrected
confidenceBarto useMath.round(c)for the percentage andMath.round(c / 20)for the filled segment count.
- Status:
Closed| Resolved: 2026-05-03 - Labels:
Bug,Stability,UI - Summary: Fixed a runtime crash where
TileCardand other UI components failed when encountering unknown content types hallucinated by the LLM. ImplementedgetSafeContentTypeConfigand added input validation.
- Status:
Closed| Resolved: 2026-05-12 | Priority:P2| Labels:Feature,AI - Created: 2026-05-11 | Web-app resolved: 2026-05-11
- Design spec:
docs/synthesis-document-plan.md - Description: On-demand command ("Generate Synthesis Document") that consolidates enriched nodes from a
.nodepadcanvas into a structured, contextualized Obsidian markdown document. Unlike the raw markdown export which dumps nodes grouped by type, this pipeline expands sparse notes into self-contained statements, clusters them into coherent thematic sections by meaning, and adds expounding prompts that push thinking into adjacent territory the notes don't cover. Acts as the bridge from nodepad's raw idea staging area into Obsidian's permanent knowledge graph. - Pipeline:
- Phase 0 (human): User adds a
reference/entitynode naming the source material. No code needed. - Phase 1 (no AI): Build edge map from
influencedByIndicesgraph; detect source anchor nodes. - Phase 2a + 2b (parallel AI calls): Decontextualize each node into a self-contained statement (Call A) while simultaneously clustering nodes into named sections (Call B).
- Phase 2c (sequential AI call): Merge A + B results; generate section intros, expounding prompts, gap markers, and overall summary.
- Phase 3 (no AI): Render to Obsidian-native markdown, inject
[[wikilinks]], write to vault. - Phase 4 (human + external tools): User reviews output against source material via Claude Code, Gemini CLI, or NotebookLM. No code needed.
- Phase 0 (human): User adds a
- New files:
plugin/src/synthesis.ts— pipeline orchestrationlib/synthesis-export.ts— Phase 3 markdown renderer
- Modified files:
plugin/src/main.ts— register commandplugin/src/view.tsx— exposegenerateSynthesisDocument()on the viewplugin/src/ai-adapter.ts— addcallDecontextualize,callCluster,callSynthesize
- Status:
Open| Priority:P3| Labels:Feature,Obsidian,UX - Created: 2026-05-11
- Description: Phase 4 of the Synthesis Document pipeline — reviewing the generated document against the source material and making corrections. This requires no plugin code: the output is a standard Obsidian markdown file that any AI tool with vault access (Claude Code, Gemini CLI, NotebookLM) can read, annotate, and help correct. The review process itself is pedagogically valuable — identifying and correcting AI errors demonstrates understanding of the source material. If a built-in review UI is later desired (diff view, section toggles), it can be added as a separate issue.
- Status:
Planned| Priority:P2| Labels:Feature,AI,Claude-Code - Created: 2026-05-11
- Description: Integrate the
claudeCLI (Claude Code) as a local AI provider for both the web app and the Obsidian plugin. Claude Code authenticates via local account credentials — no API key required. Uses the samechild_processbridge established in #024 for the plugin, and the existing/api/aiserver route for the web app. - Scope:
claude --print "<prompt>" --output-format jsonfor non-interactive enrichment- Web grounding via Claude Code's built-in web access (
--allowedTools web_search) - Settings UI: no API key field; binary detection and auth status indicator
- Shared
child_processhelper reused from Gemini CLI implementation (#024)
- Prerequisite: #024 (CLI Provider Bridge) must be complete first.