mellos-mapping 0.20.3 → 0.23.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 (75) hide show
  1. package/README.md +130 -69
  2. package/README.zh-CN.md +126 -65
  3. package/dist/hook-session-start.mjs +28 -20
  4. package/dist/mmap.mjs +303 -171
  5. package/dist/preview.mjs +1457 -0
  6. package/dist/server.mjs +1984 -741
  7. package/dist/store-paths.mjs +69 -22
  8. package/dist/terminal-worker.mjs +3331 -0
  9. package/dist/watch.mjs +957 -571
  10. package/dist/web/TERMINAL-LICENSES.txt +70 -0
  11. package/dist/web/app.css +967 -0
  12. package/dist/web/app.js +1356 -0
  13. package/dist/web/index.html +9 -0
  14. package/dist/web/terminal.css +9 -0
  15. package/dist/web/terminal.html +7 -0
  16. package/dist/web/terminal.js +9293 -0
  17. package/dist/web/xterm.css +285 -0
  18. package/dist/web.mjs +5646 -0
  19. package/docs/codex.md +189 -0
  20. package/docs/map-api.md +148 -0
  21. package/lib/domain/context.d.ts +11 -0
  22. package/lib/domain/context.js +27 -0
  23. package/lib/domain/text.d.ts +9 -0
  24. package/lib/domain/text.js +54 -0
  25. package/lib/domain/types.d.ts +3 -0
  26. package/lib/preview/index.d.ts +3 -0
  27. package/lib/preview/index.js +3 -0
  28. package/lib/preview/markdown.d.ts +8 -0
  29. package/lib/preview/markdown.js +54 -0
  30. package/lib/preview/presentation.d.ts +6 -0
  31. package/lib/preview/presentation.js +14 -0
  32. package/lib/preview/publisher.d.ts +23 -0
  33. package/lib/preview/publisher.js +143 -0
  34. package/lib/preview/svg.d.ts +3 -0
  35. package/lib/preview/svg.js +74 -0
  36. package/lib/preview/text.d.ts +4 -0
  37. package/lib/preview/text.js +13 -0
  38. package/lib/render/canvas.d.ts +1 -1
  39. package/lib/render/canvas.js +4 -2
  40. package/lib/render/draw.js +9 -6
  41. package/lib/render/render.d.ts +6 -0
  42. package/lib/render/render.js +50 -18
  43. package/lib/render/width.js +3 -1
  44. package/lib/store/atomic.d.ts +18 -0
  45. package/lib/store/atomic.js +86 -0
  46. package/lib/store/channels.d.ts +40 -0
  47. package/lib/store/channels.js +135 -0
  48. package/lib/store/format.js +21 -4
  49. package/lib/store/json-text.d.ts +9 -0
  50. package/lib/store/json-text.js +16 -0
  51. package/lib/store/maps.d.ts +12 -0
  52. package/lib/store/maps.js +42 -0
  53. package/lib/store/migration.d.ts +12 -0
  54. package/lib/store/migration.js +46 -0
  55. package/lib/store/pages.d.ts +46 -0
  56. package/lib/store/pages.js +89 -0
  57. package/lib/store/policy.d.ts +74 -0
  58. package/lib/store/policy.js +144 -0
  59. package/lib/store/project.d.ts +2 -0
  60. package/lib/store/project.js +29 -0
  61. package/lib/store/store.d.ts +15 -257
  62. package/lib/store/store.js +16 -695
  63. package/lib/store/transaction.d.ts +12 -0
  64. package/lib/store/transaction.js +91 -0
  65. package/lib/store/viewers.d.ts +81 -0
  66. package/lib/store/viewers.js +186 -0
  67. package/package.json +27 -5
  68. package/scripts/codex-cli.mjs +42 -0
  69. package/scripts/codex-register.mjs +27 -94
  70. package/scripts/mmap.mjs +27 -17
  71. package/scripts/open-pane.mjs +37 -18
  72. package/scripts/pane-core.mjs +57 -220
  73. package/scripts/terminal-session.mjs +137 -0
  74. package/scripts/tmux-session.mjs +90 -0
  75. package/scripts/watcher-command.mjs +16 -0
package/README.md CHANGED
@@ -1,16 +1,20 @@
1
1
  # Mellos Mapping
2
2
 
3
- [![CI](https://github.com/GuangminJu/mellos-mapping/actions/workflows/ci.yml/badge.svg)](https://github.com/GuangminJu/mellos-mapping/actions/workflows/ci.yml)
3
+ [![npm](https://img.shields.io/npm/v/mellos-mapping?logo=npm&logoColor=white&label=npm&color=cb3837)](https://www.npmjs.com/package/mellos-mapping)
4
+ [![downloads](https://img.shields.io/npm/dm/mellos-mapping?label=downloads&color=cb3837)](https://www.npmjs.com/package/mellos-mapping)
5
+ [![MCP registry](https://img.shields.io/badge/MCP_registry-listed-2f6feb)](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.GuangminJu/mellos-mapping)
6
+ [![CI](https://img.shields.io/github/actions/workflow/status/GuangminJu/mellos-mapping/ci.yml?branch=main&label=CI)](https://github.com/GuangminJu/mellos-mapping/actions/workflows/ci.yml)
7
+ [![license](https://img.shields.io/badge/license-MIT-444)](LICENSE)
4
8
 
5
9
  English | [简体中文](README.zh-CN.md)
6
10
 
7
11
  A live, terminal-native map of bottom-up development for
8
- [Claude Code](https://claude.com/claude-code) and Codex CLI.
12
+ [Claude Code](https://claude.com/claude-code), ChatGPT desktop Codex mode and Codex CLI.
9
13
 
10
14
  <p align="center">
11
15
  <picture>
12
16
  <source media="(prefers-color-scheme: light)" srcset="docs/demo-light.svg">
13
- <img alt="A Mellos map building itself: ghost design first, spinners climbing the layers, a cracked foundation spreading upward, honest recovery" src="docs/demo.svg" width="620">
17
+ <img alt="One declare puts the whole ghost design on screen, then the nodes light up from the bottom a foundation cracks, the damage spreads upward, and green is earned back" src="docs/demo.svg" width="620">
14
18
  </picture>
15
19
  </p>
16
20
 
@@ -20,42 +24,12 @@ dependency edges that may only point downward, ghost nodes for what is
20
24
  designed, a spinner on what is being built right now, and solid green for
21
25
  what is built *and verified*.
22
26
 
23
- ```
24
- Mellos Mapping · the plugin itself
25
-
26
- ━━━━━━━━━━━━━━━━━━━━━━━━━━ orchestration
27
-
28
- ╭╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮
29
- ╎ · MCP Server ╎
30
- ╰╌╌╌╌┬╌┬╌╌┬╌╌╌╌╯
31
- │ │ │
32
- └─┼──┼─────────────┐
33
- │ └──────┐ │
34
- │ │ │
35
- ━━━━━━━━━┿━━━━━━━━━┿━━━━━━┿━━━ contracts
36
- │ │ │
37
- ┏━━━━━━┷━━━━━━━━┓│ ╭╌╌╌╌┴╌╌╌╌╌╌╮
38
- ┃ ■ State Store ┃│ ╎ · Watcher ╎
39
- ┗━━━━━┯━━━━━━━━━┛│ ╰╌╌╌╌╌┬╌╌╌╌╌╯
40
- │ │ │
41
- │ ┌────────┘ │
42
- │ │ │
43
- ━━━━━━━━┿━┿━━━━━━━━━━━━━━━━┿━ primitives
44
- │ │ │
45
- ┏━━━━━┷━┷━━━━━━┓ ╭──────┴───────────╮
46
- ┃ ■ Map Domain ┃ │ ⠋ ASCII Renderer │
47
- ┗━━━━━━━━━━━━━━┛ ╰──────────────────╯
48
-
49
- · planned ⠋ in-progress ■ done ✗ regressed
50
- ```
51
-
52
- In a real terminal the wiring and band bars render FAINT while node boxes
53
- glow in their status colors with bold labels — a dark circuit board where
54
- the components are the bright things. Skip-level edges thread through gaps
55
- between boxes (watch the line dive between State Store and Watcher above);
56
- non-overlapping wire segments share track rows to keep the bands close.
27
+ <p align="center">
28
+ <img alt="A Claude Code session with the Mellos map pane beside it: a six-layer game engine design, L0 and L1 nodes solid green, the upper layers still dashed ghost nodes" src="docs/session-claude-code.png">
29
+ </p>
57
30
 
58
- *(This is the plugin's own map, mid-development. The spinner really spins.)*
31
+ *A real session: Claude Code on the left, the map pane on the right. L0 is
32
+ verified, L1 just lit up, everything above is still a ghost.*
59
33
 
60
34
  ## Why
61
35
 
@@ -79,6 +53,21 @@ picture makes the discipline visible:
79
53
 
80
54
  ## Install
81
55
 
56
+ Clone the branch for your host, then run one command. No build is required.
57
+
58
+ | Branch | Audience | Command from the clone |
59
+ | --- | --- | --- |
60
+ | `main` | Shared source / either host | `node install.mjs chatgpt-app` or `node install.mjs claude` |
61
+ | `claude` | Claude Code | `node install.mjs` |
62
+ | `chatgpt-app` | ChatGPT desktop, Codex mode | `node install.mjs` |
63
+
64
+ Requires Node.js 18+ and the corresponding host CLI on PATH. The installer checks
65
+ release integrity and all eight MCP tools, retains the runtime outside the clone,
66
+ and configures the host. Start a new conversation after installation.
67
+ See [release and branch instructions](docs/releasing.md).
68
+
69
+ Claude Code's marketplace installation is also available:
70
+
82
71
  Two lines inside any Claude Code conversation:
83
72
 
84
73
  ```
@@ -92,8 +81,7 @@ Or one line in a terminal:
92
81
  claude plugin marketplace add GuangminJu/mellos-mapping && claude plugin install mellos-mapping@mellos-mapping
93
82
  ```
94
83
 
95
- Requires Node.js 18+ on PATH (Claude Code itself requires Node, so you
96
- already have it). No build step: `dist/` is committed, so a clone runs as-is —
84
+ Requires Node.js 18+ on PATH (install Node separately when using native Claude Code). No build step: `dist/` is committed, so a clone runs as-is —
97
85
  `dist/server.mjs` (the MCP server), `dist/watch.mjs` (the pane),
98
86
  `dist/mmap.mjs` (the `mmap` toggle), `dist/hook-session-start.mjs` (the
99
87
  `SessionStart` hook that `hooks/hooks.json` registers) and
@@ -139,7 +127,7 @@ claude plugin marketplace update mellos-mapping && claude plugin update mellos-m
139
127
 
140
128
  Two steps because `plugin update` compares against the locally cached
141
129
  marketplace clone — the first command is what actually pulls this repo.
142
- Restart Claude Code to apply. Releases are version bumps on `master`.
130
+ Restart Claude Code to apply. Releases are version bumps on `main`.
143
131
  (In-app, `/plugin` opens the same management UI.)
144
132
 
145
133
  ### Upgrading from 0.19
@@ -166,31 +154,34 @@ That one move is the only time either process touches `.claude/`. Afterwards
166
154
  the tools write nowhere but `.mellos/`, and never outside the project
167
155
  directory they resolved at startup.
168
156
 
169
- ## Codex CLI
157
+ ## ChatGPT App · Codex mode
170
158
 
171
- The same repo doubles as a Codex plugin (codex-cli 0.147+). Three lines:
159
+ This is Codex mode in the ChatGPT desktop app (also called Codex App).
160
+ From the source branch run the following command; on `chatgpt-app`, omit the
161
+ host argument. It configures the desktop skill, marketplace and eight MCP tools.
172
162
 
173
163
  ```
174
- codex plugin marketplace add GuangminJu/mellos-mapping
175
- codex plugin add mellos-mapping@mellos-mapping
176
- node ~/.codex/plugins/cache/mellos-mapping/mellos-mapping/<version>/scripts/codex-register.mjs
164
+ node install.mjs chatgpt-app
177
165
  ```
178
166
 
179
- The first two install the skill (the map discipline) as a Codex plugin. The
180
- third registers the MCP server at user level — needed because Codex spawns
181
- plugin-bundled MCP servers inside the plugin cache with no way to see your
182
- workspace, so a bundled server would write the map into the cache. A
183
- user-level `codex mcp add` entry (which the script writes) inherits each
184
- session's working directory instead: the state file lands in your project,
185
- same as under Claude Code. The registered path is version-specific — re-run
186
- the script after updating the plugin.
187
-
188
- To watch the live pane beside a Codex session on Windows, run
167
+ Start a new conversation. The desktop skill defaults to **web-terminal**:
168
+ `mmap_open {surface: "web-terminal", page: "<slug>"}` starts a local service,
169
+ then the AI opens its URL in the current conversation's right browser panel.
170
+ The mmap terminal starts automatically, with its own font-size selector;
171
+ no manual paste or Computer Use is needed. Graphical SVG, native terminal and
172
+ Markdown remain available. With an older MCP schema, run
173
+ `node "<plugin root>/dist/web.mjs" "<project>" --terminal --page <slug>`.
174
+ A queued panel request does not prove that the user can see it.
175
+ See [desktop installation and limitations](docs/codex.md).
176
+
177
+ For Codex CLI inside Windows Terminal (not the desktop integrated terminal), run
189
178
  `node <plugin root>/scripts/open-pane.mjs <project dir>` — it splits the
190
- terminal window hosting the session (or falls back to a dedicated
191
- "mellos-mapping" window; `--window` picks that on purpose). Add
179
+ terminal window hosting the session, keeping keyboard focus on the conversation.
180
+ If that window cannot be identified or focused, it reports failure without
181
+ opening elsewhere. `--window` explicitly chooses a separate window. Add
192
182
  `--page <slug>` to open on a particular page — and with a pane already open,
193
- rerunning with `--page` retargets it instead of opening another. The pane
183
+ rerunning with `--page` retargets the pane belonging to this console. A map
184
+ open in another session or a separate window does not count as this split. The pane
194
185
  auto-follows the page being written — the map the agent is operating on
195
186
  right now; press `f` to toggle that (a manual page switch also turns it
196
187
  off), or start with `--no-follow`. Elsewhere run
@@ -198,6 +189,32 @@ off), or start with `--no-follow`. Elsewhere run
198
189
  terminal (or any terminal split). Both take the same flags — see
199
190
  [Pane flags](#pane-flags).
200
191
 
192
+ ### Desktop Markdown map
193
+
194
+ When the user chooses the document surface, the skill uses
195
+ `mmap_open {surface: "markdown", page: "<slug>"}` and opens the returned file
196
+ beside the current conversation. The document embeds a colored SVG dependency
197
+ map plus module details, evidence, and child-page links. It needs no web server,
198
+ browser rendering process, Mermaid support, or additional runtime dependencies.
199
+
200
+ Successful MCP map writes regenerate enabled previews in `.mellos/previews/`;
201
+ JSON remains the source of truth. Image nodes are static. File visibility and
202
+ automatic viewer refresh belong to the desktop host. See the
203
+ [desktop map guide](docs/codex.md#desktop-right-side-map) for regeneration,
204
+ cache behavior, and limitations.
205
+
206
+ ### Optional interactive web viewer
207
+
208
+ An additional interactive web viewer is available with
209
+ `mmap_open {surface: "web", page: "<slug>"}` or
210
+ `node "<plugin root>/dist/web.mjs" "<project directory>" --page <slug>`.
211
+ Open its returned URL in the host's right browser panel. It provides live
212
+ updates, pan/zoom, hover and pinned details, search, dependency highlighting,
213
+ filters, group overview, submaps and themes. Stop it with
214
+ `node "<plugin root>/dist/web.mjs" "<project directory>" --stop`.
215
+ Markdown/SVG and terminal workflows remain available; all surfaces share the
216
+ same map data. See [web viewer details](docs/codex.md#optional-interactive-web-viewer).
217
+
201
218
  ## Any MCP client
202
219
 
203
220
  The server ships on npm, so any MCP client (Cursor, Windsurf, Zed,
@@ -222,7 +239,7 @@ servers), then the server process's own working directory. Set
222
239
  somewhere other than the project you are working in.
223
240
 
224
241
  The skill/discipline layer is Claude Code + Codex specific; other clients
225
- get the five `mmap_*` tools and the pane, and bring their own prompting.
242
+ get the eight `mmap_*` tools and the pane, and bring their own prompting.
226
243
 
227
244
  ## Use
228
245
 
@@ -241,6 +258,25 @@ get the five `mmap_*` tools and the pane, and bring their own prompting.
241
258
  3. Watch nodes light up from the bottom. Interrupt when the picture worries
242
259
  you — that is what it is for.
243
260
 
261
+ On Linux and macOS, `mmap_open` and `mmap` automatically use tmux. The launcher
262
+ targets the inherited `TMUX`/`TMUX_PANE`; if the tool process lost those variables,
263
+ it discovers the single attached session on the default tmux server. The default
264
+ is a right split that preserves input focus; `--window` creates a new tmux window.
265
+ Repeated opens reuse the watcher bound to that source pane or session window.
266
+
267
+ For multiple attached sessions or a custom tmux socket, set these variables in
268
+ the environment of the MCP server (restart it after changing them):
269
+
270
+ | Variable | Meaning |
271
+ | --- | --- |
272
+ | `MELLOS_MAPPING_TMUX_TARGET` | Explicit tmux session or pane, such as `work:2.1` or `%7` |
273
+ | `MELLOS_MAPPING_TMUX_SOCKET` | Absolute socket path, for example `/tmp/my-tmux/socket` |
274
+
275
+ Ambiguous sessions, detached sessions and missing tmux produce a concrete error
276
+ and a fully quoted watcher command, including the project and requested page,
277
+ to paste into any visible terminal. Map writes remain available; after an open
278
+ failure the assistant retries only when the environment changes or you ask.
279
+
244
280
  The pane is mouse-aware (xterm SGR any-event tracking — the same protocol
245
281
  htop and tmux speak):
246
282
 
@@ -323,7 +359,7 @@ them verbatim and rejects anything it does not know rather than dropping it.
323
359
 
324
360
  | Flag | Effect |
325
361
  | --- | --- |
326
- | `--page <slug>` | open on this page; with a pane already running, retarget that pane instead of opening another |
362
+ | `--page <slug>` | open on this page; with this console’s pane already running, retarget it instead of opening another |
327
363
  | `--ascii` | pure-ASCII repertoire, for fonts without box-drawing glyphs |
328
364
  | `--no-color` | no ANSI color |
329
365
  | `--no-mouse` | no mouse reporting, if your terminal multiplexer wants the mouse for itself |
@@ -336,6 +372,13 @@ though one is already running for this project. Watcher-only: `--file <path>`
336
372
  names the default page's state file (the launcher derives it from the project
337
373
  directory).
338
374
 
375
+ Pane ownership is carried by the internal watcher flag `--owner <token>` and
376
+ the optional `owner` field in viewer reports. Launchers derive the token from
377
+ the source console process and its creation time; manual watchers can omit it.
378
+ Focus and quit requests to a bound viewer use its PID, so another window of
379
+ the same project cannot consume them. Bare `mmap` toggles only the pane bound
380
+ to the current console; `mmap --window` toggles the separate project window.
381
+
339
382
  ### The mmap command
340
383
 
341
384
  `mmap`, typed in any terminal, is a **toggle**: it opens the map pane for the
@@ -451,12 +494,19 @@ When a hidden sub-map changes in the background, the footer says so.
451
494
 
452
495
  ## MCP tools
453
496
 
497
+ Start with `mmap_read` to resume an existing page; a new conversation is not a
498
+ new effort. Use stable IDs, filtered reads and revision-checked writes. The
499
+ [persistent-map API guide](docs/map-api.md) covers complete CRUD, atomic mixed
500
+ batches, context checkpoints, source hashes and worktree boundaries.
501
+
454
502
  | Tool | Purpose |
455
503
  | --- | --- |
456
504
  | `mmap_declare` | Grow the map: title (`null` removes it), diagram kind, layer bands, lanes, groups (subsystems), nodes — with `status`, `evidence`, `detail`, `kind`, `group`, `lane`, `submap` — and edges, optionally labeled (all-or-nothing batch) |
457
505
  | `mmap_update` | Record progress **and revise**: status (`planned → in-progress → done` +evidence, `regressed`), relabel a node, move it to another band (`layer`), join/leave a group or lane, set a node kind or a `submap`; rename and re-rank bands (`layers`), relabel groups (`groups`) and lanes (`lanes`); `null` clears any clearable field |
458
506
  | `mmap_remove` | Revise: drop edges, nodes, groups, lanes, empty bands — and, with `pages`, whole pages, file and all (permanent; applied after this call's map edits) |
459
507
  | `mmap_view` | Render the current map as text inline (optional `zoom`, `-4`…`2`), ending with a `pages:` line naming every page the project has and which one you are looking at |
508
+ | `mmap_read` | Structured page discovery, precise IDs, filtered/paginated reads, context and source changes |
509
+ | `mmap_batch` | One-page mixed create/update/remove transaction with a revision check |
460
510
  | `mmap_setup` | Get/set the project's mapping policy — when maps open |
461
511
  | `mmap_open` | Put the map on your screen: open the pane, or retarget an open one to a `page` (`window: true` for the dedicated window). It answers with whether a pane actually reported in afterwards, not merely that a command ran — and it can never close one |
462
512
 
@@ -472,7 +522,10 @@ mean:
472
522
  - **control characters** in text fields — an ESC sequence stored in a label
473
523
  would let a map repaint the terminal of everyone who opens it. `detail` is
474
524
  the exception: newlines and tabs are how a note is written, everything else
475
- (ESC, BEL, lone CR) is still refused;
525
+ (ESC, BEL, lone CR) is still refused. File loading and library saves apply
526
+ the same control-character rules, retaining multiline evidence in older
527
+ files. Terminal rendering also neutralizes controls in maps constructed
528
+ directly by library callers;
476
529
  - **an empty string** where a field is optional — `null` is how a field is
477
530
  cleared, never a blank that renders as a box nobody can tell from a real
478
531
  one;
@@ -500,7 +553,7 @@ ends with what those reports say:
500
553
  | The line | What it means |
501
554
  | --- | --- |
502
555
  | `pane: CLOSED` | nobody is seeing this map; the assistant opens one with `mmap_open` instead of asking you to |
503
- | `pane: open on this page` | you are watching this land |
556
+ | `pane: running on this page` | a live process reports this page; its terminal may be hidden |
504
557
  | `pane: open on <other>, auto-follow on` | the pane follows the page last written, so it arrives here by itself |
505
558
  | `pane: open on <other>, auto-follow OFF` | you pinned that page by hand: the change is real and NOT on your screen. The assistant is told to say so rather than move your view |
506
559
 
@@ -510,6 +563,11 @@ not say which page was on screen. A report whose pane stopped refreshing it is
510
563
  ignored after five seconds and deleted after a minute, so a killed pane cannot
511
564
  go on claiming an audience.
512
565
 
566
+ A heartbeat does not establish screen visibility. An explicit tmux open also
567
+ selects the existing watcher's window, reveals it if another pane was zoomed,
568
+ and verifies the attached session's active window before reporting visibility.
569
+ Focusing that watcher in a shell without `TMUX` reuses its original owner.
570
+
513
571
  ### Setup: choose when maps open
514
572
 
515
573
  How eager mapping should be is a habit, not a property of a repository — so it
@@ -551,15 +609,18 @@ render as boxes and one id must mean one box.
551
609
 
552
610
  ## Development
553
611
 
612
+ See [contributing](CONTRIBUTING.md) and the
613
+ [project structure, branch and recovery guide](docs/project-maintenance.md).
614
+
554
615
  ```
555
- npm install
616
+ npm ci
556
617
  npm run verify
557
618
  ```
558
619
 
559
- `verify` is four steps, in this order: `typecheck`, `test`, `build` (bundles
560
- `dist/`, emits `lib/` with declarations, cleaning both first), and
561
- `check:package` which packs the tarball through the real `prepack`
562
- lifecycle and fails if any `exports` or `bin` target is missing from it.
620
+ Use Node.js 22.12+ for development. `verify` runs `typecheck`, `test`, `build`
621
+ (bundles `dist/` and emits `lib/` with declarations), `check:package`,
622
+ `check:codex`, and `check:release`. These check npm entrypoints, the Codex
623
+ package and both installable editions, including their MCP handshake.
563
624
 
564
625
  The repo is itself layered bottom-up, and each layer has its spec:
565
626
 
@@ -570,7 +631,7 @@ The repo is itself layered bottom-up, and each layer has its spec:
570
631
  | 1 store | `src/store/store.ts` | `store.test.ts`, `atomic-save.test.ts` | atomic state-file persistence on Node |
571
632
  | 1 semantics | `src/semantics/` | `semantics.test.ts` | medium-neutral view semantics: zoom ladder, group aggregation, page-set rules, sequence flip, the shared glyph vocabulary |
572
633
  | 2 apply | `src/server/apply.ts` | `apply.test.ts` | tool inputs → transactional op sequences |
573
- | 3 server | `src/server/server.ts` | `server.test.ts`, `save-failure.test.ts` | the five MCP tools over stdio |
634
+ | 3 server | `src/server/server.ts` | `server.test.ts`, `save-failure.test.ts` | the eight MCP tools over stdio |
574
635
  | 4 render | `src/render/` | `render.test.ts`, `routing.test.ts` | the ASCII renderer and its wire routing |
575
636
  | 4 pane | `src/watch/` | `watch.test.ts`, `pane-state.test.ts`, `input.test.ts` | the polling pane: page set, input parsing, panel and chrome |
576
637
  | — launchers | `scripts/` | `open-pane.test.mjs`, `codex-register.test.mjs` | plain-node entry points |