@yss123/cage-cli 0.2.0 → 0.3.1
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 +47 -3
- package/bin/cage.js +5 -0
- package/bin/create-cage-app.js +5 -0
- package/dist/analyze.d.ts +16 -0
- package/dist/analyze.js +18 -2
- package/dist/analyze.js.map +1 -1
- 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/baseline.d.ts +8 -0
- package/dist/baseline.js +13 -0
- package/dist/baseline.js.map +1 -1
- package/dist/bootstrap.d.ts +20 -0
- package/dist/bootstrap.js +75 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/budget.d.ts +7 -0
- package/dist/budget.js +49 -5
- package/dist/budget.js.map +1 -1
- package/dist/capabilities.d.ts +38 -0
- package/dist/capabilities.js +148 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/config.d.ts +31 -2
- package/dist/config.js +22 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +14 -0
- package/dist/context.js +35 -2
- package/dist/context.js.map +1 -1
- package/dist/create-prompt.d.ts +7 -0
- package/dist/create-prompt.js +12 -0
- package/dist/create-prompt.js.map +1 -1
- package/dist/create.d.ts +21 -1
- package/dist/create.js +23 -1
- package/dist/create.js.map +1 -1
- package/dist/derive.d.ts +23 -0
- package/dist/derive.js +40 -0
- package/dist/derive.js.map +1 -1
- package/dist/dev.d.ts +6 -0
- package/dist/dev.js +11 -0
- package/dist/dev.js.map +1 -1
- package/dist/doctor.d.ts +98 -0
- package/dist/doctor.js +93 -0
- package/dist/doctor.js.map +1 -0
- package/dist/env.d.ts +6 -0
- package/dist/env.js +11 -0
- package/dist/env.js.map +1 -1
- package/dist/findings.d.ts +27 -0
- package/dist/findings.js +20 -0
- package/dist/findings.js.map +1 -1
- package/dist/gen/contracts.d.ts +28 -0
- package/dist/gen/contracts.js +52 -12
- package/dist/gen/contracts.js.map +1 -1
- package/dist/gen/index.d.ts +26 -0
- package/dist/gen/index.js +69 -1
- package/dist/gen/index.js.map +1 -1
- package/dist/gen/zod-code.d.ts +42 -0
- package/dist/gen/zod-code.js +178 -16
- package/dist/gen/zod-code.js.map +1 -1
- package/dist/graph-approvals.d.ts +70 -0
- package/dist/graph-approvals.js +93 -0
- package/dist/graph-approvals.js.map +1 -0
- package/dist/graph-business.d.ts +135 -0
- package/dist/graph-business.js +404 -0
- package/dist/graph-business.js.map +1 -0
- package/dist/graph-command.d.ts +17 -0
- package/dist/graph-command.js +21 -0
- package/dist/graph-command.js.map +1 -1
- package/dist/graph-model.d.ts +44 -0
- package/dist/graph-model.js +36 -3
- package/dist/graph-model.js.map +1 -1
- package/dist/graph-presentation.d.ts +16 -0
- package/dist/graph-presentation.js +10 -1
- package/dist/graph-presentation.js.map +1 -1
- package/dist/graph-query.d.ts +95 -0
- package/dist/graph-query.js +62 -0
- package/dist/graph-query.js.map +1 -1
- package/dist/graph-relations.d.ts +20 -0
- package/dist/graph-relations.js +42 -10
- package/dist/graph-relations.js.map +1 -1
- package/dist/graph-search.d.ts +35 -0
- package/dist/graph-search.js +36 -0
- package/dist/graph-search.js.map +1 -1
- package/dist/graph-snapshot.d.ts +26 -0
- package/dist/graph-snapshot.js +30 -1
- package/dist/graph-snapshot.js.map +1 -1
- package/dist/graph.d.ts +13 -2
- package/dist/graph.js +61 -4
- package/dist/graph.js.map +1 -1
- package/dist/impact.d.ts +50 -0
- package/dist/impact.js +62 -2
- package/dist/impact.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +12 -0
- package/dist/init.js +15 -0
- package/dist/init.js.map +1 -1
- package/dist/load.d.ts +10 -0
- package/dist/load.js +15 -0
- package/dist/load.js.map +1 -1
- package/dist/main.d.ts +6 -0
- package/dist/main.js +93 -5
- package/dist/main.js.map +1 -1
- package/dist/migrate.d.ts +12 -0
- package/dist/migrate.js +17 -0
- package/dist/migrate.js.map +1 -1
- package/dist/ontology.d.ts +67 -2
- package/dist/ontology.js +94 -4
- package/dist/ontology.js.map +1 -1
- package/dist/process-rules.d.ts +21 -0
- package/dist/process-rules.js +100 -0
- package/dist/process-rules.js.map +1 -0
- package/dist/process.d.ts +32 -0
- package/dist/process.js +32 -0
- package/dist/process.js.map +1 -1
- package/dist/project-structure.d.ts +5 -0
- package/dist/project-structure.js +10 -0
- package/dist/project-structure.js.map +1 -1
- package/dist/registration.d.ts +16 -0
- package/dist/registration.js +56 -0
- package/dist/registration.js.map +1 -0
- package/dist/rules.d.ts +52 -0
- package/dist/rules.js +58 -0
- package/dist/rules.js.map +1 -1
- package/dist/runtime-diagnostics.d.ts +27 -0
- package/dist/runtime-diagnostics.js +60 -0
- package/dist/runtime-diagnostics.js.map +1 -0
- package/dist/snapshots.d.ts +40 -0
- package/dist/snapshots.js +62 -0
- package/dist/snapshots.js.map +1 -0
- package/dist/static-check.d.ts +33 -0
- package/dist/static-check.js +37 -1
- package/dist/static-check.js.map +1 -1
- package/dist/sync.d.ts +11 -0
- package/dist/sync.js +66 -9
- package/dist/sync.js.map +1 -1
- package/dist/upgrade.d.ts +16 -0
- package/dist/upgrade.js +21 -0
- package/dist/upgrade.js.map +1 -1
- package/dist/verify.d.ts +14 -0
- package/dist/verify.js +19 -0
- package/dist/verify.js.map +1 -1
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -1
- package/graph-ui/app.js +321 -27
- package/graph-ui/approval-flow.js +185 -0
- package/graph-ui/approval-parallel.js +110 -0
- package/graph-ui/approval-tree.js +17 -0
- package/graph-ui/business.css +1011 -0
- package/graph-ui/business.js +566 -0
- package/graph-ui/flowchart-interaction.js +177 -0
- package/graph-ui/flowchart.js +1059 -0
- package/graph-ui/graph-approvals.js +92 -0
- package/graph-ui/graph-business.js +403 -0
- package/graph-ui/graph-model.js +36 -3
- package/graph-ui/graph-relations.js +42 -10
- package/graph-ui/graph-search.js +36 -0
- package/graph-ui/index.html +26 -12
- package/graph-ui/model.js +28 -0
- package/graph-ui/relations.js +4 -0
- package/graph-ui/structure.js +44 -0
- package/graph-ui/style.css +12 -0
- package/package.json +6 -4
- package/templates/app/.dockerignore +2 -0
- package/templates/app/.env.example +10 -0
- package/templates/app/AGENTS.md +50 -10
- package/templates/app/README.md +9 -5
- package/templates/app/_gitignore +1 -0
- package/templates/app/apps/api/package.json +2 -2
- package/templates/app/apps/api/src/main.ts +5 -1
- package/templates/app/apps/api/src/worker.ts +3 -0
- package/templates/app/apps/web/index.html +1 -0
- package/templates/app/apps/web/package.json +7 -3
- package/templates/app/apps/web/src/app/app.tsx +122 -12
- package/templates/app/apps/web/src/app/styles/global.css +88 -8
- package/templates/app/apps/web/src/app/use-session.ts +43 -0
- package/templates/app/apps/web/src/app/workspace-layout.tsx +58 -19
- package/templates/app/apps/web/src/main.tsx +5 -0
- 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 +13 -5
- package/templates/app/apps/web/src/modules/approval/index.ts +4 -0
- package/templates/app/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +89 -38
- package/templates/app/apps/web/src/modules/approval/pages/approval-tasks.css +18 -0
- package/templates/app/apps/web/src/modules/auth/index.ts +4 -0
- package/templates/app/apps/web/src/modules/auth/pages/login-page.tsx +12 -0
- package/templates/app/apps/web/src/modules/inventory/index.ts +4 -0
- package/templates/app/apps/web/src/modules/inventory/pages/inventory-page.tsx +29 -1
- package/templates/app/apps/web/src/modules/purchase/components/approval-history.tsx +67 -0
- package/templates/app/apps/web/src/modules/purchase/components/order-attachments.tsx +29 -0
- package/templates/app/apps/web/src/modules/purchase/components/order-reviewers.tsx +38 -0
- package/templates/app/apps/web/src/modules/purchase/components/purchase-assistant-context.tsx +17 -0
- package/templates/app/apps/web/src/modules/purchase/components/purchase-order-form.css +6 -0
- package/templates/app/apps/web/src/modules/purchase/components/purchase-order-form.tsx +32 -3
- package/templates/app/apps/web/src/modules/purchase/index.ts +5 -0
- package/templates/app/apps/web/src/modules/purchase/lib/presentation.ts +20 -0
- package/templates/app/apps/web/src/modules/purchase/pages/purchase-intelligence.css +17 -0
- package/templates/app/apps/web/src/modules/purchase/pages/purchase-order-detail-page.tsx +156 -0
- package/templates/app/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +54 -22
- package/templates/app/apps/web/src/modules/workspace/index.ts +5 -0
- package/templates/app/apps/web/src/modules/workspace/pages/home-page.tsx +44 -0
- package/templates/app/apps/web/src/shared/hooks/use-command.ts +13 -0
- package/templates/app/apps/web/src/shared/lib/error-message.ts +15 -1
- package/templates/app/apps/web/src/shared/lib/navigation.ts +21 -0
- 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/apps/web/src/shared/ui/assistant-markdown.tsx +19 -0
- package/templates/app/apps/web/src/shared/ui/assistant-panel.css +134 -0
- package/templates/app/apps/web/src/shared/ui/assistant-panel.tsx +200 -0
- package/templates/app/apps/web/src/shared/ui/assistant-scope.tsx +72 -0
- package/templates/app/apps/web/src/shared/ui/attachment-upload.css +28 -0
- package/templates/app/apps/web/src/shared/ui/attachment-upload.tsx +163 -0
- package/templates/app/apps/web/src/shared/ui/notice.tsx +7 -0
- package/templates/app/apps/web/src/shared/ui/page-heading.tsx +7 -0
- package/templates/app/apps/web/src/shared/ui/page-state.css +47 -0
- package/templates/app/apps/web/src/shared/ui/page-state.tsx +76 -0
- package/templates/app/apps/web/src/shared/ui/require-capability.tsx +34 -0
- package/templates/app/apps/web/vite.config.ts +5 -0
- package/templates/app/cage.config.json +23 -0
- package/templates/app/db/migrations/0002_draft.sql +12 -0
- package/templates/app/db/migrations/0003_draft.sql +8 -0
- package/templates/app/db/migrations/0004_draft.sql +27 -0
- package/templates/app/deploy/nginx.conf +52 -0
- package/templates/app/docs/ai/README.md +28 -2
- package/templates/app/docs/ai/approvals.md +260 -0
- package/templates/app/docs/ai/architecture.md +26 -0
- package/templates/app/docs/ai/commenting.md +203 -0
- package/templates/app/docs/ai/diagnostics.md +80 -0
- package/templates/app/docs/ai/files.md +93 -0
- package/templates/app/docs/ai/intelligence.md +348 -0
- package/templates/app/docs/ai/ontology-context.md +59 -4
- package/templates/app/docs/ai/primitives.md +34 -1
- package/templates/app/docs/ai/project-structure.md +8 -3
- package/templates/app/docs/ai/purchase-example.md +35 -7
- package/templates/app/docs/ai/recipes.md +10 -2
- package/templates/app/docs/ai/routing.md +86 -0
- package/templates/app/docs/ai/troubleshooting.md +5 -0
- package/templates/app/docs/ai/workflow.md +24 -11
- package/templates/app/docs/errors/CAGE-AI-001.md +61 -0
- package/templates/app/docs/errors/CAGE-APPR-001.md +13 -9
- package/templates/app/docs/errors/CAGE-APPR-002.md +2 -2
- package/templates/app/docs/errors/CAGE-APPR-003.md +1 -1
- package/templates/app/docs/errors/CAGE-APPR-004.md +4 -4
- package/templates/app/docs/errors/CAGE-APPR-005.md +4 -4
- package/templates/app/docs/errors/CAGE-APPR-006.md +29 -8
- package/templates/app/docs/errors/CAGE-APPR-007.md +9 -7
- package/templates/app/docs/errors/CAGE-APPR-010.md +5 -5
- package/templates/app/docs/errors/CAGE-AUDIT-001.md +53 -0
- package/templates/app/docs/errors/CAGE-AUTH-001.md +1 -1
- package/templates/app/docs/errors/CAGE-BIZ-001.md +51 -0
- package/templates/app/docs/errors/CAGE-BIZ-002.md +49 -0
- 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 +3 -3
- 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 +6 -6
- package/templates/app/docs/errors/CAGE-CONN-008.md +5 -5
- package/templates/app/docs/errors/CAGE-CONN-009.md +6 -6
- package/templates/app/docs/errors/CAGE-CONN-010.md +6 -6
- 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 +49 -0
- package/templates/app/docs/errors/CAGE-CONN-014.md +48 -0
- package/templates/app/docs/errors/CAGE-CONN-015.md +49 -0
- package/templates/app/docs/errors/CAGE-CREATE-001.md +10 -9
- package/templates/app/docs/errors/CAGE-DECL-001.md +2 -2
- package/templates/app/docs/errors/CAGE-DECL-002.md +7 -6
- 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 +2 -2
- package/templates/app/docs/errors/CAGE-DEP-002.md +1 -1
- package/templates/app/docs/errors/CAGE-DEP-003.md +2 -2
- 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 +53 -0
- package/templates/app/docs/errors/CAGE-DLQ-001.md +2 -2
- package/templates/app/docs/errors/CAGE-ENV-001.md +4 -4
- package/templates/app/docs/errors/CAGE-ENV-002.md +51 -0
- package/templates/app/docs/errors/CAGE-ENV-003.md +48 -0
- package/templates/app/docs/errors/CAGE-EVENT-001.md +1 -1
- package/templates/app/docs/errors/CAGE-EVENT-002.md +7 -7
- package/templates/app/docs/errors/CAGE-FIELD-001.md +2 -2
- 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 +56 -0
- package/templates/app/docs/errors/CAGE-GEN-001.md +2 -2
- package/templates/app/docs/errors/CAGE-GEN-002.md +1 -1
- package/templates/app/docs/errors/CAGE-GEN-003.md +53 -0
- package/templates/app/docs/errors/CAGE-GRANT-001.md +3 -3
- package/templates/app/docs/errors/CAGE-GRANT-002.md +2 -2
- package/templates/app/docs/errors/CAGE-GRANT-003.md +7 -6
- package/templates/app/docs/errors/CAGE-IMPACT-001.md +2 -2
- package/templates/app/docs/errors/CAGE-IMPACT-002.md +52 -0
- 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 +2 -2
- package/templates/app/docs/errors/CAGE-INIT-004.md +1 -1
- package/templates/app/docs/errors/CAGE-INIT-005.md +52 -0
- 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 +3 -3
- 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 +7 -6
- package/templates/app/docs/errors/CAGE-PAIR-002.md +6 -5
- package/templates/app/docs/errors/CAGE-QUERY-001.md +1 -1
- package/templates/app/docs/errors/CAGE-QUERY-002.md +2 -2
- package/templates/app/docs/errors/CAGE-QUERY-003.md +7 -6
- package/templates/app/docs/errors/CAGE-REACT-001.md +3 -3
- package/templates/app/docs/errors/CAGE-REACT-002.md +1 -1
- package/templates/app/docs/errors/CAGE-REACT-003.md +50 -0
- package/templates/app/docs/errors/CAGE-READS-001.md +9 -6
- package/templates/app/docs/errors/CAGE-REG-001.md +13 -12
- package/templates/app/docs/errors/CAGE-REG-002.md +2 -1
- package/templates/app/docs/errors/CAGE-REG-003.md +1 -1
- package/templates/app/docs/errors/CAGE-REL-001.md +14 -14
- package/templates/app/docs/errors/CAGE-ROUTE-001.md +7 -6
- package/templates/app/docs/errors/CAGE-SCOPE-001.md +1 -1
- package/templates/app/docs/errors/CAGE-SCOPE-002.md +2 -2
- package/templates/app/docs/errors/CAGE-SECRET-001.md +2 -2
- package/templates/app/docs/errors/CAGE-SECRET-002.md +1 -1
- package/templates/app/docs/errors/CAGE-SENS-001.md +5 -5
- 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 +3 -3
- 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 +3 -2
- package/templates/app/docs/errors/CAGE-STATE-010.md +5 -5
- package/templates/app/docs/errors/CAGE-STATE-011.md +5 -5
- package/templates/app/docs/errors/CAGE-STRUCT-001.md +1 -1
- package/templates/app/docs/errors/CAGE-STRUCT-002.md +1 -1
- package/templates/app/docs/errors/CAGE-SYNC-001.md +3 -2
- package/templates/app/docs/errors/CAGE-TEST-001.md +1 -1
- package/templates/app/docs/errors/CAGE-TEST-002.md +50 -0
- package/templates/app/docs/errors/CAGE-TEST-003.md +52 -0
- package/templates/app/docs/errors/CAGE-UNSAFE-001.md +3 -2
- package/templates/app/docs/errors/CAGE-UPGRADE-001.md +2 -2
- package/templates/app/docs/errors/CAGE-WORKER-001.md +48 -0
- package/templates/app/docs/errors/CAGE-WORKER-002.md +50 -0
- package/templates/app/docs/errors/CAGE-WORKER-003.md +48 -0
- package/templates/app/docs/errors/README.md +52 -2
- 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/dept/index.ts +10 -10
- package/templates/app/packages/contracts/src/aggregates/inventory/index.ts +5 -5
- package/templates/app/packages/contracts/src/aggregates/inventory-lock/index.ts +4 -4
- package/templates/app/packages/contracts/src/aggregates/purchase-order/index.ts +34 -12
- package/templates/app/packages/contracts/src/aggregates/role/index.ts +15 -15
- package/templates/app/packages/contracts/src/aggregates/user/index.ts +16 -16
- package/templates/app/packages/contracts/src/index.ts +16 -1
- package/templates/app/packages/contracts/src/queries/index.ts +2 -2
- package/templates/app/packages/domain/package.json +5 -4
- package/templates/app/packages/domain/src/index.ts +4 -0
- package/templates/app/packages/domain/src/integrations/erp.ts +15 -0
- package/templates/app/packages/domain/src/integrations/intelligence.ts +20 -0
- package/templates/app/packages/domain/src/modules/inventory/index.ts +1 -0
- package/templates/app/packages/domain/src/modules/inventory/inventory.ts +12 -0
- package/templates/app/packages/domain/src/modules/purchase/approval-members.ts +54 -0
- package/templates/app/packages/domain/src/modules/purchase/approvals.ts +38 -6
- package/templates/app/packages/domain/src/modules/purchase/index.ts +2 -0
- package/templates/app/packages/domain/src/modules/purchase/intelligence.test.ts +224 -0
- package/templates/app/packages/domain/src/modules/purchase/jobs.ts +5 -0
- package/templates/app/packages/domain/src/modules/purchase/purchase-order.test.ts +9 -0
- package/templates/app/packages/domain/src/modules/purchase/purchase-order.ts +125 -4
- package/templates/app/packages/domain/src/modules/purchase/queries.ts +5 -0
- package/templates/app/packages/domain/src/workflows/purchase-inventory.ts +6 -0
- package/templates/app/packages/domain/src/workflows/purchase-process.ts +42 -0
- package/templates/blank/.dockerignore +2 -0
- package/templates/blank/.env.example +10 -0
- package/templates/blank/AGENTS.md +50 -10
- package/templates/blank/README.md +4 -1
- package/templates/blank/_gitignore +1 -0
- package/templates/blank/apps/api/package.json +1 -1
- package/templates/blank/apps/api/src/main.ts +4 -1
- package/templates/blank/apps/api/src/worker.ts +2 -0
- package/templates/blank/apps/web/index.html +1 -0
- package/templates/blank/apps/web/package.json +7 -3
- package/templates/blank/apps/web/src/app/app.tsx +80 -18
- package/templates/blank/apps/web/src/app/styles/global.css +90 -0
- package/templates/blank/apps/web/src/app/use-session.ts +43 -0
- package/templates/blank/apps/web/src/app/workspace-layout.tsx +30 -5
- package/templates/blank/apps/web/src/main.tsx +5 -0
- package/templates/blank/apps/web/src/modules/auth/index.ts +4 -0
- package/templates/blank/apps/web/src/modules/auth/pages/login-page.tsx +18 -1
- package/templates/blank/apps/web/src/modules/directory/index.ts +7 -0
- package/templates/blank/apps/web/src/modules/directory/pages/user-detail-page.tsx +78 -0
- package/templates/blank/apps/web/src/modules/directory/pages/users-page.tsx +93 -0
- package/templates/blank/apps/web/src/modules/workspace/index.ts +4 -0
- package/templates/blank/apps/web/src/modules/workspace/pages/home-page.tsx +17 -0
- package/templates/blank/apps/web/src/shared/lib/error-message.ts +11 -0
- package/templates/blank/apps/web/src/shared/lib/navigation.ts +21 -0
- package/templates/blank/apps/web/src/shared/ui/brand.tsx +10 -2
- package/templates/blank/apps/web/src/shared/ui/page-state.css +47 -0
- package/templates/blank/apps/web/src/shared/ui/page-state.tsx +76 -0
- package/templates/blank/apps/web/src/shared/ui/require-capability.tsx +34 -0
- package/templates/blank/apps/web/vite.config.ts +5 -0
- package/templates/blank/deploy/nginx.conf +52 -0
- package/templates/blank/docs/ai/README.md +28 -2
- package/templates/blank/docs/ai/approvals.md +260 -0
- package/templates/blank/docs/ai/architecture.md +26 -0
- package/templates/blank/docs/ai/commenting.md +203 -0
- package/templates/blank/docs/ai/diagnostics.md +80 -0
- package/templates/blank/docs/ai/files.md +93 -0
- package/templates/blank/docs/ai/intelligence.md +348 -0
- package/templates/blank/docs/ai/ontology-context.md +59 -4
- package/templates/blank/docs/ai/primitives.md +34 -1
- package/templates/blank/docs/ai/project-structure.md +8 -3
- package/templates/blank/docs/ai/purchase-example.md +35 -7
- package/templates/blank/docs/ai/recipes.md +10 -2
- package/templates/blank/docs/ai/routing.md +86 -0
- package/templates/blank/docs/ai/troubleshooting.md +5 -0
- package/templates/blank/docs/ai/workflow.md +24 -11
- package/templates/blank/docs/errors/CAGE-AI-001.md +61 -0
- package/templates/blank/docs/errors/CAGE-APPR-001.md +13 -9
- package/templates/blank/docs/errors/CAGE-APPR-002.md +2 -2
- package/templates/blank/docs/errors/CAGE-APPR-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-APPR-004.md +4 -4
- package/templates/blank/docs/errors/CAGE-APPR-005.md +4 -4
- package/templates/blank/docs/errors/CAGE-APPR-006.md +29 -8
- package/templates/blank/docs/errors/CAGE-APPR-007.md +9 -7
- package/templates/blank/docs/errors/CAGE-APPR-010.md +5 -5
- package/templates/blank/docs/errors/CAGE-AUDIT-001.md +53 -0
- package/templates/blank/docs/errors/CAGE-AUTH-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-BIZ-001.md +51 -0
- package/templates/blank/docs/errors/CAGE-BIZ-002.md +49 -0
- 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 +3 -3
- 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 +6 -6
- package/templates/blank/docs/errors/CAGE-CONN-008.md +5 -5
- package/templates/blank/docs/errors/CAGE-CONN-009.md +6 -6
- package/templates/blank/docs/errors/CAGE-CONN-010.md +6 -6
- 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 +49 -0
- package/templates/blank/docs/errors/CAGE-CONN-014.md +48 -0
- package/templates/blank/docs/errors/CAGE-CONN-015.md +49 -0
- package/templates/blank/docs/errors/CAGE-CREATE-001.md +10 -9
- package/templates/blank/docs/errors/CAGE-DECL-001.md +2 -2
- package/templates/blank/docs/errors/CAGE-DECL-002.md +7 -6
- 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 +2 -2
- package/templates/blank/docs/errors/CAGE-DEP-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-DEP-003.md +2 -2
- 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 +53 -0
- package/templates/blank/docs/errors/CAGE-DLQ-001.md +2 -2
- package/templates/blank/docs/errors/CAGE-ENV-001.md +4 -4
- package/templates/blank/docs/errors/CAGE-ENV-002.md +51 -0
- package/templates/blank/docs/errors/CAGE-ENV-003.md +48 -0
- package/templates/blank/docs/errors/CAGE-EVENT-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-EVENT-002.md +7 -7
- package/templates/blank/docs/errors/CAGE-FIELD-001.md +2 -2
- 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 +56 -0
- package/templates/blank/docs/errors/CAGE-GEN-001.md +2 -2
- package/templates/blank/docs/errors/CAGE-GEN-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-GEN-003.md +53 -0
- package/templates/blank/docs/errors/CAGE-GRANT-001.md +3 -3
- package/templates/blank/docs/errors/CAGE-GRANT-002.md +2 -2
- package/templates/blank/docs/errors/CAGE-GRANT-003.md +7 -6
- package/templates/blank/docs/errors/CAGE-IMPACT-001.md +2 -2
- package/templates/blank/docs/errors/CAGE-IMPACT-002.md +52 -0
- 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 +2 -2
- package/templates/blank/docs/errors/CAGE-INIT-004.md +1 -1
- package/templates/blank/docs/errors/CAGE-INIT-005.md +52 -0
- 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 +3 -3
- 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 +7 -6
- package/templates/blank/docs/errors/CAGE-PAIR-002.md +6 -5
- package/templates/blank/docs/errors/CAGE-QUERY-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-QUERY-002.md +2 -2
- package/templates/blank/docs/errors/CAGE-QUERY-003.md +7 -6
- package/templates/blank/docs/errors/CAGE-REACT-001.md +3 -3
- package/templates/blank/docs/errors/CAGE-REACT-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-REACT-003.md +50 -0
- package/templates/blank/docs/errors/CAGE-READS-001.md +9 -6
- package/templates/blank/docs/errors/CAGE-REG-001.md +13 -12
- package/templates/blank/docs/errors/CAGE-REG-002.md +2 -1
- package/templates/blank/docs/errors/CAGE-REG-003.md +1 -1
- package/templates/blank/docs/errors/CAGE-REL-001.md +14 -14
- package/templates/blank/docs/errors/CAGE-ROUTE-001.md +7 -6
- package/templates/blank/docs/errors/CAGE-SCOPE-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-SCOPE-002.md +2 -2
- package/templates/blank/docs/errors/CAGE-SECRET-001.md +2 -2
- package/templates/blank/docs/errors/CAGE-SECRET-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-SENS-001.md +5 -5
- 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 +3 -3
- 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 +3 -2
- package/templates/blank/docs/errors/CAGE-STATE-010.md +5 -5
- package/templates/blank/docs/errors/CAGE-STATE-011.md +5 -5
- package/templates/blank/docs/errors/CAGE-STRUCT-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-STRUCT-002.md +1 -1
- package/templates/blank/docs/errors/CAGE-SYNC-001.md +3 -2
- package/templates/blank/docs/errors/CAGE-TEST-001.md +1 -1
- package/templates/blank/docs/errors/CAGE-TEST-002.md +50 -0
- package/templates/blank/docs/errors/CAGE-TEST-003.md +52 -0
- package/templates/blank/docs/errors/CAGE-UNSAFE-001.md +3 -2
- package/templates/blank/docs/errors/CAGE-UPGRADE-001.md +2 -2
- package/templates/blank/docs/errors/CAGE-WORKER-001.md +48 -0
- package/templates/blank/docs/errors/CAGE-WORKER-002.md +50 -0
- package/templates/blank/docs/errors/CAGE-WORKER-003.md +48 -0
- package/templates/blank/docs/errors/README.md +52 -2
- package/templates/blank/docs/examples/purchase-admin/apps/api/src/main.ts +5 -1
- package/templates/blank/docs/examples/purchase-admin/apps/api/src/worker.ts +3 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/app.tsx +122 -12
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/styles/global.css +88 -8
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/use-session.ts +43 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/workspace-layout.tsx +58 -19
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/main.tsx +5 -0
- 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 +13 -5
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/index.ts +4 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +89 -38
- 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/auth/index.ts +4 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/auth/pages/login-page.tsx +12 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/inventory/index.ts +4 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/inventory/pages/inventory-page.tsx +29 -1
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/approval-history.tsx +67 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/order-attachments.tsx +29 -0
- 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-assistant-context.tsx +17 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-order-form.css +6 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-order-form.tsx +32 -3
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/index.ts +5 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/lib/presentation.ts +20 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-intelligence.css +17 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-order-detail-page.tsx +156 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +54 -22
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/workspace/index.ts +5 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/workspace/pages/home-page.tsx +44 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/hooks/use-command.ts +13 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/lib/error-message.ts +15 -1
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/lib/navigation.ts +21 -0
- 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/apps/web/src/shared/ui/assistant-markdown.tsx +19 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-panel.css +134 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-panel.tsx +200 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-scope.tsx +72 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/attachment-upload.css +28 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/attachment-upload.tsx +163 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/notice.tsx +7 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-heading.tsx +7 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-state.css +47 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-state.tsx +76 -0
- package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/require-capability.tsx +34 -0
- package/templates/blank/docs/examples/purchase-admin/cage.config.json +23 -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/dept/index.ts +10 -10
- package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/inventory/index.ts +5 -5
- package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/inventory-lock/index.ts +4 -4
- package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/purchase-order/index.ts +34 -12
- package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/role/index.ts +15 -15
- package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/user/index.ts +16 -16
- package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/index.ts +16 -1
- package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/queries/index.ts +2 -2
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/index.ts +4 -0
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/integrations/erp.ts +15 -0
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/integrations/intelligence.ts +20 -0
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/inventory/index.ts +1 -0
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/inventory/inventory.ts +12 -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 +38 -6
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/index.ts +2 -0
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/intelligence.test.ts +224 -0
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/jobs.ts +5 -0
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.test.ts +9 -0
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.ts +125 -4
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/queries.ts +5 -0
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/workflows/purchase-inventory.ts +6 -0
- package/templates/blank/docs/examples/purchase-admin/packages/domain/src/workflows/purchase-process.ts +42 -0
- package/templates/blank/package.json +3 -3
- package/templates/blank/packages/contracts/package.json +1 -1
- package/templates/blank/packages/contracts/src/aggregates/dept/index.ts +10 -10
- package/templates/blank/packages/contracts/src/aggregates/role/index.ts +15 -15
- package/templates/blank/packages/contracts/src/aggregates/user/index.ts +16 -16
- package/templates/blank/packages/contracts/src/index.ts +1 -1
- package/templates/blank/packages/contracts/src/queries/index.ts +1 -1
- package/templates/blank/packages/domain/package.json +5 -4
- package/templates/blank/packages/domain/src/index.ts +2 -1
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* 采购单声明集中列出申请材料、专业复核名单、状态、范围、命令和事件,由 API、worker 和生成器统一消费。
|
|
3
|
+
* 草稿可编辑专业复核名单,提交重新核对协作名录;handler 仅读取声明依赖,数据库写入、版本与审计由内核完成。
|
|
4
|
+
* 审批结论仍以 process 命令执行职责分离、额度和库存检查;选入名录或路由不授予权限。
|
|
5
|
+
*/
|
|
3
6
|
import {
|
|
4
7
|
aggregate,
|
|
8
|
+
bool,
|
|
5
9
|
ceiling,
|
|
6
10
|
command,
|
|
7
11
|
emit,
|
|
8
12
|
event,
|
|
9
13
|
fail,
|
|
14
|
+
files,
|
|
10
15
|
id,
|
|
11
16
|
int,
|
|
12
17
|
list,
|
|
@@ -16,22 +21,47 @@ import {
|
|
|
16
21
|
sod,
|
|
17
22
|
states,
|
|
18
23
|
text,
|
|
24
|
+
type ReadRepo,
|
|
19
25
|
} from '@yss123/cage-kernel';
|
|
20
26
|
import { z } from 'zod';
|
|
21
27
|
import { Inventory } from '../inventory/index.js';
|
|
28
|
+
import { ApprovalMember } from './approval-members.js';
|
|
22
29
|
|
|
30
|
+
/**
|
|
31
|
+
* 采购单生命周期:草稿提交后等待审批,通过后等待外部收货;退回修改重新进入草稿。
|
|
32
|
+
* received/rejected/cancelled 是流程终点,终点标记供图谱检查;记录迟到 ERP 回执仍由专门命令显式允许。
|
|
33
|
+
*/
|
|
23
34
|
export const POStatus = states('draft', 'pending_approval', 'approved', 'received', 'rejected', 'cancelled', {
|
|
24
35
|
terminal: ['received', 'rejected', 'cancelled'],
|
|
25
36
|
});
|
|
26
37
|
|
|
38
|
+
/**
|
|
39
|
+
* 采购主对象保存申请材料、流程状态和外部回执;不在此聚合直接维护库存占用记录。
|
|
40
|
+
* 所有写入都要求正金额和非空明细;部门字段提供范围依据,实际可见部门由当前角色授权决定。
|
|
41
|
+
* 金额和附件在数据库提交前由字段原语校验,用户不能通过修改前端界面绕过约束。
|
|
42
|
+
*/
|
|
27
43
|
export const PurchaseOrder = aggregate('PurchaseOrder', {
|
|
28
44
|
fields: {
|
|
45
|
+
/** 归属部门;创建输入省略时使用操作者部门,也是审批选人与部门子树范围的依据。 */
|
|
29
46
|
deptId: ref('Dept'),
|
|
47
|
+
/** 创建人由内核设置,用于本人范围与审批职责分离,客户端不提供该身份。 */
|
|
30
48
|
createdBy: ref('User'),
|
|
49
|
+
/** 可缺省的供应商电话;普通读侧按 phone 策略掩码,明文读取需要单独授权和审计。 */
|
|
31
50
|
supplierPhone: text(32).sensitive('phone').optional(),
|
|
51
|
+
/** 采购总额,以十进制金额字符串传输,最多两位小数;范例按元解释,不存整数分。 */
|
|
32
52
|
amount: money(),
|
|
53
|
+
/** 可为空的用途说明;创建可先存草稿,AI 预审会判断是否足以支撑审批。 */
|
|
54
|
+
reason: text(2000).optional(),
|
|
55
|
+
/** 是否增加专业会签;旧记录 null/缺省按 false,不改变已经启动的审批实例。 */
|
|
56
|
+
needsSpecialistReview: bool().optional(),
|
|
57
|
+
/** 提交快照的专业复核用户 UUID;旧记录可为空,启用复核时必须为 1–5 个不同且非创建人的有效名录用户。 */
|
|
58
|
+
reviewerIds: list(id()).optional(),
|
|
59
|
+
/** 申请明细快照:sku 为物料编码,qty 为整数件数;输入额外要求每行数量为正。 */
|
|
33
60
|
items: list({ sku: text(64), qty: int() }),
|
|
61
|
+
/** ERP 成功响应后回填的外部单号,尚未同步时为空;不作为采购单生命周期状态。 */
|
|
34
62
|
erpNo: text(64).optional(),
|
|
63
|
+
/** 最多十个私有文件 ID;每个上限 2 GiB,命令提交时才把 ready 上传与本单事务绑定。 */
|
|
64
|
+
attachments: files({ maxCount: 10, maxBytes: 2 * 1024 ** 3, accept: ['application/pdf', 'image/jpeg', 'image/png', 'text/plain'] }),
|
|
35
65
|
},
|
|
36
66
|
states: POStatus,
|
|
37
67
|
scope: scope.deptSubtree('deptId'),
|
|
@@ -41,16 +71,42 @@ export const PurchaseOrder = aggregate('PurchaseOrder', {
|
|
|
41
71
|
},
|
|
42
72
|
});
|
|
43
73
|
|
|
74
|
+
/** 提交快照供审批启动:orderId 关联主对象,金额和部门供声明过的路由条件使用。 */
|
|
44
75
|
export const OrderSubmitted = event('OrderSubmitted', { orderId: id(), amount: money(), deptId: id() });
|
|
76
|
+
/** 审批通过时固定需要占用/推送的物料明细,同一份事件驱动同事务建锁和异步 ERP 推送。 */
|
|
45
77
|
export const OrderApproved = event('OrderApproved', {
|
|
46
78
|
orderId: id(),
|
|
47
79
|
items: list({ sku: text(64), qty: int() }),
|
|
48
80
|
});
|
|
81
|
+
/** 取消记录原状态,使释放反应只处理此前已经批准、实际持锁的采购单。 */
|
|
49
82
|
export const OrderCancelled = event('OrderCancelled', { orderId: id(), previousStatus: text() });
|
|
83
|
+
/** 外部收货确认后发出,后台据此释放采购占用;不携带可直接写库的库存指令。 */
|
|
50
84
|
export const OrderReceived = event('OrderReceived', { orderId: id() });
|
|
51
85
|
|
|
86
|
+
/** 命令输入比持久化 int 原语更具体:至少一行且每行数量为正,避免零数量申请进入审批。 */
|
|
52
87
|
const itemsInput = z.array(z.object({ sku: z.string(), qty: z.number().int().positive() })).min(1);
|
|
53
88
|
|
|
89
|
+
/**
|
|
90
|
+
* 在设置和提交时核对专业复核名单,防止界面被绕过、名录退役或重复账号减少会签人数。
|
|
91
|
+
* disabled/范围/批准能力仍由审批运行时处理;此处只按当前命令声明的名录读依赖判断业务成员 active。
|
|
92
|
+
* 关闭专业复核必须传空名单;旧记录 null 等价 false/[]。最多五人使逐人查询有明确上限。
|
|
93
|
+
*/
|
|
94
|
+
async function validateReviewers(needsReview: boolean | null | undefined, ids: string[] | null | undefined, creator: string, members: ReadRepo<typeof ApprovalMember>) {
|
|
95
|
+
const selected = ids ?? [];
|
|
96
|
+
if (!needsReview) return selected.length ? fail('REVIEWERS_NOT_REQUIRED', '未启用专业复核时请清空复核人员') : undefined;
|
|
97
|
+
if (selected.length < 1 || selected.length > 5) return fail('REVIEWERS_REQUIRED', '专业复核需选择 1–5 位协作人');
|
|
98
|
+
if (new Set(selected).size !== selected.length) return fail('DUPLICATE_REVIEWERS', '同一人不能重复承担专业会签');
|
|
99
|
+
if (selected.includes(creator)) return fail('REVIEWER_IS_APPLICANT', '提单人不能担任本单专业复核人');
|
|
100
|
+
for (const userId of selected) {
|
|
101
|
+
if (!await members.findOne({ userId, status: 'active' })) return fail('REVIEWER_UNAVAILABLE', '所选专业复核人不在有效协作名录中');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 保存草稿;金额格式、字段长度和不变量由内核随后统一校验,handler 无额外副作用。
|
|
107
|
+
* deptId 可指定但仍须满足创建范围;attachments 为已完成上传 ID,省略时初始化为空集合。
|
|
108
|
+
* 此处不提交审批、不调用 ERP,便于用户先完成材料整理。
|
|
109
|
+
*/
|
|
54
110
|
export const create = command(PurchaseOrder, {
|
|
55
111
|
from: 'new',
|
|
56
112
|
to: 'draft',
|
|
@@ -58,18 +114,76 @@ export const create = command(PurchaseOrder, {
|
|
|
58
114
|
amount: z.string(),
|
|
59
115
|
items: itemsInput,
|
|
60
116
|
supplierPhone: z.string().optional(),
|
|
117
|
+
reason: z.string().max(2000).optional(),
|
|
118
|
+
needsSpecialistReview: z.boolean().optional(),
|
|
119
|
+
reviewerIds: z.array(z.string().uuid()).max(5).optional(),
|
|
61
120
|
deptId: z.string().uuid().optional(),
|
|
121
|
+
attachments: z.array(z.string().uuid()).max(10).optional(),
|
|
62
122
|
}),
|
|
63
|
-
|
|
123
|
+
// 草稿允许先保存未选完的复核需求;提交才要求完整名单,新记录统一 false/[],旧记录兼容 null。
|
|
124
|
+
handler: (o) => ({ ...o, needsSpecialistReview: o.needsSpecialistReview ?? false, reviewerIds: o.reviewerIds ?? [] }),
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* 在 draft 中调整本单专业复核需求和名单;需要 PurchaseOrder.setReviewers,不能直接修改待审批快照。
|
|
129
|
+
* 输入保存前核对 1–5 位不同且非提单人的 active 名录成员;关闭时用 false/[],失败整次回滚。
|
|
130
|
+
* 提交还会重新查询名录,以拒绝保存后退役的成员;名录不授予对单据的读取、批准能力或额度。
|
|
131
|
+
*/
|
|
132
|
+
export const setReviewers = command(PurchaseOrder, {
|
|
133
|
+
name: 'setReviewers', description: '设置采购单专业复核需求和人员', from: 'draft', to: null,
|
|
134
|
+
input: z.object({ id: z.string().uuid(), needsSpecialistReview: z.boolean(), reviewerIds: z.array(z.string().uuid()).max(5) }),
|
|
135
|
+
reads: { members: ApprovalMember },
|
|
136
|
+
handler: async (draft, input, { members }) => {
|
|
137
|
+
const invalid = await validateReviewers(input.needsSpecialistReview, input.reviewerIds, draft.createdBy, members);
|
|
138
|
+
return invalid ?? { needsSpecialistReview: input.needsSpecialistReview, reviewerIds: input.reviewerIds };
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// 退回后的说明只在草稿状态修改,保留提交时的版本校验和原始审计。
|
|
143
|
+
/** 只更新用途并保留 draft 状态;trim 后至少一个字符,修改结果与版本递增、审计一起提交。 */
|
|
144
|
+
export const explainPurpose = command(PurchaseOrder, {
|
|
145
|
+
from: 'draft', to: null,
|
|
146
|
+
description: '补充采购用途与必要性,保存后可以重新提交审核',
|
|
147
|
+
input: z.object({ id: z.string().uuid(), reason: z.string().trim().min(1).max(2000) }),
|
|
148
|
+
handler: (_draft, input) => ({ reason: input.reason }),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
/** 审批流程将材料不足的单据退回草稿;process 专用,浏览器不能绕过待办直接调用。 */
|
|
152
|
+
export const returnForChanges = command(PurchaseOrder, {
|
|
153
|
+
from: 'pending_approval', to: 'draft', invokedBy: 'process',
|
|
154
|
+
description: '审核材料不足时退回修改,重提后重新进行 AI 和人工审核',
|
|
155
|
+
handler: (draft) => draft,
|
|
64
156
|
});
|
|
65
157
|
|
|
158
|
+
// 附件变更与其他业务写入一样受状态、版本、范围和审计约束;审批后不能替换原始材料。
|
|
159
|
+
/** 替换完整附件 ID 集合,空数组表示移除全部;上传归属检查、绑定和解绑由同一命令事务落实。 */
|
|
160
|
+
export const setAttachments = command(PurchaseOrder, {
|
|
161
|
+
from: 'draft', to: null,
|
|
162
|
+
input: z.object({ id: z.string().uuid(), attachments: z.array(z.string().uuid()).max(10) }),
|
|
163
|
+
handler: (_draft, input) => ({ attachments: input.attachments }),
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* 提交前重查专业复核名单,避免草稿保存后退役的成员进入新流程;缺省旧字段按无需复核处理。
|
|
168
|
+
* 成功只改变状态并记录 OrderSubmitted,实例由 worker 消费后创建;HTTP 成功不表示审批完成。
|
|
169
|
+
*/
|
|
66
170
|
export const submit = command(PurchaseOrder, {
|
|
67
171
|
from: 'draft',
|
|
68
172
|
to: 'pending_approval',
|
|
69
173
|
emits: [OrderSubmitted],
|
|
70
|
-
|
|
174
|
+
reads: { members: ApprovalMember },
|
|
175
|
+
handler: async (o, _input, { members }) => {
|
|
176
|
+
if (o.items.length === 0) return fail('NO_ITEMS');
|
|
177
|
+
return await validateReviewers(o.needsSpecialistReview, o.reviewerIds, o.createdBy, members) ?? o;
|
|
178
|
+
},
|
|
71
179
|
});
|
|
72
180
|
|
|
181
|
+
/**
|
|
182
|
+
* 审批终结命令必须同时满足创建人与审批人分离、当前角色额度,以及声明的库存只读检查。
|
|
183
|
+
* stock 是 reads 绑定的受范围约束仓储;找不到 SKU 或登记数量不足时返回 STOCK_SHORT 并回滚。
|
|
184
|
+
* 该检查不扣减 available;真正占用由 OrderApproved 的同事务反应创建 InventoryLock。
|
|
185
|
+
* 范例展示资源配对,不实现多订单累计扣减、仓库出入库或价格核算。
|
|
186
|
+
*/
|
|
73
187
|
export const approve = command(PurchaseOrder, {
|
|
74
188
|
from: 'pending_approval',
|
|
75
189
|
to: 'approved',
|
|
@@ -87,6 +201,7 @@ export const approve = command(PurchaseOrder, {
|
|
|
87
201
|
},
|
|
88
202
|
});
|
|
89
203
|
|
|
204
|
+
/** 人工审批拒绝后进入终态;此时尚未批准建锁,因此不需要发出库存释放事件。 */
|
|
90
205
|
export const reject = command(PurchaseOrder, {
|
|
91
206
|
from: 'pending_approval',
|
|
92
207
|
to: 'rejected',
|
|
@@ -94,6 +209,10 @@ export const reject = command(PurchaseOrder, {
|
|
|
94
209
|
handler: (o) => o,
|
|
95
210
|
});
|
|
96
211
|
|
|
212
|
+
/**
|
|
213
|
+
* 草稿、待审批和已批准单据均可取消;显式事件映射使用提交前快照保留 previousStatus。
|
|
214
|
+
* 待审批取消会关闭对应审批,已批准取消会异步释放锁;两者都由订阅声明处理。
|
|
215
|
+
*/
|
|
97
216
|
export const cancel = command(PurchaseOrder, {
|
|
98
217
|
from: ['draft', 'pending_approval', 'approved'],
|
|
99
218
|
to: 'cancelled',
|
|
@@ -102,6 +221,7 @@ export const cancel = command(PurchaseOrder, {
|
|
|
102
221
|
});
|
|
103
222
|
|
|
104
223
|
// 仅连接器能回写 ERP 单号和收货结论,浏览器无法直接调用这两个命令。
|
|
224
|
+
/** 接受可能迟到的 ERP 回执,只补单号并递增版本;to:null 明确保留 approved/received/cancelled 原状态。 */
|
|
105
225
|
export const recordErpNo = command(PurchaseOrder, {
|
|
106
226
|
// ERP 推送可能早于取消发出、晚于取消返回;收货回调也可能先于推送应答到达。
|
|
107
227
|
// 这里只记录外部回执,保留当前生命周期,保证 outbox 后续的解锁事件能够继续投递。
|
|
@@ -112,6 +232,7 @@ export const recordErpNo = command(PurchaseOrder, {
|
|
|
112
232
|
handler: (_o, input) => ({ erpNo: input.erpNo }),
|
|
113
233
|
});
|
|
114
234
|
|
|
235
|
+
/** 只允许已批准单据确认收货;验签后的 external 调用触发事件,库存释放需等待 worker 消费。 */
|
|
115
236
|
export const markReceived = command(PurchaseOrder, {
|
|
116
237
|
from: 'approved',
|
|
117
238
|
to: 'received',
|
|
@@ -3,6 +3,11 @@ import { query } from '@yss123/cage-kernel';
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { PurchaseOrder } from './purchase-order.js';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* 按指定状态统计当前调用者可见采购单的部门分布,结果为 dept_id 与整数 n。
|
|
8
|
+
* reads 声明触发 PurchaseOrder.read 检查;safe.purchase_order 继续执行租户和数据范围过滤。
|
|
9
|
+
* :status 由内核绑定为参数,结果不代表跨权限的全公司统计;本声明没有业务写入副作用。
|
|
10
|
+
*/
|
|
6
11
|
export const poByStatus = query('poByStatus', {
|
|
7
12
|
reads: [PurchaseOrder],
|
|
8
13
|
input: z.object({ status: z.string() }),
|
|
@@ -4,6 +4,10 @@ import { reaction } from '@yss123/cage-kernel';
|
|
|
4
4
|
import { OrderApproved, OrderCancelled, OrderReceived } from '../modules/purchase/index.js';
|
|
5
5
|
import { acquireLock, releaseLock } from '../modules/inventory/index.js';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* 审批与建锁共用一笔数据库事务,任一命令失败则二者回滚;不会出现批准成功但没有锁的中间提交。
|
|
9
|
+
* acquires 仅供图规则配对,实际写入来自 acquireLock,映射只传当前批准事件的固定快照。
|
|
10
|
+
*/
|
|
7
11
|
export const lockOnApprove = reaction(OrderApproved, {
|
|
8
12
|
command: acquireLock,
|
|
9
13
|
tx: 'same',
|
|
@@ -11,12 +15,14 @@ export const lockOnApprove = reaction(OrderApproved, {
|
|
|
11
15
|
map: (e) => ({ id: e.orderId, orderId: e.orderId, items: e.items }),
|
|
12
16
|
});
|
|
13
17
|
|
|
18
|
+
/** 草稿/待审批取消从未建锁,返回 null 跳过;已批准取消进入 outbox,等待 worker 按单据顺序释放。 */
|
|
14
19
|
export const releaseOnCancel = reaction(OrderCancelled, {
|
|
15
20
|
command: releaseLock,
|
|
16
21
|
releases: 'inventory.lock',
|
|
17
22
|
map: (e) => (e.previousStatus === 'approved' ? { id: e.orderId } : null),
|
|
18
23
|
});
|
|
19
24
|
|
|
25
|
+
/** 收货事件保证来自已批准单据,因此按订单 ID 释放;默认异步失败由 worker 重试/死信处理。 */
|
|
20
26
|
export const releaseOnReceive = reaction(OrderReceived, {
|
|
21
27
|
command: releaseLock,
|
|
22
28
|
releases: 'inventory.lock',
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// 阅读规格引用真实命令与审批;人工收货通知与自动锁库存分别表达。
|
|
2
|
+
import { businessProcess } from '@yss123/cage-kernel';
|
|
3
|
+
import { PurchaseOrder, create, submit, approve, reject, cancel, markReceived, poApproval, returnForChanges, explainPurpose } from '../modules/purchase/index.js';
|
|
4
|
+
import { InventoryLock, acquireLock, releaseLock } from '../modules/inventory/index.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 面向人和 agent 的流程阅读规格,引用真实命令、审批和资源对象,供本体图展示及一致性检查。
|
|
8
|
+
* stages/transitions 说明人工、自动和等待关系,本声明本身不调度命令,也不新增权限或运行时副作用。
|
|
9
|
+
* 自动动作的真实事务和异步边界分别以 approval、reaction、connector 声明为准。
|
|
10
|
+
*/
|
|
11
|
+
export const purchaseLifecycle = businessProcess('purchase-lifecycle', {
|
|
12
|
+
title: '采购全流程', description: '从填写申请、提交审批到确认收货,查看库存占用与释放。',
|
|
13
|
+
area: { id: 'purchase', title: '采购管理', description: '采购申请、审批、收货与库存协作。' },
|
|
14
|
+
subject: PurchaseOrder, entry: 'create',
|
|
15
|
+
stages: {
|
|
16
|
+
create: { title: '填写采购申请', description: '录入采购金额和明细,保存采购草稿。', actor: '申请人', action: create },
|
|
17
|
+
submit: { title: '提交申请', description: '检查明细并提交采购审批。', actor: '申请人', action: submit },
|
|
18
|
+
approval: { title: '采购审批', description: 'AI 先核查材料;通过后部门经理审批,金额超过五万元时增加财务审批。疑难材料由本步骤转人工。', actor: 'AI、部门经理、财务', kind: 'decision', action: poApproval },
|
|
19
|
+
returned: { title: '退回修改', description: '材料不足退回草稿,保留本轮审核理由。', actor: '审批流程', action: returnForChanges },
|
|
20
|
+
revise: { title: '补充采购用途', description: '依据建议补充用途,再次提交后从 AI 预审开始。', actor: '申请人', action: explainPurpose },
|
|
21
|
+
approved: { title: '批准并锁定库存', description: '审批结论通过权限、额度和库存校验后,同事务锁定所需库存。', actor: '审批流程与系统', action: approve,
|
|
22
|
+
related: [{ object: InventoryLock, label: '同事务锁库存', via: acquireLock }] },
|
|
23
|
+
received: { title: '确认收货', description: '接收外部收货通知并更新采购单,异步释放库存锁。', actor: '外部系统与系统', kind: 'end', action: markReceived,
|
|
24
|
+
related: [{ object: InventoryLock, label: '收货后释放占用', via: releaseLock }] },
|
|
25
|
+
rejected: { title: '审批驳回', description: '驳回结论通过领域命令落到采购单,本范例此轮采购结束。', actor: '审批流程', kind: 'end', action: reject },
|
|
26
|
+
cancelled: { title: '取消采购', description: '申请人取消采购;若已批准则按实际映射释放库存占用。', actor: '申请人', kind: 'end', action: cancel,
|
|
27
|
+
related: [{ object: InventoryLock, label: '按原状态释放占用', via: releaseLock }] },
|
|
28
|
+
},
|
|
29
|
+
transitions: [
|
|
30
|
+
{ from: 'create', to: 'submit', mode: 'manual', label: '填写完成后提交' },
|
|
31
|
+
{ from: 'submit', to: 'approval', mode: 'automatic', label: '提交成功后启动审批' },
|
|
32
|
+
{ from: 'approval', to: 'approved', mode: 'automatic', label: '审批通过' },
|
|
33
|
+
{ from: 'approval', to: 'rejected', mode: 'automatic', label: '审批驳回' },
|
|
34
|
+
{ from: 'approval', to: 'returned', mode: 'automatic', label: '材料不足' },
|
|
35
|
+
{ from: 'returned', to: 'revise', mode: 'manual', label: '补充材料' },
|
|
36
|
+
{ from: 'revise', to: 'submit', mode: 'manual', label: '重新提交' },
|
|
37
|
+
{ from: 'approved', to: 'received', mode: 'wait', label: '等待外部收货通知' },
|
|
38
|
+
{ from: 'create', to: 'cancelled', mode: 'manual', label: '取消草稿', branch: true },
|
|
39
|
+
{ from: 'submit', to: 'cancelled', mode: 'manual', label: '取消审批中的采购', branch: true },
|
|
40
|
+
{ from: 'approved', to: 'cancelled', mode: 'manual', label: '取消已批准采购', branch: true },
|
|
41
|
+
],
|
|
42
|
+
});
|
|
@@ -38,6 +38,12 @@ CAGE_ADMIN_DATABASE_URL=postgresql://postgres:REPLACE_WITH_ADMIN_PASSWORD@127.0.
|
|
|
38
38
|
# 自动生成 32 字节随机值;已有值保留。同一应用的多个实例使用同一值。
|
|
39
39
|
# CAGE_COOKIE_SECRET=
|
|
40
40
|
|
|
41
|
+
# 生产 NODE_ENV=production 时必须提供合格随机密钥;固定开发值会被拒绝。
|
|
42
|
+
# 组织在审查执行 migrate 后,显式 cage bootstrap --credentials-file <新的受限文件>。
|
|
43
|
+
# API 日常启动不会初始化组织或向日志输出管理员密码。
|
|
44
|
+
# 可信代理在 apps/api/src/main.ts 显式配置地址/网段;默认 trustProxy: false。
|
|
45
|
+
# /healthz 表示存活,/readyz 检查数据库和授权监听;API 与 worker 使用同版本部署。
|
|
46
|
+
|
|
41
47
|
# [可选,开发默认 fake] 第三方连接器阶段:fake 使用模拟实现;test / prod 使用真实适配器。
|
|
42
48
|
# 本项只影响第三方外部服务,fake 阶段仍连接真实 PostgreSQL。
|
|
43
49
|
# test / prod 需另行配置业务连接器要求的地址与密钥,不是修改此值就完成对接。
|
|
@@ -50,6 +56,10 @@ CAGE_WEB_PORT=15173
|
|
|
50
56
|
# [可选,默认 3000] API 服务端口;本地 Web 代理自动转发到这个端口。
|
|
51
57
|
PORT=3000
|
|
52
58
|
|
|
59
|
+
# 私有上传目录,不能通过 Nginx/静态服务公开;生产挂载持久卷并与数据库配套备份。
|
|
60
|
+
# 默认是项目根目录 .cage-files;改变目录前必须迁移已有文件。
|
|
61
|
+
CAGE_FILES_DIR=.cage-files
|
|
62
|
+
|
|
53
63
|
# [可选,范例默认 0.0.0.0] API 监听地址;这里使用 127.0.0.1,仅允许本机访问。
|
|
54
64
|
# 需要容器内或局域网访问时改为 0.0.0.0,并按部署环境配置网络访问权限。
|
|
55
65
|
HOST=127.0.0.1
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
本节位于托管区之外,cage sync 会保留。下面的托管区提供框架工作方法。
|
|
12
12
|
|
|
13
|
-
<!-- cage:begin v0.
|
|
13
|
+
<!-- cage:begin v0.3.1 -->
|
|
14
14
|
## Cage 业务开发约定(框架托管)
|
|
15
15
|
|
|
16
16
|
### 先读,再按需求改业务
|
|
@@ -19,6 +19,33 @@
|
|
|
19
19
|
|
|
20
20
|
先读项目说明指定的学习资料,默认入口为 `docs/ai/README.md`。第一次读 `architecture.md`、`project-structure.md` 和 `primitives.md`;具体任务读 `recipes.md`,采购全链路读 `purchase-example.md`,错误查 `docs/errors/README.md` 和 `docs/ai/troubleshooting.md`。资料相对该学习目录,项目说明可指定源码仓库中的规范资料位置。
|
|
21
21
|
|
|
22
|
+
### 详细中文注释(每次开发必须遵守)
|
|
23
|
+
|
|
24
|
+
所有新增和维护的手写源码都必须写详细中文注释,先读学习目录中的 `commenting.md`(独立项目为 `docs/ai/commenting.md`)。注释是交付内容,不能以“代码自解释”或“保持简洁”为由省略。
|
|
25
|
+
|
|
26
|
+
- 每个文件开头说明模块职责、谁调用它、主要调用链和责任边界;纯导出入口也说明如何组合模块。
|
|
27
|
+
- 导出函数、类、组件、hooks、接口和业务声明使用 JSDoc,写清用途、参数含义、返回结果、主要步骤、前置条件、失败行为和副作用;复杂内部函数同样说明。参数类型已表达的语法无需重复,业务单位、空值、默认行为与约束必须解释。
|
|
28
|
+
- 领域代码说明字段和状态的业务意义、命令调用身份与权限/范围、reads 依赖、事件用途、事务与异步边界、幂等/重试及资源释放;只写实际声明和实现已有的保证。
|
|
29
|
+
- 页面说明 URL/查询参数、数据来源、临时状态、加载/空态/失败/无权限、提交后的刷新、会话与订阅清理;复杂分支、计算、顺序、并发和缓存规则在附近解释原因与过程。
|
|
30
|
+
- 测试说明场景、前置条件、动作、断言和所防止的回归;脚本说明输入、读写路径、执行顺序、外部副作用与退出条件。注释不含密钥、凭据或个人数据。
|
|
31
|
+
- 注释同时回答“做什么、为什么、如何完成、有哪些边界”,不能只有一句标题,也不能机械逐行翻译、凑字数或批量粘贴空泛模板。代码变更时同步更新注释,交付前逐文件核对。
|
|
32
|
+
- 生成契约的注释由生成器维护,不手改生成物;已执行/已发布迁移不能改写。仅补注释时不得顺便重构或改变逻辑、接口、配置值和运行文案。
|
|
33
|
+
|
|
34
|
+
### 原生 AI 能力入口
|
|
35
|
+
|
|
36
|
+
遇到以下需求,先读 `docs/ai/intelligence.md`,用 `pnpm exec cage capabilities "关键词" --format json` 核对当前安装版本的公开 API,再检查本项目 domain 导出和页面接入。关键词可直接使用下表需求名称;未命中时缩短关键词或查公开符号,不能据此断言能力不存在。
|
|
37
|
+
|
|
38
|
+
| 需求 | 框架入口与应用职责 |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| AI审批 / 智能审批 | 现有 `step` 使用 `kind: 'ai'`,支持 pass 通过、return 退回修改、manual 转人工;应用声明策略、结论命令、自动执行角色及接管人 |
|
|
41
|
+
| 业务助理 / 本体助理 | 导出 `ai({ models, assistant })`;框架提供执行循环、按领域声明生成的工具、会话、偏好记忆和 HTTP;应用配置授权及界面 |
|
|
42
|
+
| 页面上下文 / 随页助理 | `useAssistant(client.ai, page)` 配合 `useAiPageContext` / `AiPageContext`;应用上报页面、对象、选中项和草稿,服务端重读并校验业务事实 |
|
|
43
|
+
| 模型管理 / Responses | `managedModel` 接入 Admin 动态配置,支持 Chat Completions / Responses;应用配置部署加密密钥并显式授权管理者 |
|
|
44
|
+
| 性格 / 流式输出 | Admin 管理性格,SDK 提供选择、增量文字与执行进度;应用实现悬浮窗、Markdown 和确认卡片 |
|
|
45
|
+
| 上下文预算 | `ai({ context: ... })` 的配置形状见 `AiContextOptions`;框架按预算选择完整工具或发现模式,历史和本体按需读取 |
|
|
46
|
+
|
|
47
|
+
前端只使用客户端、协议与契约;后端循环、通用工具和记忆使用框架实现。页面快照和性格不授予权限。分别核对**框架支持**(公开导出)、**项目已启用**(domain 导出、迁移、模型、权限、worker、SDK)和**实际验证通过**(真实角色与模型联调);空白模板的参考代码不表示已启用。具体接入顺序和验收步骤见该指南,不必将整份指南塞入每次任务上下文。
|
|
48
|
+
|
|
22
49
|
### 业务代码放在哪里
|
|
23
50
|
|
|
24
51
|
| 位置 | 职责 |
|
|
@@ -28,7 +55,7 @@
|
|
|
28
55
|
| `packages/domain/src/index.ts` | 统一导出全部业务及组织模型;没导出的声明不会注册 |
|
|
29
56
|
| `packages/contracts/src/aggregates/<聚合>`、`queries` | 生成协议;根 index.ts 提供 @app/contracts 公共入口,只用 cage gen 更新 |
|
|
30
57
|
| `apps/api/src` | API/worker 薄启动入口,普通业务不手写 HTTP 路由 |
|
|
31
|
-
| `apps/web/src/app` |
|
|
58
|
+
| `apps/web/src/app` | 会话、URL 路由、布局、模块组合;main.tsx 只挂载和装配 Provider |
|
|
32
59
|
| `apps/web/src/modules/<业务>` | 页面、表单、专用 hooks/API/样式;从模块 index.ts 暴露页面 |
|
|
33
60
|
| `apps/web/src/shared` | 跨模块复用且不绑定业务的 UI、hooks、纯辅助函数 |
|
|
34
61
|
| `db/migrations` | 审查过的结构迁移,作用于已配置的数据库 |
|
|
@@ -40,11 +67,11 @@
|
|
|
40
67
|
### 实现一项需求的顺序
|
|
41
68
|
|
|
42
69
|
1. 先运行 `pnpm exec cage context "需求关键词"`;按需 `graph search` 查候选、`graph inspect` 查完整节点、`graph path` 看关系路径。确认中文匹配入口后按源码位置阅读实现;候选和子图不是全部依赖,具体条件不能凭连线推断。完整用法见 `docs/ai/ontology-context.md`。从用户需求确定字段、状态/动作、角色/范围、约束与后续动作;能由业务声明表达的不改框架。
|
|
43
|
-
2.
|
|
70
|
+
2. 已有业务含义变化时,修改前用 `pnpm exec cage snapshot save before-change` 保存不可覆盖的命名基线;或使用真实 Git 提交/独立本体图文件。
|
|
44
71
|
3. 先声明 aggregate/states/command/constraints/event,再写 handler、reaction/query/approval/connector,最后接业务页面。声明使用模块顶层 `export const`,从 domain 入口导出,跨文件导出名保持唯一。
|
|
45
|
-
4. 运行 `pnpm exec cage check` 和 `pnpm gen`,审查 contracts 和迁移草稿。按需运行 `pnpm exec cage impact --
|
|
46
|
-
5. 页面使用生成方法并处理 code/domainCode
|
|
47
|
-
6.
|
|
72
|
+
4. 运行 `pnpm exec cage check` 和 `pnpm gen`,审查 contracts 和迁移草稿。按需运行 `pnpm exec cage impact --snapshot before-change`,补中文图谱名。
|
|
73
|
+
5. 页面使用生成方法并处理 code/domainCode;列表、详情等多页面注册到 React Router,Link/NavLink 导航,筛选/分页进入 URL。组件状态用于弹窗和表单等临时交互。新增能力由管理员授权。数据库结构变化审查后显式 `pnpm migrate`,dev 不代办迁移。
|
|
74
|
+
6. 按 `commenting.md` 逐文件检查详细中文注释与实现一致,再按改动运行必要验证;交付时说明体验步骤、授权配置、迁移、注释覆盖,以及通过/跳过/未执行项。
|
|
48
75
|
|
|
49
76
|
### 必守边界
|
|
50
77
|
|
|
@@ -55,17 +82,25 @@
|
|
|
55
82
|
- 自定义查询声明 reads,二选一使用 sql/build,只读 `safe.*`;值参数化。不得拼接 SQL、查询基表绕过范围或硬编码密钥。
|
|
56
83
|
- scope 描述范围字段,角色数据决定实际范围;`scope.none()` 不代表所有人可访问。`can/useCan` 只控制按钮,后端负责授权。
|
|
57
84
|
- 前端从 `@app/contracts` 导入生成 API/类型,按需使用 `@yss123/cage-client`;不导入 domain、内核或数据库包。
|
|
85
|
+
- 多页面业务必须有独立 URL,不用 useState/tab 模拟整页导航;详情从 URL 取 ID 并独立加载。前端路由集中在 app,页面从模块公开入口接入 Outlet。登录后保留原路径/query/hash,401 回登录,403 展示权限提示;/admin/ 使用普通链接进入独立系统管理。前端路由不替代后端授权。实现、SPA 部署回退和浏览器配方见 docs/ai/routing.md。
|
|
58
86
|
- 跨聚合写入通过 reaction 调用命令。`tx: 'same'` 共同提交/回滚,默认 outbox 异步执行。资源 acquires/releases 是图规则标签,实际占用/释放仍由命令完成;离开持有状态要检查每条释放路径。
|
|
59
|
-
-
|
|
87
|
+
- 批量调用同一命令使用 reactionEach,声明 maxItems、唯一排序字段 orderBy、items 和 map;稳定键排序后串行执行。步骤依赖用 order,同事件同事务分组不得混用有序/无序或重复顺序。保持同事务回滚边界,见 docs/ai/primitives.md。
|
|
88
|
+
- 审批通过 approval + route 配置,结论是 process 命令;选中审批人不等于已具备能力、范围和额度。parallel(title, ...branch(...)) 声明结构化 AND:分支同时开始,内部顺序独立,全部活动分支完成后汇合;when 支持嵌套并仍按提交快照求值,声明有深度/数量边界,不支持任意跳转。currentSteps 表示当前活动节点集合,兼容字段 currentStep 只是最小活动索引,不能据此隐藏其他分支。人工节点 assignment: 'candidate' 开放候选领取/释放,approver.field 从 routable 字段选人;actions 开放转办、委派归还和前后/并行必签。任务操作与决定携带 revision,waiting 任务只能查看。approvalOperations() 为框架通用时效运行时:step.sla 配置自然分钟节点总时限,route.reminders 配置申请人催办;迁移并运行 worker 后提供持久站内提醒、已读与 Admin 通用页面,不自动批准或授予权限。政策、SDK 和边界见 docs/ai/approvals.md。第三方 IO 通过连接器,回调验签后调用 external 命令。
|
|
60
89
|
- job 的读取与调用必须列入 reads/calls。业务导入/导出放在需要的业务页面调用通用任务接口,202 只代表任务已接受;worker 必须运行。
|
|
61
90
|
- 已部署事件只做兼容扩展;新增字段设为 optional,不兼容含义用新事件。已执行/已发布迁移不能改写,结构更新新增迁移。
|
|
62
91
|
- 不手改生成物,不关闭门禁掩盖错误,不因方便自动授予生产角色新能力。unsafe 必须写明 reason/owner,不能替代普通业务声明。
|
|
63
|
-
-
|
|
92
|
+
- 按前述详细中文注释规范完成文件、API、业务声明和关键流程说明;避免无业务价值的防御分支和静默兜底。维护脚本用 TypeScript,不新增 .mjs。
|
|
64
93
|
|
|
65
94
|
### 最小命令形状
|
|
66
95
|
|
|
67
96
|
```ts
|
|
68
97
|
// 片段:Order 为已导出的聚合,OrderSubmitted 为事件,业务校验按需求添加。
|
|
98
|
+
/**
|
|
99
|
+
* 将草稿订单提交审批:只有 draft 可进入 pending_approval。
|
|
100
|
+
* 入口使用 Order.submit 能力,真实授权、范围、状态和版本由内核检查;声明本身不自动授予权限。
|
|
101
|
+
* handler 返回草稿供后续校验和持久化,OrderSubmitted 随命令事务登记,后续由已配置消费者处理。
|
|
102
|
+
* 失败不会提交这次业务变更;事件已登记也不代表后续审批已经完成。
|
|
103
|
+
*/
|
|
69
104
|
export const submitOrder = command(Order, {
|
|
70
105
|
name: 'submit',
|
|
71
106
|
from: 'draft',
|
|
@@ -79,17 +114,22 @@ export const submitOrder = command(Order, {
|
|
|
79
114
|
|
|
80
115
|
### 启动、验证与排错
|
|
81
116
|
|
|
82
|
-
在项目根目录执行:首次 `pnpm install`,复制并编辑 .env.example,仅提供已有库管理员连接后 `pnpm exec cage init`;再 `pnpm build:app`、`pnpm gen`,审查后 `pnpm migrate
|
|
117
|
+
在项目根目录执行:首次 `pnpm install`,复制并编辑 .env.example,仅提供已有库管理员连接后 `pnpm exec cage init`;再 `pnpm build:app`、`pnpm gen`,审查后 `pnpm migrate`;用 `pnpm exec cage bootstrap --credentials-file .cage/admin-credentials.json` 显式初始化组织,最后 `pnpm dev`。已有配置不能覆盖,凭据文件必须是新受限文件且父目录存在。
|
|
83
118
|
|
|
84
119
|
init 只准备账号/schema/授权并填写三个连接,不创建数据库;APP/READ/MIGRATE 指向同一个库。已有集群账号复用原密码,日常启动不用管理员。普通项目不新增 Docker 生命周期命令。
|
|
85
120
|
|
|
121
|
+
API 日常启动不初始化组织、不输出管理员密码;生产缺少合格 Cookie 密钥会拒绝启动。bootstrap 不自动授予业务能力。`/healthz` 只表示存活,`/readyz` 检查必要依赖。首阶段 API 与 worker 同版本部署,查看实际注册指纹和消费者心跳。
|
|
122
|
+
|
|
86
123
|
- `pnpm exec cage graph`:浏览器图谱,默认端口 15418,以终端为准。
|
|
87
124
|
- `pnpm exec cage context command:对象.命令 --format json --out .cage/context.json`:按完整 key 取精简上下文;默认 Markdown,可用 --depth/--limit 调整范围。CLI 每次重新抽取;Web“复制 AI 上下文”使用当前页面快照,改代码后先刷新图谱。
|
|
88
|
-
- `graph inspect/path` 有歧义时复制候选完整 key;path 默认沿箭头,--direction both
|
|
125
|
+
- `graph inspect/path` 有歧义时复制候选完整 key;path 默认沿箭头,--direction both 的逆向遍历不表示执行方向。报告中的测试/前端文件是候选,须核对;context 与图谱查询不覆盖当前图或命名快照。
|
|
126
|
+
- `pnpm exec cage capabilities 关键词 --format json`:查当前安装版本公开签名;`cage doctor`:区分注册、生成、构建、迁移、授权与实际进程证据,unknown 不能当作通过。`cage timeline/explain` 关联实际异步证据与解释授权,参数和权限见 docs/ai/diagnostics.md。
|
|
127
|
+
- 生成方法支持 signal/timeoutMs/idempotencyKey 请求选项。底层 CageResult 与 mutation 行为有区别:useCageCommand 失败抛 CageCommandError,成功才返回业务数据。订阅 client.subscribe 在退出、401、切换账号时取消查询并清除应用缓存。
|
|
89
128
|
- `pnpm exec cage gen --check`:生成一致性;`pnpm exec cage sync --check`:本托管区一致性。
|
|
90
129
|
- `pnpm exec cage test --only project`:业务测试;`pnpm verify`:类型、依赖、lint、图规则、生成、托管区、预算和测试。
|
|
91
130
|
- `pnpm exec cage verify --skip-tests` 表示不完整门禁;派生测试跳过不能当作通过。测试连接只用独立测试集群。
|
|
92
131
|
- 重要业务改动验证成功路径及有风险的反例;文档或可逆的小改动不反复跑全量数据库测试。
|
|
132
|
+
- 修改页面/导航后实际验收深链接、刷新、前进后退、登录回跳、无权限和 404;生产再查 SPA 回退。check/verify 不自动完成浏览器验收,未执行要明确报告。见 docs/ai/routing.md。
|
|
93
133
|
- CLI 报错先看 code/at/reason/fix,再查错误码册;HTTP 错误查 runtime.md。异步失败先看 worker、同步记录和死信,修复后重放,不能直接 SQL 改状态。
|
|
94
134
|
|
|
95
135
|
框架托管区由 cage sync 更新;项目独有的业务规则写在标记之外,避免升级覆盖。
|
|
@@ -12,10 +12,13 @@
|
|
|
12
12
|
2. 复制 `.env.example` 为 `.env`。按其中注释,仅填写 `CAGE_ADMIN_DATABASE_URL`,指向已有数据库。密码含特殊字符时需 URL 编码。
|
|
13
13
|
3. 执行 `pnpm exec cage init`。自动创建运行、只读、迁移账号和随机密码,填写 `.env` 并移除管理员连接;已有配置不会重置密码。
|
|
14
14
|
4. 执行 `pnpm build:app`、`pnpm gen`。审查 `db/migrations` 后执行 `pnpm migrate`,创建本项目需要的组织与系统表。
|
|
15
|
-
5. 执行 `pnpm
|
|
15
|
+
5. 执行 `pnpm exec cage bootstrap --credentials-file .cage/admin-credentials.json` 显式初始化组织;凭证只写到新的受限文件,交付后移除。业务能力需管理员配置。
|
|
16
|
+
6. 执行 `pnpm dev`,在浏览器打开终端打印的 Web 地址。日常 API 启动不初始化组织或输出密码。
|
|
16
17
|
|
|
17
18
|
登录后可从“系统管理”配置用户、部门、角色与权限,再按业务需求添加模块。页面不会显示虚构业务数据。`.env` 中三个账号连接同一个数据库;日常运行不需要管理员账号。首次迁移应在为本项目准备的库中执行,接管历史业务表需要额外映射和迁移审查。
|
|
18
19
|
|
|
20
|
+
前端已配置 React Router:`/login` 登录、`/workspace` 工作台、`/directory/users` 成员列表、`/directory/users/:id` 成员详情,以及应用 404。成员页面只读取已有组织模型,需要 User.read,未增加演示业务或数据。详情可直达、刷新,登录后返回原地址。新增业务与生产 SPA 回退按[路由和浏览器验收指南](docs/ai/routing.md)执行;反向代理示例见 [deploy/nginx.conf](deploy/nginx.conf)。
|
|
21
|
+
|
|
19
22
|
## 添加第一个业务模块
|
|
20
23
|
|
|
21
24
|
先读[工程目录与代码组织](docs/ai/project-structure.md)。在 `packages/domain/src/modules/<业务>` 新建声明,通过模块 index.ts 从领域总入口导出;运行 `pnpm exec cage check`、`pnpm gen`,审查生成契约和迁移。在 `apps/web/src/modules/<业务>` 使用 `@app/contracts` 实现页面和表单,通过模块公开入口接入 `app` 导航;共享 UI/工具放 `shared`。最后按需迁移,并由管理员分配新增能力。完整的 Note 对象示例见 [原语与最小业务](docs/ai/primitives.md)。
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// 业务声明决定接口。这个入口只装配框架,不需要另建连接池或手写 CRUD 路由。
|
|
2
2
|
// 数据库连接由框架读取项目 .env;生产环境的 WEB_DIR 指向前端构建目录。
|
|
3
|
+
// 初始化组织和数据库迁移必须在独立受控步骤完成,启动服务不会自动创建管理员或授予业务能力。
|
|
3
4
|
import { createServer } from '@yss123/cage-http';
|
|
4
5
|
import * as domain from '@app/domain';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
// 默认不接受转发头;部署在代理后时,仅在这里填写实际可信代理的地址或网段。
|
|
8
|
+
const server = createServer({ domain, webDir: process.env.WEB_DIR, title: 'Cage 业务工作台', trustProxy: false });
|
|
9
|
+
// 等待安全插件、生成路由和扩展就绪后才监听;异步事件和任务另由 worker 入口执行。
|
|
7
10
|
await server.listen();
|
|
8
11
|
|
|
9
12
|
// 退出时释放连接池及数据库通知连接,便于部署时平滑替换进程。
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// worker 处理框架异步任务;增加事件反应、审批或数据导入导出后也沿用此入口。
|
|
2
2
|
// 空白项目没有第三方演示连接器,真实外部服务按业务需求声明和配置。
|
|
3
|
+
// API 与 worker 必须加载同版本 domain;框架统一负责消费者发现、轮询、租约、重试及定时调度。
|
|
3
4
|
import { startWorker } from '@yss123/cage-http/worker';
|
|
4
5
|
import * as domain from '@app/domain';
|
|
5
6
|
|
|
7
|
+
// 不在入口重复创建连接池或自行扫表;停止句柄等待在途工作并释放框架资源。
|
|
6
8
|
const worker = await startWorker({ domain });
|
|
7
9
|
process.once('SIGINT', () => void worker.stop());
|
|
8
10
|
process.once('SIGTERM', () => void worker.stop());
|
|
@@ -10,13 +10,17 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@app/contracts": "workspace:*",
|
|
12
12
|
"@tanstack/react-query": "^5.87.1",
|
|
13
|
+
"@yss123/cage-client": "0.3.1",
|
|
13
14
|
"react": "^19.1.1",
|
|
14
|
-
"react-dom": "^19.1.1"
|
|
15
|
+
"react-dom": "^19.1.1",
|
|
16
|
+
"react-markdown": "^10.1.0",
|
|
17
|
+
"react-router-dom": "^7.18.5",
|
|
18
|
+
"remark-gfm": "^4.0.1"
|
|
15
19
|
},
|
|
16
20
|
"devDependencies": {
|
|
17
21
|
"@types/react": "^19.1.13",
|
|
18
22
|
"@types/react-dom": "^19.1.9",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
23
|
+
"typescript": "~5.9.3",
|
|
24
|
+
"vite": "^7.1.4"
|
|
21
25
|
}
|
|
22
26
|
}
|