@bonesofspring/ai-rules 0.2.20 → 0.2.22
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 +28 -0
- package/README.md +17 -2
- package/bin/cli.js +83 -6
- package/package.json +5 -2
- package/presets/_shared/README.md +2 -1
- package/presets/_shared/assets/docs-specs/INDEX.md +4 -1
- package/presets/_shared/core/agent-team/agent-artifact-contracts.md +15 -0
- package/presets/_shared/core/agent-team/agent-task-metrics.md +1 -1
- package/presets/_shared/core/agent-team/agent-team-orchestrator.md +1 -3
- package/presets/_shared/core/meta/preset-pr-checklist.md +5 -1
- package/presets/_shared/core/meta/preset-token-budget.md +7 -3
- package/presets/_shared/core/meta/preset-twin-sync.md +2 -0
- package/presets/_shared/core/testing/testing-principles.md +70 -0
- package/presets/claude/android-kotlin/agents/README.md +2 -1
- package/presets/claude/android-kotlin/agents/build-verifier.md +2 -0
- package/presets/claude/android-kotlin/agents/code-reviewer.md +2 -0
- package/presets/claude/android-kotlin/agents/debugger.md +1 -0
- package/presets/claude/android-kotlin/agents/feature-developer.md +4 -1
- package/presets/claude/android-kotlin/agents/openspec-author.md +163 -0
- package/presets/claude/android-kotlin/agents/qa-tester.md +2 -0
- package/presets/claude/android-kotlin/agents/task-analyst.md +1 -1
- package/presets/claude/android-kotlin/agents/task-router.md +9 -1
- package/presets/claude/android-kotlin/agents/tech-writer.md +4 -0
- package/presets/claude/android-kotlin/commands/README.md +0 -2
- package/presets/claude/android-kotlin/commands/task-continue.md +1 -1
- package/presets/claude/android-kotlin/commands/task.md +1 -5
- package/presets/claude/android-kotlin/commands/technical-retro.md +2 -2
- package/presets/claude/android-kotlin/hooks/chain-team-phases.sh +105 -13
- package/presets/claude/android-kotlin/rules/README.md +1 -0
- package/presets/claude/android-kotlin/rules/tooling-and-review/agent-team-orchestrator.md +7 -4
- package/presets/claude/android-kotlin/rules/tooling-and-review/ai-local-overlay.md +48 -0
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-pr-checklist.md +5 -1
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-token-budget.md +7 -3
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-twin-sync.md +2 -0
- package/presets/claude/go/README.md +1 -1
- package/presets/claude/go/agents/README.md +3 -2
- package/presets/claude/go/agents/build-verifier.md +4 -0
- package/presets/claude/go/agents/code-reviewer.md +4 -0
- package/presets/claude/go/agents/debugger.md +4 -0
- package/presets/claude/go/agents/feature-developer.md +5 -0
- package/presets/claude/go/agents/openspec-author.md +163 -0
- package/presets/claude/go/agents/qa-tester.md +4 -0
- package/presets/claude/go/agents/task-router.md +9 -1
- package/presets/claude/go/agents/tech-writer.md +4 -0
- package/presets/claude/go/commands/README.md +0 -2
- package/presets/claude/go/commands/task-continue.md +1 -1
- package/presets/claude/go/commands/task.md +1 -4
- package/presets/claude/go/hooks/chain-team-phases.sh +105 -14
- package/presets/claude/go/rules/README.md +1 -0
- package/presets/claude/go/rules/tooling-and-review/agent-team-orchestrator.md +2 -4
- package/presets/claude/go/rules/tooling-and-review/ai-local-overlay.md +48 -0
- package/presets/claude/go/rules/tooling-and-review/preset-pr-checklist.md +5 -1
- package/presets/claude/go/rules/tooling-and-review/preset-token-budget.md +7 -3
- package/presets/claude/go/rules/tooling-and-review/preset-twin-sync.md +2 -0
- package/presets/claude/ios-swift/agents/README.md +3 -2
- package/presets/claude/ios-swift/agents/build-verifier.md +2 -0
- package/presets/claude/ios-swift/agents/code-reviewer.md +2 -0
- package/presets/claude/ios-swift/agents/debugger.md +1 -0
- package/presets/claude/ios-swift/agents/feature-developer.md +4 -1
- package/presets/claude/ios-swift/agents/openspec-author.md +163 -0
- package/presets/claude/ios-swift/agents/qa-tester.md +2 -0
- package/presets/claude/ios-swift/agents/task-analyst.md +1 -1
- package/presets/claude/ios-swift/agents/task-router.md +9 -1
- package/presets/claude/ios-swift/agents/tech-writer.md +4 -0
- package/presets/claude/ios-swift/commands/README.md +0 -2
- package/presets/claude/ios-swift/commands/task-continue.md +1 -1
- package/presets/claude/ios-swift/commands/task.md +1 -5
- package/presets/claude/ios-swift/commands/technical-retro.md +2 -2
- package/presets/claude/ios-swift/hooks/chain-team-phases.sh +105 -13
- package/presets/claude/ios-swift/rules/README.md +1 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/agent-team-orchestrator.md +7 -4
- package/presets/claude/ios-swift/rules/tooling-and-review/ai-local-overlay.md +48 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-pr-checklist.md +5 -1
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-token-budget.md +7 -3
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-twin-sync.md +2 -0
- package/presets/claude/java/CLAUDE.md +1 -1
- package/presets/claude/java/agents/README.md +3 -2
- package/presets/claude/java/agents/build-verifier.md +4 -0
- package/presets/claude/java/agents/code-reviewer.md +4 -0
- package/presets/claude/java/agents/debugger.md +4 -0
- package/presets/claude/java/agents/feature-developer.md +5 -0
- package/presets/claude/java/agents/openspec-author.md +163 -0
- package/presets/claude/java/agents/qa-tester.md +4 -0
- package/presets/claude/java/agents/task-router.md +9 -1
- package/presets/claude/java/agents/tech-writer.md +4 -0
- package/presets/claude/java/commands/README.md +0 -2
- package/presets/claude/java/commands/task-continue.md +1 -1
- package/presets/claude/java/commands/task.md +1 -4
- package/presets/claude/java/hooks/chain-team-phases.sh +105 -14
- package/presets/claude/java/rules/README.md +1 -0
- package/presets/claude/java/rules/tooling-and-review/agent-team-orchestrator.md +2 -4
- package/presets/claude/java/rules/tooling-and-review/ai-local-overlay.md +48 -0
- package/presets/claude/java/rules/tooling-and-review/preset-pr-checklist.md +5 -1
- package/presets/claude/java/rules/tooling-and-review/preset-token-budget.md +7 -3
- package/presets/claude/java/rules/tooling-and-review/preset-twin-sync.md +2 -0
- package/presets/claude/mcp-ts/agents/build-verifier.md +4 -0
- package/presets/claude/mcp-ts/agents/feature-developer.md +5 -0
- package/presets/claude/mcp-ts/agents/task-analyst.md +1 -1
- package/presets/claude/mcp-ts/agents/task-router.md +1 -1
- package/presets/claude/mcp-ts/commands/README.md +0 -2
- package/presets/claude/mcp-ts/commands/task-continue.md +1 -1
- package/presets/claude/mcp-ts/commands/task.md +1 -4
- package/presets/claude/mcp-ts/commands/technical-retro.md +2 -2
- package/presets/claude/mcp-ts/hooks/chain-team-phases.sh +91 -20
- package/presets/claude/mcp-ts/rules/README.md +1 -0
- package/presets/claude/mcp-ts/rules/tooling-and-review/agent-team-orchestrator.md +2 -4
- package/presets/claude/mcp-ts/rules/tooling-and-review/ai-local-overlay.md +48 -0
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-pr-checklist.md +5 -1
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-token-budget.md +7 -3
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-twin-sync.md +2 -0
- package/presets/claude/next/README.md +1 -0
- package/presets/claude/next/agents/README.md +2 -2
- package/presets/claude/next/agents/build-verifier.md +13 -1
- package/presets/claude/next/agents/code-reviewer.md +2 -0
- package/presets/claude/next/agents/debugger.md +4 -0
- package/presets/claude/next/agents/feature-developer.md +4 -1
- package/presets/claude/next/agents/openspec-author.md +163 -0
- package/presets/claude/next/agents/qa-tester.md +4 -0
- package/presets/claude/next/agents/task-analyst.md +1 -1
- package/presets/claude/next/agents/task-router.md +5 -1
- package/presets/claude/next/agents/tech-writer.md +4 -0
- package/presets/claude/next/agents/unit-test-generator.md +1 -1
- package/presets/claude/next/agents/unit-test-planner.md +1 -1
- package/presets/claude/next/commands/README.md +0 -2
- package/presets/claude/next/commands/task-continue.md +1 -1
- package/presets/claude/next/commands/task.md +1 -4
- package/presets/claude/next/hooks/chain-team-phases.sh +105 -13
- package/presets/claude/next/rules/README.md +1 -0
- package/presets/claude/next/rules/api-and-data/http-client.md +1 -1
- package/presets/claude/next/rules/architecture/reference-features.md +1 -1
- package/presets/claude/next/rules/testing/README.md +7 -1
- package/presets/claude/next/rules/testing/tests-e2e-structure.md +86 -48
- package/presets/claude/next/rules/testing/tests-unit.md +78 -51
- package/presets/claude/next/rules/tooling-and-review/agent-team-orchestrator.md +3 -4
- package/presets/claude/next/rules/tooling-and-review/ai-local-overlay.md +48 -0
- package/presets/claude/next/rules/tooling-and-review/preset-pr-checklist.md +5 -1
- package/presets/claude/next/rules/tooling-and-review/preset-token-budget.md +7 -3
- package/presets/claude/next/rules/tooling-and-review/preset-twin-sync.md +2 -0
- package/presets/claude/next/rules/ui-and-accessibility/react-ui.md +1 -1
- package/presets/claude/next/skills/playwright-e2e/SKILL.md +5 -3
- package/presets/claude/next/skills/unit-testing/SKILL.md +6 -4
- package/presets/claude/next/team/README.md +0 -3
- package/presets/claude/nuxt/agents/README.md +1 -1
- package/presets/claude/nuxt/agents/build-verifier.md +2 -0
- package/presets/claude/nuxt/agents/code-reviewer.md +2 -0
- package/presets/claude/nuxt/agents/debugger.md +4 -0
- package/presets/claude/nuxt/agents/feature-developer.md +4 -1
- package/presets/claude/nuxt/agents/openspec-author.md +163 -0
- package/presets/claude/nuxt/agents/qa-tester.md +4 -0
- package/presets/claude/nuxt/agents/task-analyst.md +1 -1
- package/presets/claude/nuxt/agents/task-router.md +5 -1
- package/presets/claude/nuxt/agents/tech-writer.md +4 -0
- package/presets/claude/nuxt/commands/README.md +0 -2
- package/presets/claude/nuxt/commands/task-continue.md +1 -1
- package/presets/claude/nuxt/commands/task.md +1 -5
- package/presets/claude/nuxt/commands/technical-retro.md +2 -2
- package/presets/claude/nuxt/hooks/chain-team-phases.sh +105 -13
- package/presets/claude/nuxt/rules/README.md +1 -0
- package/presets/claude/nuxt/rules/testing/README.md +6 -0
- package/presets/claude/nuxt/rules/testing/tests-e2e-structure.md +86 -43
- package/presets/claude/nuxt/rules/testing/tests-unit.md +58 -45
- package/presets/claude/nuxt/rules/tooling-and-review/agent-team-orchestrator.md +8 -5
- package/presets/claude/nuxt/rules/tooling-and-review/ai-local-overlay.md +48 -0
- package/presets/claude/nuxt/rules/tooling-and-review/preset-pr-checklist.md +5 -1
- package/presets/claude/nuxt/rules/tooling-and-review/preset-token-budget.md +7 -3
- package/presets/claude/nuxt/rules/tooling-and-review/preset-twin-sync.md +2 -0
- package/presets/claude/nuxt/team/README.md +0 -3
- package/presets/claude/php-hexagonal/CLAUDE.md +1 -1
- package/presets/claude/php-hexagonal/agents/README.md +3 -2
- package/presets/claude/php-hexagonal/agents/build-verifier.md +4 -0
- package/presets/claude/php-hexagonal/agents/code-reviewer.md +4 -0
- package/presets/claude/php-hexagonal/agents/debugger.md +4 -0
- package/presets/claude/php-hexagonal/agents/feature-developer.md +5 -0
- package/presets/claude/php-hexagonal/agents/openspec-author.md +163 -0
- package/presets/claude/php-hexagonal/agents/qa-tester.md +4 -0
- package/presets/claude/php-hexagonal/agents/task-router.md +9 -1
- package/presets/claude/php-hexagonal/agents/tech-writer.md +4 -0
- package/presets/claude/php-hexagonal/commands/README.md +0 -2
- package/presets/claude/php-hexagonal/commands/task-continue.md +1 -1
- package/presets/claude/php-hexagonal/commands/task.md +1 -4
- package/presets/claude/php-hexagonal/hooks/chain-team-phases.sh +105 -14
- package/presets/claude/php-hexagonal/rules/README.md +1 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/agent-team-orchestrator.md +2 -4
- package/presets/claude/php-hexagonal/rules/tooling-and-review/ai-local-overlay.md +48 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-pr-checklist.md +5 -1
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-token-budget.md +7 -3
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-twin-sync.md +2 -0
- package/presets/claude/php-laravel/agents/README.md +3 -2
- package/presets/claude/php-laravel/agents/build-verifier.md +4 -0
- package/presets/claude/php-laravel/agents/code-reviewer.md +4 -0
- package/presets/claude/php-laravel/agents/debugger.md +4 -0
- package/presets/claude/php-laravel/agents/feature-developer.md +5 -0
- package/presets/claude/php-laravel/agents/openspec-author.md +163 -0
- package/presets/claude/php-laravel/agents/qa-tester.md +4 -0
- package/presets/claude/php-laravel/agents/task-router.md +6 -1
- package/presets/claude/php-laravel/agents/tech-writer.md +4 -0
- package/presets/claude/php-laravel/commands/README.md +0 -2
- package/presets/claude/php-laravel/commands/task-continue.md +1 -1
- package/presets/claude/php-laravel/commands/task.md +1 -4
- package/presets/claude/php-laravel/hooks/chain-team-phases.sh +105 -14
- package/presets/claude/php-laravel/rules/README.md +1 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/agent-team-orchestrator.md +2 -4
- package/presets/claude/php-laravel/rules/tooling-and-review/ai-local-overlay.md +48 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-pr-checklist.md +5 -1
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-token-budget.md +7 -3
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-twin-sync.md +2 -0
- package/presets/claude/svelte/agents/README.md +1 -1
- package/presets/claude/svelte/agents/build-verifier.md +2 -0
- package/presets/claude/svelte/agents/code-reviewer.md +2 -0
- package/presets/claude/svelte/agents/debugger.md +4 -0
- package/presets/claude/svelte/agents/feature-developer.md +4 -1
- package/presets/claude/svelte/agents/openspec-author.md +163 -0
- package/presets/claude/svelte/agents/qa-tester.md +4 -0
- package/presets/claude/svelte/agents/task-analyst.md +1 -1
- package/presets/claude/svelte/agents/task-router.md +5 -1
- package/presets/claude/svelte/agents/tech-writer.md +4 -0
- package/presets/claude/svelte/commands/README.md +0 -2
- package/presets/claude/svelte/commands/task-continue.md +1 -1
- package/presets/claude/svelte/commands/task.md +1 -5
- package/presets/claude/svelte/commands/technical-retro.md +2 -2
- package/presets/claude/svelte/hooks/chain-team-phases.sh +105 -13
- package/presets/claude/svelte/rules/README.md +1 -0
- package/presets/claude/svelte/rules/testing/README.md +6 -0
- package/presets/claude/svelte/rules/testing/tests-e2e-structure.md +87 -45
- package/presets/claude/svelte/rules/testing/tests-unit.md +70 -23
- package/presets/claude/svelte/rules/tooling-and-review/agent-team-orchestrator.md +8 -5
- package/presets/claude/svelte/rules/tooling-and-review/ai-local-overlay.md +48 -0
- package/presets/claude/svelte/rules/tooling-and-review/preset-pr-checklist.md +5 -1
- package/presets/claude/svelte/rules/tooling-and-review/preset-token-budget.md +7 -3
- package/presets/claude/svelte/rules/tooling-and-review/preset-twin-sync.md +2 -0
- package/presets/claude/svelte/team/README.md +0 -3
- package/presets/cursor/android-kotlin/agents/README.md +2 -1
- package/presets/cursor/android-kotlin/agents/build-verifier.md +2 -0
- package/presets/cursor/android-kotlin/agents/code-reviewer.md +2 -0
- package/presets/cursor/android-kotlin/agents/debugger.md +1 -0
- package/presets/cursor/android-kotlin/agents/feature-developer.md +4 -1
- package/presets/cursor/android-kotlin/agents/openspec-author.md +164 -0
- package/presets/cursor/android-kotlin/agents/qa-tester.md +2 -0
- package/presets/cursor/android-kotlin/agents/task-analyst.md +1 -1
- package/presets/cursor/android-kotlin/agents/task-router.md +9 -1
- package/presets/cursor/android-kotlin/agents/tech-writer.md +4 -0
- package/presets/cursor/android-kotlin/commands/README.md +0 -2
- package/presets/cursor/android-kotlin/commands/task-continue.md +1 -1
- package/presets/cursor/android-kotlin/commands/task.md +1 -5
- package/presets/cursor/android-kotlin/commands/technical-retro.md +2 -2
- package/presets/cursor/android-kotlin/hooks/chain-team-phases.sh +105 -13
- package/presets/cursor/android-kotlin/rules/agent-team-orchestrator.mdc +7 -4
- package/presets/cursor/android-kotlin/rules/ai-local-overlay.mdc +43 -0
- package/presets/cursor/android-kotlin/rules/preset-pr-checklist.mdc +5 -1
- package/presets/cursor/android-kotlin/rules/preset-token-budget.mdc +7 -3
- package/presets/cursor/android-kotlin/rules/preset-twin-sync.mdc +2 -0
- package/presets/cursor/go/README.md +6 -6
- package/presets/cursor/go/agents/README.md +3 -2
- package/presets/cursor/go/agents/build-verifier.md +4 -0
- package/presets/cursor/go/agents/code-reviewer.md +4 -0
- package/presets/cursor/go/agents/debugger.md +4 -0
- package/presets/cursor/go/agents/feature-developer.md +5 -0
- package/presets/cursor/go/agents/openspec-author.md +164 -0
- package/presets/cursor/go/agents/qa-tester.md +4 -0
- package/presets/cursor/go/agents/task-router.md +9 -1
- package/presets/cursor/go/agents/tech-writer.md +4 -0
- package/presets/cursor/go/commands/README.md +0 -2
- package/presets/cursor/go/commands/task-continue.md +1 -1
- package/presets/cursor/go/commands/task.md +1 -4
- package/presets/cursor/go/commands/technical-retro.md +2 -2
- package/presets/cursor/go/hooks/chain-team-phases.sh +105 -14
- package/presets/cursor/go/rules/agent-team-orchestrator.mdc +2 -4
- package/presets/cursor/go/rules/ai-local-overlay.mdc +43 -0
- package/presets/cursor/go/rules/preset-pr-checklist.mdc +5 -1
- package/presets/cursor/go/rules/preset-token-budget.mdc +7 -3
- package/presets/cursor/go/rules/preset-twin-sync.mdc +2 -0
- package/presets/cursor/ios-swift/README.md +6 -6
- package/presets/cursor/ios-swift/agents/README.md +3 -2
- package/presets/cursor/ios-swift/agents/build-verifier.md +2 -0
- package/presets/cursor/ios-swift/agents/code-reviewer.md +2 -0
- package/presets/cursor/ios-swift/agents/debugger.md +1 -0
- package/presets/cursor/ios-swift/agents/feature-developer.md +4 -1
- package/presets/cursor/ios-swift/agents/openspec-author.md +164 -0
- package/presets/cursor/ios-swift/agents/qa-tester.md +2 -0
- package/presets/cursor/ios-swift/agents/task-analyst.md +1 -1
- package/presets/cursor/ios-swift/agents/task-router.md +9 -1
- package/presets/cursor/ios-swift/agents/tech-writer.md +4 -0
- package/presets/cursor/ios-swift/commands/README.md +1 -3
- package/presets/cursor/ios-swift/commands/task-continue.md +1 -1
- package/presets/cursor/ios-swift/commands/task.md +1 -5
- package/presets/cursor/ios-swift/commands/technical-retro.md +2 -2
- package/presets/cursor/ios-swift/hooks/chain-team-phases.sh +105 -13
- package/presets/cursor/ios-swift/rules/agent-team-orchestrator.mdc +7 -4
- package/presets/cursor/ios-swift/rules/ai-local-overlay.mdc +43 -0
- package/presets/cursor/ios-swift/rules/preset-pr-checklist.mdc +5 -1
- package/presets/cursor/ios-swift/rules/preset-token-budget.mdc +7 -3
- package/presets/cursor/ios-swift/rules/preset-twin-sync.mdc +2 -0
- package/presets/cursor/java/AGENTS.md +1 -1
- package/presets/cursor/java/agents/README.md +3 -2
- package/presets/cursor/java/agents/build-verifier.md +4 -0
- package/presets/cursor/java/agents/code-reviewer.md +4 -0
- package/presets/cursor/java/agents/debugger.md +4 -0
- package/presets/cursor/java/agents/feature-developer.md +5 -0
- package/presets/cursor/java/agents/openspec-author.md +164 -0
- package/presets/cursor/java/agents/qa-tester.md +4 -0
- package/presets/cursor/java/agents/task-router.md +9 -1
- package/presets/cursor/java/agents/tech-writer.md +4 -0
- package/presets/cursor/java/commands/README.md +0 -2
- package/presets/cursor/java/commands/task-continue.md +1 -1
- package/presets/cursor/java/commands/task.md +1 -4
- package/presets/cursor/java/commands/technical-retro.md +2 -2
- package/presets/cursor/java/hooks/chain-team-phases.sh +105 -14
- package/presets/cursor/java/rules/agent-team-orchestrator.mdc +2 -4
- package/presets/cursor/java/rules/ai-local-overlay.mdc +43 -0
- package/presets/cursor/java/rules/preset-pr-checklist.mdc +5 -1
- package/presets/cursor/java/rules/preset-token-budget.mdc +7 -3
- package/presets/cursor/java/rules/preset-twin-sync.mdc +2 -0
- package/presets/cursor/mcp-ts/agents/build-verifier.md +4 -0
- package/presets/cursor/mcp-ts/agents/feature-developer.md +5 -0
- package/presets/cursor/mcp-ts/agents/task-analyst.md +1 -1
- package/presets/cursor/mcp-ts/agents/task-router.md +1 -1
- package/presets/cursor/mcp-ts/commands/README.md +0 -2
- package/presets/cursor/mcp-ts/commands/task-continue.md +1 -1
- package/presets/cursor/mcp-ts/commands/task.md +1 -4
- package/presets/cursor/mcp-ts/commands/technical-retro.md +2 -2
- package/presets/cursor/mcp-ts/hooks/chain-team-phases.sh +91 -20
- package/presets/cursor/mcp-ts/rules/agent-team-orchestrator.mdc +2 -4
- package/presets/cursor/mcp-ts/rules/ai-local-overlay.mdc +43 -0
- package/presets/cursor/mcp-ts/rules/preset-pr-checklist.mdc +5 -1
- package/presets/cursor/mcp-ts/rules/preset-token-budget.mdc +7 -3
- package/presets/cursor/mcp-ts/rules/preset-twin-sync.mdc +2 -0
- package/presets/cursor/next/README.md +8 -6
- package/presets/cursor/next/REPO_AGENTS.md +8 -0
- package/presets/cursor/next/agents/README.md +2 -2
- package/presets/cursor/next/agents/build-verifier.md +13 -1
- package/presets/cursor/next/agents/code-reviewer.md +2 -0
- package/presets/cursor/next/agents/debugger.md +4 -0
- package/presets/cursor/next/agents/feature-developer.md +4 -1
- package/presets/cursor/next/agents/openspec-author.md +164 -0
- package/presets/cursor/next/agents/qa-tester.md +4 -0
- package/presets/cursor/next/agents/task-analyst.md +1 -1
- package/presets/cursor/next/agents/task-router.md +5 -1
- package/presets/cursor/next/agents/tech-writer.md +4 -0
- package/presets/cursor/next/agents/unit-test-generator.md +1 -1
- package/presets/cursor/next/agents/unit-test-planner.md +1 -1
- package/presets/cursor/next/commands/README.md +0 -2
- package/presets/cursor/next/commands/task-continue.md +1 -1
- package/presets/cursor/next/commands/task.md +1 -4
- package/presets/cursor/next/commands/technical-retro.md +2 -2
- package/presets/cursor/next/hooks/chain-team-phases.sh +105 -13
- package/presets/cursor/next/rules/README.md +6 -3
- package/presets/cursor/next/rules/agent-team-orchestrator.mdc +7 -5
- package/presets/cursor/next/rules/ai-local-overlay.mdc +43 -0
- package/presets/cursor/next/rules/http-client.mdc +1 -1
- package/presets/cursor/next/rules/preset-pr-checklist.mdc +5 -1
- package/presets/cursor/next/rules/preset-token-budget.mdc +7 -3
- package/presets/cursor/next/rules/preset-twin-sync.mdc +2 -0
- package/presets/cursor/next/rules/react-ui.mdc +1 -1
- package/presets/cursor/next/rules/reference-features.mdc +1 -1
- package/presets/cursor/next/rules/tests-e2e-structure.mdc +85 -43
- package/presets/cursor/next/rules/tests-unit.mdc +79 -48
- package/presets/cursor/next/skills/playwright-e2e/SKILL.md +5 -3
- package/presets/cursor/next/skills/unit-testing/SKILL.md +6 -4
- package/presets/cursor/next/team/README.md +0 -3
- package/presets/cursor/nuxt/README.md +6 -6
- package/presets/cursor/nuxt/agents/README.md +1 -1
- package/presets/cursor/nuxt/agents/build-verifier.md +2 -0
- package/presets/cursor/nuxt/agents/code-reviewer.md +2 -0
- package/presets/cursor/nuxt/agents/debugger.md +4 -0
- package/presets/cursor/nuxt/agents/feature-developer.md +4 -1
- package/presets/cursor/nuxt/agents/openspec-author.md +164 -0
- package/presets/cursor/nuxt/agents/qa-tester.md +4 -0
- package/presets/cursor/nuxt/agents/task-analyst.md +1 -1
- package/presets/cursor/nuxt/agents/task-router.md +5 -1
- package/presets/cursor/nuxt/agents/tech-writer.md +4 -0
- package/presets/cursor/nuxt/commands/README.md +0 -2
- package/presets/cursor/nuxt/commands/task-continue.md +1 -1
- package/presets/cursor/nuxt/commands/task.md +1 -5
- package/presets/cursor/nuxt/commands/technical-retro.md +2 -2
- package/presets/cursor/nuxt/hooks/chain-team-phases.sh +105 -13
- package/presets/cursor/nuxt/rules/README.md +3 -1
- package/presets/cursor/nuxt/rules/agent-team-orchestrator.mdc +8 -5
- package/presets/cursor/nuxt/rules/ai-local-overlay.mdc +43 -0
- package/presets/cursor/nuxt/rules/preset-pr-checklist.mdc +5 -1
- package/presets/cursor/nuxt/rules/preset-token-budget.mdc +7 -3
- package/presets/cursor/nuxt/rules/preset-twin-sync.mdc +2 -0
- package/presets/cursor/nuxt/rules/tests-e2e-structure.mdc +87 -43
- package/presets/cursor/nuxt/rules/tests-unit.mdc +62 -47
- package/presets/cursor/nuxt/team/README.md +0 -3
- package/presets/cursor/php-hexagonal/AGENTS.md +1 -1
- package/presets/cursor/php-hexagonal/agents/README.md +3 -2
- package/presets/cursor/php-hexagonal/agents/build-verifier.md +4 -0
- package/presets/cursor/php-hexagonal/agents/code-reviewer.md +4 -0
- package/presets/cursor/php-hexagonal/agents/debugger.md +4 -0
- package/presets/cursor/php-hexagonal/agents/feature-developer.md +5 -0
- package/presets/cursor/php-hexagonal/agents/openspec-author.md +164 -0
- package/presets/cursor/php-hexagonal/agents/qa-tester.md +4 -0
- package/presets/cursor/php-hexagonal/agents/task-router.md +9 -1
- package/presets/cursor/php-hexagonal/agents/tech-writer.md +4 -0
- package/presets/cursor/php-hexagonal/commands/README.md +0 -2
- package/presets/cursor/php-hexagonal/commands/task-continue.md +1 -1
- package/presets/cursor/php-hexagonal/commands/task.md +1 -4
- package/presets/cursor/php-hexagonal/commands/technical-retro.md +2 -2
- package/presets/cursor/php-hexagonal/hooks/chain-team-phases.sh +105 -14
- package/presets/cursor/php-hexagonal/rules/agent-team-orchestrator.mdc +2 -4
- package/presets/cursor/php-hexagonal/rules/ai-local-overlay.mdc +43 -0
- package/presets/cursor/php-hexagonal/rules/preset-pr-checklist.mdc +5 -1
- package/presets/cursor/php-hexagonal/rules/preset-token-budget.mdc +7 -3
- package/presets/cursor/php-hexagonal/rules/preset-twin-sync.mdc +2 -0
- package/presets/cursor/php-laravel/AGENTS.md +1 -1
- package/presets/cursor/php-laravel/agents/README.md +3 -2
- package/presets/cursor/php-laravel/agents/build-verifier.md +4 -0
- package/presets/cursor/php-laravel/agents/code-reviewer.md +4 -0
- package/presets/cursor/php-laravel/agents/debugger.md +4 -0
- package/presets/cursor/php-laravel/agents/feature-developer.md +5 -0
- package/presets/cursor/php-laravel/agents/openspec-author.md +164 -0
- package/presets/cursor/php-laravel/agents/qa-tester.md +4 -0
- package/presets/cursor/php-laravel/agents/task-router.md +6 -1
- package/presets/cursor/php-laravel/agents/tech-writer.md +4 -0
- package/presets/cursor/php-laravel/commands/README.md +0 -2
- package/presets/cursor/php-laravel/commands/task-continue.md +1 -1
- package/presets/cursor/php-laravel/commands/task.md +1 -4
- package/presets/cursor/php-laravel/commands/technical-retro.md +2 -2
- package/presets/cursor/php-laravel/hooks/chain-team-phases.sh +105 -14
- package/presets/cursor/php-laravel/rules/agent-team-orchestrator.mdc +2 -4
- package/presets/cursor/php-laravel/rules/ai-local-overlay.mdc +43 -0
- package/presets/cursor/php-laravel/rules/preset-pr-checklist.mdc +5 -1
- package/presets/cursor/php-laravel/rules/preset-token-budget.mdc +7 -3
- package/presets/cursor/php-laravel/rules/preset-twin-sync.mdc +2 -0
- package/presets/cursor/svelte/README.md +6 -6
- package/presets/cursor/svelte/agents/README.md +1 -1
- package/presets/cursor/svelte/agents/build-verifier.md +2 -0
- package/presets/cursor/svelte/agents/code-reviewer.md +2 -0
- package/presets/cursor/svelte/agents/debugger.md +4 -0
- package/presets/cursor/svelte/agents/feature-developer.md +4 -1
- package/presets/cursor/svelte/agents/openspec-author.md +164 -0
- package/presets/cursor/svelte/agents/qa-tester.md +4 -0
- package/presets/cursor/svelte/agents/task-analyst.md +1 -1
- package/presets/cursor/svelte/agents/task-router.md +5 -1
- package/presets/cursor/svelte/agents/tech-writer.md +4 -0
- package/presets/cursor/svelte/commands/README.md +0 -2
- package/presets/cursor/svelte/commands/task-continue.md +1 -1
- package/presets/cursor/svelte/commands/task.md +1 -5
- package/presets/cursor/svelte/commands/technical-retro.md +2 -2
- package/presets/cursor/svelte/hooks/chain-team-phases.sh +105 -13
- package/presets/cursor/svelte/rules/README.md +3 -1
- package/presets/cursor/svelte/rules/agent-team-orchestrator.mdc +8 -5
- package/presets/cursor/svelte/rules/ai-local-overlay.mdc +43 -0
- package/presets/cursor/svelte/rules/preset-pr-checklist.mdc +5 -1
- package/presets/cursor/svelte/rules/preset-token-budget.mdc +7 -3
- package/presets/cursor/svelte/rules/preset-twin-sync.mdc +2 -0
- package/presets/cursor/svelte/rules/tests-e2e-structure.mdc +87 -43
- package/presets/cursor/svelte/rules/tests-unit.mdc +72 -23
- package/presets/cursor/svelte/team/README.md +0 -3
- package/scripts/_lib/embed-stems.json +31 -0
- package/scripts/aggregate-agent-task-metrics.mjs +23 -0
- package/scripts/check-chain-hook-coverage.sh +109 -0
- package/scripts/check-local-overlay.sh +136 -0
- package/scripts/check-preset-i18n.sh +2 -2
- package/scripts/check-preset-leakage.sh +4 -1
- package/scripts/check-preset-structure.sh +31 -1
- package/scripts/check-preset-token-budget.sh +120 -10
- package/scripts/check-rule-eval.mjs +16 -0
- package/scripts/check-shared-core-drift.sh +10 -32
- package/scripts/check-task-router-intents.sh +141 -0
- package/scripts/close-agent-task-human-gate.mjs +22 -5
- package/scripts/sync-shared-core-embeds.sh +9 -20
- package/scripts/test-agent-task-metrics-hooks.mjs +100 -2
- package/scripts/test-chain-team-phases-coverage.mjs +510 -0
- package/scripts/test-task-router-intents-fixtures.mjs +109 -0
- package/presets/claude/android-kotlin/commands/feature-continue.md +0 -23
- package/presets/claude/android-kotlin/commands/feature-start.md +0 -41
- package/presets/claude/go/commands/feature-continue.md +0 -23
- package/presets/claude/go/commands/feature-start.md +0 -38
- package/presets/claude/ios-swift/commands/feature-continue.md +0 -23
- package/presets/claude/ios-swift/commands/feature-start.md +0 -41
- package/presets/claude/java/commands/feature-continue.md +0 -23
- package/presets/claude/java/commands/feature-start.md +0 -38
- package/presets/claude/mcp-ts/commands/feature-continue.md +0 -23
- package/presets/claude/mcp-ts/commands/feature-start.md +0 -41
- package/presets/claude/next/commands/feature-continue.md +0 -23
- package/presets/claude/next/commands/feature-start.md +0 -38
- package/presets/claude/nuxt/commands/feature-continue.md +0 -23
- package/presets/claude/nuxt/commands/feature-start.md +0 -41
- package/presets/claude/php-hexagonal/commands/feature-continue.md +0 -23
- package/presets/claude/php-hexagonal/commands/feature-start.md +0 -38
- package/presets/claude/php-laravel/commands/feature-continue.md +0 -23
- package/presets/claude/php-laravel/commands/feature-start.md +0 -38
- package/presets/claude/svelte/commands/feature-continue.md +0 -23
- package/presets/claude/svelte/commands/feature-start.md +0 -41
- package/presets/cursor/android-kotlin/commands/feature-continue.md +0 -23
- package/presets/cursor/android-kotlin/commands/feature-start.md +0 -41
- package/presets/cursor/go/commands/feature-continue.md +0 -23
- package/presets/cursor/go/commands/feature-start.md +0 -41
- package/presets/cursor/ios-swift/commands/feature-continue.md +0 -23
- package/presets/cursor/ios-swift/commands/feature-start.md +0 -41
- package/presets/cursor/java/commands/feature-continue.md +0 -23
- package/presets/cursor/java/commands/feature-start.md +0 -41
- package/presets/cursor/mcp-ts/commands/feature-continue.md +0 -23
- package/presets/cursor/mcp-ts/commands/feature-start.md +0 -41
- package/presets/cursor/next/commands/feature-continue.md +0 -23
- package/presets/cursor/next/commands/feature-start.md +0 -41
- package/presets/cursor/nuxt/commands/feature-continue.md +0 -23
- package/presets/cursor/nuxt/commands/feature-start.md +0 -41
- package/presets/cursor/php-hexagonal/commands/feature-continue.md +0 -23
- package/presets/cursor/php-hexagonal/commands/feature-start.md +0 -41
- package/presets/cursor/php-laravel/commands/feature-continue.md +0 -23
- package/presets/cursor/php-laravel/commands/feature-start.md +0 -41
- package/presets/cursor/svelte/commands/feature-continue.md +0 -23
- package/presets/cursor/svelte/commands/feature-start.md +0 -41
|
@@ -53,3 +53,7 @@ Provide summary:
|
|
|
53
53
|
## Design guidance
|
|
54
54
|
|
|
55
55
|
- Load `design-guidance` (rule stem) when assessing structure, smells, or pattern fit.
|
|
56
|
+
|
|
57
|
+
## Receipt binding
|
|
58
|
+
|
|
59
|
+
> **Receipt binding.** When writing the terminal receipt to `artifact-manifest.json`, set `entry.receipt.attemptId = <attemptId supplied by the orchestrator>` (the orchestrator provides this via `attemptId` on invocation). The hook at `chain-team-phases.sh:readBoundReceiptOutcome` rejects entries whose `attemptId` does not match the current attempt, or whose `Date.parse(timestamps.completedAt) < Date.parse(attemptStartedAt)`. A missing or stale attemptId causes `awaiting_artifact_receipt` stalls. <!-- shared-core: receipt-binding -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: task-analyst
|
|
3
|
-
description: Task analysis specialist. Clarifies requirements, validates acceptance criteria, and decomposes work into concrete tasks. Use for
|
|
3
|
+
description: Task analysis specialist. Clarifies requirements, validates acceptance criteria, and decomposes work into concrete tasks. Use for task intake, or when the user asks to analyze or decompose a feature before coding. Writes only team artifacts; never writes production code.
|
|
4
4
|
readonly: false
|
|
5
5
|
model: fast
|
|
6
6
|
---
|
|
@@ -30,6 +30,7 @@ You are a task router for a Nuxt 3 frontend agent team. You **do not** implement
|
|
|
30
30
|
| `unit-only` | «unit», «юнит» (unit), «mapper tests», «покрой маппер» (cover mapper), «почини unit» (fix unit) | unit-test-planner → unit-test-generator, or unit-test-healer | <!-- i18n-keep: E4 -->
|
|
31
31
|
| `e2e-only` | «e2e», «playwright», «browser test», «сценарии e2e» (e2e scenarios), «почини e2e» (fix e2e) | playwright-test-planner → playwright-test-generator, or playwright-test-healer | <!-- i18n-keep: E4 -->
|
|
32
32
|
| `docs-only` | «документация» (documentation), «README», «changelog», «ADR», «migration guide» | task-analyst → tech-writer | <!-- i18n-keep: E4 -->
|
|
33
|
+
| `openspec-change` | `/opsx:propose`, `/opsx:apply`, `/opsx:archive`, `openspec/changes`, `openspec/specs`, `openspec/config.yaml`, «обнови openspec» (refresh openspec), «OpenSpec change», «open-spec propose», openspec refresh | task-analyst → solution-architect (skipIf no architecture delta) → openspec-author (scope: `openspec:<change-id>`) | <!-- i18n-keep: E4 -->
|
|
33
34
|
| `refactor` | «рефакторинг» (refactoring), «без изменения поведения» (no behavior change), «почисти» (clean up) | task-analyst → feature-developer → build-verifier → code-reviewer | <!-- i18n-keep: E4 -->
|
|
34
35
|
| `spike` | «исследуй» (investigate), «оцени» (estimate), «можно ли» (is it possible), «spike», proof of concept | task-analyst → solution-architect | <!-- i18n-keep: E4 -->
|
|
35
36
|
| `retro` | «ретро» (retro), «разбор» (postmortem), «postmortem» | (no pipeline — orchestrator runs `/technical-retro`) | <!-- i18n-keep: E4 -->
|
|
@@ -131,6 +132,7 @@ Cursor mapping when orchestrator invokes Task: `cheap` → pass `model: "fast"`
|
|
|
131
132
|
| `spec-gen` | `["after:task-analyst"]` |
|
|
132
133
|
| `migration` | `["after:migration-specialist"]` |
|
|
133
134
|
| `docs-only` | `["after:task-analyst"]` |
|
|
135
|
+
| `openspec-change` | `["after:task-analyst"]` (human approves brief + AC; openspec-author emits drafts and validator receipts under the assigned change-id) |
|
|
134
136
|
| `unit-only` | `["after:unit-test-planner"]` when new plan; `[]` for healer |
|
|
135
137
|
| `e2e-only` | `["after:playwright-test-planner"]` when new plan; `[]` for healer |
|
|
136
138
|
| `bugfix`, `review-only`, `ci-fix` | `[]` |
|
|
@@ -162,7 +164,9 @@ Detect and set routing reasons when the user asks to **generate / bootstrap prod
|
|
|
162
164
|
| `/spec-start`, "bootstrap docs/specs", "generate product spec" | `spec-gen` | task-analyst (**author mode**) → human gate → stop (or continue to feature-developer only if implement-after) |
|
|
163
165
|
| Feature/task with AC "generate specs" / missing INDEX + bootstrap AC | `spec-gen` inside feature profile | task-analyst author mode first; **not** a separate agent step |
|
|
164
166
|
|
|
165
|
-
Do **not** add a dedicated `spec-author` agent
|
|
167
|
+
Do **not** add a dedicated `spec-author` agent for `docs/specs/**`. Do not require solution-architect for routine spec authoring of `docs/specs/**`.
|
|
168
|
+
|
|
169
|
+
**openspec is a different file tree** (`openspec/changes/`, `openspec/specs/`) — it is not `docs/specs/`. The dedicated agent `openspec-author` lives in `agents/openspec-author.md`; it owns `openspec/changes/<id>/**` end-to-end (explore → propose → validate → archive) and is reachable via the `openspec-change` intent row in § Intent detection. Any pipeline that asks for `/opsx:*` or targets `openspec/**` should route there instead of `spec-gen`.
|
|
166
170
|
|
|
167
171
|
|
|
168
172
|
**specMode (optional `pipeline.json` field):** `none` for spike/research; `generate` for `spec-gen` / `/spec-start`; `consume` default when INDEX exists. Echo top-level `specMode`. Brief `## Spec mode` wins on conflict.
|
|
@@ -43,6 +43,10 @@ Conventional commit / release note snippet.
|
|
|
43
43
|
- Do not duplicate entire decomposition — summarize outcomes and how to use/extend.
|
|
44
44
|
- May create or update files under `docs/**` when the task explicitly requests it; otherwise keep primary output in team artifacts.
|
|
45
45
|
|
|
46
|
+
## OpenSpec (`openspec/changes/**`, `openspec/specs/**`)
|
|
47
|
+
|
|
48
|
+
The `openspec/**` file tree is owned by the dedicated agent **`openspec-author`**, not by this agent. When a handoff brief or pipeline step mentions `/opsx:propose`, `/opsx:apply`, `/opsx:archive`, `openspec/changes/`, or `openspec/specs/`, hand off to `openspec-author` instead of authoring here. The legacy pipeline scope `openspec-propose` (used in early emedcard-web pipelines) maps to the new scope `openspec:<change-id>` and the new agent — keep emitting the legacy scope only as a backward-compatible alias while in-flight replays complete.
|
|
49
|
+
|
|
46
50
|
## Product specs (docs/specs)
|
|
47
51
|
|
|
48
52
|
Post-delivery: when behavior or public docs changed and `docs/specs/` is in play, load **`product-specs`** (+ **`product-specs-authoring`** if updating specs). Sync page/feature specs + INDEX in the **same change set**. **Never invent** product behavior without AC/code source; label inferred lines `status: draft`. Soft-fail on miss; no-op if INDEX absent and sync not requested.
|
|
@@ -8,8 +8,6 @@ Slash commands are copied to `.cursor/commands/` on `ai-rules init cursor --pres
|
|
|
8
8
|
|---------|---------|
|
|
9
9
|
| **`/task <description>`** | **Main entry:** router → pipeline.json → roles in order |
|
|
10
10
|
| `/task-continue <slug>` | After a human gate or pause |
|
|
11
|
-
| `/feature-start <description>` | Legacy: analyst only (no router) |
|
|
12
|
-
| `/feature-continue <slug>` | Alias of task-continue |
|
|
13
11
|
| `/technical-retro [slug]` | Retro; with slug — “Agent work” block |
|
|
14
12
|
|
|
15
13
|
## `/task` examples
|
|
@@ -5,7 +5,7 @@ description: Continue an agent-team task after a human gate, pause, or review ch
|
|
|
5
5
|
|
|
6
6
|
# Task continue — after a human gate or pause
|
|
7
7
|
|
|
8
|
-
Continue the pipeline from `pipeline.json`.
|
|
8
|
+
Continue the pipeline from `pipeline.json`.
|
|
9
9
|
|
|
10
10
|
## Arguments
|
|
11
11
|
|
|
@@ -36,7 +36,7 @@ Examples:
|
|
|
36
36
|
- **do not** write `status.json` / `metrics.json` lifecycle fields yourself — the orchestration runtime/hook owns them (see **agent-artifact-contracts**). If `status.json` is missing, only a minimal bootstrap is allowed (`slug`, `intent`, `pipelineIndex: 0`, `currentAgent: steps[0]`, `state: in_progress`) — **do not** increment `pipelineIndex` by hand;
|
|
37
37
|
- invoke the subagent for `pipeline.steps[0].agent` (slug, artifact paths, scope).
|
|
38
38
|
6. **After each agent** — wait for hook handoff / reconciliation terminal receipt → `status.state`; do not start the next step until `status.json` reflects the handoff (or until there is a hook `followup_message`).
|
|
39
|
-
7. **Human gate** — if after the current step there is a gate in `humanGates` (`after:<agent>`), after the agent finishes **stop** and ask for `/task-continue <slug
|
|
39
|
+
7. **Human gate** — if after the current step there is a gate in `humanGates` (`after:<agent>`), after the agent finishes **stop** and ask for `/task-continue <slug>`.
|
|
40
40
|
|
|
41
41
|
## Do not
|
|
42
42
|
|
|
@@ -49,10 +49,6 @@ Examples:
|
|
|
49
49
|
- `awaitingHumanGate` / `state: awaiting_approval` → suggest reviewing artifacts or `/task-continue <slug>`.
|
|
50
50
|
- `in_progress` → ask: continue or a new slug.
|
|
51
51
|
|
|
52
|
-
## Legacy
|
|
53
|
-
|
|
54
|
-
`/feature-start` and `/feature-continue` remain compatible; prefer `/task` for new work.
|
|
55
|
-
|
|
56
52
|
## Metrics
|
|
57
53
|
|
|
58
54
|
Runtime/hook owns `metrics.json` and `status.json` attempt ledgers. Before the first invocation ensure `task_started` and one `activeAttempts[attemptId]` + `attempt_started` exist (router/runtime bootstrap — parent must not invent parallel indices). On `/task-continue`, run the installed chain hook `end_human_gate` action (or wrapper) so `human_gate_ended` lands before the next attempt. Do not calculate durations in agents.
|
|
@@ -10,7 +10,7 @@ The agent acts as a **neutral facilitator of a technical retrospective**, not as
|
|
|
10
10
|
## When to use
|
|
11
11
|
|
|
12
12
|
- The user asks for: “retro”, “technical retro”, “sprint/iteration review”, “action items after release”.
|
|
13
|
-
- After an agent-team pipeline finishes
|
|
13
|
+
- After an agent-team pipeline finishes.
|
|
14
14
|
- Context exists: period, topic (release, incident), task slug, notes.
|
|
15
15
|
|
|
16
16
|
## Inputs (gather, do not invent)
|
|
@@ -53,7 +53,7 @@ Do not invent facts that are not in artifacts, the diff, or the user message.
|
|
|
53
53
|
|
|
54
54
|
## “Agent work” block (required when there is a slug)
|
|
55
55
|
|
|
56
|
-
If the retro is tied to
|
|
56
|
+
If the retro is tied to an agent-team pipeline:
|
|
57
57
|
|
|
58
58
|
| Question | What to record |
|
|
59
59
|
|----------|----------------|
|
|
@@ -64,10 +64,20 @@ const STACK = 'nuxt';
|
|
|
64
64
|
const PLATFORM = 'cursor';
|
|
65
65
|
|
|
66
66
|
function waitForMetricsLock() {
|
|
67
|
+
// OD-1: real advisory lock via create-exclusive (fs.openSync(_, 'wx')).
|
|
68
|
+
// The previous impl spun on Atomics.wait against an unrelated SharedArrayBuffer
|
|
69
|
+
// and never blocked on the lock file, so two concurrent subagentStop events
|
|
70
|
+
// could both acquire the lock and corrupt metrics.json. Retry EEXIST with a
|
|
71
|
+
// 10 ms sleep up to 200 attempts (2 s ceiling). On any other error, throw.
|
|
67
72
|
for (let attempt = 0; attempt < 200; attempt += 1) {
|
|
68
|
-
try {
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
try {
|
|
74
|
+
const fd = fs.openSync(METRICS_LOCK, 'wx');
|
|
75
|
+
try { fs.closeSync(fd); } catch {}
|
|
76
|
+
return;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
if (!error || error.code !== 'EEXIST') throw error;
|
|
79
|
+
const until = Date.now() + 10;
|
|
80
|
+
while (Date.now() < until) { /* 10 ms busy-wait */ }
|
|
71
81
|
}
|
|
72
82
|
}
|
|
73
83
|
throw new Error('metrics lock timeout');
|
|
@@ -76,7 +86,7 @@ let taskLockHeld = false;
|
|
|
76
86
|
function releaseTaskLock() {
|
|
77
87
|
if (!taskLockHeld) return;
|
|
78
88
|
taskLockHeld = false;
|
|
79
|
-
try { fs.
|
|
89
|
+
try { fs.unlinkSync(METRICS_LOCK); } catch {}
|
|
80
90
|
}
|
|
81
91
|
waitForMetricsLock();
|
|
82
92
|
taskLockHeld = true;
|
|
@@ -104,7 +114,7 @@ function mutateMetrics(mutator) {
|
|
|
104
114
|
fs.writeFileSync(temporary, JSON.stringify(metrics, null, 2) + '\n');
|
|
105
115
|
fs.renameSync(temporary, METRICS_PATH);
|
|
106
116
|
} finally {
|
|
107
|
-
if (acquiredHere) { try { fs.
|
|
117
|
+
if (acquiredHere) { try { fs.unlinkSync(METRICS_LOCK); } catch {} }
|
|
108
118
|
}
|
|
109
119
|
}
|
|
110
120
|
function appendMetric(event) { mutateMetrics((metrics) => metrics.events.push({ eventId: `${metrics.task.runId}:${Date.now()}:${Math.random().toString(16).slice(2)}`, ...event })); }
|
|
@@ -138,6 +148,14 @@ const DEFAULT_ARTIFACT_OUTPUT_IDS = {
|
|
|
138
148
|
'mockup-reviewer': 'mockup-review',
|
|
139
149
|
'api-contract-reviewer': 'api-contract-review',
|
|
140
150
|
'tech-writer': 'documentation',
|
|
151
|
+
'openspec-author': 'openspec-change',
|
|
152
|
+
'qa-tester': 'qa',
|
|
153
|
+
'unit-test-planner': 'unit-test-plan',
|
|
154
|
+
'unit-test-generator': 'unit-test-spec',
|
|
155
|
+
'unit-test-healer': 'unit-test-heal',
|
|
156
|
+
'playwright-test-planner': 'e2e-plan',
|
|
157
|
+
'playwright-test-generator': 'e2e-spec',
|
|
158
|
+
'playwright-test-healer': 'e2e-heal',
|
|
141
159
|
};
|
|
142
160
|
function artifactOutputIdFor(step, agent) {
|
|
143
161
|
if (step && typeof step.artifactOutputId === 'string') return step.artifactOutputId;
|
|
@@ -244,7 +262,17 @@ function recordSkippedStep(step, stepIndex) {
|
|
|
244
262
|
function writeStatus(next) {
|
|
245
263
|
status = { ...status, ...next, slug, updatedAt: now };
|
|
246
264
|
const temporary = `${statusPath}.${process.pid}.${Date.now()}.tmp`;
|
|
247
|
-
|
|
265
|
+
// Open + write + fsync + rename so the durable file lands on disk before
|
|
266
|
+
// the orchestrator reads it. Closes the race window where a subagent that
|
|
267
|
+
// completed milliseconds before writeStatus() could otherwise invoke the
|
|
268
|
+
// next step on a stale status (in particular the human-gate write).
|
|
269
|
+
const fd = fs.openSync(temporary, 'w');
|
|
270
|
+
try {
|
|
271
|
+
fs.writeSync(fd, JSON.stringify(status, null, 2) + '\n');
|
|
272
|
+
try { fs.fsyncSync(fd); } catch {}
|
|
273
|
+
} finally {
|
|
274
|
+
fs.closeSync(fd);
|
|
275
|
+
}
|
|
248
276
|
fs.renameSync(temporary, statusPath);
|
|
249
277
|
}
|
|
250
278
|
|
|
@@ -341,6 +369,12 @@ const AGENT_HANDOFF = {
|
|
|
341
369
|
`Use playwright MCP when available. Follow playwright-agents.mdc and debug-investigation. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
342
370
|
'tech-writer': (s) =>
|
|
343
371
|
`Invoke tech-writer for slug "${s}". Write documentation.md from task artifacts. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
372
|
+
'openspec-author': (s, scope) =>
|
|
373
|
+
`Invoke openspec-author for slug "${s}"${scope ? ` (scope: ${scope})` : ''}. ` +
|
|
374
|
+
`Read openspec/config.yaml schema + rules; if openspec/** is absent, emit blocked ("openspec/** not initialized"). ` +
|
|
375
|
+
`Author openspec/changes/<change-id>/{proposal.md, design.md, tasks.md, .openspec.yaml} and the capability spec delta per phase (explore|propose|apply|archive). ` +
|
|
376
|
+
`Run \`openspec validate <change-id> --type change --strict\` and \`openspec validate --specs --strict\` (Phase 3); surface FAIL output verbatim. ` +
|
|
377
|
+
`Upsert the owned terminal receipt (artifactOutputId \`openspec-change\`) in artifact-manifest.json with validator exit code + evidence paths; do not mutate status.json lifecycle fields. `,
|
|
344
378
|
};
|
|
345
379
|
|
|
346
380
|
const REVIEW_AGENTS = new Set([
|
|
@@ -461,7 +495,19 @@ function legacyFlow() {
|
|
|
461
495
|
|
|
462
496
|
|
|
463
497
|
if (hookInput.action === 'end_human_gate') {
|
|
464
|
-
|
|
498
|
+
status.awaitingHumanGate = false;
|
|
499
|
+
// A2 (retro §8): pin a single runId per pipeline so subsequent events don't
|
|
500
|
+
// fragment the metrics ledger across multiple runId sequences. Prefer
|
|
501
|
+
// metrics.json.task.runId when metrics already exist, then status.metricsRunId,
|
|
502
|
+
// then mint a fresh seed only on first ever emit.
|
|
503
|
+
try {
|
|
504
|
+
if (fs.existsSync(METRICS_PATH)) {
|
|
505
|
+
const existing = JSON.parse(fs.readFileSync(METRICS_PATH, 'utf8'));
|
|
506
|
+
if (existing && existing.task && typeof existing.task.runId === 'string') {
|
|
507
|
+
status.metricsRunId = existing.task.runId;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
} catch {}
|
|
465
511
|
if (status.state === 'awaiting_approval') {
|
|
466
512
|
status.state = 'in_progress';
|
|
467
513
|
status.phase = status.phase === 'human_gate' ? 'executing' : status.phase;
|
|
@@ -500,11 +546,29 @@ if (hookInput.action === 'end_human_gate') {
|
|
|
500
546
|
}
|
|
501
547
|
}
|
|
502
548
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
549
|
+
// A2 (retro §8): if gate closes the final human gate of the pipeline
|
|
550
|
+
// (no resume happens, or current step's gate was the last), surface
|
|
551
|
+
// state="awaiting_approval" so a subsequent /task-continue doesn't misinterpret
|
|
552
|
+
// the post-gate idle state as "still in progress".
|
|
553
|
+
{
|
|
554
|
+
let gateWasTerminal = false;
|
|
555
|
+
if (!hookInput.activateNext && fs.existsSync(pipelinePath)) {
|
|
556
|
+
try {
|
|
557
|
+
const pipe = JSON.parse(fs.readFileSync(pipelinePath, 'utf8'));
|
|
558
|
+
const steps = pipe.steps || [];
|
|
559
|
+
const idx = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
560
|
+
const cur = steps[idx];
|
|
561
|
+
const gates = Array.isArray(pipe.humanGates) ? pipe.humanGates : [];
|
|
562
|
+
const hasGate = (step) => Array.isArray(gates) && gates.some((g) => typeof g === 'string' && getStepAgents(step).some((a) => g === `after:${a}`));
|
|
563
|
+
if (cur && hasGate(cur)) gateWasTerminal = true;
|
|
564
|
+
} catch {}
|
|
565
|
+
}
|
|
566
|
+
writeStatus({
|
|
567
|
+
awaitingHumanGate: false,
|
|
568
|
+
state: gateWasTerminal ? 'awaiting_approval' : status.state,
|
|
569
|
+
phase: status.phase,
|
|
570
|
+
});
|
|
571
|
+
}
|
|
508
572
|
process.stdout.write(JSON.stringify({ ok: true, action: 'end_human_gate', activeHumanGateEventId: status.activeHumanGateEventId || null }));
|
|
509
573
|
process.exit(0);
|
|
510
574
|
}
|
|
@@ -514,9 +578,37 @@ if (!fs.existsSync(pipelinePath)) {
|
|
|
514
578
|
}
|
|
515
579
|
|
|
516
580
|
let pipeline;
|
|
581
|
+
let pipelineParseError = null;
|
|
517
582
|
try {
|
|
518
583
|
pipeline = JSON.parse(fs.readFileSync(pipelinePath, 'utf8'));
|
|
519
|
-
} catch {
|
|
584
|
+
} catch (error) {
|
|
585
|
+
pipelineParseError = error;
|
|
586
|
+
}
|
|
587
|
+
// Modern pipelines carry an `intent` field. If pipeline.json is present but
|
|
588
|
+
// unparseable, surface the error so the orchestrator can stop and report
|
|
589
|
+
// instead of falling back to legacyFlow() — which silently drops modern
|
|
590
|
+
// roles like `openspec-author`, `qa-tester`, and the test-planner trio.
|
|
591
|
+
if (pipelineParseError) {
|
|
592
|
+
if (fs.existsSync(pipelinePath)) {
|
|
593
|
+
const raw = fs.readFileSync(pipelinePath, 'utf8');
|
|
594
|
+
const hasModernIntent = /"intent"\s*:/.test(raw);
|
|
595
|
+
appendMetric({
|
|
596
|
+
eventId: `${status.metricsRunId || slug}:pipeline_parse_error:${Date.now()}`,
|
|
597
|
+
type: 'pipeline_parse_error',
|
|
598
|
+
at: now,
|
|
599
|
+
source: 'hook',
|
|
600
|
+
attributionConfidence: 'high',
|
|
601
|
+
error: String(pipelineParseError.message || pipelineParseError),
|
|
602
|
+
hasModernIntent,
|
|
603
|
+
});
|
|
604
|
+
if (hasModernIntent) {
|
|
605
|
+
writeStatus({ state: 'blocked', phase: 'blocked', currentAgent: 'task-router' });
|
|
606
|
+
process.stdout.write(JSON.stringify({
|
|
607
|
+
followup_message: `pipeline.json is malformed for slug "${slug}" — JSON parse error: ${pipelineParseError.message}. Re-run the task-router to regenerate pipeline.json, then resume via /task-continue ${slug}.`,
|
|
608
|
+
}));
|
|
609
|
+
process.exit(0);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
520
612
|
legacyFlow();
|
|
521
613
|
}
|
|
522
614
|
|
|
@@ -14,7 +14,7 @@ Special Cursor Rule format:
|
|
|
14
14
|
### Starting a new task
|
|
15
15
|
|
|
16
16
|
- **Agent team (recommended):** `/task <description>` — the router picks roles and order; after a human gate — `/task-continue <slug>`. See **`agent-team-orchestrator.mdc`** and `.cursor/team/README.md`.
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
- **End-to-end layer checklist (for developer):** **`feature-delivery-workflow.mdc`**.
|
|
19
19
|
|
|
20
20
|
### Loading strategy
|
|
@@ -46,6 +46,8 @@ SoT prose: `packages/ai-rules/presets/_shared/core/**` (see `_shared/README.md`)
|
|
|
46
46
|
| `review/mockup-review.md` | `mockup-review.mdc` | Stack notes breakpoints; requestable |
|
|
47
47
|
| `review/ux-design.md` | `ux-design.mdc` | Stack notes form-factor; requestable |
|
|
48
48
|
| `meta/preset-*.md` | `preset-*.mdc` | author-only globs |
|
|
49
|
+
| `testing/testing-principles.md` | `tests-unit.mdc` | Stack notes: `@vue/test-utils`, `userEvent`, `lib/clients/**`, `mocks/**`, sibling `*.spec.ts`, `@/types`, `eslint.config.mjs` `jest/valid-title` |
|
|
50
|
+
| `testing/testing-principles.md` | `tests-e2e-structure.mdc` | Stack notes: Playwright, `tests/e2e/**`, `*.cases.md`, `_shared`, `{parent}__{element}` data-testid, `PREFIX-XXX`, Russian-locale MUST |
|
|
49
51
|
|
|
50
52
|
Claude twins + Cursor→Claude map: `presets/claude/nuxt/rules/README.md`.
|
|
51
53
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Orchestrates the agent team via task-router and pipeline.json. Use for /task, /task-continue,
|
|
2
|
+
description: Orchestrates the agent team via task-router and pipeline.json. Use for /task, /task-continue, task decomposition, or when the user describes a feature, bug, or review request.
|
|
3
3
|
alwaysApply: false
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -17,8 +17,6 @@ Work request without `/task` — see **`agent-team-intake.mdc`** (when to sugges
|
|
|
17
17
|
|---------|------|
|
|
18
18
|
| **`/task <desc>`** | **Preferred** — router → dynamic pipeline → first agent |
|
|
19
19
|
| `/task-continue <slug>` | After human gate or pause |
|
|
20
|
-
| `/feature-start <desc>` | Legacy: analyst-only start (no router) |
|
|
21
|
-
| `/feature-continue <slug>` | Alias of task-continue |
|
|
22
20
|
| `/spec-start [desc]` | Generate/bootstrap `docs/specs` — router intent `spec-gen` → analyst author mode → human gate |
|
|
23
21
|
| `/technical-retro [slug]` | Retro with agent team block |
|
|
24
22
|
|
|
@@ -50,6 +48,7 @@ Work request without `/task` — see **`agent-team-intake.mdc`** (when to sugges
|
|
|
50
48
|
| `playwright-test-generator` | e2e tests | e2e spec generation |
|
|
51
49
|
| `playwright-test-healer` | e2e fixes | failing/flaky e2e fixes |
|
|
52
50
|
| `tech-writer` | docs / team | docs-only, feature/migration docs |
|
|
51
|
+
| `openspec-author` | `openspec/**` only | openspec-change (`/opsx:propose`, `/opsx:apply`, `/opsx:archive`, openspec refresh) |
|
|
53
52
|
|
|
54
53
|
**Cursor frontmatter:** all team pipeline agents use `readonly: false` so they can write `.cursor/team/**`. Production/app restrictions live in the agent prompt body — do **not** set `readonly: true` (Cursor blocks *all* file writes, including team artifacts).
|
|
55
54
|
|
|
@@ -57,7 +56,7 @@ Full prompts: `.cursor/agents/*.md`. Artifact conventions: `.cursor/team/README.
|
|
|
57
56
|
|
|
58
57
|
**Behavioral UX:** `task-analyst` loads requestable skill `ux-design` for standalone intent `ux-design` and embedded required-signal / advisory UI AC. No `ux-designer` agent in v1.
|
|
59
58
|
|
|
60
|
-
**Product specs:** When `/task
|
|
59
|
+
**Product specs:** When `/task` or `/spec-start` touches pages/features/`docs/specs`: if INDEX exists and no generate intent → instruct next agent to load requestable **`product-specs`** (consume; soft-fail; never invent). If generate/bootstrap/`spec-gen` → load **`product-specs-authoring`** + skill **`spec-authoring`** inside **task-analyst** (not a separate pipeline step); pass created spec paths + INDEX diff in handoff; human gate must approve before feature-developer. No-op if INDEX absent and no author intent.
|
|
61
60
|
|
|
62
61
|
When editing `packages/ai-rules/presets/**`, follow **`preset-pr-checklist.mdc`** (+ twin-sync / layering / token-budget / leakage meta-rules).
|
|
63
62
|
|
|
@@ -180,7 +179,7 @@ After each agent completes, verify its terminal manifest receipt, then let the o
|
|
|
180
179
|
|
|
181
180
|
## Legacy mode
|
|
182
181
|
|
|
183
|
-
If `pipeline.json` is missing
|
|
182
|
+
If `pipeline.json` is missing, fall back to fixed phases: analysis → development → review → testing. Hook supports both.
|
|
184
183
|
|
|
185
184
|
## Skip pipeline when
|
|
186
185
|
|
|
@@ -196,3 +195,7 @@ Borderline work requests — see **`agent-team-intake.mdc`**.
|
|
|
196
195
|
## Auto-detection (optional)
|
|
197
196
|
|
|
198
197
|
When user describes a **non-trivial task** (not a question), suggest `/task <message>` or run router if they agree.
|
|
198
|
+
|
|
199
|
+
## Preset authoring
|
|
200
|
+
|
|
201
|
+
When the work edits `packages/ai-rules/presets/**` (or dogfood `.cursor/` sync of presets), follow meta-rules: **preset-pr-checklist**, **preset-twin-sync**, **preset-layering**, **preset-token-budget**, **preset-no-cross-stack-leakage**.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Local overlay from .ai.local/ (consumer-owned rules with priority over preset rules) — MANDATORY
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
impact: CRITICAL
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Local overlay (`.ai.local/`) — MANDATORY
|
|
8
|
+
|
|
9
|
+
This rule is mandatory. **You MUST** obey it on every turn, without exception.
|
|
10
|
+
|
|
11
|
+
## On every turn
|
|
12
|
+
|
|
13
|
+
1. **Probe** — before answering, run `ls -la .ai.local` from the repository root.
|
|
14
|
+
2. **Walk** — if `.ai.local/` exists at multiple levels (monorepo), read every level from root to leaf. **Deeper wins** in practice: more specific rules appear later in the assembled context and take precedence.
|
|
15
|
+
3. **Apply** — treat every `.ai.local/rules/*.md` and `.ai.local/conventions.md` as a higher-priority rule for this repo. The block below ("Authoring `.ai.local/rules/*.md`") defines the conventions.
|
|
16
|
+
4. **Conflict** — if a local rule conflicts with a preset rule, **the local rule wins**. If a local rule body contains `override: kill <preset-rule-name>`, drop that preset rule from your context window entirely.
|
|
17
|
+
5. **Acknowledge** — when answering a user question, briefly state which `.ai.local/` rules apply to the current task (one line is enough). Format: `Using .ai.local: <rule-name>(, <rule-name>)*`. If no `.ai.local/` exists, do NOT mention this rule.
|
|
18
|
+
|
|
19
|
+
If `.ai.local/` does not exist → **no-op**, do not error. Do not produce any log line about its absence.
|
|
20
|
+
|
|
21
|
+
## Authoring `.ai.local/rules/*.md` (consumer-side reference)
|
|
22
|
+
|
|
23
|
+
Each `.ai.local/rules/<name>.md` is a plain-markdown rule body. The model parses it as:
|
|
24
|
+
|
|
25
|
+
- Lines before `## Body` are scope metadata. Only `glob:` / `globs:` / `override:` lines are recognised.
|
|
26
|
+
- Everything from `## Body` onward is the rule body.
|
|
27
|
+
- `glob: always` → always-on. Counts against your context budget.
|
|
28
|
+
- `globs: <comma-separated globs>` → on-demand; applies only when matching files are in focus.
|
|
29
|
+
- `override: kill <preset-rule-name>` → drop that preset rule from context.
|
|
30
|
+
|
|
31
|
+
Keep files ≤ 120 lines. Match the style of preset rules (short sections, bullets, code examples).
|
|
32
|
+
|
|
33
|
+
## Limitations (read this)
|
|
34
|
+
|
|
35
|
+
- Cursor/Claude do **not** natively read `.ai.local/`. This rule is a **prompt-only** mechanism: it asks you, the model, to read and apply the files. Reliability is high but not 100%.
|
|
36
|
+
- If a user adds a file to `.ai.local/` mid-session, **restart the session** to be sure it is picked up.
|
|
37
|
+
- "Priority" is **contextual**, not enforced. Always re-read the local rule before answering questions that touch it.
|
|
38
|
+
|
|
39
|
+
## Pointers
|
|
40
|
+
|
|
41
|
+
- Authoring guide: `docs/LOCAL-OVERLAY.md` in the `@bonesofspring/ai-rules` package.
|
|
42
|
+
- Living gotchas alternative: `.cursor/team/conventions.md`.
|
|
43
|
+
- Root `AGENTS.md` reinforces this rule with a `MANDATORY` section.
|
|
@@ -19,11 +19,15 @@ Checklist for PRs that touch `packages/ai-rules/presets/**` (and dogfood `.curso
|
|
|
19
19
|
- [ ] **Core:** if `_shared/core/**` changed — all `<!-- shared-core: … -->` consumers updated (or documented intentional fork)
|
|
20
20
|
- [ ] **Twin:** Cursor change → Claude twin **same PR** (**FAIL** if missing on next, nuxt, svelte, ios-swift, android-kotlin, go, java, mcp-ts, php-hexagonal, and php-laravel — see `preset-twin-sync`)
|
|
21
21
|
- [ ] **Mapping:** `claude/<stack>/rules/README.md` mapping table is current
|
|
22
|
-
- [ ] **Token budget:** alwaysApply
|
|
22
|
+
- [ ] **Token budget:** Cursor `alwaysApply` ≤ 4 (4th slot reserved for `ai-local-overlay`); Claude session-start exactly 3; meta rules not always-on
|
|
23
|
+
- [ ] **Local overlay coverage:** every installable stack ships `ai-local-overlay.mdc` (Cursor) and `ai-local-overlay.md` (Claude) with `MANDATORY` + acknowledgement format + `docs/LOCAL-OVERLAY.md` pointer; Claude twin listed in `claude/<stack>/rules/README.md` mapping table. Run `packages/ai-rules/scripts/check-local-overlay.sh`.
|
|
23
24
|
- [ ] **Leakage:** no foreign stack agent stems / handoff strings (`preset-no-cross-stack-leakage`)
|
|
25
|
+
- [ ] **Hook-only lifecycle:** `status.json` / `metrics.json` writes happen only inside `hooks/`; agents read but never rewrite lifecycle fields. Run `packages/ai-rules/scripts/check-hook-only-lifecycle.sh`.
|
|
26
|
+
- [ ] **Chain fork:** the byte-wise MD5 uniqueness of `chain-team-phases.sh` across the 10 stacks × 2 platforms (20 hooks) holds. Run `packages/ai-rules/scripts/check-chain-hook-coverage.sh` and `packages/ai-rules/scripts/test-chain-team-phases-coverage.mjs`.
|
|
24
27
|
- [ ] **Twin depth:** domain ≥15 lines; thin aliases documented
|
|
25
28
|
- [ ] **README:** stack `rules/README.md` core→stack mapping / catalog updated if stems added
|
|
26
29
|
- [ ] **CHANGELOG / package README:** note when public preset paths or install surface change
|
|
30
|
+
- [ ] **i18n anchors:** kept-marked Cyrillic fragments in `tests-unit.md(c)` stay consistent with their English counterparts. Run `packages/ai-rules/scripts/check-preset-i18n.sh`.
|
|
27
31
|
- [ ] **Dogfood:** run `packages/ai-rules/scripts/sync-dogfood-cursor.sh` (or document intentional skip) when maintaining this monorepo
|
|
28
32
|
- [ ] **shared-core drift:** for embed-mode stems, run `packages/ai-rules/scripts/check-shared-core-drift.sh` (or document intentional fork)
|
|
29
33
|
|
|
@@ -17,12 +17,16 @@ Invariants for rule loading in an **installed** preset (consumer app).
|
|
|
17
17
|
|
|
18
18
|
| Platform | Always-on | Cap |
|
|
19
19
|
|----------|-----------|-----|
|
|
20
|
-
| Cursor | `alwaysApply: true` | **≤
|
|
20
|
+
| Cursor | `alwaysApply: true` | **≤ 4** |
|
|
21
21
|
| Claude | rules **without** `paths:` | **exactly 3** |
|
|
22
22
|
|
|
23
|
+
**Cursor 4th slot is reserved for `ai-local-overlay`** (consumer-owned `.ai.local/` rules). If you do not need local overlay, demote that rule to `globs: ["**/.ai.local/**"]` and revert to ≤3.
|
|
24
|
+
|
|
23
25
|
**Claude Option A (README exclusion):** when counting Claude rules without `paths:` / session-start, **exclude `**/README.md`** (topic indexes are not session-start rules). The intended session-start trio remains **exactly 3**; body budget sums **only those 3** rules.
|
|
24
26
|
|
|
25
|
-
Session-start body budget
|
|
27
|
+
Session-start body budget:
|
|
28
|
+
- Claude trio: ≤140 lines total (stretch ≤120).
|
|
29
|
+
- Cursor 4-set: ≤170 lines total (4 rules including `ai-local-overlay`).
|
|
26
30
|
|
|
27
31
|
## Meta / author rules
|
|
28
32
|
|
|
@@ -38,4 +42,4 @@ Orchestrator, feature-delivery, code-review, post-change gates, domain globs —
|
|
|
38
42
|
|
|
39
43
|
## Verifier
|
|
40
44
|
|
|
41
|
-
build-verifier **FAIL** if alwaysApply
|
|
45
|
+
build-verifier **FAIL** if Cursor `alwaysApply` count exceeds 4, Claude session-start count exceeds 3 (Claude count **excludes `**/README.md`**), or if a `preset-*` meta rule is marked always-on.
|
|
@@ -39,6 +39,8 @@ Cursor `.mdc` — **SoT per stack**. Claude topic `.md` — derived twin.
|
|
|
39
39
|
|
|
40
40
|
- **Domain** rules: ≥15 body lines (FAIL if thin without documented alias reason).
|
|
41
41
|
- **Thin aliases** (`agent-team-intake`, `technical-retro`): may be shorter (soft) if they only point to a command/skill.
|
|
42
|
+
- **Slim-companion rules** (UI-edit bundle, slim app-cores, slim tooling): may be shorter than 15 lines **if and only if** the body is a pointer into shared-core / stack-prose (no standalone prose). Examples live in stack `rules/README.md` (e.g. `cursor/next/rules/README.md` "UI-edit bundle" intent).
|
|
43
|
+
- Mechanical enforcement lives in `packages/ai-rules/scripts/check-preset-token-budget.sh` — see `SLIM_COMPANION_ALLOWLIST` (the 53 stems accepted as slim pointers) and `MIN_SLIM_BODY_LINES` (5-line floor). Slim-companion rules with a body of 6–14 lines whose stem is **not** in the allowlist are reported as slim violations by the script.
|
|
42
44
|
|
|
43
45
|
## Severity (build-verifier)
|
|
44
46
|
|
|
@@ -1,50 +1,94 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: E2E test and plan structure (Playwright)
|
|
3
3
|
globs: tests/e2e/**/*
|
|
4
4
|
alwaysApply: false
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<!-- shared-core: testing/testing-principles.md -->
|
|
8
8
|
|
|
9
|
+
# Testing principles
|
|
10
|
+
|
|
11
|
+
Stack-agnostic; concrete paths, runners, and selectors live in the stack adapter (`## Stack notes`).
|
|
12
|
+
|
|
13
|
+
## Behavior vs. implementation
|
|
14
|
+
|
|
15
|
+
- Verify **behavior and business rules**, not implementation or internal details.
|
|
16
|
+
|
|
17
|
+
## File naming
|
|
18
|
+
|
|
19
|
+
- For **new** tests use `*.spec.ts` / `*.spec.tsx`. Do not rename existing `*.test.ts` / `*.test.tsx` without a separate task (legacy).
|
|
20
|
+
|
|
21
|
+
## Runner and matchers
|
|
22
|
+
|
|
23
|
+
- Use the project's runner (Jest or Vitest are common); components — the project's Testing Library integration. Reuse existing matchers — no new micro-framework.
|
|
24
|
+
|
|
25
|
+
## Test title locale
|
|
26
|
+
|
|
27
|
+
- Consumer apps **may use the project locale** (often Russian) — clear business phrases stating what is checked and the expected outcome.
|
|
28
|
+
- 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).
|
|
29
|
+
|
|
30
|
+
Good (Russian locale in consumer app):
|
|
31
|
+
|
|
32
|
+
- `it('Возвращает пустой список. Пользователь не авторизован', () => {})` <!-- i18n-keep: E5 --> (Returns empty list. User is not authorized)
|
|
33
|
+
|
|
34
|
+
Bad (no capital after period; or wrong locale for configured ESLint):
|
|
35
|
+
|
|
36
|
+
- `it('Возвращает пустой список. пользователь не авторизован', () => {})` <!-- i18n-keep: E5 -->
|
|
37
|
+
- `it('Returns empty list when user is guest', () => {})` (wrong locale if ESLint enforces Russian)
|
|
38
|
+
|
|
39
|
+
## Isolation and mocks
|
|
40
|
+
|
|
41
|
+
- 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.
|
|
42
|
+
|
|
43
|
+
## Coverage of cross-cutting modules
|
|
44
|
+
|
|
45
|
+
- 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.
|
|
46
|
+
|
|
47
|
+
## Data transformation coverage
|
|
48
|
+
|
|
49
|
+
- Data transformation functions with computed fields and branches must have unit tests covering edge cases (boundary values, missing fields, unexpected value combinations).
|
|
50
|
+
|
|
51
|
+
## Reuse fixtures over ad-hoc random data
|
|
52
|
+
|
|
53
|
+
- 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.
|
|
54
|
+
|
|
55
|
+
## E2E: one canonical scenario plan per feature
|
|
56
|
+
|
|
57
|
+
- For each feature keep a **single canonical scenario plan** (distinct from implementation specs; the stack adapter names the file — typically `*.cases.md`).
|
|
58
|
+
|
|
59
|
+
## E2E: scenario ↔ test traceability
|
|
60
|
+
|
|
61
|
+
- 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.
|
|
62
|
+
|
|
63
|
+
## E2E: page objects / shared helpers
|
|
64
|
+
|
|
65
|
+
- Prefer page objects and shared helpers over scattered selectors and per-test setup duplication.
|
|
66
|
+
|
|
67
|
+
## E2E: stable identifiers (PREFIX-XXX)
|
|
68
|
+
|
|
69
|
+
- 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.
|
|
70
|
+
- Example: `test('OH-001 Отображается список заказов', async ({ page }) => { ... })` <!-- i18n-keep: E5 --> (Order list is displayed)
|
|
71
|
+
|
|
72
|
+
## E2E: selector priority
|
|
73
|
+
|
|
74
|
+
- 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}`).
|
|
75
|
+
|
|
76
|
+
## E2E: keep plans and selectors in sync with UI
|
|
77
|
+
|
|
78
|
+
- 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.
|
|
79
|
+
|
|
80
|
+
## Stack notes
|
|
81
|
+
|
|
82
|
+
- Runner: Playwright (`@playwright/test`).
|
|
9
83
|
- E2E folder: `tests/e2e/**`.
|
|
10
|
-
- Scenario plans:
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
- Prefer:
|
|
22
|
-
- page objects (e.g. `OrderHistoryPage.ts`);
|
|
23
|
-
- shared helpers from `_shared`.
|
|
24
|
-
|
|
25
|
-
# E2E test naming
|
|
26
|
-
|
|
27
|
-
- Language:
|
|
28
|
-
- all `test` / `it` names, `describe` blocks, and steps in `*.cases.md` must be formulated **in Russian**, describing behavior and the expected result. <!-- i18n-keep: E5 -->
|
|
29
|
-
- E2E title format (`test(...)` / `it(...)`):
|
|
30
|
-
- before the scenario description, put a **numbered prefix** in the form: `PREFIX-XXX Scenario description`.
|
|
31
|
-
- `PREFIX` — abbreviation from the **first letters of the words** of the entity under test, written in **Latin uppercase**.
|
|
32
|
-
- example: `OrderHistory` → `OH`, `BillingReport` → `BR`.
|
|
33
|
-
- `XXX` — sequential test number **with three digits and leading zeros**: `001`, `002`, `010`, `123`, etc.
|
|
34
|
-
- full e2e title example:
|
|
35
|
-
- `test('OH-001 Отображается список заказов', async ({ page }) => { ... })` <!-- i18n-keep: E5 -->
|
|
36
|
-
- within one entity (`PREFIX`), test numbers must form a **consistent sequence** without duplicate numbers.
|
|
37
|
-
|
|
38
|
-
# data-testid for e2e
|
|
39
|
-
|
|
40
|
-
- **Selector priority:** `data-testid` for stable elements; `getByRole` and `getByLabel` for forms and accessible elements.
|
|
41
|
-
- **Naming:** scheme `{parent}__{element}` (e.g. `history-page__title`, `history-page__recognition-banner__attach-files-button`).
|
|
42
|
-
- **Where to add:** on page root containers and key interactive elements (buttons, links, fields) that page objects target.
|
|
43
|
-
- **When UI changes:** update data-testid in components and matching selectors in page objects; align with `*.cases.md`.
|
|
44
|
-
|
|
45
|
-
# Agent requirement
|
|
46
|
-
|
|
47
|
-
When adding/changing e2e tests:
|
|
48
|
-
- First look at the matching `*.cases.md` and sync scenario names.
|
|
49
|
-
- Place specs next to plans in the same directory.
|
|
50
|
-
- Reuse shared page objects and helpers; do not copy selectors into every test.
|
|
84
|
+
- Scenario plans: `*.cases.md` — canonical source.
|
|
85
|
+
- Tests: `*.spec.ts` — Playwright implementations.
|
|
86
|
+
- Shared utilities: `tests/e2e/_shared/**`.
|
|
87
|
+
- **Russian-locale HARD policy:** all `test` / `it` titles, `describe` blocks, and `*.cases.md` steps MUST be in Russian, describing behavior + expected result. <!-- i18n-keep: E5 -->
|
|
88
|
+
- `data-testid` priority: `data-testid` for stable; `getByRole` / `getByLabel` for forms.
|
|
89
|
+
- `data-testid` naming scheme `{parent}__{element}` — example `history-page__title`, `history-page__recognition-banner__attach-files-button`.
|
|
90
|
+
- `PREFIX-XXX` example: `OrderHistory` → `OH`, `BillingReport` → `BR`.
|
|
91
|
+
- Russian example: `test('OH-001 Отображается список заказов', async ({ page }) => { ... })` <!-- i18n-keep: E5 --> (Order list is displayed).
|
|
92
|
+
- Page object example filename: `OrderHistoryPage.ts`.
|
|
93
|
+
- Cross-reference: See also **`playwright-agents.mdc`** for planner / generator / healer.
|
|
94
|
+
- `## Stack notes` content is stripped by `scripts/check-shared-core-drift.sh` before byte-comparing this file against `_shared/core/testing/testing-principles.md`; keep prose above (core content) verbatim against the core file.
|