33 * Sidebar panel showing vault statistics
44 */
55
6- import { ItemView , WorkspaceLeaf } from "obsidian" ;
6+ import { ItemView , TFile , WorkspaceLeaf } from "obsidian" ;
77import type ClawVaultPlugin from "./main" ;
88import { COMMAND_IDS , STATUS_VIEW_TYPE } from "./constants" ;
99import type { ObservationSession , ParsedTask , VaultStats } from "./vault-reader" ;
@@ -13,6 +13,8 @@ interface StatusViewData {
1313 backlogItems : ParsedTask [ ] ;
1414 recentSessions : ObservationSession [ ] ;
1515 openLoops : ParsedTask [ ] ;
16+ graphTypes : Record < string , number > ;
17+ todayObs : { count : number ; categories : string [ ] } ;
1618}
1719
1820/**
@@ -63,17 +65,21 @@ export class ClawVaultStatusView extends ItemView {
6365 this . statusContentEl . empty ( ) ;
6466
6567 try {
66- const [ stats , backlogItems , recentSessions , openLoops ] = await Promise . all ( [
68+ const [ stats , backlogItems , recentSessions , openLoops , graphTypes , todayObs ] = await Promise . all ( [
6769 this . plugin . vaultReader . getVaultStats ( ) ,
6870 this . plugin . vaultReader . getBacklogTasks ( 5 ) ,
6971 this . plugin . vaultReader . getRecentObservationSessions ( 5 ) ,
7072 this . plugin . vaultReader . getOpenLoops ( 7 ) ,
73+ this . plugin . vaultReader . getGraphTypeSummary ( ) ,
74+ this . plugin . vaultReader . getTodayObservations ( ) ,
7175 ] ) ;
7276 this . renderStats ( {
7377 stats,
7478 backlogItems,
7579 recentSessions,
7680 openLoops,
81+ graphTypes,
82+ todayObs,
7783 } ) ;
7884 } catch ( error ) {
7985 this . renderError ( error ) ;
@@ -85,7 +91,7 @@ export class ClawVaultStatusView extends ItemView {
8591 */
8692 private renderStats ( data : StatusViewData ) : void {
8793 if ( ! this . statusContentEl ) return ;
88- const { stats, backlogItems, recentSessions, openLoops } = data ;
94+ const { stats, backlogItems, recentSessions, openLoops, graphTypes , todayObs } = data ;
8995
9096 // Header
9197 const header = this . statusContentEl . createDiv ( { cls : "clawvault-status-header" } ) ;
@@ -103,6 +109,60 @@ export class ClawVaultStatusView extends ItemView {
103109 cls : "clawvault-status-counts" ,
104110 } ) ;
105111
112+ // Memory Graph section
113+ if ( stats . nodeCount > 0 || Object . keys ( graphTypes ) . length > 0 ) {
114+ const graphSection = this . statusContentEl . createDiv ( { cls : "clawvault-status-section" } ) ;
115+ graphSection . createEl ( "h4" , { text : "Memory Graph" } ) ;
116+
117+ const graphStats = graphSection . createDiv ( { cls : "clawvault-graph-stats" } ) ;
118+ graphStats . createDiv ( {
119+ text : `🔗 ${ this . formatNumber ( stats . nodeCount ) } nodes · ${ this . formatNumber ( stats . edgeCount ) } edges` ,
120+ cls : "clawvault-graph-totals" ,
121+ } ) ;
122+
123+ // Node type breakdown (top 5)
124+ const sortedTypes = Object . entries ( graphTypes )
125+ . sort ( ( a , b ) => b [ 1 ] - a [ 1 ] )
126+ . slice ( 0 , 6 ) ;
127+ if ( sortedTypes . length > 0 ) {
128+ const typeGrid = graphSection . createDiv ( { cls : "clawvault-graph-type-grid" } ) ;
129+ for ( const [ type , count ] of sortedTypes ) {
130+ const typeEl = typeGrid . createDiv ( { cls : "clawvault-graph-type-item" } ) ;
131+ typeEl . createSpan ( { text : `${ count } ` , cls : "clawvault-graph-type-count" } ) ;
132+ typeEl . createSpan ( { text : ` ${ type } ` , cls : "clawvault-graph-type-label" } ) ;
133+ }
134+ }
135+ }
136+
137+ // Today's observations
138+ if ( todayObs . count > 0 ) {
139+ const obsSection = this . statusContentEl . createDiv ( { cls : "clawvault-status-section" } ) ;
140+ obsSection . createDiv ( {
141+ text : `🔭 ${ todayObs . count } observation${ todayObs . count === 1 ? "" : "s" } today` ,
142+ cls : "clawvault-obs-today" ,
143+ } ) ;
144+ if ( todayObs . categories . length > 0 ) {
145+ obsSection . createDiv ( {
146+ text : `→ ${ todayObs . categories . join ( ", " ) } ` ,
147+ cls : "clawvault-obs-categories" ,
148+ } ) ;
149+ }
150+ }
151+
152+ // Kanban board link
153+ const boardFile = this . app . vault . getAbstractFileByPath ( "Board.md" ) ;
154+ if ( boardFile instanceof TFile ) {
155+ const kanbanSection = this . statusContentEl . createDiv ( { cls : "clawvault-status-section" } ) ;
156+ const kanbanLink = kanbanSection . createEl ( "a" , {
157+ text : "📋 Open Kanban Board" ,
158+ cls : "clawvault-kanban-link" ,
159+ } ) ;
160+ kanbanLink . addEventListener ( "click" , ( event ) => {
161+ event . preventDefault ( ) ;
162+ void this . app . workspace . openLinkText ( "Board.md" , "" , "tab" ) ;
163+ } ) ;
164+ }
165+
106166 // Tasks section
107167 if ( stats . tasks . total > 0 ) {
108168 const tasksSection = this . statusContentEl . createDiv ( { cls : "clawvault-status-section" } ) ;
0 commit comments