mellos-mapping 0.19.0 → 0.20.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
@@ -147,7 +147,7 @@ npx -y mellos-mapping
147
147
  ```
148
148
 
149
149
  The map file lands in the client session's working directory
150
- (`.claude/mellos-mapping.json`). Open the live pane from the same project:
150
+ (`.mellos/map.json`). Open the live pane from the same project:
151
151
 
152
152
  ```
153
153
  npx -y -p mellos-mapping mellos-mapping-watch
@@ -224,8 +224,8 @@ its own pan, zoom and pinned node. Because every page is its own file, two
224
224
  Claude sessions writing two pages can never clobber each other — this is
225
225
  also the answer to running several Claude sessions in one project.
226
226
 
227
- State lives in `.claude/mellos-mapping.json` (the default page) plus
228
- `.claude/mellos-mapping.pages/<page>.json` for named pages — plain JSON,
227
+ State lives in `.mellos/map.json` (the default page) plus
228
+ `.mellos/pages/<page>.json` for named pages — plain JSON,
229
229
  safe to commit if you want the maps' history in git.
230
230
 
231
231
  ### Diagram kinds
@@ -299,7 +299,9 @@ The repo is itself layered bottom-up, and each layer has its spec:
299
299
  | Layer | Code | Owns |
300
300
  | --- | --- | --- |
301
301
  | 0 domain | `src/domain/` | the map value, structural invariants, pure ops |
302
- | 1 store | `src/store/` | atomic state-file persistence, boundary validation |
302
+ | 1 format | `src/store/format.ts` | the state-file format: replay-validated parse, serialize I/O-free |
303
+ | 1 store | `src/store/store.ts` | atomic state-file persistence on Node |
304
+ | 1 semantics | `src/semantics/` | medium-neutral view semantics: zoom ladder, group aggregation, sequence flip |
303
305
  | 2 apply | `src/server/apply.ts` | tool inputs → transactional op sequences |
304
306
  | 3 server | `src/server/server.ts` | the four MCP tools over stdio |
305
307
  | 4 render | `src/render/`, `src/watch/` | ASCII renderer and the polling pane |
@@ -307,6 +309,17 @@ The repo is itself layered bottom-up, and each layer has its spec:
307
309
  `dist/` is committed deliberately: plugin installation clones this repo and
308
310
  runs nothing, so entry points ship bundled.
309
311
 
312
+ ### Library
313
+
314
+ The lower layers are also a library (`npm run build` emits `lib/` with type
315
+ declarations; npm packs it). Subpath exports mirror the source:
316
+ `mellos-mapping/domain/types`, `/domain/ops`, `/format`, `/semantics` are
317
+ **browser-safe** — no Node builtins in their import closure, gated by a test —
318
+ so a graphical client (a web panel, an editor view) can parse state files and
319
+ reuse the exact aggregation and zoom semantics the terminal pane draws with.
320
+ `/store` (Node filesystem persistence) and `/render` (the terminal renderer)
321
+ complete the surface for Node hosts.
322
+
310
323
  ## License
311
324
 
312
325
  MIT
package/README.zh-CN.md CHANGED
@@ -134,7 +134,7 @@ CLI……)都能用标准 stdio 条目接入:
134
134
  npx -y mellos-mapping
135
135
  ```
136
136
 
137
- 地图文件落在客户端会话的工作目录(`.claude/mellos-mapping.json`)。在同
137
+ 地图文件落在客户端会话的工作目录(`.mellos/map.json`)。在同
138
138
  一项目里打开实况面板:
139
139
 
140
140
  ```
@@ -204,8 +204,8 @@ npx -y -p mellos-mapping mellos-mapping-watch
204
204
  每页就是一个独立文件,两个 Claude 会话各写各页永远不会互相覆盖——这也是
205
205
  同一项目里跑多个 Claude 会话的正确姿势。
206
206
 
207
- 地图状态存在 `.claude/mellos-mapping.json`(默认页)和
208
- `.claude/mellos-mapping.pages/<页名>.json`(命名页)——纯 JSON,想在 git
207
+ 地图状态存在 `.mellos/map.json`(默认页)和
208
+ `.mellos/pages/<页名>.json`(命名页)——纯 JSON,想在 git
209
209
  里留下地图的历史就把它们提交进去。
210
210
 
211
211
  ### 图种
@@ -272,7 +272,9 @@ npm run verify # 类型检查 + 测试 + 打包
272
272
  | 层 | 代码 | 职责 |
273
273
  | --- | --- | --- |
274
274
  | 0 domain | `src/domain/` | 地图值、结构不变量、纯操作 |
275
- | 1 store | `src/store/` | 原子化状态文件持久化、边界校验 |
275
+ | 1 format | `src/store/format.ts` | 状态文件格式:重放校验的解析与序列化,零 I/O |
276
+ | 1 store | `src/store/store.ts` | Node 上的原子化状态文件持久化 |
277
+ | 1 semantics | `src/semantics/` | 媒介无关的视图语义:缩放阶梯、分组聚合、时序翻转 |
276
278
  | 2 apply | `src/server/apply.ts` | 工具输入 → 事务性操作序列 |
277
279
  | 3 server | `src/server/server.ts` | stdio 上的四个 MCP 工具 |
278
280
  | 4 render | `src/render/`、`src/watch/` | ASCII 渲染器和轮询面板 |
@@ -280,6 +282,16 @@ npm run verify # 类型检查 + 测试 + 打包
280
282
  `dist/` 是刻意提交的:插件安装就是克隆本仓库、不运行任何东西,所以入口
281
283
  文件以打包形式随仓库分发。
282
284
 
285
+ ### 库
286
+
287
+ 底部各层同时是一个库(`npm run build` 产出带类型声明的 `lib/`,npm 打包
288
+ 收录)。子路径导出与源码结构一一对应:`mellos-mapping/domain/types`、
289
+ `/domain/ops`、`/format`、`/semantics` 是**浏览器安全**的——import 闭包中
290
+ 没有任何 Node 内建模块,由测试门禁守护——图形客户端(web 面板、编辑器
291
+ 视图)可以直接解析状态文件,并复用与终端面板完全一致的聚合与缩放语义。
292
+ `/store`(Node 文件系统持久化)与 `/render`(终端渲染器)补齐 Node 宿主
293
+ 所需的完整表面。
294
+
283
295
  ## 许可证
284
296
 
285
297
  MIT
package/dist/server.mjs CHANGED
@@ -21388,13 +21388,66 @@ function removeLayer(map, id) {
21388
21388
  return ok({ ...map, layers: map.layers.filter((l) => l.id !== id) });
21389
21389
  }
21390
21390
 
21391
- // src/render/render.ts
21391
+ // src/semantics/semantics.ts
21392
21392
  var ZOOM_MIN = -4;
21393
21393
  var ZOOM_MAX = 2;
21394
21394
  var ZOOM_DEFAULT = 0;
21395
21395
  function clampZoom(n) {
21396
21396
  return Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, Math.round(n)));
21397
21397
  }
21398
+ function zoomMode(zoom) {
21399
+ if (zoom >= 1) return "detail";
21400
+ if (zoom <= -4) return "overview";
21401
+ return "boxes";
21402
+ }
21403
+ function isNeutralKind(map) {
21404
+ return map.kind !== void 0 && map.kind !== "dev";
21405
+ }
21406
+ function aggregateMap(map) {
21407
+ if (map.groups.length === 0) return void 0;
21408
+ const representative = /* @__PURE__ */ new Map();
21409
+ for (const n of map.nodes) representative.set(n.id, n.group ?? n.id);
21410
+ const nodes = map.groups.map((g) => {
21411
+ const members = map.nodes.filter((n) => n.group === g.id);
21412
+ const done = members.filter((n) => n.status === "done").length;
21413
+ return {
21414
+ id: g.id,
21415
+ // neutral kinds document structure, not progress — no member counts
21416
+ label: isNeutralKind(map) ? g.label : `${g.label} ${done}/${members.length}`,
21417
+ layer: g.layer,
21418
+ status: groupStatus(map, g.id)
21419
+ };
21420
+ });
21421
+ for (const n of map.nodes) if (n.group === void 0) nodes.push(n);
21422
+ const seen = /* @__PURE__ */ new Set();
21423
+ const edges = [];
21424
+ for (const e of map.edges) {
21425
+ const from = representative.get(e.from);
21426
+ const to = representative.get(e.to);
21427
+ if (from === to || seen.has(`${from}->${to}`)) continue;
21428
+ seen.add(`${from}->${to}`);
21429
+ edges.push({ from, to });
21430
+ }
21431
+ return {
21432
+ ...map.title !== void 0 ? { title: map.title } : {},
21433
+ ...map.kind !== void 0 ? { kind: map.kind } : {},
21434
+ layers: map.layers,
21435
+ groups: [],
21436
+ lanes: map.lanes,
21437
+ nodes,
21438
+ edges
21439
+ };
21440
+ }
21441
+ function flipForSequence(map) {
21442
+ if (map.kind !== "sequence") return map;
21443
+ return {
21444
+ ...map,
21445
+ layers: map.layers.map((l) => ({ ...l, rank: -l.rank })),
21446
+ edges: map.edges.map((e) => ({ from: e.to, to: e.from, ...e.label !== void 0 ? { label: e.label } : {} }))
21447
+ };
21448
+ }
21449
+
21450
+ // src/render/render.ts
21398
21451
  var WIDE_RANGES = [
21399
21452
  [4352, 4447],
21400
21453
  // Hangul Jamo
@@ -21659,9 +21712,6 @@ function kindGlyph(kind, unicode) {
21659
21712
  const pair = NODE_KIND_GLYPHS[kind];
21660
21713
  return pair === void 0 ? void 0 : unicode ? pair[0] : pair[1];
21661
21714
  }
21662
- function isNeutralKind(map) {
21663
- return map.kind !== void 0 && map.kind !== "dev";
21664
- }
21665
21715
  function neutralSkin(unicode) {
21666
21716
  return unicode ? { h: "\u2500", v: "\u2502", corners: ["\u256D", "\u256E", "\u2570", "\u256F"], style: "none" } : { h: "-", v: "|", corners: ["+", "+", "+", "+"], style: "none" };
21667
21717
  }
@@ -21671,21 +21721,23 @@ var LEFT_MARGIN = 2;
21671
21721
  var DETAIL_BUDGET = { innerMin: 22, innerMax: 32, noteRows: 3 };
21672
21722
  var DETAIL_PLUS_BUDGET = { innerMin: 30, innerMax: 48, noteRows: 12 };
21673
21723
  function zoomGeometry(zoom) {
21724
+ const m = zoomMode(zoom);
21725
+ const mode = m === "overview" ? "constellation" : m;
21674
21726
  switch (zoom) {
21675
21727
  case 2:
21676
- return { mode: "detail", scale: 1, pad: 1, boxGap: BOX_GAP, breathe: 1, titleGap: 1, barGap: 1, bandCounts: false, detail: DETAIL_PLUS_BUDGET };
21728
+ return { mode, scale: 1, pad: 1, boxGap: BOX_GAP, breathe: 1, titleGap: 1, barGap: 1, bandCounts: false, detail: DETAIL_PLUS_BUDGET };
21677
21729
  case 1:
21678
- return { mode: "detail", scale: 1, pad: 1, boxGap: BOX_GAP, breathe: 1, titleGap: 1, barGap: 1, bandCounts: false, detail: DETAIL_BUDGET };
21730
+ return { mode, scale: 1, pad: 1, boxGap: BOX_GAP, breathe: 1, titleGap: 1, barGap: 1, bandCounts: false, detail: DETAIL_BUDGET };
21679
21731
  case 0:
21680
- return { mode: "boxes", scale: 1, pad: 1, boxGap: BOX_GAP, breathe: 1, titleGap: 1, barGap: 1, bandCounts: false };
21732
+ return { mode, scale: 1, pad: 1, boxGap: BOX_GAP, breathe: 1, titleGap: 1, barGap: 1, bandCounts: false };
21681
21733
  case -1:
21682
- return { mode: "boxes", scale: 0.85, pad: 1, boxGap: BOX_GAP, breathe: 1, titleGap: 1, barGap: 1, bandCounts: false };
21734
+ return { mode, scale: 0.85, pad: 1, boxGap: BOX_GAP, breathe: 1, titleGap: 1, barGap: 1, bandCounts: false };
21683
21735
  case -2:
21684
- return { mode: "boxes", scale: 0.7, pad: 0, boxGap: BOX_GAP, breathe: 0, titleGap: 0, barGap: 1, bandCounts: false };
21736
+ return { mode, scale: 0.7, pad: 0, boxGap: BOX_GAP, breathe: 0, titleGap: 0, barGap: 1, bandCounts: false };
21685
21737
  case -3:
21686
- return { mode: "boxes", scale: 0.55, pad: 0, boxGap: 1, breathe: 0, titleGap: 0, barGap: 1, bandCounts: true };
21738
+ return { mode, scale: 0.55, pad: 0, boxGap: 1, breathe: 0, titleGap: 0, barGap: 1, bandCounts: true };
21687
21739
  case -4:
21688
- return { mode: "constellation", scale: 0, pad: 0, boxGap: BOX_GAP, breathe: 0, titleGap: 0, barGap: 1, bandCounts: true };
21740
+ return { mode, scale: 0, pad: 0, boxGap: BOX_GAP, breathe: 0, titleGap: 0, barGap: 1, bandCounts: true };
21689
21741
  }
21690
21742
  }
21691
21743
  var LABEL_BUDGET_MIN = 4;
@@ -21733,41 +21785,6 @@ function renderMap(map, opts) {
21733
21785
  const built = buildCanvas(map, opts);
21734
21786
  return built.canvas.emit(opts);
21735
21787
  }
21736
- function aggregateMap(map) {
21737
- if (map.groups.length === 0) return void 0;
21738
- const representative = /* @__PURE__ */ new Map();
21739
- for (const n of map.nodes) representative.set(n.id, n.group ?? n.id);
21740
- const nodes = map.groups.map((g) => {
21741
- const members = map.nodes.filter((n) => n.group === g.id);
21742
- const done = members.filter((n) => n.status === "done").length;
21743
- return {
21744
- id: g.id,
21745
- // neutral kinds document structure, not progress — no member counts
21746
- label: isNeutralKind(map) ? g.label : `${g.label} ${done}/${members.length}`,
21747
- layer: g.layer,
21748
- status: groupStatus(map, g.id)
21749
- };
21750
- });
21751
- for (const n of map.nodes) if (n.group === void 0) nodes.push(n);
21752
- const seen = /* @__PURE__ */ new Set();
21753
- const edges = [];
21754
- for (const e of map.edges) {
21755
- const from = representative.get(e.from);
21756
- const to = representative.get(e.to);
21757
- if (from === to || seen.has(`${from}->${to}`)) continue;
21758
- seen.add(`${from}->${to}`);
21759
- edges.push({ from, to });
21760
- }
21761
- return {
21762
- ...map.title !== void 0 ? { title: map.title } : {},
21763
- ...map.kind !== void 0 ? { kind: map.kind } : {},
21764
- layers: map.layers,
21765
- groups: [],
21766
- lanes: map.lanes,
21767
- nodes,
21768
- edges
21769
- };
21770
- }
21771
21788
  var AGGREGATE_GEO = {
21772
21789
  mode: "boxes",
21773
21790
  scale: 1,
@@ -21778,14 +21795,6 @@ var AGGREGATE_GEO = {
21778
21795
  barGap: 1,
21779
21796
  bandCounts: false
21780
21797
  };
21781
- function flipForSequence(map) {
21782
- if (map.kind !== "sequence") return map;
21783
- return {
21784
- ...map,
21785
- layers: map.layers.map((l) => ({ ...l, rank: -l.rank })),
21786
- edges: map.edges.map((e) => ({ from: e.to, to: e.from, ...e.label !== void 0 ? { label: e.label } : {} }))
21787
- };
21788
- }
21789
21798
  function buildCanvas(map, opts) {
21790
21799
  const oriented = flipForSequence(map);
21791
21800
  const plainGeo = zoomGeometry(opts.zoom ?? ZOOM_DEFAULT);
@@ -22135,63 +22144,9 @@ function drawBox(canvas, box, opts, neutral, focused = false) {
22135
22144
  // src/store/store.ts
22136
22145
  import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
22137
22146
  import { basename, dirname, join } from "node:path";
22147
+
22148
+ // src/store/format.ts
22138
22149
  var STATE_FILE_VERSION = 1;
22139
- var STATE_FILE_RELATIVE_PATH = join(".claude", "mellos-mapping.json");
22140
- var PAGES_DIR_NAME = "mellos-mapping.pages";
22141
- function pageFilePath(defaultFile, page) {
22142
- return page === void 0 ? defaultFile : join(dirname(defaultFile), PAGES_DIR_NAME, `${page}.json`);
22143
- }
22144
- var CONFIG_FILE_NAME = "mellos-mapping.config.json";
22145
- var CONFIG_FILE_VERSION = 1;
22146
- function configFilePath(defaultFile) {
22147
- return join(dirname(defaultFile), CONFIG_FILE_NAME);
22148
- }
22149
- var MAPPING_POLICIES = ["always", "complex", "on-request"];
22150
- function makeMappingPolicy(raw) {
22151
- return MAPPING_POLICIES.includes(raw) ? ok(raw) : err({ kind: "invalid-policy", raw, allowed: MAPPING_POLICIES });
22152
- }
22153
- function describeMappingPolicy(policy) {
22154
- switch (policy) {
22155
- case "always":
22156
- return "map every structured task \u2014 workflows, designs, architecture, technical dependencies";
22157
- case "complex":
22158
- return "map only medium or complex tasks \u2014 several modules, a new subsystem, roughly an hour or more";
22159
- case "on-request":
22160
- return "map only when the user explicitly asks";
22161
- }
22162
- }
22163
- function loadMappingPolicy(defaultFile) {
22164
- const path = configFilePath(defaultFile);
22165
- let text2;
22166
- try {
22167
- text2 = readFileSync(path, "utf8");
22168
- } catch (e) {
22169
- if (e.code === "ENOENT") return ok(void 0);
22170
- throw e;
22171
- }
22172
- let raw;
22173
- try {
22174
- raw = JSON.parse(text2);
22175
- } catch (e) {
22176
- return err({ kind: "malformed-json", path, detail: e.message });
22177
- }
22178
- if (!isRecord(raw)) return err({ kind: "bad-shape", path, detail: "root is not an object" });
22179
- if (raw["version"] !== CONFIG_FILE_VERSION) {
22180
- return err({ kind: "bad-shape", path, detail: `version is ${String(raw["version"])}, expected ${CONFIG_FILE_VERSION}` });
22181
- }
22182
- const rawPolicy = raw["policy"];
22183
- if (rawPolicy === void 0) return ok(void 0);
22184
- if (typeof rawPolicy !== "string") return err({ kind: "bad-shape", path, detail: "policy is not a string" });
22185
- const policy = makeMappingPolicy(rawPolicy);
22186
- return policy.ok ? ok(policy.value) : err({ kind: "bad-shape", path, detail: `policy is "${rawPolicy}", expected one of: ${MAPPING_POLICIES.join(" | ")}` });
22187
- }
22188
- function saveMappingPolicy(defaultFile, policy) {
22189
- const path = configFilePath(defaultFile);
22190
- mkdirSync(dirname(path), { recursive: true });
22191
- const tmp = path + ".tmp";
22192
- writeFileSync(tmp, JSON.stringify({ version: CONFIG_FILE_VERSION, policy }, null, 2) + "\n", "utf8");
22193
- renameSync(tmp, path);
22194
- }
22195
22150
  function describeStoreError(e) {
22196
22151
  switch (e.kind) {
22197
22152
  case "not-found":
@@ -22346,6 +22301,84 @@ function serializeMap(map) {
22346
22301
  };
22347
22302
  return JSON.stringify(body, null, 2) + "\n";
22348
22303
  }
22304
+
22305
+ // src/store/store.ts
22306
+ var STATE_FILE_RELATIVE_PATH = join(".mellos", "map.json");
22307
+ var PAGES_DIR_NAME = "pages";
22308
+ function pageFilePath(defaultFile, page) {
22309
+ return page === void 0 ? defaultFile : join(dirname(defaultFile), PAGES_DIR_NAME, `${page}.json`);
22310
+ }
22311
+ var CONFIG_FILE_NAME = "config.json";
22312
+ var CONFIG_FILE_VERSION = 1;
22313
+ function configFilePath(defaultFile) {
22314
+ return join(dirname(defaultFile), CONFIG_FILE_NAME);
22315
+ }
22316
+ var MAPPING_POLICIES = ["always", "complex", "on-request"];
22317
+ function makeMappingPolicy(raw) {
22318
+ return MAPPING_POLICIES.includes(raw) ? ok(raw) : err({ kind: "invalid-policy", raw, allowed: MAPPING_POLICIES });
22319
+ }
22320
+ function describeMappingPolicy(policy) {
22321
+ switch (policy) {
22322
+ case "always":
22323
+ return "map every structured task \u2014 workflows, designs, architecture, technical dependencies";
22324
+ case "complex":
22325
+ return "map only medium or complex tasks \u2014 several modules, a new subsystem, roughly an hour or more";
22326
+ case "on-request":
22327
+ return "map only when the user explicitly asks";
22328
+ }
22329
+ }
22330
+ function isRecord2(v) {
22331
+ return typeof v === "object" && v !== null && !Array.isArray(v);
22332
+ }
22333
+ function loadMappingPolicy(defaultFile) {
22334
+ const path = configFilePath(defaultFile);
22335
+ let text2;
22336
+ try {
22337
+ text2 = readFileSync(path, "utf8");
22338
+ } catch (e) {
22339
+ if (e.code === "ENOENT") return ok(void 0);
22340
+ throw e;
22341
+ }
22342
+ let raw;
22343
+ try {
22344
+ raw = JSON.parse(text2);
22345
+ } catch (e) {
22346
+ return err({ kind: "malformed-json", path, detail: e.message });
22347
+ }
22348
+ if (!isRecord2(raw)) return err({ kind: "bad-shape", path, detail: "root is not an object" });
22349
+ if (raw["version"] !== CONFIG_FILE_VERSION) {
22350
+ return err({ kind: "bad-shape", path, detail: `version is ${String(raw["version"])}, expected ${CONFIG_FILE_VERSION}` });
22351
+ }
22352
+ const rawPolicy = raw["policy"];
22353
+ if (rawPolicy === void 0) return ok(void 0);
22354
+ if (typeof rawPolicy !== "string") return err({ kind: "bad-shape", path, detail: "policy is not a string" });
22355
+ const policy = makeMappingPolicy(rawPolicy);
22356
+ return policy.ok ? ok(policy.value) : err({ kind: "bad-shape", path, detail: `policy is "${rawPolicy}", expected one of: ${MAPPING_POLICIES.join(" | ")}` });
22357
+ }
22358
+ function saveMappingPolicy(defaultFile, policy) {
22359
+ const path = configFilePath(defaultFile);
22360
+ mkdirSync(dirname(path), { recursive: true });
22361
+ const tmp = path + ".tmp";
22362
+ writeFileSync(tmp, JSON.stringify({ version: CONFIG_FILE_VERSION, policy }, null, 2) + "\n", "utf8");
22363
+ renameSync(tmp, path);
22364
+ }
22365
+ var LEGACY_STATE_FILE_RELATIVE_PATH = join(".claude", "mellos-mapping.json");
22366
+ var LEGACY_PAGES_DIR_NAME = "mellos-mapping.pages";
22367
+ var LEGACY_CONFIG_FILE_NAME = "mellos-mapping.config.json";
22368
+ function migrateLegacyStore(defaultFile) {
22369
+ const projectRoot = dirname(dirname(defaultFile));
22370
+ const legacyDefault = join(projectRoot, LEGACY_STATE_FILE_RELATIVE_PATH);
22371
+ const legacyPages = join(dirname(legacyDefault), LEGACY_PAGES_DIR_NAME);
22372
+ const legacyConfig = join(dirname(legacyDefault), LEGACY_CONFIG_FILE_NAME);
22373
+ const hasLegacy = existsSync(legacyDefault) || existsSync(legacyPages) || existsSync(legacyConfig);
22374
+ const hasCurrent = existsSync(defaultFile) || existsSync(join(dirname(defaultFile), PAGES_DIR_NAME)) || existsSync(configFilePath(defaultFile));
22375
+ if (!hasLegacy || hasCurrent) return false;
22376
+ mkdirSync(dirname(defaultFile), { recursive: true });
22377
+ if (existsSync(legacyDefault)) renameSync(legacyDefault, defaultFile);
22378
+ if (existsSync(legacyPages)) renameSync(legacyPages, join(dirname(defaultFile), PAGES_DIR_NAME));
22379
+ if (existsSync(legacyConfig)) renameSync(legacyConfig, configFilePath(defaultFile));
22380
+ return true;
22381
+ }
22349
22382
  function loadMapFile(path) {
22350
22383
  let text2;
22351
22384
  try {
@@ -22566,7 +22599,7 @@ function summarize(map) {
22566
22599
 
22567
22600
  // src/server/server.ts
22568
22601
  var SERVER_NAME = "mellos-mapping";
22569
- var SERVER_VERSION = "0.19.0";
22602
+ var SERVER_VERSION = "0.20.0";
22570
22603
  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");
22571
22604
  var PAGE = ID.optional().describe(
22572
22605
  "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."
@@ -22753,7 +22786,9 @@ function resolveStateFile(env, cwd) {
22753
22786
  return join2(projectDir, STATE_FILE_RELATIVE_PATH);
22754
22787
  }
22755
22788
  async function main() {
22756
- const server = buildServer(resolveStateFile(process.env, process.cwd()));
22789
+ const stateFile = resolveStateFile(process.env, process.cwd());
22790
+ migrateLegacyStore(stateFile);
22791
+ const server = buildServer(stateFile);
22757
22792
  await server.connect(new StdioServerTransport());
22758
22793
  }
22759
22794
  function launchedAsEntry(argv1, moduleUrl) {