Knowledge Base tab: browse, edit, navigate & graph ~/Scout/knowledge-base/#69
Open
yustme wants to merge 17 commits into
Open
Knowledge Base tab: browse, edit, navigate & graph ~/Scout/knowledge-base/#69yustme wants to merge 17 commits into
yustme wants to merge 17 commits into
Conversation
New KnowledgeBase module mirroring the PerFileItems/Proposals conventions (service + actor writer + views): - KnowledgeBaseService: builds a recursive KBNode tree from the knowledge-base/ folder, kept in sync via FSEvents. - KnowledgeBaseFileWriter: whole-file save with a baseline-mtime conflict guard (surfaces concurrent plugin writes instead of clobbering), plus create/delete/rename. Each change is git-committed scoped to its path. - Views: two-pane browser (tree + editor) with search and "New note"; KBEditorView with Edit/Preview toggle, dirty tracking, reload, conflict alert and changed-on-disk banner; KBMarkdownPreview reading renderer. - Wired into AppState, MainWindowView (.knowledgeBase) and SidebarView. - Tests for the writer helpers, tree builder and markdown parser.
…metadata - KBMarkdownPreview renders GitHub-style tables as a grid (escaped-pipe aware), constrains prose to a reading column, and collapses the leading changelog/frontmatter into a 'History & properties' disclosure. - KBEditorView opens markdown in Preview by default; editing is one click. - Tests for table parsing, separator detection, escaped pipes, and the metadata partition.
…ch, overview - KnowledgeBaseService gains a wikilink index (stem→path, per-file out-links) rebuilt on reparse, plus resolveWikilink / outgoingLinks / backlinks / localGraph / graphStats / searchContent. - InlineMarkdownText: optional `kbWikilinkHandler` environment hook so KB wikilink clicks navigate in-app (falling back to Linear/Obsidian elsewhere). - KBRightPanel: Links/Graph toggle — outgoing links + backlinks (navigable), and a native SwiftUI Canvas force-directed local graph (pan/zoom, click to open, colored by entity type). - KBOverviewView: landing page with KB stats + quick-access tiles. - KnowledgeBaseView: three-pane layout, content search with snippets, wired wikilink navigation. - Tests: wikilink extraction, index/backlinks/local-graph/stats/search, layout.
- Add Grape (SwiftGraphs/Grape 1.x) as an SPM dependency. - Replace the hand-rolled Canvas force layout with Grape's ForceDirectedGraph (KBGraphCanvas): tap a node to navigate, drag to pan, pinch to zoom; nodes colored by entity type, labels gated by degree. - KnowledgeBaseService.fullGraph() powers a whole-KB graph on the overview. - Local graph (right panel) and global graph (overview) share KBGraphCanvas. - Tests: drop the old layout test, add a fullGraph test.
- KBTableBlockView: replace Grid (which let a long cell overflow onto following rows) with fixed-width columns + HStack rows whose height tracks the tallest cell. Per-column width derived from content, clamped and wrapped. - KBGraphCanvas: start zoomed in (initialModelTransform scale) and tune node radius/label fonts/forces so labels are readable, not microscopic. - Overview global graph: cap width and bump zoom so it isn't a tiny cluster lost in whitespace.
Switch from a View-closure annotation (rendered in fixed screen space, so labels stayed tiny when zooming) to the Text annotation overload, which Grape draws on the graph canvas and scales with the viewport transform.
Grape draws symbols/text at fixed pixel size — zoom only spreads positions, so labels stayed small. Read state.modelTransform.scale and multiply node radius and label font by it, so pinch-zoom actually enlarges nodes and text (Obsidian-like). State is Observable, so the graph re-renders on zoom.
Node drag is already supported (withGraphDragGesture pins the node under the cursor and moves it, releasing back into the simulation). Bump base node radius so the hit target is comfortable to grab with the mouse.
- KBLiveEditor: NSTextView-backed editor that styles markdown inline as you type (headings, bold/italic, code, [[wikilinks]], links, [#tags], tables, code fences; syntax markers dimmed) while keeping the text exact markdown — no round-trip, so the plugin's structured tokens are preserved. - KBEditorView: Read / Rich / Source toggle; markdown opens in Rich by default, YAML stays Source.
- KBDocSegment: parse the document into blocks with exact source line ranges, plus line-precise replaceLines / replaceCell splicers (cell pipe-escaping preserved). Only the edited block/cell is rewritten; the rest stays byte-identical for the plugin. - KBEditableView: the rendered document, editable in place — double-click a paragraph/heading/list/quote/code/table-cell to edit just that piece; single-click a [[wikilink]] still navigates. Leading frontmatter/changelog collapse into 'History & properties'. - KBEditorView: 'Read' is now this editable rendered view and the default mode; Rich (live markdown) and Source (raw) remain. - Tests for segment ranges and the splicers.
contentsOfDirectory returns symlink-resolved file URLs, but scoutDirectory kept the symlink path (~/Scout -> repos/SuperScout), so the in-KB prefix guard and repo-relative paths mismatched and every save/commit was rejected. Resolve symlinks for the KB service + writer roots and in the guard/relative-path helpers so both sides use the real path.
- PaneResizeHandle: drag the Links/Graph panel's left edge to resize (220–640pt, resize cursor on hover); width persisted via @AppStorage. - Right-panel graph rebuilds (re-centered, fresh simulation) whenever the open note changes via .id(relPath), so it always reflects the current page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Knowledge Base tab — browse, read, edit, and navigate
~/Scout/knowledge-base/Adds a full Knowledge Base section to Scout.app: a file browser + reader + in-place editor + link/graph explorer over the plugin's
knowledge-base/vault. Built to match the existing module conventions (service + actor writer + views), the editorial design system, FSEvents live-reload, and guarded + git-committed writes.Reading
[[wikilinks]].[[people\|Alias]]), with per-column widths and horizontal scroll.**Last updated:** / **Prev:** / **Parent:**changelog and YAML frontmatter fold into a closed "History & properties" disclosure so the substance is on top.Editing (three modes: Read / Rich / Source)
[[wikilink]]still navigates.[[wikilinks]],[#tags], tables, code fences; syntax markers dimmed). No round-trip, so nothing is reformatted.Navigation, search & graph
[[wikilink]]navigation (falls back to Linear/Obsidian for non-KB targets) via an environment hook onInlineMarkdownText.Shell wiring
AppStateregisters the KB service + writer;MainWindowViewadds the.knowledgeBasedetail;SidebarViewadds the row.Infrastructure
SwiftGraphs/Grape) as an SPM dependency for the graph.ci.yml): runsScoutTestsand, in a parallel job, builds and uploads an unsignedScout.appartifact so the app can be downloaded and run without a local Xcode.Tests
ScoutTests/KnowledgeBase/KnowledgeBaseTests.swiftcovers the pure logic:KBDocSegmentblock parsing with source line ranges and thereplaceLines/replaceCellsplicers (multi-line, out-of-range, pipe-escaping).Notes
~/Scout(the vault is a symlink torepos/SuperScout):contentsOfDirectoryreturns symlink-resolved file URLs, so the in-KB guard and git-relative paths now resolve symlinks on both sides.CLAUDE.md).