@dawipong/opcflow 0.3.0 → 0.5.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 (98) hide show
  1. package/README.en.md +3 -1
  2. package/README.md +3 -2
  3. package/dist/cli.mjs +255 -64
  4. package/package.json +3 -1
  5. package/web/dist/assets/{abnfDiagram-VRR7QNED-B5Ymr02_.js → abnfDiagram-VRR7QNED-Cwj4KBKb.js} +1 -1
  6. package/web/dist/assets/{arc-DPoWLLje.js → arc-Ci--dbFA.js} +1 -1
  7. package/web/dist/assets/architecture-TIHT7OUA-Dx_ZsFnL.js +1 -0
  8. package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-DkSnVejp.js → architectureDiagram-ZJ3FMSHR-B83QZuM-.js} +2 -2
  9. package/web/dist/assets/{blockDiagram-677ZJIJ3-CUYUzMZC.js → blockDiagram-677ZJIJ3-C5lnvD0j.js} +1 -1
  10. package/web/dist/assets/{c4Diagram-LMCZKHZV-DhT2uxnj.js → c4Diagram-LMCZKHZV-Di1TmZQy.js} +1 -1
  11. package/web/dist/assets/channel-Bk0jbqCs.js +1 -0
  12. package/web/dist/assets/{chunk-32BRIVSS-CztnJRkA.js → chunk-32BRIVSS-BWSjcFoD.js} +1 -1
  13. package/web/dist/assets/{chunk-C7G6YPKG-jsbUGVSb.js → chunk-C7G6YPKG-DSkQqM00.js} +1 -1
  14. package/web/dist/assets/{chunk-EX3LRPZG-BH7du1zb.js → chunk-EX3LRPZG-DOdm7LPI.js} +1 -1
  15. package/web/dist/assets/{chunk-HOUHSVGY-DDAtZMtg.js → chunk-HOUHSVGY-D1LueKb6.js} +1 -1
  16. package/web/dist/assets/{chunk-ICXQ74PX-C2h9d1ob.js → chunk-ICXQ74PX-CFh6Ch4J.js} +1 -1
  17. package/web/dist/assets/{chunk-MOJQB5TN-BJQ2jnj0.js → chunk-MOJQB5TN-BrFLYoih.js} +1 -1
  18. package/web/dist/assets/{chunk-OGEWGWER-B5mrusUD.js → chunk-OGEWGWER-C1n7EcC_.js} +1 -1
  19. package/web/dist/assets/{chunk-PUDLZKDR-C6SYgnAr.js → chunk-PUDLZKDR-D4rKEnrx.js} +1 -1
  20. package/web/dist/assets/{chunk-Q4XR5HBZ-Cfw3UWMb.js → chunk-Q4XR5HBZ-DVm0yUET.js} +1 -1
  21. package/web/dist/assets/{chunk-RYQCIY6F-CCUojmgb.js → chunk-RYQCIY6F-BlZZOayN.js} +1 -1
  22. package/web/dist/assets/{chunk-V7JOEXUC-CPVDLAL6.js → chunk-V7JOEXUC-Bb-id9Vk.js} +1 -1
  23. package/web/dist/assets/{chunk-VR4S4FIN-CUMv178C.js → chunk-VR4S4FIN-DbbNoX70.js} +1 -1
  24. package/web/dist/assets/{chunk-WYO6CB5R-BaRUDpDl.js → chunk-WYO6CB5R-C0vPAP7X.js} +1 -1
  25. package/web/dist/assets/{chunk-XXDRQBXY-tmq33VNh.js → chunk-XXDRQBXY-BS9H__hw.js} +1 -1
  26. package/web/dist/assets/{chunk-ZGVPDNZ5-DK9a-Iwy.js → chunk-ZGVPDNZ5-BiBGMdZe.js} +1 -1
  27. package/web/dist/assets/classDiagram-OUVF2IWQ-XODf2seK.js +1 -0
  28. package/web/dist/assets/classDiagram-v2-EOCWNBFH-XODf2seK.js +1 -0
  29. package/web/dist/assets/{cose-bilkent-JH36ORCC-BV8ttTSE.js → cose-bilkent-JH36ORCC-TcTcCWyr.js} +1 -1
  30. package/web/dist/assets/{cynefin-VYW2F7L2-BncvlU8s.js → cynefin-VYW2F7L2-D6vfZhRU.js} +1 -1
  31. package/web/dist/assets/{cynefinDiagram-TSTJHNR4-C1e5y-Qt.js → cynefinDiagram-TSTJHNR4-BQ_p-vVW.js} +1 -1
  32. package/web/dist/assets/{dagre-VKFMJZFB-C9vqkLKd.js → dagre-VKFMJZFB-sC49sUfv.js} +1 -1
  33. package/web/dist/assets/{diagram-FQU43EPY-DkeAFpQM.js → diagram-FQU43EPY-znBmjqaC.js} +1 -1
  34. package/web/dist/assets/{diagram-G47NLZAW-B0YXSheC.js → diagram-G47NLZAW-BFZHUq5q.js} +1 -1
  35. package/web/dist/assets/{diagram-NH7WQ7WH-B-0nt2Rj.js → diagram-NH7WQ7WH-CnF3KhFt.js} +1 -1
  36. package/web/dist/assets/{diagram-OA4YK3LP-hTbE8qZc.js → diagram-OA4YK3LP-DyxQbSTl.js} +1 -1
  37. package/web/dist/assets/{diagram-WEI45ONY-z9AYL1YS.js → diagram-WEI45ONY-u45fnoLo.js} +1 -1
  38. package/web/dist/assets/{dist-zlHGdC4Y.js → dist-DeM6hNwF.js} +1 -1
  39. package/web/dist/assets/{ebnfDiagram-CCIWWBDH-BhlcOI7N.js → ebnfDiagram-CCIWWBDH-CRWFKre6.js} +1 -1
  40. package/web/dist/assets/{erDiagram-Q63AITRT-Djt4xUn4.js → erDiagram-Q63AITRT-BWW0EF63.js} +1 -1
  41. package/web/dist/assets/eventmodeling-45OFAUF4-C8O_2_YB.js +1 -0
  42. package/web/dist/assets/flowDiagram-23GEKE2U-ADg31f6W.js +1 -0
  43. package/web/dist/assets/{ganttDiagram-NO4QXBWP-CFmDEUpW.js → ganttDiagram-NO4QXBWP-Cs24RF6t.js} +2 -2
  44. package/web/dist/assets/{gitGraph-TEB2WS4Q-BiEBwxQy.js → gitGraph-TEB2WS4Q-CWN94LWl.js} +1 -1
  45. package/web/dist/assets/{gitGraphDiagram-IHSO6WYX--62v4OfD.js → gitGraphDiagram-IHSO6WYX-B_EZLwDH.js} +1 -1
  46. package/web/dist/assets/index-C58B02oD.css +1 -0
  47. package/web/dist/assets/index-Cf-76g9P.js +420 -0
  48. package/web/dist/assets/{info-DKCQHKI2-BLKxCcH7.js → info-DKCQHKI2-_3TeAGLT.js} +1 -1
  49. package/web/dist/assets/{infoDiagram-FWYZ7A6U-DcyiJUfy.js → infoDiagram-FWYZ7A6U-C2mnh_tb.js} +1 -1
  50. package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-C_XXRphh.js → ishikawaDiagram-FXEZZL3T-B_eQA-ns.js} +1 -1
  51. package/web/dist/assets/{journeyDiagram-5HDEW3XC-CsPvawEB.js → journeyDiagram-5HDEW3XC-pWgngszB.js} +1 -1
  52. package/web/dist/assets/{kanban-definition-HUTT4EX6-BxPpLtNJ.js → kanban-definition-HUTT4EX6-ov2PISLL.js} +1 -1
  53. package/web/dist/assets/{line-CE9BvxIa.js → line-DdBTKf-T.js} +1 -1
  54. package/web/dist/assets/linear-BcjVZ8a_.js +1 -0
  55. package/web/dist/assets/{mermaid-parser.core-CAAH_OSq.js → mermaid-parser.core-CICKlqAN.js} +3 -3
  56. package/web/dist/assets/{mindmap-definition-LN4V7U3C-DMqPdkF8.js → mindmap-definition-LN4V7U3C-0NmEERgv.js} +1 -1
  57. package/web/dist/assets/{packet-7NZHBO7P-ap_XD9pB.js → packet-7NZHBO7P-TpNRNd61.js} +1 -1
  58. package/web/dist/assets/{pegDiagram-2B236MQR-D3Uh6VmT.js → pegDiagram-2B236MQR-CiAlAiVi.js} +1 -1
  59. package/web/dist/assets/{pie-RZYD4A2V-C7RWGzoe.js → pie-RZYD4A2V-x4UQuGC2.js} +1 -1
  60. package/web/dist/assets/{pieDiagram-ENE6RG2P-Cfk6tbDs.js → pieDiagram-ENE6RG2P-inbfmWLn.js} +1 -1
  61. package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-CotpR7ZY.js → quadrantDiagram-ABIIQ3AL-BG-L4IlR.js} +1 -1
  62. package/web/dist/assets/{radar-I7S5WNFK-D8ICPnt1.js → radar-I7S5WNFK-ifrr9rf8.js} +1 -1
  63. package/web/dist/assets/{railroad-3IZDKUUU-B7ZJ3IRr.js → railroad-3IZDKUUU-3WK9FStR.js} +1 -1
  64. package/web/dist/assets/railroad-abnf-AHOZXSZD-DI7lfwbp.js +1 -0
  65. package/web/dist/assets/railroad-ebnf-EBAXGLYW-COZaOyR2.js +1 -0
  66. package/web/dist/assets/railroad-peg-LSFZ7HO6-BE8vI_mk.js +1 -0
  67. package/web/dist/assets/{railroadDiagram-RFXS5EU6-DY-MNsQI.js → railroadDiagram-RFXS5EU6-zGdHxvjI.js} +1 -1
  68. package/web/dist/assets/{requirementDiagram-TGXJPOKE-DkBeHVjA.js → requirementDiagram-TGXJPOKE-DYBqltr1.js} +1 -1
  69. package/web/dist/assets/{sankeyDiagram-HTMAVEWB-9CV0aY5J.js → sankeyDiagram-HTMAVEWB-Cwthl6yk.js} +1 -1
  70. package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-C3xWt8pk.js → sequenceDiagram-DBY2YBRQ-yoZvzY4D.js} +1 -1
  71. package/web/dist/assets/src-Bp5IDfvJ.js +1 -0
  72. package/web/dist/assets/{stateDiagram-2N3HPSRC-awwgArtJ.js → stateDiagram-2N3HPSRC-UXu_N6p7.js} +1 -1
  73. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-K2x-LOU8.js +1 -0
  74. package/web/dist/assets/{swimlanes-5IMT3BWC-Diauu8OM.js → swimlanes-5IMT3BWC-CJml4vNZ.js} +1 -1
  75. package/web/dist/assets/swimlanesDiagram-G3AALYLV-BJTq-tR6.js +8 -0
  76. package/web/dist/assets/{timeline-definition-FHXFAJF6-CzLt2q6q.js → timeline-definition-FHXFAJF6-DmHx8Bri.js} +1 -1
  77. package/web/dist/assets/{treeView-QDETBFTQ-lUySd_Pd.js → treeView-QDETBFTQ-CW1zfcRK.js} +1 -1
  78. package/web/dist/assets/{treemap-6X3UGDF4-BewRw9PG.js → treemap-6X3UGDF4-ReFheQXq.js} +1 -1
  79. package/web/dist/assets/{vennDiagram-L72KCM5P-gYZsJaVB.js → vennDiagram-L72KCM5P-jIe_jCw3.js} +1 -1
  80. package/web/dist/assets/{wardley-OPB4EBWU-BCrrgDHP.js → wardley-OPB4EBWU-DqwQFz9-.js} +1 -1
  81. package/web/dist/assets/{wardleyDiagram-EHGQE667-N-mJLzn_.js → wardleyDiagram-EHGQE667-DEJFp47s.js} +1 -1
  82. package/web/dist/assets/{xychartDiagram-FW5EYKEG-CbPlSd84.js → xychartDiagram-FW5EYKEG-DBBG2OXr.js} +1 -1
  83. package/web/dist/index.html +12 -12
  84. package/web/dist/assets/architecture-TIHT7OUA-Bgyz4pDY.js +0 -1
  85. package/web/dist/assets/channel-vHKEEV51.js +0 -1
  86. package/web/dist/assets/classDiagram-OUVF2IWQ-Bq-vpAZV.js +0 -1
  87. package/web/dist/assets/classDiagram-v2-EOCWNBFH-Bq-vpAZV.js +0 -1
  88. package/web/dist/assets/eventmodeling-45OFAUF4-CA5_fuzk.js +0 -1
  89. package/web/dist/assets/flowDiagram-23GEKE2U-KXHFGTuX.js +0 -1
  90. package/web/dist/assets/index-BUs4sN1r.css +0 -1
  91. package/web/dist/assets/index-D02utICb.js +0 -414
  92. package/web/dist/assets/linear-B8yeZliB.js +0 -1
  93. package/web/dist/assets/railroad-abnf-AHOZXSZD-uSXjMlP2.js +0 -1
  94. package/web/dist/assets/railroad-ebnf-EBAXGLYW-9im8bOEZ.js +0 -1
  95. package/web/dist/assets/railroad-peg-LSFZ7HO6-62Yk_rP2.js +0 -1
  96. package/web/dist/assets/src-W4W9ly-y.js +0 -1
  97. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-DCBMLj_H.js +0 -1
  98. package/web/dist/assets/swimlanesDiagram-G3AALYLV-CTpA1N8I.js +0 -8
package/README.en.md CHANGED
@@ -172,7 +172,9 @@ Generated by `init`, hand-edited afterwards — each project's coordinate system
172
172
 
173
173
  `opcflow serve` serves at `http://127.0.0.1:5620`: the artifact tree (colors update live), markdown /
174
174
  mermaid / HTML-prototype iframe / code rendering, the **review-queue diff** (approved version vs.
175
- current), an event timeline, and live SSE refresh. Approve, reject, and thumbs-up/down prototypes right
175
+ current), the **artifact relation graph** (derived edges + manually declared edges: drag to connect,
176
+ manual edges unbindable, derived edges reconciled by scan; manual edges join invalidation propagation),
177
+ an event timeline, and live SSE refresh. Approve, reject, and thumbs-up/down prototypes right
176
178
  here.
177
179
 
178
180
  ## Scripts
package/README.md CHANGED
@@ -159,8 +159,9 @@ flowchart LR
159
159
  ## 可视化工作台
160
160
 
161
161
  `opcflow serve` 起在 `http://127.0.0.1:5620`:artifact 树(状态实时变色)、markdown / mermaid / HTML 原型
162
- iframe / 代码渲染、**待审队列 diff**(approved 版本 vs 当前)、事件时间线、SSE 实时刷新。审批、打回、
163
- 给原型 👍👎 都在这里点。
162
+ iframe / 代码渲染、**待审队列 diff**(approved 版本 vs 当前)、**产出物关系图**(自动推导边 + 手动声明边:
163
+ 画布上拖线即声明、手动边可解绑、推导边由 scan 对账维护;手动边同样参与失效传播)、事件时间线、
164
+ SSE 实时刷新。审批、打回、给原型 👍👎 都在这里点。
164
165
 
165
166
  ## 脚本
166
167
 
package/dist/cli.mjs CHANGED
@@ -279,7 +279,14 @@ CREATE INDEX IF NOT EXISTS idx_events_event ON events(event);
279
279
  }
280
280
  },
281
281
  // 迁移 3:claim 时记录 git HEAD,供 hotfix 契约触碰检测与 trailer 交叉验证
282
- { version: 3, up: (db) => db.exec("ALTER TABLE tasks ADD COLUMN claim_commit TEXT") }
282
+ { version: 3, up: (db) => db.exec("ALTER TABLE tasks ADD COLUMN claim_commit TEXT") },
283
+ // 迁移 4:边来源(derived=scan 按 parents×坐标推导,对账维护;manual=用户手动声明,可解绑、scan 永不动)
284
+ {
285
+ version: 4,
286
+ up: (db) => db.exec(
287
+ "ALTER TABLE artifact_edges ADD COLUMN source TEXT NOT NULL DEFAULT 'derived' CHECK (source IN ('derived','manual'))"
288
+ )
289
+ }
283
290
  ];
284
291
  CURRENT_SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1].version;
285
292
  }
@@ -690,6 +697,7 @@ __export(kind_exports, {
690
697
  META_KINDS: () => META_KINDS,
691
698
  PM_KINDS: () => PM_KINDS,
692
699
  contractKinds: () => contractKinds,
700
+ expandPattern: () => expandPattern,
693
701
  getKindRegistry: () => getKindRegistry,
694
702
  inferKind: () => inferKind,
695
703
  kindSpec: () => kindSpec,
@@ -755,15 +763,15 @@ var init_kind = __esm({
755
763
  project: { level: "project", approval: "human", parents: [], drivesStale: true, hashMode: "text-normalize", retrieval: "summary", pathPatterns: ["{prd}/project.md"] },
756
764
  roles: { level: "project", approval: "human", parents: ["project"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{prd}/roles.md"] },
757
765
  glossary: { level: "project", approval: "human", parents: ["project"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{prd}/glossary.md"] },
758
- flow: { level: "module", approval: "human", parents: ["project", "roles", "glossary"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{prd}/flows/"] },
759
- "module-prd": { level: "module", approval: "human", parents: ["flow"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{prd}/modules/"] },
760
- "page-prd": { level: "page", approval: "human", parents: ["module-prd"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{prd}/pages/"] },
761
- "db-doc": { level: "module", approval: "human", parents: ["module-prd"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{architecture}/database/"] },
762
- "api-doc": { level: "module", approval: "human", parents: ["module-prd", "db-doc"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{architecture}/api/"] },
763
- "design-system": { level: "endpoint", approval: "human", parents: ["baseline"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{design}/systems/"] },
764
- "design-prompt": { level: "page", approval: "none", parents: ["page-prd", "api-doc", "design-system"], drivesStale: false, hashMode: "text-normalize", retrieval: "summary", pathPatterns: ["{design}/prompts/"] },
765
- prototype: { level: "page", approval: "thumbs", parents: ["design-prompt", "design-system"], drivesStale: true, hashMode: "text-normalize", retrieval: "summary", pathPatterns: ["{design}/prototypes/"] },
766
- acceptance: { level: "page", approval: "human", parents: ["page-prd", "prototype"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{acceptance}/"] },
766
+ flow: { level: "module", approval: "human", parents: ["project", "roles", "glossary"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{prd}/flows/"], coords: "{module}", defaultEndpoint: "common" },
767
+ "module-prd": { level: "module", approval: "human", parents: ["flow"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{prd}/modules/"], coords: "{module}", defaultEndpoint: "common" },
768
+ "page-prd": { level: "page", approval: "human", parents: ["module-prd"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{prd}/pages/"], coords: "{endpoint}/{module}/{page}" },
769
+ "db-doc": { level: "module", approval: "human", parents: ["module-prd"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{architecture}/database/"], coords: "{module}", defaultEndpoint: "common" },
770
+ "api-doc": { level: "module", approval: "human", parents: ["module-prd", "db-doc"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{architecture}/api/"], coords: "{module}", defaultEndpoint: "service" },
771
+ "design-system": { level: "endpoint", approval: "human", parents: ["baseline"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{design}/systems/"], coords: "{endpoint}" },
772
+ "design-prompt": { level: "page", approval: "none", parents: ["page-prd", "api-doc", "design-system"], drivesStale: false, hashMode: "text-normalize", retrieval: "summary", pathPatterns: ["{design}/prompts/"], coords: "{endpoint}/{module}/{page}" },
773
+ prototype: { level: "page", approval: "thumbs", parents: ["design-prompt", "design-system"], drivesStale: true, hashMode: "text-normalize", retrieval: "summary", pathPatterns: ["{design}/prototypes/"], coords: "{endpoint}/{module}/{page}" },
774
+ acceptance: { level: "page", approval: "human", parents: ["page-prd", "prototype"], drivesStale: true, hashMode: "text-normalize", retrieval: "full", pathPatterns: ["{acceptance}/"], coords: "{endpoint}/{module}/{page}" },
767
775
  code: { level: "module", approval: "machine", parents: ["baseline", "api-doc", "prototype"], drivesStale: false, hashMode: "directory", retrieval: "semantic" },
768
776
  doc: { level: "module", approval: "none", parents: [], drivesStale: false, hashMode: "text-normalize", retrieval: "summary" }
769
777
  };
@@ -2412,31 +2420,37 @@ import { existsSync as existsSync9, readdirSync as readdirSync4, statSync as sta
2412
2420
  import { join as join10 } from "node:path";
2413
2421
  function parseCoords(ctx, kind, relPath) {
2414
2422
  const none = { module: null, endpoint: null, page: null };
2415
- const base = (p) => p.split("/").pop().replace(/\.(md|html)$/i, "");
2416
- const seg = relPath.split("/");
2423
+ const spec = getKindRegistry(ctx.config)[kind];
2424
+ const grammar = spec?.coords;
2425
+ if (!grammar) return none;
2426
+ const prefix = spec.pathPatterns?.[0] ? expandPattern(spec.pathPatterns[0], ctx.config) : "";
2427
+ const tail = relPath.startsWith(prefix) ? relPath.slice(prefix.length) : relPath;
2428
+ const tailSegs = tail.split("/").filter(Boolean);
2429
+ const gSegs = grammar.split("/");
2430
+ const defEnd = spec.defaultEndpoint ?? null;
2417
2431
  const mod = (raw) => normalizeModule(raw, ctx.config);
2418
- switch (kind) {
2419
- case "flow":
2420
- case "module-prd":
2421
- return { module: mod(base(relPath)), endpoint: "common", page: null };
2422
- case "db-doc":
2423
- return { module: mod(base(relPath)), endpoint: "common", page: null };
2424
- case "api-doc":
2425
- return { module: mod(base(relPath)), endpoint: "service", page: null };
2426
- case "design-system":
2427
- return { module: null, endpoint: base(relPath), page: null };
2428
- case "page-prd":
2429
- case "design-prompt":
2430
- case "prototype":
2431
- case "acceptance": {
2432
- if (seg.length < 3) return none;
2433
- const endpoint = seg[seg.length - 3];
2434
- const module = mod(seg[seg.length - 2]);
2435
- return { module, endpoint, page: `${module}/${base(relPath)}` };
2436
- }
2437
- default:
2438
- return none;
2439
- }
2432
+ if (gSegs.length === 1) {
2433
+ if (tailSegs.length === 0) return null;
2434
+ const leaf = stripExt(tailSegs[tailSegs.length - 1]);
2435
+ if (gSegs[0] === "{module}") return { module: mod(leaf), endpoint: defEnd, page: null };
2436
+ if (gSegs[0] === "{endpoint}") return { module: null, endpoint: leaf, page: null };
2437
+ return none;
2438
+ }
2439
+ const hasPage = gSegs[gSegs.length - 1] === "{page}";
2440
+ const fixed = hasPage ? gSegs.length - 1 : gSegs.length;
2441
+ if (hasPage ? tailSegs.length < gSegs.length : tailSegs.length !== gSegs.length) return null;
2442
+ const cap = {};
2443
+ for (let i = 0; i < fixed; i++) cap[gSegs[i]] = stripExt(tailSegs[i]);
2444
+ if (cap["{endpoint}"] !== void 0 && !ctx.config.endpoints.includes(cap["{endpoint}"])) return null;
2445
+ const endpoint = cap["{endpoint}"] ?? defEnd;
2446
+ const module = cap["{module}"] !== void 0 ? mod(cap["{module}"]) : null;
2447
+ let page = null;
2448
+ if (hasPage) {
2449
+ const pageSegs = tailSegs.slice(fixed);
2450
+ const pageTail = pageSegs.map((s, i) => i === pageSegs.length - 1 ? stripExt(s) : s).join("/");
2451
+ page = module ? `${module}/${pageTail}` : pageTail;
2452
+ }
2453
+ return { module, endpoint, page };
2440
2454
  }
2441
2455
  function isMetaPath(ctx, relPath) {
2442
2456
  const registry = getKindRegistry(ctx.config);
@@ -2505,30 +2519,42 @@ function deriveEdges(ctx) {
2505
2519
  list.push(a);
2506
2520
  byKind.set(a.kind, list);
2507
2521
  }
2508
- const insert = ctx.db.prepare("INSERT OR IGNORE INTO artifact_edges (from_id, to_id) VALUES (?, ?)");
2522
+ const expected = /* @__PURE__ */ new Set();
2523
+ for (const child of nonMeta) {
2524
+ const parents = registry[child.kind]?.parents ?? [];
2525
+ for (const parentKind of parents) {
2526
+ const level = registry[parentKind]?.level ?? "module";
2527
+ const candidates = (byKind.get(parentKind) ?? []).filter((p) => {
2528
+ if ((level === "module" || level === "page") && child.module && p.module !== child.module) return false;
2529
+ if ((level === "endpoint" || level === "page") && child.endpoint && p.endpoint !== child.endpoint) return false;
2530
+ if (level === "page" && child.page && p.page !== child.page) return false;
2531
+ return true;
2532
+ });
2533
+ for (const parent of candidates) expected.add(`${parent.id}|${child.id}`);
2534
+ }
2535
+ }
2536
+ const existing = ctx.db.prepare("SELECT id, from_id, to_id, source FROM artifact_edges").all();
2537
+ const have = new Set(existing.map((e) => `${e.from_id}|${e.to_id}`));
2538
+ const insert = ctx.db.prepare("INSERT OR IGNORE INTO artifact_edges (from_id, to_id, source) VALUES (?, ?, 'derived')");
2539
+ const del = ctx.db.prepare("DELETE FROM artifact_edges WHERE id = ?");
2509
2540
  let created = 0;
2541
+ let pruned = 0;
2510
2542
  const tx = ctx.db.transaction(() => {
2511
- for (const child of nonMeta) {
2512
- const parents = registry[child.kind]?.parents ?? [];
2513
- for (const parentKind of parents) {
2514
- const level = registry[parentKind]?.level ?? "module";
2515
- const candidates = (byKind.get(parentKind) ?? []).filter((p) => {
2516
- if ((level === "module" || level === "page") && child.module && p.module !== child.module) return false;
2517
- if ((level === "endpoint" || level === "page") && child.endpoint && p.endpoint !== child.endpoint) return false;
2518
- if (level === "page" && child.page && p.page !== child.page) return false;
2519
- return true;
2520
- });
2521
- for (const parent of candidates) {
2522
- created += insert.run(parent.id, child.id).changes;
2523
- }
2524
- }
2543
+ for (const key of expected) {
2544
+ if (have.has(key)) continue;
2545
+ const [from, to] = key.split("|");
2546
+ created += insert.run(Number(from), Number(to)).changes;
2547
+ }
2548
+ for (const e of existing) {
2549
+ if (e.source !== "derived") continue;
2550
+ if (!expected.has(`${e.from_id}|${e.to_id}`)) pruned += del.run(e.id).changes;
2525
2551
  }
2526
2552
  });
2527
2553
  tx();
2528
- return created;
2554
+ return { created, pruned };
2529
2555
  }
2530
2556
  function scanArtifacts(ctx, actor = "system") {
2531
- const summary = { registered: 0, refreshed: 0, remapped: 0, edges: 0, skipped: [] };
2557
+ const summary = { registered: 0, refreshed: 0, remapped: 0, edges: 0, edgesPruned: 0, moved: 0, skipped: [], unresolved: [] };
2532
2558
  const files = [];
2533
2559
  for (const dir of Object.values(ctx.config.docs)) {
2534
2560
  const abs = join10(ctx.root, dir);
@@ -2552,7 +2578,7 @@ function scanArtifacts(ctx, actor = "system") {
2552
2578
  const before = row.content_hash;
2553
2579
  const after = refreshArtifact(ctx, { id: row.id }, actor);
2554
2580
  if (after.content_hash !== before) summary.refreshed++;
2555
- if (row.kind !== kind || row.module !== coords.module || row.endpoint !== coords.endpoint || row.page !== coords.page) {
2581
+ if (coords && (row.kind !== kind || row.module !== coords.module || row.endpoint !== coords.endpoint || row.page !== coords.page)) {
2556
2582
  const tx2 = ctx.db.transaction(() => {
2557
2583
  remap.run(kind, coords.module, coords.endpoint, coords.page, row.id);
2558
2584
  logEvent(ctx.db, {
@@ -2575,8 +2601,32 @@ function scanArtifacts(ctx, actor = "system") {
2575
2601
  }
2576
2602
  return;
2577
2603
  }
2604
+ if (!coords) {
2605
+ summary.unresolved.push(relPath);
2606
+ return;
2607
+ }
2578
2608
  const hash = hashPath(join10(ctx.root, relPath));
2579
2609
  if (hash === null) return;
2610
+ const movedFrom = ctx.db.prepare("SELECT * FROM artifacts WHERE content_hash = ? AND kind = ?").all(hash, kind).filter((a) => !existsSync9(join10(ctx.root, a.path)));
2611
+ if (movedFrom.length === 1) {
2612
+ const old = movedFrom[0];
2613
+ const tx2 = ctx.db.transaction(() => {
2614
+ ctx.db.prepare("UPDATE artifacts SET path = ?, module = ?, endpoint = ?, page = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?").run(relPath, coords.module, coords.endpoint, coords.page, old.id);
2615
+ logEvent(ctx.db, {
2616
+ entityType: "artifact",
2617
+ entityId: old.id,
2618
+ event: "auto_moved",
2619
+ actor,
2620
+ payload: { from: old.path, to: relPath },
2621
+ module: coords.module,
2622
+ endpoint: coords.endpoint,
2623
+ page: coords.page
2624
+ });
2625
+ });
2626
+ tx2();
2627
+ summary.moved++;
2628
+ return;
2629
+ }
2580
2630
  const tx = ctx.db.transaction(() => {
2581
2631
  const result = insert.run(kind, coords.module, coords.endpoint, coords.page, relPath, hash);
2582
2632
  logEvent(ctx.db, {
@@ -2604,9 +2654,36 @@ function scanArtifacts(ctx, actor = "system") {
2604
2654
  for (const code of expandCodeRoots(ctx)) {
2605
2655
  registerOne(code.dir, "code", { module: code.module, endpoint: code.endpoint, page: null });
2606
2656
  }
2607
- summary.edges = deriveEdges(ctx);
2657
+ const edgeResult = deriveEdges(ctx);
2658
+ summary.edges = edgeResult.created;
2659
+ summary.edgesPruned = edgeResult.pruned;
2608
2660
  return summary;
2609
2661
  }
2662
+ function registerAdHocArtifact(ctx, relPathRaw, actor) {
2663
+ const relPath = normalizeRelPath(ctx, relPathRaw);
2664
+ const existing = ctx.db.prepare("SELECT * FROM artifacts WHERE path = ?").get(relPath);
2665
+ if (existing) return existing;
2666
+ const hash = hashPath(join10(ctx.root, relPath));
2667
+ if (hash === null) throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${relPath}`);
2668
+ const kind = inferKind(relPath, ctx.config);
2669
+ const coords = parseCoords(ctx, kind, relPath) ?? { module: null, endpoint: null, page: null };
2670
+ const tx = ctx.db.transaction(() => {
2671
+ const r = ctx.db.prepare("INSERT INTO artifacts (kind, module, endpoint, page, path, content_hash) VALUES (?, ?, ?, ?, ?, ?)").run(kind, coords.module, coords.endpoint, coords.page, relPath, hash);
2672
+ logEvent(ctx.db, {
2673
+ entityType: "artifact",
2674
+ entityId: r.lastInsertRowid,
2675
+ event: "scan_registered",
2676
+ actor,
2677
+ payload: { path: relPath, kind, adHoc: true },
2678
+ module: coords.module,
2679
+ endpoint: coords.endpoint,
2680
+ page: coords.page
2681
+ });
2682
+ });
2683
+ tx();
2684
+ return ctx.db.prepare("SELECT * FROM artifacts WHERE path = ?").get(relPath);
2685
+ }
2686
+ var stripExt;
2610
2687
  var init_scan_command = __esm({
2611
2688
  "core/commands/scan.command.ts"() {
2612
2689
  "use strict";
@@ -2614,6 +2691,7 @@ var init_scan_command = __esm({
2614
2691
  init_hash();
2615
2692
  init_kind();
2616
2693
  init_artifact_commands();
2694
+ stripExt = (s) => s.replace(/\.(md|html)$/i, "");
2617
2695
  }
2618
2696
  });
2619
2697
 
@@ -3435,6 +3513,7 @@ __export(core_exports, {
3435
3513
  distillFeedback: () => distillFeedback,
3436
3514
  ensureSchema: () => ensureSchema,
3437
3515
  everApproved: () => everApproved,
3516
+ expandPattern: () => expandPattern,
3438
3517
  exportEventLog: () => exportEventLog,
3439
3518
  feedbackArtifact: () => feedbackArtifact,
3440
3519
  findProjectRoot: () => findProjectRoot,
@@ -3473,6 +3552,7 @@ __export(core_exports, {
3473
3552
  recordNote: () => recordNote,
3474
3553
  recordQaResult: () => recordQaResult,
3475
3554
  refreshArtifact: () => refreshArtifact,
3555
+ registerAdHocArtifact: () => registerAdHocArtifact,
3476
3556
  registerMetaArtifacts: () => registerMetaArtifacts,
3477
3557
  registerOutput: () => registerOutput,
3478
3558
  rejectArtifact: () => rejectArtifact,
@@ -3682,7 +3762,7 @@ __export(app_exports, {
3682
3762
  import fastifyCors from "@fastify/cors";
3683
3763
  import fastifyStatic from "@fastify/static";
3684
3764
  import Fastify from "fastify";
3685
- import { existsSync as existsSync14, readFileSync as readFileSync8, readdirSync as readdirSync7, statSync as statSync6 } from "node:fs";
3765
+ import { existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync8, readdirSync as readdirSync7, statSync as statSync6 } from "node:fs";
3686
3766
  import { isAbsolute as isAbsolute2, join as join16, normalize, relative as relative2 } from "node:path";
3687
3767
  function getArtifact(ctx, id) {
3688
3768
  const row = ctx.db.prepare("SELECT * FROM artifacts WHERE id = ?").get(id);
@@ -3706,6 +3786,9 @@ async function createServer(ctx) {
3706
3786
  if (existsSync14(webDist)) {
3707
3787
  await app.register(fastifyStatic, { root: webDist });
3708
3788
  }
3789
+ const protoRoot = join16(ctx.root, ctx.config.docs.design, "prototypes");
3790
+ mkdirSync8(protoRoot, { recursive: true });
3791
+ await app.register(fastifyStatic, { root: protoRoot, prefix: "/proto/", decorateReply: false });
3709
3792
  app.get("/api/meta", async () => ({
3710
3793
  root: ctx.root,
3711
3794
  language: ctx.config.language,
@@ -3747,15 +3830,6 @@ async function createServer(ctx) {
3747
3830
  }
3748
3831
  return { artifact, content, isDirectory, missing, feedback, events };
3749
3832
  });
3750
- app.get("/api/artifact/:id/raw", async (req, reply) => {
3751
- const artifact = getArtifact(ctx, parseInt(req.params.id));
3752
- const abs = guardedAbsPath(ctx, artifact);
3753
- if (!existsSync14(abs) || statSync6(abs).isDirectory()) {
3754
- return reply.code(404).send("not found");
3755
- }
3756
- reply.header("content-type", artifact.path.endsWith(".html") ? "text/html; charset=utf-8" : "text/plain; charset=utf-8");
3757
- return reply.send(readFileSync8(abs));
3758
- });
3759
3833
  app.get("/api/artifact/:id/files", async (req) => {
3760
3834
  const artifact = getArtifact(ctx, parseInt(req.params.id));
3761
3835
  const base = guardedAbsPath(ctx, artifact);
@@ -3817,6 +3891,117 @@ data: {"cursor":${cursor2}}
3817
3891
  }, 500);
3818
3892
  req.raw.on("close", () => clearInterval(timer));
3819
3893
  });
3894
+ app.get("/api/graph", async () => {
3895
+ const registry = getKindRegistry(ctx.config);
3896
+ const rows = ctx.db.prepare("SELECT * FROM artifacts ORDER BY id").all().filter(
3897
+ (a) => !registry[a.kind]?.meta
3898
+ );
3899
+ const ids = new Set(rows.map((a) => a.id));
3900
+ const nodes = rows.map((a) => ({
3901
+ id: a.id,
3902
+ kind: a.kind,
3903
+ path: a.path,
3904
+ module: a.module,
3905
+ endpoint: a.endpoint,
3906
+ page: a.page,
3907
+ review_status: reviewStatus(a),
3908
+ missing: !existsSync14(join16(ctx.root, a.path))
3909
+ }));
3910
+ const edges = ctx.db.prepare("SELECT id, from_id, to_id, source FROM artifact_edges").all().filter((e) => ids.has(e.from_id) && ids.has(e.to_id));
3911
+ return { nodes, edges };
3912
+ });
3913
+ app.get("/api/search", async (req) => {
3914
+ const q = (req.query.q ?? "").trim().toLowerCase();
3915
+ if (!q) return { artifacts: [], files: [] };
3916
+ const like = `%${q.replace(/[%_\\]/g, (c) => "\\" + c)}%`;
3917
+ const artifacts = ctx.db.prepare("SELECT * FROM artifacts WHERE path LIKE ? ESCAPE '\\' ORDER BY path LIMIT 30").all(like).map((a) => ({ id: a.id, kind: a.kind, path: a.path, module: a.module, endpoint: a.endpoint, review_status: reviewStatus(a) }));
3918
+ const registered = new Set(ctx.db.prepare("SELECT path FROM artifacts").all().map((r) => r.path));
3919
+ const files = [];
3920
+ const walk = (dir, rel) => {
3921
+ if (files.length >= 30) return;
3922
+ for (const name of readdirSync7(dir).sort()) {
3923
+ if (files.length >= 30) return;
3924
+ if (name.startsWith(".") || name === "node_modules" || name === "dist" || name === "build") continue;
3925
+ const full = join16(dir, name);
3926
+ const relPath = rel ? `${rel}/${name}` : name;
3927
+ if (statSync6(full).isDirectory()) walk(full, relPath);
3928
+ else if (relPath.toLowerCase().includes(q) && !registered.has(relPath)) files.push(relPath);
3929
+ }
3930
+ };
3931
+ walk(ctx.root, "");
3932
+ return { artifacts, files };
3933
+ });
3934
+ app.post("/api/artifact/register", async (req) => {
3935
+ return registerAdHocArtifact(ctx, req.body.path, req.body.actor || "user");
3936
+ });
3937
+ app.post("/api/edge", async (req, reply) => {
3938
+ const { fromId, toId } = req.body;
3939
+ const actor = req.body.actor || "user";
3940
+ if (!fromId || !toId || fromId === toId) {
3941
+ return reply.code(400).send({ error: "\u65E0\u6548\u7684\u8FB9:\u9700\u8981\u4E24\u4E2A\u4E0D\u540C\u7684\u4EA7\u7269" });
3942
+ }
3943
+ const has = (id) => ctx.db.prepare("SELECT COUNT(*) c FROM artifacts WHERE id = ?").get(id).c > 0;
3944
+ if (!has(fromId) || !has(toId)) return reply.code(404).send({ error: "\u4EA7\u7269\u4E0D\u5B58\u5728" });
3945
+ const seen = /* @__PURE__ */ new Set([toId]);
3946
+ const queue = [toId];
3947
+ const next = ctx.db.prepare("SELECT to_id FROM artifact_edges WHERE from_id = ?");
3948
+ while (queue.length) {
3949
+ const cur = queue.pop();
3950
+ for (const row of next.all(cur)) {
3951
+ if (row.to_id === fromId) return reply.code(400).send({ error: "\u4F1A\u5F62\u6210\u73AF,\u5DF2\u62D2\u7EDD" });
3952
+ if (!seen.has(row.to_id)) {
3953
+ seen.add(row.to_id);
3954
+ queue.push(row.to_id);
3955
+ }
3956
+ }
3957
+ }
3958
+ const r = ctx.db.prepare("INSERT OR IGNORE INTO artifact_edges (from_id, to_id, source) VALUES (?, ?, 'manual')").run(fromId, toId);
3959
+ if (r.changes === 0) return reply.code(409).send({ error: "\u8BE5\u5173\u7CFB\u5DF2\u5B58\u5728" });
3960
+ logEvent(ctx.db, { entityType: "artifact", entityId: toId, event: "edge_added", actor, payload: { fromId, toId, source: "manual" } });
3961
+ return { id: r.lastInsertRowid, fromId, toId, source: "manual" };
3962
+ });
3963
+ app.delete("/api/artifact/:id", async (req, reply) => {
3964
+ const id = parseInt(req.params.id);
3965
+ const row = ctx.db.prepare("SELECT * FROM artifacts WHERE id = ?").get(id);
3966
+ if (!row) return reply.code(404).send({ error: "\u4EA7\u7269\u4E0D\u5B58\u5728" });
3967
+ if (row.approved_hash !== null) return reply.code(403).send({ error: "\u8BE5\u4EA7\u7269\u6709\u5BA1\u6279\u5386\u53F2,\u4E0D\u53EF\u53D6\u6D88\u767B\u8BB0" });
3968
+ const refs = ctx.db.prepare(
3969
+ `SELECT (SELECT COUNT(*) FROM task_inputs WHERE artifact_id = ?) +
3970
+ (SELECT COUNT(*) FROM task_outputs WHERE artifact_id = ?) +
3971
+ (SELECT COUNT(*) FROM artifact_feedback WHERE artifact_id = ?) AS c`
3972
+ ).get(id, id, id);
3973
+ if (refs.c > 0) return reply.code(403).send({ error: "\u8BE5\u4EA7\u7269\u5DF2\u88AB\u4EFB\u52A1/\u53CD\u9988\u5F15\u7528,\u4E0D\u53EF\u53D6\u6D88\u767B\u8BB0" });
3974
+ const tx = ctx.db.transaction(() => {
3975
+ logEvent(ctx.db, {
3976
+ entityType: "artifact",
3977
+ entityId: id,
3978
+ event: "unregistered",
3979
+ actor: req.body?.actor || "user",
3980
+ payload: { path: row.path, kind: row.kind },
3981
+ module: row.module,
3982
+ endpoint: row.endpoint,
3983
+ page: row.page
3984
+ });
3985
+ ctx.db.prepare("DELETE FROM artifacts WHERE id = ?").run(id);
3986
+ });
3987
+ tx();
3988
+ return { ok: true };
3989
+ });
3990
+ app.delete("/api/edge/:id", async (req, reply) => {
3991
+ const id = parseInt(req.params.id);
3992
+ const edge = ctx.db.prepare("SELECT * FROM artifact_edges WHERE id = ?").get(id);
3993
+ if (!edge) return reply.code(404).send({ error: "\u8FB9\u4E0D\u5B58\u5728" });
3994
+ if (edge.source !== "manual") return reply.code(403).send({ error: "\u81EA\u52A8\u63A8\u5BFC\u7684\u5173\u7CFB\u4E0D\u53EF\u89E3\u7ED1(\u7531 scan \u6309\u5750\u6807\u4E8B\u5B9E\u7EF4\u62A4)" });
3995
+ ctx.db.prepare("DELETE FROM artifact_edges WHERE id = ?").run(id);
3996
+ logEvent(ctx.db, {
3997
+ entityType: "artifact",
3998
+ entityId: edge.to_id,
3999
+ event: "edge_removed",
4000
+ actor: req.body?.actor || "user",
4001
+ payload: { fromId: edge.from_id, toId: edge.to_id }
4002
+ });
4003
+ return { ok: true };
4004
+ });
3820
4005
  app.get("/api/review-queue", async () => {
3821
4006
  return listArtifacts(ctx, {}).filter((r) => r.review_status === "pending" || r.review_status === "invalidated").map((r) => ({
3822
4007
  ...r,
@@ -3886,11 +4071,13 @@ var init_app = __esm({
3886
4071
  "use strict";
3887
4072
  init_artifact_commands();
3888
4073
  init_retro_command();
4074
+ init_scan_command();
3889
4075
  init_sync_command();
3890
4076
  init_config();
3891
4077
  init_task_commands();
3892
4078
  init_derive();
3893
4079
  init_events();
4080
+ init_kind();
3894
4081
  init_tree();
3895
4082
  MAX_INLINE_SIZE = 1024 * 1024;
3896
4083
  }
@@ -4439,7 +4626,11 @@ async function runCommand(ctx, command, a) {
4439
4626
  }
4440
4627
  case "scan": {
4441
4628
  const s = scanArtifacts(ctx, a.actor || "system");
4442
- console.log(chalk.green(`\u2705 \u626B\u63CF\u5B8C\u6210:\u65B0\u767B\u8BB0 ${s.registered},\u5185\u5BB9\u5237\u65B0 ${s.refreshed},\u91CD\u6302\u5750\u6807 ${s.remapped},\u65B0\u589E\u8FB9 ${s.edges},\u6392\u9664\u5143\u4EA7\u7269 ${s.skipped.length}`));
4629
+ console.log(chalk.green(`\u2705 \u626B\u63CF\u5B8C\u6210:\u65B0\u767B\u8BB0 ${s.registered},\u5185\u5BB9\u5237\u65B0 ${s.refreshed},\u91CD\u6302\u5750\u6807 ${s.remapped},\u81EA\u52A8\u8DDF\u968F\u79FB\u52A8 ${s.moved},\u65B0\u589E\u8FB9 ${s.edges},\u6E05\u7406\u6B8B\u7559\u8FB9 ${s.edgesPruned},\u6392\u9664\u5143\u4EA7\u7269 ${s.skipped.length}`));
4630
+ if (s.unresolved.length > 0) {
4631
+ console.log(chalk.yellow(`\u26A0 ${s.unresolved.length} \u4E2A\u6587\u4EF6\u547D\u4E2D kind \u4F46\u8DEF\u5F84\u4E0D\u7B26 coords \u6587\u6CD5,\u672A\u767B\u8BB0(\u975E\u89C4\u8303/\u5E9F\u5F03\u7AEF?):`));
4632
+ for (const p of s.unresolved) console.log(chalk.yellow(` - ${p}`));
4633
+ }
4443
4634
  break;
4444
4635
  }
4445
4636
  case "move": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dawipong/opcflow",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Spec-anchored, drift-enforced execution layer for AI coding agents — artifact DAG, trust gates, multi-role pipeline; generates agents/MCP/hooks for Claude Code, Codex, OpenCode & Cursor.",
5
5
  "license": "MIT",
6
6
  "author": "Dawi",
@@ -59,6 +59,7 @@
59
59
  },
60
60
  "devDependencies": {
61
61
  "@ant-design/icons": "^6",
62
+ "@dagrejs/dagre": "^3.0.0",
62
63
  "@monaco-editor/react": "^4.7.0",
63
64
  "@semantic-release/changelog": "^6.0.3",
64
65
  "@semantic-release/git": "^10.0.1",
@@ -67,6 +68,7 @@
67
68
  "@types/react": "^18",
68
69
  "@types/react-dom": "^18",
69
70
  "@vitejs/plugin-react": "^6",
71
+ "@xyflow/react": "^12.11.2",
70
72
  "antd": "^6",
71
73
  "esbuild": "^0.28.1",
72
74
  "mermaid": "^11",
@@ -1 +1 @@
1
- import{m as e}from"./src-W4W9ly-y.js";import{n as t}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import"./chunk-WYO6CB5R-BaRUDpDl.js";import"./index-D02utICb.js";import{m as n,t as r}from"./mermaid-parser.core-CAAH_OSq.js";import{n as i,r as a,t as o}from"./chunk-MOJQB5TN-BJQ2jnj0.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";var c=n().RailroadAbnf.parser.LangiumParser,l=t(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=t(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=t(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=t(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=t(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=t(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=t(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:t(t=>{o.clear(),e.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(t);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new r(n);let i=n.value;e.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),e.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
1
+ import{E as e}from"./src-Bp5IDfvJ.js";import{n as t}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import"./chunk-WYO6CB5R-C0vPAP7X.js";import"./index-Cf-76g9P.js";import{m as n,t as r}from"./mermaid-parser.core-CICKlqAN.js";import{n as i,r as a,t as o}from"./chunk-MOJQB5TN-BrFLYoih.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";var c=n().RailroadAbnf.parser.LangiumParser,l=t(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=t(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=t(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=t(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=t(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=t(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=t(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:t(t=>{o.clear(),e.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(t);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new r(n);let i=n.value;e.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),e.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
@@ -1 +1 @@
1
- import{n as e,t}from"./path-BWPyau1x.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-zlHGdC4Y.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i)if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
1
+ import{n as e,t}from"./path-BWPyau1x.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-DeM6hNwF.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i)if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
@@ -0,0 +1 @@
1
+ import"./chunk-KEIR6QF5-BfrZ3jm6.js";import{M as e}from"./mermaid-parser.core-CICKlqAN.js";export{e as createArchitectureServices};