ggn-layout 0.1.0 → 0.1.1

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 (56) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/LICENSE +15 -0
  3. package/README.md +13 -5
  4. package/THIRD_PARTY_NOTICES.md +35 -3
  5. package/dist/{algorithms-CNhihjzf.js → algorithms-CndAU_xu.js} +9 -0
  6. package/dist/{algorithms-DXUI06fi.cjs → algorithms-gBJvJ1vu.cjs} +9 -0
  7. package/dist/api/index.cjs +10 -1
  8. package/dist/api/index.d.cts +12 -3
  9. package/dist/api/index.d.ts +12 -3
  10. package/dist/api/index.js +10 -1
  11. package/dist/api/layered.cjs +10 -1
  12. package/dist/api/layered.d.cts +11 -2
  13. package/dist/api/layered.d.ts +11 -2
  14. package/dist/api/layered.js +10 -1
  15. package/dist/{api-BRaDa6RG.js → api-CJOvh1wF.js} +10 -1
  16. package/dist/{api-DWBi7ngO.cjs → api-D6wZ8K92.cjs} +10 -1
  17. package/dist/{elk-json-B9eLYtu6.js → elk-json-Bli8UvHo.js} +10 -1
  18. package/dist/{elk-json-ibWtLFj2.d.cts → elk-json-Cf5biFF7.d.cts} +9 -0
  19. package/dist/{elk-json-ibWtLFj2.d.ts → elk-json-Cf5biFF7.d.ts} +9 -0
  20. package/dist/{elk-json-BtGnwuQE.cjs → elk-json-Ow0_ujWC.cjs} +10 -1
  21. package/dist/{index-Dl2hrLFA.d.cts → index-9-rJw6UF.d.cts} +11 -2
  22. package/dist/{index-C_0jvfEV.d.ts → index-CC3PKvJ0.d.ts} +11 -2
  23. package/dist/index.cjs +10 -1
  24. package/dist/index.d.cts +14 -5
  25. package/dist/index.d.ts +14 -5
  26. package/dist/index.js +10 -1
  27. package/dist/{internal-BOuvVTiR.d.cts → internal-CbM3qPZx.d.ts} +11 -2
  28. package/dist/{internal-Coxrnk9C.d.ts → internal-TOWD-Rww.d.cts} +11 -2
  29. package/dist/internal.cjs +10 -1
  30. package/dist/internal.d.cts +12 -3
  31. package/dist/internal.d.ts +12 -3
  32. package/dist/internal.js +10 -1
  33. package/dist/layered-options-BsoOG6Wx.d.ts +15 -0
  34. package/dist/layered-options-CJRS7cIk.d.cts +15 -0
  35. package/dist/layout-worker.cjs +10 -1
  36. package/dist/layout-worker.d.cts +10 -1
  37. package/dist/layout-worker.d.ts +10 -1
  38. package/dist/layout-worker.js +10 -1
  39. package/dist/options.cjs +10 -1
  40. package/dist/options.d.cts +11 -2
  41. package/dist/options.d.ts +11 -2
  42. package/dist/options.js +10 -1
  43. package/dist/{validate-B9vX3T2G.d.cts → validate-CcKdG1RG.d.cts} +9 -0
  44. package/dist/{validate-B9vX3T2G.d.ts → validate-CcKdG1RG.d.ts} +9 -0
  45. package/docs/reference/elk-algorithm-catalog.md +2 -2
  46. package/docs/reference/elk-algorithm-guide.md +4 -4
  47. package/docs/reference/elk-edge-routing-investigation.md +9 -12
  48. package/docs/reference/elk-json-format.md +1 -1
  49. package/docs/reference/elk-layout-options-mechanism.md +1 -1
  50. package/docs/reference/elk-layout-options.md +4 -4
  51. package/docs/reference/elk-node-labels.md +11 -8
  52. package/docs/reference/elk-spacing-options.md +1 -1
  53. package/docs/reference/elkjs-feature-coverage.md +2 -3
  54. package/package.json +11 -3
  55. package/dist/layered-options-COPhjoOB.d.ts +0 -6
  56. package/dist/layered-options-Dm7nJC1R.d.cts +0 -6
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Status**: 🟢 Active
4
4
  > **Last Updated**: 2026-09-10
5
- > **Parent**: [文档索引](../README.md)
5
+ > **Parent**: [文档索引](../../README.md)
6
6
  > **Objective**: 回答「图里拐角很多」的三个问题——ggn-layout 是否劣于原生 ELK Java、是否存在最优参数、算法层还有多少优化空间——并给出可执行建议与复现路径。
7
7
 
8
8
  ## 1. 问题与样本
@@ -27,7 +27,7 @@
27
27
 
28
28
  ### 3.1 方法
29
29
 
30
- 1. 从 Viewer `GET /api/events` 抓取 `run_ggn_project_feedback` 全量事件,用 `@ggn/agent` reducer 重放成场景元素;
30
+ 1. 从 Viewer `GET /api/events` 抓取 `run_ggn_project_feedback` 全量事件,用宿主应用的 event reducer 重放成场景元素;
31
31
  2. 用 kernel `measureNode()` 计算节点尺寸,导出标准 ELK JSON(19 边 / 12 节点 / `json.shapeCoords=ROOT`);
32
32
  3. **同一份 JSON** 分别跑:
33
33
  - 本仓库:`src/api/index.ts` 的 `layoutElkJson()`
@@ -138,7 +138,7 @@
138
138
 
139
139
  改造后宿主图仍是同一套 layered 语义(`rel_*` 依赖在容器内部参与分层),只是层次不再用长边表达。
140
140
 
141
- **已实施(2026-09-10)**:`@ggn/agent` 归约器不再发 `contains` 边——有子模块的 module 直接渲染成
141
+ **已实施(2026-09-10)**:宿主应用的归约器不再发 `contains` 边——有子模块的 module 直接渲染成
142
142
  `group` 容器(children = 子模块),容器自身承载标题 / 状态行 / 进度条(kernel group-renderer)。
143
143
  同口径复测(`layoutScene` 前后对照,`run_ggn_project_feedback` 63 事件快照):
144
144
 
@@ -186,22 +186,19 @@
186
186
 
187
187
  ```text
188
188
  1) 抓事件 GET http://127.0.0.1:5198/api/events → 过滤 runId
189
- 2) 重放 @ggn/agent reduceAgentEvents → createScene/updateElements → 元素集
189
+ 2) 重放 宿主应用 reducer → createScene/updateElements → 元素集
190
190
  3) 量尺寸 kernel measureNode() → 节点 width/height
191
191
  4) 导 ELK JSON id + children(size) + edges(sources/targets) + layoutOptions(ROOT 坐标 + NETWORK_SIMPLEX + edgeNodeBetweenLayers=14)
192
192
  5) 双侧跑布局 ggn-layout layoutElkJson() vs Java oracle(同一份 JSON)
193
193
  6) 比指标 逐边折点/端点(ε=0.01)+ 弯点数 + 总边长 + 交叉对
194
194
  ```
195
195
 
196
- 本次产物(临时文件,可复跑但会随 `/tmp` 清理):`/tmp/ggn-edge-input.json`(19 边样本)、
197
- `/tmp/ggn-edge-output-ggn.json`、`/tmp/ggn-edge-java-raw.txt`、`/tmp/ggn-vs-java-edge-metrics.json`。
196
+ 本次产物为一次会话内的临时文件(19 边输入样本、双侧输出、逐边指标),未入库、也未随包发布。
198
197
 
199
- Java oracle 命令(ELK 0.12.0 + 未签名 layered jar):
198
+ Java oracle 命令(ELK 0.12.0 + 未签名 layered jar;`LayoutJsonMain` 是一次会话内的临时探针程序):
200
199
 
201
200
  ```bash
202
- /opt/homebrew/opt/openjdk@21/bin/java -cp \
203
- "scripts/elk-java-debug/out-edge:scripts/elk-java-debug/lib/*" \
204
- LayoutJsonMain /tmp/ggn-edge-input.json > /tmp/ggn-edge-java-raw.txt
201
+ java -cp "<probe-out>:<elk-jars>/*" LayoutJsonMain <input.json> > <java-raw.txt>
205
202
  ```
206
203
 
207
204
  > 长期回归建议:把「层次包含 vs contains 长边」两个样本收敛为 `本仓库` 的测试用例
@@ -211,5 +208,5 @@ Java oracle 命令(ELK 0.12.0 + 未签名 layered jar):
211
208
 
212
209
  - [ELK 间距选项指南](./elk-spacing-options.md):间距成对语义与覆盖规则
213
210
  - [ELK 布局选项接口参考](./elk-layout-options.md):`LayeredOptions` 键与默认值
214
- - [GGN 渲染参数规格](../design/ggn-render-params.md):edge 渲染参数与圆角语义
215
- - [Agent 开发过程可视化事件协议](../design/agent-development-event-protocol.md):`contains` 与层级语义
211
+ - GGN 渲染参数规格(edge 渲染参数与圆角语义)——随 GGN 主仓库维护,本仓不含该文档。
212
+ - Agent 开发过程可视化事件协议(`contains` 与层级语义)——同上,随 GGN 主仓库维护。
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Status**: 🟢 Active
4
4
  > **Last Updated**: 2026-08-14
5
- > **Parent**: [文档索引](../README.md)
5
+ > **Parent**: [文档索引](../../README.md)
6
6
  > **Objective**: 移植 ELK Java「JSON Format」图格式指南——节点 / 端口 / 标签 / 边 / 边段五种基本元素与导入导出 API,并注明本移植的针对性差异(校验、超边、输出形态)。
7
7
 
8
8
  ## 1. 背景与来源(为什么有这份文档)
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Status**: 🟢 Active
4
4
  > **Last Updated**: 2026-08-14
5
- > **Parent**: [文档索引](../README.md)
5
+ > **Parent**: [文档索引](../../README.md)
6
6
  > **Objective**: 移植 ELK Java「Layout Options」机制指南——`IProperty` / `IPropertyHolder` 的读 / 写 / 查语义、同 id 不同默认值、内部属性约定,与 TS 移植的 `Property` / `MapPropertyHolder` 一一对应。
7
7
 
8
8
  ## 1. 背景与来源(为什么有这份文档)
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Status**: 🟢 Active
4
4
  > **Last Updated**: 2026-08-14
5
- > **Parent**: [文档索引](../README.md)
5
+ > **Parent**: [文档索引](../../README.md)
6
6
  > **Objective**: 移植 ELK Java 0.12.0 布局选项接口(CoreOptions / LayeredOptions)到本项目的权威对照表——选项键、TS Property、类型、默认值一一对应;供 `kernel:layout` 接线与消费方查表。
7
7
 
8
8
  ## 1. 背景与来源(为什么有这份文档)
@@ -15,7 +15,7 @@
15
15
  - 其他算法模块:各自目录下的 `options.ts`(`DEFAULTS` 对象),见 [§6 其他算法模块选项](#6-其他算法模块选项)
16
16
  - 内部属性(`*.internal.*`,非用户接口):`src/options/internal-properties.ts`,不在本表列出,见 [§8 边界](#8-边界与内部属性)
17
17
 
18
- > 与早期草稿 `plans/elk-options-canonical.md`(2026-08-07)相比,本表已按当前代码补齐并核对默认值
18
+ > 相对 2026-08-07 的早期草稿,本表已按当前代码补齐并核对默认值
19
19
  > (如 `spacing.edgeLabel = 2`、`portSortingStrategy = INPUT_ORDER` 等修正,见 [§7 针对性修改记录](#7-针对性修改记录相对-elk-java-早期移植))。
20
20
 
21
21
  ## 2. 阅读约定
@@ -275,7 +275,7 @@ layered 之外,`layoutElkJson` 按 `org.eclipse.elk.algorithm` 分派到各算
275
275
  | `layerUnzipping.strategy` 默认 `NONE` | 枚举 `OFF → NONE` 对齐 | canonical 清单 |
276
276
  | `priority.shortness` 默认 `0` | 早期误用 1 | canonical 清单 |
277
277
  | core 键归属 | `direction` / `edgeRouting` / `portConstraints` / `hierarchyHandling` 等早期误挂 `layered.*`,已修正回 core | canonical 清单 |
278
- | 命名约束 | 新增公共符号/文件名不含 `ELK`/`Elk`(`layoutElkJson`/`ElkNode` 兼容名保留) | `docs/api-workflow.md` |
278
+ | 命名约束 | 新增公共符号/文件名不含 `ELK`/`Elk`(`layoutElkJson`/`ElkNode` 兼容名保留) | 仓库约定 |
279
279
  | spacing 基准 | `LayeredSpacingsBuilder` 以 `spacing.nodeNode`(20)为基准按比例派生其余 spacing factor | `src/options/layered-spacings.ts` |
280
280
 
281
281
  ## 8. 边界与内部属性
@@ -285,7 +285,7 @@ layered 之外,`layoutElkJson` 按 `org.eclipse.elk.algorithm` 分派到各算
285
285
  **不是用户接口**,由算法/处理器写入,消费方不应依赖。
286
286
  - 未定义 `Property` 常量的 core 键(解析层按需处理,不在本表):`padding`、`edge.type`、单值全局
287
287
  `priority`、`portLabels.treatAsGroup`(热字符串 key,默认 `undefined`,见 `properties.ts` 的
288
- `registerFastStringKey`)。待办清单见 `plans/elk-options-canonical.md` §待办。
288
+ `registerFastStringKey`)。
289
289
 
290
290
  ## 9. 重新生成
291
291
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Status**: 🟢 Active
4
4
  > **Last Updated**: 2026-09-10
5
- > **Parent**: [文档索引](../README.md)
5
+ > **Parent**: [文档索引](../../README.md)
6
6
  > **Objective**: 对照 ELK 官方博文《Node Labels》(2025-08-22),记录 GGN kernel 的标签预留策略、与官方建议的逐条符合度、以及有意偏离(reservation-only label)的理由与风险控制。
7
7
 
8
8
  ## 1. 官方建议(博文要点)
@@ -22,7 +22,7 @@
22
22
 
23
23
  | 建议 | GGN 实现 | 符合度 |
24
24
  | :--- | :--- | :--- |
25
- | R1 | 组容器同时设 `nodeLabels.placement: [INSIDE, H_CENTER, V_TOP]` + `nodeSize.constraints: [NODE_LABELS]`(`packages/kernel/src/layout/elk-service.ts`) | ✅ |
25
+ | R1 | 组容器同时设 `nodeLabels.placement: [INSIDE, H_CENTER, V_TOP]` + `nodeSize.constraints: [NODE_LABELS]`(宿主应用的布局服务层) | ✅ |
26
26
  | R2 | **不适用**:node/edge 的标签由 kernel 预测量(`measureNode` / `measureEdgeLabelSize`)后以显式 `width/height` 传入,ELK 不做字体度量(ADR 0001) | ⚪ 有意的另一条路 |
27
27
  | R3 | 不适用:容器用 `H_CENTER`,本就不产生对称留白;若未来改 `H_LEFT`,子节点可开 `ASYMMETRICAL`(移植层已实现:`src/common/node-micro-layout.ts`) | ⚪ N/A |
28
28
  | R4 | 白盒 layered 依赖 ELK 原生预留;6 种 black-box(box/force/radial/stress/rectpacking/topdownpacking)由 kernel 注入 `padding.top` 手动预留 | ✅ 与 R4 一致 |
@@ -40,7 +40,7 @@ group-renderer(kernel) → 实际绘制:标题(左
40
40
 
41
41
  - 为什么这么做:一行里要放「标题 + 状态 + 事实计数」,第二行还要放徽标——ELK 的单标签模型无法表达,而且我们要求 SVG 输出完全自控(框架无关)。
42
42
  - 代价:ELK 只保证「预留 ≥ 我们给的 box」,**真实文字宽度必须 ≤ 该 box**。因此需要两条保障:
43
- 1. **P1-b 文本实测注入**(2026-09-10):`LayoutSceneInput.labelMeasurer` —— surface 用 canvas `measureText` 实测(`@ggn/vanilla-next` 的 `CanvasTextMeasurer`),布局按真实字宽预留,消除估算偏差;
43
+ 1. **P1-b 文本实测注入**(2026-09-10):`LayoutSceneInput.labelMeasurer` —— surface 用 canvas `measureText` 实测(宿主应用注入的 `labelMeasurer`),布局按真实字宽预留,消除估算偏差;
44
44
  2. **P3 字符级截断**(2026-09-10):`MAX_LABEL_CHARS = 24` / `MAX_BADGE_CHARS = 16`——纯函数、与测量器无关,保证布局与渲染拿到同一字符串;被截断时挂 `<title>` 提供全文悬停提示,`SelectionContext` 仍返回全文。
45
45
  - 维护约束:**不要**把 `nodeLabels.placement` 当成"实际标签位置"去改渲染;改标题行几何时同步改 `group-metrics.ts`(单一来源)。
46
46
 
@@ -54,11 +54,14 @@ group-renderer(kernel) → 实际绘制:标题(左
54
54
 
55
55
  ## 5. 相关实现与测试
56
56
 
57
- - 预留计算:`packages/kernel/src/compile/group-metrics.ts`(`groupTitleRowWidth` / `groupBadgeRowWidth` / `groupHeaderHeight`)
58
- - 布局接线:`packages/kernel/src/layout/elk-service.ts`(`groupLabelBox` / `groupTitleMetrics` / `reserveBlackBoxTitleWidthInPlace`)
59
- - 渲染:`packages/kernel/src/compile/group-renderer.ts`、`node-renderer.ts`
60
- - 实测注入:`packages/vanilla-next/src/text-measure.ts`(`CanvasTextMeasurer`)→ `flush({ labelMeasurer })` → `layoutScene`
61
- - 测试:`packages/kernel/tests/elk-service.test.ts`、`packages/kernel/tests/measure.test.ts`、`packages/vanilla-next/tests/module-hierarchy.test.ts`
57
+ - 预留计算:`groupTitleRowWidth` / `groupBadgeRowWidth` / `groupHeaderHeight`(宿主应用的组几何模块)
58
+ - 布局接线:`groupLabelBox` / `groupTitleMetrics` / `reserveBlackBoxTitleWidthInPlace`(宿主应用的布局服务层)
59
+ - 渲染:组渲染器与节点渲染器由宿主应用实现
60
+ - 实测注入:`labelMeasurer` → `flush(...)` → `layoutScene`
61
+ - 测试:宿主应用的布局服务、度量与模块层级测试
62
+
63
+ > 第 2-5 节的实现均在宿主应用(GGN kernel)内,不随本包发布;本包只提供 layered 布局本身
64
+ > 以及标签预留所需的几何输入。
62
65
 
63
66
  ## 6. 遗留
64
67
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Status**: 🟢 Active
4
4
  > **Last Updated**: 2026-08-14
5
- > **Parent**: [文档索引](../README.md)
5
+ > **Parent**: [文档索引](../../README.md)
6
6
  > **Objective**: 移植 ELK Java「Spacing Options」指南——间距成对语义、base value、个体间距覆盖与 margin/padding 正交关系,对应到 TS 的 `Spacings` 表与 `LayeredSpacingsBuilder`。
7
7
 
8
8
  ## 1. 背景与来源(为什么有这份文档)
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Status**: 🟢 Active
4
4
  > **Last Updated**: 2026-09-06
5
- > **Parent**: [文档索引](../README.md)
5
+ > **Parent**: [文档索引](../../README.md)
6
6
  > **Objective**: 枚举 elkjs 0.12.0 的对外特性(算法 / 能力旗标 / JSON 图格式 / 选项 / API 面),逐项对照 ggn-layout(`本仓库`)的测试覆盖,给出覆盖结论与差距清单。
7
7
 
8
8
  ## 1. 范围与方法
@@ -10,7 +10,7 @@
10
10
  - 参照对象:npm `elkjs@0.12.0`(仓库根 `node_modules/elkjs`,GWT 编译 ELK Java 0.12.0)。
11
11
  运行时枚举:`knownLayoutAlgorithms()` 11 个算法、`knownLayoutOptions()` 235 项、`knownLayoutCategories()` 8 类。
12
12
  - 被测对象:`ggn-layout`(ELK Java 0.12.0 1:1 TS 移植;声明契约 = 结果层 API `layoutElkJson`,
13
- 见 [README](../README.md) 与 GOAL-COMPLETE「等价 elkjs:输入/输出标准 ELK JSON」)。
13
+ 见 [README](../../README.md) 与 GOAL-COMPLETE「等价 elkjs:输入/输出标准 ELK JSON」)。
14
14
  - 方法:elkjs 运行时枚举特性面 → grep 实现与测试文件 → 抽样实跑套件确认全绿。
15
15
  - 抽样实跑(2026-09-06,vitest):core-providers + layout-elk-json 23/23;self-loops + short-opt-keys +
16
16
  worker + coords-modes + api-validation 62/62;mrtree/radial/rectpacking/spore/topdownpacking/vertiflex/disco 63/63。
@@ -96,5 +96,4 @@
96
96
  ## 8. 相关文档
97
97
 
98
98
  - [ELK 布局选项接口参考](./elk-layout-options.md) / [JSON 图格式指南](./elk-json-format.md)
99
- - `docs/GOAL-COMPLETE.md`(结果层 API 对齐 elkjs 记录)、`docs/agent-remarks.md`(R16/R40/R55/R72 等 elkjs 交叉验证)
100
99
  - `docs/MODULES.tsv`(模块 ↔ Java 类 ↔ 观测点)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ggn-layout",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "ELK Layered 1:1 TypeScript 移植 (模型/算法/变量名与 ELK 源码一致)",
5
5
  "type": "module",
6
6
  "exports": {
@@ -86,7 +86,11 @@
86
86
  "scripts": {
87
87
  "build": "tsc -p tsconfig.build.json --noEmit && node scripts/check-process-env-defines.mjs && tsdown",
88
88
  "smoke:pack": "node scripts/smoke-packed.mjs",
89
- "prepublishOnly": "npm run typecheck && npm run test:ci && npm run build",
89
+ "prepublishOnly": "npm run typecheck && npm run check:license && npm run test:ci && npm run build && npm run smoke:pack && npm run check:pkg",
90
+ "check:license": "node scripts/check-license-headers.mjs",
91
+ "check:pkg": "node scripts/check-publint.mjs && node scripts/check-attw.mjs && node scripts/check-doc-links.mjs",
92
+ "check:attw": "node scripts/check-attw.mjs",
93
+ "check:docs": "node scripts/check-doc-links.mjs",
90
94
  "dev": "tsdown --watch",
91
95
  "typecheck": "tsc --noEmit",
92
96
  "typecheck:src": "tsc -p tsconfig.build.json --noEmit",
@@ -131,7 +135,11 @@
131
135
  "sugiyama",
132
136
  "typescript"
133
137
  ],
134
- "license": "MIT",
138
+ "license": "(MIT AND EPL-2.0)",
139
+ "publishConfig": {
140
+ "access": "public",
141
+ "registry": "https://registry.npmjs.org/"
142
+ },
135
143
  "repository": {
136
144
  "type": "git",
137
145
  "url": "git+https://github.com/0xlxx/ggn-layout.git"
@@ -1,6 +0,0 @@
1
- import { tt as Property } from "./elk-json-ibWtLFj2.js";
2
- //#region src/options/layered-options.d.ts
3
- /** 层级处理. */
4
- declare const HIERARCHY_HANDLING: Property<string | null>;
5
- //#endregion
6
- export { HIERARCHY_HANDLING as t };
@@ -1,6 +0,0 @@
1
- import { tt as Property } from "./elk-json-ibWtLFj2.cjs";
2
- //#region src/options/layered-options.d.ts
3
- /** 层级处理. */
4
- declare const HIERARCHY_HANDLING: Property<string | null>;
5
- //#endregion
6
- export { HIERARCHY_HANDLING as t };