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,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Packaging & Updates
|
|
3
|
+
description: Electron Forge, electron-vite, auto-update routes, code signing, and fuse-flipping in the release pipeline.
|
|
4
|
+
status: active
|
|
5
|
+
last_reviewed: 2026-06-12
|
|
6
|
+
---
|
|
7
|
+
# Packaging & Updates
|
|
8
|
+
|
|
9
|
+
## TL;DR
|
|
10
|
+
|
|
11
|
+
Electron Forge packages and publishes; electron-vite builds. Auto-update is `update-electron-app` + update.electronjs.org for open-source apps, `electron-updater` feeds otherwise. Code signing on both platforms is non-optional, and fuses are flipped inside the packaging step so an unhardened binary cannot ship.
|
|
12
|
+
|
|
13
|
+
## Why this matters
|
|
14
|
+
|
|
15
|
+
Packaging is where the security posture becomes physical: signing, notarization, ASAR integrity, and fuses all happen here or not at all. It is also where users experience the app's lifecycle — an app that updates silently and reliably stays inside the 3-major security window; one with a hand-rolled update path drifts out of support and into known CVEs.
|
|
16
|
+
|
|
17
|
+
## Our principles
|
|
18
|
+
|
|
19
|
+
### 1. Electron Forge is the toolchain default
|
|
20
|
+
|
|
21
|
+
Forge is the officially recommended pipeline — maintained in the `electron/` GitHub org, composing the first-party tools (`@electron/packager`, `@electron/osx-sign`, `@electron/notarize`, `@electron/fuses`) into one configuration. **electron-builder** is the documented escape hatch when packaging needs outgrow Forge's makers (exotic targets, NSIS specifics, percentage rollouts via its updater); it is healthy and more downloaded, but "official" means Forge, and the default needs no justification in a decision record — the escape hatch does.
|
|
22
|
+
|
|
23
|
+
### 2. electron-vite is the build layer
|
|
24
|
+
|
|
25
|
+
electron-vite (v5, electron-vite.org) builds all three targets from one `electron.vite.config.ts` with `main`/`preload`/`renderer` sections — renderer HMR, main/preload hot-reload, and `utilityProcess` workers via `?modulePath`. Forge's own Vite plugin remains marked experimental and lags Vite majors, so the production pairing is electron-vite for the build and Forge for packaging. The renderer section is where web-stack build config lives — Tailwind v4 loads here as `@tailwindcss/vite`, applied to the renderer only; everything about how it is used defers to [TypeScript Frontend](../typescript/frontend.md).
|
|
26
|
+
|
|
27
|
+
### 3. Two sanctioned auto-update routes
|
|
28
|
+
|
|
29
|
+
- **Open-source, GitHub-released:** the drop-in `update-electron-app` module against **update.electronjs.org** — free, zero-infrastructure, feeding the platform-native Squirrel updaters behind Electron's built-in `autoUpdater`. It serves only semver-tagged, non-draft releases.
|
|
30
|
+
- **Everything else:** `electron-updater` with a generic, S3, or GitHub feed — channels and staged rollouts included. Self-hosted feed servers (Nucleus-style) only when rollout control demands them.
|
|
31
|
+
|
|
32
|
+
A hand-rolled update endpoint without semver and rollback discipline is an outage generator and is not a third route.
|
|
33
|
+
|
|
34
|
+
### 4. Update discipline is a fixed set of rules
|
|
35
|
+
|
|
36
|
+
- Never check for updates on `--squirrel-firstrun` — the install is still settling.
|
|
37
|
+
- Call `quitAndInstall()` only after the `update-downloaded` event.
|
|
38
|
+
- One in-flight `checkForUpdates()` at a time; double-calls corrupt state.
|
|
39
|
+
- Set `app.setAppUserModelId()` to match the Squirrel shortcut ID, or Windows notifications detach from the app.
|
|
40
|
+
- Staying inside the 3-major support window is an update-discipline item, not a backlog wish ([Security](security.md)).
|
|
41
|
+
|
|
42
|
+
### 5. Code signing is non-optional on both platforms
|
|
43
|
+
|
|
44
|
+
An unsigned build is a development artifact, never a release.
|
|
45
|
+
|
|
46
|
+
- **macOS:** Developer ID signing with the hardened runtime and entitlements, then notarization via `notarytool` (Forge wraps `@electron/notarize`). `altool` is dead; Gatekeeper rejects un-notarized apps outright.
|
|
47
|
+
- **Windows:** **Azure Artifact Signing** (renamed from Azure Trusted Signing; GA in US/Canada/Europe since Jan 2026) — cloud-HSM-backed, clears SmartScreen, runs from CI via signtool/jsign. It displaced OV/EV certificates on USB tokens, which cannot live in a pipeline.
|
|
48
|
+
|
|
49
|
+
### 6. Fuses are flipped inside the packaging step
|
|
50
|
+
|
|
51
|
+
`@electron/fuses` runs as part of the Forge packaging hook — `RunAsNode` off, `EnableEmbeddedAsarIntegrityValidation` and `OnlyLoadAppFromAsar` on ([Security](security.md) for why). Putting the flip in the pipeline rather than a checklist means a release artifact that skipped hardening cannot exist.
|
|
52
|
+
|
|
53
|
+
## Anti-patterns we reject
|
|
54
|
+
|
|
55
|
+
- **electron-packager as a standalone "toolchain."** It is a Forge internal (`@electron/packager`) now; driving it by hand re-implements Forge badly.
|
|
56
|
+
- **webpack-based Forge templates and boilerplates.** The ecosystem's motion is uniformly Vite; webpack templates receive no investment.
|
|
57
|
+
- **Shipping unsigned or un-notarized builds.** Both desktop platforms treat them as malware, because malware is what unsigned binaries usually are.
|
|
58
|
+
- **`altool`, USB-token certificates, and other pre-cloud signing flows.** They cannot run in CI, so they guarantee a human in the release loop.
|
|
59
|
+
- **Update checks wired to app startup with no event discipline.** First-run checks and premature `quitAndInstall()` are the two classic self-inflicted update outages.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Process Model
|
|
3
|
+
description: Main as orchestrator, sandboxed Node-free renderers, utilityProcess for heavy work, and the lint-enforced folder boundary.
|
|
4
|
+
status: active
|
|
5
|
+
last_reviewed: 2026-06-12
|
|
6
|
+
---
|
|
7
|
+
# Process Model
|
|
8
|
+
|
|
9
|
+
## TL;DR
|
|
10
|
+
|
|
11
|
+
Main orchestrates and nothing more. Renderers are fully sandboxed, context-isolated, and Node-free. Heavy or crash-prone work runs in a `utilityProcess` with MessagePorts wired renderer↔utility directly. The split is physical — `src/main` / `src/preload` / `src/renderer` / `src/shared` — and a lint rule enforces it.
|
|
12
|
+
|
|
13
|
+
## Why this matters
|
|
14
|
+
|
|
15
|
+
The main process owns the event loop that services every window: a CPU-heavy task in main freezes every UI the app has at once. A renderer with Node access turns any XSS into full machine compromise. The process model is where Electron apps are won or lost, and the flagship apps — VS Code, Slack, Signal, 1Password — have all converged on the same shape after learning this the hard way.
|
|
16
|
+
|
|
17
|
+
## Our principles
|
|
18
|
+
|
|
19
|
+
### 1. Main is an orchestrator
|
|
20
|
+
|
|
21
|
+
Main creates windows, registers IPC handlers, talks to the OS, and delegates. It never does CPU-heavy or blocking work — parsing large files, crypto, indexing, image processing all starve the UI event loop. If a task can take longer than a frame, it does not belong in main.
|
|
22
|
+
|
|
23
|
+
### 2. Renderers are sandboxed, context-isolated, and Node-free
|
|
24
|
+
|
|
25
|
+
Every renderer runs with the hardened quartet ([Security](security.md)) and imports nothing from Electron or Node. The renderer is a normal Vite + React web app whose only platform surface is the preload-exposed bridge object ([IPC Contracts](ipc-contracts.md)). This is what lets the renderer reuse the web frontend idiom wholesale — component, styling, and accessibility rules come from [TypeScript Frontend](../typescript/frontend.md) unchanged.
|
|
26
|
+
|
|
27
|
+
### 3. Heavy and crash-prone work runs in `utilityProcess`
|
|
28
|
+
|
|
29
|
+
`utilityProcess` is the documented home for CPU-intensive tasks, untrusted services, and components that may crash — a `child_process.fork` equivalent with Node enabled and MessagePort support. Wire MessagePorts **renderer↔utility directly** so the traffic never transits, or blocks, the main process. This is the VS Code pattern: its extension host moved out of the renderer into a `utilityProcess`, and VS Code contributed the API to Electron for exactly this purpose. electron-vite builds utility workers first-class via the `?modulePath` import suffix.
|
|
30
|
+
|
|
31
|
+
### 4. The folder split is enforced, not conventional
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
src/
|
|
35
|
+
main/ # privileged orchestration — Node + Electron main APIs
|
|
36
|
+
preload/ # the bridge — contextBridge only
|
|
37
|
+
renderer/ # the web app — no Node, no Electron imports
|
|
38
|
+
shared/ # IPC contract types — types only, imported by all three
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
A lint boundary (dependency-cruiser or ESLint import rules, the Slack pattern) fails the build when renderer code imports anything Node-touching. The rule exists because the boundary erodes one convenient import at a time, and each erosion is invisible until it is a sandbox hole. Each process target gets its own tsconfig — main and preload compile against Node types, the renderer against DOM types — so the compiler polices the boundary too.
|
|
42
|
+
|
|
43
|
+
### 5. Shared code crosses the boundary as types only
|
|
44
|
+
|
|
45
|
+
`src/shared/` holds the IPC contract types both sides consume ([IPC Contracts](ipc-contracts.md)) and nothing with runtime behaviour. A "utils" folder imported by both main and renderer is a process boundary leak: it drags Node-flavoured code toward the sandbox and couples the two sides' upgrade paths.
|
|
46
|
+
|
|
47
|
+
## Anti-patterns we reject
|
|
48
|
+
|
|
49
|
+
- **Node-enabled renderers.** Enabling `nodeIntegration` also silently disables the sandbox for that renderer — the settings only protect as a set.
|
|
50
|
+
- **Plugin or extension code in the renderer.** Untrusted code belongs in a `utilityProcess`, where a crash or compromise is contained.
|
|
51
|
+
- **CPU-heavy work in main.** It freezes every window. Move it to a utility process.
|
|
52
|
+
- **`child_process.fork` for work that talks to a renderer.** `utilityProcess` + MessagePorts replaced it; fork has no port wiring and no Services API integration.
|
|
53
|
+
- **A shared folder with runtime code.** Shared types, yes. Shared behaviour across the process boundary, no.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Security
|
|
3
|
+
description: The hardened quartet, CSP, navigation and permission policy, fuses, and the currency window — enforced defaults, not advice.
|
|
4
|
+
status: active
|
|
5
|
+
last_reviewed: 2026-06-12
|
|
6
|
+
---
|
|
7
|
+
# Security
|
|
8
|
+
|
|
9
|
+
## TL;DR
|
|
10
|
+
|
|
11
|
+
Electron's security checklist is our enforced baseline, not a menu. The quartet — `contextIsolation: true`, `sandbox: true`, `nodeIntegration: false`, `webSecurity: true` — never changes. CSP is required, permissions and navigation are explicitly handled, local content ships over a custom protocol, and fuses are flipped at package time. Staying inside the 3-major support window is itself a security control.
|
|
12
|
+
|
|
13
|
+
## Why this matters
|
|
14
|
+
|
|
15
|
+
An Electron app is a browser with a privileged process attached. Every web vulnerability the renderer inherits becomes a local-machine vulnerability the moment a boundary control is loosened — and the controls fail as a set, not individually: enabling `nodeIntegration` silently disables the sandbox for that renderer. CVE-2025-55305 showed that even apps with the runtime controls right (Signal, Slack, 1Password) were backdoorable at rest because packaging integrity was left off. The baseline below is what "done" means.
|
|
16
|
+
|
|
17
|
+
## The enforced defaults
|
|
18
|
+
|
|
19
|
+
### 1. The quartet is never changed
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
new BrowserWindow({
|
|
23
|
+
webPreferences: {
|
|
24
|
+
contextIsolation: true, // default since 12 — never off
|
|
25
|
+
sandbox: true, // default since 20 — never off
|
|
26
|
+
nodeIntegration: false, // default since 5 — never on
|
|
27
|
+
// webSecurity defaults true — never off, not even "temporarily for dev"
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
These are Electron's defaults; our rule is that no code path, flag, or debugging session turns them off. `webSecurity: false` and `allowRunningInsecureContent` as debugging crutches are how production apps ship with the front door open.
|
|
33
|
+
|
|
34
|
+
### 2. A CSP is required
|
|
35
|
+
|
|
36
|
+
Every renderer ships a Content-Security-Policy — HTTP header where content is served, `<meta http-equiv>` for custom-protocol content. `default-src 'self'`-style strictness is achievable because all privileged data flows over IPC, not fetch; a CSP containing `*` is no CSP.
|
|
37
|
+
|
|
38
|
+
### 3. Permission requests are handled, never defaulted
|
|
39
|
+
|
|
40
|
+
`session.setPermissionRequestHandler()` is registered with an explicit allowlist. The default grants permissions (camera, microphone, geolocation) to any content that asks — in a desktop app, content that asks unexpectedly is the attack.
|
|
41
|
+
|
|
42
|
+
### 4. Navigation is restricted
|
|
43
|
+
|
|
44
|
+
`will-navigate` blocks navigation away from app content, and `setWindowOpenHandler()` denies or routes every `window.open`. A renderer that can navigate to an attacker's page hands the attacker a sandboxed-but-privileged-adjacent context. `shell.openExternal` is called only on validated, allowlisted URLs (scheme check at minimum) — it launches whatever the OS associates with the input.
|
|
45
|
+
|
|
46
|
+
### 5. Local content ships over a custom protocol, not `file://`
|
|
47
|
+
|
|
48
|
+
A registered custom protocol (`app://`) scopes what the renderer can load; `file://` grants origin-level access to the filesystem's namespace and breaks standard web security semantics.
|
|
49
|
+
|
|
50
|
+
### 6. Fuses are flipped at package time
|
|
51
|
+
|
|
52
|
+
Fuses are build-time switches baked into the binary — runtime config cannot re-enable what a fuse removed:
|
|
53
|
+
|
|
54
|
+
- `RunAsNode` **off** — otherwise the shipped binary doubles as a general-purpose Node executable for anything on the machine.
|
|
55
|
+
- `EnableEmbeddedAsarIntegrityValidation` **on** and `OnlyLoadAppFromAsar` **on** — CVE-2025-55305 (Trail of Bits, 2025-09) backdoored Signal, Slack, and 1Password via local V8 heap-snapshot tampering that bypassed code-integrity checks; ASAR integrity validation is the fix, and shipping without it is now called out as a defect, not a hardening opportunity.
|
|
56
|
+
- `nodeCliInspect` stays **on** — flipping it off breaks Playwright's `_electron` launch, and the agent-closable test loop ([Surface Stack Selection](../../surface-stack-selection.md)) outranks the marginal hardening.
|
|
57
|
+
|
|
58
|
+
Fuse flipping lives in the packaging pipeline ([Packaging & Updates](packaging-and-updates.md)), so an unfused build cannot reach a release channel.
|
|
59
|
+
|
|
60
|
+
### 7. The currency window is a security obligation
|
|
61
|
+
|
|
62
|
+
Only the latest three Electron majors receive patches, and majors ship every 8 weeks — Chromium CVEs apply to your shipped app on Chromium's schedule, not yours. Falling out of the window means known-exploitable, unpatched browser bugs in production. The upgrade is scheduled work with the same priority as a dependency CVE.
|
|
63
|
+
|
|
64
|
+
## Anti-patterns we reject
|
|
65
|
+
|
|
66
|
+
- **`nodeIntegration: true` anywhere, for any window.** It also kills the sandbox for that renderer.
|
|
67
|
+
- **`webSecurity: false` or `allowRunningInsecureContent` to "unblock" development.** Fix the content, not the boundary.
|
|
68
|
+
- **The `remote` module or packages that emulate it.** Synchronous privileged access from the renderer is the whole threat model in one API.
|
|
69
|
+
- **Un-fused release builds.** Post-CVE-2025-55305, ASAR integrity off is a shipping defect.
|
|
70
|
+
- **Treating the checklist as guidance for a security review later.** It is the definition of a correctly configured app on day one.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Frontend
|
|
3
|
+
description: React 19, Server Components, SWR, Tailwind, and the design language of a Next.js application.
|
|
4
|
+
status: active
|
|
5
|
+
last_reviewed: 2026-05-26
|
|
6
|
+
---
|
|
7
|
+
# Frontend
|
|
8
|
+
|
|
9
|
+
## TL;DR
|
|
10
|
+
|
|
11
|
+
The frontend is Next.js 16 with React 19 Server Components, SWR for client-side data, and Tailwind for styling. We render on the server by default, hydrate the minimum needed for interactivity, and keep data-fetching at the leaves. The design language is consistent, calm, and accessible first.
|
|
12
|
+
|
|
13
|
+
## Why this matters
|
|
14
|
+
|
|
15
|
+
Frontend engineering in 2026 is no longer a "client-side" discipline. Most pixels are rendered on the server before they reach the browser, and the browser's job is to stay responsive to the user's input rather than to fetch data on their behalf. Getting this split right — what runs on the server, what runs on the client, what streams in between — is the single biggest determinant of how fast and how reliable the app feels. It is also where most frontend bugs live.
|
|
16
|
+
|
|
17
|
+
## Our principles
|
|
18
|
+
|
|
19
|
+
### 1. Server components are the default
|
|
20
|
+
|
|
21
|
+
Every component starts as a Server Component. We add `"use client"` only when we need state, events, or browser-only APIs. The economic argument is simple: every client component costs download, parse, hydrate, and memory on every user's device. Server components cost none of that. The ratio of server-to-client components is tracked and kept high.
|
|
22
|
+
|
|
23
|
+
### 2. Data fetches at the leaves, not the root
|
|
24
|
+
|
|
25
|
+
Data fetching happens in the component that actually renders the data, not in a page-level fetcher that passes everything down through props. This lets Suspense boundaries stream exactly as deep as they need to, and it keeps prop-drilling in check. The exception is when two leaves need the same data — then we fetch once in a common ancestor and share via React's built-in request deduplication.
|
|
26
|
+
|
|
27
|
+
### 3. SWR for client-interactive state
|
|
28
|
+
|
|
29
|
+
For state that must respond to user interaction in real time — live views, session state, optimistic updates — we use SWR. One cache, one invalidation story, one mental model. We do not mix query libraries in the same app.
|
|
30
|
+
|
|
31
|
+
### 4. Styling is Tailwind utilities, composed
|
|
32
|
+
|
|
33
|
+
We style with Tailwind utility classes. When a composition of utilities gets long or is repeated, we extract a component — not a custom CSS class. Component extraction keeps the `className` strings honest; new CSS classes are where design systems go to die of untracked one-offs.
|
|
34
|
+
|
|
35
|
+
### 5. The design system is a library, not a guideline
|
|
36
|
+
|
|
37
|
+
Buttons, inputs, modals, tooltips — every primitive is a typed, reviewed component in the shared component library. Ad-hoc styling of a button in a feature folder is a smell; the fix is to add the variant to the library, not to reimplement it.
|
|
38
|
+
|
|
39
|
+
### 6. Accessibility is a baseline, not a feature
|
|
40
|
+
|
|
41
|
+
Every interactive component supports keyboard navigation, is screen-reader labelled, and meets WCAG 2.2 AA contrast at minimum. Accessibility failures block merges the same way type errors do. The golden path for every new UI begins with "can I get to it, use it, and understand it with just the keyboard and a screen reader?"
|
|
42
|
+
|
|
43
|
+
### 7. Client state is recoverable
|
|
44
|
+
|
|
45
|
+
We do not store state in React that cannot be rebuilt from the server or the URL. Refreshing the page is the end-to-end test of this: if the user loses context after a refresh, we are holding state we should not. The URL is a first-class state container; so are Server Components.
|
|
46
|
+
|
|
47
|
+
### 8. Performance budgets are enforced in CI
|
|
48
|
+
|
|
49
|
+
Largest Contentful Paint, Interaction-to-Next-Paint, JS bundle size — all tracked in CI with budgets. A PR that regresses a budget requires an explicit waiver. Performance is never negotiated after the fact; it is designed in.
|
|
50
|
+
|
|
51
|
+
## Anti-patterns we reject
|
|
52
|
+
|
|
53
|
+
- **`useEffect` for data fetching.** `useEffect` is an escape hatch for non-React systems; it is not a data-fetching primitive. Use Server Components or SWR.
|
|
54
|
+
- **Context for everything.** React Context is a tool for genuinely app-wide concerns (theme, auth, locale). Using it to avoid prop-drilling on three levels is overreach.
|
|
55
|
+
- **CSS Modules alongside Tailwind.** One styling system. Not three.
|
|
56
|
+
- **Ad-hoc design primitives.** Every new button variant is a tax on the design system. If it needs a variant, add it to the library.
|
|
57
|
+
- **State that cannot survive refresh.** Modals that disappear on refresh lose user context; counters that reset on refresh are not counters.
|
|
58
|
+
- **"Fix it in a later PR" accessibility.** The later PR will not happen. Ship accessible or ship later.
|
|
59
|
+
|
|
60
|
+
## Further reading
|
|
61
|
+
|
|
62
|
+
- *React documentation* ([react.dev](https://react.dev)) — the canonical source for the Server Component mental model.
|
|
63
|
+
- *Patterns.dev*, Lydia Hallie & Addy Osmani — a clean survey of modern frontend patterns.
|
|
64
|
+
- *Inclusive Components*, Heydon Pickering — the pattern language of accessible component design.
|
|
65
|
+
- *Refactoring UI*, Schoger & Wathan — the design vocabulary that informs how we compose Tailwind.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
|
|
4
|
+
# electron-vite build output
|
|
5
|
+
out/
|
|
6
|
+
dist/
|
|
7
|
+
|
|
8
|
+
# Electron Forge packaging output
|
|
9
|
+
.vite/
|
|
10
|
+
make/
|
|
11
|
+
|
|
12
|
+
# Test artifacts
|
|
13
|
+
coverage/
|
|
14
|
+
playwright-report/
|
|
15
|
+
test-results/
|
|
16
|
+
|
|
17
|
+
# Tooling
|
|
18
|
+
*.tsbuildinfo
|
|
19
|
+
.DS_Store
|
|
20
|
+
.env.local
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# <%= name %>
|
|
2
|
+
|
|
3
|
+
An Electron desktop surface scaffolded by GroundWork. It is a thin adapter
|
|
4
|
+
over the workspace's capability core: business logic lives behind the promoted
|
|
5
|
+
contracts and is proven there once; this app proves wiring, rendering, and
|
|
6
|
+
interaction. The shell follows the flagship-app architecture — a privileged
|
|
7
|
+
main process that only orchestrates, a fully sandboxed Node-free renderer on
|
|
8
|
+
the same React + Tailwind stack as the web surface, and a typed IPC contract
|
|
9
|
+
at the process seam. Electron is GroundWork's standard desktop pick per its
|
|
10
|
+
surface-stack-selection principle (Playwright's `_electron` driver makes it
|
|
11
|
+
the strongest agent-closable loop of any desktop option); the engineering
|
|
12
|
+
principles this app embodies live in `docs/principles/stack/electron/`.
|
|
13
|
+
|
|
14
|
+
## Toolchain
|
|
15
|
+
|
|
16
|
+
Node is assumed (the workspace runs on it); the Electron binary is a
|
|
17
|
+
**declared prerequisite, not an assumption** — generation required no install,
|
|
18
|
+
everything below does. Every Nx target runs through `tool/electron_exec.sh`,
|
|
19
|
+
which reports `tier skipped` with a reason instead of failing cryptically when
|
|
20
|
+
the binary (or, for the smoke, a display server) is missing.
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx nx run <%= fileName %>:bootstrap # one-time: npm install (downloads the Electron binary)
|
|
24
|
+
npx nx run <%= fileName %>:run # electron-vite dev (renderer HMR, main/preload hot-reload)
|
|
25
|
+
npx nx run <%= fileName %>:build # electron-vite build → out/
|
|
26
|
+
npx nx run <%= fileName %>:lint # eslint, including the process-boundary rules
|
|
27
|
+
npx nx run <%= fileName %>:typecheck # tsc per process target (node + web tsconfigs)
|
|
28
|
+
npx nx run <%= fileName %>:test # vitest: main policy tests (node) + renderer tests (jsdom)
|
|
29
|
+
npx nx run <%= fileName %>:smoke # build + Playwright _electron boot smoke
|
|
30
|
+
npx nx run <%= fileName %>:package # electron-forge package (flips the fuses)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
This app joins the Nx workspace through `project.json` run-commands targets
|
|
34
|
+
and does **not** join `docker-compose.yml` (a desktop app has no Docker boot).
|
|
35
|
+
Its verification tiers follow the multi-surface contract: **generation**
|
|
36
|
+
(snapshot, no toolchain), **compilation** (`tsc` + lint, renderer and main
|
|
37
|
+
both), **boot** (Playwright `_electron` launch + smoke — under `xvfb` on
|
|
38
|
+
Linux CI, since Electron is never truly headless).
|
|
39
|
+
|
|
40
|
+
## Structure
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
src/
|
|
44
|
+
├── main/ # privileged orchestration — Node + Electron main APIs
|
|
45
|
+
│ ├── index.ts # window creation (hardened quartet), security policy,
|
|
46
|
+
│ │ # bundle protocol, nativeTheme broadcast
|
|
47
|
+
│ ├── ipc.ts # ipcMain.handle: sender validation + zod payloads
|
|
48
|
+
│ ├── core-client.ts # the core-access seam: main fetches the workspace
|
|
49
|
+
│ │ # gateway (API_BASE_URL); the renderer never can (CSP)
|
|
50
|
+
│ ├── core-client.test.ts
|
|
51
|
+
│ ├── policy.ts # pure, unit-tested security rules (no Electron imports)
|
|
52
|
+
│ └── policy.test.ts
|
|
53
|
+
├── preload/
|
|
54
|
+
│ └── index.ts # the narrow contextBridge API — never raw ipcRenderer
|
|
55
|
+
├── renderer/ # a normal Vite + React web app — no Node, no Electron
|
|
56
|
+
│ ├── index.html # strict CSP
|
|
57
|
+
│ └── src/
|
|
58
|
+
│ ├── assets/brand.css # GENERATED from brand-tokens.json — do not hand-edit
|
|
59
|
+
│ ├── assets/main.css # Tailwind v4 + @theme token mapping
|
|
60
|
+
│ ├── App.tsx
|
|
61
|
+
│ ├── App.test.tsx
|
|
62
|
+
│ └── main.tsx # React root + theme sync subscription
|
|
63
|
+
└── shared/
|
|
64
|
+
└── ipc.ts # the typed IPC contract — types only, both sides import it
|
|
65
|
+
tests/smoke/ # Playwright _electron boot smoke (the boot tier)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The folder split is enforced, not conventional: the renderer and shared
|
|
69
|
+
tsconfig/eslint configurations fail the build when renderer code imports
|
|
70
|
+
anything Node-touching (`docs/principles/stack/electron/process-model.md`).
|
|
71
|
+
|
|
72
|
+
## Security posture (baked, not advisory)
|
|
73
|
+
|
|
74
|
+
- **The hardened quartet** — `contextIsolation: true`, `sandbox: true`,
|
|
75
|
+
`nodeIntegration: false`, `webSecurity: true` — set explicitly in
|
|
76
|
+
`src/main/index.ts` and asserted by the framework's generation tests. No
|
|
77
|
+
code path turns them off.
|
|
78
|
+
- **Permissions denied by default**; navigation restricted via `will-navigate`
|
|
79
|
+
and `setWindowOpenHandler`; `shell.openExternal` only on allowlisted https
|
|
80
|
+
URLs (`src/main/policy.ts` — pure and unit-tested).
|
|
81
|
+
- **The renderer ships over the custom `app://` protocol**, never `file://`.
|
|
82
|
+
- **A strict CSP** in `index.html` — privileged data flows over IPC, not fetch.
|
|
83
|
+
- **Fuses flipped at package time** (`forge.config.ts`): `RunAsNode` off, ASAR
|
|
84
|
+
integrity validation + asar-only load on (CVE-2025-55305). `nodeCliInspect`
|
|
85
|
+
stays on deliberately — Playwright's `_electron` launch needs it, and the
|
|
86
|
+
agent-closable loop outranks the marginal hardening.
|
|
87
|
+
|
|
88
|
+
See `docs/principles/stack/electron/security.md` for the full baseline.
|
|
89
|
+
|
|
90
|
+
## The IPC contract
|
|
91
|
+
|
|
92
|
+
`src/shared/ipc.ts` is the single seam between renderer and main. Adding a
|
|
93
|
+
channel: declare it in the contract type, implement the handler in
|
|
94
|
+
`src/main/ipc.ts` (sender validation always; zod for non-trivial payloads),
|
|
95
|
+
expose a purpose-named method in `src/preload/index.ts`. The renderer fetches
|
|
96
|
+
through TanStack Query with `queryFn`s calling `window.api` — caching, retry,
|
|
97
|
+
and invalidation exactly as in an HTTP app. For a hosted capability core, core
|
|
98
|
+
access belongs on the privileged side of this seam: main talks to the gateway,
|
|
99
|
+
the renderer talks to main.
|
|
100
|
+
|
|
101
|
+
## Theme: a projection, not an authoring surface
|
|
102
|
+
|
|
103
|
+
`src/renderer/src/assets/brand.css` is generated from
|
|
104
|
+
`.groundwork/config/brand-tokens.json` (the design system's `visual` block —
|
|
105
|
+
palette roles in both themes, typography families, base radius). `main.css`
|
|
106
|
+
maps the custom properties into Tailwind v4 theme tokens, so components
|
|
107
|
+
consume utilities (`bg-surface`, `text-primary`, `font-display`) and never
|
|
108
|
+
declare hex values. Dark mode is `nativeTheme` in main, broadcast over IPC,
|
|
109
|
+
mirrored onto `<html data-theme>`. Re-run the design system to evolve the
|
|
110
|
+
brand, then regenerate `brand.css` to match.
|
|
111
|
+
|
|
112
|
+
## Testing
|
|
113
|
+
|
|
114
|
+
Three tiers, mirroring `docs/principles/stack/electron/` and the web stack's
|
|
115
|
+
testing discipline:
|
|
116
|
+
|
|
117
|
+
1. **Unit (node)** — `src/main/policy.test.ts`: the pure security rules.
|
|
118
|
+
2. **Unit (jsdom)** — renderer components with the bridge faked at the
|
|
119
|
+
`window.api` seam.
|
|
120
|
+
3. **Smoke (Playwright `_electron`)** — `tests/smoke/`: launch the built app,
|
|
121
|
+
assert title + rendering, one IPC round-trip, and the theme push channel.
|
|
122
|
+
Thin by design; emulator-class minutes are the expensive currency here too.
|
|
123
|
+
|
|
124
|
+
Surface tests never re-prove core business logic — that proof lives at the
|
|
125
|
+
core's contract.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { defineConfig, externalizeDepsPlugin } from 'electron-vite';
|
|
2
|
+
import react from '@vitejs/plugin-react';
|
|
3
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
4
|
+
|
|
5
|
+
// One config, three build targets — main and preload compile against the Node
|
|
6
|
+
// context, the renderer is a normal Vite + React web app. Tailwind v4 loads as
|
|
7
|
+
// a Vite plugin in the renderer section ONLY: it never applies to main or
|
|
8
|
+
// preload (docs/principles/stack/electron/packaging-and-updates.md).
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
main: {
|
|
11
|
+
plugins: [externalizeDepsPlugin()],
|
|
12
|
+
build: {
|
|
13
|
+
lib: { entry: 'src/main/index.ts' },
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
preload: {
|
|
17
|
+
plugins: [externalizeDepsPlugin()],
|
|
18
|
+
build: {
|
|
19
|
+
lib: { entry: 'src/preload/index.ts' },
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
renderer: {
|
|
23
|
+
root: 'src/renderer',
|
|
24
|
+
plugins: [react(), tailwindcss()],
|
|
25
|
+
build: {
|
|
26
|
+
rollupOptions: {
|
|
27
|
+
input: 'src/renderer/index.html',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
});
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import js from "@eslint/js";
|
|
2
|
+
import hooksPlugin from "eslint-plugin-react-hooks";
|
|
3
|
+
import tseslint from "typescript-eslint";
|
|
4
|
+
import globals from "globals";
|
|
5
|
+
|
|
6
|
+
// Node built-ins that must never reach the sandboxed renderer or the shared
|
|
7
|
+
// contract types. The list backs the lint-enforced process boundary — the
|
|
8
|
+
// Slack pattern: the folder split is physical, and a rule fails the build when
|
|
9
|
+
// it erodes (docs/principles/stack/electron/process-model.md).
|
|
10
|
+
const nodeBuiltinPatterns = ["node:*", "fs", "path", "os", "child_process", "crypto", "net", "http", "https"];
|
|
11
|
+
|
|
12
|
+
export default tseslint.config(
|
|
13
|
+
{
|
|
14
|
+
ignores: ["out/", "dist/", "node_modules/", "coverage/", "playwright-report/", "test-results/"],
|
|
15
|
+
},
|
|
16
|
+
js.configs.recommended,
|
|
17
|
+
...tseslint.configs.recommended,
|
|
18
|
+
{
|
|
19
|
+
languageOptions: {
|
|
20
|
+
globals: {
|
|
21
|
+
...globals.node,
|
|
22
|
+
...globals.es2024,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
rules: {
|
|
26
|
+
"no-console": "off",
|
|
27
|
+
"@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }],
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
// The renderer is a normal web app: browser globals, React hooks rules,
|
|
32
|
+
// and a hard boundary — no Electron, no Node. Its only platform surface
|
|
33
|
+
// is the preload-exposed window.api bridge.
|
|
34
|
+
files: ["src/renderer/**/*.{ts,tsx}"],
|
|
35
|
+
plugins: {
|
|
36
|
+
"react-hooks": hooksPlugin,
|
|
37
|
+
},
|
|
38
|
+
languageOptions: {
|
|
39
|
+
globals: {
|
|
40
|
+
...globals.browser,
|
|
41
|
+
...globals.es2024,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
rules: {
|
|
45
|
+
...hooksPlugin.configs.recommended.rules,
|
|
46
|
+
"no-restricted-imports": [
|
|
47
|
+
"error",
|
|
48
|
+
{
|
|
49
|
+
paths: [
|
|
50
|
+
{
|
|
51
|
+
name: "electron",
|
|
52
|
+
message:
|
|
53
|
+
"The renderer is sandboxed and Node-free; talk to main through window.api (docs/principles/stack/electron/process-model.md).",
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
patterns: [
|
|
57
|
+
{
|
|
58
|
+
group: nodeBuiltinPatterns,
|
|
59
|
+
message:
|
|
60
|
+
"Node built-ins do not exist in the sandboxed renderer; move the capability behind the IPC bridge.",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
// Shared code crosses the process boundary as types only.
|
|
69
|
+
files: ["src/shared/**/*.ts"],
|
|
70
|
+
rules: {
|
|
71
|
+
"no-restricted-imports": [
|
|
72
|
+
"error",
|
|
73
|
+
{
|
|
74
|
+
paths: [
|
|
75
|
+
{
|
|
76
|
+
name: "electron",
|
|
77
|
+
message:
|
|
78
|
+
"src/shared/ carries the IPC contract types only — no runtime, no Electron (docs/principles/stack/electron/process-model.md).",
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
patterns: [
|
|
82
|
+
{
|
|
83
|
+
group: nodeBuiltinPatterns,
|
|
84
|
+
message:
|
|
85
|
+
"src/shared/ carries the IPC contract types only — no runtime, no Node.",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ForgeConfig } from '@electron-forge/shared-types';
|
|
2
|
+
import { MakerZIP } from '@electron-forge/maker-zip';
|
|
3
|
+
import { FusesPlugin } from '@electron-forge/plugin-fuses';
|
|
4
|
+
import { FuseV1Options, FuseVersion } from '@electron/fuses';
|
|
5
|
+
|
|
6
|
+
// Packaging is where the security posture becomes physical: fuses are flipped
|
|
7
|
+
// inside this pipeline so an unhardened binary cannot reach a release channel
|
|
8
|
+
// (docs/principles/stack/electron/packaging-and-updates.md). Run `electron-vite
|
|
9
|
+
// build` before packaging — package.json's `main` points at the built output.
|
|
10
|
+
//
|
|
11
|
+
// Code signing is non-optional for release builds (macOS Developer ID +
|
|
12
|
+
// notarytool, Windows Azure Artifact Signing); wire osxSign/osxNotarize and the
|
|
13
|
+
// Windows signing hook here when release credentials exist. An unsigned build
|
|
14
|
+
// is a development artifact, never a release.
|
|
15
|
+
const config: ForgeConfig = {
|
|
16
|
+
packagerConfig: {
|
|
17
|
+
asar: true,
|
|
18
|
+
appBundleId: '<%= appId %>',
|
|
19
|
+
},
|
|
20
|
+
makers: [new MakerZIP({}, ['darwin', 'linux', 'win32'])],
|
|
21
|
+
plugins: [
|
|
22
|
+
new FusesPlugin({
|
|
23
|
+
version: FuseVersion.V1,
|
|
24
|
+
// The shipped binary must not double as a general-purpose Node
|
|
25
|
+
// executable (docs/principles/stack/electron/security.md).
|
|
26
|
+
[FuseV1Options.RunAsNode]: false,
|
|
27
|
+
[FuseV1Options.EnableCookieEncryption]: true,
|
|
28
|
+
[FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false,
|
|
29
|
+
// Left ON deliberately: flipping nodeCliInspect off breaks Playwright's
|
|
30
|
+
// _electron launch, and the agent-closable smoke loop outranks the
|
|
31
|
+
// marginal hardening (docs/principles/stack/electron/security.md).
|
|
32
|
+
[FuseV1Options.EnableNodeCliInspectArguments]: true,
|
|
33
|
+
// CVE-2025-55305: local V8 heap-snapshot tampering backdoored Signal,
|
|
34
|
+
// Slack, and 1Password past their code-integrity checks. ASAR integrity
|
|
35
|
+
// validation + asar-only load is the fix; shipping without it is a
|
|
36
|
+
// defect, not a hardening opportunity
|
|
37
|
+
// (docs/principles/stack/electron/security.md).
|
|
38
|
+
[FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true,
|
|
39
|
+
[FuseV1Options.OnlyLoadAppFromAsar]: true,
|
|
40
|
+
}),
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default config;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= fileName %>",
|
|
3
|
+
"productName": "<%= name %>",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"private": true,
|
|
6
|
+
"description": "Electron desktop surface scaffolded by GroundWork",
|
|
7
|
+
"main": "./out/main/index.js",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "electron-vite dev",
|
|
10
|
+
"build": "electron-vite build",
|
|
11
|
+
"start": "electron-vite preview",
|
|
12
|
+
"lint": "eslint .",
|
|
13
|
+
"lint:fix": "eslint . --fix",
|
|
14
|
+
"typecheck": "tsc --noEmit -p tsconfig.node.json --composite false && tsc --noEmit -p tsconfig.web.json --composite false",
|
|
15
|
+
"test": "vitest run",
|
|
16
|
+
"test:watch": "vitest",
|
|
17
|
+
"smoke": "playwright test",
|
|
18
|
+
"package": "electron-forge package",
|
|
19
|
+
"make": "electron-forge make"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@tanstack/react-query": "^5.90.0",
|
|
23
|
+
"react": "19.2.7",
|
|
24
|
+
"react-dom": "19.2.7",
|
|
25
|
+
"zod": "^3.24.1"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@electron-forge/cli": "^7.11.0",
|
|
29
|
+
"@electron-forge/maker-zip": "^7.11.0",
|
|
30
|
+
"@electron-forge/plugin-fuses": "^7.11.0",
|
|
31
|
+
"@electron/fuses": "^1.8.0",
|
|
32
|
+
"@playwright/test": "^1.60.0",
|
|
33
|
+
"@tailwindcss/vite": "^4.3.0",
|
|
34
|
+
"@testing-library/dom": "^10.4.1",
|
|
35
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
36
|
+
"@testing-library/react": "^16.3.2",
|
|
37
|
+
"@types/node": "^24.0.0",
|
|
38
|
+
"@types/react": "19.2.17",
|
|
39
|
+
"@types/react-dom": "19.2.3",
|
|
40
|
+
"@vitejs/plugin-react": "^5.2.0",
|
|
41
|
+
"electron": "^42.0.0",
|
|
42
|
+
"electron-vite": "^5.0.0",
|
|
43
|
+
"eslint": "^9.39.4",
|
|
44
|
+
"eslint-plugin-react-hooks": "^7.1.0",
|
|
45
|
+
"globals": "^17.4.0",
|
|
46
|
+
"jsdom": "^29.0.0",
|
|
47
|
+
"playwright": "^1.60.0",
|
|
48
|
+
"tailwindcss": "^4.3.0",
|
|
49
|
+
"typescript": "5.9.3",
|
|
50
|
+
"typescript-eslint": "^8.58.0",
|
|
51
|
+
"vite": "^7.3.0",
|
|
52
|
+
"vitest": "^4.1.0"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineConfig } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
// Boot-tier smoke configuration. The suite launches this app's own Electron
|
|
4
|
+
// binary through Playwright's _electron driver — no browser downloads are
|
|
5
|
+
// needed (`playwright install` is not required). On Linux CI it runs under
|
|
6
|
+
// xvfb; tool/electron_exec.sh handles the display guard
|
|
7
|
+
// (docs/principles/stack/electron/security.md → testing references).
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
testDir: './tests/smoke',
|
|
10
|
+
timeout: 60_000,
|
|
11
|
+
// The smoke drives one app instance; keep the lane serial and thin.
|
|
12
|
+
fullyParallel: false,
|
|
13
|
+
workers: 1,
|
|
14
|
+
use: {
|
|
15
|
+
screenshot: 'only-on-failure',
|
|
16
|
+
trace: 'retain-on-failure',
|
|
17
|
+
},
|
|
18
|
+
});
|