@powerhousedao/knowledge-note 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/README.md +359 -122
  2. package/dist/editors/knowledge-vault/components/DriveExplorer.d.ts.map +1 -1
  3. package/dist/editors/knowledge-vault/components/DriveExplorer.js +8 -2
  4. package/dist/editors/knowledge-vault/components/SearchView.d.ts +2 -0
  5. package/dist/editors/knowledge-vault/components/SearchView.d.ts.map +1 -0
  6. package/dist/editors/knowledge-vault/components/SearchView.js +96 -0
  7. package/dist/editors/knowledge-vault/hooks/use-graph-search.d.ts +25 -0
  8. package/dist/editors/knowledge-vault/hooks/use-graph-search.d.ts.map +1 -0
  9. package/dist/editors/knowledge-vault/hooks/use-graph-search.js +207 -0
  10. package/dist/package.json +2 -1
  11. package/dist/processors/graph-indexer/embedder.d.ts +5 -0
  12. package/dist/processors/graph-indexer/embedder.d.ts.map +1 -0
  13. package/dist/processors/graph-indexer/embedder.js +27 -0
  14. package/dist/processors/graph-indexer/embedding-store.d.ts +11 -0
  15. package/dist/processors/graph-indexer/embedding-store.d.ts.map +1 -0
  16. package/dist/processors/graph-indexer/embedding-store.js +70 -0
  17. package/dist/processors/graph-indexer/index.d.ts.map +1 -1
  18. package/dist/processors/graph-indexer/index.js +48 -0
  19. package/dist/processors/graph-indexer/migrations.d.ts.map +1 -1
  20. package/dist/processors/graph-indexer/migrations.js +35 -0
  21. package/dist/processors/graph-indexer/query.d.ts +21 -0
  22. package/dist/processors/graph-indexer/query.d.ts.map +1 -1
  23. package/dist/processors/graph-indexer/query.js +154 -13
  24. package/dist/processors/graph-indexer/schema.d.ts +11 -0
  25. package/dist/processors/graph-indexer/schema.d.ts.map +1 -1
  26. package/dist/style.css +63 -0
  27. package/dist/subgraphs/knowledge-graph/subgraph.d.ts +321 -12
  28. package/dist/subgraphs/knowledge-graph/subgraph.d.ts.map +1 -1
  29. package/dist/subgraphs/knowledge-graph/subgraph.js +237 -15
  30. package/package.json +2 -1
package/README.md CHANGED
@@ -1,179 +1,416 @@
1
- # Document Model Boilerplate
1
+ # bai-knowledge-note
2
2
 
3
- This Document Model Boilerplate provides code generation for scaffolding editors and models.
4
- It ensures compatibility with host applications like Connect and the Reactors for seamless document model and editor integration.
3
+ A Powerhouse Vetra package for team-wide institutional memory atomic knowledge notes with typed content, structured links, lifecycle states, and provenance tracking.
5
4
 
6
- ## Standard Document Model Workflow with help of the boilerplate.
7
- This tutorial will guide you through the process of creating a new document model using the Document Model Editor in the Connect app.
5
+ ## Architecture
8
6
 
9
- <details>
10
- <summary>Available NPM commands</summary>
7
+ ```
8
+ bai-knowledge-note/
9
+ ├── document-models/ 11 document models (data schemas + reducers)
10
+ ├── editors/ 10 editors + 1 drive-app (UI layer)
11
+ ├── processors/ Graph indexer (data pipeline)
12
+ ├── subgraphs/ Knowledge graph (GraphQL query API)
13
+ ├── powerhouse.manifest.json
14
+ └── powerhouse.config.json
15
+ ```
11
16
 
12
- - `generate`: Updates the generated code according to the JSON spec and GraphQL schema of your document model, made in Connect.
13
- - `lint`: Checks for errors with ESLint and TypeScript checking.
14
- - `format`: Formats the code using Prettier.
15
- - `build`: Builds the library project using Vite.
16
- - `storybook`: Starts Storybook in development mode.
17
- - `build-storybook`: Builds Storybook.
18
- - `test`: Runs Jest for testing.
17
+ ## Document Models
19
18
 
20
- </details>
19
+ 11 document types defining the knowledge vault's data layer:
21
20
 
22
- ### 1. Defining Your Document Model GraphQL Schema
23
- Start by creating your own 'Powerhouse Project' (Document model + editor).
21
+ | Model | Type | Role |
22
+ |-------|------|------|
23
+ | **KnowledgeNote** | `bai/knowledge-note` | Atomic knowledge claims with title, content, typed links, topics, provenance |
24
+ | **Moc** | `bai/moc` | Maps of Content — topic navigation hubs organizing notes into clusters |
25
+ | **Source** | `bai/source` | Raw ingested material (articles, transcripts, documentation) |
26
+ | **ResearchClaim** | `bai/research-claim` | Ars Contexta methodology foundation (249 claims) |
27
+ | **KnowledgeGraph** | `bai/knowledge-graph` | Materialized graph singleton |
28
+ | **PipelineQueue** | `bai/pipeline-queue` | Processing task tracker singleton |
29
+ | **HealthReport** | `bai/health-report` | Point-in-time vault diagnostics |
30
+ | **VaultConfig** | `bai/vault-config` | Vault configuration singleton |
31
+ | **Observation** | `bai/observation` | Operational learning signals |
32
+ | **Tension** | `bai/tension` | Unresolved contradictions between claims |
33
+ | **Derivation** | `bai/derivation` | Configuration audit trail |
24
34
 
25
- Step 1: Run the following command to set up your project inside this directory:
35
+ Each model lives in `document-models/<name>/v1/` with `gen/` (auto-generated types, action creators) and `src/` (hand-written reducers).
26
36
 
27
- ```bash
28
- npm create document-model-lib
29
- ```
37
+ ## Editors
30
38
 
31
- Step 2: Use the Document Model Editor in the Connect app
39
+ React components for viewing and editing each document type. All editors use the `useSelectedXDocument()` hook pattern from `@powerhousedao/reactor-browser` which returns `[document, dispatch]`.
32
40
 
33
- The following command gives you access to all the powerhouse CLI tools available, install it globally if you are a poweruser.
41
+ ### Drive App: Knowledge Vault
34
42
 
35
- ```bash
36
- npm install ph-cmd
37
- ```
38
- Now you are able to launch Connect in Studio Mode (Locally):
43
+ The main entry point (`editors/knowledge-vault/`). Registered as a drive-app in the manifest — this is what users see when they open the drive in Connect. Features:
39
44
 
40
- ```bash
41
- npm run connect
45
+ - **Notes tab** — Paginated grid of NoteCards with status badges, topics, and link counts
46
+ - **Graph tab** — Cytoscape.js visualization with fcose layout, semantic clustering around MOC hubs, position persistence across sessions, and cross-cluster edge separation
47
+ - **Sources tab** — Ingested source material with status tracking
48
+ - **Pipeline tab** — Processing queue with phase tracking
49
+ - **Health tab** — Vault diagnostics dashboard
50
+ - **Config tab** — Vault configuration
51
+
52
+ ### Document Editors
53
+
54
+ | Editor | Document Type | Purpose |
55
+ |--------|--------------|---------|
56
+ | `knowledge-note-editor` | `bai/knowledge-note` | Textarea editor with markdown preview, links section, topic management |
57
+ | `moc-editor` | `bai/moc` | Core ideas, tensions, open questions, child MOC references |
58
+ | `source-editor` | `bai/source` | Source ingestion with content preview and extraction stats |
59
+ | `research-claim-editor` | `bai/research-claim` | Methodology claim viewer |
60
+ | `health-report-editor` | `bai/health-report` | Health check results |
61
+ | `pipeline-queue-editor` | `bai/pipeline-queue` | Task queue management |
62
+ | `observation-editor` | `bai/observation` | Operational signals |
63
+ | `tension-editor` | `bai/tension` | Contradiction tracking |
64
+ | `vault-config-editor` | `bai/vault-config` | Configuration management |
65
+ | `knowledge-graph-editor` | `bai/knowledge-graph` | Graph document viewer |
66
+
67
+ ## Processor: Graph Indexer
68
+
69
+ The data pipeline that turns document operations into a queryable relational index (`processors/graph-indexer/`).
70
+
71
+ ### How it works
72
+
73
+ **Registration:** `processors/factory.ts` → `graph-indexer/factory.ts` — called once per drive on startup. Creates a namespaced PGlite store (`GraphIndexerProcessor_<driveId>`) and registers a filter for `bai/knowledge-note` + `powerhouse/document-drive` operations.
74
+
75
+ **Processing:** `onOperations()` is called whenever matching operations occur:
76
+
77
+ 1. **Deduplicates** — keeps only the last operation per document in a batch
78
+ 2. **Handles deletions** — `DELETE_NODE` on the drive removes the node + all edges from the index
79
+ 3. **Filters** — skips anything that isn't `bai/knowledge-note`
80
+ 4. **Reconciles** — for each changed document, reads `context.resultingState`:
81
+ - Upserts into `graph_nodes` (id, title, description, noteType, status)
82
+ - Deletes old edges for that source document
83
+ - Inserts new edges from the note's `links[]` array
84
+
85
+ **Schema:**
86
+
87
+ ```
88
+ graph_nodes: id, document_id, title, description, note_type, status, updated_at
89
+ graph_edges: id, source_document_id, target_document_id, link_type, target_title, updated_at
42
90
  ```
43
91
 
44
- Open the 'Document Model' creator at the bottom of connect to define your document mode with it's GraphQL Schema Definition.
45
- This schema will define the structure and fields for your document model using GraphQL.
46
- Follow one of our tutorials on Academy to get familiar with the process.
92
+ Indexes on `source_document_id`, `target_document_id`, and `status` for query performance.
47
93
 
48
- ### 2. Defining Document Model Operations
49
- Using the Document Model Operations Editor, define the operations for your document model and their GraphQL counterparts.
50
- These operations will handle state changes within your document model.
94
+ **On disconnect:** No-op — preserves indexed data across restarts. The reactor does not replay historical operations, so wiping tables would leave the index permanently empty.
51
95
 
52
- **Best Practices:**
96
+ ## Subgraph: Knowledge Graph
53
97
 
54
- - Clearly define CRUD operations (Create, Read, Update, Delete).
55
- - Use GraphQL input types to specify the parameters for each operation.
56
- - Ensure that operations align with user intent to maintain a clean and understandable API.
98
+ GraphQL query layer exposing the indexed data (`subgraphs/knowledge-graph/`). Registered at `/graphql/knowledgeGraph`.
57
99
 
58
- ### 3. Generating Scaffolding Code
59
- Export your document model as a .zip file from Connect.
60
- Import the .zip file into your project directory created in Step 1.
61
- Run the following command to generate the scaffolding code:
100
+ ### Queries
62
101
 
63
- ```bash
64
- npm run generate YourModelName.phdm.zip
102
+ | Query | Description |
103
+ |-------|-------------|
104
+ | `knowledgeGraphNodes(driveId)` | All indexed nodes |
105
+ | `knowledgeGraphEdges(driveId)` | All indexed edges |
106
+ | `knowledgeGraphStats(driveId)` | Node count, edge count, orphan count |
107
+ | `knowledgeGraphSearch(driveId, query, limit?)` | Text search on title + description |
108
+ | `knowledgeGraphOrphans(driveId)` | Nodes with no incoming edges |
109
+ | `knowledgeGraphConnections(driveId, documentId, depth?)` | BFS traversal from a node |
110
+ | `knowledgeGraphBacklinks(driveId, documentId)` | Edges pointing TO a document |
111
+ | `knowledgeGraphForwardLinks(driveId, documentId)` | Edges pointing FROM a document |
112
+ | `knowledgeGraphTriangles(driveId, limit?)` | Pairs that share a target but aren't linked |
113
+ | `knowledgeGraphBridges(driveId)` | Articulation points that connect clusters |
114
+ | `knowledgeGraphDensity(driveId)` | Graph density metric |
115
+ | `knowledgeGraphDebug(driveId)` | Raw DB rows for debugging |
116
+
117
+ ### Mutations
118
+
119
+ | Mutation | Description |
120
+ |----------|-------------|
121
+ | `knowledgeGraphReindex(driveId)` | Backfill the index by reading all notes — use when the processor missed historical operations |
122
+
123
+ ## Deep Dive: Processor + Subgraph Architecture
124
+
125
+ ### The Problem They Solve
126
+
127
+ Powerhouse documents are stored as **operation logs** (event sourcing). To read a note's title, you replay all its operations to reconstruct the current state. This works for individual documents, but becomes expensive when you need to:
128
+
129
+ - Search across 500+ notes by keyword
130
+ - Find all notes linking to a specific note
131
+ - Calculate graph metrics (density, orphans, bridges)
132
+ - Render a graph visualization of all notes and edges
133
+
134
+ Without an index, every query would require loading and replaying every document in the drive. The processor + subgraph pattern solves this by maintaining a **materialized read model** — a relational projection of document state that's always up to date.
135
+
136
+ ### How the Processor Works (Write Path)
137
+
138
+ The `GraphIndexerProcessor` sits between the Reactor and a PGlite relational database. It implements the `RelationalDbProcessor` base class from `@powerhousedao/shared/processors`.
139
+
140
+ ```
141
+ ┌─────────────────────────────────────────────────────┐
142
+ │ Reactor │
143
+ │ │
144
+ │ Document A ──op──▶ ┌───────────────────────────┐ │
145
+ │ Document B ──op──▶ │ GraphIndexerProcessor │ │
146
+ │ Document C ──op──▶ │ │ │
147
+ │ Drive (delete)──op─▶│ filter: │ │
148
+ │ │ bai/knowledge-note │ │
149
+ │ │ powerhouse/document-drive│ │
150
+ │ │ │ │
151
+ │ │ onOperations(ops[]): │ │
152
+ │ │ 1. deduplicate │ │
153
+ │ │ 2. handle deletions │ │
154
+ │ │ 3. upsert graph_nodes │ │
155
+ │ │ 4. reconcile graph_edges │ │
156
+ │ └──────────┬────────────────┘ │
157
+ │ │ │
158
+ │ ┌──────────▼────────────────┐ │
159
+ │ │ PGlite (namespaced) │ │
160
+ │ │ │ │
161
+ │ │ graph_nodes │ │
162
+ │ │ id, document_id, title │ │
163
+ │ │ description, note_type │ │
164
+ │ │ status, updated_at │ │
165
+ │ │ │ │
166
+ │ │ graph_edges │ │
167
+ │ │ id, source_document_id │ │
168
+ │ │ target_document_id │ │
169
+ │ │ link_type, target_title │ │
170
+ │ └───────────────────────────┘ │
171
+ └─────────────────────────────────────────────────────┘
65
172
  ```
66
173
 
67
- This will create a new directory under /document-models containing:
174
+ **Key design decisions:**
68
175
 
69
- JSON file with the document model specification.
70
- GraphQL file with state and operation schemas.
71
- A gen/ folder with autogenerated code.
72
- A src/ folder for your custom code implementation.
176
+ 1. **Filter-based subscription** The processor declares interest in specific document types and scopes. The Reactor only sends matching operations, avoiding unnecessary work:
177
+ ```typescript
178
+ const filter: ProcessorFilter = {
179
+ branch: ["main"],
180
+ documentId: ["*"],
181
+ documentType: ["bai/knowledge-note", "powerhouse/document-drive"],
182
+ scope: ["global"],
183
+ };
184
+ ```
73
185
 
74
- ### 4. Implementing Reducer Code and Unit Tests
75
- Navigate to the reducer directory:
186
+ 2. **State reconciliation, not event replay** — The processor doesn't interpret individual operations (SET_TITLE, ADD_LINK, etc.). Instead, it reads `context.resultingState` — the full document state after the operation — and upserts the entire node + edges. This means it doesn't need to know the document model's operation semantics.
187
+
188
+ 3. **Namespace isolation** — Each drive gets its own PGlite namespace (`GraphIndexerProcessor_<driveId>`), so multiple drives don't interfere with each other. The namespace is derived deterministically from the drive ID.
189
+
190
+ 4. **Idempotent migrations** — Tables and indexes are created with `ifNotExists`, so the processor can restart safely without schema conflicts.
191
+
192
+ 5. **No-op on disconnect** — The processor preserves its data across server restarts. Since the Reactor doesn't replay historical operations to processors, wiping on disconnect would leave the index empty until new edits arrive.
193
+
194
+ ### How the Subgraph Works (Read Path)
195
+
196
+ The `KnowledgeGraphSubgraph` extends `BaseSubgraph` from `@powerhousedao/reactor-api` and exposes the indexed data via GraphQL at `/graphql/knowledgeGraph`.
76
197
 
77
- ```bash
78
- cd document-models/"YourModelName"/src/reducers
198
+ ```
199
+ ┌──────────────────────────────────────────────────┐
200
+ │ GraphQL Clients │
201
+ │ │
202
+ │ Connect UI ─────────┐ │
203
+ │ AI Agent (MCP) ─────┤ │
204
+ │ Switchboard CLI ────┤ query / mutation │
205
+ │ Third-party app ────┤ │
206
+ │ curl / Postman ─────┘ │
207
+ │ │ │
208
+ │ ┌──────────▼───────────────────┐ │
209
+ │ │ /graphql/knowledgeGraph │ │
210
+ │ │ │ │
211
+ │ │ KnowledgeGraphSubgraph │ │
212
+ │ │ ├─ getDb(driveId) │ │
213
+ │ │ │ → namespaced Kysely │ │
214
+ │ │ ├─ getQuery(driveId) │ │
215
+ │ │ │ → typed query API │ │
216
+ │ │ ├─ reindexDrive() │ │
217
+ │ │ │ → backfill from │ │
218
+ │ │ │ reactorClient │ │
219
+ │ │ └─ ensureGraphDoc() │ │
220
+ │ │ → auto-create │ │
221
+ │ │ bai/knowledge- │ │
222
+ │ │ graph doc │ │
223
+ │ └──────────┬───────────────────┘ │
224
+ │ │ │
225
+ │ ┌──────────▼───────────────────┐ │
226
+ │ │ PGlite (same namespace as │ │
227
+ │ │ the processor writes to) │ │
228
+ │ └──────────────────────────────┘ │
229
+ └──────────────────────────────────────────────────┘
79
230
  ```
80
231
 
81
- Implement the reducer functions for each document model operation. These functions will handle state transitions.
232
+ **The subgraph reads from the same PGlite tables the processor writes to.** This is the key architectural link — the processor is the write path, the subgraph is the read path, and they share a namespace.
82
233
 
83
- Add utility functions in:
234
+ The subgraph provides two levels of query abstraction:
84
235
 
85
- ```bash
86
- document-models/"YourModelName"/src/utils.ts
236
+ 1. **`getDb(driveId)`** — Returns a typed `Kysely<DB>` instance scoped to the processor's namespace. This centralizes the `IRelationalDbLegacy → IRelationalDb → Kysely` cast in one place.
237
+
238
+ 2. **`getQuery(driveId)`** — Wraps `getDb` with the `createGraphQuery()` helper that provides high-level methods (`allNodes()`, `searchNodes()`, `connections()`, `triangles()`, `bridges()`, etc.). All queries use Kysely's type-safe query builder.
239
+
240
+ ### How Third-Party Plugins Can Use This
241
+
242
+ Any application that can make GraphQL requests to the Reactor's endpoint can query the knowledge graph. The subgraph is accessible at `/graphql/knowledgeGraph` (local: `http://localhost:4001/graphql/knowledgeGraph`, remote: `https://your-switchboard.example.com/graphql/knowledgeGraph`).
243
+
244
+ **Example: Search notes from any client**
245
+
246
+ ```graphql
247
+ query SearchNotes($driveId: ID!, $query: String!) {
248
+ knowledgeGraphSearch(driveId: $driveId, query: $query, limit: 20) {
249
+ documentId
250
+ title
251
+ description
252
+ noteType
253
+ status
254
+ }
255
+ }
87
256
  ```
88
257
 
89
- Write unit tests to ensure the correctness of your reducers:
258
+ **Example: Get graph structure for visualization**
259
+
260
+ ```graphql
261
+ query GraphData($driveId: ID!) {
262
+ knowledgeGraphNodes(driveId: $driveId) {
263
+ documentId
264
+ title
265
+ noteType
266
+ status
267
+ }
268
+ knowledgeGraphEdges(driveId: $driveId) {
269
+ sourceDocumentId
270
+ targetDocumentId
271
+ linkType
272
+ targetTitle
273
+ }
274
+ knowledgeGraphStats(driveId: $driveId) {
275
+ nodeCount
276
+ edgeCount
277
+ orphanCount
278
+ }
279
+ }
280
+ ```
90
281
 
91
- Test files should be located in:
282
+ **Example: Find synthesis opportunities (triangles)**
92
283
 
93
- ```bash
94
- document-models/"YourModelName"/src/reducers/tests
284
+ ```graphql
285
+ query FindTriangles($driveId: ID!) {
286
+ knowledgeGraphTriangles(driveId: $driveId, limit: 10) {
287
+ noteA { documentId title }
288
+ noteB { documentId title }
289
+ sharedTarget { documentId title }
290
+ }
291
+ }
95
292
  ```
96
293
 
97
- Run the tests:
294
+ **Example: Backfill the index after deployment**
98
295
 
99
- ```bash
100
- npm test
296
+ ```graphql
297
+ mutation Reindex($driveId: ID!) {
298
+ knowledgeGraphReindex(driveId: $driveId) {
299
+ indexedNodes
300
+ indexedEdges
301
+ errors
302
+ }
303
+ }
101
304
  ```
102
305
 
103
- Test the editor functionality:
306
+ **Using the Switchboard CLI:**
104
307
 
105
308
  ```bash
106
- npm run connect
309
+ # Search
310
+ switchboard query '{ knowledgeGraphSearch(driveId: "<UUID>", query: "reactor") { documentId title } }'
311
+
312
+ # Stats
313
+ switchboard query '{ knowledgeGraphStats(driveId: "<UUID>") { nodeCount edgeCount orphanCount } }'
314
+
315
+ # Reindex
316
+ switchboard query 'mutation { knowledgeGraphReindex(driveId: "<UUID>") { indexedNodes indexedEdges errors } }'
107
317
  ```
108
318
 
109
- ### 5. Implementing Document Editors
110
- Generate the editor template for your document model:
319
+ **Using MCP (for AI agents):**
320
+
321
+ AI agents connected via MCP can't call the subgraph directly, but they can use `mcp__reactor-mcp__getDocument` to read individual documents. The Switchboard CLI provides the fastest path for agents to query the graph index — the `powerhouse-knowledge` plugin uses this pattern.
322
+
323
+ ### Why This Pattern Matters
324
+
325
+ The processor + subgraph pattern is the recommended way to build **read-optimized projections** in Powerhouse:
326
+
327
+ | Concern | Without processor | With processor |
328
+ |---------|------------------|----------------|
329
+ | Search 500 notes by keyword | Load all 500 documents, replay ops, scan content | Single SQL `LIKE` query on `graph_nodes.title` |
330
+ | Find orphan notes | Load all docs, build adjacency list in memory | `SELECT * FROM graph_nodes WHERE document_id NOT IN (SELECT target_document_id FROM graph_edges)` |
331
+ | Graph density | Load everything, count manually | Two `COUNT(*)` queries |
332
+ | Incremental updates | Reload everything on each change | Upsert one row per changed document |
333
+
334
+ The same pattern can be applied to any domain — an invoice tracker could project invoice totals into a summary table, a project manager could index task statuses, etc. The processor handles the write path (operation → relational row), and the subgraph handles the read path (GraphQL → SQL → response).
335
+
336
+ ## Data Flow
111
337
 
112
- ```bash
113
- npm run generate -- --editor YourModelName --document-types powerhouse/YourModelName
114
338
  ```
339
+ User edits a note in the editor
340
+ → dispatch(setTitle({...}))
341
+ → operation recorded on the document
342
+ → Reactor sends operation to GraphIndexerProcessor
343
+ → Processor upserts graph_nodes + graph_edges in PGlite
344
+ → Subgraph queries return updated data
345
+ → GraphView in the drive-app renders the graph
346
+ ```
347
+
348
+ ## Drive Structure
115
349
 
116
- The --editor flag specifies the name of your document model.
117
- The --document-types flag links the editor to your document model type.
118
- After generation:
350
+ Documents are organized into folders within the drive:
119
351
 
120
- Open the editor template:
352
+ | Folder | Document Types | Purpose |
353
+ |--------|---------------|---------|
354
+ | `/knowledge/notes/` | `bai/knowledge-note` | Atomic knowledge claims |
355
+ | `/knowledge/` | `bai/moc` | Maps of Content |
356
+ | `/sources/` | `bai/source` | Raw input material |
357
+ | `/research/` | `bai/research-claim` | Methodology foundation |
358
+ | `/ops/queue/` | `bai/pipeline-queue` | Pipeline singleton |
359
+ | `/ops/health/` | `bai/health-report` | Health report singleton |
360
+ | `/ops/sessions/` | `bai/observation` | Operational signals |
361
+ | `/self/` | `bai/knowledge-graph`, `bai/vault-config` | Singletons |
362
+
363
+ ## Development
121
364
 
122
365
  ```bash
123
- editors/YourModelName/editor.tsx
366
+ # Install dependencies
367
+ bun install
368
+
369
+ # Start Vetra Studio with live code generation
370
+ ph vetra --watch
371
+
372
+ # Type check
373
+ bun tsc --noEmit
374
+
375
+ # Lint
376
+ bun eslint <file>
377
+
378
+ # Format
379
+ bun prettier --write <file>
380
+
381
+ # Run tests
382
+ bun test
124
383
  ```
125
384
 
126
- Customize the editor interface to suit your document model.
385
+ ### Subgraph Endpoint Configuration
386
+
387
+ The Search tab and other editor features that query the Knowledge Graph subgraph need to reach the reactor's GraphQL endpoint. The endpoint is resolved automatically in most cases:
127
388
 
128
- ### 6. Testing the Document Editor
129
- Run the Connect app to test your document editor:
389
+ | Environment | How it works |
390
+ |-------------|-------------|
391
+ | **`ph vetra --watch`** (local dev) | Auto-detected: Vite runs on port 3000/3001, subgraph at `http://localhost:4001/graphql/knowledgeGraph` |
392
+ | **Connect production** (same origin) | Auto-detected: relative path `/graphql/knowledgeGraph` |
393
+ | **Deployed** (Connect and Switchboard on different domains) | Set `VITE_SUBGRAPH_URL` env var |
394
+
395
+ For deployed environments where Connect runs on a different domain than the Switchboard (e.g., `connect.example.com` vs `switchboard-dev.powerhouse.xyz`), create a `.env` file:
130
396
 
131
397
  ```bash
132
- npm run connect
133
- ```
134
-
135
- Verify that the editor functions as expected.
136
- Perform end-to-end testing to ensure smooth integration between the document model and its editor.
137
-
138
- ### 7. Adding a Manifest File
139
- Create a manifest file to describe your document model and editor. This enables proper integration with the host application.
140
-
141
- **Example manifest.json:**
142
-
143
- ```json
144
- {
145
- "name": "your-model-name",
146
- "description": "A brief description of your document model.",
147
- "category": "your-category", // e.g., "Finance", "People Ops", "Legal"
148
- "publisher": {
149
- "name": "your-publisher-name",
150
- "url": "your-publisher-url"
151
- },
152
- "documentModels": [
153
- {
154
- "id": "your-model-id",
155
- "name": "your-model-name"
156
- }
157
- ],
158
- "editors": [
159
- {
160
- "id": "your-editor-id",
161
- "name": "your-editor-name",
162
- "documentTypes": ["your-model-id"]
163
- }
164
- ]
165
- }
398
+ # .env
399
+ VITE_SUBGRAPH_URL=https://switchboard-dev.powerhouse.xyz/graphql/knowledgeGraph
166
400
  ```
167
401
 
168
- ### Steps to finalize:
402
+ This is only needed when the app and reactor are on different origins. Local development and same-origin deployments work without any configuration.
403
+
404
+ ## Graph View
405
+
406
+ The knowledge graph visualization uses `cytoscape-fcose` (force-directed layout) with semantic clustering:
169
407
 
170
- Place the manifest file at your project root.
171
- Update your index.js to export your modules and include the new document model and editor.
408
+ - **MOC hubs** act as cluster anchors with higher repulsion, pulling their CORE_IDEA-linked notes into visible topic neighborhoods
409
+ - **Cross-cluster edges** have weak elasticity and long ideal lengths, preventing topic groups from collapsing together
410
+ - **Position persistence** via localStorage — positions survive tab switches and page reloads. New nodes are placed by fcose while existing nodes stay pinned
411
+ - **MOC group drag** — dragging a MOC diamond moves its entire cluster of connected notes
412
+ - **Re-layout button** clears cached positions and recomputes a fresh layout
172
413
 
173
- ### Final Thoughts
174
- You've now successfully created a Document Model and its corresponding Editor using the Connect app!
414
+ ## License
175
415
 
176
- Next Steps:
177
- - Expand functionality: Add more operations or complex logic to your document model.
178
- - Improve UX: Enhance the document editor for a smoother user experience.
179
- - Integrate with other systems: Use APIs or GraphQL to connect your document model with external services.
416
+ AGPL-3.0-only
@@ -1 +1 @@
1
- {"version":3,"file":"DriveExplorer.d.ts","sourceRoot":"","sources":["../../../../editors/knowledge-vault/components/DriveExplorer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA+BlD,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW,2CA+UtD"}
1
+ {"version":3,"file":"DriveExplorer.d.ts","sourceRoot":"","sources":["../../../../editors/knowledge-vault/components/DriveExplorer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAiClD,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW,2CAiWtD"}
@@ -7,6 +7,7 @@ import { GraphView } from "./GraphView.js";
7
7
  import { NoteList } from "./NoteList.js";
8
8
  import { SourceList } from "./SourceList.js";
9
9
  import { HealthDashboard } from "./HealthDashboard.js";
10
+ import { SearchView } from "./SearchView.js";
10
11
  import { GettingStartedButton } from "./GettingStarted.js";
11
12
  import { useKnowledgeNotes } from "../hooks/use-knowledge-notes.js";
12
13
  import { useKnowledgeGraph, buildSyncPayload, } from "../hooks/use-knowledge-graph.js";
@@ -15,7 +16,7 @@ import { useKnowledgeGraphDocumentById } from "@powerhousedao/knowledge-note/doc
15
16
  import { actions as graphActions } from "@powerhousedao/knowledge-note/document-models/knowledge-graph";
16
17
  import { ThemeToggle } from "../../shared/theme-context.js";
17
18
  export function DriveExplorer({ children }) {
18
- const [viewMode, setViewMode] = useState("notes");
19
+ const [viewMode, setViewMode] = useState("search");
19
20
  const { notes } = useKnowledgeNotes();
20
21
  const { graphDoc, graphState, hasGraphDoc } = useKnowledgeGraph(notes);
21
22
  const fileNodes = useFileNodesInSelectedDrive();
@@ -106,6 +107,11 @@ export function DriveExplorer({ children }) {
106
107
  setViewMode(mode);
107
108
  }
108
109
  const TABS = [
110
+ {
111
+ key: "search",
112
+ label: "Search",
113
+ icon: (_jsxs("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("circle", { cx: "11", cy: "11", r: "8" }), _jsx("path", { d: "m21 21-4.35-4.35" })] })),
114
+ },
109
115
  {
110
116
  key: "notes",
111
117
  label: "Notes",
@@ -155,7 +161,7 @@ export function DriveExplorer({ children }) {
155
161
  }, children: tab.badge }))] }, tab.key))), showDocumentEditor && (_jsxs("span", { className: "flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium", style: {
156
162
  backgroundColor: "var(--bai-hover)",
157
163
  color: "var(--bai-accent)",
158
- }, children: [_jsxs("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7" }), _jsx("path", { d: "M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z" })] }), "Editing"] }))] }), _jsxs("div", { className: "flex items-center gap-3", children: [hasGraphDoc && graphState && (_jsxs("span", { className: "text-[10px]", style: { color: "var(--bai-text-faint)" }, children: [graphState.nodes.length, "n / ", graphState.edges.length, "e"] })), _jsx(ThemeToggle, {}), _jsx(GettingStartedButton, {}), _jsx(CreateMenu, {})] })] }), _jsx("div", { className: "flex-1 overflow-auto", children: showDocumentEditor ? (_jsx("div", { className: "h-full", children: children })) : viewMode === "graph" ? (_jsx(GraphView, { notes: notes, graphState: graphState, mocs: mocs, tensions: tensions })) : viewMode === "sources" ? (_jsx(SourceList, {})) : viewMode === "health" ? (_jsx(HealthDashboard, {})) : (_jsx(NoteList, { notes: notes })) })] })] }));
164
+ }, children: [_jsxs("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7" }), _jsx("path", { d: "M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z" })] }), "Editing"] }))] }), _jsxs("div", { className: "flex items-center gap-3", children: [hasGraphDoc && graphState && (_jsxs("span", { className: "text-[10px]", style: { color: "var(--bai-text-faint)" }, children: [graphState.nodes.length, "n / ", graphState.edges.length, "e"] })), _jsx(ThemeToggle, {}), _jsx(GettingStartedButton, {}), _jsx(CreateMenu, {})] })] }), _jsx("div", { className: "flex-1 overflow-auto", children: showDocumentEditor ? (_jsx("div", { className: "h-full", children: children })) : viewMode === "graph" ? (_jsx(GraphView, { notes: notes, graphState: graphState, mocs: mocs, tensions: tensions })) : viewMode === "search" ? (_jsx(SearchView, {})) : viewMode === "sources" ? (_jsx(SourceList, {})) : viewMode === "health" ? (_jsx(HealthDashboard, {})) : (_jsx(NoteList, { notes: notes })) })] })] }));
159
165
  }
160
166
  const CREATE_ITEMS = [
161
167
  {
@@ -0,0 +1,2 @@
1
+ export declare function SearchView(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=SearchView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchView.d.ts","sourceRoot":"","sources":["../../../../editors/knowledge-vault/components/SearchView.tsx"],"names":[],"mappings":"AA+CA,wBAAgB,UAAU,4CAmGzB"}