@yss123/cage-cli 0.3.0 → 0.3.2
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/README.md +7 -3
- package/dist/approval-tree.d.ts +88 -0
- package/dist/approval-tree.js +18 -0
- package/dist/approval-tree.js.map +1 -0
- package/dist/capabilities.js +46 -31
- package/dist/capabilities.js.map +1 -1
- package/dist/graph-approvals.d.ts +11 -1
- package/dist/graph-approvals.js +18 -5
- package/dist/graph-approvals.js.map +1 -1
- package/dist/graph-relations.js +10 -8
- package/dist/graph-relations.js.map +1 -1
- package/dist/graph.js +2 -0
- package/dist/graph.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/ontology.js +8 -5
- package/dist/ontology.js.map +1 -1
- package/dist/project-structure.js +2 -2
- package/dist/project-structure.js.map +1 -1
- package/dist/sync.d.ts +1 -1
- package/dist/sync.js +25 -108
- package/dist/sync.js.map +1 -1
- package/graph-ui/approval-flow.js +28 -8
- package/graph-ui/approval-parallel.js +110 -0
- package/graph-ui/approval-tree.js +17 -0
- package/graph-ui/business.css +26 -0
- package/graph-ui/business.js +30 -13
- package/graph-ui/graph-approvals.js +18 -5
- package/graph-ui/graph-relations.js +10 -8
- package/package.json +6 -6
- package/templates/app/.agents/skills/cage-development/SKILL.md +10 -0
- package/templates/app/AGENTS.md +39 -122
- package/templates/app/CLAUDE.md +6 -0
- package/templates/app/README.md +9 -8
- package/templates/app/apps/api/package.json +2 -2
- package/templates/app/apps/web/package.json +1 -1
- package/templates/app/apps/web/src/modules/approval/components/task-operation-dialog.tsx +61 -0
- package/templates/app/apps/web/src/modules/approval/hooks/use-approval-tasks.ts +6 -9
- package/templates/app/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +81 -49
- package/templates/app/apps/web/src/modules/approval/pages/approval-tasks.css +18 -0
- package/templates/app/apps/web/src/modules/purchase/components/approval-history.tsx +39 -4
- package/templates/app/apps/web/src/modules/purchase/components/order-reviewers.tsx +38 -0
- package/templates/app/apps/web/src/modules/purchase/components/purchase-order-form.tsx +9 -2
- package/templates/app/apps/web/src/modules/purchase/pages/purchase-intelligence.css +2 -0
- package/templates/app/apps/web/src/modules/purchase/pages/purchase-order-detail-page.tsx +2 -0
- package/templates/app/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +2 -0
- package/templates/app/apps/web/src/shared/lib/error-message.ts +6 -1
- package/templates/app/apps/web/src/shared/ui/approval-member-picker.css +10 -0
- package/templates/app/apps/web/src/shared/ui/approval-member-picker.tsx +51 -0
- package/templates/app/cage.config.json +14 -0
- package/templates/app/db/migrations/0004_draft.sql +27 -0
- package/templates/app/docs/README.md +11 -0
- package/templates/app/docs/development/README.md +64 -0
- package/templates/app/docs/development/examples/note/note-detail-page.tsx +106 -0
- package/templates/app/docs/development/examples/note/note.ts +67 -0
- package/templates/app/docs/development/examples/note/notes-page.tsx +87 -0
- package/templates/{blank/docs/ai → app/docs/development/examples}/purchase-example.md +24 -10
- package/templates/{blank/docs/ai → app/docs/development/getting-started}/architecture.md +4 -4
- package/templates/app/docs/development/getting-started/first-feature.md +66 -0
- package/templates/{blank/docs/ai → app/docs/development/getting-started}/workflow.md +13 -12
- package/templates/app/docs/development/guides/approvals.md +270 -0
- package/templates/app/docs/development/guides/business-collaboration.md +63 -0
- package/templates/{blank/docs/ai → app/docs/development/guides}/files.md +5 -1
- package/templates/app/docs/{ai → development/guides}/intelligence.md +4 -4
- package/templates/{blank/docs/ai → app/docs/development/guides}/recipes.md +31 -11
- package/templates/app/docs/{ai → development/guides}/relations.md +2 -2
- package/templates/app/docs/{ai → development/guides}/routing.md +1 -1
- package/templates/{blank/docs/ai → app/docs/development/guides}/transfers.md +1 -1
- package/templates/{blank/docs/ai → app/docs/development/reference}/commenting.md +1 -1
- package/templates/app/docs/{ai → development/reference}/primitives.md +8 -62
- package/templates/app/docs/{ai → development/reference}/project-structure.md +2 -2
- package/templates/app/docs/development/skills/cage-development/SKILL.md +134 -0
- package/templates/{blank/docs/ai → app/docs/development/tools}/diagnostics.md +3 -3
- package/templates/{blank/docs/ai → app/docs/development/tools}/ontology-context.md +3 -3
- package/templates/app/docs/{ai → development/tools}/troubleshooting.md +7 -1
- package/templates/app/docs/errors/CAGE-AI-001.md +3 -3
- package/templates/app/docs/errors/CAGE-APPR-001.md +13 -10
- package/templates/app/docs/errors/CAGE-APPR-002.md +1 -1
- package/templates/app/docs/errors/CAGE-APPR-003.md +1 -1
- package/templates/app/docs/errors/CAGE-APPR-004.md +1 -1
- package/templates/app/docs/errors/CAGE-APPR-005.md +5 -5
- package/templates/app/docs/errors/CAGE-APPR-006.md +25 -10
- package/templates/app/docs/errors/CAGE-APPR-007.md +9 -7
- package/templates/app/docs/errors/CAGE-APPR-010.md +1 -1
- package/templates/app/docs/errors/CAGE-AUDIT-001.md +1 -1
- package/templates/app/docs/errors/CAGE-AUTH-001.md +1 -1
- package/templates/app/docs/errors/CAGE-BIZ-001.md +1 -1
- package/templates/app/docs/errors/CAGE-BIZ-002.md +1 -1
- package/templates/app/docs/errors/CAGE-BUDGET-001.md +1 -1
- package/templates/app/docs/errors/CAGE-BUDGET-002.md +1 -1
- package/templates/app/docs/errors/CAGE-BUDGET-003.md +1 -1
- package/templates/app/docs/errors/CAGE-CMD-002.md +1 -1
- package/templates/app/docs/errors/CAGE-CMD-003.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-001.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-002.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-003.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-004.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-005.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-006.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-007.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-008.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-009.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-010.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-011.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-012.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-013.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-014.md +1 -1
- package/templates/app/docs/errors/CAGE-CONN-015.md +1 -1
- package/templates/app/docs/errors/CAGE-CREATE-001.md +2 -2
- package/templates/app/docs/errors/CAGE-DECL-001.md +1 -1
- package/templates/app/docs/errors/CAGE-DECL-002.md +1 -1
- package/templates/app/docs/errors/CAGE-DECL-003.md +1 -1
- package/templates/app/docs/errors/CAGE-DECL-004.md +1 -1
- package/templates/app/docs/errors/CAGE-DEP-001.md +1 -1
- package/templates/app/docs/errors/CAGE-DEP-002.md +1 -1
- package/templates/app/docs/errors/CAGE-DEP-003.md +1 -1
- package/templates/app/docs/errors/CAGE-DEP-004.md +1 -1
- package/templates/app/docs/errors/CAGE-DEP-005.md +1 -1
- package/templates/app/docs/errors/CAGE-DIAG-001.md +1 -1
- package/templates/app/docs/errors/CAGE-DLQ-001.md +1 -1
- package/templates/app/docs/errors/CAGE-ENV-001.md +1 -1
- package/templates/app/docs/errors/CAGE-ENV-002.md +1 -1
- package/templates/app/docs/errors/CAGE-ENV-003.md +1 -1
- package/templates/app/docs/errors/CAGE-EVENT-001.md +2 -2
- package/templates/app/docs/errors/CAGE-EVENT-002.md +1 -1
- package/templates/app/docs/errors/CAGE-FIELD-001.md +1 -1
- package/templates/app/docs/errors/CAGE-FIELD-002.md +1 -1
- package/templates/app/docs/errors/CAGE-FIELD-003.md +1 -1
- package/templates/app/docs/errors/CAGE-FIELD-004.md +1 -1
- package/templates/app/docs/errors/CAGE-FILE-001.md +1 -1
- package/templates/app/docs/errors/CAGE-GEN-001.md +1 -1
- package/templates/app/docs/errors/CAGE-GEN-002.md +1 -1
- package/templates/app/docs/errors/CAGE-GEN-003.md +1 -1
- package/templates/app/docs/errors/CAGE-GRANT-001.md +1 -1
- package/templates/app/docs/errors/CAGE-GRANT-002.md +1 -1
- package/templates/app/docs/errors/CAGE-GRANT-003.md +1 -1
- package/templates/app/docs/errors/CAGE-IMPACT-001.md +1 -1
- package/templates/app/docs/errors/CAGE-IMPACT-002.md +1 -1
- package/templates/app/docs/errors/CAGE-INIT-001.md +1 -1
- package/templates/app/docs/errors/CAGE-INIT-002.md +1 -1
- package/templates/app/docs/errors/CAGE-INIT-003.md +1 -1
- package/templates/app/docs/errors/CAGE-INIT-004.md +1 -1
- package/templates/app/docs/errors/CAGE-INIT-005.md +1 -1
- package/templates/app/docs/errors/CAGE-JOB-001.md +1 -1
- package/templates/app/docs/errors/CAGE-JOB-002.md +1 -1
- package/templates/app/docs/errors/CAGE-JOB-003.md +1 -1
- package/templates/app/docs/errors/CAGE-LINT-001.md +1 -1
- package/templates/app/docs/errors/CAGE-MIG-001.md +1 -1
- package/templates/app/docs/errors/CAGE-MIG-002.md +1 -1
- package/templates/app/docs/errors/CAGE-MIG-005.md +1 -1
- package/templates/app/docs/errors/CAGE-NAME-001.md +1 -1
- package/templates/app/docs/errors/CAGE-NAME-002.md +1 -1
- package/templates/app/docs/errors/CAGE-NAME-003.md +1 -1
- package/templates/app/docs/errors/CAGE-NAME-004.md +1 -1
- package/templates/app/docs/errors/CAGE-NAME-005.md +1 -1
- package/templates/app/docs/errors/CAGE-NAME-006.md +1 -1
- package/templates/app/docs/errors/CAGE-ORG-001.md +1 -1
- package/templates/app/docs/errors/CAGE-PAIR-002.md +1 -1
- package/templates/app/docs/errors/CAGE-QUERY-001.md +1 -1
- package/templates/app/docs/errors/CAGE-QUERY-002.md +1 -1
- package/templates/app/docs/errors/CAGE-QUERY-003.md +1 -1
- package/templates/app/docs/errors/CAGE-REACT-001.md +1 -1
- package/templates/app/docs/errors/CAGE-REACT-002.md +1 -1
- package/templates/app/docs/errors/CAGE-REACT-003.md +1 -1
- package/templates/app/docs/errors/CAGE-READS-001.md +1 -1
- package/templates/app/docs/errors/CAGE-REG-001.md +2 -2
- package/templates/app/docs/errors/CAGE-REG-002.md +1 -1
- package/templates/app/docs/errors/CAGE-REG-003.md +1 -1
- package/templates/app/docs/errors/CAGE-REL-001.md +1 -1
- package/templates/app/docs/errors/CAGE-ROUTE-001.md +1 -1
- package/templates/app/docs/errors/CAGE-SCOPE-001.md +1 -1
- package/templates/app/docs/errors/CAGE-SCOPE-002.md +1 -1
- package/templates/app/docs/errors/CAGE-SECRET-001.md +1 -1
- package/templates/app/docs/errors/CAGE-SECRET-002.md +1 -1
- package/templates/app/docs/errors/CAGE-SENS-001.md +1 -1
- package/templates/app/docs/errors/CAGE-SQL-001.md +1 -1
- package/templates/app/docs/errors/CAGE-SQL-002.md +1 -1
- package/templates/app/docs/errors/CAGE-STATE-001.md +1 -1
- package/templates/app/docs/errors/CAGE-STATE-002.md +1 -1
- package/templates/app/docs/errors/CAGE-STATE-003.md +1 -1
- package/templates/app/docs/errors/CAGE-STATE-004.md +1 -1
- package/templates/app/docs/errors/CAGE-STATE-005.md +1 -1
- package/templates/app/docs/errors/CAGE-STATE-010.md +1 -1
- package/templates/app/docs/errors/CAGE-STATE-011.md +1 -1
- package/templates/app/docs/errors/CAGE-STRUCT-001.md +4 -4
- package/templates/app/docs/errors/CAGE-STRUCT-002.md +3 -3
- package/templates/app/docs/errors/CAGE-SYNC-001.md +4 -4
- package/templates/app/docs/errors/CAGE-TEST-001.md +1 -1
- package/templates/app/docs/errors/CAGE-TEST-002.md +1 -1
- package/templates/app/docs/errors/CAGE-TEST-003.md +1 -1
- package/templates/app/docs/errors/CAGE-UNSAFE-001.md +1 -1
- package/templates/app/docs/errors/CAGE-UPGRADE-001.md +1 -1
- package/templates/app/docs/errors/CAGE-WORKER-001.md +1 -1
- package/templates/app/docs/errors/CAGE-WORKER-002.md +1 -1
- package/templates/app/docs/errors/CAGE-WORKER-003.md +1 -1
- package/templates/app/docs/errors/README.md +3 -3
- package/templates/app/docs/errors/runtime.md +1 -1
- package/templates/app/package.json +3 -3
- package/templates/app/packages/contracts/package.json +1 -1
- package/templates/app/packages/contracts/src/aggregates/approval-member/index.ts +70 -0
- package/templates/app/packages/contracts/src/aggregates/purchase-order/index.ts +10 -2
- package/templates/app/packages/contracts/src/index.ts +9 -0
- package/templates/app/packages/domain/package.json +5 -5
- package/templates/app/packages/domain/src/modules/purchase/approval-members.ts +54 -0
- package/templates/app/packages/domain/src/modules/purchase/approvals.ts +19 -8
- package/templates/app/packages/domain/src/modules/purchase/index.ts +2 -1
- package/templates/app/packages/domain/src/modules/purchase/intelligence.test.ts +169 -7
- package/templates/app/packages/domain/src/modules/purchase/purchase-order.ts +56 -5
- package/templates/blank/.agents/skills/cage-development/SKILL.md +10 -0
- package/templates/blank/AGENTS.md +39 -122
- package/templates/blank/CLAUDE.md +6 -0
- package/templates/blank/README.md +3 -3
- package/templates/blank/apps/api/package.json +1 -1
- package/templates/blank/apps/web/package.json +1 -1
- package/templates/blank/docs/README.md +11 -0
- package/templates/blank/docs/development/README.md +64 -0
- package/templates/blank/docs/development/examples/note/note-detail-page.tsx +106 -0
- package/templates/blank/docs/development/examples/note/note.ts +67 -0
- package/templates/blank/docs/development/examples/note/notes-page.tsx +87 -0
- package/templates/{app/docs/ai → blank/docs/development/examples}/purchase-example.md +24 -10
- package/templates/{app/docs/ai → blank/docs/development/getting-started}/architecture.md +4 -4
- package/templates/blank/docs/development/getting-started/first-feature.md +66 -0
- package/templates/{app/docs/ai → blank/docs/development/getting-started}/workflow.md +13 -12
- package/templates/blank/docs/development/guides/approvals.md +270 -0
- package/templates/blank/docs/development/guides/business-collaboration.md +63 -0
- package/templates/{app/docs/ai → blank/docs/development/guides}/files.md +5 -1
- package/templates/blank/docs/{ai → development/guides}/intelligence.md +4 -4
- package/templates/{app/docs/ai → blank/docs/development/guides}/recipes.md +31 -11
- package/templates/blank/docs/{ai → development/guides}/relations.md +2 -2
- package/templates/blank/docs/{ai → development/guides}/routing.md +1 -1
- package/templates/{app/docs/ai → blank/docs/development/guides}/transfers.md +1 -1
- package/templates/{app/docs/ai → blank/docs/development/reference}/commenting.md +1 -1
- package/templates/blank/docs/{ai → development/reference}/primitives.md +8 -62
- package/templates/blank/docs/{ai → development/reference}/project-structure.md +2 -2
- package/templates/blank/docs/development/skills/cage-development/SKILL.md +134 -0
- package/templates/{app/docs/ai → blank/docs/development/tools}/diagnostics.md +3 -3
- package/templates/{app/docs/ai → blank/docs/development/tools}/ontology-context.md +3 -3
- package/templates/blank/docs/{ai → development/tools}/troubleshooting.md +7 -1
- package/templates/blank/docs/errors/CAGE-AI-001.md +3 -3
- package/templates/blank/docs/errors/CAGE-APPR-001.md +13 -10
- package/templates/blank/docs/errors/CAGE-APPR-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-APPR-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-APPR-004.md +1 -1
- package/templates/blank/docs/errors/CAGE-APPR-005.md +5 -5
- package/templates/blank/docs/errors/CAGE-APPR-006.md +25 -10
- package/templates/blank/docs/errors/CAGE-APPR-007.md +9 -7
- package/templates/blank/docs/errors/CAGE-APPR-010.md +1 -1
- package/templates/blank/docs/errors/CAGE-AUDIT-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-AUTH-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-BIZ-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-BIZ-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-BUDGET-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-BUDGET-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-BUDGET-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-CMD-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-CMD-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-004.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-005.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-006.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-007.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-008.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-009.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-010.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-011.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-012.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-013.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-014.md +1 -1
- package/templates/blank/docs/errors/CAGE-CONN-015.md +1 -1
- package/templates/blank/docs/errors/CAGE-CREATE-001.md +2 -2
- package/templates/blank/docs/errors/CAGE-DECL-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-DECL-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-DECL-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-DECL-004.md +1 -1
- package/templates/blank/docs/errors/CAGE-DEP-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-DEP-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-DEP-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-DEP-004.md +1 -1
- package/templates/blank/docs/errors/CAGE-DEP-005.md +1 -1
- package/templates/blank/docs/errors/CAGE-DIAG-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-DLQ-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-ENV-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-ENV-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-ENV-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-EVENT-001.md +2 -2
- package/templates/blank/docs/errors/CAGE-EVENT-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-FIELD-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-FIELD-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-FIELD-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-FIELD-004.md +1 -1
- package/templates/blank/docs/errors/CAGE-FILE-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-GEN-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-GEN-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-GEN-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-GRANT-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-GRANT-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-GRANT-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-IMPACT-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-IMPACT-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-INIT-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-INIT-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-INIT-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-INIT-004.md +1 -1
- package/templates/blank/docs/errors/CAGE-INIT-005.md +1 -1
- package/templates/blank/docs/errors/CAGE-JOB-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-JOB-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-JOB-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-LINT-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-MIG-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-MIG-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-MIG-005.md +1 -1
- package/templates/blank/docs/errors/CAGE-NAME-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-NAME-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-NAME-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-NAME-004.md +1 -1
- package/templates/blank/docs/errors/CAGE-NAME-005.md +1 -1
- package/templates/blank/docs/errors/CAGE-NAME-006.md +1 -1
- package/templates/blank/docs/errors/CAGE-ORG-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-PAIR-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-QUERY-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-QUERY-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-QUERY-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-REACT-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-REACT-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-REACT-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-READS-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-REG-001.md +2 -2
- package/templates/blank/docs/errors/CAGE-REG-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-REG-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-REL-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-ROUTE-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-SCOPE-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-SCOPE-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-SECRET-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-SECRET-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-SENS-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-SQL-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-SQL-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-STATE-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-STATE-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-STATE-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-STATE-004.md +1 -1
- package/templates/blank/docs/errors/CAGE-STATE-005.md +1 -1
- package/templates/blank/docs/errors/CAGE-STATE-010.md +1 -1
- package/templates/blank/docs/errors/CAGE-STATE-011.md +1 -1
- package/templates/blank/docs/errors/CAGE-STRUCT-001.md +4 -4
- package/templates/blank/docs/errors/CAGE-STRUCT-002.md +3 -3
- package/templates/blank/docs/errors/CAGE-SYNC-001.md +4 -4
- package/templates/blank/docs/errors/CAGE-TEST-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-TEST-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-TEST-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-UNSAFE-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-UPGRADE-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-WORKER-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-WORKER-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-WORKER-003.md +1 -1
- package/templates/blank/docs/errors/README.md +3 -3
- package/templates/blank/docs/errors/runtime.md +1 -1
- package/templates/blank/docs/examples/purchase-admin/README.md +1 -1
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/components/task-operation-dialog.tsx +61 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/hooks/use-approval-tasks.ts +6 -9
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +81 -49
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/pages/approval-tasks.css +18 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/approval-history.tsx +39 -4
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/order-reviewers.tsx +38 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-order-form.tsx +9 -2
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-intelligence.css +2 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-order-detail-page.tsx +2 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +2 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/lib/error-message.ts +6 -1
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/approval-member-picker.css +10 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/approval-member-picker.tsx +51 -0
- package/templates/blank/docs/examples/purchase-admin/cage.config.json +14 -0
- package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/approval-member/index.ts +70 -0
- package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/purchase-order/index.ts +10 -2
- package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/index.ts +9 -0
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/approval-members.ts +54 -0
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/approvals.ts +19 -8
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/index.ts +2 -1
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/intelligence.test.ts +169 -7
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.ts +56 -5
- package/templates/blank/package.json +3 -3
- package/templates/blank/packages/contracts/package.json +1 -1
- package/templates/blank/packages/domain/package.json +5 -5
- package/templates/app/docs/ai/README.md +0 -98
- package/templates/blank/docs/ai/README.md +0 -98
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 开发步骤与交付要求
|
|
2
2
|
|
|
3
|
-
[返回学习入口](README.md) · [
|
|
3
|
+
[返回学习入口](../README.md) · [框架开发 Skill](../skills/cage-development/SKILL.md) · [完整入门课](first-feature.md) · [详细中文注释](../reference/commenting.md)
|
|
4
4
|
|
|
5
5
|
本页命令在**应用根目录**执行,除非注明“框架根目录”。使用项目安装的 CLI:`pnpm exec cage ...`。项目脚本可简写为 `pnpm gen / pnpm migrate / pnpm dev / pnpm verify`;不要假定机器已全局安装 cage。
|
|
6
6
|
|
|
@@ -25,7 +25,7 @@ pnpm dev
|
|
|
25
25
|
|
|
26
26
|
`init` 自动创建独立账号与随机密码,填写 APP/READ/MIGRATE 连接和 Cookie 密钥,成功后删除文件中的管理员连接。三个连接使用同一数据库。已有 Cage 集群账号时复用原连接,不能重置其他应用的账号密码。生产环境可由平台直接提供账号连接,不必执行本地 init。
|
|
27
27
|
|
|
28
|
-
`bootstrap` 独立初始化组织,不自动授予业务能力。管理员凭据只进入新的受限文件,不进入服务控制台;已有用户时不重置。交付后移除凭据文件。日常 API 启动不初始化组织;生产缺少合格 Cookie 密钥会拒绝启动。具体文件权限与诊断用法见[能力发现与状态诊断](diagnostics.md)。
|
|
28
|
+
`bootstrap` 独立初始化组织,不自动授予业务能力。管理员凭据只进入新的受限文件,不进入服务控制台;已有用户时不重置。交付后移除凭据文件。日常 API 启动不初始化组织;生产缺少合格 Cookie 密钥会拒绝启动。具体文件权限与诊断用法见[能力发现与状态诊断](../tools/diagnostics.md)。
|
|
29
29
|
|
|
30
30
|
`.env.example` 是配置说明,`.env` 是本机私密配置,二者不混用。CLI 自动加载应用 `.env`,部署环境同名变量优先。API 和 worker 启动需重启后读取变更;不要输出整个 `.env` 排障。
|
|
31
31
|
|
|
@@ -33,12 +33,12 @@ pnpm dev
|
|
|
33
33
|
|
|
34
34
|
## 做一项业务修改
|
|
35
35
|
|
|
36
|
-
1. 读 AGENTS.md
|
|
36
|
+
1. 读 AGENTS.md 和[框架开发 Skill](../skills/cage-development/SKILL.md),确认需求属于领域模块、前端模块、组织配置还是框架。阅读需求和文档后,按[业务澄清与共同设计](../guides/business-collaboration.md)主动提出疑问、选项和建议,与用户确定相关规则及验收;已明确部分继续推进。按任务选手册,必要时本地搜索术语;用 `capabilities` 核对公开 API、`context "需求关键词"` 定位当前业务。按需 `graph search/inspect/path`,阅读对应源码、范例与测试;证据边界见[本体上下文指南](../tools/ontology-context.md)。遵守[目录规范](../reference/project-structure.md)和[详细中文注释规范](../reference/commenting.md),发现能力缺口先说明,不编造 API。
|
|
37
37
|
2. 涉及已存在业务含义变化时,**修改前**运行 `pnpm exec cage snapshot save before-change` 保存命名基线;也可使用真实 Git 提交或独立本体图文件。
|
|
38
38
|
3. 在所属领域模块写字段、状态、不变量和命令输入;再实现 handler、事件、查询与审批。跨模块反应放 workflows,第三方协议放 integrations。从模块 index 到 domain 总入口逐层导出,避免跨文件 export 名冲突。同步编写详细中文注释:文件职责与调用链、导出声明及输入字段、权限/状态/reads/事件/事务、关键步骤和失败边界;涉及已有行为时补齐受影响的上下游说明。
|
|
39
39
|
4. `pnpm exec cage check` 检查声明和图规则;`pnpm gen` 更新契约与迁移草稿。聚合和命令填写中文 `description`,需要覆盖时补 `cage.config.json` 的 `graph.labels`(如 `aggregate:Note`、`command:Note.archive`、`capability:Note.export`)。这些名称同时用于图谱和 `/admin` 授权界面;修改后重启 API。不重命名实际能力点来实现翻译。在图谱确认连接与资源生命周期。
|
|
40
40
|
5. 审查数据库变更,特别是非空字段、数据回填、删列和索引。已执行的迁移不可改写。需要落库时显式 `pnpm migrate`。
|
|
41
|
-
6. 页面和表单放 `apps/web/src/modules/<业务>`,从模块公开入口接入 app 的 URL 路由;依赖生成 contracts,处理失败结果。列表、详情等多页面使用 React Router,筛选和分页进入 URL;组件状态只管理页面内临时交互。新增能力由管理员授权,页面按钮可用 `useCan` 控制。按[路由与浏览器验收](routing.md)检查直达、刷新、前进后退和登录回跳。
|
|
41
|
+
6. 页面和表单放 `apps/web/src/modules/<业务>`,从模块公开入口接入 app 的 URL 路由;依赖生成 contracts,处理失败结果。列表、详情等多页面使用 React Router,筛选和分页进入 URL;组件状态只管理页面内临时交互。新增能力由管理员授权,页面按钮可用 `useCan` 控制。按[路由与浏览器验收](../guides/routing.md)检查直达、刷新、前进后退和登录回跳。
|
|
42
42
|
7. 补足重要业务反例并运行相关验证;测试解释夹具目的、所保护的规则和覆盖边界。按注释规范审查本次 diff,核对页面、组件/hooks、类型字段、脚本副作用和恢复流程的说明是否完整准确。提交源声明、契约和审查过的迁移,报告跳过及未执行项。
|
|
43
43
|
|
|
44
44
|
### 如何保存和比较基线
|
|
@@ -98,7 +98,7 @@ if (!result.ok) {
|
|
|
98
98
|
- `atomic: true` 请求整批原子处理,普通逐行导入需展示成功/失败计数及报告。HTTP 202 仅代表接受任务,不能立即提示处理完成。
|
|
99
99
|
- worker 必须运行;任务可能 queued/retrying/failed/expired。下载会再次校验当前权限。导出的系统列和掩码值不能原样回导。
|
|
100
100
|
|
|
101
|
-
CSV 编码、限制、SDK 与完整接口见本项目自带的[业务页导入导出](transfers.md)。给新业务做入口时按实际生成的签名调用,不硬编码采购单专属逻辑进框架。
|
|
101
|
+
CSV 编码、限制、SDK 与完整接口见本项目自带的[业务页导入导出](../guides/transfers.md)。给新业务做入口时按实际生成的签名调用,不硬编码采购单专属逻辑进框架。
|
|
102
102
|
|
|
103
103
|
## 工具做什么,结果在哪里
|
|
104
104
|
|
|
@@ -106,12 +106,12 @@ CSV 编码、限制、SDK 与完整接口见本项目自带的[业务页导入
|
|
|
106
106
|
| --- | --- | --- |
|
|
107
107
|
| `pnpm exec cage analyze` | 抽取显式声明与源码位置 | `.cage/ontology.json` |
|
|
108
108
|
| `pnpm exec cage capabilities 关键词 --format json` | 查询当前安装版本的公开能力 | 公开签名、声明位置和学习入口 |
|
|
109
|
-
| `pnpm exec cage doctor` | 统一核对注册、生成、构建及可用运行证据 | pass / fail / unknown 与下一步;见[诊断指南](diagnostics.md) |
|
|
109
|
+
| `pnpm exec cage doctor` | 统一核对注册、生成、构建及可用运行证据 | pass / fail / unknown 与下一步;见[诊断指南](../tools/diagnostics.md) |
|
|
110
110
|
| `pnpm exec cage snapshot save 名称` | 保存不可覆盖的命名基线 | `.cage/snapshots`;配合 `impact --snapshot 名称` |
|
|
111
111
|
| `pnpm exec cage check` | 静态检查、注册表与图规则 | 终端 `code/at/reason/fix` |
|
|
112
112
|
| `pnpm exec cage graph` | 启动中文本体图谱 | 默认 `http://127.0.0.1:15418`,按终端地址访问 |
|
|
113
113
|
| `pnpm exec cage context "需求或节点"` | 开发前取得相关子图、原因、源码与候选验证 | 默认终端 Markdown;`--format json --out .cage/context.json` 保存结构化报告 |
|
|
114
|
-
| `pnpm exec cage graph search/inspect/path ...` | 检索候选 / 精确节点 / 关系路径 | 同源中文与证据;每次重新抽取,见[用法](ontology-context.md) |
|
|
114
|
+
| `pnpm exec cage graph search/inspect/path ...` | 检索候选 / 精确节点 / 关系路径 | 同源中文与证据;每次重新抽取,见[用法](../tools/ontology-context.md) |
|
|
115
115
|
| `pnpm gen` | 更新契约、结构说明、迁移草稿 | `packages/contracts/src`、`db/migrations`、`generated`、`.cage/ontology.json` |
|
|
116
116
|
| `pnpm exec cage gen --check` | 只比较需提交的生成物 | 不一致时报 CAGE-GEN;不是实际数据库漂移扫描 |
|
|
117
117
|
| `pnpm exec cage test --only project` | 项目测试 | `.cage/test-results.json` 与终端 |
|
|
@@ -127,10 +127,10 @@ CSV 编码、限制、SDK 与完整接口见本项目自带的[业务页导入
|
|
|
127
127
|
## 验证要与改动匹配
|
|
128
128
|
|
|
129
129
|
- 文档、文案、可逆的小改动:检查链接、格式、资料分发;不需要重复运行全套数据库测试。
|
|
130
|
-
- 所有源码变更:按[注释交付清单](commenting.md#交付前逐项核对)人工核对中文职责、接口与关键流程说明;静态检查不能替代注释准确性检查。仅补注释时不新增复述实现的测试、不改写已执行迁移。
|
|
130
|
+
- 所有源码变更:按[注释交付清单](../reference/commenting.md#交付前逐项核对)人工核对中文职责、接口与关键流程说明;静态检查不能替代注释准确性检查。仅补注释时不新增复述实现的测试、不改写已执行迁移。
|
|
131
131
|
- 命令/约束/反应变化:针对成功路径及真正的风险增加用例,如越权拒绝、额度边界、资源释放、同事务回滚。不要写只复述实现的测试。
|
|
132
132
|
- 领域结构变化:check、gen、生成一致性、类型检查;有数据库影响时在独立测试库验证迁移和读写。
|
|
133
|
-
- 页面或导航变化:构建后按[浏览器配方](routing.md)实际操作,包含深链接、新标签页、刷新、前进后退、登录回跳、无权限和 404。check/verify 不自动执行浏览器验收;未操作时明确报告未执行,不能写“页面功能完整”。
|
|
133
|
+
- 页面或导航变化:构建后按[浏览器配方](../guides/routing.md)实际操作,包含深链接、新标签页、刷新、前进后退、登录回跳、无权限和 404。check/verify 不自动执行浏览器验收;未操作时明确报告未执行,不能写“页面功能完整”。
|
|
134
134
|
- 发布前:按项目要求执行完整 verify/build/test,核对分发包。没有执行的项目明确写出原因。
|
|
135
135
|
|
|
136
136
|
测试使用真实 PostgreSQL。`CAGE_TEST_DATABASE_URL` 供独立测试集群使用,测试工具会准备角色和临时数据库;不要指向业务/生产集群。没有设置时 testkit 可使用内嵌的真实 PostgreSQL,这与 dev 的固定已有库流程不同。
|
|
@@ -140,12 +140,13 @@ CSV 编码、限制、SDK 与完整接口见本项目自带的[业务页导入
|
|
|
140
140
|
## 可以交给 AI 的任务描述
|
|
141
141
|
|
|
142
142
|
```text
|
|
143
|
-
先读 AGENTS.md 和它指定的 docs/
|
|
143
|
+
先读 AGENTS.md 和它指定的 docs/development/README.md,再参考对应标准范例。
|
|
144
144
|
需求:为某业务增加……
|
|
145
|
+
阅读需求、业务文档和现有代码,主动指出疑点与建议,给出可行选项、影响和推荐理由,让我选择业务规则;已给出的答案直接沿用,技术事实自行查证。
|
|
145
146
|
先用 cage context 查询现有业务,必要时 graph inspect/path,确认候选与关系后阅读实现。
|
|
146
|
-
|
|
147
|
+
把已确定的规则映射到字段、状态、能力与范围、事件/资源和验收,再修改 domain、生成契约和迁移草稿、接入业务页面;等待业务选择时推进独立部分。
|
|
147
148
|
使用真实公开 API;不要手写业务路由、直接写表或新增本地数据库生命周期命令。
|
|
148
|
-
按 docs/
|
|
149
|
+
按 docs/development/reference/commenting.md 给新建和修改代码写详细中文注释,覆盖职责、API/字段、步骤、原因和边界,同步修正相关上下游说明。
|
|
149
150
|
按改动运行必要检查,报告通过/跳过/未执行项和需要的管理员配置。
|
|
150
151
|
```
|
|
151
152
|
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# 审批任务流转、并行分支与流程时效
|
|
2
|
+
|
|
3
|
+
## 第一次接入审批
|
|
4
|
+
|
|
5
|
+
审批负责谁在什么步骤作出决定,业务状态由领域结论命令落实。先完成下列最小链路,再按需要阅读后面的并行、加签与时效选项。普通自动状态变化直接使用命令和反应,无需套审批。
|
|
6
|
+
|
|
7
|
+
1. 业务对象有草稿、待审批和相应结论状态。提交命令声明 emits 并成功发出提交事件;通过/拒绝等结论声明为 process 命令。
|
|
8
|
+
2. approval 绑定提交事件、结论命令和取消事件,route 定义步骤与选人;两者都从 domain 入口导出。routable 只包含选路和任务需要的业务快照字段。
|
|
9
|
+
3. 配置实际负责人/角色成员,并分别授予所需能力、范围和额度;声明 role code 不会创建角色或分配人员。检查迁移和运行中的 worker。
|
|
10
|
+
4. 页面先通过业务契约提交,再读取真实待办,通过公开任务接口携带当前 revision 作出决定。业务列表中的“待审批”不等于当前用户拥有待办。
|
|
11
|
+
5. 观察提交事件、待办、决定与领域最终状态;用不合格主体验证拒绝,按需求验证撤回。缺少待办时按[排错方法](../tools/troubleshooting.md)查具体断点,不直接把单据改成通过。
|
|
12
|
+
|
|
13
|
+
完整跨文件参考见[采购导读](../examples/purchase-example.md),基础声明见[审批绑定与选人](../reference/primitives.md#审批绑定与选人)。本页后续的客户端操作是接入片段,业务符号与 UI 需来自当前应用。
|
|
14
|
+
|
|
15
|
+
[返回学习入口](../README.md) · [审批原语](../reference/primitives.md) · [AI 审批](intelligence.md)
|
|
16
|
+
|
|
17
|
+
本页描述 Cage 原生审批引擎的顺序/条件/结构化 AND 并行、字段选人、候选领取/释放、转办、委派归还、前后/并行必签、操作记录,以及框架通用的自然分钟时限、站内提醒和申请人催办。它参考 Flowable 的任务责任划分和并行汇合语义,不表示支持全部 BPMN 或与 Flowable XML 兼容。
|
|
18
|
+
|
|
19
|
+
## 声明选人和节点操作
|
|
20
|
+
|
|
21
|
+
人工步骤默认 `assignment: 'direct'`,为每位选中的人分别建立已分配任务。`mode: 'any'` 表示至少一位原审批人通过,`mode: 'all'` 表示全部原审批人通过。转办、委派和加签通过 `actions` 逐项开放,未写的动作关闭。
|
|
22
|
+
|
|
23
|
+
以下是局部步骤片段,需放进应用已经导出的 `route`,并与自己的 `approval` 绑定配合:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { approver, step } from '@yss123/cage-approval';
|
|
27
|
+
|
|
28
|
+
// 为角色中的每位审批人直派一票;任一原票通过后仍需等待所有追加的必签票。
|
|
29
|
+
step('部门审核', approver.role('reviewer'), {
|
|
30
|
+
mode: 'any',
|
|
31
|
+
actions: { transfer: true, delegate: true, addSign: true },
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// reviewers 必须是本聚合的公开字段并列入 approval.routable;领取成功不产生新的业务权限。
|
|
35
|
+
step('专业审核', approver.field('reviewers'), {
|
|
36
|
+
assignment: 'candidate',
|
|
37
|
+
actions: { transfer: true, delegate: true, addSign: true },
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`assignment: 'candidate'` 只创建一项 `assigneeId: null` 的共享任务,候选人必须先领取才能决定。它独立开放 `claim/unclaim`,无需在 `actions` 中增加字段;即使没有其他动作政策也能领取/释放。候选池只支持 `any`,`candidate + all` 在声明时拒绝;逐人会签使用默认的 `direct`。
|
|
42
|
+
|
|
43
|
+
流程启动时保存选人规则、分配方式和动作政策的步骤快照。新 `step` 在 `actions.addSign: true` 时自动记录 `signPositions: ['parallel', 'before', 'after']`,应用无需另传签序配置。修改代码不会改变在途实例政策,也不会把旧直派任务合并为候选池。角色和部门规则在候选列表及领取时查询当前组织数据,字段选人使用提交时保存的路由变量;规则快照不等于冻结一份候选成员名单。AI 步骤的人工接管仍使用原来的直派方式,不开放任务管理动作。
|
|
44
|
+
|
|
45
|
+
### 按单据字段选人
|
|
46
|
+
|
|
47
|
+
`approver.field('reviewers')` 支持单个 UUID 字符串或原数组长度为 1–200 的 UUID 数组,重复人员去重。字段必须存在、不是 hidden,并列入对应 `approval.routable`;不满足时声明检查报 `CAGE-APPR-001`。数组可用 `list(id())` 声明,单人可用已有的 UUID 或用户引用字段;选人器不执行任意 JS、SQL 或字符串表达式。
|
|
48
|
+
|
|
49
|
+
字段缺失或为 `null` 时解析为空候选,开启节点报 `CAGE-APPR-007`;空数组、非法 UUID、数组中包含非字符串或超过 200 项报 `INVALID_INPUT`。开启字段选人或候选节点时,所有选中的 ID 必须属于当前租户且账号 active,否则整批失败,不静默去掉无效人员或默认批准。旧的固定用户/部门负责人直派规则保持原有开启行为。
|
|
50
|
+
|
|
51
|
+
开启节点的账号校验不会替用户授予批准/read 能力或数据范围。领取、转办、委派、加签和实际决定仍按当时的权限核验;配置了有效用户也不代表其最终额度、职责分离等业务硬约束一定满足。
|
|
52
|
+
|
|
53
|
+
## 结构化并行分支与 AND 汇合
|
|
54
|
+
|
|
55
|
+
`parallel(title, ...branches)` 声明同时推进的分支组,`branch(title, ...nodes)` 声明其中一条具名分支。分支内部可以有多个顺序步骤、条件和嵌套并行组;所有实际展开的分支都完成后,才开启组后面的节点。下例是应用路由片段,需要从 domain 入口导出,并绑定自己的 `approval`;`requiresLegal` 必须列入该绑定的 `routable`,角色与相应业务权限由应用明确配置。
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { approver, branch, eq, parallel, route, step, when } from '@yss123/cage-approval';
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 材料审核后同时推进业务与专业两条线;专业线的法务条件在提交时求值。
|
|
62
|
+
* 各线均完成才创建最终确认待办,结论仍由 approval 绑定的领域命令落实。
|
|
63
|
+
*/
|
|
64
|
+
export const documentRoute = route('document-review', [
|
|
65
|
+
step('材料审核', approver.role('reviewer')),
|
|
66
|
+
parallel('联合审查',
|
|
67
|
+
branch('业务线',
|
|
68
|
+
step('业务复核', approver.role('business-reviewer')),
|
|
69
|
+
step('预算核对', approver.role('budget-reviewer')),
|
|
70
|
+
),
|
|
71
|
+
branch('专业线',
|
|
72
|
+
step('专业评估', approver.role('specialist')),
|
|
73
|
+
when(eq('requiresLegal', true),
|
|
74
|
+
step('法务审查', approver.role('legal-reviewer')),
|
|
75
|
+
),
|
|
76
|
+
),
|
|
77
|
+
),
|
|
78
|
+
step('最终确认', approver.role('final-reviewer')),
|
|
79
|
+
]);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
业务复核通过后即可进入预算核对,无需等待专业评估;专业线也独立前进。只有两条线均通过,最终确认才出现。节点内 `mode: 'all'` 是同一节点的多人会签,`addSign` 的 `placement: 'parallel'` 是同一节点的追加必签,两者都不会创建流程分支;它们可以继续用于某条分支中的人工节点。
|
|
83
|
+
|
|
84
|
+
条件只在实例启动时依据提交变量求值,执行中不重新读取单据来改变路线。声明中的容器不能为空;如果某条分支的全部条件均不满足,展开后该分支直接通过汇合,不生成虚假任务。如果整个路由没有展开出任何办理节点,则明确拒绝启动。每个并行组要求 2–16 条名称不重复的分支;整份声明最多 128 个人工/AI 办理节点、512 个结构节点和 8 层容器。条件不满足不会绕过声明结构校验。
|
|
85
|
+
|
|
86
|
+
拒绝、退回或取消结束整个审批轮次,关闭其他分支中的活动节点和 pending/waiting 任务;尚未开启的后续节点不再创建。正常推进在实例锁内检查持久前驱状态,节点唯一键防止并发分支重复创建同一汇合后继。若同一次启动或推进中的任一新节点无法开启,整个本次事务回滚,不留下部分成功的分支入口。已经在较早事务中通过的票仍保留。
|
|
87
|
+
|
|
88
|
+
最终业务结论仍以实际推进完成的办理人身份调用领域命令。并行组后没有明确的最终审批节点时,最后完成分支的人可能承担该身份;额度、职责分离或状态约束不满足会回滚本次决定。需要固定最终责任人时,应像上例一样在 AND 汇合后声明明确的最终节点。
|
|
89
|
+
|
|
90
|
+
### 快照、历史和界面定位
|
|
91
|
+
|
|
92
|
+
执行计划保存在既有 `flow.approval_instance.steps` JSON 中,每个叶子步骤附带 `execution.schema/dependsOn/branchPath/definitionVersion`。`dependsOn` 是本实例内的前驱索引,全部前驱 approved 才能开启当前节点;数组中的声明遍历顺序不是实际完成顺序。`branchPath` 按外层到内层记录并行组及分支名称,普通主线为空数组。无需为这次并行能力新增 DDL 迁移;仍需完成当前版本已发布的 AI、任务流转和时效迁移,并让 API/worker 使用同一版本。
|
|
93
|
+
|
|
94
|
+
`definitionVersion` 是流程名、路由节点和催办政策等路由声明的 SHA256 内容指纹,不包含领域命令实现。它用于识别实例启动时保存的路线,不能替代完整的定义发布、版本回滚、领域命令版本绑定或在途迁移。代码更新不重算已有实例的依赖和政策;没有 `execution` 的历史快照仍按相邻顺序执行,历史版本指纹为 null,不追溯伪造。
|
|
95
|
+
|
|
96
|
+
任务摘要提供 `branchPath`;`client.approvalHistory(aggregate, id)` 提供 `currentSteps`、`definitionVersion` 及各步骤的 `branchPath/dependsOn`,仍遵守当前单据与详情读取权限。`currentSteps` 是完整活动节点集合,包含排队、运行、人工接管和待诊断的失败节点;只有通过状态满足后继依赖。`currentStep` 只保留最小活动索引作为旧客户端摘要,不能代表整轮只有一个节点,也不能据此判断其他分支是否前进。申请列表另有 `activeSteps`,提供各活动节点的名称、截止时间和分支路径。
|
|
97
|
+
|
|
98
|
+
`cage graph` 递归展示条件和 AND 分叉/汇合;节点编号只定位声明,图中分列的分支才表达并发关系。它展示已声明的结构,不是运行时设计器,也不直接证明某个实例已完成。当前只支持这种有界结构树,不支持任意连线、循环、OR/包容网关、事件竞争、指定节点跳转或在途实例迁移。
|
|
99
|
+
|
|
100
|
+
## 迁移和部署
|
|
101
|
+
|
|
102
|
+
通过应用原有 `pnpm migrate` 执行系统迁移,再将 API 与 worker 切换到同一版本:
|
|
103
|
+
|
|
104
|
+
| 系统迁移 | 数据含义 |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| `cage:approval_task_actions_001` | 任务 revision、委派责任、original/additional 和追加式动作历史;旧任务保持 original、revision=0 |
|
|
107
|
+
| `cage:approval_task_stages_002` | 新增 assignment、父任务和签序;仅候选任务允许持有人为空,旧任务保持 direct |
|
|
108
|
+
| `cage:approval_deadlines_003` | 节点截止/临期/扫描时间、实例催办政策与冷却、持久站内提醒及已读;旧值为 null,不自动开始计时 |
|
|
109
|
+
|
|
110
|
+
已发布的审批 DDL 和旧迁移没有改写。旧原票及旧版并行加签的 `parentTaskId/signPosition` 为空;升级不伪造旧签序或历史操作。升级后新创建的加签票保存父任务和签序。旧快照不会自动增加 actions、assignment 或 signPositions;升级前已经保存 `addSign: true` 但没有 signPositions 的节点只允许 parallel,before/after 返回 FORBIDDEN。没有 addSign 政策的旧实例仍完全禁止加签。不能把旧库基线测试中可创建直派任务理解为支持新版 API/worker 在未迁移数据库上运行。
|
|
111
|
+
|
|
112
|
+
## 六种操作的区别
|
|
113
|
+
|
|
114
|
+
| 操作 | 结果 | 边界 |
|
|
115
|
+
| --- | --- | --- |
|
|
116
|
+
| claim 领取 | 未分配候选任务归当前用户处理,离开可领取列表 | 实时检查候选资格、active、批准/read 和单据范围;一个任务只能有一位持有人 |
|
|
117
|
+
| unclaim 释放 | 当前持有人清空分配,任务重新进入候选池 | 仅 candidate;委派未归还或存在未完成子票时拒绝;保留已完成子票和历史 |
|
|
118
|
+
| transfer 转办 | 接收人成为当前审批人,原审批人失去该任务决定权 | 双方须有单据 read/范围及批准能力;不转移角色授权 |
|
|
119
|
+
| delegate 委派 | 保存原负责人,将待办交受托人处理 | 受托人只能 resolve;不能批准、拒绝、退回、再次转办/委派/加签或释放 |
|
|
120
|
+
| resolve 归还 | 返回服务端保存的原负责人,等待其审批 | 不推进节点;原负责人停用或失去批准/read 时拒绝 |
|
|
121
|
+
| addSign 加签 | 当前节点添加独立必签任务,按 placement 控制签署顺序 | 仅原始任务可发起,每次 1–20 人、每节点累计最多 20 人;不创建新流程节点 |
|
|
122
|
+
|
|
123
|
+
领取后移出候选角色不会自动取消已经承担的任务责任。只要仍有当前批准/read 权限和单据范围,该持有人可以正常决定或释放;失去这些业务权限后会拒绝操作。候选任务可以在动作政策允许时转办给有业务权限的非候选人,转办后仍保留 candidate 属性,新持有人也能按规则释放。没有管理员强制释放或无可用人员的通用恢复入口,不能在文档中以直接改表代替恢复功能。
|
|
124
|
+
|
|
125
|
+
接收人不能是本人或同节点其他任务的当前/保留负责人,包括已经决定的人。候选领取也不能领取本人已经承担另一票的节点原票;例如完成前签的人不能在原票被释放后再领原票。转办或释放不能把独立会签名额压缩为同人多票。
|
|
126
|
+
|
|
127
|
+
## 前签、后签和并行必签
|
|
128
|
+
|
|
129
|
+
`addSign` 的 `placement` 省略时为 `parallel`,已有客户端保持原来的并行含义。请求的位置还必须包含在当前实例的 signPositions 中,客户端不能仅凭新版声明替旧实例开放前后签。同一次追加的多位签署人彼此并行,不表示按 `userIds` 顺序逐人串签。
|
|
130
|
+
|
|
131
|
+
| placement | 创建时 | 何时恢复或激活 |
|
|
132
|
+
| --- | --- | --- |
|
|
133
|
+
| `parallel` | 原票和新加签票均可处理 | 原票通过仍须等待全部追加票 |
|
|
134
|
+
| `before` | 父任务变为 waiting,新加签票为 pending | 全部前签批准后,仍在 waiting 的父任务恢复为 pending |
|
|
135
|
+
| `after` | 父任务可处理,新加签票为 waiting | all 等自己的父票批准;any 等本节点任意原票批准 |
|
|
136
|
+
|
|
137
|
+
waiting 任务只能查看,不能决定或执行任务管理动作。前签完成恢复父票、后签从 waiting 激活为 pending 时都会增加该任务的 revision;原来等待页面保存的版本不可直接提交。
|
|
138
|
+
|
|
139
|
+
`any` 需要至少一张原票和全部追加票通过。其他原审批人先批准时,其余 pending/waiting 原票会 skipped,已经创建的前签、并行签、后签全部保留为必签;全部 waiting 后签此时激活。前签随后完成不会复活已经 skipped 的父票。`all` 需要全部原票和追加票通过,每张父票只激活自己的后签。
|
|
140
|
+
|
|
141
|
+
任一当前可决定的任务拒绝或退回,会调用原有领域结论命令;成功后关闭同轮次剩余 pending 和 waiting。取消或重新提交也会关闭旧轮次两种状态的任务。不能通过释放仍带未完成前/后/并行子票的候选任务来丢弃必签责任。
|
|
142
|
+
|
|
143
|
+
最终推进流程的实际决定人必须通过领域结论命令的额度、职责分离、状态和版本约束。后签人可能成为最终签署人;若其额度不足,最后决定、版本、阶段变化及本次历史共同回滚,之前已提交的父票保留。引擎不会自动改用更早审批人的身份。
|
|
144
|
+
|
|
145
|
+
## 客户端调用
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import { client } from '@app/contracts';
|
|
149
|
+
|
|
150
|
+
const candidates = await client.approvalCandidateTasks();
|
|
151
|
+
if (candidates.ok && candidates.data.length) {
|
|
152
|
+
const task = candidates.data[0];
|
|
153
|
+
// 展示候选不代表任务已被占用;服务端在领取事务中再次检查候选规则、权限和版本。
|
|
154
|
+
const claimed = await client.approvalTaskAction(task.id, {
|
|
155
|
+
action: 'claim', expectedRevision: task.revision, reason: '由我负责核查材料',
|
|
156
|
+
});
|
|
157
|
+
if (claimed.ok) {
|
|
158
|
+
// 领取已增加任务版本,后续界面读取本人待办并使用新版本;此处不自动替用户批准。
|
|
159
|
+
await client.approvalTasks();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
其他已提供的调用如下,目标用户 ID 由应用选人界面提供,不在页面写死员工 ID:
|
|
165
|
+
|
|
166
|
+
- `client.approvalTasks()` 读取本人 pending;`client.approvalTasks('waiting')` 查看等待签署依赖的本人任务。
|
|
167
|
+
- `client.approvalCandidateTasks()` 读取当前可领取的共享任务,不把它们混入本人的可决定清单。
|
|
168
|
+
- `approvalTaskAction(id, { action: 'claim' | 'unclaim' | 'resolve', expectedRevision, reason })` 不接受目标用户字段。
|
|
169
|
+
- 转办/委派为 `{ action: 'transfer' | 'delegate', targetUserId, expectedRevision, reason }`。
|
|
170
|
+
- 加签为 `{ action: 'addSign', userIds, placement?: 'parallel' | 'before' | 'after', expectedRevision, reason }`;目标数组不能重复。
|
|
171
|
+
- `client.decideApprovalTask(id, 'approve' | 'reject' | 'return', { expectedRevision, comment? })` 提交审批决定。
|
|
172
|
+
- `client.approvalTaskHistory(process, aggregate, id, { after?, limit? })` 返回 `items/nextCursor`;默认 50,最多 200 条。
|
|
173
|
+
|
|
174
|
+
摘要中的 `assigneeId` 是当前持有人,未领取时为 null;`assignment` 区分 direct/candidate,`parentTaskId/signPosition` 表示加签来源和顺序,`signPositions` 提供本实例允许发起的签序,`delegation: 'pending'` 表示只能归还。`actions/signPositions` 仅提示实例开放的管理政策,不能代替当前用户权限或任务状态校验。
|
|
175
|
+
|
|
176
|
+
任务 `revision` 与单据 `version` 不同。candidate 节点或启用了任一任务管理动作的节点,决定也必须携带 `expectedRevision`;其他旧直派节点保留不带版本的引擎/HTTP 兼容调用,SDK 始终要求版本。领取、释放、转办、决定、激活或关闭任务都会使相应版本递增。冲突后重新读取并让用户核对;接口没有跨请求成功回执缓存,超时不表示服务端未提交,不可盲目重发。
|
|
177
|
+
|
|
178
|
+
助理的 `approval_tasks` 只查询本人 pending 待办,`approval_decide` 可以保存并提交读取到的 `expectedRevision`,决定时仍检查委派状态、归属和权限。助理目前没有候选领取/释放、转办、委派归还或加签的管理写工具;这些功能由页面直接调用 SDK。
|
|
179
|
+
|
|
180
|
+
## HTTP、可见性与操作记录
|
|
181
|
+
|
|
182
|
+
| HTTP | 输入/行为 |
|
|
183
|
+
| --- | --- |
|
|
184
|
+
| GET `/api/approval/tasks` | `status` 默认 pending,可用 waiting 查看本人等待任务 |
|
|
185
|
+
| GET `/api/approval/candidate-tasks` | 当前未领取、规则和权限均符合的任务 |
|
|
186
|
+
| POST `/api/approval/tasks/:id/claim`、`unclaim` | `expectedRevision/reason` |
|
|
187
|
+
| POST `/api/approval/tasks/:id/transfer`、`delegate` | `targetUserId/expectedRevision/reason` |
|
|
188
|
+
| POST `/api/approval/tasks/:id/resolve` | `expectedRevision/reason` |
|
|
189
|
+
| POST `/api/approval/tasks/:id/add-sign` | `userIds/placement?/expectedRevision/reason` |
|
|
190
|
+
| POST `/api/approval/tasks/:id/approve`、`reject`、`return` | `expectedRevision/comment` |
|
|
191
|
+
| GET `/api/approval/task-history/:process/:aggregate/:id` | `after` 记录 ID 字符串,`limit` 分页大小 |
|
|
192
|
+
|
|
193
|
+
所有写入沿用会话与 CSRF。意见/原因最多 1000 字,管理动作原因去首尾空白后必须非空;未知字段、伪造 action 和非法 placement 拒绝。任务不在当前租户、不是本人持有,或领取时已经归别人,返回 NOT_FOUND;策略未开放、候选资格或能力不符返回 FORBIDDEN;仍可操作的任务版本过期返回 CONFLICT;waiting、已关闭、委派状态不允许或非当前步骤返回 INVALID_TRANSITION。并发抢领失败不保证都返回版本冲突,另一个人已持有时会返回 NOT_FOUND。
|
|
194
|
+
|
|
195
|
+
每个流程分别扫描本人对应状态最近 200 条任务,或最近 200 条未领取候选任务,再按当前单据 read/范围过滤;候选还检查批准能力、当前选人规则和同节点是否已经承担其他票。停用或失去当前读取权限后不会继续披露相应摘要。过滤后可能不足 200 条,当前没有分页游标,不能据此断言更早没有符合条件的任务。
|
|
196
|
+
|
|
197
|
+
`vars` 保留提交时路由变量的含义,但始终去 hidden 并对敏感字段掩码。即使具备明文能力,也需另经正式业务读取接口获得带审计的明文。
|
|
198
|
+
|
|
199
|
+
领取、释放、转办、委派、归还、加签、激活、人工决定、跳过和取消写入独立动作记录,与本次任务变更共同事务提交或回滚。应用账号只有记录 INSERT/SELECT 权限;这不是数据库管理员也无法修改的防篡改存储。当前单据授权读者可分页查看人工意见,处理过任务不产生永久读权。不要把凭据或无权共享的额外明文写入原因;迁移前发生的操作不会自动补录。
|
|
200
|
+
|
|
201
|
+
## 当前界面和验收边界
|
|
202
|
+
|
|
203
|
+
框架 Admin 用同一收件箱表格展示本人、可领取和等待加签任务及各类数量;采购范例提供“待我处理 / 可领取 / 等待加签”三个视图。两者都有领取、释放、受托任务归还及正常决定入口。waiting 仅展示,不显示决定按钮;候选和受托任务分别显示领取、归还入口。采购 `/approvals` 用 `view=candidates`、`view=waiting` 保存视图,默认本人待办不需要 view 参数。界面可提示操作,未完成子票等动态限制仍由服务端拒绝。
|
|
204
|
+
|
|
205
|
+
采购范例包含协作名录选人、转办/委派/三种加签及分页人工操作历史,详见 [采购导读](../examples/purchase-example.md)。框架 Admin 提供通用任务收件箱,启用审批运营后提供“我的申请”和“流程提醒”,不依赖采购的页面、名录或额外业务字段。框架支持、应用路由启用、浏览器验收仍是不同状态。
|
|
206
|
+
|
|
207
|
+
应用接入需检查真实角色、路由、迁移、worker 与浏览器路径,覆盖相关成功和拒绝场景;框架历史回归结果不能代替当前应用验收。
|
|
208
|
+
|
|
209
|
+
尚未实现受限岗位规则、代理时间段、嵌套委派、无可用人员的通用恢复、减签/撤销加签、任意串行加签链、指定节点退回、任意流程图/循环/OR 网关、工作日计时、自动升级、抄送、邮件/短信通知和可视化运行时设计器。
|
|
210
|
+
|
|
211
|
+
## 框架通用时限、提醒与催办
|
|
212
|
+
|
|
213
|
+
这组能力实现在 `@yss123/cage-approval`,复用内核的 runtime/worker 扩展,不需要业务项目创建通知表或编写定时任务。应用只需声明政策,沿用正常迁移、API 与 worker 启动流程。旧实例未声明时限或催办政策时不会被升级自动开放。
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
import { approvalOperations, approver, route, step } from '@yss123/cage-approval';
|
|
217
|
+
|
|
218
|
+
/** 通用站内运营服务,从 domain 入口导出,worker 才会扫描到期节点。 */
|
|
219
|
+
export const approvalOps = approvalOperations();
|
|
220
|
+
|
|
221
|
+
/** 局部接入示意:对应 approval 必须已绑定,并把 createdBy 列入 routable。 */
|
|
222
|
+
export const documentRoute = route('document-review', [
|
|
223
|
+
step('部门审核', approver.role('reviewer'), {
|
|
224
|
+
sla: { durationMinutes: 1440, remindBeforeMinutes: 60 },
|
|
225
|
+
actions: { transfer: true, delegate: true, addSign: true },
|
|
226
|
+
}),
|
|
227
|
+
], { reminders: { requesterField: 'createdBy', cooldownMinutes: 15 } });
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
`durationMinutes` 是进入人工节点后可用的**自然分钟总时限**,`remindBeforeMinutes` 是截止前多少分钟进入临期提醒。两者允许小数分钟,换算后至少一毫秒、至多 525600 分钟,提前量严格小于时限;省略提前量则只发超时提醒。每条并行分支的节点在实际开启时独立开始计时,尚未满足前驱的节点不提前计时。时限以数据库持久时间计算,加签、转办、委派、领取和释放都不重置;后签激活时该节点可能已经超时。AI 节点及其人工接管不使用此人工节点 SLA,已有人工接管待办仍可接收申请人催办。没有工作日历、节假日扣除或按员工时区计算的工作时间。
|
|
231
|
+
|
|
232
|
+
临期/超时由 worker 扫描各分支的持久活动节点并写入站内提醒。同一节点阶段、任务、收件人去重;worker 重启或并发扫描不重复投递同一项。已经跨过截止时间时只补超时,不补过时临期。转办或后签激活后的新办理人可在下一次扫描收到当前阶段提醒。waiting 票不会收到“请处理”提醒,取消、完成和不再活动的步骤停止投递;提醒不会自动批准、自动转办或替人取得能力。
|
|
233
|
+
|
|
234
|
+
每次 tick 最多扫描 25 个节点,每个节点最多投递 100 个尚未收到当前阶段提醒的任务/接收人配对,后续扫描继续补齐;扫描位置保存在数据库并轮转,完成投递的旧节点不会永久占满批次。角色选人仍读取当前完整候选集合,尚未验证大组织生产规模性能。手动催办最多 200 个合格配对,超出明确返回 INVALID_TRANSITION 且不写通知或冷却。提醒实际到达时间受 worker 轮询和队列积压影响,不是精确到毫秒的送达承诺。
|
|
235
|
+
|
|
236
|
+
接收人根据当前 pending 任务的持有人、未归还委派的原负责人或未领取候选规则计算,并实时过滤 active、批准/read 能力与单据范围。候选人已承担本节点另一票时不接收可领取提醒。通知读取与标已读仍核对本人、当前权限及接收关系,转出或撤权后不能凭旧通知继续查看原因。它是当前协作收件箱;永久操作追溯仍用 `approvalTaskHistory`。
|
|
237
|
+
|
|
238
|
+
申请人由路由 `reminders.requesterField` 指定,必须是公开且进入 `routable` 的单个用户 UUID 字段,并随提交冻结。仅能读取单据不等于能催办。催办绑定实例 UUID 与 `expectedStep`,并行实例还必须提交完整且按升序排列的 `expectedSteps`,其值使用最近一次申请摘要中的 `currentSteps`。即使并行实例暂时只剩一个活动节点,也不能省略该集合;否则返回 INVALID_INPUT。最小索引未变而另一分支已推进时,旧集合仍会返回 CONFLICT,页面应刷新后由用户重新核对。
|
|
239
|
+
|
|
240
|
+
催办事务同时检查活动集合、业务提交版本、申请人和冷却时间,向全部活动节点的合格任务/接收人配对投递。同实例跨分支、跨节点共享冷却,冷却中或旧业务版本返回 CONFLICT;无合格接收人明确失败且不消耗冷却。催办只增加提醒和操作记录,不修改业务 version 或待办 revision。本人申请从最近 200 个匹配实例中再按当前可见性过滤,未提供分页,不能把返回数量当作完整历史总数。
|
|
241
|
+
|
|
242
|
+
公共 SDK 使用与其他命令相同的会话和 CSRF:
|
|
243
|
+
|
|
244
|
+
| 调用 | 用途 |
|
|
245
|
+
| --- | --- |
|
|
246
|
+
| `client.approvalRequests()` | 本人发起且开放催办的运行实例,含 currentSteps、逐节点 activeSteps、最近截止 dueAt 和 nextUrgeAt |
|
|
247
|
+
| `client.urgeApproval(instanceId, { expectedStep, expectedSteps, reason })` | 并行必填完整 expectedSteps;原因 1–1000 字;返回任务/接收人配对数及再次可催办时间 |
|
|
248
|
+
| `client.approvalNotices({ after?, limit?, unreadOnly? })` | 本人当前可见提醒,返回 items/nextCursor,游标始终为字符串 |
|
|
249
|
+
| `client.readApprovalNotice(id)` | 标已读;重复请求保留首次已读时间 |
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
const requests = await client.approvalRequests();
|
|
253
|
+
if (requests.ok && requests.data.length) {
|
|
254
|
+
const selected = requests.data[0];
|
|
255
|
+
// 页面应先让申请人选择实例并填写原因;同时提交最小索引与完整集合,防止旧页面误催已变化的分支。
|
|
256
|
+
const result = await client.urgeApproval(selected.id, {
|
|
257
|
+
expectedStep: selected.currentStep,
|
|
258
|
+
expectedSteps: selected.currentSteps,
|
|
259
|
+
reason: '材料已补齐,请继续审核',
|
|
260
|
+
});
|
|
261
|
+
if (result.ok) {
|
|
262
|
+
// recipientCount 按任务与接收人配对计数;同一人处理两条分支可收到两条提醒,不是去重人数。
|
|
263
|
+
console.log(`已发送 ${result.data.recipientCount} 条站内催办提醒`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
对应接口为 GET `/api/approval/requests`、POST `/api/approval/instances/:id/urge`、GET `/api/approval/notices`、POST `/api/approval/notices/:id/read`。只有启用运行时才注册,并写入 OpenAPI。提醒分页按底层稳定记录游标推进,授权过滤后空页也可能有 nextCursor,应继续加载直到 null;单条通知不包含整份路由变量。
|
|
269
|
+
|
|
270
|
+
框架 Admin 的 `/admin/#/requests` 可填写原因并催办,`/admin/#/notices?view=unread` 可筛选、翻页和标已读;`view=all` 展示当前可见的全部提醒,`#/tasks` 展示截止时间。业务应用可以直接使用这些页面,也可以消费公共 SDK 构建自己的界面。采购仅作为接入验收载体,框架功能不依赖采购业务代码。
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# 业务澄清与共同设计
|
|
2
|
+
|
|
3
|
+
[返回学习入口](../README.md) · [框架开发 Skill](../skills/cage-development/SKILL.md) · [业务设计与能力选择](recipes.md)
|
|
4
|
+
|
|
5
|
+
用户可能只有一个目标,业务文档也可能有遗漏、歧义或相互冲突的规则。agent 阅读后应主动提出疑问和建议,帮助用户比较方案、作出选择,再把选择落实为 Cage 业务声明与验收结果。本页用于开发时的协作,不是应用内 AI 助理的交互协议。
|
|
6
|
+
|
|
7
|
+
## 先核对事实,找出需要共同决定的事
|
|
8
|
+
|
|
9
|
+
先读当前对话、项目业务约定和受影响的源码,区分“用户希望怎样”“文档约定怎样”“系统现在怎样”。已经明确的需求沿用;用户明确要求改变旧规则时说明影响并执行,不因为旧文档不同而重复请求同一决定。
|
|
10
|
+
|
|
11
|
+
主动检查对象和术语、参与人及范围、状态与动作、金额/数量/时间口径、失败与撤回、页面体验和验收标准。只检查本次相关内容,不要求用户先填写一份完整问卷。发现疑点应尽量说明具体位置和影响,不把未说明的内容当作默认允许,也不照搬采购示例中的规则。
|
|
12
|
+
|
|
13
|
+
| 发现的情况 | agent 如何处理 | 用户需要决定什么 |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| “大额需审批”“负责人可见”等描述有多种解释 | 指出缺失的阈值、负责人来源或可见范围,列出可行理解及影响 | 业务口径与希望的行为 |
|
|
16
|
+
| 业务文档互相矛盾,或与现有行为不一致 | 引用冲突位置,说明当前实现;已有明确新要求时直接采用,否则给出调整方案 | 哪条规则应作为目标,变更适用范围 |
|
|
17
|
+
| 框架文档写法不清、签名或版本不一致 | 按[能力诊断](../tools/diagnostics.md)核对安装版本、公开导出与实现,说明查证结果和仍不确定的部分 | 仅在影响业务目标或实现范围时选择方案;API 是否存在由证据确定 |
|
|
18
|
+
| 需求无法由当前能力直接表达 | 说明缺口,比较已有能力可实现的方案、应用扩展或框架扩展及成本;只提供有依据的选项 | 保留目标并扩展、接受明确的行为调整,或延后相关部分 |
|
|
19
|
+
| 规则可实现,但存在更清楚的使用方式或遗漏的失败体验 | 提出具体建议,解释收益和额外工作,标明是可选改进 | 是否纳入本次;未采纳不妨碍已明确工作 |
|
|
20
|
+
| 命名、目录归属、普通组件组织等技术选择 | 按项目约定和框架指南自行解决;有实质业务影响时再说明 | 通常无需选择实现细节 |
|
|
21
|
+
|
|
22
|
+
代码能说明当前行为,框架文档能说明能力边界,都不能单独证明用户希望的业务。查证不能解决的业务疑问要提出;已经查明的技术事实不转交用户猜测。资料确有错误时指出来源,在任务授权范围内修正或记录,不把猜测写成已实现能力。
|
|
23
|
+
|
|
24
|
+
## 每次提问都帮助用户作选择
|
|
25
|
+
|
|
26
|
+
一个有用的问题通常包含以下内容,按复杂程度合并表达即可:
|
|
27
|
+
|
|
28
|
+
1. **疑点与依据**:哪句话、哪段规则或哪个现有行为有问题,以及为什么会影响结果。
|
|
29
|
+
2. **选项与影响**:给出少量可行方案,通常两到三个;说明用户能观察到的区别,以及必要的配置、实现成本或框架限制。允许用户补充其他方案。
|
|
30
|
+
3. **推荐与理由**:结合已知业务、现有实现和框架能力推荐一个方案。缺乏推荐依据时说明还缺什么事实,不为了给建议而编造行业规则。
|
|
31
|
+
4. **本次需要的决定**:明确让用户选择哪个业务规则,以及未决定前哪一部分暂不落实。
|
|
32
|
+
|
|
33
|
+
例如应问“提交后哪些人可以修改申请”,再由 agent 选择对应命令和状态约束;不要让用户先决定 `from/to` 怎样写。金额阈值、审批人、数据可见范围等也不能从示例或技术便利性推断。
|
|
34
|
+
|
|
35
|
+
优先提出影响下一步设计的少量问题,相关问题可以合并。其余已发现疑点简短列为后续事项,随工作推进继续澄清;不要为了减少提问而隐去重要疑点,也不要一次倾倒所有可能的问题。用户只回答一部分时,保留这些答案,下一轮只追问剩余的相关事项。
|
|
36
|
+
|
|
37
|
+
## 在选择中推进实现
|
|
38
|
+
|
|
39
|
+
- 对需要业务选择的部分,在获得答案前保留为待定;可以继续阅读、核对能力、实现不依赖该决定的部分。不要把待定策略写成生效的权限、金额计算或状态规则。
|
|
40
|
+
- 可选改进单独说明;已明确任务照常推进。不要把每个建议都变成一个必须批准的关卡。
|
|
41
|
+
- 用户已有明确选择、授权或要求“你来定”时,按该范围推进并说明采用的规则。推荐选项、界面预选、等待时间和沉默均不构成新的选择;用户委托决定也不扩大任务或外部操作的授权范围。
|
|
42
|
+
- 实现中发现约定无法落地时,带着实际证据和替代方案回到用户,不默默降低要求。用户改变规则时,先指出受影响的声明、页面、数据和验收,再修改相关部分,无需重新确认无关规则。
|
|
43
|
+
|
|
44
|
+
简单任务在对话中简短记录即可;需要后续维护的规则写入项目已有业务文档或 AGENTS.md 的托管区外,并从项目入口引用。保留“已确定的规则及依据”“尚待决定的事项”“可选建议”的区别。客户业务事实不写进框架通用教材,也不写进会被 `cage sync` 覆盖的区域。
|
|
45
|
+
|
|
46
|
+
确定规则后,按[能力选择](recipes.md)映射到聚合、命令、状态、范围、审批或连接器,同时补充能观察结果的验收例子。记录不要求固定文件格式,也不要求每项小改动新增计划文件。
|
|
47
|
+
|
|
48
|
+
## 示例:文档没有写清金额边界
|
|
49
|
+
|
|
50
|
+
业务文档写着:“金额低于 5000 元由部门负责人审批;超过 5000 元增加财务审批。”
|
|
51
|
+
|
|
52
|
+
agent 读后可以提出:
|
|
53
|
+
|
|
54
|
+
> 这两条规则没有覆盖恰好 5000 元,会影响审批路径。可以选择:
|
|
55
|
+
>
|
|
56
|
+
> - A:满 5000 元就增加财务审批。
|
|
57
|
+
> - B:5000 元仍只由部门负责人审批,超过才增加财务。
|
|
58
|
+
>
|
|
59
|
+
> 我建议 A,让阈值本身也经过财务审核;这是一项待你选择的业务规则。你希望采用哪一种?也可以指定其他边界。
|
|
60
|
+
|
|
61
|
+
用户选择 A 后,agent 将规则落实为“低于 5000 元仅部门负责人审批;大于等于 5000 元增加财务”,按当前审批能力实现条件,并验证 4999.99、5000、5000.01 元三种输入。金额精度和单位仍沿用项目约定;若尚未约定且影响实现,也应继续提出。
|
|
62
|
+
|
|
63
|
+
如果文档还没说明财务与部门负责人的先后关系,这仍是独立疑点:说明顺序审批和并行审批的业务区别及当前支持方式,再让用户选择。金额边界已有答案,不再重复询问;选人、授权和真实待办的验收按[审批指南](approvals.md)落实。
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# 私有文件字段与断点续传
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
先理解三个独立动作:上传原始字节得到文件 ID,业务命令将该 ID 绑定到字段,通过受控下载接口读取内容。只声明 file 字段不会上传文件,只保存文件名也不会保存内容。
|
|
4
|
+
|
|
5
|
+
第一次接入依次完成本页的声明、客户端上传与授权下载,再增加暂停/续传等交互。验证上传内容与下载内容一致、业务保存失败有明确反馈、范围外主体下载被拒绝;文件目录存在或页面显示附件名都不足以证明链路成功。
|
|
6
|
+
|
|
7
|
+
[返回学习入口](../README.md) · [原语](../reference/primitives.md) · [权限与执行模型](../getting-started/architecture.md)
|
|
4
8
|
|
|
5
9
|
文件字节由 `@yss123/cage-files` 管理;业务字段只保存文件 ID。上传完成得到临时文件,业务命令成功后才正式绑定。不要把文件内容、Base64、存储路径或公开 URL 放进业务字段、事件或审计。
|
|
6
10
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 原生智能助理与 AI 审批
|
|
2
2
|
|
|
3
|
-
[返回学习入口](README.md) · [审批与命令](primitives.md) · [架构与执行模型](architecture.md)
|
|
3
|
+
[返回学习入口](../README.md) · [审批与命令](../reference/primitives.md) · [架构与执行模型](../getting-started/architecture.md)
|
|
4
4
|
|
|
5
5
|
这是当前框架的可选运行能力,使用自研持久状态机,不依赖 DeepSeek-Harness。框架提供模型适配、工具、任务、记忆、HTTP 和 SDK;应用提供领域声明、审核策略、角色授权及界面。开发阶段的 `cage context` 查询源码本体,与这里面向登录用户的运行时助理用途不同。
|
|
6
6
|
|
|
@@ -36,7 +36,7 @@ pnpm exec cage capabilities "Responses" --format json
|
|
|
36
36
|
| 项目已启用 | domain 根入口导出 `ai()`、API/worker 使用相同声明、系统迁移已执行、模型及相关角色权限已配置;有助理需求时包含 `assistant` 并接入 SDK |
|
|
37
37
|
| 实际验证通过 | 真实角色和模型下完成本次需求的读取、交互、审批或写入验收;报告通过、跳过与未执行项 |
|
|
38
38
|
|
|
39
|
-
先查现有 domain 入口,已有 AI 运行时就扩展该声明;框架只允许一个 `ai()` 运行时。空白模板只注册组织模型,`docs/examples/purchase-admin` 是参考源码,不代表启用了助理。标准范例可沿 `packages/domain/src/integrations/intelligence.ts`、`packages/domain/src/modules/purchase/approvals.ts` 和 `apps/web/src/shared/ui/assistant-panel.tsx` 阅读,路径规则见[学习入口](README.md)。后端循环、通用工具、会话表和性格管理使用框架;应用侧完成业务策略、授权与界面组合。
|
|
39
|
+
先查现有 domain 入口,已有 AI 运行时就扩展该声明;框架只允许一个 `ai()` 运行时。空白模板只注册组织模型,`docs/examples/purchase-admin` 是参考源码,不代表启用了助理。标准范例可沿 `packages/domain/src/integrations/intelligence.ts`、`packages/domain/src/modules/purchase/approvals.ts` 和 `apps/web/src/shared/ui/assistant-panel.tsx` 阅读,路径规则见[学习入口](../README.md)。后端循环、通用工具、会话表和性格管理使用框架;应用侧完成业务策略、授权与界面组合。
|
|
40
40
|
|
|
41
41
|
## 启用后端
|
|
42
42
|
|
|
@@ -292,7 +292,7 @@ const assistant = useAssistant(client.ai, page);
|
|
|
292
292
|
// progress.tool / toolName / toolState:当前工具及执行状态。
|
|
293
293
|
```
|
|
294
294
|
|
|
295
|
-
以上片段的 hooks 从 `@yss123/cage-client` 导入,record/location 是应用路由与数据。SDK 会在卸载、退出和切换账号时取消订阅并清理 hook 状态;应用其他缓存仍须按[开发步骤](workflow.md)处理。
|
|
295
|
+
以上片段的 hooks 从 `@yss123/cage-client` 导入,record/location 是应用路由与数据。SDK 会在卸载、退出和切换账号时取消订阅并清理 hook 状态;应用其他缓存仍须按[开发步骤](../getting-started/workflow.md)处理。
|
|
296
296
|
|
|
297
297
|
`send` / `respond` 返回的 Promise 等待本轮完成或需要用户交互;界面应在等待期间渲染 `streamingText` 和 `progress`。`run.status`、步数、工具调用数和待确认操作也随事件更新,不必等 Promise 返回。`model.started` 表示开始一次模型调用,`message.delta` 是增量文本,`tool.started` / `tool.completed` 表示实际工具进度;这些事件不包含模型的私有推理内容。新的模型步骤会重置当前文本,最终以 `message.completed` 校准。
|
|
298
298
|
|
|
@@ -345,4 +345,4 @@ Token 使用优先按模型返回 usage 核算;缺少 usage 时使用文本估
|
|
|
345
345
|
- AI 审批:覆盖 pass、return、manual,检查退回修改后的新轮次从头开始;模型失败应按节点配置转人工或留在失败状态,不得伪造通过。
|
|
346
346
|
- 管理配置:验证模型连接和一次实际工具交互,性格切换作用于后续消息;需要 Responses 接续或压缩时分别核对实际支持,连接成功不能替代这些验证。
|
|
347
347
|
|
|
348
|
-
`cage doctor` 可辅助检查注册、迁移和进程证据,但未知项不能当作通过;诊断用法见[能力发现与状态诊断](diagnostics.md)。模型输出质量需要应用使用自己的规则样例评测。框架验证的是权限、状态、预算和事务边界;发布前需使用实际模型服务、实际角色和审批样例联调。
|
|
348
|
+
`cage doctor` 可辅助检查注册、迁移和进程证据,但未知项不能当作通过;诊断用法见[能力发现与状态诊断](../tools/diagnostics.md)。模型输出质量需要应用使用自己的规则样例评测。框架验证的是权限、状态、预算和事务边界;发布前需使用实际模型服务、实际角色和审批样例联调。
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 业务设计与能力选择
|
|
2
2
|
|
|
3
|
-
[返回学习入口](README.md) · [原语示例](primitives.md) · [开发步骤](workflow.md)
|
|
3
|
+
[返回学习入口](../README.md) · [原语示例](../reference/primitives.md) · [开发步骤](../getting-started/workflow.md)
|
|
4
4
|
|
|
5
|
-
本页用于把用户的业务描述转成 Cage
|
|
5
|
+
本页用于把用户的业务描述转成 Cage 项目的可执行修改。先通过[框架开发 Skill](../skills/cage-development/SKILL.md)理解执行模型,首次使用可沿[完整入门课](../getting-started/first-feature.md)学习。按需要读对应配方,不要求为每个任务加载所有能力。
|
|
6
6
|
|
|
7
7
|
需要 AI 审批、业务助理、随页聊天、模型管理或性格配置时,先用 `cage capabilities` 查框架能力,再按[原生智能化指南](intelligence.md)接入。普通业务建模仍按下文声明聚合和命令;接入已有框架服务无需另建一套通用后端。
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## 先确定业务边界与执行路径
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
开始编码前,从用户需求、业务文档和现有实现中确定以下信息。按[业务澄清与共同设计](business-collaboration.md)主动提出歧义、冲突、遗漏及有价值的建议,给出选项、影响与推荐理由,让用户选择业务规则。已明确的条件直接采用,API 和普通技术细节由 agent 查证处理;下表用于发现相关问题,不要求用户逐项填表。
|
|
12
12
|
|
|
13
13
|
| 业务问题 | 落到什么声明 | 例如 |
|
|
14
14
|
| --- | --- | --- |
|
|
@@ -20,11 +20,30 @@
|
|
|
20
20
|
| 取消/失败要撤销什么? | cancelOn、释放命令、补偿流程 | 取消待办、释放占用、远端撤销或人工补偿 |
|
|
21
21
|
| 页面需要看什么? | 生成的 list/get、query、业务页面 | 分页、详情、按状态汇总、导出与导入 |
|
|
22
22
|
|
|
23
|
+
聚合按业务身份、生命周期和一致性要求划分。一个页面可展示多个聚合,一个聚合也可服务多个页面;不要把页面数量直接当成聚合数量。先识别必须始终成立的不变量,再确定哪些变化需要共同提交。需求没有审批或第三方时,普通命令和生成读取接口就能构成完整功能。
|
|
24
|
+
|
|
25
|
+
### 在相近能力之间作选择
|
|
26
|
+
|
|
27
|
+
| 判断依据 | 选择与边界 |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| 关系只有成员链接,还是有自己的状态与业务属性? | 纯链接用 manyToMany;需要管理关系生命周期时建独立聚合。hasMany 是对目标 ref 的反查,变更归属走目标命令 |
|
|
30
|
+
| 是改变阶段,还是在当前阶段修改字段? | 改阶段用 from/to;仅修改已有记录字段用 to: null,仍声明 from,不让 handler 直接改变 status |
|
|
31
|
+
| 是普通对象读取,还是汇总/联表? | 前者使用生成 list/get;后者声明 query、reads 与安全视图。前端筛选不能承担后端数据范围 |
|
|
32
|
+
| 两项业务变化是否必须一起成功? | 必须共同提交时使用同事务反应;允许稍后完成时走 outbox,明确失败、重试和结果展示 |
|
|
33
|
+
| 是否涉及事务外系统? | 网络 IO 放连接器;超时可能已经远端成功,需要幂等与核对/补偿,不能用数据库事务保证远端回滚 |
|
|
34
|
+
| 需要人工决定,还是确定的业务联动? | 人工/AI 审批使用现有审批流程;确定的自动联动使用事件与反应,不给每个状态变化都加审批 |
|
|
35
|
+
|
|
36
|
+
### 主体与范围必须能够落实到数据
|
|
37
|
+
|
|
38
|
+
先确定真实账号及组织关系,再列出各主体需要的能力和记录范围。当前授权模型使用已声明的归属字段;`scope.none()` 仍要求授权,但不能表达部门/创建人范围。声明了一个自定义 applicantId 或 companyName 不会自动获得“本人/本企业”过滤,应核对框架实际支持的范围字段与当前组织映射。
|
|
39
|
+
|
|
40
|
+
角色是后台分配的数据,能力是被授权的动作,门户是界面组织方式。当前会话公开类型不应通过类型断言凭空添加 roles;若需求要展示实际角色列表,应查找当前允许的读取接口或明确所需接口缺口。多角色能力/范围按框架规则合并,前端切换菜单不会自动切换服务端执行身份。用不同真实主体验证权限,不能用固定姓名或公司名称模拟范围。
|
|
41
|
+
|
|
23
42
|
## 新增一个普通管理对象
|
|
24
43
|
|
|
25
|
-
按[最小便笺业务](primitives.md)新增 `packages/domain/src/modules/<业务>/<对象>.ts`:字段、范围、不变量、create/update/archive 命令。采用唯一的导出名和必要的 `name` 覆盖,避免 index 的 `export *` 丢失重名符号。
|
|
44
|
+
按[最小便笺业务](../reference/primitives.md)新增 `packages/domain/src/modules/<业务>/<对象>.ts`:字段、范围、不变量、create/update/archive 命令。采用唯一的导出名和必要的 `name` 覆盖,避免 index 的 `export *` 丢失重名符号。
|
|
26
45
|
|
|
27
|
-
从模块 index 到 domain 入口导出后运行 check/gen,审查迁移,再在 `apps/web/src/modules/<业务>` 使用生成 contracts 做列表、详情、表单和操作按钮,经模块公开入口注册到 app 路由。列表和详情都有独立 URL,筛选/分页进入 query,按[浏览器配方](routing.md)检查导航。最后给角色授权并补图谱中文名。完整归属规则见[目录规范](project-structure.md)。不要手写后端增删改查路由、ORM 实体与 repository,也不要复制框架鉴权代码。
|
|
46
|
+
从模块 index 到 domain 入口导出后运行 check/gen,审查迁移,再在 `apps/web/src/modules/<业务>` 使用生成 contracts 做列表、详情、表单和操作按钮,经模块公开入口注册到 app 路由。列表和详情都有独立 URL,筛选/分页进入 query,按[浏览器配方](routing.md)检查导航。最后给角色授权并补图谱中文名。完整归属规则见[目录规范](../reference/project-structure.md)。不要手写后端增删改查路由、ORM 实体与 repository,也不要复制框架鉴权代码。
|
|
28
47
|
|
|
29
48
|
完成标准:授权用户能创建和修改,范围外数据不可见,归档后的允许行为符合业务要求,生成契约和迁移一致。没有审批需求时不必添加审批;没有外部系统时不必添加连接器。
|
|
30
49
|
|
|
@@ -42,7 +61,7 @@
|
|
|
42
61
|
4. 配置实际部门负责人、角色或指定用户;给审批人配置能力、范围和额度。
|
|
43
62
|
5. 页面通过待办接口操作。通过后需占用资源时用反应调用资源命令,按业务一致性选择同事务。
|
|
44
63
|
|
|
45
|
-
|
|
64
|
+
完成标准:提交生成待办、正确的人审批、越权和自审批拒绝、取消能结束待办、资源配对完整。转办、委派归还及当前节点前签、后签和并行必签见[审批任务流转](approvals.md),须显式启用政策并传任务版本,旧实例是否开放签序以其快照为准。任意流程设计器、动态 JS 选人和指定节点退回仍需明确扩展范围。
|
|
46
65
|
|
|
47
66
|
## 加入 AI 审批或随页助理
|
|
48
67
|
|
|
@@ -79,10 +98,11 @@
|
|
|
79
98
|
## 给编程工具的任务模板
|
|
80
99
|
|
|
81
100
|
```text
|
|
82
|
-
阅读当前项目 AGENTS.md,按 docs/
|
|
83
|
-
遵守 docs/
|
|
101
|
+
阅读当前项目 AGENTS.md,按 docs/development/README.md 找到本次需求对应的原语和标准范例。
|
|
102
|
+
遵守 docs/development/reference/project-structure.md:领域和前端按业务建 modules,app 组合页面,shared 只放通用代码,不平铺 src 或堆进 main.tsx。
|
|
84
103
|
业务:……;角色与数据范围:……;状态与允许动作:……;审批/外部系统/资源占用:……。
|
|
85
|
-
|
|
104
|
+
阅读后主动指出描述或文档中的疑点,按 docs/development/guides/business-collaboration.md 给出可行选项、影响与推荐,让我选择;已明确条件不重复询问,普通技术细节自行查证处理。
|
|
105
|
+
将已选择的规则映射到 domain、页面、契约、迁移、授权和验收,再完成实现;等待业务决定时继续不依赖该决定的工作,可选建议不阻塞已明确任务。
|
|
86
106
|
使用当前公开 API;对无法表达的需求说明具体缺口,不编造方法。
|
|
87
107
|
生成文件通过 cage gen 更新,数据库使用已有 .env 配置,按改动完成必要验证。
|
|
88
108
|
交付时说明用户如何体验、管理员需配置什么,以及通过/跳过/未执行的检查。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 业务对象之间的关系
|
|
2
2
|
|
|
3
|
-
[返回学习入口](README.md) · [最小业务](primitives.md) · [开发步骤](workflow.md)
|
|
3
|
+
[返回学习入口](../README.md) · [最小业务](../reference/primitives.md) · [开发步骤](../getting-started/workflow.md)
|
|
4
4
|
|
|
5
5
|
关系和普通属性统一写在 `aggregate(...).fields` 中。业务不需要另写 `relations` 区块,也不用为单纯“便笺与用户的关联”创建 `NoteMember` 聚合。
|
|
6
6
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
## 完整领域例子
|
|
22
22
|
|
|
23
|
-
下面可作为 `packages/domain/src/modules/note/note.ts`。它是[最小便笺](primitives.md)的关系版本,按需要替换原文件,避免重复声明 Note。
|
|
23
|
+
下面可作为 `packages/domain/src/modules/note/note.ts`。它是[最小便笺](../reference/primitives.md)的关系版本,按需要替换原文件,避免重复声明 Note。
|
|
24
24
|
|
|
25
25
|
```ts
|
|
26
26
|
import {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 业务前端路由与浏览器验收
|
|
2
2
|
|
|
3
|
-
[返回学习入口](README.md) · [工程目录](project-structure.md) · [开发步骤](workflow.md)
|
|
3
|
+
[返回学习入口](../README.md) · [工程目录](../reference/project-structure.md) · [开发步骤](../getting-started/workflow.md)
|
|
4
4
|
|
|
5
5
|
多页面业务默认使用 React Router 的 BrowserRouter。列表、详情、报表等可独立访问的页面必须有 URL;在 app 中统一组合路由和工作台布局,页面从模块 index.ts 导出。useState 用于弹窗、未提交表单和按钮忙碌状态。筛选、分页和需要分享的选项使用 useSearchParams。
|
|
6
6
|
|