@bovinphang/frontend-craft 2.8.0 → 3.0.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 (681) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +64 -0
  4. package/CHANGELOG.zh-CN.md +64 -0
  5. package/CONTRIBUTING.md +74 -54
  6. package/CONTRIBUTING.zh-CN.md +75 -53
  7. package/README.md +150 -38
  8. package/README.openclaw.md +86 -11
  9. package/README.openclaw.zh-CN.md +86 -11
  10. package/README.zh-CN.md +147 -35
  11. package/agents/fec-code-reviewer.md +24 -3
  12. package/agents/fec-debugger.md +1 -1
  13. package/agents/fec-doc-updater.md +1 -1
  14. package/agents/fec-e2e-runner.md +1 -1
  15. package/agents/fec-figma-implementer.md +1 -1
  16. package/agents/fec-performance-optimizer.md +1 -1
  17. package/agents/fec-refactor-cleaner.md +4 -1
  18. package/agents/fec-refactoring-expert.md +81 -0
  19. package/agents/fec-security-reviewer.md +17 -1
  20. package/agents/fec-test-planner.md +1 -1
  21. package/agents/fec-typescript-reviewer.md +25 -9
  22. package/agents/fec-ui-checker.md +11 -11
  23. package/commands/fec-debug.md +1 -1
  24. package/commands/fec-refactor-plan.md +17 -0
  25. package/commands/fec-refactor.md +18 -0
  26. package/commands/fec-review.md +40 -10
  27. package/commands/fec-scaffold.md +1 -1
  28. package/commands/fec-smell.md +17 -0
  29. package/commands/fec-tdd.md +6 -2
  30. package/common-content.lock.json +3795 -0
  31. package/dist/bin/frontend-craft.js +386 -55
  32. package/dist/hooks/fec-run-tests.js +5 -1
  33. package/dist/hooks/fec-session-start.js +1 -1
  34. package/docs/common-migration.md +61 -0
  35. package/docs/example-prompts.md +29 -12
  36. package/docs/ja-JP/README.md +129 -34
  37. package/docs/ko-KR/README.md +129 -34
  38. package/docs/project-structure.md +49 -14
  39. package/docs/refactoring/README.md +50 -0
  40. package/docs/refactoring/catalog.md +105 -0
  41. package/docs/refactoring/smell-refactoring-matrix.md +41 -0
  42. package/docs/review-and-diagram-workflows.md +39 -0
  43. package/docs/runtimes/antigravity.md +13 -5
  44. package/docs/runtimes/augment.md +13 -5
  45. package/docs/runtimes/claude.md +26 -10
  46. package/docs/runtimes/claude.zh-CN.md +26 -10
  47. package/docs/runtimes/cline.md +13 -5
  48. package/docs/runtimes/codebuddy.md +13 -5
  49. package/docs/runtimes/codex.md +13 -5
  50. package/docs/runtimes/compatibility.md +42 -0
  51. package/docs/runtimes/copilot.md +13 -5
  52. package/docs/runtimes/cursor.md +13 -5
  53. package/docs/runtimes/gemini.md +13 -5
  54. package/docs/runtimes/kilo.md +13 -5
  55. package/docs/runtimes/openclaw.md +13 -5
  56. package/docs/runtimes/opencode.md +13 -5
  57. package/docs/runtimes/qoder.md +11 -12
  58. package/docs/runtimes/trae.md +13 -5
  59. package/docs/runtimes/windsurf.md +13 -5
  60. package/docs/superpowers/plans/2026-09-26-content-integrity.md +145 -0
  61. package/docs/superpowers/plans/2026-09-26-diagram-quality.md +170 -0
  62. package/docs/superpowers/specs/2026-09-26-diagram-quality-design.md +77 -0
  63. package/docs/superpowers/specs/2026-09-26-project-optimization-design.md +95 -0
  64. package/docs/zh-CN/common-migration.md +57 -0
  65. package/docs/zh-CN/example-prompts.md +29 -12
  66. package/docs/zh-CN/project-structure.md +49 -11
  67. package/docs/zh-CN/review-and-diagram-workflows.md +39 -0
  68. package/docs/zh-TW/README.md +129 -34
  69. package/localized/zh-CN/agents/fec-code-reviewer.md +22 -3
  70. package/localized/zh-CN/agents/fec-refactor-cleaner.md +3 -0
  71. package/localized/zh-CN/agents/fec-refactoring-expert.md +53 -0
  72. package/localized/zh-CN/agents/fec-security-reviewer.md +16 -0
  73. package/localized/zh-CN/agents/fec-typescript-reviewer.md +24 -8
  74. package/localized/zh-CN/commands/fec-refactor-plan.md +15 -0
  75. package/localized/zh-CN/commands/fec-refactor.md +14 -0
  76. package/localized/zh-CN/commands/fec-review.md +40 -9
  77. package/localized/zh-CN/commands/fec-smell.md +13 -0
  78. package/localized/zh-CN/commands/fec-tdd.md +4 -0
  79. package/localized/zh-CN/skills/cc-c-project-standard/SKILL.md +25 -0
  80. package/localized/zh-CN/skills/cc-c-project-standard/examples/engineering/README.md +7 -0
  81. package/localized/zh-CN/skills/cc-c-project-standard/examples/engineering/boundary.c +26 -0
  82. package/localized/zh-CN/skills/cc-c-project-standard/examples/engineering/boundary.h +15 -0
  83. package/localized/zh-CN/skills/cc-c-project-standard/examples/engineering/boundary_test.c +73 -0
  84. package/localized/zh-CN/skills/cc-c-project-standard/references/common/engineering-practices.md +237 -0
  85. package/localized/zh-CN/skills/cc-c-project-standard/references/common/engineering-practices.rules.json +121 -0
  86. package/localized/zh-CN/skills/cc-c-project-standard/references/common/engineering-practices.sources.json +377 -0
  87. package/localized/zh-CN/skills/cc-c-project-standard/references/engineering-practices.md +106 -0
  88. package/localized/zh-CN/skills/cc-c-project-standard/references/practice.md +37 -0
  89. package/localized/zh-CN/skills/cc-cpp-project-standard/SKILL.md +25 -0
  90. package/localized/zh-CN/skills/cc-cpp-project-standard/examples/engineering/README.md +7 -0
  91. package/localized/zh-CN/skills/cc-cpp-project-standard/examples/engineering/boundary.cpp +26 -0
  92. package/localized/zh-CN/skills/cc-cpp-project-standard/examples/engineering/boundary.hpp +12 -0
  93. package/localized/zh-CN/skills/cc-cpp-project-standard/examples/engineering/boundary_test.cpp +38 -0
  94. package/localized/zh-CN/skills/cc-cpp-project-standard/references/common/engineering-practices.md +237 -0
  95. package/localized/zh-CN/skills/cc-cpp-project-standard/references/common/engineering-practices.rules.json +121 -0
  96. package/localized/zh-CN/skills/cc-cpp-project-standard/references/common/engineering-practices.sources.json +377 -0
  97. package/localized/zh-CN/skills/cc-cpp-project-standard/references/engineering-practices.md +106 -0
  98. package/localized/zh-CN/skills/cc-cpp-project-standard/references/practice.md +37 -0
  99. package/localized/zh-CN/skills/cc-debug-methodology/SKILL.md +8 -0
  100. package/localized/zh-CN/skills/cc-debug-methodology/references/method.md +13 -0
  101. package/localized/zh-CN/skills/cc-doc-sync-core/SKILL.md +8 -0
  102. package/localized/zh-CN/skills/cc-doc-sync-core/references/method.md +12 -0
  103. package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/SKILL.md +5 -5
  104. package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/references/flowchart-quality.md +1 -1
  105. package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/references/layout-and-export.md +9 -9
  106. package/localized/zh-CN/skills/cc-electron-project-standard/SKILL.md +21 -0
  107. package/localized/zh-CN/skills/cc-electron-project-standard/examples/engineering/README.md +7 -0
  108. package/localized/zh-CN/skills/cc-electron-project-standard/examples/engineering/ipc-lifecycle.cjs +44 -0
  109. package/localized/zh-CN/skills/cc-electron-project-standard/examples/engineering/ipc-lifecycle.test.cjs +44 -0
  110. package/localized/zh-CN/skills/cc-electron-project-standard/examples/engineering/package.json +8 -0
  111. package/localized/zh-CN/skills/cc-electron-project-standard/examples/minimal/README.md +9 -0
  112. package/localized/zh-CN/skills/cc-electron-project-standard/examples/minimal/boundary.cjs +19 -0
  113. package/localized/zh-CN/skills/cc-electron-project-standard/examples/minimal/boundary.test.cjs +7 -0
  114. package/localized/zh-CN/skills/cc-electron-project-standard/examples/minimal/index.html +1 -0
  115. package/localized/zh-CN/skills/cc-electron-project-standard/examples/minimal/main.cjs +20 -0
  116. package/localized/zh-CN/skills/cc-electron-project-standard/examples/minimal/package.json +9 -0
  117. package/localized/zh-CN/skills/cc-electron-project-standard/examples/minimal/preload.cjs +2 -0
  118. package/localized/zh-CN/skills/cc-electron-project-standard/examples/minimal/renderer.js +4 -0
  119. package/localized/zh-CN/skills/cc-electron-project-standard/references/common/engineering-practices.md +237 -0
  120. package/localized/zh-CN/skills/cc-electron-project-standard/references/common/engineering-practices.rules.json +121 -0
  121. package/localized/zh-CN/skills/cc-electron-project-standard/references/common/engineering-practices.sources.json +377 -0
  122. package/localized/zh-CN/skills/cc-electron-project-standard/references/engineering-practices.md +73 -0
  123. package/localized/zh-CN/skills/cc-electron-project-standard/references/practice.md +19 -0
  124. package/localized/zh-CN/skills/cc-electron-project-standard/references/verification.md +17 -0
  125. package/localized/zh-CN/skills/cc-go-concurrency/SKILL.md +25 -0
  126. package/localized/zh-CN/skills/cc-go-concurrency/references/common/engineering-practices.md +237 -0
  127. package/localized/zh-CN/skills/cc-go-concurrency/references/common/engineering-practices.rules.json +121 -0
  128. package/localized/zh-CN/skills/cc-go-concurrency/references/common/engineering-practices.sources.json +377 -0
  129. package/localized/zh-CN/skills/cc-go-concurrency/references/engineering-practices.md +73 -0
  130. package/localized/zh-CN/skills/cc-go-concurrency/references/practice.md +37 -0
  131. package/localized/zh-CN/skills/cc-go-project-standard/SKILL.md +25 -0
  132. package/localized/zh-CN/skills/cc-go-project-standard/examples/engineering/README.md +7 -0
  133. package/localized/zh-CN/skills/cc-go-project-standard/examples/engineering/go.mod +3 -0
  134. package/localized/zh-CN/skills/cc-go-project-standard/examples/engineering/lifecycle.go +71 -0
  135. package/localized/zh-CN/skills/cc-go-project-standard/examples/engineering/lifecycle_test.go +22 -0
  136. package/localized/zh-CN/skills/cc-go-project-standard/references/common/engineering-practices.md +237 -0
  137. package/localized/zh-CN/skills/cc-go-project-standard/references/common/engineering-practices.rules.json +121 -0
  138. package/localized/zh-CN/skills/cc-go-project-standard/references/common/engineering-practices.sources.json +377 -0
  139. package/localized/zh-CN/skills/cc-go-project-standard/references/engineering-practices.md +106 -0
  140. package/localized/zh-CN/skills/cc-go-project-standard/references/practice.md +37 -0
  141. package/localized/zh-CN/skills/cc-java-project-standard/SKILL.md +25 -0
  142. package/localized/zh-CN/skills/cc-java-project-standard/examples/engineering/README.md +5 -0
  143. package/localized/zh-CN/skills/cc-java-project-standard/examples/engineering/ResourceBoundary.java +26 -0
  144. package/localized/zh-CN/skills/cc-java-project-standard/examples/engineering/ResourceBoundaryTest.java +41 -0
  145. package/localized/zh-CN/skills/cc-java-project-standard/references/common/engineering-practices.md +237 -0
  146. package/localized/zh-CN/skills/cc-java-project-standard/references/common/engineering-practices.rules.json +121 -0
  147. package/localized/zh-CN/skills/cc-java-project-standard/references/common/engineering-practices.sources.json +377 -0
  148. package/localized/zh-CN/skills/cc-java-project-standard/references/engineering-practices.md +106 -0
  149. package/localized/zh-CN/skills/cc-java-project-standard/references/practice.md +37 -0
  150. package/localized/zh-CN/skills/cc-java-runtime/SKILL.md +25 -0
  151. package/localized/zh-CN/skills/cc-java-runtime/references/common/engineering-practices.md +237 -0
  152. package/localized/zh-CN/skills/cc-java-runtime/references/common/engineering-practices.rules.json +121 -0
  153. package/localized/zh-CN/skills/cc-java-runtime/references/common/engineering-practices.sources.json +377 -0
  154. package/localized/zh-CN/skills/cc-java-runtime/references/engineering-practices.md +73 -0
  155. package/localized/zh-CN/skills/cc-java-runtime/references/practice.md +37 -0
  156. package/localized/zh-CN/skills/cc-native-memory-safety/SKILL.md +25 -0
  157. package/localized/zh-CN/skills/cc-native-memory-safety/references/common/engineering-practices.md +237 -0
  158. package/localized/zh-CN/skills/cc-native-memory-safety/references/common/engineering-practices.rules.json +121 -0
  159. package/localized/zh-CN/skills/cc-native-memory-safety/references/common/engineering-practices.sources.json +377 -0
  160. package/localized/zh-CN/skills/cc-native-memory-safety/references/engineering-practices.md +73 -0
  161. package/localized/zh-CN/skills/cc-native-memory-safety/references/practice.md +37 -0
  162. package/localized/zh-CN/skills/cc-python-async/SKILL.md +25 -0
  163. package/localized/zh-CN/skills/cc-python-async/references/common/engineering-practices.md +237 -0
  164. package/localized/zh-CN/skills/cc-python-async/references/common/engineering-practices.rules.json +121 -0
  165. package/localized/zh-CN/skills/cc-python-async/references/common/engineering-practices.sources.json +377 -0
  166. package/localized/zh-CN/skills/cc-python-async/references/engineering-practices.md +73 -0
  167. package/localized/zh-CN/skills/cc-python-async/references/practice.md +37 -0
  168. package/localized/zh-CN/skills/cc-python-project-standard/SKILL.md +25 -0
  169. package/localized/zh-CN/skills/cc-python-project-standard/examples/engineering/README.md +7 -0
  170. package/localized/zh-CN/skills/cc-python-project-standard/examples/engineering/resource_boundary.py +37 -0
  171. package/localized/zh-CN/skills/cc-python-project-standard/examples/engineering/test_resource_boundary.py +49 -0
  172. package/localized/zh-CN/skills/cc-python-project-standard/references/common/engineering-practices.md +237 -0
  173. package/localized/zh-CN/skills/cc-python-project-standard/references/common/engineering-practices.rules.json +121 -0
  174. package/localized/zh-CN/skills/cc-python-project-standard/references/common/engineering-practices.sources.json +377 -0
  175. package/localized/zh-CN/skills/cc-python-project-standard/references/engineering-practices.md +106 -0
  176. package/localized/zh-CN/skills/cc-python-project-standard/references/practice.md +37 -0
  177. package/localized/zh-CN/skills/cc-refactoring-core/SKILL.md +8 -0
  178. package/localized/zh-CN/skills/cc-refactoring-core/references/method.md +16 -0
  179. package/localized/zh-CN/skills/cc-rust-async/SKILL.md +25 -0
  180. package/localized/zh-CN/skills/cc-rust-async/references/common/engineering-practices.md +237 -0
  181. package/localized/zh-CN/skills/cc-rust-async/references/common/engineering-practices.rules.json +121 -0
  182. package/localized/zh-CN/skills/cc-rust-async/references/common/engineering-practices.sources.json +377 -0
  183. package/localized/zh-CN/skills/cc-rust-async/references/engineering-practices.md +73 -0
  184. package/localized/zh-CN/skills/cc-rust-async/references/practice.md +37 -0
  185. package/localized/zh-CN/skills/cc-rust-project-standard/SKILL.md +25 -0
  186. package/localized/zh-CN/skills/cc-rust-project-standard/examples/engineering/Cargo.lock +7 -0
  187. package/localized/zh-CN/skills/cc-rust-project-standard/examples/engineering/Cargo.toml +8 -0
  188. package/localized/zh-CN/skills/cc-rust-project-standard/examples/engineering/README.md +5 -0
  189. package/localized/zh-CN/skills/cc-rust-project-standard/examples/engineering/src/lib.rs +43 -0
  190. package/localized/zh-CN/skills/cc-rust-project-standard/references/common/engineering-practices.md +237 -0
  191. package/localized/zh-CN/skills/cc-rust-project-standard/references/common/engineering-practices.rules.json +121 -0
  192. package/localized/zh-CN/skills/cc-rust-project-standard/references/common/engineering-practices.sources.json +377 -0
  193. package/localized/zh-CN/skills/cc-rust-project-standard/references/engineering-practices.md +106 -0
  194. package/localized/zh-CN/skills/cc-rust-project-standard/references/practice.md +37 -0
  195. package/localized/zh-CN/skills/cc-source-driven-development/SKILL.md +8 -0
  196. package/localized/zh-CN/skills/cc-source-driven-development/references/method.md +19 -0
  197. package/localized/zh-CN/skills/cc-tauri-project-standard/SKILL.md +21 -0
  198. package/localized/zh-CN/skills/cc-tauri-project-standard/examples/minimal/README.md +9 -0
  199. package/localized/zh-CN/skills/cc-tauri-project-standard/examples/minimal/core/Cargo.lock +5 -0
  200. package/localized/zh-CN/skills/cc-tauri-project-standard/examples/minimal/core/Cargo.toml +9 -0
  201. package/localized/zh-CN/skills/cc-tauri-project-standard/examples/minimal/core/src/lib.rs +46 -0
  202. package/localized/zh-CN/skills/cc-tauri-project-standard/examples/minimal/src-tauri/Cargo.toml +12 -0
  203. package/localized/zh-CN/skills/cc-tauri-project-standard/examples/minimal/src-tauri/build.rs +5 -0
  204. package/localized/zh-CN/skills/cc-tauri-project-standard/examples/minimal/src-tauri/capabilities/main.json +6 -0
  205. package/localized/zh-CN/skills/cc-tauri-project-standard/examples/minimal/src-tauri/permissions/documents.toml +4 -0
  206. package/localized/zh-CN/skills/cc-tauri-project-standard/examples/minimal/src-tauri/src/main.rs +22 -0
  207. package/localized/zh-CN/skills/cc-tauri-project-standard/examples/minimal/src-tauri/tauri.conf.json +13 -0
  208. package/localized/zh-CN/skills/cc-tauri-project-standard/examples/minimal/ui/app.js +5 -0
  209. package/localized/zh-CN/skills/cc-tauri-project-standard/examples/minimal/ui/index.html +1 -0
  210. package/localized/zh-CN/skills/cc-tauri-project-standard/references/common/engineering-practices.md +237 -0
  211. package/localized/zh-CN/skills/cc-tauri-project-standard/references/common/engineering-practices.rules.json +121 -0
  212. package/localized/zh-CN/skills/cc-tauri-project-standard/references/common/engineering-practices.sources.json +377 -0
  213. package/localized/zh-CN/skills/cc-tauri-project-standard/references/engineering-practices.md +73 -0
  214. package/localized/zh-CN/skills/cc-tauri-project-standard/references/practice.md +20 -0
  215. package/localized/zh-CN/skills/cc-tauri-project-standard/references/verification.md +18 -0
  216. package/localized/zh-CN/skills/cc-tdd-methodology/SKILL.md +8 -0
  217. package/localized/zh-CN/skills/cc-tdd-methodology/references/method.md +13 -0
  218. package/localized/zh-CN/skills/cc-technical-diagrams/SKILL.md +34 -0
  219. package/localized/zh-CN/skills/{fec-image-generation → cc-technical-diagrams}/assets/interactive-diagram.html +371 -371
  220. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/README.md +14 -0
  221. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/architecture.json +121 -0
  222. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/invalid-explicit.json +41 -0
  223. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/sequence.json +53 -0
  224. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/sequence.mmd +21 -0
  225. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/workflow.json +98 -0
  226. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/workflow.mmd +7 -0
  227. package/localized/zh-CN/skills/{fec-image-generation → cc-technical-diagrams}/references/diagram-workflows.md +12 -5
  228. package/localized/zh-CN/skills/{fec-image-generation → cc-technical-diagrams}/references/html-technical-diagrams.md +14 -7
  229. package/localized/zh-CN/skills/cc-technical-diagrams/references/png-qa-autofix.md +37 -0
  230. package/localized/zh-CN/skills/cc-technical-diagrams/scripts/diagram-browser.mjs +153 -0
  231. package/localized/zh-CN/skills/cc-technical-diagrams/scripts/diagram-layout.mjs +176 -0
  232. package/{skills/fec-image-generation → localized/zh-CN/skills/cc-technical-diagrams}/scripts/export-diagram.mjs +48 -80
  233. package/localized/zh-CN/skills/cc-technical-diagrams/scripts/mermaid-render.mjs +64 -0
  234. package/localized/zh-CN/skills/cc-technical-diagrams/scripts/png-qa.mjs +462 -0
  235. package/localized/zh-CN/skills/{fec-image-generation → cc-technical-diagrams}/scripts/tech-diagram-render.mjs +193 -53
  236. package/localized/zh-CN/skills/{fec-typescript-project-standard → cc-typescript-project-standard}/SKILL.md +10 -4
  237. package/localized/zh-CN/skills/cc-typescript-project-standard/examples/engineering/README.md +7 -0
  238. package/localized/zh-CN/skills/cc-typescript-project-standard/examples/engineering/boundary.test.ts +16 -0
  239. package/localized/zh-CN/skills/cc-typescript-project-standard/examples/engineering/input.ts +12 -0
  240. package/localized/zh-CN/skills/cc-typescript-project-standard/examples/engineering/package.json +12 -0
  241. package/localized/zh-CN/skills/cc-typescript-project-standard/examples/engineering/pnpm-lock.yaml +39 -0
  242. package/localized/zh-CN/skills/cc-typescript-project-standard/examples/engineering/pnpm-workspace.yaml +1 -0
  243. package/localized/zh-CN/skills/cc-typescript-project-standard/examples/engineering/tsconfig.json +8 -0
  244. package/localized/zh-CN/skills/cc-typescript-project-standard/references/common/engineering-practices.md +237 -0
  245. package/localized/zh-CN/skills/cc-typescript-project-standard/references/common/engineering-practices.rules.json +121 -0
  246. package/localized/zh-CN/skills/cc-typescript-project-standard/references/common/engineering-practices.sources.json +377 -0
  247. package/localized/zh-CN/skills/cc-typescript-project-standard/references/engineering-practices.md +106 -0
  248. package/localized/zh-CN/skills/{fec-typescript-project-standard → cc-typescript-project-standard}/references/type-safety-patterns.md +5 -34
  249. package/localized/zh-CN/skills/{fec-typescript-project-standard → cc-typescript-project-standard}/references/type-safety.md +6 -0
  250. package/localized/zh-CN/skills/eval_queries.json +738 -72
  251. package/localized/zh-CN/skills/fec-api-integration/SKILL.md +5 -1
  252. package/localized/zh-CN/skills/fec-api-integration/references/common/engineering-practices.md +237 -0
  253. package/localized/zh-CN/skills/fec-api-integration/references/common/engineering-practices.rules.json +121 -0
  254. package/localized/zh-CN/skills/fec-api-integration/references/common/engineering-practices.sources.json +377 -0
  255. package/localized/zh-CN/skills/fec-api-integration/references/engineering-practices.md +73 -0
  256. package/localized/zh-CN/skills/fec-code-review/SKILL.md +24 -1
  257. package/localized/zh-CN/skills/fec-code-review/references/common/engineering-practices.md +237 -0
  258. package/localized/zh-CN/skills/fec-code-review/references/common/engineering-practices.rules.json +121 -0
  259. package/localized/zh-CN/skills/fec-code-review/references/common/engineering-practices.sources.json +377 -0
  260. package/localized/zh-CN/skills/fec-code-review/references/engineering-practices.md +73 -0
  261. package/localized/zh-CN/skills/fec-code-review/references/report-template.md +11 -1
  262. package/localized/zh-CN/skills/fec-code-smells/SKILL.md +33 -0
  263. package/localized/zh-CN/skills/fec-code-smells/references/detection-guide.md +25 -0
  264. package/localized/zh-CN/skills/fec-code-smells/references/smell-catalog.md +817 -0
  265. package/localized/zh-CN/skills/fec-code-smells/references/smell-to-refactoring-map.md +265 -0
  266. package/localized/zh-CN/skills/fec-data-fetching/SKILL.md +4 -0
  267. package/localized/zh-CN/skills/fec-data-fetching/references/common/engineering-practices.md +237 -0
  268. package/localized/zh-CN/skills/fec-data-fetching/references/common/engineering-practices.rules.json +121 -0
  269. package/localized/zh-CN/skills/fec-data-fetching/references/common/engineering-practices.sources.json +377 -0
  270. package/localized/zh-CN/skills/fec-data-fetching/references/engineering-practices.md +73 -0
  271. package/localized/zh-CN/skills/fec-debug-framework/SKILL.md +1 -50
  272. package/localized/zh-CN/skills/fec-debug-framework/references/common/debug.md +13 -0
  273. package/localized/zh-CN/skills/fec-dependency-upgrade/SKILL.md +4 -0
  274. package/localized/zh-CN/skills/fec-dependency-upgrade/references/common/engineering-practices.md +237 -0
  275. package/localized/zh-CN/skills/fec-dependency-upgrade/references/common/engineering-practices.rules.json +121 -0
  276. package/localized/zh-CN/skills/fec-dependency-upgrade/references/common/engineering-practices.sources.json +377 -0
  277. package/localized/zh-CN/skills/fec-dependency-upgrade/references/engineering-practices.md +73 -0
  278. package/localized/zh-CN/skills/fec-doc-sync/SKILL.md +7 -28
  279. package/localized/zh-CN/skills/fec-doc-sync/references/common/doc-sync.md +12 -0
  280. package/localized/zh-CN/skills/fec-image-generation/SKILL.md +7 -71
  281. package/localized/zh-CN/skills/fec-image-generation/references/png-qa-autofix.md +9 -2
  282. package/localized/zh-CN/skills/fec-image-generation/scripts/diagram-layout.mjs +176 -0
  283. package/localized/zh-CN/skills/fec-image-generation/scripts/png-qa.mjs +36 -5
  284. package/localized/zh-CN/skills/fec-react-project-standard/SKILL.md +6 -0
  285. package/localized/zh-CN/skills/fec-react-project-standard/examples/engineering/README.md +7 -0
  286. package/localized/zh-CN/skills/fec-react-project-standard/examples/engineering/package.json +15 -0
  287. package/localized/zh-CN/skills/fec-react-project-standard/examples/engineering/pnpm-lock.yaml +662 -0
  288. package/localized/zh-CN/skills/fec-react-project-standard/examples/engineering/pnpm-workspace.yaml +1 -0
  289. package/localized/zh-CN/skills/fec-react-project-standard/examples/engineering/request-view.mjs +24 -0
  290. package/localized/zh-CN/skills/fec-react-project-standard/examples/engineering/request-view.test.mjs +33 -0
  291. package/localized/zh-CN/skills/fec-react-project-standard/references/common/engineering-practices.md +237 -0
  292. package/localized/zh-CN/skills/fec-react-project-standard/references/common/engineering-practices.rules.json +121 -0
  293. package/localized/zh-CN/skills/fec-react-project-standard/references/common/engineering-practices.sources.json +377 -0
  294. package/localized/zh-CN/skills/fec-react-project-standard/references/engineering-practices.md +73 -0
  295. package/localized/zh-CN/skills/fec-react-project-standard/references/generic-component-types.md +37 -0
  296. package/localized/zh-CN/skills/fec-react-project-standard/references/react-quality-patterns.md +3 -3
  297. package/localized/zh-CN/skills/fec-react-project-standard/references/react-runtime-patterns.md +1 -1
  298. package/localized/zh-CN/skills/fec-refactor-clean/SKILL.md +3 -0
  299. package/localized/zh-CN/skills/fec-refactoring/SKILL.md +25 -0
  300. package/localized/zh-CN/skills/fec-refactoring/references/common/refactoring.md +16 -0
  301. package/localized/zh-CN/skills/fec-refactoring/references/principles.md +13 -0
  302. package/localized/zh-CN/skills/fec-refactoring/references/refactoring-vs-feature-change.md +25 -0
  303. package/localized/zh-CN/skills/fec-refactoring/references/when-to-refactor.md +17 -0
  304. package/localized/zh-CN/skills/fec-refactoring/references/workflow.md +7 -0
  305. package/localized/zh-CN/skills/fec-refactoring-api/SKILL.md +25 -0
  306. package/localized/zh-CN/skills/fec-refactoring-api/references/api-refactorings.md +496 -0
  307. package/localized/zh-CN/skills/fec-refactoring-catalog/SKILL.md +21 -0
  308. package/localized/zh-CN/skills/fec-refactoring-catalog/references/catalog-index.md +99 -0
  309. package/localized/zh-CN/skills/fec-refactoring-catalog/references/composition-guide.md +49 -0
  310. package/localized/zh-CN/skills/fec-refactoring-catalog/references/selection-guide.md +41 -0
  311. package/localized/zh-CN/skills/fec-refactoring-control/SKILL.md +25 -0
  312. package/localized/zh-CN/skills/fec-refactoring-control/references/conditional-refactorings.md +299 -0
  313. package/localized/zh-CN/skills/fec-refactoring-data/SKILL.md +25 -0
  314. package/localized/zh-CN/skills/fec-refactoring-data/references/data-refactorings.md +248 -0
  315. package/localized/zh-CN/skills/fec-refactoring-encapsulation/SKILL.md +25 -0
  316. package/localized/zh-CN/skills/fec-refactoring-encapsulation/references/encapsulation-refactorings.md +452 -0
  317. package/localized/zh-CN/skills/fec-refactoring-functions/SKILL.md +25 -0
  318. package/localized/zh-CN/skills/fec-refactoring-functions/references/function-refactorings.md +567 -0
  319. package/localized/zh-CN/skills/fec-refactoring-inheritance/SKILL.md +25 -0
  320. package/localized/zh-CN/skills/fec-refactoring-inheritance/references/inheritance-refactorings.md +550 -0
  321. package/localized/zh-CN/skills/fec-refactoring-move-features/SKILL.md +25 -0
  322. package/localized/zh-CN/skills/fec-refactoring-move-features/references/moving-refactorings.md +453 -0
  323. package/localized/zh-CN/skills/fec-refactoring-validation/SKILL.md +52 -0
  324. package/localized/zh-CN/skills/fec-refactoring-validation/references/behavior-preservation.md +15 -0
  325. package/localized/zh-CN/skills/fec-refactoring-validation/references/refactoring-test-checklist.md +25 -0
  326. package/localized/zh-CN/skills/fec-security-review/SKILL.md +20 -0
  327. package/localized/zh-CN/skills/fec-security-review/references/common/engineering-practices.md +237 -0
  328. package/localized/zh-CN/skills/fec-security-review/references/common/engineering-practices.rules.json +121 -0
  329. package/localized/zh-CN/skills/fec-security-review/references/common/engineering-practices.sources.json +377 -0
  330. package/localized/zh-CN/skills/fec-security-review/references/engineering-practices.md +73 -0
  331. package/localized/zh-CN/skills/fec-security-review/references/report-template.md +10 -0
  332. package/localized/zh-CN/skills/fec-tdd-workflow/SKILL.md +12 -40
  333. package/localized/zh-CN/skills/fec-tdd-workflow/references/common/tdd.md +13 -0
  334. package/localized/zh-CN/skills/fec-testing-strategy/SKILL.md +4 -0
  335. package/localized/zh-CN/skills/fec-testing-strategy/references/common/engineering-practices.md +237 -0
  336. package/localized/zh-CN/skills/fec-testing-strategy/references/common/engineering-practices.rules.json +121 -0
  337. package/localized/zh-CN/skills/fec-testing-strategy/references/common/engineering-practices.sources.json +377 -0
  338. package/localized/zh-CN/skills/fec-testing-strategy/references/engineering-practices.md +73 -0
  339. package/localized/zh-CN/skills/fec-vue3-project-standard/SKILL.md +4 -0
  340. package/localized/zh-CN/skills/fec-vue3-project-standard/references/common/engineering-practices.md +237 -0
  341. package/localized/zh-CN/skills/fec-vue3-project-standard/references/common/engineering-practices.rules.json +121 -0
  342. package/localized/zh-CN/skills/fec-vue3-project-standard/references/common/engineering-practices.sources.json +377 -0
  343. package/localized/zh-CN/skills/fec-vue3-project-standard/references/engineering-practices.md +73 -0
  344. package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-project-structure.md +2 -2
  345. package/localized/zh-CN/skills/metadata.json +2222 -626
  346. package/localized/zh-CN/skills/relations.json +472 -75
  347. package/localized/zh-CN/templates/shared/rules/fec-agent-workflow.md +1 -0
  348. package/localized/zh-CN/templates/shared/rules/fec-source-driven-development.md +3 -29
  349. package/localized/zh-CN/templates/shared/rules/fec-typescript.md +4 -4
  350. package/localized/zh-CN/templates/shared/rules/references/common/source-driven-development.md +19 -0
  351. package/openclaw.plugin.json +2 -3
  352. package/package.json +34 -17
  353. package/skills/cc-c-project-standard/SKILL.md +25 -0
  354. package/skills/cc-c-project-standard/examples/engineering/README.md +7 -0
  355. package/skills/cc-c-project-standard/examples/engineering/boundary.c +26 -0
  356. package/skills/cc-c-project-standard/examples/engineering/boundary.h +15 -0
  357. package/skills/cc-c-project-standard/examples/engineering/boundary_test.c +73 -0
  358. package/skills/cc-c-project-standard/references/common/engineering-practices.md +237 -0
  359. package/skills/cc-c-project-standard/references/common/engineering-practices.rules.json +121 -0
  360. package/skills/cc-c-project-standard/references/common/engineering-practices.sources.json +377 -0
  361. package/skills/cc-c-project-standard/references/engineering-practices.md +106 -0
  362. package/skills/cc-c-project-standard/references/practice.md +37 -0
  363. package/skills/cc-cpp-project-standard/SKILL.md +25 -0
  364. package/skills/cc-cpp-project-standard/examples/engineering/README.md +7 -0
  365. package/skills/cc-cpp-project-standard/examples/engineering/boundary.cpp +26 -0
  366. package/skills/cc-cpp-project-standard/examples/engineering/boundary.hpp +12 -0
  367. package/skills/cc-cpp-project-standard/examples/engineering/boundary_test.cpp +38 -0
  368. package/skills/cc-cpp-project-standard/references/common/engineering-practices.md +237 -0
  369. package/skills/cc-cpp-project-standard/references/common/engineering-practices.rules.json +121 -0
  370. package/skills/cc-cpp-project-standard/references/common/engineering-practices.sources.json +377 -0
  371. package/skills/cc-cpp-project-standard/references/engineering-practices.md +106 -0
  372. package/skills/cc-cpp-project-standard/references/practice.md +37 -0
  373. package/skills/cc-debug-methodology/SKILL.md +8 -0
  374. package/skills/cc-debug-methodology/references/method.md +13 -0
  375. package/skills/cc-doc-sync-core/SKILL.md +8 -0
  376. package/skills/cc-doc-sync-core/references/method.md +12 -0
  377. package/skills/{fec-drawio-studio → cc-drawio-studio}/SKILL.md +5 -5
  378. package/skills/{fec-drawio-studio → cc-drawio-studio}/references/flowchart-quality.md +1 -1
  379. package/skills/{fec-drawio-studio → cc-drawio-studio}/references/layout-and-export.md +9 -9
  380. package/skills/cc-electron-project-standard/SKILL.md +21 -0
  381. package/skills/cc-electron-project-standard/examples/engineering/README.md +7 -0
  382. package/skills/cc-electron-project-standard/examples/engineering/ipc-lifecycle.cjs +44 -0
  383. package/skills/cc-electron-project-standard/examples/engineering/ipc-lifecycle.test.cjs +44 -0
  384. package/skills/cc-electron-project-standard/examples/engineering/package.json +8 -0
  385. package/skills/cc-electron-project-standard/examples/minimal/README.md +9 -0
  386. package/skills/cc-electron-project-standard/examples/minimal/boundary.cjs +19 -0
  387. package/skills/cc-electron-project-standard/examples/minimal/boundary.test.cjs +7 -0
  388. package/skills/cc-electron-project-standard/examples/minimal/index.html +1 -0
  389. package/skills/cc-electron-project-standard/examples/minimal/main.cjs +20 -0
  390. package/skills/cc-electron-project-standard/examples/minimal/package.json +9 -0
  391. package/skills/cc-electron-project-standard/examples/minimal/preload.cjs +2 -0
  392. package/skills/cc-electron-project-standard/examples/minimal/renderer.js +4 -0
  393. package/skills/cc-electron-project-standard/references/common/engineering-practices.md +237 -0
  394. package/skills/cc-electron-project-standard/references/common/engineering-practices.rules.json +121 -0
  395. package/skills/cc-electron-project-standard/references/common/engineering-practices.sources.json +377 -0
  396. package/skills/cc-electron-project-standard/references/engineering-practices.md +73 -0
  397. package/skills/cc-electron-project-standard/references/practice.md +19 -0
  398. package/skills/cc-electron-project-standard/references/verification.md +17 -0
  399. package/skills/cc-go-concurrency/SKILL.md +25 -0
  400. package/skills/cc-go-concurrency/references/common/engineering-practices.md +237 -0
  401. package/skills/cc-go-concurrency/references/common/engineering-practices.rules.json +121 -0
  402. package/skills/cc-go-concurrency/references/common/engineering-practices.sources.json +377 -0
  403. package/skills/cc-go-concurrency/references/engineering-practices.md +73 -0
  404. package/skills/cc-go-concurrency/references/practice.md +37 -0
  405. package/skills/cc-go-project-standard/SKILL.md +25 -0
  406. package/skills/cc-go-project-standard/examples/engineering/README.md +7 -0
  407. package/skills/cc-go-project-standard/examples/engineering/go.mod +3 -0
  408. package/skills/cc-go-project-standard/examples/engineering/lifecycle.go +71 -0
  409. package/skills/cc-go-project-standard/examples/engineering/lifecycle_test.go +22 -0
  410. package/skills/cc-go-project-standard/references/common/engineering-practices.md +237 -0
  411. package/skills/cc-go-project-standard/references/common/engineering-practices.rules.json +121 -0
  412. package/skills/cc-go-project-standard/references/common/engineering-practices.sources.json +377 -0
  413. package/skills/cc-go-project-standard/references/engineering-practices.md +106 -0
  414. package/skills/cc-go-project-standard/references/practice.md +37 -0
  415. package/skills/cc-java-project-standard/SKILL.md +25 -0
  416. package/skills/cc-java-project-standard/examples/engineering/README.md +7 -0
  417. package/skills/cc-java-project-standard/examples/engineering/ResourceBoundary.java +26 -0
  418. package/skills/cc-java-project-standard/examples/engineering/ResourceBoundaryTest.java +41 -0
  419. package/skills/cc-java-project-standard/references/common/engineering-practices.md +237 -0
  420. package/skills/cc-java-project-standard/references/common/engineering-practices.rules.json +121 -0
  421. package/skills/cc-java-project-standard/references/common/engineering-practices.sources.json +377 -0
  422. package/skills/cc-java-project-standard/references/engineering-practices.md +106 -0
  423. package/skills/cc-java-project-standard/references/practice.md +35 -0
  424. package/skills/cc-java-runtime/SKILL.md +25 -0
  425. package/skills/cc-java-runtime/references/common/engineering-practices.md +237 -0
  426. package/skills/cc-java-runtime/references/common/engineering-practices.rules.json +121 -0
  427. package/skills/cc-java-runtime/references/common/engineering-practices.sources.json +377 -0
  428. package/skills/cc-java-runtime/references/engineering-practices.md +73 -0
  429. package/skills/cc-java-runtime/references/practice.md +37 -0
  430. package/skills/cc-native-memory-safety/SKILL.md +25 -0
  431. package/skills/cc-native-memory-safety/references/common/engineering-practices.md +237 -0
  432. package/skills/cc-native-memory-safety/references/common/engineering-practices.rules.json +121 -0
  433. package/skills/cc-native-memory-safety/references/common/engineering-practices.sources.json +377 -0
  434. package/skills/cc-native-memory-safety/references/engineering-practices.md +73 -0
  435. package/skills/cc-native-memory-safety/references/practice.md +37 -0
  436. package/skills/cc-python-async/SKILL.md +25 -0
  437. package/skills/cc-python-async/references/common/engineering-practices.md +237 -0
  438. package/skills/cc-python-async/references/common/engineering-practices.rules.json +121 -0
  439. package/skills/cc-python-async/references/common/engineering-practices.sources.json +377 -0
  440. package/skills/cc-python-async/references/engineering-practices.md +73 -0
  441. package/skills/cc-python-async/references/practice.md +37 -0
  442. package/skills/cc-python-project-standard/SKILL.md +25 -0
  443. package/skills/cc-python-project-standard/examples/engineering/README.md +7 -0
  444. package/skills/cc-python-project-standard/examples/engineering/resource_boundary.py +37 -0
  445. package/skills/cc-python-project-standard/examples/engineering/test_resource_boundary.py +49 -0
  446. package/skills/cc-python-project-standard/references/common/engineering-practices.md +237 -0
  447. package/skills/cc-python-project-standard/references/common/engineering-practices.rules.json +121 -0
  448. package/skills/cc-python-project-standard/references/common/engineering-practices.sources.json +377 -0
  449. package/skills/cc-python-project-standard/references/engineering-practices.md +106 -0
  450. package/skills/cc-python-project-standard/references/practice.md +37 -0
  451. package/skills/cc-refactoring-core/SKILL.md +8 -0
  452. package/skills/cc-refactoring-core/references/method.md +16 -0
  453. package/skills/cc-rust-async/SKILL.md +25 -0
  454. package/skills/cc-rust-async/references/common/engineering-practices.md +237 -0
  455. package/skills/cc-rust-async/references/common/engineering-practices.rules.json +121 -0
  456. package/skills/cc-rust-async/references/common/engineering-practices.sources.json +377 -0
  457. package/skills/cc-rust-async/references/engineering-practices.md +73 -0
  458. package/skills/cc-rust-async/references/practice.md +37 -0
  459. package/skills/cc-rust-project-standard/SKILL.md +25 -0
  460. package/skills/cc-rust-project-standard/examples/engineering/Cargo.lock +7 -0
  461. package/skills/cc-rust-project-standard/examples/engineering/Cargo.toml +8 -0
  462. package/skills/cc-rust-project-standard/examples/engineering/README.md +5 -0
  463. package/skills/cc-rust-project-standard/examples/engineering/src/lib.rs +43 -0
  464. package/skills/cc-rust-project-standard/references/common/engineering-practices.md +237 -0
  465. package/skills/cc-rust-project-standard/references/common/engineering-practices.rules.json +121 -0
  466. package/skills/cc-rust-project-standard/references/common/engineering-practices.sources.json +377 -0
  467. package/skills/cc-rust-project-standard/references/engineering-practices.md +106 -0
  468. package/skills/cc-rust-project-standard/references/practice.md +37 -0
  469. package/skills/cc-source-driven-development/SKILL.md +8 -0
  470. package/skills/cc-source-driven-development/references/method.md +19 -0
  471. package/skills/cc-tauri-project-standard/SKILL.md +21 -0
  472. package/skills/cc-tauri-project-standard/examples/minimal/README.md +9 -0
  473. package/skills/cc-tauri-project-standard/examples/minimal/core/Cargo.lock +5 -0
  474. package/skills/cc-tauri-project-standard/examples/minimal/core/Cargo.toml +9 -0
  475. package/skills/cc-tauri-project-standard/examples/minimal/core/src/lib.rs +46 -0
  476. package/skills/cc-tauri-project-standard/examples/minimal/src-tauri/Cargo.toml +12 -0
  477. package/skills/cc-tauri-project-standard/examples/minimal/src-tauri/build.rs +5 -0
  478. package/skills/cc-tauri-project-standard/examples/minimal/src-tauri/capabilities/main.json +6 -0
  479. package/skills/cc-tauri-project-standard/examples/minimal/src-tauri/permissions/documents.toml +4 -0
  480. package/skills/cc-tauri-project-standard/examples/minimal/src-tauri/src/main.rs +22 -0
  481. package/skills/cc-tauri-project-standard/examples/minimal/src-tauri/tauri.conf.json +13 -0
  482. package/skills/cc-tauri-project-standard/examples/minimal/ui/app.js +5 -0
  483. package/skills/cc-tauri-project-standard/examples/minimal/ui/index.html +1 -0
  484. package/skills/cc-tauri-project-standard/references/common/engineering-practices.md +237 -0
  485. package/skills/cc-tauri-project-standard/references/common/engineering-practices.rules.json +121 -0
  486. package/skills/cc-tauri-project-standard/references/common/engineering-practices.sources.json +377 -0
  487. package/skills/cc-tauri-project-standard/references/engineering-practices.md +73 -0
  488. package/skills/cc-tauri-project-standard/references/practice.md +20 -0
  489. package/skills/cc-tauri-project-standard/references/verification.md +18 -0
  490. package/skills/cc-tdd-methodology/SKILL.md +8 -0
  491. package/skills/cc-tdd-methodology/references/method.md +13 -0
  492. package/skills/cc-technical-diagrams/SKILL.md +34 -0
  493. package/skills/{fec-image-generation → cc-technical-diagrams}/assets/interactive-diagram.html +371 -371
  494. package/skills/cc-technical-diagrams/assets/quality-examples/README.md +14 -0
  495. package/skills/cc-technical-diagrams/assets/quality-examples/architecture.json +121 -0
  496. package/skills/cc-technical-diagrams/assets/quality-examples/invalid-explicit.json +41 -0
  497. package/skills/cc-technical-diagrams/assets/quality-examples/sequence.json +53 -0
  498. package/skills/cc-technical-diagrams/assets/quality-examples/sequence.mmd +21 -0
  499. package/skills/cc-technical-diagrams/assets/quality-examples/workflow.json +98 -0
  500. package/skills/cc-technical-diagrams/assets/quality-examples/workflow.mmd +7 -0
  501. package/skills/{fec-image-generation → cc-technical-diagrams}/references/diagram-workflows.md +12 -5
  502. package/skills/{fec-image-generation → cc-technical-diagrams}/references/html-technical-diagrams.md +14 -7
  503. package/skills/cc-technical-diagrams/references/png-qa-autofix.md +37 -0
  504. package/skills/cc-technical-diagrams/scripts/diagram-browser.mjs +153 -0
  505. package/skills/cc-technical-diagrams/scripts/diagram-layout.mjs +176 -0
  506. package/{localized/zh-CN/skills/fec-image-generation → skills/cc-technical-diagrams}/scripts/export-diagram.mjs +48 -80
  507. package/skills/cc-technical-diagrams/scripts/mermaid-render.mjs +64 -0
  508. package/skills/cc-technical-diagrams/scripts/png-qa.mjs +462 -0
  509. package/skills/{fec-image-generation → cc-technical-diagrams}/scripts/tech-diagram-render.mjs +193 -53
  510. package/skills/{fec-typescript-project-standard → cc-typescript-project-standard}/SKILL.md +10 -4
  511. package/skills/cc-typescript-project-standard/examples/engineering/README.md +9 -0
  512. package/skills/cc-typescript-project-standard/examples/engineering/boundary.test.ts +16 -0
  513. package/skills/cc-typescript-project-standard/examples/engineering/input.ts +12 -0
  514. package/skills/cc-typescript-project-standard/examples/engineering/package.json +12 -0
  515. package/skills/cc-typescript-project-standard/examples/engineering/pnpm-lock.yaml +39 -0
  516. package/skills/cc-typescript-project-standard/examples/engineering/pnpm-workspace.yaml +1 -0
  517. package/skills/cc-typescript-project-standard/examples/engineering/tsconfig.json +8 -0
  518. package/skills/cc-typescript-project-standard/references/common/engineering-practices.md +237 -0
  519. package/skills/cc-typescript-project-standard/references/common/engineering-practices.rules.json +121 -0
  520. package/skills/cc-typescript-project-standard/references/common/engineering-practices.sources.json +377 -0
  521. package/skills/cc-typescript-project-standard/references/engineering-practices.md +106 -0
  522. package/skills/{fec-typescript-project-standard → cc-typescript-project-standard}/references/type-safety-patterns.md +6 -35
  523. package/skills/{fec-typescript-project-standard → cc-typescript-project-standard}/references/type-safety.md +7 -1
  524. package/skills/eval_queries.json +738 -72
  525. package/skills/fec-api-integration/SKILL.md +5 -1
  526. package/skills/fec-api-integration/references/common/engineering-practices.md +237 -0
  527. package/skills/fec-api-integration/references/common/engineering-practices.rules.json +121 -0
  528. package/skills/fec-api-integration/references/common/engineering-practices.sources.json +377 -0
  529. package/skills/fec-api-integration/references/engineering-practices.md +73 -0
  530. package/skills/fec-code-review/SKILL.md +24 -1
  531. package/skills/fec-code-review/references/common/engineering-practices.md +237 -0
  532. package/skills/fec-code-review/references/common/engineering-practices.rules.json +121 -0
  533. package/skills/fec-code-review/references/common/engineering-practices.sources.json +377 -0
  534. package/skills/fec-code-review/references/engineering-practices.md +73 -0
  535. package/skills/fec-code-review/references/report-template.md +11 -1
  536. package/skills/fec-code-smells/SKILL.md +33 -0
  537. package/skills/fec-code-smells/references/detection-guide.md +25 -0
  538. package/skills/fec-code-smells/references/smell-catalog.md +861 -0
  539. package/skills/fec-code-smells/references/smell-to-refactoring-map.md +265 -0
  540. package/skills/fec-data-fetching/SKILL.md +5 -1
  541. package/skills/fec-data-fetching/references/common/engineering-practices.md +237 -0
  542. package/skills/fec-data-fetching/references/common/engineering-practices.rules.json +121 -0
  543. package/skills/fec-data-fetching/references/common/engineering-practices.sources.json +377 -0
  544. package/skills/fec-data-fetching/references/engineering-practices.md +73 -0
  545. package/skills/fec-debug-framework/SKILL.md +2 -51
  546. package/skills/fec-debug-framework/references/common/debug.md +13 -0
  547. package/skills/fec-dependency-upgrade/SKILL.md +4 -0
  548. package/skills/fec-dependency-upgrade/references/common/engineering-practices.md +237 -0
  549. package/skills/fec-dependency-upgrade/references/common/engineering-practices.rules.json +121 -0
  550. package/skills/fec-dependency-upgrade/references/common/engineering-practices.sources.json +377 -0
  551. package/skills/fec-dependency-upgrade/references/engineering-practices.md +73 -0
  552. package/skills/fec-doc-sync/SKILL.md +7 -28
  553. package/skills/fec-doc-sync/references/common/doc-sync.md +12 -0
  554. package/skills/fec-image-generation/SKILL.md +7 -72
  555. package/skills/fec-image-generation/references/png-qa-autofix.md +9 -2
  556. package/skills/fec-image-generation/scripts/diagram-layout.mjs +176 -0
  557. package/skills/fec-image-generation/scripts/png-qa.mjs +36 -5
  558. package/skills/fec-legacy-web-standard/SKILL.md +1 -1
  559. package/skills/fec-react-project-standard/SKILL.md +6 -0
  560. package/skills/fec-react-project-standard/examples/engineering/README.md +7 -0
  561. package/skills/fec-react-project-standard/examples/engineering/package.json +15 -0
  562. package/skills/fec-react-project-standard/examples/engineering/pnpm-lock.yaml +662 -0
  563. package/skills/fec-react-project-standard/examples/engineering/pnpm-workspace.yaml +1 -0
  564. package/skills/fec-react-project-standard/examples/engineering/request-view.mjs +24 -0
  565. package/skills/fec-react-project-standard/examples/engineering/request-view.test.mjs +33 -0
  566. package/skills/fec-react-project-standard/references/common/engineering-practices.md +237 -0
  567. package/skills/fec-react-project-standard/references/common/engineering-practices.rules.json +121 -0
  568. package/skills/fec-react-project-standard/references/common/engineering-practices.sources.json +377 -0
  569. package/skills/fec-react-project-standard/references/engineering-practices.md +73 -0
  570. package/skills/fec-react-project-standard/references/generic-component-types.md +37 -0
  571. package/skills/fec-react-project-standard/references/react-quality-patterns.md +3 -3
  572. package/skills/fec-react-project-standard/references/react-runtime-patterns.md +1 -1
  573. package/skills/fec-refactor-clean/SKILL.md +3 -0
  574. package/skills/fec-refactoring/SKILL.md +25 -0
  575. package/skills/fec-refactoring/references/common/refactoring.md +16 -0
  576. package/skills/fec-refactoring/references/principles.md +13 -0
  577. package/skills/fec-refactoring/references/refactoring-vs-feature-change.md +27 -0
  578. package/skills/fec-refactoring/references/when-to-refactor.md +31 -0
  579. package/skills/fec-refactoring/references/workflow.md +7 -0
  580. package/skills/fec-refactoring-api/SKILL.md +25 -0
  581. package/skills/fec-refactoring-api/references/api-refactorings.md +496 -0
  582. package/skills/fec-refactoring-catalog/SKILL.md +28 -0
  583. package/skills/fec-refactoring-catalog/references/catalog-index.md +99 -0
  584. package/skills/fec-refactoring-catalog/references/composition-guide.md +49 -0
  585. package/skills/fec-refactoring-catalog/references/selection-guide.md +47 -0
  586. package/skills/fec-refactoring-control/SKILL.md +25 -0
  587. package/skills/fec-refactoring-control/references/conditional-refactorings.md +299 -0
  588. package/skills/fec-refactoring-data/SKILL.md +25 -0
  589. package/skills/fec-refactoring-data/references/data-refactorings.md +248 -0
  590. package/skills/fec-refactoring-encapsulation/SKILL.md +25 -0
  591. package/skills/fec-refactoring-encapsulation/references/encapsulation-refactorings.md +452 -0
  592. package/skills/fec-refactoring-functions/SKILL.md +25 -0
  593. package/skills/fec-refactoring-functions/references/function-refactorings.md +567 -0
  594. package/skills/fec-refactoring-inheritance/SKILL.md +25 -0
  595. package/skills/fec-refactoring-inheritance/references/inheritance-refactorings.md +550 -0
  596. package/skills/fec-refactoring-move-features/SKILL.md +25 -0
  597. package/skills/fec-refactoring-move-features/references/moving-refactorings.md +453 -0
  598. package/skills/fec-refactoring-validation/SKILL.md +59 -0
  599. package/skills/fec-refactoring-validation/references/behavior-preservation.md +53 -0
  600. package/skills/fec-refactoring-validation/references/refactoring-test-checklist.md +42 -0
  601. package/skills/fec-security-review/SKILL.md +20 -0
  602. package/skills/fec-security-review/references/common/engineering-practices.md +237 -0
  603. package/skills/fec-security-review/references/common/engineering-practices.rules.json +121 -0
  604. package/skills/fec-security-review/references/common/engineering-practices.sources.json +377 -0
  605. package/skills/fec-security-review/references/engineering-practices.md +73 -0
  606. package/skills/fec-security-review/references/report-template.md +10 -0
  607. package/skills/fec-tdd-workflow/SKILL.md +14 -42
  608. package/skills/fec-tdd-workflow/references/common/tdd.md +13 -0
  609. package/skills/fec-testing-strategy/SKILL.md +4 -0
  610. package/skills/fec-testing-strategy/references/common/engineering-practices.md +237 -0
  611. package/skills/fec-testing-strategy/references/common/engineering-practices.rules.json +121 -0
  612. package/skills/fec-testing-strategy/references/common/engineering-practices.sources.json +377 -0
  613. package/skills/fec-testing-strategy/references/engineering-practices.md +73 -0
  614. package/skills/fec-vue3-project-standard/SKILL.md +4 -0
  615. package/skills/fec-vue3-project-standard/references/common/engineering-practices.md +237 -0
  616. package/skills/fec-vue3-project-standard/references/common/engineering-practices.rules.json +121 -0
  617. package/skills/fec-vue3-project-standard/references/common/engineering-practices.sources.json +377 -0
  618. package/skills/fec-vue3-project-standard/references/engineering-practices.md +73 -0
  619. package/skills/fec-vue3-project-standard/references/vue3-project-structure.md +2 -2
  620. package/skills/metadata.json +2230 -629
  621. package/skills/relations.json +467 -74
  622. package/templates/shared/rules/fec-agent-workflow.md +1 -0
  623. package/templates/shared/rules/fec-source-driven-development.md +3 -29
  624. package/templates/shared/rules/fec-typescript.md +4 -4
  625. package/templates/shared/rules/references/common/source-driven-development.md +19 -0
  626. package/docs/superpowers/plans/2026-05-29-fec-debug.md +0 -491
  627. package/docs/superpowers/specs/2026-05-29-fec-debug-design.md +0 -340
  628. package/localized/zh-CN/skills/fec-source-driven-development/SKILL.md +0 -87
  629. package/skills/fec-source-driven-development/SKILL.md +0 -87
  630. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/data/THIRD_PARTY_NOTICES.md +0 -0
  631. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/data/brand-icons.json +0 -0
  632. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/data/shape-index.json +0 -0
  633. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/references/data-residency.md +0 -0
  634. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/references/diagram-patterns.md +0 -0
  635. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/references/troubleshooting.md +0 -0
  636. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/references/xml-and-mermaid.md +0 -0
  637. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/brand-symbols.mjs +0 -0
  638. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/diagram-lint.mjs +0 -0
  639. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/diagram-url.mjs +0 -0
  640. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/drawio-export.mjs +0 -0
  641. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/layout-graph.mjs +0 -0
  642. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/png-embed-fix.mjs +0 -0
  643. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/scan-go-packages.mjs +0 -0
  644. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/scan-js-modules.mjs +0 -0
  645. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/scan-python-classes.mjs +0 -0
  646. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/scan-python-modules.mjs +0 -0
  647. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/scan-rust-modules.mjs +0 -0
  648. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/scan-ts-modules.mjs +0 -0
  649. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/shape-query.mjs +0 -0
  650. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/studio-core.mjs +0 -0
  651. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/styles/built-in/corporate.json +0 -0
  652. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/styles/built-in/default.json +0 -0
  653. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/styles/built-in/handdrawn.json +0 -0
  654. /package/localized/zh-CN/skills/{fec-drawio-studio → cc-drawio-studio}/styles/schema.json +0 -0
  655. /package/localized/zh-CN/skills/{fec-image-generation → cc-technical-diagrams}/scripts/interactive-diagram-server.mjs +0 -0
  656. /package/skills/{fec-drawio-studio → cc-drawio-studio}/data/THIRD_PARTY_NOTICES.md +0 -0
  657. /package/skills/{fec-drawio-studio → cc-drawio-studio}/data/brand-icons.json +0 -0
  658. /package/skills/{fec-drawio-studio → cc-drawio-studio}/data/shape-index.json +0 -0
  659. /package/skills/{fec-drawio-studio → cc-drawio-studio}/references/data-residency.md +0 -0
  660. /package/skills/{fec-drawio-studio → cc-drawio-studio}/references/diagram-patterns.md +0 -0
  661. /package/skills/{fec-drawio-studio → cc-drawio-studio}/references/troubleshooting.md +0 -0
  662. /package/skills/{fec-drawio-studio → cc-drawio-studio}/references/xml-and-mermaid.md +0 -0
  663. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/brand-symbols.mjs +0 -0
  664. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/diagram-lint.mjs +0 -0
  665. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/diagram-url.mjs +0 -0
  666. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/drawio-export.mjs +0 -0
  667. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/layout-graph.mjs +0 -0
  668. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/png-embed-fix.mjs +0 -0
  669. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/scan-go-packages.mjs +0 -0
  670. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/scan-js-modules.mjs +0 -0
  671. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/scan-python-classes.mjs +0 -0
  672. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/scan-python-modules.mjs +0 -0
  673. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/scan-rust-modules.mjs +0 -0
  674. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/scan-ts-modules.mjs +0 -0
  675. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/shape-query.mjs +0 -0
  676. /package/skills/{fec-drawio-studio → cc-drawio-studio}/scripts/studio-core.mjs +0 -0
  677. /package/skills/{fec-drawio-studio → cc-drawio-studio}/styles/built-in/corporate.json +0 -0
  678. /package/skills/{fec-drawio-studio → cc-drawio-studio}/styles/built-in/default.json +0 -0
  679. /package/skills/{fec-drawio-studio → cc-drawio-studio}/styles/built-in/handdrawn.json +0 -0
  680. /package/skills/{fec-drawio-studio → cc-drawio-studio}/styles/schema.json +0 -0
  681. /package/skills/{fec-image-generation → cc-technical-diagrams}/scripts/interactive-diagram-server.mjs +0 -0
@@ -3,6 +3,19 @@
3
3
 
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
6
+ import { layoutText, fitNodeText, routeConnector, placeEdgeLabel, overlaps } from "./diagram-layout.mjs";
7
+
8
+ /** @type {import("./diagram-layout.mjs").QualityIssue[]} */
9
+ const qualityIssues = [];
10
+ /** @type {Array<{id:string,owner:string,kind:string,text:string,lines:string[],x:number,y:number,width:number,height:number}>} */
11
+ const textBounds = [];
12
+ /** @type {Box[]} */
13
+ let routeObstacles = [];
14
+ /** @type {Array<Array<[number,number]>>} */
15
+ const occupiedRoutes = [];
16
+ /** @type {Array<{id:string,label:string,points:Array<[number,number]>}>} */
17
+ const deferredLabels=[];
18
+ let finalCanvas = { width: 0, height: 0 };
6
19
 
7
20
  const ALLOWED_TYPES = new Set(["workflow", "sequence", "dataflow", "lifecycle", "architecture"]);
8
21
  const NODE_TYPES = new Set([
@@ -34,8 +47,12 @@ try {
34
47
  /** @type {SummaryCard[]} */
35
48
  const summary = "summary" in renderResult ? /** @type {SummaryCard[]} */ (renderResult.summary) : [];
36
49
  const style = normalizeVisualStyle(diagram.visual, "/visual");
37
- const html = renderHtml(diagram.meta.title, diagram.meta.subtitle ?? "", renderResult.svg, type, summary, style);
50
+ const rawHtml = renderHtml(diagram.meta.title, diagram.meta.subtitle ?? "", renderResult.svg, type, summary, style);
38
51
 
52
+ const pageStyles = rawHtml.match(/<style>([\s\S]*?)<\/style>/)?.[1] ?? "";
53
+ const diagramStyles=(pageStyles.match(/[^{}]+\{[^{}]*\}/g) ?? []).filter(rule=>/^\s*(?:[:][r]oot|\[data-|\.node|\.edge|\.group|\.lane|\.legend|\.flow|\.label|\.sublabel|\.muted|\.actor|\.step|\.lifeline|\.tech-diagram|\.surface|\.stage|marker|#arrow)/.test(rule)).join("\n");
54
+ const svgStyles = diagramStyles.replaceAll(":root", "svg").replaceAll(/\[data-theme=/g, "svg[data-theme=").replaceAll(/\[data-visual-style=/g, "svg[data-visual-style=");
55
+ const html = rawHtml.replace('data-visual-style="default" data-export-root', `data-visual-style="${style}" data-export-root`).replace(/(<svg[^>]*>)/, `$1<style>${svgStyles}\nsvg{font-family:ui-sans-serif,system-ui,"Segoe UI",sans-serif;}svg[data-theme="dark"]{--surface:#172033;--text:#e2e8f0;--muted:#94a3b8;--line:#94a3b8;}svg[data-theme="light"]{--surface:#f8fafc;--text:#0f172a;--muted:#475569;--line:#475569;--frontend:#0369a1;--backend:#047857;--database:#0e7490;--external:#475569;--agent:#0e7490;--model:#7e22ce;--memory:#047857;--gateway:#a16207;--browser:#0369a1;--queue:#c2410c;--flow-control:#b45309;--flow-data:#0369a1;--flow-read:#047857;--flow-write:#15803d;--flow-async:#64748b;--flow-feedback:#7e22ce;}</style>`);
39
56
  fs.mkdirSync(path.dirname(path.resolve(outputPath)), { recursive: true });
40
57
  fs.writeFileSync(outputPath, html, "utf8");
41
58
 
@@ -50,6 +67,7 @@ try {
50
67
  input: inputPath,
51
68
  output: outputPath,
52
69
  manifest: args.manifest ?? null,
70
+ quality: { status: qualityIssues.length ? "partial" : "estimated", issues: qualityIssues },
53
71
  nodes: renderResult.manifest.boxes.length,
54
72
  connectors: renderResult.manifest.connectors.length,
55
73
  };
@@ -165,6 +183,7 @@ function renderArchitecture(diagram) {
165
183
  label,
166
184
  sublabel: "",
167
185
  type,
186
+ kind: "group",
168
187
  };
169
188
  groupBoxes.push(box);
170
189
  }
@@ -187,6 +206,14 @@ function renderArchitecture(diagram) {
187
206
  });
188
207
  }
189
208
 
209
+ prepareBoxes(boxes, nodes);
210
+ for (const node of nodes) {
211
+ const box = boxes.get(String(node.id));
212
+ const group = groupBoxes.find((candidate) => candidate.id === node.group);
213
+ if (box && group && (box.x < group.x + 12 || box.y < group.y + 32 || box.x + box.width > group.x + group.width - 12 || box.y + box.height > group.y + group.height - 12)) qualityIssues.push({code:"group-containment",id:box.id,message:`Node "${box.id}" exceeds group "${group.id}" content area.`});
214
+ }
215
+
216
+
190
217
  /** @type {Connector[]} */
191
218
  const connectors = [];
192
219
  const flowSet = new Set();
@@ -209,11 +236,13 @@ function renderArchitecture(diagram) {
209
236
  const contentBottom = Math.max(360, maxBoxExtent(allBoxes, "y") + 64);
210
237
  const legend = normalizeLegend(diagram.legend, [...boxes.values()]);
211
238
  const flowLegend = normalizeFlowLegend(diagram.flowLegend, [...flowSet]);
212
- const legendWidth = Math.max(88 + legend.length * 118, 88 + flowLegend.length * 128);
213
- const width = Math.max(860, maxBoxExtent(allBoxes, "x") + 64, legendWidth);
214
- const legendSvg = renderArchitectureLegend(legend, 44, contentBottom - 4);
215
- const flowLegendSvg = renderFlowLegend(flowLegend, 44, contentBottom + (legend.length > 0 ? 42 : 0));
216
- const height = contentBottom + (legend.length > 0 ? 54 : 0) + (flowLegend.length > 0 ? 54 : 0);
239
+ const width = Math.max(860, maxBoxExtent(allBoxes, "x") + 64);
240
+ const columns=Math.max(1,Math.floor((width-88)/200));
241
+ const legendHeight=legend.length ? 30+Math.ceil(legend.length/columns)*72 : 0;
242
+ const flowHeight=flowLegend.length ? 30+Math.ceil(flowLegend.length/columns)*72 : 0;
243
+ const legendSvg = renderArchitectureLegend(legend,44,contentBottom-4,columns);
244
+ const flowLegendSvg = renderFlowLegend(flowLegend,44,contentBottom+legendHeight,columns);
245
+ const height=contentBottom+legendHeight+flowHeight+32;
217
246
  const groupSvg = groupBoxes.map(renderGroup).join("\n");
218
247
  const boxSvg = [...boxes.values()].map(renderBox).join("\n");
219
248
  const svg = wrapSvg(width, height, `${groupSvg}\n${connectionSvg}\n${boxSvg}\n${legendSvg}\n${flowLegendSvg}`);
@@ -249,8 +278,8 @@ function renderLaneDiagram(diagram, itemKey, edgeKey) {
249
278
  assertObject(item, `/${itemKey}/${index}`);
250
279
  return requireNumber(item, "col", `/${itemKey}/${index}/col`);
251
280
  }));
252
- const width = Math.max(780, 190 + (maxCol + 1) * 180);
253
- const height = Math.max(420, 140 + lanes.length * 145);
281
+ let width = Math.max(780, 190 + (maxCol + 1) * 180);
282
+ let height = Math.max(420, 140 + lanes.length * 145);
254
283
  const laneHeight = 118;
255
284
  const top = 72;
256
285
  const left = 142;
@@ -285,6 +314,36 @@ function renderLaneDiagram(diagram, itemKey, edgeKey) {
285
314
  boxes.set(id, box);
286
315
  }
287
316
 
317
+ prepareBoxes(boxes, items);
318
+ let laneTop = 72;
319
+ /** @type {Array<{y:number,height:number}>} */
320
+ const laneGeometry = [];
321
+ const columns = [...new Set(items.map((item) => Number(item.col)))].sort((a, b) => a - b);
322
+ const columnX = new Map();
323
+ let nextX = 160;
324
+ for (const col of columns) {
325
+ columnX.set(col, nextX);
326
+ nextX += Math.max(0, ...items.filter((item) => item.col === col).map((item) => boxes.get(String(item.id))?.width ?? 0)) + 64;
327
+ }
328
+ for (const lane of lanes) {
329
+ const members = items.filter((item) => item.lane === lane.id);
330
+ const columnBottom = new Map();
331
+ for (const item of members) {
332
+ const box = boxes.get(String(item.id));
333
+ if (!box) continue;
334
+ box.x = Number(columnX.get(Number(item.col)));
335
+ const baseline = columnBottom.get(item.col) ?? laneTop + 48;
336
+ box.y = baseline + (typeof item.yOffset === "number" ? item.yOffset : 0);
337
+ columnBottom.set(item.col, box.y + box.height + 32);
338
+ }
339
+ const bottom = Math.max(laneTop + 112, ...members.map((item) => { const b = boxes.get(String(item.id)); return b ? b.y + b.height + 24 : laneTop; }));
340
+ laneGeometry.push({ y: laneTop, height: bottom - laneTop });
341
+ laneTop = bottom + 32;
342
+ }
343
+ width = Math.max(width, nextX + 40);
344
+ height = Math.max(height, laneTop + 40);
345
+
346
+
288
347
  /** @type {Connector[]} */
289
348
  const connectors = [];
290
349
  const edgeSvg = edges.map((edge, index) => {
@@ -303,8 +362,8 @@ function renderLaneDiagram(diagram, itemKey, edgeKey) {
303
362
  }).join("\n");
304
363
 
305
364
  const laneSvg = lanes.map((lane, index) => {
306
- const y = top + index * laneHeight;
307
- return `<g class="lane"><rect x="34" y="${y}" width="${width - 68}" height="${laneHeight - 16}" rx="10"/><text x="52" y="${y + 28}" class="label muted">${escapeHtml(String(lane.label))}</text></g>`;
365
+ const y = laneGeometry[index].y;
366
+ return `<g class="lane"><rect x="34" y="${y}" width="${width - 68}" height="${laneGeometry[index].height}" rx="10"/><text x="52" y="${y + 28}" class="label muted">${escapeHtml(String(lane.label))}</text></g>`;
308
367
  }).join("\n");
309
368
  const boxSvg = [...boxes.values()].map(renderBox).join("\n");
310
369
  const svg = wrapSvg(width, height, `${laneSvg}\n${edgeSvg}\n${boxSvg}`);
@@ -323,8 +382,8 @@ function renderSequence(diagram) {
323
382
  const participants = requireObjectArray(diagram.participants, "/participants");
324
383
  const messages = requireObjectArray(diagram.messages, "/messages");
325
384
  const ids = new Set();
326
- const width = Math.max(760, 160 + participants.length * 170);
327
- const height = Math.max(420, 170 + messages.length * 82);
385
+ let width = Math.max(760, 160 + participants.length * 170);
386
+ let height = Math.max(420, 170 + messages.length * 82);
328
387
  const top = 74;
329
388
  const laneGap = (width - 160) / Math.max(1, participants.length - 1);
330
389
  /** @type {Map<string, Box>} */
@@ -349,25 +408,40 @@ function renderSequence(diagram) {
349
408
  });
350
409
  }
351
410
 
411
+ prepareBoxes(boxes, participants);
412
+ const gap = Math.max(280, ...[...boxes.values()].map(box=>box.width+80), ...messages.map((m) => layoutText(typeof m.label === "string" ? m.label : "", 260, 12, 16).width + 60));
413
+ width = Math.max(width, 160 + participants.length * gap);
414
+ [...boxes.values()].forEach((box, index) => { box.x = 80 + index * gap + gap / 2 - box.width / 2; });
415
+ let messageY = Math.max(...[...boxes.values()].map((box) => box.y + box.height)) + 72;
416
+ height = Math.max(height, messageY + messages.length * 108 + 80);
417
+
418
+
352
419
  /** @type {Connector[]} */
353
420
  const connectors = [];
354
- const lifelines = [...boxes.values()].map((box) => `<line x1="${centerX(box)}" y1="${box.y + box.height}" x2="${centerX(box)}" y2="${height - 56}" class="lifeline"/>`).join("\n");
421
+
355
422
  const messageSvg = messages.map((message, index) => {
356
423
  assertObject(message, `/messages/${index}`);
424
+ if (["activation","activate","deactivate","fragment","alt","loop","par","async"].some((key)=>key in message)) throw usageError(`/messages/${index}`,"Complex sequence semantics require the Mermaid route; do not simplify activation/fragments/async fields.");
357
425
  const from = requireId(message, "from", `/messages/${index}/from`);
358
426
  const to = requireId(message, "to", `/messages/${index}/to`);
359
427
  const fromBox = boxes.get(from);
360
428
  const toBox = boxes.get(to);
361
429
  if (!fromBox) throw usageError(`/messages/${index}/from`, `Unknown endpoint "${from}".`);
362
430
  if (!toBox) throw usageError(`/messages/${index}/to`, `Unknown endpoint "${to}".`);
363
- const y = top + 104 + index * 72;
431
+ const messageText = typeof message.label === "string" ? message.label : "";
432
+ const textLayout = layoutText(messageText, 190, 12, 16);
433
+ const y = messageY;
434
+ messageY += Math.max(72, textLayout.height + 56 + (from === to ? 32 : 0));
364
435
  /** @type {Array<[number, number]>} */
365
- const points = [[centerX(fromBox), y], [centerX(toBox), y]];
436
+ const points = from === to ? [[centerX(fromBox), y], [centerX(fromBox) + 64, y], [centerX(fromBox) + 64, y + 32], [centerX(fromBox), y + 32]] : [[centerX(fromBox), y], [centerX(toBox), y]];
437
+ occupiedRoutes.push(points);
366
438
  const variant = normalizeVariant(message.variant, `/messages/${index}/variant`);
367
- connectors.push({ id: `${from}-${to}-${index}`, from, to, points });
439
+ connectors.push({ id: `${from}-${to}-${index}`, from, to, points, kind: "sequence", self: from === to });
368
440
  return renderConnector(points, variant, typeof message.label === "string" ? message.label : "");
369
441
  }).join("\n");
370
442
  const boxSvg = [...boxes.values()].map(renderBox).join("\n");
443
+ height=Math.max(height,messageY+80);
444
+ const lifelines = [...boxes.values()].map((box) => `<line x1="${centerX(box)}" y1="${box.y + box.height}" x2="${centerX(box)}" y2="${height - 56}" class="lifeline"/>`).join("\n");
371
445
  const svg = wrapSvg(width, height, `${lifelines}\n${messageSvg}\n${boxSvg}`);
372
446
 
373
447
  return { svg, manifest: manifestFrom(width, height, [...boxes.values()], connectors) };
@@ -410,6 +484,8 @@ function renderDataflow(diagram) {
410
484
  });
411
485
  }
412
486
 
487
+ prepareBoxes(boxes, nodes);
488
+
413
489
  /** @type {Connector[]} */
414
490
  const connectors = [];
415
491
  const stageSvg = stages.map((stage, index) => {
@@ -463,22 +539,45 @@ function countStageBefore(nodes, endIndex, stage) {
463
539
  return count;
464
540
  }
465
541
 
542
+
543
+ /** @param {Map<string, Box>} boxes @param {Array<Record<string, unknown>>} sources */
544
+ function prepareBoxes(boxes, sources) {
545
+ for (const [id, box] of boxes) {
546
+ const source = sources.find((item) => item.id === id) ?? {};
547
+ const fitted = fitNodeText(box, { width: typeof source.width === "number", height: typeof source.height === "number" });
548
+ boxes.set(id, fitted.box);
549
+ qualityIssues.push(...fitted.issues);
550
+ }
551
+ routeObstacles = [...boxes.values()];
552
+ }
553
+
554
+ /** @param {string} id @param {string} owner @param {string} kind @param {string} text @param {import("./diagram-layout.mjs").TextLayout} layout @param {number} cx @param {number} top @param {string} cls */
555
+ function renderText(id, owner, kind, text, layout, cx, top, cls) {
556
+ textBounds.push({ id, owner, kind, text, lines: layout.lines, x: cx - layout.width / 2, y: top, width: layout.width, height: layout.height });
557
+ return `<text data-label-id="${escapeHtml(id)}" x="${cx}" y="${top + layout.fontSize}" class="${cls}" font-size="${layout.fontSize}" text-anchor="middle">${layout.lines.map((line, i) => `<tspan x="${cx}" dy="${i ? layout.lineHeight : 0}">${escapeHtml(line)}</tspan>`).join("")}</text>`;
558
+ }
559
+
466
560
  /**
467
561
  * @param {Box} box
468
562
  */
469
563
  function renderBox(box) {
470
- const labelLines = wrapLabel(box.label, 18).slice(0, 2);
471
564
  const shape = box.shape ?? "box";
472
565
  const isSemantic = isSemanticNodeType(box.type);
473
- const labelStartY = shape === "diamond" ? centerY(box) - (labelLines.length > 1 ? 5 : -3) : box.y + (isSemantic ? Math.max(30, box.height - 24) : 23);
474
- const labelSvg = labelLines.map((line, index) => `<text x="${centerX(box)}" y="${labelStartY + index * 13}" class="label" text-anchor="middle">${escapeHtml(line)}</text>`).join("\n");
475
- const sublabel = box.sublabel ? `<text x="${centerX(box)}" y="${box.y + box.height - 13}" class="sublabel" text-anchor="middle">${escapeHtml(box.sublabel)}</text>` : "";
476
- const actor = box.actor ? `<text x="${centerX(box)}" y="${box.y - 8}" class="actor" text-anchor="middle">${escapeHtml(box.actor)}</text>` : "";
477
- const step = box.step ? `<g class="step-badge"><circle cx="${box.x + 13}" cy="${box.y + 13}" r="10"/><text x="${box.x + 13}" y="${box.y + 17}" text-anchor="middle">${escapeHtml(box.step)}</text></g>` : "";
566
+ const available = shape === "diamond" ? box.width * 0.5 - 12 : (box.type === "queue" ? box.width - 64 : box.width - 32);
567
+ const main = layoutText(box.label, available);
568
+ const sub = layoutText(box.sublabel, available, 12, 16);
569
+ const total = main.height + (box.sublabel ? sub.height + 6 : 0);
570
+ const textTop = shape === "diamond" ? centerY(box) - total / 2 : box.y + (["database", "vectorstore"].includes(box.type) ? 30 : box.type === "queue" ? 20 : isSemantic ? 46 : box.actor ? 40 : 20);
571
+ const labelSvg = renderText(box.id + "-label", box.id, "node", box.label, main, centerX(box), textTop, "label");
572
+ const sublabel = box.sublabel ? renderText(box.id + "-sub", box.id, "node", box.sublabel, sub, centerX(box), textTop + main.height + 6, "sublabel") : "";
573
+ const actorLayout=layoutText(box.actor??"",box.width-32,12,16);
574
+ const actor = box.actor ? renderText(box.id+"-actor",box.id,"group",box.actor,actorLayout,centerX(box),box.y-actorLayout.height-12,"actor") : "";
575
+ const stepLayout=layoutText(box.step??"",Math.max(14,box.width-16),9,12);
576
+ const step = box.step ? `<g class="step-badge"><circle cx="${box.x + 13}" cy="${box.y + 13}" r="${Math.max(10,stepLayout.width/2+4)}"/>${renderText(box.id+"-step",box.id,"group",box.step,stepLayout,box.x+13,box.y+7,"step-label")}</g>` : "";
478
577
  const shapeSvg = renderSemanticShape(box) ?? (shape === "diamond"
479
578
  ? `<polygon points="${centerX(box)},${box.y} ${box.x + box.width},${centerY(box)} ${centerX(box)},${box.y + box.height} ${box.x},${centerY(box)}"/>`
480
579
  : `<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="${shape === "terminal" ? Math.round(box.height / 2) : 10}"/>`);
481
- return `<g class="node node-${box.type}">${actor}\n${shapeSvg}\n${step}\n${labelSvg}\n${sublabel}</g>`;
580
+ return `<g data-node-id="${escapeHtml(box.id)}" class="node node-${box.type}">${actor}\n${shapeSvg}\n${step}\n${labelSvg}\n${sublabel}</g>`;
482
581
  }
483
582
 
484
583
  /**
@@ -514,8 +613,9 @@ function renderSemanticShape(box) {
514
613
  return `<path d="M ${box.x} ${box.y} L ${box.x + box.width - fold} ${box.y} L ${box.x + box.width} ${box.y + fold} L ${box.x + box.width} ${box.y + box.height} L ${box.x} ${box.y + box.height} Z"/><path d="M ${box.x + box.width - fold} ${box.y} L ${box.x + box.width - fold} ${box.y + fold} L ${box.x + box.width} ${box.y + fold}" fill="none"/>`;
515
614
  }
516
615
  if (box.type === "queue") {
517
- const ry = Math.min(18, box.height / 3);
518
- return `<ellipse cx="${box.x + ry}" cy="${cy}" rx="${ry * 0.58}" ry="${ry}"/><rect x="${box.x + ry}" y="${cy - ry}" width="${box.width - ry * 2}" height="${ry * 2}" stroke="none"/><line x1="${box.x + ry}" y1="${cy - ry}" x2="${box.x + box.width - ry}" y2="${cy - ry}"/><line x1="${box.x + ry}" y1="${cy + ry}" x2="${box.x + box.width - ry}" y2="${cy + ry}"/><ellipse cx="${box.x + box.width - ry}" cy="${cy}" rx="${ry * 0.58}" ry="${ry}"/>`;
616
+ const ry = box.height / 2;
617
+ const end = Math.min(18, box.width / 6);
618
+ return `<ellipse cx="${box.x + end}" cy="${cy}" rx="${end}" ry="${ry}"/><rect x="${box.x + end}" y="${cy - ry}" width="${box.width - end * 2}" height="${ry * 2}" stroke="none"/><line x1="${box.x + end}" y1="${cy - ry}" x2="${box.x + box.width - end}" y2="${cy - ry}"/><line x1="${box.x + end}" y1="${cy + ry}" x2="${box.x + box.width - end}" y2="${cy + ry}"/><ellipse cx="${box.x + box.width - end}" cy="${cy}" rx="${end}" ry="${ry}"/>`;
519
619
  }
520
620
  if (box.type === "browser") {
521
621
  return `<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="10"/><rect x="${box.x}" y="${box.y}" width="${box.width}" height="20" rx="10" class="node-chrome"/><circle cx="${box.x + 14}" cy="${box.y + 10}" r="3" class="node-dot"/><circle cx="${box.x + 26}" cy="${box.y + 10}" r="3" class="node-dot"/><circle cx="${box.x + 38}" cy="${box.y + 10}" r="3" class="node-dot"/>`;
@@ -534,7 +634,7 @@ function renderSemanticShape(box) {
534
634
  * @param {Box} box
535
635
  */
536
636
  function renderGroup(box) {
537
- return `<g class="group group-${box.type}"><rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="14"/><text x="${box.x + 16}" y="${box.y + 26}" class="label muted">${escapeHtml(box.label)}</text></g>`;
637
+ return `<g class="group group-${box.type}"><rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="14"/>${renderText(box.id+"-group",box.id,"group",box.label,layoutText(box.label,box.width-32,12,16),box.x+box.width/2,box.y+10,"sublabel")}</g>`;
538
638
  }
539
639
 
540
640
  /**
@@ -544,8 +644,12 @@ function renderGroup(box) {
544
644
  */
545
645
  function renderConnector(points, variant, label, flow = "") {
546
646
  const pathData = points.map(([x, y], index) => `${index === 0 ? "M" : "L"} ${x} ${y}`).join(" ");
547
- const midpoint = points[Math.floor((points.length - 1) / 2)];
548
- const labelSvg = label ? `<text x="${midpoint[0]}" y="${midpoint[1] - 8}" class="edge-label" text-anchor="middle">${escapeHtml(label)}</text>` : "";
647
+ const textLayout = layoutText(label, 190, 12, 16);
648
+ const placed = placeEdgeLabel(points, textLayout, [...routeObstacles, ...textBounds]);
649
+ const id = `edge-label-${textBounds.length}`;
650
+ if (label) qualityIssues.push(...placed.issues.map((issue) => ({ ...issue, id })));
651
+ if(label) deferredLabels.push({id,label,points});
652
+ const labelSvg = label ? renderText(id, id, "edge", label, textLayout, placed.rect.x + placed.rect.width / 2, placed.rect.y, "edge-label") : "";
549
653
  const marker = flow ? `flow-${flow}` : (variant === "return" ? "default" : variant);
550
654
  return `<g class="edge edge-${variant}${flow ? ` flow-${flow}` : ""}"><path d="${pathData}" marker-end="url(#arrow-${marker})"/>\n${labelSvg}</g>`;
551
655
  }
@@ -556,7 +660,19 @@ function renderConnector(points, variant, label, flow = "") {
556
660
  * @param {string} body
557
661
  */
558
662
  function wrapSvg(width, height, body) {
559
- return `<svg class="tech-diagram" data-export-root="1" role="img" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg">
663
+ for(let i=textBounds.length-1;i>=0;i--) if(textBounds[i].kind === "edge") textBounds.splice(i,1);
664
+ for(const {id,label,points} of deferredLabels) {
665
+ const layout=layoutText(label,190,12,16);
666
+ const placed=placeEdgeLabel(points,layout,[...routeObstacles,...textBounds],occupiedRoutes);
667
+ qualityIssues.push(...placed.issues);
668
+ const replacement=renderText(id,id,"edge",label,layout,placed.rect.x+placed.rect.width/2,placed.rect.y,"edge-label");
669
+ body=body.replace(new RegExp('<text data-label-id="'+id+'"[^>]*>[\\s\\S]*?</text>'),replacement);
670
+ }
671
+
672
+ width = Math.ceil(Math.max(width, ...routeObstacles.map((b) => b.x + b.width + 40), ...textBounds.map((b) => b.x + b.width + 40), ...occupiedRoutes.flat().map((p) => p[0] + 40)));
673
+ height = Math.ceil(Math.max(height, ...routeObstacles.map((b) => b.y + b.height + 40), ...textBounds.map((b) => b.y + b.height + 40), ...occupiedRoutes.flat().map((p) => p[1] + 40)));
674
+ finalCanvas = { width, height };
675
+ return `<svg class="tech-diagram" data-theme="light" data-visual-style="default" data-export-root="1" role="img" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg">
560
676
  <defs>
561
677
  <marker id="arrow-default" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z"/></marker>
562
678
  <marker id="arrow-emphasis" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z"/></marker>
@@ -760,8 +876,8 @@ button {
760
876
  .node-glyph-outline, .node-glyph-line { fill: none; stroke: currentColor; }
761
877
  .node-chrome { fill: currentColor; opacity: 0.25; stroke: none; }
762
878
  .node-dot { fill: currentColor; stroke: none; opacity: 0.65; }
763
- .label { fill: var(--text); font-weight: 650; font-size: 12px; }
764
- .sublabel, .muted, .actor { fill: var(--muted); font-size: 10px; }
879
+ .label { fill: var(--text); font-weight: 650; font-size: 14px; }
880
+ .sublabel, .muted, .actor { fill: var(--muted); font-size: 12px; }
765
881
  .actor { font-weight: 650; }
766
882
  .step-badge circle { fill: var(--panel); stroke: currentColor; stroke-width: 1.3; }
767
883
  .step-badge text { fill: var(--text); font-size: 9px; font-weight: 750; }
@@ -775,7 +891,7 @@ button {
775
891
  .flow-write path { stroke: var(--flow-write); stroke-dasharray: 5 4; }
776
892
  .flow-async path { stroke: var(--flow-async); stroke-dasharray: 4 4; }
777
893
  .flow-feedback path { stroke: var(--flow-feedback); stroke-width: 2; }
778
- .edge-label { fill: var(--muted); font-size: 10px; paint-order: stroke; stroke: var(--surface); stroke-width: 5px; stroke-linejoin: round; }
894
+ .edge-label { fill: var(--muted); font-size: 12px; paint-order: stroke; stroke: var(--surface); stroke-width: 5px; stroke-linejoin: round; }
779
895
  .lifeline { stroke: color-mix(in srgb, var(--muted), transparent 48%); stroke-dasharray: 4 5; }
780
896
  .summary-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; margin-top: 12px; }
781
897
  .summary-card { background: var(--panel); border: 1px solid color-mix(in srgb, var(--muted), transparent 74%); border-radius: 8px; padding: 12px; }
@@ -823,16 +939,25 @@ ${summaryHtml}
823
939
  <script>
824
940
  const root = document.documentElement;
825
941
  const stored = localStorage.getItem("fec-tech-diagram-theme");
826
- if (stored === "dark" || stored === "light") root.dataset.theme = stored;
942
+ const diagramSvg = document.querySelector("[data-export-root]");
943
+ root.dataset.theme = stored === "dark" ? "dark" : "light";
944
+ diagramSvg.dataset.theme = root.dataset.theme;
945
+ diagramSvg.dataset.visualStyle = root.dataset.visualStyle;
827
946
  document.querySelector('[data-action="theme"]').addEventListener("click", () => {
828
947
  const next = root.dataset.theme === "light" ? "dark" : "light";
829
948
  root.dataset.theme = next;
949
+ diagramSvg.dataset.theme = next;
830
950
  localStorage.setItem("fec-tech-diagram-theme", next);
831
951
  });
832
952
  document.querySelector('[data-action="print"]').addEventListener("click", () => window.print());
833
953
  document.querySelector('[data-action="svg"]').addEventListener("click", () => {
834
954
  const svg = document.querySelector("[data-export-root]");
835
- const source = new XMLSerializer().serializeToString(svg);
955
+ const clone = svg.cloneNode(true);
956
+ const originals = [svg, ...svg.querySelectorAll("*")];
957
+ const copies = [clone, ...clone.querySelectorAll("*")];
958
+ const properties = ["fill","stroke","stroke-width","stroke-dasharray","font-family","font-size","font-weight","color","opacity","paint-order","text-anchor"];
959
+ originals.forEach((element,index) => { const computed=getComputedStyle(element); properties.forEach(property=>copies[index].style?.setProperty(property,computed.getPropertyValue(property))); });
960
+ const source = new XMLSerializer().serializeToString(clone);
836
961
  const blob = new Blob([source], { type: "image/svg+xml" });
837
962
  const link = document.createElement("a");
838
963
  link.href = URL.createObjectURL(blob);
@@ -866,10 +991,20 @@ ${summary.map((card) => ` <article class="summary-card summary-${card.type}">
866
991
  * @param {Connector[]} connectors
867
992
  */
868
993
  function manifestFrom(width, height, boxes, connectors) {
994
+ for(const connector of connectors) if(connector.points.some(([x,y])=>x<0||y<0)) qualityIssues.push({code:"connector-out-of-bounds",id:connector.id,message:`Connector "${connector.id}" has negative explicit coordinates.`});
995
+ const nodes = boxes.filter((box) => box.kind !== "group");
996
+ for (const box of boxes) if (box.x < 0 || box.y < 0) qualityIssues.push({code:"box-out-of-bounds",id:box.id,message:`Box "${box.id}" has negative coordinates.`});
997
+ for (let i=0;i<nodes.length;i++) for (let j=i+1;j<nodes.length;j++) if (overlaps(nodes[i],nodes[j])) qualityIssues.push({code:"box-overlap",id:nodes[i].id,message:`Nodes "${nodes[i].id}" and "${nodes[j].id}" overlap.`});
869
998
  return {
870
- canvas: { width, height },
871
- boxes: boxes.map(({ id, x, y, width: boxWidth, height: boxHeight, label }) => ({ id, x, y, width: boxWidth, height: boxHeight, label })),
999
+ canvas: finalCanvas.width ? finalCanvas : { width, height },
1000
+ boxes: boxes.map(({ id, x, y, width: boxWidth, height: boxHeight, label, kind }) => ({ id, x, y, width: boxWidth, height: boxHeight, label, kind })),
1001
+ groups: boxes.filter((box) => box.kind === "group").map((box) => ({ ...box })),
872
1002
  connectors,
1003
+ labels: textBounds,
1004
+ coordinateSpace: "svg",
1005
+ scale: 1,
1006
+ measurement: "estimated",
1007
+ issues: qualityIssues,
873
1008
  };
874
1009
  }
875
1010
 
@@ -905,14 +1040,15 @@ function routeWithWaypoints(from, to, waypoints, pointer) {
905
1040
  if (!Array.isArray(waypoints)) throw usageError(pointer, "Expected array of [x, y] waypoints.");
906
1041
  /** @type {Array<[number, number]>} */
907
1042
  const parsed = waypoints.map((point, index) => {
908
- if (!Array.isArray(point) || point.length !== 2 || typeof point[0] !== "number" || typeof point[1] !== "number") {
1043
+ if (!Array.isArray(point) || point.length !== 2 || typeof point[0] !== "number" || typeof point[1] !== "number" || !Number.isFinite(point[0]) || !Number.isFinite(point[1])) {
909
1044
  throw usageError(`${pointer}/${index}`, "Expected [x, y] number tuple.");
910
1045
  }
911
1046
  return [point[0], point[1]];
912
1047
  });
913
- const firstTarget = parsed[0] ?? [centerX(to), centerY(to)];
914
- const lastTarget = parsed[parsed.length - 1] ?? [centerX(from), centerY(from)];
915
- return [edgePointToward(from, firstTarget), ...parsed, edgePointToward(to, lastTarget)];
1048
+ const result = routeConnector(from, to, routeObstacles.filter((box) => box.id !== from.id && box.id !== to.id), occupiedRoutes, parsed);
1049
+ qualityIssues.push(...result.issues);
1050
+ occupiedRoutes.push(result.points);
1051
+ return result.points;
916
1052
  }
917
1053
 
918
1054
  /**
@@ -1006,11 +1142,13 @@ function normalizeLegend(legend, boxes) {
1006
1142
  * @param {number} x
1007
1143
  * @param {number} y
1008
1144
  */
1009
- function renderArchitectureLegend(items, x, y) {
1145
+ function renderArchitectureLegend(items, x, y, columns = 4) {
1010
1146
  if (items.length === 0) return "";
1011
1147
  const itemSvg = items.map((item, index) => {
1012
- const itemX = x + index * 118;
1013
- return `<g class="node node-${item.type}"><rect x="${itemX}" y="${y + 16}" width="16" height="10" rx="2"/><text x="${itemX + 24}" y="${y + 25}" class="sublabel">${escapeHtml(item.label)}</text></g>`;
1148
+ const itemX = x + (index % columns) * 200;
1149
+ const itemY = y + Math.floor(index / columns) * 72;
1150
+ const text = layoutText(item.label,160,12,16);
1151
+ return `<g class="node node-${item.type}"><rect x="${itemX}" y="${itemY + 16}" width="16" height="10" rx="2"/>${renderText("legend-"+index,"legend","group",item.label,text,itemX+24+text.width/2,itemY+14,"sublabel")}</g>`;
1014
1152
  }).join("\n");
1015
1153
  return `<g class="legend"><text x="${x}" y="${y}" class="label">Legend</text>\n${itemSvg}</g>`;
1016
1154
  }
@@ -1020,11 +1158,13 @@ function renderArchitectureLegend(items, x, y) {
1020
1158
  * @param {number} x
1021
1159
  * @param {number} y
1022
1160
  */
1023
- function renderFlowLegend(items, x, y) {
1161
+ function renderFlowLegend(items, x, y, columns = 4) {
1024
1162
  if (items.length === 0) return "";
1025
1163
  const itemSvg = items.map((item, index) => {
1026
- const itemX = x + index * 128;
1027
- return `<g class="edge flow-${item.type}"><path d="M ${itemX} ${y + 22} L ${itemX + 28} ${y + 22}" marker-end="url(#arrow-flow-${item.type})"/><text x="${itemX + 38}" y="${y + 26}" class="sublabel">${escapeHtml(item.label)}</text></g>`;
1164
+ const itemX = x + (index % columns) * 200;
1165
+ const itemY = y + Math.floor(index / columns) * 72;
1166
+ const text = layoutText(item.label,152,12,16);
1167
+ return `<g class="edge flow-${item.type}"><path d="M ${itemX} ${itemY + 22} L ${itemX + 28} ${itemY + 22}" marker-end="url(#arrow-flow-${item.type})"/>${renderText("flow-legend-"+index,"flow-legend","group",item.label,text,itemX+38+text.width/2,itemY+14,"sublabel")}</g>`;
1028
1168
  }).join("\n");
1029
1169
  return `<g class="flow-legend"><text x="${x}" y="${y}" class="label">Flow Legend</text>\n${itemSvg}</g>`;
1030
1170
  }
@@ -1115,13 +1255,10 @@ function normalizeSummary(summary) {
1115
1255
  * @returns {Array<[number, number]>}
1116
1256
  */
1117
1257
  function routeBoxes(from, to) {
1118
- const start = [centerX(from), centerY(from)];
1119
- const end = [centerX(to), centerY(to)];
1120
- if (Math.abs(start[1] - end[1]) < 18) {
1121
- return [[from.x + from.width, start[1]], [to.x, end[1]]];
1122
- }
1123
- const midX = Math.round((start[0] + end[0]) / 2);
1124
- return [[start[0], start[1]], [midX, start[1]], [midX, end[1]], [end[0], end[1]]];
1258
+ const result = routeConnector(from, to, routeObstacles.filter((box) => box.id !== from.id && box.id !== to.id), occupiedRoutes);
1259
+ qualityIssues.push(...result.issues);
1260
+ occupiedRoutes.push(result.points);
1261
+ return result.points;
1125
1262
  }
1126
1263
 
1127
1264
  /**
@@ -1341,6 +1478,7 @@ function printReport(report, format) {
1341
1478
  * type: string;
1342
1479
  * actor?: string;
1343
1480
  * step?: string;
1481
+ * kind?: string;
1344
1482
  * shape?: "box" | "diamond" | "terminal";
1345
1483
  * }} Box
1346
1484
  *
@@ -1348,6 +1486,8 @@ function printReport(report, format) {
1348
1486
  * id: string;
1349
1487
  * from: string;
1350
1488
  * to: string;
1489
+ * kind?: string;
1490
+ * self?: boolean;
1351
1491
  * points: Array<[number, number]>;
1352
1492
  * }} Connector
1353
1493
  *
@@ -1,10 +1,12 @@
1
1
  ---
2
- name: fec-typescript-project-standard
3
- description: 用于创建、配置、审查或调试前端应用、库、SDK、CLI、monorepo 包中的 TypeScript 项目规范,包括 tsconfig、strictness、module/moduleResolution、路径别名、project references、声明文件、package exports、公共 API 类型、DTO、高级泛型、判别联合、类型守卫、类型收窄或类型级回归。React/Vue/Next/Nuxt 组件架构优先使用框架项目 skill;中文触发词包括 TypeScript 项目规范、TS 项目规范、TypeScript 类型安全、类型建模、泛型、判别联合、类型收窄、tsconfig、声明文件。
2
+ name: cc-typescript-project-standard
3
+ description: 用于TypeScript 工程配置、模块解析、公共类型、声明文件、包导出、类型收窄或泛型契约需要设计审查,适用于应用、SDK、CLI、桌面进程与库。
4
4
  ---
5
5
 
6
6
  # TypeScript 项目规范
7
7
 
8
+ 本入口面向库、CLI、桌面核心及服务中的语言工程;应用角色由实际子工程证据决定,不由前端/后端产品名决定。
9
+
8
10
  ## 用途
9
11
 
10
12
  统一 TypeScript 层的工程配置、类型边界和发布产物规则。适用于前端应用、组件库、SDK、CLI、monorepo package 和纯 TypeScript 工具库,但不接管 React、Vue、Next.js、Nuxt 或 Vite 的框架架构职责。
@@ -19,7 +21,7 @@ description: 用于创建、配置、审查或调试前端应用、库、SDK、C
19
21
  - React、Vue、Next.js、Nuxt 等框架的组件架构、路由组织和状态管理归对应框架 skill;本流程只处理跨框架 TypeScript 契约和工程边界。
20
22
 
21
23
  2. 收敛 `tsconfig`
22
- - 默认开启 `strict`,不要为通过构建关闭 `noImplicitAny`、`strictNullChecks` 或 `exactOptionalPropertyTypes` 等关键约束。
24
+ - 新代码优先 `strict` 并保留已有检查,不为掩盖缺陷关闭 `noImplicitAny` 或 `strictNullChecks`。`exactOptionalPropertyTypes` 是独立选项;有依据时以局部、兼容迁移引入更严格配置。
23
25
  - 按运行环境选择 `target`、`lib`、`module` 和 `moduleResolution`;浏览器应用、Node 脚本、库包不要共用一份含混配置。
24
26
  - 将基础配置、应用配置、测试配置和构建声明配置拆开,避免测试全局类型污染生产代码。
25
27
  - 路径别名必须同时被 TypeScript、bundler、test runner 和发布产物理解;库包不得发布无法解析的源码别名。
@@ -43,7 +45,7 @@ description: 用于创建、配置、审查或调试前端应用、库、SDK、C
43
45
 
44
46
  ## 约束
45
47
 
46
- - 不用 `skipLibCheck`、`any`、无守卫非空断言或宽泛 `as` 掩盖真实边界问题。
48
+ - 不用 `any`、无守卫非空断言或宽泛 `as` 掩盖未经验证的边界。合理的 `skipLibCheck` 依赖政策与检查自身公共API有别,需记录其限制。
47
49
  - 不在应用代码中依赖发布包私有深层路径。
48
50
  - 不把框架目录结构、组件分层、路由组织或状态管理决策放进本流程;这些交给对应框架或专项流程。
49
51
  - 不让生成类型、测试类型或 Node-only 类型污染浏览器运行代码。
@@ -52,3 +54,7 @@ description: 用于创建、配置、审查或调试前端应用、库、SDK、C
52
54
  ## 预期输出
53
55
 
54
56
  输出应包含 TypeScript 上下文判断、关键 `tsconfig`/package 类型入口建议、类型边界方案、声明文件或 public API 风险、验证命令。完成后项目应能独立 typecheck,公开类型可被消费方解析,类型安全问题有明确收窄或建模方案。
57
+
58
+ ## 工程实践
59
+
60
+ 按当前任务读取[本入口工程细则](references/engineering-practices.md),再按链接选择公共原则。规则级别与例外以实际项目契约为准;不因产品前后端标签限制语言或职责。
@@ -0,0 +1,7 @@
1
+ # 外部输入边界 — EP-TS-01
2
+
3
+ 将此目录复制到可写临时位置。样例自有Node >=22.18目标(原生类型擦除),不升级父项目。显式准备:pnpm install --ignore-scripts --frozen-lockfile,然后pnpm typecheck。PowerShell设$env:CRAFT_ENGINEERING_DEFECTIVE为1,运行pnpm test,非法输入命名断言应失败;设为0或移除变量后同组两个测试通过。POSIX可在测试命令前设置同名环境变量。
4
+
5
+ 回调记录校验前后的真实副作用,缺陷分支故意以断言替代校验;默认受保护。这里不验证付款服务、浏览器、异步状态及声明发布。仅依赖本目录源码和已声明工具,node_modules/build/log应留在可写副本。
6
+
7
+ [Node.js 类型擦除历史与限制](https://nodejs.org/api/typescript.html):运行时类型擦除与显式 TypeScript 类型检查分开。
@@ -0,0 +1,16 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { acceptAmount } from "./input.ts";
4
+
5
+ test("EP-TS-01 rejects invalid input before any effect", () => {
6
+ const effects: number[] = [];
7
+ for (const input of [{ amount: "10" }, { amount: -1 }, { amount: Number.MAX_SAFE_INTEGER + 1 }, null]) {
8
+ assert.throws(() => acceptAmount(input, amount => effects.push(amount)), /invalid amount/);
9
+ assert.deepEqual(effects, []);
10
+ }
11
+ });
12
+ test("EP-TS-01 accepts a valid input exactly once", () => {
13
+ const effects: number[] = [];
14
+ acceptAmount({ amount: 10 }, amount => effects.push(amount));
15
+ assert.deepEqual(effects, [10]);
16
+ });
@@ -0,0 +1,12 @@
1
+ /** Test switch only; normal use always validates the external boundary. */
2
+ export function acceptAmount(value: unknown, effect: (amount: number) => void): void {
3
+ if (process.env.CRAFT_ENGINEERING_DEFECTIVE === "1") {
4
+ effect((value as { amount: number }).amount);
5
+ return;
6
+ }
7
+ if (typeof value !== "object" || value === null || !("amount" in value)
8
+ || typeof value.amount !== "number" || !Number.isSafeInteger(value.amount) || value.amount <= 0) {
9
+ throw new TypeError("invalid amount");
10
+ }
11
+ effect(value.amount);
12
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "engineering-typescript-boundary-example",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "engines": { "node": ">=22.18.0" },
7
+ "scripts": {
8
+ "typecheck": "tsc --noEmit",
9
+ "test": "node --experimental-strip-types --test --test-reporter=tap boundary.test.ts"
10
+ },
11
+ "devDependencies": { "typescript": "5.9.3", "@types/node": "22.20.5" }
12
+ }
@@ -0,0 +1,39 @@
1
+ lockfileVersion: '9.0'
2
+
3
+ settings:
4
+ autoInstallPeers: true
5
+ excludeLinksFromLockfile: false
6
+
7
+ importers:
8
+
9
+ .:
10
+ devDependencies:
11
+ '@types/node':
12
+ specifier: 22.20.5
13
+ version: 22.20.5
14
+ typescript:
15
+ specifier: 5.9.3
16
+ version: 5.9.3
17
+
18
+ packages:
19
+
20
+ '@types/node@22.20.5':
21
+ resolution: {integrity: sha512-U2+DNr+wSjpsTS/wZGYHq7GcwfuSmKiKvoPvK22zwTlRhU91yOniN4qRR5KhIjvif7ysw/dz/hKmfDH0Ris4aA==}
22
+
23
+ typescript@5.9.3:
24
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
25
+ engines: {node: '>=14.17'}
26
+ hasBin: true
27
+
28
+ undici-types@6.21.0:
29
+ resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
30
+
31
+ snapshots:
32
+
33
+ '@types/node@22.20.5':
34
+ dependencies:
35
+ undici-types: 6.21.0
36
+
37
+ typescript@5.9.3: {}
38
+
39
+ undici-types@6.21.0: {}
@@ -0,0 +1,8 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022", "module": "NodeNext", "moduleResolution": "NodeNext",
4
+ "strict": true, "noEmit": true, "allowImportingTsExtensions": true,
5
+ "types": ["node"]
6
+ },
7
+ "include": ["*.ts"]
8
+ }