agentic-dev 0.2.10 → 0.2.12
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 +50 -29
- package/bin/agentic-dev.mjs +656 -124
- package/lib/scaffold.mjs +109 -6
- package/package.json +8 -22
- package/.agent/prd.json +0 -29
- package/.agent/progress.txt +0 -1
- package/.agent/prompt.md +0 -21
- package/.agent/ralph-loop-state.json +0 -13
- package/.agent/ralph-supervisor-state.json +0 -12
- package/.agent/ralph-supervisor.sh +0 -238
- package/.agent/ralph.sh +0 -305
- package/.agent/runs/README.md +0 -7
- package/.agent/sdd-build-ast-audit.json +0 -13
- package/.claude/CLAUDE.md +0 -44
- package/.claude/agentic-dev.json +0 -3
- package/.claude/agents/ai-dev.md +0 -27
- package/.claude/agents/backend-dev.md +0 -26
- package/.claude/agents/db-dev.md +0 -26
- package/.claude/agents/devops.md +0 -27
- package/.claude/agents/frontend-dev.md +0 -25
- package/.claude/agents/github-ops.md +0 -25
- package/.claude/agents/test-dev.md +0 -26
- package/.claude/agents/uiux-designer.md +0 -25
- package/.claude/settings.json +0 -49
- package/.claude/settings.local.json +0 -8
- package/.claude/skills/sdd/SKILL.md +0 -189
- package/.claude/skills/sdd/agents/openai.yaml +0 -4
- package/.claude/skills/sdd/references/section-map.md +0 -67
- package/.claude/workspace-config.json +0 -3
- package/.codex/agentic-dev.json +0 -3
- package/.codex/agents/README.md +0 -22
- package/.codex/agents/api.toml +0 -11
- package/.codex/agents/architecture.toml +0 -11
- package/.codex/agents/ci.toml +0 -11
- package/.codex/agents/gitops.toml +0 -11
- package/.codex/agents/orchestrator.toml +0 -11
- package/.codex/agents/quality.toml +0 -11
- package/.codex/agents/runtime.toml +0 -11
- package/.codex/agents/security.toml +0 -11
- package/.codex/agents/specs.toml +0 -11
- package/.codex/agents/ui.toml +0 -11
- package/.codex/config.toml +0 -46
- package/.codex/skills/SKILL.md +0 -13
- package/.codex/skills/sdd/SKILL.md +0 -189
- package/.codex/skills/sdd/agents/openai.yaml +0 -4
- package/.codex/skills/sdd/references/section-map.md +0 -67
- package/.dockerignore +0 -8
- package/.env.example +0 -50
- package/.gitignore +0 -16
- package/AGENTS.md +0 -86
- package/SDD_SKILL.md +0 -589
- package/client/admin/.dockerignore +0 -3
- package/client/admin/.env.example +0 -1
- package/client/admin/Dockerfile +0 -16
- package/client/admin/Dockerfile.dev +0 -18
- package/client/admin/README.md +0 -20
- package/client/admin/index.html +0 -12
- package/client/admin/package.json +0 -41
- package/client/admin/postcss.config.js +0 -6
- package/client/admin/scripts/ui-parity-admin-adapter.mjs +0 -65
- package/client/admin/src/api/alerts.ts +0 -33
- package/client/admin/src/api/client.ts +0 -71
- package/client/admin/src/api/orders.ts +0 -33
- package/client/admin/src/api/support.ts +0 -11
- package/client/admin/src/app/App.tsx +0 -23
- package/client/admin/src/auth/AuthProvider.tsx +0 -122
- package/client/admin/src/auth/ProtectedRoute.tsx +0 -22
- package/client/admin/src/auth/auth-client.ts +0 -38
- package/client/admin/src/auth/types.ts +0 -18
- package/client/admin/src/components/AdminNotificationsDrawer.tsx +0 -162
- package/client/admin/src/components/AdminShell.tsx +0 -76
- package/client/admin/src/components/ui/button.tsx +0 -34
- package/client/admin/src/components/ui/input.tsx +0 -21
- package/client/admin/src/lib/cn.ts +0 -6
- package/client/admin/src/lib/specRouteCatalog.json +0 -30
- package/client/admin/src/lib/specScreens.json +0 -22
- package/client/admin/src/main.tsx +0 -17
- package/client/admin/src/pages/AdminDashboardPage.tsx +0 -171
- package/client/admin/src/pages/AdminLoginPage.tsx +0 -75
- package/client/admin/src/pages/AdminQueuePage.tsx +0 -107
- package/client/admin/src/pages/AdminSupportPage.tsx +0 -61
- package/client/admin/src/styles/globals.css +0 -17
- package/client/admin/src/theme-vars.ts +0 -18
- package/client/admin/src/theme.ts +0 -25
- package/client/admin/src/vite-env.d.ts +0 -1
- package/client/admin/tailwind.config.js +0 -8
- package/client/admin/tsconfig.json +0 -25
- package/client/admin/vite.config.ts +0 -12
- package/client/landing/.dockerignore +0 -3
- package/client/landing/.env.example +0 -1
- package/client/landing/Dockerfile +0 -16
- package/client/landing/Dockerfile.dev +0 -18
- package/client/landing/README.md +0 -18
- package/client/landing/index.html +0 -12
- package/client/landing/package.json +0 -41
- package/client/landing/postcss.config.js +0 -6
- package/client/landing/scripts/ui-parity-landing-adapter.mjs +0 -65
- package/client/landing/src/App.tsx +0 -21
- package/client/landing/src/api/catalog.ts +0 -30
- package/client/landing/src/api/client.ts +0 -30
- package/client/landing/src/auth/AuthProvider.tsx +0 -122
- package/client/landing/src/auth/ProtectedRoute.tsx +0 -22
- package/client/landing/src/auth/auth-client.ts +0 -38
- package/client/landing/src/auth/types.ts +0 -18
- package/client/landing/src/components/LandingShell.tsx +0 -34
- package/client/landing/src/lib/specRouteCatalog.json +0 -23
- package/client/landing/src/lib/specScreens.json +0 -17
- package/client/landing/src/main.tsx +0 -17
- package/client/landing/src/pages/LandingHomePage.tsx +0 -215
- package/client/landing/src/pages/LandingLoginPage.tsx +0 -90
- package/client/landing/src/pages/LandingWorkspacePage.tsx +0 -126
- package/client/landing/src/styles/globals.css +0 -17
- package/client/landing/src/theme-vars.ts +0 -16
- package/client/landing/src/theme.ts +0 -21
- package/client/landing/src/vite-env.d.ts +0 -1
- package/client/landing/tailwind.config.js +0 -8
- package/client/landing/tsconfig.json +0 -25
- package/client/landing/vite.config.ts +0 -12
- package/client/mobile/.dockerignore +0 -2
- package/client/mobile/.env.example +0 -1
- package/client/mobile/Dockerfile +0 -16
- package/client/mobile/Dockerfile.dev +0 -18
- package/client/mobile/README.md +0 -19
- package/client/mobile/index.html +0 -12
- package/client/mobile/package.json +0 -42
- package/client/mobile/postcss.config.js +0 -6
- package/client/mobile/scripts/ui-parity-mobile-adapter.mjs +0 -67
- package/client/mobile/src/App.tsx +0 -1
- package/client/mobile/src/api/client.ts +0 -62
- package/client/mobile/src/api/fulfillment.ts +0 -55
- package/client/mobile/src/api/shipping.ts +0 -56
- package/client/mobile/src/app/App.tsx +0 -23
- package/client/mobile/src/auth/AuthProvider.tsx +0 -122
- package/client/mobile/src/auth/ProtectedRoute.tsx +0 -27
- package/client/mobile/src/auth/auth-client.ts +0 -38
- package/client/mobile/src/auth/types.ts +0 -18
- package/client/mobile/src/components/InShell.tsx +0 -74
- package/client/mobile/src/components/ui/button.tsx +0 -35
- package/client/mobile/src/components/ui/card.tsx +0 -15
- package/client/mobile/src/components/ui/input.tsx +0 -21
- package/client/mobile/src/lib/cn.ts +0 -6
- package/client/mobile/src/lib/specRouteCatalog.json +0 -26
- package/client/mobile/src/lib/specScreens.json +0 -22
- package/client/mobile/src/lib/useSpeechRecognitionInput.ts +0 -271
- package/client/mobile/src/main.tsx +0 -17
- package/client/mobile/src/pages/DashboardPage.tsx +0 -172
- package/client/mobile/src/pages/FulfillmentPage.tsx +0 -138
- package/client/mobile/src/pages/LoginPage.tsx +0 -74
- package/client/mobile/src/pages/ShippingPage.tsx +0 -338
- package/client/mobile/src/styles/globals.css +0 -23
- package/client/mobile/src/theme-vars.ts +0 -16
- package/client/mobile/src/theme.ts +0 -21
- package/client/mobile/src/vite-env.d.ts +0 -1
- package/client/mobile/tailwind.config.js +0 -8
- package/client/mobile/tsconfig.json +0 -25
- package/client/mobile/vite.config.ts +0 -12
- package/client/web/.dockerignore +0 -3
- package/client/web/.env.example +0 -1
- package/client/web/Dockerfile +0 -16
- package/client/web/Dockerfile.dev +0 -18
- package/client/web/README.md +0 -47
- package/client/web/index.html +0 -12
- package/client/web/package.json +0 -42
- package/client/web/postcss.config.js +0 -6
- package/client/web/scripts/ui-parity-web-adapter.mjs +0 -66
- package/client/web/src/api/client.ts +0 -30
- package/client/web/src/api/orders.ts +0 -42
- package/client/web/src/app/App.tsx +0 -21
- package/client/web/src/auth/AuthProvider.tsx +0 -122
- package/client/web/src/auth/ProtectedRoute.tsx +0 -22
- package/client/web/src/auth/auth-client.ts +0 -38
- package/client/web/src/auth/types.ts +0 -18
- package/client/web/src/components/AppShell.tsx +0 -59
- package/client/web/src/components/ui/button.tsx +0 -35
- package/client/web/src/components/ui/card.tsx +0 -7
- package/client/web/src/components/ui/input.tsx +0 -21
- package/client/web/src/lib/cn.ts +0 -6
- package/client/web/src/lib/specRouteCatalog.json +0 -23
- package/client/web/src/lib/specScreens.json +0 -17
- package/client/web/src/main.tsx +0 -17
- package/client/web/src/pages/DashboardPage.tsx +0 -158
- package/client/web/src/pages/LoginPage.tsx +0 -72
- package/client/web/src/pages/OrdersPage.tsx +0 -123
- package/client/web/src/styles/globals.css +0 -17
- package/client/web/src/theme-vars.ts +0 -18
- package/client/web/src/theme.ts +0 -25
- package/client/web/src/vite-env.d.ts +0 -1
- package/client/web/tailwind.config.js +0 -8
- package/client/web/tsconfig.json +0 -25
- package/client/web/vite.config.ts +0 -12
- package/compose.yml +0 -206
- package/infra/compose/.env.dev.example +0 -28
- package/infra/compose/.env.prod.example +0 -29
- package/infra/compose/README.md +0 -35
- package/infra/compose/dev.yml +0 -125
- package/infra/compose/prod.yml +0 -126
- package/infra/terraform/README.md +0 -34
- package/infra/terraform/aws/data/.terraform.lock.hcl +0 -25
- package/infra/terraform/aws/data/README.md +0 -18
- package/infra/terraform/aws/data/main.tf +0 -147
- package/infra/terraform/aws/data/outputs.tf +0 -14
- package/infra/terraform/aws/data/variables.tf +0 -57
- package/infra/terraform/aws/data/versions.tf +0 -10
- package/infra/terraform/aws/domain/.terraform.lock.hcl +0 -25
- package/infra/terraform/aws/domain/README.md +0 -20
- package/infra/terraform/aws/domain/env/dev.tfvars.example +0 -6
- package/infra/terraform/aws/domain/env/prod.tfvars.example +0 -7
- package/infra/terraform/aws/domain/main.tf +0 -149
- package/infra/terraform/aws/domain/outputs.tf +0 -29
- package/infra/terraform/aws/domain/variables.tf +0 -58
- package/infra/terraform/aws/domain/versions.tf +0 -10
- package/infra/terraform/openstack/README.md +0 -38
- package/infra/terraform/openstack/dev/.terraform.lock.hcl +0 -24
- package/infra/terraform/openstack/dev/README.md +0 -18
- package/infra/terraform/openstack/dev/main.tf +0 -49
- package/infra/terraform/openstack/dev/providers.tf +0 -15
- package/infra/terraform/openstack/dev/terraform.tfvars.example +0 -54
- package/infra/terraform/openstack/dev/variables.tf +0 -210
- package/infra/terraform/openstack/dev/versions.tf +0 -10
- package/infra/terraform/openstack/modules/environment_host/main.tf +0 -143
- package/infra/terraform/openstack/modules/environment_host/outputs.tf +0 -25
- package/infra/terraform/openstack/modules/environment_host/templates/docker-host-user-data.sh.tftpl +0 -40
- package/infra/terraform/openstack/modules/environment_host/variables.tf +0 -145
- package/infra/terraform/openstack/modules/environment_host/versions.tf +0 -7
- package/infra/terraform/openstack/prod/.terraform.lock.hcl +0 -24
- package/infra/terraform/openstack/prod/README.md +0 -18
- package/infra/terraform/openstack/prod/main.tf +0 -49
- package/infra/terraform/openstack/prod/providers.tf +0 -15
- package/infra/terraform/openstack/prod/terraform.tfvars.example +0 -55
- package/infra/terraform/openstack/prod/variables.tf +0 -210
- package/infra/terraform/openstack/prod/versions.tf +0 -10
- package/infra/terraform/openstack/server/.terraform.lock.hcl +0 -45
- package/infra/terraform/openstack/server/README.md +0 -47
- package/infra/terraform/openstack/server/main.tf +0 -161
- package/infra/terraform/openstack/server/outputs.tf +0 -30
- package/infra/terraform/openstack/server/providers.tf +0 -30
- package/infra/terraform/openstack/server/templates/server-user-data.sh.tftpl +0 -50
- package/infra/terraform/openstack/server/variables.tf +0 -233
- package/infra/terraform/openstack/server/zz_aspace.auto.tfvars.example.json +0 -29
- package/pnpm-workspace.yaml +0 -2
- package/scripts/dev/audit_sdd_build_ast.py +0 -277
- package/sdd/01_planning/01_feature/INDEX.md +0 -16
- package/sdd/01_planning/01_feature/README.md +0 -76
- package/sdd/01_planning/01_feature/alerts_feature_spec.md +0 -55
- package/sdd/01_planning/01_feature/auth_feature_spec.md +0 -57
- package/sdd/01_planning/01_feature/catalog_feature_spec.md +0 -61
- package/sdd/01_planning/01_feature/fulfillment_feature_spec.md +0 -58
- package/sdd/01_planning/01_feature/health_feature_spec.md +0 -52
- package/sdd/01_planning/01_feature/inventory_feature_spec.md +0 -60
- package/sdd/01_planning/01_feature/order_feature_spec.md +0 -63
- package/sdd/01_planning/01_feature/shipping_feature_spec.md +0 -55
- package/sdd/01_planning/01_feature/support_feature_spec.md +0 -53
- package/sdd/01_planning/01_feature/user_feature_spec.md +0 -54
- package/sdd/01_planning/02_screen/INDEX.md +0 -13
- package/sdd/01_planning/02_screen/README.md +0 -41
- package/sdd/01_planning/02_screen/admin_screen_spec.pdf +0 -0
- package/sdd/01_planning/02_screen/assets/README.md +0 -16
- package/sdd/01_planning/02_screen/assets/example/README.md +0 -13
- package/sdd/01_planning/02_screen/landing_screen_spec.pdf +0 -0
- package/sdd/01_planning/02_screen/mobile_screen_spec.pdf +0 -0
- package/sdd/01_planning/02_screen/web_screen_spec.pdf +0 -0
- package/sdd/01_planning/03_architecture/INDEX.md +0 -9
- package/sdd/01_planning/03_architecture/README.md +0 -25
- package/sdd/01_planning/03_architecture/architecture_document_structure.md +0 -77
- package/sdd/01_planning/03_architecture/backend/README.md +0 -10
- package/sdd/01_planning/03_architecture/frontend/README.md +0 -12
- package/sdd/01_planning/03_architecture/infra/README.md +0 -10
- package/sdd/01_planning/03_architecture/tech-research/README.md +0 -4
- package/sdd/01_planning/03_architecture/templates_system_architecture.md +0 -84
- package/sdd/01_planning/04_data/INDEX.md +0 -4
- package/sdd/01_planning/04_data/README.md +0 -10
- package/sdd/01_planning/04_data/templates_data_modeling.md +0 -119
- package/sdd/01_planning/05_api/README.md +0 -12
- package/sdd/01_planning/05_api/templates_api_contract.md +0 -90
- package/sdd/01_planning/06_iac/README.md +0 -11
- package/sdd/01_planning/06_iac/templates_runtime_and_cicd_baseline.md +0 -46
- package/sdd/01_planning/07_integration/README.md +0 -11
- package/sdd/01_planning/07_integration/templates_frontend_api_integration.md +0 -46
- package/sdd/01_planning/08_nonfunctional/README.md +0 -7
- package/sdd/01_planning/09_security/README.md +0 -7
- package/sdd/01_planning/10_test/README.md +0 -12
- package/sdd/01_planning/10_test/templates_test_strategy.md +0 -60
- package/sdd/01_planning/INDEX.md +0 -19
- package/sdd/01_planning/README.md +0 -17
- package/sdd/02_plan/01_feature/README.md +0 -34
- package/sdd/02_plan/01_feature/_feature_todo_template.md +0 -29
- package/sdd/02_plan/02_screen/INDEX.md +0 -19
- package/sdd/02_plan/02_screen/README.md +0 -39
- package/sdd/02_plan/02_screen/_screen_todo_template.md +0 -60
- package/sdd/02_plan/03_architecture/README.md +0 -23
- package/sdd/02_plan/03_architecture/architecture_document_governance.md +0 -40
- package/sdd/02_plan/03_architecture/build_ast_runtime_tree_governance.md +0 -53
- package/sdd/02_plan/03_architecture/repository_governance.md +0 -39
- package/sdd/02_plan/03_architecture/runtime_and_structure_governance.md +0 -38
- package/sdd/02_plan/03_architecture/templates-hexagonal-template-architecture.md +0 -9
- package/sdd/02_plan/03_architecture/toolchain_governance.md +0 -98
- package/sdd/02_plan/04_data/README.md +0 -5
- package/sdd/02_plan/05_api/README.md +0 -5
- package/sdd/02_plan/06_iac/README.md +0 -11
- package/sdd/02_plan/06_iac/dev_runtime_delivery.md +0 -36
- package/sdd/02_plan/06_iac/template_runtime_delivery.md +0 -50
- package/sdd/02_plan/07_integration/README.md +0 -5
- package/sdd/02_plan/07_integration/frontend_live_integration.md +0 -31
- package/sdd/02_plan/08_nonfunctional/README.md +0 -5
- package/sdd/02_plan/08_nonfunctional/repository_hygiene.md +0 -26
- package/sdd/02_plan/09_security/README.md +0 -5
- package/sdd/02_plan/10_test/README.md +0 -11
- package/sdd/02_plan/10_test/regression_verification.md +0 -39
- package/sdd/02_plan/10_test/templates/README.md +0 -8
- package/sdd/02_plan/10_test/templates/ui_parity_web_contract.template.yaml +0 -23
- package/sdd/02_plan/10_test/verification_strategy.md +0 -43
- package/sdd/02_plan/99_generated/from_planning/ui_parity/.gitkeep +0 -1
- package/sdd/02_plan/README.md +0 -40
- package/sdd/03_build/01_feature/README.md +0 -20
- package/sdd/03_build/01_feature/domain/README.md +0 -3
- package/sdd/03_build/01_feature/domain/account_and_access.md +0 -20
- package/sdd/03_build/01_feature/domain/catalog_and_inventory.md +0 -20
- package/sdd/03_build/01_feature/domain/ordering_and_fulfillment.md +0 -21
- package/sdd/03_build/01_feature/domain/support_and_observability.md +0 -21
- package/sdd/03_build/01_feature/domain_surfaces.md +0 -28
- package/sdd/03_build/01_feature/service/README.md +0 -3
- package/sdd/03_build/01_feature/service/admin_surface.md +0 -15
- package/sdd/03_build/01_feature/service/landing_surface.md +0 -13
- package/sdd/03_build/01_feature/service/mobile_surface.md +0 -14
- package/sdd/03_build/01_feature/service/web_surface.md +0 -14
- package/sdd/03_build/02_screen/README.md +0 -25
- package/sdd/03_build/02_screen/_screen_build_template.md +0 -26
- package/sdd/03_build/02_screen/admin/README.md +0 -5
- package/sdd/03_build/02_screen/landing/README.md +0 -5
- package/sdd/03_build/02_screen/mobile/README.md +0 -5
- package/sdd/03_build/02_screen/web/README.md +0 -5
- package/sdd/03_build/03_architecture/README.md +0 -10
- package/sdd/03_build/03_architecture/architecture_document_governance.md +0 -30
- package/sdd/03_build/03_architecture/build_ast_runtime_tree_governance.md +0 -24
- package/sdd/03_build/03_architecture/repository_governance.md +0 -18
- package/sdd/03_build/03_architecture/toolchain_governance.md +0 -36
- package/sdd/03_build/06_iac/README.md +0 -3
- package/sdd/03_build/06_iac/dev_runtime_delivery.md +0 -10
- package/sdd/03_build/06_iac/template_runtime_delivery.md +0 -49
- package/sdd/03_build/07_integration/README.md +0 -3
- package/sdd/03_build/07_integration/frontend_live_integration.md +0 -11
- package/sdd/03_build/08_nonfunctional/README.md +0 -3
- package/sdd/03_build/08_nonfunctional/repository_hygiene.md +0 -10
- package/sdd/03_build/10_test/README.md +0 -9
- package/sdd/03_build/10_test/regression_verification.md +0 -16
- package/sdd/03_build/10_test/verification_harness.md +0 -11
- package/sdd/03_build/README.md +0 -35
- package/sdd/03_verify/01_feature/README.md +0 -5
- package/sdd/03_verify/01_feature/domain_verification.md +0 -14
- package/sdd/03_verify/01_feature/service_verification.md +0 -22
- package/sdd/03_verify/02_screen/README.md +0 -6
- package/sdd/03_verify/02_screen/_screen_verify_template.md +0 -20
- package/sdd/03_verify/02_screen/admin/README.md +0 -4
- package/sdd/03_verify/02_screen/landing/README.md +0 -4
- package/sdd/03_verify/02_screen/mobile/README.md +0 -4
- package/sdd/03_verify/02_screen/web/README.md +0 -4
- package/sdd/03_verify/03_architecture/README.md +0 -10
- package/sdd/03_verify/03_architecture/architecture_document_governance.md +0 -15
- package/sdd/03_verify/03_architecture/build_ast_runtime_tree_governance.md +0 -28
- package/sdd/03_verify/03_architecture/repository_governance.md +0 -16
- package/sdd/03_verify/03_architecture/toolchain_governance.md +0 -58
- package/sdd/03_verify/06_iac/README.md +0 -3
- package/sdd/03_verify/06_iac/dev_runtime_delivery.md +0 -10
- package/sdd/03_verify/06_iac/template_runtime_delivery.md +0 -42
- package/sdd/03_verify/07_integration/README.md +0 -3
- package/sdd/03_verify/07_integration/frontend_live_integration.md +0 -16
- package/sdd/03_verify/08_nonfunctional/README.md +0 -3
- package/sdd/03_verify/08_nonfunctional/repository_hygiene.md +0 -14
- package/sdd/03_verify/10_test/README.md +0 -9
- package/sdd/03_verify/10_test/regression_verification.md +0 -16
- package/sdd/03_verify/10_test/ui_parity/README.md +0 -4
- package/sdd/03_verify/10_test/ui_parity/loop_runs/.gitkeep +0 -0
- package/sdd/03_verify/10_test/ui_parity/reference/.gitkeep +0 -0
- package/sdd/03_verify/10_test/ui_parity/staged_runs/.gitkeep +0 -0
- package/sdd/03_verify/10_test/verification_harness.md +0 -17
- package/sdd/03_verify/README.md +0 -22
- package/sdd/05_operate/01_runbooks/.gitkeep +0 -1
- package/sdd/05_operate/01_runbooks/README.md +0 -4
- package/sdd/05_operate/02_delivery_status/README.md +0 -4
- package/sdd/05_operate/02_delivery_status/service_status.md +0 -16
- package/sdd/05_operate/README.md +0 -12
- package/sdd/99_toolchain/01_automation/.gitkeep +0 -1
- package/sdd/99_toolchain/01_automation/README.md +0 -76
- package/sdd/99_toolchain/01_automation/agentic-dev/analyze_proof_results.py +0 -132
- package/sdd/99_toolchain/01_automation/agentic-dev/analyze_route_gap.py +0 -85
- package/sdd/99_toolchain/01_automation/agentic-dev/assets/repo-contract.template.json +0 -75
- package/sdd/99_toolchain/01_automation/agentic-dev/bootstrap_frontend_parity.sh +0 -84
- package/sdd/99_toolchain/01_automation/agentic-dev/init_frontend_parity.sh +0 -33
- package/sdd/99_toolchain/01_automation/agentic-dev/init_repo_contract.sh +0 -51
- package/sdd/99_toolchain/01_automation/agentic-dev/repo-contract.json +0 -76
- package/sdd/99_toolchain/01_automation/agentic-dev/resolve_frontend_target.py +0 -52
- package/sdd/99_toolchain/01_automation/agentic-dev/resolve_repo_contract.py +0 -56
- package/sdd/99_toolchain/01_automation/agentic-dev/run_frontend_target.sh +0 -100
- package/sdd/99_toolchain/01_automation/agentic-dev/run_repo_phase.sh +0 -140
- package/sdd/99_toolchain/01_automation/agentic-dev/validate_json_schema.py +0 -39
- package/sdd/99_toolchain/01_automation/agentic-parity-harness-design.md +0 -291
- package/sdd/99_toolchain/01_automation/assets/admin_screen_capture/dashboard.png +0 -0
- package/sdd/99_toolchain/01_automation/assets/admin_screen_capture/login.png +0 -0
- package/sdd/99_toolchain/01_automation/assets/admin_screen_capture/queue.png +0 -0
- package/sdd/99_toolchain/01_automation/assets/admin_screen_capture/support.png +0 -0
- package/sdd/99_toolchain/01_automation/assets/landing_screen_capture/home.png +0 -0
- package/sdd/99_toolchain/01_automation/assets/landing_screen_capture/login.png +0 -0
- package/sdd/99_toolchain/01_automation/assets/landing_screen_capture/workspace.png +0 -0
- package/sdd/99_toolchain/01_automation/assets/mobile_screen_capture/dashboard.png +0 -0
- package/sdd/99_toolchain/01_automation/assets/mobile_screen_capture/fulfillment.png +0 -0
- package/sdd/99_toolchain/01_automation/assets/mobile_screen_capture/login.png +0 -0
- package/sdd/99_toolchain/01_automation/assets/web_screen_capture/dashboard.png +0 -0
- package/sdd/99_toolchain/01_automation/assets/web_screen_capture/login.png +0 -0
- package/sdd/99_toolchain/01_automation/assets/web_screen_capture/orders.png +0 -0
- package/sdd/99_toolchain/01_automation/build_asset_recipes.py +0 -10
- package/sdd/99_toolchain/01_automation/build_screen_spec_pdf.py +0 -427
- package/sdd/99_toolchain/01_automation/capture_screen_assets.mjs +0 -148
- package/sdd/99_toolchain/01_automation/harness-layout.md +0 -34
- package/sdd/99_toolchain/01_automation/parity-execution-tooling-design.md +0 -319
- package/sdd/99_toolchain/01_automation/playwright_exactness_manifest.py +0 -21
- package/sdd/99_toolchain/01_automation/run_playwright_exactness.py +0 -87
- package/sdd/99_toolchain/01_automation/screen_spec_manifest.py +0 -321
- package/sdd/99_toolchain/01_automation/spec_asset_builder.py +0 -274
- package/sdd/99_toolchain/01_automation/ui-contract-projection.md +0 -79
- package/sdd/99_toolchain/01_automation/ui-parity/README.md +0 -60
- package/sdd/99_toolchain/01_automation/ui-parity/cli/extract-reference-pages.mjs +0 -2
- package/sdd/99_toolchain/01_automation/ui-parity/cli/materialize-reference-assets.mjs +0 -58
- package/sdd/99_toolchain/01_automation/ui-parity/cli/normalize-reference-assets.mjs +0 -2
- package/sdd/99_toolchain/01_automation/ui-parity/cli/route-gap-report.mjs +0 -187
- package/sdd/99_toolchain/01_automation/ui-parity/cli/run-proof.mjs +0 -50
- package/sdd/99_toolchain/01_automation/ui-parity/cli/scaffold-contract.mjs +0 -62
- package/sdd/99_toolchain/01_automation/ui-parity/cli/upload-parity1.mjs +0 -2
- package/sdd/99_toolchain/01_automation/ui-parity/contracts/collector-metadata.schema.json +0 -33
- package/sdd/99_toolchain/01_automation/ui-parity/contracts/proof-result.schema.json +0 -76
- package/sdd/99_toolchain/01_automation/ui-parity/contracts/route-gap-report.schema.json +0 -95
- package/sdd/99_toolchain/01_automation/ui-parity/core/capture-runner.mjs +0 -55
- package/sdd/99_toolchain/01_automation/ui-parity/core/load-adapter.mjs +0 -25
- package/sdd/99_toolchain/01_automation/ui-parity/core/load-contract.mjs +0 -81
- package/sdd/99_toolchain/01_automation/ui-parity/core/paths.mjs +0 -23
- package/sdd/99_toolchain/01_automation/ui-parity/core/proof-runner.mjs +0 -255
- package/sdd/99_toolchain/01_automation/ui-parity/interfaces/ui-parity-artifact-layout.md +0 -23
- package/sdd/99_toolchain/01_automation/ui-parity/interfaces/ui-parity-proof-interface.md +0 -60
- package/sdd/99_toolchain/01_automation/ui-parity/interfaces/ui-parity-route-gap-interface.md +0 -82
- package/sdd/99_toolchain/01_automation/ui-parity/runtime/playwright-runtime.mjs +0 -16
- package/sdd/99_toolchain/01_automation/ui-parity/runtime/static-runtime.mjs +0 -6
- package/sdd/99_toolchain/02_policies/.gitkeep +0 -1
- package/sdd/99_toolchain/02_policies/build-ast-governance-policy.md +0 -22
- package/sdd/99_toolchain/02_policies/compose-runtime-baseline-policy.md +0 -24
- package/sdd/99_toolchain/02_policies/convention-storage-policy.md +0 -26
- package/sdd/99_toolchain/02_policies/main-push-before-dev-deploy-policy.md +0 -27
- package/sdd/99_toolchain/02_policies/regression-verification-policy.md +0 -22
- package/sdd/99_toolchain/03_templates/.gitkeep +0 -1
- package/sdd/99_toolchain/03_templates/asset_recipe_manifest.example.py +0 -38
- package/sdd/99_toolchain/03_templates/generated_assets/README.md +0 -11
- package/sdd/99_toolchain/03_templates/generated_assets/example-brand-lockup.svg +0 -3
- package/sdd/99_toolchain/03_templates/generated_assets/example-brand-mark.svg +0 -3
- package/sdd/99_toolchain/03_templates/generated_assets/example-brand-wordmark.svg +0 -3
- package/sdd/99_toolchain/03_templates/playwright_exactness_manifest.example.py +0 -21
- package/sdd/99_toolchain/README.md +0 -23
- package/sdd/README.md +0 -21
- package/server/.dockerignore +0 -4
- package/server/.env.example +0 -19
- package/server/Dockerfile +0 -22
- package/server/Dockerfile.dev +0 -19
- package/server/README.md +0 -33
- package/server/__init__.py +0 -0
- package/server/api/__init__.py +0 -1
- package/server/api/http/__init__.py +0 -4
- package/server/api/http/app.py +0 -53
- package/server/api/http/router.py +0 -24
- package/server/config.py +0 -52
- package/server/contexts/__init__.py +0 -12
- package/server/contexts/alerts/__init__.py +0 -1
- package/server/contexts/alerts/application/__init__.py +0 -13
- package/server/contexts/alerts/application/services.py +0 -41
- package/server/contexts/alerts/contracts/__init__.py +0 -3
- package/server/contexts/alerts/contracts/http/__init__.py +0 -3
- package/server/contexts/alerts/contracts/http/router.py +0 -37
- package/server/contexts/alerts/domain/__init__.py +0 -15
- package/server/contexts/alerts/domain/models.py +0 -29
- package/server/contexts/alerts/infrastructure/__init__.py +0 -11
- package/server/contexts/alerts/infrastructure/repository.py +0 -41
- package/server/contexts/auth/__init__.py +0 -1
- package/server/contexts/auth/application/__init__.py +0 -3
- package/server/contexts/auth/application/ports.py +0 -10
- package/server/contexts/auth/application/services.py +0 -64
- package/server/contexts/auth/contracts/__init__.py +0 -4
- package/server/contexts/auth/contracts/http/__init__.py +0 -4
- package/server/contexts/auth/contracts/http/dependencies.py +0 -37
- package/server/contexts/auth/contracts/http/router.py +0 -19
- package/server/contexts/auth/domain/__init__.py +0 -3
- package/server/contexts/auth/domain/models.py +0 -24
- package/server/contexts/auth/infrastructure/__init__.py +0 -4
- package/server/contexts/auth/infrastructure/adapters/memory.py +0 -19
- package/server/contexts/auth/infrastructure/adapters/mongodb.py +0 -24
- package/server/contexts/auth/infrastructure/adapters/sqlalchemy.py +0 -74
- package/server/contexts/auth/infrastructure/repository.py +0 -28
- package/server/contexts/catalog/__init__.py +0 -1
- package/server/contexts/catalog/application/__init__.py +0 -28
- package/server/contexts/catalog/application/ports.py +0 -15
- package/server/contexts/catalog/application/services.py +0 -154
- package/server/contexts/catalog/contracts/__init__.py +0 -3
- package/server/contexts/catalog/contracts/http/__init__.py +0 -3
- package/server/contexts/catalog/contracts/http/router.py +0 -60
- package/server/contexts/catalog/domain/__init__.py +0 -45
- package/server/contexts/catalog/domain/models.py +0 -113
- package/server/contexts/catalog/infrastructure/__init__.py +0 -4
- package/server/contexts/catalog/infrastructure/adapters/memory.py +0 -62
- package/server/contexts/catalog/infrastructure/repository.py +0 -8
- package/server/contexts/fulfillment/__init__.py +0 -1
- package/server/contexts/fulfillment/application/__init__.py +0 -13
- package/server/contexts/fulfillment/application/ports.py +0 -20
- package/server/contexts/fulfillment/application/services.py +0 -85
- package/server/contexts/fulfillment/contracts/__init__.py +0 -3
- package/server/contexts/fulfillment/contracts/http/__init__.py +0 -3
- package/server/contexts/fulfillment/contracts/http/router.py +0 -40
- package/server/contexts/fulfillment/domain/__init__.py +0 -25
- package/server/contexts/fulfillment/domain/models.py +0 -73
- package/server/contexts/fulfillment/infrastructure/__init__.py +0 -13
- package/server/contexts/fulfillment/infrastructure/adapters/memory.py +0 -43
- package/server/contexts/fulfillment/infrastructure/repository.py +0 -97
- package/server/contexts/health/__init__.py +0 -1
- package/server/contexts/health/application/__init__.py +0 -3
- package/server/contexts/health/application/services.py +0 -2
- package/server/contexts/health/contracts/__init__.py +0 -3
- package/server/contexts/health/contracts/http/__init__.py +0 -3
- package/server/contexts/health/contracts/http/router.py +0 -10
- package/server/contexts/inventory/__init__.py +0 -1
- package/server/contexts/inventory/application/__init__.py +0 -28
- package/server/contexts/inventory/application/ports.py +0 -11
- package/server/contexts/inventory/application/services.py +0 -214
- package/server/contexts/inventory/contracts/__init__.py +0 -3
- package/server/contexts/inventory/contracts/http/__init__.py +0 -3
- package/server/contexts/inventory/contracts/http/router.py +0 -82
- package/server/contexts/inventory/domain/__init__.py +0 -33
- package/server/contexts/inventory/domain/models.py +0 -93
- package/server/contexts/inventory/infrastructure/__init__.py +0 -4
- package/server/contexts/inventory/infrastructure/adapters/memory.py +0 -24
- package/server/contexts/inventory/infrastructure/repository.py +0 -8
- package/server/contexts/orders/__init__.py +0 -1
- package/server/contexts/orders/application/__init__.py +0 -19
- package/server/contexts/orders/application/services.py +0 -127
- package/server/contexts/orders/contracts/__init__.py +0 -3
- package/server/contexts/orders/contracts/http/__init__.py +0 -3
- package/server/contexts/orders/contracts/http/router.py +0 -82
- package/server/contexts/orders/domain/__init__.py +0 -29
- package/server/contexts/orders/domain/models.py +0 -95
- package/server/contexts/orders/infrastructure/__init__.py +0 -7
- package/server/contexts/orders/infrastructure/repository.py +0 -104
- package/server/contexts/shipping/__init__.py +0 -1
- package/server/contexts/shipping/application/__init__.py +0 -13
- package/server/contexts/shipping/application/services.py +0 -92
- package/server/contexts/shipping/contracts/__init__.py +0 -3
- package/server/contexts/shipping/contracts/http/__init__.py +0 -3
- package/server/contexts/shipping/contracts/http/router.py +0 -40
- package/server/contexts/shipping/domain/__init__.py +0 -19
- package/server/contexts/shipping/domain/models.py +0 -48
- package/server/contexts/shipping/infrastructure/__init__.py +0 -9
- package/server/contexts/shipping/infrastructure/repository.py +0 -50
- package/server/contexts/support/__init__.py +0 -1
- package/server/contexts/support/application/__init__.py +0 -13
- package/server/contexts/support/application/services.py +0 -29
- package/server/contexts/support/contracts/__init__.py +0 -3
- package/server/contexts/support/contracts/http/__init__.py +0 -3
- package/server/contexts/support/contracts/http/router.py +0 -40
- package/server/contexts/support/domain/__init__.py +0 -13
- package/server/contexts/support/domain/models.py +0 -27
- package/server/contexts/support/infrastructure/__init__.py +0 -11
- package/server/contexts/support/infrastructure/repository.py +0 -70
- package/server/contexts/user/__init__.py +0 -1
- package/server/contexts/user/application/__init__.py +0 -3
- package/server/contexts/user/application/ports.py +0 -11
- package/server/contexts/user/application/services.py +0 -44
- package/server/contexts/user/contracts/__init__.py +0 -3
- package/server/contexts/user/contracts/http/__init__.py +0 -3
- package/server/contexts/user/contracts/http/router.py +0 -26
- package/server/contexts/user/domain/__init__.py +0 -3
- package/server/contexts/user/domain/models.py +0 -22
- package/server/contexts/user/infrastructure/__init__.py +0 -3
- package/server/contexts/user/infrastructure/adapters/memory.py +0 -27
- package/server/contexts/user/infrastructure/adapters/mongodb.py +0 -41
- package/server/contexts/user/infrastructure/adapters/sqlalchemy.py +0 -94
- package/server/contexts/user/infrastructure/factory.py +0 -28
- package/server/data/README.md +0 -24
- package/server/data/bootstrap/alerts.json +0 -38
- package/server/data/bootstrap/auth_accounts.json +0 -18
- package/server/data/bootstrap/catalog_products.json +0 -179
- package/server/data/bootstrap/fulfillment_events.json +0 -5
- package/server/data/bootstrap/fulfillment_notes.json +0 -5
- package/server/data/bootstrap/fulfillment_tasks.json +0 -50
- package/server/data/bootstrap/inventory_levels.json +0 -80
- package/server/data/bootstrap/orders.json +0 -62
- package/server/data/bootstrap/shipping_shipments.json +0 -50
- package/server/data/bootstrap/support_faqs.json +0 -26
- package/server/data/bootstrap/users.json +0 -20
- package/server/data/bootstrap_loader.py +0 -15
- package/server/docker-entrypoint.sh +0 -56
- package/server/main.py +0 -3
- package/server/pyproject.toml +0 -36
- package/server/shared/__init__.py +0 -1
- package/server/shared/application/__init__.py +0 -3
- package/server/shared/application/health.py +0 -2
- package/server/shared/infrastructure/__init__.py +0 -10
- package/server/shared/infrastructure/runtime.py +0 -6
- package/server/shared/infrastructure/security.py +0 -33
- package/server/tests/e2e/test_domain_feature_flows.py +0 -483
- package/server/tests/test_health.py +0 -49
- package/server/uv.lock +0 -1169
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
ROOT = Path(__file__).resolve().parents[3]
|
|
7
|
-
SCREEN_DIR = ROOT / "sdd/01_planning/02_screen"
|
|
8
|
-
ASSET_DIR = ROOT / "sdd/99_toolchain/01_automation/assets"
|
|
9
|
-
DESKTOP_CAPTURE_POLICY = {
|
|
10
|
-
"reference_visible_area": "1710x951",
|
|
11
|
-
"default_viewport": "1690x940",
|
|
12
|
-
"capture_mode": "viewport-first",
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def screen(
|
|
17
|
-
*,
|
|
18
|
-
code: str,
|
|
19
|
-
name: str,
|
|
20
|
-
route: str,
|
|
21
|
-
access: str,
|
|
22
|
-
features: list[str],
|
|
23
|
-
asset: str,
|
|
24
|
-
requires_auth: bool,
|
|
25
|
-
callouts: list[tuple[tuple[float, float], str, str]],
|
|
26
|
-
crop_box: tuple[int, int, int, int] | None = None,
|
|
27
|
-
segments: list[dict] | None = None,
|
|
28
|
-
) -> dict:
|
|
29
|
-
item = {
|
|
30
|
-
"code": code,
|
|
31
|
-
"name": name,
|
|
32
|
-
"route": route,
|
|
33
|
-
"access": access,
|
|
34
|
-
"features": features,
|
|
35
|
-
"asset": asset,
|
|
36
|
-
"requires_auth": requires_auth,
|
|
37
|
-
"callouts": callouts,
|
|
38
|
-
}
|
|
39
|
-
if crop_box:
|
|
40
|
-
item["crop_box"] = crop_box
|
|
41
|
-
if segments:
|
|
42
|
-
item["segments"] = segments
|
|
43
|
-
return item
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
SCREEN_MANIFESTS = {
|
|
47
|
-
"web": {
|
|
48
|
-
"title": "Templates Web Screen Spec",
|
|
49
|
-
"service_label": "web",
|
|
50
|
-
"output": str(SCREEN_DIR / "web_screen_spec.pdf"),
|
|
51
|
-
"asset_dir": str(ASSET_DIR / "web_screen_capture"),
|
|
52
|
-
"base_url": "http://127.0.0.1:3001",
|
|
53
|
-
"api_base": "http://127.0.0.1:8000/api/v1",
|
|
54
|
-
"storage_key": "web.auth.token",
|
|
55
|
-
"capture_policy": DESKTOP_CAPTURE_POLICY,
|
|
56
|
-
"trim_background": False,
|
|
57
|
-
"cover_note": "첫 페이지는 web 화면코드 인덱스다. 이후 페이지는 좌측 화면 캡처와 우측 번호형 기능 테이블을 함께 제공한다.",
|
|
58
|
-
"source_refs": [
|
|
59
|
-
{"label": "implementation", "path": "client/web/src/app/App.tsx"},
|
|
60
|
-
{"label": "implementation", "path": "client/web/src/pages"},
|
|
61
|
-
{"label": "capture assets", "path": "sdd/99_toolchain/01_automation/assets/web_screen_capture"},
|
|
62
|
-
],
|
|
63
|
-
"screens": [
|
|
64
|
-
screen(
|
|
65
|
-
code="WEB-S001",
|
|
66
|
-
name="Web Login",
|
|
67
|
-
route="/login",
|
|
68
|
-
access="public",
|
|
69
|
-
features=["AUT-F001", "AUT-F002"],
|
|
70
|
-
asset="login.png",
|
|
71
|
-
requires_auth=False,
|
|
72
|
-
callouts=[
|
|
73
|
-
((0.25, 0.31), "서비스 소개 카피", "실제 API 인증 흐름과 로그인 이후 앱 셸 진입 방식을 좌측 설명 영역에서 안내한다."),
|
|
74
|
-
((0.78, 0.21), "Sign in 헤더", "web 로그인 목적과 예시 계정 프리셋 상태를 보여준다."),
|
|
75
|
-
((0.78, 0.38), "자격 증명 입력", "이메일과 비밀번호를 입력하고 오류 상태를 같은 카드 안에서 확인한다."),
|
|
76
|
-
((0.78, 0.48), "Continue CTA", "인증 성공 시 저장된 토큰으로 `auth/me`를 다시 호출한 뒤 보호 라우트로 이동한다."),
|
|
77
|
-
],
|
|
78
|
-
),
|
|
79
|
-
screen(
|
|
80
|
-
code="WEB-S002",
|
|
81
|
-
name="Web Dashboard",
|
|
82
|
-
route="/",
|
|
83
|
-
access="protected",
|
|
84
|
-
features=["AUT-F002", "ORD-F001"],
|
|
85
|
-
asset="dashboard.png",
|
|
86
|
-
requires_auth=True,
|
|
87
|
-
callouts=[
|
|
88
|
-
((0.17, 0.09), "상단 앱 셸", "브랜드, Overview/Orders 전환, 검색, 알림, 사용자 액션을 한 줄 헤더로 제공한다."),
|
|
89
|
-
((0.26, 0.25), "운영 통계 카드", "주문 overview 핵심 지표와 로딩 또는 오류 상태를 상단 카드 묶음으로 보여준다."),
|
|
90
|
-
((0.34, 0.60), "Recent activity 표", "최근 주문 이벤트를 주문 ID, 일자, customer, 상태 기준으로 읽는 메인 데이터 테이블이다."),
|
|
91
|
-
((0.83, 0.55), "Selected detail 패널", "선택 주문의 product, customer, status, amount를 보조 패널에서 확인한다."),
|
|
92
|
-
],
|
|
93
|
-
),
|
|
94
|
-
screen(
|
|
95
|
-
code="WEB-S003",
|
|
96
|
-
name="Web Orders",
|
|
97
|
-
route="/orders",
|
|
98
|
-
access="protected",
|
|
99
|
-
features=["AUT-F002", "ORD-F002"],
|
|
100
|
-
asset="orders.png",
|
|
101
|
-
requires_auth=True,
|
|
102
|
-
callouts=[
|
|
103
|
-
((0.17, 0.09), "상단 앱 셸", "Overview와 Orders 간 전환, 검색, 알림, 로그아웃 등 공통 워크스페이스 셸을 유지한다."),
|
|
104
|
-
((0.36, 0.25), "검색/필터 바", "Search orders 입력값으로 product, customer, 상태, 주문 ID를 클라이언트 필터링한다."),
|
|
105
|
-
((0.78, 0.25), "액션 버튼", "Reset으로 필터를 초기화하고 New order CTA로 신규 흐름 진입점을 노출한다."),
|
|
106
|
-
((0.44, 0.61), "주문 목록 테이블", "주문 ID, product, customer, 상태를 기준으로 현재 결과 집합을 표 형태로 보여준다."),
|
|
107
|
-
],
|
|
108
|
-
),
|
|
109
|
-
],
|
|
110
|
-
},
|
|
111
|
-
"admin": {
|
|
112
|
-
"title": "Templates Admin Screen Spec",
|
|
113
|
-
"service_label": "admin",
|
|
114
|
-
"output": str(SCREEN_DIR / "admin_screen_spec.pdf"),
|
|
115
|
-
"asset_dir": str(ASSET_DIR / "admin_screen_capture"),
|
|
116
|
-
"base_url": "http://127.0.0.1:4000",
|
|
117
|
-
"api_base": "http://127.0.0.1:8000/api/v1",
|
|
118
|
-
"storage_key": "admin.auth.token",
|
|
119
|
-
"capture_policy": DESKTOP_CAPTURE_POLICY,
|
|
120
|
-
"trim_background": False,
|
|
121
|
-
"cover_note": "첫 페이지는 admin 화면코드 인덱스다. 이후 페이지는 좌측 화면 캡처와 우측 번호형 기능 테이블을 함께 제공한다.",
|
|
122
|
-
"source_refs": [
|
|
123
|
-
{"label": "implementation", "path": "client/admin/src/app/App.tsx"},
|
|
124
|
-
{"label": "implementation", "path": "client/admin/src/pages"},
|
|
125
|
-
{"label": "capture assets", "path": "sdd/99_toolchain/01_automation/assets/admin_screen_capture"},
|
|
126
|
-
],
|
|
127
|
-
"screens": [
|
|
128
|
-
screen(
|
|
129
|
-
code="ADM-S001",
|
|
130
|
-
name="Admin Login",
|
|
131
|
-
route="/login",
|
|
132
|
-
access="public",
|
|
133
|
-
features=["AUT-F001", "AUT-F002"],
|
|
134
|
-
asset="login.png",
|
|
135
|
-
requires_auth=False,
|
|
136
|
-
callouts=[
|
|
137
|
-
((0.24, 0.34), "운영 콘솔 소개 영역", "좌측 다크 패널에서 Admin console 컨텍스트와 실로그인 인증 흐름을 설명한다."),
|
|
138
|
-
((0.79, 0.18), "Restricted access 헤더", "관리자 접근 제어 맥락과 Sign in 제목을 우측 카드 상단에 배치한다."),
|
|
139
|
-
((0.79, 0.36), "자격 증명 입력", "이메일, 비밀번호, 오류 메시지를 한 폼 안에서 처리한다."),
|
|
140
|
-
((0.79, 0.48), "Open admin console CTA", "성공 시 관리자 토큰 저장 후 운영 셸로 진입한다."),
|
|
141
|
-
],
|
|
142
|
-
),
|
|
143
|
-
screen(
|
|
144
|
-
code="ADM-S002",
|
|
145
|
-
name="Admin Dashboard",
|
|
146
|
-
route="/",
|
|
147
|
-
access="protected",
|
|
148
|
-
features=["AUT-F002", "ORD-F003"],
|
|
149
|
-
asset="dashboard.png",
|
|
150
|
-
requires_auth=True,
|
|
151
|
-
callouts=[
|
|
152
|
-
((0.08, 0.35), "좌측 운영 레일", "대시보드, 거래 관리, 고객지원으로 이동하는 관리자 전용 내비게이션 레일이다."),
|
|
153
|
-
((0.40, 0.18), "운영 요약 카드", "운영 핵심 수치를 카드 단위로 먼저 요약해 전체 상태를 빠르게 파악하게 한다."),
|
|
154
|
-
((0.37, 0.58), "거래 상태별 현황", "단계별 거래 건수를 리스트형 카드로 보여주는 메인 분석 영역이다."),
|
|
155
|
-
((0.79, 0.58), "운영 알림", "위험/일반 알림을 tone별 카드로 묶어 후속 조치를 안내한다."),
|
|
156
|
-
],
|
|
157
|
-
),
|
|
158
|
-
screen(
|
|
159
|
-
code="ADM-S003",
|
|
160
|
-
name="Admin Queue",
|
|
161
|
-
route="/queue",
|
|
162
|
-
access="protected",
|
|
163
|
-
features=["AUT-F002", "ORD-F003"],
|
|
164
|
-
asset="queue.png",
|
|
165
|
-
requires_auth=True,
|
|
166
|
-
callouts=[
|
|
167
|
-
((0.08, 0.35), "좌측 운영 레일", "현재 거래 관리 섹션 위치를 강조하면서 다른 운영 화면으로 이동할 수 있다."),
|
|
168
|
-
((0.33, 0.24), "거래관리 헤더", "현재 큐 화면 제목과 전체 거래 건수를 요약해 상단에 고정한다."),
|
|
169
|
-
((0.44, 0.60), "거래 큐 테이블", "주문 ID, 상품, 고객 정보를 기준으로 관리자 작업 대상을 표로 노출한다."),
|
|
170
|
-
((0.82, 0.60), "상태/SLA 열", "운영 우선순위 판단에 필요한 상태와 SLA 정보를 같은 행에서 확인하게 한다."),
|
|
171
|
-
],
|
|
172
|
-
),
|
|
173
|
-
screen(
|
|
174
|
-
code="ADM-S004",
|
|
175
|
-
name="Admin Support",
|
|
176
|
-
route="/support",
|
|
177
|
-
access="protected",
|
|
178
|
-
features=["AUT-F002", "SUP-F001"],
|
|
179
|
-
asset="support.png",
|
|
180
|
-
requires_auth=True,
|
|
181
|
-
callouts=[
|
|
182
|
-
((0.08, 0.35), "좌측 운영 레일", "고객지원 섹션과 다른 관리자 기능을 오가는 공통 운영 내비게이션이다."),
|
|
183
|
-
((0.37, 0.21), "FAQ 관리 헤더", "현재 화면이 FAQ 운영 surface임을 제목으로 표시한다."),
|
|
184
|
-
((0.46, 0.55), "FAQ 목록", "질문과 노출 상태를 row 단위 카드로 보여주는 읽기 모델 영역이다."),
|
|
185
|
-
((0.86, 0.09), "상단 글로벌 액션", "알림, 현재 사용자, 로그아웃 등 관리자 공통 액션을 상단 바에 유지한다."),
|
|
186
|
-
],
|
|
187
|
-
),
|
|
188
|
-
],
|
|
189
|
-
},
|
|
190
|
-
"mobile": {
|
|
191
|
-
"title": "Templates Mobile Screen Spec",
|
|
192
|
-
"service_label": "mobile",
|
|
193
|
-
"output": str(SCREEN_DIR / "mobile_screen_spec.pdf"),
|
|
194
|
-
"asset_dir": str(ASSET_DIR / "mobile_screen_capture"),
|
|
195
|
-
"base_url": "http://127.0.0.1:3002",
|
|
196
|
-
"api_base": "http://127.0.0.1:8000/api/v1",
|
|
197
|
-
"storage_key": "mobile.auth.token",
|
|
198
|
-
"capture_policy": DESKTOP_CAPTURE_POLICY,
|
|
199
|
-
"trim_background": False,
|
|
200
|
-
"cover_note": "첫 페이지는 mobile 화면코드 인덱스다. 이후 페이지는 좌측 화면 캡처와 우측 번호형 기능 테이블을 함께 제공한다.",
|
|
201
|
-
"source_refs": [
|
|
202
|
-
{"label": "implementation", "path": "client/mobile/src/app/App.tsx"},
|
|
203
|
-
{"label": "implementation", "path": "client/mobile/src/pages"},
|
|
204
|
-
{"label": "capture assets", "path": "sdd/99_toolchain/01_automation/assets/mobile_screen_capture"},
|
|
205
|
-
],
|
|
206
|
-
"screens": [
|
|
207
|
-
screen(
|
|
208
|
-
code="MOB-S001",
|
|
209
|
-
name="Mobile Login",
|
|
210
|
-
route="/login",
|
|
211
|
-
access="public",
|
|
212
|
-
features=["AUT-F001", "AUT-F002"],
|
|
213
|
-
asset="login.png",
|
|
214
|
-
requires_auth=False,
|
|
215
|
-
callouts=[
|
|
216
|
-
((0.25, 0.32), "IN 소개 영역", "상담 흐름과 운영 상태를 동시에 여는 템플릿 맥락을 좌측 hero에서 설명한다."),
|
|
217
|
-
((0.79, 0.19), "Sign in 헤더", "IN workspace 진입 목적과 operator 기본 계정을 우측 로그인 카드 상단에 표시한다."),
|
|
218
|
-
((0.79, 0.39), "자격 증명 입력", "operator@example.com 기준 로그인 입력과 오류 상태를 한 폼에서 처리한다."),
|
|
219
|
-
((0.79, 0.49), "Continue CTA", "로그인 성공 시 저장된 세션으로 IN 보호 라우트에 진입한다."),
|
|
220
|
-
],
|
|
221
|
-
),
|
|
222
|
-
screen(
|
|
223
|
-
code="MOB-S002",
|
|
224
|
-
name="Mobile Dashboard",
|
|
225
|
-
route="/",
|
|
226
|
-
access="protected",
|
|
227
|
-
features=["AUT-F002", "FUL-F001"],
|
|
228
|
-
asset="dashboard.png",
|
|
229
|
-
requires_auth=True,
|
|
230
|
-
callouts=[
|
|
231
|
-
((0.15, 0.11), "상단 IN 셸", "Overview/Fulfillment 전환, relay status pill, 사용자 정보, 로그아웃을 묶은 공통 헤더다."),
|
|
232
|
-
((0.34, 0.25), "Units in motion hero", "현재 이행 중인 unit 수와 모바일 워크스페이스 목적을 한눈에 보여주는 대형 hero section이다."),
|
|
233
|
-
((0.27, 0.48), "운영 통계 카드", "Open tasks, blocked, outbound ready 지표를 카드 묶음으로 제공한다."),
|
|
234
|
-
((0.33, 0.79), "Relay timeline", "패킹, 예외 검토, 출고 준비 이벤트를 시간축 카드로 정리한다."),
|
|
235
|
-
((0.83, 0.60), "Stage load", "단계별 작업량과 병목 구간을 우측 보조 패널에서 보여준다."),
|
|
236
|
-
],
|
|
237
|
-
),
|
|
238
|
-
screen(
|
|
239
|
-
code="MOB-S003",
|
|
240
|
-
name="Mobile Fulfillment",
|
|
241
|
-
route="/fulfillment",
|
|
242
|
-
access="protected",
|
|
243
|
-
features=["AUT-F002", "FUL-F002"],
|
|
244
|
-
asset="fulfillment.png",
|
|
245
|
-
requires_auth=True,
|
|
246
|
-
callouts=[
|
|
247
|
-
((0.15, 0.11), "상단 IN 셸", "Fulfillment 화면에서도 Overview/Fulfillment 전환과 사용자 액션이 동일한 헤더 구조를 유지한다."),
|
|
248
|
-
((0.36, 0.23), "Fulfillment board 헤더", "현재 이행 보드 화면의 제목과 task surface 설명을 상단에서 제공한다."),
|
|
249
|
-
((0.39, 0.58), "Fulfillment board 테이블", "Order, task, assignee, status, SLA를 행 단위로 정리한 메인 운영 테이블이다."),
|
|
250
|
-
((0.83, 0.59), "Fulfillment notes", "이행 메모와 운영 체크포인트를 별도 패널로 분리해 보조 컨텍스트를 제공한다."),
|
|
251
|
-
],
|
|
252
|
-
),
|
|
253
|
-
],
|
|
254
|
-
},
|
|
255
|
-
"landing": {
|
|
256
|
-
"title": "Templates Landing Screen Spec",
|
|
257
|
-
"service_label": "landing",
|
|
258
|
-
"output": str(SCREEN_DIR / "landing_screen_spec.pdf"),
|
|
259
|
-
"asset_dir": str(ASSET_DIR / "landing_screen_capture"),
|
|
260
|
-
"base_url": "http://127.0.0.1:3000",
|
|
261
|
-
"api_base": "http://127.0.0.1:8000/api/v1",
|
|
262
|
-
"storage_key": "landing.auth.token",
|
|
263
|
-
"capture_policy": DESKTOP_CAPTURE_POLICY,
|
|
264
|
-
"trim_background": False,
|
|
265
|
-
"cover_note": "첫 페이지는 landing 화면코드 인덱스다. 이후 페이지는 좌측 화면 캡처와 우측 번호형 기능 테이블을 함께 제공한다.",
|
|
266
|
-
"source_refs": [
|
|
267
|
-
{"label": "implementation", "path": "client/landing/src/App.tsx"},
|
|
268
|
-
{"label": "implementation", "path": "client/landing/src/pages"},
|
|
269
|
-
{"label": "capture assets", "path": "sdd/99_toolchain/01_automation/assets/landing_screen_capture"},
|
|
270
|
-
],
|
|
271
|
-
"screens": [
|
|
272
|
-
screen(
|
|
273
|
-
code="LND-S001",
|
|
274
|
-
name="Landing Home",
|
|
275
|
-
route="/",
|
|
276
|
-
access="public",
|
|
277
|
-
features=["CAT-F001", "AUT-F002"],
|
|
278
|
-
asset="home.png",
|
|
279
|
-
requires_auth=False,
|
|
280
|
-
callouts=[
|
|
281
|
-
((0.16, 0.05), "글로벌 헤더", "브랜드, 섹션 앵커, 로그인 또는 workspace handoff 링크를 상단 헤더에 배치한다."),
|
|
282
|
-
((0.27, 0.20), "히어로 메시지와 CTA", "서비스 가치 제안과 Sign in/See examples CTA를 첫 섹션에서 강조한다."),
|
|
283
|
-
((0.77, 0.25), "카탈로그 스냅샷", "실시간 product 수, active count, highlighted catalog 상태를 요약 카드로 보여준다."),
|
|
284
|
-
((0.30, 0.56), "Features grid", "라이브 catalog product를 카드 그리드로 노출하는 예시 섹션이다."),
|
|
285
|
-
((0.50, 0.75), "Live proof 섹션", "`/api/v1/catalog/products` 기반 sync 결과를 집계 카드와 함께 증빙한다."),
|
|
286
|
-
((0.50, 0.92), "마무리 CTA", "템플릿 시작 CTA로 로그인 또는 workspace 진입을 유도하는 하단 배너다."),
|
|
287
|
-
],
|
|
288
|
-
),
|
|
289
|
-
screen(
|
|
290
|
-
code="LND-S002",
|
|
291
|
-
name="Landing Login",
|
|
292
|
-
route="/login",
|
|
293
|
-
access="public",
|
|
294
|
-
features=["AUT-F001", "AUT-F002"],
|
|
295
|
-
asset="login.png",
|
|
296
|
-
requires_auth=False,
|
|
297
|
-
callouts=[
|
|
298
|
-
((0.24, 0.34), "랜딩 소개 패널", "로그인 후 `/workspace`로 이어지는 흐름과 landing 복귀 링크를 좌측 소개 영역에서 설명한다."),
|
|
299
|
-
((0.78, 0.20), "Sign in 헤더", "멤버 접근 맥락과 workspace 진입 목적을 우측 로그인 폼 상단에 둔다."),
|
|
300
|
-
((0.78, 0.39), "자격 증명 입력", "이메일, 비밀번호, 오류 메시지를 같은 카드 안에서 처리한다."),
|
|
301
|
-
((0.78, 0.50), "Continue CTA", "성공 시 토큰 저장 후 보호된 `/workspace`로 이동한다."),
|
|
302
|
-
],
|
|
303
|
-
),
|
|
304
|
-
screen(
|
|
305
|
-
code="LND-S003",
|
|
306
|
-
name="Landing Workspace",
|
|
307
|
-
route="/workspace",
|
|
308
|
-
access="protected",
|
|
309
|
-
features=["AUT-F002", "CAT-F001"],
|
|
310
|
-
asset="workspace.png",
|
|
311
|
-
requires_auth=True,
|
|
312
|
-
callouts=[
|
|
313
|
-
((0.16, 0.07), "멤버 셸 헤더", "Workspace 링크, 현재 사용자, 로그아웃을 포함한 보호 라우트 전용 헤더다."),
|
|
314
|
-
((0.30, 0.32), "Protected workspace 카드", "인증된 사용자 전용 shell 설명과 catalog sync 상태를 메인 카드에 배치한다."),
|
|
315
|
-
((0.77, 0.32), "Current member 카드", "현재 로그인 사용자의 email, role, status를 우측 패널에서 보여준다."),
|
|
316
|
-
((0.30, 0.78), "Workspace product grid", "보호 라우트 안에서 조회한 product 목록을 카드 그리드로 렌더링한다."),
|
|
317
|
-
],
|
|
318
|
-
),
|
|
319
|
-
],
|
|
320
|
-
},
|
|
321
|
-
}
|
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import argparse
|
|
4
|
-
import atexit
|
|
5
|
-
import base64
|
|
6
|
-
import importlib.util
|
|
7
|
-
import re
|
|
8
|
-
import shutil
|
|
9
|
-
import subprocess
|
|
10
|
-
import tempfile
|
|
11
|
-
from io import BytesIO
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
from typing import Sequence
|
|
14
|
-
|
|
15
|
-
from PIL import Image, ImageChops
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
TEMP_DIR = Path(tempfile.mkdtemp(prefix="spec-asset-builder-"))
|
|
19
|
-
PAGE_CACHE: dict[tuple[str, int, int], Image.Image] = {}
|
|
20
|
-
SVG_IMAGE_HREF_PATTERN = re.compile(r'href="data:image/png;base64,([^"]+)"')
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def cleanup_tempdir() -> None:
|
|
24
|
-
shutil.rmtree(TEMP_DIR, ignore_errors=True)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
atexit.register(cleanup_tempdir)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def parse_args(
|
|
31
|
-
argv: Sequence[str] | None = None,
|
|
32
|
-
*,
|
|
33
|
-
default_manifest: Path | None = None,
|
|
34
|
-
default_recipes_var: str = "ASSET_RECIPES",
|
|
35
|
-
) -> argparse.Namespace:
|
|
36
|
-
parser = argparse.ArgumentParser(description="Build static design assets from a recipe manifest.")
|
|
37
|
-
parser.add_argument("--manifest", default=str(default_manifest) if default_manifest else None, help="Path to the Python recipe manifest.")
|
|
38
|
-
parser.add_argument("--recipes-var", default=default_recipes_var, help="Manifest variable name that contains the recipe list.")
|
|
39
|
-
parser.add_argument("--asset", action="append", dest="assets", help="Asset id to build. Repeatable. Default builds all assets.")
|
|
40
|
-
parser.add_argument("--list", action="store_true", help="List available asset ids and exit.")
|
|
41
|
-
parser.add_argument("--verify-exact", action="store_true", help="Verify that each generated output is pixel-identical to the resolved source crop.")
|
|
42
|
-
args = parser.parse_args(argv)
|
|
43
|
-
|
|
44
|
-
if not args.manifest:
|
|
45
|
-
parser.error("--manifest is required")
|
|
46
|
-
|
|
47
|
-
return args
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def load_manifest(manifest_path: Path, recipes_var: str) -> list[dict]:
|
|
51
|
-
spec = importlib.util.spec_from_file_location("asset_recipe_manifest", manifest_path)
|
|
52
|
-
if spec is None or spec.loader is None:
|
|
53
|
-
raise SystemExit(f"Unable to load manifest: {manifest_path}")
|
|
54
|
-
|
|
55
|
-
module = importlib.util.module_from_spec(spec)
|
|
56
|
-
spec.loader.exec_module(module)
|
|
57
|
-
recipes = getattr(module, recipes_var, None)
|
|
58
|
-
if recipes is None:
|
|
59
|
-
raise SystemExit(f"Manifest {manifest_path} does not define {recipes_var}")
|
|
60
|
-
if not isinstance(recipes, list):
|
|
61
|
-
raise SystemExit(f"{recipes_var} in {manifest_path} must be a list")
|
|
62
|
-
return recipes
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def load_pdf_page(path: Path, page: int, dpi: int) -> Image.Image:
|
|
66
|
-
key = (str(path), page, dpi)
|
|
67
|
-
cached = PAGE_CACHE.get(key)
|
|
68
|
-
if cached is not None:
|
|
69
|
-
return cached.copy()
|
|
70
|
-
|
|
71
|
-
output_prefix = TEMP_DIR / f"{path.stem}-p{page}-{dpi}"
|
|
72
|
-
subprocess.run(
|
|
73
|
-
[
|
|
74
|
-
"pdftoppm",
|
|
75
|
-
"-png",
|
|
76
|
-
"-singlefile",
|
|
77
|
-
"-f",
|
|
78
|
-
str(page),
|
|
79
|
-
"-l",
|
|
80
|
-
str(page),
|
|
81
|
-
"-r",
|
|
82
|
-
str(dpi),
|
|
83
|
-
str(path),
|
|
84
|
-
str(output_prefix),
|
|
85
|
-
],
|
|
86
|
-
capture_output=True,
|
|
87
|
-
text=True,
|
|
88
|
-
check=True,
|
|
89
|
-
)
|
|
90
|
-
image = Image.open(output_prefix.with_suffix(".png")).convert("RGBA")
|
|
91
|
-
PAGE_CACHE[key] = image.copy()
|
|
92
|
-
return image
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def load_image(path: Path) -> Image.Image:
|
|
96
|
-
return Image.open(path).convert("RGBA")
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def resolve_source(source: dict) -> Image.Image:
|
|
100
|
-
kind = source["kind"]
|
|
101
|
-
if kind == "pdf_page":
|
|
102
|
-
return load_pdf_page(Path(source["path"]), int(source["page"]), int(source["dpi"]))
|
|
103
|
-
if kind == "image":
|
|
104
|
-
return load_image(Path(source["path"]))
|
|
105
|
-
raise ValueError(f"Unsupported source kind: {kind}")
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def make_white_transparent(image: Image.Image, threshold: int) -> Image.Image:
|
|
109
|
-
converted = image.convert("RGBA")
|
|
110
|
-
pixels = []
|
|
111
|
-
for red, green, blue, alpha in converted.getdata():
|
|
112
|
-
if alpha and red >= threshold and green >= threshold and blue >= threshold:
|
|
113
|
-
pixels.append((255, 255, 255, 0))
|
|
114
|
-
else:
|
|
115
|
-
pixels.append((red, green, blue, alpha))
|
|
116
|
-
converted.putdata(pixels)
|
|
117
|
-
return converted
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def transform_image(image: Image.Image, recipe: dict) -> Image.Image:
|
|
121
|
-
working = image.copy()
|
|
122
|
-
|
|
123
|
-
crop_box = recipe.get("crop_box")
|
|
124
|
-
if crop_box is not None:
|
|
125
|
-
working = working.crop(tuple(crop_box))
|
|
126
|
-
|
|
127
|
-
threshold = recipe.get("transparent_white_threshold")
|
|
128
|
-
if threshold is not None:
|
|
129
|
-
working = make_white_transparent(working, int(threshold))
|
|
130
|
-
|
|
131
|
-
if recipe.get("trim"):
|
|
132
|
-
bbox = working.getbbox()
|
|
133
|
-
if not bbox:
|
|
134
|
-
raise ValueError(f"Recipe {recipe['id']} trimmed to empty image")
|
|
135
|
-
working = working.crop(bbox)
|
|
136
|
-
|
|
137
|
-
return working
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
def encode_svg(image: Image.Image) -> str:
|
|
141
|
-
buffer = BytesIO()
|
|
142
|
-
image.save(buffer, format="PNG")
|
|
143
|
-
payload = base64.b64encode(buffer.getvalue()).decode("ascii")
|
|
144
|
-
return (
|
|
145
|
-
f'<svg xmlns="http://www.w3.org/2000/svg" width="{image.width}" height="{image.height}" '
|
|
146
|
-
f'viewBox="0 0 {image.width} {image.height}" fill="none" role="img" aria-hidden="true">\n'
|
|
147
|
-
f' <image width="{image.width}" height="{image.height}" href="data:image/png;base64,{payload}" />\n'
|
|
148
|
-
"</svg>\n"
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
def write_output(image: Image.Image, output_path: Path, output_format: str) -> None:
|
|
153
|
-
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
154
|
-
if output_format == "svg":
|
|
155
|
-
output_path.write_text(encode_svg(image), encoding="utf-8")
|
|
156
|
-
return
|
|
157
|
-
if output_format == "png":
|
|
158
|
-
image.save(output_path, format="PNG")
|
|
159
|
-
return
|
|
160
|
-
raise ValueError(f"Unsupported output format: {output_format}")
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
def read_output_image(output_path: Path, output_format: str) -> Image.Image:
|
|
164
|
-
if output_format == "png":
|
|
165
|
-
return Image.open(output_path).convert("RGBA")
|
|
166
|
-
if output_format == "svg":
|
|
167
|
-
raw = output_path.read_text(encoding="utf-8")
|
|
168
|
-
matched = SVG_IMAGE_HREF_PATTERN.search(raw)
|
|
169
|
-
if not matched:
|
|
170
|
-
raise ValueError(f"Unable to decode embedded PNG from {output_path}")
|
|
171
|
-
buffer = BytesIO(base64.b64decode(matched.group(1)))
|
|
172
|
-
return Image.open(buffer).convert("RGBA")
|
|
173
|
-
raise ValueError(f"Unsupported output format: {output_format}")
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
def verify_exact_output(output_path: Path, output_format: str, expected_image: Image.Image) -> None:
|
|
177
|
-
actual = read_output_image(output_path, output_format)
|
|
178
|
-
expected = expected_image.convert("RGBA")
|
|
179
|
-
|
|
180
|
-
if actual.size != expected.size:
|
|
181
|
-
raise SystemExit(f"Exact verification failed for {output_path}: size mismatch {actual.size} != {expected.size}")
|
|
182
|
-
|
|
183
|
-
if ImageChops.difference(actual, expected).getbbox() is not None:
|
|
184
|
-
raise SystemExit(f"Exact verification failed for {output_path}: pixel mismatch")
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
def infer_output_format(recipe: dict, output_path: Path) -> str:
|
|
188
|
-
if recipe.get("output_format"):
|
|
189
|
-
return str(recipe["output_format"])
|
|
190
|
-
if output_path.suffix.lower() == ".png":
|
|
191
|
-
return "png"
|
|
192
|
-
return "svg"
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
def emit_recipe(
|
|
196
|
-
recipe: dict,
|
|
197
|
-
*,
|
|
198
|
-
source_image: Image.Image | None = None,
|
|
199
|
-
selected_assets: set[str] | None = None,
|
|
200
|
-
verify_exact: bool = False,
|
|
201
|
-
) -> list[Path]:
|
|
202
|
-
source = source_image if source_image is not None else resolve_source(recipe["source"])
|
|
203
|
-
rendered = transform_image(source, recipe)
|
|
204
|
-
written: list[Path] = []
|
|
205
|
-
|
|
206
|
-
output = recipe.get("output")
|
|
207
|
-
if output is not None and (selected_assets is None or recipe["id"] in selected_assets):
|
|
208
|
-
output_path = Path(output)
|
|
209
|
-
output_format = infer_output_format(recipe, output_path)
|
|
210
|
-
write_output(rendered, output_path, output_format)
|
|
211
|
-
if verify_exact:
|
|
212
|
-
verify_exact_output(output_path, output_format, rendered)
|
|
213
|
-
written.append(output_path)
|
|
214
|
-
|
|
215
|
-
for child in recipe.get("children", []):
|
|
216
|
-
written.extend(
|
|
217
|
-
emit_recipe(
|
|
218
|
-
child,
|
|
219
|
-
source_image=rendered,
|
|
220
|
-
selected_assets=selected_assets,
|
|
221
|
-
verify_exact=verify_exact,
|
|
222
|
-
)
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
return written
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
def collect_asset_ids(recipes: list[dict]) -> list[str]:
|
|
229
|
-
asset_ids: list[str] = []
|
|
230
|
-
for recipe in recipes:
|
|
231
|
-
if recipe.get("output") is not None:
|
|
232
|
-
asset_ids.append(recipe["id"])
|
|
233
|
-
asset_ids.extend(collect_asset_ids(recipe.get("children", [])))
|
|
234
|
-
return asset_ids
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
def main(
|
|
238
|
-
argv: Sequence[str] | None = None,
|
|
239
|
-
*,
|
|
240
|
-
default_manifest: Path | None = None,
|
|
241
|
-
default_recipes_var: str = "ASSET_RECIPES",
|
|
242
|
-
) -> None:
|
|
243
|
-
args = parse_args(argv, default_manifest=default_manifest, default_recipes_var=default_recipes_var)
|
|
244
|
-
manifest_path = Path(args.manifest).resolve()
|
|
245
|
-
recipes = load_manifest(manifest_path, args.recipes_var)
|
|
246
|
-
asset_ids = collect_asset_ids(recipes)
|
|
247
|
-
|
|
248
|
-
if args.list:
|
|
249
|
-
for asset_id in asset_ids:
|
|
250
|
-
print(asset_id)
|
|
251
|
-
return
|
|
252
|
-
|
|
253
|
-
selected_assets = set(args.assets) if args.assets else None
|
|
254
|
-
if selected_assets is not None:
|
|
255
|
-
unknown = sorted(selected_assets.difference(asset_ids))
|
|
256
|
-
if unknown:
|
|
257
|
-
raise SystemExit(f"Unknown asset ids: {', '.join(unknown)}")
|
|
258
|
-
|
|
259
|
-
written: list[Path] = []
|
|
260
|
-
for recipe in recipes:
|
|
261
|
-
written.extend(
|
|
262
|
-
emit_recipe(
|
|
263
|
-
recipe,
|
|
264
|
-
selected_assets=selected_assets,
|
|
265
|
-
verify_exact=args.verify_exact,
|
|
266
|
-
)
|
|
267
|
-
)
|
|
268
|
-
|
|
269
|
-
for path in written:
|
|
270
|
-
print(path)
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
if __name__ == "__main__":
|
|
274
|
-
main()
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# UI Contract Projection
|
|
2
|
-
|
|
3
|
-
`UI Contract Projection`은 화면설계서, 계약 문서, reference asset을 제품 UI 구조 위로 투영하고 검증하는 템플릿/스킬 계층의 공통 명칭이다.
|
|
4
|
-
|
|
5
|
-
## Canonical Naming
|
|
6
|
-
|
|
7
|
-
- capability: `UI Contract Projection`
|
|
8
|
-
- modes:
|
|
9
|
-
- `strict projection`
|
|
10
|
-
- `soft projection`
|
|
11
|
-
- common actions:
|
|
12
|
-
- `project`
|
|
13
|
-
- `verify`
|
|
14
|
-
- `report`
|
|
15
|
-
|
|
16
|
-
## Ownership Boundary
|
|
17
|
-
|
|
18
|
-
- 이 문서는 Claude/Codex 스킬과 CLI 래퍼가 공유할 일반 템플릿 계약만 정의한다.
|
|
19
|
-
- 제품별 screen registry, contract rows, evidence 경로는 각 제품 저장소의 `sdd`에서 확장한다.
|
|
20
|
-
- 제품 런타임 route, auth, layout은 이 템플릿을 이유로 분기하지 않는다.
|
|
21
|
-
|
|
22
|
-
## Skill Prompt Skeleton
|
|
23
|
-
|
|
24
|
-
```md
|
|
25
|
-
Goal: run UI Contract Projection for {product} {screen_or_flow}
|
|
26
|
-
Mode: {strict projection | soft projection}
|
|
27
|
-
Inputs:
|
|
28
|
-
- contract: {path}
|
|
29
|
-
- source artifact: {pdf|figma export|reference image|yaml}
|
|
30
|
-
- product target: {repo path or route}
|
|
31
|
-
|
|
32
|
-
Rules:
|
|
33
|
-
- Preserve product runtime behavior.
|
|
34
|
-
- Use React + shadcn/ui primitives and CSS token surface first.
|
|
35
|
-
- Keep projection assets in sdd/toolchain only.
|
|
36
|
-
- Do not add spec/proof/parity-only branches to runtime.
|
|
37
|
-
|
|
38
|
-
Outputs:
|
|
39
|
-
- updated product UI
|
|
40
|
-
- updated sdd contract/evidence
|
|
41
|
-
- projection report
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## CLI Contract Template
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
ui-contract-projection project \
|
|
48
|
-
--mode strict \
|
|
49
|
-
--contract <path> \
|
|
50
|
-
--source <path-or-id> \
|
|
51
|
-
--target <repo-or-route>
|
|
52
|
-
|
|
53
|
-
ui-contract-projection verify \
|
|
54
|
-
--mode strict \
|
|
55
|
-
--contract <path> \
|
|
56
|
-
--target <url-or-route> \
|
|
57
|
-
--evidence-root <path>
|
|
58
|
-
|
|
59
|
-
ui-contract-projection report \
|
|
60
|
-
--contract <path> \
|
|
61
|
-
--evidence-root <path> \
|
|
62
|
-
--format markdown
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Required Gates
|
|
66
|
-
|
|
67
|
-
1. `Structure`
|
|
68
|
-
2. `Behavior`
|
|
69
|
-
3. `Data`
|
|
70
|
-
4. `UI Contract Projection`
|
|
71
|
-
|
|
72
|
-
`strict projection`은 앞선 세 gate를 통과한 뒤에만 사용한다.
|
|
73
|
-
|
|
74
|
-
## Frontend Defaults
|
|
75
|
-
|
|
76
|
-
- `React + shadcn/ui`
|
|
77
|
-
- CSS token surface
|
|
78
|
-
- style expansion via `scss`, `styled-components`, or equivalent modern layer
|
|
79
|
-
- shared primitives before screen-specific markup
|