@bonesofspring/ai-rules 0.2.11 → 0.2.13
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 +42 -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-artifact-contracts.md +114 -0
- package/presets/_shared/core/agent-team/agent-task-metrics.md +30 -0
- package/presets/_shared/core/agent-team/agent-team-orchestrator.md +71 -4
- 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 +11 -4
- package/presets/claude/go/agents/code-reviewer.md +8 -1
- package/presets/claude/go/agents/feature-developer.md +8 -1
- package/presets/claude/go/agents/task-analyst.md +8 -1
- package/presets/claude/go/agents/task-router.md +35 -3
- package/presets/claude/go/commands/task-continue.md +17 -16
- package/presets/claude/go/commands/task.md +11 -5
- package/presets/claude/go/commands/technical-retro.md +4 -0
- package/presets/claude/go/hooks/chain-team-phases.sh +411 -69
- package/presets/claude/go/rules/README.md +6 -0
- package/presets/claude/go/rules/tooling-and-review/agent-team-orchestrator.md +33 -4
- 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 +19 -0
- package/presets/claude/ios-swift/agents/build-verifier.md +11 -4
- package/presets/claude/ios-swift/agents/code-reviewer.md +9 -14
- package/presets/claude/ios-swift/agents/feature-developer.md +8 -1
- package/presets/claude/ios-swift/agents/task-analyst.md +8 -1
- package/presets/claude/ios-swift/agents/task-router.md +33 -1
- package/presets/claude/ios-swift/commands/task-continue.md +17 -16
- package/presets/claude/ios-swift/commands/task.md +11 -5
- package/presets/claude/ios-swift/commands/technical-retro.md +4 -0
- package/presets/claude/ios-swift/hooks/chain-team-phases.sh +393 -70
- package/presets/claude/ios-swift/rules/README.md +6 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/agent-team-orchestrator.md +36 -1
- 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 +19 -0
- package/presets/claude/java/agents/build-verifier.md +11 -4
- package/presets/claude/java/agents/code-reviewer.md +8 -1
- package/presets/claude/java/agents/feature-developer.md +8 -1
- package/presets/claude/java/agents/task-analyst.md +8 -1
- package/presets/claude/java/agents/task-router.md +33 -1
- package/presets/claude/java/commands/task-continue.md +17 -16
- package/presets/claude/java/commands/task.md +11 -5
- package/presets/claude/java/commands/technical-retro.md +4 -0
- package/presets/claude/java/hooks/chain-team-phases.sh +411 -69
- package/presets/claude/java/rules/README.md +6 -0
- package/presets/claude/java/rules/tooling-and-review/agent-team-orchestrator.md +33 -4
- 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 +19 -0
- package/presets/claude/mcp-ts/agents/build-verifier.md +11 -4
- package/presets/claude/mcp-ts/agents/feature-developer.md +7 -1
- package/presets/claude/mcp-ts/agents/task-analyst.md +8 -1
- package/presets/claude/mcp-ts/agents/task-router.md +35 -3
- package/presets/claude/mcp-ts/commands/task-continue.md +21 -20
- package/presets/claude/mcp-ts/commands/task.md +11 -5
- package/presets/claude/mcp-ts/commands/technical-retro.md +4 -0
- package/presets/claude/mcp-ts/hooks/chain-team-phases.sh +397 -55
- package/presets/claude/mcp-ts/rules/README.md +6 -0
- package/presets/claude/mcp-ts/rules/tooling-and-review/agent-team-orchestrator.md +33 -4
- 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 +19 -0
- package/presets/claude/next/agents/accessibility-reviewer.md +6 -12
- package/presets/claude/next/agents/api-contract-reviewer.md +6 -12
- package/presets/claude/next/agents/build-verifier.md +10 -14
- package/presets/claude/next/agents/ci-investigator.md +7 -13
- package/presets/claude/next/agents/code-reviewer.md +9 -14
- package/presets/claude/next/agents/debugger.md +6 -12
- package/presets/claude/next/agents/feature-developer.md +8 -1
- package/presets/claude/next/agents/migration-specialist.md +6 -12
- package/presets/claude/next/agents/performance-auditor.md +5 -11
- package/presets/claude/next/agents/qa-tester.md +6 -12
- package/presets/claude/next/agents/security-reviewer.md +6 -12
- package/presets/claude/next/agents/solution-architect.md +6 -12
- package/presets/claude/next/agents/task-analyst.md +10 -16
- package/presets/claude/next/agents/task-router.md +33 -1
- package/presets/claude/next/agents/tech-writer.md +6 -13
- package/presets/claude/next/agents/unit-test-generator.md +6 -10
- package/presets/claude/next/agents/unit-test-healer.md +6 -10
- package/presets/claude/next/agents/unit-test-planner.md +5 -11
- package/presets/claude/next/commands/task-continue.md +17 -16
- package/presets/claude/next/commands/task.md +11 -5
- package/presets/claude/next/commands/technical-retro.md +4 -0
- package/presets/claude/next/hooks/chain-team-phases.sh +413 -70
- package/presets/claude/next/rules/README.md +6 -0
- package/presets/claude/next/rules/tooling-and-review/agent-team-orchestrator.md +32 -3
- 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 +32 -1
- package/presets/claude/next/team/fixtures/artifact-manifest.example.json +61 -0
- package/presets/claude/next/team/fixtures/bugfix-standard.json +10 -0
- package/presets/claude/next/team/fixtures/feature-full.json +10 -0
- package/presets/claude/next/team/fixtures/feature-light.json +10 -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 +52 -0
- package/presets/claude/php-hexagonal/agents/ci-investigator.md +21 -0
- package/presets/claude/php-hexagonal/agents/code-reviewer.md +47 -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 +54 -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 +32 -0
- package/presets/claude/php-hexagonal/agents/task-router.md +101 -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 +55 -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 +724 -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 +208 -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 +48 -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 +52 -0
- package/presets/claude/php-laravel/agents/ci-investigator.md +21 -0
- package/presets/claude/php-laravel/agents/code-reviewer.md +47 -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 +54 -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 +32 -0
- package/presets/claude/php-laravel/agents/task-router.md +120 -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 +55 -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 +724 -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 +205 -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 +28 -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 +10 -3
- package/presets/cursor/go/agents/code-reviewer.md +8 -1
- package/presets/cursor/go/agents/feature-developer.md +8 -1
- package/presets/cursor/go/agents/task-analyst.md +8 -1
- package/presets/cursor/go/agents/task-router.md +33 -1
- package/presets/cursor/go/commands/task-continue.md +17 -16
- package/presets/cursor/go/commands/task.md +11 -5
- package/presets/cursor/go/commands/technical-retro.md +4 -0
- package/presets/cursor/go/hooks/chain-team-phases.sh +411 -69
- package/presets/cursor/go/rules/README.md +6 -0
- package/presets/cursor/go/rules/agent-team-orchestrator.mdc +33 -4
- 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 +19 -0
- package/presets/cursor/ios-swift/agents/build-verifier.md +11 -4
- package/presets/cursor/ios-swift/agents/code-reviewer.md +9 -14
- package/presets/cursor/ios-swift/agents/feature-developer.md +8 -1
- package/presets/cursor/ios-swift/agents/task-analyst.md +8 -1
- package/presets/cursor/ios-swift/agents/task-router.md +33 -1
- package/presets/cursor/ios-swift/commands/task-continue.md +17 -16
- package/presets/cursor/ios-swift/commands/task.md +11 -5
- package/presets/cursor/ios-swift/commands/technical-retro.md +4 -0
- package/presets/cursor/ios-swift/hooks/chain-team-phases.sh +411 -70
- package/presets/cursor/ios-swift/rules/README.md +6 -0
- package/presets/cursor/ios-swift/rules/agent-team-orchestrator.mdc +26 -1
- 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 +19 -0
- package/presets/cursor/java/agents/build-verifier.md +11 -4
- package/presets/cursor/java/agents/code-reviewer.md +8 -1
- package/presets/cursor/java/agents/feature-developer.md +8 -1
- package/presets/cursor/java/agents/task-analyst.md +8 -1
- package/presets/cursor/java/agents/task-router.md +33 -1
- package/presets/cursor/java/commands/task-continue.md +17 -16
- package/presets/cursor/java/commands/task.md +11 -5
- package/presets/cursor/java/commands/technical-retro.md +4 -0
- package/presets/cursor/java/hooks/chain-team-phases.sh +411 -69
- package/presets/cursor/java/rules/README.md +6 -0
- package/presets/cursor/java/rules/agent-team-orchestrator.mdc +33 -4
- 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 +19 -0
- package/presets/cursor/mcp-ts/agents/build-verifier.md +10 -3
- package/presets/cursor/mcp-ts/agents/feature-developer.md +7 -1
- package/presets/cursor/mcp-ts/agents/task-analyst.md +8 -1
- package/presets/cursor/mcp-ts/agents/task-router.md +33 -1
- package/presets/cursor/mcp-ts/commands/task-continue.md +19 -18
- package/presets/cursor/mcp-ts/commands/task.md +11 -5
- package/presets/cursor/mcp-ts/commands/technical-retro.md +4 -0
- package/presets/cursor/mcp-ts/hooks/chain-team-phases.sh +397 -55
- package/presets/cursor/mcp-ts/rules/README.md +6 -0
- package/presets/cursor/mcp-ts/rules/agent-team-orchestrator.mdc +33 -4
- 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 +19 -0
- package/presets/cursor/next/agents/accessibility-reviewer.md +7 -14
- package/presets/cursor/next/agents/api-contract-reviewer.md +7 -14
- package/presets/cursor/next/agents/build-verifier.md +10 -15
- package/presets/cursor/next/agents/ci-investigator.md +7 -14
- package/presets/cursor/next/agents/code-reviewer.md +9 -14
- package/presets/cursor/next/agents/debugger.md +6 -12
- package/presets/cursor/next/agents/feature-developer.md +8 -1
- package/presets/cursor/next/agents/migration-specialist.md +7 -14
- package/presets/cursor/next/agents/performance-auditor.md +6 -13
- package/presets/cursor/next/agents/qa-tester.md +6 -13
- package/presets/cursor/next/agents/security-reviewer.md +7 -14
- package/presets/cursor/next/agents/solution-architect.md +6 -12
- package/presets/cursor/next/agents/task-analyst.md +10 -16
- package/presets/cursor/next/agents/task-router.md +33 -1
- package/presets/cursor/next/agents/tech-writer.md +6 -13
- package/presets/cursor/next/agents/unit-test-generator.md +6 -11
- package/presets/cursor/next/agents/unit-test-healer.md +6 -11
- package/presets/cursor/next/agents/unit-test-planner.md +6 -13
- package/presets/cursor/next/commands/task-continue.md +17 -16
- package/presets/cursor/next/commands/task.md +11 -5
- package/presets/cursor/next/commands/technical-retro.md +4 -0
- package/presets/cursor/next/hooks/chain-team-phases.sh +417 -70
- package/presets/cursor/next/rules/README.md +6 -0
- package/presets/cursor/next/rules/agent-team-orchestrator.mdc +33 -4
- 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 +33 -2
- package/presets/cursor/next/team/fixtures/artifact-manifest.example.json +61 -0
- package/presets/cursor/next/team/fixtures/bugfix-standard.json +10 -0
- package/presets/cursor/next/team/fixtures/feature-full.json +10 -0
- package/presets/cursor/next/team/fixtures/feature-light.json +10 -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 +52 -0
- package/presets/cursor/php-hexagonal/agents/ci-investigator.md +21 -0
- package/presets/cursor/php-hexagonal/agents/code-reviewer.md +47 -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 +54 -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 +32 -0
- package/presets/cursor/php-hexagonal/agents/task-router.md +101 -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 +55 -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 +724 -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 +202 -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 +52 -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 +52 -0
- package/presets/cursor/php-laravel/agents/ci-investigator.md +21 -0
- package/presets/cursor/php-laravel/agents/code-reviewer.md +47 -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 +54 -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 +32 -0
- package/presets/cursor/php-laravel/agents/task-router.md +120 -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 +55 -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 +724 -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 +203 -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 +28 -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,190 @@ if (!fs.existsSync(statusPath)) {
|
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
let status;
|
|
62
|
+
const now = new Date().toISOString();
|
|
63
|
+
const STACK = 'ios-swift';
|
|
64
|
+
const PLATFORM = 'claude';
|
|
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
|
+
const DEFAULT_ARTIFACT_OUTPUT_IDS = {
|
|
126
|
+
'task-router': 'routing',
|
|
127
|
+
'task-analyst': 'analysis',
|
|
128
|
+
'solution-architect': 'architecture',
|
|
129
|
+
'migration-specialist': 'migration-plan',
|
|
130
|
+
debugger: 'debug',
|
|
131
|
+
'ci-investigator': 'ci',
|
|
132
|
+
'feature-developer': 'implementation',
|
|
133
|
+
'build-verifier': 'validation',
|
|
134
|
+
'code-reviewer': 'review',
|
|
135
|
+
'security-reviewer': 'security-review',
|
|
136
|
+
'accessibility-reviewer': 'a11y-review',
|
|
137
|
+
'performance-auditor': 'perf-report',
|
|
138
|
+
'api-contract-reviewer': 'api-contract-review',
|
|
139
|
+
'tech-writer': 'documentation',
|
|
140
|
+
};
|
|
141
|
+
function artifactOutputIdFor(step, agent) {
|
|
142
|
+
if (step && typeof step.artifactOutputId === 'string') return step.artifactOutputId;
|
|
143
|
+
if (step?.artifactOutputIds && typeof step.artifactOutputIds[agent] === 'string') return step.artifactOutputIds[agent];
|
|
144
|
+
return DEFAULT_ARTIFACT_OUTPUT_IDS[agent] || agent;
|
|
145
|
+
}
|
|
146
|
+
function activateAttempts(step, stepIndex) {
|
|
147
|
+
const active = { ...(status.activeAttempts || {}) }; const agents = getStepAgents(step);
|
|
148
|
+
const parallelGroupId = step.parallel && agents.length > 1 ? `${status.metricsRunId || slug}:step-${stepIndex}` : null;
|
|
149
|
+
for (const agent of agents) {
|
|
150
|
+
const attempt = nextAttemptOrdinal(stepIndex, agent); const runId = status.metricsRunId || `${slug}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
151
|
+
status.metricsRunId = runId; const attemptId = `${runId}:step-${stepIndex}:${agent}:attempt-${attempt}`;
|
|
152
|
+
if (active[attemptId]) continue;
|
|
153
|
+
active[attemptId] = { agent, stepIndex, attempt, startedAt: now, parallelGroupId };
|
|
154
|
+
appendMetric({ type: 'attempt_started', at: now, attemptId, stepIndex, stepLabel: step.label || null, agent, role: roleFor(agent), attempt, parallelGroupId, source: 'hook', attributionConfidence: 'high' });
|
|
155
|
+
}
|
|
156
|
+
status.activeAttempts = active;
|
|
157
|
+
}
|
|
158
|
+
function resolvedAttempt() {
|
|
159
|
+
const active = status.activeAttempts || {}; const entries = Object.entries(active);
|
|
160
|
+
const stableAttemptId = hookInput.attemptId;
|
|
161
|
+
if (stableAttemptId) {
|
|
162
|
+
return active[stableAttemptId] ? { attemptId: stableAttemptId, entry: active[stableAttemptId], confidence: 'high' } : null;
|
|
163
|
+
}
|
|
164
|
+
if (entries.length === 1) return { attemptId: entries[0][0], entry: entries[0][1], confidence: 'high' };
|
|
165
|
+
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 {}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
function readBoundReceiptOutcome(agent, step, resolved) {
|
|
169
|
+
if (!agent || !resolved) return { outcome: null, receiptRequired: false };
|
|
170
|
+
const manifestPath = path.join(taskDir, 'artifact-manifest.json');
|
|
171
|
+
if (!fs.existsSync(manifestPath)) return { outcome: null, receiptRequired: false };
|
|
172
|
+
try {
|
|
173
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
174
|
+
const artifacts = Array.isArray(manifest.artifacts) ? manifest.artifacts : [];
|
|
175
|
+
const expectedOutputId = artifactOutputIdFor(step, agent);
|
|
176
|
+
const attemptStartedAt = Date.parse(resolved.entry.startedAt);
|
|
177
|
+
const owned = artifacts
|
|
178
|
+
.filter((entry) => {
|
|
179
|
+
if (!entry || entry.producer !== agent || !entry.receipt || typeof entry.receipt.outcome !== 'string') return false;
|
|
180
|
+
const boundByAttempt = typeof entry.receipt.attemptId === 'string' && entry.receipt.attemptId === resolved.attemptId;
|
|
181
|
+
const boundByOutput = entry.receipt.attemptId == null && entry.id === expectedOutputId;
|
|
182
|
+
if (!boundByAttempt && !boundByOutput) return false;
|
|
183
|
+
const terminalAt = Date.parse(entry.timestamps?.completedAt || entry.timestamps?.updatedAt || '');
|
|
184
|
+
return Number.isFinite(terminalAt) && (!Number.isFinite(attemptStartedAt) || terminalAt >= attemptStartedAt);
|
|
185
|
+
})
|
|
186
|
+
.sort((a, b) => {
|
|
187
|
+
const ta = Date.parse(a.timestamps?.completedAt || a.timestamps?.updatedAt || 0) || 0;
|
|
188
|
+
const tb = Date.parse(b.timestamps?.completedAt || b.timestamps?.updatedAt || 0) || 0;
|
|
189
|
+
return tb - ta;
|
|
190
|
+
});
|
|
191
|
+
return { outcome: owned[0]?.receipt?.outcome || null, receiptRequired: true };
|
|
192
|
+
} catch {
|
|
193
|
+
return { outcome: null, receiptRequired: false };
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function reconcileStatusFromManifest(agent, step, resolved) {
|
|
197
|
+
const terminal = new Set(['completed', 'blocked', 'changes_requested', 'validation_failed']);
|
|
198
|
+
const { outcome, receiptRequired } = readBoundReceiptOutcome(agent, step, resolved);
|
|
199
|
+
if (terminal.has(outcome)) {
|
|
200
|
+
status.state = outcome;
|
|
201
|
+
return outcome;
|
|
202
|
+
}
|
|
203
|
+
if (receiptRequired) {
|
|
204
|
+
status.state = 'awaiting_artifact_receipt';
|
|
205
|
+
status.phase = 'blocked';
|
|
206
|
+
return status.state;
|
|
207
|
+
}
|
|
208
|
+
if (terminal.has(status.state)) return status.state;
|
|
209
|
+
// Host reported subagent completed and no blocking receipt → treat as completed for metrics/advance.
|
|
210
|
+
if (hookInput.status === 'completed') {
|
|
211
|
+
status.state = 'completed';
|
|
212
|
+
return 'completed';
|
|
213
|
+
}
|
|
214
|
+
return status.state;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function finishActiveAttempt() {
|
|
218
|
+
const resolved = resolvedAttempt(); if (!resolved) return null;
|
|
219
|
+
const durationMs = Date.parse(now) - Date.parse(resolved.entry.startedAt);
|
|
220
|
+
const outcome = ['completed', 'blocked', 'changes_requested', 'validation_failed'].includes(status.state) ? status.state : 'unknown';
|
|
221
|
+
appendMetric({ type: 'attempt_finished', at: now, attemptId: resolved.attemptId, outcome, durationMs: Number.isFinite(durationMs) && durationMs >= 0 ? durationMs : null, retryAfterFix: status.retryAfterFix || null, source: resolved.source || 'hook', attributionConfidence: resolved.confidence });
|
|
222
|
+
const active = { ...(status.activeAttempts || {}) }; delete active[resolved.attemptId]; status.activeAttempts = active; status.lastCompletedAttempt = { attemptId: resolved.attemptId, completedAt: now }; return { ...resolved, outcome };
|
|
223
|
+
}
|
|
224
|
+
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; }
|
|
225
|
+
function endHumanGateIfResumed() {
|
|
226
|
+
if (!status.activeHumanGateEventId || status.awaitingHumanGate || status.state === 'awaiting_approval') return;
|
|
227
|
+
appendMetric({ type: 'human_gate_ended', at: now, gateStartedEventId: status.activeHumanGateEventId, source: 'hook', attributionConfidence: 'high' });
|
|
228
|
+
delete status.activeHumanGateEventId;
|
|
229
|
+
}
|
|
230
|
+
function completeTaskMetrics() { appendMetric({ type: 'task_completed', at: now, outcome: status.state === 'completed' ? 'completed' : 'unknown', source: 'hook', attributionConfidence: 'high' }); }
|
|
231
|
+
function recordSkippedStep(step, stepIndex) {
|
|
232
|
+
for (const agent of getStepAgents(step)) {
|
|
233
|
+
const runId = status.metricsRunId || `${slug}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
234
|
+
status.metricsRunId = runId;
|
|
235
|
+
const attempt = nextAttemptOrdinal(stepIndex, agent);
|
|
236
|
+
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' });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
66
239
|
|
|
67
|
-
const now = new Date().toISOString();
|
|
68
240
|
|
|
69
241
|
function writeStatus(next) {
|
|
70
242
|
status = { ...status, ...next, slug, updatedAt: now };
|
|
71
|
-
|
|
243
|
+
const temporary = `${statusPath}.${process.pid}.${Date.now()}.tmp`;
|
|
244
|
+
fs.writeFileSync(temporary, JSON.stringify(status, null, 2) + '\n');
|
|
245
|
+
fs.renameSync(temporary, statusPath);
|
|
72
246
|
}
|
|
73
247
|
|
|
74
248
|
function out(message) {
|
|
@@ -105,9 +279,8 @@ function skipIfMatches(skipIf, dir) {
|
|
|
105
279
|
|
|
106
280
|
function findNextExecutableStep(steps, startIdx, dir) {
|
|
107
281
|
for (let i = startIdx; i < steps.length; i++) {
|
|
108
|
-
if (!skipIfMatches(steps[i].skipIf, dir)) {
|
|
109
|
-
|
|
110
|
-
}
|
|
282
|
+
if (!skipIfMatches(steps[i].skipIf, dir)) return { step: steps[i], index: i };
|
|
283
|
+
recordSkippedStep(steps[i], i);
|
|
111
284
|
}
|
|
112
285
|
return null;
|
|
113
286
|
}
|
|
@@ -115,56 +288,56 @@ function findNextExecutableStep(steps, startIdx, dir) {
|
|
|
115
288
|
const AGENT_HANDOFF = {
|
|
116
289
|
'task-analyst': (s) =>
|
|
117
290
|
`Invoke task-analyst for slug "${s}". Write brief.md and decomposition.md under .claude/team/tasks/${s}/. ` +
|
|
118
|
-
`
|
|
291
|
+
`Upsert the analysis receipt in artifact-manifest.json; do not mutate status.json lifecycle fields. Do not use legacy phase analysis.`,
|
|
119
292
|
debugger: (s) =>
|
|
120
293
|
`Invoke debugger subagent for slug "${s}". Investigate root cause; write debug-report.md with fixApplied: true/false. ` +
|
|
121
|
-
`
|
|
294
|
+
`Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
122
295
|
'solution-architect': (s) =>
|
|
123
|
-
`Invoke solution-architect for slug "${s}". Read brief.md; write architecture.md.
|
|
296
|
+
`Invoke solution-architect for slug "${s}". Read brief.md; write architecture.md. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
124
297
|
'migration-specialist': (s) =>
|
|
125
|
-
`Invoke migration-specialist for slug "${s}". Read brief.md; write migration-plan.md.
|
|
298
|
+
`Invoke migration-specialist for slug "${s}". Read brief.md; write migration-plan.md. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
126
299
|
'api-contract-reviewer': (s) =>
|
|
127
|
-
`Invoke api-contract-reviewer (readonly) for slug "${s}". Write api-contract-review.md.
|
|
300
|
+
`Invoke api-contract-reviewer (readonly) for slug "${s}". Write api-contract-review.md. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
128
301
|
'ci-investigator': (s) =>
|
|
129
302
|
`Invoke ci-investigator for slug "${s}". Diagnose CI failure; write ci-report.md; apply minimal fix. ` +
|
|
130
|
-
`Use ci-investigation skill.
|
|
303
|
+
`Use ci-investigation skill. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
131
304
|
'feature-developer': (s) =>
|
|
132
305
|
`Invoke feature-developer for slug "${s}". Read brief.md, decomposition.md, validation-report.md, review.md, architecture.md, migration-plan.md, api-contract-review.md, debug-report.md if present. ` +
|
|
133
306
|
`Follow feature-delivery-workflow.mdc and reference-features.mdc. Prefer Features/Presentation/Domain/Data (or SPM module) paths over app/src. ` +
|
|
134
|
-
`Include XCTest/Swift Testing unit coverage for mappers/logic before handoff.
|
|
307
|
+
`Include XCTest/Swift Testing unit coverage for mappers/logic before handoff. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
135
308
|
'build-verifier': (s) =>
|
|
136
309
|
`Invoke build-verifier (readonly) for slug "${s}". Follow xcode-tooling.mdc and post-change-build.mdc. ` +
|
|
137
310
|
`Run xcodebuild (or swift build/test for SPM-only), SwiftLint/SwiftFormat if configured, and targeted unit smoke — never yarn/ESLint/Stylelint from app/. ` +
|
|
138
|
-
`Write validation-report.md
|
|
311
|
+
`Write validation-report.md and emit receipt outcome completed or validation_failed. Do not edit production code.`,
|
|
139
312
|
'accessibility-reviewer': (s) =>
|
|
140
|
-
`Invoke accessibility-reviewer (readonly) for slug "${s}". Review Presentation/SwiftUI (or UIKit) diff for VoiceOver/Dynamic Type/accessibilityIdentifier; write a11y-review.md.
|
|
313
|
+
`Invoke accessibility-reviewer (readonly) for slug "${s}". Review Presentation/SwiftUI (or UIKit) diff for VoiceOver/Dynamic Type/accessibilityIdentifier; write a11y-review.md. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
141
314
|
'performance-auditor': (s) =>
|
|
142
|
-
`Invoke performance-auditor (readonly) for slug "${s}". Audit launch/SwiftUI performance risks; write perf-report.md.
|
|
315
|
+
`Invoke performance-auditor (readonly) for slug "${s}". Audit launch/SwiftUI performance risks; write perf-report.md. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
143
316
|
'code-reviewer': (s) =>
|
|
144
317
|
`Invoke code-reviewer subagent (readonly) for slug "${s}". Review git diff vs brief.md per code-review-mr.mdc. ` +
|
|
145
|
-
`
|
|
318
|
+
`Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
146
319
|
'security-reviewer': (s) =>
|
|
147
|
-
`Invoke security-reviewer (readonly) for slug "${s}". Write security-review.md.
|
|
320
|
+
`Invoke security-reviewer (readonly) for slug "${s}". Write security-review.md. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
148
321
|
'qa-tester': (s, scope) =>
|
|
149
322
|
`Invoke qa-tester for slug "${s}"${scope ? ` (scope: ${scope})` : ''}. ` +
|
|
150
|
-
`Add/update XCTest and XCUITest (*UITests) per brief. Follow tests-ui.mdc and skill xcuitest-e2e.
|
|
323
|
+
`Add/update XCTest and XCUITest (*UITests) per brief. Follow tests-ui.mdc and skill xcuitest-e2e. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
151
324
|
'unit-test-planner': (s) =>
|
|
152
|
-
`Invoke unit-test-planner for slug "${s}". Write unit-test-plan.md for XCTest/Swift Testing. Use unit-testing skill.
|
|
325
|
+
`Invoke unit-test-planner for slug "${s}". Write unit-test-plan.md for XCTest/Swift Testing. Use unit-testing skill. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
153
326
|
'unit-test-generator': (s) =>
|
|
154
|
-
`Invoke unit-test-generator for slug "${s}". Implement *Tests from unit-test-plan.md. Use unit-testing skill.
|
|
327
|
+
`Invoke unit-test-generator for slug "${s}". Implement *Tests from unit-test-plan.md. Use unit-testing skill. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
155
328
|
'unit-test-healer': (s) =>
|
|
156
|
-
`Invoke unit-test-healer for slug "${s}". Fix failing unit tests. Use unit-testing and debug-investigation skills.
|
|
329
|
+
`Invoke unit-test-healer for slug "${s}". Fix failing unit tests. Use unit-testing and debug-investigation skills. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
157
330
|
'xcuitest-test-planner': (s) =>
|
|
158
331
|
`Invoke xcuitest-test-planner for slug "${s}". Create/update XCUITest plans (*UITests / *.cases.md if used). ` +
|
|
159
|
-
`Follow tests-ui.mdc and the xcuitest-e2e skill. Do not use Playwright MCP.
|
|
332
|
+
`Follow tests-ui.mdc and the xcuitest-e2e skill. Do not use Playwright MCP. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
160
333
|
'xcuitest-test-generator': (s) =>
|
|
161
334
|
`Invoke xcuitest-test-generator for slug "${s}". Generate/update *UITests from matching plans/*.cases.md. ` +
|
|
162
|
-
`Follow tests-ui.mdc and the xcuitest-e2e skill. Do not use Playwright MCP.
|
|
335
|
+
`Follow tests-ui.mdc and the xcuitest-e2e skill. Do not use Playwright MCP. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
163
336
|
'xcuitest-test-healer': (s) =>
|
|
164
337
|
`Invoke xcuitest-test-healer for slug "${s}". Fix failing/flaky XCUITest while preserving plan assertions. ` +
|
|
165
|
-
`Follow tests-ui.mdc, xcuitest-e2e, and debug-investigation. Do not use Playwright MCP.
|
|
338
|
+
`Follow tests-ui.mdc, xcuitest-e2e, and debug-investigation. Do not use Playwright MCP. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
166
339
|
'tech-writer': (s) =>
|
|
167
|
-
`Invoke tech-writer for slug "${s}". Write documentation.md from task artifacts.
|
|
340
|
+
`Invoke tech-writer for slug "${s}". Write documentation.md from task artifacts. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
|
|
168
341
|
};
|
|
169
342
|
|
|
170
343
|
const REVIEW_AGENTS = new Set([
|
|
@@ -174,16 +347,35 @@ const REVIEW_AGENTS = new Set([
|
|
|
174
347
|
'api-contract-reviewer',
|
|
175
348
|
]);
|
|
176
349
|
|
|
177
|
-
function
|
|
350
|
+
function metricsHandoff(agent) {
|
|
351
|
+
const matches = Object.entries(status.activeAttempts || {}).filter(([, entry]) => entry.agent === agent);
|
|
352
|
+
if (matches.length === 1) {
|
|
353
|
+
return ` Metrics attemptId: ${matches[0][0]}; write owned artifact-manifest receipt outcome. If the hook cannot identify a parallel stop, append a minimal { attemptId, outcome } receipt to .metrics-receipts.json; do not mutate status.json or calculate duration.`;
|
|
354
|
+
}
|
|
355
|
+
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.';
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function artifactHandoff(step, agent) {
|
|
359
|
+
const inputIds = Array.isArray(step?.artifactInputIds) ? step.artifactInputIds.join(', ') : 'manifest defaults';
|
|
360
|
+
return ` Artifact inputs: ${inputIds}; owned output ID: ${artifactOutputIdFor(step, agent)}. Bind the terminal receipt to the supplied attemptId.`;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function handoffForAgent(agent, scope, step = null) {
|
|
178
364
|
const fn = AGENT_HANDOFF[agent];
|
|
179
|
-
|
|
365
|
+
const handoff = fn ? fn(slug, scope) : `Invoke ${agent} subagent for slug "${slug}". Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`;
|
|
366
|
+
return handoff + artifactHandoff(step, agent) + metricsHandoff(agent);
|
|
180
367
|
}
|
|
181
368
|
|
|
182
369
|
function handoffForParallelStep(step) {
|
|
183
370
|
const agents = getStepAgents(step);
|
|
371
|
+
const attemptIds = Object.entries(status.activeAttempts || {})
|
|
372
|
+
.filter(([, entry]) => agents.includes(entry.agent))
|
|
373
|
+
.map(([attemptId, entry]) => `${entry.agent}=${attemptId}`);
|
|
184
374
|
return (
|
|
185
375
|
`Invoke IN PARALLEL (one message, multiple Task calls): ${agents.join(' AND ')} for slug "${slug}". ` +
|
|
186
|
-
`Each agent writes its artifact and
|
|
376
|
+
`Each agent writes its artifact and owned receipt; the hook records parallelCompleted from stops. Do not mutate status.json lifecycle fields. ` +
|
|
377
|
+
`Artifact inputs: ${Array.isArray(step.artifactInputIds) ? step.artifactInputIds.join(', ') : 'manifest defaults'}; owned output IDs: ${agents.map((agent) => `${agent}=${artifactOutputIdFor(step, agent)}`).join('; ')}. ` +
|
|
378
|
+
`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.`
|
|
187
379
|
);
|
|
188
380
|
}
|
|
189
381
|
|
|
@@ -215,34 +407,42 @@ function legacyFlow() {
|
|
|
215
407
|
out(handoffForAgent('qa-tester'));
|
|
216
408
|
process.exit(0);
|
|
217
409
|
}
|
|
218
|
-
|
|
410
|
+
function scheduleLegacyRetry(agent, retryAfterFix) {
|
|
411
|
+
const stepIndex = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
412
|
+
const predecessorAttemptId = status.lastCompletedAttempt?.attemptId || null;
|
|
413
|
+
appendMetric({ type: 'retry_scheduled', at: now, attemptId: predecessorAttemptId, nextAgent: agent, retryAfterFix: retryAfterFix || null, source: 'hook', attributionConfidence: 'unknown' });
|
|
414
|
+
activateAttempts({ agent }, stepIndex);
|
|
415
|
+
}
|
|
416
|
+
if (status.state === 'changes_requested') {
|
|
417
|
+
const reviewer = status.currentAgent;
|
|
418
|
+
if (!reviewer) {
|
|
419
|
+
process.stdout.write('{}');
|
|
420
|
+
process.exit(0);
|
|
421
|
+
}
|
|
422
|
+
scheduleLegacyRetry('feature-developer', reviewer);
|
|
219
423
|
writeStatus({
|
|
220
424
|
currentAgent: 'feature-developer',
|
|
221
425
|
state: 'in_progress',
|
|
222
426
|
phase: 'executing',
|
|
223
|
-
retryAfterFix:
|
|
427
|
+
retryAfterFix: reviewer,
|
|
224
428
|
});
|
|
225
|
-
out(
|
|
226
|
-
handoffForAgent('feature-developer') +
|
|
227
|
-
` After fixes, re-run ${status.currentAgent}.`,
|
|
228
|
-
);
|
|
429
|
+
out(handoffForAgent('feature-developer') + ` After fixes, re-run ${reviewer}.`);
|
|
229
430
|
process.exit(0);
|
|
230
431
|
}
|
|
231
432
|
if (status.state === 'validation_failed' && status.currentAgent === 'build-verifier') {
|
|
433
|
+
scheduleLegacyRetry('feature-developer', 'build-verifier');
|
|
232
434
|
writeStatus({
|
|
233
435
|
currentAgent: 'feature-developer',
|
|
234
436
|
state: 'in_progress',
|
|
235
437
|
phase: 'executing',
|
|
236
438
|
retryAfterFix: 'build-verifier',
|
|
237
439
|
});
|
|
238
|
-
out(
|
|
239
|
-
handoffForAgent('feature-developer') +
|
|
240
|
-
` Read validation-report.md. After fixes, re-run build-verifier.`,
|
|
241
|
-
);
|
|
440
|
+
out(handoffForAgent('feature-developer') + ' Read validation-report.md. After fixes, re-run build-verifier.');
|
|
242
441
|
process.exit(0);
|
|
243
442
|
}
|
|
244
443
|
if (status.state === 'completed' && status.retryAfterFix) {
|
|
245
444
|
const retry = status.retryAfterFix;
|
|
445
|
+
scheduleLegacyRetry(retry, null);
|
|
246
446
|
writeStatus({ currentAgent: retry, state: 'in_progress', retryAfterFix: null });
|
|
247
447
|
out(handoffForAgent(retry));
|
|
248
448
|
process.exit(0);
|
|
@@ -256,6 +456,56 @@ function legacyFlow() {
|
|
|
256
456
|
process.exit(0);
|
|
257
457
|
}
|
|
258
458
|
|
|
459
|
+
|
|
460
|
+
if (hookInput.action === 'end_human_gate') {
|
|
461
|
+
status.awaitingHumanGate = false;
|
|
462
|
+
if (status.state === 'awaiting_approval') {
|
|
463
|
+
status.state = 'in_progress';
|
|
464
|
+
status.phase = status.phase === 'human_gate' ? 'executing' : status.phase;
|
|
465
|
+
}
|
|
466
|
+
if (status.activeHumanGateEventId) {
|
|
467
|
+
appendMetric({
|
|
468
|
+
type: 'human_gate_ended',
|
|
469
|
+
at: now,
|
|
470
|
+
gateStartedEventId: status.activeHumanGateEventId,
|
|
471
|
+
source: 'orchestrator',
|
|
472
|
+
attributionConfidence: 'high',
|
|
473
|
+
});
|
|
474
|
+
delete status.activeHumanGateEventId;
|
|
475
|
+
}
|
|
476
|
+
if (hookInput.activateNext && fs.existsSync(pipelinePath)) {
|
|
477
|
+
let resumePipeline = null;
|
|
478
|
+
try { resumePipeline = JSON.parse(fs.readFileSync(pipelinePath, 'utf8')); } catch {}
|
|
479
|
+
if (resumePipeline) {
|
|
480
|
+
const resumeSteps = resumePipeline.steps || [];
|
|
481
|
+
const resumeStart = (typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0) + 1;
|
|
482
|
+
const resumeNext = findNextExecutableStep(resumeSteps, resumeStart, taskDir);
|
|
483
|
+
if (resumeNext) {
|
|
484
|
+
const resumeAgents = getStepAgents(resumeNext.step);
|
|
485
|
+
activateAttempts(resumeNext.step, resumeNext.index);
|
|
486
|
+
writeStatus({
|
|
487
|
+
pipelineIndex: resumeNext.index,
|
|
488
|
+
currentAgent: resumeAgents[0],
|
|
489
|
+
phase: 'executing',
|
|
490
|
+
state: 'in_progress',
|
|
491
|
+
awaitingHumanGate: false,
|
|
492
|
+
parallelCompleted: [],
|
|
493
|
+
});
|
|
494
|
+
if (resumeNext.step.parallel && resumeAgents.length > 1) out(handoffForParallelStep(resumeNext.step));
|
|
495
|
+
else out(handoffForAgent(resumeAgents[0], resumeNext.step.scope, resumeNext.step));
|
|
496
|
+
process.exit(0);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
writeStatus({
|
|
501
|
+
awaitingHumanGate: false,
|
|
502
|
+
state: status.state,
|
|
503
|
+
phase: status.phase,
|
|
504
|
+
});
|
|
505
|
+
process.stdout.write(JSON.stringify({ ok: true, action: 'end_human_gate', activeHumanGateEventId: status.activeHumanGateEventId || null }));
|
|
506
|
+
process.exit(0);
|
|
507
|
+
}
|
|
508
|
+
|
|
259
509
|
if (!fs.existsSync(pipelinePath)) {
|
|
260
510
|
legacyFlow();
|
|
261
511
|
}
|
|
@@ -268,7 +518,30 @@ try {
|
|
|
268
518
|
}
|
|
269
519
|
|
|
270
520
|
const steps = pipeline.steps || [];
|
|
521
|
+
const initialIdx = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
522
|
+
const initialStep = steps[initialIdx];
|
|
523
|
+
const activeAttemptCountBeforeFinish = Object.keys(status.activeAttempts || {}).length;
|
|
524
|
+
const completingAgentHint = (() => {
|
|
525
|
+
const resolved = resolvedAttempt();
|
|
526
|
+
if (resolved?.entry?.agent) return resolved.entry.agent;
|
|
527
|
+
if (status.currentAgent) return status.currentAgent;
|
|
528
|
+
return getStepAgents(initialStep)[0];
|
|
529
|
+
})();
|
|
530
|
+
const reconcilingAttempt = resolvedAttempt();
|
|
531
|
+
reconcileStatusFromManifest(completingAgentHint, initialStep, reconcilingAttempt);
|
|
532
|
+
if (status.state === 'awaiting_artifact_receipt') {
|
|
533
|
+
writeStatus({});
|
|
534
|
+
process.stdout.write('{}');
|
|
535
|
+
process.exit(0);
|
|
536
|
+
}
|
|
537
|
+
const finishedAttempt = finishActiveAttempt();
|
|
538
|
+
if (!finishedAttempt && (hookInput.attemptId || activeAttemptCountBeforeFinish > 0)) {
|
|
539
|
+
process.stdout.write('{}');
|
|
540
|
+
process.exit(0);
|
|
541
|
+
}
|
|
542
|
+
endHumanGateIfResumed();
|
|
271
543
|
if (steps.length === 0 || pipeline.autoChain === false) {
|
|
544
|
+
writeStatus({});
|
|
272
545
|
process.stdout.write('{}');
|
|
273
546
|
process.exit(0);
|
|
274
547
|
}
|
|
@@ -278,68 +551,116 @@ if (status.awaitingHumanGate || status.state === 'awaiting_approval') {
|
|
|
278
551
|
process.exit(0);
|
|
279
552
|
}
|
|
280
553
|
|
|
281
|
-
|
|
282
|
-
|
|
554
|
+
function nearestPrecedingStepIndex(agent, fromIndex, fallback) {
|
|
555
|
+
for (let index = fromIndex - 1; index >= 0; index -= 1) {
|
|
556
|
+
if (getStepAgents(steps[index]).includes(agent)) return index;
|
|
557
|
+
}
|
|
558
|
+
const match = steps.findIndex((step) => getStepAgents(step).includes(agent));
|
|
559
|
+
return match >= 0 ? match : fallback;
|
|
560
|
+
}
|
|
561
|
+
function scheduleRetry(agent, retryAfterFix, predecessor, explicitStepIndex = null) {
|
|
562
|
+
const currentIndex = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
563
|
+
const stepIndex = Number.isInteger(explicitStepIndex) ? explicitStepIndex : nearestPrecedingStepIndex(agent, currentIndex, currentIndex);
|
|
564
|
+
const predecessorAttemptId = predecessor?.attemptId || status.lastCompletedAttempt?.attemptId || null;
|
|
565
|
+
appendMetric({ type: 'retry_scheduled', at: now, attemptId: predecessorAttemptId, nextAgent: agent, retryAfterFix: retryAfterFix || null, source: 'hook', attributionConfidence: predecessor ? predecessor.confidence : 'unknown' });
|
|
566
|
+
activateAttempts(steps[stepIndex] || { agent }, stepIndex);
|
|
567
|
+
return stepIndex;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const idx = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
571
|
+
const currentStep = steps[idx];
|
|
572
|
+
const completedAgent = finishedAttempt?.entry?.agent || status.currentAgent || getStepAgents(currentStep)[0];
|
|
573
|
+
const stepAgents = getStepAgents(currentStep);
|
|
574
|
+
|
|
575
|
+
if (currentStep?.parallel && stepAgents.length > 1) {
|
|
576
|
+
const done = [...(status.parallelCompleted || [])];
|
|
577
|
+
const outcomes = { ...(status.parallelOutcomes || {}) };
|
|
578
|
+
if (finishedAttempt && completedAgent) {
|
|
579
|
+
if (!done.includes(completedAgent)) done.push(completedAgent);
|
|
580
|
+
outcomes[completedAgent] = { outcome: finishedAttempt.outcome || status.state, attemptId: finishedAttempt.attemptId, confidence: finishedAttempt.confidence };
|
|
581
|
+
}
|
|
582
|
+
writeStatus({ parallelCompleted: done, parallelOutcomes: outcomes });
|
|
583
|
+
const remaining = stepAgents.filter((agent) => !done.includes(agent));
|
|
584
|
+
if (remaining.length > 0) {
|
|
585
|
+
process.stdout.write('{}');
|
|
586
|
+
process.exit(0);
|
|
587
|
+
}
|
|
588
|
+
const blockedProducer = stepAgents.find((agent) => outcomes[agent]?.outcome === 'blocked');
|
|
589
|
+
if (blockedProducer) {
|
|
590
|
+
writeStatus({ parallelCompleted: [], parallelOutcomes: {}, state: 'blocked', phase: 'blocked', currentAgent: blockedProducer });
|
|
591
|
+
process.stdout.write('{}');
|
|
592
|
+
process.exit(0);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
const retryReviewer = stepAgents.find((agent) => outcomes[agent]?.outcome === 'changes_requested');
|
|
596
|
+
if (retryReviewer) {
|
|
597
|
+
const retryAfterFixStepIndex = idx;
|
|
598
|
+
const predecessor = outcomes[retryReviewer] ? { attemptId: outcomes[retryReviewer].attemptId, confidence: outcomes[retryReviewer].confidence } : finishedAttempt;
|
|
599
|
+
const developerIndex = scheduleRetry('feature-developer', retryReviewer, predecessor);
|
|
600
|
+
writeStatus({ pipelineIndex: developerIndex, currentAgent: 'feature-developer', state: 'in_progress', phase: 'executing', retryAfterFix: retryReviewer, retryAfterFixStepIndex, parallelCompleted: [], parallelOutcomes: {} });
|
|
601
|
+
out(handoffForAgent('feature-developer', steps[developerIndex]?.scope, steps[developerIndex]) + ` After fixes, re-run ${retryReviewer}.`);
|
|
602
|
+
process.exit(0);
|
|
603
|
+
}
|
|
604
|
+
writeStatus({ parallelCompleted: [], parallelOutcomes: {}, state: 'completed' });
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
if (status.state === 'blocked') {
|
|
608
|
+
writeStatus({ state: 'blocked', phase: 'blocked', currentAgent: completedAgent });
|
|
609
|
+
process.stdout.write('{}');
|
|
610
|
+
process.exit(0);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
if (status.state === 'changes_requested') {
|
|
614
|
+
const reviewer = status.currentAgent || finishedAttempt?.entry?.agent;
|
|
615
|
+
if (!reviewer) {
|
|
616
|
+
process.stdout.write('{}');
|
|
617
|
+
process.exit(0);
|
|
618
|
+
}
|
|
619
|
+
const retryAfterFixStepIndex = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
620
|
+
const developerIndex = scheduleRetry('feature-developer', reviewer, finishedAttempt);
|
|
283
621
|
writeStatus({
|
|
622
|
+
pipelineIndex: developerIndex,
|
|
284
623
|
currentAgent: 'feature-developer',
|
|
285
624
|
state: 'in_progress',
|
|
286
625
|
phase: 'executing',
|
|
287
626
|
retryAfterFix: reviewer,
|
|
627
|
+
retryAfterFixStepIndex,
|
|
288
628
|
});
|
|
289
|
-
out(
|
|
290
|
-
handoffForAgent('feature-developer') +
|
|
291
|
-
` After fixes, re-run ${reviewer}.`,
|
|
292
|
-
);
|
|
629
|
+
out(handoffForAgent('feature-developer', steps[developerIndex]?.scope, steps[developerIndex]) + ` After fixes, re-run ${reviewer}.`);
|
|
293
630
|
process.exit(0);
|
|
294
631
|
}
|
|
295
632
|
|
|
296
633
|
if (status.state === 'validation_failed' && status.currentAgent === 'build-verifier') {
|
|
634
|
+
const retryAfterFixStepIndex = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
635
|
+
const developerIndex = scheduleRetry('feature-developer', 'build-verifier', finishedAttempt);
|
|
297
636
|
writeStatus({
|
|
637
|
+
pipelineIndex: developerIndex,
|
|
298
638
|
currentAgent: 'feature-developer',
|
|
299
639
|
state: 'in_progress',
|
|
300
640
|
phase: 'executing',
|
|
301
641
|
retryAfterFix: 'build-verifier',
|
|
642
|
+
retryAfterFixStepIndex,
|
|
302
643
|
});
|
|
303
|
-
out(
|
|
304
|
-
handoffForAgent('feature-developer') +
|
|
305
|
-
` Read validation-report.md. After fixes, re-run build-verifier.`,
|
|
306
|
-
);
|
|
644
|
+
out(handoffForAgent('feature-developer', steps[developerIndex]?.scope, steps[developerIndex]) + ' Read validation-report.md. After fixes, re-run build-verifier.');
|
|
307
645
|
process.exit(0);
|
|
308
646
|
}
|
|
309
647
|
|
|
310
648
|
if (status.state === 'completed' && status.retryAfterFix) {
|
|
311
649
|
const retry = status.retryAfterFix;
|
|
312
|
-
|
|
313
|
-
|
|
650
|
+
const retryIndex = scheduleRetry(retry, null, finishedAttempt, status.retryAfterFixStepIndex);
|
|
651
|
+
writeStatus({ pipelineIndex: retryIndex, currentAgent: retry, state: 'in_progress', retryAfterFix: null, retryAfterFixStepIndex: null });
|
|
652
|
+
out(handoffForAgent(retry, steps[retryIndex]?.scope, steps[retryIndex]));
|
|
314
653
|
process.exit(0);
|
|
315
654
|
}
|
|
316
655
|
|
|
317
|
-
const idx = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
318
|
-
const currentStep = steps[idx];
|
|
319
656
|
if (!currentStep) {
|
|
320
657
|
writeStatus({ phase: 'done', state: 'completed', currentAgent: null });
|
|
321
658
|
out(`Pipeline complete for "${slug}". Run /technical-retro ${slug}.`);
|
|
322
659
|
process.exit(0);
|
|
323
660
|
}
|
|
324
661
|
|
|
325
|
-
const completedAgent = status.currentAgent || getStepAgents(currentStep)[0];
|
|
326
|
-
const stepAgents = getStepAgents(currentStep);
|
|
327
|
-
|
|
328
|
-
if (currentStep.parallel && stepAgents.length > 1) {
|
|
329
|
-
const done = [...(status.parallelCompleted || [])];
|
|
330
|
-
if (completedAgent && !done.includes(completedAgent)) {
|
|
331
|
-
done.push(completedAgent);
|
|
332
|
-
}
|
|
333
|
-
writeStatus({ parallelCompleted: done });
|
|
334
|
-
const remaining = stepAgents.filter((a) => !done.includes(a));
|
|
335
|
-
if (remaining.length > 0) {
|
|
336
|
-
process.stdout.write('{}');
|
|
337
|
-
process.exit(0);
|
|
338
|
-
}
|
|
339
|
-
writeStatus({ parallelCompleted: [] });
|
|
340
|
-
}
|
|
341
|
-
|
|
342
662
|
if (hasGateAfterStep(currentStep, pipeline.humanGates)) {
|
|
663
|
+
beginHumanGate();
|
|
343
664
|
writeStatus({
|
|
344
665
|
awaitingHumanGate: true,
|
|
345
666
|
state: 'awaiting_approval',
|
|
@@ -351,6 +672,7 @@ if (hasGateAfterStep(currentStep, pipeline.humanGates)) {
|
|
|
351
672
|
|
|
352
673
|
const next = findNextExecutableStep(steps, idx + 1, taskDir);
|
|
353
674
|
if (!next) {
|
|
675
|
+
completeTaskMetrics();
|
|
354
676
|
writeStatus({
|
|
355
677
|
pipelineIndex: steps.length,
|
|
356
678
|
phase: 'done',
|
|
@@ -365,6 +687,7 @@ if (!next) {
|
|
|
365
687
|
const { step: nextStep, index: nextIdx } = next;
|
|
366
688
|
const nextAgents = getStepAgents(nextStep);
|
|
367
689
|
|
|
690
|
+
activateAttempts(nextStep, nextIdx);
|
|
368
691
|
writeStatus({
|
|
369
692
|
pipelineIndex: nextIdx,
|
|
370
693
|
currentAgent: nextAgents[0],
|
|
@@ -377,6 +700,6 @@ writeStatus({
|
|
|
377
700
|
if (nextStep.parallel && nextAgents.length > 1) {
|
|
378
701
|
out(handoffForParallelStep(nextStep));
|
|
379
702
|
} else {
|
|
380
|
-
out(handoffForAgent(nextAgents[0], nextStep.scope));
|
|
703
|
+
out(handoffForAgent(nextAgents[0], nextStep.scope, nextStep));
|
|
381
704
|
}
|
|
382
705
|
NODE
|
|
@@ -77,3 +77,9 @@ Shared taxonomy: `presets/_shared/README.md`. Sync marker: `<!-- shared-core:
|
|
|
77
77
|
| `testing/` | XCTest, XCUITest |
|
|
78
78
|
| `ui-and-accessibility/` | SwiftUI, ViewModels, navigation |
|
|
79
79
|
| `tooling-and-review/` | Quality, review, build, security, tooling, agent-team, retro, **preset meta** |
|
|
80
|
+
|
|
81
|
+
## Metrics policy mapping
|
|
82
|
+
|
|
83
|
+
| Shared core | Runtime integration | Loading |
|
|
84
|
+
|-------------|---------------------|---------|
|
|
85
|
+
| `agent-team/agent-task-metrics.md` | `agent-team-orchestrator` + `hooks/chain-team-phases.sh` | requestable/on-demand; never session-start |
|