@bonesofspring/ai-rules 0.2.21 → 0.2.23
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 +8 -0
- package/README.md +6 -2
- package/bin/cli.js +32 -8
- package/bin/mavis-install.js +441 -0
- package/package.json +9 -2
- package/presets/_shared/core/agent-team/agent-artifact-contracts.md +2 -0
- package/presets/_shared/core/meta/preset-pr-checklist.md +1 -0
- package/presets/_shared/core/meta/preset-twin-sync.md +17 -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 +3 -0
- package/presets/claude/android-kotlin/agents/qa-tester.md +2 -0
- package/presets/claude/android-kotlin/agents/task-router.md +4 -0
- package/presets/claude/android-kotlin/hooks/chain-team-phases.sh +51 -11
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-twin-sync.md +17 -1
- 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/qa-tester.md +4 -0
- package/presets/claude/go/agents/task-router.md +4 -0
- package/presets/claude/go/hooks/chain-team-phases.sh +51 -11
- package/presets/claude/go/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/go/rules/tooling-and-review/preset-twin-sync.md +17 -1
- 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 +3 -0
- package/presets/claude/ios-swift/agents/qa-tester.md +2 -0
- package/presets/claude/ios-swift/agents/task-router.md +4 -0
- package/presets/claude/ios-swift/hooks/chain-team-phases.sh +51 -11
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-twin-sync.md +17 -1
- 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/qa-tester.md +4 -0
- package/presets/claude/java/agents/task-router.md +4 -0
- package/presets/claude/java/hooks/chain-team-phases.sh +51 -11
- package/presets/claude/java/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/java/rules/tooling-and-review/preset-twin-sync.md +17 -1
- 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-router.md +1 -1
- package/presets/claude/mcp-ts/hooks/chain-team-phases.sh +51 -11
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-twin-sync.md +17 -1
- package/presets/claude/next/agents/build-verifier.md +2 -0
- 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 +3 -0
- package/presets/claude/next/agents/qa-tester.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/hooks/chain-team-phases.sh +51 -11
- 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 +1 -1
- package/presets/claude/next/rules/testing/tests-e2e-structure.md +2 -0
- package/presets/claude/next/rules/testing/tests-unit.md +3 -5
- package/presets/claude/next/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/next/rules/tooling-and-review/preset-twin-sync.md +17 -1
- 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/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 +3 -0
- package/presets/claude/nuxt/agents/qa-tester.md +4 -0
- package/presets/claude/nuxt/hooks/chain-team-phases.sh +51 -11
- package/presets/claude/nuxt/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/nuxt/rules/tooling-and-review/preset-twin-sync.md +17 -1
- 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/qa-tester.md +4 -0
- package/presets/claude/php-hexagonal/agents/task-router.md +4 -0
- package/presets/claude/php-hexagonal/hooks/chain-team-phases.sh +51 -11
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-twin-sync.md +17 -1
- 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/qa-tester.md +4 -0
- package/presets/claude/php-laravel/agents/task-router.md +1 -0
- package/presets/claude/php-laravel/hooks/chain-team-phases.sh +51 -11
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-twin-sync.md +17 -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 +3 -0
- package/presets/claude/svelte/agents/qa-tester.md +4 -0
- package/presets/claude/svelte/hooks/chain-team-phases.sh +51 -11
- package/presets/claude/svelte/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/svelte/rules/tooling-and-review/preset-twin-sync.md +17 -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 +3 -0
- package/presets/cursor/android-kotlin/agents/qa-tester.md +2 -0
- package/presets/cursor/android-kotlin/agents/task-router.md +4 -0
- package/presets/cursor/android-kotlin/hooks/chain-team-phases.sh +51 -11
- package/presets/cursor/android-kotlin/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/android-kotlin/rules/preset-twin-sync.mdc +17 -1
- 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/qa-tester.md +4 -0
- package/presets/cursor/go/agents/task-router.md +4 -0
- package/presets/cursor/go/hooks/chain-team-phases.sh +51 -11
- package/presets/cursor/go/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/go/rules/preset-twin-sync.mdc +17 -1
- 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 +3 -0
- package/presets/cursor/ios-swift/agents/qa-tester.md +2 -0
- package/presets/cursor/ios-swift/agents/task-router.md +4 -0
- package/presets/cursor/ios-swift/hooks/chain-team-phases.sh +51 -11
- package/presets/cursor/ios-swift/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/ios-swift/rules/preset-twin-sync.mdc +17 -1
- 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/qa-tester.md +4 -0
- package/presets/cursor/java/agents/task-router.md +4 -0
- package/presets/cursor/java/hooks/chain-team-phases.sh +51 -11
- package/presets/cursor/java/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/java/rules/preset-twin-sync.mdc +17 -1
- 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-router.md +1 -1
- package/presets/cursor/mcp-ts/hooks/chain-team-phases.sh +51 -11
- package/presets/cursor/mcp-ts/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/mcp-ts/rules/preset-twin-sync.mdc +17 -1
- package/presets/cursor/next/agents/build-verifier.md +2 -0
- 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 +3 -0
- package/presets/cursor/next/agents/qa-tester.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/hooks/chain-team-phases.sh +51 -11
- package/presets/cursor/next/rules/http-client.mdc +1 -1
- package/presets/cursor/next/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/next/rules/preset-twin-sync.mdc +17 -1
- 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 +2 -0
- package/presets/cursor/next/rules/tests-unit.mdc +3 -5
- 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/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 +3 -0
- package/presets/cursor/nuxt/agents/qa-tester.md +4 -0
- package/presets/cursor/nuxt/hooks/chain-team-phases.sh +51 -11
- package/presets/cursor/nuxt/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/nuxt/rules/preset-twin-sync.mdc +17 -1
- 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/qa-tester.md +4 -0
- package/presets/cursor/php-hexagonal/agents/task-router.md +4 -0
- package/presets/cursor/php-hexagonal/hooks/chain-team-phases.sh +51 -11
- package/presets/cursor/php-hexagonal/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/php-hexagonal/rules/preset-twin-sync.mdc +17 -1
- 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/qa-tester.md +4 -0
- package/presets/cursor/php-laravel/agents/task-router.md +1 -0
- package/presets/cursor/php-laravel/hooks/chain-team-phases.sh +51 -11
- package/presets/cursor/php-laravel/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/php-laravel/rules/preset-twin-sync.mdc +17 -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 +3 -0
- package/presets/cursor/svelte/agents/qa-tester.md +4 -0
- package/presets/cursor/svelte/hooks/chain-team-phases.sh +51 -11
- package/presets/cursor/svelte/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/svelte/rules/preset-twin-sync.mdc +17 -1
- 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 +94 -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 +110 -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 +35 -0
- package/presets/mavis/next/rules/preset-token-budget.md +36 -0
- package/presets/mavis/next/rules/preset-twin-sync.md +65 -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/scripts/capture-cli-golden.mjs +44 -0
- package/scripts/check-chain-hook-coverage.sh +1 -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-preset-leakage.sh +35 -3
- package/scripts/check-preset-structure.sh +73 -0
- package/scripts/check-preset-token-budget.sh +100 -0
- package/scripts/check-shared-core-drift.sh +18 -0
- package/scripts/check-task-router-intents.sh +154 -0
- 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/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/generate-mavis-next.mjs +704 -0
- package/scripts/lib/cli-golden.mjs +50 -0
- package/scripts/lib/discover-hooks.mjs +72 -0
- package/scripts/probe-mavis-capabilities.mjs +480 -0
- package/scripts/test-agent-task-metrics-hooks.mjs +120 -16
- package/scripts/test-chain-team-phases-coverage.mjs +110 -8
- package/scripts/test-cli-init-clean.mjs +256 -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-probe-mavis-capabilities.mjs +205 -0
- package/scripts/test-task-router-intents-fixtures.mjs +109 -0
|
@@ -52,3 +52,7 @@ Provide summary:
|
|
|
52
52
|
## Design guidance
|
|
53
53
|
|
|
54
54
|
- Load `design-guidance` (rule stem) when assessing structure, smells, or pattern fit.
|
|
55
|
+
|
|
56
|
+
## Receipt binding
|
|
57
|
+
|
|
58
|
+
> **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 -->
|
|
@@ -15,7 +15,7 @@ You generate unit tests from project test plans.
|
|
|
15
15
|
## Rules
|
|
16
16
|
|
|
17
17
|
1. Follow **`unit-testing` skill** and **`rules/testing/tests-unit.md`**.
|
|
18
|
-
2. Write specs
|
|
18
|
+
2. Write specs under the mirrored path `app/src/<rel>` → `app/__tests__/unit/<rel>`; do not colocate them under `app/src/**`.
|
|
19
19
|
3. Use `@testing-library/react` and `userEvent` for components; project test-store/mocks for store/API.
|
|
20
20
|
4. `describe` / `it` titles in **Russian**, each sentence starting with a capital letter.
|
|
21
21
|
5. Do not weaken or skip scenarios from the plan without documenting a blocker in the handoff.
|
|
@@ -18,7 +18,7 @@ Use the **`unit-testing` skill** and **`rules/testing/tests-unit.md`**.
|
|
|
18
18
|
|
|
19
19
|
1. Map acceptance criteria to test scenarios (mappers, store logic, client behavior, components).
|
|
20
20
|
2. Identify gaps vs existing specs — do not duplicate covered cases.
|
|
21
|
-
3. Specify file paths for planned specs
|
|
21
|
+
3. Specify mirrored file paths for planned specs: `app/src/<rel>` → `app/__tests__/unit/<rel>`.
|
|
22
22
|
4. List behavior branches: happy path, edge cases, error paths.
|
|
23
23
|
|
|
24
24
|
## Output
|
|
@@ -64,10 +64,20 @@ const STACK = 'next';
|
|
|
64
64
|
const PLATFORM = 'claude';
|
|
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 })); }
|
|
@@ -483,7 +493,19 @@ function legacyFlow() {
|
|
|
483
493
|
|
|
484
494
|
|
|
485
495
|
if (hookInput.action === 'end_human_gate') {
|
|
486
|
-
|
|
496
|
+
status.awaitingHumanGate = false;
|
|
497
|
+
// A2 (retro §8): pin a single runId per pipeline so subsequent events don't
|
|
498
|
+
// fragment the metrics ledger across multiple runId sequences. Prefer
|
|
499
|
+
// metrics.json.task.runId when metrics already exist, then status.metricsRunId,
|
|
500
|
+
// then mint a fresh seed only on first ever emit.
|
|
501
|
+
try {
|
|
502
|
+
if (fs.existsSync(METRICS_PATH)) {
|
|
503
|
+
const existing = JSON.parse(fs.readFileSync(METRICS_PATH, 'utf8'));
|
|
504
|
+
if (existing && existing.task && typeof existing.task.runId === 'string') {
|
|
505
|
+
status.metricsRunId = existing.task.runId;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
} catch {}
|
|
487
509
|
if (status.state === 'awaiting_approval') {
|
|
488
510
|
status.state = 'in_progress';
|
|
489
511
|
status.phase = status.phase === 'human_gate' ? 'executing' : status.phase;
|
|
@@ -522,11 +544,29 @@ if (hookInput.action === 'end_human_gate') {
|
|
|
522
544
|
}
|
|
523
545
|
}
|
|
524
546
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
547
|
+
// A2 (retro §8): if gate closes the final human gate of the pipeline
|
|
548
|
+
// (no resume happens, or current step's gate was the last), surface
|
|
549
|
+
// state="awaiting_approval" so a subsequent /task-continue doesn't misinterpret
|
|
550
|
+
// the post-gate idle state as "still in progress".
|
|
551
|
+
{
|
|
552
|
+
let gateWasTerminal = false;
|
|
553
|
+
if (!hookInput.activateNext && fs.existsSync(pipelinePath)) {
|
|
554
|
+
try {
|
|
555
|
+
const pipe = JSON.parse(fs.readFileSync(pipelinePath, 'utf8'));
|
|
556
|
+
const steps = pipe.steps || [];
|
|
557
|
+
const idx = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
558
|
+
const cur = steps[idx];
|
|
559
|
+
const gates = Array.isArray(pipe.humanGates) ? pipe.humanGates : [];
|
|
560
|
+
const hasGate = (step) => Array.isArray(gates) && gates.some((g) => typeof g === 'string' && getStepAgents(step).some((a) => g === `after:${a}`));
|
|
561
|
+
if (cur && hasGate(cur)) gateWasTerminal = true;
|
|
562
|
+
} catch {}
|
|
563
|
+
}
|
|
564
|
+
writeStatus({
|
|
565
|
+
awaitingHumanGate: false,
|
|
566
|
+
state: gateWasTerminal ? 'awaiting_approval' : status.state,
|
|
567
|
+
phase: status.phase,
|
|
568
|
+
});
|
|
569
|
+
}
|
|
530
570
|
process.stdout.write(JSON.stringify({ ok: true, action: 'end_human_gate', activeHumanGateEventId: status.activeHumanGateEventId || null }));
|
|
531
571
|
process.exit(0);
|
|
532
572
|
}
|
|
@@ -37,7 +37,7 @@ impact: HIGH
|
|
|
37
37
|
|
|
38
38
|
## Agent requirement
|
|
39
39
|
|
|
40
|
-
- When changing the shared client implementation — **update or add behavior tests**
|
|
40
|
+
- When changing the shared client implementation — **update or add behavior tests** under the mirrored `app/__tests__/unit/lib/clients/**` path (`testing/tests-unit.md`).
|
|
41
41
|
- Do not introduce a **second full HTTP stack** without an explicit task and alignment with repo architecture.
|
|
42
42
|
|
|
43
43
|
## Incorrect
|
|
@@ -25,7 +25,7 @@ Replace **TBD** with real paths after team agreement (or on `ai-rules init` in t
|
|
|
25
25
|
| Store slice | **TBD** `app/src/store/slices/<example>/` | slice, thunks, selectors, types |
|
|
26
26
|
| API service | **TBD** `app/src/api/services/<example>/` | service, mappers, barrel |
|
|
27
27
|
| Types module | **TBD** `app/src/types/<example>/` | domain types, JSDoc, barrel export |
|
|
28
|
-
| Unit tests | **TBD**
|
|
28
|
+
| Unit tests | **TBD** mirrored under `app/__tests__/unit/<rel>` | `*.spec.ts`, describe/it naming |
|
|
29
29
|
| E2E area | **TBD** `app/__tests__/e2e/<Area>/` | `*.cases.md`, page objects, `_shared/` |
|
|
30
30
|
|
|
31
31
|
## How to use
|
|
@@ -5,7 +5,7 @@ Unit, e2e, Playwright agents.
|
|
|
5
5
|
| File | Contents | Loading |
|
|
6
6
|
|------|----------|---------|
|
|
7
7
|
| `playwright-agents.md` | Planner / generator / healer — e2e structure | session start |
|
|
8
|
-
| `tests-unit.md` | Unit/integration; describe/it naming in Russian (locale) | `paths: app/
|
|
8
|
+
| `tests-unit.md` | Unit/integration; mirrored `app/__tests__/unit/**` placement; describe/it naming in Russian (locale) | `paths: app/__tests__/unit/**/*.spec.*`, `*.test.*` |
|
|
9
9
|
| `tests-e2e-structure.md` | `*.cases.md`, page objects, data-testid | `paths: app/__tests__/e2e/**` |
|
|
10
10
|
|
|
11
11
|
See also `.claude/agents/playwright-test-*.md` after `ai-rules init`.
|
|
@@ -78,9 +78,11 @@ Bad (no capital after period; or wrong locale for configured ESLint):
|
|
|
78
78
|
|
|
79
79
|
- Runner: Playwright (`@playwright/test`).
|
|
80
80
|
- E2E folder: `app/__tests__/e2e/**`.
|
|
81
|
+
- Placement mirrors source paths: `app/src/<rel>` → `app/__tests__/e2e/<rel>`. Use the deepest folder of the source under test; page-wide scenarios mirror the page folder.
|
|
81
82
|
- Scenario plans: `*.cases.md` files — canonical source of scenarios.
|
|
82
83
|
- Tests: `*.spec.ts` files — Playwright scenario implementations.
|
|
83
84
|
- Shared utilities and abstractions: `app/__tests__/e2e/**/_shared/**` — constants, fluent interfaces, helpers.
|
|
85
|
+
- Root exceptions that do not mirror a single source module: `_shared/`, `smoke.spec.ts`, and `seed.spec.ts`.
|
|
84
86
|
- `data-testid` naming scheme: `{parent}__{element}` — example `history-page__title`, `history-page__recognition-banner__attach-files-button`.
|
|
85
87
|
- `PREFIX-XXX` example: `OrderHistory` → `OH`, `BillingReport` → `BR`; Russian example — `test('OH-001 Отображается список заказов', async ({ page }) => { ... })` <!-- i18n-keep: E5 --> (Order list is displayed).
|
|
86
88
|
- Page object example filename: `OrderHistoryPage.ts` (the seed test pointer lives at `app/__tests__/e2e/seed.spec.ts`).
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Unit and integration tests (Testing Library and project runner)
|
|
3
3
|
paths:
|
|
4
|
-
- app/src/**/*.spec.{ts,tsx}
|
|
5
|
-
- app/src/**/*.test.{ts,tsx}
|
|
6
4
|
- app/__tests__/unit/**/*.spec.{ts,tsx}
|
|
7
5
|
- app/__tests__/unit/**/*.test.{ts,tsx}
|
|
8
|
-
impact: MEDIUM
|
|
9
6
|
---
|
|
10
7
|
|
|
11
8
|
# Testing principles
|
|
@@ -87,8 +84,9 @@ Bad (no capital after period; or wrong locale for configured ESLint):
|
|
|
87
84
|
- `jest/valid-title` ESLint rule in `app/eslint.config.mjs` enforces the Russian capital-after-period rule (when configured).
|
|
88
85
|
- `@/types` and `@/api` imports — types come from the public API surface, never duplicated in tests.
|
|
89
86
|
- `app/src/mocks/**` — shared fixtures and MSW handlers live here (or repo equivalent).
|
|
90
|
-
-
|
|
91
|
-
-
|
|
87
|
+
- Unit-test placement mirrors source paths: `app/src/<rel>` → `app/__tests__/unit/<rel>`. Do not colocate `*.spec.ts(x)` or `*.test.ts(x)` under `app/src/**`.
|
|
88
|
+
- HTTP-client behavior tests live under the mirrored `app/__tests__/unit/lib/clients/**` path (prefer `*.spec.ts`).
|
|
89
|
+
- UI tests live under the mirrored `app/__tests__/unit/ui/**` path. Import the source under test through the `@/` alias.
|
|
92
90
|
- `## 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.
|
|
93
91
|
|
|
94
92
|
## Incorrect
|
|
@@ -18,6 +18,7 @@ Checklist for PRs that touch `packages/ai-rules/presets/**` (and dogfood `.curso
|
|
|
18
18
|
- [ ] **SoT:** edits in `packages/…` (not only root `.cursor/`)
|
|
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
|
+
- [ ] **Mavis derive:** mapped `cursor/<stack>/` change → `mavis/<stack>/` + `adapter-map.json` **same PR** when the stack is in `releasedStacks` (run `generate-mavis-next.mjs` + `check-mavis-adapter-map.mjs` for `next`; see `preset-twin-sync` § Mavis derivation)
|
|
21
22
|
- [ ] **Mapping:** `claude/<stack>/rules/README.md` mapping table is current
|
|
22
23
|
- [ ] **Token budget:** Cursor `alwaysApply` ≤ 4 (4th slot reserved for `ai-local-overlay`); Claude session-start exactly 3; meta rules not always-on
|
|
23
24
|
- [ ] **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`.
|
|
@@ -28,19 +28,34 @@ Cursor `.mdc` — **SoT per stack**. Claude topic `.md` — derived twin.
|
|
|
28
28
|
| `php-laravel` | `presets/cursor/php-laravel/rules/*.mdc` | `presets/claude/php-laravel/rules/<topic>/` | Keep in `claude/php-laravel/rules/README.md` |
|
|
29
29
|
| `android-kotlin` | `presets/cursor/android-kotlin/rules/*.mdc` | `presets/claude/android-kotlin/rules/<topic>/` | Keep in `claude/android-kotlin/rules/README.md` |
|
|
30
30
|
|
|
31
|
+
## Mavis derivation (not a Claude twin)
|
|
32
|
+
|
|
33
|
+
| Stack | Cursor SoT | Mavis derive | Manifest |
|
|
34
|
+
|-------|------------|--------------|----------|
|
|
35
|
+
| `next` | `presets/cursor/next/**` | `presets/mavis/next/**` via `generate-mavis-next.mjs` | **Required** `adapter-map.json` |
|
|
36
|
+
|
|
37
|
+
Mavis is a **third platform adapter**, not a Claude-style topic twin:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
_shared/core → cursor/<stack> → mavis/<stack>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Regenerate with `node packages/ai-rules/scripts/generate-mavis-next.mjs`; validate with `node packages/ai-rules/scripts/check-mavis-adapter-map.mjs`.
|
|
44
|
+
|
|
31
45
|
## Same-PR checklist
|
|
32
46
|
|
|
33
47
|
1. Edit Cursor rule first (body + frontmatter).
|
|
34
48
|
2. Update Claude twin: body + `paths:` (from Cursor `globs:` / requestable triggers); drop `alwaysApply`.
|
|
35
49
|
3. Update mapping table row if stem/path changed.
|
|
36
50
|
4. If body embeds core (`<!-- shared-core: … -->`), sync core consumers across stacks when core changed.
|
|
51
|
+
5. When mapped `cursor/<stack>/` sources change, regenerate `mavis/<stack>/` and refresh `adapter-map.json` `sourceRevision` in the **same PR** (run `generate-mavis-next.mjs` + `check-mavis-adapter-map.mjs` for `next`).
|
|
37
52
|
|
|
38
53
|
## Twin depth
|
|
39
54
|
|
|
40
55
|
- **Domain** rules: ≥15 body lines (FAIL if thin without documented alias reason).
|
|
41
56
|
- **Thin aliases** (`agent-team-intake`, `technical-retro`): may be shorter (soft) if they only point to a command/skill.
|
|
42
57
|
- **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
|
-
-
|
|
58
|
+
- 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.
|
|
44
59
|
|
|
45
60
|
## Severity (build-verifier)
|
|
46
61
|
|
|
@@ -54,5 +69,6 @@ Cursor `.mdc` — **SoT per stack**. Claude topic `.md` — derived twin.
|
|
|
54
69
|
- **php-hexagonal:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go / java / mcp-ts; mapping table required).
|
|
55
70
|
- **php-laravel:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go / java / mcp-ts / php-hexagonal; mapping table required).
|
|
56
71
|
- **android-kotlin:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go / java / mcp-ts / php-*; mapping table required).
|
|
72
|
+
- **mavis/next:** `cursor/next` mapped source changed without mavis regeneration / `adapter-map.json` `sourceRevision` drift → **FAIL** (`check-mavis-adapter-map.mjs`).
|
|
57
73
|
|
|
58
74
|
Dogfood: sync packages → root `.cursor/` after Cursor SoT changes (not the reverse). Use `packages/ai-rules/scripts/sync-dogfood-cursor.sh`.
|
|
@@ -55,7 +55,7 @@ For a reusable component:
|
|
|
55
55
|
|
|
56
56
|
- 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).
|
|
57
57
|
- 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.
|
|
58
|
-
- Tests for utilities and data —
|
|
58
|
+
- Tests for utilities and data — under the mirrored path `app/__tests__/unit/<rel>` per `testing/tests-unit.md`, with the same prefix (`RequestForAnalysisRecommendations.utils.spec.ts`, etc.).
|
|
59
59
|
|
|
60
60
|
# Styles and design tokens
|
|
61
61
|
|
|
@@ -8,11 +8,13 @@ description: Plans, generates, and heals Playwright e2e tests using this preset'
|
|
|
8
8
|
## Project Layout
|
|
9
9
|
|
|
10
10
|
- Test root: `app/__tests__/e2e`.
|
|
11
|
-
-
|
|
11
|
+
- Mirror formula: `app/src/<rel>` → `app/__tests__/e2e/<rel>` (drop `app/src`, preserve the relative path).
|
|
12
|
+
- Place artifacts at the deepest mirrored folder of the source under test; page-wide scenarios use the page folder.
|
|
13
|
+
- Test plans: `*.cases.md` files in the mirrored folder.
|
|
12
14
|
- Executable specs: `*.spec.ts` files in the same folder.
|
|
13
|
-
- Seed/setup reference: `app/__tests__/e2e/seed.spec.ts`.
|
|
15
|
+
- Seed/setup reference: `app/__tests__/e2e/seed.spec.ts`. Root exceptions: `_shared/`, `smoke.spec.ts`, and `seed.spec.ts`.
|
|
14
16
|
|
|
15
|
-
Do not introduce top-level `specs
|
|
17
|
+
Do not introduce top-level `specs/`, `tests/`, or feature-named folders for real coverage unless the user explicitly asks for a sandbox.
|
|
16
18
|
|
|
17
19
|
## Planner
|
|
18
20
|
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: unit-testing
|
|
3
|
-
description: Plans, generates, and heals unit tests for mappers, thunks, HTTP client behavior, and React components using
|
|
3
|
+
description: Plans, generates, and heals unit tests for mappers, thunks, HTTP client behavior, and React components using mirrored paths under app/__tests__/unit and tests-unit rules. Use for unit test planning, generation, or fixing failing unit tests.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Unit Testing
|
|
7
7
|
|
|
8
8
|
## Project Layout
|
|
9
9
|
|
|
10
|
-
-
|
|
10
|
+
- Test root: `app/__tests__/unit`.
|
|
11
|
+
- Mirror formula: `app/src/<rel>` → `app/__tests__/unit/<rel>` (drop `app/src`, preserve the relative path).
|
|
12
|
+
- Place specs at the deepest mirrored folder of the module under test; do not colocate tests under `app/src/**`.
|
|
11
13
|
- Legacy `*.test.ts` / `*.test.tsx` — do not rename without a separate task.
|
|
12
14
|
- Runner: Jest or Vitest as configured in the target repo; components use `@testing-library/react`.
|
|
13
15
|
|
|
@@ -17,11 +19,11 @@ Follow **`rules/testing/tests-unit.md`**.
|
|
|
17
19
|
|
|
18
20
|
Write or update `.claude/team/tasks/<slug>/unit-test-plan.md`.
|
|
19
21
|
|
|
20
|
-
Each scenario needs a Russian `it()` title (capital letter after each sentence). Cover mappers, thunks, client behavior branches, and component interactions per AC.
|
|
22
|
+
Each scenario needs a Russian `it()` title (capital letter after each sentence). Cover mappers, thunks, client behavior branches, and component interactions per AC. Record the mirrored target path under `app/__tests__/unit/`.
|
|
21
23
|
|
|
22
24
|
## Generator
|
|
23
25
|
|
|
24
|
-
Implement specs from `unit-test-plan.md
|
|
26
|
+
Implement specs from `unit-test-plan.md` under the mirrored `app/__tests__/unit/` path. Import the source under test through the `@/` alias. Reuse project test-store, HTTP mocks, and existing test utilities. Do not change production code.
|
|
25
27
|
|
|
26
28
|
## Healer
|
|
27
29
|
|
|
@@ -96,6 +96,8 @@ Write the owned terminal receipt described under **Artifact contract**. If **FAI
|
|
|
96
96
|
|
|
97
97
|
Do not fix code — report only. Do not advance to code-reviewer until PASS.
|
|
98
98
|
|
|
99
|
+
**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 -->
|
|
100
|
+
|
|
99
101
|
## Artifact contract
|
|
100
102
|
|
|
101
103
|
- **Authoritative inputs:** read `.claude/team/tasks/<slug>/artifact-manifest.json` first; consume handoff `artifactInputIds` when supplied, otherwise consume the manifest entries for brief/decomposition, implementation evidence, pipeline scope, and changed files.
|
|
@@ -54,6 +54,8 @@ Write the owned terminal receipt described under **Artifact contract**. If **REQ
|
|
|
54
54
|
|
|
55
55
|
Do not mix this output with retrospective facilitation — keep review and retro separate.
|
|
56
56
|
|
|
57
|
+
**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 -->
|
|
58
|
+
|
|
57
59
|
## Design guidance
|
|
58
60
|
|
|
59
61
|
- Load `design-guidance` (rule stem) when assessing structure, smells, or pattern fit.
|
|
@@ -80,3 +80,7 @@ Do not perform formal code review or write e2e plans — those are separate agen
|
|
|
80
80
|
|
|
81
81
|
- When writing or changing code, load / follow rule `anti-sycophancy-discipline`.
|
|
82
82
|
- When acting on review feedback (`changes_requested` / human comments): verify each item against the codebase before implementing; no performative agreement.
|
|
83
|
+
|
|
84
|
+
## Receipt binding
|
|
85
|
+
|
|
86
|
+
> **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 -->
|
|
@@ -12,6 +12,7 @@ You are a senior frontend developer working in a Nuxt 3 monorepo with strict lay
|
|
|
12
12
|
2. Read `status.json` — proceed if `in_progress`, `approved`, or `retryAfterFix`.
|
|
13
13
|
3. Read `pipeline.json` for step context and scope.
|
|
14
14
|
4. Follow the **`feature-delivery` skill** (layer order, reference features, validation handoff).
|
|
15
|
+
5. **Verify carry-over at HEAD before applying** (refactor intent only). When the brief comes from a prior review's carry-over findings list, for each item run `git show HEAD:<path>` or `grep` to confirm the finding still applies at the current HEAD; if the file already contains the fix (carry-over was closed in a prior uncommitted batch), mark it as **NO-OP at HEAD** in `implementation.md` and skip the edit; if the file is unchanged, apply the fix and cite file:line. Target ≤2 NO-OP items per refactor pipeline.
|
|
15
16
|
|
|
16
17
|
## Task execution rules
|
|
17
18
|
|
|
@@ -39,6 +40,8 @@ Emit the owned implementation receipt with outcome `completed`. Handoff: tasks d
|
|
|
39
40
|
|
|
40
41
|
Do not perform formal code review — that is the code-reviewer subagent's job.
|
|
41
42
|
|
|
43
|
+
**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 -->
|
|
44
|
+
|
|
42
45
|
## Design guidance
|
|
43
46
|
|
|
44
47
|
- Load `design-guidance` (rule stem) when assessing structure, smells, or pattern fit.
|
|
@@ -52,3 +52,7 @@ Provide summary:
|
|
|
52
52
|
## Design guidance
|
|
53
53
|
|
|
54
54
|
- Load `design-guidance` (rule stem) when assessing structure, smells, or pattern fit.
|
|
55
|
+
|
|
56
|
+
## Receipt binding
|
|
57
|
+
|
|
58
|
+
> **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 -->
|
|
@@ -64,10 +64,20 @@ const STACK = 'nuxt';
|
|
|
64
64
|
const PLATFORM = 'claude';
|
|
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 })); }
|
|
@@ -483,7 +493,19 @@ function legacyFlow() {
|
|
|
483
493
|
|
|
484
494
|
|
|
485
495
|
if (hookInput.action === 'end_human_gate') {
|
|
486
|
-
|
|
496
|
+
status.awaitingHumanGate = false;
|
|
497
|
+
// A2 (retro §8): pin a single runId per pipeline so subsequent events don't
|
|
498
|
+
// fragment the metrics ledger across multiple runId sequences. Prefer
|
|
499
|
+
// metrics.json.task.runId when metrics already exist, then status.metricsRunId,
|
|
500
|
+
// then mint a fresh seed only on first ever emit.
|
|
501
|
+
try {
|
|
502
|
+
if (fs.existsSync(METRICS_PATH)) {
|
|
503
|
+
const existing = JSON.parse(fs.readFileSync(METRICS_PATH, 'utf8'));
|
|
504
|
+
if (existing && existing.task && typeof existing.task.runId === 'string') {
|
|
505
|
+
status.metricsRunId = existing.task.runId;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
} catch {}
|
|
487
509
|
if (status.state === 'awaiting_approval') {
|
|
488
510
|
status.state = 'in_progress';
|
|
489
511
|
status.phase = status.phase === 'human_gate' ? 'executing' : status.phase;
|
|
@@ -522,11 +544,29 @@ if (hookInput.action === 'end_human_gate') {
|
|
|
522
544
|
}
|
|
523
545
|
}
|
|
524
546
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
547
|
+
// A2 (retro §8): if gate closes the final human gate of the pipeline
|
|
548
|
+
// (no resume happens, or current step's gate was the last), surface
|
|
549
|
+
// state="awaiting_approval" so a subsequent /task-continue doesn't misinterpret
|
|
550
|
+
// the post-gate idle state as "still in progress".
|
|
551
|
+
{
|
|
552
|
+
let gateWasTerminal = false;
|
|
553
|
+
if (!hookInput.activateNext && fs.existsSync(pipelinePath)) {
|
|
554
|
+
try {
|
|
555
|
+
const pipe = JSON.parse(fs.readFileSync(pipelinePath, 'utf8'));
|
|
556
|
+
const steps = pipe.steps || [];
|
|
557
|
+
const idx = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
558
|
+
const cur = steps[idx];
|
|
559
|
+
const gates = Array.isArray(pipe.humanGates) ? pipe.humanGates : [];
|
|
560
|
+
const hasGate = (step) => Array.isArray(gates) && gates.some((g) => typeof g === 'string' && getStepAgents(step).some((a) => g === `after:${a}`));
|
|
561
|
+
if (cur && hasGate(cur)) gateWasTerminal = true;
|
|
562
|
+
} catch {}
|
|
563
|
+
}
|
|
564
|
+
writeStatus({
|
|
565
|
+
awaitingHumanGate: false,
|
|
566
|
+
state: gateWasTerminal ? 'awaiting_approval' : status.state,
|
|
567
|
+
phase: status.phase,
|
|
568
|
+
});
|
|
569
|
+
}
|
|
530
570
|
process.stdout.write(JSON.stringify({ ok: true, action: 'end_human_gate', activeHumanGateEventId: status.activeHumanGateEventId || null }));
|
|
531
571
|
process.exit(0);
|
|
532
572
|
}
|
|
@@ -14,6 +14,7 @@ Checklist for PRs that touch `packages/ai-rules/presets/**` (and dogfood `.curso
|
|
|
14
14
|
- [ ] **SoT:** edits in `packages/…` (not only root `.cursor/`)
|
|
15
15
|
- [ ] **Core:** if `_shared/core/**` changed — all `<!-- shared-core: … -->` consumers updated (or documented intentional fork)
|
|
16
16
|
- [ ] **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`)
|
|
17
|
+
- [ ] **Mavis derive:** mapped `cursor/<stack>/` change → `mavis/<stack>/` + `adapter-map.json` **same PR** when the stack is in `releasedStacks` (run `generate-mavis-next.mjs` + `check-mavis-adapter-map.mjs` for `next`; see `preset-twin-sync` § Mavis derivation)
|
|
17
18
|
- [ ] **Mapping:** `claude/<stack>/rules/README.md` mapping table is current
|
|
18
19
|
- [ ] **Token budget:** Cursor `alwaysApply` ≤ 4 (4th slot reserved for `ai-local-overlay`); Claude session-start exactly 3; meta rules not always-on
|
|
19
20
|
- [ ] **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`.
|
|
@@ -24,19 +24,34 @@ Cursor `.mdc` — **SoT per stack**. Claude topic `.md` — derived twin.
|
|
|
24
24
|
| `php-laravel` | `presets/cursor/php-laravel/rules/*.mdc` | `presets/claude/php-laravel/rules/<topic>/` | Keep in `claude/php-laravel/rules/README.md` |
|
|
25
25
|
| `android-kotlin` | `presets/cursor/android-kotlin/rules/*.mdc` | `presets/claude/android-kotlin/rules/<topic>/` | Keep in `claude/android-kotlin/rules/README.md` |
|
|
26
26
|
|
|
27
|
+
## Mavis derivation (not a Claude twin)
|
|
28
|
+
|
|
29
|
+
| Stack | Cursor SoT | Mavis derive | Manifest |
|
|
30
|
+
|-------|------------|--------------|----------|
|
|
31
|
+
| `next` | `presets/cursor/next/**` | `presets/mavis/next/**` via `generate-mavis-next.mjs` | **Required** `adapter-map.json` |
|
|
32
|
+
|
|
33
|
+
Mavis is a **third platform adapter**, not a Claude-style topic twin:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
_shared/core → cursor/<stack> → mavis/<stack>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Regenerate with `node packages/ai-rules/scripts/generate-mavis-next.mjs`; validate with `node packages/ai-rules/scripts/check-mavis-adapter-map.mjs`.
|
|
40
|
+
|
|
27
41
|
## Same-PR checklist
|
|
28
42
|
|
|
29
43
|
1. Edit Cursor rule first (body + frontmatter).
|
|
30
44
|
2. Update Claude twin: body + `paths:` (from Cursor `globs:` / requestable triggers); drop `alwaysApply`.
|
|
31
45
|
3. Update mapping table row if stem/path changed.
|
|
32
46
|
4. If body embeds core (`<!-- shared-core: … -->`), sync core consumers across stacks when core changed.
|
|
47
|
+
5. When mapped `cursor/<stack>/` sources change, regenerate `mavis/<stack>/` and refresh `adapter-map.json` `sourceRevision` in the **same PR** (run `generate-mavis-next.mjs` + `check-mavis-adapter-map.mjs` for `next`).
|
|
33
48
|
|
|
34
49
|
## Twin depth
|
|
35
50
|
|
|
36
51
|
- **Domain** rules: ≥15 body lines (FAIL if thin without documented alias reason).
|
|
37
52
|
- **Thin aliases** (`agent-team-intake`, `technical-retro`): may be shorter (soft) if they only point to a command/skill.
|
|
38
53
|
- **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).
|
|
39
|
-
-
|
|
54
|
+
- 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.
|
|
40
55
|
|
|
41
56
|
## Severity (build-verifier)
|
|
42
57
|
|
|
@@ -50,5 +65,6 @@ Cursor `.mdc` — **SoT per stack**. Claude topic `.md` — derived twin.
|
|
|
50
65
|
- **php-hexagonal:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go / java / mcp-ts; mapping table required).
|
|
51
66
|
- **php-laravel:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go / java / mcp-ts / php-hexagonal; mapping table required).
|
|
52
67
|
- **android-kotlin:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go / java / mcp-ts / php-*; mapping table required).
|
|
68
|
+
- **mavis/next:** `cursor/next` mapped source changed without mavis regeneration / `adapter-map.json` `sourceRevision` drift → **FAIL** (`check-mavis-adapter-map.mjs`).
|
|
53
69
|
|
|
54
70
|
Dogfood: sync packages → root `.cursor/` after Cursor SoT changes (not the reverse). Use `packages/ai-rules/scripts/sync-dogfood-cursor.sh`.
|
|
@@ -65,3 +65,7 @@ Document PASS/FAIL in `validation-report.md`.
|
|
|
65
65
|
|
|
66
66
|
13. **Product-specs assets (FAIL):** package must ship `presets/_shared/assets/docs-specs/INDEX.md`, `_templates/page.md`, `_templates/feature.md`. Cursor+Claude twins for `product-specs` and `product-specs-authoring` must embed matching shared-core markers; both stems **requestable** (`alwaysApply: false` / Claude `paths: docs/specs/**`) — never session-start.
|
|
67
67
|
14. **Optional consumer check (WARN default):** `scripts/check-product-specs.sh` + schema stub may exist for opt-in consumer CI; **FAIL** only with `--strict` or AC that requires named specs — do not force consumer CI.
|
|
68
|
+
|
|
69
|
+
## Receipt binding
|
|
70
|
+
|
|
71
|
+
> **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 -->
|
|
@@ -49,3 +49,7 @@ Write `.claude/team/tasks/<slug>/review.md` with verdict APPROVE | REQUEST_CHANG
|
|
|
49
49
|
- **Owned outputs:** `review.md`; upsert only the manifest entry assigned by handoff (`artifactOutputId`; fallback `review`) and preserve all foreign entries.
|
|
50
50
|
- **Terminal receipt:** cover applicable AC/task IDs, list authoritative evidence paths, and emit `completed` or `changes_requested`. Bind it to the supplied `attemptId` when present.
|
|
51
51
|
- **Shared state:** never create or mutate `status.json` or `metrics.json`; the orchestration runtime/hook owns lifecycle, gates, retries, attempts, and timestamps.
|
|
52
|
+
|
|
53
|
+
## Receipt binding
|
|
54
|
+
|
|
55
|
+
> **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 -->
|
|
@@ -42,3 +42,7 @@ If a Sentry/Datadog (or similar) MCP is ready and the task is a production error
|
|
|
42
42
|
|
|
43
43
|
- When writing or changing code, load / follow rule `anti-sycophancy-discipline`.
|
|
44
44
|
- When acting on review feedback (`changes_requested` / human comments): verify each item against the codebase before implementing; no performative agreement.
|
|
45
|
+
|
|
46
|
+
## Receipt binding
|
|
47
|
+
|
|
48
|
+
> **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 -->
|
|
@@ -11,6 +11,7 @@ Implement PHP features following hexagonal boundaries.
|
|
|
11
11
|
1. Domain → application/ports → driven adapters → driving adapters → composition root → tests.
|
|
12
12
|
2. Read `feature-delivery-workflow.mdc`, `architecture-boundaries.mdc`, layer globs.
|
|
13
13
|
3. After `*.php` edits: invoke `post-change-test.mdc` (+ `php-tooling.mdc`).
|
|
14
|
+
4. **Verify carry-over at HEAD before applying** (refactor intent only). When the brief comes from a prior review's carry-over findings list, for each item run `git show HEAD:<path>` or `grep` to confirm the finding still applies at the current HEAD; if the file already contains the fix, mark it as **NO-OP at HEAD** in `implementation.md` and skip the edit; if the file is unchanged, apply the fix and cite file:line. Target ≤2 NO-OP items per refactor pipeline.
|
|
14
15
|
|
|
15
16
|
## Do / Don't
|
|
16
17
|
|
|
@@ -89,3 +90,7 @@ Load requestable rule `mcp-usage` when verifying third-party library APIs (Conte
|
|
|
89
90
|
- **Owned outputs:** `implementation.md` plus changed implementation/test paths; upsert only the manifest entry assigned by handoff (`artifactOutputId`; fallback `implementation`) and preserve all foreign entries.
|
|
90
91
|
- **Terminal receipt:** cover applicable AC/task IDs, list authoritative evidence paths, and emit `completed` or `blocked`. Bind it to the supplied `attemptId` when present.
|
|
91
92
|
- **Shared state:** never create or mutate `status.json` or `metrics.json`; the orchestration runtime/hook owns lifecycle, gates, retries, attempts, and timestamps.
|
|
93
|
+
|
|
94
|
+
## Receipt binding
|
|
95
|
+
|
|
96
|
+
> **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 -->
|
|
@@ -22,3 +22,7 @@ Coordinate with existing plans under `.claude/team/tasks/<slug>/`.
|
|
|
22
22
|
## Design guidance
|
|
23
23
|
|
|
24
24
|
- Load `design-guidance` (rule stem) when assessing structure, smells, or pattern fit.
|
|
25
|
+
|
|
26
|
+
## Receipt binding
|
|
27
|
+
|
|
28
|
+
> **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 -->
|
|
@@ -74,6 +74,10 @@ Keep top-level `profile` and emit this top-level object in every new `pipeline.j
|
|
|
74
74
|
- Use concrete flags: `public-contract`, `cross-layer`, `security-sensitive`, `migration`, `destructive`, `concurrency-state`, `external-dependency`, `unclear-acceptance-criteria`, `broad-test-surface`, `behavior-regression`.
|
|
75
75
|
- `routingReasons` must be non-empty and explain profile, gates, specialists, skips, or checkpoints; never write “standard by default.”
|
|
76
76
|
- `estimatedWorkPackages` is an integer ≥1; `openDecisionCount` is an integer ≥0. Do not lower complexity because implementation is familiar.
|
|
77
|
+
- Add **api-contract-reviewer** for new/changed backend contracts — before developer.
|
|
78
|
+
- Add **accessibility-reviewer** / **security-reviewer** after build-verifier (parallel when both apply).
|
|
79
|
+
- Add **tech-writer** when docs/changelog requested.
|
|
80
|
+
|
|
77
81
|
|
|
78
82
|
## Model tiers (`steps[].model`)
|
|
79
83
|
|