@bonesofspring/ai-rules 0.2.22 → 0.2.24
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 +17 -0
- package/README.md +10 -2
- package/bin/cli.js +56 -9
- package/bin/mavis-install.js +441 -0
- package/bin/opencode-install.js +531 -0
- package/package.json +17 -3
- package/presets/_shared/core/agent-team/agent-team-orchestrator.md +2 -2
- package/presets/_shared/core/meta/preset-layering.md +3 -3
- package/presets/_shared/core/meta/preset-no-cross-stack-leakage.md +1 -1
- package/presets/_shared/core/meta/preset-pr-checklist.md +5 -3
- package/presets/_shared/core/meta/preset-token-budget.md +3 -0
- package/presets/_shared/core/meta/preset-twin-sync.md +32 -0
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-layering.md +3 -3
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -1
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-pr-checklist.md +5 -3
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-token-budget.md +3 -0
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-twin-sync.md +32 -0
- package/presets/claude/go/rules/tooling-and-review/preset-layering.md +3 -3
- package/presets/claude/go/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -1
- package/presets/claude/go/rules/tooling-and-review/preset-pr-checklist.md +5 -3
- package/presets/claude/go/rules/tooling-and-review/preset-token-budget.md +3 -0
- package/presets/claude/go/rules/tooling-and-review/preset-twin-sync.md +32 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-layering.md +3 -3
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -1
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-pr-checklist.md +5 -3
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-token-budget.md +3 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-twin-sync.md +32 -0
- package/presets/claude/java/rules/tooling-and-review/preset-layering.md +3 -3
- package/presets/claude/java/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -1
- package/presets/claude/java/rules/tooling-and-review/preset-pr-checklist.md +5 -3
- package/presets/claude/java/rules/tooling-and-review/preset-token-budget.md +3 -0
- package/presets/claude/java/rules/tooling-and-review/preset-twin-sync.md +32 -0
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-layering.md +3 -3
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -1
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-pr-checklist.md +5 -3
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-token-budget.md +3 -0
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-twin-sync.md +32 -0
- package/presets/claude/next/REPO_AGENTS.md +10 -5
- package/presets/claude/next/agents/build-verifier.md +3 -1
- package/presets/claude/next/rules/tooling-and-review/ai-local-overlay.md +1 -1
- package/presets/claude/next/rules/tooling-and-review/preset-layering.md +3 -3
- package/presets/claude/next/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -1
- package/presets/claude/next/rules/tooling-and-review/preset-pr-checklist.md +5 -3
- package/presets/claude/next/rules/tooling-and-review/preset-token-budget.md +3 -0
- package/presets/claude/next/rules/tooling-and-review/preset-twin-sync.md +32 -0
- package/presets/claude/nuxt/rules/tooling-and-review/preset-layering.md +3 -3
- package/presets/claude/nuxt/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -1
- package/presets/claude/nuxt/rules/tooling-and-review/preset-pr-checklist.md +5 -3
- package/presets/claude/nuxt/rules/tooling-and-review/preset-token-budget.md +3 -0
- package/presets/claude/nuxt/rules/tooling-and-review/preset-twin-sync.md +32 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-layering.md +3 -3
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -1
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-pr-checklist.md +5 -3
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-token-budget.md +3 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-twin-sync.md +32 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-layering.md +3 -3
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -1
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-pr-checklist.md +5 -3
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-token-budget.md +3 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-twin-sync.md +32 -0
- package/presets/claude/svelte/rules/tooling-and-review/preset-layering.md +3 -3
- package/presets/claude/svelte/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -1
- package/presets/claude/svelte/rules/tooling-and-review/preset-pr-checklist.md +5 -3
- package/presets/claude/svelte/rules/tooling-and-review/preset-token-budget.md +3 -0
- package/presets/claude/svelte/rules/tooling-and-review/preset-twin-sync.md +32 -0
- package/presets/cursor/android-kotlin/rules/preset-layering.mdc +3 -3
- package/presets/cursor/android-kotlin/rules/preset-no-cross-stack-leakage.mdc +1 -1
- package/presets/cursor/android-kotlin/rules/preset-pr-checklist.mdc +5 -3
- package/presets/cursor/android-kotlin/rules/preset-token-budget.mdc +3 -0
- package/presets/cursor/android-kotlin/rules/preset-twin-sync.mdc +32 -0
- package/presets/cursor/go/rules/preset-layering.mdc +3 -3
- package/presets/cursor/go/rules/preset-no-cross-stack-leakage.mdc +1 -1
- package/presets/cursor/go/rules/preset-pr-checklist.mdc +5 -3
- package/presets/cursor/go/rules/preset-token-budget.mdc +3 -0
- package/presets/cursor/go/rules/preset-twin-sync.mdc +32 -0
- package/presets/cursor/ios-swift/rules/preset-layering.mdc +3 -3
- package/presets/cursor/ios-swift/rules/preset-no-cross-stack-leakage.mdc +1 -1
- package/presets/cursor/ios-swift/rules/preset-pr-checklist.mdc +5 -3
- package/presets/cursor/ios-swift/rules/preset-token-budget.mdc +3 -0
- package/presets/cursor/ios-swift/rules/preset-twin-sync.mdc +32 -0
- package/presets/cursor/java/rules/preset-layering.mdc +3 -3
- package/presets/cursor/java/rules/preset-no-cross-stack-leakage.mdc +1 -1
- package/presets/cursor/java/rules/preset-pr-checklist.mdc +5 -3
- package/presets/cursor/java/rules/preset-token-budget.mdc +3 -0
- package/presets/cursor/java/rules/preset-twin-sync.mdc +32 -0
- package/presets/cursor/mcp-ts/rules/preset-layering.mdc +3 -3
- package/presets/cursor/mcp-ts/rules/preset-no-cross-stack-leakage.mdc +1 -1
- package/presets/cursor/mcp-ts/rules/preset-pr-checklist.mdc +5 -3
- package/presets/cursor/mcp-ts/rules/preset-token-budget.mdc +3 -0
- package/presets/cursor/mcp-ts/rules/preset-twin-sync.mdc +32 -0
- package/presets/cursor/next/REPO_AGENTS.md +10 -5
- package/presets/cursor/next/agents/build-verifier.md +3 -1
- package/presets/cursor/next/rules/ai-local-overlay.mdc +1 -1
- package/presets/cursor/next/rules/preset-layering.mdc +3 -3
- package/presets/cursor/next/rules/preset-no-cross-stack-leakage.mdc +1 -1
- package/presets/cursor/next/rules/preset-pr-checklist.mdc +5 -3
- package/presets/cursor/next/rules/preset-token-budget.mdc +3 -0
- package/presets/cursor/next/rules/preset-twin-sync.mdc +32 -0
- package/presets/cursor/nuxt/rules/preset-layering.mdc +3 -3
- package/presets/cursor/nuxt/rules/preset-no-cross-stack-leakage.mdc +1 -1
- package/presets/cursor/nuxt/rules/preset-pr-checklist.mdc +5 -3
- package/presets/cursor/nuxt/rules/preset-token-budget.mdc +3 -0
- package/presets/cursor/nuxt/rules/preset-twin-sync.mdc +32 -0
- package/presets/cursor/php-hexagonal/rules/preset-layering.mdc +3 -3
- package/presets/cursor/php-hexagonal/rules/preset-no-cross-stack-leakage.mdc +1 -1
- package/presets/cursor/php-hexagonal/rules/preset-pr-checklist.mdc +5 -3
- package/presets/cursor/php-hexagonal/rules/preset-token-budget.mdc +3 -0
- package/presets/cursor/php-hexagonal/rules/preset-twin-sync.mdc +32 -0
- package/presets/cursor/php-laravel/rules/preset-layering.mdc +3 -3
- package/presets/cursor/php-laravel/rules/preset-no-cross-stack-leakage.mdc +1 -1
- package/presets/cursor/php-laravel/rules/preset-pr-checklist.mdc +5 -3
- package/presets/cursor/php-laravel/rules/preset-token-budget.mdc +3 -0
- package/presets/cursor/php-laravel/rules/preset-twin-sync.mdc +32 -0
- package/presets/cursor/svelte/rules/preset-layering.mdc +3 -3
- package/presets/cursor/svelte/rules/preset-no-cross-stack-leakage.mdc +1 -1
- package/presets/cursor/svelte/rules/preset-pr-checklist.mdc +5 -3
- package/presets/cursor/svelte/rules/preset-token-budget.mdc +3 -0
- package/presets/cursor/svelte/rules/preset-twin-sync.mdc +32 -0
- package/presets/mavis/README.md +60 -0
- package/presets/mavis/next/MAVIS.md +67 -0
- package/presets/mavis/next/MCP.md +36 -0
- package/presets/mavis/next/README.md +15 -0
- package/presets/mavis/next/REPO_AGENTS.md +96 -0
- package/presets/mavis/next/adapter-map.json +959 -0
- package/presets/mavis/next/agents/README.md +206 -0
- package/presets/mavis/next/agents/accessibility-reviewer.md +61 -0
- package/presets/mavis/next/agents/api-contract-reviewer.md +57 -0
- package/presets/mavis/next/agents/build-verifier.md +112 -0
- package/presets/mavis/next/agents/ci-investigator.md +63 -0
- package/presets/mavis/next/agents/code-reviewer.md +61 -0
- package/presets/mavis/next/agents/codebase-analyzer.md +21 -0
- package/presets/mavis/next/agents/debugger.md +80 -0
- package/presets/mavis/next/agents/feature-developer.md +101 -0
- package/presets/mavis/next/agents/migration-specialist.md +67 -0
- package/presets/mavis/next/agents/mockup-reviewer.md +53 -0
- package/presets/mavis/next/agents/openspec-author.md +157 -0
- package/presets/mavis/next/agents/performance-auditor.md +68 -0
- package/presets/mavis/next/agents/playwright-test-generator.md +28 -0
- package/presets/mavis/next/agents/playwright-test-healer.md +28 -0
- package/presets/mavis/next/agents/playwright-test-planner.md +21 -0
- package/presets/mavis/next/agents/qa-tester.md +52 -0
- package/presets/mavis/next/agents/security-reviewer.md +54 -0
- package/presets/mavis/next/agents/solution-architect.md +68 -0
- package/presets/mavis/next/agents/task-analyst.md +166 -0
- package/presets/mavis/next/agents/task-router.md +178 -0
- package/presets/mavis/next/agents/tech-writer.md +57 -0
- package/presets/mavis/next/agents/unit-test-generator.md +31 -0
- package/presets/mavis/next/agents/unit-test-healer.md +32 -0
- package/presets/mavis/next/agents/unit-test-planner.md +54 -0
- package/presets/mavis/next/commands/README.md +49 -0
- package/presets/mavis/next/commands/spec-start.md +24 -0
- package/presets/mavis/next/commands/task-continue.md +50 -0
- package/presets/mavis/next/commands/task.md +50 -0
- package/presets/mavis/next/commands/technical-retro.md +80 -0
- package/presets/mavis/next/hooks/README.md +22 -0
- package/presets/mavis/next/hooks/chain-team-phases.sh +845 -0
- package/presets/mavis/next/mcp.json +19 -0
- package/presets/mavis/next/rules/README.md +16 -0
- package/presets/mavis/next/rules/agent-team-intake.md +11 -0
- package/presets/mavis/next/rules/agent-team-orchestrator.md +210 -0
- package/presets/mavis/next/rules/ai-local-overlay.md +37 -0
- package/presets/mavis/next/rules/anti-sycophancy-discipline.md +23 -0
- package/presets/mavis/next/rules/api-services.md +72 -0
- package/presets/mavis/next/rules/architecture-boundaries-ui.md +9 -0
- package/presets/mavis/next/rules/architecture-boundaries.md +86 -0
- package/presets/mavis/next/rules/arrow-functions.md +25 -0
- package/presets/mavis/next/rules/code-quality-and-refactoring.md +40 -0
- package/presets/mavis/next/rules/code-review-mr.md +40 -0
- package/presets/mavis/next/rules/css-property-order-stylelint.md +5 -0
- package/presets/mavis/next/rules/design-guidance.md +99 -0
- package/presets/mavis/next/rules/feature-delivery-workflow.md +49 -0
- package/presets/mavis/next/rules/http-client.md +55 -0
- package/presets/mavis/next/rules/layer-barrel-exports.md +68 -0
- package/presets/mavis/next/rules/mcp-usage.md +86 -0
- package/presets/mavis/next/rules/mockup-review.md +107 -0
- package/presets/mavis/next/rules/navigation-router-stack.md +56 -0
- package/presets/mavis/next/rules/navigation-router-ui.md +10 -0
- package/presets/mavis/next/rules/next-app-core.md +29 -0
- package/presets/mavis/next/rules/next-app-router.md +44 -0
- package/presets/mavis/next/rules/no-props-spread.md +56 -0
- package/presets/mavis/next/rules/no-type-assertion-as-import-export.md +51 -0
- package/presets/mavis/next/rules/package-manager.md +11 -0
- package/presets/mavis/next/rules/playwright-agents.md +67 -0
- package/presets/mavis/next/rules/post-change-lint.md +35 -0
- package/presets/mavis/next/rules/preset-layering.md +27 -0
- package/presets/mavis/next/rules/preset-no-cross-stack-leakage.md +90 -0
- package/presets/mavis/next/rules/preset-pr-checklist.md +36 -0
- package/presets/mavis/next/rules/preset-token-budget.md +39 -0
- package/presets/mavis/next/rules/preset-twin-sync.md +81 -0
- package/presets/mavis/next/rules/product-specs-authoring.md +112 -0
- package/presets/mavis/next/rules/product-specs.md +56 -0
- package/presets/mavis/next/rules/public-imports.md +50 -0
- package/presets/mavis/next/rules/react-a11y-coding.md +31 -0
- package/presets/mavis/next/rules/react-next-anti-hallucination.md +60 -0
- package/presets/mavis/next/rules/react-ui.md +105 -0
- package/presets/mavis/next/rules/reference-features.md +45 -0
- package/presets/mavis/next/rules/security-next.md +45 -0
- package/presets/mavis/next/rules/store-rtk.md +78 -0
- package/presets/mavis/next/rules/technical-retro.md +11 -0
- package/presets/mavis/next/rules/tests-e2e-structure.md +72 -0
- package/presets/mavis/next/rules/tests-unit.md +72 -0
- package/presets/mavis/next/rules/types-jsdoc.md +43 -0
- package/presets/mavis/next/rules/ux-design.md +99 -0
- package/presets/mavis/next/skills/README.md +21 -0
- package/presets/mavis/next/skills/ci-investigation/SKILL.md +39 -0
- package/presets/mavis/next/skills/code-review/SKILL.md +39 -0
- package/presets/mavis/next/skills/debug-investigation/SKILL.md +26 -0
- package/presets/mavis/next/skills/feature-delivery/SKILL.md +34 -0
- package/presets/mavis/next/skills/mockup-review/SKILL.md +24 -0
- package/presets/mavis/next/skills/playwright-e2e/SKILL.md +28 -0
- package/presets/mavis/next/skills/react-performance/SKILL.md +39 -0
- package/presets/mavis/next/skills/spec-authoring/SKILL.md +21 -0
- package/presets/mavis/next/skills/spec-discovery/SKILL.md +53 -0
- package/presets/mavis/next/skills/technical-retro/SKILL.md +49 -0
- package/presets/mavis/next/skills/unit-testing/SKILL.md +29 -0
- package/presets/mavis/next/skills/ux-design/SKILL.md +31 -0
- package/presets/mavis/next/skills/write-adr/SKILL.md +36 -0
- package/presets/mavis/next/team/README.md +148 -0
- package/presets/mavis/next/team/conventions.md +21 -0
- package/presets/mavis/next/team/fixtures/artifact-manifest.example.json +79 -0
- package/presets/mavis/next/team/fixtures/bugfix-standard.json +25 -0
- package/presets/mavis/next/team/fixtures/feature-full.json +29 -0
- package/presets/mavis/next/team/fixtures/feature-light.json +27 -0
- package/presets/mavis/next/team/fixtures/feature-with-figma-url.json +17 -0
- package/presets/mavis/next/team/fixtures/feature-with-ux-no-figma.json +17 -0
- package/presets/mavis/next/team/fixtures/memlog.example.md +9 -0
- package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/human-gate/metrics.json +69 -0
- package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/missing-ledger/status.json +5 -0
- package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/parallel-receipts/metrics.json +79 -0
- package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/serial-retry/metrics.json +124 -0
- package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/validation-failed/metrics.json +124 -0
- package/presets/mavis/next/team/fixtures/metrics.example.json +54 -0
- package/presets/mavis/next/team/fixtures/mockup-review-fail-embedded-status.json +8 -0
- package/presets/mavis/next/team/fixtures/mockup-review-standalone.json +14 -0
- package/presets/mavis/next/team/fixtures/ux-design-standalone.json +15 -0
- package/presets/mavis/next/team/tasks/.gitkeep +0 -0
- package/presets/mavis/platform-contract.json +131 -0
- package/presets/opencode/README.md +61 -0
- package/presets/opencode/next/MCP.md +36 -0
- package/presets/opencode/next/OPENCODE.md +65 -0
- package/presets/opencode/next/README.md +16 -0
- package/presets/opencode/next/REPO_AGENTS.md +97 -0
- package/presets/opencode/next/adapter-map.json +959 -0
- package/presets/opencode/next/agents/README.md +201 -0
- package/presets/opencode/next/agents/accessibility-reviewer.md +73 -0
- package/presets/opencode/next/agents/api-contract-reviewer.md +69 -0
- package/presets/opencode/next/agents/build-verifier.md +124 -0
- package/presets/opencode/next/agents/ci-investigator.md +71 -0
- package/presets/opencode/next/agents/code-reviewer.md +73 -0
- package/presets/opencode/next/agents/codebase-analyzer.md +33 -0
- package/presets/opencode/next/agents/debugger.md +88 -0
- package/presets/opencode/next/agents/feature-developer.md +109 -0
- package/presets/opencode/next/agents/migration-specialist.md +79 -0
- package/presets/opencode/next/agents/mockup-reviewer.md +65 -0
- package/presets/opencode/next/agents/openspec-author.md +169 -0
- package/presets/opencode/next/agents/performance-auditor.md +80 -0
- package/presets/opencode/next/agents/playwright-test-generator.md +36 -0
- package/presets/opencode/next/agents/playwright-test-healer.md +36 -0
- package/presets/opencode/next/agents/playwright-test-planner.md +33 -0
- package/presets/opencode/next/agents/qa-tester.md +60 -0
- package/presets/opencode/next/agents/security-reviewer.md +66 -0
- package/presets/opencode/next/agents/solution-architect.md +80 -0
- package/presets/opencode/next/agents/task-analyst.md +178 -0
- package/presets/opencode/next/agents/task-router.md +190 -0
- package/presets/opencode/next/agents/tech-writer.md +69 -0
- package/presets/opencode/next/agents/unit-test-generator.md +39 -0
- package/presets/opencode/next/agents/unit-test-healer.md +40 -0
- package/presets/opencode/next/agents/unit-test-planner.md +66 -0
- package/presets/opencode/next/commands/README.md +49 -0
- package/presets/opencode/next/commands/spec-start.md +32 -0
- package/presets/opencode/next/commands/task-continue.md +58 -0
- package/presets/opencode/next/commands/task.md +58 -0
- package/presets/opencode/next/commands/technical-retro.md +88 -0
- package/presets/opencode/next/hooks/README.md +22 -0
- package/presets/opencode/next/hooks/chain-team-phases.sh +845 -0
- package/presets/opencode/next/opencode.json +33 -0
- package/presets/opencode/next/rules/README.md +20 -0
- package/presets/opencode/next/rules/agent-team-intake.md +11 -0
- package/presets/opencode/next/rules/agent-team-orchestrator.md +214 -0
- package/presets/opencode/next/rules/ai-local-overlay.md +37 -0
- package/presets/opencode/next/rules/anti-sycophancy-discipline.md +23 -0
- package/presets/opencode/next/rules/api-services.md +72 -0
- package/presets/opencode/next/rules/architecture-boundaries-ui.md +9 -0
- package/presets/opencode/next/rules/architecture-boundaries.md +86 -0
- package/presets/opencode/next/rules/arrow-functions.md +25 -0
- package/presets/opencode/next/rules/code-quality-and-refactoring.md +40 -0
- package/presets/opencode/next/rules/code-review-mr.md +40 -0
- package/presets/opencode/next/rules/css-property-order-stylelint.md +5 -0
- package/presets/opencode/next/rules/design-guidance.md +99 -0
- package/presets/opencode/next/rules/feature-delivery-workflow.md +49 -0
- package/presets/opencode/next/rules/http-client.md +55 -0
- package/presets/opencode/next/rules/layer-barrel-exports.md +68 -0
- package/presets/opencode/next/rules/mcp-usage.md +86 -0
- package/presets/opencode/next/rules/mockup-review.md +107 -0
- package/presets/opencode/next/rules/navigation-router-stack.md +56 -0
- package/presets/opencode/next/rules/navigation-router-ui.md +10 -0
- package/presets/opencode/next/rules/next-app-core.md +29 -0
- package/presets/opencode/next/rules/next-app-router.md +44 -0
- package/presets/opencode/next/rules/no-props-spread.md +56 -0
- package/presets/opencode/next/rules/no-type-assertion-as-import-export.md +51 -0
- package/presets/opencode/next/rules/package-manager.md +11 -0
- package/presets/opencode/next/rules/playwright-agents.md +67 -0
- package/presets/opencode/next/rules/post-change-lint.md +35 -0
- package/presets/opencode/next/rules/preset-layering.md +27 -0
- package/presets/opencode/next/rules/preset-no-cross-stack-leakage.md +90 -0
- package/presets/opencode/next/rules/preset-pr-checklist.md +36 -0
- package/presets/opencode/next/rules/preset-token-budget.md +39 -0
- package/presets/opencode/next/rules/preset-twin-sync.md +81 -0
- package/presets/opencode/next/rules/product-specs-authoring.md +112 -0
- package/presets/opencode/next/rules/product-specs.md +56 -0
- package/presets/opencode/next/rules/public-imports.md +50 -0
- package/presets/opencode/next/rules/react-a11y-coding.md +31 -0
- package/presets/opencode/next/rules/react-next-anti-hallucination.md +60 -0
- package/presets/opencode/next/rules/react-ui.md +105 -0
- package/presets/opencode/next/rules/reference-features.md +45 -0
- package/presets/opencode/next/rules/security-next.md +45 -0
- package/presets/opencode/next/rules/store-rtk.md +78 -0
- package/presets/opencode/next/rules/technical-retro.md +11 -0
- package/presets/opencode/next/rules/tests-e2e-structure.md +72 -0
- package/presets/opencode/next/rules/tests-unit.md +72 -0
- package/presets/opencode/next/rules/types-jsdoc.md +43 -0
- package/presets/opencode/next/rules/ux-design.md +99 -0
- package/presets/opencode/next/skills/README.md +21 -0
- package/presets/opencode/next/skills/ci-investigation/SKILL.md +44 -0
- package/presets/opencode/next/skills/code-review/SKILL.md +44 -0
- package/presets/opencode/next/skills/debug-investigation/SKILL.md +59 -0
- package/presets/opencode/next/skills/feature-delivery/SKILL.md +39 -0
- package/presets/opencode/next/skills/mockup-review/SKILL.md +29 -0
- package/presets/opencode/next/skills/playwright-e2e/SKILL.md +33 -0
- package/presets/opencode/next/skills/react-performance/SKILL.md +44 -0
- package/presets/opencode/next/skills/spec-authoring/SKILL.md +26 -0
- package/presets/opencode/next/skills/spec-discovery/SKILL.md +58 -0
- package/presets/opencode/next/skills/technical-retro/SKILL.md +54 -0
- package/presets/opencode/next/skills/unit-testing/SKILL.md +34 -0
- package/presets/opencode/next/skills/ux-design/SKILL.md +36 -0
- package/presets/opencode/next/skills/write-adr/SKILL.md +41 -0
- package/presets/opencode/next/team/README.md +148 -0
- package/presets/opencode/next/team/conventions.md +21 -0
- package/presets/opencode/next/team/fixtures/artifact-manifest.example.json +79 -0
- package/presets/opencode/next/team/fixtures/bugfix-standard.json +25 -0
- package/presets/opencode/next/team/fixtures/feature-full.json +29 -0
- package/presets/opencode/next/team/fixtures/feature-light.json +27 -0
- package/presets/opencode/next/team/fixtures/feature-with-figma-url.json +17 -0
- package/presets/opencode/next/team/fixtures/feature-with-ux-no-figma.json +17 -0
- package/presets/opencode/next/team/fixtures/memlog.example.md +9 -0
- package/presets/opencode/next/team/fixtures/metrics-scenarios/tasks/human-gate/metrics.json +69 -0
- package/presets/opencode/next/team/fixtures/metrics-scenarios/tasks/missing-ledger/status.json +5 -0
- package/presets/opencode/next/team/fixtures/metrics-scenarios/tasks/parallel-receipts/metrics.json +79 -0
- package/presets/opencode/next/team/fixtures/metrics-scenarios/tasks/serial-retry/metrics.json +124 -0
- package/presets/opencode/next/team/fixtures/metrics-scenarios/tasks/validation-failed/metrics.json +124 -0
- package/presets/opencode/next/team/fixtures/metrics.example.json +54 -0
- package/presets/opencode/next/team/fixtures/mockup-review-fail-embedded-status.json +8 -0
- package/presets/opencode/next/team/fixtures/mockup-review-standalone.json +14 -0
- package/presets/opencode/next/team/fixtures/ux-design-standalone.json +15 -0
- package/presets/opencode/next/team/tasks/.gitkeep +0 -0
- package/presets/opencode/platform-contract.json +131 -0
- package/scripts/capture-cli-golden.mjs +48 -0
- package/scripts/check-chain-hook-coverage.sh +2 -0
- package/scripts/check-mavis-adapter-map.mjs +294 -0
- package/scripts/check-mavis-local-overlay.mjs +56 -0
- package/scripts/check-mavis-platform-contract.mjs +388 -0
- package/scripts/check-mavis-token-budget.mjs +48 -0
- package/scripts/check-opencode-adapter-map.mjs +294 -0
- package/scripts/check-opencode-local-overlay.mjs +56 -0
- package/scripts/check-opencode-platform-contract.mjs +388 -0
- package/scripts/check-opencode-token-budget.mjs +48 -0
- package/scripts/check-preset-leakage.sh +64 -3
- package/scripts/check-preset-structure.sh +108 -0
- package/scripts/check-shared-core-drift.sh +18 -0
- package/scripts/check-task-router-intents.sh +15 -2
- package/scripts/fixtures/cli-golden/claude/next.json +130 -0
- package/scripts/fixtures/cli-golden/cursor/next.json +132 -0
- package/scripts/fixtures/cli-golden/mavis/next.json +125 -0
- package/scripts/fixtures/cli-golden/opencode/next.json +125 -0
- package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/cursor/AGENTS.md +1 -0
- package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/cursor/rules/extra.mdc +1 -0
- package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/cursor/rules/sample.mdc +2 -0
- package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/mavis/MAVIS.md +1 -0
- package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/mavis/adapter-map.json +26 -0
- package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/mavis/rules/sample.md +2 -0
- package/scripts/fixtures/mavis-adapter-map/valid/cursor/AGENTS.md +1 -0
- package/scripts/fixtures/mavis-adapter-map/valid/cursor/rules/sample.mdc +2 -0
- package/scripts/fixtures/mavis-adapter-map/valid/mavis/MAVIS.md +1 -0
- package/scripts/fixtures/mavis-adapter-map/valid/mavis/adapter-map.json +26 -0
- package/scripts/fixtures/mavis-adapter-map/valid/mavis/rules/sample.md +2 -0
- package/scripts/fixtures/mavis-platform-contract/invalid-minimax-destination.json +131 -0
- package/scripts/fixtures/mavis-platform-contract/invalid-missing-capability.json +126 -0
- package/scripts/fixtures/mavis-platform-contract/invalid-released-unknown-stack.json +133 -0
- package/scripts/fixtures/mavis-platform-contract/invalid-unknown-native-path.json +131 -0
- package/scripts/fixtures/mavis-platform-contract/invalid-version-pin.json +132 -0
- package/scripts/fixtures/mavis-platform-contract/valid.json +131 -0
- package/scripts/fixtures/mavis-probe/AGENTS.md +6 -0
- package/scripts/fixtures/mavis-probe/agents/probe-agent.md +6 -0
- package/scripts/fixtures/mavis-probe/fake-mcode.mjs +98 -0
- package/scripts/fixtures/mavis-probe/output.schema.json +28 -0
- package/scripts/fixtures/mavis-probe/rules/probe.md +5 -0
- package/scripts/fixtures/mavis-probe/skills/probe/SKILL.md +11 -0
- package/scripts/fixtures/opencode-adapter-map/invalid-unmapped/cursor/AGENTS.md +1 -0
- package/scripts/fixtures/opencode-adapter-map/invalid-unmapped/cursor/rules/extra.mdc +1 -0
- package/scripts/fixtures/opencode-adapter-map/invalid-unmapped/cursor/rules/sample.mdc +2 -0
- package/scripts/fixtures/opencode-adapter-map/invalid-unmapped/opencode/OPENCODE.md +1 -0
- package/scripts/fixtures/opencode-adapter-map/invalid-unmapped/opencode/adapter-map.json +26 -0
- package/scripts/fixtures/opencode-adapter-map/invalid-unmapped/opencode/rules/sample.md +2 -0
- package/scripts/fixtures/opencode-adapter-map/valid/cursor/AGENTS.md +1 -0
- package/scripts/fixtures/opencode-adapter-map/valid/cursor/rules/sample.mdc +2 -0
- package/scripts/fixtures/opencode-adapter-map/valid/opencode/OPENCODE.md +1 -0
- package/scripts/fixtures/opencode-adapter-map/valid/opencode/adapter-map.json +26 -0
- package/scripts/fixtures/opencode-adapter-map/valid/opencode/rules/sample.md +2 -0
- package/scripts/fixtures/opencode-platform-contract/invalid-home-destination.json +131 -0
- package/scripts/fixtures/opencode-platform-contract/invalid-missing-capability.json +126 -0
- package/scripts/fixtures/opencode-platform-contract/invalid-released-unknown-stack.json +133 -0
- package/scripts/fixtures/opencode-platform-contract/invalid-unknown-native-path.json +131 -0
- package/scripts/fixtures/opencode-platform-contract/invalid-version-pin.json +132 -0
- package/scripts/fixtures/opencode-platform-contract/valid.json +131 -0
- package/scripts/generate-mavis-next.mjs +706 -0
- package/scripts/generate-opencode-next.mjs +831 -0
- package/scripts/lib/cli-golden.mjs +50 -0
- package/scripts/lib/discover-hooks.mjs +94 -0
- package/scripts/probe-mavis-capabilities.mjs +480 -0
- package/scripts/sync-dogfood-mavis.sh +90 -0
- package/scripts/sync-dogfood-opencode.sh +85 -0
- package/scripts/test-agent-task-metrics-hooks.mjs +25 -16
- package/scripts/test-chain-team-phases-coverage.mjs +15 -7
- package/scripts/test-cli-init-clean.mjs +367 -0
- package/scripts/test-cli-mcp-merge.mjs +23 -0
- package/scripts/test-mavis-context-budget.mjs +55 -0
- package/scripts/test-mavis-orchestration.mjs +649 -0
- package/scripts/test-opencode-context-budget.mjs +53 -0
- package/scripts/test-probe-mavis-capabilities.mjs +205 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<!-- shared-core: architecture/product-specs.md -->
|
|
2
|
+
|
|
3
|
+
# Product specs (docs/specs)
|
|
4
|
+
|
|
5
|
+
Product page/feature **behavior** specs live under the consumer repo `docs/specs/**`. This stem covers **discovery and presence** — not layer implementation order (see `feature-delivery-workflow`) and not code-structure mirroring (see `reference-features`).
|
|
6
|
+
|
|
7
|
+
**Authoring** (Generate / Bootstrap modes, INDEX/frontmatter v1, body checklist, greenfield, conflict precedence) → load **`product-specs-authoring`** when generation is requested (`/spec-start`, brief AC, or router `spec-gen`).
|
|
8
|
+
|
|
9
|
+
**Pipeline `specMode`:** `consume` (this stem) · `generate` (authoring stem) · `none` (spike/research — skip INDEX row requirement; do not invent a dummy INDEX). Primary field: `brief.md` `## Spec mode`; optional `pipeline.json` `specMode`.
|
|
10
|
+
|
|
11
|
+
## Modes (summary)
|
|
12
|
+
|
|
13
|
+
| Mode | When | Behavior |
|
|
14
|
+
|------|------|----------|
|
|
15
|
+
| **Consume** (default) | INDEX exists or globs hit `docs/specs/**` without generate intent | Discover via INDEX; soft-fail on miss; **never invent** INDEX/specs |
|
|
16
|
+
| **Generate** | Explicit generate intent / AC / `/spec-start` with existing tree | Create/update page/feature specs + INDEX from stated sources |
|
|
17
|
+
| **Bootstrap** | Explicit bootstrap / `/spec-start` when tree absent | Create INDEX + templates + first domain spec |
|
|
18
|
+
| **None** (`specMode: none`) | Spike / research / preset-only | Skip INDEX requirement and author mode; no dummy INDEX row |
|
|
19
|
+
|
|
20
|
+
Greenfield: agents may create INDEX/specs **only** on explicit intent, AC, or `/spec-start`. Missing INDEX alone does **not** authorize inventing the tree.
|
|
21
|
+
|
|
22
|
+
## Presence policy
|
|
23
|
+
|
|
24
|
+
- If `specMode` is **`none`** → do **not** require an INDEX row; continue from brief/AC. Do not invent INDEX.
|
|
25
|
+
- If `docs/specs/INDEX.md` is **missing** → the tree is **optional** (greenfield OK for *consume*). Continue with code/brief discovery; do not invent an INDEX solely because this stem loaded.
|
|
26
|
+
- If INDEX **exists** and `specMode` is not `none` → it is the **required discovery path** for work that touches a listed page, feature, route, or alias.
|
|
27
|
+
|
|
28
|
+
## Discovery algorithm
|
|
29
|
+
|
|
30
|
+
1. Always start at `docs/specs/INDEX.md` when present (skip when `specMode: none`).
|
|
31
|
+
2. Resolve the entry by: route, stable `id`, PageName / alias, or domain folder.
|
|
32
|
+
3. Read the **linked page** spec and, when INDEX or page Related links it, the optional domain `feature.md`. Do **not** dump the whole `docs/specs/**` tree into the prompt — locator = those linked files.
|
|
33
|
+
|
|
34
|
+
## Miss policy (INDEX present, row or file missing)
|
|
35
|
+
|
|
36
|
+
- Record the gap in `open_questions` / handoff gaps.
|
|
37
|
+
- Fall back to code discovery and consumer `.ai/context/**` when present.
|
|
38
|
+
- **Do not invent** product behavior, states, interactions, or contracts.
|
|
39
|
+
- Hard-fail / block only when the task’s acceptance criteria explicitly require a named spec that is absent (human/gate decision).
|
|
40
|
+
|
|
41
|
+
## Authoring pointer
|
|
42
|
+
|
|
43
|
+
Same-changeset INDEX updates, frontmatter v1, required body headings, templates, and conflict precedence live in **`product-specs-authoring`**. Do not paste the full checklist here.
|
|
44
|
+
|
|
45
|
+
## Non-goals
|
|
46
|
+
|
|
47
|
+
- Not a replacement for `.ai/context/**` (external AI Code Review glossary) or `reference-features` (file-layout mirror).
|
|
48
|
+
- Not Tessl / an external host as primary SoT.
|
|
49
|
+
- No stack filesystem path recipes in this core body — path examples belong only in adapter **Stack notes**.
|
|
50
|
+
|
|
51
|
+
## Related
|
|
52
|
+
|
|
53
|
+
- `product-specs-authoring` — generation modes, contracts, self-check.
|
|
54
|
+
- Skill `spec-discovery` — opt-in research-before-spec (author mode only; not default consume).
|
|
55
|
+
- `reference-features` — code structure mirror (how to layout files), not product behavior.
|
|
56
|
+
- Consumer `.ai/context/**` when present — review/domain glossary; cross-link, do not replace.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Public imports (`@/types`, `@/api`)
|
|
2
|
+
|
|
3
|
+
**Collisions:** type imports — `@/types` section below; API outside `app/src/api/**` — `@/api` section below (mirrors ESLint `no-restricted-imports` in `app/eslint.config.mjs`).
|
|
4
|
+
|
|
5
|
+
## `@/types`
|
|
6
|
+
|
|
7
|
+
- **Public types API** — barrel `app/src/types/index.ts`; import types only as `@/types` (or `@/types/index`).
|
|
8
|
+
- **Forbidden** to bypass the barrel: `@/types/<anything>`, except enums.
|
|
9
|
+
- **Enums** — only `@/types/enums` / `@/types/enums.ts`.
|
|
10
|
+
- Inside `app/src/types/**` — relative imports between layer files.
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
// ✅
|
|
14
|
+
import type { TUserProfile } from '@/types'
|
|
15
|
+
import { SomeEnum } from '@/types/enums'
|
|
16
|
+
|
|
17
|
+
// ❌
|
|
18
|
+
import type { TUserProfile } from '@/types/User.types'
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
New public types — re-export in `app/src/types/index.ts` per **`layer-barrel-exports.md`**.
|
|
22
|
+
|
|
23
|
+
## `@/api`
|
|
24
|
+
|
|
25
|
+
- **Public API** — barrel `app/src/api/index.ts`. Outside `app/src/api/**` — only `import … from '@/api'` (or `@/api/index`).
|
|
26
|
+
- **Forbidden** from outside the layer: `@/api/<anything>`, except `@/api/index`.
|
|
27
|
+
- Inside `app/src/api/**` — relative imports and `@/api/services/**`, `@/api/clients/**`.
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// ✅ in store, UI, lib outside app/src/api
|
|
31
|
+
import { MedcardApiService } from '@/api'
|
|
32
|
+
|
|
33
|
+
// ❌ outside app/src/api
|
|
34
|
+
import { MedcardApiService } from '@/api/services/MedcardApiService/MedcardApiService'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
New public API symbols — re-export in `app/src/api/index.ts` per **`layer-barrel-exports.md`**.
|
|
38
|
+
## Incorrect
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import type { TUserProfile } from '@/types/User.types'
|
|
42
|
+
import { OrdersApi } from '@/api/services/OrdersApi'
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Correct
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import type { TUserProfile } from '@/types'
|
|
49
|
+
import { ordersApi } from '@/api'
|
|
50
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# A11y when developing UI
|
|
2
|
+
|
|
3
|
+
The reviewer (`accessibility-reviewer`) checks the diff; these rules apply **while writing** code.
|
|
4
|
+
|
|
5
|
+
## Semantics and ARIA
|
|
6
|
+
|
|
7
|
+
- Prefer **native elements** (`button`, `a`, `label`, `input`) over `div` with `onClick`.
|
|
8
|
+
- **`role` / `aria-*`** — only when there is no native equivalent; do not duplicate what semantics already provide.
|
|
9
|
+
- Headings — `h1`–`h6` hierarchy without skipping levels for styling.
|
|
10
|
+
|
|
11
|
+
## Forms
|
|
12
|
+
|
|
13
|
+
- Every input is associated with a **`label`** (`htmlFor` / `id` or wrapper).
|
|
14
|
+
- Error messages — **`aria-describedby`**, `aria-invalid` on validation errors.
|
|
15
|
+
- Submit vs button — explicit `type`.
|
|
16
|
+
|
|
17
|
+
## Keyboard and focus
|
|
18
|
+
|
|
19
|
+
- All interactive elements are **reachable via Tab** and activatable with Enter/Space where expected.
|
|
20
|
+
- **Modals/drawers** — focus trap, return focus to trigger on close, Esc closes (if UX allows).
|
|
21
|
+
- Do not remove visible **focus outline** without an accessible custom focus style.
|
|
22
|
+
|
|
23
|
+
## Content
|
|
24
|
+
|
|
25
|
+
- Images — **`alt`** (empty `alt` only for decorative images).
|
|
26
|
+
- Icon buttons — **`aria-label`** or visually hidden text.
|
|
27
|
+
- Dynamic updates — `aria-live` for critical status/error (use sparingly).
|
|
28
|
+
|
|
29
|
+
## Verification
|
|
30
|
+
|
|
31
|
+
- When unsure — devtools a11y tree or `accessibility-reviewer` in the pipeline for UI-heavy features.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# React / Next / RTK anti-hallucination
|
|
2
|
+
|
|
3
|
+
These rows **OVERRIDE** generation for the listed patterns. Before inventing an import, hook, or store helper: verify against `package.json` (installed majors) and sibling files in the same layer. If unsure, mark `// VERIFY: lib.symbol @ version` and surface the uncertainty — do not silently stub.
|
|
4
|
+
|
|
5
|
+
App Router–specific rows (async `params` / `cookies()`, invented auth helpers, etc.) stay in **`next-app-router.md`**. This rule covers broader React / RTK / Next phantom imports and boundary mistakes across `app/**`.
|
|
6
|
+
|
|
7
|
+
## 1. Phantom / wrong Next imports
|
|
8
|
+
|
|
9
|
+
| ❌ Avoid | ✅ Prefer |
|
|
10
|
+
|---------|----------|
|
|
11
|
+
| `import Head from 'next/head'` in App Router trees | Metadata API (`export const metadata` / `generateMetadata`) or project pattern |
|
|
12
|
+
| `import { … } from 'next/document'` / `_app` / `_document` APIs in App Router repos | App Router `layout.tsx` / `template.tsx`; do not invent Pages Router entrypoints |
|
|
13
|
+
| Invented paths: `next/server-actions`, `next/rsc`, `next/auth`, `next/cache/react` | Real exports from installed `next` (`next/server`, `next/cache`, `next/headers`, …) — check docs for **that** major |
|
|
14
|
+
| `getServerSideProps` / `getStaticProps` / `getInitialProps` in `app/` routes | RSC data loaders, route handlers, or server actions — mirror sibling routes |
|
|
15
|
+
| `import Image from 'next/image/legacy'` without verifying package | `next/image` (or repo’s established image helper); mark `VERIFY` if legacy path is intentional |
|
|
16
|
+
|
|
17
|
+
## 2. RSC / client boundary
|
|
18
|
+
|
|
19
|
+
| ❌ Avoid | ✅ Prefer |
|
|
20
|
+
|---------|----------|
|
|
21
|
+
| `useAppSelector` / `useDispatch` / RTK hooks in a Server Component (no `'use client'`) | Client boundary component, or server data via `@/api` / loaders — see `next-app-core` |
|
|
22
|
+
| `process.env.SECRET_*` / non-`NEXT_PUBLIC_` secrets in client bundles | Server-only env; client gets only `NEXT_PUBLIC_*` or values from a server action/API |
|
|
23
|
+
| Passing non-serializable props (functions, class instances, store) from RSC → client | Plain data props; callbacks stay in client trees |
|
|
24
|
+
| Importing a `'use client'` module that re-exports server-only secrets into the client graph | Keep secrets in server modules; split barrels so client never pulls them |
|
|
25
|
+
|
|
26
|
+
## 3. React patterns
|
|
27
|
+
|
|
28
|
+
| ❌ Avoid | ✅ Prefer |
|
|
29
|
+
|---------|----------|
|
|
30
|
+
| Invented hooks from wrong packages (`useFormState` from `react-dom` when the repo uses a form lib; fake `use` from `react-redux`) | Copy import path from a sibling file; confirm symbol in installed React / React-DOM major |
|
|
31
|
+
| Deprecated React APIs without version check (`ReactDOM.render`, `findDOMNode`, string refs, `defaultProps` on function components) | Current API for the installed React major (`createRoot`, function defaults, …) |
|
|
32
|
+
| `import { useEffectEvent } from 'react'` (or similar) when `package.json` React may not ship it yet | Check React version first; else local pattern / mark `VERIFY` |
|
|
33
|
+
| Phantom packages: `react-server-dom`, `@react/cache`, invented `@/hooks/useServerQuery` | Only packages in lockfile + public hooks already used in the repo |
|
|
34
|
+
|
|
35
|
+
## 4. RTK / RTK Query phantoms
|
|
36
|
+
|
|
37
|
+
| ❌ Avoid | ✅ Prefer |
|
|
38
|
+
|---------|----------|
|
|
39
|
+
| Fake `createSlice` options (`extraReducers` as plain object without builder, invented `slice.injectEndpoints`) | RTK patterns from existing slices (`store-rtk.md`); builder callback for `extraReducers` |
|
|
40
|
+
| Invented RTKQ helpers: `api.injectQuery`, `createApiEndpoint`, `useLazyGetX` without a matching `endpoints` definition | Endpoints defined on the real `createApi` instance; hooks generated from that API |
|
|
41
|
+
| Deep / wrong store imports: `@/store/slices/foo/fooSlice` or `@/store/index` when public API is `@/store` | Public store barrel / typed hooks as in sibling UI (`public-imports.md`) |
|
|
42
|
+
| Storing raw transport DTOs or inventing axios/fetch error shapes in slice state | Domain models + transport error types from `@/types` as in existing thunks |
|
|
43
|
+
|
|
44
|
+
## 5. Navigation / data
|
|
45
|
+
|
|
46
|
+
| ❌ Avoid | ✅ Prefer |
|
|
47
|
+
|---------|----------|
|
|
48
|
+
| `import { useRouter } from 'next/router'` in App Router apps | `next/navigation` (`useRouter`, `usePathname`, `useSearchParams`) — see `navigation-router-stack.md` |
|
|
49
|
+
| `Router.push` / Pages `withRouter` patterns in `app/` UI | App Router navigation helpers already used in `app/src/ui/**` |
|
|
50
|
+
| Client `fetch` / raw HTTP from UI or `page.tsx` bypassing `@/api` | Services via `@/api` / established loaders (`api-services.md`, `http-client.md`) |
|
|
51
|
+
| Invented `next/link` props that siblings never use (e.g. fake prefetch enums) | Match existing `<Link>` usage; verify against installed Next |
|
|
52
|
+
|
|
53
|
+
## 6. Version drift
|
|
54
|
+
|
|
55
|
+
| ❌ Avoid | ✅ Prefer |
|
|
56
|
+
|---------|----------|
|
|
57
|
+
| Bleeding-edge Next/React APIs (“I saw it in a blog”) without checking `package.json` | Confirm major/minor in manifest + lockfile; copy a sibling that already compiles |
|
|
58
|
+
| Assuming async `cookies()` / `headers()` / `params` behavior from a newer Next than installed | Follow **installed** Next + `next-app-router.md` table; mark `VERIFY` if majors differ across docs |
|
|
59
|
+
|
|
60
|
+
When a row conflicts with a verified sibling pattern in this repo, **the sibling wins** — update this banlist in a preset PR rather than inventing a third path.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# General component rules
|
|
2
|
+
|
|
3
|
+
- Use **functional components** with hooks, no classes.
|
|
4
|
+
- A component should:
|
|
5
|
+
- stay as "thin" as possible on business logic;
|
|
6
|
+
- delegate state to store/hooks when needed in multiple places;
|
|
7
|
+
- rely on **shared project UI design primitives** (packages or local component library), if present.
|
|
8
|
+
- Before a new custom control — search for an existing or close component in the repository / project UI packages and reuse or extend it.
|
|
9
|
+
- For repeated logic, create `useSomething` hooks nearby or in `src/ui/hooks/**`.
|
|
10
|
+
- When accessing store, API, shared helpers, and utilities, components and hooks must use only their **public API** (for example, `@/store`, `@/store/slices/Foo`, `@/lib/utils`), not internal implementation files of other modules.
|
|
11
|
+
|
|
12
|
+
# File structure
|
|
13
|
+
|
|
14
|
+
For a page/large block:
|
|
15
|
+
- `FeatureBlock.tsx` — JSX and composition.
|
|
16
|
+
- `styles.ts` or adjacent style module — per repository convention (CSS Modules, CSS-in-JS, etc.).
|
|
17
|
+
- `index.ts` — re-export (if needed externally).
|
|
18
|
+
|
|
19
|
+
## Child components (`./components`)
|
|
20
|
+
|
|
21
|
+
- Local subcomponents used only by this block go in **`./components/<ComponentName>/`** relative to the parent component folder (do not leave large JSX chunks and "internal" components in the same file as the parent).
|
|
22
|
+
- Each subcomponent has **its own** folder with the same name as the public component:
|
|
23
|
+
- `ComponentName.tsx` — markup and composition;
|
|
24
|
+
- `styles.ts` — styles for this subcomponent only (do not import `styles` from sibling components — see Styles below);
|
|
25
|
+
- when needed — `ComponentName.data.ts`, `ComponentName.utils.ts`, `ComponentName.hooks.ts` with the same prefix rules as the parent;
|
|
26
|
+
- optional `index.ts` re-export.
|
|
27
|
+
- The parent imports subcomponents from `./components/...`, not inline implementations.
|
|
28
|
+
|
|
29
|
+
For a reusable component:
|
|
30
|
+
- Folder named after the component:
|
|
31
|
+
- `ComponentName.tsx`
|
|
32
|
+
- style files per project scheme;
|
|
33
|
+
- optional: `types.ts`, `ComponentName.hooks.ts` (see prefix rules below).
|
|
34
|
+
|
|
35
|
+
## Adjacent helper modules (naming)
|
|
36
|
+
|
|
37
|
+
**File name prefix = public component name** (as in `ComponentName.tsx` in that folder), in **PascalCase**. Do not introduce separate "descriptive" file names by content meaning (`analysisPreparationIconMap.ts`, `buildAnalysisIdToNameMap.ts`, etc.) — that breaks the link to the component and creates one-off names.
|
|
38
|
+
|
|
39
|
+
**Role suffix:**
|
|
40
|
+
|
|
41
|
+
| Suffix | Purpose | Content examples |
|
|
42
|
+
|--------|---------|------------------|
|
|
43
|
+
| `ComponentName.data.ts` | Static data and UI configuration | `id → icon/label` maps, list constants, display lookup tables |
|
|
44
|
+
| `ComponentName.utils.ts` | Pure non-React functions | formatting, prop/data preprocessing for render, `build…`/`map…` helpers |
|
|
45
|
+
| `ComponentName.hooks.ts` | Hooks used only by this block | local `use…` (if not moved to `src/ui/hooks/**`) |
|
|
46
|
+
|
|
47
|
+
- Multiple constants/maps or multiple functions — still **one** `.data.ts` and one `.utils.ts`; do not split by "topic" into separate files without good reason (size, different responsibility at subcomponent level).
|
|
48
|
+
- If logic belongs to a **subcomponent** in a subfolder (`components/Child/Child.tsx`), the same rules apply to **`Child.data.ts`**, **`Child.utils.ts`** for that subcomponent.
|
|
49
|
+
- Tests for utilities and data — under the mirrored path `app/__tests__/unit/<rel>` per `tests-unit.md`, with the same prefix (`RequestForAnalysisRecommendations.utils.spec.ts`, etc.).
|
|
50
|
+
|
|
51
|
+
# Styles and design tokens
|
|
52
|
+
|
|
53
|
+
- **Root** styled export in adjacent `styles` — **`Root`**; in JSX: `<s.Root>` with `import * as s from './styles'`. Nested — `Title`, `List`, etc. Not `Container`/`Wrapper` for a single wrapper.
|
|
54
|
+
- **Forbidden** to import another component's `styles` (`../Other/styles`, `../../styles`). Allowed: `./styles`, shared primitives from `@/ui/components/...` or design-system packages.
|
|
55
|
+
- CSS / `styled` order — Stylelint idiomatic-order: `css-property-order-stylelint.md` (loads on `styles.ts` / `.css`).
|
|
56
|
+
- For visuals use **the style stack and tokens already in the project** (variables, theme, shared classes, design package).
|
|
57
|
+
- Avoid:
|
|
58
|
+
- inline styles except simple cases;
|
|
59
|
+
- duplicating styling already covered by shared primitives;
|
|
60
|
+
- "magic" literals (`#xxxxxx`, arbitrary `17px` / `23px`) when the project has tokens or scale.
|
|
61
|
+
- If no suitable token exists — a local primitive **in one place**, aligned with the design system when possible.
|
|
62
|
+
|
|
63
|
+
# Props and typing
|
|
64
|
+
|
|
65
|
+
- **Do not pass props via spread** (`<Foo {...x} />`). Only explicit attributes; details and exceptions — `no-props-spread.md` (in `app/src/ui` ESLint catches this too).
|
|
66
|
+
- Describe props with `type Props = { ... }` or `interface Props { ... }`.
|
|
67
|
+
- Do not use `any`; when needed:
|
|
68
|
+
- generics (`<T>`), `unknown`, type predicates and user-defined type guards.
|
|
69
|
+
- For domain entities use types from `@/types` (and enums from `@/types/enums`), not redefined locally (`public-imports.md`).
|
|
70
|
+
|
|
71
|
+
# Logic and side effects
|
|
72
|
+
|
|
73
|
+
- Side effects and async:
|
|
74
|
+
- when possible, move to store (thunks, middleware) or dedicated hooks.
|
|
75
|
+
- Components must not:
|
|
76
|
+
- know API details directly (URL, DTO shape);
|
|
77
|
+
- map "raw" DTOs — only domain types;
|
|
78
|
+
- contain non-trivial computations and data transforms (boolean flags, complex string concatenation, aggregates, etc.). In most cases display data should be prepared at mapping/preparation stages (API → domain model → store), and components use ready fields.
|
|
79
|
+
|
|
80
|
+
# UI testing
|
|
81
|
+
|
|
82
|
+
- For non-trivial components add tests:
|
|
83
|
+
- **Testing Library** for React as adopted in the project;
|
|
84
|
+
- verify behavior and business rules, not specific CSS classes.
|
|
85
|
+
- In tests prefer text, roles, and aria attributes.
|
|
86
|
+
## Incorrect
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import { mapUserDto } from '@/api/services/UsersApi/userResponseMappers'
|
|
90
|
+
|
|
91
|
+
export const UserBadge = ({ dto }: { dto: unknown }) => {
|
|
92
|
+
const user = mapUserDto(dto as any) // mapping + deep import in UI
|
|
93
|
+
return <span>{user.name}</span>
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Correct
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import type { TUserProfile } from '@/types'
|
|
101
|
+
|
|
102
|
+
export const UserBadge = ({ user }: { user: TUserProfile }) => {
|
|
103
|
+
return <span>{user.name}</span>
|
|
104
|
+
}
|
|
105
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<!-- shared-core: architecture/reference-features.template.md -->
|
|
2
|
+
|
|
3
|
+
# Reference features
|
|
4
|
+
|
|
5
|
+
Before implementing, find a feature of the same type and **mirror its structure**; do not invent a new file organization.
|
|
6
|
+
|
|
7
|
+
## Reference table
|
|
8
|
+
|
|
9
|
+
Replace placeholders with **real** paths after `ai-rules init` / team agreement:
|
|
10
|
+
|
|
11
|
+
| Layer | Reference | What to copy |
|
|
12
|
+
|-------|-----------|--------------|
|
|
13
|
+
| UI / Presentation | **TBD** | components, styles/data helpers, barrel |
|
|
14
|
+
| State / ViewModel | **TBD** | slice/VM, selectors, types |
|
|
15
|
+
| API / Data | **TBD** | service/repo, mappers, barrel |
|
|
16
|
+
| Domain / Types | **TBD** | domain types, public export |
|
|
17
|
+
| Unit tests | **TBD** | `*.spec` / XCTest naming |
|
|
18
|
+
| E2E / UI tests | **TBD** | cases/plans, page objects / accessibility IDs |
|
|
19
|
+
|
|
20
|
+
## How to use
|
|
21
|
+
|
|
22
|
+
1. Identify affected layers from `decomposition.md` or the task.
|
|
23
|
+
2. Open the reference from the table (after paths are filled).
|
|
24
|
+
3. Mirror naming, file order, import patterns, and tests.
|
|
25
|
+
4. If there is no reference — pick the **closest** existing feature of the same layer and record the choice in the handoff.
|
|
26
|
+
|
|
27
|
+
## Living conventions
|
|
28
|
+
|
|
29
|
+
After init the team maintains **local** gotchas, patterns, and decisions in a consumer-owned store (not in shared core and not only in root `AGENTS.md`):
|
|
30
|
+
|
|
31
|
+
| Section | What to record |
|
|
32
|
+
|---------|----------------|
|
|
33
|
+
| Gotchas | Recurring traps, fragile spots, “do not do X in this repo” |
|
|
34
|
+
| Patterns | Local patterns beyond the reference table |
|
|
35
|
+
| Decisions | Short ADR links / product decisions that affect code |
|
|
36
|
+
|
|
37
|
+
Path pointer and stack tables — in the preset adapter (`team/conventions.md`). The file is **not** always-on.
|
|
38
|
+
|
|
39
|
+
## Related rules
|
|
40
|
+
|
|
41
|
+
- `code-quality-and-refactoring` — repeat patterns, no deep-import.
|
|
42
|
+
- `feature-delivery-workflow` — layer order.
|
|
43
|
+
- skill `feature-delivery` — end-to-end scenario.
|
|
44
|
+
|
|
45
|
+
> Concrete path tables, globs, and dogfood checklists live in the stack adapter **Stack notes**.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Security (Next.js)
|
|
2
|
+
|
|
3
|
+
Coding-time checklist. Full audit → agent `security-reviewer` + skill `code-review`.
|
|
4
|
+
|
|
5
|
+
## Secrets and env
|
|
6
|
+
|
|
7
|
+
- Never put service / secret keys in `NEXT_PUBLIC_*` or client bundles (`sk_`, private API keys, DB URLs).
|
|
8
|
+
- Do not commit `.env*` with real secrets; use CI / secret manager patterns already in the repo.
|
|
9
|
+
- Prefer server-only modules for privileged clients; do not import them into Client Components.
|
|
10
|
+
|
|
11
|
+
## Auth and session
|
|
12
|
+
|
|
13
|
+
- Enforce auth on the **server** (layouts, pages, Server Actions, route handlers) — not only Edge middleware.
|
|
14
|
+
- Middleware may refresh sessions; do not treat middleware alone as authorization.
|
|
15
|
+
- Prefer httpOnly secure cookies over `localStorage` for tokens when the repo pattern allows.
|
|
16
|
+
- Never trust client-only session claims without a server verify step used by the project.
|
|
17
|
+
|
|
18
|
+
## Mutations and input
|
|
19
|
+
|
|
20
|
+
- Server Actions / route handlers: validate untrusted input at the edge (Zod or the repo’s schema pattern).
|
|
21
|
+
- Prefer an explicit success/error response shape over throwing opaque errors to the client.
|
|
22
|
+
- CSRF / origin checks — follow existing repo middleware and form patterns for state-changing requests.
|
|
23
|
+
|
|
24
|
+
## XSS and output
|
|
25
|
+
|
|
26
|
+
- Avoid `dangerouslySetInnerHTML` unless sanitized and unavoidable; prefer text nodes / safe components.
|
|
27
|
+
- Sanitize or encode user-generated HTML/markdown before render.
|
|
28
|
+
- Open redirects: validate redirect targets against an allowlist or same-origin paths.
|
|
29
|
+
|
|
30
|
+
## Data exposure
|
|
31
|
+
|
|
32
|
+
- Do not log tokens, passwords, or full PII in client or server logs.
|
|
33
|
+
- Do not return full privileged records to the client — map to the minimum domain fields the UI needs.
|
|
34
|
+
|
|
35
|
+
## Anti-hallucination
|
|
36
|
+
|
|
37
|
+
| ❌ Avoid | ✅ Prefer |
|
|
38
|
+
|---------|----------|
|
|
39
|
+
| Invented auth helpers not in `package.json` / codebase | Copy patterns from existing auth routes |
|
|
40
|
+
| Putting secrets in `NEXT_PUBLIC_*` | Server-only env + server modules |
|
|
41
|
+
| Auth only in middleware | Server `getUser` / session verify in layout/page/action |
|
|
42
|
+
|
|
43
|
+
## Agent requirement
|
|
44
|
+
|
|
45
|
+
On auth, forms, payments, or env changes — load this rule and `code-review-mr.md`. Route sensitive features through `security-reviewer`.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# General principles
|
|
2
|
+
|
|
3
|
+
- Use **Redux Toolkit**:
|
|
4
|
+
- `createSlice`, `createAsyncThunk`, RTK Query (if used).
|
|
5
|
+
- Store **domain models**, not "raw" DTOs from the API.
|
|
6
|
+
- All data computations and transformations (including computed fields, boolean flags, aggregates, human-readable strings, etc.) must happen **between the API response and writing to store** — in mappers or a separate data-preparation layer. Store holds the prepared domain model.
|
|
7
|
+
- Separate:
|
|
8
|
+
- "server" state (data from API) and
|
|
9
|
+
- local UI state (selection/filters/flags).
|
|
10
|
+
|
|
11
|
+
# Slice structure
|
|
12
|
+
|
|
13
|
+
- Each domain module — its own slice in `app/src/store/slices/**`.
|
|
14
|
+
- A slice exports:
|
|
15
|
+
- default `reducer`;
|
|
16
|
+
- `actions` as named exports;
|
|
17
|
+
- selectors `selectSomething(state: RootState): Type`.
|
|
18
|
+
- State:
|
|
19
|
+
- explicit state type;
|
|
20
|
+
- careful `initialState` initialization.
|
|
21
|
+
|
|
22
|
+
# Async and side effects
|
|
23
|
+
|
|
24
|
+
- Async requests:
|
|
25
|
+
- via `createAsyncThunk` or RTK Query.
|
|
26
|
+
- inside thunks:
|
|
27
|
+
- call API through services imported from `@/api` (**`public-imports.md`**);
|
|
28
|
+
- do not call the HTTP client directly — only through those services.
|
|
29
|
+
- Side effects (logging, analytics, file handling):
|
|
30
|
+
- move to middleware (`app/src/store/middleware/**`) or specialized slices.
|
|
31
|
+
|
|
32
|
+
# Typing
|
|
33
|
+
|
|
34
|
+
- Use `RootState`, `AppDispatch`, and typed hooks `useAppDispatch`, `useAppSelector` (if present).
|
|
35
|
+
- **HTTP and API errors**:
|
|
36
|
+
- do not import types from **third-party HTTP libraries** that are not in current dependencies and existing slices (guide — **`package.json`** and neighboring files);
|
|
37
|
+
- when a service returns the application client's **response wrapper** — use the **matching type from `@/types`** (as in the barrel and similar thunks);
|
|
38
|
+
- on errors after a service call — rely on the **same transport error class/contract** the shared client uses (from `@/types`), and parse body/status **by fields of the current implementation**, not an imagined API;
|
|
39
|
+
- in **`catch`**, prefer **`instanceof`** on the transport error class from `@/types` (if present in code) over bare `as`, when expressible without noise (see `no-type-assertion-as-import-export.md`).
|
|
40
|
+
- For entities:
|
|
41
|
+
- define domain types (including computed fields) in `app/src/types/**`, export through barrel, import in slices from `@/types` as **source of truth** for data shape (`public-imports.md`);
|
|
42
|
+
- avoid duplicating entity descriptions in multiple places.
|
|
43
|
+
- **Domain boundary**: in **state**, store domain models; the client **response wrapper** type is acceptable as a thunk **return type** or interim before mapping — without duplicating DTOs in state fields unnecessarily (aligned with `api-services.md` and `http-client.md`).
|
|
44
|
+
|
|
45
|
+
# Slice testing
|
|
46
|
+
|
|
47
|
+
- For important slices:
|
|
48
|
+
- test reducers (initialization, main state transitions).
|
|
49
|
+
- test selectors (including edge cases).
|
|
50
|
+
- Thunks:
|
|
51
|
+
- cover with tests and API-layer mocks when possible.
|
|
52
|
+
|
|
53
|
+
# Agent requirement
|
|
54
|
+
|
|
55
|
+
When changing/creating a slice:
|
|
56
|
+
- Do not put API logic inside reducers/components.
|
|
57
|
+
- Strictly type state and actions.
|
|
58
|
+
- Use a consistent naming style for actions and selectors, as in existing slices.
|
|
59
|
+
- For HTTP errors and responses, rely on **`http-client.md`** and contracts from `@/types`, not external HTTP library types outside project dependencies.
|
|
60
|
+
## Incorrect
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
export const loadProfile = createAsyncThunk('profile/load', async () => {
|
|
64
|
+
const res = await fetch('/api/profile')
|
|
65
|
+
return res.json() // raw DTO into slice
|
|
66
|
+
})
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Correct
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { profileApi } from '@/api'
|
|
73
|
+
|
|
74
|
+
export const loadProfile = createAsyncThunk('profile/load', async () => {
|
|
75
|
+
// service returns domain model already mapped
|
|
76
|
+
return profileApi.getProfile()
|
|
77
|
+
})
|
|
78
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!-- shared-core: review/technical-retro.md -->
|
|
2
|
+
|
|
3
|
+
# Technical retro — rule alias
|
|
4
|
+
|
|
5
|
+
Full scenario (including the **“Agent work”** block for a slug from team tasks) lives in the slash command:
|
|
6
|
+
|
|
7
|
+
**`commands/technical-retro.md`** → `/technical-retro`
|
|
8
|
+
|
|
9
|
+
When a task has `metrics.json`, use the local aggregation script and state the cohort, sample size, incomplete artifacts, attribution confidence, active attempt duration, and human-gate wait separately. Do not score malformed artifacts or gate wait as agent work.
|
|
10
|
+
|
|
11
|
+
Use this rule only if the command is unavailable. Do not duplicate the command contents in the response — follow the command file and skill `technical-retro`.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<!-- shared-core: testing/testing-principles.md -->
|
|
2
|
+
|
|
3
|
+
# Testing principles
|
|
4
|
+
|
|
5
|
+
Stack-agnostic; concrete paths, runners, and selectors live in the stack adapter (`## Stack notes`).
|
|
6
|
+
|
|
7
|
+
## Behavior vs. implementation
|
|
8
|
+
|
|
9
|
+
- Verify **behavior and business rules**, not implementation or internal details.
|
|
10
|
+
|
|
11
|
+
## File naming
|
|
12
|
+
|
|
13
|
+
- For **new** tests use `*.spec.ts` / `*.spec.tsx`. Do not rename existing `*.test.ts` / `*.test.tsx` without a separate task (legacy).
|
|
14
|
+
|
|
15
|
+
## Runner and matchers
|
|
16
|
+
|
|
17
|
+
- Use the project's runner (Jest or Vitest are common); components — the project's Testing Library integration. Reuse existing matchers — no new micro-framework.
|
|
18
|
+
|
|
19
|
+
## Test title locale
|
|
20
|
+
|
|
21
|
+
- Consumer apps **may use the project locale** (often Russian) — clear business phrases stating what is checked and the expected outcome.
|
|
22
|
+
- When ESLint enforces the locale (e.g. `jest/valid-title`): each sentence must start with a **capital letter** (including after `.`, `!`, `?`); a space after `.` followed by a lowercase letter is forbidden ("capital after period" violation).
|
|
23
|
+
|
|
24
|
+
Good (Russian locale in consumer app):
|
|
25
|
+
|
|
26
|
+
- `it('Возвращает пустой список. Пользователь не авторизован', () => {})` <!-- i18n-keep: E5 --> (Returns empty list. User is not authorized)
|
|
27
|
+
|
|
28
|
+
Bad (no capital after period; or wrong locale for configured ESLint):
|
|
29
|
+
|
|
30
|
+
- `it('Возвращает пустой список. пользователь не авторизован', () => {})` <!-- i18n-keep: E5 -->
|
|
31
|
+
- `it('Returns empty list when user is guest', () => {})` (wrong locale if ESLint enforces Russian)
|
|
32
|
+
|
|
33
|
+
## Isolation and mocks
|
|
34
|
+
|
|
35
|
+
- Mock at the **public-contract boundary**; use the project's accepted HTTP/API/store mock approach. Do not mock what is part of the feature's public contract if that breaks the test's meaning.
|
|
36
|
+
|
|
37
|
+
## Coverage of cross-cutting modules
|
|
38
|
+
|
|
39
|
+
- When changing a **shared cross-cutting module** (e.g. HTTP client body parsing, headers, error / auth handling) — **update or add behavior tests** covering success, error, and edge branches relevant to the module under change.
|
|
40
|
+
|
|
41
|
+
## Data transformation coverage
|
|
42
|
+
|
|
43
|
+
- Data transformation functions with computed fields and branches must have unit tests covering edge cases (boundary values, missing fields, unexpected value combinations).
|
|
44
|
+
|
|
45
|
+
## Reuse fixtures over ad-hoc random data
|
|
46
|
+
|
|
47
|
+
- Prefer shared fixtures / handlers from the project's accepted mocks module; do not duplicate interfaces in tests. Use the API response types (DTO types) and the **target domain types** from the project's public type surface.
|
|
48
|
+
|
|
49
|
+
## E2E: one canonical scenario plan per feature
|
|
50
|
+
|
|
51
|
+
- For each feature keep a **single canonical scenario plan** (distinct from implementation specs; the stack adapter names the file — typically `*.cases.md`).
|
|
52
|
+
|
|
53
|
+
## E2E: scenario ↔ test traceability
|
|
54
|
+
|
|
55
|
+
- Every scenario has a corresponding test. **Do not weaken** assertions to match an outdated implementation — tests must reflect business expectations from the plan. Colocate plan and executable tests in the same directory.
|
|
56
|
+
|
|
57
|
+
## E2E: page objects / shared helpers
|
|
58
|
+
|
|
59
|
+
- Prefer page objects and shared helpers over scattered selectors and per-test setup duplication.
|
|
60
|
+
|
|
61
|
+
## E2E: stable identifiers (PREFIX-XXX)
|
|
62
|
+
|
|
63
|
+
- When scenarios need stable IDs, prefix the title with `PREFIX-XXX`: `PREFIX` = first letters of words in the entity under test (Latin uppercase); `XXX` = sequential number with three digits and leading zeros. Within one `PREFIX`, numbers must form a consistent sequence with no duplicates.
|
|
64
|
+
- Example: `test('OH-001 Отображается список заказов', async ({ page }) => { ... })` <!-- i18n-keep: E5 --> (Order list is displayed)
|
|
65
|
+
|
|
66
|
+
## E2E: selector priority
|
|
67
|
+
|
|
68
|
+
- Prefer role/label selectors for accessibility and forms; fall back to `data-testid` for stable elements. Use a **hierarchical naming convention** on page roots and key interactive elements (stack adapter defines the scheme — typically `{parent}__{element}`).
|
|
69
|
+
|
|
70
|
+
## E2E: keep plans and selectors in sync with UI
|
|
71
|
+
|
|
72
|
+
- When changing UI: update selectors in page objects and cross-check with the scenario plan. When adding/changing tests: read the matching plan and sync scenario titles first.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<!-- shared-core: testing/testing-principles.md -->
|
|
2
|
+
|
|
3
|
+
# Testing principles
|
|
4
|
+
|
|
5
|
+
Stack-agnostic; concrete paths, runners, and selectors live in the stack adapter (`## Stack notes`).
|
|
6
|
+
|
|
7
|
+
## Behavior vs. implementation
|
|
8
|
+
|
|
9
|
+
- Verify **behavior and business rules**, not implementation or internal details.
|
|
10
|
+
|
|
11
|
+
## File naming
|
|
12
|
+
|
|
13
|
+
- For **new** tests use `*.spec.ts` / `*.spec.tsx`. Do not rename existing `*.test.ts` / `*.test.tsx` without a separate task (legacy).
|
|
14
|
+
|
|
15
|
+
## Runner and matchers
|
|
16
|
+
|
|
17
|
+
- Use the project's runner (Jest or Vitest are common); components — the project's Testing Library integration. Reuse existing matchers — no new micro-framework.
|
|
18
|
+
|
|
19
|
+
## Test title locale
|
|
20
|
+
|
|
21
|
+
- Consumer apps **may use the project locale** (often Russian) — clear business phrases stating what is checked and the expected outcome.
|
|
22
|
+
- When ESLint enforces the locale (e.g. `jest/valid-title`): each sentence must start with a **capital letter** (including after `.`, `!`, `?`); a space after `.` followed by a lowercase letter is forbidden ("capital after period" violation).
|
|
23
|
+
|
|
24
|
+
Good (Russian locale in consumer app):
|
|
25
|
+
|
|
26
|
+
- `it('Возвращает пустой список. Пользователь не авторизован', () => {})` <!-- i18n-keep: E5 --> (Returns empty list. User is not authorized)
|
|
27
|
+
|
|
28
|
+
Bad (no capital after period; or wrong locale for configured ESLint):
|
|
29
|
+
|
|
30
|
+
- `it('Возвращает пустой список. пользователь не авторизован', () => {})` <!-- i18n-keep: E5 -->
|
|
31
|
+
- `it('Returns empty list when user is guest', () => {})` (wrong locale if ESLint enforces Russian)
|
|
32
|
+
|
|
33
|
+
## Isolation and mocks
|
|
34
|
+
|
|
35
|
+
- Mock at the **public-contract boundary**; use the project's accepted HTTP/API/store mock approach. Do not mock what is part of the feature's public contract if that breaks the test's meaning.
|
|
36
|
+
|
|
37
|
+
## Coverage of cross-cutting modules
|
|
38
|
+
|
|
39
|
+
- When changing a **shared cross-cutting module** (e.g. HTTP client body parsing, headers, error / auth handling) — **update or add behavior tests** covering success, error, and edge branches relevant to the module under change.
|
|
40
|
+
|
|
41
|
+
## Data transformation coverage
|
|
42
|
+
|
|
43
|
+
- Data transformation functions with computed fields and branches must have unit tests covering edge cases (boundary values, missing fields, unexpected value combinations).
|
|
44
|
+
|
|
45
|
+
## Reuse fixtures over ad-hoc random data
|
|
46
|
+
|
|
47
|
+
- Prefer shared fixtures / handlers from the project's accepted mocks module; do not duplicate interfaces in tests. Use the API response types (DTO types) and the **target domain types** from the project's public type surface.
|
|
48
|
+
|
|
49
|
+
## E2E: one canonical scenario plan per feature
|
|
50
|
+
|
|
51
|
+
- For each feature keep a **single canonical scenario plan** (distinct from implementation specs; the stack adapter names the file — typically `*.cases.md`).
|
|
52
|
+
|
|
53
|
+
## E2E: scenario ↔ test traceability
|
|
54
|
+
|
|
55
|
+
- Every scenario has a corresponding test. **Do not weaken** assertions to match an outdated implementation — tests must reflect business expectations from the plan. Colocate plan and executable tests in the same directory.
|
|
56
|
+
|
|
57
|
+
## E2E: page objects / shared helpers
|
|
58
|
+
|
|
59
|
+
- Prefer page objects and shared helpers over scattered selectors and per-test setup duplication.
|
|
60
|
+
|
|
61
|
+
## E2E: stable identifiers (PREFIX-XXX)
|
|
62
|
+
|
|
63
|
+
- When scenarios need stable IDs, prefix the title with `PREFIX-XXX`: `PREFIX` = first letters of words in the entity under test (Latin uppercase); `XXX` = sequential number with three digits and leading zeros. Within one `PREFIX`, numbers must form a consistent sequence with no duplicates.
|
|
64
|
+
- Example: `test('OH-001 Отображается список заказов', async ({ page }) => { ... })` <!-- i18n-keep: E5 --> (Order list is displayed)
|
|
65
|
+
|
|
66
|
+
## E2E: selector priority
|
|
67
|
+
|
|
68
|
+
- Prefer role/label selectors for accessibility and forms; fall back to `data-testid` for stable elements. Use a **hierarchical naming convention** on page roots and key interactive elements (stack adapter defines the scheme — typically `{parent}__{element}`).
|
|
69
|
+
|
|
70
|
+
## E2E: keep plans and selectors in sync with UI
|
|
71
|
+
|
|
72
|
+
- When changing UI: update selectors in page objects and cross-check with the scenario plan. When adding/changing tests: read the matching plan and sync scenario titles first.
|