logseq-graph-living-atlas 0.1.0

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 (41) hide show
  1. package/.env.example +29 -0
  2. package/CHANGELOG.md +38 -0
  3. package/CODE_OF_CONDUCT.md +33 -0
  4. package/CONTRIBUTING.md +116 -0
  5. package/GOVERNANCE.md +40 -0
  6. package/LICENSE +21 -0
  7. package/MAINTAINERS.md +34 -0
  8. package/README.md +370 -0
  9. package/ROADMAP.md +38 -0
  10. package/SECURITY.md +43 -0
  11. package/SUPPORT.md +31 -0
  12. package/dist/assets/AtlasCanvas-p-Pb_C3p.js +172 -0
  13. package/dist/assets/index-Cb0dgkF5.css +1 -0
  14. package/dist/assets/index-D-LUf-q7.js +12 -0
  15. package/dist/assets/three-DQCgX68K.js +3947 -0
  16. package/dist/index.html +13 -0
  17. package/docs/ADAPTERS.md +48 -0
  18. package/docs/API.md +145 -0
  19. package/docs/ARCHITECTURE.md +93 -0
  20. package/docs/CONCEPTS.md +62 -0
  21. package/docs/MCP.md +74 -0
  22. package/docs/RELEASE.md +65 -0
  23. package/docs/REPO_GUIDE.md +92 -0
  24. package/docs/TROUBLESHOOTING.md +138 -0
  25. package/docs/assets/living-atlas-demo.png +0 -0
  26. package/docs/assets/living-atlas-pathfinder.png +0 -0
  27. package/docs/assets/living-atlas-radar.png +0 -0
  28. package/docs/assets/living-atlas-source-detail.png +0 -0
  29. package/package.json +102 -0
  30. package/server/brain-service.mjs +201 -0
  31. package/server/contracts.mjs +346 -0
  32. package/server/fixture/create-fixture-graph.mjs +115 -0
  33. package/server/graph/pathfinding.mjs +155 -0
  34. package/server/graph/quality.mjs +11 -0
  35. package/server/graph/utils.mjs +25 -0
  36. package/server/graph-index.mjs +920 -0
  37. package/server/logseq/parser.mjs +121 -0
  38. package/server/logseq/source-adapter.mjs +147 -0
  39. package/server/redaction.mjs +89 -0
  40. package/server/service.mjs +777 -0
  41. package/server/source-adapter-contract.d.ts +46 -0
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Living Atlas</title>
7
+ <script type="module" crossorigin src="/assets/index-D-LUf-q7.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-Cb0dgkF5.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
@@ -0,0 +1,48 @@
1
+ # Source Adapters
2
+
3
+ Living Atlas reads normalized source records through a small adapter contract. The default adapter indexes Logseq markdown from `pages/` and `journals/`, but the graph builder and HTTP service do not depend on Logseq-specific filesystem code.
4
+
5
+ ## Contract
6
+
7
+ The public type shape is declared in `server/source-adapter-contract.d.ts`.
8
+
9
+ An adapter must provide:
10
+
11
+ - `kind`: short stable adapter name for diagnostics.
12
+ - `root`: local source root used for cache and source detail boundaries.
13
+ - `readManifest()`: returns `{ pages, graphId, fingerprint, maxMtimeMs }`.
14
+ - `readRecords()`: returns normalized page records.
15
+ - `watchDirectories()`: optional local directories for native watch events.
16
+
17
+ `fingerprint` must change when indexed source identity or content changes. Do not rely only on size and mtime; timestamp-preserving same-size rewrites must still invalidate the cache. `graphId` should be stable for the same source root without exposing an absolute path.
18
+
19
+ ## Record Shape
20
+
21
+ Records use Logseq-like page semantics even when an adapter reads another source:
22
+
23
+ - `id`: stable normalized page id.
24
+ - `name`: display name.
25
+ - `path`: absolute local source path, used only inside the local service.
26
+ - `type`, `tags`, `status`, `source`, `confidence`, `lastContacted`: metadata strings used by filters and graph health.
27
+ - `updatedAt` and `mtimeMs`: activity timestamps.
28
+ - `out`: outgoing page ids.
29
+ - `relations`: typed links such as parent/company/owner with optional local evidence.
30
+ - `props`: raw allowlisted source properties for source detail.
31
+
32
+ Adapters should keep records deterministic: sort input records, normalize ids the same way every run, and avoid network calls inside `readRecords()`.
33
+
34
+ ## Safety Rules
35
+
36
+ - Do not write to the source graph from an adapter.
37
+ - Do not put generated cache files inside the source root.
38
+ - Do not return arbitrary private properties unless the UI needs them and redaction handles them.
39
+ - Keep evidence strings local-only; redacted JSON must not leak relation text.
40
+
41
+ ## Validation
42
+
43
+ Before merging a new adapter, add:
44
+
45
+ - a service test using `createBrainService({ sourceAdapter })`;
46
+ - parser or fixture tests for source-specific edge cases;
47
+ - a contract test proving snapshots, node detail, and deltas still validate;
48
+ - a public fixture or generated test data path with no private records.
package/docs/API.md ADDED
@@ -0,0 +1,145 @@
1
+ # Living Atlas API
2
+
3
+ The Local Index Service is a localhost API for the bundled UI. It is not a remote service contract yet.
4
+
5
+ By default the service accepts requests only from loopback clients with local `Host` and `Origin` values. Packaged CLI runs against real graphs also require a local API token by default. Demo mode stays unauthenticated, and `--allow-unauthenticated-read` is available for trusted local fixture experiments.
6
+
7
+ ## Authentication
8
+
9
+ `POST /api/reindex` requires a token unless `--allow-unauthenticated-reindex` is enabled.
10
+
11
+ When read-token mode is enabled, every `/api/*` route requires one of:
12
+
13
+ ```text
14
+ Authorization: Bearer <token>
15
+ x-living-atlas-token: <token>
16
+ ```
17
+
18
+ The `/api/events` SSE route also accepts `?token=<token>` for `EventSource` compatibility. Query-string tokens are not accepted on normal JSON routes. Treat service logs and browser diagnostics that include event URLs as sensitive while token mode is enabled.
19
+
20
+ The bundled browser UI supports token-protected local reads by accepting `#token=<token>` in the URL fragment. The fragment is stored in session storage, removed from the visible URL, and then used as an `Authorization` header for normal API calls. SSE still uses `/api/events?token=<token>` because browser `EventSource` does not support custom headers.
21
+
22
+ ## Errors
23
+
24
+ Errors are JSON for API routes:
25
+
26
+ ```json
27
+ { "ok": false, "error": "radius must be an integer from 0 to 8." }
28
+ ```
29
+
30
+ Invalid query parameters return `400`. Missing tokens return `401`. Non-local requests return `403`. Packaged CLI runs against real graphs require API read tokens by default; demo mode and explicit `--allow-unauthenticated-read` runs do not.
31
+
32
+ API JSON responses are sent with `Cache-Control: no-store` and `X-Content-Type-Options: nosniff`. Bundled static HTML is also no-store; hashed static assets may use long-lived immutable caching.
33
+
34
+ When a local browser origin is allowed by same-origin rules or `--allowed-origin`, API error responses keep the same CORS headers as successful responses. Disallowed origins intentionally receive no CORS grant. Split frontend/API development must pass an explicit `--allowed-origin`.
35
+
36
+ ## Endpoints
37
+
38
+ All JSON endpoints accept `redact=1` for support screenshots or bug reports. Redaction preserves counts, numeric metrics, enum fields, and graph shape, but replaces page names, ids, labels, source paths, tags, previews, relation evidence, insight copy, properties, and provenance strings with deterministic placeholders within that response. Redacted output is for sharing shape and behavior only; do not use it as an application cache.
39
+
40
+ ### `GET /api/health`
41
+
42
+ Returns service status, graph totals, a non-path graph id, manifest fingerprint, cache status, watch mode, bind host, and whether read-token mode is enabled. Absolute paths are omitted unless `--debug-paths` is set.
43
+
44
+ ### `GET /api/snapshot`
45
+
46
+ Returns the render-ready graph packet.
47
+
48
+ Query parameters:
49
+
50
+ | Parameter | Default | Range | Meaning |
51
+ | --- | ---: | ---: | --- |
52
+ | `nodeBudget` | `7200` | `0..25000` | Maximum rendered nodes. `0` means service default. |
53
+ | `linkBudget` | `18000` | `0..100000` | Maximum rendered links. `0` means service default. |
54
+
55
+ The `totals` fields describe the full indexed graph. The `nodes` and `links` arrays may be a sampled render budget for large graphs. This endpoint is budgeted by default so casual API reads do not accidentally move a full 10k-100k graph payload through the browser.
56
+
57
+ `graph.id` is a stable non-path graph identity used for browser-local review storage. It is HMAC-derived from a per-install secret kept in the OS user cache, so exported payloads are not correlated by a raw path hash. `graph.fingerprint` is a content-manifest fingerprint used for cache and change detection. Neither value is an authorization secret.
58
+
59
+ ### `GET /api/focus?q=<page>`
60
+
61
+ Returns a selected page or cluster slice plus a bounded neighborhood.
62
+
63
+ Query parameters:
64
+
65
+ | Parameter | Default | Range | Meaning |
66
+ | --- | ---: | ---: | --- |
67
+ | `q` | empty | text | Page or cluster query. |
68
+ | `radius` | `2` | `0..8` | Link-hop radius around the seed. |
69
+ | `limit` | `1800` | `1..10000` | Maximum nodes in the focus packet. |
70
+
71
+ ### `GET /api/search?q=<page-or-tag>`
72
+
73
+ Searches the full indexed graph, not only the sampled render overview. Use this for command palettes and exact page lookup at 10k-100k scale.
74
+
75
+ Query parameters:
76
+
77
+ | Parameter | Default | Range | Meaning |
78
+ | --- | ---: | ---: | --- |
79
+ | `q` | empty | text | Page, type, cluster, status, source, confidence, or tag query. |
80
+ | `limit` | `8` | `1..50` | Maximum returned page nodes. |
81
+
82
+ Response fields include `totalMatches` and `omitted` so the UI can distinguish the full graph search result from the visible render budget.
83
+
84
+ ### `GET /api/node?q=<page>`
85
+
86
+ Returns detail for one page: source-relative path, allowlisted properties, sampled backlinks, sampled outlinks, direct-edge totals, review context, and related intelligence.
87
+
88
+ Query parameters:
89
+
90
+ | Parameter | Default | Range | Meaning |
91
+ | --- | ---: | ---: | --- |
92
+ | `q` | empty | text | Page id or name query. |
93
+ | `edgeLimit` | `250` | `1..1000` | Maximum inbound and outbound edge samples returned per direction. Totals are still reported as `backlinksTotal` and `outlinksTotal`. |
94
+
95
+ ### `GET /api/path?from=<page>&to=<page>`
96
+
97
+ Returns a bounded shortest route plus alternate scored routes and step-level evidence.
98
+
99
+ Query parameters:
100
+
101
+ | Parameter | Default | Range | Meaning |
102
+ | --- | ---: | ---: | --- |
103
+ | `from` | empty | text | Start page query. |
104
+ | `to` | empty | text | End page query. |
105
+ | `maxDepth` | `7` | `1..12` | Maximum hop depth. |
106
+
107
+ ### `GET /api/connectors`
108
+
109
+ Returns candidate cross-cluster connector opportunities.
110
+
111
+ Query parameters:
112
+
113
+ | Parameter | Default | Range | Meaning |
114
+ | --- | ---: | ---: | --- |
115
+ | `limit` | `12` | `1..100` | Maximum connector candidates. |
116
+
117
+ `GET /api/bridges` is a deprecated compatibility alias and emits a `Deprecation: true` header.
118
+
119
+ ### `GET /api/delta`
120
+
121
+ Returns the current graph delta relative to the previous snapshot after a reindex. On first load it compares the current snapshot to itself.
122
+
123
+ ### `GET /api/events`
124
+
125
+ Server-Sent Events stream.
126
+
127
+ Initial frame:
128
+
129
+ ```text
130
+ event: snapshot
131
+ data: {"generatedAt":"...","totals":{"pages":1,"nodes":1,"links":0}}
132
+ ```
133
+
134
+ Reindex frame:
135
+
136
+ ```text
137
+ event: graph_delta
138
+ data: {"type":"graph_delta","eventSeq":1,"changeCounts":{"addedNodes":1,"changedNodes":0,"removedNodes":0,"addedLinks":0,"removedLinks":0},"events":[{"kind":"node.created","seq":1}],"eventsOmitted":0}
139
+ ```
140
+
141
+ The service caps live event detail per reindex burst to keep the stream small. SSE frames include `changeCounts` plus sampled `events`; they do not include full node/link arrays. `eventsOmitted` reports how many additional changed nodes or links were summarized out of the frame. Fetch `/api/snapshot` after a large reindex when the UI needs the full current graph.
142
+
143
+ ### `POST /api/reindex`
144
+
145
+ Forces a local reindex and broadcasts a `graph_delta` frame. This does not write to Logseq.
@@ -0,0 +1,93 @@
1
+ # Living Atlas Architecture
2
+
3
+ Living Atlas is a local cinematic view over the Logseq graph. It intentionally keeps rendering, indexing, agent tooling, and guarded graph writes separate.
4
+
5
+ ```text
6
+ Logseq markdown files
7
+ -> Logseq source adapter
8
+ -> file parser and manifest
9
+ -> Local Index Service
10
+ -> injected graph source
11
+ -> stable layout/cache contract
12
+ -> snapshot/focus/delta APIs
13
+ -> SSE graph_delta stream
14
+ -> 3D Atlas App
15
+ -> Three.js point-cloud renderer
16
+ -> sparse edge reveal
17
+ -> modes/search/callouts/insights stream
18
+ -> Logseq MCP
19
+ -> agent-facing reads/writes
20
+ -> schema/git guards
21
+ -> provenance-preserving writeback path
22
+ -> External automation
23
+ -> future scheduled insights
24
+ -> anomaly/suggestion generation
25
+ -> Logseq plugin
26
+ -> future launcher/deep-link only
27
+ ```
28
+
29
+ ## Contracts
30
+
31
+ The Local Index Service binds to `127.0.0.1` and only accepts loopback peer addresses plus localhost Host/Origin headers. Remote access should remain off until there is an explicit authentication and transport plan.
32
+
33
+ Packaged CLI runs against real graphs require local API read tokens by default. Demo mode remains unauthenticated because it uses generated public fixture data.
34
+
35
+ Runtime contracts live in `server/contracts.mjs`. Startup cache reads, cache writes, and API snapshot enrichment validate snapshot, record, manifest, and cache-envelope shape before trusting generated data. Malformed or stale cache payloads are ignored and rebuilt from source markdown.
36
+
37
+ The HTTP runtime is importable through `createBrainService()` in `server/service.mjs`. The executable `server/brain-service.mjs` is intentionally only a CLI adapter, so contributors can test the service lifecycle without spawning a subprocess. The factory defaults to token-required API reads; tests and demos must opt into `allowUnauthenticatedRead: true` explicitly. `createBrainService()` accepts a source adapter with `readManifest()`, `readRecords()`, and optional `watchDirectories()`, which keeps Logseq filesystem IO out of graph algorithms and makes future source adapters testable.
38
+
39
+ - `GET /api/snapshot`: render-ready graph packet with nodes, links, clusters, insights, and totals.
40
+ - `GET /api/search?q=<page-or-tag>`: full-index command search that is not limited to the sampled render overview.
41
+ - `GET /api/focus?q=<page>`: selected page plus radius-limited neighborhood.
42
+ - `GET /api/node?q=<page>`: source-page detail, Logseq relative path, allowlisted properties, sampled backlinks/outlinks, direct-edge totals, and related insights.
43
+ - `GET /api/path?from=<page>&to=<page>`: shortest bounded graph route with step-level wikilink evidence.
44
+ - `GET /api/delta`: changes between the current and previous snapshot after a reindex.
45
+ - `GET /api/events`: Server-Sent Events stream for `graph_delta`.
46
+ - `POST /api/reindex`: manual local reindex; optionally protected by `LIVING_ATLAS_TOKEN`.
47
+
48
+ See `docs/API.md` for query parameter ranges, error semantics, and SSE frame examples.
49
+
50
+ ## Visual Policy
51
+
52
+ The whole graph is rendered as a point-cloud knowledge mass. Edges are intentionally sparse in the overview layer and become visible in focus, connector, and path-like states. The UI should answer why a pulse exists; it should not animate activity that is not grounded in indexed graph data.
53
+
54
+ The default composition is a cinematic projection over real graph data: graph-derived knowledge regions, visual-field density from cluster population, particle heat from file activity, bright cores from page link count, and sparse connector filaments from cluster-to-cluster relationships. The visual layer can stylize positions, but labels, counts, path evidence, source panels, and stream items must remain tied to the indexed Logseq snapshot.
55
+
56
+ Pathfinder is the first workflow that turns the cinematic field into an operating surface: it asks how two entities connect, narrows the rendered field to the route, and shows evidence for each hop. The Source Page panel then grounds the selected lens in the concrete Logseq file path, selected metadata, backlink/outlink counts, and neighbor chips.
57
+
58
+ When WebGL is unavailable, the renderer fallback must remain useful: it exposes loaded graph totals, top regions, high-signal pages that can be opened into the same source-detail workflow, and actionable atlas intelligence. The fallback is not visually equivalent to the cinematic field, but it should preserve core inspection workflows.
59
+
60
+ ## Parser And Source Adapter
61
+
62
+ The default Logseq source adapter indexes `pages/**/*.md` and `journals/**/*.md`. It requires `pages/` so accidental non-Logseq folders fail early. Advanced Logseq syntax remains best effort and should be added through golden fixtures.
63
+
64
+ Page identity is derived from the graph-relative Logseq namespace path. `pages/schema/properties.md` and `pages/schema___properties.md` both map to `schema/properties`, so duplicate namespace identities are rejected instead of silently merging graph nodes.
65
+
66
+ The local service consumes the adapter interface, not raw Logseq filesystem functions. Graph code receives normalized page records and should stay independent of where those records came from.
67
+
68
+ ## Cache
69
+
70
+ The Local Index Service writes a persistent local cache in the OS user cache directory by default. Startup checks a manifest fingerprint built from indexed markdown names, sizes, mtimes, and content hashes. If the fingerprint matches, the service loads the cached render snapshot and source records; if it differs, it reparses markdown and atomically refreshes the cache.
71
+
72
+ Cache writes are rejected when the configured path is inside `LOGSEQ_ROOT`, because the visualization service must not add generated artifacts to the graph. Cache files store graph-relative source paths and only preserve the allowlisted record fields needed for rendering, source detail, and parent inference. They still contain derived graph structure and should be treated as sensitive for real graphs.
73
+
74
+ The API exposes two non-path graph identifiers. `graph.id` is stable across ordinary markdown edits and lets browser-local review flags survive source changes. It is HMAC-derived with a per-install secret in the OS user cache rather than exposed as a raw path hash. `graph.fingerprint` changes with the source manifest and drives cache invalidation, deltas, and stale-cache rebuilds.
75
+
76
+ Watch mode uses native file events for ordinary markdown changes and an adaptive manifest poll as a fallback for missed nested, synced-folder, or rename events. The fallback poll slows down on larger graphs so 10k and 100k graphs are not restatted every second.
77
+
78
+ ## Scale Policy
79
+
80
+ - 1k nodes: full point cloud and broad interaction are acceptable.
81
+ - 10k nodes: precomputed layout and sparse edges are required; CI also exercises a 10k-file disk/API/reindex path.
82
+ - 100k nodes: the current release serves a budgeted overview from an in-memory graph and compact SSE change summaries. An opt-in `npm run eval:service:100k` path exercises a 100k-file disk/watch service run outside normal CI. True cluster-first storage, page-level level-of-detail endpoints, and binary deltas remain future work.
83
+
84
+ The renderer also has an adaptive quality policy in `src/visuals/model/quality.ts`. Small graphs stay in the full cinematic tier with high pixel ratio, bloom, dense dust, and dense tether lines. 10k-scale views move to a balanced tier that lowers pixel ratio and nonessential particle density while preserving labels, search, focus, and path evidence. 100k-scale views, reduced-motion users, and low-power devices move to a safe budgeted-overview tier with capped pixel ratio and reduced nebula/tether budgets.
85
+
86
+ The service keeps a per-snapshot runtime lookup for node maps, adjacency, incoming/outgoing edges, cluster membership, and search rows. Interactive routes use that lookup so search, focus, node detail, and pathfinding do not rebuild full graph indexes on every request. The first implementation still uses stable deterministic layout and JSON packets; the service boundary is ready for a future SQLite/DuckDB cache without changing the renderer contract.
87
+
88
+ ## Verification Policy
89
+
90
+ - `npm test` covers graph parsing, stable snapshots, path evidence, source detail, snapshot diffs, and the service reindex/SSE delta contract.
91
+ - `npm run test:ui` builds the app, verifies the primary Whole Mind surface against a generated fixture graph, performs a Pathfinder route, checks canvas pixel signal, and writes QA screenshots to a temporary directory unless `LIVING_ATLAS_QA_DIR` is set.
92
+ - `npm run test:ui:scale` renders generated 10k and budgeted 100k atlas payloads in Chromium, checks adaptive renderer quality, canvas pixel signal, and full-total display.
93
+ - `npm run eval` builds synthetic 1k, 10k, and 100k graphs to keep snapshot generation and payload size within explicit limits, then runs a 10k-file service-level disk/API/reindex evaluation.
@@ -0,0 +1,62 @@
1
+ # Living Atlas Concepts
2
+
3
+ Living Atlas uses cinematic language in the interface, but each term maps back to ordinary graph behavior from local Logseq markdown.
4
+
5
+ ## Page Node
6
+
7
+ A dot backed by a real markdown page from `pages/` or `journals/`. Selecting one shows its graph-relative source path, allowlisted properties, incoming links, outgoing links, and review context.
8
+
9
+ ## Visual Field
10
+
11
+ The particle cloud around page nodes. It is a projection of the graph layout, not extra source data. It helps clusters feel alive without changing the counts or links.
12
+
13
+ ## Connector
14
+
15
+ A page that links otherwise distant regions of the graph. Older code and the compatibility API may still use `bridge`, but the public product term is connector because it describes the job more plainly.
16
+
17
+ Use connectors to answer: "What pages make two topics talk to each other?"
18
+
19
+ ## Hub
20
+
21
+ A high-degree page with many direct links. Hubs can be useful anchors, but a hub is not automatically a connector. A company index, topic map, or daily planning page can be a hub without connecting separate regions.
22
+
23
+ Use hubs to answer: "What pages are shaping a lot of the map?"
24
+
25
+ ## Island
26
+
27
+ A region with few or no paths to the rest of the graph. Islands can be intentional archives, unfinished imports, or concepts that need linking.
28
+
29
+ Use islands to answer: "What knowledge exists but is not connected enough to be useful?"
30
+
31
+ ## Gap
32
+
33
+ A page that needs review because it has weak metadata, missing provenance, low confidence, unresolved links, or very few connections. The UI says "Needs review" where possible.
34
+
35
+ Use gaps to answer: "What should I clean up before trusting this area?"
36
+
37
+ ## Phantom Matter
38
+
39
+ Unresolved link targets. These are wikilinks that point to pages that do not exist yet. They are useful because they reveal intended structure before the real page exists.
40
+
41
+ Use phantom matter to answer: "What pages did I imply but never create?"
42
+
43
+ ## Source Truth
44
+
45
+ The evidence shown for a selected page: graph-relative file path, allowlisted properties, link directions, and local review flags. Living Atlas is read-only, so fixing source truth happens in Logseq or a separate guarded writeback tool.
46
+
47
+ ## Timeline Replay
48
+
49
+ A layout filtered by page update time. It shows how the visible graph grows across recent frames. It is not git history; it is derived from markdown file timestamps available to the local index service.
50
+
51
+ ## View Lenses
52
+
53
+ The lens buttons are meant to answer different operating questions:
54
+
55
+ - **All**: what is in the indexed graph right now?
56
+ - **Core**: what pages are structurally or recently important enough to orient the atlas?
57
+ - **Active**: what changed recently?
58
+ - **Connectors**: what pages join separated regions?
59
+ - **Gaps**: what should be cleaned up before trusting the map?
60
+ - **Review**: what did I explicitly flag for follow-up?
61
+
62
+ Group filters and promoted labels are graph-derived. Living Atlas starts from page `type::`, tags, links, and activity, then falls back to generic regions such as topics when the graph does not provide enough structure. It should not require a private ontology to produce useful top-level regions.
package/docs/MCP.md ADDED
@@ -0,0 +1,74 @@
1
+ # MCP And Writeback
2
+
3
+ Living Atlas does not ship a writeback MCP server in this package. The compatible companion MCP package is [`logseq-graph-mcp`](https://github.com/johnschieferleuhlenbrock/logseq-graph-mcp).
4
+
5
+ The atlas is the read-only visualization and index service. It reads Logseq markdown, builds local graph snapshots, and serves a localhost UI/API. Any workflow that creates, updates, deletes, or annotates Logseq pages belongs in a separate guarded MCP server.
6
+
7
+ ## Boundary
8
+
9
+ - Living Atlas reads `pages/**/*.md` and `journals/**/*.md`.
10
+ - Living Atlas never writes to the graph.
11
+ - `POST /api/reindex` only refreshes the in-memory/cache snapshot.
12
+ - Review flags in the browser are local UI state, not Logseq writes.
13
+ - Agent writeback should require explicit MCP tool authorization, validation, and provenance.
14
+
15
+ ## Recommended Integration
16
+
17
+ Run the systems side by side:
18
+
19
+ ```text
20
+ Logseq graph
21
+ -> Living Atlas local index service
22
+ -> logseq-graph-mcp stdio server for guarded agent reads/writes
23
+ ```
24
+
25
+ The atlas can surface a page, path, connector candidate, stale note, or proof gap. MCP integrations can use that selection as context, but the writeback path should stay outside the renderer and should write back through explicit tools.
26
+
27
+ ## Compatibility Contract
28
+
29
+ | Area | Living Atlas | `logseq-graph-mcp` |
30
+ | --- | --- | --- |
31
+ | Root | `--root /path/to/logseq` or `LOGSEQ_ROOT` | `--root /path/to/logseq` or `LOGSEQ_ROOT` |
32
+ | Transport | Local HTTP UI/API on `127.0.0.1` | stdio MCP process |
33
+ | Writes | Never writes to the graph | Write tools are guarded; `--readonly` disables all writes |
34
+ | Node floor | Node.js `20.19.0` or newer | Node.js `20.17.0` or newer |
35
+ | Shared behavior | Reindexes files after filesystem changes | Reads/writes markdown files under the same graph root |
36
+
37
+ When both are installed together, use Node.js `20.19.0` or newer. The MCP server has no HTTP port, so it does not conflict with the Atlas UI/API port.
38
+
39
+ ## Install MCP
40
+
41
+ ```bash
42
+ npx logseq-graph-mcp --root /absolute/path/to/logseq --readonly
43
+ ```
44
+
45
+ For an agent client such as Claude Desktop, configure `logseq-graph-mcp` as a stdio server and keep `LOGSEQ_ROOT` pointed at the same graph that you open in Living Atlas.
46
+
47
+ ## Smoke Test
48
+
49
+ 1. Start Living Atlas against a graph:
50
+
51
+ ```bash
52
+ living-atlas --root /absolute/path/to/logseq
53
+ ```
54
+
55
+ 2. Open the printed `#token=...` URL and select a node.
56
+ 3. Confirm the Source Page panel shows a graph-relative path like `pages/Example.md`.
57
+ 4. Start the MCP server against the same root:
58
+
59
+ ```bash
60
+ npx logseq-graph-mcp --root /absolute/path/to/logseq --readonly
61
+ ```
62
+
63
+ 5. In an MCP client, call `graph_status` and confirm the root and page count are expected.
64
+ 6. If MCP write tools are enabled, verify them separately and confirm the atlas only updates after a filesystem change plus reindex/watch event.
65
+
66
+ For the repository fixture smoke:
67
+
68
+ ```bash
69
+ npm run smoke:mcp
70
+ ```
71
+
72
+ ## Public Repo Status
73
+
74
+ This repository intentionally documents the MCP boundary but does not require an MCP package for install, demo mode, validation, or npm package smoke tests. The `smoke:mcp` command is optional because it uses the published MCP package from npm unless `LOGSEQ_GRAPH_MCP_CLI` points at a local MCP checkout.
@@ -0,0 +1,65 @@
1
+ # Release Checklist
2
+
3
+ Use this before publishing a public tag or npm package.
4
+
5
+ 1. Confirm the branch is `main`.
6
+ 2. Confirm the public GitHub repository exists and `origin` points at it.
7
+ 3. Confirm the npm package name and README install commands match the release plan.
8
+ 4. Confirm one-time npm trusted publishing setup:
9
+
10
+ - the npm package is owned by the publishing account or organization;
11
+ - the GitHub repository is configured as a trusted publisher for the package:
12
+
13
+ ```bash
14
+ npx npm@latest trust github logseq-graph-living-atlas \
15
+ --repo johnschieferleuhlenbrock/logseq-graph-living-atlas \
16
+ --file release.yml \
17
+ --env npm \
18
+ --allow-publish \
19
+ --yes
20
+ ```
21
+
22
+ - the protected GitHub environment is named `npm`, matching `.github/workflows/release.yml`;
23
+ - the release workflow has `id-token: write`, uses npm with trusted publishing support, and publishes through OIDC.
24
+
25
+ 5. Remove local graph artifacts:
26
+
27
+ ```bash
28
+ npm run clean
29
+ ```
30
+
31
+ 6. Run the full source gate:
32
+
33
+ ```bash
34
+ npx playwright install chromium
35
+ npm run validate
36
+ npm audit --audit-level=moderate
37
+ ```
38
+
39
+ 7. Commit with a public-safe author identity.
40
+ 8. Push `main` to `origin`.
41
+ 9. Create and check out a `vX.Y.Z` tag that matches `package.json` and points at `origin/main`.
42
+ 10. Prove the package path from that exact tag:
43
+
44
+ ```bash
45
+ npm pack --dry-run
46
+ npm run smoke:package
47
+ npm run check:release
48
+ ```
49
+
50
+ 11. Review package contents for accidental graph data, private paths, or local-only files.
51
+ 12. Push the tag.
52
+ 13. Let the protected `Release` workflow publish through npm trusted publishing.
53
+
54
+ The Release workflow enforces exact tag publishing before it calls `npm publish`. npm automatically generates provenance when trusted publishing succeeds from the public GitHub repository.
55
+
56
+ For a first-release bootstrap or emergency manual publish from a clean `main` checkout, complete the same checks and publish without GitHub OIDC provenance:
57
+
58
+ ```bash
59
+ npm run check:release
60
+ npm publish --access public
61
+ ```
62
+
63
+ After a manual publish, push the matching tag. The Release workflow is idempotent and exits cleanly when the exact package version already exists on npm.
64
+
65
+ Do not publish from a dirty worktree. Do not publish a package that requires a private Logseq graph to start; `living-atlas --demo` must work from the installed package.
@@ -0,0 +1,92 @@
1
+ # Repository Guide
2
+
3
+ ## Layout
4
+
5
+ ```text
6
+ server/
7
+ brain-service.mjs Thin CLI wrapper for npm and source runs
8
+ service.mjs Importable Local HTTP/SSE service, static file host, cache/watch/SSE state
9
+ contracts.mjs Runtime validation for API snapshots, records, manifests, cache envelopes
10
+ graph-index.mjs Pure graph model, metrics, layout packets, insights, pathfinding
11
+ graph/
12
+ pathfinding.mjs Bounded route search, route evidence, alternate path scoring
13
+ quality.mjs Shared proof-review signals for graph scoring and x-ray context
14
+ utils.mjs Shared graph utility helpers such as adjacency, lookup, rounding
15
+ fixture/
16
+ create-fixture-graph.mjs Runtime-safe public fixture graph used by demo and package smoke
17
+ logseq/
18
+ parser.mjs Logseq markdown parsing and wikilink/property extraction
19
+ source-adapter.mjs Source adapter interface, folder discovery, manifest fingerprinting, page records
20
+ source-adapter-contract.d.ts Public adapter contract for alternate local sources
21
+
22
+ src/
23
+ api.ts Browser API client
24
+ components/ Focused React components that are not graph math or renderer internals
25
+ CommandBar.tsx Search input, command suggestions, and reset affordance
26
+ FirstRunPrimer.tsx First-run action panel with prop-driven workflow hooks
27
+ PathfinderPanel.tsx Path tracing controls, route score, alternate paths, failure copy
28
+ SideRail.tsx Brand mark and mode navigation
29
+ SourceTruthPanel.tsx Static renderer/source-of-truth explanation
30
+ StatsStrip.tsx Top-level graph totals and scale policy badge
31
+ TimelineFooter.tsx Replay controls, timeline stops, and live/offline footer state
32
+ graph/ Pure graph selectors, filter groups, and view-preset policy used by the UI
33
+ main.tsx React application shell and workflow state
34
+ state/ Browser-local persistence helpers
35
+ styles.css Product chrome, panels, responsive layout
36
+ types.ts Shared client-side types
37
+ visuals/
38
+ AtlasCanvas.tsx Three.js renderer, picking, labels, shaders, camera
39
+ materials.ts Shader material factories
40
+ model/ Pure renderer model helpers for link selection, budgets, and layout policy
41
+ links.ts Visible-link selection and cross-region connector summaries
42
+
43
+ tests/
44
+ frontend/ tsx-powered unit tests for pure frontend graph/UI policy
45
+ fixtures/ Generated public-safe Logseq graph fixtures
46
+ *.test.mjs Node test runner coverage for parser/service behavior
47
+ ui-smoke.mjs Playwright smoke test against fixture data
48
+ ui-scale-smoke.mjs Browser render proof for 10k and budgeted 100k atlas payloads
49
+ scale-eval.mjs Synthetic 1k, 10k, and 100k graph evaluation
50
+ service-scale-eval.mjs Configurable local service disk/API/reindex/watch evaluation; 10k in CI, 100k opt-in
51
+
52
+ scripts/
53
+ demo.mjs Builds a safe local demo service from generated fixture data
54
+ clean.mjs Removes generated local artifacts
55
+ runtime-check.mjs Syntax-checks Node runtime files that are not covered by TypeScript
56
+ public-readiness.mjs Checks branch, package metadata, generated artifacts, and sensitive terms
57
+
58
+ docs/
59
+ ARCHITECTURE.md Runtime boundaries and scale policy
60
+ REPO_GUIDE.md File ownership and contribution map
61
+ ROADMAP.md Public roadmap, non-goals, and contribution direction
62
+ ```
63
+
64
+ ## Boundaries
65
+
66
+ - `server/logseq/` owns Logseq markdown/source parsing and the default source adapter. It should not know about graph layout, insights, HTTP, React, or DOM concerns.
67
+ - `server/graph-index.mjs` may build graph contracts, metrics, layout, insights, and compose focused `server/graph/` helpers. It should not read files directly or know about React/DOM concerns.
68
+ - `server/graph/` owns focused graph algorithms that can be tested or replaced independently. It should not read Logseq files or serve HTTP.
69
+ - `server/service.mjs` may serve API/static assets and manage cache/watch/SSE state. It should consume a source adapter and should not call Logseq filesystem functions directly.
70
+ - `server/brain-service.mjs` should stay a thin CLI wrapper around `createBrainService`.
71
+ - `server/source-adapter-contract.d.ts` documents the adapter boundary for contributors; update it when adapter record semantics change.
72
+ - `src/main.tsx` may coordinate app state and panels. It should not parse markdown or read the filesystem.
73
+ - `src/components/` may hold focused React UI components. It should receive behavior through props and avoid API/storage side effects.
74
+ - `src/graph/` may select and budget renderable graph subsets and own filter/preset semantics. It should stay pure and browser-storage free.
75
+ - `src/visuals/AtlasCanvas.tsx` may render and interact with the graph. It should not fetch data or mutate graph state.
76
+ - `src/visuals/model/` should hold pure renderer policy that can be tested without WebGL.
77
+ - `tests/fixtures/` must stay generic and safe for public CI.
78
+ - `.github/` keeps CI, issue templates, and PR hygiene aligned to `main`.
79
+
80
+ ## Future Refactor Targets
81
+
82
+ The current renderer and application shell are intentionally dense because the first milestone prioritized visual fidelity and live interaction. The preferred future split is:
83
+
84
+ - `src/state/` for view filters, replay, review flags, and persisted preferences.
85
+ - `src/panels/` for command, cognition stream, filters, source page, and pathfinder surfaces.
86
+ - `src/visuals/` continue splitting camera, picking, labels, shaders, particles, and layout adapters out of the renderer.
87
+ - `server/graph/` split into parsing, metrics, clustering, pathfinding, and API DTOs.
88
+ - keep shared API/cache schemas under runtime validation as new payloads are added.
89
+
90
+ When an API payload changes, update `server/contracts.mjs`, `src/types.ts`, `docs/API.md`, and the relevant contract tests in the same patch. Runtime validators are the server source of truth; TypeScript types are client mirrors and should not drift.
91
+
92
+ Do that incrementally with tests. Do not mix large refactors with visual behavior changes.