@givolt/i3-composer-agent 3.0.0 → 3.1.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 (494) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude/commands/i3-ui-demo.md +21 -0
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/.claude-plugin/plugin.json +1 -1
  5. package/.codex-plugin/plugin.json +2 -2
  6. package/.gemini/commands/i3-ui-demo.toml +21 -0
  7. package/README.md +10 -8
  8. package/bin/i3-composer-agent.cjs +38 -44
  9. package/bin/install.cjs +15 -3
  10. package/bin/native-layout.cjs +2 -1
  11. package/bin/native-migration.cjs +19 -2
  12. package/bin/retired-sop-fingerprints.json +213 -0
  13. package/bin/wizard.cjs +7 -18
  14. package/commands/i3-ui-demo.toml +21 -0
  15. package/docs/codebuddy-setup.md +20 -23
  16. package/docs/codex-setup.md +2 -2
  17. package/docs/comparison.md +131 -0
  18. package/docs/developer-onboarding.md +143 -0
  19. package/docs/opencode-setup.md +1 -1
  20. package/docs/other-hosts.md +2 -2
  21. package/docs/skill-anatomy.md +211 -0
  22. package/docs/upstream-repository/AGENTS.md +92 -0
  23. package/docs/upstream-repository/CLAUDE.md +60 -0
  24. package/docs/upstream-repository/CONTRIBUTING.md +137 -0
  25. package/docs/upstream-repository/README.md +8 -0
  26. package/docs/upstream-repository/gitattributes.txt +1 -0
  27. package/docs/upstream-repository/gitignore.txt +10 -0
  28. package/docs/upstream-repository/manifest.json +71 -0
  29. package/docs/upstream-repository/opencode-skills.link +1 -0
  30. package/docs/upstream-repository/skill-gap.yml +80 -0
  31. package/docs/upstream-repository/skills-contributing.md +15 -0
  32. package/docs/upstream-repository/test-plugin-install.yml +167 -0
  33. package/docs/workbuddy-setup.md +7 -10
  34. package/evals/cases/i3-ui-demo.json +98 -0
  35. package/evals/fixtures/i3-ui-demo/asset-management.md +25 -0
  36. package/evals/zh-CN/cases/i3-ui-demo.json +103 -0
  37. package/hooks/PROTOTYPE.md +16 -8
  38. package/hooks/i3-prototype.cjs +4 -10
  39. package/hooks/manage.cjs +30 -31
  40. package/package.json +42 -5
  41. package/plugin.json +1 -1
  42. package/scripts/ui-demo-dependencies-test.js +228 -0
  43. package/scripts/ui-demo-mcp-test.js +95 -0
  44. package/scripts/ui-demo-test.js +170 -0
  45. package/scripts/ui-prototype-execution-runtime-test.js +1 -1
  46. package/scripts/ui-prototype-native-test.js +25 -3
  47. package/skills/i3-enterprise-sop/SKILL.md +15 -15
  48. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/ad/assets-manifest.json +9 -29
  49. package/{references/enterprise-sop-resources/ad/README.md → skills/i3-enterprise-sop/references/ad/readme.md} +4 -4
  50. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/assets-manifest.json +64 -33
  51. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/brd/assets-manifest.json +9 -20
  52. package/{references/enterprise-sop-resources/brd/README.md → skills/i3-enterprise-sop/references/brd/readme.md} +4 -4
  53. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/codebuddy-project-guide.md +1 -1
  54. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/controlled_handoff.py +52 -7
  55. package/{references/engineering-skeleton-resources → skills/i3-enterprise-sop/references/engineering-skeleton}/adoption.md +1 -1
  56. package/{references/engineering-skeleton-resources/README.md → skills/i3-enterprise-sop/references/engineering-skeleton/readme.md} +2 -2
  57. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/handoff-contract.md +2 -2
  58. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/lifecycle-contract.md +1 -1
  59. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/plan-handoff.md +3 -3
  60. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/prd/assets-manifest.json +20 -26
  61. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/prd/prompts/01-generate.md +1 -1
  62. package/{references/enterprise-sop-resources/prd/README.md → skills/i3-enterprise-sop/references/prd/readme.md} +4 -4
  63. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/prd/template-contracts.md +3 -3
  64. package/{references/enterprise-sop-resources/prd/templates/AD.md → skills/i3-enterprise-sop/references/prd/templates/ad.md} +1 -1
  65. package/{references/enterprise-sop-resources/prd/templates/PRD.md → skills/i3-enterprise-sop/references/prd/templates/prd.md} +1 -1
  66. package/{references/enterprise-sop-resources/README.md → skills/i3-enterprise-sop/references/readme.md} +14 -12
  67. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/recovery-contract.md +2 -2
  68. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/stages.json +16 -7
  69. package/skills/i3-enterprise-sop/references/technical-baseline/assets-manifest.json +84 -0
  70. package/{references/enterprise-sop-resources/technical-baseline/baselines//344/274/201/344/270/232/345/272/224/347/224/250-/346/212/200/346/234/257/350/247/204/347/272/246_v0.0.2.md → skills/i3-enterprise-sop/references/technical-baseline/baselines/enterprise-application-technical-baseline-v0-0-4.md} +122 -37
  71. package/{references/enterprise-sop-resources/technical-baseline/README.md → skills/i3-enterprise-sop/references/technical-baseline/readme.md} +8 -8
  72. package/{references/enterprise-sop-resources/technical-baseline/templates/TECHNICAL-BASELINE.md → skills/i3-enterprise-sop/references/technical-baseline/templates/technical-baseline.md} +1 -1
  73. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/template-contracts.md +7 -7
  74. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/testcase/assets-manifest.json +9 -29
  75. package/{references/enterprise-sop-resources/testcase/README.md → skills/i3-enterprise-sop/references/testcase/readme.md} +4 -4
  76. package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/verification/review_handoff.py +3 -3
  77. package/skills/i3-ui-demo/SKILL.md +234 -0
  78. package/skills/i3-ui-demo/assets/antdv-build/package-lock.json +3363 -0
  79. package/skills/i3-ui-demo/assets/antdv-build/package.json +28 -0
  80. package/skills/i3-ui-demo/assets/design-source.json +11 -0
  81. package/skills/i3-ui-demo/assets/host-targets.json +739 -0
  82. package/skills/i3-ui-demo/assets/official-files.json +76 -0
  83. package/skills/i3-ui-demo/assets/starter/index.html +11 -0
  84. package/skills/i3-ui-demo/assets/starter/package-lock.json +2299 -0
  85. package/skills/i3-ui-demo/assets/starter/package.json +28 -0
  86. package/skills/i3-ui-demo/assets/starter/provenance.json +14 -0
  87. package/skills/i3-ui-demo/assets/starter/public/prototype-config.json +22 -0
  88. package/skills/i3-ui-demo/assets/starter/src/App.vue +64 -0
  89. package/skills/i3-ui-demo/assets/starter/src/PrototypeShell.vue +59 -0
  90. package/skills/i3-ui-demo/assets/starter/src/config.ts +23 -0
  91. package/skills/i3-ui-demo/assets/starter/src/domain/presentation.ts +30 -0
  92. package/skills/i3-ui-demo/assets/starter/src/domain/theme.ts +25 -0
  93. package/skills/i3-ui-demo/assets/starter/src/main.ts +18 -0
  94. package/skills/i3-ui-demo/assets/starter/src/style.css +26 -0
  95. package/skills/i3-ui-demo/assets/starter/tests/presentation.test.ts +23 -0
  96. package/skills/i3-ui-demo/assets/starter/tests/theme.test.ts +26 -0
  97. package/skills/i3-ui-demo/assets/starter/tsconfig.json +15 -0
  98. package/skills/i3-ui-demo/assets/starter/vite.config.ts +4 -0
  99. package/skills/i3-ui-demo/assets/templates/enterprise-admin/capability-definition.json +1395 -0
  100. package/skills/i3-ui-demo/assets/templates/enterprise-admin/component-inventory.json +707 -0
  101. package/skills/i3-ui-demo/assets/templates/enterprise-admin/design-system.md +26 -0
  102. package/skills/i3-ui-demo/assets/templates/enterprise-admin/generation.json +49 -0
  103. package/skills/i3-ui-demo/assets/templates/enterprise-admin/index.html +534 -0
  104. package/skills/i3-ui-demo/assets/templates/enterprise-admin/manifest.json +9 -0
  105. package/skills/i3-ui-demo/assets/templates/enterprise-admin/offline-build.json +265 -0
  106. package/skills/i3-ui-demo/assets/templates/enterprise-admin/offline.js +8888 -0
  107. package/skills/i3-ui-demo/assets/templates/enterprise-admin/origin.json +344 -0
  108. package/skills/i3-ui-demo/assets/templates/enterprise-admin/preset.json +928 -0
  109. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/app.js +22 -0
  110. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/assets/empty.svg +1 -0
  111. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/assets/reference-styles.json +1 -0
  112. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/assets/result-403.svg +1 -0
  113. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/assets/result-404.svg +1 -0
  114. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/assets-manifest.json +334 -0
  115. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/baseline.json +173 -0
  116. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/conversion.md +30 -0
  117. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/credits.md +17 -0
  118. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/design-tokens.json +881 -0
  119. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/index.html +28 -0
  120. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/licenses/@qin-ui-antdv-next-pro.txt +9 -0
  121. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/licenses/ant-design-icons.txt +22 -0
  122. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/licenses/antdv-next.txt +21 -0
  123. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/package.json +12 -0
  124. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/browser-routes.json +298 -0
  125. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/coverage.json +180 -0
  126. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/integrity.json +13 -0
  127. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/keyboard.json +11 -0
  128. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/responsive.json +125 -0
  129. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/review.md +51 -0
  130. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/rules.log +150 -0
  131. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/flow-editor-html.png +0 -0
  132. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/flow-editor-original.png +0 -0
  133. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/intent-create-html.png +0 -0
  134. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/intent-create-original.png +0 -0
  135. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/models-html.png +0 -0
  136. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/models-original.png +0 -0
  137. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/workbench-html.png +0 -0
  138. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/workbench-original.png +0 -0
  139. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/selection.json +9 -0
  140. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/visual-comparison.json +342 -0
  141. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/readme.md +73 -0
  142. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/reference.md +59 -0
  143. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/routes.json +178 -0
  144. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/controls.js +99 -0
  145. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/dialogs.js +54 -0
  146. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/dom.js +264 -0
  147. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/forms.js +47 -0
  148. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/icons.js +41 -0
  149. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/layout.js +47 -0
  150. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/router.js +63 -0
  151. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/state.js +90 -0
  152. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/table.js +41 -0
  153. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/widgets.js +8 -0
  154. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/AgentDetail.html +3 -0
  155. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/AgentDetail.js +36 -0
  156. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/AgentEditor.html +2 -0
  157. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/AgentEditor.js +51 -0
  158. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/AgentsPage.html +3 -0
  159. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/AgentsPage.js +48 -0
  160. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/CheckResults.html +2 -0
  161. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/CheckResults.js +6 -0
  162. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/ResourcePicker.html +2 -0
  163. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/ResourcePicker.js +13 -0
  164. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/data.js +24 -0
  165. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/domain.js +32 -0
  166. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/registry.js +25 -0
  167. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/store.js +85 -0
  168. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentClose.html +2 -0
  169. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentClose.js +17 -0
  170. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentCreate.html +2 -0
  171. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentCreate.js +66 -0
  172. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentDecisions.html +3 -0
  173. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentDecisions.js +38 -0
  174. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentDetail.html +2 -0
  175. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentDetail.js +66 -0
  176. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentDocument.html +2 -0
  177. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentDocument.js +5 -0
  178. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentHeader.html +2 -0
  179. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentHeader.js +12 -0
  180. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentHistory.html +2 -0
  181. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentHistory.js +11 -0
  182. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentList.html +2 -0
  183. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentList.js +116 -0
  184. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentReplan.html +2 -0
  185. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentReplan.js +32 -0
  186. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentRevision.html +2 -0
  187. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentRevision.js +49 -0
  188. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentSummary.html +2 -0
  189. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentSummary.js +10 -0
  190. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentWorkspace.html +2 -0
  191. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentWorkspace.js +77 -0
  192. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/data.js +60 -0
  193. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/domain.js +105 -0
  194. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/store.js +212 -0
  195. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/AuditPanel.html +2 -0
  196. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/AuditPanel.js +18 -0
  197. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelDetail.html +2 -0
  198. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelDetail.js +23 -0
  199. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelEditor.html +2 -0
  200. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelEditor.js +78 -0
  201. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelGrant.html +2 -0
  202. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelGrant.js +55 -0
  203. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelReferences.html +2 -0
  204. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelReferences.js +26 -0
  205. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelRelease.html +2 -0
  206. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelRelease.js +38 -0
  207. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelStatus.html +2 -0
  208. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelStatus.js +7 -0
  209. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelTable.html +2 -0
  210. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelTable.js +72 -0
  211. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelTester.html +2 -0
  212. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelTester.js +46 -0
  213. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelsPage.html +2 -0
  214. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelsPage.js +52 -0
  215. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/RowActions.html +2 -0
  216. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/RowActions.js +19 -0
  217. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/UsagePanel.html +2 -0
  218. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/UsagePanel.js +30 -0
  219. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/data.js +48 -0
  220. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/domain.js +39 -0
  221. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/store.js +129 -0
  222. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/IncidentDetail.html +4 -0
  223. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/IncidentDetail.js +21 -0
  224. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/IntentSource.html +2 -0
  225. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/IntentSource.js +8 -0
  226. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/OperationActionDialog.html +2 -0
  227. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/OperationActionDialog.js +37 -0
  228. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/OperationEntry.html +2 -0
  229. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/OperationEntry.js +10 -0
  230. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/OperationsPage.html +2 -0
  231. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/OperationsPage.js +37 -0
  232. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/RepairTrack.html +2 -0
  233. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/RepairTrack.js +49 -0
  234. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/RunDetail.html +4 -0
  235. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/RunDetail.js +22 -0
  236. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/SourceSummary.html +2 -0
  237. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/SourceSummary.js +9 -0
  238. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/commands.js +82 -0
  239. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/examples.js +47 -0
  240. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/model.js +61 -0
  241. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/repair.js +68 -0
  242. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/store.js +55 -0
  243. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/types.js +1 -0
  244. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/workbench.js +18 -0
  245. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/ManagementTable.html +3 -0
  246. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/ManagementTable.js +28 -0
  247. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcCreateEntry.html +2 -0
  248. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcCreateEntry.js +18 -0
  249. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcDetail.html +2 -0
  250. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcDetail.js +31 -0
  251. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcEditor.html +2 -0
  252. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcEditor.js +27 -0
  253. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcLifecycle.html +2 -0
  254. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcLifecycle.js +16 -0
  255. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcPage.html +2 -0
  256. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcPage.js +43 -0
  257. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcPicker.html +4 -0
  258. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcPicker.js +34 -0
  259. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcProgress.html +2 -0
  260. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcProgress.js +30 -0
  261. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcWizard.html +3 -0
  262. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcWizard.js +67 -0
  263. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcWorkspace.html +2 -0
  264. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcWorkspace.js +41 -0
  265. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcsPage.html +2 -0
  266. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcsPage.js +31 -0
  267. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/ServiceEditor.html +2 -0
  268. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/ServiceEditor.js +26 -0
  269. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/ServiceList.html +2 -0
  270. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/ServiceList.js +70 -0
  271. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/data.js +8 -0
  272. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/domain.js +62 -0
  273. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/management.js +36 -0
  274. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/managementStore.js +49 -0
  275. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/store.js +132 -0
  276. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/AdminList.html +2 -0
  277. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/AdminList.js +38 -0
  278. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/EffectiveGrants.html +2 -0
  279. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/EffectiveGrants.js +11 -0
  280. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/GrantEditor.html +2 -0
  281. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/GrantEditor.js +45 -0
  282. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/MemberEditor.html +2 -0
  283. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/MemberEditor.js +54 -0
  284. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/MembersPage.html +3 -0
  285. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/MembersPage.js +27 -0
  286. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/RecordsPage.html +2 -0
  287. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/RecordsPage.js +12 -0
  288. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/RoleEditor.html +2 -0
  289. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/RoleEditor.js +45 -0
  290. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/RolesPage.html +3 -0
  291. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/RolesPage.js +38 -0
  292. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/domain.js +61 -0
  293. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/state.js +51 -0
  294. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/store.js +116 -0
  295. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseActionDialog.html +2 -0
  296. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseActionDialog.js +45 -0
  297. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseDetail.html +4 -0
  298. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseDetail.js +30 -0
  299. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseEditor.html +2 -0
  300. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseEditor.js +67 -0
  301. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseExecution.html +2 -0
  302. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseExecution.js +5 -0
  303. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleasesPage.html +4 -0
  304. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleasesPage.js +60 -0
  305. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/commands.js +157 -0
  306. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/model.js +136 -0
  307. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/store.js +76 -0
  308. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewDetail.html +3 -0
  309. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewDetail.js +26 -0
  310. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewEvidence.html +2 -0
  311. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewEvidence.js +14 -0
  312. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewProcess.html +2 -0
  313. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewProcess.js +113 -0
  314. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewsPage.html +3 -0
  315. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewsPage.js +62 -0
  316. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/commands.js +97 -0
  317. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/model.js +147 -0
  318. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/store.js +13 -0
  319. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ColumnSettings.html +2 -0
  320. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ColumnSettings.js +9 -0
  321. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ListBatchBar.html +2 -0
  322. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ListBatchBar.js +8 -0
  323. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ListDeleteDialog.html +2 -0
  324. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ListDeleteDialog.js +37 -0
  325. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ListMore.html +2 -0
  326. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ListMore.js +8 -0
  327. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/RecordMetadata.html +2 -0
  328. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/RecordMetadata.js +17 -0
  329. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/columns.js +32 -0
  330. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/deliveryGuide.js +49 -0
  331. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/deliveryView.js +12 -0
  332. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/listBatch.js +15 -0
  333. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/listSelection.js +37 -0
  334. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/policy.js +68 -0
  335. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/session.js +44 -0
  336. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/ConfirmationDialog.html +2 -0
  337. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/ConfirmationDialog.js +25 -0
  338. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/ConsoleShell.html +2 -0
  339. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/ConsoleShell.js +53 -0
  340. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/PrototypeGuide.html +10 -0
  341. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/PrototypeGuide.js +30 -0
  342. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/ScopePage.html +2 -0
  343. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/ScopePage.js +10 -0
  344. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/SessionDialog.html +2 -0
  345. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/SessionDialog.js +9 -0
  346. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/confirmation.js +3 -0
  347. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/navigation.js +19 -0
  348. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecDocument.html +2 -0
  349. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecDocument.js +8 -0
  350. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecEdit.html +2 -0
  351. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecEdit.js +32 -0
  352. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecHeader.html +2 -0
  353. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecHeader.js +15 -0
  354. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecHistory.html +2 -0
  355. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecHistory.js +11 -0
  356. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecReview.html +2 -0
  357. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecReview.js +57 -0
  358. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecWorkspace.html +2 -0
  359. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecWorkspace.js +37 -0
  360. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/data.js +20 -0
  361. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/domain.js +55 -0
  362. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/store.js +151 -0
  363. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/ArtifactDetail.html +3 -0
  364. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/ArtifactDetail.js +18 -0
  365. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TaskCreate.html +2 -0
  366. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TaskCreate.js +40 -0
  367. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TaskDetail.html +2 -0
  368. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TaskDetail.js +51 -0
  369. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TaskLaunch.html +2 -0
  370. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TaskLaunch.js +9 -0
  371. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TasksPage.html +5 -0
  372. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TasksPage.js +48 -0
  373. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/domain.js +204 -0
  374. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/exampleSource.js +22 -0
  375. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/registry.js +135 -0
  376. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/store.js +137 -0
  377. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workbench/WorkbenchPage.html +3 -0
  378. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workbench/WorkbenchPage.js +36 -0
  379. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workbench/model.js +56 -0
  380. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workbench/store.js +15 -0
  381. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/FlowCanvas.html +2 -0
  382. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/FlowCanvas.js +27 -0
  383. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/FlowDetail.html +4 -0
  384. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/FlowDetail.js +31 -0
  385. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/FlowEditor.html +2 -0
  386. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/FlowEditor.js +68 -0
  387. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/WorkflowsPage.html +5 -0
  388. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/WorkflowsPage.js +55 -0
  389. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/data.js +16 -0
  390. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/domain.js +83 -0
  391. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/registry.js +18 -0
  392. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/store.js +61 -0
  393. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/admin.css +60 -0
  394. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/agents.css +46 -0
  395. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/antdv.css +295 -0
  396. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/app.css +102 -0
  397. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/delivery.css +4 -0
  398. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/intents.css +37 -0
  399. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/native.css +22 -0
  400. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/operations.css +2 -0
  401. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/pbc.css +3 -0
  402. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/permissions.css +22 -0
  403. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/pro.css +1 -0
  404. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/releases.css +4 -0
  405. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/reset.css +246 -0
  406. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/reviews.css +8 -0
  407. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/tasks.css +6 -0
  408. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/tokens.css +15 -0
  409. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/workbench.css +61 -0
  410. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/workflows.css +1 -0
  411. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/admin-rules.test.js +96 -0
  412. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/agents.test.js +14 -0
  413. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/intent-state.test.js +37 -0
  414. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/list-batch.test.js +44 -0
  415. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/operation-fixtures.js +19 -0
  416. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/operation-repair.test.js +14 -0
  417. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/operations.test.js +25 -0
  418. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/pbc-management.test.js +17 -0
  419. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/pbc-state.test.js +24 -0
  420. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/permission-config.test.js +23 -0
  421. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/permissions.test.js +24 -0
  422. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/releases.test.js +50 -0
  423. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/reviews.test.js +36 -0
  424. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/runtime-forms-router.test.js +28 -0
  425. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/runtime-state.test.js +42 -0
  426. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/runtime-stores.test.js +16 -0
  427. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/spec-state.test.js +11 -0
  428. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/tasks.test.js +27 -0
  429. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/workbench.test.js +34 -0
  430. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/workflows.test.js +16 -0
  431. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tools/convert.mjs +168 -0
  432. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tools/serve.mjs +7 -0
  433. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tools/styles.mjs +11 -0
  434. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tools/verify.mjs +24 -0
  435. package/skills/i3-ui-demo/assets/templates/enterprise-admin/serve.cjs +16 -0
  436. package/skills/i3-ui-demo/assets/templates/enterprise-admin/template-inventory.json +28791 -0
  437. package/skills/i3-ui-demo/assets/templates/enterprise-admin/template.json +9 -0
  438. package/skills/i3-ui-demo/assets/templates/enterprise-admin/usability.css +44 -0
  439. package/skills/i3-ui-demo/assets/templates.json +10 -0
  440. package/skills/i3-ui-demo/assets/versions.json +20 -0
  441. package/skills/i3-ui-demo/readme.md +350 -0
  442. package/skills/i3-ui-demo/references/browser.md +71 -0
  443. package/skills/i3-ui-demo/references/dependencies.md +67 -0
  444. package/skills/i3-ui-demo/references/resources.md +142 -0
  445. package/skills/i3-ui-demo/scripts/dependencies.cjs +364 -0
  446. package/skills/i3-ui-demo/scripts/design-install.cjs +105 -0
  447. package/skills/i3-ui-demo/scripts/design-provider.cjs +57 -0
  448. package/skills/i3-ui-demo/scripts/locations.cjs +52 -0
  449. package/skills/i3-ui-demo/scripts/mcp.cjs +112 -0
  450. package/skills/i3-ui-demo/scripts/provider-discovery.cjs +131 -0
  451. package/skills/i3-ui-demo/scripts/resources.cjs +283 -0
  452. package/skills/i3-ui-prototype/SKILL.md +1 -1
  453. package/skills/i3-ui-prototype/references/execution-evidence.md +12 -56
  454. package/skills/i3-ui-prototype/scripts/codebuddy-registration.cjs +1 -1
  455. package/skills/i3-ui-prototype/scripts/execution-runtime.cjs +5 -2
  456. package/skills/i3-ui-prototype/scripts/hosts/codebuddy.cjs +3 -2
  457. package/skills/i3-ui-prototype/scripts/native-delivery.cjs +2 -2
  458. package/skills/i3-ui-prototype/scripts/prototype-hooks.cjs +23 -20
  459. package/docs/ui-prototype-native/MAIN-SESSION-REPORT.md +0 -66
  460. package/docs/ui-prototype-native/USAGE.md +0 -93
  461. package/references/enterprise-sop-resources/technical-baseline/assets-manifest.json +0 -101
  462. package/references/enterprise-sop-resources/technical-baseline/baselines/PROVENANCE.md +0 -40
  463. package/references/enterprise-sop-resources/technical-baseline/references/engineering-directory-v0.2.0/adoption.md +0 -112
  464. package/references/enterprise-sop-resources/technical-baseline/references/engineering-directory-v0.2.0/directory-standard.md +0 -119
  465. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/ad/prompts/01-generate.md +0 -0
  466. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/ad/prompts/02-review.md +0 -0
  467. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/ad/prompts/03-revise.md +0 -0
  468. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/ad/prompts/04-recheck.md +0 -0
  469. /package/{references/enterprise-sop-resources/ad/templates/AD.md → skills/i3-enterprise-sop/references/ad/templates/ad.md} +0 -0
  470. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/brd/prompts/01-generate.md +0 -0
  471. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/brd/prompts/02-review.md +0 -0
  472. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/brd/prompts/03-revise.md +0 -0
  473. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/brd/prompts/04-recheck.md +0 -0
  474. /package/{references/enterprise-sop-resources/brd/templates/BRD.md → skills/i3-enterprise-sop/references/brd/templates/brd.md} +0 -0
  475. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/controlled-handoff.md +0 -0
  476. /package/{references/engineering-skeleton-resources → skills/i3-enterprise-sop/references/engineering-skeleton}/catalog.json +0 -0
  477. /package/{references/engineering-skeleton-resources → skills/i3-enterprise-sop/references/engineering-skeleton}/directory-standard.md +0 -0
  478. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/handoff.py +0 -0
  479. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/prd/prompts/02-review.md +0 -0
  480. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/prd/prompts/03-revise.md +0 -0
  481. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/prd/prompts/04-recheck.md +0 -0
  482. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/review-handoff.md +0 -0
  483. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/selection-handoff.md +0 -0
  484. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/selection_handoff.py +0 -0
  485. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/testcase/prompts/01-generate.md +0 -0
  486. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/testcase/prompts/02-review.md +0 -0
  487. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/testcase/prompts/03-revise.md +0 -0
  488. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/testcase/prompts/04-recheck.md +0 -0
  489. /package/{references/enterprise-sop-resources/testcase/templates/TestCase.md → skills/i3-enterprise-sop/references/testcase/templates/testcase.md} +0 -0
  490. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/verification/check_execution.py +0 -0
  491. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/verification/check_native_execution.py +0 -0
  492. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/verification/check_reads.py +0 -0
  493. /package/{references/enterprise-sop-resources/verification/README.md → skills/i3-enterprise-sop/references/verification/readme.md} +0 -0
  494. /package/{references/enterprise-sop-resources → skills/i3-enterprise-sop/references}/verification/review-output.schema.json +0 -0
@@ -0,0 +1,3 @@
1
+ <!-- 来源:src/workbench/WorkbenchPage.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <div class="page-heading wb-heading"><div><h1>工作台</h1><p>{{ (session.actor.name) }},从待办继续推进你的需求与交付。</p></div><template data-component="Space" wrap=""><template data-component="Select" data-model-value="(store.range)" aria-label="工作台查看范围" data-bind-options="([{ label: '与我相关', value: 'mine' }, { label: '全部授权范围', value: 'all' }])"></template><template data-component="Button" aria-label="刷新工作台" data-on-click="(refresh)"><template data-component="ReloadOutlined"></template></template><template data-component="Button" type="primary" data-bind-disabled="(!session.can('intent:view', session.actor.tenantId) || !session.can('intent:edit', session.actor.tenantId))" data-on-click="(router.push('/intents/new'))"><template data-component="PlusOutlined"></template>发起意图</template></template></div><template data-component="Alert" data-if="(!session.can('intent:view') &amp;&amp; !session.can('pbc:view') &amp;&amp; !session.can('task:view'))" type="info" show-icon="" title="当前身份尚无业务查看权限" description="首页只统计有权查看的记录。请联系业务管理员在权限管理中配置功能及数据范围。" class="page-alert"></template><template data-component="Alert" data-if="(store.notices.length)" class="page-alert" type="error" show-icon="" title="部分本地记录读取失败,请先重新加载核对" data-bind-description="(store.notices.join(';'))"><template data-slot="action"><template data-component="Button" data-on-click="(refresh)">重新加载</template></template></template><p class="wb-scope-note">{{ (store.range === 'mine' ? '与我相关:我创建或负责的需求、任务,以及关联的 PBC。' : '全部授权范围:仅显示当前身份获准查看的业务记录。') }} 数据来自本浏览器的演示记录。</p><div class="wb-metrics" aria-label="工作概览"><button class="panel wb-metric" data-on-click="(focusSection('wb-todos'))"><span class="wb-metric-icon"><template data-component="CheckSquareOutlined"></template></span><span><span class="wb-metric-label">待处理事项</span><strong>{{ (store.data.todos.length) }}</strong><small>其中 {{ (store.data.actionable) }} 项具备下一步处理权限</small></span><template data-component="ArrowRightOutlined"></template></button><button class="panel wb-metric" data-on-click="(focusSection('wb-deliveries'))"><span class="wb-metric-icon"><template data-component="ProjectOutlined"></template></span><span><span class="wb-metric-label">在途交付</span><strong>{{ (store.data.ongoing) }}</strong><small>执行、人工确认或异常处理中</small></span><template data-component="ArrowRightOutlined"></template></button><button class="panel wb-metric" data-on-click="(focusSection('wb-pbcs'))"><span class="wb-metric-icon"><template data-component="AppstoreOutlined"></template></span><span><span class="wb-metric-label">{{ (store.range === 'mine' ? '相关 PBC' : '可见 PBC') }}</span><strong>{{ (store.data.pbcs.length) }}</strong><small>进入工作区查看需求、任务与产物</small></span><template data-component="ArrowRightOutlined"></template></button></div><div class="wb-grid"><div class="wb-main"><section id="wb-todos" class="panel wb-panel" tabindex="-1" aria-labelledby="wb-todo-title"><div class="section-heading"><h2 id="wb-todo-title">{{ (heading) }}待办</h2><template data-component="Input.Search" data-model-value="(keyword)" aria-label="搜索工作台待办" placeholder="搜索名称或编号" allow-clear="" class="wb-search"></template></div><template data-component="Tabs" data-model-active-key="(group)" data-bind-items="([{ key: 'all', label: '全部' }, { key: '需求与规格', label: '需求与规格' }, { key: 'PBC 归属', label: 'PBC 归属' }, { key: '交付任务', label: '交付任务' }, { key: '质量与评审', label: '质量与评审' }, { key: '门禁与发布', label: '门禁与发布' }, { key: '运行管理', label: '运行管理' }])"></template><template data-component="ProTable" data-if="(filtered.length)" class="wb-todo-table" data-bind-table="(table)" data-bind-search="(async () =&gt; { })" data-bind-control="(false)" data-bind-table-container="(false)" row-key="id" data-bind-scroll="({ x: 690 })" size="small" data-bind-pagination="({ showSizeChanger: false, showTotal: (n) =&gt; '共 ' + n + ' 项' })"></template><div data-if="(filtered.length)" class="wb-todo-mobile"><article data-each="t in (table.dataSource.value)" data-bind-key="(t.id)"><template data-component="RouterLink" data-bind-to="(t.path)" class="model-link">{{ (t.title) }}</template><span class="mono muted">{{ (t.code) }}</span><template data-component="Tag" data-bind-color="(t.allowed ? 'blue' : 'default')">{{ (t.status) }}</template><p>{{ (t.reason) }}</p><small class="muted">{{ (t.affiliation) }} · {{ (tenantLabel(t.tenantId)) }}<br>创建人 {{ (t.createdBy) }}<br>更新 {{ (formatDate(t.updatedAt)) }}</small><template data-component="Button" size="small" data-on-click="(router.push(t.path))">{{ (t.action) }}</template></article><template data-component="Pagination" data-model-current="(table.pageParam.current)" data-bind-page-size="(5)" data-bind-total="(filtered.length)" size="small" data-bind-show-size-changer="(false)"></template></div><template data-component="Empty" data-if="(!filtered.length)" data-bind-description="(keyword || group !== 'all' ? '没有符合筛选条件的待办' : '当前范围暂无待办')" class="wb-empty"><template data-component="Button" data-if="(keyword || group !== 'all')" data-on-click="keyword = '';
3
+ group = 'all';">清除筛选</template><template data-component="Button" data-else-if="(store.range === 'mine')" data-on-click="(store.range = 'all')">查看全部授权范围</template><p class="muted">汇总意图、规格、PBC、交付、评审、发布与运行待办。</p></template><p class="wb-footnote">待办是业务记录的汇总入口;修改与删除请进入相应管理页面。</p></section><section id="wb-pbcs" class="panel wb-panel" tabindex="-1" aria-labelledby="wb-pbc-title"><div class="section-heading"><h2 id="wb-pbc-title">{{ (heading) }}PBC</h2><template data-component="Button" type="link" data-bind-disabled="(!session.can('pbc:view'))" data-on-click="(router.push('/pbcs'))">PBC 管理 <template data-component="ArrowRightOutlined"></template></template></div><div data-if="(store.data.pbcs.length)" class="wb-pbcs"><button data-each="p in (store.data.pbcs.slice(0, 4))" data-bind-key="(p.id)" class="wb-pbc" data-on-click="(router.push('/pbcs/' + p.id + '/workspace'))"><span class="wb-pbc-top"><strong>{{ (p.name) }}</strong><template data-component="Tag" data-bind-color="(p.state === 'archived' ? 'default' : 'green')">{{ (p.state === 'archived' ? '已归档' : '正常') }}</template></span><span>{{ (p.ebc) }} · {{ (tenantLabel(p.tenantId)) }}</span><span class="muted">负责人 {{ (p.owner) }} · {{ (p.services.filter(s =&gt; !s.isDeleted).length) }} 项服务方案</span><span class="wb-pbc-bottom">进入交付工作区 <template data-component="ArrowRightOutlined"></template></span></button></div><template data-component="Empty" data-else="" description="当前范围暂无 PBC" class="wb-empty"><p class="muted">需求完成规格确认后,可以关联已有 PBC 或创建新 PBC。</p></template><p data-if="(store.data.pbcs.length &gt; 4)" class="wb-footnote">这里显示前 4 个 PBC,完整记录可进入 PBC 管理查看。</p></section><section id="wb-deliveries" class="panel wb-panel" tabindex="-1" aria-labelledby="wb-delivery-title"><div class="section-heading"><h2 id="wb-delivery-title">{{ (heading) }}交付</h2><template data-component="Button" type="link" data-bind-disabled="(!session.can('task:view'))" data-on-click="(router.push('/tasks'))">交付任务 <template data-component="ArrowRightOutlined"></template></template></div><div data-if="(store.data.deliveries.length)" class="wb-deliveries"><article data-each="t in (store.data.deliveries.slice(0, 4))" data-bind-key="(t.id)" class="wb-delivery"><div class="wb-delivery-info"><template data-component="RouterLink" data-bind-to="('/tasks/' + t.id)" class="model-link">{{ (t.name) }}</template><span class="muted">{{ (t.code) }} · {{ (t.project) }} · {{ (t.owner) }}</span><span>{{ (t.stage) }} <template data-component="Tag" data-bind-color="(t.status === 'failed' ? 'red' : t.status === 'waiting' ? 'orange' : 'blue')">{{ (t.label) }}</template></span></div><div class="wb-progress"><template data-component="Progress" data-bind-percent="(t.progress)" data-bind-status="(t.status === 'failed' ? 'exception' : 'normal')" size="small"></template><small class="muted">研发阶段进度 · {{ (formatDate(t.updatedAt)) }}</small></div></article></div><template data-component="Empty" data-else="" description="当前范围暂无交付任务" class="wb-empty"></template><p data-if="(store.data.deliveries.length &gt; 4)" class="wb-footnote">最近更新的 4 个任务;完整记录请进入交付任务。</p></section></div><aside class="wb-side"><section class="panel wb-panel" aria-label="快捷入口"><h2>快捷入口</h2><div class="wb-shortcuts"><template data-component="Button" data-bind-disabled="(!session.can('pbc:view') || !session.can('intent:view') || !session.can('pbc:create'))" data-on-click="(create = true)"><template data-component="AppstoreOutlined"></template>新建 PBC <template data-component="ArrowRightOutlined"></template></template><small class="muted">需有已确认规格及对应租户创建权限。</small><template data-component="Button" data-bind-disabled="(!session.can('task:view') || !session.can('task:create'))" data-on-click="(router.push('/tasks/new'))"><template data-component="ProjectOutlined"></template>发起交付 <template data-component="ArrowRightOutlined"></template></template><small class="muted">需完成 PBC 归属并选择可用交付流程。</small><template data-component="Button" data-bind-disabled="(!session.can('intent:view'))" data-on-click="(router.push('/intents'))">意图与需求 <template data-component="ArrowRightOutlined"></template></template><template data-component="Button" data-bind-disabled="(!session.can('task:view') || !session.can('artifact:view'))" data-on-click="(router.push('/reviews'))">质量与评审 <template data-component="ArrowRightOutlined"></template></template><template data-component="Button" data-bind-disabled="(!session.can('task:view') || !session.can('artifact:view'))" data-on-click="(router.push('/releases'))">门禁与发布 <template data-component="ArrowRightOutlined"></template></template><template data-component="Button" data-bind-disabled="(!session.can('operation:view'))" data-on-click="(router.push('/operations'))">运行管理 <template data-component="ArrowRightOutlined"></template></template><template data-component="Button" data-bind-disabled="(!session.can('model:view'))" data-on-click="(router.push('/models'))">模型管理 <template data-component="ArrowRightOutlined"></template></template></div><p class="wb-footnote">入口按授权显示可用状态。无权限时请联系业务管理员。</p></section><section class="panel wb-panel" aria-label="公告与规范提醒"><div class="section-heading"><h2><template data-component="NotificationOutlined"></template> 公告与规范</h2><template data-component="Tag">演示</template></div><ul class="wb-notices"><li data-each="n in (alerts)" data-bind-key="(n.id)"><button data-on-click="(notice = n.id)"><span class="wb-notice-meta">{{ (n.category) }} · {{ (n.date) }}</span><strong>{{ (n.title) }}</strong><span class="muted">查看详情 <template data-component="ArrowRightOutlined"></template></span></button></li></ul><p class="wb-footnote">只读内容样例,未发送真实通知。</p></section><section class="panel wb-panel wb-coming"><h2>运行反馈已接入</h2><p>运行验收与异常按原记录汇总;处理后待办同步更新,历史证据保留。</p></section></aside></div><template data-component="PbcCreateEntry" data-bind-open="(create)" data-on-close="(create = false)"></template><template data-component="Modal" data-bind-open="(!!selectedNotice)" data-bind-title="(selectedNotice?.title)" data-on-cancel="(notice = '')" data-bind-footer="(null)"><template data-if="(selectedNotice)"><p class="muted">{{ (selectedNotice.category) }} · {{ (selectedNotice.date) }} · 演示内容</p><p class="wb-notice-content">{{ (selectedNotice.body) }}</p><template data-component="Button" data-on-click="(notice = '')">关闭</template></template></template>
@@ -0,0 +1,36 @@
1
+ import { computed, ref, watch } from '../../runtime/state.js';
2
+ import { h } from '../../runtime/dom.js';
3
+ import { useRouter } from "../../runtime/router.js";
4
+ import { Alert, Button, Empty, Input, Modal, Pagination, Progress, Select, Space, Tabs, Tag } from "../../runtime/widgets.js";
5
+ import { PlusOutlined, ArrowRightOutlined, ReloadOutlined, CheckSquareOutlined, AppstoreOutlined, ProjectOutlined, NotificationOutlined } from "../../runtime/icons.js";
6
+ import { ProTable, useTable } from "../../runtime/widgets.js";
7
+ import { useWorkbench } from "./store.js";
8
+ import { useSession } from "../shared/session.js";
9
+ import { formatDate, tenantLabel } from "../shared/policy.js";
10
+ import PbcCreateEntry from "../pbc/PbcCreateEntry.js";
11
+ import { createComponent } from '../../runtime/dom.js';
12
+ export default createComponent({ name: 'WorkbenchPage', propKeys: [], template: new URL('./WorkbenchPage.html', import.meta.url).href, setup(__props, __emit) {
13
+ const store = useWorkbench(), session = useSession(), router = useRouter(), keyword = ref(''), group = ref('all'), create = ref(false), notice = ref('');
14
+ const filtered = computed(() => store.data.todos.filter(t => (group.value === 'all' || t.group === group.value) && (!keyword.value.trim() || (t.title + t.code + t.reason).toLowerCase().includes(keyword.value.trim().toLowerCase()))));
15
+ const heading = computed(() => store.range === 'mine' ? '我的' : '授权范围内的');
16
+ const render = (fn) => (_, row) => fn(row);
17
+ const columns = [
18
+ { title: '待办事项', key: 'title', width: 280, render: render(t => h('div', { class: 'wb-item' }, [h('button', { class: 'text-button model-link', onClick: () => router.push(t.path) }, t.title), h('span', { class: 'mono muted' }, t.code), h('span', { class: 'muted' }, t.affiliation + ' · ' + tenantLabel(t.tenantId)), h('span', { class: 'muted' }, '创建人 ' + t.createdBy + ' · 更新 ' + formatDate(t.updatedAt))])) },
19
+ { title: '当前状态与下一步', key: 'status', width: 290, render: render(t => h('div', { class: 'wb-item' }, [h(Tag, { color: t.allowed ? 'blue' : 'default' }, () => t.status), h('span', { class: 'wb-reason' }, t.reason)])) },
20
+ { title: '操作', key: 'action', width: 120, fixed: 'right', render: render(t => h(Button, { type: 'link', onClick: () => router.push(t.path), 'aria-label': t.action + ' ' + t.code }, () => t.action)) },
21
+ ];
22
+ const table = useTable({ columns, pageParam: { current: 1, pageSize: 5, total: 0 } });
23
+ function updateTable() { const p = table.pageParam; p.total = filtered.value.length; const pages = Math.max(1, Math.ceil(p.total / (p.pageSize || 5))); if ((p.current || 1) > pages)
24
+ p.current = pages; table.dataSource.value = filtered.value.slice(((p.current || 1) - 1) * (p.pageSize || 5), (p.current || 1) * (p.pageSize || 5)); }
25
+ watch(filtered, () => { table.pageParam.current = 1; updateTable(); }, { immediate: true });
26
+ watch(() => [table.pageParam.current, table.pageParam.pageSize], updateTable);
27
+ const alerts = [
28
+ { id: 'scope', category: '产品公告', title: '工作台首版:从待办继续交付', date: '2026-09-11', body: '工作台已连接意图、规格、PBC 与交付任务。点击待办进入原业务页处理,返回后会更新状态。当前展示本浏览器保存的演示记录。质量评审已接入,同一确认点只汇总一次;发布审批、运行验收与异常已接入。' },
29
+ { id: 'prototype', category: '规范提醒', title: '功能开发先确认交互原型', date: '2026-09-08', body: '功能范围确认后,先评审高保真交互原型,再与规格、设计和接口契约对齐,进入正式编码、测试与验收。已确认的原型和版本记录保留,后续变更需复核受影响部分。' },
30
+ { id: 'authority', category: '使用提示', title: '功能可见与操作取决于授权配置', date: '2026-09-10', body: '岗位名称仅用于说明使用场景。页面、动作与数据范围由权限管理配置;账号和登录由 MaxKey 管理。“与我相关”按创建人、负责人和可见关联记录计算,不等于拥有该记录的操作权限。' },
31
+ ];
32
+ const selectedNotice = computed(() => alerts.find(n => n.id === notice.value));
33
+ function focusSection(id) { document.getElementById(id)?.scrollIntoView({ behavior: 'smooth', block: 'start' }); document.getElementById(id)?.focus({ preventScroll: true }); }
34
+ function refresh() { window.location.reload(); }
35
+ return { computed, ref, watch, h, useRouter, Alert, Button, Empty, Input, Modal, Pagination, Progress, Select, Space, Tabs, Tag, PlusOutlined, ArrowRightOutlined, ReloadOutlined, CheckSquareOutlined, AppstoreOutlined, ProjectOutlined, NotificationOutlined, ProTable, useTable, useWorkbench, useSession, formatDate, tenantLabel, PbcCreateEntry, store, session, router, keyword, group, create, notice, filtered, heading, render, columns, table, updateTable, alerts, selectedNotice, focusSection, refresh };
36
+ } });
@@ -0,0 +1,56 @@
1
+ import { operationTodos } from "../operations/workbench.js";
2
+ import { activeRelease, hasPendingRelease, releaseUrl, allowedReason, taskReleaseLabel, releaseSummary } from "../releases/model.js";
3
+ import { actors, can } from "../shared/policy.js";
4
+ import { affiliation, deliveryGuide, actorAccess } from "../shared/deliveryGuide.js";
5
+ import { statusLabels, currentNode, taskProgress } from "../tasks/domain.js";
6
+ import { actionableReview, canReadReview, reviewStatus, stateLabels, actionReason, reviewUrl } from "../reviews/model.js";
7
+ // Two demo authorization profiles share one person; their permissions are never merged.
8
+ const person = (id) => id === 'complete' ? 'lin' : id;
9
+ export function relatedTo(actor, row) {
10
+ if (person(row.createdById) === person(actor.id))
11
+ return true;
12
+ const owners = new Set(actors.filter(a => a.name === row.owner).map(a => person(a.id)));
13
+ return owners.size === 1 && owners.has(person(actor.id));
14
+ }
15
+ export function buildWorkbench(input, range) {
16
+ const { actor } = input, access = actorAccess(actor);
17
+ const visible = (a, t, p) => input.active && access(a, t, p);
18
+ const intents = input.intents.filter(i => !i.isDeleted && visible('intent:view', i.tenantId));
19
+ const tasks = input.tasks.filter(t => !t.isDeleted && visible('task:view', t.tenantId, t.binding.pbcId));
20
+ const ownIntents = intents.filter(i => relatedTo(actor, i)), ownTasks = tasks.filter(t => relatedTo(actor, t));
21
+ const relatedPbcs = new Set([...ownTasks.map(t => t.binding.pbcId), ...input.jobs.filter(j => j.status === 'done' && ownIntents.some(i => i.id === j.intentId && i.tenantId === j.tenantId)).map(j => j.pbc.id)]);
22
+ const pbcs = input.pbcs.filter(p => !p.isDeleted && visible('pbc:view', p.tenantId, p.id) && (range === 'all' || relatedTo(actor, p) || relatedPbcs.has(p.id)));
23
+ const listIntents = range === 'mine' ? ownIntents : intents, listTasks = range === 'mine' ? ownTasks : tasks;
24
+ const todos = listIntents.flatMap(i => {
25
+ const spec = input.specs.find(s => s.intentId === i.id && !s.isDeleted && s.tenantId === i.tenantId && visible('spec:view', s.tenantId));
26
+ const g = deliveryGuide(i, spec, input.jobs, visible);
27
+ if (g.stage === 'done')
28
+ return [];
29
+ return [{ id: 'intent:' + i.id, code: i.code, title: i.title, group: g.stage === 'pbc' ? 'PBC 归属' : '需求与规格', status: g.label, reason: g.reason, path: g.path, action: g.allowed ? g.action : '查看详情', allowed: g.allowed, updatedAt: spec?.updatedAt || i.updatedAt, createdBy: i.createdBy, tenantId: i.tenantId, affiliation: affiliation(i, input.jobs, input.pbcs, visible).label }];
30
+ });
31
+ for (const t of listTasks) {
32
+ const review = canReadReview(actor, t) ? actionableReview(t) : undefined;
33
+ if (review) {
34
+ const allowed = ['confirm', 'edit', 'replan'].some(a => !actionReason(t, review, actor, a));
35
+ todos.push({ id: 'task:' + t.id, code: t.code, title: t.name, group: '质量与评审', status: stateLabels[reviewStatus(t, review)], reason: t.reason + (allowed ? '' : ' 当前可阅读证据;处理需对应授权或等待当前检查完成。'), path: reviewUrl(t.id, review.id), action: allowed ? '处理评审' : '查看评审', allowed, updatedAt: t.updatedAt, createdBy: t.createdBy, tenantId: t.tenantId, affiliation: visible('pbc:view', t.tenantId, t.binding.pbcId) ? (input.pbcs.find(p => p.id === t.binding.pbcId && !p.isDeleted && p.tenantId === t.tenantId)?.name || t.binding.project) : 'PBC 详情未授权' });
36
+ continue;
37
+ }
38
+ const release = canReadReview(actor, t) ? activeRelease(t) : undefined;
39
+ if (canReadReview(actor, t) && t.status === 'ready' && hasPendingRelease(t)) {
40
+ const operation = release?.unconfirmed ? 'verify' : release?.state === 'pending' ? 'approve' : release?.state === 'approved' ? 'start' : release?.state === 'failed' ? 'retry' : release?.state === 'paused' ? 'resume' : ['deploying', 'canary', 'observing', 'rollingBack'].includes(release?.state || '') ? 'advance' : 'submit';
41
+ const allowed = release ? !allowedReason(t, release, actor, operation) : can(actor, 'release:edit', t.tenantId, t.binding.pbcId, 'production');
42
+ todos.push({ id: 'task:' + t.id, code: t.code, title: t.name, group: '门禁与发布', status: release ? (release.unconfirmed ? '结果待核实' : taskReleaseLabel(t, actor)) : t.releases?.length ? '待准备生产发布' : '待准备发布', reason: release ? releaseSummary(release) : (t.releases?.length ? '当前没有进行中的生产发布,准备材料后申请人工授权。' : '质量点处理结束,准备固定版本的发布材料并人工授权。'), path: release ? releaseUrl(release, !!release.startedAt) : '/releases?task=' + t.id + '&prepare=1', action: allowed ? '处理发布' : '查看发布', allowed, updatedAt: t.updatedAt, createdBy: t.createdBy, tenantId: t.tenantId, affiliation: visible('pbc:view', t.tenantId, t.binding.pbcId) ? t.binding.project : 'PBC 详情未授权' });
43
+ continue;
44
+ }
45
+ if (!['draft', 'waiting', 'failed', 'paused', 'manual'].includes(t.status))
46
+ continue;
47
+ const required = t.status === 'waiting' ? 'workflow:approve' : 'task:operate';
48
+ const allowed = visible(required, t.tenantId, t.binding.pbcId);
49
+ todos.push({ id: 'task:' + t.id, code: t.code, title: t.name, group: '交付任务', status: statusLabels[t.status], reason: allowed ? t.reason : t.reason + ' 当前缺少处理权限,可查看已有进度。', path: '/tasks/' + t.id, action: allowed ? '处理任务' : '查看任务', allowed, updatedAt: t.updatedAt, createdBy: t.createdBy, tenantId: t.tenantId, affiliation: visible('pbc:view', t.tenantId, t.binding.pbcId) ? (input.pbcs.find(p => p.id === t.binding.pbcId && !p.isDeleted && p.tenantId === t.tenantId)?.name || t.binding.project) : 'PBC 详情未授权' });
50
+ }
51
+ const runtimeTodos = operationTodos(listTasks, actor, input.active);
52
+ todos.push(...runtimeTodos);
53
+ todos.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt) || a.id.localeCompare(b.id));
54
+ const deliveries = listTasks.map(t => { const r = canReadReview(actor, t) ? actionableReview(t) : undefined; return { id: t.id, name: t.name, code: t.code, status: t.status, pendingOperation: runtimeTodos.some(x => x.taskId === t.id), pendingReview: !!r, pendingRelease: todos.some(x => x.id === 'task:' + t.id && x.group === '门禁与发布'), label: taskReleaseLabel(t, actor) || (r ? stateLabels[reviewStatus(t, r)] : statusLabels[t.status]), stage: r?.title || currentNode(t)?.name || '待启动', progress: taskProgress(t), updatedAt: t.updatedAt, owner: t.owner, project: visible('pbc:view', t.tenantId, t.binding.pbcId) ? (input.pbcs.find(p => p.id === t.binding.pbcId && p.tenantId === t.tenantId && !p.isDeleted)?.name || t.binding.project) : 'PBC 详情未授权' }; }).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
55
+ return { todos, pbcs, deliveries, actionable: todos.filter(t => t.allowed).length, ongoing: deliveries.filter(t => t.pendingOperation || t.pendingReview || t.pendingRelease || ['running', 'waiting', 'failed', 'paused', 'manual'].includes(t.status)).length };
56
+ }
@@ -0,0 +1,15 @@
1
+ import { computed, ref, watch } from '../../runtime/state.js';
2
+ import { defineStore } from "../../runtime/state.js";
3
+ import { useSession } from "../shared/session.js";
4
+ import { useIntents } from "../intents/store.js";
5
+ import { useSpecs } from "../specs/store.js";
6
+ import { usePbcs } from "../pbc/store.js";
7
+ import { taskRecords, taskReadError } from "../tasks/registry.js";
8
+ import { buildWorkbench } from "./model.js";
9
+ export const useWorkbench = defineStore('workbench', () => {
10
+ const session = useSession(), intents = useIntents(), specs = useSpecs(), pbcs = usePbcs(), range = ref('mine');
11
+ watch(() => session.key, () => { range.value = 'mine'; });
12
+ const data = computed(() => buildWorkbench({ actor: session.actor, active: session.state === 'active', intents: intents.items, specs: specs.items, jobs: pbcs.jobs, pbcs: pbcs.catalog, tasks: taskRecords.value }, range.value));
13
+ const notices = computed(() => [intents.notice, specs.notice, pbcs.notice, taskReadError.value].filter(Boolean));
14
+ return { range, data, notices };
15
+ });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/workflows/FlowCanvas.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <section class="flow-canvas" aria-label="流程画布"><div class="flow-canvas-tools"><span>{{ (body.nodes.length) }} 个节点 · {{ (body.edges.length) }} 条连线</span><template data-component="Space"><template data-component="Button" aria-label="缩小画布" data-bind-disabled="(zoom &lt;= .25)" data-on-click="(zoom = Math.max(.25, zoom - .1))">−</template><span class="flow-zoom">{{ (Math.round(zoom * 100)) }}%</span><template data-component="Button" aria-label="放大画布" data-bind-disabled="(zoom &gt;= 1.5)" data-on-click="(zoom = Math.min(1.5, zoom + .1))">+</template><template data-component="Button" data-on-click="(fit)">适合画布</template></template></div><div ref="viewport" class="flow-viewport" tabindex="0" aria-label="可滚动流程画布"><div data-bind-style="({ width: size.width * zoom + 'px', height: size.height * zoom + 'px' })"><div class="flow-board" data-bind-style="({ width: size.width + 'px', height: size.height + 'px', transform: `scale(${zoom})` })"><svg class="flow-edges" data-bind-width="(size.width)" data-bind-height="(size.height)" aria-hidden="true"><defs><marker id="flow-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z" fill="#8291aa"></path></marker></defs><g data-each="edge in (edges)" data-bind-key="(edge.id)"><path data-bind-d="(edge.path)" fill="none" stroke="#8291aa" stroke-width="2" marker-end="url(#flow-arrow)"></path><text data-if="(edge.label)" data-bind-x="(edge.x)" data-bind-y="(edge.y)" text-anchor="middle">{{ (edge.label) }}</text></g></svg><div data-each="n in (body.nodes)" data-bind-key="(n.id)" class="flow-node" data-bind-class="(['kind-' + n.kind, { selected: selected === n.id }])" role="button" tabindex="0" data-bind-aria-label="('节点 ' + n.name)" data-bind-aria-pressed="(selected === n.id)" data-bind-style="({ left: n.x + 'px', top: n.y + 'px' })" data-on-pointerdown="(down($event, n))" data-on-pointermove="(move)" data-on-pointerup="(drag = undefined)" data-on-pointercancel="(drag = undefined)" data-on-keydown="(key($event, n))"><div class="flow-node-top"><span class="flow-node-kind">{{ (kindLabel(n)) }}</span><span data-if="(protectedNode(n))" class="flow-lock">保护</span></div><strong>{{ (n.name) }}</strong><small>{{ (n.kind === 'loop' ? '最多 ' + (n.limit || '未设置') + ' 次 · 耗尽转人工' : n.gate === 'production' ? '人工授权后方可发布' : n.kind === 'verify' ? '与实现 Agent 独立' : n.output || '流程控制节点') }}</small></div></div></div></div><div class="flow-canvas-hint"><template data-component="Tag" color="blue">{{ (readonly ? '版本预览' : '可编辑草稿') }}</template>{{ (readonly ? '选择节点查看属性' : '拖动节点调整布局;选中后用方向键微调,右侧配置连线。') }}</div></section>
@@ -0,0 +1,27 @@
1
+ import { computed, ref } from '../../runtime/state.js';
2
+ import { Button, Space, Tag } from "../../runtime/widgets.js";
3
+ import { kindLabel, protectedNode } from "./domain.js";
4
+ import { createComponent } from '../../runtime/dom.js';
5
+ export default createComponent({ name: 'FlowCanvas', propKeys: ["body", "readonly", "selected"], template: new URL('./FlowCanvas.html', import.meta.url).href, setup(__props, __emit) {
6
+ const props = __props, emit = __emit, zoom = ref(0.8), viewport = ref();
7
+ const size = computed(() => ({ width: Math.max(1190, ...props.body.nodes.map(n => n.x + 260)), height: Math.max(480, ...props.body.nodes.map(n => n.y + 160)) }));
8
+ const edges = computed(() => props.body.edges.flatMap(e => { const a = props.body.nodes.find(n => n.id === e.from), b = props.body.nodes.find(n => n.id === e.to); if (!a || !b)
9
+ return []; const down = Math.abs(a.y - b.y) > 80; const x1 = a.x + (down ? 100 : b.x > a.x ? 200 : 0), y1 = a.y + (down ? 104 : 52), x2 = b.x + (down ? 100 : b.x > a.x ? 0 : 200), y2 = b.y + (down ? 0 : 52); return [{ ...e, path: down ? `M${x1},${y1} C${x1},${y1 + 50} ${x2},${y2 - 50} ${x2},${y2}` : `M${x1},${y1} C${(x1 + x2) / 2},${y1} ${(x1 + x2) / 2},${y2} ${x2},${y2}`, x: (x1 + x2) / 2, y: (y1 + y2) / 2 - 8 }]; }));
10
+ let drag;
11
+ function down(e, n) { emit('select', n.id); if (props.readonly || e.button !== 0)
12
+ return; drag = { id: n.id, startX: e.clientX, startY: e.clientY, x: n.x, y: n.y, pointer: e.pointerId }; e.currentTarget.setPointerCapture(e.pointerId); }
13
+ function move(e) { if (!drag || drag.pointer !== e.pointerId)
14
+ return; emit('move', drag.id, Math.max(20, Math.min(2400, Math.round(drag.x + (e.clientX - drag.startX) / zoom.value))), Math.max(20, Math.min(2000, Math.round(drag.y + (e.clientY - drag.startY) / zoom.value)))); }
15
+ function key(e, n) { if (['Enter', ' '].includes(e.key)) {
16
+ e.preventDefault();
17
+ emit('select', n.id);
18
+ } if (!props.readonly && ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.key)) {
19
+ e.preventDefault();
20
+ emit('move', n.id, Math.max(20, n.x + (e.key === 'ArrowRight' ? 20 : e.key === 'ArrowLeft' ? -20 : 0)), Math.max(20, n.y + (e.key === 'ArrowDown' ? 20 : e.key === 'ArrowUp' ? -20 : 0)));
21
+ } }
22
+ function fit() { zoom.value = Math.max(.25, Math.min(1, ((viewport.value?.clientWidth || 900) - 24) / size.value.width)); if (viewport.value) {
23
+ viewport.value.scrollTop = 0;
24
+ viewport.value.scrollLeft = 0;
25
+ } }
26
+ return { computed, ref, Button, Space, Tag, kindLabel, protectedNode, props, emit, zoom, viewport, size, edges, drag, down, move, key, fit };
27
+ } });
@@ -0,0 +1,4 @@
1
+ <!-- 来源:src/workflows/FlowDetail.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <template data-component="Result" data-if="(!record || !body)" status="404" title="模板不存在或无权访问"><template data-slot="extra"><template data-component="Button" data-on-click="(router.push('/workflows'))">返回列表</template></template></template><template data-else=""><div class="page-heading"><div><template data-component="Button" type="link" class="agent-back" data-on-click="(router.push('/workflows'))">← 返回模板列表</template><div class="agent-title"><h1>{{ (record.body.name) }}</h1><template data-component="Tag" data-bind-color="(record.enabled ? 'green' : 'default')">{{ (record.enabled ? '已启用' : '已停用') }}</template></div><p>{{ (record.body.description) }}</p></div><template data-component="Space" wrap=""><template data-component="Button" data-bind-disabled="(!can('workflow:status') || (!record.enabled &amp;&amp; !record.versions.length))" data-on-click="(toggle)">{{ (record.enabled ? '停用模板' : '启用模板') }}</template><template data-component="Button" data-bind-disabled="(!can('workflow:edit') || record.state === 'review')" data-on-click="(router.push('/workflows/' + record.id + '/edit'))">编辑草稿</template><template data-component="Button" type="primary" data-bind-disabled="(!can('workflow:use') || !record.enabled)" data-on-click="useVersion = record.versions.at(-1)?.number;
3
+ useOpen = true;">保存版本选择</template><template data-component="Button" type="primary" data-bind-disabled="(!can('workflow:use') || !can('task:create') || !record.enabled)" data-on-click="(router.push({ path: '/tasks/new', query: { flow: record.id, version: record.versions.at(-1)?.number } }))">用于发起交付</template></template></div><template data-component="Alert" data-if="(error)" class="page-alert" type="error" show-icon="" data-bind-title="(error)" closable="" data-on-close="(error = '')"></template><template data-component="Alert" data-if="(record.state === 'review')" class="page-alert" type="info" show-icon="" title="草稿等待配置审核" data-bind-description="('提交人:' + record.requestName + ';变更说明:' + record.reviewNote)"><template data-slot="action"><template data-component="Space" wrap=""><template data-component="Button" data-if="(can('workflow:edit'))" data-on-click="(run(() =&gt; store.withdraw(record.id, record.recordVersion)))">撤回审核</template><template data-component="Button" type="primary" data-bind-disabled="(!can('workflow:publish') || record.requestBy === session.actor.id)" data-on-click="note = '';
4
+ reviewOpen = true;">审核配置</template></template></template></template><template data-component="Alert" data-else-if="(record.state === 'draft' &amp;&amp; record.reviewNote)" class="page-alert" type="warning" title="配置已退回" data-bind-description="(record.reviewNote)" show-icon=""></template><div class="agent-meta-strip"><span>项目 <strong>{{ (record.project) }}</strong></span><span>标识 <strong>{{ (record.body.code) }}</strong></span><span>最新发布 <strong>{{ (record.versions.length ? 'v' + record.versions.at(-1).number : '尚未发布') }}</strong></span><span>草稿 <strong>{{ ({ draft: '编辑中', review: '待审核', published: '与最新发布一致' }[record.state]) }}</strong></span></div><section class="agent-panel"><template data-component="Tabs" data-model-active-key="(active)" data-bind-items="([{ key: 'flow', label: '流程配置' }, { key: 'versions', label: '版本与差异' }, { key: 'handoff', label: '版本选择记录' }, { key: 'metadata', label: '基础信息' }, ...(can('workflow:audit') ? [{ key: 'records', label: '操作记录' }] : [])])"></template><template data-if="(active === 'flow' || active === 'versions')"><div class="flow-version-tools"><template data-component="Space" wrap=""><span>查看</span><template data-component="Select" data-model-value="(version)" aria-label="查看流程版本" data-bind-options="(versions)" style="width:190px"></template><template data-if="(active === 'versions' &amp;&amp; record.versions.length)"><span>对比</span><template data-component="Select" data-bind-value="(compare || String(record.versions.at(-1)?.number))" aria-label="对比基准版本" data-bind-options="(versions.filter(v =&gt; v.value !== 'draft'))" style="width:160px" data-on-change="(v =&gt; compare = String(v))"></template></template></template><template data-component="Button" data-if="(version !== 'draft')" data-bind-disabled="(!can('workflow:edit') || record.state === 'review')" data-on-click="(restore)">基于此版本编辑</template></div><template data-if="(active === 'versions')"><template data-component="Alert" type="info" show-icon="" title="发布版本只读保留" description="草稿保存和新版本发布都不会改写历史版本。版本历史不适用批量删除。"></template><div class="flow-version-history"><article data-each="v in (record.versions.slice().reverse())" data-bind-key="(v.number)"><template data-component="Tag" color="blue">v{{ (v.number) }}</template><strong>{{ (v.note) }}</strong><span>{{ (v.by) }} · {{ (formatDate(v.at)) }}</span><template data-component="Button" type="link" data-on-click="(version = String(v.number))">查看此版</template></article><p data-if="(!record.versions.length)" class="muted">尚无发布版本。保存并提交草稿后可审核发布。</p></div><h2>差异明细</h2><ul data-if="(changes.length)" class="flow-diff"><li data-each="(change,i) in (changes)" data-bind-key="(i)">{{ (change) }}</li></ul><p data-else="" class="muted">{{ (record.versions.length ? '与所选基准版本没有差异。' : '发布首版后可对比差异。') }}</p></template><template data-component="Alert" data-if="(issues.length)" class="page-alert" type="warning" show-icon="" data-bind-title="(issues.length + ' 项配置或资源待处理')" description="下方检查包含当前资源状态,可能与历史发布时不同。"></template><div class="flow-editor-layout"><template data-component="FlowCanvas" data-bind-body="(body)" readonly="" data-bind-selected="(selected)" data-on-select="(selected = $event)"></template><aside class="flow-properties"><template data-if="(node)"><h2>{{ (node.name) }}</h2><template data-component="Tag">{{ (kindLabel(node)) }}</template><dl class="flow-node-details"><dt data-if="(node.agentId)">执行 Agent</dt><dd data-if="(node.agentId)">{{ (store.choices(record).find(a =&gt; a.id === node.agentId)?.name || '引用不可用或无权查看') }}</dd><dt data-if="(node.input)">输入产物</dt><dd data-if="(node.input)">{{ (node.input) }}</dd><dt data-if="(node.output)">输出产物</dt><dd data-if="(node.output)">{{ (node.output) }}</dd><dt data-if="(node.permission)">确认权限</dt><dd data-if="(node.permission)">交付人工确认</dd><dt data-if="(node.tool)">登记工具</dt><dd data-if="(node.tool)">{{ (node.tool === 'ci-check' ? '项目 CI · 质量检查' : '契约查询') }}(示例)</dd><dt data-if="(node.limit)">修复上限</dt><dd data-if="(node.limit)">{{ (node.limit) }} 次,耗尽转人工</dd><dt data-if="(node.condition)">判断条件</dt><dd data-if="(node.condition)">{{ (node.condition === 'checks.passed' ? '质量检查通过' : '人工评审通过') }}</dd></dl></template><p class="muted">配置预览不触发执行。</p></aside></div><div data-if="(issues.length)" class="flow-checks"><div data-each="c in (issues)" data-bind-key="(c.id)" class="flow-check"><template data-component="Tag" color="orange">待处理</template><div><strong>{{ (c.title) }}</strong><p>{{ (c.detail) }}</p></div></div></div></template><template data-else-if="(active === 'handoff')"><template data-component="Alert" type="info" show-icon="" title="已固定版本,尚未创建任务" description="这些是本地原型的交接凭据,可通过右上角“用于发起交付”选择需求并创建任务。选择记录只读,不适用删除。"></template><article data-each="u in (store.uses(record))" data-bind-key="(u.id)" class="flow-use" data-bind-class="({ selected: u.id === useId })"><div><template data-component="Tag" color="blue">v{{ (u.version.number) }}</template><strong>{{ (u.version.body.name) }}</strong></div><p>{{ (u.project) }} · {{ (u.by) }} · {{ (formatDate(u.at)) }}</p><p class="muted">所选版本:{{ (u.version.note) }};{{ (u.version.body.nodes.length) }} 个节点,快照保留。</p><p data-each="a in (u.agentVersions)" data-bind-key="(a.id)" class="muted">{{ (a.name) }} · 选择时记录 v{{ (a.recordVersion) }}</p><small class="agent-code">{{ (u.id) }}</small></article><p data-if="(!store.uses(record).length)" class="muted">尚未选择版本。启用模板后可从右上角“使用模板”体验。</p></template><template data-component="RecordMetadata" data-else-if="(active === 'metadata')" data-bind-record="(record)"></template><section data-else-if="(active === 'records' &amp;&amp; can('workflow:audit'))"><p class="muted">操作记录只读保留,不适用删除。</p><ol class="agent-audit"><li data-each="a in (store.audits(record))" data-bind-key="(a.id)"><strong>{{ (a.action) }}</strong><span>{{ (a.actor) }} · {{ (formatDate(a.at)) }}</span><p>{{ (a.detail) }}</p></li></ol><p data-if="(!store.audits(record).length)" class="muted">暂无操作记录。</p></section></section><template data-component="Modal" data-bind-open="(reviewOpen)" title="审核流程配置" data-bind-footer="(null)" data-on-cancel="(reviewOpen = false)"><p>提交人:{{ (record.requestName) }};拟发布版本:v{{ ((record.versions.at(-1)?.number || 0) + 1) }}</p><p>{{ (record.reviewNote) }}</p><p class="muted">审核当前草稿、版本差异和检查结果;确认后生成不可变发布快照。</p><template data-component="Input.TextArea" data-model-value="(note)" aria-label="审核意见" placeholder="退回时请填写原因"></template><template data-component="Alert" data-if="(error)" type="error" data-bind-title="(error)"></template><template data-component="Space" class="flow-modal-actions"><template data-component="Button" data-on-click="(reviewOpen = false)">取消</template><template data-component="Button" danger="" data-on-click="(review(false))">退回修改</template><template data-component="Button" type="primary" data-on-click="(review(true))">确认审核发布</template></template></template><template data-component="Modal" data-bind-open="(useOpen)" title="选择交付模板版本" data-bind-footer="(null)" data-on-cancel="(useOpen = false)"><p>项目:{{ (record.project) }}</p><template data-component="Select" data-model-value="(useVersion)" aria-label="使用模板版本" class="full-width" data-bind-options="(record.versions.map(v =&gt; ({ value: v.number, label: 'v' + v.number + ' · ' + v.note })).reverse())"></template><p class="muted">确认后保存此版本的交接快照。后续模板更新不会改写此选择,当前不会启动实际任务。</p><template data-component="Alert" data-if="(error)" type="error" data-bind-title="(error)"></template><template data-component="Space" class="flow-modal-actions"><template data-component="Button" data-on-click="(useOpen = false)">取消</template><template data-component="Button" type="primary" data-on-click="(use)">确认选择版本</template></template></template></template>
@@ -0,0 +1,31 @@
1
+ import { computed, ref } from '../../runtime/state.js';
2
+ import { useRoute, useRouter } from "../../runtime/router.js";
3
+ import { Alert, Button, Input, Modal, Result, Select, Space, Tabs, Tag, message } from "../../runtime/widgets.js";
4
+ import { useWorkflows } from "./store.js";
5
+ import { useSession } from "../shared/session.js";
6
+ import { formatDate } from "../shared/policy.js";
7
+ import { diffBodies, kindLabel } from "./domain.js";
8
+ import FlowCanvas from "./FlowCanvas.js";
9
+ import RecordMetadata from "../shared/RecordMetadata.js";
10
+ import { confirmAction } from "../shell/confirmation.js";
11
+ import { createComponent } from '../../runtime/dom.js';
12
+ export default createComponent({ name: 'FlowDetail', propKeys: [], template: new URL('./FlowDetail.html', import.meta.url).href, setup(__props, __emit) {
13
+ const route = useRoute(), router = useRouter(), store = useWorkflows(), session = useSession(), active = ref(String(route.query.tab || 'flow')), selected = ref('build'), version = ref('draft'), compare = ref(''), error = ref(''), reviewOpen = ref(false), useOpen = ref(false), note = ref(''), useVersion = ref(), useId = ref('');
14
+ const record = computed(() => store.item(String(route.params.id))), body = computed(() => { const r = record.value; return version.value === 'draft' ? r?.body : r?.versions.find(v => String(v.number) === version.value)?.body; }), node = computed(() => body.value?.nodes.find(n => n.id === selected.value)), versions = computed(() => [{ value: 'draft', label: '当前草稿 / 配置' }, ...(record.value?.versions.slice().reverse().map(v => ({ value: String(v.number), label: '已发布 v' + v.number })) || [])]), checks = computed(() => record.value && body.value ? store.checks(record.value, body.value) : []), issues = computed(() => checks.value.filter(c => !c.ok)), changes = computed(() => { const r = record.value, before = r?.versions.find(v => String(v.number) === (compare.value || String(r?.versions.at(-1)?.number))); return before && body.value ? diffBodies(before.body, body.value) : []; });
15
+ const can = (a) => !!record.value && session.can(a, record.value.tenantId, record.value.pbcId);
16
+ function run(fn) { error.value = ''; try {
17
+ fn();
18
+ }
19
+ catch (e) {
20
+ error.value = e.message;
21
+ } }
22
+ function toggle() { const r = record.value; if (!r)
23
+ return; confirmAction({ title: (r.enabled ? '停用' : '启用') + '模板?', content: '此操作只影响新的版本选择,既有交接快照保留。', okText: r.enabled ? '确认停用' : '确认启用', cancelText: '取消', onOk: () => run(() => { store.toggle(r.id, r.recordVersion); message.success('模板状态已更新'); }) }); }
24
+ function review(approved) { const r = record.value; if (r)
25
+ run(() => { store.review(r.id, r.recordVersion, approved, note.value); reviewOpen.value = false; message.success(approved ? '配置已审核发布' : '已退回草稿'); }); }
26
+ function use() { const r = record.value; if (r && useVersion.value)
27
+ run(() => { const result = store.selectVersion(r.id, r.recordVersion, useVersion.value); useId.value = result.id; useOpen.value = false; active.value = 'handoff'; message.success('已保存版本选择,尚未创建执行任务'); }); }
28
+ function restore() { const r = record.value; if (!r || !body.value)
29
+ return; confirmAction({ title: '基于此版本创建草稿?', content: '将替换当前草稿,发布历史和已有交接快照保持不变。', okText: '创建草稿', cancelText: '取消', onOk: () => run(() => { store.fromVersion(r.id, r.recordVersion, body.value); router.push('/workflows/' + r.id + '/edit'); }) }); }
30
+ return { computed, ref, useRoute, useRouter, Alert, Button, Input, Modal, Result, Select, Space, Tabs, Tag, message, useWorkflows, useSession, formatDate, diffBodies, kindLabel, FlowCanvas, RecordMetadata, confirmAction, route, router, store, session, active, selected, version, compare, error, reviewOpen, useOpen, note, useVersion, useId, record, body, node, versions, checks, issues, changes, can, run, toggle, review, use, restore };
31
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/workflows/FlowEditor.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <template data-component="Result" data-if="(!draft)" status="404" title="模板不存在或无权访问"></template><template data-else=""><div class="page-heading flow-heading"><div><template data-component="Button" type="link" class="agent-back" data-on-click="(router.push('/workflows'))">← 返回模板列表</template><h1>{{ (isNew ? '创建流程模板' : '编辑流程草稿') }}</h1><p>组合交付步骤,明确每一步的执行资源与产物。</p></div><template data-component="Space" wrap=""><template data-component="Tag" data-if="(dirty)" color="orange">有未保存修改</template><template data-component="Button" data-on-click="(showChecks = !showChecks)">检查流程</template><template data-component="Button" type="primary" data-bind-disabled="(!allowed)" data-bind-loading="(busy)" data-on-click="(save())">保存草稿</template></template></div><template data-component="Alert" data-if="(!allowed)" type="warning" show-icon="" title="当前草稿只读" description="需要编辑权限;审核中的配置须先撤回。"></template><template data-component="Alert" data-if="(error)" class="page-alert" type="error" show-icon="" data-bind-title="(error)" closable="" data-on-close="(error = '')"></template><template data-component="Form" layout="vertical" class="flow-basics" data-bind-disabled="(!allowed)"><template data-component="FormItem" label="模板名称" required=""><template data-component="Input" data-model-value="(draft.body.name)" aria-label="模板名称" placeholder="例如:供热工单 AI 应用交付" data-bind-maxlength="(80)"></template></template><template data-component="FormItem" label="模板标识" required=""><template data-component="Input" data-model-value="(draft.body.code)" aria-label="模板标识" placeholder="heating-ai-delivery" data-bind-disabled="(!isNew)" data-bind-maxlength="(50)"></template></template><template data-component="FormItem" label="所属项目" required=""><template data-component="Select" data-bind-value="(draft.pbcId)" aria-label="模板所属项目" data-bind-disabled="(!isNew)" data-bind-options="(store.projects.map(p =&gt; ({ value: p.id, label: p.name })))" data-on-change="(v =&gt; project(String(v)))"></template></template><template data-component="FormItem" label="用途说明"><template data-component="Input" data-model-value="(draft.body.description)" aria-label="模板用途" data-bind-maxlength="(300)"></template></template></template><div class="flow-palette"><span>添加节点</span><template data-component="Button" data-each="k in (kinds)" data-bind-key="(k.value)" data-bind-disabled="(!allowed)" data-on-click="(add(k.value))">{{ (k.mark) }} {{ (k.label) }}</template><template data-component="Button" data-bind-disabled="(!allowed)" data-on-click="(arrange)">自动整理</template></div><div class="flow-editor-layout"><template data-component="FlowCanvas" data-bind-body="(draft.body)" data-bind-selected="(selected)" data-bind-readonly="(!allowed)" data-on-select="(selected = $event)" data-on-move="(move)"></template><aside class="flow-properties" aria-label="节点属性"><template data-if="(node)"><div class="flow-prop-title"><h2>节点属性</h2><template data-component="Tag" data-bind-color="(protectedNode(node) ? 'blue' : 'default')">{{ (protectedNode(node) ? '治理保护' : kindLabel(node)) }}</template></div><template data-component="Form" layout="vertical" data-bind-disabled="(!allowed)"><template data-component="FormItem" label="节点名称"><template data-component="Input" data-model-value="(node.name)" aria-label="节点名称" data-bind-maxlength="(50)"></template></template><template data-component="FormItem" data-if="(['agent', 'verify', 'loop'].includes(node.kind))" label="执行 Agent" required=""><template data-component="Select" data-model-value="(node.agentId)" aria-label="节点执行 Agent" data-bind-options="(agentOptions)" placeholder="选择可用 Agent" allow-clear=""></template><p class="muted">仅显示同一项目内有权查看的配置。</p></template><template data-component="FormItem" data-if="(node.kind === 'tool')" label="登记工具 / CI" required=""><template data-component="Select" data-model-value="(node.tool)" aria-label="节点工具" data-bind-options="([{ value: 'ci-check', label: '项目 CI · 质量检查(示例)' }, { value: 'contract-read', label: '契约查询(示例)' }])"></template></template><template data-if="(['agent', 'verify', 'loop', 'tool'].includes(node.kind))"><template data-component="FormItem" label="输入产物" required=""><template data-component="Input" data-model-value="(node.input)" aria-label="输入产物" placeholder="例如:规格与代码"></template></template><template data-component="FormItem" label="输出产物" required=""><template data-component="Input" data-model-value="(node.output)" aria-label="输出产物" placeholder="例如:检查报告"></template></template></template><template data-component="FormItem" data-if="(node.kind === 'human')" label="确认所需权限"><template data-component="Select" data-model-value="(node.permission)" aria-label="确认权限" data-bind-disabled="(!!node.gate)" data-bind-options="([{ value: 'workflow:approve', label: '交付人工确认' }])"></template><p class="muted">按权限分配给成员,不限定岗位名称。</p></template><template data-component="FormItem" data-if="(node.kind === 'branch')" label="判断条件"><template data-component="Select" data-model-value="(node.condition)" aria-label="分支条件" data-bind-options="([{ value: 'checks.passed', label: '质量检查通过' }, { value: 'review.approved', label: '人工评审通过' }])"></template></template><template data-component="FormItem" data-if="(node.kind === 'loop')" label="最多修复次数"><template data-component="InputNumber" data-model-value="(node.limit)" aria-label="最多修复次数" data-bind-min="(1)" data-bind-max="(10)" data-bind-precision="(0)"></template><p class="muted">耗尽后转人工处理;修复后仍需独立验证。范围为原型示例。</p></template></template><h3>后续连线</h3><div data-each="edge in (draft.body.edges.filter(e =&gt; e.from === node?.id))" data-bind-key="(edge.id)" class="flow-connection"><span>{{ (edge.label ? edge.label + ' → ' : '') }}{{ (draft.body.nodes.find(n =&gt; n.id === edge.to)?.name) }}</span><template data-component="Button" type="text" danger="" data-bind-disabled="(!allowed)" data-bind-aria-label="('移除连线至 ' + draft.body.nodes.find(n =&gt; n.id === edge.to)?.name)" data-on-click="(draft.body.edges = draft.body.edges.filter(e =&gt; e.id !== edge.id))">×</template></div><template data-if="(node.kind !== 'archive')"><template data-component="Select" data-if="(node.kind === 'branch')" data-model-value="(branchLabel)" aria-label="分支出口" data-bind-disabled="(!allowed)" data-bind-options="(['满足', '不满足'].map(v =&gt; ({ value: v, label: v })))"></template><template data-component="Select" data-model-value="(connectTo)" aria-label="连接到节点" data-bind-disabled="(!allowed)" placeholder="选择后续节点" data-bind-options="(draft.body.nodes.filter(n =&gt; n.id !== node?.id &amp;&amp; n.kind !== 'start').map(n =&gt; ({ value: n.id, label: n.name })))"></template><template data-component="Button" block="" data-bind-disabled="(!allowed || !connectTo)" data-on-click="(connect)">添加连线</template></template><p data-if="(protectedNode(node))" class="muted">必要治理节点不可删除。连接变化仍需通过全路径检查。</p><template data-component="Button" danger="" block="" data-bind-disabled="(!allowed || protectedNode(node))" data-on-click="(removeNode)">删除节点</template></template></aside></div><section data-if="(showChecks)" class="agent-panel flow-checks" aria-label="流程检查结果"><h2>{{ (issues.length ? '检查发现 ' + issues.length + ' 项待处理' : '流程检查通过') }}</h2><p class="muted">本地结构、引用与治理检查;真实 CI、产物类型和 Dapr 执行未接入。</p><div data-each="c in (issues.length ? issues : checks.filter(c =&gt; ['gates', 'release', 'independent', 'cycle'].includes(c.id)))" data-bind-key="(c.id)" class="flow-check"><template data-component="Tag" data-bind-color="(c.ok ? 'green' : 'orange')">{{ (c.ok ? '通过' : '待处理') }}</template><div><strong>{{ (c.title) }}</strong><p>{{ (c.detail) }}</p></div><template data-component="Button" data-if="(c.nodeId)" data-on-click="(selected = c.nodeId)">定位节点</template></div></section><section class="flow-submit"><div><h2>提交配置审核</h2><p class="muted">草稿通过检查后提交,由有发布权限的其他成员审核。现有发布版继续保留。</p><template data-component="Input.TextArea" data-model-value="(note)" aria-label="版本变更说明" placeholder="说明本次节点、资源或流程调整" data-bind-rows="(2)" data-bind-maxlength="(500)"></template></div><template data-component="Button" data-bind-disabled="(!allowed)" data-bind-loading="(busy)" data-on-click="(save(true))">保存并提交审核</template></section></template>
@@ -0,0 +1,68 @@
1
+ import { computed, onBeforeUnmount, ref, watch } from '../../runtime/state.js';
2
+ import { onBeforeRouteLeave, useRoute, useRouter } from "../../runtime/router.js";
3
+ import { Alert, Button, Form, FormItem, Input, InputNumber, Select, Space, Tag, Result, message } from "../../runtime/widgets.js";
4
+ import { useWorkflows } from "./store.js";
5
+ import { useSession } from "../shared/session.js";
6
+ import { clone, kinds, kindLabel, protectedNode } from "./domain.js";
7
+ import FlowCanvas from "./FlowCanvas.js";
8
+ import { confirmAction } from "../shell/confirmation.js";
9
+ import { createComponent } from '../../runtime/dom.js';
10
+ export default createComponent({ name: 'FlowEditor', propKeys: [], template: new URL('./FlowEditor.html', import.meta.url).href, setup(__props, __emit) {
11
+ const route = useRoute(), router = useRouter(), store = useWorkflows(), session = useSession(), isNew = ref(route.params.id === undefined), source = isNew.value ? store.blank() : store.item(String(route.params.id)), draft = ref(source ? clone(source) : undefined), saved = ref(JSON.stringify(draft.value)), selected = ref('build'), error = ref(''), showChecks = ref(false), connectTo = ref(), branchLabel = ref('满足'), note = ref(''), busy = ref(false);
12
+ const node = computed(() => draft.value?.body.nodes.find(n => n.id === selected.value)), dirty = computed(() => JSON.stringify(draft.value) !== saved.value), allowed = computed(() => !!draft.value && session.can('workflow:edit', draft.value.tenantId, draft.value.pbcId) && draft.value.state !== 'review'), checks = computed(() => draft.value ? store.checks(draft.value) : []), issues = computed(() => checks.value.filter(c => !c.ok)), agentOptions = computed(() => draft.value ? store.choices(draft.value).map(a => ({ value: a.id, label: a.name + (a.available ? '' : ' · ' + a.reason), disabled: !a.available })) : []);
13
+ function project(id) { const p = store.projects.find(p => p.id === id); if (p && draft.value) {
14
+ draft.value.pbcId = p.id;
15
+ draft.value.tenantId = p.tenantId;
16
+ draft.value.project = p.name;
17
+ draft.value.body.nodes.forEach(n => { if (n.agentId)
18
+ n.agentId = ''; });
19
+ } }
20
+ function add(kind) { if (!draft.value || !allowed.value)
21
+ return; const n = { id: crypto.randomUUID(), kind, name: kinds.find(k => k.value === kind).label, x: 80 + (draft.value.body.nodes.length % 4) * 260, y: 480 + Math.floor((draft.value.body.nodes.length - 8) / 4) * 160, input: '', output: '', ...(kind === 'loop' ? { limit: 2 } : {}), ...(kind === 'branch' ? { condition: 'checks.passed' } : {}), ...(kind === 'human' ? { permission: 'workflow:approve' } : {}) }; draft.value.body.nodes.push(n); selected.value = n.id; }
22
+ function removeNode() { const n = node.value; if (!n || protectedNode(n) || !draft.value)
23
+ return; draft.value.body.nodes = draft.value.body.nodes.filter(x => x.id !== n.id); draft.value.body.edges = draft.value.body.edges.filter(e => e.from !== n.id && e.to !== n.id); selected.value = 'start'; }
24
+ function connect() { const d = draft.value, n = node.value; if (!d || !n || !connectTo.value)
25
+ return; const label = n.kind === 'branch' ? branchLabel.value : ''; if (d.body.edges.some(e => e.from === n.id && e.to === connectTo.value && e.label === label)) {
26
+ error.value = '这条连线已存在。';
27
+ return;
28
+ } d.body.edges.push({ id: crypto.randomUUID(), from: n.id, to: connectTo.value, label }); connectTo.value = undefined; }
29
+ function move(id, x, y) { const n = draft.value?.body.nodes.find(n => n.id === id); if (n && allowed.value) {
30
+ n.x = x;
31
+ n.y = y;
32
+ } }
33
+ function arrange() { draft.value?.body.nodes.forEach((n, i) => { const row = Math.floor(i / 4), col = i % 4; n.x = 70 + (row % 2 ? 3 - col : col) * 270; n.y = 60 + row * 200; }); }
34
+ async function save(submit = false) { if (!draft.value || busy.value)
35
+ return; error.value = ''; busy.value = true; try {
36
+ if (submit && issues.value.length) {
37
+ showChecks.value = true;
38
+ throw Error('流程检查未通过,请先处理下方问题。');
39
+ }
40
+ if (submit && !note.value.trim())
41
+ throw Error('请填写版本变更说明。');
42
+ let r = store.save(draft.value, isNew.value);
43
+ isNew.value = false;
44
+ draft.value = clone(r);
45
+ saved.value = JSON.stringify(draft.value);
46
+ if (submit)
47
+ r = store.submit(r.id, r.recordVersion, note.value);
48
+ saved.value = JSON.stringify(draft.value);
49
+ message.success(submit ? '已提交配置审核' : '草稿已保存,发布版本保持不变');
50
+ await router.replace('/workflows/' + r.id);
51
+ }
52
+ catch (e) {
53
+ error.value = e.message;
54
+ }
55
+ finally {
56
+ busy.value = false;
57
+ } }
58
+ onBeforeRouteLeave(() => { if (!dirty.value)
59
+ return true; return new Promise(resolve => confirmAction({ title: '离开未保存的流程?', content: '本次画布与属性修改尚未保存。', okText: '放弃修改并离开', cancelText: '继续编辑', onOk: () => resolve(true), onCancel: () => resolve(false) })); });
60
+ function unload(e) { if (dirty.value) {
61
+ e.preventDefault();
62
+ e.returnValue = '';
63
+ } }
64
+ window.addEventListener('beforeunload', unload);
65
+ onBeforeUnmount(() => window.removeEventListener('beforeunload', unload));
66
+ watch(selected, () => connectTo.value = undefined);
67
+ return { computed, onBeforeUnmount, ref, watch, onBeforeRouteLeave, useRoute, useRouter, Alert, Button, Form, FormItem, Input, InputNumber, Select, Space, Tag, Result, message, useWorkflows, useSession, clone, kinds, kindLabel, protectedNode, FlowCanvas, confirmAction, route, router, store, session, isNew, source, draft, saved, selected, error, showChecks, connectTo, branchLabel, note, busy, node, dirty, allowed, checks, issues, agentOptions, project, add, removeNode, connect, move, arrange, save, unload };
68
+ } });
@@ -0,0 +1,5 @@
1
+ <!-- 来源:src/workflows/WorkflowsPage.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <div class="page-heading"><div><h1>研发交付流程</h1><p>定义一次研发交付经过哪些步骤、由谁执行,以及何时需要人工确认。</p></div><template data-component="Button" type="primary" data-bind-disabled="(!session.can('workflow:edit'))" data-on-click="(router.push('/workflows/new'))">创建模板</template></div><div class="workflow-purpose"><article><strong>什么时候用</strong><p>需求规格与 PBC 归属完成后,发起交付时选择。</p></article><article><strong>输入什么</strong><p>确认的规格、交互原型,以及项目和资源权限。</p></article><article><strong>得到什么</strong><p>一项交付任务,持续记录阶段进度、产物与待处理事项。</p></article><template data-component="Button" type="primary" data-bind-disabled="(!session.can('task:create'))" data-on-click="(router.push('/tasks/new'))">发起一次交付</template></div><div class="agent-overview"><span>全部模板 <strong>{{ (store.records.length) }}</strong></span><span>可供选择 <strong>{{ (store.records.filter(r =&gt; r.enabled).length) }}</strong></span><span>待审核 <strong>{{ (store.records.filter(r =&gt; r.state === 'review').length) }}</strong></span><span class="muted">草稿修改不影响已发布版本</span></div><section class="auth-list"><div class="auth-filters"><template data-component="Input" data-model-value="(query)" aria-label="搜索流程模板" placeholder="搜索模板名称、标识或用途" allow-clear=""></template><template data-component="Select" data-model-value="(project)" aria-label="流程项目筛选" data-bind-options="([{ value: 'all', label: '全部可见项目' }, ...[...new Set(store.records.map(r =&gt; r.project))].map(v =&gt; ({ value: v, label: v }))])"></template><template data-component="Select" data-model-value="(state)" aria-label="流程状态筛选" data-bind-options="([{ value: 'all', label: '全部配置状态' }, ...Object.entries(labels).map(([value, label]) =&gt; ({ value, label }))])"></template><template data-component="Button" data-on-click="query = '';
3
+ state = 'all';
4
+ project = 'all';">重置</template></div><div class="auth-tools"><template data-component="ListBatchBar" data-bind-count="(selection.selected.value.length)" data-bind-allowed="(canDelete)" data-on-remove="(targets = selection.selected.value)" data-on-clear="(selection.clear)"></template><template data-component="Space" wrap=""><template data-component="Button" data-on-click="(desc = !desc)">时间{{ (desc ? '倒序' : '正序') }}</template><template data-component="Button" data-bind-loading="(refreshing)" data-on-click="(refresh)">刷新</template><template data-component="ColumnSettings" data-bind-preferences="(prefs)"></template></template></div><template data-component="Alert" data-if="(error)" type="error" show-icon="" data-bind-title="(error)" closable="" data-on-close="(error = '')"></template><template data-component="Alert" data-if="(store.scene === 'error')" type="error" show-icon="" title="流程模板加载失败" description="请重试,现有草稿保持不变。"><template data-slot="action"><template data-component="Button" data-on-click="(refresh)">重试</template></template></template><template data-else=""><template data-component="ProTable" data-bind-table="(table)" data-bind-search="(async () =&gt; { })" data-bind-control="(false)" data-bind-table-container="(false)" row-key="id" data-bind-loading="(refreshing)" data-bind-row-selection="(selection.rowSelection.value)" data-bind-scroll="({ x: 'max-content' })" data-bind-pagination="({ showTotal: (n) =&gt; '共 ' + n + ' 项', showSizeChanger: true, pageSizeOptions: [5, 10, 20] })"></template><p data-if="(!filtered.length)" class="muted">没有符合条件的流程模板。可调整筛选,或创建模板。</p></template></section><template data-component="ListDeleteDialog" data-if="(targets.length)" data-model-targets="(targets)" label="流程模板" data-bind-check="(store.checkRemove)" data-bind-submit="(store.removeMany)" data-on-close="(targets = [])" data-on-deleted="targets = [];
5
+ selection.clear();"></template>
@@ -0,0 +1,55 @@
1
+ import { computed, ref, watch } from '../../runtime/state.js';
2
+ import { h } from '../../runtime/dom.js';
3
+ import { useRouter } from "../../runtime/router.js";
4
+ import { Alert, Button, Input, Select, Space, Tag, message } from "../../runtime/widgets.js";
5
+ import { ProTable, useTable } from "../../runtime/widgets.js";
6
+ import { useWorkflows } from "./store.js";
7
+ import { useSession } from "../shared/session.js";
8
+ import { formatDate, tenantLabel } from "../shared/policy.js";
9
+ import { useColumns } from "../shared/columns.js";
10
+ import { useListSelection } from "../shared/listSelection.js";
11
+ import ListMore from "../shared/ListMore.js";
12
+ import ColumnSettings from "../shared/ColumnSettings.js";
13
+ import ListBatchBar from "../shared/ListBatchBar.js";
14
+ import ListDeleteDialog from "../shared/ListDeleteDialog.js";
15
+ import { confirmAction } from "../shell/confirmation.js";
16
+ import { createComponent } from '../../runtime/dom.js';
17
+ export default createComponent({ name: 'WorkflowsPage', propKeys: [], template: new URL('./WorkflowsPage.html', import.meta.url).href, setup(__props, __emit) {
18
+ const store = useWorkflows(), session = useSession(), router = useRouter(), query = ref(''), state = ref('all'), project = ref('all'), desc = ref(true), refreshing = ref(false), targets = ref([]), error = ref('');
19
+ const rows = computed(() => store.records.map(r => ({ ...r, name: r.body.name, code: r.body.code })));
20
+ const prefs = useColumns('workflows', [{ key: 'name', label: '模板名称', locked: true }, { key: 'project', label: '所属项目', defaultVisible: true }, { key: 'state', label: '配置状态', defaultVisible: true }, { key: 'version', label: '发布版本', defaultVisible: true }, { key: 'enabled', label: '启用状态', defaultVisible: true }, { key: 'createdBy', label: '创建人', defaultVisible: true }, { key: 'createdAt', label: '创建时间', defaultVisible: true }, { key: 'code', label: '模板标识' }, { key: 'tenantId', label: '所属租户' }, { key: 'createdDept', label: '创建部门' }, { key: 'updatedBy', label: '修改人' }, { key: 'updatedAt', label: '修改时间' }, { key: 'recordVersion', label: '记录版本' }, { key: 'actions', label: '操作', locked: true }]);
21
+ const labels = { draft: '编辑中', review: '待审核', published: '已发布' }, canDelete = computed(() => session.can('workflow:delete'));
22
+ function toggle(r) { confirmAction({ title: (r.enabled ? '停用' : '启用') + r.body.name + '?', content: r.enabled ? '停用后不再供新的任务选择,历史版本与交接快照保留。' : '启用前将检查最新发布版本的配置与资源。', okText: r.enabled ? '确认停用' : '确认启用', cancelText: '取消', onOk: () => { try {
23
+ store.toggle(r.id, r.recordVersion);
24
+ message.success('模板状态已更新');
25
+ }
26
+ catch (e) {
27
+ error.value = e.message;
28
+ } } }); }
29
+ function action(key, r) { if (key === 'delete')
30
+ targets.value = [{ id: r.id, name: r.body.name, recordVersion: r.recordVersion }];
31
+ else if (key === 'toggle')
32
+ toggle(r);
33
+ else if (key === 'copy') {
34
+ try {
35
+ const copy = store.copy(r.id);
36
+ router.push('/workflows/' + copy.id + '/edit');
37
+ }
38
+ catch (e) {
39
+ error.value = e.message;
40
+ }
41
+ }
42
+ else
43
+ router.push('/workflows/' + r.id + (key === 'edit' ? '/edit' : key === 'versions' ? '?tab=versions' : key === 'audit' ? '?tab=records' : '')); }
44
+ function actions(r) { const allowed = (a) => session.can(('workflow:' + a), r.tenantId, r.pbcId); return h('div', { class: 'row-actions' }, [h(Button, { type: 'link', disabled: !allowed('edit') || r.state === 'review', onClick: () => action('edit', r) }, () => '编辑'), h(ListMore, { name: r.body.name, items: [{ key: 'detail', label: '查看详情' }, { key: 'versions', label: '版本与差异' }, { key: 'copy', label: '复制为新模板', disabled: !allowed('edit') }, { key: 'toggle', label: r.enabled ? '停用模板' : '启用模板', disabled: !allowed('status') || (!r.enabled && !r.versions.length) }, { key: 'audit', label: '操作记录', disabled: !allowed('audit') }, { key: 'delete', label: '删除模板', danger: true, disabled: !allowed('delete') }], onAction: (k) => action(k, r) })]); }
45
+ const table = useTable({ pageParam: { current: 1, pageSize: 5, total: 0 }, columns: prefs.choices.map(c => ({ key: c.key, title: c.label, dataIndex: c.key, width: c.key === 'name' ? 225 : c.key === 'actions' ? 130 : c.key.endsWith('At') ? 170 : c.key === 'project' ? 105 : ['state', 'enabled', 'version', 'createdBy'].includes(c.key) ? 90 : 125, fixed: c.key === 'actions' ? 'right' : undefined, ...(c.key === 'name' ? { render: (_, r) => h('div', [h(Button, { type: 'link', class: 'agent-name', onClick: () => router.push('/workflows/' + r.id) }, () => String(r.name)), h('small', { class: 'agent-code' }, () => String(r.code))]) } : c.key === 'actions' ? { render: (_, r) => actions(r) } : c.key === 'state' ? { render: (v) => h(Tag, { color: v === 'review' ? 'orange' : v === 'published' ? 'blue' : 'default' }, () => labels[v]) } : c.key === 'enabled' ? { render: (v) => h(Tag, { color: v ? 'green' : 'default' }, () => v ? '已启用' : '已停用') } : c.key === 'version' ? { render: (_, r) => r.versions.at(-1) ? 'v' + r.versions.at(-1).number : '未发布' } : c.key === 'tenantId' ? { render: (v) => tenantLabel(String(v)) } : c.key.endsWith('At') ? { render: (v) => formatDate(String(v)) } : {}) })) });
46
+ const columns = new Map(table.columns.value.map(c => [c.key, c]));
47
+ watch(prefs.keys, keys => table.columns.value = keys.map(k => columns.get(k)).filter(Boolean), { immediate: true });
48
+ const filtered = computed(() => store.scene === 'empty' ? [] : rows.value.filter(r => (r.name + r.code + r.body.description).toLowerCase().includes(query.value.trim().toLowerCase()) && (state.value === 'all' || r.state === state.value) && (project.value === 'all' || r.project === project.value)).sort((a, b) => desc.value ? b.createdAt.localeCompare(a.createdAt) : a.createdAt.localeCompare(b.createdAt)));
49
+ watch([filtered, () => table.pageParam.current, () => table.pageParam.pageSize], () => { const size = table.pageParam.pageSize || 5, max = Math.max(1, Math.ceil(filtered.value.length / size)); if ((table.pageParam.current || 1) > max)
50
+ table.setPageParam({ current: max }); const start = ((table.pageParam.current || 1) - 1) * size; table.dataSource.value = filtered.value.slice(start, start + size); table.setPageParam({ total: filtered.value.length }); }, { immediate: true });
51
+ const selection = useListSelection(table.dataSource, computed(() => JSON.stringify([session.key, query.value, state.value, project.value, desc.value, table.pageParam.current, table.pageParam.pageSize])), canDelete, r => r.name);
52
+ watch([query, state, project], () => table.setPageParam({ current: 1 }));
53
+ async function refresh() { selection.clear(); refreshing.value = true; await new Promise(r => setTimeout(r, 200)); store.scene = 'normal'; refreshing.value = false; }
54
+ return { computed, ref, watch, h, useRouter, Alert, Button, Input, Select, Space, Tag, message, ProTable, useTable, useWorkflows, useSession, formatDate, tenantLabel, useColumns, useListSelection, ListMore, ColumnSettings, ListBatchBar, ListDeleteDialog, confirmAction, store, session, router, query, state, project, desc, refreshing, targets, error, rows, prefs, labels, canDelete, toggle, action, actions, table, columns, filtered, selection, refresh };
55
+ } });
@@ -0,0 +1,16 @@
1
+ import { actors, metadata } from "../shared/policy.js";
2
+ export function standardBody() {
3
+ const nodes = [{ id: 'start', kind: 'start', name: '交付开始', x: 70, y: 60 }, { id: 'prototype', kind: 'human', name: '确认交互原型', gate: 'prototype', permission: 'workflow:approve', x: 340, y: 60 }, { id: 'build', kind: 'agent', name: '实现应用', agentId: 'agent-1', input: '已确认规格与原型', output: '代码与变更说明', x: 610, y: 60 }, { id: 'ci', kind: 'tool', name: '运行质量检查', tool: 'ci-check', input: '代码与测试清单', output: '检查报告', x: 880, y: 60 }, { id: 'verify', kind: 'verify', name: '独立验证产物', agentId: 'agent-2', input: '代码、规格与检查报告', output: '独立验证结论', x: 880, y: 260 }, { id: 'approval', kind: 'human', name: '批准生产发布', gate: 'production', permission: 'workflow:approve', x: 610, y: 260 }, { id: 'release', kind: 'publish', name: '发布已验证版本', x: 340, y: 260 }, { id: 'archive', kind: 'archive', name: '归档交付证据', x: 70, y: 260 }];
4
+ return { name: '供热工单 AI 应用交付', code: 'heating-ai-delivery', description: '从已确认的规格与原型出发,完成实现、验证、人工批准与交付归档。', nodes, edges: nodes.slice(0, -1).map((n, i) => ({ id: 'edge-' + i, from: n.id, to: nodes[i + 1].id, label: '' })) };
5
+ }
6
+ export function seedFlows() {
7
+ return ['供热工单 AI 应用交付', '服务接口交付草稿', '知识服务交付草稿', '轻量迭代草稿', '专项测试草稿', '北方巡检交付草稿'].map((name, i) => {
8
+ const body = standardBody();
9
+ body.name = name;
10
+ body.code = i ? 'delivery-template-' + i : body.code;
11
+ if (i === 5)
12
+ body.nodes.forEach(n => { if (n.agentId)
13
+ n.agentId = ''; });
14
+ return { ...metadata(actors[0], new Date(Date.UTC(2026, 8, 10, 12, 20 - i)).toISOString(), i === 5 ? 'north' : 'heating'), id: 'flow-' + i, pbcId: i === 5 ? 'pbc-6' : 'pbc-0', project: i === 5 ? '巡检管理' : '供热工单', body, versions: i ? [] : [{ number: 1, body: JSON.parse(JSON.stringify(body)), note: '标准交付流程示例', by: '王睿', at: '2026-09-10T12:30:00.000Z', submittedBy: '陈敏' }], state: i ? 'draft' : 'published', enabled: i === 0, draftBy: 'chen' };
15
+ });
16
+ }
@@ -0,0 +1,83 @@
1
+ export const clone = (x) => JSON.parse(JSON.stringify(x));
2
+ export const kinds = [{ value: 'agent', label: 'Agent 执行', mark: 'A' }, { value: 'human', label: '人工确认', mark: '人' }, { value: 'tool', label: '工具与 CI', mark: 'CI' }, { value: 'branch', label: '条件分支', mark: '◇' }, { value: 'loop', label: '有限修复', mark: '↻' }, { value: 'publish', label: '发布', mark: '↗' }, { value: 'archive', label: '归档', mark: '✓' }];
3
+ export const kindLabel = (n) => n.kind === 'start' ? '开始' : n.kind === 'verify' ? '独立验证' : kinds.find(k => k.value === n.kind)?.label || n.kind;
4
+ export const protectedNode = (n) => n.kind === 'start' || n.kind === 'verify' || !!n.gate;
5
+ export function basics(b) { if (!b.name.trim() || !b.code.trim())
6
+ throw Error('请填写模板名称和标识。'); if (!/^[a-z][a-z0-9-]{2,49}$/.test(b.code))
7
+ throw Error('模板标识须为 3–50 位小写字母、数字或连字符,字母开头。'); if (b.name.length > 80)
8
+ throw Error('模板名称不能超过 80 个字符。'); }
9
+ export function validateFlow(b, agents) {
10
+ const checks = [], nodes = b.nodes, edges = b.edges, ids = new Set(nodes.map(n => n.id));
11
+ const add = (id, ok, title, detail, nodeId) => checks.push({ id, ok, title, detail, nodeId });
12
+ add('identity', !!b.name.trim() && /^[a-z][a-z0-9-]{2,49}$/.test(b.code), '模板基本信息', '名称与标识完整且有效。');
13
+ const edgesValid = edges.every(e => ids.has(e.from) && ids.has(e.to) && e.from !== e.to) && new Set(edges.map(e => e.from + '|' + e.to + '|' + e.label)).size === edges.length;
14
+ add('structure', nodes.length > 0 && nodes.length <= 80 && ids.size === nodes.length && edgesValid && nodes.every(n => n.name.trim()), '节点与连线结构', '节点名称完整且 ID 唯一、连线端点有效;本原型最多 80 个节点。');
15
+ const starts = nodes.filter(n => n.kind === 'start'), ends = nodes.filter(n => n.kind === 'archive');
16
+ const outgoing = (id) => edges.filter(e => e.from === id && ids.has(e.to));
17
+ const reach = (from, skip) => { const seen = new Set(), todo = [from]; while (todo.length) {
18
+ const v = todo.pop();
19
+ if (v === skip || seen.has(v))
20
+ continue;
21
+ seen.add(v);
22
+ todo.push(...outgoing(v).map(e => e.to));
23
+ } return seen; };
24
+ const seen = starts.length === 1 ? reach(starts[0].id) : new Set();
25
+ const colors = new Map();
26
+ function visit(id) { if (colors.get(id) === 1)
27
+ return false; if (colors.get(id) === 2)
28
+ return true; colors.set(id, 1); for (const e of outgoing(id))
29
+ if (!visit(e.to))
30
+ return false; colors.set(id, 2); return true; }
31
+ const acyclic = nodes.every(n => visit(n.id));
32
+ add('cycle', acyclic, '有界执行', '普通连线不允许成环;返工须使用有次数上限的有限修复节点。');
33
+ add('connectivity', starts.length === 1 && ends.length > 0 && nodes.every(n => seen.has(n.id) && ends.some(e => reach(n.id).has(e.id))) && edges.every(e => e.to !== starts[0]?.id), '完整可达路径', '必须只有一个开始,全部节点从开始可达并能到达归档。');
34
+ for (const n of nodes) {
35
+ const out = outgoing(n.id);
36
+ add('ports-' + n.id, n.kind === 'branch' ? out.length === 2 && out.some(e => e.label === '满足') && out.some(e => e.label === '不满足') : n.kind === 'archive' ? out.length === 0 : out.length === 1, '出口 · ' + n.name, n.kind === 'branch' ? '分支必须有“满足”和“不满足”两个出口。' : n.kind === 'archive' ? '归档节点没有后续出口。' : '此节点应连接一个后续节点。', n.id);
37
+ if (['agent', 'verify', 'loop'].includes(n.kind)) {
38
+ const a = agents.find(a => a.id === n.agentId);
39
+ add('agent-' + n.id, !!a?.available, 'Agent · ' + n.name, a?.available ? a.name + ' · 配置与使用授权有效' : a?.reason || '请绑定本项目内可见的 Agent。', n.id);
40
+ }
41
+ if (['agent', 'verify', 'tool', 'loop'].includes(n.kind))
42
+ add('io-' + n.id, !!n.input?.trim() && !!n.output?.trim(), '产物 · ' + n.name, '请明确输入与输出产物名称;正式 schema/类型校验待实现。', n.id);
43
+ if (n.kind === 'tool')
44
+ add('tool-' + n.id, ['ci-check', 'contract-read'].includes(n.tool || ''), '工具 · ' + n.name, '从固定示例目录选择已登记工具或 CI。', n.id);
45
+ if (n.kind === 'branch')
46
+ add('condition-' + n.id, ['checks.passed', 'review.approved'].includes(n.condition || ''), '条件 · ' + n.name, '选择已登记的结果条件。', n.id);
47
+ if (n.kind === 'loop')
48
+ add('limit-' + n.id, Number.isInteger(n.limit) && n.limit > 0 && n.limit <= 10, '次数上限 · ' + n.name, '修复 1–10 次(原型候选范围),耗尽转人工处理;不能自动发布。', n.id);
49
+ if (n.kind === 'human')
50
+ add('human-' + n.id, n.permission === 'workflow:approve', '确认权限 · ' + n.name, '人工确认必须关联已登记的交付人工确认动作。', n.id);
51
+ }
52
+ const proto = nodes.filter(n => n.gate === 'prototype' && n.kind === 'human'), verify = nodes.filter(n => n.kind === 'verify'), approval = nodes.filter(n => n.gate === 'production' && n.kind === 'human'), publishes = nodes.filter(n => n.kind === 'publish');
53
+ const dominates = (gate, target) => !!gate && starts.length === 1 && seen.has(target.id) && !reach(starts[0].id, gate.id).has(target.id);
54
+ add('gates', proto.length === 1 && verify.length === 1 && approval.length === 1 && publishes.length > 0, '必要治理节点', '此交付模板必须包含一次原型确认、独立验证、生产人工批准及发布。');
55
+ add('prototype', proto.length === 1 && nodes.filter(n => ['agent', 'loop', 'tool', 'verify', 'publish'].includes(n.kind)).every(n => dominates(proto[0], n)), '原型确认先于实现', '实现与工具执行的所有路径必须先经过原型确认。');
56
+ add('release', verify.length === 1 && approval.length === 1 && dominates(verify[0], approval[0]) && publishes.every(n => dominates(verify[0], n) && dominates(approval[0], n)), '发布门禁不可旁路', '到达发布的所有路径必须先完成独立验证和生产人工批准,且顺序正确。');
57
+ const workers = nodes.filter(n => n.kind === 'agent' || n.kind === 'loop');
58
+ add('independent', verify.length === 1 && !!verify[0].agentId && workers.every(n => n.agentId !== verify[0].agentId), '独立验证配置', '验证 Agent 必须不同于实现和修复 Agent;运行上下文独立性仍需后端验证。');
59
+ add('after-verify', verify.length === 1 && nodes.filter(n => ['agent', 'loop', 'tool'].includes(n.kind)).every(n => !reach(verify[0].id).has(n.id)), '验证后产物保持不变', '验证之后不能再实现、修复或调用工具改写产物;修改必须回到新一轮验证。');
60
+ return checks;
61
+ }
62
+ export function assertRemovable(r, used) { if (r.enabled)
63
+ throw Error('请先停用模板。'); if (r.state === 'review')
64
+ throw Error('请先撤回配置审核。'); if (used)
65
+ throw Error('流程已有版本选择或交付任务引用,保留历史引用,不能删除。'); }
66
+ export function diffBodies(before, after) { const changes = []; for (const k of ['name', 'code', 'description'])
67
+ if (before[k] !== after[k])
68
+ changes.push(k === 'name' ? '模板名称:' + before[k] + ' → ' + after[k] : k === 'description' ? '更新用途说明' : '更新模板标识'); for (const n of after.nodes) {
69
+ const old = before.nodes.find(x => x.id === n.id);
70
+ if (!old)
71
+ changes.push('新增节点:' + n.name);
72
+ else if (JSON.stringify(old) !== JSON.stringify(n)) {
73
+ for (const k of [...new Set([...Object.keys(old), ...Object.keys(n)])])
74
+ if (old[k] !== n[k])
75
+ changes.push(n.name + ' · ' + ({ name: '名称', agentId: 'Agent', tool: '工具', input: '输入', output: '输出', limit: '修复上限', condition: '条件', permission: '权限', x: '横向位置', y: '纵向位置' }[k] || k) + ':' + String(old[k] ?? '未设置') + ' → ' + String(n[k] ?? '未设置'));
76
+ }
77
+ } for (const n of before.nodes)
78
+ if (!after.nodes.some(x => x.id === n.id))
79
+ changes.push('移除节点:' + n.name); const edgeLabel = (b, e) => (b.nodes.find(n => n.id === e.from)?.name || e.from) + ' → ' + (b.nodes.find(n => n.id === e.to)?.name || e.to) + (e.label ? '(' + e.label + ')' : ''); for (const e of after.edges)
80
+ if (!before.edges.some(x => x.from === e.from && x.to === e.to && x.label === e.label))
81
+ changes.push('新增连线:' + edgeLabel(after, e)); for (const e of before.edges)
82
+ if (!after.edges.some(x => x.from === e.from && x.to === e.to && x.label === e.label))
83
+ changes.push('移除连线:' + edgeLabel(before, e)); return changes; }