@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: Use when creating, configuring, reviewing, or debugging TypeScript project standards across frontend apps, libraries, SDKs, CLIs, monorepo packages, tsconfig, strictness, module/moduleResolution, path aliases, project references, declaration files, package exports, public API types, DTOs, advanced generics, discriminated unions, type guards, type narrowing, or type-level regressions. Prefer framework project skills for React/Vue/Next/Nuxt component architecture; Chinese triggers include TypeScript project specification, TS project specification, TypeScript type safety, type modeling, generics, discriminative unions, type narrowing, tsconfig, declaration files.
2
+ name: cc-typescript-project-standard
3
+ description: Use when TypeScript configuration, module resolution, public API types, declarations, package exports, narrowing or generic contracts need design or review in applications, SDKs, CLI tools, desktop processes or libraries.
4
4
  ---
5
5
 
6
6
  # TypeScript project specifications
7
7
 
8
+ Apply to libraries, CLI tools, desktop cores and services. Determine the application role from the actual project; a frontend/backend product name does not constrain the language.
9
+
8
10
  ## Purpose
9
11
 
10
12
  Unify project configuration, type boundaries, and release product rules for the TypeScript layer. Works with front-end applications, component libraries, SDKs, CLIs, monorepo packages, and pure TypeScript tool libraries, but does not take over the framework architecture responsibilities of React, Vue, Next.js, Nuxt, or Vite.
@@ -19,7 +21,7 @@ Unify project configuration, type boundaries, and release product rules for the
19
21
  - The component architecture, routing organization, and state management of frameworks such as React, Vue, Next.js, and Nuxt belong to the corresponding framework skills; this process only deals with cross-framework TypeScript contracts and project boundaries.
20
22
 
21
23
  2. Convergence `tsconfig`
22
- - Turn on `strict` by default, do not turn off key constraints such as `noImplicitAny`, `strictNullChecks` or `exactOptionalPropertyTypes` for pass builds.
24
+ - Prefer `strict` for new code and preserve existing checks; do not disable `noImplicitAny` or `strictNullChecks` merely to hide a defect. `exactOptionalPropertyTypes` is a separate option; introduce stricter settings through a scoped, compatible migration when justified.
23
25
  - Select `target`, `lib`, `module` and `moduleResolution` according to the running environment; browser applications, Node scripts, and library packages should not share an ambiguous configuration.
24
26
  - Separate basic configuration, application configuration, test configuration and build declaration configuration to avoid testing global types from polluting production code.
25
27
  - Path aliases must be understood by TypeScript, bundler, test runner, and published products at the same time; library packages must not publish source code aliases that cannot be resolved.
@@ -43,7 +45,7 @@ Unify project configuration, type boundaries, and release product rules for the
43
45
 
44
46
  ## Constraints
45
47
 
46
- - Don't use `skipLibCheck`, `any`, unguarded non-null assertions or the wide `as` to mask real boundary issues.
48
+ - Do not use `any`, unguarded non-null assertions or broad `as` to conceal an unverified boundary. A justified `skipLibCheck` dependency policy is separate from checking your own public API; record its limits.
47
49
  - Do not rely on release package private deep paths in application code.
48
50
  - Do not put framework directory structure, component layering, routing organization or state management decisions into this process; these are left to the corresponding framework or dedicated process.
49
51
  - Don't pollute browser running code with generated, test, or Node-only types.
@@ -52,3 +54,7 @@ Unify project configuration, type boundaries, and release product rules for the
52
54
  ## Expected Output
53
55
 
54
56
  The output should include TypeScript context determinations, key `tsconfig`/package type entry suggestions, type boundary schemes, declaration file or public API risks, and verification commands. After completion, the project should be able to independently typecheck, public types can be parsed by consumers, and type safety issues should have clear narrowing or modeling solutions.
57
+
58
+ ## Engineering practices
59
+
60
+ Read the [local engineering decisions](references/engineering-practices.md) for this task and follow their links to relevant shared principles. Apply levels and exceptions against actual project contracts; product frontend/backend labels do not constrain language or role.
@@ -0,0 +1,9 @@
1
+ # External input boundary — EP-TS-01
2
+
3
+ Use a separate writable copy of this directory. This example targets Node >=22.18 for native type stripping, with explicitly declared TypeScript and Node types; it does not change the parent project's supported versions.
4
+
5
+ Prepare once: `pnpm install --ignore-scripts --frozen-lockfile`. Then `pnpm typecheck` and `pnpm test`. In PowerShell set `$env:CRAFT_ENGINEERING_DEFECTIVE='1'` and run the same test: the named invalid-input assertion must fail after successful preparation/type checking. Set it to `'0'` (or remove it) and rerun: both tests pass. POSIX: prefix the test command with `CRAFT_ENGINEERING_DEFECTIVE=1` or `=0`.
6
+
7
+ The callback records real effects before/after validation; the defective branch deliberately replaces validation with a cast. Default behavior is protected. This does not test a payment backend, browser, async state or declaration publishing; those require their own consumer checks. No test imports parent-repository source. Install/build output belongs only to the writable copy.
8
+
9
+ [Node.js type-stripping history and limitations](https://nodejs.org/api/typescript.html): runtime stripping is separate from the explicit TypeScript type check.
@@ -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: {}