@bonesofspring/ai-rules 0.2.11 → 0.2.12
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 +30 -0
- package/README.md +5 -1
- package/bin/cli.js +4 -0
- package/package.json +1 -1
- package/presets/_shared/README.md +1 -1
- package/presets/_shared/core/agent-team/agent-task-metrics.md +30 -0
- package/presets/_shared/core/agent-team/agent-team-orchestrator.md +9 -1
- package/presets/_shared/core/meta/preset-layering.md +1 -1
- package/presets/_shared/core/meta/preset-no-cross-stack-leakage.md +5 -5
- package/presets/_shared/core/meta/preset-pr-checklist.md +1 -1
- package/presets/_shared/core/meta/preset-twin-sync.md +4 -0
- package/presets/_shared/core/review/technical-retro.md +2 -0
- package/presets/claude/go/agents/build-verifier.md +2 -2
- package/presets/claude/go/agents/task-router.md +4 -0
- package/presets/claude/go/commands/task-continue.md +17 -16
- package/presets/claude/go/commands/task.md +4 -0
- package/presets/claude/go/commands/technical-retro.md +4 -0
- package/presets/claude/go/hooks/chain-team-phases.sh +226 -26
- package/presets/claude/go/rules/README.md +6 -0
- package/presets/claude/go/rules/tooling-and-review/agent-team-orchestrator.md +4 -0
- package/presets/claude/go/rules/tooling-and-review/preset-layering.md +1 -1
- package/presets/claude/go/rules/tooling-and-review/preset-no-cross-stack-leakage.md +5 -5
- package/presets/claude/go/rules/tooling-and-review/preset-pr-checklist.md +1 -1
- package/presets/claude/go/rules/tooling-and-review/preset-twin-sync.md +4 -0
- package/presets/claude/go/rules/tooling-and-review/technical-retro.md +2 -0
- package/presets/claude/go/team/README.md +8 -0
- package/presets/claude/ios-swift/agents/build-verifier.md +3 -3
- package/presets/claude/ios-swift/agents/task-router.md +4 -0
- package/presets/claude/ios-swift/commands/task-continue.md +17 -16
- package/presets/claude/ios-swift/commands/task.md +4 -0
- package/presets/claude/ios-swift/commands/technical-retro.md +4 -0
- package/presets/claude/ios-swift/hooks/chain-team-phases.sh +226 -26
- package/presets/claude/ios-swift/rules/README.md +6 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/agent-team-orchestrator.md +4 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-layering.md +1 -1
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-no-cross-stack-leakage.md +5 -5
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-pr-checklist.md +1 -1
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-twin-sync.md +4 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/technical-retro.md +2 -0
- package/presets/claude/ios-swift/team/README.md +8 -0
- package/presets/claude/java/agents/build-verifier.md +3 -3
- package/presets/claude/java/agents/task-router.md +4 -0
- package/presets/claude/java/commands/task-continue.md +17 -16
- package/presets/claude/java/commands/task.md +4 -0
- package/presets/claude/java/commands/technical-retro.md +4 -0
- package/presets/claude/java/hooks/chain-team-phases.sh +226 -26
- package/presets/claude/java/rules/README.md +6 -0
- package/presets/claude/java/rules/tooling-and-review/agent-team-orchestrator.md +4 -0
- package/presets/claude/java/rules/tooling-and-review/preset-layering.md +1 -1
- package/presets/claude/java/rules/tooling-and-review/preset-no-cross-stack-leakage.md +5 -5
- package/presets/claude/java/rules/tooling-and-review/preset-pr-checklist.md +1 -1
- package/presets/claude/java/rules/tooling-and-review/preset-twin-sync.md +4 -0
- package/presets/claude/java/rules/tooling-and-review/technical-retro.md +2 -0
- package/presets/claude/java/team/README.md +8 -0
- package/presets/claude/mcp-ts/agents/build-verifier.md +2 -2
- package/presets/claude/mcp-ts/agents/task-router.md +4 -0
- package/presets/claude/mcp-ts/commands/task-continue.md +21 -20
- package/presets/claude/mcp-ts/commands/task.md +4 -0
- package/presets/claude/mcp-ts/commands/technical-retro.md +4 -0
- package/presets/claude/mcp-ts/hooks/chain-team-phases.sh +226 -26
- package/presets/claude/mcp-ts/rules/README.md +6 -0
- package/presets/claude/mcp-ts/rules/tooling-and-review/agent-team-orchestrator.md +4 -0
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-layering.md +1 -1
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-no-cross-stack-leakage.md +5 -5
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-pr-checklist.md +1 -1
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-twin-sync.md +4 -0
- package/presets/claude/mcp-ts/rules/tooling-and-review/technical-retro.md +2 -4
- package/presets/claude/mcp-ts/team/README.md +8 -0
- package/presets/claude/next/agents/build-verifier.md +3 -3
- package/presets/claude/next/agents/task-router.md +4 -0
- package/presets/claude/next/commands/task-continue.md +17 -16
- package/presets/claude/next/commands/task.md +4 -0
- package/presets/claude/next/commands/technical-retro.md +4 -0
- package/presets/claude/next/hooks/chain-team-phases.sh +226 -26
- package/presets/claude/next/rules/README.md +6 -0
- package/presets/claude/next/rules/tooling-and-review/agent-team-orchestrator.md +4 -0
- package/presets/claude/next/rules/tooling-and-review/preset-layering.md +1 -1
- package/presets/claude/next/rules/tooling-and-review/preset-no-cross-stack-leakage.md +5 -5
- package/presets/claude/next/rules/tooling-and-review/preset-pr-checklist.md +1 -1
- package/presets/claude/next/rules/tooling-and-review/preset-twin-sync.md +4 -0
- package/presets/claude/next/rules/tooling-and-review/technical-retro.md +2 -0
- package/presets/claude/next/team/README.md +19 -0
- package/presets/claude/php-hexagonal/CLAUDE.md +31 -0
- package/presets/claude/php-hexagonal/MCP.md +15 -0
- package/presets/claude/php-hexagonal/README.md +26 -0
- package/presets/claude/php-hexagonal/REPO_AGENTS.md +46 -0
- package/presets/claude/php-hexagonal/agents/README.md +32 -0
- package/presets/claude/php-hexagonal/agents/api-contract-reviewer.md +23 -0
- package/presets/claude/php-hexagonal/agents/build-verifier.md +45 -0
- package/presets/claude/php-hexagonal/agents/ci-investigator.md +21 -0
- package/presets/claude/php-hexagonal/agents/code-reviewer.md +40 -0
- package/presets/claude/php-hexagonal/agents/codebase-analyzer.md +28 -0
- package/presets/claude/php-hexagonal/agents/debugger.md +29 -0
- package/presets/claude/php-hexagonal/agents/feature-developer.md +47 -0
- package/presets/claude/php-hexagonal/agents/integration-test-generator.md +22 -0
- package/presets/claude/php-hexagonal/agents/integration-test-healer.md +22 -0
- package/presets/claude/php-hexagonal/agents/integration-test-planner.md +22 -0
- package/presets/claude/php-hexagonal/agents/migration-specialist.md +31 -0
- package/presets/claude/php-hexagonal/agents/performance-auditor.md +22 -0
- package/presets/claude/php-hexagonal/agents/qa-tester.md +24 -0
- package/presets/claude/php-hexagonal/agents/security-reviewer.md +20 -0
- package/presets/claude/php-hexagonal/agents/solution-architect.md +28 -0
- package/presets/claude/php-hexagonal/agents/task-analyst.md +25 -0
- package/presets/claude/php-hexagonal/agents/task-router.md +73 -0
- package/presets/claude/php-hexagonal/agents/tech-writer.md +15 -0
- package/presets/claude/php-hexagonal/agents/unit-test-generator.md +21 -0
- package/presets/claude/php-hexagonal/agents/unit-test-healer.md +13 -0
- package/presets/claude/php-hexagonal/agents/unit-test-planner.md +26 -0
- package/presets/claude/php-hexagonal/commands/README.md +13 -0
- package/presets/claude/php-hexagonal/commands/feature-continue.md +51 -0
- package/presets/claude/php-hexagonal/commands/feature-start.md +30 -0
- package/presets/claude/php-hexagonal/commands/task-continue.md +50 -0
- package/presets/claude/php-hexagonal/commands/task.md +53 -0
- package/presets/claude/php-hexagonal/commands/technical-retro.md +62 -0
- package/presets/claude/php-hexagonal/hooks/README.md +16 -0
- package/presets/claude/php-hexagonal/hooks/chain-team-phases.sh +582 -0
- package/presets/claude/php-hexagonal/hooks/examples/README.md +18 -0
- package/presets/claude/php-hexagonal/hooks/examples/format-edited.example.sh +11 -0
- package/presets/claude/php-hexagonal/hooks/examples/secret-guard.example.sh +10 -0
- package/presets/claude/php-hexagonal/hooks/examples/test-on-save.example.sh +19 -0
- package/presets/claude/php-hexagonal/hooks/guard-shell-command.sh +80 -0
- package/presets/claude/php-hexagonal/mcp.json +11 -0
- package/presets/claude/php-hexagonal/rules/README.md +67 -0
- package/presets/claude/php-hexagonal/rules/api-and-data/README.md +14 -0
- package/presets/claude/php-hexagonal/rules/api-and-data/adapters-driven.md +38 -0
- package/presets/claude/php-hexagonal/rules/api-and-data/adapters-driving.md +38 -0
- package/presets/claude/php-hexagonal/rules/api-and-data/api-grpc.md +29 -0
- package/presets/claude/php-hexagonal/rules/api-and-data/api-http.md +36 -0
- package/presets/claude/php-hexagonal/rules/api-and-data/messaging-adapters.md +37 -0
- package/presets/claude/php-hexagonal/rules/api-and-data/persistence-adapters.md +33 -0
- package/presets/claude/php-hexagonal/rules/architecture/README.md +16 -0
- package/presets/claude/php-hexagonal/rules/architecture/application-usecases.md +31 -0
- package/presets/claude/php-hexagonal/rules/architecture/boundaries.md +34 -0
- package/presets/claude/php-hexagonal/rules/architecture/composition-root.md +33 -0
- package/presets/claude/php-hexagonal/rules/architecture/domain-layer.md +37 -0
- package/presets/claude/php-hexagonal/rules/architecture/feature-delivery.md +53 -0
- package/presets/claude/php-hexagonal/rules/architecture/module-public-api.md +31 -0
- package/presets/claude/php-hexagonal/rules/architecture/ports-interfaces.md +34 -0
- package/presets/claude/php-hexagonal/rules/architecture/reference-features.md +39 -0
- package/presets/claude/php-hexagonal/rules/stack/README.md +10 -0
- package/presets/claude/php-hexagonal/rules/stack/php-app-core.md +35 -0
- package/presets/claude/php-hexagonal/rules/stack/php-conventions.md +51 -0
- package/presets/claude/php-hexagonal/rules/testing/README.md +11 -0
- package/presets/claude/php-hexagonal/rules/testing/e2e.md +35 -0
- package/presets/claude/php-hexagonal/rules/testing/integration.md +31 -0
- package/presets/claude/php-hexagonal/rules/testing/unit.md +32 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/README.md +21 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/agent-team-intake.md +26 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/agent-team-orchestrator.md +183 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/anti-sycophancy-discipline.md +29 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/code-quality.md +53 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/code-review.md +60 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/design-guidance.md +111 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/php-tooling.md +39 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/post-change-test.md +31 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-layering.md +36 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-no-cross-stack-leakage.md +69 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-pr-checklist.md +39 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-token-budget.md +41 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-twin-sync.md +50 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/security-php.md +29 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/technical-retro.md +22 -0
- package/presets/claude/php-hexagonal/rules/ui-and-accessibility/README.md +5 -0
- package/presets/claude/php-hexagonal/skills/README.md +5 -0
- package/presets/claude/php-hexagonal/skills/ci-investigation/SKILL.md +11 -0
- package/presets/claude/php-hexagonal/skills/code-review/SKILL.md +25 -0
- package/presets/claude/php-hexagonal/skills/debug-investigation/SKILL.md +15 -0
- package/presets/claude/php-hexagonal/skills/feature-delivery/SKILL.md +30 -0
- package/presets/claude/php-hexagonal/skills/integration-testing/SKILL.md +15 -0
- package/presets/claude/php-hexagonal/skills/technical-retro/SKILL.md +54 -0
- package/presets/claude/php-hexagonal/skills/unit-testing/SKILL.md +14 -0
- package/presets/claude/php-hexagonal/skills/write-adr/SKILL.md +41 -0
- package/presets/claude/php-hexagonal/team/README.md +37 -0
- package/presets/claude/php-hexagonal/team/conventions.md +21 -0
- package/presets/claude/php-hexagonal/team/fixtures/bugfix-standard.json +37 -0
- package/presets/claude/php-hexagonal/team/fixtures/feature-full.json +25 -0
- package/presets/claude/php-hexagonal/team/fixtures/feature-light.json +17 -0
- package/presets/claude/php-laravel/CLAUDE.md +20 -0
- package/presets/claude/php-laravel/MCP.md +5 -0
- package/presets/claude/php-laravel/README.md +30 -0
- package/presets/claude/php-laravel/REPO_AGENTS.md +47 -0
- package/presets/claude/php-laravel/agents/README.md +32 -0
- package/presets/claude/php-laravel/agents/api-contract-reviewer.md +23 -0
- package/presets/claude/php-laravel/agents/build-verifier.md +45 -0
- package/presets/claude/php-laravel/agents/ci-investigator.md +21 -0
- package/presets/claude/php-laravel/agents/code-reviewer.md +40 -0
- package/presets/claude/php-laravel/agents/codebase-analyzer.md +28 -0
- package/presets/claude/php-laravel/agents/debugger.md +29 -0
- package/presets/claude/php-laravel/agents/feature-developer.md +47 -0
- package/presets/claude/php-laravel/agents/integration-test-generator.md +22 -0
- package/presets/claude/php-laravel/agents/integration-test-healer.md +22 -0
- package/presets/claude/php-laravel/agents/integration-test-planner.md +22 -0
- package/presets/claude/php-laravel/agents/migration-specialist.md +31 -0
- package/presets/claude/php-laravel/agents/performance-auditor.md +22 -0
- package/presets/claude/php-laravel/agents/qa-tester.md +30 -0
- package/presets/claude/php-laravel/agents/security-reviewer.md +32 -0
- package/presets/claude/php-laravel/agents/solution-architect.md +29 -0
- package/presets/claude/php-laravel/agents/task-analyst.md +25 -0
- package/presets/claude/php-laravel/agents/task-router.md +92 -0
- package/presets/claude/php-laravel/agents/tech-writer.md +15 -0
- package/presets/claude/php-laravel/agents/unit-test-generator.md +21 -0
- package/presets/claude/php-laravel/agents/unit-test-healer.md +13 -0
- package/presets/claude/php-laravel/agents/unit-test-planner.md +26 -0
- package/presets/claude/php-laravel/commands/README.md +13 -0
- package/presets/claude/php-laravel/commands/feature-continue.md +51 -0
- package/presets/claude/php-laravel/commands/feature-start.md +30 -0
- package/presets/claude/php-laravel/commands/task-continue.md +50 -0
- package/presets/claude/php-laravel/commands/task.md +53 -0
- package/presets/claude/php-laravel/commands/technical-retro.md +62 -0
- package/presets/claude/php-laravel/hooks/README.md +16 -0
- package/presets/claude/php-laravel/hooks/chain-team-phases.sh +582 -0
- package/presets/claude/php-laravel/hooks/examples/README.md +18 -0
- package/presets/claude/php-laravel/hooks/examples/format-edited.example.sh +11 -0
- package/presets/claude/php-laravel/hooks/examples/secret-guard.example.sh +10 -0
- package/presets/claude/php-laravel/hooks/examples/test-on-save.example.sh +19 -0
- package/presets/claude/php-laravel/hooks/guard-shell-command.sh +80 -0
- package/presets/claude/php-laravel/mcp.json +11 -0
- package/presets/claude/php-laravel/rules/README.md +67 -0
- package/presets/claude/php-laravel/rules/api-and-data/README.md +3 -0
- package/presets/claude/php-laravel/rules/api-and-data/eloquent-persistence.md +31 -0
- package/presets/claude/php-laravel/rules/api-and-data/events-listeners.md +31 -0
- package/presets/claude/php-laravel/rules/api-and-data/form-requests.md +29 -0
- package/presets/claude/php-laravel/rules/api-and-data/http-layer.md +32 -0
- package/presets/claude/php-laravel/rules/api-and-data/jobs-queues.md +41 -0
- package/presets/claude/php-laravel/rules/api-and-data/policies-authorization.md +29 -0
- package/presets/claude/php-laravel/rules/api-and-data/routes-api.md +29 -0
- package/presets/claude/php-laravel/rules/architecture/README.md +3 -0
- package/presets/claude/php-laravel/rules/architecture/actions-services.md +30 -0
- package/presets/claude/php-laravel/rules/architecture/boundaries.md +34 -0
- package/presets/claude/php-laravel/rules/architecture/domain-layer.md +24 -0
- package/presets/claude/php-laravel/rules/architecture/feature-delivery.md +51 -0
- package/presets/claude/php-laravel/rules/architecture/module-public-api.md +29 -0
- package/presets/claude/php-laravel/rules/architecture/reference-features.md +40 -0
- package/presets/claude/php-laravel/rules/architecture/service-providers.md +28 -0
- package/presets/claude/php-laravel/rules/stack/README.md +3 -0
- package/presets/claude/php-laravel/rules/stack/laravel-app-core.md +32 -0
- package/presets/claude/php-laravel/rules/stack/laravel-conventions.md +38 -0
- package/presets/claude/php-laravel/rules/testing/README.md +3 -0
- package/presets/claude/php-laravel/rules/testing/e2e.md +34 -0
- package/presets/claude/php-laravel/rules/testing/integration.md +30 -0
- package/presets/claude/php-laravel/rules/testing/unit.md +30 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/README.md +3 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/agent-team-intake.md +21 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/agent-team-orchestrator.md +180 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/anti-sycophancy-discipline.md +29 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/code-quality.md +52 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/code-review.md +58 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/design-guidance.md +111 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/php-tooling.md +37 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/post-change-test.md +29 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-layering.md +33 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-no-cross-stack-leakage.md +66 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-pr-checklist.md +36 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-token-budget.md +38 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-twin-sync.md +47 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/security-php.md +58 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/technical-retro.md +17 -0
- package/presets/claude/php-laravel/rules/ui-and-accessibility/README.md +3 -0
- package/presets/claude/php-laravel/skills/README.md +5 -0
- package/presets/claude/php-laravel/skills/ci-investigation/SKILL.md +11 -0
- package/presets/claude/php-laravel/skills/code-review/SKILL.md +25 -0
- package/presets/claude/php-laravel/skills/debug-investigation/SKILL.md +15 -0
- package/presets/claude/php-laravel/skills/feature-delivery/SKILL.md +30 -0
- package/presets/claude/php-laravel/skills/integration-testing/SKILL.md +15 -0
- package/presets/claude/php-laravel/skills/technical-retro/SKILL.md +54 -0
- package/presets/claude/php-laravel/skills/unit-testing/SKILL.md +14 -0
- package/presets/claude/php-laravel/skills/write-adr/SKILL.md +41 -0
- package/presets/claude/php-laravel/team/README.md +17 -0
- package/presets/claude/php-laravel/team/conventions.md +21 -0
- package/presets/claude/php-laravel/team/fixtures/bugfix-standard.json +12 -0
- package/presets/claude/php-laravel/team/fixtures/feature-full.json +15 -0
- package/presets/claude/php-laravel/team/fixtures/feature-light.json +8 -0
- package/presets/cursor/go/agents/build-verifier.md +2 -2
- package/presets/cursor/go/agents/task-router.md +4 -0
- package/presets/cursor/go/commands/task-continue.md +17 -16
- package/presets/cursor/go/commands/task.md +4 -0
- package/presets/cursor/go/commands/technical-retro.md +4 -0
- package/presets/cursor/go/hooks/chain-team-phases.sh +226 -26
- package/presets/cursor/go/rules/README.md +6 -0
- package/presets/cursor/go/rules/agent-team-orchestrator.mdc +4 -0
- package/presets/cursor/go/rules/preset-layering.mdc +1 -1
- package/presets/cursor/go/rules/preset-no-cross-stack-leakage.mdc +5 -5
- package/presets/cursor/go/rules/preset-pr-checklist.mdc +1 -1
- package/presets/cursor/go/rules/preset-twin-sync.mdc +4 -0
- package/presets/cursor/go/rules/technical-retro.mdc +2 -0
- package/presets/cursor/go/team/README.md +8 -0
- package/presets/cursor/ios-swift/agents/build-verifier.md +3 -3
- package/presets/cursor/ios-swift/agents/task-router.md +4 -0
- package/presets/cursor/ios-swift/commands/task-continue.md +17 -16
- package/presets/cursor/ios-swift/commands/task.md +4 -0
- package/presets/cursor/ios-swift/commands/technical-retro.md +4 -0
- package/presets/cursor/ios-swift/hooks/chain-team-phases.sh +226 -26
- package/presets/cursor/ios-swift/rules/README.md +6 -0
- package/presets/cursor/ios-swift/rules/agent-team-orchestrator.mdc +4 -0
- package/presets/cursor/ios-swift/rules/preset-layering.mdc +1 -1
- package/presets/cursor/ios-swift/rules/preset-no-cross-stack-leakage.mdc +5 -5
- package/presets/cursor/ios-swift/rules/preset-pr-checklist.mdc +1 -1
- package/presets/cursor/ios-swift/rules/preset-twin-sync.mdc +4 -0
- package/presets/cursor/ios-swift/rules/technical-retro.mdc +2 -0
- package/presets/cursor/ios-swift/team/README.md +8 -0
- package/presets/cursor/java/agents/build-verifier.md +3 -3
- package/presets/cursor/java/agents/task-router.md +4 -0
- package/presets/cursor/java/commands/task-continue.md +17 -16
- package/presets/cursor/java/commands/task.md +4 -0
- package/presets/cursor/java/commands/technical-retro.md +4 -0
- package/presets/cursor/java/hooks/chain-team-phases.sh +226 -26
- package/presets/cursor/java/rules/README.md +6 -0
- package/presets/cursor/java/rules/agent-team-orchestrator.mdc +4 -0
- package/presets/cursor/java/rules/preset-layering.mdc +1 -1
- package/presets/cursor/java/rules/preset-no-cross-stack-leakage.mdc +5 -5
- package/presets/cursor/java/rules/preset-pr-checklist.mdc +1 -1
- package/presets/cursor/java/rules/preset-twin-sync.mdc +4 -0
- package/presets/cursor/java/rules/technical-retro.mdc +2 -0
- package/presets/cursor/java/team/README.md +8 -0
- package/presets/cursor/mcp-ts/agents/build-verifier.md +2 -2
- package/presets/cursor/mcp-ts/agents/task-router.md +4 -0
- package/presets/cursor/mcp-ts/commands/task-continue.md +19 -18
- package/presets/cursor/mcp-ts/commands/task.md +4 -0
- package/presets/cursor/mcp-ts/commands/technical-retro.md +4 -0
- package/presets/cursor/mcp-ts/hooks/chain-team-phases.sh +226 -26
- package/presets/cursor/mcp-ts/rules/README.md +6 -0
- package/presets/cursor/mcp-ts/rules/agent-team-orchestrator.mdc +4 -0
- package/presets/cursor/mcp-ts/rules/preset-layering.mdc +1 -1
- package/presets/cursor/mcp-ts/rules/preset-no-cross-stack-leakage.mdc +5 -5
- package/presets/cursor/mcp-ts/rules/preset-pr-checklist.mdc +1 -1
- package/presets/cursor/mcp-ts/rules/preset-twin-sync.mdc +4 -0
- package/presets/cursor/mcp-ts/rules/technical-retro.mdc +2 -4
- package/presets/cursor/mcp-ts/team/README.md +8 -0
- package/presets/cursor/next/agents/build-verifier.md +3 -3
- package/presets/cursor/next/agents/task-router.md +4 -0
- package/presets/cursor/next/commands/task-continue.md +17 -16
- package/presets/cursor/next/commands/task.md +4 -0
- package/presets/cursor/next/commands/technical-retro.md +4 -0
- package/presets/cursor/next/hooks/chain-team-phases.sh +230 -26
- package/presets/cursor/next/rules/README.md +6 -0
- package/presets/cursor/next/rules/agent-team-orchestrator.mdc +4 -0
- package/presets/cursor/next/rules/preset-layering.mdc +1 -1
- package/presets/cursor/next/rules/preset-no-cross-stack-leakage.mdc +5 -5
- package/presets/cursor/next/rules/preset-pr-checklist.mdc +1 -1
- package/presets/cursor/next/rules/preset-twin-sync.mdc +4 -0
- package/presets/cursor/next/rules/technical-retro.mdc +2 -0
- package/presets/cursor/next/team/README.md +19 -0
- package/presets/cursor/next/team/fixtures/metrics-scenarios/tasks/human-gate/metrics.json +69 -0
- package/presets/cursor/next/team/fixtures/metrics-scenarios/tasks/missing-ledger/status.json +5 -0
- package/presets/cursor/next/team/fixtures/metrics-scenarios/tasks/parallel-receipts/metrics.json +79 -0
- package/presets/cursor/next/team/fixtures/metrics-scenarios/tasks/serial-retry/metrics.json +124 -0
- package/presets/cursor/next/team/fixtures/metrics-scenarios/tasks/validation-failed/metrics.json +124 -0
- package/presets/cursor/next/team/fixtures/metrics.example.json +54 -0
- package/presets/cursor/php-hexagonal/AGENTS.md +39 -0
- package/presets/cursor/php-hexagonal/BUGBOT.md +11 -0
- package/presets/cursor/php-hexagonal/MCP.md +15 -0
- package/presets/cursor/php-hexagonal/README.md +26 -0
- package/presets/cursor/php-hexagonal/REPO_AGENTS.md +46 -0
- package/presets/cursor/php-hexagonal/agents/README.md +36 -0
- package/presets/cursor/php-hexagonal/agents/api-contract-reviewer.md +23 -0
- package/presets/cursor/php-hexagonal/agents/build-verifier.md +45 -0
- package/presets/cursor/php-hexagonal/agents/ci-investigator.md +21 -0
- package/presets/cursor/php-hexagonal/agents/code-reviewer.md +40 -0
- package/presets/cursor/php-hexagonal/agents/codebase-analyzer.md +28 -0
- package/presets/cursor/php-hexagonal/agents/debugger.md +29 -0
- package/presets/cursor/php-hexagonal/agents/feature-developer.md +47 -0
- package/presets/cursor/php-hexagonal/agents/integration-test-generator.md +22 -0
- package/presets/cursor/php-hexagonal/agents/integration-test-healer.md +22 -0
- package/presets/cursor/php-hexagonal/agents/integration-test-planner.md +22 -0
- package/presets/cursor/php-hexagonal/agents/migration-specialist.md +31 -0
- package/presets/cursor/php-hexagonal/agents/performance-auditor.md +22 -0
- package/presets/cursor/php-hexagonal/agents/qa-tester.md +24 -0
- package/presets/cursor/php-hexagonal/agents/security-reviewer.md +20 -0
- package/presets/cursor/php-hexagonal/agents/solution-architect.md +28 -0
- package/presets/cursor/php-hexagonal/agents/task-analyst.md +25 -0
- package/presets/cursor/php-hexagonal/agents/task-router.md +73 -0
- package/presets/cursor/php-hexagonal/agents/tech-writer.md +15 -0
- package/presets/cursor/php-hexagonal/agents/unit-test-generator.md +21 -0
- package/presets/cursor/php-hexagonal/agents/unit-test-healer.md +13 -0
- package/presets/cursor/php-hexagonal/agents/unit-test-planner.md +26 -0
- package/presets/cursor/php-hexagonal/commands/README.md +54 -0
- package/presets/cursor/php-hexagonal/commands/feature-continue.md +19 -0
- package/presets/cursor/php-hexagonal/commands/feature-start.md +33 -0
- package/presets/cursor/php-hexagonal/commands/task-continue.md +50 -0
- package/presets/cursor/php-hexagonal/commands/task.md +53 -0
- package/presets/cursor/php-hexagonal/commands/technical-retro.md +85 -0
- package/presets/cursor/php-hexagonal/hooks/README.md +12 -0
- package/presets/cursor/php-hexagonal/hooks/chain-team-phases.sh +582 -0
- package/presets/cursor/php-hexagonal/hooks/examples/README.md +18 -0
- package/presets/cursor/php-hexagonal/hooks/examples/format-edited.example.sh +11 -0
- package/presets/cursor/php-hexagonal/hooks/examples/secret-guard.example.sh +10 -0
- package/presets/cursor/php-hexagonal/hooks/examples/test-on-save.example.sh +19 -0
- package/presets/cursor/php-hexagonal/hooks/guard-shell-command.sh +80 -0
- package/presets/cursor/php-hexagonal/hooks.json +17 -0
- package/presets/cursor/php-hexagonal/mcp.json +11 -0
- package/presets/cursor/php-hexagonal/rules/README.md +106 -0
- package/presets/cursor/php-hexagonal/rules/adapters-driven.mdc +41 -0
- package/presets/cursor/php-hexagonal/rules/adapters-driving.mdc +42 -0
- package/presets/cursor/php-hexagonal/rules/agent-team-intake.mdc +20 -0
- package/presets/cursor/php-hexagonal/rules/agent-team-orchestrator.mdc +177 -0
- package/presets/cursor/php-hexagonal/rules/anti-sycophancy-discipline.mdc +30 -0
- package/presets/cursor/php-hexagonal/rules/api-grpc.mdc +31 -0
- package/presets/cursor/php-hexagonal/rules/api-http.mdc +40 -0
- package/presets/cursor/php-hexagonal/rules/application-usecases.mdc +33 -0
- package/presets/cursor/php-hexagonal/rules/architecture-boundaries.mdc +36 -0
- package/presets/cursor/php-hexagonal/rules/code-quality-and-refactoring.mdc +54 -0
- package/presets/cursor/php-hexagonal/rules/code-review-mr.mdc +54 -0
- package/presets/cursor/php-hexagonal/rules/composition-root.mdc +37 -0
- package/presets/cursor/php-hexagonal/rules/design-guidance.mdc +112 -0
- package/presets/cursor/php-hexagonal/rules/domain-layer.mdc +39 -0
- package/presets/cursor/php-hexagonal/rules/feature-delivery-workflow.mdc +47 -0
- package/presets/cursor/php-hexagonal/rules/messaging-adapters.mdc +38 -0
- package/presets/cursor/php-hexagonal/rules/module-public-api.mdc +32 -0
- package/presets/cursor/php-hexagonal/rules/persistence-adapters.mdc +35 -0
- package/presets/cursor/php-hexagonal/rules/php-app-core.mdc +37 -0
- package/presets/cursor/php-hexagonal/rules/php-conventions.mdc +53 -0
- package/presets/cursor/php-hexagonal/rules/php-tooling.mdc +38 -0
- package/presets/cursor/php-hexagonal/rules/ports-interfaces.mdc +37 -0
- package/presets/cursor/php-hexagonal/rules/post-change-test.mdc +30 -0
- package/presets/cursor/php-hexagonal/rules/preset-layering.mdc +36 -0
- package/presets/cursor/php-hexagonal/rules/preset-no-cross-stack-leakage.mdc +69 -0
- package/presets/cursor/php-hexagonal/rules/preset-pr-checklist.mdc +39 -0
- package/presets/cursor/php-hexagonal/rules/preset-token-budget.mdc +41 -0
- package/presets/cursor/php-hexagonal/rules/preset-twin-sync.mdc +50 -0
- package/presets/cursor/php-hexagonal/rules/reference-features.mdc +40 -0
- package/presets/cursor/php-hexagonal/rules/security-php.mdc +33 -0
- package/presets/cursor/php-hexagonal/rules/technical-retro.mdc +16 -0
- package/presets/cursor/php-hexagonal/rules/tests-e2e.mdc +36 -0
- package/presets/cursor/php-hexagonal/rules/tests-integration.mdc +33 -0
- package/presets/cursor/php-hexagonal/rules/tests-unit.mdc +35 -0
- package/presets/cursor/php-hexagonal/skills/README.md +5 -0
- package/presets/cursor/php-hexagonal/skills/ci-investigation/SKILL.md +11 -0
- package/presets/cursor/php-hexagonal/skills/code-review/SKILL.md +25 -0
- package/presets/cursor/php-hexagonal/skills/debug-investigation/SKILL.md +15 -0
- package/presets/cursor/php-hexagonal/skills/feature-delivery/SKILL.md +30 -0
- package/presets/cursor/php-hexagonal/skills/integration-testing/SKILL.md +15 -0
- package/presets/cursor/php-hexagonal/skills/technical-retro/SKILL.md +54 -0
- package/presets/cursor/php-hexagonal/skills/unit-testing/SKILL.md +14 -0
- package/presets/cursor/php-hexagonal/skills/write-adr/SKILL.md +41 -0
- package/presets/cursor/php-hexagonal/team/README.md +41 -0
- package/presets/cursor/php-hexagonal/team/conventions.md +21 -0
- package/presets/cursor/php-hexagonal/team/fixtures/bugfix-standard.json +37 -0
- package/presets/cursor/php-hexagonal/team/fixtures/feature-full.json +25 -0
- package/presets/cursor/php-hexagonal/team/fixtures/feature-light.json +17 -0
- package/presets/cursor/php-laravel/AGENTS.md +39 -0
- package/presets/cursor/php-laravel/BUGBOT.md +9 -0
- package/presets/cursor/php-laravel/MCP.md +5 -0
- package/presets/cursor/php-laravel/README.md +33 -0
- package/presets/cursor/php-laravel/REPO_AGENTS.md +47 -0
- package/presets/cursor/php-laravel/agents/README.md +36 -0
- package/presets/cursor/php-laravel/agents/api-contract-reviewer.md +23 -0
- package/presets/cursor/php-laravel/agents/build-verifier.md +45 -0
- package/presets/cursor/php-laravel/agents/ci-investigator.md +21 -0
- package/presets/cursor/php-laravel/agents/code-reviewer.md +40 -0
- package/presets/cursor/php-laravel/agents/codebase-analyzer.md +28 -0
- package/presets/cursor/php-laravel/agents/debugger.md +29 -0
- package/presets/cursor/php-laravel/agents/feature-developer.md +47 -0
- package/presets/cursor/php-laravel/agents/integration-test-generator.md +22 -0
- package/presets/cursor/php-laravel/agents/integration-test-healer.md +22 -0
- package/presets/cursor/php-laravel/agents/integration-test-planner.md +22 -0
- package/presets/cursor/php-laravel/agents/migration-specialist.md +31 -0
- package/presets/cursor/php-laravel/agents/performance-auditor.md +22 -0
- package/presets/cursor/php-laravel/agents/qa-tester.md +30 -0
- package/presets/cursor/php-laravel/agents/security-reviewer.md +32 -0
- package/presets/cursor/php-laravel/agents/solution-architect.md +29 -0
- package/presets/cursor/php-laravel/agents/task-analyst.md +25 -0
- package/presets/cursor/php-laravel/agents/task-router.md +92 -0
- package/presets/cursor/php-laravel/agents/tech-writer.md +15 -0
- package/presets/cursor/php-laravel/agents/unit-test-generator.md +21 -0
- package/presets/cursor/php-laravel/agents/unit-test-healer.md +13 -0
- package/presets/cursor/php-laravel/agents/unit-test-planner.md +26 -0
- package/presets/cursor/php-laravel/commands/README.md +54 -0
- package/presets/cursor/php-laravel/commands/feature-continue.md +19 -0
- package/presets/cursor/php-laravel/commands/feature-start.md +33 -0
- package/presets/cursor/php-laravel/commands/task-continue.md +50 -0
- package/presets/cursor/php-laravel/commands/task.md +53 -0
- package/presets/cursor/php-laravel/commands/technical-retro.md +85 -0
- package/presets/cursor/php-laravel/hooks/README.md +12 -0
- package/presets/cursor/php-laravel/hooks/chain-team-phases.sh +582 -0
- package/presets/cursor/php-laravel/hooks/examples/README.md +18 -0
- package/presets/cursor/php-laravel/hooks/examples/format-edited.example.sh +11 -0
- package/presets/cursor/php-laravel/hooks/examples/secret-guard.example.sh +10 -0
- package/presets/cursor/php-laravel/hooks/examples/test-on-save.example.sh +19 -0
- package/presets/cursor/php-laravel/hooks/guard-shell-command.sh +80 -0
- package/presets/cursor/php-laravel/hooks.json +17 -0
- package/presets/cursor/php-laravel/mcp.json +11 -0
- package/presets/cursor/php-laravel/rules/README.md +111 -0
- package/presets/cursor/php-laravel/rules/actions-services.mdc +33 -0
- package/presets/cursor/php-laravel/rules/agent-team-intake.mdc +20 -0
- package/presets/cursor/php-laravel/rules/agent-team-orchestrator.mdc +178 -0
- package/presets/cursor/php-laravel/rules/anti-sycophancy-discipline.mdc +30 -0
- package/presets/cursor/php-laravel/rules/architecture-boundaries.mdc +37 -0
- package/presets/cursor/php-laravel/rules/code-quality-and-refactoring.mdc +54 -0
- package/presets/cursor/php-laravel/rules/code-review-mr.mdc +56 -0
- package/presets/cursor/php-laravel/rules/design-guidance.mdc +112 -0
- package/presets/cursor/php-laravel/rules/domain-layer.mdc +27 -0
- package/presets/cursor/php-laravel/rules/eloquent-persistence.mdc +34 -0
- package/presets/cursor/php-laravel/rules/events-listeners.mdc +34 -0
- package/presets/cursor/php-laravel/rules/feature-delivery-workflow.mdc +50 -0
- package/presets/cursor/php-laravel/rules/form-requests.mdc +32 -0
- package/presets/cursor/php-laravel/rules/http-layer.mdc +35 -0
- package/presets/cursor/php-laravel/rules/jobs-queues.mdc +44 -0
- package/presets/cursor/php-laravel/rules/laravel-app-core.mdc +35 -0
- package/presets/cursor/php-laravel/rules/laravel-conventions.mdc +41 -0
- package/presets/cursor/php-laravel/rules/module-public-api.mdc +31 -0
- package/presets/cursor/php-laravel/rules/php-tooling.mdc +39 -0
- package/presets/cursor/php-laravel/rules/policies-authorization.mdc +32 -0
- package/presets/cursor/php-laravel/rules/post-change-test.mdc +31 -0
- package/presets/cursor/php-laravel/rules/preset-layering.mdc +36 -0
- package/presets/cursor/php-laravel/rules/preset-no-cross-stack-leakage.mdc +69 -0
- package/presets/cursor/php-laravel/rules/preset-pr-checklist.mdc +39 -0
- package/presets/cursor/php-laravel/rules/preset-token-budget.mdc +41 -0
- package/presets/cursor/php-laravel/rules/preset-twin-sync.mdc +50 -0
- package/presets/cursor/php-laravel/rules/reference-features.mdc +42 -0
- package/presets/cursor/php-laravel/rules/routes-api.mdc +32 -0
- package/presets/cursor/php-laravel/rules/security-php.mdc +61 -0
- package/presets/cursor/php-laravel/rules/service-providers.mdc +31 -0
- package/presets/cursor/php-laravel/rules/technical-retro.mdc +16 -0
- package/presets/cursor/php-laravel/rules/tests-e2e.mdc +36 -0
- package/presets/cursor/php-laravel/rules/tests-integration.mdc +33 -0
- package/presets/cursor/php-laravel/rules/tests-unit.mdc +33 -0
- package/presets/cursor/php-laravel/skills/README.md +5 -0
- package/presets/cursor/php-laravel/skills/ci-investigation/SKILL.md +11 -0
- package/presets/cursor/php-laravel/skills/code-review/SKILL.md +25 -0
- package/presets/cursor/php-laravel/skills/debug-investigation/SKILL.md +15 -0
- package/presets/cursor/php-laravel/skills/feature-delivery/SKILL.md +30 -0
- package/presets/cursor/php-laravel/skills/integration-testing/SKILL.md +15 -0
- package/presets/cursor/php-laravel/skills/technical-retro/SKILL.md +54 -0
- package/presets/cursor/php-laravel/skills/unit-testing/SKILL.md +14 -0
- package/presets/cursor/php-laravel/skills/write-adr/SKILL.md +41 -0
- package/presets/cursor/php-laravel/team/README.md +17 -0
- package/presets/cursor/php-laravel/team/conventions.md +21 -0
- package/presets/cursor/php-laravel/team/fixtures/bugfix-standard.json +12 -0
- package/presets/cursor/php-laravel/team/fixtures/feature-full.json +15 -0
- package/presets/cursor/php-laravel/team/fixtures/feature-light.json +8 -0
|
@@ -50,6 +50,8 @@ if (!slug) {
|
|
|
50
50
|
const taskDir = path.join(TEAM_ROOT, 'tasks', slug);
|
|
51
51
|
const statusPath = path.join(taskDir, 'status.json');
|
|
52
52
|
const pipelinePath = path.join(taskDir, 'pipeline.json');
|
|
53
|
+
const METRICS_PATH = path.join(taskDir, 'metrics.json');
|
|
54
|
+
const METRICS_LOCK = `${METRICS_PATH}.lock`;
|
|
53
55
|
|
|
54
56
|
if (!fs.existsSync(statusPath)) {
|
|
55
57
|
process.stdout.write('{}');
|
|
@@ -57,18 +59,121 @@ if (!fs.existsSync(statusPath)) {
|
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
let status;
|
|
62
|
+
const now = new Date().toISOString();
|
|
63
|
+
const STACK = 'next';
|
|
64
|
+
const PLATFORM = 'cursor';
|
|
65
|
+
|
|
66
|
+
function waitForMetricsLock() {
|
|
67
|
+
for (let attempt = 0; attempt < 200; attempt += 1) {
|
|
68
|
+
try { fs.mkdirSync(METRICS_LOCK); return; } catch (error) {
|
|
69
|
+
if (error && error.code !== 'EEXIST') throw error;
|
|
70
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 10);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
throw new Error('metrics lock timeout');
|
|
74
|
+
}
|
|
75
|
+
let taskLockHeld = false;
|
|
76
|
+
function releaseTaskLock() {
|
|
77
|
+
if (!taskLockHeld) return;
|
|
78
|
+
taskLockHeld = false;
|
|
79
|
+
try { fs.rmdirSync(METRICS_LOCK); } catch {}
|
|
80
|
+
}
|
|
81
|
+
waitForMetricsLock();
|
|
82
|
+
taskLockHeld = true;
|
|
83
|
+
process.on('exit', releaseTaskLock);
|
|
60
84
|
try {
|
|
61
85
|
status = JSON.parse(fs.readFileSync(statusPath, 'utf8'));
|
|
62
86
|
} catch {
|
|
87
|
+
releaseTaskLock();
|
|
63
88
|
process.stdout.write('{}');
|
|
64
89
|
process.exit(0);
|
|
65
90
|
}
|
|
91
|
+
function mutateMetrics(mutator) {
|
|
92
|
+
const acquiredHere = !taskLockHeld;
|
|
93
|
+
if (acquiredHere) waitForMetricsLock();
|
|
94
|
+
try {
|
|
95
|
+
let metrics;
|
|
96
|
+
try { metrics = JSON.parse(fs.readFileSync(METRICS_PATH, 'utf8')); } catch {
|
|
97
|
+
const runId = status.metricsRunId || `${slug}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
98
|
+
status.metricsRunId = runId;
|
|
99
|
+
metrics = { schemaVersion: 1, task: { runId, slug, preset: 'ai-rules', stack: STACK, platform: PLATFORM, intent: status.intent || 'unknown', profile: 'unknown' }, events: [] };
|
|
100
|
+
metrics.events.push({ eventId: `${runId}:task_started`, type: 'task_started', at: now, source: 'hook', attributionConfidence: 'high' });
|
|
101
|
+
}
|
|
102
|
+
mutator(metrics);
|
|
103
|
+
const temporary = `${METRICS_PATH}.${process.pid}.${Date.now()}.tmp`;
|
|
104
|
+
fs.writeFileSync(temporary, JSON.stringify(metrics, null, 2) + '\n');
|
|
105
|
+
fs.renameSync(temporary, METRICS_PATH);
|
|
106
|
+
} finally {
|
|
107
|
+
if (acquiredHere) { try { fs.rmdirSync(METRICS_LOCK); } catch {} }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function appendMetric(event) { mutateMetrics((metrics) => metrics.events.push({ eventId: `${metrics.task.runId}:${Date.now()}:${Math.random().toString(16).slice(2)}`, ...event })); }
|
|
111
|
+
function nextAttemptOrdinal(stepIndex, agent) {
|
|
112
|
+
try {
|
|
113
|
+
const metrics = JSON.parse(fs.readFileSync(METRICS_PATH, 'utf8'));
|
|
114
|
+
return metrics.events.reduce((highest, event) => event.type === 'attempt_started' && event.stepIndex === stepIndex && event.agent === agent ? Math.max(highest, Number(event.attempt) || 0) : highest, 0) + 1;
|
|
115
|
+
} catch { return 1; }
|
|
116
|
+
}
|
|
117
|
+
function roleFor(agent) {
|
|
118
|
+
if (/analyst|architect|router|migration/.test(agent || '')) return 'planning';
|
|
119
|
+
if (/verifier/.test(agent || '')) return 'validation';
|
|
120
|
+
if (/reviewer|auditor/.test(agent || '')) return 'review';
|
|
121
|
+
if (/test|qa/.test(agent || '')) return 'testing';
|
|
122
|
+
if (/writer/.test(agent || '')) return 'docs';
|
|
123
|
+
return 'implementation';
|
|
124
|
+
}
|
|
125
|
+
function activateAttempts(step, stepIndex) {
|
|
126
|
+
const active = { ...(status.activeAttempts || {}) }; const agents = getStepAgents(step);
|
|
127
|
+
const parallelGroupId = step.parallel && agents.length > 1 ? `${status.metricsRunId || slug}:step-${stepIndex}` : null;
|
|
128
|
+
for (const agent of agents) {
|
|
129
|
+
const attempt = nextAttemptOrdinal(stepIndex, agent); const runId = status.metricsRunId || `${slug}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
130
|
+
status.metricsRunId = runId; const attemptId = `${runId}:step-${stepIndex}:${agent}:attempt-${attempt}`;
|
|
131
|
+
if (active[attemptId]) continue;
|
|
132
|
+
active[attemptId] = { agent, stepIndex, attempt, startedAt: now, parallelGroupId };
|
|
133
|
+
appendMetric({ type: 'attempt_started', at: now, attemptId, stepIndex, stepLabel: step.label || null, agent, role: roleFor(agent), attempt, parallelGroupId, source: 'hook', attributionConfidence: 'high' });
|
|
134
|
+
}
|
|
135
|
+
status.activeAttempts = active;
|
|
136
|
+
}
|
|
137
|
+
function resolvedAttempt() {
|
|
138
|
+
const active = status.activeAttempts || {}; const entries = Object.entries(active);
|
|
139
|
+
const stableAttemptId = hookInput.attemptId;
|
|
140
|
+
if (stableAttemptId) {
|
|
141
|
+
return active[stableAttemptId]
|
|
142
|
+
? { attemptId: stableAttemptId, entry: active[stableAttemptId], confidence: 'high' }
|
|
143
|
+
: null;
|
|
144
|
+
}
|
|
145
|
+
if (entries.length === 1) return { attemptId: entries[0][0], entry: entries[0][1], confidence: 'high' };
|
|
146
|
+
try { const receipts = JSON.parse(fs.readFileSync(path.join(taskDir, '.metrics-receipts.json'), 'utf8')); const receipt = Array.isArray(receipts) ? receipts.find((item) => active[item.attemptId]) : null; if (receipt) return { attemptId: receipt.attemptId, entry: active[receipt.attemptId], confidence: 'fallback', source: 'agent' }; } catch {}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
function finishActiveAttempt() {
|
|
150
|
+
const resolved = resolvedAttempt(); if (!resolved) return null;
|
|
151
|
+
const durationMs = Date.parse(now) - Date.parse(resolved.entry.startedAt);
|
|
152
|
+
appendMetric({ type: 'attempt_finished', at: now, attemptId: resolved.attemptId, outcome: ['completed', 'changes_requested', 'validation_failed'].includes(status.state) ? status.state : 'unknown', durationMs: Number.isFinite(durationMs) && durationMs >= 0 ? durationMs : null, retryAfterFix: status.retryAfterFix || null, source: resolved.source || 'hook', attributionConfidence: resolved.confidence });
|
|
153
|
+
const active = { ...(status.activeAttempts || {}) }; delete active[resolved.attemptId]; status.activeAttempts = active; status.lastCompletedAttempt = { attemptId: resolved.attemptId, completedAt: now }; return resolved;
|
|
154
|
+
}
|
|
155
|
+
function beginHumanGate() { const eventId = `${status.metricsRunId || slug}:gate:${Date.now()}`; appendMetric({ eventId, type: 'human_gate_started', at: now, source: 'hook', attributionConfidence: 'high' }); status.activeHumanGateEventId = eventId; }
|
|
156
|
+
function endHumanGateIfResumed() {
|
|
157
|
+
if (!status.activeHumanGateEventId || status.awaitingHumanGate || status.state === 'awaiting_approval') return;
|
|
158
|
+
appendMetric({ type: 'human_gate_ended', at: now, gateStartedEventId: status.activeHumanGateEventId, source: 'hook', attributionConfidence: 'high' });
|
|
159
|
+
delete status.activeHumanGateEventId;
|
|
160
|
+
}
|
|
161
|
+
function completeTaskMetrics() { appendMetric({ type: 'task_completed', at: now, outcome: status.state === 'completed' ? 'completed' : 'unknown', source: 'hook', attributionConfidence: 'high' }); }
|
|
162
|
+
function recordSkippedStep(step, stepIndex) {
|
|
163
|
+
for (const agent of getStepAgents(step)) {
|
|
164
|
+
const runId = status.metricsRunId || `${slug}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
165
|
+
status.metricsRunId = runId;
|
|
166
|
+
const attempt = nextAttemptOrdinal(stepIndex, agent);
|
|
167
|
+
appendMetric({ type: 'attempt_skipped', at: now, attemptId: `${runId}:step-${stepIndex}:${agent}:attempt-${attempt}`, stepIndex, stepLabel: step.label || null, agent, role: roleFor(agent), attempt, outcome: 'skipped', source: 'hook', attributionConfidence: 'high' });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
66
170
|
|
|
67
|
-
const now = new Date().toISOString();
|
|
68
171
|
|
|
69
172
|
function writeStatus(next) {
|
|
70
173
|
status = { ...status, ...next, slug, updatedAt: now };
|
|
71
|
-
|
|
174
|
+
const temporary = `${statusPath}.${process.pid}.${Date.now()}.tmp`;
|
|
175
|
+
fs.writeFileSync(temporary, JSON.stringify(status, null, 2) + '\n');
|
|
176
|
+
fs.renameSync(temporary, statusPath);
|
|
72
177
|
}
|
|
73
178
|
|
|
74
179
|
function out(message) {
|
|
@@ -105,9 +210,8 @@ function skipIfMatches(skipIf, dir) {
|
|
|
105
210
|
|
|
106
211
|
function findNextExecutableStep(steps, startIdx, dir) {
|
|
107
212
|
for (let i = startIdx; i < steps.length; i++) {
|
|
108
|
-
if (!skipIfMatches(steps[i].skipIf, dir)) {
|
|
109
|
-
|
|
110
|
-
}
|
|
213
|
+
if (!skipIfMatches(steps[i].skipIf, dir)) return { step: steps[i], index: i };
|
|
214
|
+
recordSkippedStep(steps[i], i);
|
|
111
215
|
}
|
|
112
216
|
return null;
|
|
113
217
|
}
|
|
@@ -172,16 +276,29 @@ const REVIEW_AGENTS = new Set([
|
|
|
172
276
|
'api-contract-reviewer',
|
|
173
277
|
]);
|
|
174
278
|
|
|
279
|
+
function metricsHandoff(agent) {
|
|
280
|
+
const matches = Object.entries(status.activeAttempts || {}).filter(([, entry]) => entry.agent === agent);
|
|
281
|
+
if (matches.length === 1) {
|
|
282
|
+
return ` Metrics attemptId: ${matches[0][0]}; update normal status only. If the hook cannot identify a parallel stop, append a minimal { attemptId, outcome } receipt to .metrics-receipts.json; do not calculate duration.`;
|
|
283
|
+
}
|
|
284
|
+
return ' Metrics: use the supplied attemptId when available; for a parallel completion, write a minimal { attemptId, outcome } receipt to .metrics-receipts.json rather than relying on currentAgent. Do not calculate duration.';
|
|
285
|
+
}
|
|
286
|
+
|
|
175
287
|
function handoffForAgent(agent, scope) {
|
|
176
288
|
const fn = AGENT_HANDOFF[agent];
|
|
177
|
-
|
|
289
|
+
const handoff = fn ? fn(slug, scope) : `Invoke ${agent} subagent for slug "${slug}". Update status.json when done.`;
|
|
290
|
+
return handoff + metricsHandoff(agent);
|
|
178
291
|
}
|
|
179
292
|
|
|
180
293
|
function handoffForParallelStep(step) {
|
|
181
294
|
const agents = getStepAgents(step);
|
|
295
|
+
const attemptIds = Object.entries(status.activeAttempts || {})
|
|
296
|
+
.filter(([, entry]) => agents.includes(entry.agent))
|
|
297
|
+
.map(([attemptId, entry]) => `${entry.agent}=${attemptId}`);
|
|
182
298
|
return (
|
|
183
299
|
`Invoke IN PARALLEL (one message, multiple Task calls): ${agents.join(' AND ')} for slug "${slug}". ` +
|
|
184
|
-
`Each agent writes its artifact and appends itself to status.json parallelCompleted when done
|
|
300
|
+
`Each agent writes its artifact and appends itself to status.json parallelCompleted when done. ` +
|
|
301
|
+
`Metrics attemptIds: ${attemptIds.join('; ')}. If the hook cannot identify a parallel stop, append a minimal { attemptId, outcome } receipt to .metrics-receipts.json; do not calculate duration.`
|
|
185
302
|
);
|
|
186
303
|
}
|
|
187
304
|
|
|
@@ -213,34 +330,38 @@ function legacyFlow() {
|
|
|
213
330
|
out(handoffForAgent('qa-tester'));
|
|
214
331
|
process.exit(0);
|
|
215
332
|
}
|
|
333
|
+
function scheduleLegacyRetry(agent, retryAfterFix) {
|
|
334
|
+
const stepIndex = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
335
|
+
const predecessorAttemptId = status.lastCompletedAttempt?.attemptId || null;
|
|
336
|
+
appendMetric({ type: 'retry_scheduled', at: now, attemptId: predecessorAttemptId, nextAgent: agent, retryAfterFix: retryAfterFix || null, source: 'hook', attributionConfidence: 'unknown' });
|
|
337
|
+
activateAttempts({ agent }, stepIndex);
|
|
338
|
+
}
|
|
216
339
|
if (status.state === 'changes_requested' && REVIEW_AGENTS.has(status.currentAgent)) {
|
|
340
|
+
const reviewer = status.currentAgent;
|
|
341
|
+
scheduleLegacyRetry('feature-developer', reviewer);
|
|
217
342
|
writeStatus({
|
|
218
343
|
currentAgent: 'feature-developer',
|
|
219
344
|
state: 'in_progress',
|
|
220
345
|
phase: 'executing',
|
|
221
|
-
retryAfterFix:
|
|
346
|
+
retryAfterFix: reviewer,
|
|
222
347
|
});
|
|
223
|
-
out(
|
|
224
|
-
handoffForAgent('feature-developer') +
|
|
225
|
-
` After fixes, re-run ${status.currentAgent}.`,
|
|
226
|
-
);
|
|
348
|
+
out(handoffForAgent('feature-developer') + ` After fixes, re-run ${reviewer}.`);
|
|
227
349
|
process.exit(0);
|
|
228
350
|
}
|
|
229
351
|
if (status.state === 'validation_failed' && status.currentAgent === 'build-verifier') {
|
|
352
|
+
scheduleLegacyRetry('feature-developer', 'build-verifier');
|
|
230
353
|
writeStatus({
|
|
231
354
|
currentAgent: 'feature-developer',
|
|
232
355
|
state: 'in_progress',
|
|
233
356
|
phase: 'executing',
|
|
234
357
|
retryAfterFix: 'build-verifier',
|
|
235
358
|
});
|
|
236
|
-
out(
|
|
237
|
-
handoffForAgent('feature-developer') +
|
|
238
|
-
` Read validation-report.md. After fixes, re-run build-verifier.`,
|
|
239
|
-
);
|
|
359
|
+
out(handoffForAgent('feature-developer') + ' Read validation-report.md. After fixes, re-run build-verifier.');
|
|
240
360
|
process.exit(0);
|
|
241
361
|
}
|
|
242
362
|
if (status.state === 'completed' && status.retryAfterFix) {
|
|
243
363
|
const retry = status.retryAfterFix;
|
|
364
|
+
scheduleLegacyRetry(retry, null);
|
|
244
365
|
writeStatus({ currentAgent: retry, state: 'in_progress', retryAfterFix: null });
|
|
245
366
|
out(handoffForAgent(retry));
|
|
246
367
|
process.exit(0);
|
|
@@ -254,6 +375,56 @@ function legacyFlow() {
|
|
|
254
375
|
process.exit(0);
|
|
255
376
|
}
|
|
256
377
|
|
|
378
|
+
|
|
379
|
+
if (hookInput.action === 'end_human_gate') {
|
|
380
|
+
status.awaitingHumanGate = false;
|
|
381
|
+
if (status.state === 'awaiting_approval') {
|
|
382
|
+
status.state = 'in_progress';
|
|
383
|
+
status.phase = status.phase === 'human_gate' ? 'executing' : status.phase;
|
|
384
|
+
}
|
|
385
|
+
if (status.activeHumanGateEventId) {
|
|
386
|
+
appendMetric({
|
|
387
|
+
type: 'human_gate_ended',
|
|
388
|
+
at: now,
|
|
389
|
+
gateStartedEventId: status.activeHumanGateEventId,
|
|
390
|
+
source: 'orchestrator',
|
|
391
|
+
attributionConfidence: 'high',
|
|
392
|
+
});
|
|
393
|
+
delete status.activeHumanGateEventId;
|
|
394
|
+
}
|
|
395
|
+
if (hookInput.activateNext && fs.existsSync(pipelinePath)) {
|
|
396
|
+
let resumePipeline = null;
|
|
397
|
+
try { resumePipeline = JSON.parse(fs.readFileSync(pipelinePath, 'utf8')); } catch {}
|
|
398
|
+
if (resumePipeline) {
|
|
399
|
+
const resumeSteps = resumePipeline.steps || [];
|
|
400
|
+
const resumeStart = (typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0) + 1;
|
|
401
|
+
const resumeNext = findNextExecutableStep(resumeSteps, resumeStart, taskDir);
|
|
402
|
+
if (resumeNext) {
|
|
403
|
+
const resumeAgents = getStepAgents(resumeNext.step);
|
|
404
|
+
activateAttempts(resumeNext.step, resumeNext.index);
|
|
405
|
+
writeStatus({
|
|
406
|
+
pipelineIndex: resumeNext.index,
|
|
407
|
+
currentAgent: resumeAgents[0],
|
|
408
|
+
phase: 'executing',
|
|
409
|
+
state: 'in_progress',
|
|
410
|
+
awaitingHumanGate: false,
|
|
411
|
+
parallelCompleted: [],
|
|
412
|
+
});
|
|
413
|
+
if (resumeNext.step.parallel && resumeAgents.length > 1) out(handoffForParallelStep(resumeNext.step));
|
|
414
|
+
else out(handoffForAgent(resumeAgents[0], resumeNext.step.scope));
|
|
415
|
+
process.exit(0);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
writeStatus({
|
|
420
|
+
awaitingHumanGate: false,
|
|
421
|
+
state: status.state,
|
|
422
|
+
phase: status.phase,
|
|
423
|
+
});
|
|
424
|
+
process.stdout.write(JSON.stringify({ ok: true, action: 'end_human_gate', activeHumanGateEventId: status.activeHumanGateEventId || null }));
|
|
425
|
+
process.exit(0);
|
|
426
|
+
}
|
|
427
|
+
|
|
257
428
|
if (!fs.existsSync(pipelinePath)) {
|
|
258
429
|
legacyFlow();
|
|
259
430
|
}
|
|
@@ -266,6 +437,15 @@ try {
|
|
|
266
437
|
}
|
|
267
438
|
|
|
268
439
|
const steps = pipeline.steps || [];
|
|
440
|
+
const initialIdx = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
441
|
+
const initialStep = steps[initialIdx];
|
|
442
|
+
const activeAttemptCountBeforeFinish = Object.keys(status.activeAttempts || {}).length;
|
|
443
|
+
const finishedAttempt = finishActiveAttempt();
|
|
444
|
+
if (!finishedAttempt && (hookInput.attemptId || activeAttemptCountBeforeFinish > 0)) {
|
|
445
|
+
process.stdout.write('{}');
|
|
446
|
+
process.exit(0);
|
|
447
|
+
}
|
|
448
|
+
endHumanGateIfResumed();
|
|
269
449
|
if (steps.length === 0 || pipeline.autoChain === false) {
|
|
270
450
|
process.stdout.write('{}');
|
|
271
451
|
process.exit(0);
|
|
@@ -276,38 +456,59 @@ if (status.awaitingHumanGate || status.state === 'awaiting_approval') {
|
|
|
276
456
|
process.exit(0);
|
|
277
457
|
}
|
|
278
458
|
|
|
459
|
+
function nearestPrecedingStepIndex(agent, fromIndex, fallback) {
|
|
460
|
+
for (let index = fromIndex - 1; index >= 0; index -= 1) {
|
|
461
|
+
if (getStepAgents(steps[index]).includes(agent)) return index;
|
|
462
|
+
}
|
|
463
|
+
const match = steps.findIndex((step) => getStepAgents(step).includes(agent));
|
|
464
|
+
return match >= 0 ? match : fallback;
|
|
465
|
+
}
|
|
466
|
+
function scheduleRetry(agent, retryAfterFix, predecessor, explicitStepIndex = null) {
|
|
467
|
+
const currentIndex = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
468
|
+
const stepIndex = Number.isInteger(explicitStepIndex)
|
|
469
|
+
? explicitStepIndex
|
|
470
|
+
: nearestPrecedingStepIndex(agent, currentIndex, currentIndex);
|
|
471
|
+
const predecessorAttemptId = predecessor?.attemptId || status.lastCompletedAttempt?.attemptId || null;
|
|
472
|
+
appendMetric({ type: 'retry_scheduled', at: now, attemptId: predecessorAttemptId, nextAgent: agent, retryAfterFix: retryAfterFix || null, source: 'hook', attributionConfidence: predecessor ? predecessor.confidence : 'unknown' });
|
|
473
|
+
activateAttempts(steps[stepIndex] || { agent }, stepIndex);
|
|
474
|
+
return stepIndex;
|
|
475
|
+
}
|
|
476
|
+
|
|
279
477
|
if (status.state === 'changes_requested' && REVIEW_AGENTS.has(status.currentAgent)) {
|
|
280
478
|
const reviewer = status.currentAgent;
|
|
479
|
+
const retryAfterFixStepIndex = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
480
|
+
const developerIndex = scheduleRetry('feature-developer', reviewer, finishedAttempt);
|
|
281
481
|
writeStatus({
|
|
482
|
+
pipelineIndex: developerIndex,
|
|
282
483
|
currentAgent: 'feature-developer',
|
|
283
484
|
state: 'in_progress',
|
|
284
485
|
phase: 'executing',
|
|
285
486
|
retryAfterFix: reviewer,
|
|
487
|
+
retryAfterFixStepIndex,
|
|
286
488
|
});
|
|
287
|
-
out(
|
|
288
|
-
handoffForAgent('feature-developer') +
|
|
289
|
-
` After fixes, re-run ${reviewer}.`,
|
|
290
|
-
);
|
|
489
|
+
out(handoffForAgent('feature-developer') + ` After fixes, re-run ${reviewer}.`);
|
|
291
490
|
process.exit(0);
|
|
292
491
|
}
|
|
293
492
|
|
|
294
493
|
if (status.state === 'validation_failed' && status.currentAgent === 'build-verifier') {
|
|
494
|
+
const retryAfterFixStepIndex = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
495
|
+
const developerIndex = scheduleRetry('feature-developer', 'build-verifier', finishedAttempt);
|
|
295
496
|
writeStatus({
|
|
497
|
+
pipelineIndex: developerIndex,
|
|
296
498
|
currentAgent: 'feature-developer',
|
|
297
499
|
state: 'in_progress',
|
|
298
500
|
phase: 'executing',
|
|
299
501
|
retryAfterFix: 'build-verifier',
|
|
502
|
+
retryAfterFixStepIndex,
|
|
300
503
|
});
|
|
301
|
-
out(
|
|
302
|
-
handoffForAgent('feature-developer') +
|
|
303
|
-
` Read validation-report.md. After fixes, re-run build-verifier.`,
|
|
304
|
-
);
|
|
504
|
+
out(handoffForAgent('feature-developer') + ' Read validation-report.md. After fixes, re-run build-verifier.');
|
|
305
505
|
process.exit(0);
|
|
306
506
|
}
|
|
307
507
|
|
|
308
508
|
if (status.state === 'completed' && status.retryAfterFix) {
|
|
309
509
|
const retry = status.retryAfterFix;
|
|
310
|
-
|
|
510
|
+
const retryIndex = scheduleRetry(retry, null, finishedAttempt, status.retryAfterFixStepIndex);
|
|
511
|
+
writeStatus({ pipelineIndex: retryIndex, currentAgent: retry, state: 'in_progress', retryAfterFix: null, retryAfterFixStepIndex: null });
|
|
311
512
|
out(handoffForAgent(retry));
|
|
312
513
|
process.exit(0);
|
|
313
514
|
}
|
|
@@ -320,7 +521,7 @@ if (!currentStep) {
|
|
|
320
521
|
process.exit(0);
|
|
321
522
|
}
|
|
322
523
|
|
|
323
|
-
const completedAgent = status.currentAgent || getStepAgents(currentStep)[0];
|
|
524
|
+
const completedAgent = finishedAttempt?.entry?.agent || status.currentAgent || getStepAgents(currentStep)[0];
|
|
324
525
|
const stepAgents = getStepAgents(currentStep);
|
|
325
526
|
|
|
326
527
|
if (currentStep.parallel && stepAgents.length > 1) {
|
|
@@ -338,6 +539,7 @@ if (currentStep.parallel && stepAgents.length > 1) {
|
|
|
338
539
|
}
|
|
339
540
|
|
|
340
541
|
if (hasGateAfterStep(currentStep, pipeline.humanGates)) {
|
|
542
|
+
beginHumanGate();
|
|
341
543
|
writeStatus({
|
|
342
544
|
awaitingHumanGate: true,
|
|
343
545
|
state: 'awaiting_approval',
|
|
@@ -349,6 +551,7 @@ if (hasGateAfterStep(currentStep, pipeline.humanGates)) {
|
|
|
349
551
|
|
|
350
552
|
const next = findNextExecutableStep(steps, idx + 1, taskDir);
|
|
351
553
|
if (!next) {
|
|
554
|
+
completeTaskMetrics();
|
|
352
555
|
writeStatus({
|
|
353
556
|
pipelineIndex: steps.length,
|
|
354
557
|
phase: 'done',
|
|
@@ -363,6 +566,7 @@ if (!next) {
|
|
|
363
566
|
const { step: nextStep, index: nextIdx } = next;
|
|
364
567
|
const nextAgents = getStepAgents(nextStep);
|
|
365
568
|
|
|
569
|
+
activateAttempts(nextStep, nextIdx);
|
|
366
570
|
writeStatus({
|
|
367
571
|
pipelineIndex: nextIdx,
|
|
368
572
|
currentAgent: nextAgents[0],
|
|
@@ -100,3 +100,9 @@ Claude twins + Cursor→Claude map: `presets/claude/next/rules/README.md`.
|
|
|
100
100
|
**Коллизии формулировок:** импорт типов и API — источник правды **`public-imports.mdc`**; дублирует ESLint `no-restricted-imports` в `app/eslint.config.mjs`.
|
|
101
101
|
|
|
102
102
|
Задачи на **сеть, замену HTTP‑библиотеки, новые эндпоинты**: опираться на **`http-client.mdc`** + **`api-services.mdc`** + **`store-rtk.mdc`**.
|
|
103
|
+
|
|
104
|
+
## Metrics policy mapping
|
|
105
|
+
|
|
106
|
+
| Shared core | Runtime integration | Loading |
|
|
107
|
+
|-------------|---------------------|---------|
|
|
108
|
+
| `agent-team/agent-task-metrics.md` | `agent-team-orchestrator` + `hooks/chain-team-phases.sh` | requestable/on-demand; never session-start |
|
|
@@ -79,6 +79,10 @@ flowchart TD
|
|
|
79
79
|
|
|
80
80
|
**Source of truth for order:** `pipeline.json` → `steps[]`. Never hardcode analyst → dev → review → QA when `pipeline.json` exists.
|
|
81
81
|
|
|
82
|
+
## Metrics lifecycle
|
|
83
|
+
|
|
84
|
+
Use the local `metrics.json` ledger described by **agent-task-metrics**: initialize attempts before invocation, let hooks record host-clock ends, and never guess a parallel completion from `currentAgent`.
|
|
85
|
+
|
|
82
86
|
## status.json (pipeline mode)
|
|
83
87
|
|
|
84
88
|
```json
|
|
@@ -24,7 +24,7 @@ alwaysApply: false
|
|
|
24
24
|
## Куда класть новое правило
|
|
25
25
|
|
|
26
26
|
1. Общие принципы для всех стеков → **core** + адаптеры с `<!-- shared-core: … -->`.
|
|
27
|
-
2. Только один из installable стеков (`next` / `ios-swift` / `go` / `java`) → **stack-specific** (не в `_shared`).
|
|
27
|
+
2. Только один из installable стеков (`next` / `ios-swift` / `go` / `java` / `mcp-ts` / `php-hexagonal` / `php-laravel`) → **stack-specific** (не в `_shared`).
|
|
28
28
|
3. Только Cursor или только Claude packaging → platform artifact / frontmatter, не дублировать семантику.
|
|
29
29
|
|
|
30
30
|
## SoT
|
|
@@ -17,7 +17,7 @@ alwaysApply: false
|
|
|
17
17
|
|
|
18
18
|
- `next` must not require iOS-only agents/tooling (`xcuitest-*`, `xcodebuild` as required handoff, Keychain-only rules).
|
|
19
19
|
- `ios-swift` must not ship Playwright handoffs or Next lint recipes as required commands.
|
|
20
|
-
- `go` / `java` / `mcp-ts` must not ship Playwright, XCUITest, Next lint recipes, or `xcodebuild`/`SwiftLint` as required handoffs.
|
|
20
|
+
- `go` / `java` / `php-hexagonal` / `php-laravel` / `mcp-ts` must not ship Playwright, XCUITest, Next lint recipes, or `xcodebuild`/`SwiftLint` as required handoffs.
|
|
21
21
|
- `mcp-ts` must not ship Go tool commands (`go test`, `go vet`, `golangci-lint`) or `integration-test-*` agents as required delivery gates.
|
|
22
22
|
- Shared core must not embed stack paths (`app/src/**`, `Features/**`, `playwright`, `xcodebuild`).
|
|
23
23
|
|
|
@@ -36,16 +36,16 @@ Required instead: `xcuitest-test-*` stems; build-verifier mentions `xcodebuild`
|
|
|
36
36
|
- `xcuitest-test-` as handoff stems
|
|
37
37
|
- Requiring `xcodebuild` / SwiftLint as the default post-change gate for Next app work
|
|
38
38
|
|
|
39
|
-
## Forbidden in go / java hooks/agents (FAIL)
|
|
39
|
+
## Forbidden in go / java / php-hexagonal / php-laravel hooks/agents (FAIL)
|
|
40
40
|
|
|
41
|
-
Shared backend-stack bans (
|
|
41
|
+
Shared backend-stack bans (`go`, `java`, `php-hexagonal`, and `php-laravel`):
|
|
42
42
|
|
|
43
43
|
- `playwright-test-`, `playwright-e2e`, `user-playwright`, `app/__tests__/e2e`
|
|
44
44
|
- Positive yarn recipes `lint:js` / `lint:css`
|
|
45
45
|
- `xcuitest-test-`, `xcodebuild`, `SwiftLint` as required handoffs
|
|
46
46
|
- Agent file `accessibility-reviewer` (no UI surface)
|
|
47
47
|
|
|
48
|
-
Required instead: `integration-test-*`; build-verifier / `post-change-test` plus stack tooling — `go-tooling` (`go test`, `go vet`)
|
|
48
|
+
Required instead: `integration-test-*`; build-verifier / `post-change-test` plus stack tooling — `go-tooling` (`go test`, `go vet`), `java-tooling` (`mvn test` / `./gradlew test`), or `php-tooling` (`php artisan test` / `composer test` / `vendor/bin/phpunit`).
|
|
49
49
|
|
|
50
50
|
## Forbidden in mcp-ts hooks/agents (FAIL)
|
|
51
51
|
|
|
@@ -66,4 +66,4 @@ Required instead: package-manager–discovered typecheck/test (`mcp-ts-tooling`,
|
|
|
66
66
|
|
|
67
67
|
## Chain fork
|
|
68
68
|
|
|
69
|
-
`hooks/chain-team-phases.sh` must differ **byte-wise** pairwise among `next`, `ios-swift`, `go`, `java`,
|
|
69
|
+
`hooks/chain-team-phases.sh` must differ **byte-wise** pairwise among `next`, `ios-swift`, `go`, `java`, `mcp-ts`, `php-hexagonal`, and `php-laravel` (per platform).
|
|
@@ -17,7 +17,7 @@ alwaysApply: false
|
|
|
17
17
|
|
|
18
18
|
- [ ] **SoT:** правки в `packages/…` (не только root `.cursor/`)
|
|
19
19
|
- [ ] **Core:** если менялся `_shared/core/**` — обновлены все `<!-- shared-core: … -->` consumers (или documented intentional fork)
|
|
20
|
-
- [ ] **Twin:** Cursor change → Claude twin **same PR** (**FAIL** if missing on next, ios-swift, go, and
|
|
20
|
+
- [ ] **Twin:** Cursor change → Claude twin **same PR** (**FAIL** if missing on next, ios-swift, go, java, mcp-ts, php-hexagonal, and php-laravel — см. `preset-twin-sync`)
|
|
21
21
|
- [ ] **Mapping:** `claude/<stack>/rules/README.md` mapping table актуален
|
|
22
22
|
- [ ] **Token budget:** alwaysApply / session-start ≤ 3; meta rules not always-on
|
|
23
23
|
- [ ] **Leakage:** нет чужих stack agent stems / handoff strings (`preset-no-cross-stack-leakage`)
|
|
@@ -22,6 +22,8 @@ Cursor `.mdc` — **SoT per stack**. Claude topic `.md` — derived twin.
|
|
|
22
22
|
| `go` | `presets/cursor/go/rules/*.mdc` | `presets/claude/go/rules/<topic>/` | Keep in `claude/go/rules/README.md` |
|
|
23
23
|
| `java` | `presets/cursor/java/rules/*.mdc` | `presets/claude/java/rules/<topic>/` | Keep in `claude/java/rules/README.md` |
|
|
24
24
|
| `mcp-ts` | `presets/cursor/mcp-ts/rules/*.mdc` | `presets/claude/mcp-ts/rules/<topic>/` | Keep in `claude/mcp-ts/rules/README.md` |
|
|
25
|
+
| `php-hexagonal` | `presets/cursor/php-hexagonal/rules/*.mdc` | `presets/claude/php-hexagonal/rules/<topic>/` | Keep in `claude/php-hexagonal/rules/README.md` |
|
|
26
|
+
| `php-laravel` | `presets/cursor/php-laravel/rules/*.mdc` | `presets/claude/php-laravel/rules/<topic>/` | Keep in `claude/php-laravel/rules/README.md` |
|
|
25
27
|
|
|
26
28
|
## Same-PR checklist
|
|
27
29
|
|
|
@@ -42,5 +44,7 @@ Cursor `.mdc` — **SoT per stack**. Claude topic `.md` — derived twin.
|
|
|
42
44
|
- **go:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift; mapping table required).
|
|
43
45
|
- **java:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go; mapping table required).
|
|
44
46
|
- **mcp-ts:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go / java; mapping table required).
|
|
47
|
+
- **php-hexagonal:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go / java / mcp-ts; mapping table required).
|
|
48
|
+
- **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).
|
|
45
49
|
|
|
46
50
|
Dogfood: sync packages → root `.cursor/` after Cursor SoT changes (not the reverse). Use `packages/ai-rules/scripts/sync-dogfood-cursor.sh`.
|
|
@@ -11,4 +11,6 @@ alwaysApply: false
|
|
|
11
11
|
|
|
12
12
|
**`commands/technical-retro.md`** → `/technical-retro`
|
|
13
13
|
|
|
14
|
+
When a task has `metrics.json`, use the local aggregation script and state the cohort, sample size, incomplete artifacts, attribution confidence, active attempt duration, and human-gate wait separately. Do not score malformed artifacts or gate wait as agent work.
|
|
15
|
+
|
|
14
16
|
Используй rule только если command недоступен. Не дублируй содержимое command в ответе — следуй command-файлу и skill `technical-retro`.
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
<slug>/
|
|
13
13
|
pipeline.json
|
|
14
14
|
status.json
|
|
15
|
+
metrics.json # schema-v1 append-only event ledger (see Local metrics ledger)
|
|
15
16
|
brief.md
|
|
16
17
|
decomposition.md
|
|
17
18
|
debug-report.md # fixApplied: true/false
|
|
@@ -71,6 +72,8 @@
|
|
|
71
72
|
"awaitingHumanGate": false,
|
|
72
73
|
"parallelCompleted": [],
|
|
73
74
|
"retryAfterFix": null,
|
|
75
|
+
"activeAttempts": {},
|
|
76
|
+
"lastCompletedAttempt": null,
|
|
74
77
|
"updatedAt": "2026-05-29T12:00:00.000Z"
|
|
75
78
|
}
|
|
76
79
|
```
|
|
@@ -107,3 +110,19 @@ Bootstrap `<slug>/` by **writing** `pipeline.json` / `status.json` (Write tool).
|
|
|
107
110
|
## Git
|
|
108
111
|
|
|
109
112
|
Commit task artifacts if you want them to survive `ai-rules clean cursor`. Or copy finished tasks to `docs/agent-workflow/tasks/<slug>/`.
|
|
113
|
+
|
|
114
|
+
## Local metrics ledger
|
|
115
|
+
|
|
116
|
+
`metrics.json` is an append-only schema-v1 event ledger for one task run. It contains only allowlisted IDs, task dimensions, timestamps, outcomes, and attribution confidence—never prompts, secrets, file paths, or contents. Policy SoT: `presets/_shared/core/agent-team/agent-task-metrics.md`. The router writes `task_started` / `attempt_started`; the hook records host-clock completion and human-gate edges under a per-task lock with temp-and-rename.
|
|
117
|
+
|
|
118
|
+
`status.json.activeAttempts` is a transient timing bridge keyed by `attemptId`; `lastCompletedAttempt` is diagnostic. For parallel stops, the hook must use a stable payload identity or the sole active attempt. Otherwise an explicit `.metrics-receipts.json` receipt is fallback data marked `source: agent`, `attributionConfidence: fallback`; it must never guess from `currentAgent`.
|
|
119
|
+
|
|
120
|
+
After a human gate, `/task-continue` closes wait via the installed hook (do not hand-edit `pipelineIndex` first):
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
printf '%s\n' '{"status":"completed","action":"end_human_gate","activateNext":true}' | bash .cursor/hooks/chain-team-phases.sh
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
That appends `human_gate_ended` before the next `attempt_started`. Claude twins use the same payload against `.claude/hooks/chain-team-phases.sh`. Other installable stacks ship the same ledger contract in their `team/README.md`.
|
|
127
|
+
|
|
128
|
+
Aggregate with `node packages/ai-rules/scripts/aggregate-agent-task-metrics.mjs --team-root .cursor/team`. It reports role/agent count, completed count, total/average duration, distinct completed run IDs, separate human-gate wait, and incomplete artifacts. For retros, see `/technical-retro` → **Metrics evidence**.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"task": {
|
|
4
|
+
"runId": "human-gate-run",
|
|
5
|
+
"slug": "human-gate",
|
|
6
|
+
"preset": "ai-rules",
|
|
7
|
+
"stack": "next",
|
|
8
|
+
"platform": "cursor",
|
|
9
|
+
"intent": "feature",
|
|
10
|
+
"profile": "full"
|
|
11
|
+
},
|
|
12
|
+
"events": [
|
|
13
|
+
{
|
|
14
|
+
"eventId": "human-gate-run:task",
|
|
15
|
+
"type": "task_started",
|
|
16
|
+
"at": "2026-07-31T17:00:00.000Z",
|
|
17
|
+
"source": "router",
|
|
18
|
+
"attributionConfidence": "high"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"eventId": "human-gate-run:gate:1",
|
|
22
|
+
"type": "human_gate_started",
|
|
23
|
+
"at": "2026-07-31T17:01:00.000Z",
|
|
24
|
+
"source": "hook",
|
|
25
|
+
"attributionConfidence": "high"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"eventId": "human-gate-run:gate:end",
|
|
29
|
+
"type": "human_gate_ended",
|
|
30
|
+
"at": "2026-07-31T17:11:00.000Z",
|
|
31
|
+
"gateStartedEventId": "human-gate-run:gate:1",
|
|
32
|
+
"source": "command",
|
|
33
|
+
"attributionConfidence": "high"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"eventId": "human-gate-run:1:feature-developer:1:start",
|
|
37
|
+
"type": "attempt_started",
|
|
38
|
+
"at": "2026-07-31T17:11:00.000Z",
|
|
39
|
+
"attemptId": "human-gate-run:step-1:feature-developer:attempt-1",
|
|
40
|
+
"stepIndex": 1,
|
|
41
|
+
"stepLabel": null,
|
|
42
|
+
"agent": "feature-developer",
|
|
43
|
+
"role": "implementation",
|
|
44
|
+
"attempt": 1,
|
|
45
|
+
"parallelGroupId": null,
|
|
46
|
+
"source": "hook",
|
|
47
|
+
"attributionConfidence": "high"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"eventId": "human-gate-run:1:feature-developer:1:finish",
|
|
51
|
+
"type": "attempt_finished",
|
|
52
|
+
"at": "2026-07-31T17:12:00.000Z",
|
|
53
|
+
"attemptId": "human-gate-run:step-1:feature-developer:attempt-1",
|
|
54
|
+
"outcome": "completed",
|
|
55
|
+
"durationMs": 60000,
|
|
56
|
+
"retryAfterFix": null,
|
|
57
|
+
"source": "hook",
|
|
58
|
+
"attributionConfidence": "high"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"eventId": "human-gate-run:done",
|
|
62
|
+
"type": "task_completed",
|
|
63
|
+
"at": "2026-07-31T17:12:00.000Z",
|
|
64
|
+
"outcome": "completed",
|
|
65
|
+
"source": "hook",
|
|
66
|
+
"attributionConfidence": "high"
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|