@bonesofspring/ai-rules 0.2.0 → 0.2.2

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.
Files changed (193) hide show
  1. package/README.md +10 -18
  2. package/bin/cli.js +73 -258
  3. package/package.json +3 -4
  4. package/presets/claude/ios-swift/CLAUDE.md +27 -0
  5. package/presets/claude/ios-swift/README.md +29 -0
  6. package/presets/claude/ios-swift/commands/README.md +3 -0
  7. package/presets/claude/ios-swift/rules/README.md +44 -0
  8. package/presets/claude/ios-swift/rules/api-and-data/README.md +9 -0
  9. package/presets/claude/ios-swift/rules/api-and-data/networking.md +49 -0
  10. package/presets/claude/ios-swift/rules/architecture/README.md +10 -0
  11. package/presets/claude/ios-swift/rules/architecture/boundaries.md +33 -0
  12. package/presets/claude/ios-swift/rules/architecture/feature-delivery.md +60 -0
  13. package/presets/claude/ios-swift/rules/stack/README.md +10 -0
  14. package/presets/claude/ios-swift/rules/stack/ios-app-core.md +42 -0
  15. package/presets/claude/ios-swift/rules/stack/swift-conventions.md +51 -0
  16. package/presets/claude/ios-swift/rules/testing/README.md +10 -0
  17. package/presets/claude/ios-swift/rules/testing/ui.md +41 -0
  18. package/presets/claude/ios-swift/rules/testing/unit.md +41 -0
  19. package/presets/claude/ios-swift/rules/tooling-and-review/README.md +11 -0
  20. package/presets/claude/ios-swift/rules/tooling-and-review/code-quality.md +38 -0
  21. package/presets/claude/ios-swift/rules/tooling-and-review/code-review.md +41 -0
  22. package/presets/claude/ios-swift/rules/tooling-and-review/post-change-build.md +31 -0
  23. package/presets/claude/ios-swift/rules/ui-and-accessibility/README.md +10 -0
  24. package/presets/claude/ios-swift/rules/ui-and-accessibility/swiftui.md +61 -0
  25. package/presets/claude/ios-swift/rules/ui-and-accessibility/viewmodels.md +43 -0
  26. package/presets/claude/next/CLAUDE.md +5 -29
  27. package/presets/claude/next/README.md +0 -10
  28. package/presets/claude/next/agents/README.md +0 -125
  29. package/presets/claude/next/commands/README.md +2 -10
  30. package/presets/claude/next/hooks/README.md +2 -5
  31. package/presets/claude/next/rules/README.md +11 -25
  32. package/presets/claude/next/rules/api-and-data/README.md +1 -7
  33. package/presets/claude/next/rules/architecture/README.md +2 -9
  34. package/presets/claude/next/rules/stack/README.md +1 -9
  35. package/presets/claude/next/rules/testing/README.md +1 -9
  36. package/presets/claude/next/rules/tooling-and-review/README.md +1 -14
  37. package/presets/claude/next/rules/ui-and-accessibility/README.md +1 -8
  38. package/presets/claude/next/skills/README.md +1 -11
  39. package/presets/cursor/ios-swift/README.md +17 -0
  40. package/presets/cursor/ios-swift/commands/README.md +3 -0
  41. package/presets/cursor/ios-swift/rules/README.md +33 -0
  42. package/presets/cursor/ios-swift/rules/architecture-boundaries.mdc +34 -0
  43. package/presets/cursor/ios-swift/rules/code-quality-and-refactoring.mdc +39 -0
  44. package/presets/cursor/ios-swift/rules/code-review-mr.mdc +42 -0
  45. package/presets/cursor/ios-swift/rules/feature-delivery-workflow.mdc +61 -0
  46. package/presets/cursor/ios-swift/rules/ios-app-core.mdc +43 -0
  47. package/presets/cursor/ios-swift/rules/networking-services.mdc +49 -0
  48. package/presets/cursor/ios-swift/rules/post-change-build.mdc +32 -0
  49. package/presets/cursor/ios-swift/rules/state-and-viewmodels.mdc +43 -0
  50. package/presets/cursor/ios-swift/rules/swift-conventions.mdc +51 -0
  51. package/presets/cursor/ios-swift/rules/swiftui-ui.mdc +61 -0
  52. package/presets/cursor/ios-swift/rules/tests-ui.mdc +41 -0
  53. package/presets/cursor/ios-swift/rules/tests-unit.mdc +41 -0
  54. package/presets/cursor/next/commands/README.md +1 -49
  55. package/presets/cursor/next/rules/README.md +0 -47
  56. package/presets/cursor/next/rules/api-services.mdc +10 -12
  57. package/presets/cursor/next/rules/architecture-boundaries.mdc +12 -31
  58. package/presets/cursor/next/rules/code-quality-and-refactoring.mdc +4 -5
  59. package/presets/cursor/next/rules/code-review-mr.mdc +7 -14
  60. package/presets/cursor/next/rules/next-app-core.mdc +61 -18
  61. package/presets/cursor/next/rules/no-props-spread.mdc +4 -27
  62. package/presets/cursor/next/rules/playwright-agents.mdc +1 -2
  63. package/presets/cursor/next/rules/react-ui.mdc +3 -32
  64. package/presets/cursor/next/rules/store-rtk.mdc +6 -13
  65. package/presets/cursor/next/rules/tests-unit.mdc +10 -30
  66. package/CHANGELOG.md +0 -22
  67. package/presets/claude/next/agents/accessibility-reviewer.md +0 -65
  68. package/presets/claude/next/agents/api-contract-reviewer.md +0 -69
  69. package/presets/claude/next/agents/build-verifier.md +0 -64
  70. package/presets/claude/next/agents/ci-investigator.md +0 -62
  71. package/presets/claude/next/agents/code-reviewer.md +0 -62
  72. package/presets/claude/next/agents/debugger.md +0 -63
  73. package/presets/claude/next/agents/feature-developer.md +0 -27
  74. package/presets/claude/next/agents/migration-specialist.md +0 -69
  75. package/presets/claude/next/agents/performance-auditor.md +0 -68
  76. package/presets/claude/next/agents/qa-tester.md +0 -56
  77. package/presets/claude/next/agents/security-reviewer.md +0 -64
  78. package/presets/claude/next/agents/solution-architect.md +0 -70
  79. package/presets/claude/next/agents/task-analyst.md +0 -109
  80. package/presets/claude/next/agents/task-router.md +0 -70
  81. package/presets/claude/next/agents/tech-writer.md +0 -60
  82. package/presets/claude/next/agents/unit-test-generator.md +0 -37
  83. package/presets/claude/next/agents/unit-test-healer.md +0 -38
  84. package/presets/claude/next/agents/unit-test-planner.md +0 -62
  85. package/presets/claude/next/commands/feature-continue.md +0 -51
  86. package/presets/claude/next/commands/feature-start.md +0 -30
  87. package/presets/claude/next/commands/task-continue.md +0 -49
  88. package/presets/claude/next/commands/task.md +0 -50
  89. package/presets/claude/next/commands/technical-retro.md +0 -58
  90. package/presets/claude/next/hooks/chain-team-phases.sh +0 -342
  91. package/presets/claude/next/hooks/guard-shell-command.sh +0 -77
  92. package/presets/claude/next/rules/api-and-data/api-services.md +0 -57
  93. package/presets/claude/next/rules/api-and-data/http-client.md +0 -40
  94. package/presets/claude/next/rules/api-and-data/store-rtk.md +0 -65
  95. package/presets/claude/next/rules/architecture/api-public-imports.md +0 -8
  96. package/presets/claude/next/rules/architecture/architecture-boundaries.md +0 -72
  97. package/presets/claude/next/rules/architecture/feature-delivery-workflow.md +0 -79
  98. package/presets/claude/next/rules/architecture/layer-barrel-exports.md +0 -58
  99. package/presets/claude/next/rules/architecture/public-imports.md +0 -46
  100. package/presets/claude/next/rules/architecture/reference-features.md +0 -37
  101. package/presets/claude/next/rules/architecture/types-public-imports.md +0 -8
  102. package/presets/claude/next/rules/stack/arrow-functions.md +0 -45
  103. package/presets/claude/next/rules/stack/navigation-router.md +0 -61
  104. package/presets/claude/next/rules/stack/next-app-core.md +0 -33
  105. package/presets/claude/next/rules/stack/next-app-router.md +0 -36
  106. package/presets/claude/next/rules/stack/no-type-assertion.md +0 -59
  107. package/presets/claude/next/rules/stack/types-jsdoc.md +0 -37
  108. package/presets/claude/next/rules/testing/playwright-agents.md +0 -74
  109. package/presets/claude/next/rules/testing/tests-e2e-structure.md +0 -52
  110. package/presets/claude/next/rules/testing/tests-unit.md +0 -66
  111. package/presets/claude/next/rules/tooling-and-review/agent-team-intake.md +0 -15
  112. package/presets/claude/next/rules/tooling-and-review/agent-team-orchestrator.md +0 -134
  113. package/presets/claude/next/rules/tooling-and-review/code-quality.md +0 -42
  114. package/presets/claude/next/rules/tooling-and-review/code-review-mr.md +0 -67
  115. package/presets/claude/next/rules/tooling-and-review/package-manager.md +0 -11
  116. package/presets/claude/next/rules/tooling-and-review/post-change-lint.md +0 -33
  117. package/presets/claude/next/rules/ui-and-accessibility/component-styles.md +0 -56
  118. package/presets/claude/next/rules/ui-and-accessibility/css-property-order.md +0 -14
  119. package/presets/claude/next/rules/ui-and-accessibility/no-props-spread.md +0 -57
  120. package/presets/claude/next/rules/ui-and-accessibility/react-a11y-coding.md +0 -37
  121. package/presets/claude/next/rules/ui-and-accessibility/react-ui.md +0 -90
  122. package/presets/claude/next/skills/ci-investigation/SKILL.md +0 -36
  123. package/presets/claude/next/skills/code-review/SKILL.md +0 -26
  124. package/presets/claude/next/skills/debug-investigation/SKILL.md +0 -28
  125. package/presets/claude/next/skills/feature-delivery/SKILL.md +0 -15
  126. package/presets/claude/next/skills/playwright-e2e/SKILL.md +0 -31
  127. package/presets/claude/next/skills/technical-retro/SKILL.md +0 -40
  128. package/presets/claude/next/skills/unit-testing/SKILL.md +0 -32
  129. package/presets/claude/next/team/README.md +0 -46
  130. package/presets/claude/next/team/tasks/.gitkeep +0 -1
  131. package/presets/cursor/next/AGENTS.md +0 -43
  132. package/presets/cursor/next/BUGBOT.md +0 -14
  133. package/presets/cursor/next/agents/README.md +0 -158
  134. package/presets/cursor/next/agents/accessibility-reviewer.md +0 -67
  135. package/presets/cursor/next/agents/api-contract-reviewer.md +0 -71
  136. package/presets/cursor/next/agents/build-verifier.md +0 -66
  137. package/presets/cursor/next/agents/ci-investigator.md +0 -64
  138. package/presets/cursor/next/agents/code-reviewer.md +0 -64
  139. package/presets/cursor/next/agents/debugger.md +0 -64
  140. package/presets/cursor/next/agents/feature-developer.md +0 -27
  141. package/presets/cursor/next/agents/migration-specialist.md +0 -71
  142. package/presets/cursor/next/agents/performance-auditor.md +0 -70
  143. package/presets/cursor/next/agents/playwright-test-generator.md +0 -26
  144. package/presets/cursor/next/agents/playwright-test-healer.md +0 -26
  145. package/presets/cursor/next/agents/playwright-test-planner.md +0 -28
  146. package/presets/cursor/next/agents/qa-tester.md +0 -57
  147. package/presets/cursor/next/agents/security-reviewer.md +0 -66
  148. package/presets/cursor/next/agents/solution-architect.md +0 -71
  149. package/presets/cursor/next/agents/task-analyst.md +0 -112
  150. package/presets/cursor/next/agents/task-router.md +0 -71
  151. package/presets/cursor/next/agents/tech-writer.md +0 -62
  152. package/presets/cursor/next/agents/unit-test-generator.md +0 -39
  153. package/presets/cursor/next/agents/unit-test-healer.md +0 -40
  154. package/presets/cursor/next/agents/unit-test-planner.md +0 -64
  155. package/presets/cursor/next/commands/feature-continue.md +0 -19
  156. package/presets/cursor/next/commands/feature-start.md +0 -33
  157. package/presets/cursor/next/commands/task-continue.md +0 -49
  158. package/presets/cursor/next/commands/task.md +0 -50
  159. package/presets/cursor/next/commands/technical-retro.md +0 -81
  160. package/presets/cursor/next/hooks/README.md +0 -8
  161. package/presets/cursor/next/hooks/chain-team-phases.sh +0 -380
  162. package/presets/cursor/next/hooks/guard-shell-command.sh +0 -77
  163. package/presets/cursor/next/hooks.json +0 -17
  164. package/presets/cursor/next/rules/agent-team-intake.mdc +0 -14
  165. package/presets/cursor/next/rules/agent-team-orchestrator.mdc +0 -139
  166. package/presets/cursor/next/rules/api-public-imports.mdc +0 -8
  167. package/presets/cursor/next/rules/arrow-functions.mdc +0 -46
  168. package/presets/cursor/next/rules/css-property-order-stylelint.mdc +0 -16
  169. package/presets/cursor/next/rules/feature-delivery-workflow.mdc +0 -76
  170. package/presets/cursor/next/rules/http-client.mdc +0 -42
  171. package/presets/cursor/next/rules/layer-barrel-exports.mdc +0 -59
  172. package/presets/cursor/next/rules/navigation-router-stack.mdc +0 -62
  173. package/presets/cursor/next/rules/next-app-router.mdc +0 -36
  174. package/presets/cursor/next/rules/no-cross-component-styles-import.mdc +0 -58
  175. package/presets/cursor/next/rules/no-type-assertion-as-import-export.mdc +0 -60
  176. package/presets/cursor/next/rules/package-manager.mdc +0 -16
  177. package/presets/cursor/next/rules/post-change-lint.mdc +0 -38
  178. package/presets/cursor/next/rules/public-imports.mdc +0 -48
  179. package/presets/cursor/next/rules/react-a11y-coding.mdc +0 -37
  180. package/presets/cursor/next/rules/reference-features.mdc +0 -39
  181. package/presets/cursor/next/rules/technical-retro.mdc +0 -12
  182. package/presets/cursor/next/rules/types-jsdoc.mdc +0 -42
  183. package/presets/cursor/next/rules/types-public-imports.mdc +0 -8
  184. package/presets/cursor/next/skills/README.md +0 -15
  185. package/presets/cursor/next/skills/ci-investigation/SKILL.md +0 -36
  186. package/presets/cursor/next/skills/code-review/SKILL.md +0 -26
  187. package/presets/cursor/next/skills/debug-investigation/SKILL.md +0 -28
  188. package/presets/cursor/next/skills/feature-delivery/SKILL.md +0 -15
  189. package/presets/cursor/next/skills/playwright-e2e/SKILL.md +0 -31
  190. package/presets/cursor/next/skills/technical-retro/SKILL.md +0 -40
  191. package/presets/cursor/next/skills/unit-testing/SKILL.md +0 -32
  192. package/presets/cursor/next/team/README.md +0 -104
  193. package/presets/cursor/next/team/tasks/.gitkeep +0 -0
@@ -1,342 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Chains agent team phases after subagent completion when wired into Claude Code hooks.
3
-
4
- set -euo pipefail
5
-
6
- input=$(cat)
7
-
8
- INPUT="$input" node <<'NODE'
9
- const fs = require('fs');
10
- const path = require('path');
11
-
12
- const TEAM_ROOT = path.join(process.cwd(), '.claude', 'team');
13
-
14
- const inputRaw = process.env.INPUT || '';
15
- let hookInput;
16
- try {
17
- hookInput = JSON.parse(inputRaw);
18
- } catch {
19
- process.stdout.write('{}');
20
- process.exit(0);
21
- }
22
-
23
- if (hookInput.status !== 'completed') {
24
- process.stdout.write('{}');
25
- process.exit(0);
26
- }
27
-
28
- const activePath = path.join(TEAM_ROOT, 'active-task.json');
29
-
30
- if (!fs.existsSync(activePath)) {
31
- process.stdout.write('{}');
32
- process.exit(0);
33
- }
34
-
35
- let active;
36
- try {
37
- active = JSON.parse(fs.readFileSync(activePath, 'utf8'));
38
- } catch {
39
- process.stdout.write('{}');
40
- process.exit(0);
41
- }
42
-
43
- const slug = active.slug;
44
- if (!slug) {
45
- process.stdout.write('{}');
46
- process.exit(0);
47
- }
48
-
49
- const taskDir = path.join(TEAM_ROOT, 'tasks', slug);
50
- const statusPath = path.join(taskDir, 'status.json');
51
- const pipelinePath = path.join(taskDir, 'pipeline.json');
52
-
53
- if (!fs.existsSync(statusPath)) {
54
- process.stdout.write('{}');
55
- process.exit(0);
56
- }
57
-
58
- let status;
59
- try {
60
- status = JSON.parse(fs.readFileSync(statusPath, 'utf8'));
61
- } catch {
62
- process.stdout.write('{}');
63
- process.exit(0);
64
- }
65
-
66
- const now = new Date().toISOString();
67
-
68
- function writeStatus(next) {
69
- status = { ...status, ...next, slug, updatedAt: now };
70
- fs.writeFileSync(statusPath, JSON.stringify(status, null, 2) + '\n');
71
- }
72
-
73
- function out(message) {
74
- process.stdout.write(JSON.stringify({ followup_message: message }));
75
- }
76
-
77
- function readArtifact(name) {
78
- const p = path.join(taskDir, name);
79
- if (!fs.existsSync(p)) return '';
80
- try {
81
- return fs.readFileSync(p, 'utf8');
82
- } catch {
83
- return '';
84
- }
85
- }
86
-
87
- function getStepAgents(step) {
88
- if (!step) return [];
89
- return Array.isArray(step.agent) ? step.agent : [step.agent];
90
- }
91
-
92
- function skipIfMatches(skipIf) {
93
- if (!skipIf) return false;
94
- if (skipIf === 'debugger.fixed') {
95
- const text = readArtifact('debug-report.md');
96
- return /fixApplied:\s*true/i.test(text) || /\*\*Fix applied:\*\*\s*true/i.test(text);
97
- }
98
- if (skipIf === 'ci-investigator.resolved') {
99
- const text = readArtifact('ci-report.md');
100
- return /fixApplied:\s*true/i.test(text) || /## Verdict\s*\nPASS/i.test(text);
101
- }
102
- return false;
103
- }
104
-
105
- function findNextExecutableStep(steps, startIdx) {
106
- for (let i = startIdx; i < steps.length; i++) {
107
- if (!skipIfMatches(steps[i].skipIf)) {
108
- return { step: steps[i], index: i };
109
- }
110
- }
111
- return null;
112
- }
113
-
114
- const AGENT_HANDOFF = {
115
- 'task-analyst': (s) =>
116
- `Invoke task-analyst for slug "${s}". Write brief.md and decomposition.md under .claude/team/tasks/${s}/. ` +
117
- `Set status.json: phase executing, state awaiting_approval if human gate applies.`,
118
- debugger: (s) =>
119
- `Invoke debugger subagent for slug "${s}". Write debug-report.md with fixApplied: true/false. Update status.json when done.`,
120
- 'solution-architect': (s) =>
121
- `Invoke solution-architect for slug "${s}". Read brief.md; write architecture.md. Update status.json when done.`,
122
- 'migration-specialist': (s) =>
123
- `Invoke migration-specialist for slug "${s}". Read brief.md; write migration-plan.md. Update status.json when done.`,
124
- 'api-contract-reviewer': (s) =>
125
- `Invoke api-contract-reviewer for slug "${s}". Write api-contract-review.md. Update status.json when done.`,
126
- 'ci-investigator': (s) =>
127
- `Invoke ci-investigator for slug "${s}". Use ci-investigation skill. Write ci-report.md. Update status.json when done.`,
128
- 'feature-developer': (s) =>
129
- `Invoke feature-developer for slug "${s}". Read brief.md, decomposition.md, validation-report.md, review.md if present. ` +
130
- `Follow rules/architecture/feature-delivery-workflow.md and architecture/reference-features.md. Include unit tests before handoff. Update status.json when done.`,
131
- 'build-verifier': (s) =>
132
- `Invoke build-verifier for slug "${s}". Run lint:js, lint:css, type-check, targeted unit tests from app/. ` +
133
- `Write validation-report.md. Set state completed or validation_failed. Do not edit production code.`,
134
- 'accessibility-reviewer': (s) =>
135
- `Invoke accessibility-reviewer for slug "${s}". Write a11y-review.md. Update status.json when done.`,
136
- 'performance-auditor': (s) =>
137
- `Invoke performance-auditor for slug "${s}". Write perf-report.md. Update status.json when done.`,
138
- 'code-reviewer': (s) =>
139
- `Invoke code-reviewer for slug "${s}". Review git diff per rules/tooling-and-review/code-review-mr.md. Update status.json when done.`,
140
- 'security-reviewer': (s) =>
141
- `Invoke security-reviewer for slug "${s}". Write security-review.md. Update status.json when done.`,
142
- 'qa-tester': (s, scope) =>
143
- `Invoke qa-tester for slug "${s}"${scope ? ` (scope: ${scope})` : ''}. Update status.json when done.`,
144
- 'unit-test-planner': (s) =>
145
- `Invoke unit-test-planner for slug "${s}". Use unit-testing skill. Update status.json when done.`,
146
- 'unit-test-generator': (s) =>
147
- `Invoke unit-test-generator for slug "${s}". Use unit-testing skill. Update status.json when done.`,
148
- 'unit-test-healer': (s) =>
149
- `Invoke unit-test-healer for slug "${s}". Use unit-testing and debug-investigation skills. Update status.json when done.`,
150
- 'playwright-test-planner': (s) =>
151
- `Invoke playwright-test-planner for slug "${s}". Follow rules/testing/playwright-agents.md and playwright-e2e skill. Update status.json when done.`,
152
- 'playwright-test-generator': (s) =>
153
- `Invoke playwright-test-generator for slug "${s}". Use Playwright MCP tools when available. Update status.json when done.`,
154
- 'playwright-test-healer': (s) =>
155
- `Invoke playwright-test-healer for slug "${s}". Use Playwright MCP when available. Update status.json when done.`,
156
- 'tech-writer': (s) =>
157
- `Invoke tech-writer for slug "${s}". Write documentation.md. Update status.json when done.`,
158
- };
159
-
160
- const REVIEW_AGENTS = new Set([
161
- 'code-reviewer',
162
- 'accessibility-reviewer',
163
- 'security-reviewer',
164
- 'api-contract-reviewer',
165
- ]);
166
-
167
- function handoffForAgent(agent, scope) {
168
- const fn = AGENT_HANDOFF[agent];
169
- return fn ? fn(slug, scope) : `Invoke ${agent} subagent for slug "${slug}". Update status.json when done.`;
170
- }
171
-
172
- function handoffForParallelStep(step) {
173
- const agents = getStepAgents(step);
174
- return (
175
- `Invoke IN PARALLEL (one message, multiple Task calls): ${agents.join(' AND ')} for slug "${slug}". ` +
176
- `Each agent appends itself to status.json parallelCompleted when done.`
177
- );
178
- }
179
-
180
- function hasGateAfter(agent, humanGates) {
181
- return Array.isArray(humanGates) && humanGates.includes(`after:${agent}`);
182
- }
183
-
184
- function hasGateAfterStep(step, humanGates) {
185
- return getStepAgents(step).some((a) => hasGateAfter(a, humanGates));
186
- }
187
-
188
- function legacyFlow() {
189
- if (status.phase === 'development' && status.state === 'completed') {
190
- writeStatus({ phase: 'executing', state: 'in_progress', currentAgent: 'build-verifier' });
191
- out(handoffForAgent('build-verifier'));
192
- process.exit(0);
193
- }
194
- if (status.currentAgent === 'build-verifier' && status.state === 'completed') {
195
- writeStatus({ phase: 'executing', state: 'in_progress', currentAgent: 'code-reviewer' });
196
- out(handoffForAgent('code-reviewer'));
197
- process.exit(0);
198
- }
199
- if (status.phase === 'review' && status.state === 'completed') {
200
- writeStatus({ phase: 'executing', state: 'in_progress', currentAgent: 'qa-tester' });
201
- out(handoffForAgent('qa-tester'));
202
- process.exit(0);
203
- }
204
- if (status.state === 'changes_requested' && REVIEW_AGENTS.has(status.currentAgent)) {
205
- writeStatus({
206
- currentAgent: 'feature-developer',
207
- state: 'in_progress',
208
- phase: 'executing',
209
- retryAfterFix: status.currentAgent,
210
- });
211
- out(handoffForAgent('feature-developer') + ` After fixes, re-run ${status.currentAgent}.`);
212
- process.exit(0);
213
- }
214
- if (status.state === 'validation_failed') {
215
- writeStatus({
216
- currentAgent: 'feature-developer',
217
- state: 'in_progress',
218
- retryAfterFix: 'build-verifier',
219
- });
220
- out(handoffForAgent('feature-developer') + ` Read validation-report.md. Re-run build-verifier after fixes.`);
221
- process.exit(0);
222
- }
223
- if (status.state === 'completed' && status.retryAfterFix) {
224
- const retry = status.retryAfterFix;
225
- writeStatus({ currentAgent: retry, state: 'in_progress', retryAfterFix: null });
226
- out(handoffForAgent(retry));
227
- process.exit(0);
228
- }
229
- if (status.phase === 'testing' && status.state === 'completed') {
230
- writeStatus({ phase: 'done', state: 'completed' });
231
- out(`Pipeline complete for "${slug}". Run /technical-retro ${slug}.`);
232
- process.exit(0);
233
- }
234
- process.stdout.write('{}');
235
- process.exit(0);
236
- }
237
-
238
- if (!fs.existsSync(pipelinePath)) {
239
- legacyFlow();
240
- }
241
-
242
- let pipeline;
243
- try {
244
- pipeline = JSON.parse(fs.readFileSync(pipelinePath, 'utf8'));
245
- } catch {
246
- legacyFlow();
247
- }
248
-
249
- const steps = pipeline.steps || [];
250
- if (steps.length === 0 || pipeline.autoChain === false) {
251
- process.stdout.write('{}');
252
- process.exit(0);
253
- }
254
-
255
- if (status.awaitingHumanGate || status.state === 'awaiting_approval') {
256
- process.stdout.write('{}');
257
- process.exit(0);
258
- }
259
-
260
- if (status.state === 'changes_requested' && REVIEW_AGENTS.has(status.currentAgent)) {
261
- const reviewer = status.currentAgent;
262
- writeStatus({
263
- currentAgent: 'feature-developer',
264
- state: 'in_progress',
265
- phase: 'executing',
266
- retryAfterFix: reviewer,
267
- });
268
- out(handoffForAgent('feature-developer') + ` After fixes, re-run ${reviewer}.`);
269
- process.exit(0);
270
- }
271
-
272
- if (status.state === 'validation_failed' && status.currentAgent === 'build-verifier') {
273
- writeStatus({
274
- currentAgent: 'feature-developer',
275
- state: 'in_progress',
276
- phase: 'executing',
277
- retryAfterFix: 'build-verifier',
278
- });
279
- out(handoffForAgent('feature-developer') + ` Read validation-report.md. Re-run build-verifier after fixes.`);
280
- process.exit(0);
281
- }
282
-
283
- if (status.state === 'completed' && status.retryAfterFix) {
284
- const retry = status.retryAfterFix;
285
- writeStatus({ currentAgent: retry, state: 'in_progress', retryAfterFix: null });
286
- out(handoffForAgent(retry));
287
- process.exit(0);
288
- }
289
-
290
- const idx = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
291
- const currentStep = steps[idx];
292
- if (!currentStep) {
293
- writeStatus({ phase: 'done', state: 'completed', currentAgent: null });
294
- out(`Pipeline complete for "${slug}". Run /technical-retro ${slug}.`);
295
- process.exit(0);
296
- }
297
-
298
- const completedAgent = status.currentAgent || getStepAgents(currentStep)[0];
299
- const stepAgents = getStepAgents(currentStep);
300
-
301
- if (currentStep.parallel && stepAgents.length > 1) {
302
- const done = [...(status.parallelCompleted || [])];
303
- if (completedAgent && !done.includes(completedAgent)) done.push(completedAgent);
304
- writeStatus({ parallelCompleted: done });
305
- if (stepAgents.filter((a) => !done.includes(a)).length > 0) {
306
- process.stdout.write('{}');
307
- process.exit(0);
308
- }
309
- writeStatus({ parallelCompleted: [] });
310
- }
311
-
312
- if (hasGateAfterStep(currentStep, pipeline.humanGates)) {
313
- writeStatus({ awaitingHumanGate: true, state: 'awaiting_approval', currentAgent: completedAgent });
314
- process.stdout.write('{}');
315
- process.exit(0);
316
- }
317
-
318
- const next = findNextExecutableStep(steps, idx + 1);
319
- if (!next) {
320
- writeStatus({ pipelineIndex: steps.length, phase: 'done', state: 'completed', currentAgent: null });
321
- out(`Pipeline complete for "${slug}". Run /technical-retro ${slug}.`);
322
- process.exit(0);
323
- }
324
-
325
- const { step: nextStep, index: nextIdx } = next;
326
- const nextAgents = getStepAgents(nextStep);
327
-
328
- writeStatus({
329
- pipelineIndex: nextIdx,
330
- currentAgent: nextAgents[0],
331
- phase: 'executing',
332
- state: 'in_progress',
333
- awaitingHumanGate: false,
334
- parallelCompleted: [],
335
- });
336
-
337
- if (nextStep.parallel && nextAgents.length > 1) {
338
- out(handoffForParallelStep(nextStep));
339
- } else {
340
- out(handoffForAgent(nextAgents[0], nextStep.scope));
341
- }
342
- NODE
@@ -1,77 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Lightweight shell guard for Claude projects using this preset.
3
-
4
- set -euo pipefail
5
-
6
- input=$(cat)
7
-
8
- INPUT="$input" node <<'NODE'
9
- const fs = require('fs');
10
-
11
- const raw = process.env.INPUT || '';
12
- let event;
13
- try {
14
- event = JSON.parse(raw);
15
- } catch {
16
- process.stdout.write('{ "permission": "allow" }');
17
- process.exit(0);
18
- }
19
-
20
- const command = String(event.command || event.input?.command || '');
21
- if (!command.trim()) {
22
- process.stdout.write('{ "permission": "allow" }');
23
- process.exit(0);
24
- }
25
-
26
- function out(permission, userMessage, agentMessage) {
27
- process.stdout.write(JSON.stringify({
28
- permission,
29
- user_message: userMessage,
30
- agent_message: agentMessage || userMessage,
31
- }));
32
- }
33
-
34
- const dangerousGit = /\bgit\s+(reset\s+--hard|clean\s+-[^\n]*f|push\s+--force|push\s+-f|checkout\s+--\s+)/;
35
- if (dangerousGit.test(command)) {
36
- out(
37
- 'ask',
38
- 'This command looks destructive for git state. Review it before continuing.',
39
- 'A project hook flagged a destructive git command. Ask the user before running it.',
40
- );
41
- process.exit(0);
42
- }
43
-
44
- const managerByFile = [
45
- ['yarn.lock', 'yarn'],
46
- ['pnpm-lock.yaml', 'pnpm'],
47
- ['package-lock.json', 'npm'],
48
- ].find(([file]) => fs.existsSync(file));
49
-
50
- let expected = managerByFile?.[1];
51
- if (!expected && fs.existsSync('package.json')) {
52
- try {
53
- const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
54
- const pm = typeof pkg.packageManager === 'string' ? pkg.packageManager : '';
55
- expected = pm.split('@')[0] || undefined;
56
- } catch {
57
- // Ignore invalid package.json in the hook; the agent can diagnose it later.
58
- }
59
- }
60
-
61
- if (!expected) {
62
- process.stdout.write('{ "permission": "allow" }');
63
- process.exit(0);
64
- }
65
-
66
- const used = command.match(/(^|[;&|]\s*)(npm|yarn|pnpm)\s+/)?.[2];
67
- if (used && used !== expected) {
68
- out(
69
- 'ask',
70
- `This repository appears to use ${expected}, but the command uses ${used}. Confirm before continuing.`,
71
- `Use ${expected} for package scripts and installs unless the user explicitly approves ${used}.`,
72
- );
73
- process.exit(0);
74
- }
75
-
76
- process.stdout.write('{ "permission": "allow" }');
77
- NODE
@@ -1,57 +0,0 @@
1
- ---
2
- paths:
3
- - app/src/api/services/**/*.ts
4
- ---
5
-
6
- # Роль API слоя
7
-
8
- - Инкапсулировать всё, что связано с:
9
- - HTTP‑запросами через **экземпляры прикладных API‑клиентов** в `app/src/api/clients/**`, собранные на **общей реализации** из `app/src/lib/clients/**` (как в существующем коде); подробности — **`api-and-data/http-client.md`**; положение слоя в схеме **порты и адаптеры** — `architecture/architecture-boundaries.md`;
10
- - URL/путями,
11
- - заголовками и кодами ответов,
12
- - DTO backend.
13
- - Предоставлять UI и store **стабильный доменный интерфейс**:
14
- - функции, работающие с доменными типами из `@/types` (`architecture/public-imports.md`).
15
- - мапперы между DTO и доменными типами.
16
-
17
- # Структура модулей
18
-
19
- - Для каждой доменной области (например, заказы, биллинг, настройки аккаунта):
20
- - отдельный каталог в `app/src/api/services/<ИмяСервиса или фичи>/**` по конвенции репозитория.
21
- - Внутри модуля:
22
- - файлы с вызовами API (`index.ts` или `*.service.ts`);
23
- - файлы мапперов (`*responseMappers.ts`);
24
- - специфичные типы запросов/ответов (если не вынесены в `app/src/types/**` с экспортом через barrel `@/types`).
25
- - при необходимости — локальные `index.ts` / barrel внутри модуля для структуры **внутри** `app/src/api/**`; **снаружи** этого слоя UI, store и остальной код импортируют только из корневого barrel `app/src/api/index.ts` (`import … from '@/api'`, **`architecture/public-imports.md`**).
26
-
27
- # Мапперы и типы
28
-
29
- - Для каждого запроса/эндпоинта:
30
- - описывать **response‑тип (DTO)**, точно соответствующий контракту backend;
31
- - определять **целевой доменный тип** в `app/src/types/**`, с которым будет работать приложение (включая вычисляемые/агрегированные поля).
32
- - Мапперы (например, `*responseMappers.ts`):
33
- - чистые функции, без сайд‑эффектов;
34
- - выполняют все необходимые вычисления и преобразования данных (булевы флаги, склейка строк, агрегаты и т.п.) при переводе из DTO в доменные модели;
35
- - при необходимости обеспечивают обратное преобразование (доменные модели → транспортные типы).
36
- - UI и store работают только с доменными типами (из `@/types` или экспортируемыми из public API слоя API), а не с «сырыми» DTO.
37
- - **Не вызывать `fetch` напрямую** в теле API‑методов: только через клиент; исключения — узкие модули (например JSON‑RPC), если так уже устроено в репозитории.
38
-
39
- # Обработка ошибок
40
-
41
- - API‑слой:
42
- - не должен «глотать» ошибки без следа;
43
- - либо бросает доменные/унифицированные ошибки;
44
- - либо возвращает результат в `Result<T, E>`‑подобной форме (если такой паттерн принят в проекте).
45
- - Интеграция с APM/трассировкой (если есть в проекте):
46
- - централизованно (HTTP‑клиент, обёртки), а не в каждом методе сервиса.
47
-
48
- # Требование к агенту
49
-
50
- При добавлении/изменении API‑метода:
51
-
52
- - Следовать существующим сервисам и мапперам как эталону.
53
- - Пройти чеклист barrel-экспортов (**`architecture/layer-barrel-exports.md`**): локальный `index.ts` → фасад слоя → корневой barrel.
54
- - Не смешивать слой API и UI/store:
55
- - компоненты не должны зависеть от DTO;
56
- - store не должен сам собирать URL/коды эндпоинтов и не обходить сервисы; **транспортный тип ответа** и **контракт ошибки** из `@/types` (как у прикладного клиента) допустимы во thunk при разборе `catch`/payload, если так выстроен сервис (см. `api-and-data/store-rtk.md`, `api-and-data/http-client.md`).
57
- - При использовании API‑сервисов в UI, store и утилитах **вне** `app/src/api/**` импортировать **только** из `@/api` (корневой barrel), см. **`architecture/public-imports.md`**; внутри слоя API — по относительным путям или `@/api/services/**` / `@/api/clients/**`, не дублируя публичный контракт мимо корневого barrel для внешних потребителей.
@@ -1,40 +0,0 @@
1
- ---
2
- paths:
3
- - app/src/lib/clients/**/*.ts
4
- - app/src/api/clients/**/*.ts
5
- ---
6
-
7
- # HTTP-транспорт
8
-
9
- **Имена** фабрик, классов ошибок, типов ответа и конфига — **как в текущем коде репозитория** и в barrel `app/src/types/index.ts`. Ниже — **архитектурные правила**, а не спецификация переименований.
10
-
11
- ## Роль слоя
12
-
13
- - Обычные REST‑вызовы к backend идут через **одну реализацию** в `app/src/lib/clients/**` (модуль общего клиента) и **преднастроенные экземпляры** в `app/src/api/clients/**`, по тому же паттерну, что уже принят в проекте.
14
- - Место транспорта в общей картине **порты и адаптеры** — в `architecture/architecture-boundaries.md` (раздел **«Порты и адаптеры»**).
15
- - **Не** вызывать `fetch` напрямую из `app/src/api/services/**`, store и UI (см. `architecture/architecture-boundaries.md`, `api-and-data/api-services.md`); из store/UI — только вызовы через сервисы из `@/api` (`architecture/public-imports.md`).
16
- - **Исключения** (узкие протоколы, отдельный транспорт) — только там, где в репозитории уже есть образец; повторять его, не плодить произвольные обходы общего клиента.
17
-
18
- ## Типы
19
-
20
- - Всё, что относится к **контракту запроса/ответа/ошибки** приложения и реэкспортируется для HTTP‑слоя, импортировать **только** из barrel `@/types`, без deep‑импортов из внутренних файлов `app/src/types/**` (см. `architecture/public-imports.md`).
21
- - Не поднимать в новом коде **типы и зависимости от внешнего HTTP‑клиента**, от которого проект ушёл; ориентир — **`package.json`** и существующие вызовы.
22
-
23
- ## Контракт ошибок
24
-
25
- - Ошибки сети и HTTP должны приходить в **едином виде**, который задаёт общий клиент (обычно класс/обёртка с полем вроде `response` для тела и статуса).
26
- - В **`catch`** ориентироваться на **фактическую форму** ошибки в этом репозитории (как в соседних слайсах/сервисах): доступ к телу ошибки, статусу, диагностическому коду — **по полям текущей реализации**, без выдумывания второго формата.
27
-
28
- ## Поведение, которое остаётся в клиенте
29
-
30
- - Общие заголовки, `credentials`, загрузка файлов (**FormData** / снятие лишних заголовков), бинарные ответы (**blob** и аналоги), единообразный разбор JSON и прочих тел.
31
- - Перехват **401 / refresh**, обработка **404** и т.п. — **централизованно**, если так уже сделано в клиенте; не дублировать ту же логику в каждом сервисе.
32
-
33
- ## Связь со store
34
-
35
- - Thunk может возвращать **тип обёртки успешного ответа**, если сервис так устроен; в **state** по возможности класть **доменные** типы после маппинга. Подробнее — `api-and-data/store-rtk.md`.
36
-
37
- ## Требование к агенту
38
-
39
- - Меняя реализацию общего клиента — **обновить или добавить behavior‑тесты** рядом с модулем клиента (`testing/tests-unit.md`).
40
- - Не вводить **второй полноценный HTTP‑стек** без явной задачи и согласования с архитектурой репозитория.
@@ -1,65 +0,0 @@
1
- ---
2
- paths:
3
- - app/src/store/**/*.ts
4
- ---
5
-
6
- # Общие принципы
7
-
8
- - Использовать **Redux Toolkit**:
9
- - `createSlice`, `createAsyncThunk`, RTK Query (если используется).
10
- - Хранить в store **доменные модели**, не «сырые» DTO из API.
11
- - Все вычисления и преобразования данных (включая вычисляемые поля, булевые флаги, агрегаты, человеко‑читаемые строки и т.п.) должны выполняться **между ответом API и записью в store** — в мапперах или отдельном слое подготовки данных. Store хранит уже подготовленную доменную модель.
12
- - Разделять:
13
- - «серверное» состояние (данные из API) и
14
- - локальное UI‑состояние (выбор/фильтры/флаги).
15
-
16
- # Структура слайсов
17
-
18
- - Каждый доменный модуль — свой слайс в `app/src/store/slices/**`.
19
- - Слайс экспортирует:
20
- - `reducer` по умолчанию;
21
- - `actions` именованным экспортом;
22
- - селекторы `selectSomething(state: RootState): Type`.
23
- - Состояние:
24
- - явный тип для state;
25
- - аккуратная инициализация initialState.
26
-
27
- # Асинхронность и сайд‑эффекты
28
-
29
- - Асинхронные запросы:
30
- - через `createAsyncThunk` или RTK Query.
31
- - внутри thunk:
32
- - вызывать API через сервисы, импортированные из `@/api` (**`architecture/public-imports.md`**);
33
- - не вызывать HTTP‑клиент напрямую — только через эти сервисы.
34
- - Сайд‑эффекты (логирование, аналитика, работа с файлами):
35
- - выносить в middleware (`app/src/store/middleware/**`) или специализированные слайсы.
36
-
37
- # Типизация
38
-
39
- - Использовать `RootState`, `AppDispatch` и типизированные хуки `useAppDispatch`, `useAppSelector` (если есть).
40
- - **HTTP и ошибки API**:
41
- - не импортировать типы **сторонних HTTP‑библиотек**, которых нет в актуальных зависимостях и существующих слайсах (ориентир — **`package.json`** и соседние файлы);
42
- - когда сервис возвращает **обёртку ответа** прикладного клиента — использовать **соответствующий тип из `@/types`** (как в barrel и в аналогичных thunk’ах);
43
- - при ошибках после вызова сервиса — опираться на **тот же класс/контракт ошибки транспорта**, что использует общий клиент (из `@/types`), и разбирать тело/статус **по полям текущей реализации**, а не по воображаемому API;
44
- - в **`catch`** предпочитать **`instanceof`** на класс ошибки транспорта из `@/types` (если он есть в коде) вместо голого `as`, когда это выразимо без шума (см. `stack/no-type-assertion.md`).
45
- - Для сущностей:
46
- - доменные типы (включая вычисляемые поля) определять в `app/src/types/**`, экспортировать через barrel и импортировать в слайсы из `@/types` как **источник правды** (`architecture/public-imports.md`);
47
- - избегать дублирования описаний сущностей в нескольких местах.
48
- - **Граница домена**: в **state** хранить доменные модели; тип **обёртки ответа клиента** допустим как тип **возвращаемого значения thunk** или промежуточно до маппинга — без дублирования DTO в полях state без нужды (согласовано с `api-and-data/api-services.md` и `api-and-data/http-client.md`).
49
-
50
- # Тестирование слайсов
51
-
52
- - Для важных слайсов:
53
- - тестировать редюсеры (инициализация, основные переходы состояний);
54
- - тестировать селекторы (включая edge cases).
55
- - Thunk’и:
56
- - по возможности покрывать тестами с моками API‑слоя.
57
-
58
- # Требование к агенту
59
-
60
- При изменении/создании слайса:
61
-
62
- - Не класть логику API внутрь редюсеров/компонентов.
63
- - Строго типизировать state и actions.
64
- - Использовать **единый стиль именования actions и селекторов**, как в существующих слайсах.
65
- - При работе с ошибками и ответами HTTP опираться на **`api-and-data/http-client.md`** и контракты из `@/types`, а не на типы внешних HTTP‑библиотек вне зависимостей проекта.
@@ -1,8 +0,0 @@
1
- ---
2
- paths:
3
- - app/src/api/**/*
4
- ---
5
-
6
- # Deprecated
7
-
8
- Содержимое перенесено в **`architecture/public-imports.md`** (раздел `@/api`).