@bonesofspring/ai-rules 0.2.2 → 0.2.4
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 +65 -0
- package/README.md +27 -4
- package/bin/cli.js +285 -72
- package/package.json +3 -2
- package/presets/claude/ios-swift/CLAUDE.md +28 -20
- package/presets/claude/ios-swift/MCP.md +14 -0
- package/presets/claude/ios-swift/README.md +18 -15
- package/presets/claude/ios-swift/agents/README.md +55 -0
- package/presets/claude/ios-swift/agents/accessibility-reviewer.md +67 -0
- package/presets/claude/ios-swift/agents/api-contract-reviewer.md +72 -0
- package/presets/claude/ios-swift/agents/build-verifier.md +64 -0
- package/presets/claude/ios-swift/agents/ci-investigator.md +73 -0
- package/presets/claude/ios-swift/agents/code-reviewer.md +75 -0
- package/presets/claude/ios-swift/agents/debugger.md +72 -0
- package/presets/claude/ios-swift/agents/feature-developer.md +35 -0
- package/presets/claude/ios-swift/agents/migration-specialist.md +73 -0
- package/presets/claude/ios-swift/agents/performance-auditor.md +72 -0
- package/presets/claude/ios-swift/agents/qa-tester.md +65 -0
- package/presets/claude/ios-swift/agents/security-reviewer.md +69 -0
- package/presets/claude/ios-swift/agents/solution-architect.md +17 -0
- package/presets/claude/ios-swift/agents/task-analyst.md +25 -0
- package/presets/claude/ios-swift/agents/task-router.md +62 -0
- package/presets/claude/ios-swift/agents/tech-writer.md +63 -0
- package/presets/claude/ios-swift/agents/unit-test-generator.md +54 -0
- package/presets/claude/ios-swift/agents/unit-test-healer.md +53 -0
- package/presets/claude/ios-swift/agents/unit-test-planner.md +64 -0
- package/presets/claude/ios-swift/agents/xcuitest-test-generator.md +47 -0
- package/presets/claude/ios-swift/agents/xcuitest-test-healer.md +47 -0
- package/presets/claude/ios-swift/agents/xcuitest-test-planner.md +67 -0
- package/presets/claude/ios-swift/commands/README.md +12 -2
- package/presets/claude/ios-swift/commands/feature-continue.md +51 -0
- package/presets/claude/ios-swift/commands/feature-start.md +30 -0
- package/presets/claude/ios-swift/commands/task-continue.md +49 -0
- package/presets/claude/ios-swift/commands/task.md +50 -0
- package/presets/claude/ios-swift/commands/technical-retro.md +58 -0
- package/presets/claude/ios-swift/hooks/README.md +10 -0
- package/presets/claude/ios-swift/hooks/chain-team-phases.sh +382 -0
- package/presets/claude/ios-swift/hooks/guard-shell-command.sh +79 -0
- package/presets/claude/ios-swift/mcp.json +12 -0
- package/presets/claude/ios-swift/rules/README.md +25 -14
- package/presets/claude/ios-swift/rules/api-and-data/README.md +2 -1
- package/presets/claude/ios-swift/rules/api-and-data/networking.md +2 -2
- package/presets/claude/ios-swift/rules/api-and-data/persistence.md +30 -0
- package/presets/claude/ios-swift/rules/architecture/README.md +3 -1
- package/presets/claude/ios-swift/rules/architecture/feature-delivery.md +10 -2
- package/presets/claude/ios-swift/rules/architecture/module-public-api.md +25 -0
- package/presets/claude/ios-swift/rules/architecture/reference-features.md +50 -0
- package/presets/claude/ios-swift/rules/stack/ios-app-core.md +2 -1
- package/presets/claude/ios-swift/rules/testing/ui.md +2 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/README.md +6 -1
- package/presets/claude/ios-swift/rules/tooling-and-review/agent-team-intake.md +18 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/agent-team-orchestrator.md +47 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/code-review.md +5 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/post-change-build.md +5 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/security-ios.md +36 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/technical-retro.md +14 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/xcode-tooling.md +24 -0
- package/presets/claude/ios-swift/rules/ui-and-accessibility/README.md +2 -1
- package/presets/claude/ios-swift/rules/ui-and-accessibility/navigation.md +28 -0
- package/presets/claude/ios-swift/skills/README.md +13 -0
- package/presets/claude/ios-swift/skills/ci-investigation/SKILL.md +39 -0
- package/presets/claude/ios-swift/skills/code-review/SKILL.md +27 -0
- package/presets/claude/ios-swift/skills/debug-investigation/SKILL.md +30 -0
- package/presets/claude/ios-swift/skills/feature-delivery/SKILL.md +27 -0
- package/presets/claude/ios-swift/skills/technical-retro/SKILL.md +10 -0
- package/presets/claude/ios-swift/skills/unit-testing/SKILL.md +32 -0
- package/presets/claude/ios-swift/skills/xcuitest-e2e/SKILL.md +33 -0
- package/presets/claude/ios-swift/team/README.md +27 -0
- package/presets/claude/ios-swift/team/fixtures/bugfix-standard.json +33 -0
- package/presets/claude/ios-swift/team/fixtures/feature-full.json +48 -0
- package/presets/claude/ios-swift/team/fixtures/feature-light.json +36 -0
- package/presets/claude/next/CLAUDE.md +29 -5
- package/presets/claude/next/MCP.md +16 -0
- package/presets/claude/next/README.md +12 -0
- package/presets/claude/next/agents/README.md +155 -1
- package/presets/claude/next/agents/accessibility-reviewer.md +65 -0
- package/presets/claude/next/agents/api-contract-reviewer.md +69 -0
- package/presets/claude/next/agents/build-verifier.md +64 -0
- package/presets/claude/next/agents/ci-investigator.md +62 -0
- package/presets/claude/next/agents/code-reviewer.md +63 -0
- package/presets/claude/next/agents/debugger.md +63 -0
- package/presets/claude/next/agents/feature-developer.md +27 -0
- package/presets/claude/next/agents/migration-specialist.md +69 -0
- package/presets/claude/next/agents/performance-auditor.md +68 -0
- package/presets/claude/next/agents/qa-tester.md +56 -0
- package/presets/claude/next/agents/security-reviewer.md +64 -0
- package/presets/claude/next/agents/solution-architect.md +70 -0
- package/presets/claude/next/agents/task-analyst.md +111 -0
- package/presets/claude/next/agents/task-router.md +94 -0
- package/presets/claude/next/agents/tech-writer.md +61 -0
- package/presets/claude/next/agents/unit-test-generator.md +37 -0
- package/presets/claude/next/agents/unit-test-healer.md +38 -0
- package/presets/claude/next/agents/unit-test-planner.md +62 -0
- package/presets/claude/next/commands/README.md +10 -2
- package/presets/claude/next/commands/feature-continue.md +51 -0
- package/presets/claude/next/commands/feature-start.md +30 -0
- package/presets/claude/next/commands/task-continue.md +49 -0
- package/presets/claude/next/commands/task.md +50 -0
- package/presets/claude/next/commands/technical-retro.md +58 -0
- package/presets/claude/next/hooks/README.md +5 -2
- package/presets/claude/next/hooks/chain-team-phases.sh +380 -0
- package/presets/claude/next/hooks/guard-shell-command.sh +77 -0
- package/presets/claude/next/mcp.json +20 -0
- package/presets/claude/next/rules/README.md +42 -11
- package/presets/claude/next/rules/api-and-data/README.md +7 -1
- package/presets/claude/next/rules/api-and-data/api-services.md +57 -0
- package/presets/claude/next/rules/api-and-data/http-client.md +40 -0
- package/presets/claude/next/rules/api-and-data/store-rtk.md +65 -0
- package/presets/claude/next/rules/architecture/README.md +11 -2
- package/presets/claude/next/rules/architecture/architecture-boundaries-ui.md +15 -0
- package/presets/claude/next/rules/architecture/architecture-boundaries.md +75 -0
- package/presets/claude/next/rules/architecture/feature-delivery-workflow.md +79 -0
- package/presets/claude/next/rules/architecture/layer-barrel-exports.md +58 -0
- package/presets/claude/next/rules/architecture/public-imports.md +46 -0
- package/presets/claude/next/rules/architecture/reference-features.md +37 -0
- package/presets/claude/next/rules/stack/README.md +10 -1
- package/presets/claude/next/rules/stack/arrow-functions.md +45 -0
- package/presets/claude/next/rules/stack/navigation-router-ui.md +15 -0
- package/presets/claude/next/rules/stack/navigation-router.md +64 -0
- package/presets/claude/next/rules/stack/next-app-core.md +33 -0
- package/presets/claude/next/rules/stack/next-app-router.md +36 -0
- package/presets/claude/next/rules/stack/no-type-assertion.md +59 -0
- package/presets/claude/next/rules/stack/types-jsdoc.md +37 -0
- package/presets/claude/next/rules/testing/README.md +9 -1
- package/presets/claude/next/rules/testing/playwright-agents.md +74 -0
- package/presets/claude/next/rules/testing/tests-e2e-structure.md +52 -0
- package/presets/claude/next/rules/testing/tests-unit.md +66 -0
- package/presets/claude/next/rules/tooling-and-review/README.md +12 -1
- package/presets/claude/next/rules/tooling-and-review/agent-team-intake.md +15 -0
- package/presets/claude/next/rules/tooling-and-review/agent-team-orchestrator.md +145 -0
- package/presets/claude/next/rules/tooling-and-review/code-quality.md +42 -0
- package/presets/claude/next/rules/tooling-and-review/code-review-mr.md +30 -0
- package/presets/claude/next/rules/tooling-and-review/package-manager.md +11 -0
- package/presets/claude/next/rules/tooling-and-review/post-change-lint.md +44 -0
- package/presets/claude/next/rules/ui-and-accessibility/README.md +10 -1
- package/presets/claude/next/rules/ui-and-accessibility/css-property-order.md +14 -0
- package/presets/claude/next/rules/ui-and-accessibility/no-props-spread.md +57 -0
- package/presets/claude/next/rules/ui-and-accessibility/react-a11y-coding.md +37 -0
- package/presets/claude/next/rules/ui-and-accessibility/react-ui.md +91 -0
- package/presets/claude/next/skills/README.md +11 -1
- package/presets/claude/next/skills/ci-investigation/SKILL.md +36 -0
- package/presets/claude/next/skills/code-review/SKILL.md +26 -0
- package/presets/claude/next/skills/debug-investigation/SKILL.md +28 -0
- package/presets/claude/next/skills/feature-delivery/SKILL.md +15 -0
- package/presets/claude/next/skills/playwright-e2e/SKILL.md +31 -0
- package/presets/claude/next/skills/technical-retro/SKILL.md +40 -0
- package/presets/claude/next/skills/unit-testing/SKILL.md +32 -0
- package/presets/claude/next/team/README.md +105 -0
- package/presets/claude/next/team/fixtures/bugfix-standard.json +15 -0
- package/presets/claude/next/team/fixtures/feature-full.json +16 -0
- package/presets/claude/next/team/fixtures/feature-light.json +17 -0
- package/presets/claude/next/team/tasks/.gitkeep +1 -0
- package/presets/cursor/ios-swift/AGENTS.md +47 -0
- package/presets/cursor/ios-swift/BUGBOT.md +15 -0
- package/presets/cursor/ios-swift/MCP.md +16 -0
- package/presets/cursor/ios-swift/README.md +27 -7
- package/presets/cursor/ios-swift/agents/README.md +55 -0
- package/presets/cursor/ios-swift/agents/accessibility-reviewer.md +67 -0
- package/presets/cursor/ios-swift/agents/api-contract-reviewer.md +72 -0
- package/presets/cursor/ios-swift/agents/build-verifier.md +64 -0
- package/presets/cursor/ios-swift/agents/ci-investigator.md +73 -0
- package/presets/cursor/ios-swift/agents/code-reviewer.md +75 -0
- package/presets/cursor/ios-swift/agents/debugger.md +72 -0
- package/presets/cursor/ios-swift/agents/feature-developer.md +35 -0
- package/presets/cursor/ios-swift/agents/migration-specialist.md +73 -0
- package/presets/cursor/ios-swift/agents/performance-auditor.md +72 -0
- package/presets/cursor/ios-swift/agents/qa-tester.md +65 -0
- package/presets/cursor/ios-swift/agents/security-reviewer.md +69 -0
- package/presets/cursor/ios-swift/agents/solution-architect.md +17 -0
- package/presets/cursor/ios-swift/agents/task-analyst.md +25 -0
- package/presets/cursor/ios-swift/agents/task-router.md +62 -0
- package/presets/cursor/ios-swift/agents/tech-writer.md +63 -0
- package/presets/cursor/ios-swift/agents/unit-test-generator.md +54 -0
- package/presets/cursor/ios-swift/agents/unit-test-healer.md +53 -0
- package/presets/cursor/ios-swift/agents/unit-test-planner.md +64 -0
- package/presets/cursor/ios-swift/agents/xcuitest-test-generator.md +47 -0
- package/presets/cursor/ios-swift/agents/xcuitest-test-healer.md +47 -0
- package/presets/cursor/ios-swift/agents/xcuitest-test-planner.md +67 -0
- package/presets/cursor/ios-swift/commands/README.md +49 -1
- package/presets/cursor/ios-swift/commands/feature-continue.md +19 -0
- package/presets/cursor/ios-swift/commands/feature-start.md +33 -0
- package/presets/cursor/ios-swift/commands/task-continue.md +49 -0
- package/presets/cursor/ios-swift/commands/task.md +50 -0
- package/presets/cursor/ios-swift/commands/technical-retro.md +81 -0
- package/presets/cursor/ios-swift/hooks/README.md +8 -0
- package/presets/cursor/ios-swift/hooks/chain-team-phases.sh +382 -0
- package/presets/cursor/ios-swift/hooks/guard-shell-command.sh +79 -0
- package/presets/cursor/ios-swift/hooks.json +17 -0
- package/presets/cursor/ios-swift/mcp.json +11 -0
- package/presets/cursor/ios-swift/rules/README.md +45 -13
- package/presets/cursor/ios-swift/rules/agent-team-intake.mdc +16 -0
- package/presets/cursor/ios-swift/rules/agent-team-orchestrator.mdc +85 -0
- package/presets/cursor/ios-swift/rules/code-review-mr.mdc +1 -0
- package/presets/cursor/ios-swift/rules/feature-delivery-workflow.mdc +1 -1
- package/presets/cursor/ios-swift/rules/ios-app-core.mdc +2 -1
- package/presets/cursor/ios-swift/rules/module-public-api.mdc +26 -0
- package/presets/cursor/ios-swift/rules/navigation-coordinators.mdc +29 -0
- package/presets/cursor/ios-swift/rules/networking-services.mdc +2 -2
- package/presets/cursor/ios-swift/rules/persistence-data.mdc +31 -0
- package/presets/cursor/ios-swift/rules/reference-features.mdc +53 -0
- package/presets/cursor/ios-swift/rules/security-ios.mdc +35 -0
- package/presets/cursor/ios-swift/rules/technical-retro.mdc +12 -0
- package/presets/cursor/ios-swift/rules/tests-ui.mdc +1 -0
- package/presets/cursor/ios-swift/rules/xcode-tooling.mdc +20 -0
- package/presets/cursor/ios-swift/skills/README.md +13 -0
- package/presets/cursor/ios-swift/skills/ci-investigation/SKILL.md +39 -0
- package/presets/cursor/ios-swift/skills/code-review/SKILL.md +27 -0
- package/presets/cursor/ios-swift/skills/debug-investigation/SKILL.md +30 -0
- package/presets/cursor/ios-swift/skills/feature-delivery/SKILL.md +27 -0
- package/presets/cursor/ios-swift/skills/technical-retro/SKILL.md +10 -0
- package/presets/cursor/ios-swift/skills/unit-testing/SKILL.md +32 -0
- package/presets/cursor/ios-swift/skills/xcuitest-e2e/SKILL.md +33 -0
- package/presets/cursor/ios-swift/team/README.md +31 -0
- package/presets/cursor/ios-swift/team/fixtures/bugfix-standard.json +33 -0
- package/presets/cursor/ios-swift/team/fixtures/feature-full.json +48 -0
- package/presets/cursor/ios-swift/team/fixtures/feature-light.json +36 -0
- package/presets/cursor/next/AGENTS.md +36 -0
- package/presets/cursor/next/BUGBOT.md +14 -0
- package/presets/cursor/next/MCP.md +16 -0
- package/presets/cursor/next/agents/README.md +165 -0
- package/presets/cursor/next/agents/accessibility-reviewer.md +67 -0
- package/presets/cursor/next/agents/api-contract-reviewer.md +71 -0
- package/presets/cursor/next/agents/build-verifier.md +66 -0
- package/presets/cursor/next/agents/ci-investigator.md +64 -0
- package/presets/cursor/next/agents/code-reviewer.md +64 -0
- package/presets/cursor/next/agents/debugger.md +64 -0
- package/presets/cursor/next/agents/feature-developer.md +28 -0
- package/presets/cursor/next/agents/migration-specialist.md +71 -0
- package/presets/cursor/next/agents/performance-auditor.md +70 -0
- package/presets/cursor/next/agents/playwright-test-generator.md +27 -0
- package/presets/cursor/next/agents/playwright-test-healer.md +27 -0
- package/presets/cursor/next/agents/playwright-test-planner.md +28 -0
- package/presets/cursor/next/agents/qa-tester.md +58 -0
- package/presets/cursor/next/agents/security-reviewer.md +66 -0
- package/presets/cursor/next/agents/solution-architect.md +71 -0
- package/presets/cursor/next/agents/task-analyst.md +112 -0
- package/presets/cursor/next/agents/task-router.md +95 -0
- package/presets/cursor/next/agents/tech-writer.md +62 -0
- package/presets/cursor/next/agents/unit-test-generator.md +39 -0
- package/presets/cursor/next/agents/unit-test-healer.md +40 -0
- package/presets/cursor/next/agents/unit-test-planner.md +64 -0
- package/presets/cursor/next/commands/README.md +49 -1
- package/presets/cursor/next/commands/feature-continue.md +19 -0
- package/presets/cursor/next/commands/feature-start.md +33 -0
- package/presets/cursor/next/commands/task-continue.md +49 -0
- package/presets/cursor/next/commands/task.md +50 -0
- package/presets/cursor/next/commands/technical-retro.md +81 -0
- package/presets/cursor/next/hooks/README.md +8 -0
- package/presets/cursor/next/hooks/chain-team-phases.sh +380 -0
- package/presets/cursor/next/hooks/guard-shell-command.sh +77 -0
- package/presets/cursor/next/hooks.json +17 -0
- package/presets/cursor/next/mcp.json +19 -0
- package/presets/cursor/next/rules/README.md +67 -0
- package/presets/cursor/next/rules/agent-team-intake.mdc +14 -0
- package/presets/cursor/next/rules/agent-team-orchestrator.mdc +147 -0
- package/presets/cursor/next/rules/api-services.mdc +12 -10
- package/presets/cursor/next/rules/architecture-boundaries-ui.mdc +15 -0
- package/presets/cursor/next/rules/architecture-boundaries.mdc +31 -12
- package/presets/cursor/next/rules/arrow-functions.mdc +46 -0
- package/presets/cursor/next/rules/code-quality-and-refactoring.mdc +5 -4
- package/presets/cursor/next/rules/code-review-mr.mdc +21 -40
- package/presets/cursor/next/rules/css-property-order-stylelint.mdc +16 -0
- package/presets/cursor/next/rules/feature-delivery-workflow.mdc +76 -0
- package/presets/cursor/next/rules/http-client.mdc +42 -0
- package/presets/cursor/next/rules/layer-barrel-exports.mdc +59 -0
- package/presets/cursor/next/rules/navigation-router-stack.mdc +62 -0
- package/presets/cursor/next/rules/navigation-router-ui.mdc +16 -0
- package/presets/cursor/next/rules/next-app-core.mdc +18 -61
- package/presets/cursor/next/rules/next-app-router.mdc +36 -0
- package/presets/cursor/next/rules/no-props-spread.mdc +27 -4
- package/presets/cursor/next/rules/no-type-assertion-as-import-export.mdc +60 -0
- package/presets/cursor/next/rules/package-manager.mdc +16 -0
- package/presets/cursor/next/rules/playwright-agents.mdc +2 -1
- package/presets/cursor/next/rules/post-change-lint.mdc +40 -0
- package/presets/cursor/next/rules/public-imports.mdc +48 -0
- package/presets/cursor/next/rules/react-a11y-coding.mdc +37 -0
- package/presets/cursor/next/rules/react-ui.mdc +33 -3
- package/presets/cursor/next/rules/reference-features.mdc +39 -0
- package/presets/cursor/next/rules/store-rtk.mdc +13 -6
- package/presets/cursor/next/rules/technical-retro.mdc +12 -0
- package/presets/cursor/next/rules/tests-unit.mdc +30 -10
- package/presets/cursor/next/rules/types-jsdoc.mdc +42 -0
- package/presets/cursor/next/skills/README.md +15 -0
- package/presets/cursor/next/skills/ci-investigation/SKILL.md +36 -0
- package/presets/cursor/next/skills/code-review/SKILL.md +26 -0
- package/presets/cursor/next/skills/debug-investigation/SKILL.md +28 -0
- package/presets/cursor/next/skills/feature-delivery/SKILL.md +15 -0
- package/presets/cursor/next/skills/playwright-e2e/SKILL.md +31 -0
- package/presets/cursor/next/skills/technical-retro/SKILL.md +40 -0
- package/presets/cursor/next/skills/unit-testing/SKILL.md +32 -0
- package/presets/cursor/next/team/README.md +109 -0
- package/presets/cursor/next/team/fixtures/bugfix-standard.json +15 -0
- package/presets/cursor/next/team/fixtures/feature-full.json +16 -0
- package/presets/cursor/next/team/fixtures/feature-light.json +17 -0
- package/presets/cursor/next/team/tasks/.gitkeep +0 -0
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Chains agent team steps from pipeline.json after subagentStop.
|
|
3
|
+
# Falls back to legacy phase-based flow when pipeline.json is absent.
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
input=$(cat)
|
|
8
|
+
|
|
9
|
+
INPUT="$input" node <<'NODE'
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
|
|
13
|
+
const TEAM_ROOT = path.join(process.cwd(), '.claude', 'team');
|
|
14
|
+
|
|
15
|
+
const inputRaw = process.env.INPUT || '';
|
|
16
|
+
let hookInput;
|
|
17
|
+
try {
|
|
18
|
+
hookInput = JSON.parse(inputRaw);
|
|
19
|
+
} catch {
|
|
20
|
+
process.stdout.write('{}');
|
|
21
|
+
process.exit(0);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (hookInput.status !== 'completed') {
|
|
25
|
+
process.stdout.write('{}');
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const activePath = path.join(TEAM_ROOT, 'active-task.json');
|
|
30
|
+
|
|
31
|
+
if (!fs.existsSync(activePath)) {
|
|
32
|
+
process.stdout.write('{}');
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let active;
|
|
37
|
+
try {
|
|
38
|
+
active = JSON.parse(fs.readFileSync(activePath, 'utf8'));
|
|
39
|
+
} catch {
|
|
40
|
+
process.stdout.write('{}');
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const slug = active.slug;
|
|
45
|
+
if (!slug) {
|
|
46
|
+
process.stdout.write('{}');
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const taskDir = path.join(TEAM_ROOT, 'tasks', slug);
|
|
51
|
+
const statusPath = path.join(taskDir, 'status.json');
|
|
52
|
+
const pipelinePath = path.join(taskDir, 'pipeline.json');
|
|
53
|
+
|
|
54
|
+
if (!fs.existsSync(statusPath)) {
|
|
55
|
+
process.stdout.write('{}');
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let status;
|
|
60
|
+
try {
|
|
61
|
+
status = JSON.parse(fs.readFileSync(statusPath, 'utf8'));
|
|
62
|
+
} catch {
|
|
63
|
+
process.stdout.write('{}');
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const now = new Date().toISOString();
|
|
68
|
+
|
|
69
|
+
function writeStatus(next) {
|
|
70
|
+
status = { ...status, ...next, slug, updatedAt: now };
|
|
71
|
+
fs.writeFileSync(statusPath, JSON.stringify(status, null, 2) + '\n');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function out(message) {
|
|
75
|
+
process.stdout.write(JSON.stringify({ followup_message: message }));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function readArtifact(name) {
|
|
79
|
+
const p = path.join(taskDir, name);
|
|
80
|
+
if (!fs.existsSync(p)) return '';
|
|
81
|
+
try {
|
|
82
|
+
return fs.readFileSync(p, 'utf8');
|
|
83
|
+
} catch {
|
|
84
|
+
return '';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function getStepAgents(step) {
|
|
89
|
+
if (!step) return [];
|
|
90
|
+
return Array.isArray(step.agent) ? step.agent : [step.agent];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function skipIfMatches(skipIf, dir) {
|
|
94
|
+
if (!skipIf) return false;
|
|
95
|
+
if (skipIf === 'debugger.fixed') {
|
|
96
|
+
const text = readArtifact('debug-report.md');
|
|
97
|
+
return /fixApplied:\s*true/i.test(text) || /\*\*Fix applied:\*\*\s*true/i.test(text);
|
|
98
|
+
}
|
|
99
|
+
if (skipIf === 'ci-investigator.resolved') {
|
|
100
|
+
const text = readArtifact('ci-report.md');
|
|
101
|
+
return /fixApplied:\s*true/i.test(text) || /## Verdict\s*\nPASS/i.test(text);
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function findNextExecutableStep(steps, startIdx, dir) {
|
|
107
|
+
for (let i = startIdx; i < steps.length; i++) {
|
|
108
|
+
if (!skipIfMatches(steps[i].skipIf, dir)) {
|
|
109
|
+
return { step: steps[i], index: i };
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const AGENT_HANDOFF = {
|
|
116
|
+
'task-analyst': (s) =>
|
|
117
|
+
`Invoke task-analyst for slug "${s}". Write brief.md and decomposition.md under .claude/team/tasks/${s}/. ` +
|
|
118
|
+
`Set status.json: phase executing, state awaiting_approval if human gate applies. Do not use legacy phase analysis.`,
|
|
119
|
+
debugger: (s) =>
|
|
120
|
+
`Invoke debugger subagent for slug "${s}". Investigate root cause; write debug-report.md with fixApplied: true/false. ` +
|
|
121
|
+
`Update status.json when done.`,
|
|
122
|
+
'solution-architect': (s) =>
|
|
123
|
+
`Invoke solution-architect for slug "${s}". Read brief.md; write architecture.md. Update status.json when done.`,
|
|
124
|
+
'migration-specialist': (s) =>
|
|
125
|
+
`Invoke migration-specialist for slug "${s}". Read brief.md; write migration-plan.md. Update status.json when done.`,
|
|
126
|
+
'api-contract-reviewer': (s) =>
|
|
127
|
+
`Invoke api-contract-reviewer (readonly) for slug "${s}". Write api-contract-review.md. Update status.json when done.`,
|
|
128
|
+
'ci-investigator': (s) =>
|
|
129
|
+
`Invoke ci-investigator for slug "${s}". Diagnose CI failure; write ci-report.md; apply minimal fix. ` +
|
|
130
|
+
`Use ci-investigation skill. Update status.json when done.`,
|
|
131
|
+
'feature-developer': (s) =>
|
|
132
|
+
`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
|
+
`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. Update status.json when done.`,
|
|
135
|
+
'build-verifier': (s) =>
|
|
136
|
+
`Invoke build-verifier (readonly) for slug "${s}". Follow xcode-tooling.mdc and post-change-build.mdc. ` +
|
|
137
|
+
`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. Set state completed or validation_failed. Do not edit production code.`,
|
|
139
|
+
'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. Update status.json when done.`,
|
|
141
|
+
'performance-auditor': (s) =>
|
|
142
|
+
`Invoke performance-auditor (readonly) for slug "${s}". Audit launch/SwiftUI performance risks; write perf-report.md. Update status.json when done.`,
|
|
143
|
+
'code-reviewer': (s) =>
|
|
144
|
+
`Invoke code-reviewer subagent (readonly) for slug "${s}". Review git diff vs brief.md per code-review-mr.mdc. ` +
|
|
145
|
+
`Update status.json when done.`,
|
|
146
|
+
'security-reviewer': (s) =>
|
|
147
|
+
`Invoke security-reviewer (readonly) for slug "${s}". Write security-review.md. Update status.json when done.`,
|
|
148
|
+
'qa-tester': (s, scope) =>
|
|
149
|
+
`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. Update status.json when done.`,
|
|
151
|
+
'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. Update status.json when done.`,
|
|
153
|
+
'unit-test-generator': (s) =>
|
|
154
|
+
`Invoke unit-test-generator for slug "${s}". Implement *Tests from unit-test-plan.md. Use unit-testing skill. Update status.json when done.`,
|
|
155
|
+
'unit-test-healer': (s) =>
|
|
156
|
+
`Invoke unit-test-healer for slug "${s}". Fix failing unit tests. Use unit-testing and debug-investigation skills. Update status.json when done.`,
|
|
157
|
+
'xcuitest-test-planner': (s) =>
|
|
158
|
+
`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. Update status.json when done.`,
|
|
160
|
+
'xcuitest-test-generator': (s) =>
|
|
161
|
+
`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. Update status.json when done.`,
|
|
163
|
+
'xcuitest-test-healer': (s) =>
|
|
164
|
+
`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. Update status.json when done.`,
|
|
166
|
+
'tech-writer': (s) =>
|
|
167
|
+
`Invoke tech-writer for slug "${s}". Write documentation.md from task artifacts. Update status.json when done.`,
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const REVIEW_AGENTS = new Set([
|
|
171
|
+
'code-reviewer',
|
|
172
|
+
'accessibility-reviewer',
|
|
173
|
+
'security-reviewer',
|
|
174
|
+
'api-contract-reviewer',
|
|
175
|
+
]);
|
|
176
|
+
|
|
177
|
+
function handoffForAgent(agent, scope) {
|
|
178
|
+
const fn = AGENT_HANDOFF[agent];
|
|
179
|
+
return fn ? fn(slug, scope) : `Invoke ${agent} subagent for slug "${slug}". Update status.json when done.`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function handoffForParallelStep(step) {
|
|
183
|
+
const agents = getStepAgents(step);
|
|
184
|
+
return (
|
|
185
|
+
`Invoke IN PARALLEL (one message, multiple Task calls): ${agents.join(' AND ')} for slug "${slug}". ` +
|
|
186
|
+
`Each agent writes its artifact and appends itself to status.json parallelCompleted when done.`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function hasGateAfter(agent, humanGates) {
|
|
191
|
+
return Array.isArray(humanGates) && humanGates.includes(`after:${agent}`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function hasGateAfterStep(step, humanGates) {
|
|
195
|
+
return getStepAgents(step).some((a) => hasGateAfter(a, humanGates));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function legacyFlow() {
|
|
199
|
+
if (status.phase === 'analysis') {
|
|
200
|
+
process.stdout.write('{}');
|
|
201
|
+
process.exit(0);
|
|
202
|
+
}
|
|
203
|
+
if (status.phase === 'development' && (status.state === 'completed' || status.state === 'in_progress')) {
|
|
204
|
+
writeStatus({ phase: 'executing', state: 'in_progress', currentAgent: 'build-verifier' });
|
|
205
|
+
out(handoffForAgent('build-verifier'));
|
|
206
|
+
process.exit(0);
|
|
207
|
+
}
|
|
208
|
+
if (status.currentAgent === 'build-verifier' && status.state === 'completed') {
|
|
209
|
+
writeStatus({ phase: 'executing', state: 'in_progress', currentAgent: 'code-reviewer' });
|
|
210
|
+
out(handoffForAgent('code-reviewer'));
|
|
211
|
+
process.exit(0);
|
|
212
|
+
}
|
|
213
|
+
if (status.phase === 'review' && status.state === 'completed') {
|
|
214
|
+
writeStatus({ phase: 'executing', state: 'in_progress', currentAgent: 'qa-tester' });
|
|
215
|
+
out(handoffForAgent('qa-tester'));
|
|
216
|
+
process.exit(0);
|
|
217
|
+
}
|
|
218
|
+
if (status.state === 'changes_requested' && REVIEW_AGENTS.has(status.currentAgent)) {
|
|
219
|
+
writeStatus({
|
|
220
|
+
currentAgent: 'feature-developer',
|
|
221
|
+
state: 'in_progress',
|
|
222
|
+
phase: 'executing',
|
|
223
|
+
retryAfterFix: status.currentAgent,
|
|
224
|
+
});
|
|
225
|
+
out(
|
|
226
|
+
handoffForAgent('feature-developer') +
|
|
227
|
+
` After fixes, re-run ${status.currentAgent}.`,
|
|
228
|
+
);
|
|
229
|
+
process.exit(0);
|
|
230
|
+
}
|
|
231
|
+
if (status.state === 'validation_failed' && status.currentAgent === 'build-verifier') {
|
|
232
|
+
writeStatus({
|
|
233
|
+
currentAgent: 'feature-developer',
|
|
234
|
+
state: 'in_progress',
|
|
235
|
+
phase: 'executing',
|
|
236
|
+
retryAfterFix: 'build-verifier',
|
|
237
|
+
});
|
|
238
|
+
out(
|
|
239
|
+
handoffForAgent('feature-developer') +
|
|
240
|
+
` Read validation-report.md. After fixes, re-run build-verifier.`,
|
|
241
|
+
);
|
|
242
|
+
process.exit(0);
|
|
243
|
+
}
|
|
244
|
+
if (status.state === 'completed' && status.retryAfterFix) {
|
|
245
|
+
const retry = status.retryAfterFix;
|
|
246
|
+
writeStatus({ currentAgent: retry, state: 'in_progress', retryAfterFix: null });
|
|
247
|
+
out(handoffForAgent(retry));
|
|
248
|
+
process.exit(0);
|
|
249
|
+
}
|
|
250
|
+
if (status.phase === 'testing' && status.state === 'completed') {
|
|
251
|
+
writeStatus({ phase: 'done', state: 'completed' });
|
|
252
|
+
out(`Pipeline complete for "${slug}". Run /technical-retro ${slug}.`);
|
|
253
|
+
process.exit(0);
|
|
254
|
+
}
|
|
255
|
+
process.stdout.write('{}');
|
|
256
|
+
process.exit(0);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (!fs.existsSync(pipelinePath)) {
|
|
260
|
+
legacyFlow();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
let pipeline;
|
|
264
|
+
try {
|
|
265
|
+
pipeline = JSON.parse(fs.readFileSync(pipelinePath, 'utf8'));
|
|
266
|
+
} catch {
|
|
267
|
+
legacyFlow();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const steps = pipeline.steps || [];
|
|
271
|
+
if (steps.length === 0 || pipeline.autoChain === false) {
|
|
272
|
+
process.stdout.write('{}');
|
|
273
|
+
process.exit(0);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (status.awaitingHumanGate || status.state === 'awaiting_approval') {
|
|
277
|
+
process.stdout.write('{}');
|
|
278
|
+
process.exit(0);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (status.state === 'changes_requested' && REVIEW_AGENTS.has(status.currentAgent)) {
|
|
282
|
+
const reviewer = status.currentAgent;
|
|
283
|
+
writeStatus({
|
|
284
|
+
currentAgent: 'feature-developer',
|
|
285
|
+
state: 'in_progress',
|
|
286
|
+
phase: 'executing',
|
|
287
|
+
retryAfterFix: reviewer,
|
|
288
|
+
});
|
|
289
|
+
out(
|
|
290
|
+
handoffForAgent('feature-developer') +
|
|
291
|
+
` After fixes, re-run ${reviewer}.`,
|
|
292
|
+
);
|
|
293
|
+
process.exit(0);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (status.state === 'validation_failed' && status.currentAgent === 'build-verifier') {
|
|
297
|
+
writeStatus({
|
|
298
|
+
currentAgent: 'feature-developer',
|
|
299
|
+
state: 'in_progress',
|
|
300
|
+
phase: 'executing',
|
|
301
|
+
retryAfterFix: 'build-verifier',
|
|
302
|
+
});
|
|
303
|
+
out(
|
|
304
|
+
handoffForAgent('feature-developer') +
|
|
305
|
+
` Read validation-report.md. After fixes, re-run build-verifier.`,
|
|
306
|
+
);
|
|
307
|
+
process.exit(0);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (status.state === 'completed' && status.retryAfterFix) {
|
|
311
|
+
const retry = status.retryAfterFix;
|
|
312
|
+
writeStatus({ currentAgent: retry, state: 'in_progress', retryAfterFix: null });
|
|
313
|
+
out(handoffForAgent(retry));
|
|
314
|
+
process.exit(0);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const idx = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
|
|
318
|
+
const currentStep = steps[idx];
|
|
319
|
+
if (!currentStep) {
|
|
320
|
+
writeStatus({ phase: 'done', state: 'completed', currentAgent: null });
|
|
321
|
+
out(`Pipeline complete for "${slug}". Run /technical-retro ${slug}.`);
|
|
322
|
+
process.exit(0);
|
|
323
|
+
}
|
|
324
|
+
|
|
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
|
+
if (hasGateAfterStep(currentStep, pipeline.humanGates)) {
|
|
343
|
+
writeStatus({
|
|
344
|
+
awaitingHumanGate: true,
|
|
345
|
+
state: 'awaiting_approval',
|
|
346
|
+
currentAgent: completedAgent,
|
|
347
|
+
});
|
|
348
|
+
process.stdout.write('{}');
|
|
349
|
+
process.exit(0);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const next = findNextExecutableStep(steps, idx + 1, taskDir);
|
|
353
|
+
if (!next) {
|
|
354
|
+
writeStatus({
|
|
355
|
+
pipelineIndex: steps.length,
|
|
356
|
+
phase: 'done',
|
|
357
|
+
state: 'completed',
|
|
358
|
+
currentAgent: null,
|
|
359
|
+
awaitingHumanGate: false,
|
|
360
|
+
});
|
|
361
|
+
out(`Pipeline complete for "${slug}". Run /technical-retro ${slug}.`);
|
|
362
|
+
process.exit(0);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const { step: nextStep, index: nextIdx } = next;
|
|
366
|
+
const nextAgents = getStepAgents(nextStep);
|
|
367
|
+
|
|
368
|
+
writeStatus({
|
|
369
|
+
pipelineIndex: nextIdx,
|
|
370
|
+
currentAgent: nextAgents[0],
|
|
371
|
+
phase: 'executing',
|
|
372
|
+
state: 'in_progress',
|
|
373
|
+
awaitingHumanGate: false,
|
|
374
|
+
parallelCompleted: [],
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
if (nextStep.parallel && nextAgents.length > 1) {
|
|
378
|
+
out(handoffForParallelStep(nextStep));
|
|
379
|
+
} else {
|
|
380
|
+
out(handoffForAgent(nextAgents[0], nextStep.scope));
|
|
381
|
+
}
|
|
382
|
+
NODE
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Lightweight shell guard for Claude Code projects using this preset.
|
|
3
|
+
# iOS: do NOT blanket-block xcodebuild / simctl / xcrun / swiftlint / swiftformat.
|
|
4
|
+
# Package-manager mismatch checks apply only when a JS lockfile/package.json exists.
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
input=$(cat)
|
|
9
|
+
|
|
10
|
+
INPUT="$input" node <<'NODE'
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
|
|
13
|
+
const raw = process.env.INPUT || '';
|
|
14
|
+
let event;
|
|
15
|
+
try {
|
|
16
|
+
event = JSON.parse(raw);
|
|
17
|
+
} catch {
|
|
18
|
+
process.stdout.write('{ "permission": "allow" }');
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const command = String(event.command || event.input?.command || '');
|
|
23
|
+
if (!command.trim()) {
|
|
24
|
+
process.stdout.write('{ "permission": "allow" }');
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function out(permission, userMessage, agentMessage) {
|
|
29
|
+
process.stdout.write(JSON.stringify({
|
|
30
|
+
permission,
|
|
31
|
+
user_message: userMessage,
|
|
32
|
+
agent_message: agentMessage || userMessage,
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const dangerousGit = /\bgit\s+(reset\s+--hard|clean\s+-[^\n]*f|push\s+--force|push\s+-f|checkout\s+--\s+)/;
|
|
37
|
+
if (dangerousGit.test(command)) {
|
|
38
|
+
out(
|
|
39
|
+
'ask',
|
|
40
|
+
'This command looks destructive for git state. Review it before continuing.',
|
|
41
|
+
'A project hook flagged a destructive git command. Ask the user before running it.',
|
|
42
|
+
);
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const managerByFile = [
|
|
47
|
+
['yarn.lock', 'yarn'],
|
|
48
|
+
['pnpm-lock.yaml', 'pnpm'],
|
|
49
|
+
['package-lock.json', 'npm'],
|
|
50
|
+
].find(([file]) => fs.existsSync(file));
|
|
51
|
+
|
|
52
|
+
let expected = managerByFile?.[1];
|
|
53
|
+
if (!expected && fs.existsSync('package.json')) {
|
|
54
|
+
try {
|
|
55
|
+
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
|
56
|
+
const pm = typeof pkg.packageManager === 'string' ? pkg.packageManager : '';
|
|
57
|
+
expected = pm.split('@')[0] || undefined;
|
|
58
|
+
} catch {
|
|
59
|
+
// Ignore invalid package.json in the hook; the agent can diagnose it later.
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!expected) {
|
|
64
|
+
process.stdout.write('{ "permission": "allow" }');
|
|
65
|
+
process.exit(0);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const used = command.match(/(^|[;&|]\s*)(npm|yarn|pnpm)\s+/)?.[2];
|
|
69
|
+
if (used && used !== expected) {
|
|
70
|
+
out(
|
|
71
|
+
'ask',
|
|
72
|
+
`This repository appears to use ${expected}, but the command uses ${used}. Confirm before continuing.`,
|
|
73
|
+
`Use ${expected} for package scripts and installs unless the user explicitly approves ${used}.`,
|
|
74
|
+
);
|
|
75
|
+
process.exit(0);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
process.stdout.write('{ "permission": "allow" }');
|
|
79
|
+
NODE
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
# `.claude/rules` (preset ios-swift)
|
|
2
2
|
|
|
3
|
-
В Claude Code все `.md` под `rules/` **обнаруживаются рекурсивно**. Тела
|
|
3
|
+
В Claude Code все `.md` под `rules/` **обнаруживаются рекурсивно**. Тела **derived** из Cursor SoT; индексы — не второй SoT.
|
|
4
4
|
|
|
5
5
|
## SoT sync
|
|
6
6
|
|
|
7
7
|
| Principle | Detail |
|
|
8
8
|
|-----------|--------|
|
|
9
9
|
| **SoT** | `presets/cursor/ios-swift/rules/*.mdc` — edit here first |
|
|
10
|
-
| **Derive** | Claude topic `.md` = body
|
|
11
|
-
| **Drop** | Cursor-only keys (`alwaysApply`); keep short `description`
|
|
12
|
-
| **
|
|
10
|
+
| **Derive** | Claude topic `.md` = body + `paths:` (from Cursor `globs:` / requestable triggers) |
|
|
11
|
+
| **Drop** | Cursor-only keys (`alwaysApply`); keep short `description` |
|
|
12
|
+
| **Checklist** | change Cursor → update Claude twin **same PR** |
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## Loading budget
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
- **Session-start (no `paths:`):** ровно **3** — `ios-app-core`, `boundaries`, `code-quality` (≤120 body lines total)
|
|
17
|
+
- **Все остальные** — с `paths:` (commands/team/agents и/или Feature/Swift globs)
|
|
18
|
+
- **Soft twin depth:** domain rules ≥15 body lines; thin aliases (`agent-team-intake`, `technical-retro`) могут быть короче (как next)
|
|
19
|
+
|
|
20
|
+
## Cursor → Claude mapping
|
|
17
21
|
|
|
18
22
|
| Cursor `.mdc` (SoT) | Claude topic |
|
|
19
23
|
|---------------------|--------------|
|
|
@@ -21,24 +25,31 @@
|
|
|
21
25
|
| `swift-conventions.mdc` | `stack/swift-conventions.md` |
|
|
22
26
|
| `architecture-boundaries.mdc` | `architecture/boundaries.md` |
|
|
23
27
|
| `feature-delivery-workflow.mdc` | `architecture/feature-delivery.md` |
|
|
28
|
+
| `reference-features.mdc` | `architecture/reference-features.md` |
|
|
29
|
+
| `module-public-api.mdc` | `architecture/module-public-api.md` |
|
|
24
30
|
| `networking-services.mdc` | `api-and-data/networking.md` |
|
|
31
|
+
| `persistence-data.mdc` | `api-and-data/persistence.md` |
|
|
25
32
|
| `swiftui-ui.mdc` | `ui-and-accessibility/swiftui.md` |
|
|
26
33
|
| `state-and-viewmodels.mdc` | `ui-and-accessibility/viewmodels.md` |
|
|
34
|
+
| `navigation-coordinators.mdc` | `ui-and-accessibility/navigation.md` |
|
|
27
35
|
| `tests-unit.mdc` | `testing/unit.md` |
|
|
28
36
|
| `tests-ui.mdc` | `testing/ui.md` |
|
|
29
37
|
| `code-quality-and-refactoring.mdc` | `tooling-and-review/code-quality.md` |
|
|
30
38
|
| `code-review-mr.mdc` | `tooling-and-review/code-review.md` |
|
|
31
39
|
| `post-change-build.mdc` | `tooling-and-review/post-change-build.md` |
|
|
40
|
+
| `xcode-tooling.mdc` | `tooling-and-review/xcode-tooling.md` |
|
|
41
|
+
| `security-ios.mdc` | `tooling-and-review/security-ios.md` |
|
|
42
|
+
| `agent-team-intake.mdc` | `tooling-and-review/agent-team-intake.md` |
|
|
43
|
+
| `agent-team-orchestrator.mdc` | `tooling-and-review/agent-team-orchestrator.md` |
|
|
44
|
+
| `technical-retro.mdc` | `tooling-and-review/technical-retro.md` |
|
|
32
45
|
|
|
33
46
|
## Folders
|
|
34
47
|
|
|
35
48
|
| Папка | О чём |
|
|
36
49
|
|-------|--------|
|
|
37
|
-
| `stack/` | Стек,
|
|
38
|
-
| `architecture/` |
|
|
39
|
-
| `api-and-data/` |
|
|
40
|
-
| `testing/` |
|
|
41
|
-
| `ui-and-accessibility/` | SwiftUI,
|
|
42
|
-
| `tooling-and-review/` |
|
|
43
|
-
|
|
44
|
-
Path-scoped rules use frontmatter `paths:` (same patterns as Cursor `globs:`). Rules without `paths:` apply broadly (Claude equivalent of Cursor alwaysApply / requestable).
|
|
50
|
+
| `stack/` | Стек, Swift conventions |
|
|
51
|
+
| `architecture/` | Границы, feature-delivery, reference-features, SPM public API |
|
|
52
|
+
| `api-and-data/` | Networking, persistence |
|
|
53
|
+
| `testing/` | XCTest, XCUITest |
|
|
54
|
+
| `ui-and-accessibility/` | SwiftUI, ViewModels, navigation |
|
|
55
|
+
| `tooling-and-review/` | Quality, review, build, security, tooling, agent-team, retro |
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# API and data
|
|
2
2
|
|
|
3
|
-
Сетевой слой, DTO, mappers
|
|
3
|
+
Сетевой слой, persistence, DTO, mappers. Index only — тела в topic `.md`.
|
|
4
4
|
|
|
5
5
|
| File | Cursor SoT |
|
|
6
6
|
|------|------------|
|
|
7
7
|
| [`networking.md`](./networking.md) | `networking-services.mdc` |
|
|
8
|
+
| [`persistence.md`](./persistence.md) | `persistence-data.mdc` |
|
|
8
9
|
|
|
9
10
|
Sync: change Cursor → update Claude twin same PR. Full map: [`../README.md`](../README.md).
|
|
@@ -9,8 +9,8 @@ paths:
|
|
|
9
9
|
- Инкапсулировать:
|
|
10
10
|
- HTTP-запросы (`URLSession` или клиент проекта),
|
|
11
11
|
- URL, headers, status codes,
|
|
12
|
-
- Codable DTO
|
|
13
|
-
|
|
12
|
+
- Codable DTO (транспорт).
|
|
13
|
+
- Локальное хранение / Keychain — **`persistence.md`**, не смешивать с HTTP-клиентом без фасада-репозитория.
|
|
14
14
|
- Наружу (Domain, ViewModel через repository) отдавать **доменные типы**, не DTO.
|
|
15
15
|
|
|
16
16
|
# Структура модулей
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Persistence — SwiftData / Core Data / файлы / Keychain (не HTTP)
|
|
3
|
+
paths:
|
|
4
|
+
- "**/Persistence/**/*.swift"
|
|
5
|
+
- "**/Keychain/**/*.swift"
|
|
6
|
+
- "**/*Storage*.swift"
|
|
7
|
+
- "**/*Cache*.swift"
|
|
8
|
+
- "**/*SwiftData*.swift"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Persistence (Data)
|
|
12
|
+
|
|
13
|
+
Отделить от HTTP (`api-and-data/networking.md`): здесь локальное хранение и секреты на диске/Keychain.
|
|
14
|
+
|
|
15
|
+
## Рамка
|
|
16
|
+
|
|
17
|
+
- Выбор стека (**SwiftData / Core Data / UserDefaults / files**) — **как в репо**; не внедрять второй persistence-стек без задачи.
|
|
18
|
+
- Public API — протоколы в Domain (`…Repository` / `…Store`); реализации в Data.
|
|
19
|
+
- **Keychain** — только для credentials/токенов; не класть PII «для удобства» в UserDefaults.
|
|
20
|
+
|
|
21
|
+
## Правила
|
|
22
|
+
|
|
23
|
+
- DTO/Entity persistence ≠ network DTO; маппинг явный.
|
|
24
|
+
- Миграции схемы — по принятому в репо процессу; не ломать silently.
|
|
25
|
+
- `@MainActor` на store — только если UI-facing; тяжёлый I/O — off-main + hop обратно.
|
|
26
|
+
- Ошибки — typed; не глотать `try?` на критичном persist.
|
|
27
|
+
|
|
28
|
+
## Требование к агенту
|
|
29
|
+
|
|
30
|
+
Не смешивать URLSession и persistence в одном типе без фасада-репозитория. Тесты — in-memory / fake store.
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# Architecture
|
|
2
2
|
|
|
3
|
-
Границы
|
|
3
|
+
Границы слоёв, DI, доставка фичи, SPM public API. Index only — тела в topic `.md`.
|
|
4
4
|
|
|
5
5
|
| File | Cursor SoT |
|
|
6
6
|
|------|------------|
|
|
7
7
|
| [`boundaries.md`](./boundaries.md) | `architecture-boundaries.mdc` |
|
|
8
8
|
| [`feature-delivery.md`](./feature-delivery.md) | `feature-delivery-workflow.mdc` |
|
|
9
|
+
| [`reference-features.md`](./reference-features.md) | `reference-features.mdc` |
|
|
10
|
+
| [`module-public-api.md`](./module-public-api.md) | `module-public-api.mdc` |
|
|
9
11
|
|
|
10
12
|
Sync: change Cursor → update Claude twin same PR. Full map: [`../README.md`](../README.md).
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Сквозной чеклист доставки iOS-фичи и матрица «зона → правило». Use when implementing features, adding screens/API, or extending existing iOS flows.
|
|
3
|
+
paths:
|
|
4
|
+
- .claude/commands/**/*
|
|
5
|
+
- .claude/team/**/*
|
|
6
|
+
- .claude/agents/**/*
|
|
7
|
+
- Features/**/*
|
|
8
|
+
- **/Presentation/**/*
|
|
9
|
+
- **/Domain/**/*
|
|
10
|
+
- **/Data/**/*
|
|
3
11
|
---
|
|
4
12
|
|
|
5
13
|
# Доставка фичи (iOS)
|
|
@@ -13,7 +21,7 @@ description: Сквозной чеклист доставки iOS-фичи и м
|
|
|
13
21
|
3. **ViewModel** — состояние, вызовы use case / протоколов; DI из App; без DTO и URL (`ui-and-accessibility/viewmodels.md`).
|
|
14
22
|
4. **View / navigation** — тонкие SwiftUI Views, Design System; навигация как в репо (`ui-and-accessibility/swiftui.md`).
|
|
15
23
|
5. **Тесты** — unit на mappers / use cases / VM (`testing/unit.md`); UI-потоки — XCUITest (`testing/ui.md`).
|
|
16
|
-
6. **Завершение** —
|
|
24
|
+
6. **Завершение** — **вызвать** `tooling-and-review/post-change-build.md` (+ `tooling-and-review/xcode-tooling.md`): сборка затронутых таргетов + lint/format по конфигу репо.
|
|
17
25
|
|
|
18
26
|
## Поток данных (ориентир)
|
|
19
27
|
|
|
@@ -55,6 +63,6 @@ flowchart LR
|
|
|
55
63
|
| `**/*.swift` (стиль) | `stack/swift-conventions.md` |
|
|
56
64
|
| `*Tests/**` | `testing/unit.md` |
|
|
57
65
|
| `*UITests/**` | `testing/ui.md` |
|
|
58
|
-
| После правок Swift | `tooling-and-review/post-change-build.md` |
|
|
66
|
+
| После правок Swift | `tooling-and-review/post-change-build.md` (+ `tooling-and-review/xcode-tooling.md`) |
|
|
59
67
|
|
|
60
68
|
При добавлении или расширении фичи **пройти чеклист** и правила из таблицы для затронутых зон.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: SPM / модули — public API, access control, запрет deep-import internals
|
|
3
|
+
paths:
|
|
4
|
+
- "**/Package.swift"
|
|
5
|
+
- "**/*Public*.swift"
|
|
6
|
+
- "**/Sources/**/*.swift"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Module public API (SPM)
|
|
10
|
+
|
|
11
|
+
## Рамка
|
|
12
|
+
|
|
13
|
+
- Потребители модуля импортируют **только public/open** API; `internal`/`fileprivate` — для реализации.
|
|
14
|
+
- Deep-import чужих internal файлов — повод вынести символ в public API или рефакторить границы.
|
|
15
|
+
|
|
16
|
+
## Правила
|
|
17
|
+
|
|
18
|
+
- Новый публичный тип/функция — явный `public` + документация/пример использования при необходимости.
|
|
19
|
+
- Barrel-стиль: один входной модуль / umbrella, если так заведено в репо.
|
|
20
|
+
- Не экспортировать DTO сети из Presentation-facing модулей.
|
|
21
|
+
- Версионирование breaking API — осознанно (SemVer пакета / release notes).
|
|
22
|
+
|
|
23
|
+
## Требование к агенту
|
|
24
|
+
|
|
25
|
+
Перед `public` на тип — проверить, нужен ли он снаружи. Следовать access control соседних модулей.
|