gaia-framework 1.57.0 → 1.57.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/gaia-framework.js +27 -19
- package/gaia-install.sh +1 -1
- package/package.json +15 -11
- package/.claude/commands/gaia-a11y-testing.md +0 -17
- package/.claude/commands/gaia-action-items.md +0 -23
- package/.claude/commands/gaia-add-feature.md +0 -17
- package/.claude/commands/gaia-add-stories.md +0 -17
- package/.claude/commands/gaia-advanced-elicitation.md +0 -17
- package/.claude/commands/gaia-adversarial.md +0 -15
- package/.claude/commands/gaia-agent-analyst.md +0 -14
- package/.claude/commands/gaia-agent-architect.md +0 -14
- package/.claude/commands/gaia-agent-brainstorming.md +0 -14
- package/.claude/commands/gaia-agent-data-engineer.md +0 -14
- package/.claude/commands/gaia-agent-design-thinking.md +0 -14
- package/.claude/commands/gaia-agent-dev-angular.md +0 -14
- package/.claude/commands/gaia-agent-dev-flutter.md +0 -14
- package/.claude/commands/gaia-agent-dev-go.md +0 -14
- package/.claude/commands/gaia-agent-dev-java.md +0 -14
- package/.claude/commands/gaia-agent-dev-mobile.md +0 -14
- package/.claude/commands/gaia-agent-dev-python.md +0 -14
- package/.claude/commands/gaia-agent-dev-typescript.md +0 -14
- package/.claude/commands/gaia-agent-devops.md +0 -14
- package/.claude/commands/gaia-agent-innovation.md +0 -14
- package/.claude/commands/gaia-agent-performance.md +0 -14
- package/.claude/commands/gaia-agent-pm.md +0 -14
- package/.claude/commands/gaia-agent-presentation.md +0 -14
- package/.claude/commands/gaia-agent-problem-solver.md +0 -14
- package/.claude/commands/gaia-agent-qa.md +0 -14
- package/.claude/commands/gaia-agent-security.md +0 -14
- package/.claude/commands/gaia-agent-sm.md +0 -14
- package/.claude/commands/gaia-agent-storyteller.md +0 -14
- package/.claude/commands/gaia-agent-tech-writer.md +0 -14
- package/.claude/commands/gaia-agent-test-architect.md +0 -14
- package/.claude/commands/gaia-agent-ux-designer.md +0 -14
- package/.claude/commands/gaia-agent-validator.md +0 -14
- package/.claude/commands/gaia-atdd.md +0 -17
- package/.claude/commands/gaia-brainstorm.md +0 -17
- package/.claude/commands/gaia-brainstorming.md +0 -17
- package/.claude/commands/gaia-brownfield.md +0 -17
- package/.claude/commands/gaia-build-configs.md +0 -22
- package/.claude/commands/gaia-change-request.md +0 -11
- package/.claude/commands/gaia-changelog.md +0 -16
- package/.claude/commands/gaia-check-dod.md +0 -17
- package/.claude/commands/gaia-check-review-gate.md +0 -17
- package/.claude/commands/gaia-ci-setup.md +0 -17
- package/.claude/commands/gaia-code-review.md +0 -17
- package/.claude/commands/gaia-correct-course.md +0 -17
- package/.claude/commands/gaia-create-arch.md +0 -17
- package/.claude/commands/gaia-create-epics.md +0 -17
- package/.claude/commands/gaia-create-prd.md +0 -17
- package/.claude/commands/gaia-create-story.md +0 -23
- package/.claude/commands/gaia-create-ux.md +0 -17
- package/.claude/commands/gaia-creative-sprint.md +0 -17
- package/.claude/commands/gaia-deploy-checklist.md +0 -17
- package/.claude/commands/gaia-design-thinking.md +0 -17
- package/.claude/commands/gaia-dev-story.md +0 -23
- package/.claude/commands/gaia-document-project.md +0 -17
- package/.claude/commands/gaia-domain-research.md +0 -17
- package/.claude/commands/gaia-edge-cases.md +0 -15
- package/.claude/commands/gaia-edit-arch.md +0 -17
- package/.claude/commands/gaia-edit-prd.md +0 -17
- package/.claude/commands/gaia-edit-test-plan.md +0 -17
- package/.claude/commands/gaia-editorial-prose.md +0 -15
- package/.claude/commands/gaia-editorial-structure.md +0 -15
- package/.claude/commands/gaia-epic-status.md +0 -17
- package/.claude/commands/gaia-fix-story.md +0 -17
- package/.claude/commands/gaia-help.md +0 -15
- package/.claude/commands/gaia-index-docs.md +0 -15
- package/.claude/commands/gaia-infra-design.md +0 -17
- package/.claude/commands/gaia-innovation.md +0 -17
- package/.claude/commands/gaia-market-research.md +0 -17
- package/.claude/commands/gaia-memory-hygiene.md +0 -17
- package/.claude/commands/gaia-merge-docs.md +0 -16
- package/.claude/commands/gaia-mobile-testing.md +0 -17
- package/.claude/commands/gaia-nfr.md +0 -17
- package/.claude/commands/gaia-party.md +0 -17
- package/.claude/commands/gaia-perf-testing.md +0 -17
- package/.claude/commands/gaia-performance-review.md +0 -17
- package/.claude/commands/gaia-pitch-deck.md +0 -17
- package/.claude/commands/gaia-post-deploy.md +0 -17
- package/.claude/commands/gaia-problem-solving.md +0 -17
- package/.claude/commands/gaia-product-brief.md +0 -17
- package/.claude/commands/gaia-project-context.md +0 -17
- package/.claude/commands/gaia-qa-tests.md +0 -17
- package/.claude/commands/gaia-quick-dev.md +0 -17
- package/.claude/commands/gaia-quick-spec.md +0 -17
- package/.claude/commands/gaia-readiness-check.md +0 -17
- package/.claude/commands/gaia-refresh-ground-truth.md +0 -17
- package/.claude/commands/gaia-release-plan.md +0 -17
- package/.claude/commands/gaia-resume.md +0 -25
- package/.claude/commands/gaia-retro.md +0 -20
- package/.claude/commands/gaia-review-a11y.md +0 -16
- package/.claude/commands/gaia-review-api.md +0 -16
- package/.claude/commands/gaia-review-deps.md +0 -16
- package/.claude/commands/gaia-review-perf.md +0 -16
- package/.claude/commands/gaia-review-security.md +0 -16
- package/.claude/commands/gaia-rollback-plan.md +0 -17
- package/.claude/commands/gaia-run-all-reviews.md +0 -17
- package/.claude/commands/gaia-security-review.md +0 -17
- package/.claude/commands/gaia-shard-doc.md +0 -15
- package/.claude/commands/gaia-slide-deck.md +0 -17
- package/.claude/commands/gaia-sprint-plan.md +0 -17
- package/.claude/commands/gaia-sprint-status.md +0 -17
- package/.claude/commands/gaia-storytelling.md +0 -17
- package/.claude/commands/gaia-summarize.md +0 -16
- package/.claude/commands/gaia-teach-testing.md +0 -17
- package/.claude/commands/gaia-tech-debt-review.md +0 -20
- package/.claude/commands/gaia-tech-research.md +0 -17
- package/.claude/commands/gaia-test-automate.md +0 -17
- package/.claude/commands/gaia-test-design.md +0 -17
- package/.claude/commands/gaia-test-framework.md +0 -17
- package/.claude/commands/gaia-test-review.md +0 -17
- package/.claude/commands/gaia-threat-model.md +0 -17
- package/.claude/commands/gaia-trace.md +0 -17
- package/.claude/commands/gaia-triage-findings.md +0 -20
- package/.claude/commands/gaia-val-validate-plan.md +0 -17
- package/.claude/commands/gaia-val-validate.md +0 -17
- package/.claude/commands/gaia-validate-framework.md +0 -17
- package/.claude/commands/gaia-validate-prd.md +0 -17
- package/.claude/commands/gaia-validate-story.md +0 -22
- package/.claude/commands/gaia.md +0 -32
- package/CLAUDE.md +0 -165
- package/_gaia/_config/agent-manifest.csv +0 -29
- package/_gaia/_config/agents/CUSTOMIZATION-README.md +0 -117
- package/_gaia/_config/files-manifest.csv +0 -30
- package/_gaia/_config/gaia-help.csv +0 -82
- package/_gaia/_config/global.yaml +0 -45
- package/_gaia/_config/lifecycle-sequence.yaml +0 -593
- package/_gaia/_config/manifest.yaml +0 -24
- package/_gaia/_config/skill-manifest.csv +0 -12
- package/_gaia/_config/task-manifest.csv +0 -17
- package/_gaia/_config/workflow-manifest.csv +0 -73
- package/_gaia/_memory/tier2-results/.gitkeep +0 -0
- package/_gaia/_memory/tier2-results/checkpoint-resume-2026-03-24.yaml +0 -6
- package/_gaia/_memory/tier2-results/engine-scenarios-2026-03-22.yaml +0 -14
- package/_gaia/core/.resolved/.gitkeep +0 -0
- package/_gaia/core/agents/orchestrator.md +0 -303
- package/_gaia/core/config.yaml +0 -8
- package/_gaia/core/engine/error-recovery.xml +0 -28
- package/_gaia/core/engine/protocols/discover-inputs.xml +0 -31
- package/_gaia/core/engine/protocols/handoff.xml +0 -21
- package/_gaia/core/engine/protocols/preflight-check.xml +0 -31
- package/_gaia/core/engine/task-runner.xml +0 -63
- package/_gaia/core/engine/workflow.xml +0 -225
- package/_gaia/core/module-help.csv +0 -21
- package/_gaia/core/protocols/agent-specification-protocol.md +0 -103
- package/_gaia/core/protocols/review-gate-check.xml +0 -29
- package/_gaia/core/protocols/sprint-status-write-safety.xml +0 -35
- package/_gaia/core/protocols/status-sync.xml +0 -49
- package/_gaia/core/tasks/editorial-review-prose.xml +0 -42
- package/_gaia/core/tasks/editorial-review-structure.xml +0 -43
- package/_gaia/core/tasks/generate-changelog.xml +0 -35
- package/_gaia/core/tasks/help.md +0 -45
- package/_gaia/core/tasks/index-docs.xml +0 -46
- package/_gaia/core/tasks/merge-docs.xml +0 -34
- package/_gaia/core/tasks/review-accessibility.xml +0 -47
- package/_gaia/core/tasks/review-adversarial.xml +0 -55
- package/_gaia/core/tasks/review-api-design.xml +0 -38
- package/_gaia/core/tasks/review-dependency-audit.xml +0 -38
- package/_gaia/core/tasks/review-edge-case-hunter.xml +0 -52
- package/_gaia/core/tasks/review-performance.xml +0 -49
- package/_gaia/core/tasks/review-security.xml +0 -37
- package/_gaia/core/tasks/shard-doc.xml +0 -49
- package/_gaia/core/tasks/summarize-doc.xml +0 -33
- package/_gaia/core/tasks/validate-framework.xml +0 -66
- package/_gaia/core/workflows/brainstorming/steps/step-01-session-setup.md +0 -7
- package/_gaia/core/workflows/brainstorming/steps/step-02-technique-selection.md +0 -20
- package/_gaia/core/workflows/brainstorming/steps/step-03-technique-execution.md +0 -11
- package/_gaia/core/workflows/brainstorming/steps/step-04-idea-organization.md +0 -14
- package/_gaia/core/workflows/brainstorming/template.md +0 -38
- package/_gaia/core/workflows/brainstorming/workflow.yaml +0 -26
- package/_gaia/core/workflows/party-mode/steps/step-01-agent-loading.md +0 -11
- package/_gaia/core/workflows/party-mode/steps/step-02-discussion-orchestration.md +0 -16
- package/_gaia/core/workflows/party-mode/steps/step-03-graceful-exit.md +0 -10
- package/_gaia/core/workflows/party-mode/workflow.yaml +0 -23
- package/_gaia/creative/.resolved/.gitkeep +0 -0
- package/_gaia/creative/agents/brainstorming-coach.md +0 -93
- package/_gaia/creative/agents/design-thinking-coach.md +0 -91
- package/_gaia/creative/agents/innovation-strategist.md +0 -89
- package/_gaia/creative/agents/presentation-designer.md +0 -99
- package/_gaia/creative/agents/problem-solver.md +0 -90
- package/_gaia/creative/agents/storyteller.md +0 -90
- package/_gaia/creative/config.yaml +0 -8
- package/_gaia/creative/data/design-methods.csv +0 -28
- package/_gaia/creative/data/innovation-frameworks.csv +0 -15
- package/_gaia/creative/data/solving-methods.csv +0 -14
- package/_gaia/creative/data/story-types.csv +0 -12
- package/_gaia/creative/module-help.csv +0 -8
- package/_gaia/creative/teams/creative-squad.yaml +0 -10
- package/_gaia/creative/workflows/creative-sprint/checklist.md +0 -10
- package/_gaia/creative/workflows/creative-sprint/instructions.xml +0 -40
- package/_gaia/creative/workflows/creative-sprint/workflow.yaml +0 -11
- package/_gaia/creative/workflows/design-thinking/checklist.md +0 -25
- package/_gaia/creative/workflows/design-thinking/instructions.xml +0 -38
- package/_gaia/creative/workflows/design-thinking/workflow.yaml +0 -13
- package/_gaia/creative/workflows/innovation-strategy/checklist.md +0 -26
- package/_gaia/creative/workflows/innovation-strategy/instructions.xml +0 -34
- package/_gaia/creative/workflows/innovation-strategy/workflow.yaml +0 -13
- package/_gaia/creative/workflows/pitch-deck/checklist.md +0 -22
- package/_gaia/creative/workflows/pitch-deck/instructions.xml +0 -49
- package/_gaia/creative/workflows/pitch-deck/workflow.yaml +0 -15
- package/_gaia/creative/workflows/problem-solving/checklist.md +0 -26
- package/_gaia/creative/workflows/problem-solving/instructions.xml +0 -39
- package/_gaia/creative/workflows/problem-solving/workflow.yaml +0 -13
- package/_gaia/creative/workflows/slide-deck/checklist.md +0 -21
- package/_gaia/creative/workflows/slide-deck/instructions.xml +0 -39
- package/_gaia/creative/workflows/slide-deck/workflow.yaml +0 -15
- package/_gaia/creative/workflows/storytelling/checklist.md +0 -26
- package/_gaia/creative/workflows/storytelling/instructions.xml +0 -38
- package/_gaia/creative/workflows/storytelling/workflow.yaml +0 -13
- package/_gaia/dev/agents/_base-dev.md +0 -180
- package/_gaia/dev/agents/angular-dev.md +0 -70
- package/_gaia/dev/agents/flutter-dev.md +0 -70
- package/_gaia/dev/agents/go-dev.md +0 -72
- package/_gaia/dev/agents/java-dev.md +0 -70
- package/_gaia/dev/agents/mobile-dev.md +0 -70
- package/_gaia/dev/agents/python-dev.md +0 -70
- package/_gaia/dev/agents/typescript-dev.md +0 -70
- package/_gaia/dev/config.yaml +0 -11
- package/_gaia/dev/knowledge/_index.csv +0 -25
- package/_gaia/dev/knowledge/angular/angular-conventions.md +0 -119
- package/_gaia/dev/knowledge/angular/angular-patterns.md +0 -126
- package/_gaia/dev/knowledge/angular/ngrx-state.md +0 -124
- package/_gaia/dev/knowledge/angular/rxjs-patterns.md +0 -119
- package/_gaia/dev/knowledge/flutter/dart-conventions.md +0 -143
- package/_gaia/dev/knowledge/flutter/platform-channels.md +0 -144
- package/_gaia/dev/knowledge/flutter/state-management.md +0 -144
- package/_gaia/dev/knowledge/flutter/widget-patterns.md +0 -134
- package/_gaia/dev/knowledge/go/gin-fiber-patterns.md +0 -40
- package/_gaia/dev/knowledge/go/go-conventions.md +0 -54
- package/_gaia/dev/knowledge/go/go-stdlib-patterns.md +0 -39
- package/_gaia/dev/knowledge/go/go-testing-patterns.md +0 -39
- package/_gaia/dev/knowledge/java/jpa-patterns.md +0 -136
- package/_gaia/dev/knowledge/java/maven-gradle.md +0 -189
- package/_gaia/dev/knowledge/java/microservices.md +0 -159
- package/_gaia/dev/knowledge/java/spring-boot-patterns.md +0 -160
- package/_gaia/dev/knowledge/mobile/kotlin-patterns.md +0 -193
- package/_gaia/dev/knowledge/mobile/mobile-testing.md +0 -186
- package/_gaia/dev/knowledge/mobile/react-native-patterns.md +0 -162
- package/_gaia/dev/knowledge/mobile/swift-patterns.md +0 -190
- package/_gaia/dev/knowledge/python/data-pipelines.md +0 -169
- package/_gaia/dev/knowledge/python/django-patterns.md +0 -145
- package/_gaia/dev/knowledge/python/fastapi-patterns.md +0 -164
- package/_gaia/dev/knowledge/python/python-conventions.md +0 -170
- package/_gaia/dev/knowledge/typescript/express-patterns.md +0 -188
- package/_gaia/dev/knowledge/typescript/nextjs-patterns.md +0 -166
- package/_gaia/dev/knowledge/typescript/react-patterns.md +0 -176
- package/_gaia/dev/knowledge/typescript/ts-conventions.md +0 -133
- package/_gaia/dev/module-help.csv +0 -10
- package/_gaia/dev/skills/_skill-index.yaml +0 -55
- package/_gaia/dev/skills/api-design.md +0 -229
- package/_gaia/dev/skills/code-review-standards.md +0 -226
- package/_gaia/dev/skills/database-design.md +0 -172
- package/_gaia/dev/skills/docker-workflow.md +0 -222
- package/_gaia/dev/skills/documentation-standards.md +0 -256
- package/_gaia/dev/skills/git-workflow.md +0 -157
- package/_gaia/dev/skills/security-basics.md +0 -230
- package/_gaia/dev/skills/testing-patterns.md +0 -232
- package/_gaia/lifecycle/.resolved/.gitkeep +0 -0
- package/_gaia/lifecycle/agents/analyst.md +0 -104
- package/_gaia/lifecycle/agents/architect.md +0 -109
- package/_gaia/lifecycle/agents/data-engineer.md +0 -99
- package/_gaia/lifecycle/agents/devops.md +0 -110
- package/_gaia/lifecycle/agents/performance.md +0 -92
- package/_gaia/lifecycle/agents/pm.md +0 -112
- package/_gaia/lifecycle/agents/qa.md +0 -89
- package/_gaia/lifecycle/agents/security.md +0 -108
- package/_gaia/lifecycle/agents/sm.md +0 -119
- package/_gaia/lifecycle/agents/tech-writer.md +0 -94
- package/_gaia/lifecycle/agents/ux-designer.md +0 -94
- package/_gaia/lifecycle/agents/validator.md +0 -189
- package/_gaia/lifecycle/config.yaml +0 -14
- package/_gaia/lifecycle/module-help.csv +0 -39
- package/_gaia/lifecycle/skills/ground-truth-management.md +0 -252
- package/_gaia/lifecycle/skills/memory-management.md +0 -322
- package/_gaia/lifecycle/skills/validation-patterns.md +0 -230
- package/_gaia/lifecycle/teams/team-data-intensive.yaml +0 -12
- package/_gaia/lifecycle/teams/team-enterprise.yaml +0 -16
- package/_gaia/lifecycle/teams/team-full.yaml +0 -13
- package/_gaia/lifecycle/teams/team-implementation.yaml +0 -8
- package/_gaia/lifecycle/teams/team-planning.yaml +0 -9
- package/_gaia/lifecycle/teams/team-quick-ship.yaml +0 -6
- package/_gaia/lifecycle/teams/team-security-focused.yaml +0 -13
- package/_gaia/lifecycle/templates/api-documentation-template.md +0 -112
- package/_gaia/lifecycle/templates/architecture-template.md +0 -65
- package/_gaia/lifecycle/templates/brownfield-architecture-template.md +0 -198
- package/_gaia/lifecycle/templates/brownfield-assessment-template.md +0 -78
- package/_gaia/lifecycle/templates/brownfield-onboarding-template.md +0 -160
- package/_gaia/lifecycle/templates/dependency-map-template.md +0 -73
- package/_gaia/lifecycle/templates/deployment-template.md +0 -52
- package/_gaia/lifecycle/templates/epic-status-template.md +0 -64
- package/_gaia/lifecycle/templates/event-catalog-template.md +0 -78
- package/_gaia/lifecycle/templates/nfr-assessment-template.md +0 -96
- package/_gaia/lifecycle/templates/prd-template.md +0 -83
- package/_gaia/lifecycle/templates/product-brief-template.md +0 -48
- package/_gaia/lifecycle/templates/review-template.md +0 -47
- package/_gaia/lifecycle/templates/sprint-plan-template.md +0 -45
- package/_gaia/lifecycle/templates/story-template.md +0 -118
- package/_gaia/lifecycle/templates/tech-debt-dashboard-template.md +0 -71
- package/_gaia/lifecycle/templates/test-plan-template.md +0 -56
- package/_gaia/lifecycle/templates/ux-design-assessment-template.md +0 -122
- package/_gaia/lifecycle/workflows/1-analysis/advanced-elicitation/instructions.xml +0 -44
- package/_gaia/lifecycle/workflows/1-analysis/advanced-elicitation/methods.csv +0 -9
- package/_gaia/lifecycle/workflows/1-analysis/advanced-elicitation/workflow.yaml +0 -33
- package/_gaia/lifecycle/workflows/1-analysis/brainstorm-project/checklist.md +0 -24
- package/_gaia/lifecycle/workflows/1-analysis/brainstorm-project/instructions.xml +0 -39
- package/_gaia/lifecycle/workflows/1-analysis/brainstorm-project/workflow.yaml +0 -19
- package/_gaia/lifecycle/workflows/1-analysis/create-product-brief/checklist.md +0 -27
- package/_gaia/lifecycle/workflows/1-analysis/create-product-brief/instructions.xml +0 -57
- package/_gaia/lifecycle/workflows/1-analysis/create-product-brief/workflow.yaml +0 -38
- package/_gaia/lifecycle/workflows/1-analysis/domain-research/checklist.md +0 -22
- package/_gaia/lifecycle/workflows/1-analysis/domain-research/instructions.xml +0 -34
- package/_gaia/lifecycle/workflows/1-analysis/domain-research/workflow.yaml +0 -15
- package/_gaia/lifecycle/workflows/1-analysis/market-research/checklist.md +0 -28
- package/_gaia/lifecycle/workflows/1-analysis/market-research/instructions.xml +0 -42
- package/_gaia/lifecycle/workflows/1-analysis/market-research/workflow.yaml +0 -15
- package/_gaia/lifecycle/workflows/1-analysis/technical-research/checklist.md +0 -22
- package/_gaia/lifecycle/workflows/1-analysis/technical-research/instructions.xml +0 -34
- package/_gaia/lifecycle/workflows/1-analysis/technical-research/workflow.yaml +0 -15
- package/_gaia/lifecycle/workflows/2-planning/create-prd/checklist.md +0 -36
- package/_gaia/lifecycle/workflows/2-planning/create-prd/instructions.xml +0 -80
- package/_gaia/lifecycle/workflows/2-planning/create-prd/workflow.yaml +0 -23
- package/_gaia/lifecycle/workflows/2-planning/create-ux-design/checklist.md +0 -26
- package/_gaia/lifecycle/workflows/2-planning/create-ux-design/instructions.xml +0 -49
- package/_gaia/lifecycle/workflows/2-planning/create-ux-design/workflow.yaml +0 -23
- package/_gaia/lifecycle/workflows/2-planning/edit-prd/checklist.md +0 -17
- package/_gaia/lifecycle/workflows/2-planning/edit-prd/instructions.xml +0 -50
- package/_gaia/lifecycle/workflows/2-planning/edit-prd/workflow.yaml +0 -22
- package/_gaia/lifecycle/workflows/2-planning/validate-prd/checklist.md +0 -12
- package/_gaia/lifecycle/workflows/2-planning/validate-prd/instructions.xml +0 -52
- package/_gaia/lifecycle/workflows/2-planning/validate-prd/workflow.yaml +0 -19
- package/_gaia/lifecycle/workflows/3-solutioning/create-architecture/checklist.md +0 -32
- package/_gaia/lifecycle/workflows/3-solutioning/create-architecture/instructions.xml +0 -100
- package/_gaia/lifecycle/workflows/3-solutioning/create-architecture/workflow.yaml +0 -41
- package/_gaia/lifecycle/workflows/3-solutioning/create-epics-stories/checklist.md +0 -30
- package/_gaia/lifecycle/workflows/3-solutioning/create-epics-stories/instructions.xml +0 -86
- package/_gaia/lifecycle/workflows/3-solutioning/create-epics-stories/workflow.yaml +0 -34
- package/_gaia/lifecycle/workflows/3-solutioning/edit-architecture/checklist.md +0 -24
- package/_gaia/lifecycle/workflows/3-solutioning/edit-architecture/instructions.xml +0 -91
- package/_gaia/lifecycle/workflows/3-solutioning/edit-architecture/workflow.yaml +0 -32
- package/_gaia/lifecycle/workflows/3-solutioning/implementation-readiness/checklist.md +0 -66
- package/_gaia/lifecycle/workflows/3-solutioning/implementation-readiness/instructions.xml +0 -160
- package/_gaia/lifecycle/workflows/3-solutioning/implementation-readiness/workflow.yaml +0 -48
- package/_gaia/lifecycle/workflows/3-solutioning/infrastructure-design/checklist.md +0 -24
- package/_gaia/lifecycle/workflows/3-solutioning/infrastructure-design/instructions.xml +0 -44
- package/_gaia/lifecycle/workflows/3-solutioning/infrastructure-design/workflow.yaml +0 -23
- package/_gaia/lifecycle/workflows/3-solutioning/security-threat-model/checklist.md +0 -24
- package/_gaia/lifecycle/workflows/3-solutioning/security-threat-model/instructions.xml +0 -55
- package/_gaia/lifecycle/workflows/3-solutioning/security-threat-model/workflow.yaml +0 -23
- package/_gaia/lifecycle/workflows/4-implementation/action-items/instructions.xml +0 -131
- package/_gaia/lifecycle/workflows/4-implementation/action-items/workflow.yaml +0 -19
- package/_gaia/lifecycle/workflows/4-implementation/add-stories/checklist.md +0 -27
- package/_gaia/lifecycle/workflows/4-implementation/add-stories/instructions.xml +0 -100
- package/_gaia/lifecycle/workflows/4-implementation/add-stories/workflow.yaml +0 -35
- package/_gaia/lifecycle/workflows/4-implementation/change-request/checklist.md +0 -25
- package/_gaia/lifecycle/workflows/4-implementation/change-request/instructions.xml +0 -123
- package/_gaia/lifecycle/workflows/4-implementation/change-request/workflow.yaml +0 -38
- package/_gaia/lifecycle/workflows/4-implementation/check-dod/checklist.md +0 -18
- package/_gaia/lifecycle/workflows/4-implementation/check-dod/instructions.xml +0 -54
- package/_gaia/lifecycle/workflows/4-implementation/check-dod/workflow.yaml +0 -19
- package/_gaia/lifecycle/workflows/4-implementation/check-review-gate/checklist.md +0 -18
- package/_gaia/lifecycle/workflows/4-implementation/check-review-gate/instructions.xml +0 -53
- package/_gaia/lifecycle/workflows/4-implementation/check-review-gate/workflow.yaml +0 -19
- package/_gaia/lifecycle/workflows/4-implementation/code-review/checklist.md +0 -18
- package/_gaia/lifecycle/workflows/4-implementation/code-review/instructions.xml +0 -50
- package/_gaia/lifecycle/workflows/4-implementation/code-review/workflow.yaml +0 -24
- package/_gaia/lifecycle/workflows/4-implementation/correct-course/checklist.md +0 -21
- package/_gaia/lifecycle/workflows/4-implementation/correct-course/instructions.xml +0 -63
- package/_gaia/lifecycle/workflows/4-implementation/correct-course/workflow.yaml +0 -25
- package/_gaia/lifecycle/workflows/4-implementation/create-story/checklist.md +0 -38
- package/_gaia/lifecycle/workflows/4-implementation/create-story/instructions.xml +0 -194
- package/_gaia/lifecycle/workflows/4-implementation/create-story/workflow.yaml +0 -26
- package/_gaia/lifecycle/workflows/4-implementation/dev-story/checklist.md +0 -26
- package/_gaia/lifecycle/workflows/4-implementation/dev-story/instructions.xml +0 -268
- package/_gaia/lifecycle/workflows/4-implementation/dev-story/workflow.yaml +0 -51
- package/_gaia/lifecycle/workflows/4-implementation/epic-status/checklist.md +0 -25
- package/_gaia/lifecycle/workflows/4-implementation/epic-status/instructions.xml +0 -62
- package/_gaia/lifecycle/workflows/4-implementation/epic-status/workflow.yaml +0 -24
- package/_gaia/lifecycle/workflows/4-implementation/fix-story/checklist.md +0 -12
- package/_gaia/lifecycle/workflows/4-implementation/fix-story/instructions.xml +0 -67
- package/_gaia/lifecycle/workflows/4-implementation/fix-story/workflow.yaml +0 -17
- package/_gaia/lifecycle/workflows/4-implementation/qa-generate-tests/checklist.md +0 -19
- package/_gaia/lifecycle/workflows/4-implementation/qa-generate-tests/instructions.xml +0 -52
- package/_gaia/lifecycle/workflows/4-implementation/qa-generate-tests/workflow.yaml +0 -20
- package/_gaia/lifecycle/workflows/4-implementation/retrospective/checklist.md +0 -15
- package/_gaia/lifecycle/workflows/4-implementation/retrospective/instructions.xml +0 -164
- package/_gaia/lifecycle/workflows/4-implementation/retrospective/workflow.yaml +0 -30
- package/_gaia/lifecycle/workflows/4-implementation/run-all-reviews/checklist.md +0 -14
- package/_gaia/lifecycle/workflows/4-implementation/run-all-reviews/instructions.xml +0 -78
- package/_gaia/lifecycle/workflows/4-implementation/run-all-reviews/workflow.yaml +0 -16
- package/_gaia/lifecycle/workflows/4-implementation/security-review/checklist.md +0 -29
- package/_gaia/lifecycle/workflows/4-implementation/security-review/instructions.xml +0 -80
- package/_gaia/lifecycle/workflows/4-implementation/security-review/workflow.yaml +0 -27
- package/_gaia/lifecycle/workflows/4-implementation/sprint-planning/checklist.md +0 -29
- package/_gaia/lifecycle/workflows/4-implementation/sprint-planning/instructions.xml +0 -140
- package/_gaia/lifecycle/workflows/4-implementation/sprint-planning/workflow.yaml +0 -33
- package/_gaia/lifecycle/workflows/4-implementation/sprint-status/checklist.md +0 -18
- package/_gaia/lifecycle/workflows/4-implementation/sprint-status/instructions.xml +0 -36
- package/_gaia/lifecycle/workflows/4-implementation/sprint-status/workflow.yaml +0 -19
- package/_gaia/lifecycle/workflows/4-implementation/tech-debt-review/checklist.md +0 -30
- package/_gaia/lifecycle/workflows/4-implementation/tech-debt-review/instructions.xml +0 -147
- package/_gaia/lifecycle/workflows/4-implementation/tech-debt-review/workflow.yaml +0 -24
- package/_gaia/lifecycle/workflows/4-implementation/triage-findings/checklist.md +0 -17
- package/_gaia/lifecycle/workflows/4-implementation/triage-findings/instructions.xml +0 -124
- package/_gaia/lifecycle/workflows/4-implementation/triage-findings/workflow.yaml +0 -15
- package/_gaia/lifecycle/workflows/4-implementation/val-refresh-ground-truth/checklist.md +0 -48
- package/_gaia/lifecycle/workflows/4-implementation/val-refresh-ground-truth/instructions.xml +0 -125
- package/_gaia/lifecycle/workflows/4-implementation/val-refresh-ground-truth/workflow.yaml +0 -31
- package/_gaia/lifecycle/workflows/4-implementation/val-validate-artifact/checklist.md +0 -54
- package/_gaia/lifecycle/workflows/4-implementation/val-validate-artifact/instructions.xml +0 -147
- package/_gaia/lifecycle/workflows/4-implementation/val-validate-artifact/test-structure.sh +0 -116
- package/_gaia/lifecycle/workflows/4-implementation/val-validate-artifact/workflow.yaml +0 -29
- package/_gaia/lifecycle/workflows/4-implementation/val-validate-plan/checklist.md +0 -34
- package/_gaia/lifecycle/workflows/4-implementation/val-validate-plan/instructions.xml +0 -162
- package/_gaia/lifecycle/workflows/4-implementation/val-validate-plan/workflow.yaml +0 -39
- package/_gaia/lifecycle/workflows/4-implementation/validate-story/checklist.md +0 -23
- package/_gaia/lifecycle/workflows/4-implementation/validate-story/instructions.xml +0 -146
- package/_gaia/lifecycle/workflows/4-implementation/validate-story/workflow.yaml +0 -25
- package/_gaia/lifecycle/workflows/5-deployment/deployment-checklist/checklist.md +0 -29
- package/_gaia/lifecycle/workflows/5-deployment/deployment-checklist/instructions.xml +0 -59
- package/_gaia/lifecycle/workflows/5-deployment/deployment-checklist/workflow.yaml +0 -39
- package/_gaia/lifecycle/workflows/5-deployment/post-deploy-verify/checklist.md +0 -19
- package/_gaia/lifecycle/workflows/5-deployment/post-deploy-verify/instructions.xml +0 -33
- package/_gaia/lifecycle/workflows/5-deployment/post-deploy-verify/workflow.yaml +0 -15
- package/_gaia/lifecycle/workflows/5-deployment/release-plan/checklist.md +0 -20
- package/_gaia/lifecycle/workflows/5-deployment/release-plan/instructions.xml +0 -33
- package/_gaia/lifecycle/workflows/5-deployment/release-plan/workflow.yaml +0 -19
- package/_gaia/lifecycle/workflows/5-deployment/rollback-plan/checklist.md +0 -20
- package/_gaia/lifecycle/workflows/5-deployment/rollback-plan/instructions.xml +0 -33
- package/_gaia/lifecycle/workflows/5-deployment/rollback-plan/workflow.yaml +0 -15
- package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/checklist.md +0 -52
- package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/instructions.xml +0 -122
- package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/test-step7.sh +0 -149
- package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/workflow.yaml +0 -33
- package/_gaia/lifecycle/workflows/anytime/document-project/checklist.md +0 -11
- package/_gaia/lifecycle/workflows/anytime/document-project/instructions.xml +0 -26
- package/_gaia/lifecycle/workflows/anytime/document-project/workflow.yaml +0 -15
- package/_gaia/lifecycle/workflows/anytime/generate-project-context/checklist.md +0 -11
- package/_gaia/lifecycle/workflows/anytime/generate-project-context/instructions.xml +0 -22
- package/_gaia/lifecycle/workflows/anytime/generate-project-context/workflow.yaml +0 -15
- package/_gaia/lifecycle/workflows/anytime/memory-hygiene/checklist.md +0 -24
- package/_gaia/lifecycle/workflows/anytime/memory-hygiene/instructions.xml +0 -108
- package/_gaia/lifecycle/workflows/anytime/memory-hygiene/workflow.yaml +0 -15
- package/_gaia/lifecycle/workflows/anytime/performance-review/checklist.md +0 -25
- package/_gaia/lifecycle/workflows/anytime/performance-review/instructions.xml +0 -62
- package/_gaia/lifecycle/workflows/anytime/performance-review/workflow.yaml +0 -15
- package/_gaia/lifecycle/workflows/cross-phase/add-feature/checklist.md +0 -30
- package/_gaia/lifecycle/workflows/cross-phase/add-feature/instructions.xml +0 -85
- package/_gaia/lifecycle/workflows/cross-phase/add-feature/workflow.yaml +0 -37
- package/_gaia/lifecycle/workflows/quick-flow/quick-dev/checklist.md +0 -11
- package/_gaia/lifecycle/workflows/quick-flow/quick-dev/instructions.xml +0 -26
- package/_gaia/lifecycle/workflows/quick-flow/quick-dev/workflow.yaml +0 -19
- package/_gaia/lifecycle/workflows/quick-flow/quick-spec/checklist.md +0 -13
- package/_gaia/lifecycle/workflows/quick-flow/quick-spec/instructions.xml +0 -27
- package/_gaia/lifecycle/workflows/quick-flow/quick-spec/workflow.yaml +0 -15
- package/_gaia/testing/.resolved/.gitkeep +0 -0
- package/_gaia/testing/agents/test-architect.md +0 -131
- package/_gaia/testing/config.yaml +0 -8
- package/_gaia/testing/knowledge/_index.csv +0 -22
- package/_gaia/testing/knowledge/accessibility/axe-core-patterns.md +0 -177
- package/_gaia/testing/knowledge/accessibility/wcag-checks.md +0 -191
- package/_gaia/testing/knowledge/core/deterministic-testing.md +0 -167
- package/_gaia/testing/knowledge/core/fixture-architecture.md +0 -131
- package/_gaia/testing/knowledge/core/test-isolation.md +0 -142
- package/_gaia/testing/knowledge/core/test-pyramid.md +0 -129
- package/_gaia/testing/knowledge/extended/api-testing-patterns.md +0 -196
- package/_gaia/testing/knowledge/extended/data-factories.md +0 -158
- package/_gaia/testing/knowledge/extended/risk-governance.md +0 -119
- package/_gaia/testing/knowledge/extended/selector-resilience.md +0 -109
- package/_gaia/testing/knowledge/mobile-testing/appium-patterns.md +0 -164
- package/_gaia/testing/knowledge/mobile-testing/react-native-testing.md +0 -193
- package/_gaia/testing/knowledge/mobile-testing/responsive-testing.md +0 -177
- package/_gaia/testing/knowledge/performance/k6-patterns.md +0 -200
- package/_gaia/testing/knowledge/performance/lighthouse-ci.md +0 -158
- package/_gaia/testing/knowledge/specialized/contract-testing.md +0 -173
- package/_gaia/testing/knowledge/specialized/test-healing.md +0 -129
- package/_gaia/testing/knowledge/specialized/visual-testing.md +0 -129
- package/_gaia/testing/knowledge/unit-testing/jest-vitest-patterns.md +0 -193
- package/_gaia/testing/knowledge/unit-testing/junit5-patterns.md +0 -200
- package/_gaia/testing/knowledge/unit-testing/pytest-patterns.md +0 -185
- package/_gaia/testing/module-help.csv +0 -13
- package/_gaia/testing/workflows/accessibility-testing/checklist.md +0 -12
- package/_gaia/testing/workflows/accessibility-testing/instructions.xml +0 -41
- package/_gaia/testing/workflows/accessibility-testing/workflow.yaml +0 -13
- package/_gaia/testing/workflows/atdd/checklist.md +0 -6
- package/_gaia/testing/workflows/atdd/instructions.xml +0 -36
- package/_gaia/testing/workflows/atdd/workflow.yaml +0 -22
- package/_gaia/testing/workflows/ci-setup/checklist.md +0 -9
- package/_gaia/testing/workflows/ci-setup/instructions.xml +0 -43
- package/_gaia/testing/workflows/ci-setup/workflow.yaml +0 -11
- package/_gaia/testing/workflows/edit-test-plan/checklist.md +0 -20
- package/_gaia/testing/workflows/edit-test-plan/instructions.xml +0 -65
- package/_gaia/testing/workflows/edit-test-plan/workflow.yaml +0 -35
- package/_gaia/testing/workflows/mobile-testing/checklist.md +0 -13
- package/_gaia/testing/workflows/mobile-testing/instructions.xml +0 -41
- package/_gaia/testing/workflows/mobile-testing/workflow.yaml +0 -11
- package/_gaia/testing/workflows/nfr-assessment/checklist.md +0 -7
- package/_gaia/testing/workflows/nfr-assessment/instructions.xml +0 -26
- package/_gaia/testing/workflows/nfr-assessment/workflow.yaml +0 -11
- package/_gaia/testing/workflows/performance-testing/checklist.md +0 -11
- package/_gaia/testing/workflows/performance-testing/instructions.xml +0 -41
- package/_gaia/testing/workflows/performance-testing/workflow.yaml +0 -11
- package/_gaia/testing/workflows/teach-me-testing/checklist.md +0 -6
- package/_gaia/testing/workflows/teach-me-testing/instructions.xml +0 -28
- package/_gaia/testing/workflows/teach-me-testing/workflow.yaml +0 -12
- package/_gaia/testing/workflows/test-automation/checklist.md +0 -6
- package/_gaia/testing/workflows/test-automation/instructions.xml +0 -49
- package/_gaia/testing/workflows/test-automation/workflow.yaml +0 -11
- package/_gaia/testing/workflows/test-design/checklist.md +0 -9
- package/_gaia/testing/workflows/test-design/instructions.xml +0 -47
- package/_gaia/testing/workflows/test-design/workflow.yaml +0 -11
- package/_gaia/testing/workflows/test-framework/checklist.md +0 -8
- package/_gaia/testing/workflows/test-framework/instructions.xml +0 -25
- package/_gaia/testing/workflows/test-framework/workflow.yaml +0 -11
- package/_gaia/testing/workflows/test-review/checklist.md +0 -9
- package/_gaia/testing/workflows/test-review/instructions.xml +0 -51
- package/_gaia/testing/workflows/test-review/workflow.yaml +0 -11
- package/_gaia/testing/workflows/traceability/checklist.md +0 -6
- package/_gaia/testing/workflows/traceability/instructions.xml +0 -49
- package/_gaia/testing/workflows/traceability/workflow.yaml +0 -21
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Swift and SwiftUI Patterns
|
|
3
|
-
stack: mobile
|
|
4
|
-
version: "1.0"
|
|
5
|
-
focus: [swift]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Swift and SwiftUI Patterns
|
|
9
|
-
|
|
10
|
-
## Principle
|
|
11
|
-
|
|
12
|
-
Build iOS interfaces with SwiftUI's declarative syntax, use Combine for reactive data flow, apply protocol-oriented programming for flexible abstractions, and manage memory carefully with ARC (Automatic Reference Counting). Prefer value types (structs, enums) over reference types (classes) unless identity semantics are required.
|
|
13
|
-
|
|
14
|
-
## Rationale
|
|
15
|
-
|
|
16
|
-
SwiftUI re-renders views when their state changes, similar to React. Views are lightweight structs, not persistent objects, so the framework creates and discards them freely. Combine provides a native reactive pipeline for transforming and combining async data streams. Protocol-oriented programming (POP) avoids the fragile base class problem of inheritance. ARC requires explicit attention to retain cycles, especially in closures and delegate patterns.
|
|
17
|
-
|
|
18
|
-
## Pattern Examples
|
|
19
|
-
|
|
20
|
-
### Pattern 1: SwiftUI Views with State Management
|
|
21
|
-
|
|
22
|
-
```swift
|
|
23
|
-
import SwiftUI
|
|
24
|
-
|
|
25
|
-
// View Model — ObservableObject publishes changes
|
|
26
|
-
@MainActor
|
|
27
|
-
class UserListViewModel: ObservableObject {
|
|
28
|
-
@Published var users: [User] = []
|
|
29
|
-
@Published var isLoading = false
|
|
30
|
-
@Published var errorMessage: String?
|
|
31
|
-
|
|
32
|
-
private let repository: UserRepository
|
|
33
|
-
|
|
34
|
-
init(repository: UserRepository = .shared) {
|
|
35
|
-
self.repository = repository
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
func loadUsers() async {
|
|
39
|
-
isLoading = true
|
|
40
|
-
errorMessage = nil
|
|
41
|
-
do {
|
|
42
|
-
users = try await repository.fetchAll()
|
|
43
|
-
} catch {
|
|
44
|
-
errorMessage = error.localizedDescription
|
|
45
|
-
}
|
|
46
|
-
isLoading = false
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// SwiftUI View — lightweight struct
|
|
51
|
-
struct UserListView: View {
|
|
52
|
-
@StateObject private var viewModel = UserListViewModel()
|
|
53
|
-
|
|
54
|
-
var body: some View {
|
|
55
|
-
NavigationStack {
|
|
56
|
-
Group {
|
|
57
|
-
if viewModel.isLoading {
|
|
58
|
-
ProgressView("Loading...")
|
|
59
|
-
} else if let error = viewModel.errorMessage {
|
|
60
|
-
ContentUnavailableView(
|
|
61
|
-
"Error", systemImage: "exclamationmark.triangle",
|
|
62
|
-
description: Text(error)
|
|
63
|
-
)
|
|
64
|
-
} else {
|
|
65
|
-
List(viewModel.users) { user in
|
|
66
|
-
NavigationLink(value: user) {
|
|
67
|
-
UserRow(user: user)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
.navigationTitle("Users")
|
|
73
|
-
.task { await viewModel.loadUsers() }
|
|
74
|
-
.refreshable { await viewModel.loadUsers() }
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Reusable subview
|
|
80
|
-
struct UserRow: View {
|
|
81
|
-
let user: User
|
|
82
|
-
|
|
83
|
-
var body: some View {
|
|
84
|
-
HStack {
|
|
85
|
-
AsyncImage(url: user.avatarURL) { image in
|
|
86
|
-
image.resizable().scaledToFill()
|
|
87
|
-
} placeholder: {
|
|
88
|
-
Circle().fill(.gray.opacity(0.3))
|
|
89
|
-
}
|
|
90
|
-
.frame(width: 44, height: 44)
|
|
91
|
-
.clipShape(Circle())
|
|
92
|
-
|
|
93
|
-
VStack(alignment: .leading) {
|
|
94
|
-
Text(user.name).font(.headline)
|
|
95
|
-
Text(user.email).font(.subheadline).foregroundStyle(.secondary)
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Pattern 2: Combine Pipeline
|
|
103
|
-
|
|
104
|
-
```swift
|
|
105
|
-
import Combine
|
|
106
|
-
|
|
107
|
-
class SearchViewModel: ObservableObject {
|
|
108
|
-
@Published var query = ""
|
|
109
|
-
@Published var results: [SearchResult] = []
|
|
110
|
-
|
|
111
|
-
private var cancellables = Set<AnyCancellable>()
|
|
112
|
-
private let searchService: SearchService
|
|
113
|
-
|
|
114
|
-
init(searchService: SearchService) {
|
|
115
|
-
self.searchService = searchService
|
|
116
|
-
|
|
117
|
-
$query
|
|
118
|
-
.debounce(for: .milliseconds(300), scheduler: RunLoop.main)
|
|
119
|
-
.removeDuplicates()
|
|
120
|
-
.filter { $0.count >= 2 }
|
|
121
|
-
.flatMap { [weak self] query -> AnyPublisher<[SearchResult], Never> in
|
|
122
|
-
guard let self else { return Just([]).eraseToAnyPublisher() }
|
|
123
|
-
return self.searchService.search(query: query)
|
|
124
|
-
.catch { _ in Just([]) }
|
|
125
|
-
.eraseToAnyPublisher()
|
|
126
|
-
}
|
|
127
|
-
.receive(on: RunLoop.main)
|
|
128
|
-
.assign(to: &$results)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Pattern 3: Protocol-Oriented Programming
|
|
134
|
-
|
|
135
|
-
```swift
|
|
136
|
-
// Protocol defines the contract
|
|
137
|
-
protocol Repository {
|
|
138
|
-
associatedtype Entity: Identifiable
|
|
139
|
-
func fetchAll() async throws -> [Entity]
|
|
140
|
-
func fetchById(_ id: Entity.ID) async throws -> Entity?
|
|
141
|
-
func save(_ entity: Entity) async throws -> Entity
|
|
142
|
-
func delete(_ id: Entity.ID) async throws
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Default implementation via protocol extension
|
|
146
|
-
extension Repository {
|
|
147
|
-
func fetchOrThrow(_ id: Entity.ID) async throws -> Entity {
|
|
148
|
-
guard let entity = try await fetchById(id) else {
|
|
149
|
-
throw RepositoryError.notFound(String(describing: id))
|
|
150
|
-
}
|
|
151
|
-
return entity
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Concrete implementation
|
|
156
|
-
struct UserRepository: Repository {
|
|
157
|
-
typealias Entity = User
|
|
158
|
-
private let apiClient: APIClient
|
|
159
|
-
|
|
160
|
-
func fetchAll() async throws -> [User] {
|
|
161
|
-
try await apiClient.get("/users")
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
func fetchById(_ id: String) async throws -> User? {
|
|
165
|
-
try? await apiClient.get("/users/\(id)")
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
func save(_ entity: User) async throws -> User {
|
|
169
|
-
try await apiClient.post("/users", body: entity)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
func delete(_ id: String) async throws {
|
|
173
|
-
try await apiClient.delete("/users/\(id)")
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## Anti-Patterns
|
|
179
|
-
|
|
180
|
-
- **Retain cycles in closures**: Capturing `self` strongly in escaping closures causes memory leaks. Use `[weak self]` and guard against nil.
|
|
181
|
-
- **Massive view bodies**: SwiftUI views with 100+ lines in `body`. Extract subviews as separate structs.
|
|
182
|
-
- **Using `@ObservedObject` for owned objects**: `@ObservedObject` does not own its object; use `@StateObject` for objects created by the view.
|
|
183
|
-
- **Forcing class inheritance for abstraction**: Use protocols and protocol extensions instead of base classes.
|
|
184
|
-
|
|
185
|
-
## Integration Points
|
|
186
|
-
|
|
187
|
-
- **React Native**: Native modules in Swift bridge to React Native; see `react-native-patterns.md`.
|
|
188
|
-
- **Mobile Testing**: XCTest and XCUITest for unit and UI testing; see `mobile-testing.md`.
|
|
189
|
-
- **Kotlin**: Cross-platform considerations with Kotlin Multiplatform; see `kotlin-patterns.md`.
|
|
190
|
-
- **Combine**: Integrates with SwiftUI's `@Published` and async/await via `values` property.
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Data Pipeline Patterns
|
|
3
|
-
stack: python
|
|
4
|
-
version: "1.0"
|
|
5
|
-
focus: [data-pipelines]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Data Pipeline Patterns
|
|
9
|
-
|
|
10
|
-
## Principle
|
|
11
|
-
|
|
12
|
-
Design pipelines as composable, idempotent stages: extract, transform, load. Use pandas for batch tabular processing, async I/O for concurrent data fetching, and chunked processing for large datasets that do not fit in memory. Choose batch vs. stream based on latency requirements, not data volume.
|
|
13
|
-
|
|
14
|
-
## Rationale
|
|
15
|
-
|
|
16
|
-
ETL pipelines are the backbone of data-driven applications. Composable stages make pipelines testable in isolation and rerunnable without side effects (idempotency). Pandas provides powerful vectorized operations but can consume excessive memory on large datasets; chunked reading and processing prevent OOM errors. Async I/O dramatically speeds up the extract phase when pulling from multiple sources concurrently.
|
|
17
|
-
|
|
18
|
-
## Pattern Examples
|
|
19
|
-
|
|
20
|
-
### Pattern 1: Chunked Pandas Processing
|
|
21
|
-
|
|
22
|
-
```python
|
|
23
|
-
import pandas as pd
|
|
24
|
-
from pathlib import Path
|
|
25
|
-
from typing import Iterator
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def read_in_chunks(
|
|
29
|
-
filepath: Path, chunk_size: int = 10_000
|
|
30
|
-
) -> Iterator[pd.DataFrame]:
|
|
31
|
-
"""Read large CSV in chunks to avoid memory exhaustion."""
|
|
32
|
-
return pd.read_csv(
|
|
33
|
-
filepath,
|
|
34
|
-
chunksize=chunk_size,
|
|
35
|
-
dtype={"user_id": str, "amount": float},
|
|
36
|
-
parse_dates=["created_at"],
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def transform_chunk(df: pd.DataFrame) -> pd.DataFrame:
|
|
41
|
-
"""Apply transformations to a single chunk."""
|
|
42
|
-
return (
|
|
43
|
-
df
|
|
44
|
-
.dropna(subset=["user_id", "amount"])
|
|
45
|
-
.assign(
|
|
46
|
-
amount_usd=lambda x: x["amount"] * x["exchange_rate"],
|
|
47
|
-
month=lambda x: x["created_at"].dt.to_period("M"),
|
|
48
|
-
)
|
|
49
|
-
.query("amount_usd > 0")
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def run_pipeline(input_path: Path, output_path: Path) -> int:
|
|
54
|
-
"""Process file in chunks and write aggregated results."""
|
|
55
|
-
results = []
|
|
56
|
-
total_rows = 0
|
|
57
|
-
|
|
58
|
-
for chunk in read_in_chunks(input_path):
|
|
59
|
-
transformed = transform_chunk(chunk)
|
|
60
|
-
aggregated = (
|
|
61
|
-
transformed
|
|
62
|
-
.groupby("month")
|
|
63
|
-
.agg(total=("amount_usd", "sum"), count=("amount_usd", "size"))
|
|
64
|
-
.reset_index()
|
|
65
|
-
)
|
|
66
|
-
results.append(aggregated)
|
|
67
|
-
total_rows += len(transformed)
|
|
68
|
-
|
|
69
|
-
final = pd.concat(results).groupby("month").sum().reset_index()
|
|
70
|
-
final.to_parquet(output_path, index=False)
|
|
71
|
-
return total_rows
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Pattern 2: Async Extract from Multiple APIs
|
|
75
|
-
|
|
76
|
-
```python
|
|
77
|
-
import asyncio
|
|
78
|
-
import httpx
|
|
79
|
-
from dataclasses import dataclass
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
@dataclass
|
|
83
|
-
class ExtractResult:
|
|
84
|
-
source: str
|
|
85
|
-
data: list[dict]
|
|
86
|
-
record_count: int
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
async def fetch_source(
|
|
90
|
-
client: httpx.AsyncClient, name: str, url: str
|
|
91
|
-
) -> ExtractResult:
|
|
92
|
-
"""Fetch data from a single API source."""
|
|
93
|
-
response = await client.get(url, timeout=30.0)
|
|
94
|
-
response.raise_for_status()
|
|
95
|
-
data = response.json()["results"]
|
|
96
|
-
return ExtractResult(source=name, data=data, record_count=len(data))
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
async def extract_all(sources: dict[str, str]) -> list[ExtractResult]:
|
|
100
|
-
"""Fetch from all sources concurrently."""
|
|
101
|
-
async with httpx.AsyncClient() as client:
|
|
102
|
-
tasks = [
|
|
103
|
-
fetch_source(client, name, url)
|
|
104
|
-
for name, url in sources.items()
|
|
105
|
-
]
|
|
106
|
-
return await asyncio.gather(*tasks, return_exceptions=True)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
# Usage
|
|
110
|
-
sources = {
|
|
111
|
-
"users": "https://api.example.com/users",
|
|
112
|
-
"orders": "https://api.example.com/orders",
|
|
113
|
-
"products": "https://api.example.com/products",
|
|
114
|
-
}
|
|
115
|
-
results = asyncio.run(extract_all(sources))
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### Pattern 3: Idempotent Load with Upsert
|
|
119
|
-
|
|
120
|
-
```python
|
|
121
|
-
from sqlalchemy import text
|
|
122
|
-
from sqlalchemy.ext.asyncio import AsyncSession
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
async def upsert_records(
|
|
126
|
-
session: AsyncSession,
|
|
127
|
-
records: list[dict],
|
|
128
|
-
table: str,
|
|
129
|
-
conflict_key: str,
|
|
130
|
-
) -> int:
|
|
131
|
-
"""Idempotent upsert — safe to rerun without duplicates."""
|
|
132
|
-
if not records:
|
|
133
|
-
return 0
|
|
134
|
-
|
|
135
|
-
columns = list(records[0].keys())
|
|
136
|
-
col_list = ", ".join(columns)
|
|
137
|
-
val_placeholders = ", ".join(f":{col}" for col in columns)
|
|
138
|
-
update_set = ", ".join(
|
|
139
|
-
f"{col} = EXCLUDED.{col}"
|
|
140
|
-
for col in columns
|
|
141
|
-
if col != conflict_key
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
query = text(f"""
|
|
145
|
-
INSERT INTO {table} ({col_list})
|
|
146
|
-
VALUES ({val_placeholders})
|
|
147
|
-
ON CONFLICT ({conflict_key})
|
|
148
|
-
DO UPDATE SET {update_set}
|
|
149
|
-
""")
|
|
150
|
-
|
|
151
|
-
await session.execute(query, records)
|
|
152
|
-
await session.commit()
|
|
153
|
-
return len(records)
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
## Anti-Patterns
|
|
157
|
-
|
|
158
|
-
- **Loading entire dataset into memory**: `pd.read_csv("huge.csv")` on a 10GB file. Use `chunksize` parameter or Dask for out-of-core processing.
|
|
159
|
-
- **Non-idempotent loads**: INSERT without conflict handling causes duplicate records on rerun. Always use upsert or delete-then-insert.
|
|
160
|
-
- **Sequential API calls**: Fetching 20 API sources one at a time when they are independent. Use `asyncio.gather` for concurrent extraction.
|
|
161
|
-
- **String concatenation for SQL**: Building queries with f-strings opens SQL injection risks. Use parameterized queries.
|
|
162
|
-
- **No error handling per stage**: A failure in transform should not require re-extracting. Checkpoint intermediate results.
|
|
163
|
-
|
|
164
|
-
## Integration Points
|
|
165
|
-
|
|
166
|
-
- **Django**: Management commands (`manage.py run_pipeline`) invoke pipeline stages; see `django-patterns.md`.
|
|
167
|
-
- **FastAPI**: API endpoints trigger pipeline runs or report status; see `fastapi-patterns.md`.
|
|
168
|
-
- **Python Conventions**: Type hints and project structure apply to pipeline code; see `python-conventions.md`.
|
|
169
|
-
- **Testing**: Test each stage independently with fixture data; verify idempotency by running load twice.
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Django Application Patterns
|
|
3
|
-
stack: python
|
|
4
|
-
version: "1.0"
|
|
5
|
-
focus: [django]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Django Application Patterns
|
|
9
|
-
|
|
10
|
-
## Principle
|
|
11
|
-
|
|
12
|
-
Leverage Django's "batteries included" philosophy: use the ORM for data access, class-based views (CBVs) for reusable view logic, DRF serializers for API contracts, middleware for cross-cutting concerns, and signals sparingly for decoupled event handling. Keep business logic in model methods or dedicated service modules, not in views.
|
|
13
|
-
|
|
14
|
-
## Rationale
|
|
15
|
-
|
|
16
|
-
Django's ORM, admin, and middleware system are deeply integrated. Fighting the framework (e.g., using raw SQL everywhere, avoiding CBVs) increases maintenance burden. CBVs with mixins enable code reuse across views. DRF serializers validate input, serialize output, and document the API shape in one place. Signals enable loose coupling but overuse makes control flow invisible.
|
|
17
|
-
|
|
18
|
-
## Pattern Examples
|
|
19
|
-
|
|
20
|
-
### Pattern 1: Model with Business Logic
|
|
21
|
-
|
|
22
|
-
```python
|
|
23
|
-
from django.db import models
|
|
24
|
-
from django.utils import timezone
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class Order(models.Model):
|
|
28
|
-
class Status(models.TextChoices):
|
|
29
|
-
DRAFT = "draft", "Draft"
|
|
30
|
-
CONFIRMED = "confirmed", "Confirmed"
|
|
31
|
-
SHIPPED = "shipped", "Shipped"
|
|
32
|
-
CANCELLED = "cancelled", "Cancelled"
|
|
33
|
-
|
|
34
|
-
customer = models.ForeignKey(
|
|
35
|
-
"customers.Customer",
|
|
36
|
-
on_delete=models.PROTECT,
|
|
37
|
-
related_name="orders",
|
|
38
|
-
)
|
|
39
|
-
status = models.CharField(
|
|
40
|
-
max_length=20, choices=Status.choices, default=Status.DRAFT
|
|
41
|
-
)
|
|
42
|
-
created_at = models.DateTimeField(auto_now_add=True)
|
|
43
|
-
confirmed_at = models.DateTimeField(null=True, blank=True)
|
|
44
|
-
|
|
45
|
-
class Meta:
|
|
46
|
-
ordering = ["-created_at"]
|
|
47
|
-
indexes = [
|
|
48
|
-
models.Index(fields=["status", "created_at"]),
|
|
49
|
-
]
|
|
50
|
-
|
|
51
|
-
def confirm(self) -> None:
|
|
52
|
-
if self.status != self.Status.DRAFT:
|
|
53
|
-
raise ValueError(f"Cannot confirm order in {self.status} status")
|
|
54
|
-
self.status = self.Status.CONFIRMED
|
|
55
|
-
self.confirmed_at = timezone.now()
|
|
56
|
-
self.save(update_fields=["status", "confirmed_at"])
|
|
57
|
-
|
|
58
|
-
@property
|
|
59
|
-
def total(self) -> Decimal:
|
|
60
|
-
return sum(item.subtotal for item in self.items.all())
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### Pattern 2: DRF Serializer and ViewSet
|
|
64
|
-
|
|
65
|
-
```python
|
|
66
|
-
from rest_framework import serializers, viewsets, permissions, status
|
|
67
|
-
from rest_framework.decorators import action
|
|
68
|
-
from rest_framework.response import Response
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class OrderSerializer(serializers.ModelSerializer):
|
|
72
|
-
total = serializers.DecimalField(read_only=True, max_digits=10, decimal_places=2)
|
|
73
|
-
items = OrderItemSerializer(many=True, read_only=True)
|
|
74
|
-
|
|
75
|
-
class Meta:
|
|
76
|
-
model = Order
|
|
77
|
-
fields = ["id", "customer", "status", "total", "items", "created_at"]
|
|
78
|
-
read_only_fields = ["status", "created_at"]
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
class OrderViewSet(viewsets.ModelViewSet):
|
|
82
|
-
queryset = Order.objects.select_related("customer").prefetch_related("items")
|
|
83
|
-
serializer_class = OrderSerializer
|
|
84
|
-
permission_classes = [permissions.IsAuthenticated]
|
|
85
|
-
|
|
86
|
-
def get_queryset(self):
|
|
87
|
-
return super().get_queryset().filter(customer__user=self.request.user)
|
|
88
|
-
|
|
89
|
-
@action(detail=True, methods=["post"])
|
|
90
|
-
def confirm(self, request, pk=None):
|
|
91
|
-
order = self.get_object()
|
|
92
|
-
try:
|
|
93
|
-
order.confirm()
|
|
94
|
-
return Response(self.get_serializer(order).data)
|
|
95
|
-
except ValueError as e:
|
|
96
|
-
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### Pattern 3: Custom Middleware
|
|
100
|
-
|
|
101
|
-
```python
|
|
102
|
-
import time
|
|
103
|
-
import logging
|
|
104
|
-
|
|
105
|
-
logger = logging.getLogger(__name__)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
class RequestTimingMiddleware:
|
|
109
|
-
"""Logs request duration for performance monitoring."""
|
|
110
|
-
|
|
111
|
-
def __init__(self, get_response):
|
|
112
|
-
self.get_response = get_response
|
|
113
|
-
|
|
114
|
-
def __call__(self, request):
|
|
115
|
-
start = time.monotonic()
|
|
116
|
-
response = self.get_response(request)
|
|
117
|
-
duration_ms = (time.monotonic() - start) * 1000
|
|
118
|
-
|
|
119
|
-
logger.info(
|
|
120
|
-
"request_completed",
|
|
121
|
-
extra={
|
|
122
|
-
"method": request.method,
|
|
123
|
-
"path": request.path,
|
|
124
|
-
"status": response.status_code,
|
|
125
|
-
"duration_ms": round(duration_ms, 2),
|
|
126
|
-
},
|
|
127
|
-
)
|
|
128
|
-
response["X-Request-Duration-Ms"] = str(round(duration_ms, 2))
|
|
129
|
-
return response
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
## Anti-Patterns
|
|
133
|
-
|
|
134
|
-
- **Business logic in views**: Views should validate input and delegate to model methods or service functions. Keep views thin.
|
|
135
|
-
- **Signal spaghetti**: Overusing signals makes control flow untraceable. Prefer explicit method calls; reserve signals for truly decoupled concerns (e.g., audit logging).
|
|
136
|
-
- **Missing `select_related`/`prefetch_related`**: Accessing related objects in loops without prefetching causes N+1 queries.
|
|
137
|
-
- **Raw SQL in views**: Use the ORM or at minimum `RawSQL` within the queryset API. Raw SQL bypasses Django's protections and is harder to maintain.
|
|
138
|
-
- **Fat serializers with nested writes**: Deeply nested writable serializers are fragile. Use separate endpoints for nested resources.
|
|
139
|
-
|
|
140
|
-
## Integration Points
|
|
141
|
-
|
|
142
|
-
- **FastAPI**: Django ORM can be used alongside FastAPI for async needs; see `fastapi-patterns.md`.
|
|
143
|
-
- **Data Pipelines**: Django management commands often serve as ETL entry points; see `data-pipelines.md`.
|
|
144
|
-
- **Python Conventions**: Follow PEP 8 and type hints throughout Django code; see `python-conventions.md`.
|
|
145
|
-
- **Testing**: Use `pytest-django` with fixtures and factory_boy for test data generation.
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: FastAPI Application Patterns
|
|
3
|
-
stack: python
|
|
4
|
-
version: "1.0"
|
|
5
|
-
focus: [fastapi]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# FastAPI Application Patterns
|
|
9
|
-
|
|
10
|
-
## Principle
|
|
11
|
-
|
|
12
|
-
Use Pydantic models for request/response validation and serialization, FastAPI's dependency injection for shared resources (database sessions, auth), async endpoints for I/O-bound work, and background tasks for fire-and-forget operations. Structure the application with routers for modular organization.
|
|
13
|
-
|
|
14
|
-
## Rationale
|
|
15
|
-
|
|
16
|
-
FastAPI combines ASGI async performance with automatic OpenAPI documentation generated from Pydantic models and type hints. Dependency injection provides a clean, testable way to manage shared resources like database connections, without global state. Async endpoints allow handling thousands of concurrent connections efficiently, critical for APIs with external service calls or database queries.
|
|
17
|
-
|
|
18
|
-
## Pattern Examples
|
|
19
|
-
|
|
20
|
-
### Pattern 1: Pydantic Models and Validation
|
|
21
|
-
|
|
22
|
-
```python
|
|
23
|
-
from pydantic import BaseModel, Field, EmailStr, field_validator
|
|
24
|
-
from datetime import datetime
|
|
25
|
-
from enum import Enum
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class UserRole(str, Enum):
|
|
29
|
-
ADMIN = "admin"
|
|
30
|
-
MEMBER = "member"
|
|
31
|
-
VIEWER = "viewer"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
class CreateUserRequest(BaseModel):
|
|
35
|
-
email: EmailStr
|
|
36
|
-
name: str = Field(min_length=1, max_length=100)
|
|
37
|
-
role: UserRole = UserRole.MEMBER
|
|
38
|
-
tags: list[str] = Field(default_factory=list, max_length=10)
|
|
39
|
-
|
|
40
|
-
@field_validator("name")
|
|
41
|
-
@classmethod
|
|
42
|
-
def name_must_not_be_blank(cls, v: str) -> str:
|
|
43
|
-
if not v.strip():
|
|
44
|
-
raise ValueError("Name must not be blank")
|
|
45
|
-
return v.strip()
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class UserResponse(BaseModel):
|
|
49
|
-
id: int
|
|
50
|
-
email: str
|
|
51
|
-
name: str
|
|
52
|
-
role: UserRole
|
|
53
|
-
created_at: datetime
|
|
54
|
-
|
|
55
|
-
model_config = {"from_attributes": True} # enables ORM mode
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### Pattern 2: Dependency Injection for DB Sessions
|
|
59
|
-
|
|
60
|
-
```python
|
|
61
|
-
from fastapi import Depends, FastAPI, HTTPException, status
|
|
62
|
-
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
|
|
63
|
-
from typing import AsyncGenerator
|
|
64
|
-
|
|
65
|
-
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db")
|
|
66
|
-
SessionLocal = async_sessionmaker(engine, expire_on_commit=False)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
async def get_db() -> AsyncGenerator[AsyncSession, None]:
|
|
70
|
-
async with SessionLocal() as session:
|
|
71
|
-
try:
|
|
72
|
-
yield session
|
|
73
|
-
await session.commit()
|
|
74
|
-
except Exception:
|
|
75
|
-
await session.rollback()
|
|
76
|
-
raise
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
async def get_current_user(
|
|
80
|
-
token: str = Depends(oauth2_scheme),
|
|
81
|
-
db: AsyncSession = Depends(get_db),
|
|
82
|
-
) -> User:
|
|
83
|
-
user = await user_repo.get_by_token(db, token)
|
|
84
|
-
if not user:
|
|
85
|
-
raise HTTPException(
|
|
86
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
87
|
-
detail="Invalid credentials",
|
|
88
|
-
)
|
|
89
|
-
return user
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
# Router with dependencies
|
|
93
|
-
router = APIRouter(prefix="/api/v1/users", tags=["users"])
|
|
94
|
-
|
|
95
|
-
@router.get("/", response_model=list[UserResponse])
|
|
96
|
-
async def list_users(
|
|
97
|
-
skip: int = 0,
|
|
98
|
-
limit: int = 20,
|
|
99
|
-
db: AsyncSession = Depends(get_db),
|
|
100
|
-
current_user: User = Depends(get_current_user),
|
|
101
|
-
):
|
|
102
|
-
return await user_repo.get_all(db, skip=skip, limit=limit)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
@router.post("/", response_model=UserResponse, status_code=201)
|
|
106
|
-
async def create_user(
|
|
107
|
-
payload: CreateUserRequest,
|
|
108
|
-
db: AsyncSession = Depends(get_db),
|
|
109
|
-
current_user: User = Depends(get_current_user),
|
|
110
|
-
):
|
|
111
|
-
if current_user.role != UserRole.ADMIN:
|
|
112
|
-
raise HTTPException(status_code=403, detail="Admin required")
|
|
113
|
-
return await user_repo.create(db, payload)
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### Pattern 3: Background Tasks and Error Handling
|
|
117
|
-
|
|
118
|
-
```python
|
|
119
|
-
from fastapi import BackgroundTasks
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
async def send_welcome_email(email: str, name: str) -> None:
|
|
123
|
-
"""Fire-and-forget background task."""
|
|
124
|
-
await email_service.send(
|
|
125
|
-
to=email,
|
|
126
|
-
subject="Welcome!",
|
|
127
|
-
body=f"Hello {name}, welcome aboard.",
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
@router.post("/register", response_model=UserResponse, status_code=201)
|
|
132
|
-
async def register(
|
|
133
|
-
payload: CreateUserRequest,
|
|
134
|
-
background_tasks: BackgroundTasks,
|
|
135
|
-
db: AsyncSession = Depends(get_db),
|
|
136
|
-
):
|
|
137
|
-
user = await user_repo.create(db, payload)
|
|
138
|
-
background_tasks.add_task(send_welcome_email, user.email, user.name)
|
|
139
|
-
return user
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
# Centralized exception handler
|
|
143
|
-
@app.exception_handler(ValueError)
|
|
144
|
-
async def value_error_handler(request, exc):
|
|
145
|
-
return JSONResponse(
|
|
146
|
-
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
147
|
-
content={"detail": str(exc)},
|
|
148
|
-
)
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
## Anti-Patterns
|
|
152
|
-
|
|
153
|
-
- **Sync endpoints for I/O**: Using `def` instead of `async def` for endpoints that call databases or external APIs blocks the event loop.
|
|
154
|
-
- **Business logic in route handlers**: Route functions should validate and delegate. Put logic in service modules or repository classes.
|
|
155
|
-
- **Missing response_model**: Without `response_model`, FastAPI cannot filter sensitive fields or generate accurate OpenAPI docs.
|
|
156
|
-
- **Global database sessions**: Creating a single global session instead of per-request sessions via dependency injection causes concurrency issues.
|
|
157
|
-
- **Catching broad exceptions silently**: `except Exception: pass` hides bugs. Catch specific exceptions and return meaningful errors.
|
|
158
|
-
|
|
159
|
-
## Integration Points
|
|
160
|
-
|
|
161
|
-
- **Django**: FastAPI can complement Django for async-heavy workloads; see `django-patterns.md`.
|
|
162
|
-
- **Data Pipelines**: FastAPI endpoints can trigger async pipeline runs; see `data-pipelines.md`.
|
|
163
|
-
- **Python Conventions**: Type hints are mandatory in FastAPI; see `python-conventions.md`.
|
|
164
|
-
- **Testing**: Use `httpx.AsyncClient` with `app` for async test cases.
|