groundwork-method 0.0.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +823 -0
- package/LICENSE +21 -0
- package/README.md +44 -29
- package/bin/groundwork.js +1723 -0
- package/dist/src/generators/add-capability/generator.d.ts +8 -0
- package/dist/src/generators/add-capability/generator.js +60 -0
- package/dist/src/generators/add-capability/generator.js.map +1 -0
- package/dist/src/generators/cli-app/generator.d.ts +9 -0
- package/dist/src/generators/cli-app/generator.js +140 -0
- package/dist/src/generators/cli-app/generator.js.map +1 -0
- package/dist/src/generators/docs-site/generator.d.ts +5 -0
- package/dist/src/generators/docs-site/generator.js +441 -0
- package/dist/src/generators/docs-site/generator.js.map +1 -0
- package/dist/src/generators/electron-app/generator.d.ts +6 -0
- package/dist/src/generators/electron-app/generator.js +261 -0
- package/dist/src/generators/electron-app/generator.js.map +1 -0
- package/dist/src/generators/flutter-app/generator.d.ts +6 -0
- package/dist/src/generators/flutter-app/generator.js +314 -0
- package/dist/src/generators/flutter-app/generator.js.map +1 -0
- package/dist/src/generators/go-microservice/generator.d.ts +8 -0
- package/dist/src/generators/go-microservice/generator.js +232 -0
- package/dist/src/generators/go-microservice/generator.js.map +1 -0
- package/dist/src/generators/nextjs-app/generator.d.ts +8 -0
- package/dist/src/generators/nextjs-app/generator.js +294 -0
- package/dist/src/generators/nextjs-app/generator.js.map +1 -0
- package/dist/src/generators/python-microservice/generator.d.ts +13 -0
- package/dist/src/generators/python-microservice/generator.js +265 -0
- package/dist/src/generators/python-microservice/generator.js.map +1 -0
- package/dist/src/generators/shared/brand-tokens.d.ts +89 -0
- package/dist/src/generators/shared/brand-tokens.js +308 -0
- package/dist/src/generators/shared/brand-tokens.js.map +1 -0
- package/dist/src/generators/shared/capabilities.d.ts +101 -0
- package/dist/src/generators/shared/capabilities.js +279 -0
- package/dist/src/generators/shared/capabilities.js.map +1 -0
- package/dist/src/generators/shared/provenance.d.ts +2 -0
- package/dist/src/generators/shared/provenance.js +85 -0
- package/dist/src/generators/shared/provenance.js.map +1 -0
- package/dist/src/generators/shared/scaffold-helpers.d.ts +72 -0
- package/dist/src/generators/shared/scaffold-helpers.js +309 -0
- package/dist/src/generators/shared/scaffold-helpers.js.map +1 -0
- package/dist/src/generators/system-test-runner/generator.d.ts +23 -0
- package/dist/src/generators/system-test-runner/generator.js +173 -0
- package/dist/src/generators/system-test-runner/generator.js.map +1 -0
- package/dist/src/generators/workspace-dev-cli/generator.d.ts +7 -0
- package/dist/src/generators/workspace-dev-cli/generator.js +138 -0
- package/dist/src/generators/workspace-dev-cli/generator.js.map +1 -0
- package/generators.json +57 -0
- package/lib/repo-map/grammars/tree-sitter-c.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-cpp.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-csharp.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-dart.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-go.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-java.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-javascript.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-kotlin.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-lua.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-php.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-python.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-ruby.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-rust.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-scala.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-swift.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-tsx.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-typescript.wasm +0 -0
- package/lib/repo-map/index.js +386 -0
- package/lib/repo-map/languages.js +514 -0
- package/lib/repo-map/pagerank.js +59 -0
- package/migrations/README.md +60 -0
- package/migrations/_template/cli-migration.js +27 -0
- package/migrations/gw-bet-prose-redesign.js +105 -0
- package/migrations/gw-drop-test-manifest.js +37 -0
- package/migrations/gw-register-serena-mcp.js +42 -0
- package/migrations/gw-relocate-hidden-skills.js +40 -0
- package/migrations/gw-seed-config-toml.js +24 -0
- package/migrations/index.json +40 -0
- package/package.json +70 -6
- package/src/AGENTS.md +36 -0
- package/src/config/config.toml +30 -0
- package/src/config/groundwork-state.json +5 -0
- package/src/docs/llms.txt +72 -0
- package/src/docs/principles/ai-native/agent-native-systems.md +90 -0
- package/src/docs/principles/ai-native/agentic-systems.md +78 -0
- package/src/docs/principles/ai-native/ai-engineering.md +100 -0
- package/src/docs/principles/ai-native/ai-native-product.md +76 -0
- package/src/docs/principles/delivery/cost-engineering.md +89 -0
- package/src/docs/principles/delivery/day-2-operational-baseline.md +57 -0
- package/src/docs/principles/delivery/devex.md +88 -0
- package/src/docs/principles/delivery/platform.md +101 -0
- package/src/docs/principles/delivery/progressive-delivery.md +92 -0
- package/src/docs/principles/design/ai-native-design.md +73 -0
- package/src/docs/principles/design/design-foundations.md +80 -0
- package/src/docs/principles/design/design-systems-and-tokens.md +72 -0
- package/src/docs/principles/design/interaction-and-motion.md +69 -0
- package/src/docs/principles/design/layout-and-space.md +72 -0
- package/src/docs/principles/design/usability-and-ux.md +79 -0
- package/src/docs/principles/design/visual-design.md +84 -0
- package/src/docs/principles/foundations/code-craft.md +86 -0
- package/src/docs/principles/foundations/continuous-discovery.md +75 -0
- package/src/docs/principles/foundations/documentation.md +102 -0
- package/src/docs/principles/foundations/prioritization-and-appetite.md +78 -0
- package/src/docs/principles/foundations/product-engineering.md +90 -0
- package/src/docs/principles/foundations/product-risks.md +89 -0
- package/src/docs/principles/foundations/requirements-and-specs.md +80 -0
- package/src/docs/principles/foundations/success-metrics.md +66 -0
- package/src/docs/principles/foundations/testing.md +108 -0
- package/src/docs/principles/index.md +24 -0
- package/src/docs/principles/quality/accessibility.md +88 -0
- package/src/docs/principles/quality/observability.md +84 -0
- package/src/docs/principles/quality/performance.md +84 -0
- package/src/docs/principles/quality/privacy.md +92 -0
- package/src/docs/principles/quality/reliability.md +89 -0
- package/src/docs/principles/quality/security.md +78 -0
- package/src/docs/principles/stack/postgres.md +100 -0
- package/src/docs/principles/system-design/api-design.md +86 -0
- package/src/docs/principles/system-design/architecture-decisions.md +81 -0
- package/src/docs/principles/system-design/code-structure.md +104 -0
- package/src/docs/principles/system-design/data-engineering.md +87 -0
- package/src/docs/principles/system-design/durable-execution.md +89 -0
- package/src/docs/principles/system-design/evolutionary-architecture.md +81 -0
- package/src/docs/principles/system-design/identity-and-access.md +76 -0
- package/src/docs/principles/system-design/integration-patterns.md +84 -0
- package/src/docs/principles/system-design/real-time.md +83 -0
- package/src/docs/principles/system-design/surface-architecture.md +74 -0
- package/src/docs/ways-of-working/documentation.md +69 -0
- package/src/docs/ways-of-working/how-we-work.md +76 -0
- package/src/docs/ways-of-working/units-of-work.md +40 -0
- package/src/engineer-skills/groundwork-electron-engineer/SKILL.md +123 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/documentation.md +126 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/ipc-contracts.md +138 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/observability.md +37 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/packaging-and-updates.md +82 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/performance-and-reliability.md +80 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/process-model.md +94 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/security.md +107 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/testing-and-smoke.md +129 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/theming-and-tokens.md +74 -0
- package/src/engineer-skills/groundwork-electron-engineer/sync-anchor.md +22 -0
- package/src/engineer-skills/groundwork-flutter-engineer/SKILL.md +114 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/accessibility.md +92 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/architecture.md +189 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/data-and-contracts.md +136 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/documentation.md +122 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/navigation.md +122 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/observability.md +37 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/performance-and-reliability.md +100 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/platform-channels.md +93 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/releases-and-distribution.md +84 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/security.md +96 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/state-management.md +166 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/testing.md +160 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/theming-and-design-tokens.md +109 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/widgets-and-composition.md +123 -0
- package/src/engineer-skills/groundwork-flutter-engineer/sync-anchor.md +24 -0
- package/src/engineer-skills/groundwork-go-engineer/SKILL.md +174 -0
- package/src/engineer-skills/groundwork-go-engineer/references/api-design.md +82 -0
- package/src/engineer-skills/groundwork-go-engineer/references/architecture.md +42 -0
- package/src/engineer-skills/groundwork-go-engineer/references/capability-ports.md +50 -0
- package/src/engineer-skills/groundwork-go-engineer/references/code-craft-security.md +34 -0
- package/src/engineer-skills/groundwork-go-engineer/references/concurrency.md +108 -0
- package/src/engineer-skills/groundwork-go-engineer/references/documentation.md +130 -0
- package/src/engineer-skills/groundwork-go-engineer/references/go-services.md +77 -0
- package/src/engineer-skills/groundwork-go-engineer/references/http-handlers.md +172 -0
- package/src/engineer-skills/groundwork-go-engineer/references/implementation-patterns.md +156 -0
- package/src/engineer-skills/groundwork-go-engineer/references/integration-realtime-data.md +57 -0
- package/src/engineer-skills/groundwork-go-engineer/references/observability.md +49 -0
- package/src/engineer-skills/groundwork-go-engineer/references/postgres.md +41 -0
- package/src/engineer-skills/groundwork-go-engineer/references/reliability-performance.md +105 -0
- package/src/engineer-skills/groundwork-go-engineer/references/testing.md +201 -0
- package/src/engineer-skills/groundwork-go-engineer/sync-anchor.md +20 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/SKILL.md +112 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/accessibility.md +111 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/architecture.md +323 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/data-fetching.md +458 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/documentation.md +324 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/error-boundaries.md +383 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/mutations-and-forms.md +396 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/observability.md +48 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/performance-and-deployment.md +947 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/routing-and-navigation.md +405 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/security.md +131 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/server-components.md +394 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/tailwind-and-styling.md +134 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/testing.md +491 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/type-system.md +368 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/ux-principles.md +230 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/visual-language.md +69 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/sync-anchor.md +16 -0
- package/src/engineer-skills/groundwork-python-engineer/SKILL.md +199 -0
- package/src/engineer-skills/groundwork-python-engineer/references/api-standards.md +88 -0
- package/src/engineer-skills/groundwork-python-engineer/references/architecture.md +57 -0
- package/src/engineer-skills/groundwork-python-engineer/references/async-patterns.md +103 -0
- package/src/engineer-skills/groundwork-python-engineer/references/capability-ports.md +44 -0
- package/src/engineer-skills/groundwork-python-engineer/references/database.md +88 -0
- package/src/engineer-skills/groundwork-python-engineer/references/documentation-mcp.md +167 -0
- package/src/engineer-skills/groundwork-python-engineer/references/implementation-patterns.md +166 -0
- package/src/engineer-skills/groundwork-python-engineer/references/ml-pipelines.md +119 -0
- package/src/engineer-skills/groundwork-python-engineer/references/ml-systems-ai-engineering.md +74 -0
- package/src/engineer-skills/groundwork-python-engineer/references/observability.md +57 -0
- package/src/engineer-skills/groundwork-python-engineer/references/resilience.md +126 -0
- package/src/engineer-skills/groundwork-python-engineer/references/security.md +148 -0
- package/src/engineer-skills/groundwork-python-engineer/references/testing.md +216 -0
- package/src/engineer-skills/groundwork-python-engineer/sync-anchor.md +20 -0
- package/src/generators/add-capability/generator.ts +70 -0
- package/src/generators/add-capability/schema.json +30 -0
- package/src/generators/capabilities/llm/capability.json +28 -0
- package/src/generators/capabilities/llm/providers/anthropic/footprint.json +13 -0
- package/src/generators/capabilities/llm/providers/anthropic/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/anthropic/stacks/python/src/__packageName__/adapters/llm.py.template +61 -0
- package/src/generators/capabilities/llm/providers/local/footprint.json +13 -0
- package/src/generators/capabilities/llm/providers/local/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/local/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
- package/src/generators/capabilities/llm/providers/localai/footprint.json +29 -0
- package/src/generators/capabilities/llm/providers/localai/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/localai/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
- package/src/generators/capabilities/llm/providers/none/footprint.json +9 -0
- package/src/generators/capabilities/llm/providers/none/stacks/go/internal/llm/llm.go.template +35 -0
- package/src/generators/capabilities/llm/providers/none/stacks/python/src/__packageName__/adapters/llm.py.template +25 -0
- package/src/generators/capabilities/llm/providers/ollama/footprint.json +20 -0
- package/src/generators/capabilities/llm/providers/ollama/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/ollama/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
- package/src/generators/capabilities/llm/providers/openai/footprint.json +13 -0
- package/src/generators/capabilities/llm/providers/openai/stacks/go/internal/llm/llm.go.template +98 -0
- package/src/generators/capabilities/llm/providers/openai/stacks/python/src/__packageName__/adapters/llm.py.template +60 -0
- package/src/generators/capabilities/llm/stacks/go/internal/core/service/llm.go.template +12 -0
- package/src/generators/capabilities/llm/stacks/go/internal/llm/llm_test.go.template +33 -0
- package/src/generators/capabilities/llm/stacks/python/src/__packageName__/core/llm.py.template +15 -0
- package/src/generators/capabilities/llm/stacks/python/tests/contracts/test_llm.py.template +37 -0
- package/src/generators/cli-app/files/README.md.template +76 -0
- package/src/generators/cli-app/files/build.mjs.template +15 -0
- package/src/generators/cli-app/files/package.json.template +21 -0
- package/src/generators/cli-app/files/src/cli.ts.template +67 -0
- package/src/generators/cli-app/files/src/commands/hello.ts.template +17 -0
- package/src/generators/cli-app/files/src/commands/status.ts.template +23 -0
- package/src/generators/cli-app/files/src/core/client.test.ts.template +80 -0
- package/src/generators/cli-app/files/src/core/client.ts.template +64 -0
- package/src/generators/cli-app/files/src/registry.test.ts.template +35 -0
- package/src/generators/cli-app/files/src/registry.ts.template +31 -0
- package/src/generators/cli-app/files/tsconfig.json.template +16 -0
- package/src/generators/cli-app/files/tsconfig.test.json.template +11 -0
- package/src/generators/cli-app/generator.ts +138 -0
- package/src/generators/cli-app/schema.json +24 -0
- package/src/generators/docs-site/files/.gitignore.ejs +40 -0
- package/src/generators/docs-site/files/app/docs/__slug__/page.tsx +101 -0
- package/src/generators/docs-site/files/app/docs/layout.tsx +14 -0
- package/src/generators/docs-site/files/app/docs.css +43 -0
- package/src/generators/docs-site/files/app/layout.tsx +24 -0
- package/src/generators/docs-site/files/app/page.tsx +135 -0
- package/src/generators/docs-site/files/app/source.ts +8 -0
- package/src/generators/docs-site/files/components/mermaid.tsx +67 -0
- package/src/generators/docs-site/files/next.config.mjs +10 -0
- package/src/generators/docs-site/files/package.json +32 -0
- package/src/generators/docs-site/files/pnpm-workspace.yaml +7 -0
- package/src/generators/docs-site/files/postcss.config.mjs +6 -0
- package/src/generators/docs-site/files/source.config.ts +77 -0
- package/src/generators/docs-site/files/tailwind.config.js +10 -0
- package/src/generators/docs-site/files/tsconfig.json +27 -0
- package/src/generators/docs-site/generator.ts +476 -0
- package/src/generators/docs-site/schema.json +17 -0
- package/src/generators/electron-app/docs/principles/stack/electron/index.md +49 -0
- package/src/generators/electron-app/docs/principles/stack/electron/ipc-contracts.md +71 -0
- package/src/generators/electron-app/docs/principles/stack/electron/packaging-and-updates.md +59 -0
- package/src/generators/electron-app/docs/principles/stack/electron/process-model.md +53 -0
- package/src/generators/electron-app/docs/principles/stack/electron/security.md +70 -0
- package/src/generators/electron-app/docs/principles/stack/typescript/frontend.md +65 -0
- package/src/generators/electron-app/files/.gitignore.template +20 -0
- package/src/generators/electron-app/files/README.md.template +125 -0
- package/src/generators/electron-app/files/electron.vite.config.ts +31 -0
- package/src/generators/electron-app/files/eslint.config.mjs +92 -0
- package/src/generators/electron-app/files/forge.config.ts.template +44 -0
- package/src/generators/electron-app/files/package.json.template +54 -0
- package/src/generators/electron-app/files/playwright.config.ts +18 -0
- package/src/generators/electron-app/files/project.json.template +65 -0
- package/src/generators/electron-app/files/src/main/core-client.test.ts +81 -0
- package/src/generators/electron-app/files/src/main/core-client.ts +55 -0
- package/src/generators/electron-app/files/src/main/index.ts +157 -0
- package/src/generators/electron-app/files/src/main/ipc.ts +52 -0
- package/src/generators/electron-app/files/src/main/policy.test.ts +71 -0
- package/src/generators/electron-app/files/src/main/policy.ts +73 -0
- package/src/generators/electron-app/files/src/preload/index.ts +23 -0
- package/src/generators/electron-app/files/src/renderer/index.html.template +20 -0
- package/src/generators/electron-app/files/src/renderer/src/App.test.tsx +61 -0
- package/src/generators/electron-app/files/src/renderer/src/App.tsx.template +43 -0
- package/src/generators/electron-app/files/src/renderer/src/assets/main.css +40 -0
- package/src/generators/electron-app/files/src/renderer/src/env.d.ts +14 -0
- package/src/generators/electron-app/files/src/renderer/src/main.tsx +25 -0
- package/src/generators/electron-app/files/src/shared/ipc.ts +54 -0
- package/src/generators/electron-app/files/tests/smoke/app.spec.ts.template +133 -0
- package/src/generators/electron-app/files/tool/electron_exec.sh.template +83 -0
- package/src/generators/electron-app/files/tsconfig.json +7 -0
- package/src/generators/electron-app/files/tsconfig.node.json +27 -0
- package/src/generators/electron-app/files/tsconfig.web.json +22 -0
- package/src/generators/electron-app/files/vitest.config.ts +32 -0
- package/src/generators/electron-app/files/vitest.setup.ts +1 -0
- package/src/generators/electron-app/generator.ts +288 -0
- package/src/generators/electron-app/schema.json +23 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/architecture.md +78 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/index.md +38 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/platform-channels.md +51 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/releases-and-distribution.md +59 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/state-management.md +85 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/testing.md +86 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/widgets-and-composition.md +69 -0
- package/src/generators/flutter-app/files/.gitignore.template +30 -0
- package/src/generators/flutter-app/files/README.md.template +100 -0
- package/src/generators/flutter-app/files/analysis_options.yaml.template +18 -0
- package/src/generators/flutter-app/files/integration_test/app_test.dart.template +64 -0
- package/src/generators/flutter-app/files/lib/app.dart.template +24 -0
- package/src/generators/flutter-app/files/lib/config/app_config.dart +15 -0
- package/src/generators/flutter-app/files/lib/data/repositories/status_repository.dart +36 -0
- package/src/generators/flutter-app/files/lib/data/services/api_client.dart +71 -0
- package/src/generators/flutter-app/files/lib/domain/models/health_status.dart +23 -0
- package/src/generators/flutter-app/files/lib/main.dart +11 -0
- package/src/generators/flutter-app/files/lib/router.dart +23 -0
- package/src/generators/flutter-app/files/lib/ui/core/theme/app_theme.dart +110 -0
- package/src/generators/flutter-app/files/lib/ui/home/home_view.dart +89 -0
- package/src/generators/flutter-app/files/lib/ui/home/home_view_model.dart.template +38 -0
- package/src/generators/flutter-app/files/project.json.template +51 -0
- package/src/generators/flutter-app/files/pubspec.yaml.template +47 -0
- package/src/generators/flutter-app/files/test/api_client_test.dart.template +63 -0
- package/src/generators/flutter-app/files/test/fakes/fake_status_repository.dart.template +19 -0
- package/src/generators/flutter-app/files/test/home_view_test.dart.template +58 -0
- package/src/generators/flutter-app/files/tool/flutter_exec.sh.template +60 -0
- package/src/generators/flutter-app/generator.ts +362 -0
- package/src/generators/flutter-app/schema.json +23 -0
- package/src/generators/go-microservice/docs/principles/stack/go/concurrency.md +123 -0
- package/src/generators/go-microservice/docs/principles/stack/go/index.md +70 -0
- package/src/generators/go-microservice/docs/principles/stack/go/testing.md +168 -0
- package/src/generators/go-microservice/files/.air.toml.template +38 -0
- package/src/generators/go-microservice/files/.env.template +4 -0
- package/src/generators/go-microservice/files/.golangci.yml.template +82 -0
- package/src/generators/go-microservice/files/Dockerfile.dev.template +12 -0
- package/src/generators/go-microservice/files/asyncapi-pubsub.yaml.template +33 -0
- package/src/generators/go-microservice/files/asyncapi-ws.yaml.template +34 -0
- package/src/generators/go-microservice/files/cmd/api/main.go.template +149 -0
- package/src/generators/go-microservice/files/cmd/api/main_test.go.template +99 -0
- package/src/generators/go-microservice/files/cmd/worker/cleanup/main.go.template +39 -0
- package/src/generators/go-microservice/files/db/schema.sql.template +24 -0
- package/src/generators/go-microservice/files/go.mod.template +39 -0
- package/src/generators/go-microservice/files/internal/config/config.go.template +52 -0
- package/src/generators/go-microservice/files/internal/config/otel.go.template +93 -0
- package/src/generators/go-microservice/files/internal/core/domain/errors.go.template +16 -0
- package/src/generators/go-microservice/files/internal/core/domain/model.go.template +28 -0
- package/src/generators/go-microservice/files/internal/core/domain/user.go.template +13 -0
- package/src/generators/go-microservice/files/internal/core/pagination.go.template +16 -0
- package/src/generators/go-microservice/files/internal/core/service/app_service.go.template +79 -0
- package/src/generators/go-microservice/files/internal/core/service/event_hub.go.template +9 -0
- package/src/generators/go-microservice/files/internal/core/service/message_queue.go.template +10 -0
- package/src/generators/go-microservice/files/internal/core/service/outbox_repository.go.template +31 -0
- package/src/generators/go-microservice/files/internal/core/service/repository.go.template +23 -0
- package/src/generators/go-microservice/files/internal/core/service/user_repository.go.template +15 -0
- package/src/generators/go-microservice/files/internal/core/service/user_service.go.template +43 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/app_handler.go.template +108 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/auth_middleware_test.go.template +52 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/clerk_webhook.go.template +202 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/clerk_webhook_test.go.template +82 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/health_handler.go.template +80 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/middleware.go.template +87 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/middleware_test.go.template +76 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/repository.go.template +37 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_auth.go.template +40 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_loadshed.go.template +38 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_logging.go.template +40 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_ratelimit.go.template +48 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_test.go.template +81 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/router.go.template +105 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/types.go.template +70 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/websocket_handler.go.template +39 -0
- package/src/generators/go-microservice/files/internal/httpclient/http_client.go.template +87 -0
- package/src/generators/go-microservice/files/internal/kafka/kafka.go.template +34 -0
- package/src/generators/go-microservice/files/internal/postgres/postgres.go.template +195 -0
- package/src/generators/go-microservice/files/internal/postgres/postgres_test.go.template +156 -0
- package/src/generators/go-microservice/files/internal/postgres/user_repository.go.template +56 -0
- package/src/generators/go-microservice/files/internal/pubsub/gcp_pubsub.go.template +35 -0
- package/src/generators/go-microservice/files/internal/websocket/client.go.template +151 -0
- package/src/generators/go-microservice/files/internal/websocket/hub.go.template +261 -0
- package/src/generators/go-microservice/files/scripts/apply-schema.sh.template +21 -0
- package/src/generators/go-microservice/files/tools/tools.go.template +10 -0
- package/src/generators/go-microservice/generator.ts +240 -0
- package/src/generators/go-microservice/schema.json +63 -0
- package/src/generators/nextjs-app/docs/principles/stack/typescript/frontend.md +65 -0
- package/src/generators/nextjs-app/files/.dockerignore.template +7 -0
- package/src/generators/nextjs-app/files/.env.example.template +24 -0
- package/src/generators/nextjs-app/files/.gitignore.template +5 -0
- package/src/generators/nextjs-app/files/Dockerfile +53 -0
- package/src/generators/nextjs-app/files/app/(auth)/sign-in/__sign-in__/page.tsx.template +9 -0
- package/src/generators/nextjs-app/files/app/(auth)/sign-up/__sign-up__/page.tsx.template +9 -0
- package/src/generators/nextjs-app/files/app/api/config/route.ts.template +39 -0
- package/src/generators/nextjs-app/files/app/api/healthz/route.test.ts +15 -0
- package/src/generators/nextjs-app/files/app/api/healthz/route.ts +5 -0
- package/src/generators/nextjs-app/files/app/api/proxy/__path__/route.test.ts.template +55 -0
- package/src/generators/nextjs-app/files/app/api/proxy/__path__/route.ts.template +126 -0
- package/src/generators/nextjs-app/files/app/error.tsx +39 -0
- package/src/generators/nextjs-app/files/app/global-error.tsx +68 -0
- package/src/generators/nextjs-app/files/app/globals.css +105 -0
- package/src/generators/nextjs-app/files/app/layout.tsx +59 -0
- package/src/generators/nextjs-app/files/app/loading.tsx +13 -0
- package/src/generators/nextjs-app/files/app/not-found.tsx +30 -0
- package/src/generators/nextjs-app/files/app/page.tsx +20 -0
- package/src/generators/nextjs-app/files/components/providers/default.tsx +19 -0
- package/src/generators/nextjs-app/files/components/providers/production.tsx +32 -0
- package/src/generators/nextjs-app/files/components/providers/telemetry.tsx +76 -0
- package/src/generators/nextjs-app/files/components/render-smoke.test.tsx +29 -0
- package/src/generators/nextjs-app/files/components/theme-provider.tsx +11 -0
- package/src/generators/nextjs-app/files/components.json +21 -0
- package/src/generators/nextjs-app/files/eslint.config.mjs +120 -0
- package/src/generators/nextjs-app/files/hooks/use-toast.ts +7 -0
- package/src/generators/nextjs-app/files/instrumentation.ts +90 -0
- package/src/generators/nextjs-app/files/lib/api/fetcher.ts.template +130 -0
- package/src/generators/nextjs-app/files/lib/config.ts +21 -0
- package/src/generators/nextjs-app/files/lib/logger.ts +29 -0
- package/src/generators/nextjs-app/files/lib/schemas/index.ts +19 -0
- package/src/generators/nextjs-app/files/lib/utils.ts +6 -0
- package/src/generators/nextjs-app/files/next.config.mjs +9 -0
- package/src/generators/nextjs-app/files/package.json +70 -0
- package/src/generators/nextjs-app/files/postcss.config.mjs +8 -0
- package/src/generators/nextjs-app/files/proxy.test.ts.template +30 -0
- package/src/generators/nextjs-app/files/proxy.ts +31 -0
- package/src/generators/nextjs-app/files/public/.gitkeep +1 -0
- package/src/generators/nextjs-app/files/tsconfig.json +42 -0
- package/src/generators/nextjs-app/files/vitest.config.mts +15 -0
- package/src/generators/nextjs-app/files/vitest.setup.ts +7 -0
- package/src/generators/nextjs-app/generator.ts +307 -0
- package/src/generators/nextjs-app/schema.json +44 -0
- package/src/generators/python-microservice/docs/principles/stack/python/async.md +168 -0
- package/src/generators/python-microservice/docs/principles/stack/python/documentation.md +240 -0
- package/src/generators/python-microservice/docs/principles/stack/python/mcp.md +147 -0
- package/src/generators/python-microservice/docs/principles/stack/python/resilience.md +193 -0
- package/src/generators/python-microservice/docs/principles/stack/python/testing.md +322 -0
- package/src/generators/python-microservice/files/.env.example.template +30 -0
- package/src/generators/python-microservice/files/Dockerfile.template +36 -0
- package/src/generators/python-microservice/files/db/schema.sql.template +19 -0
- package/src/generators/python-microservice/files/pyproject.toml.template +76 -0
- package/src/generators/python-microservice/files/scripts/apply-schema.sh.template +25 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/comfyui.py.template +87 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/config.py.template +48 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/database.py.template +21 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/message_queue.py.template +29 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/repository.py.template +130 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/telemetry.py.template +68 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/websocket_hub.py.template +36 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/domain/entities.py.template +22 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/domain/exceptions.py.template +43 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/ports.py.template +42 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/service/example_service.py.template +68 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/dependencies.py.template +50 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/middleware.py.template +131 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/router.py.template +37 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/websocket_handler.py.template +20 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/worker/cleanup.py.template +35 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/worker/worker.py.template +28 -0
- package/src/generators/python-microservice/files/src/__packageName__/main.py.template +108 -0
- package/src/generators/python-microservice/files/tests/test_main.py.template +74 -0
- package/src/generators/python-microservice/files/tests/test_middleware.py.template +109 -0
- package/src/generators/python-microservice/files/tests/test_worker.py.template +16 -0
- package/src/generators/python-microservice/generator.ts +286 -0
- package/src/generators/python-microservice/schema.json +86 -0
- package/src/generators/shared/brand-tokens.ts +301 -0
- package/src/generators/shared/capabilities.ts +349 -0
- package/src/generators/shared/provenance.ts +61 -0
- package/src/generators/shared/scaffold-helpers.ts +309 -0
- package/src/generators/system-test-runner/NATIVE-CHECK-CONTRACT.md +20 -0
- package/src/generators/system-test-runner/files/tests/bets/.gitkeep +0 -0
- package/src/generators/system-test-runner/files/tests/bets/_archive/.gitkeep +0 -0
- package/src/generators/system-test-runner/files/tests/conftest.py.template +503 -0
- package/src/generators/system-test-runner/files/tests/pyproject.toml.template +20 -0
- package/src/generators/system-test-runner/files/tests/system/pages/__init__.py.template +9 -0
- package/src/generators/system-test-runner/files/tests/system/pages/base_page.py.template +36 -0
- package/src/generators/system-test-runner/files/tests/system/test_a11y_smoke.py.template +132 -0
- package/src/generators/system-test-runner/files/tests/system/test_contract_conformance.py.template +140 -0
- package/src/generators/system-test-runner/files/tests/system/test_layout_geometry.py.template +109 -0
- package/src/generators/system-test-runner/files/tests/system/test_render_smoke.py.template +257 -0
- package/src/generators/system-test-runner/files/tests/system/test_system.py.template +158 -0
- package/src/generators/system-test-runner/files/tests/system/test_token_conformance.py.template +206 -0
- package/src/generators/system-test-runner/files/tests/system/test_visual_regression.py.template +104 -0
- package/src/generators/system-test-runner/generator.ts +196 -0
- package/src/generators/system-test-runner/schema.json +24 -0
- package/src/generators/workspace-dev-cli/cli-src/build.mjs +42 -0
- package/src/generators/workspace-dev-cli/cli-src/dist/dev-bundle.js +2168 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/bet.ts +442 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/completion.ts +87 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/doctor.ts +139 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/lifecycle.ts +548 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/quality.ts +127 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/surface.ts +214 -0
- package/src/generators/workspace-dev-cli/cli-src/src/index.ts +127 -0
- package/src/generators/workspace-dev-cli/cli-src/src/registry.ts +194 -0
- package/src/generators/workspace-dev-cli/cli-src/src/theme/color.ts +130 -0
- package/src/generators/workspace-dev-cli/cli-src/src/theme/render.ts +158 -0
- package/src/generators/workspace-dev-cli/cli-src/src/theme/tokens.ts +122 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/context.ts +43 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/extensions.ts +99 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/paths.ts +46 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/proc.ts +106 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/prompt.ts +108 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/runners.ts +70 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/services.ts +221 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/version.ts +21 -0
- package/src/generators/workspace-dev-cli/cli-src/tsconfig.json +16 -0
- package/src/generators/workspace-dev-cli/files/.agents/skills/workspace-cli/SKILL.md.template +74 -0
- package/src/generators/workspace-dev-cli/files/dev.template +16 -0
- package/src/generators/workspace-dev-cli/files/docker-compose.yml.template +20 -0
- package/src/generators/workspace-dev-cli/files/scripts/cli/templates/milestone-test.pytmpl.template +46 -0
- package/src/generators/workspace-dev-cli/files/scripts/cli/templates/slice-test.pytmpl.template +38 -0
- package/src/generators/workspace-dev-cli/generator.ts +136 -0
- package/src/generators/workspace-dev-cli/schema.json +22 -0
- package/src/hidden-skills/code-intelligence.md +135 -0
- package/src/hidden-skills/groundwork-architect/SKILL.md +114 -0
- package/src/hidden-skills/groundwork-architect/references/agentic-systems.md +44 -0
- package/src/hidden-skills/groundwork-architect/references/ai-native-architecture.md +37 -0
- package/src/hidden-skills/groundwork-architect/references/api-and-contracts.md +45 -0
- package/src/hidden-skills/groundwork-architect/references/core-and-boundaries.md +45 -0
- package/src/hidden-skills/groundwork-architect/references/data-architecture.md +33 -0
- package/src/hidden-skills/groundwork-architect/references/decision-records.md +34 -0
- package/src/hidden-skills/groundwork-architect/references/durable-execution.md +45 -0
- package/src/hidden-skills/groundwork-architect/references/evolutionary-architecture.md +37 -0
- package/src/hidden-skills/groundwork-architect/references/identity-and-access.md +41 -0
- package/src/hidden-skills/groundwork-architect/references/integration-patterns.md +39 -0
- package/src/hidden-skills/groundwork-architect/references/observability.md +36 -0
- package/src/hidden-skills/groundwork-architect/references/performance-and-scale.md +41 -0
- package/src/hidden-skills/groundwork-architect/references/platform-and-delivery.md +47 -0
- package/src/hidden-skills/groundwork-architect/references/realtime-and-async.md +28 -0
- package/src/hidden-skills/groundwork-architect/references/reliability.md +31 -0
- package/src/hidden-skills/groundwork-architect/references/security-and-trust.md +47 -0
- package/src/hidden-skills/groundwork-architect/references/surface-architecture.md +40 -0
- package/src/hidden-skills/groundwork-architect/sync-anchor.md +34 -0
- package/src/hidden-skills/groundwork-architecture/architecture-template.md +50 -0
- package/src/hidden-skills/groundwork-architecture/instructions.md +139 -0
- package/src/hidden-skills/groundwork-architecture/phases/01-context-ingestion.md +18 -0
- package/src/hidden-skills/groundwork-architecture/phases/02-technical-constraints.md +27 -0
- package/src/hidden-skills/groundwork-architecture/phases/03-service-design.md +19 -0
- package/src/hidden-skills/groundwork-architecture/phases/04-data-flow-communication.md +23 -0
- package/src/hidden-skills/groundwork-architecture/phases/05-component-boundaries-contracts.md +17 -0
- package/src/hidden-skills/groundwork-architecture/phases/06-draft-review-present.md +38 -0
- package/src/hidden-skills/groundwork-architecture/phases/07-commit.md +33 -0
- package/src/hidden-skills/groundwork-architecture/templates/architecture-cache.md +43 -0
- package/src/hidden-skills/groundwork-architecture-extract/instructions.md +163 -0
- package/src/hidden-skills/groundwork-architecture-extract/templates/architecture-extract-cache.md +21 -0
- package/src/hidden-skills/groundwork-bet/briefs/acceptance-auditor.md +68 -0
- package/src/hidden-skills/groundwork-bet/briefs/blind-reviewer.md +56 -0
- package/src/hidden-skills/groundwork-bet/briefs/coverage-auditor.md +95 -0
- package/src/hidden-skills/groundwork-bet/briefs/edge-case-tracer.md +64 -0
- package/src/hidden-skills/groundwork-bet/briefs/experience-auditor.md +83 -0
- package/src/hidden-skills/groundwork-bet/briefs/slice-worker.md +257 -0
- package/src/hidden-skills/groundwork-bet/instructions.md +88 -0
- package/src/hidden-skills/groundwork-bet/templates/bet-progress-test.md +115 -0
- package/src/hidden-skills/groundwork-bet/templates/change-proposal.md +38 -0
- package/src/hidden-skills/groundwork-bet/templates/decomposition/meta.json +4 -0
- package/src/hidden-skills/groundwork-bet/templates/decomposition/milestone-index.md +31 -0
- package/src/hidden-skills/groundwork-bet/templates/decomposition/slice.md +31 -0
- package/src/hidden-skills/groundwork-bet/templates/pitch.md +45 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/01-ui-design.md +51 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/02-data-flows.md +36 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/03-api-design.md +90 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/04-data-design.md +29 -0
- package/src/hidden-skills/groundwork-bet/workflows/01-discovery.md +200 -0
- package/src/hidden-skills/groundwork-bet/workflows/02-design.md +178 -0
- package/src/hidden-skills/groundwork-bet/workflows/03-decomposition.md +242 -0
- package/src/hidden-skills/groundwork-bet/workflows/04-delivery.md +226 -0
- package/src/hidden-skills/groundwork-bet/workflows/05-validation.md +210 -0
- package/src/hidden-skills/groundwork-design-system/instructions.md +125 -0
- package/src/hidden-skills/groundwork-design-system/templates/brand-tokens.md +182 -0
- package/src/hidden-skills/groundwork-design-system/templates/design-system-cache.md +64 -0
- package/src/hidden-skills/groundwork-design-system/tracks/_foundation.md +136 -0
- package/src/hidden-skills/groundwork-design-system/tracks/agentic-protocol.md +269 -0
- package/src/hidden-skills/groundwork-design-system/tracks/cli.md +355 -0
- package/src/hidden-skills/groundwork-design-system/tracks/graphical-ui.md +330 -0
- package/src/hidden-skills/groundwork-design-system-extract/instructions.md +124 -0
- package/src/hidden-skills/groundwork-design-system-extract/templates/design-system-extract-cache.md +19 -0
- package/src/hidden-skills/groundwork-designer/SKILL.md +108 -0
- package/src/hidden-skills/groundwork-designer/references/accessibility.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/ai-native-design.md +37 -0
- package/src/hidden-skills/groundwork-designer/references/design-review.md +29 -0
- package/src/hidden-skills/groundwork-designer/references/design-systems-and-tokens.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/interaction-and-motion.md +37 -0
- package/src/hidden-skills/groundwork-designer/references/layout-and-space.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/usability-and-ux.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/visual-craft.md +49 -0
- package/src/hidden-skills/groundwork-designer/sync-anchor.md +20 -0
- package/src/hidden-skills/groundwork-doc-sync/instructions.md +100 -0
- package/src/hidden-skills/groundwork-elicit/instructions.md +66 -0
- package/src/hidden-skills/groundwork-elicit/methods.md +65 -0
- package/src/hidden-skills/groundwork-infra-adopt/instructions.md +168 -0
- package/src/hidden-skills/groundwork-infra-adopt/templates/infra-adopt-cache.md +21 -0
- package/src/hidden-skills/groundwork-mvp/instructions.md +223 -0
- package/src/hidden-skills/groundwork-mvp/templates/mvp-cache.md +9 -0
- package/src/hidden-skills/groundwork-patch/instructions.md +40 -0
- package/src/hidden-skills/groundwork-persona/instructions.md +65 -0
- package/src/hidden-skills/groundwork-product/SKILL.md +102 -0
- package/src/hidden-skills/groundwork-product/references/ai-native-product.md +45 -0
- package/src/hidden-skills/groundwork-product/references/discovery-and-opportunity.md +38 -0
- package/src/hidden-skills/groundwork-product/references/product-risks.md +52 -0
- package/src/hidden-skills/groundwork-product/references/requirements-and-specs.md +39 -0
- package/src/hidden-skills/groundwork-product/references/scope-and-sequencing.md +35 -0
- package/src/hidden-skills/groundwork-product/references/shaping-and-appetite.md +48 -0
- package/src/hidden-skills/groundwork-product/references/success-metrics-and-signals.md +37 -0
- package/src/hidden-skills/groundwork-product/sync-anchor.md +19 -0
- package/src/hidden-skills/groundwork-product-brief/instructions.md +231 -0
- package/src/hidden-skills/groundwork-product-brief-extract/instructions.md +139 -0
- package/src/hidden-skills/groundwork-product-brief-extract/templates/product-brief-extract-cache.md +17 -0
- package/src/hidden-skills/groundwork-review/checklists/architecture.md +93 -0
- package/src/hidden-skills/groundwork-review/checklists/bet-pitch.md +94 -0
- package/src/hidden-skills/groundwork-review/checklists/decomposition.md +135 -0
- package/src/hidden-skills/groundwork-review/checklists/design-system.md +85 -0
- package/src/hidden-skills/groundwork-review/checklists/domain-entity.md +66 -0
- package/src/hidden-skills/groundwork-review/checklists/implementation-readiness.md +47 -0
- package/src/hidden-skills/groundwork-review/checklists/infrastructure.md +68 -0
- package/src/hidden-skills/groundwork-review/checklists/maturity.md +71 -0
- package/src/hidden-skills/groundwork-review/checklists/product-brief.md +69 -0
- package/src/hidden-skills/groundwork-review/checklists/technical-design.md +112 -0
- package/src/hidden-skills/groundwork-review/instructions.md +181 -0
- package/src/hidden-skills/groundwork-scaffold/instructions.md +254 -0
- package/src/hidden-skills/groundwork-scaffold/phases/01-ingestion-service-mapping.md +87 -0
- package/src/hidden-skills/groundwork-scaffold/phases/02-scaffolding-execution.md +15 -0
- package/src/hidden-skills/groundwork-scaffold/phases/03-service-documentation-api-stubs.md +100 -0
- package/src/hidden-skills/groundwork-scaffold/phases/04-infrastructure-verification.md +17 -0
- package/src/hidden-skills/groundwork-scaffold/phases/05-draft-review.md +19 -0
- package/src/hidden-skills/groundwork-scaffold/phases/06-commit.md +19 -0
- package/src/hidden-skills/groundwork-scaffold/templates/scaffold-cache.md +23 -0
- package/src/hidden-skills/groundwork-scan/instructions.md +164 -0
- package/src/hidden-skills/groundwork-scan/references/digest-schema.md +66 -0
- package/src/hidden-skills/groundwork-scan/references/exclusions.md +44 -0
- package/src/hidden-skills/groundwork-scan/templates/architecture-findings.md +42 -0
- package/src/hidden-skills/groundwork-scan/templates/design-findings.md +23 -0
- package/src/hidden-skills/groundwork-scan/templates/overview.md +26 -0
- package/src/hidden-skills/groundwork-scan/templates/product-findings.md +23 -0
- package/src/hidden-skills/groundwork-scan/templates/scan-state.json +19 -0
- package/src/hidden-skills/groundwork-stack-forge/instructions.md +150 -0
- package/src/hidden-skills/groundwork-stack-forge/references/authoring-engineer-skills.md +107 -0
- package/src/hidden-skills/groundwork-surface-activation/instructions.md +138 -0
- package/src/hidden-skills/groundwork-update/briefs/reconcile-worker.md +196 -0
- package/src/hidden-skills/groundwork-update/instructions.md +200 -0
- package/src/hidden-skills/groundwork-writer/SKILL.md +278 -0
- package/src/hidden-skills/maturity-model.md +125 -0
- package/src/hidden-skills/operating-contract.md +400 -0
- package/src/hidden-skills/repo-map-schema.md +90 -0
- package/src/hidden-skills/templates/adr.md +57 -0
- package/src/hidden-skills/templates/capability-ports.md +71 -0
- package/src/hidden-skills/templates/discovery-notes.md +33 -0
- package/src/hidden-skills/templates/domain-entity.md +80 -0
- package/src/hidden-skills/templates/gap-ledger.md +21 -0
- package/src/hidden-skills/templates/handoff.md +37 -0
- package/src/hidden-skills/templates/maturity.md +39 -0
- package/src/hidden-skills/templates/surfaces.md +207 -0
- package/src/skills/groundwork-check/SKILL.md +56 -0
- package/src/skills/groundwork-check/instructions.md +70 -0
- package/src/skills/groundwork-orchestrator/SKILL.md +176 -0
- package/src/skills/groundwork-orchestrator/workflow-index.md +50 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Navigation
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [The Router Is go_router](#the-router-is-go_router)
|
|
5
|
+
- [The Route Table](#the-route-table)
|
|
6
|
+
- [Typed Routes](#typed-routes)
|
|
7
|
+
- [Tab Scaffolds: StatefulShellRoute](#tab-scaffolds-statefulshellroute)
|
|
8
|
+
- [Auth Guards: Centralized redirect](#auth-guards-centralized-redirect)
|
|
9
|
+
- [The Route as State](#the-route-as-state)
|
|
10
|
+
- [Deep Links](#deep-links)
|
|
11
|
+
- [What Remains for Navigator 1.0](#what-remains-for-navigator-10)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## The Router Is go_router
|
|
16
|
+
|
|
17
|
+
go_router (flutter.dev verified publisher, declared feature-complete — a stable platform piece) owns app-level navigation. The router lives in one module as a provider:
|
|
18
|
+
|
|
19
|
+
```dart
|
|
20
|
+
final routerProvider = Provider<GoRouter>((ref) {
|
|
21
|
+
return GoRouter(
|
|
22
|
+
routes: [/* the route table */],
|
|
23
|
+
redirect: (context, state) => _guard(ref, state),
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`MaterialApp.router(routerConfig: ref.watch(routerProvider))` is the only place the router meets the widget tree. Hand-rolled `RouterDelegate`/Navigator 2.0 code is legacy — it is the API go_router exists to hide. Do not write it, and refactor it away on contact.
|
|
29
|
+
|
|
30
|
+
## The Route Table
|
|
31
|
+
|
|
32
|
+
One table, hierarchical, every destination declared:
|
|
33
|
+
|
|
34
|
+
```dart
|
|
35
|
+
GoRoute(
|
|
36
|
+
path: '/orders',
|
|
37
|
+
name: 'orders',
|
|
38
|
+
builder: (context, state) => const OrdersView(),
|
|
39
|
+
routes: [
|
|
40
|
+
GoRoute(
|
|
41
|
+
path: ':orderId',
|
|
42
|
+
name: 'order-detail',
|
|
43
|
+
builder: (context, state) =>
|
|
44
|
+
OrderDetailView(orderId: state.pathParameters['orderId']!),
|
|
45
|
+
),
|
|
46
|
+
],
|
|
47
|
+
)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Conventions:
|
|
51
|
+
|
|
52
|
+
- Paths are URL-shaped and lowercase-kebab; names exist for every route.
|
|
53
|
+
- The view receives parsed parameters via its constructor — it does not read `GoRouterState` internally.
|
|
54
|
+
- New screens are added to the table, never pushed ad hoc from a feature file.
|
|
55
|
+
|
|
56
|
+
## Typed Routes
|
|
57
|
+
|
|
58
|
+
As the table grows past a few routes, adopt `go_router_builder` typed routes — route paths and parameters as generated, compile-checked classes:
|
|
59
|
+
|
|
60
|
+
```dart
|
|
61
|
+
@TypedGoRoute<OrderDetailRoute>(path: '/orders/:orderId')
|
|
62
|
+
class OrderDetailRoute extends GoRouteData {
|
|
63
|
+
const OrderDetailRoute({required this.orderId});
|
|
64
|
+
final String orderId;
|
|
65
|
+
|
|
66
|
+
@override
|
|
67
|
+
Widget build(BuildContext context, GoRouterState state) =>
|
|
68
|
+
OrderDetailView(orderId: orderId);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Navigation becomes compile-checked:
|
|
72
|
+
const OrderDetailRoute(orderId: '42').go(context);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Stringly-typed `context.go('/orders/$id')` calls scattered through features are the navigation equivalent of hand-rolled JSON — acceptable only while the table is a handful of routes, refactored to typed routes as it grows.
|
|
76
|
+
|
|
77
|
+
## Tab Scaffolds: StatefulShellRoute
|
|
78
|
+
|
|
79
|
+
Bottom-bar/tab UIs use `StatefulShellRoute.indexedStack` — per-tab navigation stacks whose state survives tab switches:
|
|
80
|
+
|
|
81
|
+
```dart
|
|
82
|
+
StatefulShellRoute.indexedStack(
|
|
83
|
+
builder: (context, state, shell) => AppScaffold(shell: shell),
|
|
84
|
+
branches: [
|
|
85
|
+
StatefulShellBranch(routes: [GoRoute(path: '/home', ...)]),
|
|
86
|
+
StatefulShellBranch(routes: [GoRoute(path: '/settings', ...)]),
|
|
87
|
+
],
|
|
88
|
+
)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Do not hand-roll tab stacks with nested Navigators.
|
|
92
|
+
|
|
93
|
+
## Auth Guards: Centralized redirect
|
|
94
|
+
|
|
95
|
+
Auth is one `redirect` function on the router — never per-screen checks:
|
|
96
|
+
|
|
97
|
+
```dart
|
|
98
|
+
String? _guard(Ref ref, GoRouterState state) {
|
|
99
|
+
final signedIn = ref.read(sessionProvider).isSignedIn;
|
|
100
|
+
final signingIn = state.matchedLocation == '/sign-in';
|
|
101
|
+
if (!signedIn && !signingIn) return '/sign-in?from=${state.matchedLocation}';
|
|
102
|
+
if (signedIn && signingIn) return '/';
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Wire the session provider to the router with `refreshListenable` (or rebuild the router provider on session change) so guard decisions re-evaluate when auth state changes.
|
|
108
|
+
|
|
109
|
+
## The Route as State
|
|
110
|
+
|
|
111
|
+
The URL is a first-class state container. Selected entity id, active tab, current screen — if the route encodes it, **no provider duplicates it**; a provider mirroring the route will drift. This also makes navigation state survive process death for free, which matters because mobile processes die constantly.
|
|
112
|
+
|
|
113
|
+
## Deep Links
|
|
114
|
+
|
|
115
|
+
Anything declared as a `GoRoute` is deep-linkable across Android/iOS — that falls out of the declarative table. Practical consequences:
|
|
116
|
+
|
|
117
|
+
- Every route must render sensibly when entered **directly** (cold start onto `/orders/42`): the view model fetches what it needs from its id parameters; no route depends on in-memory state a previous screen happened to leave behind.
|
|
118
|
+
- Guard-sensitive routes are protected by the central `redirect`, so deep links cannot skip auth.
|
|
119
|
+
|
|
120
|
+
## What Remains for Navigator 1.0
|
|
121
|
+
|
|
122
|
+
Imperative `showDialog`, `showModalBottomSheet`, and one-off local flows are fine — they are transient UI, not app navigation. The boundary: if a destination should be linkable, restorable, or guarded, it is a `GoRoute`; if it is a momentary overlay, Navigator 1.0 primitives are correct.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Observability
|
|
2
|
+
|
|
3
|
+
A Flutter client emits no OpenTelemetry server spans. Distributed tracing lives at the capability core, where the gateway owns the request trace and asserts it with an in-memory exporter — which is why trace-assertions are N/A on the client (`references/testing.md`). The client's observability job is **crash and UX telemetry**: what broke, where, and what the user was doing when it did. Instrument for the questions you will ask when a crash report lands; the discipline is the framework canon adapted to a device you do not control (`docs/principles/quality/observability.md`).
|
|
4
|
+
|
|
5
|
+
## Crash and Error Reporting
|
|
6
|
+
|
|
7
|
+
A crash/error sink (Sentry or Firebase Crashlytics shape) captures unhandled failures. Two handlers are mandatory, because they catch different errors:
|
|
8
|
+
|
|
9
|
+
- `FlutterError.onError` — errors raised inside the Flutter framework (build, layout, paint).
|
|
10
|
+
- `PlatformDispatcher.instance.onError` — uncaught async and platform errors that never enter the framework.
|
|
11
|
+
|
|
12
|
+
Wiring only the first leaves the async crash invisible — the one you never see is the one outside the handler you wired. Native engine and platform-channel crashes report through the sink's native layer.
|
|
13
|
+
|
|
14
|
+
## Structured Breadcrumb Logging
|
|
15
|
+
|
|
16
|
+
Breadcrumbs, not `print`. A trail of structured events — navigation, command fired, repository call, state transition — lets a crash report reconstruct the path to the failure. `print()` is dropped in release builds and carries no structure even in debug. Attach the screen/route and the operation to each event; emit at an agreed severity rather than as free text.
|
|
17
|
+
|
|
18
|
+
## Performance Traces
|
|
19
|
+
|
|
20
|
+
Custom performance traces (Firebase Performance shape) wrap the spans the user *feels*: app start, screen render, and the gateway round-trip as seen from the device. This is client-perceived latency — a different number from the server span the core owns, and the only one that includes the user's network and frame budget. Add frame/jank metrics where smoothness is the product.
|
|
21
|
+
|
|
22
|
+
## What to Capture vs PII
|
|
23
|
+
|
|
24
|
+
- **Capture** error type and stack, the breadcrumb trail, screen, operation, client-perceived latency, and device/OS/app-version context.
|
|
25
|
+
- **Never** put tokens, PII, or full payloads in breadcrumbs or crash context. The sink is third-party — scrub before the event leaves the device.
|
|
26
|
+
|
|
27
|
+
## Where Distributed Tracing Lives
|
|
28
|
+
|
|
29
|
+
The end-to-end request trace is the capability core's, asserted there. The client does not mirror it with spans of its own; it correlates by attaching a request/correlation id it can surface in a breadcrumb, so a crash report points back at the server trace.
|
|
30
|
+
|
|
31
|
+
## Anti-Patterns
|
|
32
|
+
|
|
33
|
+
- **`print` as telemetry.** Dropped in release, structureless in debug.
|
|
34
|
+
- **One error handler.** `FlutterError.onError` alone lets async errors escape uncaught.
|
|
35
|
+
- **PII in crash context.** Emails, tokens, and payloads following the event off-device.
|
|
36
|
+
- **A client tracing story.** Re-implementing spans to mirror the backend — there is no client span surface; correlate, don't duplicate.
|
|
37
|
+
- **Over-instrumenting.** Custom traces nobody reads are cost without a question behind them.
|
package/src/engineer-skills/groundwork-flutter-engineer/references/performance-and-reliability.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Performance & Reliability
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [Two Budgets a Client Spends](#two-budgets-a-client-spends)
|
|
5
|
+
- [The Frame Budget](#the-frame-budget)
|
|
6
|
+
- [List Virtualization](#list-virtualization)
|
|
7
|
+
- [Image and Asset Memory](#image-and-asset-memory)
|
|
8
|
+
- [Isolates for Heavy Compute](#isolates-for-heavy-compute)
|
|
9
|
+
- [Startup Time](#startup-time)
|
|
10
|
+
- [Resilience on the Typed Client](#resilience-on-the-typed-client)
|
|
11
|
+
- [Optimistic UI and Offline](#optimistic-ui-and-offline)
|
|
12
|
+
- [Graceful Degradation](#graceful-degradation)
|
|
13
|
+
- [What Lives in the Core, Not Here](#what-lives-in-the-core-not-here)
|
|
14
|
+
- [Anti-Patterns](#anti-patterns)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Two Budgets a Client Spends
|
|
19
|
+
|
|
20
|
+
Performance is a budget spent deliberately, not "fast enough" tuned afterward (`docs/principles/quality/performance.md`). A client spends two budgets. The **frame budget** is local: 16ms to produce a frame at 60Hz, 8ms at 120Hz, and a build that overruns it drops the frame the user feels as jank. The **round-trip budget** is remote: the time from a tap to a rendered result, most of which is the gateway call the app does not control. Allocate both top-down — decide the interaction's target before building it — and measure the tail, not the average: the one stutter in a scroll is the experience users remember (`docs/principles/quality/performance.md`).
|
|
21
|
+
|
|
22
|
+
## The Frame Budget
|
|
23
|
+
|
|
24
|
+
Jank is a build that does too much, too often. The mechanics of keeping builds cheap live in the widget and state references; this is the performance lens on them:
|
|
25
|
+
|
|
26
|
+
- **`const` and extracted widgets** canonicalise subtrees the framework skips on rebuild — the cheapest performance work available (`references/widgets-and-composition.md`).
|
|
27
|
+
- **`RepaintBoundary`** isolates a frequently-repainting subtree (an animation, a progress indicator) so its repaint does not invalidate the rest of the layer tree. Wrap the moving part, not the whole screen — a boundary has its own cost, so it earns its place only where repaint actually churns.
|
|
28
|
+
- **Narrow rebuild scope.** A god-provider per screen rebuilds everything when one field changes; split providers by concern so the graph recomputes at the right granularity (`references/state-management.md`). Watch the narrowest provider a widget needs, never the whole state object for one field.
|
|
29
|
+
- **Pure builds.** A `build` that fires work or mutates state turns rebuild cadence into behaviour and into cost (`references/widgets-and-composition.md`).
|
|
30
|
+
|
|
31
|
+
Profile before you optimise — the obvious cause of a jank is usually wrong. Flutter DevTools' timeline and the raster/UI thread split tell you whether a frame overran in build or in paint; the "obvious" bottleneck almost always isn't (`docs/principles/quality/performance.md`).
|
|
32
|
+
|
|
33
|
+
## List Virtualization
|
|
34
|
+
|
|
35
|
+
A scrollable collection of unknown or large length is built lazily — `ListView.builder` / `GridView.builder` / `SliverList`, never a `ListView(children: [...])` that constructs every row up front. Eager construction allocates the whole list before the first frame and is the most common source of scroll jank and startup memory spikes. Give reorderable or filterable rows a `ValueKey(item.id)` so element state follows identity through rebuilds (`references/widgets-and-composition.md`).
|
|
36
|
+
|
|
37
|
+
## Image and Asset Memory
|
|
38
|
+
|
|
39
|
+
Decoded images dominate a client's memory; a full-resolution image rendered into a thumbnail wastes most of what it decoded. Constrain the decode, not just the display:
|
|
40
|
+
|
|
41
|
+
```dart
|
|
42
|
+
Image.network(
|
|
43
|
+
url,
|
|
44
|
+
cacheWidth: 320, // decode to the size actually shown, not the source resolution
|
|
45
|
+
fit: BoxFit.cover,
|
|
46
|
+
);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Size on-disk and remote assets to their rendered footprint, and let the framework's image cache evict — do not hold decoded bytes in app state. Oversized decodes are a memory budget overrun the same way an unbounded queue is a latency bomb.
|
|
50
|
+
|
|
51
|
+
## Isolates for Heavy Compute
|
|
52
|
+
|
|
53
|
+
The UI isolate renders frames; anything that can take longer than a frame must not run on it. Parsing a large payload, hashing, cryptographic work, image transforms — move them to a background isolate with `compute()` or a long-lived `Isolate`, so the work never blocks the frame loop:
|
|
54
|
+
|
|
55
|
+
```dart
|
|
56
|
+
final parsed = await compute(parseLargeReport, rawBytes);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This is the client's version of the hot-path discipline: the scoped, profiled paths that demand care, not every function (`docs/principles/quality/performance.md`). Repository translation of an ordinary payload stays on the UI isolate; reach for an isolate when a profile shows the work itself overrunning the frame.
|
|
60
|
+
|
|
61
|
+
## Startup Time
|
|
62
|
+
|
|
63
|
+
Cold start is the first interaction, and it spends the round-trip and frame budgets at once. Keep `main()` and the first frame thin: `ProviderScope` at the root and nothing else, no synchronous I/O before `runApp`, and defer non-critical provider initialisation until after the first frame paints. Render a skeleton from the first frame and let real data arrive into it — the app should be visible before it is fully loaded, never blank while it fetches.
|
|
64
|
+
|
|
65
|
+
## Resilience on the Typed Client
|
|
66
|
+
|
|
67
|
+
Reliability is designed in, not hoped for (`docs/principles/quality/reliability.md`). For a client, that discipline lives at the one seam that talks to the gateway — the `Dio` instance and the repositories above it (`references/data-and-contracts.md`):
|
|
68
|
+
|
|
69
|
+
- **Timeout always.** Every outbound call has connect and receive timeouts set on the one configured `Dio` instance — a hung connection otherwise holds a loading spinner forever.
|
|
70
|
+
- **Retry transient failures only, with jitter.** A retry interceptor retries connection errors and timeouts with bounded, jittered exponential backoff; jitter is not optional, because a fleet of clients retrying in lockstep is a thundering herd against the gateway. A `4xx` is permanent — retrying it wastes the budget. Retry at this one layer, not in every repository on top of it.
|
|
71
|
+
- **Map transport failures to domain states.** `DioException` never crosses above the data layer; the repository turns an unreachable gateway into a domain state the UI renders, and lets a contract violation surface as an error (`references/data-and-contracts.md`).
|
|
72
|
+
|
|
73
|
+
## Optimistic UI and Offline
|
|
74
|
+
|
|
75
|
+
A mobile process dies constantly and a network drops mid-interaction; state the app cannot rebuild from the core or the route is state it silently loses (`references/state-management.md`). Two patterns follow:
|
|
76
|
+
|
|
77
|
+
- **Optimistic update.** Reflect the user's action in state immediately, fire the mutation, and reconcile on the result — invalidate the provider to re-derive from the repository on success, roll back on failure. A Riverpod `Mutation` surfaces the pending/error lifecycle without a hand-rolled boolean (`references/state-management.md`).
|
|
78
|
+
- **Offline read-through.** A repository that caches can serve its last-known value while a refresh is in flight, so a dropped connection degrades to stale-but-present rather than empty. Mark served-stale state so the UI can show it honestly.
|
|
79
|
+
|
|
80
|
+
## Graceful Degradation
|
|
81
|
+
|
|
82
|
+
Every feature that depends on the gateway has a defined behaviour when the gateway is down — decided at design time, built alongside the happy path, never "we'll figure out what to show later" (`docs/principles/quality/reliability.md`). A view renders `loading` / `error` / `data` exhaustively, and the error case is a real designed state with a retry affordance, not a thrown exception reaching the user (`references/state-management.md`). A non-critical panel whose data is unavailable renders its own empty or "unavailable" state while the rest of the screen works — partial function beats a blank screen.
|
|
83
|
+
|
|
84
|
+
## What Lives in the Core, Not Here
|
|
85
|
+
|
|
86
|
+
Server reliability patterns do not belong on a client, and importing them here is miscategorised work. They live in the capability core and its services (`docs/principles/quality/reliability.md`):
|
|
87
|
+
|
|
88
|
+
- **SLOs and error budgets** are defined per service in the core, measured server-side. The client contributes client-observed latency to that picture; it does not own the objective.
|
|
89
|
+
- **Load shedding** protects the server from overload and must work regardless of client behaviour — it is a server-side backstop, not something a well-behaved client implements for it.
|
|
90
|
+
- **Circuit breakers** are earned against slow downstreams and tuned against real traffic at the service layer. A client's bounded, budgeted retry is the right amount of resilience at the edge; a breaker estimated locally by one app trips on noise. The business rules about a failure — whether it is recoverable, the retry budget — are proven in the core, and the surface renders the result.
|
|
91
|
+
|
|
92
|
+
## Anti-Patterns
|
|
93
|
+
|
|
94
|
+
- **Jank shipped, fixed later.** If you ship a stuttering scroll, users remember slow.
|
|
95
|
+
- **`ListView(children: [...])` for a dynamic or long list.** Eager construction of every row — use the `.builder` constructor.
|
|
96
|
+
- **Heavy work on the UI isolate.** A parse or hash that overruns a frame freezes the app — `compute()` it.
|
|
97
|
+
- **Full-resolution decode for a thumbnail.** Decoded image memory, wasted — constrain `cacheWidth`/`cacheHeight`.
|
|
98
|
+
- **Retry without jitter, or at every layer.** Lockstep retries are a thundering herd; layered retries multiply one tap into a storm.
|
|
99
|
+
- **No degraded state.** A feature with no defined behaviour when the gateway is down ships a blank screen or a raw exception.
|
|
100
|
+
- **Reimplementing server reliability on the client.** Load shedding, SLOs, and reflexive circuit breakers belong in the core, not the surface.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Platform Channels
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [The Decision Ladder](#the-decision-ladder)
|
|
5
|
+
- [Check the Plugin Shelf First](#check-the-plugin-shelf-first)
|
|
6
|
+
- [Pigeon: the Default for Structured APIs](#pigeon-the-default-for-structured-apis)
|
|
7
|
+
- [Wrapping the Native Module](#wrapping-the-native-module)
|
|
8
|
+
- [ffigen/jnigen: the Tracked Destination](#ffigenjnigen-the-tracked-destination)
|
|
9
|
+
- [Raw MethodChannel](#raw-methodchannel)
|
|
10
|
+
- [iOS Build Wiring](#ios-build-wiring)
|
|
11
|
+
- [Testing the Boundary](#testing-the-boundary)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## The Decision Ladder
|
|
16
|
+
|
|
17
|
+
When a capability is not reachable from Dart:
|
|
18
|
+
|
|
19
|
+
1. **pub.dev** — a maintained, verified-publisher plugin is a dependency decision, not an interop project.
|
|
20
|
+
2. **Pigeon module** — write Swift/Kotlin behind a generated, typed boundary.
|
|
21
|
+
3. **Raw MethodChannel** — a single fire-and-forget call with no evolving surface, nothing more.
|
|
22
|
+
|
|
23
|
+
Dropping to native is a **capability decision, never a performance reflex**. Profile in Dart first — rendering and isolates cover almost every performance complaint, and a native detour taken for imagined speed buys two codebases for one feature. Legitimate native triggers: a platform API with no maintained plugin (HealthKit details, background modes, vendor SDKs), OS-integrated UI Flutter cannot render (widgets/complications, App Intents), hardware access below the plugin ecosystem.
|
|
24
|
+
|
|
25
|
+
## Check the Plugin Shelf First
|
|
26
|
+
|
|
27
|
+
Before writing native code: search pub.dev, check publisher verification, maintenance cadence, and issue tracker health. Rewriting a maintained verified-publisher plugin is negative work. Write native code when the shelf is empty or unmaintained.
|
|
28
|
+
|
|
29
|
+
## Pigeon: the Default for Structured APIs
|
|
30
|
+
|
|
31
|
+
Define the API once in Dart; Pigeon generates type-safe stubs on both sides — misspelled methods and mistyped arguments become compile errors instead of runtime channel exceptions:
|
|
32
|
+
|
|
33
|
+
```dart
|
|
34
|
+
// pigeons/battery_api.dart
|
|
35
|
+
import 'package:pigeon/pigeon.dart';
|
|
36
|
+
|
|
37
|
+
@ConfigurePigeon(PigeonOptions(
|
|
38
|
+
dartOut: 'lib/data/services/gen/battery_api.g.dart',
|
|
39
|
+
kotlinOut: 'android/app/src/main/kotlin/.../BatteryApi.kt',
|
|
40
|
+
swiftOut: 'ios/Runner/BatteryApi.swift',
|
|
41
|
+
))
|
|
42
|
+
@HostApi()
|
|
43
|
+
abstract class BatteryApi {
|
|
44
|
+
int batteryLevel();
|
|
45
|
+
bool isCharging();
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Run `dart run pigeon --input pigeons/battery_api.dart` and implement the generated interface in Kotlin/Swift. **Every structured Flutter↔native API goes through Pigeon** — keep the native side a small module the agent can regenerate.
|
|
50
|
+
|
|
51
|
+
## Wrapping the Native Module
|
|
52
|
+
|
|
53
|
+
The Dart side of a Pigeon API is a **service in the data layer**, like any other platform API:
|
|
54
|
+
|
|
55
|
+
```dart
|
|
56
|
+
class BatteryService {
|
|
57
|
+
BatteryService(this._api);
|
|
58
|
+
final BatteryApi _api;
|
|
59
|
+
|
|
60
|
+
Future<BatteryReading> read() async => BatteryReading(
|
|
61
|
+
level: await _api.batteryLevel(),
|
|
62
|
+
charging: await _api.isCharging(),
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
final batteryServiceProvider = Provider<BatteryService>(
|
|
67
|
+
(ref) => BatteryService(BatteryApi()),
|
|
68
|
+
);
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Repositories/view models consume the service; nothing above the data layer knows a channel exists. **Native code never grows business rules** — it is transport to an OS capability; rules live in the core or the view model where they are proven.
|
|
72
|
+
|
|
73
|
+
## ffigen/jnigen: the Tracked Destination
|
|
74
|
+
|
|
75
|
+
The ecosystem is mid-migration to channel-free codegen interop: `ffigen` (C/Obj-C/Swift; stable) and `jnigen` (Java/Kotlin via JNI; pre-1.0), on build hooks / native assets (default-enabled since Flutter 3.38). The stance:
|
|
76
|
+
|
|
77
|
+
- **Adopt where a dependency already ships it** — that is the dependency's choice.
|
|
78
|
+
- **Pigeon remains the app-code default** until the jnigen path reaches 1.0.
|
|
79
|
+
- Aim refactors at the destination; re-evaluate at the next ecosystem survey.
|
|
80
|
+
|
|
81
|
+
## Raw MethodChannel
|
|
82
|
+
|
|
83
|
+
Acceptable for exactly one shape: a single trivial call with no evolving surface (toggle a platform flag, read one value). The moment a channel grows a second method or a structured payload, it becomes a Pigeon definition. Hand-written channels for any real API surface are legacy — stringly-typed, runtime-failing, agent-hostile.
|
|
84
|
+
|
|
85
|
+
## iOS Build Wiring
|
|
86
|
+
|
|
87
|
+
**Swift Package Manager is the iOS/macOS default as of Flutter 3.44.** New native modules and plugin dependencies use SwiftPM; CocoaPods is the legacy path kept only where a required dependency has not migrated. Do not add new Podfile-based wiring.
|
|
88
|
+
|
|
89
|
+
## Testing the Boundary
|
|
90
|
+
|
|
91
|
+
- **Unit/widget tiers:** fake the Pigeon-fronted **service** in Dart like any other service — the native side does not run.
|
|
92
|
+
- **Emulator tier:** the native implementation is exercised by `integration_test` (or Patrol, when the flow crosses into OS UI) only where the capability is observable.
|
|
93
|
+
- Pure pass-through wrappers over OS APIs get a thin smoke test, not a re-proof of the OS.
|
package/src/engineer-skills/groundwork-flutter-engineer/references/releases-and-distribution.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Releases and Distribution
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [Why This Is Architecture](#why-this-is-architecture)
|
|
5
|
+
- [Signing](#signing)
|
|
6
|
+
- [CI/CD Pipeline](#cicd-pipeline)
|
|
7
|
+
- [Versioning](#versioning)
|
|
8
|
+
- [Forced Upgrade: the Compatibility Floor](#forced-upgrade-the-compatibility-floor)
|
|
9
|
+
- [Shorebird Code Push](#shorebird-code-push)
|
|
10
|
+
- [Release Checklist](#release-checklist)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Why This Is Architecture
|
|
15
|
+
|
|
16
|
+
A mobile surface cannot be rolled back and cannot be force-refreshed: every version ever shipped is potentially still running, store review adds days of latency, and a signing mistake can permanently lock the listing. Treat release engineering as the half of the contract-compatibility story that lives outside the repo — and keep it CI-driven, because a human clicking through Xcode is a step the delivery loop stalls on.
|
|
17
|
+
|
|
18
|
+
## Signing
|
|
19
|
+
|
|
20
|
+
**Android**
|
|
21
|
+
|
|
22
|
+
- One upload keystore per app, generated once, stored in a secret manager **with an independent secure copy** — the official docs warn it is unrecoverable.
|
|
23
|
+
- `key.properties` and the keystore are never in git; CI injects them from encrypted secrets (or Codemagic code-signing identities).
|
|
24
|
+
- **Play App Signing** holds the actual app signing key, so a compromised upload key is rotatable.
|
|
25
|
+
|
|
26
|
+
**iOS**
|
|
27
|
+
|
|
28
|
+
- **App Store Connect API keys** authenticate CI — no human Apple ID sessions in automation.
|
|
29
|
+
- Certificates/provisioning profiles are fastlane-match-style: encrypted, centrally stored, CI-fetched. Codemagic's managed signing is the equivalent.
|
|
30
|
+
|
|
31
|
+
A keystore or service-account JSON committed to a repo is an **incident**, not a finding: rotate it, scrub history, then fix the pipeline. The generated `.gitignore` already excludes signing material — keep it that way.
|
|
32
|
+
|
|
33
|
+
## CI/CD Pipeline
|
|
34
|
+
|
|
35
|
+
Default stack: **GitHub Actions + fastlane** (`supply` → Play, `deliver`/`pilot` → App Store Connect/TestFlight). **Codemagic** is the recorded Flutter-native alternative; fastlane is preinstalled there, so the stacks compose. Pick one per product and record it.
|
|
36
|
+
|
|
37
|
+
The standard flow:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
PR → analyze + widget tests + emulator integration lane (the test gate)
|
|
41
|
+
main → build signed release artifacts (CI-owned build number)
|
|
42
|
+
artifact → internal track / TestFlight first
|
|
43
|
+
promote → staged rollout to production
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
No artifact reaches a store that CI did not build, sign, and test. Manual store uploads are unrepeatable releases — refuse them.
|
|
47
|
+
|
|
48
|
+
## Versioning
|
|
49
|
+
|
|
50
|
+
pubspec carries `version: x.y.z+buildNumber`:
|
|
51
|
+
|
|
52
|
+
- **Humans own `x.y.z`** — the user-visible, compatibility-relevant part.
|
|
53
|
+
- **CI owns the build number**, auto-incrementing per release build via `--build-number` (and `--build-name` when overriding the version). Hand-bumped build numbers collide, and collided build numbers are store-upload rejections.
|
|
54
|
+
|
|
55
|
+
## Forced Upgrade: the Compatibility Floor
|
|
56
|
+
|
|
57
|
+
The core's stance is that a published contract field is never broken — because the fleet lags releases by months and cannot be recalled. Forced upgrade is the other half of that bargain:
|
|
58
|
+
|
|
59
|
+
- The core (or a config endpoint / Firebase Remote Config) publishes a **minimum supported version**; the app compares at startup.
|
|
60
|
+
- The **`upgrader`** package implements the prompt: `minAppVersion` below the floor auto-hides "Later"/"Ignore".
|
|
61
|
+
- Two tiers, used deliberately:
|
|
62
|
+
- **Soft prompt** (dismissible) — new features, gentle migration pressure.
|
|
63
|
+
- **Hard force** (blocking) — security issues, or a contract the core can no longer serve.
|
|
64
|
+
|
|
65
|
+
Operational rules: the floor advances slowly and each advance is a recorded product decision; between "never break a field" and the floor, every fleet version is served correctly. **Shipping a contract-breaking core change without first raising the floor and waiting out adoption is a sequencing defect** — flag it whenever a slice proposes it.
|
|
66
|
+
|
|
67
|
+
## Shorebird Code Push
|
|
68
|
+
|
|
69
|
+
Shorebird (stable on Android and iOS, store-policy compliant) is the OTA lane for **Dart-only hotfixes** — it skips store latency for Dart-level defects, with `shorebird_code_push` for in-app patch checks. Boundaries:
|
|
70
|
+
|
|
71
|
+
- Native-code changes (plugins, Pigeon modules, SDK bumps) still require a store release.
|
|
72
|
+
- A patched 1.4.2 is still 1.4.2 to the contract — OTA never substitutes for the version floor.
|
|
73
|
+
- It is a hotfix channel, not the release process; features and floors move through the stores.
|
|
74
|
+
|
|
75
|
+
## Release Checklist
|
|
76
|
+
|
|
77
|
+
Before a release slice closes:
|
|
78
|
+
|
|
79
|
+
- [ ] CI builds, signs, and tests the artifact; no manual store steps.
|
|
80
|
+
- [ ] Build number CI-assigned; `x.y.z` deliberately chosen.
|
|
81
|
+
- [ ] No signing material, `key.properties`, ASC keys, or service-account JSON in the diff.
|
|
82
|
+
- [ ] Contract changes verified against the version floor (raise the floor first, then ship the change after adoption).
|
|
83
|
+
- [ ] Internal track / TestFlight before production; staged rollout configured.
|
|
84
|
+
- [ ] If Shorebird patched anything since the last release, the patch content is folded into this store release.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [The Posture](#the-posture)
|
|
5
|
+
- [No Secrets in the Binary](#no-secrets-in-the-binary)
|
|
6
|
+
- [Secure Storage for Tokens](#secure-storage-for-tokens)
|
|
7
|
+
- [Transport and Certificate Pinning](#transport-and-certificate-pinning)
|
|
8
|
+
- [Deep Link and Intent Validation](#deep-link-and-intent-validation)
|
|
9
|
+
- [Biometric and Auth-Token Handling](#biometric-and-auth-token-handling)
|
|
10
|
+
- [Obfuscation's Real Limits](#obfuscations-real-limits)
|
|
11
|
+
- [Security Review Checklist](#security-review-checklist)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## The Posture
|
|
16
|
+
|
|
17
|
+
A shipped mobile binary runs on a device the attacker owns. It can be pulled off the device, decompiled, patched, and run under a debugger or a proxy. So the client is **not** a trust boundary — it is hostile territory you are deploying into. Every security guarantee that matters is enforced server-side, behind the gateway (`references/data-and-contracts.md` → The Seam); the client's job is to handle credentials carefully and fail safe, not to keep secrets or enforce rules. This file is the Flutter idiom of the framework security canon (`docs/principles/quality/security.md`); when this file and the canon disagree, the canon wins and this file is the one to fix.
|
|
18
|
+
|
|
19
|
+
The recurring mistake is treating the app as trusted because it is "your" code. It stops being yours the moment it ships.
|
|
20
|
+
|
|
21
|
+
## No Secrets in the Binary
|
|
22
|
+
|
|
23
|
+
There is no secure place in the app bundle for a secret. API keys, signing keys, and shared credentials compiled into Dart — or passed via `--dart-define`, or baked into a `.env` asset — are all recoverable from the binary. The config seam already states this: no `.env` files baked in, no secrets in `--dart-define` (`references/data-and-contracts.md` → Configuration).
|
|
24
|
+
|
|
25
|
+
- A capability that needs a secret (a third-party API key, a server-to-server credential) lives **server-side**, behind a core endpoint the app calls with its user session. The surface never embeds a provider key — one owner per capability, keys stay server-side.
|
|
26
|
+
- `--dart-define` is for non-secret configuration only: the gateway base URL, build flavour, feature toggles.
|
|
27
|
+
- If the app appears to need a secret to call a third party directly, that call belongs on the server; route it through the core.
|
|
28
|
+
|
|
29
|
+
## Secure Storage for Tokens
|
|
30
|
+
|
|
31
|
+
Session and refresh tokens go in the platform keystore via `flutter_secure_storage`, which is backed by the iOS **Keychain** and the Android **Keystore**/EncryptedSharedPreferences. `SharedPreferences` and plain files are world-readable on a rooted/jailbroken device — they are never used for anything sensitive.
|
|
32
|
+
|
|
33
|
+
```dart
|
|
34
|
+
const _storage = FlutterSecureStorage(
|
|
35
|
+
aOptions: AndroidOptions(encryptedSharedPreferences: true),
|
|
36
|
+
iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock_this_device),
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
Future<void> saveSession(String token) =>
|
|
40
|
+
_storage.write(key: 'session_token', value: token);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- Tokens read out of secure storage are injected as a header by a single dio interceptor (`references/data-and-contracts.md` → dio Conventions), not stored in widget state or passed through constructors.
|
|
44
|
+
- `first_unlock_this_device` keeps the credential off device backups and off other devices; widen it only with a recorded reason.
|
|
45
|
+
- Clear secure storage on sign-out and on detected token invalidation — a lingering token is a credential waiting to be lifted.
|
|
46
|
+
|
|
47
|
+
## Transport and Certificate Pinning
|
|
48
|
+
|
|
49
|
+
All traffic is HTTPS; the dio client rejects plaintext. For an app handling sensitive data, pin the gateway's certificate (or its public-key/SPKI hash) so a user-installed or malicious root CA cannot transparently proxy the connection.
|
|
50
|
+
|
|
51
|
+
```dart
|
|
52
|
+
(dio.httpClientAdapter as IOHttpClientAdapter).createHttpClient = () {
|
|
53
|
+
final client = HttpClient();
|
|
54
|
+
client.badCertificateCallback = (cert, host, port) =>
|
|
55
|
+
_spkiSha256(cert) == _pinnedSpkiHash; // pin to the key, not the leaf cert
|
|
56
|
+
return client;
|
|
57
|
+
};
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- Pin to the SPKI hash, not a specific leaf certificate, so routine certificate renewal does not brick the app; ship at least one backup pin for rotation.
|
|
61
|
+
- Pinning raises the bar against interception but is bypassable on a fully compromised device — it is defence in depth, not a substitute for server-side authorization.
|
|
62
|
+
|
|
63
|
+
## Deep Link and Intent Validation
|
|
64
|
+
|
|
65
|
+
Every `GoRoute` is deep-linkable, and a deep link is untrusted input from another app or a web page (`references/navigation.md` → Deep Links). Route parameters arriving cold are hostile until proven otherwise.
|
|
66
|
+
|
|
67
|
+
- Validate and parse path/query parameters in the view model that receives them; never assume a deep-linked id exists, belongs to the user, or is well-formed. The server authorizes the fetch — the client renders the result or an error state.
|
|
68
|
+
- Guard-sensitive destinations are protected by the central `redirect` (`references/navigation.md` → Auth Guards), so a deep link cannot skip authentication. Confirm new protected routes are covered by the guard, not by a per-screen check.
|
|
69
|
+
- Treat any token or credential arriving *in* a deep link (an OAuth callback) as single-use, validated server-side, and never logged.
|
|
70
|
+
|
|
71
|
+
## Biometric and Auth-Token Handling
|
|
72
|
+
|
|
73
|
+
Biometric unlock (`local_auth`) gates access to a credential already held in the keystore; it does not authenticate the user to the server. The server trusts the session token, not the fingerprint.
|
|
74
|
+
|
|
75
|
+
- Use biometrics to unlock or re-confirm before a sensitive action, then present the keystore-held token to the gateway. The biometric check is a local gate, not a replacement for a verified session.
|
|
76
|
+
- Token refresh runs through the dio interceptor against the auth provider; the app does not mint, sign, or verify tokens itself. Auth is boring technology — `docs/principles/system-design/identity-and-access.md`.
|
|
77
|
+
- On biometric failure or lockout, fall back to full re-authentication, never to an unguarded path.
|
|
78
|
+
|
|
79
|
+
## Obfuscation's Real Limits
|
|
80
|
+
|
|
81
|
+
`flutter build --obfuscate --split-debug-info` renames symbols and raises the cost of reverse engineering. It is a speed bump, not a control: it does not encrypt logic, hide strings reliably, or protect anything the earlier sections cover. An obfuscated binary still hands a determined attacker every embedded secret and every client-side check.
|
|
82
|
+
|
|
83
|
+
Ship it for the marginal friction, and depend on it for nothing. The actual protections are: no secrets in the binary, tokens in the keystore, TLS pinning, and authorization on the server.
|
|
84
|
+
|
|
85
|
+
## Security Review Checklist
|
|
86
|
+
|
|
87
|
+
For any PR touching auth, secure storage, the dio client, deep-link routes, or build config:
|
|
88
|
+
|
|
89
|
+
- [ ] No secret, key, or credential embedded in Dart, assets, or `--dart-define`
|
|
90
|
+
- [ ] Tokens and credentials in `flutter_secure_storage` — never `SharedPreferences` or plain files
|
|
91
|
+
- [ ] Secure storage cleared on sign-out and token invalidation
|
|
92
|
+
- [ ] Transport is HTTPS only; pinning present (with a backup pin) for sensitive apps
|
|
93
|
+
- [ ] Deep-link parameters validated in the view model; protected routes covered by the central guard
|
|
94
|
+
- [ ] No client-side check standing in for a server-side authorization decision
|
|
95
|
+
- [ ] Biometrics gate a keystore credential — they do not authenticate to the server
|
|
96
|
+
- [ ] Obfuscation enabled, and relied on for nothing
|