mellos-mapping 0.16.0 → 0.18.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.
package/README.md CHANGED
@@ -130,9 +130,12 @@ To watch the live pane beside a Codex session on Windows, run
130
130
  terminal window hosting the session (or falls back to a dedicated
131
131
  "mellos-mapping" window; `--window` picks that on purpose). Add
132
132
  `--page <slug>` to open on a particular page — and with a pane already open,
133
- rerunning with `--page` retargets it instead of opening another. Elsewhere
134
- run `node <plugin root>/dist/watch.mjs` (same `--page` flag) from the
135
- project directory in a second terminal (or any terminal split).
133
+ rerunning with `--page` retargets it instead of opening another. The pane
134
+ auto-follows the page being written the map the agent is operating on
135
+ right now; press `f` to toggle that (a manual page switch also turns it
136
+ off), or start with `--no-follow`. Elsewhere run
137
+ `node <plugin root>/dist/watch.mjs` (same `--page` / `--no-follow` flags)
138
+ from the project directory in a second terminal (or any terminal split).
136
139
 
137
140
  ## Any MCP client
138
141
 
package/README.zh-CN.md CHANGED
@@ -120,8 +120,10 @@ node ~/.codex/plugins/cache/mellos-mapping/mellos-mapping/<版本>/scripts/codex
120
120
  终端窗口里分屏(识别不到就确定性地开到专属的 "mellos-mapping" 窗口;
121
121
  `--window` 则是主动选择专属窗口)。加 `--page <slug>` 指定打开哪一页;
122
122
  面板已经开着时,带 `--page` 重跑一次不会再开新面板,而是让现有面板
123
- 切到那一页。其他环境在项目目录下的第二个终端(或任意分屏)运行
124
- `node <插件根>/dist/watch.mjs`(同样支持 `--page`)。
123
+ 切到那一页。面板默认**自动跟随**正在被写入的页——AI 此刻操作哪张图,
124
+ 就看哪张图;按 `f` 开关(手动切页也会关掉),或用 `--no-follow` 启动。
125
+ 其他环境在项目目录下的第二个终端(或任意分屏)运行
126
+ `node <插件根>/dist/watch.mjs`(同样支持 `--page` / `--no-follow`)。
125
127
 
126
128
  ## 任意 MCP 客户端
127
129
 
package/dist/server.mjs CHANGED
@@ -22515,7 +22515,7 @@ function summarize(map) {
22515
22515
 
22516
22516
  // src/server/server.ts
22517
22517
  var SERVER_NAME = "mellos-mapping";
22518
- var SERVER_VERSION = "0.16.0";
22518
+ var SERVER_VERSION = "0.18.0";
22519
22519
  var ID = external_exports.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/, "lowercase letters, digits and dashes, 1-64 chars").describe("stable kebab-case identifier");
22520
22520
  var PAGE = ID.optional().describe(
22521
22521
  "page (parallel map) this call targets; omit for the default page. One effort = one page: start a NEW effort on its own page named after the effort, so concurrent sessions never write over each other and the pane can switch between pages."
@@ -22556,7 +22556,7 @@ function buildServer(stateFile) {
22556
22556
  "mmap_declare",
22557
22557
  {
22558
22558
  title: "Declare map structure",
22559
- description: "Grow the Mellos map: set the title and diagram kind, add layer bands, lanes and groups (labeled subsystems within a band \u2014 the zoomed-out view renders groups, so declare them for any map beyond a handful of nodes), add nodes, add dependency edges. Declare the whole ghost design up front, then grow it as understanding deepens. Edges must point strictly downward (a node may only use nodes on lower layers); the batch is all-or-nothing.",
22559
+ description: "Grow the Mellos map: set the title and diagram kind, add layer bands, lanes and groups (labeled subsystems within ONE band \u2014 declare them when a single band grows crowded, roughly five or more nodes in that band; a group must be a strict subset of its band, and a map spread thin across many bands needs none), add nodes, add dependency edges. Declare the whole ghost design up front, then grow it as understanding deepens. Edges must point strictly downward (a node may only use nodes on lower layers); the batch is all-or-nothing.",
22560
22560
  inputSchema: {
22561
22561
  page: PAGE,
22562
22562
  title: external_exports.string().max(120).optional().describe("map title, e.g. the feature being built"),
package/dist/watch.mjs CHANGED
@@ -1259,6 +1259,7 @@ function parseInput(chunk) {
1259
1259
  else if (ch === "-") events.push({ kind: "zoom", delta: -1 });
1260
1260
  else if (ch === " ") events.push({ kind: "next-page" });
1261
1261
  else if (ch === "\x7F" || ch === "\b") events.push({ kind: "back" });
1262
+ else if (ch === "f" || ch === "F") events.push({ kind: "follow-toggle" });
1262
1263
  else if (ch >= "1" && ch <= "9") events.push({ kind: "page", index: ch.charCodeAt(0) - "1".charCodeAt(0) });
1263
1264
  else if (KEY_PAN[ch]) events.push({ kind: "pan", ...KEY_PAN[ch] });
1264
1265
  i += 1;
@@ -1274,6 +1275,7 @@ function parseArgs(argv, cwd) {
1274
1275
  let color = true;
1275
1276
  let mouse = true;
1276
1277
  let page;
1278
+ let follow = true;
1277
1279
  for (let i = 0; i < argv.length; i++) {
1278
1280
  switch (argv[i]) {
1279
1281
  case "--file":
@@ -1296,11 +1298,26 @@ function parseArgs(argv, cwd) {
1296
1298
  case "--no-mouse":
1297
1299
  mouse = false;
1298
1300
  break;
1301
+ case "--no-follow":
1302
+ follow = false;
1303
+ break;
1299
1304
  default:
1300
1305
  break;
1301
1306
  }
1302
1307
  }
1303
- return { file, intervalMs, unicode, color, mouse, page };
1308
+ return { file, intervalMs, unicode, color, mouse, page, follow };
1309
+ }
1310
+ function dividerRow(width, unicode, follow) {
1311
+ const grip = unicode ? " \u22EF " : " ~ ";
1312
+ let bar = (unicode ? "\u2500" : "-").repeat(width);
1313
+ const gripAt = Math.max(0, Math.floor((width - grip.length) / 2));
1314
+ if (width > grip.length + 2) bar = bar.slice(0, gripAt) + grip + bar.slice(gripAt + grip.length);
1315
+ if (follow) {
1316
+ const tag = unicode ? " \u21E2 follow " : " > follow ";
1317
+ const at = width - tag.length - 1;
1318
+ if (at > gripAt + grip.length) bar = bar.slice(0, at) + tag + bar.slice(at + tag.length);
1319
+ }
1320
+ return bar;
1304
1321
  }
1305
1322
  function mostRecentPageFile(files, mtimeOf) {
1306
1323
  let best;
@@ -1678,6 +1695,7 @@ function main() {
1678
1695
  let activeFile;
1679
1696
  let firstScan = true;
1680
1697
  let pendingFocusFile = cfg.page === void 0 ? void 0 : pageFilePath(cfg.file, cfg.page);
1698
+ let follow = cfg.follow;
1681
1699
  let lastTabSegments = [];
1682
1700
  let tabScroll = 0;
1683
1701
  let offsetX = 0;
@@ -1744,6 +1762,10 @@ function main() {
1744
1762
  };
1745
1763
  const handSwitch = (file) => {
1746
1764
  pendingFocusFile = void 0;
1765
+ if (follow) {
1766
+ follow = false;
1767
+ flash = { text: "auto-follow off \u2014 press f to re-enable", until: Date.now() + 3e3 };
1768
+ }
1747
1769
  switchPage(file);
1748
1770
  };
1749
1771
  const hitTest = (termX, termY) => {
@@ -1805,10 +1827,7 @@ function main() {
1805
1827
  } else {
1806
1828
  panel = mapPanel(map, cfg.unicode, panelWidth, panelContentRows);
1807
1829
  }
1808
- const grip = cfg.unicode ? " \u22EF " : " ~ ";
1809
- const bar = (cfg.unicode ? "\u2500" : "-").repeat(viewW);
1810
- const gripAt = Math.max(0, Math.floor((viewW - grip.length) / 2));
1811
- const separator = viewW > grip.length + 2 ? bar.slice(0, gripAt) + grip + bar.slice(gripAt + grip.length) : bar;
1830
+ const separator = dividerRow(viewW, cfg.unicode, follow);
1812
1831
  const panelRows = [
1813
1832
  cfg.color ? `\x1B[90m${separator}${RESET}` : separator,
1814
1833
  ...panel.map(
@@ -1875,6 +1894,7 @@ function main() {
1875
1894
  pageViews.delete(known);
1876
1895
  }
1877
1896
  }
1897
+ const changedFiles = [];
1878
1898
  for (const file of pageFiles) {
1879
1899
  let mtimeMs;
1880
1900
  try {
@@ -1886,6 +1906,7 @@ function main() {
1886
1906
  if (mtimeMs === entry?.mtimeMs) continue;
1887
1907
  const loaded = loadMapFile(file);
1888
1908
  if (loaded.ok) {
1909
+ if (!firstScan) changedFiles.push(file);
1889
1910
  const becameFresh = !firstScan && file !== activeFile;
1890
1911
  pageData.set(file, { map: loaded.value, mtimeMs, fresh: becameFresh });
1891
1912
  if (file === activeFile) {
@@ -1905,9 +1926,15 @@ function main() {
1905
1926
  if (request !== void 0 && !(firstScan && pendingFocusFile !== void 0)) {
1906
1927
  pendingFocusFile = pageFilePath(cfg.file, request.page);
1907
1928
  }
1929
+ let requestApplied = false;
1908
1930
  if (pendingFocusFile !== void 0 && pageFiles.includes(pendingFocusFile)) {
1909
1931
  if (pendingFocusFile !== activeFile) switchPage(pendingFocusFile);
1910
1932
  pendingFocusFile = void 0;
1933
+ requestApplied = true;
1934
+ }
1935
+ if (follow && !requestApplied && changedFiles.length > 0 && dragAnchor === void 0) {
1936
+ const target = mostRecentPageFile(changedFiles, (f) => pageData.get(f)?.mtimeMs);
1937
+ if (target !== activeFile) switchPage(target);
1911
1938
  }
1912
1939
  firstScan = false;
1913
1940
  if (activeFile === void 0 || !pageFiles.includes(activeFile)) {
@@ -2076,6 +2103,11 @@ function main() {
2076
2103
  case "back":
2077
2104
  if (climbBack()) dirty = true;
2078
2105
  break;
2106
+ case "follow-toggle":
2107
+ follow = !follow;
2108
+ flash = { text: follow ? "auto-follow on" : "auto-follow off", until: Date.now() + 2500 };
2109
+ dirty = true;
2110
+ break;
2079
2111
  }
2080
2112
  }
2081
2113
  if (dirty) paint();
@@ -2110,6 +2142,7 @@ export {
2110
2142
  anchorOffsets,
2111
2143
  clampPanelRows,
2112
2144
  diveOrigin,
2145
+ dividerRow,
2113
2146
  fitWidth,
2114
2147
  launchedAsEntry,
2115
2148
  liveRipples,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mellos-mapping",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "mcpName": "io.github.GuangminJu/mellos-mapping",
5
5
  "description": "A live layered dependency map for bottom-up development — MCP server + terminal pane. Ghost the design first, then light nodes up from the bottom as they are built and verified.",
6
6
  "type": "module",