@givolt/i3-composer-agent 2.2.3 → 2.3.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.
- package/.agents/plugins/marketplace.json +1 -1
- package/.claude/commands/i3-prototype.md +23 -0
- package/.claude/commands/i3-review.md +1 -1
- package/.claude/commands/i3-ship.md +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +2 -2
- package/.gemini/commands/i3-prototype.toml +23 -0
- package/.gemini/commands/i3-review.toml +1 -1
- package/.gemini/commands/i3-ship.toml +1 -1
- package/README.md +15 -5
- package/agents/code-reviewer.md +1 -1
- package/agents/test-engineer.md +1 -1
- package/bin/native-layout.cjs +2 -0
- package/commands/i3-prototype.toml +23 -0
- package/commands/i3-review.toml +1 -1
- package/commands/i3-ship.toml +1 -1
- package/docs/agents.md +2 -2
- package/docs/codebuddy-setup.md +2 -2
- package/docs/codex-setup.md +1 -1
- package/docs/copilot-setup.md +4 -0
- package/docs/cursor-setup.md +3 -0
- package/docs/other-hosts.md +44 -9
- package/docs/workbuddy-setup.md +2 -2
- package/evals/README.md +2 -0
- package/evals/cases/i3-documentation-and-adrs.json +18 -0
- package/evals/cases/i3-test-driven-development.json +8 -0
- package/evals/cases/i3-ui-prototype.json +49 -0
- package/evals/fixtures/i3-documentation-and-adrs/prose-review/README.md +19 -0
- package/evals/fixtures/i3-documentation-and-adrs/prose-review/queue.js +32 -0
- package/evals/fixtures/i3-ui-prototype/business-brief.md +7 -0
- package/evals/plugin/tdd-fires-on-pasted-bug/graders/failing-test-first.md +7 -0
- package/evals/plugin/tdd-fires-on-pasted-bug/graders/skill-fired.md +5 -0
- package/evals/plugin/tdd-fires-on-pasted-bug/prompt.md +15 -0
- package/evals/plugin/tdd-stays-quiet-on-debug/graders/not-fired.md +8 -0
- package/evals/plugin/tdd-stays-quiet-on-debug/prompt.md +25 -0
- package/evals/zh-CN/cases/i3-documentation-and-adrs.json +19 -0
- package/evals/zh-CN/cases/i3-test-driven-development.json +4 -0
- package/evals/zh-CN/cases/i3-ui-prototype.json +50 -0
- package/hooks/SIMPLIFY-IGNORE.md +3 -2
- package/hooks/simplify-ignore-test.sh +93 -1
- package/hooks/simplify-ignore.sh +94 -11
- package/package.json +27 -1
- package/plugin.json +1 -1
- package/references/performance-checklist.md +4 -2
- package/scripts/enterprise-template-test.js +139 -0
- package/scripts/lib/skill-lint-test.js +113 -1
- package/scripts/lib/skill-lint.js +62 -8
- package/scripts/run-evals-test.js +207 -0
- package/scripts/run-evals.js +47 -9
- package/scripts/template-adapter-test.js +155 -0
- package/scripts/ui-prototype-test.js +114 -0
- package/scripts/validate-commands-test.js +30 -0
- package/scripts/validate-commands.js +6 -16
- package/scripts/validate-reference-links-test.js +18 -0
- package/scripts/validate-reference-links.js +4 -2
- package/scripts/validate-skills.js +26 -3
- package/skills/i3-documentation-and-adrs/SKILL.md +9 -0
- package/skills/i3-frontend-ui-engineering/SKILL.md +5 -1
- package/skills/i3-idea-refine/SKILL.md +20 -5
- package/skills/i3-incremental-implementation/SKILL.md +4 -0
- package/skills/i3-performance-optimization/SKILL.md +10 -10
- package/skills/i3-security-and-hardening/references/hardening-patterns.md +1 -1
- package/skills/i3-shipping-and-launch/SKILL.md +6 -0
- package/skills/i3-test-driven-development/SKILL.md +3 -3
- package/skills/i3-ui-prototype/SKILL.md +119 -0
- package/skills/i3-ui-prototype/assets/templates/catalog.json +147 -0
- package/skills/i3-ui-prototype/assets/templates/classic-admin/manifest.json +9 -0
- package/skills/i3-ui-prototype/assets/templates/classic-admin/preset.json +6 -0
- package/skills/i3-ui-prototype/assets/templates/common/app/app.mjs +89 -0
- package/skills/i3-ui-prototype/assets/templates/common/app/config.json +1 -0
- package/skills/i3-ui-prototype/assets/templates/common/app/domain.mjs +20 -0
- package/skills/i3-ui-prototype/assets/templates/common/app/index.html +17 -0
- package/skills/i3-ui-prototype/assets/templates/common/app/serve.cjs +16 -0
- package/skills/i3-ui-prototype/assets/templates/common/app/styles.css +670 -0
- package/skills/i3-ui-prototype/assets/templates/common/app/tokens.css +19 -0
- package/skills/i3-ui-prototype/assets/templates/common/design-system/master.md +20 -0
- package/skills/i3-ui-prototype/assets/templates/common/gallery.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/common/mocks/applications.json +5 -0
- package/skills/i3-ui-prototype/assets/templates/common/requirements-map.json +8 -0
- package/skills/i3-ui-prototype/assets/templates/common/serve-gallery.cjs +16 -0
- package/skills/i3-ui-prototype/assets/templates/credits.md +17 -0
- package/skills/i3-ui-prototype/assets/templates/data-operations/manifest.json +9 -0
- package/skills/i3-ui-prototype/assets/templates/data-operations/preset.json +6 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/design-system.md +32 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/index.html +29 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/manifest.json +9 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/origin.json +344 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/preset.json +928 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/app.js +22 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/assets/empty.svg +1 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/assets/reference-styles.json +1 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/assets/result-403.svg +1 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/assets/result-404.svg +1 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/assets-manifest.json +334 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/baseline.json +173 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/conversion.md +30 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/credits.md +17 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/design-tokens.json +881 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/index.html +28 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/licenses/@qin-ui-antdv-next-pro.txt +9 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/licenses/ant-design-icons.txt +22 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/licenses/antdv-next.txt +21 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/package.json +12 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/browser-routes.json +298 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/coverage.json +180 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/integrity.json +13 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/keyboard.json +11 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/responsive.json +125 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/review.md +51 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/rules.log +150 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/flow-editor-html.png +0 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/flow-editor-original.png +0 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/intent-create-html.png +0 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/intent-create-original.png +0 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/models-html.png +0 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/models-original.png +0 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/workbench-html.png +0 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/screenshots/workbench-original.png +0 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/selection.json +9 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/qa/visual-comparison.json +342 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/readme.md +73 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/reference.md +59 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/routes.json +178 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/controls.js +99 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/dialogs.js +54 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/dom.js +264 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/forms.js +47 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/icons.js +41 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/layout.js +47 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/router.js +63 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/state.js +90 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/table.js +41 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/runtime/widgets.js +8 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/AgentDetail.html +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/AgentDetail.js +36 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/AgentEditor.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/AgentEditor.js +51 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/AgentsPage.html +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/AgentsPage.js +48 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/CheckResults.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/CheckResults.js +6 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/ResourcePicker.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/ResourcePicker.js +13 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/data.js +24 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/domain.js +32 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/registry.js +25 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/agents/store.js +85 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentClose.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentClose.js +17 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentCreate.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentCreate.js +66 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentDecisions.html +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentDecisions.js +38 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentDetail.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentDetail.js +66 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentDocument.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentDocument.js +5 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentHeader.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentHeader.js +12 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentHistory.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentHistory.js +11 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentList.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentList.js +116 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentReplan.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentReplan.js +32 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentRevision.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentRevision.js +49 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentSummary.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentSummary.js +10 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentWorkspace.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/IntentWorkspace.js +77 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/data.js +60 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/domain.js +105 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/intents/store.js +212 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/AuditPanel.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/AuditPanel.js +18 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelDetail.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelDetail.js +23 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelEditor.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelEditor.js +78 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelGrant.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelGrant.js +55 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelReferences.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelReferences.js +26 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelRelease.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelRelease.js +38 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelStatus.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelStatus.js +7 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelTable.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelTable.js +72 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelTester.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelTester.js +46 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelsPage.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/ModelsPage.js +52 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/RowActions.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/RowActions.js +19 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/UsagePanel.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/UsagePanel.js +30 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/data.js +48 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/domain.js +39 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/store.js +129 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/IncidentDetail.html +4 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/IncidentDetail.js +21 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/IntentSource.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/IntentSource.js +8 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/OperationActionDialog.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/OperationActionDialog.js +37 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/OperationEntry.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/OperationEntry.js +10 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/OperationsPage.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/OperationsPage.js +37 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/RepairTrack.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/RepairTrack.js +49 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/RunDetail.html +4 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/RunDetail.js +22 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/SourceSummary.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/SourceSummary.js +9 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/commands.js +82 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/examples.js +47 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/model.js +61 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/repair.js +68 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/store.js +55 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/types.js +1 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/operations/workbench.js +18 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/ManagementTable.html +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/ManagementTable.js +28 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcCreateEntry.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcCreateEntry.js +18 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcDetail.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcDetail.js +31 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcEditor.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcEditor.js +27 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcLifecycle.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcLifecycle.js +16 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcPage.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcPage.js +43 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcPicker.html +4 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcPicker.js +34 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcProgress.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcProgress.js +30 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcWizard.html +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcWizard.js +67 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcWorkspace.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcWorkspace.js +41 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcsPage.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/PbcsPage.js +31 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/ServiceEditor.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/ServiceEditor.js +26 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/ServiceList.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/ServiceList.js +70 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/data.js +8 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/domain.js +62 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/management.js +36 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/managementStore.js +49 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/pbc/store.js +132 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/AdminList.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/AdminList.js +38 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/EffectiveGrants.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/EffectiveGrants.js +11 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/GrantEditor.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/GrantEditor.js +45 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/MemberEditor.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/MemberEditor.js +54 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/MembersPage.html +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/MembersPage.js +27 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/RecordsPage.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/RecordsPage.js +12 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/RoleEditor.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/RoleEditor.js +45 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/RolesPage.html +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/RolesPage.js +38 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/domain.js +61 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/state.js +51 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/permissions/store.js +116 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseActionDialog.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseActionDialog.js +45 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseDetail.html +4 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseDetail.js +30 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseEditor.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseEditor.js +67 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseExecution.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleaseExecution.js +5 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleasesPage.html +4 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/ReleasesPage.js +60 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/commands.js +157 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/model.js +136 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/releases/store.js +76 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewDetail.html +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewDetail.js +26 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewEvidence.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewEvidence.js +14 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewProcess.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewProcess.js +113 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewsPage.html +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/ReviewsPage.js +62 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/commands.js +97 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/model.js +147 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/reviews/store.js +13 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ColumnSettings.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ColumnSettings.js +9 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ListBatchBar.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ListBatchBar.js +8 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ListDeleteDialog.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ListDeleteDialog.js +37 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ListMore.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/ListMore.js +8 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/RecordMetadata.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/RecordMetadata.js +17 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/columns.js +32 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/deliveryGuide.js +49 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/deliveryView.js +12 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/listBatch.js +15 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/listSelection.js +37 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/policy.js +68 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shared/session.js +44 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/ConfirmationDialog.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/ConfirmationDialog.js +25 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/ConsoleShell.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/ConsoleShell.js +53 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/PrototypeGuide.html +10 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/PrototypeGuide.js +30 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/ScopePage.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/ScopePage.js +10 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/SessionDialog.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/SessionDialog.js +9 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/confirmation.js +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/shell/navigation.js +19 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecDocument.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecDocument.js +8 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecEdit.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecEdit.js +32 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecHeader.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecHeader.js +15 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecHistory.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecHistory.js +11 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecReview.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecReview.js +57 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecWorkspace.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/SpecWorkspace.js +37 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/data.js +20 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/domain.js +55 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/specs/store.js +151 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/ArtifactDetail.html +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/ArtifactDetail.js +18 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TaskCreate.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TaskCreate.js +40 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TaskDetail.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TaskDetail.js +51 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TaskLaunch.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TaskLaunch.js +9 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TasksPage.html +5 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/TasksPage.js +48 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/domain.js +204 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/exampleSource.js +22 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/registry.js +135 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/tasks/store.js +137 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workbench/WorkbenchPage.html +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workbench/WorkbenchPage.js +36 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workbench/model.js +56 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workbench/store.js +15 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/FlowCanvas.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/FlowCanvas.js +27 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/FlowDetail.html +4 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/FlowDetail.js +31 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/FlowEditor.html +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/FlowEditor.js +68 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/WorkflowsPage.html +5 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/WorkflowsPage.js +55 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/data.js +16 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/domain.js +83 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/registry.js +18 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/workflows/store.js +61 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/admin.css +60 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/agents.css +46 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/antdv.css +295 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/app.css +102 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/delivery.css +4 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/intents.css +37 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/native.css +22 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/operations.css +2 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/pbc.css +3 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/permissions.css +22 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/pro.css +1 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/releases.css +4 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/reset.css +246 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/reviews.css +8 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/tasks.css +6 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/tokens.css +15 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/workbench.css +61 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/styles/workflows.css +1 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/admin-rules.test.js +96 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/agents.test.js +14 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/intent-state.test.js +37 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/list-batch.test.js +44 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/operation-fixtures.js +19 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/operation-repair.test.js +14 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/operations.test.js +25 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/pbc-management.test.js +17 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/pbc-state.test.js +24 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/permission-config.test.js +23 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/permissions.test.js +24 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/releases.test.js +50 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/reviews.test.js +36 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/runtime-forms-router.test.js +28 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/runtime-state.test.js +42 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/runtime-stores.test.js +16 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/spec-state.test.js +11 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/tasks.test.js +27 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/workbench.test.js +34 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tests/workflows.test.js +16 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tools/convert.mjs +168 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tools/serve.mjs +7 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tools/styles.mjs +11 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/tools/verify.mjs +24 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/serve.cjs +16 -0
- package/skills/i3-ui-prototype/assets/templates/enterprise-admin/usability.css +44 -0
- package/skills/i3-ui-prototype/assets/templates/gallery/index.html +40 -0
- package/skills/i3-ui-prototype/assets/templates/modern-workspace/manifest.json +9 -0
- package/skills/i3-ui-prototype/assets/templates/modern-workspace/preset.json +6 -0
- package/skills/i3-ui-prototype/assets/templates/serve-gallery.cjs +16 -0
- package/skills/i3-ui-prototype/references/artifact-contract.md +41 -0
- package/skills/i3-ui-prototype/references/enterprise-admin.md +38 -0
- package/skills/i3-ui-prototype/references/expert-adapter.md +42 -0
- package/skills/i3-ui-prototype/references/template-adapters.md +57 -0
- package/skills/i3-ui-prototype/references/workflow-contract.md +19 -0
- package/skills/i3-ui-prototype/scripts/adapters/easel-html.cjs +30 -0
- package/skills/i3-ui-prototype/scripts/adapters/legacy-html.cjs +28 -0
- package/skills/i3-ui-prototype/scripts/check-design-provider.cjs +9 -0
- package/skills/i3-ui-prototype/scripts/check-prototype.cjs +14 -0
- package/skills/i3-ui-prototype/scripts/enterprise-template.cjs +88 -0
- package/skills/i3-ui-prototype/scripts/init-prototype.cjs +8 -0
- package/skills/i3-ui-prototype/scripts/manage-baseline.cjs +11 -0
- package/skills/i3-ui-prototype/scripts/prototype-lib.cjs +255 -0
- package/skills/i3-ui-prototype/scripts/template-adapters.cjs +89 -0
- package/skills/i3-using-agent-skills/SKILL.md +5 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { actors, metadata } from "../shared/policy.js";
|
|
2
|
+
export const providers = ['企业模型服务', '云端模型服务', '私有化模型服务'];
|
|
3
|
+
export const projects = ['供热工单', 'EASEL 研发', '知识助手'];
|
|
4
|
+
export const agents = ['需求规划 Agent', '研发编码 Agent', '质量评审 Agent', '报修分诊 Agent'];
|
|
5
|
+
export const credentials = [
|
|
6
|
+
{ label: '企业模型服务 · 受管凭据', value: 'vault://demo/models/enterprise' },
|
|
7
|
+
{ label: '云端模型服务 · 受管凭据', value: 'vault://demo/models/cloud' },
|
|
8
|
+
{ label: '私有化服务 · 受管凭据', value: 'vault://demo/models/private' },
|
|
9
|
+
];
|
|
10
|
+
const base = { endpoint: 'https://models.example.invalid/v1', credential: credentials[0].value,
|
|
11
|
+
kind: 'chat', inputPrice: 2, outputPrice: 8, enabled: true, health: 'normal',
|
|
12
|
+
agents: [agents[0], agents[1]], quota: 10000000, version: 1, testedVersion: 1, updatedAt: '2026-09-08 18:20' };
|
|
13
|
+
const originalModels = [
|
|
14
|
+
{ ...base, agents: [...base.agents, '质量评审 Agent'], id: 'demo-1', name: '通用对话模型', alias: 'general-chat', provider: providers[0], capabilities: ['文本', '工具调用'], projects: [...projects] },
|
|
15
|
+
{ ...base, id: 'demo-2', name: '深度推理模型', alias: 'reasoning-pro', provider: providers[0], capabilities: ['文本', '推理'], projects: projects.slice(0, 2), inputPrice: 4, outputPrice: 16 },
|
|
16
|
+
{ ...base, id: 'demo-3', name: '代码助手', alias: 'code-assistant', provider: providers[1], credential: credentials[1].value, capabilities: ['文本', '工具调用'], projects: projects.slice(1) },
|
|
17
|
+
{ ...base, id: 'demo-4', name: '图文理解模型', alias: 'vision-chat', provider: providers[1], credential: credentials[1].value, capabilities: ['文本', '视觉'], projects: [projects[0]], inputPrice: 3, outputPrice: 12 },
|
|
18
|
+
{ ...base, id: 'demo-5', name: '知识检索模型', alias: 'embedding-base', provider: providers[2], credential: credentials[2].value, capabilities: ['向量'], kind: 'embedding', dimension: 1024, projects: [projects[0], projects[2]], health: 'error', testedVersion: undefined, inputPrice: .5, outputPrice: 0 },
|
|
19
|
+
{ ...base, id: 'demo-6', name: '备用对话模型', alias: 'backup-chat', provider: providers[2], credential: credentials[2].value, capabilities: ['文本'], projects: [], agents: [], health: 'untested', enabled: false, testedVersion: undefined },
|
|
20
|
+
];
|
|
21
|
+
export const projectCatalog = [
|
|
22
|
+
{ value: '供热工单', tenantId: 'heating' }, { value: 'EASEL 研发', tenantId: 'heating' }, { value: '知识助手', tenantId: 'north' },
|
|
23
|
+
];
|
|
24
|
+
export const agentCatalog = [
|
|
25
|
+
{ value: '需求规划 Agent', projects: ['供热工单', 'EASEL 研发', '知识助手'] },
|
|
26
|
+
{ value: '研发编码 Agent', projects: ['供热工单', 'EASEL 研发'] },
|
|
27
|
+
{ value: '质量评审 Agent', projects: ['供热工单', 'EASEL 研发', '知识助手'] },
|
|
28
|
+
{ value: '报修分诊 Agent', projects: ['供热工单'] },
|
|
29
|
+
];
|
|
30
|
+
export const seedModels = originalModels.map((m, index) => {
|
|
31
|
+
const grants = ['heating', 'north'].map(tenantId => ({ tenantId,
|
|
32
|
+
projects: m.projects.filter(p => projectCatalog.some(c => c.value === p && c.tenantId === tenantId)), agents: [...m.agents],
|
|
33
|
+
})).filter(g => g.projects.length).map(g => ({ ...g, agents: g.agents.filter(a => agentCatalog.some(c => c.value === a && g.projects.every(p => c.projects.includes(p)))) }));
|
|
34
|
+
const item = { ...m, ...metadata(actors[0], '2026-09-08T10:20:00.000Z', 'platform'),
|
|
35
|
+
grants, references: index < 4 ? [{ name: index === 2 ? '研发编码 Agent' : '标准交付流程', kind: index === 2 ? 'Agent' : '流程模板', version: 'v1' }] : [],
|
|
36
|
+
publishState: m.enabled ? 'published' : 'draft', liveVersion: m.enabled ? 1 : undefined };
|
|
37
|
+
if (item.liveVersion)
|
|
38
|
+
item.liveConfig = { ...m };
|
|
39
|
+
return item;
|
|
40
|
+
});
|
|
41
|
+
export const seedAudit = [
|
|
42
|
+
{ id: 'a1', time: '2026-09-08 18:20', actor: '陈 · 平台管理员', model: '知识检索模型', action: '连接测试', detail: '模拟连接超时,等待检查服务地址。' },
|
|
43
|
+
{ id: 'a2', time: '2026-09-08 18:12', actor: '陈 · 平台管理员', model: '通用对话模型', action: '使用授权', detail: '已授权 3 个演示项目。' },
|
|
44
|
+
{ id: 'a3', time: '2026-09-08 18:00', actor: '陈 · 平台管理员', model: '通用对话模型', action: '启用模型', detail: '演示配置 v1 已启用。' },
|
|
45
|
+
];
|
|
46
|
+
export const fmtNumber = (n) => new Intl.NumberFormat('zh-CN').format(n);
|
|
47
|
+
export const timestamp = () => new Date().toLocaleString('sv-SE').slice(0, 16);
|
|
48
|
+
export const clone = (v) => JSON.parse(JSON.stringify(v));
|
package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/domain.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const modelConfigKeys = ['name', 'alias', 'provider', 'kind', 'endpoint', 'credential', 'capabilities', 'inputPrice', 'outputPrice', 'dimension'];
|
|
2
|
+
export function configSnapshot(model) { return Object.fromEntries(modelConfigKeys.map(key => [key, model[key]])); }
|
|
3
|
+
export function assertVersion(model, expected) {
|
|
4
|
+
if (model.recordVersion !== expected)
|
|
5
|
+
throw new Error('记录版本已变化,请重新打开并核对后提交。');
|
|
6
|
+
}
|
|
7
|
+
export function assertDelete(model) {
|
|
8
|
+
if (model.references.length)
|
|
9
|
+
throw new Error('模型仍被引用,请先调整关联资源。');
|
|
10
|
+
if (model.enabled)
|
|
11
|
+
throw new Error('请先停用模型,再执行删除。');
|
|
12
|
+
if (model.publishState === 'review')
|
|
13
|
+
throw new Error('发布申请正在评审,暂不能删除。');
|
|
14
|
+
}
|
|
15
|
+
export function requestPublish(model, actorId, actorName) {
|
|
16
|
+
if (model.health !== 'normal' || model.testedVersion !== model.version)
|
|
17
|
+
throw new Error('请先完成当前配置版本的测试。');
|
|
18
|
+
if (model.publishState === 'review')
|
|
19
|
+
throw new Error('该版本已提交评审,请等待结果。');
|
|
20
|
+
if (model.liveVersion === model.version)
|
|
21
|
+
throw new Error('当前版本已经发布。');
|
|
22
|
+
return { ...model, publishState: 'review', requestBy: actorId, requestName: actorName, requestId: 'DEMO-CFG-' + model.id.slice(-6) + '-v' + model.version, publishNote: '' };
|
|
23
|
+
}
|
|
24
|
+
export function finishPublish(model, actorId, actorName, at, approve, distributed, note) {
|
|
25
|
+
if (model.publishState !== 'review' || model.testedVersion !== model.version)
|
|
26
|
+
throw new Error('申请状态或配置版本已变化,请重新核对。');
|
|
27
|
+
if (model.requestBy === actorId)
|
|
28
|
+
throw new Error('发布申请须由另一位有权审核的人确认。');
|
|
29
|
+
if (!note.trim())
|
|
30
|
+
throw new Error('请填写评审意见。');
|
|
31
|
+
if (!approve)
|
|
32
|
+
return { ...model, publishState: 'draft', publishNote: '退回修改:' + note.trim() };
|
|
33
|
+
if (!distributed)
|
|
34
|
+
return { ...model, publishState: 'failed', publishNote: '评审通过,但模拟发布失败。当前生效版本保持不变。' };
|
|
35
|
+
return { ...model, publishState: 'published', liveVersion: model.version, liveConfig: configSnapshot(model), publishedBy: actorName, publishedAt: at, publishNote: note.trim() };
|
|
36
|
+
}
|
|
37
|
+
export function authorizedUse(model, tenantId, project, agent) {
|
|
38
|
+
return !model.isDeleted && !!model.liveVersion && model.enabled && model.grants.some((g) => g.tenantId === tenantId && g.projects.includes(project) && g.agents.includes(agent));
|
|
39
|
+
}
|
package/skills/i3-ui-prototype/assets/templates/enterprise-admin/reference/src/models/store.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { defineStore } from "../../runtime/state.js";
|
|
2
|
+
import { agentModelReferences, modelAgentEntries, modelProjectEntries } from "../agents/registry.js";
|
|
3
|
+
import { ref, computed } from '../../runtime/state.js';
|
|
4
|
+
import { clone, seedModels, seedAudit, projectCatalog, agentCatalog } from "./data.js";
|
|
5
|
+
import { useSession } from "../shared/session.js";
|
|
6
|
+
import { metadata } from "../shared/policy.js";
|
|
7
|
+
import { assertVersion, assertDelete, modelConfigKeys, requestPublish, finishPublish } from "./domain.js";
|
|
8
|
+
import { assertBatch } from "../shared/listBatch.js";
|
|
9
|
+
const STORAGE = 'i3-prototype-antdv-models-v010';
|
|
10
|
+
export const useModels = defineStore('models', () => {
|
|
11
|
+
const session = useSession(), records = ref(clone(seedModels)), audit = ref(clone(seedAudit)), scene = ref('normal');
|
|
12
|
+
const persistenceError = ref(false), error = ref('');
|
|
13
|
+
try {
|
|
14
|
+
const v = JSON.parse(localStorage.getItem(STORAGE) || 'null');
|
|
15
|
+
if (v?.schema === 3 && Array.isArray(v.audit) && v.records?.every((m) => Array.isArray(m.grants) && m.createdAt)) {
|
|
16
|
+
records.value = v.records;
|
|
17
|
+
audit.value = v.audit;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
persistenceError.value = true;
|
|
22
|
+
}
|
|
23
|
+
const models = computed(() => records.value.filter(m => !m.isDeleted && (session.readable('model:view', 'platform') || (session.readable('model:view', session.actor.tenantId) && m.liveVersion && m.grants.some(g => g.tenantId === session.actor.tenantId)))).map(m => {
|
|
24
|
+
if (session.readable('model:view', 'platform'))
|
|
25
|
+
return { ...m, references: [...m.references, ...agentModelReferences(m.id)] };
|
|
26
|
+
const grants = m.grants.filter(g => g.tenantId === session.actor.tenantId);
|
|
27
|
+
return { ...m, ...m.liveConfig, version: m.liveVersion, health: m.liveVersion === m.version ? m.health : 'normal', testedVersion: m.liveVersion, grants, projects: grants.flatMap(g => g.projects), agents: [...new Set(grants.flatMap(g => g.agents))], credential: '由平台托管', endpoint: '通过统一模型入口调用', requestId: undefined, requestBy: undefined, requestName: undefined, publishNote: undefined, publishState: 'published', references: [], liveConfig: undefined };
|
|
28
|
+
}));
|
|
29
|
+
const canEdit = computed(() => session.can('model:edit', 'platform')), readOnly = computed(() => !canEdit.value);
|
|
30
|
+
// Local simulation of the configured generation route; model use is a resource grant.
|
|
31
|
+
function generationResource(tenantId) {
|
|
32
|
+
const m = records.value.find(m => m.id === 'demo-1' && !m.isDeleted && m.enabled && m.liveVersion && m.grants.some(g => g.tenantId === tenantId && g.agents.includes('需求规划 Agent') && g.projects.length > 0));
|
|
33
|
+
return m ? { modelId: m.id, name: typeof m.liveConfig?.name === 'string' ? m.liveConfig.name : m.name, version: m.liveVersion, agent: '需求规划 Agent', agentVersion: '1.0(模拟)' } : undefined;
|
|
34
|
+
}
|
|
35
|
+
function commit(next, entries) {
|
|
36
|
+
try {
|
|
37
|
+
localStorage.setItem(STORAGE, JSON.stringify({ schema: 3, records: next, audit: entries }));
|
|
38
|
+
persistenceError.value = false;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
persistenceError.value = true;
|
|
42
|
+
throw new Error('浏览器无法保存演示数据,本次提交未完成。请保留输入后重试。');
|
|
43
|
+
}
|
|
44
|
+
records.value = next;
|
|
45
|
+
audit.value = entries;
|
|
46
|
+
}
|
|
47
|
+
function change(id, permission, action, fn, expected) {
|
|
48
|
+
session.require(permission, 'platform');
|
|
49
|
+
session.writeCheck();
|
|
50
|
+
const current = records.value.find(m => m.id === id && !m.isDeleted);
|
|
51
|
+
if (!current)
|
|
52
|
+
throw new Error('没有权限访问或管理此模型。');
|
|
53
|
+
if (expected !== undefined)
|
|
54
|
+
assertVersion(current, expected);
|
|
55
|
+
const at = new Date().toISOString(), changed = fn(clone(current));
|
|
56
|
+
changed.recordVersion = current.recordVersion + 1;
|
|
57
|
+
changed.updatedAt = at;
|
|
58
|
+
changed.updatedBy = session.actor.name;
|
|
59
|
+
const entry = { id: crypto.randomUUID(), time: at, actor: session.actor.name, model: changed.name, action, detail: '配置 v' + changed.version + ';' + (changed.publishNote || '操作成功(演示)') };
|
|
60
|
+
commit(records.value.map(m => m.id === id ? changed : m), [entry, ...audit.value].slice(0, 200));
|
|
61
|
+
error.value = '';
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
function save(input, isNew) {
|
|
65
|
+
session.require('model:edit', 'platform');
|
|
66
|
+
if (records.value.some(m => !m.isDeleted && m.id !== input.id && m.alias === input.alias))
|
|
67
|
+
throw new Error('模型标识已存在。');
|
|
68
|
+
if (isNew) {
|
|
69
|
+
session.writeCheck();
|
|
70
|
+
const at = new Date().toISOString();
|
|
71
|
+
const record = { ...clone(input), ...metadata(session.actor, at, 'platform'), version: 1, enabled: false, health: 'untested', testedVersion: undefined, publishState: 'draft', grants: [], projects: [], agents: [], references: [], liveVersion: undefined, liveConfig: undefined };
|
|
72
|
+
commit([record, ...records.value], [{ id: crypto.randomUUID(), time: at, actor: session.actor.name, model: record.name, action: '接入模型', detail: '保存草稿 v1,等待测试与发布。' }, ...audit.value]);
|
|
73
|
+
scene.value = 'normal';
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
return change(input.id, 'model:edit', '保存配置草稿', m => {
|
|
77
|
+
if (m.publishState === 'review')
|
|
78
|
+
throw new Error('当前版本正在评审,请等待结果后再修改。');
|
|
79
|
+
const fields = Object.fromEntries(modelConfigKeys.map(k => [k, input[k]]));
|
|
80
|
+
return { ...m, ...fields, version: m.version + 1, health: 'untested', testedVersion: undefined, publishState: 'draft', publishNote: '', requestId: undefined };
|
|
81
|
+
}, input.recordVersion);
|
|
82
|
+
}
|
|
83
|
+
function test(id, version, pass) {
|
|
84
|
+
return change(id, 'model:test', '连接与能力测试', m => {
|
|
85
|
+
if (m.version !== version || m.publishState === 'review')
|
|
86
|
+
throw new Error('配置版本或评审状态已变化,请重新核对后测试。');
|
|
87
|
+
return { ...m, health: pass ? 'normal' : 'error', testedVersion: pass ? version : undefined };
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function toggle(id, expected) {
|
|
91
|
+
return change(id, 'model:status', '调整启停状态', m => {
|
|
92
|
+
if (!m.enabled && !m.liveVersion)
|
|
93
|
+
throw new Error('请先发布经测试和评审的配置,再启用模型。');
|
|
94
|
+
return { ...m, enabled: !m.enabled };
|
|
95
|
+
}, expected);
|
|
96
|
+
}
|
|
97
|
+
function grant(id, grants, quota, expected) {
|
|
98
|
+
return change(id, 'model:grant', '更新使用授权', m => {
|
|
99
|
+
if (!Number.isFinite(quota) || quota < 1)
|
|
100
|
+
throw new Error('请输入有效共享额度。');
|
|
101
|
+
const seen = new Set();
|
|
102
|
+
for (const g of grants) {
|
|
103
|
+
if (seen.has(g.tenantId) || !g.projects.length || !g.agents.length || g.projects.some(p => ![...projectCatalog, ...modelProjectEntries()].some(c => c.value === p && c.tenantId === g.tenantId)) || g.agents.some(a => ![...agentCatalog, ...modelAgentEntries()].some(c => c.value === a && g.projects.every(p => c.projects.includes(p)))))
|
|
104
|
+
throw new Error('请检查每个租户下的项目与 Agent 授权关系。');
|
|
105
|
+
seen.add(g.tenantId);
|
|
106
|
+
}
|
|
107
|
+
return { ...m, grants: clone(grants), projects: [...new Set(grants.flatMap(g => g.projects))], agents: [...new Set(grants.flatMap(g => g.agents))], quota };
|
|
108
|
+
}, expected);
|
|
109
|
+
}
|
|
110
|
+
function submit(id, expected) { return change(id, 'model:edit', '提交发布申请', m => requestPublish(m, session.actor.id, session.actor.name), expected); }
|
|
111
|
+
function review(id, expected, approve, note) { return change(id, 'model:publish', approve ? '评审并发布' : '退回配置', m => finishPublish(m, session.actor.id, session.actor.name, new Date().toISOString(), approve, session.publishResult === 'success', note), expected); }
|
|
112
|
+
function remove(id, expected) { return change(id, 'model:delete', '逻辑删除模型', m => { assertDelete({ ...m, references: [...m.references, ...agentModelReferences(m.id)] }); return { ...m, isDeleted: true }; }, expected); }
|
|
113
|
+
function checkRemove(target) {
|
|
114
|
+
session.require('model:delete', 'platform');
|
|
115
|
+
assertBatch(records.value, [target], m => assertDelete({ ...m, references: [...m.references, ...agentModelReferences(m.id)] }));
|
|
116
|
+
}
|
|
117
|
+
function removeMany(targets) {
|
|
118
|
+
session.require('model:delete', 'platform');
|
|
119
|
+
const selected = assertBatch(records.value, targets, m => assertDelete({ ...m, references: [...m.references, ...agentModelReferences(m.id)] }));
|
|
120
|
+
session.writeCheck();
|
|
121
|
+
const ids = new Set(selected.map(m => m.id)), at = new Date().toISOString(), batchId = crypto.randomUUID();
|
|
122
|
+
const next = records.value.map(m => ids.has(m.id) ? { ...m, isDeleted: true, recordVersion: m.recordVersion + 1, updatedAt: at, updatedBy: session.actor.name } : m);
|
|
123
|
+
const entries = selected.map(m => ({ id: crypto.randomUUID(), time: at, actor: session.actor.name, model: m.name, action: '批量逻辑删除模型', detail: '批次 ' + batchId + ';本批共 ' + selected.length + ' 项' }));
|
|
124
|
+
commit(next, [...entries, ...audit.value].slice(0, 200));
|
|
125
|
+
}
|
|
126
|
+
function reset() { commit(clone(seedModels), clone(seedAudit)); scene.value = 'normal'; error.value = ''; }
|
|
127
|
+
function agentChoices(tenantId, project, agentKey) { return records.value.map(m => ({ id: m.id, name: String(m.liveConfig?.name || m.name), version: m.liveVersion, enabled: m.enabled, kind: String(m.liveConfig?.kind || m.kind), capabilities: (m.liveConfig?.capabilities || m.capabilities), deleted: m.isDeleted, authorized: m.grants.some(g => g.tenantId === tenantId && g.projects.includes(project) && g.agents.includes(agentKey)) })); }
|
|
128
|
+
return { agentChoices, models, audit, readOnly, canEdit, scene, persistenceError, error, save, test, toggle, grant, submit, review, remove, checkRemove, removeMany, reset, generationResource };
|
|
129
|
+
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<!-- 来源:src/operations/IncidentDetail.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
|
|
2
|
+
<template data-component="Result" data-if="(!row || !incident)" status="403" title="异常不存在或无权访问"><template data-slot="extra"><template data-component="Button" data-on-click="(router.push('/operations'))">返回运行管理</template></template></template><template data-else=""><div class="page-heading"><div><template data-component="Button" type="link" class="agent-back" data-on-click="(router.push('/operations?tab=incidents'))">← 异常队列</template><h1>{{ (incident.title) }}</h1><p>{{ (incident.code) }} · {{ (formatDate(incident.observedAt)) }} · 证据 v{{ (incident.evidenceVersion) }}</p></div><template data-component="Tag" data-bind-color="(incident.closed ? 'green' : 'orange')">{{ (row.run.unconfirmed ? '结果待核实' : incidentLabel(incident)) }}</template></div><template data-component="Alert" data-if="(row.run.unconfirmed)" type="warning" show-icon="" title="异常处理结果待核实"><template data-slot="action"><template data-component="Button" data-on-click="(verify)">查询原请求回执</template></template></template><template data-else=""><div class="ops-layout"><div><section class="ops-card"><div class="ops-section-head"><h2>已观测事实</h2><template data-component="Tag" color="red">{{ (incident.band) }} · 模拟提示</template></div><p>{{ (incident.signal) }}</p><p>异常发生于 {{ (incident.source.version) }} / {{ (incident.source.config) }};来源证据固定,后续修复不会覆盖。</p><p class="muted">偏差等级仅为本地样例提示,未据此配置生产阈值或自动执行操作。</p><h3>请求与日志线索</h3><p class="mono">{{ (incident.traceId) }}</p><pre class="ops-logs">{{ (incident.logs.map(l => formatDate(l.at) + ' [' + l.level + '] ' + l.text).join('\n')) }}</pre></section><section class="ops-card"><div class="ops-section-head"><h2>调查报告</h2><template data-component="Button" data-bind-disabled="(!!store.reason(row, 'diagnose', incident.id))" data-bind-title="(store.reason(row, 'diagnose', incident.id))" data-on-click="(action = 'diagnose')">补充调查</template></div><template data-component="Select" data-if="(incident.reports.length)" data-model-value="(reportVersion)" aria-label="调查报告版本" data-bind-placeholder="('当前报告 v' + incident.reports.at(-1).number)" data-bind-options="([...incident.reports].reverse().map(r => ({ value: r.number, label: '报告 v' + r.number + ' · ' + formatDate(r.at) })))"></template><p data-if="(!report)" class="ops-empty">尚无调查报告。先结合日志线索补充调查,再决定如何处理。</p><template data-else=""><template data-component="Alert" data-if="(report.status === 'incomplete')" type="warning" title="资料未齐备,需继续调查"></template><h3>事实</h3><ul><li data-each="f in (report.facts)" data-bind-key="(f)">{{ (f) }}</li></ul><h3>待验证假设</h3><ul><li data-each="f in (report.hypotheses)" data-bind-key="(f)">{{ (f) }}</li></ul><p data-if="(!report.hypotheses.length)" class="muted">资料不足,暂不形成根因判断。</p><h3>待补充问题</h3><ul><li data-each="q in (report.questions)" data-bind-key="(q)">{{ (q) }}</li></ul><p>{{ (report.suggestion) }}</p><small class="muted">{{ (report.by) }} · 报告 v{{ (report.number) }} · {{ (formatDate(report.at)) }}</small></template></section></div><aside><section class="ops-card"><h2>分诊与处理</h2><p>根据最新调查报告选择处理方向。立即修复和排期修复都通过需求交付流程推进。</p><template data-component="Space" direction="vertical" style="width:100%"><template data-component="Button" data-each="a in ['triageNow', 'triagePlan', 'triageReject']" data-bind-key="(a)" block="" data-bind-type="(a === 'triageNow' ? 'primary' : 'default')" data-bind-disabled="(!!store.reason(row, a, incident.id) || !!linked)" data-bind-title="(linked ? '已关联修复需求,请在修复跟踪继续。' : store.reason(row, a, incident.id))" data-on-click="reportVersion = undefined;
|
|
3
|
+
action = a;">{{ (({ triageNow: '立即修复', triagePlan: '排期修复', triageReject: '驳回异常' })[a]) }}</template></template><div data-if="(incident.triage)" class="ops-check"><strong>已记录:{{ (incidentLabel(incident)) }}</strong><p>{{ (incident.triage.note) }}</p><small>{{ (incident.triage.actor) }} · 报告 v{{ (incident.triage.reportVersion) }} · {{ (formatDate(incident.triage.at)) }}</small></div><template data-component="Button" style="margin-top:16px" block="" data-bind-disabled="(!store.session.can('intent:view', incident.tenantId))" data-on-click="(router.push(route.path + '/repair'))">{{ (linked ? '查看修复跟踪' : '关联或创建修复需求') }} →</template></section><section data-if="(incident.closed)" class="ops-card"><h2>修复关闭记录</h2><p>{{ (incident.closed.note) }}</p><p>修复版本 {{ (incident.closed.target.version) }} · 证据 v{{ (incident.closed.target.evidenceVersion) }}</p><small>{{ (incident.closed.actor) }} · {{ (formatDate(incident.closed.at)) }}</small></section></aside></div></template><section data-if="(!row.run.unconfirmed)" class="ops-card"><h2>异常处理历史</h2><article data-each="e in (row.run.events.filter(e => e.incidentId === incident.id).slice().reverse())" data-bind-key="(e.id)" class="ops-check"><strong>{{ (e.action) }}</strong><p>{{ (e.detail) }}</p><small>{{ (e.actor) }} · {{ (formatDate(e.at)) }}</small></article><h3 data-if="(incident.triageHistory?.length)">分诊依据</h3><p data-each="(t,n) in (incident.triageHistory || [])" data-bind-key="(n)">{{ (({ now: '立即修复', plan: '排期修复', reject: '驳回异常' })[t.choice]) }} · 报告 v{{ (t.reportVersion) }} · {{ (t.actor) }} · {{ (formatDate(t.at)) }}</p></section><template data-component="SourceSummary" data-bind-source="(incident.source)"></template><template data-component="RecordMetadata" data-bind-record="(incident)"></template><template data-component="OperationActionDialog" data-if="(action)" data-bind-row="(row)" data-bind-action="(action)" data-bind-incident-id="(incident.id)" data-on-close="(action = undefined)" data-on-done="action = undefined;
|
|
4
|
+
reportVersion = undefined;"></template></template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { computed, ref } from '../../runtime/state.js';
|
|
2
|
+
import { useRoute, useRouter } from "../../runtime/router.js";
|
|
3
|
+
import { Alert, Button, Result, Select, Space, Tag, message } from "../../runtime/widgets.js";
|
|
4
|
+
import { useOperations } from "./store.js";
|
|
5
|
+
import { incidentLabel } from "./model.js";
|
|
6
|
+
import { linkedIntent } from "./repair.js";
|
|
7
|
+
import { formatDate } from "../shared/policy.js";
|
|
8
|
+
import RecordMetadata from "../shared/RecordMetadata.js";
|
|
9
|
+
import SourceSummary from "./SourceSummary.js";
|
|
10
|
+
import OperationActionDialog from "./OperationActionDialog.js";
|
|
11
|
+
import { createComponent } from '../../runtime/dom.js';
|
|
12
|
+
export default createComponent({ name: 'IncidentDetail', propKeys: [], template: new URL('./IncidentDetail.html', import.meta.url).href, setup(__props, __emit) {
|
|
13
|
+
const route = useRoute(), router = useRouter(), store = useOperations(), row = computed(() => store.rows.find(r => r.task.id === route.params.taskId && r.run.id === route.params.runId)), incident = computed(() => row.value?.run.incidents.find(i => i.id === route.params.incidentId)), action = ref(), reportVersion = ref(), report = computed(() => incident.value?.reports.find(r => r.number === reportVersion.value) || incident.value?.reports.at(-1)), linked = computed(() => linkedIntent(store.intents.items, incident.value?.id || ''));
|
|
14
|
+
function verify() { try {
|
|
15
|
+
store.apply(row.value.run.id, { id: crypto.randomUUID(), action: 'verify', expected: row.value.run.recordVersion });
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
message.error(e.message);
|
|
19
|
+
} }
|
|
20
|
+
return { computed, ref, useRoute, useRouter, Alert, Button, Result, Select, Space, Tag, message, useOperations, incidentLabel, linkedIntent, formatDate, RecordMetadata, SourceSummary, OperationActionDialog, route, router, store, row, incident, action, reportVersion, report, linked, verify };
|
|
21
|
+
} });
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
<!-- 来源:src/operations/IntentSource.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
|
|
2
|
+
<template data-component="Alert" data-each="l in (intent.operationLinks || [])" data-bind-key="(l.incidentId)" class="page-alert" type="info" data-bind-title="(l.unconfirmed ? '运行异常关联结果待核实' : '来源运行异常:' + l.incidentCode)" data-bind-description="(l.incidentTitle + ' · ' + l.project + ' · 发布版本 ' + l.sourceVersion)"><template data-slot="action"><template data-component="Button" data-bind-disabled="(!session.can('operation:view', l.tenantId, l.pbcId, 'production'))" data-on-click="(router.push('/operations/' + l.taskId + '/' + l.runId + '/incidents/' + l.incidentId + '/repair'))">查看修复跟踪</template></template></template>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Alert, Button } from "../../runtime/widgets.js";
|
|
2
|
+
import { useRouter } from "../../runtime/router.js";
|
|
3
|
+
import { useSession } from "../shared/session.js";
|
|
4
|
+
import { createComponent } from '../../runtime/dom.js';
|
|
5
|
+
export default createComponent({ name: 'IntentSource', propKeys: ["intent"], template: new URL('./IntentSource.html', import.meta.url).href, setup(__props, __emit) {
|
|
6
|
+
const props = __props, session = useSession(), router = useRouter();
|
|
7
|
+
return { Alert, Button, useRouter, useSession, props, session, router };
|
|
8
|
+
} });
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
<!-- 来源:src/operations/OperationActionDialog.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
|
|
2
|
+
<template data-component="Modal" open="" data-bind-title="(operationLabels[action])" data-bind-width="(600)" data-bind-footer="(null)" data-on-cancel="(emit('close'))"><div class="ops-form"><p>{{ (row.run.source.service) }} · {{ (row.run.source.version) }} · 生产环境</p><p class="muted">绑定运行记录 v{{ (expected) }};处理人 {{ (store.session.actor.name) }}。{{ (action === 'closeIncident' ? '关闭前须核对新修复版本的验收与回归证据。' : '提交会保留来源、说明和操作回执。') }}</p><template data-component="Alert" data-if="(stale)" type="warning" title="页面版本已变化,原说明保留"><template data-slot="action"><template data-component="Button" data-on-click="(rebase)">核对当前版本</template></template></template><template data-component="Alert" data-if="(why || error)" data-bind-type="(why ? 'warning' : 'info')" data-bind-title="(error || why)" show-icon=""></template><template data-component="Alert" data-if="(target)" type="info" data-bind-title="('本次关闭依据:修复版本 ' + target.version + ' · 证据 v' + target.evidenceVersion)" data-bind-description="(target.digest + ' / ' + target.config)"></template><p data-if="(incidentId)" class="muted">异常处理依据:最新报告 v{{ (row.run.incidents.find(i => i.id === incidentId)?.reports.at(-1)?.number || 0) }}。</p><label>处理说明 <template data-component="TextArea" data-model-value="(note)" aria-label="处理说明" data-bind-rows="(4)" data-bind-maxlength="(2000)" placeholder="填写核对结果、处理理由或后续安排"></template></label><template data-component="Checkbox" data-if="(['accept', 'rejectAcceptance', 'closeIncident'].includes(action))" data-model-checked="(checked)">已核对本次版本、证据与处理影响</template><details class="ops-demo"><summary>原型演示控件</summary><label data-if="(action === 'observe' || action === 'diagnose')">本轮模拟证据 <template data-component="Select" data-model-value="(outcome)" aria-label="本轮模拟证据" data-bind-options="([{ value: 'pass', label: '完整 / 通过' }, { value: 'fail', label: '业务失败 / 调查不完整' }, { value: 'missing', label: '证据缺失' }, { value: 'stale', label: '证据过期' }])"></template></label><label>本次模拟响应 <template data-component="Select" data-model-value="(store.response)" aria-label="本次模拟响应" data-bind-options="([{ value: 'success', label: '成功' }, { value: 'failure', label: '服务失败,保留输入' }, { value: 'unknown', label: '响应不明,查询原请求' }])"></template></label><p>仅改变本地演示结果,不连接监控或生产服务。</p></details><div class="ops-buttons"><template data-component="Button" data-on-click="(emit('close'))">取消</template><template data-component="Button" type="primary" data-bind-loading="(busy)" data-bind-disabled="(!!why || stale)" data-on-click="(submit)">提交{{ (operationLabels[action]) }}</template></div></div></template>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { computed, ref, watch } from '../../runtime/state.js';
|
|
2
|
+
import { Alert, Button, Checkbox, Modal, Select, TextArea } from "../../runtime/widgets.js";
|
|
3
|
+
import { useOperations } from "./store.js";
|
|
4
|
+
import { operationLabels } from "./model.js";
|
|
5
|
+
import { createComponent } from '../../runtime/dom.js';
|
|
6
|
+
export default createComponent({ name: 'OperationActionDialog', propKeys: ["row", "action", "incidentId", "target"], template: new URL('./OperationActionDialog.html', import.meta.url).href, setup(__props, __emit) {
|
|
7
|
+
const props = __props, emit = __emit, store = useOperations();
|
|
8
|
+
const expected = ref(props.row.run.recordVersion), target = ref(props.target), note = ref(''), checked = ref(false), outcome = ref('pass'), error = ref(''), busy = ref(false), request = ref(crypto.randomUUID());
|
|
9
|
+
const draftKey = 'i3-prototype-antdv-ops-draft:' + store.session.actor.id + ':' + props.row.run.id + ':' + props.action + ':' + (props.incidentId || '');
|
|
10
|
+
try {
|
|
11
|
+
note.value = sessionStorage.getItem(draftKey) || '';
|
|
12
|
+
}
|
|
13
|
+
catch { }
|
|
14
|
+
watch(note, v => { try {
|
|
15
|
+
sessionStorage.setItem(draftKey, v);
|
|
16
|
+
}
|
|
17
|
+
catch { } });
|
|
18
|
+
const current = computed(() => store.find(props.row.run.id)), why = computed(() => !current.value ? '记录已不可访问。' : props.action === 'closeIncident' ? store.closeReason(current.value, props.incidentId, target.value) : store.reason(current.value, props.action, props.incidentId)), stale = computed(() => current.value?.run.recordVersion !== expected.value || JSON.stringify(props.target) !== JSON.stringify(target.value));
|
|
19
|
+
function rebase() { if (!current.value)
|
|
20
|
+
return; expected.value = current.value.run.recordVersion; target.value = props.target; checked.value = false; request.value = crypto.randomUUID(); error.value = '已载入当前记录版本;请重新核对证据,原说明已保留。'; }
|
|
21
|
+
function submit() { busy.value = true; error.value = ''; try {
|
|
22
|
+
store.apply(props.row.run.id, { id: request.value, action: props.action, expected: expected.value, note: note.value, checked: checked.value, outcome: outcome.value, incidentId: props.incidentId, target: target.value });
|
|
23
|
+
try {
|
|
24
|
+
sessionStorage.removeItem(draftKey);
|
|
25
|
+
}
|
|
26
|
+
catch { }
|
|
27
|
+
;
|
|
28
|
+
emit('done');
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
error.value = e.message;
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
busy.value = false;
|
|
35
|
+
} }
|
|
36
|
+
return { computed, ref, watch, Alert, Button, Checkbox, Modal, Select, TextArea, useOperations, operationLabels, props, emit, store, expected, target, note, checked, outcome, error, busy, request, draftKey, current, why, stale, rebase, submit };
|
|
37
|
+
} });
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
<!-- 来源:src/operations/OperationEntry.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
|
|
2
|
+
<template data-component="Alert" data-if="(runs.length)" class="page-alert" type="info" show-icon="" title="已进入运行验收" data-bind-description="(runs.map(r => r.source.version + ' · ' + acceptanceLabel(r) + ' · ' + healthLabel(r)).join(';'))"><template data-slot="action"><template data-component="Button" data-on-click="(router.push('/operations?task=' + task.id + (releaseId ? '&run=' + runs[0].id : '')))">运行记录与异常</template></template></template>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { computed } from '../../runtime/state.js';
|
|
2
|
+
import { useRouter } from "../../runtime/router.js";
|
|
3
|
+
import { Alert, Button } from "../../runtime/widgets.js";
|
|
4
|
+
import { useSession } from "../shared/session.js";
|
|
5
|
+
import { canReadRun, runsForTask, acceptanceLabel, healthLabel } from "./model.js";
|
|
6
|
+
import { createComponent } from '../../runtime/dom.js';
|
|
7
|
+
export default createComponent({ name: 'OperationEntry', propKeys: ["task", "releaseId"], template: new URL('./OperationEntry.html', import.meta.url).href, setup(__props, __emit) {
|
|
8
|
+
const props = __props, session = useSession(), router = useRouter(), runs = computed(() => canReadRun(props.task, session.actor) ? runsForTask(props.task).filter(r => !props.releaseId || r.source.releaseId === props.releaseId) : []);
|
|
9
|
+
return { computed, useRouter, Alert, Button, useSession, canReadRun, runsForTask, acceptanceLabel, healthLabel, props, session, router, runs };
|
|
10
|
+
} });
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
<!-- 来源:src/operations/OperationsPage.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
|
|
2
|
+
<div class="page-heading"><div><h1>运行管理</h1><p>核对业务运行结果,分诊异常,跟踪修复后的重新验收。</p></div><template data-component="Button" data-bind-disabled="(!store.session.can('artifact:view'))" data-on-click="(router.push('/releases'))">查看发布记录</template></div><div class="task-metrics"><article><span>待运行验收</span><strong>{{ (rows.filter(r => !sourceReason(r.task, r.run) && acceptanceLabel(r.run) === '待验收').length) }}</strong></article><article><span>当前运行异常</span><strong>{{ (rows.filter(r => !sourceReason(r.task, r.run) && healthLabel(r.run) === '运行异常').length) }}</strong></article><article><span>未结束异常</span><strong>{{ (incidents.filter(i => !['已关闭', '已驳回'].includes(i.status)).length) }}</strong></article><article><span>验收通过</span><strong>{{ (rows.filter(r => acceptanceLabel(r.run) === '验收通过').length) }}</strong></article></div><template data-component="Alert" data-if="(error || store.notice)" type="error" show-icon="" data-bind-title="(error || store.notice)" class="page-alert"></template><template data-component="Alert" data-if="(route.query.task)" class="page-alert" type="info" title="当前仅显示来源任务的运行记录"><template data-slot="action"><template data-component="Button" data-on-click="(router.replace('/operations'))">查看全部</template></template></template><template data-component="Alert" data-if="(!store.rows.length)" class="page-alert" type="info" show-icon="" title="尚无可见的生产运行记录" description="从已核实成功的生产发布进入运行验收;评审原型可载入一组独立模拟样例。"><template data-slot="action"><template data-component="Button" data-bind-disabled="(!store.session.can('operation:observe') || !store.session.can('task:create'))" data-on-click="(addExamples)">载入运行演示样例</template></template></template><div class="ops-section-head"><template data-component="Tabs" data-model-active-key="(tab)" data-bind-items="([{ key: 'runs', label: '运行记录与验收' }, { key: 'incidents', label: '异常队列' }])"></template><template data-component="Select" data-model-value="(pbc)" aria-label="运行 PBC 筛选" data-bind-options="([{ value: 'all', label: '全部可见 PBC' }, ...Array.from(new Map(store.rows.map(r => [r.run.source.pbcId, { value: r.run.source.pbcId, label: r.run.source.project }])).values())])"></template></div><template data-component="Alert" data-if="(rows.some(r => r.run.unconfirmed))" class="page-alert" type="warning" title="存在待核实的运行记录" description="请在运行记录中查询原请求回执。未核实结果暂不计入异常统计。"></template><template data-component="ManagementTable" data-bind-key="(tab)" data-bind-page-key="(tab === 'runs' ? '运行记录' : '运行异常')" data-bind-rows="(tab === 'runs' ? runs : incidents)" readonly="" data-bind-scene="(store.scene)" data-bind-more="(more)" data-bind-owner-label="(tab === 'runs' ? '验收人' : '处理人')" data-bind-context-label="(tab === 'runs' ? 'PBC / 版本 / 最近观测' : 'PBC / 异常版本')" data-on-action="(action)" data-on-refresh="(store.scene = 'normal')"></template><p class="review-footnote">运行记录由已核实成功的生产发布产生。验收与异常证据不可删除或批量删除,业务处理通过详情页记录;预发布仍在发布模块查看。</p><details class="ops-demo"><summary>原型评审:样例与列表状态</summary><template data-component="Space" wrap=""><template data-component="Button" data-if="(store.rows.length)" data-bind-disabled="(!store.session.can('operation:observe') || !store.session.can('task:create'))" data-on-click="(addExamples)">载入运行演示样例</template><template data-component="Select" data-model-value="(store.scene)" aria-label="运行列表演示状态" data-bind-options="([{ value: 'normal', label: '正常列表' }, { value: 'empty', label: '空列表' }, { value: 'error', label: '加载失败' }])"></template></template><p>包含正常、缺失证据、新异常、已关联需求和等待修复验证;全部为本地模拟,保留已有数据。</p></details><template data-component="RunDetail" data-if="(route.query.run)" data-bind-id="(String(route.query.run))" data-on-close="(router.replace({ query: { ...route.query, run: undefined } }))"></template>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { computed, ref, watch } from '../../runtime/state.js';
|
|
2
|
+
import { useRoute, useRouter } from "../../runtime/router.js";
|
|
3
|
+
import { Alert, Button, Select, Space, Tabs, message } from "../../runtime/widgets.js";
|
|
4
|
+
import { useOperations } from "./store.js";
|
|
5
|
+
import { acceptanceLabel, healthLabel, incidentLabel, sourceReason } from "./model.js";
|
|
6
|
+
import ManagementTable from "../pbc/ManagementTable.js";
|
|
7
|
+
import RunDetail from "./RunDetail.js";
|
|
8
|
+
import { createComponent } from '../../runtime/dom.js';
|
|
9
|
+
export default createComponent({ name: 'OperationsPage', propKeys: [], template: new URL('./OperationsPage.html', import.meta.url).href, setup(__props, __emit) {
|
|
10
|
+
const store = useOperations(), route = useRoute(), router = useRouter(), tab = ref(String(route.query.tab || 'runs')), pbc = ref(String(route.query.pbc || 'all')), error = ref('');
|
|
11
|
+
watch(tab, v => router.replace({ query: { ...route.query, tab: v, run: undefined } }));
|
|
12
|
+
watch(() => route.query.pbc, v => pbc.value = String(v || 'all'));
|
|
13
|
+
const rows = computed(() => store.rows.filter(r => (pbc.value === 'all' || r.run.source.pbcId === pbc.value) && (!route.query.task || r.task.id === route.query.task)));
|
|
14
|
+
const runs = computed(() => rows.value.map(({ run: r, task }) => ({ ...r, name: r.source.service, code: r.code, status: sourceReason(task, r) && !r.unconfirmed ? '历史记录' : acceptanceLabel(r), context: r.source.project + ' · ' + r.source.version + ' · ' + healthLabel(r), owner: r.unconfirmed ? '待核实' : r.acceptances.at(-1)?.actor || (sourceReason(task, r) ? '历史记录' : '尚未验收') })));
|
|
15
|
+
const incidents = computed(() => rows.value.flatMap(({ run: r }) => r.unconfirmed ? [] : r.incidents.map(i => ({ ...i, name: i.title, status: incidentLabel(i), context: i.source.project + ' · ' + i.source.version, owner: i.triage?.actor || '待分诊' }))));
|
|
16
|
+
function more(r) { return tab.value === 'runs' ? [{ key: 'detail', label: '运行证据与验收' }, { key: 'source', label: '来源交付任务' }, { key: 'delete', label: '删除 / 批量删除不适用:保留历史证据', disabled: true }] : [{ key: 'detail', label: '异常详情与分诊' }, { key: 'repair', label: '修复跟踪' }, { key: 'delete', label: '删除 / 批量删除不适用:保留处理记录', disabled: true }]; }
|
|
17
|
+
function action(key, r) { if (tab.value === 'runs') {
|
|
18
|
+
const row = store.find(r.id);
|
|
19
|
+
if (key === 'source')
|
|
20
|
+
router.push('/tasks/' + row.task.id);
|
|
21
|
+
else
|
|
22
|
+
router.replace({ query: { ...route.query, run: r.id } });
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
const row = rows.value.find(x => x.run.incidents.some(i => i.id === r.id));
|
|
26
|
+
router.push('/operations/' + row.task.id + '/' + row.run.id + '/incidents/' + r.id + (key === 'repair' ? '/repair' : ''));
|
|
27
|
+
} }
|
|
28
|
+
function addExamples() { try {
|
|
29
|
+
const n = store.addExamples();
|
|
30
|
+
message.success(n ? '已载入独立运行样例' : '样例已存在,保留当前评审数据');
|
|
31
|
+
error.value = '';
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
error.value = e.message;
|
|
35
|
+
} }
|
|
36
|
+
return { computed, ref, watch, useRoute, useRouter, Alert, Button, Select, Space, Tabs, message, useOperations, acceptanceLabel, healthLabel, incidentLabel, sourceReason, ManagementTable, RunDetail, store, route, router, tab, pbc, error, rows, runs, incidents, more, action, addExamples };
|
|
37
|
+
} });
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
<!-- 来源:src/operations/RepairTrack.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
|
|
2
|
+
<template data-component="Result" data-if="(!row || !incident || !store.session.can('intent:view', row.run.tenantId))" status="403" title="修复记录不存在或无权访问"><template data-slot="extra"><template data-component="Button" data-on-click="(router.push('/operations'))">返回运行管理</template></template></template><template data-else=""><div class="page-heading"><div><template data-component="Button" type="link" class="agent-back" data-on-click="(router.push(route.path.replace('/repair', '')))">← 异常详情</template><h1>修复跟踪</h1><p>{{ (incident.code) }} · {{ (incident.title) }}</p></div><template data-component="Tag" data-bind-color="(incident.closed ? 'green' : 'orange')">{{ (row.run.unconfirmed || link?.unconfirmed ? '结果待核实' : incident.closed ? '修复已关闭' : intent ? '修复进行中' : '待关联修复需求') }}</template></div><template data-component="Alert" data-if="(error)" class="page-alert" type="warning" show-icon="" data-bind-title="(error)"></template><template data-component="Alert" data-if="(row.run.unconfirmed)" class="page-alert" type="warning" title="原处理结果待核实,请返回异常详情查询原请求回执。"></template><section data-if="(!intent && !row.run.unconfirmed)" class="ops-card ops-link-form"><h2>把异常接入需求交付流程</h2><p>新建需求从意图草稿开始;关联已有需求则沿用其规格与交付记录。保留异常来源,不自动确认规格或创建 PBC。</p><template data-component="Alert" data-if="(linkReason)" type="info" data-bind-title="(linkReason)"></template><div class="ops-form"><label>处理方式 <template data-component="Select" data-model-value="(mode)" aria-label="修复需求处理方式" data-bind-options="([{ value: 'new', label: '创建修复意图草稿' }, { value: 'existing', label: '关联已有需求' }])"></template></label><label data-if="(mode === 'existing')">已有需求 <template data-component="Select" data-model-value="(targetId)" show-search="" option-filter-prop="label" aria-label="关联已有修复需求" placeholder="选择同租户已有需求" data-bind-options="(store.intents.items.filter(i => i.tenantId === incident.tenantId && i.status !== 'closed').map(i => ({ value: i.id, label: i.code + ' · ' + i.title })))"></template></label><label>修复与关联说明 <template data-component="TextArea" data-model-value="(note)" aria-label="修复与关联说明" data-bind-rows="(4)" data-bind-maxlength="(2000)" placeholder="说明要解决的问题、影响范围及如何验证"></template></label><div data-if="(expected !== row.run.recordVersion || error)" class="ops-buttons"><template data-component="Button" data-on-click="(rebase)">核对当前版本</template></div><details class="ops-demo"><summary>原型演示:提交响应</summary><template data-component="Select" data-model-value="(store.response)" aria-label="关联模拟响应" data-bind-options="([{ value: 'success', label: '成功' }, { value: 'failure', label: '保存失败' }, { value: 'unknown', label: '响应不明' }])"></template></details><div class="ops-buttons"><template data-component="Button" type="primary" data-bind-disabled="(!!linkReason || expected !== row.run.recordVersion)" data-on-click="(submit)">{{ (mode === 'new' ? '创建修复意图草稿' : '确认关联需求') }}</template></div></div></section><template data-component="Alert" data-if="(link?.unconfirmed)" class="page-alert" type="warning" show-icon="" title="关联结果待核实" description="保留原请求,查询实际关联结果;不会重复创建需求。"><template data-slot="action"><template data-component="Button" data-on-click="(verify)">查询原关联回执</template></template></template><template data-if="(intent && !link?.unconfirmed && !row.run.unconfirmed)"><div class="ops-chain"><article><span>01</span><h3>修复需求</h3><p>{{ (intent.code) }}</p><template data-component="Tag">{{ (intent.status === 'confirmed' ? '意图已确认' : intent.status === 'ready' ? '待确认意图' : intent.status === 'closed' ? '需求已关闭' : '待澄清 / 草稿') }}</template></article><article><span>02</span><h3>规格与交付</h3><p>{{ (linkedTasks.length ? '已有 ' + linkedTasks.length + ' 个后续交付任务' : '等待需求确认与交付') }}</p></article><article><span>03</span><h3>新版本与回归</h3><p>{{ (candidates.length ? '已有 ' + candidates.length + ' 个生产修复版本' : '尚无新生产修复版本') }}</p></article><article><span>04</span><h3>运行验收与关闭</h3><p>{{ (incident.closed ? '已保留关闭证据' : '待核对新版本验收') }}</p></article></div><section class="ops-card"><div class="ops-section-head"><h2>{{ (intent.title) }}</h2><template data-component="Button" type="primary" data-on-click="(router.push('/intents/' + intent.id + '/workspace'))">继续处理需求</template></div><p>{{ (link?.note) }}</p><p class="muted">关联人 {{ (link?.actor) }} · 原异常版本 {{ (link?.sourceVersion) }}。需求已有的确认记录保持,新修复范围仍需核对规格。</p><template data-component="Space" wrap=""><template data-component="Button" data-on-click="(router.push('/intents/' + intent.id))">需求详情与来源</template><template data-component="Button" data-if="(store.session.can('spec:view', intent.tenantId))" data-on-click="(router.push('/intents/' + intent.id + '/spec'))">需求规格</template><template data-component="Button" data-if="(store.session.can('task:create', intent.tenantId, incident.source.pbcId))" data-on-click="(router.push('/tasks/new?intent=' + intent.id))">发起交付</template></template></section><section class="ops-card"><h2>后续交付与生产修复版本</h2><p data-if="(!linkedTasks.length)" class="muted">尚无异常发生后创建的交付任务。创建需求、生成代码或发布成功均不会自动关闭异常。</p><article data-each="t in (linkedTasks)" data-bind-key="(t.id)" class="ops-check"><template data-component="Button" type="link" data-on-click="(router.push('/tasks/' + t.id))">{{ (t.code) }} · {{ (t.name) }}</template><template data-component="Tag">{{ (taskReleaseLabel(t, store.session.actor) || statusLabels[t.status]) }}</template></article><label data-if="(candidates.length)" class="ops-target">用于关闭的修复版本 <template data-component="Select" data-model-value="(chosen)" aria-label="选择修复版本" placeholder="选择新生产版本,核对回归和人工验收" data-bind-options="(candidates.map(c => ({ value: c.runId, label: c.version + ' · ' + store.find(c.runId)?.run.source.service })))"></template></label><div data-if="(targetRow)" class="ops-check"><p>人工验收:{{ (acceptanceLabel(targetRow.run)) }} · 当前健康:{{ (healthLabel(targetRow.run)) }}</p><p>证据 v{{ (target?.evidenceVersion) }} · {{ (target?.digest) }} · {{ (target?.config) }}</p><template data-component="Button" data-on-click="(router.push('/operations?run=' + target.runId))">补齐观测与运行验收</template></div></section><section class="ops-card"><h2>{{ (incident.closed ? '关闭证据' : '确认修复结果') }}</h2><template data-if="(incident.closed)"><p>{{ (incident.closed.note) }}</p><p>{{ (incident.closed.actor) }} · 修复版本 {{ (incident.closed.target.version) }} · 证据 v{{ (incident.closed.target.evidenceVersion) }}</p></template><template data-else=""><template data-component="Alert" data-if="(closeReason)" type="info" show-icon="" data-bind-title="(closeReason)"></template><p>关闭会绑定所选生产修复版本、回归证据、验收人和处理说明,旧异常与旧版本继续保留。</p><template data-component="Button" type="primary" data-bind-disabled="(!!closeReason)" data-on-click="(closing = true)">确认修复并关闭</template></template></section></template><template data-component="SourceSummary" data-bind-source="(incident.source)"></template><template data-component="OperationActionDialog" data-if="(closing)" data-bind-row="(row)" action="closeIncident" data-bind-incident-id="(incident.id)" data-bind-target="(target)" data-on-close="(closing = false)" data-on-done="(closing = false)"></template></template>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { computed, ref, watch } from '../../runtime/state.js';
|
|
2
|
+
import { useRoute, useRouter } from "../../runtime/router.js";
|
|
3
|
+
import { Alert, Button, Checkbox, Input, Result, Select, Space, Tag, TextArea, message } from "../../runtime/widgets.js";
|
|
4
|
+
import { useOperations } from "./store.js";
|
|
5
|
+
import { linkedIntent, repairCandidates } from "./repair.js";
|
|
6
|
+
import { acceptanceLabel, healthLabel, runsForTask } from "./model.js";
|
|
7
|
+
import { taskReleaseLabel } from "../releases/model.js";
|
|
8
|
+
import { statusLabels } from "../tasks/domain.js";
|
|
9
|
+
import OperationActionDialog from "./OperationActionDialog.js";
|
|
10
|
+
import SourceSummary from "./SourceSummary.js";
|
|
11
|
+
import { createComponent } from '../../runtime/dom.js';
|
|
12
|
+
export default createComponent({ name: 'RepairTrack', propKeys: [], template: new URL('./RepairTrack.html', import.meta.url).href, setup(__props, __emit) {
|
|
13
|
+
const route = useRoute(), router = useRouter(), store = useOperations(), row = computed(() => store.rows.find(r => r.task.id === route.params.taskId && r.run.id === route.params.runId)), incident = computed(() => row.value?.run.incidents.find(i => i.id === route.params.incidentId)), intent = computed(() => linkedIntent(store.intents.items, String(route.params.incidentId))), link = computed(() => intent.value?.operationLinks?.find(l => l.incidentId === incident.value?.id)), linkedTasks = computed(() => intent.value ? store.tasks.filter(t => t.binding.intentId === intent.value.id && t.createdAt > incident.value.observedAt && t.binding.pbcId === incident.value.source.pbcId) : []), candidates = computed(() => incident.value ? repairCandidates(incident.value, store.intents.items, store.tasks, store.session.actor) : []), chosen = ref(''), target = computed(() => candidates.value.find(c => c.runId === chosen.value)), targetRow = computed(() => target.value ? store.find(target.value.runId) : undefined), closing = ref(false), error = ref(''), mode = ref('new'), targetId = ref(''), note = ref(''), expected = ref(row.value?.run.recordVersion || 0), intentExpected = ref(), request = ref(crypto.randomUUID());
|
|
14
|
+
const draftKey = 'i3-prototype-antdv-ops-link:' + store.session.actor.id + ':' + route.params.incidentId;
|
|
15
|
+
try {
|
|
16
|
+
note.value = sessionStorage.getItem(draftKey) || '';
|
|
17
|
+
}
|
|
18
|
+
catch { }
|
|
19
|
+
watch(note, v => { try {
|
|
20
|
+
sessionStorage.setItem(draftKey, v);
|
|
21
|
+
}
|
|
22
|
+
catch { } });
|
|
23
|
+
watch(targetId, id => intentExpected.value = store.intents.get(id)?.recordVersion);
|
|
24
|
+
const linkReason = computed(() => !row.value || !incident.value ? '异常不存在。' : row.value.run.unconfirmed ? '先查询运行记录的原请求回执。' : !store.session.can('operation:link', incident.value.tenantId, incident.value.source.pbcId, 'production') || !store.session.can('intent:edit', incident.value.tenantId) ? '当前没有关联修复需求权限。' : incident.value.closed || !['now', 'plan'].includes(incident.value.triage?.choice || '') ? '先将异常分诊为立即修复或排期修复。' : '');
|
|
25
|
+
const closeReason = computed(() => row.value && incident.value ? store.closeReason(row.value, incident.value.id, target.value) : '异常不存在。');
|
|
26
|
+
function rebase() { expected.value = row.value?.run.recordVersion || 0; intentExpected.value = store.intents.get(targetId.value)?.recordVersion; request.value = crypto.randomUUID(); error.value = '已载入当前版本,请核对后重新提交;说明已保留。'; }
|
|
27
|
+
function submit() { try {
|
|
28
|
+
if (mode.value === 'existing' && !targetId.value)
|
|
29
|
+
throw Error('请选择已有需求。');
|
|
30
|
+
store.link(row.value.run.id, incident.value.id, { id: request.value, note: note.value, targetId: mode.value === 'existing' ? targetId.value : undefined }, expected.value, intentExpected.value);
|
|
31
|
+
try {
|
|
32
|
+
sessionStorage.removeItem(draftKey);
|
|
33
|
+
}
|
|
34
|
+
catch { }
|
|
35
|
+
;
|
|
36
|
+
error.value = '';
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
error.value = e.message;
|
|
40
|
+
} }
|
|
41
|
+
function verify() { try {
|
|
42
|
+
store.verifyLink(incident.value.id);
|
|
43
|
+
error.value = '';
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
error.value = e.message;
|
|
47
|
+
} }
|
|
48
|
+
return { computed, ref, watch, useRoute, useRouter, Alert, Button, Checkbox, Input, Result, Select, Space, Tag, TextArea, message, useOperations, linkedIntent, repairCandidates, acceptanceLabel, healthLabel, runsForTask, taskReleaseLabel, statusLabels, OperationActionDialog, SourceSummary, route, router, store, row, incident, intent, link, linkedTasks, candidates, chosen, target, targetRow, closing, error, mode, targetId, note, expected, intentExpected, request, draftKey, linkReason, closeReason, rebase, submit, verify };
|
|
49
|
+
} });
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<!-- 来源:src/operations/RunDetail.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
|
|
2
|
+
<template data-component="Drawer" open="" data-bind-size="(860)" title="运行记录与验收" data-on-close="(emit('close'))"><template data-if="(row)"><div class="ops-title"><div><h2>{{ (row.run.source.service) }}</h2><p class="mono muted">{{ (row.run.code) }}</p></div><template data-component="Space"><template data-component="Tag" data-bind-color="(acceptanceLabel(row.run) === '验收通过' ? 'green' : 'orange')">{{ (acceptanceLabel(row.run)) }}</template><template data-component="Tag" data-bind-color="(healthLabel(row.run) === '运行异常' ? 'red' : 'blue')">{{ (healthLabel(row.run)) }}</template></template></div><template data-component="SourceSummary" data-bind-source="(row.run.source)"></template><template data-component="Alert" data-if="(row.run.unconfirmed)" type="warning" show-icon="" title="上次操作结果待核实" description="先查询原请求回执,确认实际结果后再继续。"><template data-slot="action"><template data-component="Button" data-on-click="(verify)">查询原请求回执</template></template></template><template data-else=""><template data-component="Alert" data-if="(sourceReason(row.task, row.run))" type="warning" data-bind-title="(sourceReason(row.task, row.run))"></template><section class="ops-card"><div class="ops-section-head"><h2>运行观测与业务证据</h2><template data-component="Button" data-bind-disabled="(!!store.reason(row, 'observe'))" data-bind-title="(store.reason(row, 'observe'))" data-on-click="(action = 'observe')">获取最新观测</template></div><p class="muted">观测健康与人工验收分别记录。下列数据为本地模拟,实际指标由绑定规格和业务场景确定。</p><template data-component="Select" data-if="(row.run.observations.length)" data-model-value="(version)" aria-label="观测证据版本" data-bind-placeholder="('当前证据 v' + row.run.observations.at(-1).number)" data-bind-options="([...row.run.observations].reverse().map(e => ({ value: e.number, label: '证据 v' + e.number + ' · ' + formatDate(e.at) })))"></template><p data-if="(!selected)" class="ops-empty">尚未取得运行观测。发布成功后,需要先补齐业务证据,再进行人工验收。</p><template data-else=""><div data-if="(selected.errorRate !== undefined)" class="ops-signals"><div><span>错误率(模拟)</span><strong>{{ (selected.errorRate) }}%</strong></div><div><span>P95 延迟(模拟)</span><strong>{{ (selected.p95) }} ms</strong></div><div><span>证据版本</span><strong>v{{ (selected.number) }}</strong></div></div><article data-each="check in (selected.checks)" data-bind-key="(check.id)" class="ops-check"><div><strong>{{ (check.name) }}</strong><template data-component="Tag" data-bind-color="(check.status === 'pass' ? 'green' : check.status === 'fail' ? 'red' : 'orange')">{{ (({ pass: '通过', fail: '失败', missing: '缺失', stale: '过期' })[check.status]) }}</template></div><p>{{ (check.criterion) }}</p><small class="muted">{{ (check.detail) }}</small></article></template><template data-component="Alert" data-if="(store.reason(row, 'accept'))" type="info" data-bind-title="(store.reason(row, 'accept'))"></template><div class="ops-buttons"><template data-component="Button" data-bind-disabled="(!!store.reason(row, 'rejectAcceptance'))" data-on-click="(action = 'rejectAcceptance')">记录验收不通过</template><template data-component="Button" type="primary" data-bind-disabled="(!!store.reason(row, 'accept'))" data-on-click="version = undefined;
|
|
3
|
+
action = 'accept';">记录验收通过</template></div></section><section class="ops-card"><h2>异常记录 <span class="muted">{{ (row.run.incidents.length) }}</span></h2><p data-if="(!row.run.incidents.length)" class="muted">当前没有关联异常。暂无异常不等于已通过验收。</p><article data-each="i in (row.run.incidents)" data-bind-key="(i.id)" class="ops-check"><template data-component="Button" type="link" data-on-click="router.push(path(i.id));
|
|
4
|
+
emit('close');">{{ (i.code) }} · {{ (i.title) }}</template><template data-component="Tag">{{ (incidentLabel(i)) }}</template><p>{{ (i.signal) }}</p></article></section><section class="ops-card"><h2>人工验收历史</h2><p data-if="(!row.run.acceptances.length)" class="muted">尚无人工验收结论。</p><article data-each="a in ([...row.run.acceptances].reverse())" data-bind-key="(a.id)" class="ops-check"><strong>{{ (a.verdict === 'pass' ? '验收通过' : '验收不通过') }} · 证据 v{{ (a.evidenceVersion) }}</strong><p>{{ (a.note) }}</p><small class="muted">{{ (a.actor) }} · {{ (formatDate(a.at)) }}</small></article></section><section class="ops-card"><h2>操作记录</h2><article data-each="e in ([...row.run.events].reverse())" data-bind-key="(e.id)" class="ops-check"><strong>{{ (e.action) }}</strong><p>{{ (e.detail) }}</p><small>{{ (e.actor) }} · {{ (formatDate(e.at)) }}</small></article></section></template><template data-component="RecordMetadata" data-bind-record="(row.run)"></template><template data-component="OperationActionDialog" data-if="(action)" data-bind-row="(row)" data-bind-action="(action)" data-on-close="(action = undefined)" data-on-done="(action = undefined)"></template></template><template data-component="Alert" data-else="" type="warning" title="运行记录不存在或不在当前授权范围。"></template></template>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { computed, ref } from '../../runtime/state.js';
|
|
2
|
+
import { useRouter } from "../../runtime/router.js";
|
|
3
|
+
import { Alert, Button, Drawer, Select, Space, Tag, message } from "../../runtime/widgets.js";
|
|
4
|
+
import { useOperations } from "./store.js";
|
|
5
|
+
import { acceptanceLabel, healthLabel, incidentLabel, sourceReason } from "./model.js";
|
|
6
|
+
import { formatDate } from "../shared/policy.js";
|
|
7
|
+
import RecordMetadata from "../shared/RecordMetadata.js";
|
|
8
|
+
import SourceSummary from "./SourceSummary.js";
|
|
9
|
+
import OperationActionDialog from "./OperationActionDialog.js";
|
|
10
|
+
import { createComponent } from '../../runtime/dom.js';
|
|
11
|
+
export default createComponent({ name: 'RunDetail', propKeys: ["id"], template: new URL('./RunDetail.html', import.meta.url).href, setup(__props, __emit) {
|
|
12
|
+
const props = __props, emit = __emit, store = useOperations(), router = useRouter(), row = computed(() => store.find(props.id)), action = ref(), version = ref(), selected = computed(() => row.value?.run.observations.find(v => v.number === version.value) || row.value?.run.observations.at(-1));
|
|
13
|
+
function verify() { try {
|
|
14
|
+
store.apply(props.id, { id: crypto.randomUUID(), action: 'verify', expected: row.value.run.recordVersion });
|
|
15
|
+
message.success('原请求已核实');
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
message.error(e.message);
|
|
19
|
+
} }
|
|
20
|
+
const path = (id) => '/operations/' + row.value.task.id + '/' + props.id + '/incidents/' + id;
|
|
21
|
+
return { computed, ref, useRouter, Alert, Button, Drawer, Select, Space, Tag, message, useOperations, acceptanceLabel, healthLabel, incidentLabel, sourceReason, formatDate, RecordMetadata, SourceSummary, OperationActionDialog, props, emit, store, router, row, action, version, selected, verify, path };
|
|
22
|
+
} });
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
<!-- 来源:src/operations/SourceSummary.vue;HTML / 原生 DOM 绑定,不含 Vue 运行时。 -->
|
|
2
|
+
<section class="ops-card"><h2>绑定的生产版本</h2><template data-component="Descriptions" size="small" bordered="" data-bind-column="({ xs: 1, sm: 2 })" data-bind-items="([{ key: 'service', label: '应用 / 服务', content: source.service }, { key: 'pbc', label: 'PBC', content: source.project }, { key: 'version', label: '发布版本', content: source.version + ' / 修订 v' + source.revision }, { key: 'env', label: '环境', content: '生产环境' }, { key: 'digest', label: '制品摘要', content: source.digest }, { key: 'config', label: '配置快照', content: source.config }, { key: 'spec', label: '来源版本', content: '规格 v' + source.specVersion + ' / 流程 v' + source.flowVersion }, { key: 'at', label: '发布时间', content: formatDate(source.publishedAt) }])"></template><div class="ops-buttons"><template data-component="Button" data-if="(session.can('artifact:view', source.tenantId, source.pbcId))" data-on-click="(router.push('/releases/' + source.taskId + '/' + source.releaseId))">发布来源</template><template data-component="Button" data-on-click="(router.push('/tasks/' + source.taskId))">交付任务</template><template data-component="Button" data-if="(session.can('pbc:view', source.tenantId, source.pbcId))" data-on-click="(router.push('/pbcs/' + source.pbcId + '/workspace'))">PBC 工作区</template></div></section>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useRouter } from "../../runtime/router.js";
|
|
2
|
+
import { Button, Descriptions } from "../../runtime/widgets.js";
|
|
3
|
+
import { useSession } from "../shared/session.js";
|
|
4
|
+
import { formatDate } from "../shared/policy.js";
|
|
5
|
+
import { createComponent } from '../../runtime/dom.js';
|
|
6
|
+
export default createComponent({ name: 'SourceSummary', propKeys: ["source"], template: new URL('./SourceSummary.html', import.meta.url).href, setup(__props, __emit) {
|
|
7
|
+
const props = __props, router = useRouter(), session = useSession();
|
|
8
|
+
return { useRouter, Button, Descriptions, useSession, formatDate, props, router, session };
|
|
9
|
+
} });
|