@givolt/i3-composer-agent 2.3.7 → 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 (497) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude/commands/i3-sop.md +19 -0
  3. package/.claude/commands/i3-ui-demo.md +21 -0
  4. package/.claude-plugin/marketplace.json +1 -1
  5. package/.claude-plugin/plugin.json +1 -1
  6. package/.codex-plugin/plugin.json +2 -2
  7. package/.gemini/commands/i3-sop.toml +19 -0
  8. package/.gemini/commands/i3-ui-demo.toml +21 -0
  9. package/README.md +42 -6
  10. package/bin/i3-composer-agent.cjs +38 -44
  11. package/bin/install.cjs +15 -3
  12. package/bin/native-layout.cjs +2 -1
  13. package/bin/native-migration.cjs +19 -2
  14. package/bin/retired-sop-fingerprints.json +213 -0
  15. package/bin/wizard.cjs +7 -18
  16. package/commands/i3-sop.toml +19 -0
  17. package/commands/i3-ui-demo.toml +21 -0
  18. package/docs/codebuddy-setup.md +20 -23
  19. package/docs/codex-setup.md +2 -2
  20. package/docs/comparison.md +131 -0
  21. package/docs/developer-onboarding.md +143 -0
  22. package/docs/opencode-setup.md +1 -1
  23. package/docs/other-hosts.md +2 -2
  24. package/docs/skill-anatomy.md +211 -0
  25. package/docs/upstream-repository/AGENTS.md +92 -0
  26. package/docs/upstream-repository/CLAUDE.md +60 -0
  27. package/docs/upstream-repository/CONTRIBUTING.md +137 -0
  28. package/docs/upstream-repository/README.md +8 -0
  29. package/docs/upstream-repository/gitattributes.txt +1 -0
  30. package/docs/upstream-repository/gitignore.txt +10 -0
  31. package/docs/upstream-repository/manifest.json +71 -0
  32. package/docs/upstream-repository/opencode-skills.link +1 -0
  33. package/docs/upstream-repository/skill-gap.yml +80 -0
  34. package/docs/upstream-repository/skills-contributing.md +15 -0
  35. package/docs/upstream-repository/test-plugin-install.yml +167 -0
  36. package/docs/workbuddy-setup.md +7 -10
  37. package/evals/cases/i3-enterprise-sop.json +64 -0
  38. package/evals/cases/i3-ui-demo.json +98 -0
  39. package/evals/fixtures/i3-enterprise-sop/brief.md +11 -0
  40. package/evals/fixtures/i3-ui-demo/asset-management.md +25 -0
  41. package/evals/zh-CN/cases/i3-enterprise-sop.json +61 -0
  42. package/evals/zh-CN/cases/i3-ui-demo.json +103 -0
  43. package/hooks/PROTOTYPE.md +16 -8
  44. package/hooks/i3-prototype.cjs +4 -10
  45. package/hooks/manage.cjs +30 -31
  46. package/package.json +48 -5
  47. package/plugin.json +1 -1
  48. package/scripts/ui-demo-dependencies-test.js +228 -0
  49. package/scripts/ui-demo-mcp-test.js +95 -0
  50. package/scripts/ui-demo-test.js +170 -0
  51. package/scripts/ui-prototype-execution-runtime-test.js +1 -1
  52. package/scripts/ui-prototype-native-test.js +25 -3
  53. package/skills/i3-enterprise-sop/SKILL.md +173 -0
  54. package/skills/i3-enterprise-sop/agents/openai.yaml +2 -0
  55. package/skills/i3-enterprise-sop/references/ad/assets-manifest.json +86 -0
  56. package/skills/i3-enterprise-sop/references/ad/prompts/01-generate.md +58 -0
  57. package/skills/i3-enterprise-sop/references/ad/prompts/02-review.md +54 -0
  58. package/skills/i3-enterprise-sop/references/ad/prompts/03-revise.md +54 -0
  59. package/skills/i3-enterprise-sop/references/ad/prompts/04-recheck.md +54 -0
  60. package/skills/i3-enterprise-sop/references/ad/readme.md +70 -0
  61. package/skills/i3-enterprise-sop/references/ad/templates/ad.md +337 -0
  62. package/skills/i3-enterprise-sop/references/assets-manifest.json +230 -0
  63. package/skills/i3-enterprise-sop/references/brd/assets-manifest.json +83 -0
  64. package/skills/i3-enterprise-sop/references/brd/prompts/01-generate.md +51 -0
  65. package/skills/i3-enterprise-sop/references/brd/prompts/02-review.md +47 -0
  66. package/skills/i3-enterprise-sop/references/brd/prompts/03-revise.md +47 -0
  67. package/skills/i3-enterprise-sop/references/brd/prompts/04-recheck.md +47 -0
  68. package/skills/i3-enterprise-sop/references/brd/readme.md +50 -0
  69. package/skills/i3-enterprise-sop/references/brd/templates/brd.md +169 -0
  70. package/skills/i3-enterprise-sop/references/codebuddy-project-guide.md +34 -0
  71. package/skills/i3-enterprise-sop/references/controlled-handoff.md +41 -0
  72. package/skills/i3-enterprise-sop/references/controlled_handoff.py +379 -0
  73. package/skills/i3-enterprise-sop/references/engineering-skeleton/adoption.md +200 -0
  74. package/skills/i3-enterprise-sop/references/engineering-skeleton/catalog.json +17 -0
  75. package/skills/i3-enterprise-sop/references/engineering-skeleton/directory-standard.md +119 -0
  76. package/skills/i3-enterprise-sop/references/engineering-skeleton/readme.md +52 -0
  77. package/skills/i3-enterprise-sop/references/handoff-contract.md +196 -0
  78. package/skills/i3-enterprise-sop/references/handoff.py +277 -0
  79. package/skills/i3-enterprise-sop/references/lifecycle-contract.md +91 -0
  80. package/skills/i3-enterprise-sop/references/plan-handoff.md +73 -0
  81. package/skills/i3-enterprise-sop/references/prd/assets-manifest.json +109 -0
  82. package/skills/i3-enterprise-sop/references/prd/prompts/01-generate.md +64 -0
  83. package/skills/i3-enterprise-sop/references/prd/prompts/02-review.md +49 -0
  84. package/skills/i3-enterprise-sop/references/prd/prompts/03-revise.md +48 -0
  85. package/skills/i3-enterprise-sop/references/prd/prompts/04-recheck.md +47 -0
  86. package/skills/i3-enterprise-sop/references/prd/readme.md +137 -0
  87. package/skills/i3-enterprise-sop/references/prd/template-contracts.md +39 -0
  88. package/skills/i3-enterprise-sop/references/prd/templates/ad.md +17 -0
  89. package/skills/i3-enterprise-sop/references/prd/templates/prd.md +257 -0
  90. package/skills/i3-enterprise-sop/references/readme.md +167 -0
  91. package/skills/i3-enterprise-sop/references/recovery-contract.md +65 -0
  92. package/skills/i3-enterprise-sop/references/review-handoff.md +105 -0
  93. package/skills/i3-enterprise-sop/references/selection-handoff.md +55 -0
  94. package/skills/i3-enterprise-sop/references/selection_handoff.py +225 -0
  95. package/skills/i3-enterprise-sop/references/stages.json +271 -0
  96. package/skills/i3-enterprise-sop/references/technical-baseline/assets-manifest.json +84 -0
  97. package/skills/i3-enterprise-sop/references/technical-baseline/baselines/enterprise-application-technical-baseline-v0-0-4.md +380 -0
  98. package/skills/i3-enterprise-sop/references/technical-baseline/readme.md +132 -0
  99. package/skills/i3-enterprise-sop/references/technical-baseline/templates/technical-baseline.md +133 -0
  100. package/skills/i3-enterprise-sop/references/template-contracts.md +142 -0
  101. package/skills/i3-enterprise-sop/references/testcase/assets-manifest.json +91 -0
  102. package/skills/i3-enterprise-sop/references/testcase/prompts/01-generate.md +53 -0
  103. package/skills/i3-enterprise-sop/references/testcase/prompts/02-review.md +51 -0
  104. package/skills/i3-enterprise-sop/references/testcase/prompts/03-revise.md +49 -0
  105. package/skills/i3-enterprise-sop/references/testcase/prompts/04-recheck.md +51 -0
  106. package/skills/i3-enterprise-sop/references/testcase/readme.md +61 -0
  107. package/skills/i3-enterprise-sop/references/testcase/templates/testcase.md +269 -0
  108. package/skills/i3-enterprise-sop/references/verification/check_execution.py +185 -0
  109. package/skills/i3-enterprise-sop/references/verification/check_native_execution.py +282 -0
  110. package/skills/i3-enterprise-sop/references/verification/check_reads.py +348 -0
  111. package/skills/i3-enterprise-sop/references/verification/readme.md +149 -0
  112. package/skills/i3-enterprise-sop/references/verification/review-output.schema.json +155 -0
  113. package/skills/i3-enterprise-sop/references/verification/review_handoff.py +329 -0
  114. package/skills/i3-ui-demo/SKILL.md +234 -0
  115. package/skills/i3-ui-demo/assets/antdv-build/package-lock.json +3363 -0
  116. package/skills/i3-ui-demo/assets/antdv-build/package.json +28 -0
  117. package/skills/i3-ui-demo/assets/design-source.json +11 -0
  118. package/skills/i3-ui-demo/assets/host-targets.json +739 -0
  119. package/skills/i3-ui-demo/assets/official-files.json +76 -0
  120. package/skills/i3-ui-demo/assets/starter/index.html +11 -0
  121. package/skills/i3-ui-demo/assets/starter/package-lock.json +2299 -0
  122. package/skills/i3-ui-demo/assets/starter/package.json +28 -0
  123. package/skills/i3-ui-demo/assets/starter/provenance.json +14 -0
  124. package/skills/i3-ui-demo/assets/starter/public/prototype-config.json +22 -0
  125. package/skills/i3-ui-demo/assets/starter/src/App.vue +64 -0
  126. package/skills/i3-ui-demo/assets/starter/src/PrototypeShell.vue +59 -0
  127. package/skills/i3-ui-demo/assets/starter/src/config.ts +23 -0
  128. package/skills/i3-ui-demo/assets/starter/src/domain/presentation.ts +30 -0
  129. package/skills/i3-ui-demo/assets/starter/src/domain/theme.ts +25 -0
  130. package/skills/i3-ui-demo/assets/starter/src/main.ts +18 -0
  131. package/skills/i3-ui-demo/assets/starter/src/style.css +26 -0
  132. package/skills/i3-ui-demo/assets/starter/tests/presentation.test.ts +23 -0
  133. package/skills/i3-ui-demo/assets/starter/tests/theme.test.ts +26 -0
  134. package/skills/i3-ui-demo/assets/starter/tsconfig.json +15 -0
  135. package/skills/i3-ui-demo/assets/starter/vite.config.ts +4 -0
  136. package/skills/i3-ui-demo/assets/templates/enterprise-admin/capability-definition.json +1395 -0
  137. package/skills/i3-ui-demo/assets/templates/enterprise-admin/component-inventory.json +707 -0
  138. package/skills/i3-ui-demo/assets/templates/enterprise-admin/design-system.md +26 -0
  139. package/skills/i3-ui-demo/assets/templates/enterprise-admin/generation.json +49 -0
  140. package/skills/i3-ui-demo/assets/templates/enterprise-admin/index.html +534 -0
  141. package/skills/i3-ui-demo/assets/templates/enterprise-admin/manifest.json +9 -0
  142. package/skills/i3-ui-demo/assets/templates/enterprise-admin/offline-build.json +265 -0
  143. package/skills/i3-ui-demo/assets/templates/enterprise-admin/offline.js +8888 -0
  144. package/skills/i3-ui-demo/assets/templates/enterprise-admin/origin.json +344 -0
  145. package/skills/i3-ui-demo/assets/templates/enterprise-admin/preset.json +928 -0
  146. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/app.js +22 -0
  147. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/assets/empty.svg +1 -0
  148. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/assets/reference-styles.json +1 -0
  149. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/assets/result-403.svg +1 -0
  150. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/assets/result-404.svg +1 -0
  151. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/assets-manifest.json +334 -0
  152. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/baseline.json +173 -0
  153. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/conversion.md +30 -0
  154. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/credits.md +17 -0
  155. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/design-tokens.json +881 -0
  156. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/index.html +28 -0
  157. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/licenses/@qin-ui-antdv-next-pro.txt +9 -0
  158. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/licenses/ant-design-icons.txt +22 -0
  159. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/licenses/antdv-next.txt +21 -0
  160. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/package.json +12 -0
  161. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/browser-routes.json +298 -0
  162. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/coverage.json +180 -0
  163. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/integrity.json +13 -0
  164. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/keyboard.json +11 -0
  165. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/responsive.json +125 -0
  166. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/review.md +51 -0
  167. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/rules.log +150 -0
  168. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/flow-editor-html.png +0 -0
  169. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/flow-editor-original.png +0 -0
  170. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/intent-create-html.png +0 -0
  171. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/intent-create-original.png +0 -0
  172. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/models-html.png +0 -0
  173. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/models-original.png +0 -0
  174. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/workbench-html.png +0 -0
  175. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/screenshots/workbench-original.png +0 -0
  176. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/selection.json +9 -0
  177. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/qa/visual-comparison.json +342 -0
  178. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/readme.md +73 -0
  179. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/reference.md +59 -0
  180. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/routes.json +178 -0
  181. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/controls.js +99 -0
  182. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/dialogs.js +54 -0
  183. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/dom.js +264 -0
  184. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/forms.js +47 -0
  185. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/icons.js +41 -0
  186. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/layout.js +47 -0
  187. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/router.js +63 -0
  188. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/state.js +90 -0
  189. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/table.js +41 -0
  190. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/runtime/widgets.js +8 -0
  191. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/AgentDetail.html +3 -0
  192. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/AgentDetail.js +36 -0
  193. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/AgentEditor.html +2 -0
  194. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/AgentEditor.js +51 -0
  195. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/AgentsPage.html +3 -0
  196. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/AgentsPage.js +48 -0
  197. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/CheckResults.html +2 -0
  198. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/CheckResults.js +6 -0
  199. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/ResourcePicker.html +2 -0
  200. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/ResourcePicker.js +13 -0
  201. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/data.js +24 -0
  202. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/domain.js +32 -0
  203. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/registry.js +25 -0
  204. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/agents/store.js +85 -0
  205. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentClose.html +2 -0
  206. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentClose.js +17 -0
  207. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentCreate.html +2 -0
  208. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentCreate.js +66 -0
  209. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentDecisions.html +3 -0
  210. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentDecisions.js +38 -0
  211. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentDetail.html +2 -0
  212. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentDetail.js +66 -0
  213. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentDocument.html +2 -0
  214. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentDocument.js +5 -0
  215. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentHeader.html +2 -0
  216. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentHeader.js +12 -0
  217. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentHistory.html +2 -0
  218. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentHistory.js +11 -0
  219. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentList.html +2 -0
  220. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentList.js +116 -0
  221. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentReplan.html +2 -0
  222. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentReplan.js +32 -0
  223. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentRevision.html +2 -0
  224. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentRevision.js +49 -0
  225. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentSummary.html +2 -0
  226. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentSummary.js +10 -0
  227. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentWorkspace.html +2 -0
  228. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/IntentWorkspace.js +77 -0
  229. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/data.js +60 -0
  230. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/domain.js +105 -0
  231. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/intents/store.js +212 -0
  232. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/AuditPanel.html +2 -0
  233. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/AuditPanel.js +18 -0
  234. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelDetail.html +2 -0
  235. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelDetail.js +23 -0
  236. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelEditor.html +2 -0
  237. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelEditor.js +78 -0
  238. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelGrant.html +2 -0
  239. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelGrant.js +55 -0
  240. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelReferences.html +2 -0
  241. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelReferences.js +26 -0
  242. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelRelease.html +2 -0
  243. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelRelease.js +38 -0
  244. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelStatus.html +2 -0
  245. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelStatus.js +7 -0
  246. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelTable.html +2 -0
  247. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelTable.js +72 -0
  248. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelTester.html +2 -0
  249. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelTester.js +46 -0
  250. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelsPage.html +2 -0
  251. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/ModelsPage.js +52 -0
  252. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/RowActions.html +2 -0
  253. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/RowActions.js +19 -0
  254. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/UsagePanel.html +2 -0
  255. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/UsagePanel.js +30 -0
  256. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/data.js +48 -0
  257. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/domain.js +39 -0
  258. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/models/store.js +129 -0
  259. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/IncidentDetail.html +4 -0
  260. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/IncidentDetail.js +21 -0
  261. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/IntentSource.html +2 -0
  262. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/IntentSource.js +8 -0
  263. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/OperationActionDialog.html +2 -0
  264. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/OperationActionDialog.js +37 -0
  265. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/OperationEntry.html +2 -0
  266. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/OperationEntry.js +10 -0
  267. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/OperationsPage.html +2 -0
  268. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/OperationsPage.js +37 -0
  269. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/RepairTrack.html +2 -0
  270. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/RepairTrack.js +49 -0
  271. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/RunDetail.html +4 -0
  272. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/RunDetail.js +22 -0
  273. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/SourceSummary.html +2 -0
  274. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/SourceSummary.js +9 -0
  275. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/commands.js +82 -0
  276. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/examples.js +47 -0
  277. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/model.js +61 -0
  278. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/repair.js +68 -0
  279. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/store.js +55 -0
  280. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/types.js +1 -0
  281. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/operations/workbench.js +18 -0
  282. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/ManagementTable.html +3 -0
  283. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/ManagementTable.js +28 -0
  284. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcCreateEntry.html +2 -0
  285. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcCreateEntry.js +18 -0
  286. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcDetail.html +2 -0
  287. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcDetail.js +31 -0
  288. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcEditor.html +2 -0
  289. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcEditor.js +27 -0
  290. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcLifecycle.html +2 -0
  291. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcLifecycle.js +16 -0
  292. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcPage.html +2 -0
  293. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcPage.js +43 -0
  294. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcPicker.html +4 -0
  295. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcPicker.js +34 -0
  296. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcProgress.html +2 -0
  297. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcProgress.js +30 -0
  298. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcWizard.html +3 -0
  299. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcWizard.js +67 -0
  300. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcWorkspace.html +2 -0
  301. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcWorkspace.js +41 -0
  302. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcsPage.html +2 -0
  303. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/PbcsPage.js +31 -0
  304. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/ServiceEditor.html +2 -0
  305. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/ServiceEditor.js +26 -0
  306. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/ServiceList.html +2 -0
  307. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/ServiceList.js +70 -0
  308. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/data.js +8 -0
  309. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/domain.js +62 -0
  310. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/management.js +36 -0
  311. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/managementStore.js +49 -0
  312. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/pbc/store.js +132 -0
  313. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/AdminList.html +2 -0
  314. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/AdminList.js +38 -0
  315. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/EffectiveGrants.html +2 -0
  316. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/EffectiveGrants.js +11 -0
  317. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/GrantEditor.html +2 -0
  318. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/GrantEditor.js +45 -0
  319. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/MemberEditor.html +2 -0
  320. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/MemberEditor.js +54 -0
  321. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/MembersPage.html +3 -0
  322. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/MembersPage.js +27 -0
  323. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/RecordsPage.html +2 -0
  324. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/RecordsPage.js +12 -0
  325. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/RoleEditor.html +2 -0
  326. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/RoleEditor.js +45 -0
  327. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/RolesPage.html +3 -0
  328. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/RolesPage.js +38 -0
  329. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/domain.js +61 -0
  330. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/state.js +51 -0
  331. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/permissions/store.js +116 -0
  332. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseActionDialog.html +2 -0
  333. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseActionDialog.js +45 -0
  334. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseDetail.html +4 -0
  335. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseDetail.js +30 -0
  336. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseEditor.html +2 -0
  337. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseEditor.js +67 -0
  338. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseExecution.html +2 -0
  339. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleaseExecution.js +5 -0
  340. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleasesPage.html +4 -0
  341. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/ReleasesPage.js +60 -0
  342. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/commands.js +157 -0
  343. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/model.js +136 -0
  344. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/releases/store.js +76 -0
  345. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewDetail.html +3 -0
  346. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewDetail.js +26 -0
  347. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewEvidence.html +2 -0
  348. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewEvidence.js +14 -0
  349. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewProcess.html +2 -0
  350. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewProcess.js +113 -0
  351. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewsPage.html +3 -0
  352. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/ReviewsPage.js +62 -0
  353. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/commands.js +97 -0
  354. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/model.js +147 -0
  355. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/reviews/store.js +13 -0
  356. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ColumnSettings.html +2 -0
  357. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ColumnSettings.js +9 -0
  358. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ListBatchBar.html +2 -0
  359. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ListBatchBar.js +8 -0
  360. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ListDeleteDialog.html +2 -0
  361. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ListDeleteDialog.js +37 -0
  362. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ListMore.html +2 -0
  363. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/ListMore.js +8 -0
  364. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/RecordMetadata.html +2 -0
  365. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/RecordMetadata.js +17 -0
  366. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/columns.js +32 -0
  367. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/deliveryGuide.js +49 -0
  368. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/deliveryView.js +12 -0
  369. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/listBatch.js +15 -0
  370. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/listSelection.js +37 -0
  371. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/policy.js +68 -0
  372. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shared/session.js +44 -0
  373. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/ConfirmationDialog.html +2 -0
  374. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/ConfirmationDialog.js +25 -0
  375. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/ConsoleShell.html +2 -0
  376. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/ConsoleShell.js +53 -0
  377. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/PrototypeGuide.html +10 -0
  378. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/PrototypeGuide.js +30 -0
  379. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/ScopePage.html +2 -0
  380. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/ScopePage.js +10 -0
  381. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/SessionDialog.html +2 -0
  382. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/SessionDialog.js +9 -0
  383. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/confirmation.js +3 -0
  384. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/shell/navigation.js +19 -0
  385. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecDocument.html +2 -0
  386. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecDocument.js +8 -0
  387. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecEdit.html +2 -0
  388. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecEdit.js +32 -0
  389. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecHeader.html +2 -0
  390. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecHeader.js +15 -0
  391. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecHistory.html +2 -0
  392. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecHistory.js +11 -0
  393. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecReview.html +2 -0
  394. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecReview.js +57 -0
  395. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecWorkspace.html +2 -0
  396. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/SpecWorkspace.js +37 -0
  397. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/data.js +20 -0
  398. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/domain.js +55 -0
  399. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/specs/store.js +151 -0
  400. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/ArtifactDetail.html +3 -0
  401. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/ArtifactDetail.js +18 -0
  402. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TaskCreate.html +2 -0
  403. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TaskCreate.js +40 -0
  404. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TaskDetail.html +2 -0
  405. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TaskDetail.js +51 -0
  406. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TaskLaunch.html +2 -0
  407. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TaskLaunch.js +9 -0
  408. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TasksPage.html +5 -0
  409. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/TasksPage.js +48 -0
  410. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/domain.js +204 -0
  411. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/exampleSource.js +22 -0
  412. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/registry.js +135 -0
  413. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/tasks/store.js +137 -0
  414. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workbench/WorkbenchPage.html +3 -0
  415. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workbench/WorkbenchPage.js +36 -0
  416. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workbench/model.js +56 -0
  417. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workbench/store.js +15 -0
  418. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/FlowCanvas.html +2 -0
  419. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/FlowCanvas.js +27 -0
  420. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/FlowDetail.html +4 -0
  421. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/FlowDetail.js +31 -0
  422. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/FlowEditor.html +2 -0
  423. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/FlowEditor.js +68 -0
  424. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/WorkflowsPage.html +5 -0
  425. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/WorkflowsPage.js +55 -0
  426. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/data.js +16 -0
  427. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/domain.js +83 -0
  428. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/registry.js +18 -0
  429. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/src/workflows/store.js +61 -0
  430. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/admin.css +60 -0
  431. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/agents.css +46 -0
  432. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/antdv.css +295 -0
  433. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/app.css +102 -0
  434. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/delivery.css +4 -0
  435. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/intents.css +37 -0
  436. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/native.css +22 -0
  437. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/operations.css +2 -0
  438. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/pbc.css +3 -0
  439. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/permissions.css +22 -0
  440. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/pro.css +1 -0
  441. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/releases.css +4 -0
  442. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/reset.css +246 -0
  443. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/reviews.css +8 -0
  444. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/tasks.css +6 -0
  445. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/tokens.css +15 -0
  446. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/workbench.css +61 -0
  447. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/styles/workflows.css +1 -0
  448. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/admin-rules.test.js +96 -0
  449. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/agents.test.js +14 -0
  450. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/intent-state.test.js +37 -0
  451. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/list-batch.test.js +44 -0
  452. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/operation-fixtures.js +19 -0
  453. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/operation-repair.test.js +14 -0
  454. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/operations.test.js +25 -0
  455. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/pbc-management.test.js +17 -0
  456. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/pbc-state.test.js +24 -0
  457. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/permission-config.test.js +23 -0
  458. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/permissions.test.js +24 -0
  459. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/releases.test.js +50 -0
  460. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/reviews.test.js +36 -0
  461. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/runtime-forms-router.test.js +28 -0
  462. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/runtime-state.test.js +42 -0
  463. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/runtime-stores.test.js +16 -0
  464. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/spec-state.test.js +11 -0
  465. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/tasks.test.js +27 -0
  466. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/workbench.test.js +34 -0
  467. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tests/workflows.test.js +16 -0
  468. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tools/convert.mjs +168 -0
  469. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tools/serve.mjs +7 -0
  470. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tools/styles.mjs +11 -0
  471. package/skills/i3-ui-demo/assets/templates/enterprise-admin/reference/tools/verify.mjs +24 -0
  472. package/skills/i3-ui-demo/assets/templates/enterprise-admin/serve.cjs +16 -0
  473. package/skills/i3-ui-demo/assets/templates/enterprise-admin/template-inventory.json +28791 -0
  474. package/skills/i3-ui-demo/assets/templates/enterprise-admin/template.json +9 -0
  475. package/skills/i3-ui-demo/assets/templates/enterprise-admin/usability.css +44 -0
  476. package/skills/i3-ui-demo/assets/templates.json +10 -0
  477. package/skills/i3-ui-demo/assets/versions.json +20 -0
  478. package/skills/i3-ui-demo/readme.md +350 -0
  479. package/skills/i3-ui-demo/references/browser.md +71 -0
  480. package/skills/i3-ui-demo/references/dependencies.md +67 -0
  481. package/skills/i3-ui-demo/references/resources.md +142 -0
  482. package/skills/i3-ui-demo/scripts/dependencies.cjs +364 -0
  483. package/skills/i3-ui-demo/scripts/design-install.cjs +105 -0
  484. package/skills/i3-ui-demo/scripts/design-provider.cjs +57 -0
  485. package/skills/i3-ui-demo/scripts/locations.cjs +52 -0
  486. package/skills/i3-ui-demo/scripts/mcp.cjs +112 -0
  487. package/skills/i3-ui-demo/scripts/provider-discovery.cjs +131 -0
  488. package/skills/i3-ui-demo/scripts/resources.cjs +283 -0
  489. package/skills/i3-ui-prototype/SKILL.md +1 -1
  490. package/skills/i3-ui-prototype/references/execution-evidence.md +12 -56
  491. package/skills/i3-ui-prototype/scripts/codebuddy-registration.cjs +1 -1
  492. package/skills/i3-ui-prototype/scripts/execution-runtime.cjs +5 -2
  493. package/skills/i3-ui-prototype/scripts/hosts/codebuddy.cjs +3 -2
  494. package/skills/i3-ui-prototype/scripts/native-delivery.cjs +2 -2
  495. package/skills/i3-ui-prototype/scripts/prototype-hooks.cjs +23 -20
  496. package/docs/ui-prototype-native/MAIN-SESSION-REPORT.md +0 -66
  497. package/docs/ui-prototype-native/USAGE.md +0 -93
@@ -0,0 +1,61 @@
1
+ import { can } from "../shared/policy.js";
2
+ export const clone = (value) => JSON.parse(JSON.stringify(value));
3
+ export function resolveActor(base, state) {
4
+ const roleIds = new Set(state.members.filter(m => m.actorId === base.id && !m.isDeleted).flatMap(m => m.roleIds));
5
+ const roles = state.roles.filter(r => roleIds.has(r.id) && r.enabled && !r.isDeleted);
6
+ return { ...base, label: roles.map(r => r.name).join('、') || '未分配业务角色', grants: roles.flatMap(r => r.grants.map(g => ({ ...clone(g), id: r.id + ':' + g.id, name: r.name + ' / ' + g.name }))) };
7
+ }
8
+ const subset = (values, allowed) => allowed.includes('*') || values.every(v => v !== '*' && allowed.includes(v));
9
+ export function checkDelegation(actor, role) {
10
+ if (!can(actor, 'permission:grant', role.tenantId))
11
+ throw Error('没有配置权限,或对象超出管理范围。');
12
+ for (const g of role.grants) {
13
+ if (!g.name.trim())
14
+ throw Error('请填写授权组名称。');
15
+ if (g.environmentIds && (!g.environmentIds.length || g.environmentIds.some(e => !['*', 'staging', 'production'].includes(e))))
16
+ throw Error('请选择有效的目标环境范围。');
17
+ if (!g.actions.length || !g.tenantIds.length || !g.pbcIds?.length)
18
+ throw Error('每个授权组都需要选择功能、租户和 PBC 范围。');
19
+ if (role.tenantId !== 'platform' && g.tenantIds.some(t => t !== role.tenantId))
20
+ throw Error('租户角色的授权不能超出所属租户。');
21
+ if (!actor.grants.some(a => a.actions.includes('permission:grant') && subset(g.tenantIds, a.tenantIds) && subset(g.pbcIds, a.pbcIds || ['*']) && subset(g.environmentIds || ['*'], a.environmentIds || ['*'])))
22
+ throw Error('拟授出的权限范围超出可管理范围。');
23
+ if (g.actions.some(a => a.startsWith('permission:')) && !actor.grants.some(a => a.actions.includes('permission:delegate') && subset(g.tenantIds, a.tenantIds) && subset(g.pbcIds, a.pbcIds || ['*'])))
24
+ throw Error('没有转授权限管理能力的授权。');
25
+ }
26
+ }
27
+ export function assertVersion(record, expected) {
28
+ if (!record || record.isDeleted)
29
+ throw Error('记录已不存在,请刷新。');
30
+ if (record.recordVersion !== expected)
31
+ throw Error('记录已被更新,请重新打开并核对最新内容。');
32
+ }
33
+ export function validateRole(role, roles) {
34
+ if (!role.name.trim() || role.name.length > 40 || !role.description.trim())
35
+ throw Error('请填写角色名称与用途说明,名称不超过 40 个字符。');
36
+ if (!/^[a-z][a-z0-9-]{1,39}$/.test(role.code))
37
+ throw Error('角色编码使用 2—40 位小写字母、数字或短横线,以字母开头。');
38
+ if (roles.some(r => r.id !== role.id && !r.isDeleted && r.tenantId === role.tenantId && r.code === role.code))
39
+ throw Error('所属范围内的角色编码已存在。');
40
+ }
41
+ export function deletableRole(role, members) {
42
+ if (role.protected)
43
+ throw Error('系统引导角色受保护,不能删除。');
44
+ const count = members.filter(m => !m.isDeleted && m.roleIds.includes(role.id)).length;
45
+ if (count)
46
+ throw Error('仍有关联成员 ' + count + ' 人,请先调整成员授权。');
47
+ }
48
+ export function checkMembership(actor, member, roles, before) {
49
+ if (!can(actor, 'permission:members', member.tenantId))
50
+ throw Error('没有成员管理权限,或对象超出管理范围。');
51
+ if (!member.roleIds.length)
52
+ throw Error('请选择至少一个角色;取消全部授权请使用移除业务关联。');
53
+ if (before?.roleIds.some(id => roles.find(r => r.id === id)?.protected && !member.roleIds.includes(id)))
54
+ throw Error('系统引导管理员关联受保护。');
55
+ for (const id of member.roleIds) {
56
+ const role = roles.find(r => r.id === id && !r.isDeleted && r.enabled && r.tenantId === member.tenantId);
57
+ if (!role)
58
+ throw Error('角色已停用、不存在或所属范围不同。');
59
+ checkDelegation(actor, role);
60
+ }
61
+ }
@@ -0,0 +1,51 @@
1
+ import { reactive } from '../../runtime/state.js';
2
+ import { actors, metadata, actionGroups } from "../shared/policy.js";
3
+ import { clone } from "./domain.js";
4
+ export const authorityKey = 'i3-prototype-antdv-v010-authority';
5
+ export function seedAuthority() {
6
+ const at = '2026-09-10T08:00:00.000Z', admin = actors[0], roles = [], members = [];
7
+ for (const actor of actors) {
8
+ for (const g of actor.grants.filter(g => g.actions.length)) {
9
+ const tenantId = g.tenantIds.includes('*') || g.tenantIds.includes('platform') ? 'platform' : actor.tenantId;
10
+ const id = 'role-' + actor.id + '-' + g.id;
11
+ roles.push({ ...metadata(admin, at, tenantId), id, name: g.name, code: actor.id + '-' + g.id, description: '沿用业务原型的示例角色,可按管理权限调整。', enabled: true, protected: false, grants: [{ ...clone(g), pbcIds: g.pbcIds || ['*'] }] });
12
+ let m = members.find(m => m.actorId === actor.id && m.tenantId === tenantId);
13
+ if (!m) {
14
+ m = { ...metadata(admin, at, tenantId), id: actor.id + ':' + tenantId, actorId: actor.id, roleIds: [] };
15
+ members.push(m);
16
+ }
17
+ m.roleIds.push(id);
18
+ }
19
+ }
20
+ const management = actionGroups.find(g => g.name === '权限管理').items.map(i => i.value);
21
+ roles.unshift({ ...metadata(admin, at, 'platform'), id: 'system-admin', name: '权限管理员', code: 'permission-admin', description: '管理平台及授权范围内的业务权限;原型引导角色。', enabled: true, protected: true, grants: [{ id: 'admin', name: '权限管理', actions: management, tenantIds: ['*'], pbcIds: ['*'] }] });
22
+ members.find(m => m.actorId === admin.id && m.tenantId === 'platform').roleIds.push('system-admin');
23
+ roles.push({ ...metadata(admin, at, 'heating'), id: 'heating-manager', name: '供热权限维护员', code: 'heating-access-manager', description: '只能维护供热范围的业务授权,不能转授管理权限。', enabled: true, protected: false, grants: [{ id: 'limited', name: '供热管理范围', actions: management.filter(a => a !== 'permission:delegate'), tenantIds: ['heating'], pbcIds: ['*'] }] });
24
+ return { version: 1, roles, members, records: [] };
25
+ }
26
+ let initial = seedAuthority();
27
+ try {
28
+ const saved = JSON.parse(localStorage.getItem(authorityKey) || 'null');
29
+ if (saved?.version && Array.isArray(saved.roles) && Array.isArray(saved.members) && Array.isArray(saved.records))
30
+ initial = saved;
31
+ }
32
+ catch { /* Resettable local prototype. */ }
33
+ export const authority = reactive(initial);
34
+ export function persistAuthority(next) {
35
+ try {
36
+ localStorage.setItem(authorityKey, JSON.stringify(next));
37
+ }
38
+ catch {
39
+ throw Error('浏览器无法保存本次授权,原权限保持不变。');
40
+ }
41
+ Object.assign(authority, next);
42
+ }
43
+ if (typeof window !== 'undefined')
44
+ window.addEventListener('storage', event => { if (event.key === authorityKey && event.newValue) {
45
+ try {
46
+ const data = JSON.parse(event.newValue);
47
+ if (data.version > authority.version)
48
+ Object.assign(authority, data);
49
+ }
50
+ catch { /* invalid local event ignored */ }
51
+ } });
@@ -0,0 +1,116 @@
1
+ import { computed, ref } from '../../runtime/state.js';
2
+ import { defineStore } from "../../runtime/state.js";
3
+ import { useSession } from "../shared/session.js";
4
+ import { actors, metadata, actionGroups, tenantLabel } from "../shared/policy.js";
5
+ import { authority, persistAuthority, seedAuthority } from "./state.js";
6
+ import { clone, resolveActor, validateRole, checkDelegation, checkMembership, deletableRole, assertVersion } from "./domain.js";
7
+ import { assertBatch } from "../shared/listBatch.js";
8
+ export const useAuthority = defineStore('authority', () => {
9
+ const session = useSession(), scene = ref('normal');
10
+ const roles = computed(() => authority.roles.filter(r => !r.isDeleted && session.can('permission:view', r.tenantId)));
11
+ const members = computed(() => authority.members.filter(m => !m.isDeleted && session.can('permission:view', m.tenantId)));
12
+ const records = computed(() => authority.records.filter(r => session.can('permission:audit', r.tenantId)));
13
+ const actorName = (id) => actors.find(a => a.id === id)?.name || id;
14
+ const roleName = (id) => authority.roles.find(r => r.id === id)?.name || id;
15
+ const touch = (r) => ({ ...r, recordVersion: r.recordVersion + 1, updatedBy: session.actor.name, updatedAt: new Date().toISOString() });
16
+ function describe(value) {
17
+ if (value === null || value === undefined)
18
+ return '无';
19
+ if (Array.isArray(value))
20
+ return value.length ? value.map(describe).join('\n\n') : '无';
21
+ if (typeof value !== 'object')
22
+ return String(value);
23
+ const v = value;
24
+ if (Array.isArray(v.actions))
25
+ return String(v.name) + ':' + v.actions.map(a => actionGroups.flatMap(g => g.items).find(i => i.value === a)?.label || a).join('、') + '\n范围:' + v.tenantIds.map(t => t === '*' ? '全部范围' : tenantLabel(t)).join('、') + '\nPBC:' + (v.pbcIds || ['*']).map(p => p === '*' ? '全部 PBC(含新建)' : ['供热工单', '客户服务', '能源台账', '知识助手', '运营报表', '收费管理', '巡检管理'][Number(p.replace('pbc-', ''))] || p).join('、');
26
+ const labels = { name: '名称', description: '用途说明', enabled: '角色状态', isDeleted: '业务记录已移除', member: '成员', roles: '关联角色' };
27
+ return Object.entries(v).filter(([k]) => k !== 'id').map(([k, x]) => (labels[k] || k) + ':' + (typeof x === 'boolean' ? (k === 'enabled' ? (x ? '启用' : '停用') : (x ? '是' : '否')) : describe(x))).join('\n');
28
+ }
29
+ function apply(operation, target, tenantId, reason, before, after, mutate) {
30
+ if (!reason.trim())
31
+ throw Error('请填写变更原因。');
32
+ session.writeCheck();
33
+ const next = clone(authority);
34
+ mutate(next);
35
+ next.version++;
36
+ next.records.unshift({ id: crypto.randomUUID(), actorId: session.actor.id, actorName: session.actor.name, at: new Date().toISOString(), tenantId, target, operation, reason, before: describe(before), after: describe(after) });
37
+ persistAuthority(next);
38
+ }
39
+ function saveRole(input, reason) {
40
+ const old = authority.roles.find(r => r.id === input.id);
41
+ session.require('permission:roles', input.tenantId);
42
+ if (old) {
43
+ session.require('permission:roles', old.tenantId);
44
+ assertVersion(old, input.recordVersion);
45
+ if (old.protected)
46
+ throw Error('系统引导角色受保护。');
47
+ if (input.tenantId !== old.tenantId || input.code !== old.code)
48
+ throw Error('角色创建后编码和所属范围不可修改。');
49
+ }
50
+ validateRole(input, authority.roles);
51
+ const fields = { name: input.name.trim(), code: input.code, description: input.description.trim() };
52
+ const next = old ? { ...touch(old), ...fields } : { ...metadata(session.actor, new Date().toISOString(), input.tenantId), ...fields, id: input.id, grants: [], enabled: true, protected: false };
53
+ apply(old ? '编辑角色' : '新增角色', input.name, input.tenantId, reason, old ? { name: old.name, description: old.description } : null, fields, s => { const i = s.roles.findIndex(r => r.id === next.id); if (i < 0)
54
+ s.roles.push(next);
55
+ else
56
+ s.roles[i] = next; });
57
+ }
58
+ function saveGrants(input, reason) {
59
+ const old = authority.roles.find(r => r.id === input.id);
60
+ assertVersion(old, input.recordVersion);
61
+ session.require('permission:grant', old.tenantId);
62
+ if (old.protected)
63
+ throw Error('系统引导角色受保护。');
64
+ const next = { ...touch(old), grants: clone(input.grants) };
65
+ checkDelegation(session.actor, next);
66
+ apply('配置权限', old.name, old.tenantId, reason, old.grants, next.grants, s => { s.roles[s.roles.findIndex(r => r.id === input.id)] = next; });
67
+ }
68
+ function toggleRole(role, reason) {
69
+ const old = authority.roles.find(r => r.id === role.id);
70
+ assertVersion(old, role.recordVersion);
71
+ session.require('permission:roles', old.tenantId);
72
+ if (old.protected)
73
+ throw Error('系统引导角色受保护。');
74
+ const next = { ...touch(old), enabled: !old.enabled };
75
+ apply(next.enabled ? '启用角色' : '停用角色', old.name, old.tenantId, reason, { enabled: old.enabled }, { enabled: next.enabled }, s => { s.roles[s.roles.findIndex(r => r.id === role.id)] = next; });
76
+ }
77
+ function sameScope(rows) { if (new Set(rows.map(r => r.tenantId)).size > 1)
78
+ throw Error('请按同一所属范围筛选后批量操作。'); }
79
+ function checkDeleteRole(t) { assertBatch(authority.roles, [t], r => { session.require('permission:delete', r.tenantId); deletableRole(r, authority.members); }); }
80
+ function deleteRoles(targets) {
81
+ const rows = assertBatch(authority.roles, targets, r => { session.require('permission:delete', r.tenantId); deletableRole(r, authority.members); });
82
+ sameScope(rows);
83
+ apply('删除角色', rows.map(r => r.name).join('、'), rows[0].tenantId, '确认删除所选角色', rows.map(r => ({ id: r.id, name: r.name })), { isDeleted: true }, s => { for (const row of rows)
84
+ s.roles[s.roles.findIndex(r => r.id === row.id)] = { ...touch(row), isDeleted: true }; });
85
+ }
86
+ function saveMember(input, reason) {
87
+ const old = authority.members.find(m => m.id === input.id);
88
+ session.require('permission:members', input.tenantId);
89
+ if (old && !old.isDeleted)
90
+ assertVersion(old, input.recordVersion);
91
+ if (!actors.some(a => a.id === input.actorId))
92
+ throw Error('身份目录中没有该成员。');
93
+ if (old && (old.actorId !== input.actorId || old.tenantId !== input.tenantId))
94
+ throw Error('成员和所属范围不可更换。');
95
+ if (authority.members.some(m => !m.isDeleted && m.id !== input.id && m.actorId === input.actorId && m.tenantId === input.tenantId))
96
+ throw Error('该成员在此范围已有关联,请编辑现有授权。');
97
+ checkMembership(session.actor, input, authority.roles, old);
98
+ const next = old ? { ...touch(old), roleIds: [...new Set(input.roleIds)], isDeleted: false } : { ...metadata(session.actor, new Date().toISOString(), input.tenantId), id: input.id, actorId: input.actorId, roleIds: [...new Set(input.roleIds)] };
99
+ apply(old && !old.isDeleted ? '修改成员授权' : '添加成员关联', actorName(input.actorId), input.tenantId, reason, old ? old.roleIds.map(roleName) : [], next.roleIds.map(roleName), s => { const i = s.members.findIndex(m => m.id === next.id); if (i < 0)
100
+ s.members.push(next);
101
+ else
102
+ s.members[i] = next; });
103
+ }
104
+ function checkDeleteMember(t) { assertBatch(authority.members, [t], m => { session.require('permission:delete', m.tenantId); session.require('permission:members', m.tenantId); if (m.roleIds.some(id => authority.roles.find(r => r.id === id)?.protected))
105
+ throw Error('系统引导管理员关联受保护。'); }); }
106
+ function deleteMembers(targets) {
107
+ targets.forEach(checkDeleteMember);
108
+ const rows = assertBatch(authority.members, targets, () => { });
109
+ sameScope(rows);
110
+ apply('移除成员关联', rows.map(m => actorName(m.actorId)).join('、'), rows[0].tenantId, '确认移除业务关联,保留身份账号', rows.map(m => ({ member: actorName(m.actorId), roles: m.roleIds.map(roleName) })), { isDeleted: true }, s => { for (const row of rows)
111
+ s.members[s.members.findIndex(m => m.id === row.id)] = { ...touch(row), isDeleted: true }; });
112
+ }
113
+ function effective(actorId, tenantId) { session.require('permission:view', tenantId); return resolveActor(actors.find(a => a.id === actorId), { ...authority, members: authority.members.filter(m => m.tenantId === tenantId) }); }
114
+ function reset() { const next = seedAuthority(); next.version = authority.version + 1; persistAuthority(next); scene.value = 'normal'; }
115
+ return { roles, members, records, scene, actorName, roleName, saveRole, saveGrants, toggleRole, checkDeleteRole, deleteRoles, saveMember, checkDeleteMember, deleteMembers, effective, reset };
116
+ });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/releases/ReleaseActionDialog.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <template data-component="Modal" data-bind-open="(true)" data-bind-title="(actionLabels[action])" data-bind-width="(650)" data-bind-mask-closable="(false)" data-on-cancel="(emit('close'))"><div class="release-note"><strong>{{ (v.name) }} · {{ (v.version) }}</strong><p>{{ (environmentLabel(v.environment)) }} · 发布单修订 v{{ (v.number) }} · 配置 {{ (v.config) }}</p><p>制品 {{ (v.materials?.digest || '缺失') }} · 首次灰度 {{ (v.traffic) }}%</p></div><template data-component="Alert" data-if="(action === 'approve')" type="warning" show-icon="" data-bind-title="('此授权仅覆盖本版本在' + environmentLabel(v.environment) + '的首次灰度及后续全量')" description="变更制品、配置、环境或灰度方案后,必须重新检查和人工授权。" class="page-alert"></template><template data-component="Alert" data-if="(['rollback', 'stop'].includes(action))" class="page-alert" type="warning" show-icon="" data-bind-title="(action === 'rollback' ? '目标稳定版本:' + (v.materials?.rollback?.version || '无') : '停止本次发布并撤除本版本流量')" description="应用恢复不会自动还原数据库;按本版迁移与恢复方案单独核查。"></template><template data-component="Alert" data-if="(stale)" type="warning" show-icon="" title="记录已变化,操作说明保留"><template data-slot="action"><template data-component="Button" data-on-click="(rebase)">已核对当前版本</template></template></template><template data-component="Alert" data-if="(reason || error)" type="error" show-icon="" data-bind-title="(error || reason)" class="page-alert"></template><template data-component="ProForm" name="release-action" data-bind-form="(form)" layout="vertical" data-bind-disabled="(busy)"></template><template data-component="Checkbox" data-if="(action === 'approve')" data-model-checked="(checked)">已核对本版证据、目标环境、灰度阈值及恢复方案</template><p class="muted">关闭后保留本账号的说明;登录失效或版本变化时不会自动提交。</p><template data-slot="footer"><template data-component="Space" wrap=""><template data-component="Button" data-on-click="(emit('close'))">取消并保留说明</template><template data-component="Button" type="primary" data-bind-danger="(['rollback', 'stop'].includes(action))" data-bind-loading="(busy)" data-bind-disabled="(!!reason || stale || (action === 'approve' &amp;&amp; !checked))" data-on-click="(submit)">{{ (actionLabels[action]) }}</template></template></template></template>
@@ -0,0 +1,45 @@
1
+ import { computed, ref, watch } from '../../runtime/state.js';
2
+ import { Alert, Button, Checkbox, Modal, Space } from "../../runtime/widgets.js";
3
+ import { ProForm, useForm } from "../../runtime/widgets.js";
4
+ import { useReleases } from "./store.js";
5
+ import { actionLabels, versionOf, environmentLabel } from "./model.js";
6
+ import { createComponent } from '../../runtime/dom.js';
7
+ export default createComponent({ name: 'ReleaseActionDialog', propKeys: ["row", "action", "outcome"], template: new URL('./ReleaseActionDialog.html', import.meta.url).href, setup(__props, __emit) {
8
+ const props = __props, emit = __emit, store = useReleases(), busy = ref(false), error = ref(''), checked = ref(false);
9
+ const storage = 'i3-prototype-antdv-release-action:' + store.session.actor.id + ':' + props.row.id + ':' + props.action;
10
+ let saved;
11
+ try {
12
+ saved = JSON.parse(sessionStorage.getItem(storage) || 'null');
13
+ }
14
+ catch {
15
+ saved = null;
16
+ }
17
+ const expected = ref(saved?.expected ?? props.row.recordVersion), id = ref(saved?.id || crypto.randomUUID());
18
+ const form = useForm({ note: saved?.note || '' }, [{ path: 'note', label: '操作说明', component: 'textarea', span: 24, rows: 3, maxlength: 2000, rules: ['approve', 'return', 'pause', 'resume', 'retry', 'rollback', 'stop'].includes(props.action) ? [{ required: true, whitespace: true, message: '请填写操作说明' }] : [] }]);
19
+ const fresh = computed(() => store.find(props.row.id)), v = computed(() => versionOf(fresh.value?.release || props.row.release)), stale = computed(() => fresh.value?.recordVersion !== expected.value), reason = computed(() => fresh.value ? store.reason(fresh.value, props.action) : '记录不可访问。');
20
+ watch([() => form.formData.note, expected, id], () => { try {
21
+ sessionStorage.setItem(storage, JSON.stringify({ note: form.formData.note, expected: expected.value, id: id.value }));
22
+ }
23
+ catch {
24
+ error.value = '输入缓存保存失败,请保留说明。';
25
+ } }, { flush: 'sync' });
26
+ function rebase() { expected.value = fresh.value.recordVersion; id.value = crypto.randomUUID(); checked.value = false; error.value = ''; }
27
+ async function submit() { try {
28
+ await form.formRef.value?.validate();
29
+ }
30
+ catch {
31
+ return;
32
+ } if (busy.value)
33
+ return; busy.value = true; error.value = ''; try {
34
+ store.apply(props.row.task.id, props.row.id, { id: id.value, action: props.action, expected: expected.value, note: form.formData.note, checked: checked.value, outcome: props.outcome });
35
+ sessionStorage.removeItem(storage);
36
+ emit('saved');
37
+ }
38
+ catch (e) {
39
+ error.value = e.message;
40
+ }
41
+ finally {
42
+ busy.value = false;
43
+ } }
44
+ return { computed, ref, watch, Alert, Button, Checkbox, Modal, Space, ProForm, useForm, useReleases, actionLabels, versionOf, environmentLabel, props, emit, store, busy, error, checked, storage, saved, expected, id, form, fresh, v, stale, reason, rebase, submit };
45
+ } });
@@ -0,0 +1,4 @@
1
+ <!-- 来源:src/releases/ReleaseDetail.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <template data-component="Result" data-if="(!row || !r || !v)" status="403" title="发布单不存在或无权访问"><template data-slot="extra"><template data-component="Button" data-on-click="(router.push('/releases'))">返回发布列表</template></template></template><template data-else=""><template data-component="OperationEntry" data-bind-task="(row.task)" data-bind-release-id="(r.id)"></template><div class="page-heading"><div><template data-component="Button" type="link" class="agent-back" data-on-click="(router.push('/releases'))">← 返回门禁与发布</template><div class="release-title"><h1>{{ (execution ? '发布执行与结果' : v.name) }}</h1><template data-component="Tag" data-bind-color="(r.unconfirmed ? 'orange' : releaseColors[r.state])">{{ (r.unconfirmed ? '结果待核实' : releaseLabels[r.state]) }}</template></div><p>{{ (r.code) }} · {{ (execution ? v.name + ' · ' : '') }}{{ (v.version) }} · {{ (environmentLabel(v.environment)) }} · 修订 v{{ (v.number) }}</p></div><template data-component="Space" wrap=""><template data-component="Button" data-on-click="(router.push('/tasks/' + row.task.id))">来源任务</template><template data-component="Button" data-on-click="(router.push(releaseUrl(r, !execution)))">{{ (execution ? '审核与版本证据' : '执行与结果') }}</template></template></div><template data-component="Alert" data-if="(r.unconfirmed)" class="page-alert" type="warning" show-icon="" title="上次提交响应不明,请查询原请求回执" data-bind-description="('原编号 ' + r.unconfirmed + ';查询结果前不会再次推进。')"></template><template data-component="Alert" data-if="(execution &amp;&amp; !r.unconfirmed)" class="page-alert" data-bind-type="(r.state === 'failed' ? 'error' : r.state === 'succeeded' ? 'success' : 'info')" show-icon="" data-bind-title="(releaseSummary(r))" data-bind-description="(r.state === 'succeeded' ? '本次发布完成;运行验收与归档属于后续范围。' : '当前展示模拟部署和观测结果,每一步均保留原版本、当前流量及回执。')"></template><div class="release-layout"><section class="agent-panel release-content"><template data-if="(execution)"><template data-if="(!r.unconfirmed)"><ol class="release-steps" aria-label="发布阶段"><li data-each="(name,i) in (stages)" data-bind-key="(name)" data-bind-class="({ done: stepDone(i), current: i === step })"><span>{{ (i + 1) }}</span><strong>{{ (name) }}</strong></li></ol><div class="release-traffic"><div><span class="muted">本次版本 {{ (v.version) }} 的流量</span><strong>{{ (r.traffic) }}<small>%</small></strong><p>{{ (r.state === 'rolledBack' ? '已切回 ' + v.materials?.rollback?.version : r.state === 'stopped' ? '本次版本流量已撤除' : r.traffic === 100 ? '本次版本已接入全部流量' : r.traffic === 0 ? '新版本尚未接入流量' : '保留当前比例,按本版阈值判断后续动作') }}</p></div><template data-component="Progress" type="circle" data-bind-percent="(r.traffic)" data-bind-size="(140)" data-bind-status="(r.state === 'failed' ? 'exception' : 'normal')"></template></div><div class="release-stat-grid"><article><span>错误率</span><strong>{{ (r.observation ? r.observation.errorRate + '%' : '待灰度后采集') }}</strong><small>上限 {{ (v.errorLimit) }}%</small></article><article><span>P95 延迟</span><strong>{{ (r.observation ? r.observation.latency + ' ms' : '待灰度后采集') }}</strong><small>上限 {{ (v.latencyLimit) }} ms</small></article><article><span>有限重试</span><strong>{{ (r.retries) }} / 2</strong><small>只重试失败步骤</small></article></div><p data-if="(r.observation)" class="muted">观测时间 {{ (formatDate(r.observation.at)) }} · {{ (r.observation.pass ? '达到本版阈值' : '未达到本版阈值,禁止全量') }} · 指标均为模拟</p></template><template data-component="Alert" data-else="" type="info" show-icon="" title="本次提交的执行结果尚待核实" description="核实前不展示本次提交的阶段、流量或观测结论;已有执行记录保留,下方待核实回执不作为完成依据。" class="page-alert"></template><div class="release-note"><strong>{{ (v.materials?.rollback ? '稳定版本恢复目标:' + v.materials.rollback.version : '首次发布:暂无稳定版本可回滚') }}</strong><p>{{ (v.rollbackPlan) }}</p><p>{{ (v.materials?.migration === 'expand-contract' ? '本次包含兼容扩展迁移;应用回滚后,数据库保持当前迁移状态,需单独核查。' : '本次材料登记无数据库变更;停止或回滚仍须保留恢复记录。') }}</p></div><h2>执行与恢复记录</h2><ol class="release-events"><li data-each="event in ([...r.events].reverse())" data-bind-key="(event.id)"><div><strong>{{ (event.action) }}</strong><template data-component="Tag" data-if="(event.id === r.unconfirmed)" color="orange">待核实回执</template><template data-component="Tag">本版流量 {{ (event.traffic) }}%</template></div><p>{{ (event.detail) }}</p><small>{{ (event.actor) }} · {{ (formatDate(event.at)) }} · 修订 v{{ (event.version) }}</small><code>{{ (event.id) }}</code></li></ol></template><template data-else=""><template data-component="Tabs" data-model-active-key="(tab)" data-bind-items="([{ key: 'evidence', label: '发布前证据' }, { key: 'versions', label: '版本快照 (' + r.versions.length + ')' }, { key: 'history', label: '操作与授权记录' }])"></template><template data-if="(tab === 'evidence')"><div class="section-heading"><h2>发布前检查</h2><template data-component="Tag" data-bind-color="(checks.every(c =&gt; ['pass', 'na'].includes(c.status)) ? 'green' : 'orange')">{{ (checks.filter(c =&gt; !['pass', 'na'].includes(c.status)).length) }} 项待补齐</template></div><p class="muted">核对固定版本的材料;灰度观测在授权、部署及接入流量之后进行。</p><p data-if="(v.preflight)">最近检查:{{ (v.preflight.by) }} · {{ (formatDate(v.preflight.at)) }}</p><template data-component="Alert" data-else="" type="info" show-icon="" title="本修订版尚未执行发布前检查" class="page-alert"></template><div class="review-checks"><details data-each="c in (checks)" data-bind-key="(c.id)"><summary><template data-component="Tag" data-bind-color="(c.status === 'pass' || c.status === 'na' ? 'green' : c.status === 'fail' ? 'red' : 'orange')">{{ (c.status === 'pass' ? '通过' : c.status === 'na' ? '不适用' : c.status === 'fail' ? '失败' : '缺失') }}</template><strong>{{ (c.name) }}</strong></summary><p class="release-check-detail">{{ (c.detail) }}</p></details></div><h2 class="release-section-title">固定的交付产物</h2><div class="release-ref-list"><template data-component="RouterLink" data-each="ref in (v.refs)" data-bind-key="(ref.id)" data-bind-to="('/tasks/' + row.task.id + '/artifacts/' + ref.id + '?version=' + ref.version)">{{ (ref.name) }} v{{ (ref.version) }} →</template></div><h3>发布说明</h3><p class="review-text">{{ (v.description || '尚未填写') }}</p><h3>灰度与恢复方案</h3><p>首次 {{ (v.traffic) }}% → 观测达标 → 全量;错误率 ≤ {{ (v.errorLimit) }}%,P95 ≤ {{ (v.latencyLimit) }}ms。</p><p class="review-text">{{ (v.rollbackPlan || '尚未填写') }}</p></template><template data-else-if="(tab === 'versions')"><div class="section-heading"><h2>不可变版本依据</h2><template data-component="Select" data-model-value="(selectedVersion)" aria-label="发布修订版" data-bind-options="([{ value: 0, label: '当前修订 v' + v.number }, ...r.versions.filter(x =&gt; x.number !== v?.number).map(x =&gt; ({ value: x.number, label: '历史修订 v' + x.number }))])"></template></div><template data-if="(evidence)"><dl class="task-trace"><dt>应用 / 修订版本</dt><dd>{{ (evidence.version) }} / v{{ (evidence.number) }}</dd><dt>目标环境 / 配置</dt><dd>{{ (environmentLabel(evidence.environment)) }} / {{ (evidence.config) }}</dd><dt>来源任务 / 规格 / 流程</dt><dd>{{ (evidence.sourceCode) }} / v{{ (evidence.specVersion) }} / {{ (evidence.flowName) }} v{{ (evidence.flowVersion) }}</dd><dt>提交标识</dt><dd>{{ (evidence.materials?.commit || '缺失') }}</dd><dt>制品摘要</dt><dd class="mono">{{ (evidence.materials?.digest || '缺失') }}</dd><dt>发布说明</dt><dd class="review-text">{{ (evidence.description) }}</dd><dt>首次灰度与阈值</dt><dd>{{ (evidence.traffic) }}% · 错误率 ≤ {{ (evidence.errorLimit) }}% · P95 ≤ {{ (evidence.latencyLimit) }} ms</dd><dt>回退与恢复</dt><dd class="review-text">{{ (evidence.rollbackPlan) }}</dd><dt>修订人 / 时间</dt><dd>{{ (evidence.by) }} · {{ (formatDate(evidence.at)) }}</dd></dl><template data-component="Alert" data-if="(evidence.number !== v.number)" type="info" show-icon="" title="正在查看历史快照,不能用于当前发布授权"></template></template></template><ol data-else="" class="release-events"><li data-each="event in ([...r.events].reverse())" data-bind-key="(event.id)"><strong>{{ (event.action) }} · 修订 v{{ (event.version) }}</strong><p>{{ (event.detail) }}</p><small>{{ (event.actor) }} · {{ (formatDate(event.at)) }}</small><code>{{ (event.id) }}</code></li></ol></template></section><aside class="release-aside"><section class="agent-panel"><h2>{{ (execution ? '执行操作' : '当前待办') }}</h2><p>{{ (releaseSummary(r)) }}</p><div class="release-action-stack"><div data-each="a in (actions)" data-bind-key="(a)"><template data-component="Button" data-bind-type="(a === actions[0] ? 'primary' : 'default')" data-bind-disabled="(!!store.reason(row, a))" data-on-click="(action = a)">{{ (label(a)) }}</template><small data-if="(store.reason(row, a))">{{ (store.reason(row, a)) }}</small></div><template data-component="Button" data-if="(!execution &amp;&amp; !r.startedAt)" data-bind-disabled="(!!store.reason(row, 'edit'))" data-on-click="(editing = true)">修改发布单</template><small data-if="(!execution &amp;&amp; !r.startedAt &amp;&amp; store.reason(row, 'edit'))">{{ (store.reason(row, 'edit')) }}</small><template data-if="(showRecovery)"><template data-component="Button" danger="" data-bind-disabled="(!!store.reason(row, 'rollback'))" data-on-click="(action = 'rollback')">回滚至稳定版本</template><small data-if="(store.reason(row, 'rollback'))">{{ (store.reason(row, 'rollback')) }}</small><template data-component="Button" danger="" data-bind-disabled="(!!store.reason(row, 'stop'))" data-on-click="(action = 'stop')">停止并撤流</template></template></div><p data-if="(!actions.length)" class="muted">{{ (r.state === 'succeeded' ? '发布已完成,可查看结果和恢复记录。' : '当前没有待提交动作,可查看历史或返回列表。') }}</p></section><section class="agent-panel"><h2>本次授权</h2><template data-if="(r.approval)"><template data-component="Tag" color="green">已授权修订 v{{ (r.approval.version) }}</template><p>{{ (r.approval.actor) }} · {{ (formatDate(r.approval.at)) }}</p><p class="review-text">{{ (r.approval.note) }}</p></template><p data-else="" class="muted">本修订版尚无有效人工授权。</p><p>目标:{{ (environmentLabel(v.environment)) }}<br>首次流量:{{ (v.traffic) }}%</p></section><section class="agent-panel"><h2>来源与记录</h2><template data-component="RouterLink" data-bind-to="('/tasks/' + row.task.id)">{{ (row.task.code) }} →</template><p><template data-component="RouterLink" data-if="(store.session.can('pbc:view', row.task.tenantId, r.pbcId))" data-bind-to="('/pbcs/' + r.pbcId + '/workspace')">{{ (row.project) }} →</template><span data-else="">{{ (row.project) }}</span></p><template data-component="Button" type="link" data-on-click="(router.push('/reviews?task=' + row.task.id))">查看质量确认</template><template data-component="RecordMetadata" data-bind-record="(r)"></template><p class="muted">记录版本 v{{ (r.recordVersion) }} · 逻辑删除:否</p></section><section data-if="(execution)" class="agent-panel release-demo"><h2>原型演示</h2><p class="muted">控制下一步模拟结果,不触发真实发布。</p><label for="release-event-outcome">下一步事件结果</label><template data-component="Select" id="release-event-outcome" data-model-value="(outcome)" data-bind-options="([{ value: 'pass', label: '成功' }, { value: 'fail', label: '步骤失败' }])"></template><label for="release-response">下一次提交响应</label><template data-component="Select" id="release-response" data-model-value="(store.response)" data-bind-options="([{ value: 'success', label: '正常返回' }, { value: 'failure', label: '提交失败(未执行)' }, { value: 'unknown', label: '响应不明(先查回执)' }])"></template></section></aside></div><template data-component="ReleaseEditor" data-if="(editing)" data-bind-row="(row)" data-on-close="(editing = false)" data-on-saved="editing = false;
3
+ selectedVersion = 0;
4
+ tab = 'evidence';"></template><template data-component="ReleaseActionDialog" data-if="(action)" data-bind-row="(row)" data-bind-action="(action)" data-bind-outcome="(action === 'advance' ? outcome : 'pass')" data-on-close="(action = undefined)" data-on-saved="(saved)"></template></template>
@@ -0,0 +1,30 @@
1
+ import OperationEntry from "../operations/OperationEntry.js";
2
+ import { computed, ref, watch } from '../../runtime/state.js';
3
+ import { useRoute, useRouter } from "../../runtime/router.js";
4
+ import { Alert, Button, Result, Space, Tag, Tabs, Select, Progress } from "../../runtime/widgets.js";
5
+ import { useReleases } from "./store.js";
6
+ import { versionOf, releaseLabels, releaseSummary, releaseColors, environmentLabel, releaseChecks, releaseUrl, actionLabels } from "./model.js";
7
+ import { formatDate } from "../shared/policy.js";
8
+ import RecordMetadata from "../shared/RecordMetadata.js";
9
+ import ReleaseEditor from "./ReleaseEditor.js";
10
+ import ReleaseActionDialog from "./ReleaseActionDialog.js";
11
+ import { createComponent } from '../../runtime/dom.js';
12
+ export default createComponent({ name: 'ReleaseDetail', propKeys: ["execution"], template: new URL('./ReleaseDetail.html', import.meta.url).href, setup(__props, __emit) {
13
+ const props = __props, route = useRoute(), router = useRouter(), store = useReleases(), row = computed(() => { const r = store.find(String(route.params.releaseId)); return r?.task.id === route.params.taskId ? r : undefined; }), r = computed(() => row.value?.release), v = computed(() => r.value ? versionOf(r.value) : undefined), tab = ref(String(route.query.tab || 'evidence')), editing = ref(false), action = ref(), outcome = ref('pass'), selectedVersion = ref(Number(route.query.version) || 0);
14
+ const evidence = computed(() => r.value?.versions.find(v => v.number === selectedVersion.value) || v.value), checks = computed(() => row.value ? releaseChecks(row.value.task, row.value.release) : []);
15
+ const actions = computed(() => { if (!r.value)
16
+ return []; if (r.value.unconfirmed)
17
+ return ['verify']; if (!props.execution)
18
+ return r.value.state === 'draft' || r.value.state === 'returned' ? ['check', 'submit'] : r.value.state === 'pending' ? ['approve', 'return'] : r.value.state === 'approved' ? ['start'] : []; return r.value.state === 'approved' ? ['start'] : ['deploying', 'canary', 'observing', 'rollingBack'].includes(r.value.state) ? ['advance', 'pause'] : r.value.state === 'paused' ? ['resume'] : r.value.state === 'failed' ? ['retry'] : []; });
19
+ const showRecovery = computed(() => props.execution && r.value?.startedAt && !['stopped', 'rolledBack'].includes(r.value.state));
20
+ function label(a) { if (a !== 'advance')
21
+ return actionLabels[a]; return r.value?.state === 'deploying' ? '部署完成,接入 ' + v.value?.traffic + '% 灰度' : r.value?.state === 'canary' ? '采集本次灰度观测' : r.value?.state === 'observing' ? '观测达标,继续全量' : '确认回滚结果'; }
22
+ const stepDone = (i) => !!r.value && (i === 0 ? !!r.value.approval : i === 1 || i === 2 ? r.value.receipts.some(x => x.action === 'advance' && ['canary', 'observing', 'succeeded'].includes(x.state)) : i === 3 ? r.value.receipts.some(x => x.state === 'succeeded') : ['succeeded', 'rolledBack', 'stopped'].includes(r.value.state));
23
+ const stages = ['人工授权', '部署制品', '首次灰度', '观测与全量', '发布结果'];
24
+ const effectiveState = computed(() => r.value?.state === 'failed' ? r.value.failedStage : r.value?.state === 'paused' ? r.value.previousState : r.value?.state);
25
+ const step = computed(() => !r.value ? 0 : ['draft', 'pending', 'returned'].includes(effectiveState.value || '') ? 0 : effectiveState.value === 'approved' ? 1 : effectiveState.value === 'deploying' ? 1 : effectiveState.value === 'canary' ? 2 : effectiveState.value === 'observing' ? 3 : ['succeeded', 'rolledBack', 'stopped'].includes(r.value.state) ? 4 : 2);
26
+ const saved = () => { const a = action.value; action.value = undefined; outcome.value = 'pass'; if (a === 'start' && r.value)
27
+ router.push(releaseUrl(r.value, true)); };
28
+ watch(() => [route.params.releaseId, route.query.tab, route.query.version], () => { selectedVersion.value = Number(route.query.version) || 0; action.value = undefined; editing.value = false; tab.value = String(route.query.tab || 'evidence'); });
29
+ return { OperationEntry, computed, ref, watch, useRoute, useRouter, Alert, Button, Result, Space, Tag, Tabs, Select, Progress, useReleases, versionOf, releaseLabels, releaseSummary, releaseColors, environmentLabel, releaseChecks, releaseUrl, actionLabels, formatDate, RecordMetadata, ReleaseEditor, ReleaseActionDialog, props, route, router, store, row, r, v, tab, editing, action, outcome, selectedVersion, evidence, checks, actions, showRecovery, label, stepDone, stages, effectiveState, step, saved };
30
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/releases/ReleaseEditor.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <template data-component="Drawer" data-bind-open="(true)" data-bind-title="(row ? '修改发布单 · 生成新修订版' : '准备发布')" data-bind-size="(760)" data-bind-mask="({ closable: false })" data-on-close="(emit('close'))"><template data-component="Alert" data-if="(restored)" class="page-alert" type="info" show-icon="" title="已恢复本账号上次未提交的输入"></template><template data-component="Alert" data-if="(stale)" class="page-alert" type="warning" show-icon="" title="当前记录已更新,输入仍保留" description="请对照当前来源和发布详情,核对后再提交。"><template data-slot="action"><template data-component="Button" data-on-click="(rebase)">已核对,采用当前版本</template></template></template><template data-component="Alert" data-if="(error)" class="page-alert" type="error" show-icon="" data-bind-title="(error)"></template><template data-component="ProForm" name="release-editor" data-bind-form="(form)" layout="vertical" data-bind-disabled="(busy)"></template><div data-if="(task)" class="release-note"><strong>{{ (task.binding.project) }} · 规格 v{{ (task.binding.spec.number) }} · 流程 v{{ (task.binding.flow.number) }}</strong><p>{{ (task.releaseMaterials ? '此任务提供独立发布材料,保存后仍需检查和人工授权。' : '此任务没有独立发布材料,可保存草稿;缺失证据会阻止提交。') }}</p><p>{{ (task.releaseMaterials?.rollback ? '已有稳定版本 ' + task.releaseMaterials.rollback.version + ';回滚不自动还原数据库。' : '首次发布暂无稳定版本可回滚;异常时停止并撤流。') }}</p></div><p class="muted">关闭会保留本账号未提交的输入。保存草稿不产生部署或流量。</p><p data-if="(!allowed)" class="muted">当前账号缺少来源 PBC 或目标环境的发布编辑权限,请在权限管理中配置。</p><template data-slot="footer"><template data-component="Space" wrap=""><template data-component="Button" data-on-click="(emit('close'))">关闭并保留输入</template><template data-component="Button" type="primary" data-bind-disabled="(!allowed || stale)" data-bind-loading="(busy)" data-on-click="(save)">保存发布草稿</template></template></template></template>
@@ -0,0 +1,67 @@
1
+ import { computed, ref, watch } from '../../runtime/state.js';
2
+ import { Alert, Button, Drawer, Space, message } from "../../runtime/widgets.js";
3
+ import { ProForm, useForm } from "../../runtime/widgets.js";
4
+ import { useReleases } from "./store.js";
5
+ import { environments, versionOf } from "./model.js";
6
+ import { clone } from "../tasks/domain.js";
7
+ import { createComponent } from '../../runtime/dom.js';
8
+ export default createComponent({ name: 'ReleaseEditor', propKeys: ["row", "taskId"], template: new URL('./ReleaseEditor.html', import.meta.url).href, setup(__props, __emit) {
9
+ const props = __props, emit = __emit, store = useReleases(), busy = ref(false), error = ref('');
10
+ const storage = 'i3-prototype-antdv-release-editor:' + store.session.actor.id + ':' + (props.row?.id || props.taskId || 'new');
11
+ const first = props.row?.task || store.tasks.find(t => t.id === props.taskId) || store.tasks.find(t => !store.sourceReason(t));
12
+ const baseline = { name: first?.name.replace('样例', '') || '', version: '1.0.0', environment: 'production', config: first?.releaseMaterials?.config || 'config-v1', description: '', traffic: 10, errorLimit: 1, latencyLimit: 800, rollbackPlan: '' };
13
+ const initial = { ...baseline, ...(props.row ? clone(versionOf(props.row.release)) : {}), taskId: first?.id || '' };
14
+ let saved;
15
+ try {
16
+ saved = JSON.parse(sessionStorage.getItem(storage) || 'null');
17
+ }
18
+ catch {
19
+ saved = null;
20
+ }
21
+ const expected = ref(saved?.expected ?? (props.row?.recordVersion || first?.recordVersion || 0)), request = ref(saved?.request || crypto.randomUUID()), restored = ref(!!saved);
22
+ const form = useForm({ ...initial, ...saved?.data }, [
23
+ { path: 'taskId', label: '来源交付任务', component: 'select', span: 24, disabled: !!props.row, options: computed(() => store.tasks.map(t => ({ value: t.id, label: t.code + ' · ' + t.name + (store.sourceReason(t) ? ' · ' + store.sourceReason(t) : ''), disabled: !!store.sourceReason(t) }))), rules: [{ required: true, message: '请选择来源任务' }] },
24
+ { path: 'name', label: '发布名称', component: 'input', span: 24, maxlength: 80, rules: [{ required: true, whitespace: true, message: '请输入发布名称' }] },
25
+ { path: 'version', label: '应用版本', component: 'input', span: 12, xs: 24, sm: 12, placeholder: '例如 1.0.0', rules: [{ required: true, message: '请输入应用版本' }] },
26
+ { path: 'environment', label: '目标环境', component: 'select', span: 12, xs: 24, sm: 12, options: environments, allowClear: false },
27
+ { path: 'config', label: '配置快照', component: 'input', span: 24, extra: '与本次制品材料一并核对;修改配置后需重新检查。' },
28
+ { path: 'description', label: '发布说明', component: 'textarea', span: 24, rows: 3, maxlength: 2000, placeholder: '本次范围、影响及验收关注点' },
29
+ { path: 'traffic', label: '首次灰度比例(%)', component: 'input-number', span: 8, xs: 24, sm: 8, min: 1, max: 50 },
30
+ { path: 'errorLimit', label: '错误率上限(%)', component: 'input-number', span: 8, xs: 24, sm: 8, min: 0.01, max: 100 },
31
+ { path: 'latencyLimit', label: 'P95 延迟上限(ms)', component: 'input-number', span: 8, xs: 24, sm: 8, min: 1 },
32
+ { path: 'rollbackPlan', label: '回退与恢复方案', component: 'textarea', span: 24, rows: 3, maxlength: 2000, placeholder: '回滚目标、停止撤流条件,以及数据库处理说明' },
33
+ ]);
34
+ const task = computed(() => store.tasks.find(t => t.id === form.formData.taskId)), currentVersion = computed(() => props.row ? store.find(props.row.id)?.recordVersion : task.value?.recordVersion), stale = computed(() => expected.value !== currentVersion.value);
35
+ const allowed = computed(() => !!task.value && store.session.can('release:edit', task.value.tenantId, task.value.binding.pbcId, form.formData.environment));
36
+ watch(() => form.formData.taskId, () => { if (!props.row) {
37
+ expected.value = task.value?.recordVersion || 0;
38
+ request.value = crypto.randomUUID();
39
+ } });
40
+ watch([() => JSON.stringify(form.formData), expected, request], () => { try {
41
+ sessionStorage.setItem(storage, JSON.stringify({ data: form.formData, expected: expected.value, request: request.value }));
42
+ }
43
+ catch {
44
+ error.value = '输入缓存保存失败,请保留输入后重试。';
45
+ } }, { flush: 'sync' });
46
+ function rebase() { expected.value = currentVersion.value || 0; request.value = crypto.randomUUID(); error.value = ''; restored.value = false; }
47
+ async function save() { try {
48
+ await form.formRef.value?.validate();
49
+ }
50
+ catch {
51
+ return;
52
+ } if (busy.value || !task.value)
53
+ return; busy.value = true; error.value = ''; try {
54
+ const f = form.formData, payload = { name: f.name, version: f.version, environment: f.environment, config: f.config, description: f.description, traffic: f.traffic, errorLimit: f.errorLimit, latencyLimit: f.latencyLimit, rollbackPlan: f.rollbackPlan };
55
+ const r = props.row ? store.apply(task.value.id, props.row.id, { id: request.value, expected: expected.value, action: 'edit', note: '修订发布单', input: payload }) : store.create(task.value.id, payload, request.value, expected.value);
56
+ sessionStorage.removeItem(storage);
57
+ message.success(r.unconfirmed ? '提交响应待核实,请查询原回执' : '发布草稿已保存');
58
+ emit('saved', r.id);
59
+ }
60
+ catch (e) {
61
+ error.value = e.message;
62
+ }
63
+ finally {
64
+ busy.value = false;
65
+ } }
66
+ return { computed, ref, watch, Alert, Button, Drawer, Space, message, ProForm, useForm, useReleases, environments, versionOf, clone, props, emit, store, busy, error, storage, first, baseline, initial, saved, expected, request, restored, form, task, currentVersion, stale, allowed, rebase, save };
67
+ } });
@@ -0,0 +1,2 @@
1
+ <!-- 来源:src/releases/ReleaseExecution.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <template data-component="ReleaseDetail" execution=""></template>
@@ -0,0 +1,5 @@
1
+ import ReleaseDetail from "./ReleaseDetail.js";
2
+ import { createComponent } from '../../runtime/dom.js';
3
+ export default createComponent({ name: 'ReleaseExecution', propKeys: [], template: new URL('./ReleaseExecution.html', import.meta.url).href, setup(__props, __emit) {
4
+ return { ReleaseDetail };
5
+ } });
@@ -0,0 +1,4 @@
1
+ <!-- 来源:src/releases/ReleasesPage.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
2
+ <div class="page-heading"><div><h1>门禁与发布</h1><p>从交付产物准备发布,核对证据后人工放行,跟踪灰度与恢复结果。</p></div><template data-component="Button" type="primary" data-bind-disabled="(!store.session.can('release:edit'))" data-on-click="(creating = true)">准备发布</template></div><div class="task-metrics"><article><span>待准备 / 修订</span><strong>{{ (store.rows.filter(r =&gt; !r.release.unconfirmed &amp;&amp; ['draft', 'returned'].includes(r.release.state)).length) }}</strong></article><article><span>待人工授权</span><strong>{{ (store.rows.filter(r =&gt; !r.release.unconfirmed &amp;&amp; r.release.state === 'pending').length) }}</strong></article><article><span>执行 / 待处理</span><strong>{{ (store.rows.filter(r =&gt; r.release.unconfirmed || ['approved', 'deploying', 'canary', 'observing', 'failed', 'paused', 'rollingBack'].includes(r.release.state)).length) }}</strong></article><article><span>已结束</span><strong>{{ (store.rows.filter(r =&gt; !r.release.unconfirmed &amp;&amp; ['succeeded', 'rolledBack', 'stopped'].includes(r.release.state)).length) }}</strong></article></div><template data-component="Alert" data-if="(route.query.task)" type="info" show-icon="" class="page-alert" title="正在查看来源任务的发布单"><template data-slot="action"><template data-component="Button" data-on-click="(router.replace('/releases'))">查看全部发布</template></template></template><template data-component="Alert" data-if="(!store.session.can('release:edit'))" type="info" show-icon="" class="page-alert" title="当前账号尚未配置发布操作权限" description="既有账号的授权保持原样。管理员可在权限管理中配置发布动作及租户、PBC、目标环境范围。"></template><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="(state)" aria-label="发布状态筛选" data-bind-options="([{ value: 'all', label: '全部状态' }, ...Object.entries(releaseLabels).map(([value, label]) =&gt; ({ value, label }))])"></template><template data-component="Select" data-model-value="(env)" aria-label="发布环境筛选" data-bind-options="([{ value: 'all', label: '全部环境' }, ...environments])"></template><template data-component="Select" data-model-value="(project)" aria-label="发布 PBC 筛选" data-bind-options="([{ value: 'all', label: '全部可见 PBC' }, ...Array.from(new Map(store.rows.map(r =&gt; [r.task.binding.pbcId, { value: r.task.binding.pbcId, label: r.project }])).values())])"></template><template data-component="Button" data-on-click="(reset)">重置</template></div><div class="auth-tools"><template data-component="ListBatchBar" data-bind-count="(selection.selected.value.length)" data-bind-allowed="(store.session.can('release:delete'))" data-on-remove="(selectRows(selection.selected.value))" data-on-clear="(selection.clear)"></template><template data-component="Space" wrap=""><template data-component="Select" data-model-value="(sort)" aria-label="发布排序" data-bind-options="([{ value: 'newest', label: '更新时间倒序' }, { value: 'oldest', label: '更新时间正序' }])"></template><template data-component="Button" data-bind-loading="(loading)" data-on-click="(refresh)">刷新</template><template data-component="ColumnSettings" data-bind-preferences="(prefs)"></template></template></div><template data-component="Alert" data-if="(error || store.notice)" type="error" show-icon="" data-bind-title="(error || store.notice)"></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-component="ProTable" data-else="" data-bind-table="(table)" data-bind-control="(false)" data-bind-table-container="(false)" data-bind-search="(async () =&gt; { })" row-key="id" data-bind-row-selection="(selection.rowSelection.value)" data-bind-loading="(loading)" data-bind-scroll="({ x: 'max-content' })" data-bind-pagination="({ showTotal: (n) =&gt; '共 ' + n + ' 项', showSizeChanger: true, pageSizeOptions: [5, 10, 20] })"></template><div data-if="(!filtered.length &amp;&amp; store.scene === 'normal')" class="release-empty"><p>{{ (store.rows.length ? '当前筛选没有发布单,可重置筛选。' : '还没有发布单。从已完成质量检查的任务开始准备。') }}</p><template data-component="Button" data-if="(store.rows.length)" data-on-click="(reset)">重置筛选</template><template data-component="Button" data-else="" data-on-click="(addExamples)">载入发布演示样例</template><p class="muted">样例使用独立模拟材料,不补写已有任务的缺失证据。</p></div></section><p class="review-footnote">只允许删除未提交的发布草稿;授权、执行、失败和恢复记录须保留。材料检查与灰度观测为两个阶段,首次生产流量前必须人工授权。</p><template data-component="ReleaseEditor" data-if="(creating || editing)" data-bind-row="(editing)" data-bind-task-id="(String(route.query.task || ''))" data-on-close="creating = false;
3
+ editing = undefined;" data-on-saved="(saved)"></template><template data-component="ListDeleteDialog" data-if="(targets.length)" data-model-targets="(targets)" label="发布草稿" data-bind-check="(store.checkDelete)" data-bind-submit="(store.removeMany)" data-on-close="(targets = [])" data-on-deleted="targets = [];
4
+ selection.clear();"></template>
@@ -0,0 +1,60 @@
1
+ import { computed, ref, watch } from '../../runtime/state.js';
2
+ import { h } from '../../runtime/dom.js';
3
+ import { useRoute, useRouter } from "../../runtime/router.js";
4
+ import { Alert, Button, Input, Select, Space, Tag, Empty, message } from "../../runtime/widgets.js";
5
+ import { ProTable, useTable } from "../../runtime/widgets.js";
6
+ import { useReleases } from "./store.js";
7
+ import { releaseLabels, releaseColors, versionOf, environments, environmentLabel, releaseUrl } from "./model.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 ListBatchBar from "../shared/ListBatchBar.js";
13
+ import ListDeleteDialog from "../shared/ListDeleteDialog.js";
14
+ import ColumnSettings from "../shared/ColumnSettings.js";
15
+ import ReleaseEditor from "./ReleaseEditor.js";
16
+ import { createComponent } from '../../runtime/dom.js';
17
+ export default createComponent({ name: 'ReleasesPage', propKeys: [], template: new URL('./ReleasesPage.html', import.meta.url).href, setup(__props, __emit) {
18
+ const store = useReleases(), route = useRoute(), router = useRouter(), query = ref(''), state = ref('all'), env = ref('all'), project = ref(String(route.query.pbc || 'all')), sort = ref('newest'), loading = ref(false), editing = ref(), creating = ref(route.query.prepare === '1'), targets = ref([]), error = ref('');
19
+ const prefs = useColumns('releases-v013', [{ key: 'name', label: '发布单', locked: true }, { key: 'project', label: '所属 PBC', defaultVisible: true }, { key: 'environment', label: '目标环境', defaultVisible: true }, { key: 'state', label: '发布状态', defaultVisible: true }, { key: 'createdBy', label: '创建人', defaultVisible: true }, { key: 'createdAt', label: '创建时间', defaultVisible: true }, { key: 'updatedBy', label: '更新人' }, { key: 'updatedAt', label: '更新时间' }, { key: 'tenant', label: '租户' }, { key: 'department', label: '创建部门' }, { key: 'approver', label: '授权人' }, { key: 'approvedAt', label: '授权时间' }, { key: 'version', label: '记录版本' }, { key: 'actions', label: '操作', locked: true }]);
20
+ function more(r) { return [{ key: 'edit', label: '修改发布单', disabled: !!store.reason(r, 'edit') }, { key: 'execution', label: '执行与结果' }, { key: 'task', label: '来源任务' }, { key: 'history', label: '版本与操作记录' }, { key: 'delete', label: '删除草稿', danger: true, disabled: !!store.reason(r, 'delete') }]; }
21
+ function selectRows(rows) { targets.value = rows.map(r => ({ id: r.id, name: versionOf(r.release).name, recordVersion: r.recordVersion })); }
22
+ function action(key, r) { if (key === 'edit') {
23
+ editing.value = r;
24
+ return;
25
+ } if (key === 'delete') {
26
+ selectRows([r]);
27
+ return;
28
+ } router.push(key === 'task' ? '/tasks/' + r.task.id : releaseUrl(r.release, key === 'execution') + (key === 'history' ? '?tab=history' : '')); }
29
+ const render = (f) => (_, row) => f(row);
30
+ const columns = prefs.choices.map(c => ({ key: c.key, title: c.label, width: c.key === 'name' ? 285 : c.key === 'actions' ? 145 : c.key.endsWith('At') ? 165 : 130, fixed: c.key === 'actions' ? 'right' : undefined, render: render(r => { const x = r.release, v = versionOf(x); if (c.key === 'name')
31
+ return h('div', { class: 'review-list-name' }, [h(Button, { type: 'link', onClick: () => router.push(releaseUrl(x)) }, () => v.name), h('small', { class: 'mono muted' }, x.code + ' · ' + v.version + ' / 修订 v' + v.number), h('span', { class: 'muted' }, x.unconfirmed ? '提交结果待核实' : r.task.code)]); if (c.key === 'actions')
32
+ return h('div', { class: 'row-actions' }, [h(Button, { type: 'link', onClick: () => router.push(releaseUrl(x)) }, () => ['draft', 'returned', 'pending', 'approved'].includes(x.state) ? '处理' : '查看'), h(ListMore, { name: x.code, items: more(r), onAction: (key) => action(key, r) })]); if (c.key === 'state')
33
+ return h(Tag, { color: releaseColors[x.state] }, () => x.unconfirmed ? '结果待核实' : releaseLabels[x.state]); if (c.key === 'environment')
34
+ return environmentLabel(v.environment); if (c.key === 'project')
35
+ return r.project; if (c.key === 'tenant')
36
+ return tenantLabel(x.tenantId); if (c.key === 'department')
37
+ return x.createdDept; if (c.key === 'approver')
38
+ return x.approval?.actor || '—'; if (c.key === 'approvedAt')
39
+ return formatDate(x.approval?.at || ''); if (c.key === 'version')
40
+ return 'v' + x.recordVersion; if (c.key.endsWith('At'))
41
+ return formatDate(x[c.key]); return x[c.key]; }) }));
42
+ const table = useTable({ columns, pageParam: { current: 1, pageSize: 5, total: 0 } }), allColumns = new Map(table.columns.value.map(c => [c.key, c]));
43
+ watch(prefs.keys, keys => table.columns.value = keys.map(k => allColumns.get(k)).filter(Boolean), { immediate: true });
44
+ const filtered = computed(() => store.scene === 'empty' ? [] : store.rows.filter(r => (!route.query.task || r.task.id === route.query.task) && (state.value === 'all' || r.release.state === state.value) && (env.value === 'all' || versionOf(r.release).environment === env.value) && (project.value === 'all' || r.task.binding.pbcId === project.value) && (versionOf(r.release).name + r.release.code + r.task.code).toLowerCase().includes(query.value.trim().toLowerCase())).sort((a, b) => (sort.value === 'newest' ? -1 : 1) * a.release.updatedAt.localeCompare(b.release.updatedAt)));
45
+ watch([query, state, env, project, sort], () => table.setPageParam({ current: 1 }));
46
+ watch([filtered, () => table.pageParam.current, () => table.pageParam.pageSize], () => { const size = table.pageParam.pageSize || 5; table.pageParam.current = Math.min(table.pageParam.current || 1, Math.max(1, Math.ceil(filtered.value.length / size))); table.pageParam.total = filtered.value.length; table.dataSource.value = filtered.value.slice(((table.pageParam.current || 1) - 1) * size, (table.pageParam.current || 1) * size); }, { immediate: true });
47
+ const selection = useListSelection(table.dataSource, computed(() => JSON.stringify([store.session.key, query.value, state.value, env.value, project.value, sort.value, table.pageParam.current, table.pageParam.pageSize])), computed(() => true), r => r.release.code);
48
+ async function refresh() { selection.clear(); loading.value = true; await new Promise(r => setTimeout(r, 180)); store.scene = 'normal'; loading.value = false; }
49
+ function reset() { query.value = ''; state.value = 'all'; env.value = 'all'; project.value = 'all'; }
50
+ function addExamples() { try {
51
+ const n = store.addExamples();
52
+ message.success(n ? '已添加独立发布样例' : '发布样例已存在,请选择对应任务');
53
+ creating.value = true;
54
+ }
55
+ catch (e) {
56
+ error.value = e.message;
57
+ } }
58
+ function saved(id) { creating.value = false; editing.value = undefined; router.push(releaseUrl(store.find(id).release)); }
59
+ return { computed, ref, watch, h, useRoute, useRouter, Alert, Button, Input, Select, Space, Tag, Empty, message, ProTable, useTable, useReleases, releaseLabels, releaseColors, versionOf, environments, environmentLabel, releaseUrl, formatDate, tenantLabel, useColumns, useListSelection, ListMore, ListBatchBar, ListDeleteDialog, ColumnSettings, ReleaseEditor, store, route, router, query, state, env, project, sort, loading, editing, creating, targets, error, prefs, more, selectRows, action, render, columns, table, allColumns, filtered, selection, refresh, reset, addExamples, saved };
60
+ } });