@gempack/squad-mcp 0.5.0 → 0.6.1

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 (102) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +3 -2
  3. package/CHANGELOG.md +271 -17
  4. package/INSTALL.md +156 -24
  5. package/README.md +278 -27
  6. package/agents/{PO.md → product-owner.md} +33 -1
  7. package/agents/{Senior-Architect.md → senior-architect.md} +33 -1
  8. package/agents/{Senior-DBA.md → senior-dba.md} +33 -1
  9. package/agents/{Senior-Dev-Reviewer.md → senior-dev-reviewer.md} +33 -1
  10. package/agents/{Senior-Dev-Security.md → senior-dev-security.md} +33 -1
  11. package/agents/{Senior-Developer.md → senior-developer.md} +33 -1
  12. package/agents/{Senior-QA.md → senior-qa.md} +33 -1
  13. package/agents/{TechLead-Consolidator.md → tech-lead-consolidator.md} +7 -1
  14. package/agents/{TechLead-Planner.md → tech-lead-planner.md} +7 -1
  15. package/commands/squad-review.md +10 -58
  16. package/commands/squad.md +11 -70
  17. package/dist/config/ownership-matrix.d.ts +24 -2
  18. package/dist/config/ownership-matrix.js +466 -139
  19. package/dist/config/ownership-matrix.js.map +1 -1
  20. package/dist/config/squad-yaml.d.ts +242 -0
  21. package/dist/config/squad-yaml.js +403 -0
  22. package/dist/config/squad-yaml.js.map +1 -0
  23. package/dist/errors.d.ts +1 -1
  24. package/dist/errors.js +1 -1
  25. package/dist/errors.js.map +1 -1
  26. package/dist/format/pr-review.d.ts +61 -0
  27. package/dist/format/pr-review.js +146 -0
  28. package/dist/format/pr-review.js.map +1 -0
  29. package/dist/index.js +19 -13
  30. package/dist/index.js.map +1 -1
  31. package/dist/learning/format.d.ts +29 -0
  32. package/dist/learning/format.js +55 -0
  33. package/dist/learning/format.js.map +1 -0
  34. package/dist/learning/store.d.ts +102 -0
  35. package/dist/learning/store.js +169 -0
  36. package/dist/learning/store.js.map +1 -0
  37. package/dist/resources/agent-loader.d.ts +8 -1
  38. package/dist/resources/agent-loader.js +83 -48
  39. package/dist/resources/agent-loader.js.map +1 -1
  40. package/dist/tasks/select.d.ts +64 -0
  41. package/dist/tasks/select.js +84 -0
  42. package/dist/tasks/select.js.map +1 -0
  43. package/dist/tasks/store.d.ts +338 -0
  44. package/dist/tasks/store.js +321 -0
  45. package/dist/tasks/store.js.map +1 -0
  46. package/dist/tools/compose-advisory-bundle.d.ts +5 -5
  47. package/dist/tools/compose-advisory-bundle.js +24 -12
  48. package/dist/tools/compose-advisory-bundle.js.map +1 -1
  49. package/dist/tools/compose-prd-parse.d.ts +53 -0
  50. package/dist/tools/compose-prd-parse.js +167 -0
  51. package/dist/tools/compose-prd-parse.js.map +1 -0
  52. package/dist/tools/compose-squad-workflow.d.ts +28 -10
  53. package/dist/tools/compose-squad-workflow.js +0 -0
  54. package/dist/tools/compose-squad-workflow.js.map +1 -1
  55. package/dist/tools/consolidate.d.ts +55 -4
  56. package/dist/tools/consolidate.js +87 -15
  57. package/dist/tools/consolidate.js.map +1 -1
  58. package/dist/tools/expand-task.d.ts +51 -0
  59. package/dist/tools/expand-task.js +35 -0
  60. package/dist/tools/expand-task.js.map +1 -0
  61. package/dist/tools/list-tasks.d.ts +31 -0
  62. package/dist/tools/list-tasks.js +50 -0
  63. package/dist/tools/list-tasks.js.map +1 -0
  64. package/dist/tools/next-task.d.ts +37 -0
  65. package/dist/tools/next-task.js +60 -0
  66. package/dist/tools/next-task.js.map +1 -0
  67. package/dist/tools/read-learnings.d.ts +53 -0
  68. package/dist/tools/read-learnings.js +72 -0
  69. package/dist/tools/read-learnings.js.map +1 -0
  70. package/dist/tools/read-squad-config.d.ts +23 -0
  71. package/dist/tools/read-squad-config.js +34 -0
  72. package/dist/tools/read-squad-config.js.map +1 -0
  73. package/dist/tools/record-learning.d.ts +62 -0
  74. package/dist/tools/record-learning.js +80 -0
  75. package/dist/tools/record-learning.js.map +1 -0
  76. package/dist/tools/record-tasks.d.ts +71 -0
  77. package/dist/tools/record-tasks.js +45 -0
  78. package/dist/tools/record-tasks.js.map +1 -0
  79. package/dist/tools/registry.d.ts +1 -1
  80. package/dist/tools/registry.js +71 -39
  81. package/dist/tools/registry.js.map +1 -1
  82. package/dist/tools/score-rubric.d.ts +74 -0
  83. package/dist/tools/score-rubric.js +140 -0
  84. package/dist/tools/score-rubric.js.map +1 -0
  85. package/dist/tools/slice-files-for-task.d.ts +31 -0
  86. package/dist/tools/slice-files-for-task.js +52 -0
  87. package/dist/tools/slice-files-for-task.js.map +1 -0
  88. package/dist/tools/update-task-status.d.ts +29 -0
  89. package/dist/tools/update-task-status.js +35 -0
  90. package/dist/tools/update-task-status.js.map +1 -0
  91. package/package.json +11 -1
  92. package/skills/squad/SKILL.md +454 -0
  93. package/tools/_tasks-io.mjs +69 -0
  94. package/tools/list-tasks.mjs +110 -0
  95. package/tools/next-task.mjs +131 -0
  96. package/tools/post-review.mjs +212 -0
  97. package/tools/record-learning.mjs +145 -0
  98. package/tools/record-tasks.mjs +186 -0
  99. package/tools/update-task-status.mjs +114 -0
  100. /package/{agents → shared}/Skill-Squad-Dev.md +0 -0
  101. /package/{agents → shared}/Skill-Squad-Review.md +0 -0
  102. /package/{agents → shared}/_Severity-and-Ownership.md +0 -0
@@ -1,188 +1,515 @@
1
1
  export const AGENT_NAMES = [
2
- 'po',
3
- 'tech-lead-planner',
4
- 'tech-lead-consolidator',
5
- 'senior-architect',
6
- 'senior-dba',
7
- 'senior-developer',
8
- 'senior-dev-reviewer',
9
- 'senior-dev-security',
10
- 'senior-qa',
2
+ "product-owner",
3
+ "tech-lead-planner",
4
+ "tech-lead-consolidator",
5
+ "senior-architect",
6
+ "senior-dba",
7
+ "senior-developer",
8
+ "senior-dev-reviewer",
9
+ "senior-dev-security",
10
+ "senior-qa",
11
11
  ];
12
12
  export const AGENT_NAMES_TUPLE = AGENT_NAMES;
13
13
  export const AGENTS = {
14
- po: {
15
- name: 'po',
16
- role: 'Business value, UX, requirements fit',
17
- owns: ['Business value and requirements', 'User experience'],
14
+ "product-owner": {
15
+ name: "product-owner",
16
+ role: "Business value, UX, requirements fit",
17
+ owns: ["Business value and requirements", "User experience"],
18
18
  conventions: [],
19
+ weight: 8,
20
+ dimension: "Business & UX",
19
21
  },
20
- 'tech-lead-planner': {
21
- name: 'tech-lead-planner',
22
- role: 'Pre-implementation trade-offs and viability',
23
- owns: ['Plan viability and trade-off framing (pre-impl)'],
22
+ "tech-lead-planner": {
23
+ name: "tech-lead-planner",
24
+ role: "Pre-implementation trade-offs and viability",
25
+ owns: ["Plan viability and trade-off framing (pre-impl)"],
24
26
  conventions: [],
27
+ weight: 0,
28
+ dimension: "",
25
29
  },
26
- 'tech-lead-consolidator': {
27
- name: 'tech-lead-consolidator',
28
- role: 'Post-implementation final verdict',
29
- owns: ['Final merge verdict', 'Design trade-offs', 'CI/CD and deploy', 'Technical debt'],
30
+ "tech-lead-consolidator": {
31
+ name: "tech-lead-consolidator",
32
+ role: "Post-implementation final verdict",
33
+ owns: [
34
+ "Final merge verdict",
35
+ "Design trade-offs",
36
+ "CI/CD and deploy",
37
+ "Technical debt",
38
+ ],
30
39
  conventions: [],
40
+ weight: 0,
41
+ dimension: "",
31
42
  },
32
- 'senior-architect': {
33
- name: 'senior-architect',
34
- role: 'Boundaries, DI, scalability',
35
- owns: ['Module and domain boundaries', 'Coupling', 'DI registrations and lifetimes', 'Architectural scalability'],
43
+ "senior-architect": {
44
+ name: "senior-architect",
45
+ role: "Boundaries, DI, scalability",
46
+ owns: [
47
+ "Module and domain boundaries",
48
+ "Coupling",
49
+ "DI registrations and lifetimes",
50
+ "Architectural scalability",
51
+ ],
36
52
  conventions: [
37
- '*ServiceCollectionExtensions.cs',
38
- 'Program.cs',
39
- 'Startup.cs',
40
- '*.csproj',
41
- 'Directory.Packages.props',
53
+ "*ServiceCollectionExtensions.cs",
54
+ "Program.cs",
55
+ "Startup.cs",
56
+ "*.csproj",
57
+ "Directory.Packages.props",
42
58
  ],
59
+ weight: 18,
60
+ dimension: "Architecture",
43
61
  },
44
- 'senior-dba': {
45
- name: 'senior-dba',
46
- role: 'Queries, migrations, EF, cache',
47
- owns: ['Queries and database performance', 'Migrations and schema', 'EF mappings', 'Data cache', 'Database concurrency'],
62
+ "senior-dba": {
63
+ name: "senior-dba",
64
+ role: "Queries, migrations, EF, cache",
65
+ owns: [
66
+ "Queries and database performance",
67
+ "Migrations and schema",
68
+ "EF mappings",
69
+ "Data cache",
70
+ "Database concurrency",
71
+ ],
48
72
  conventions: [
49
- '*Repository.cs',
50
- '*Configuration.cs (EF entity config)',
51
- 'Migrations/* (default `dotnet ef migrations` naming)',
73
+ "*Repository.cs",
74
+ "*Configuration.cs (EF entity config)",
75
+ "Migrations/* (default `dotnet ef migrations` naming)",
52
76
  ],
77
+ weight: 14,
78
+ dimension: "Data Layer",
53
79
  },
54
- 'senior-developer': {
55
- name: 'senior-developer',
56
- role: 'Correctness, robustness, APIs, observability',
57
- owns: ['Technical correctness', 'Robustness', 'API contracts', 'External integrations', 'Observability', 'App performance'],
80
+ "senior-developer": {
81
+ name: "senior-developer",
82
+ role: "Correctness, robustness, APIs, observability",
83
+ owns: [
84
+ "Technical correctness",
85
+ "Robustness",
86
+ "API contracts",
87
+ "External integrations",
88
+ "Observability",
89
+ "App performance",
90
+ ],
58
91
  conventions: [],
92
+ weight: 18,
93
+ dimension: "Application Code",
59
94
  },
60
- 'senior-dev-reviewer': {
61
- name: 'senior-dev-reviewer',
62
- role: 'Readability, idioms, naming',
63
- owns: ['Readability and code smells', 'C#/.NET best practices', 'Naming conventions'],
95
+ "senior-dev-reviewer": {
96
+ name: "senior-dev-reviewer",
97
+ role: "Readability, idioms, naming",
98
+ owns: [
99
+ "Readability and code smells",
100
+ "C#/.NET best practices",
101
+ "Naming conventions",
102
+ ],
64
103
  conventions: [],
104
+ weight: 10,
105
+ dimension: "Code Quality",
65
106
  },
66
- 'senior-dev-security': {
67
- name: 'senior-dev-security',
68
- role: 'OWASP, authz, sensitive data',
69
- owns: ['OWASP Top 10', 'Authentication and authorization', 'Sensitive data protection'],
70
- conventions: ['*Controller.cs (with [ApiController])', 'Auth*.cs'],
107
+ "senior-dev-security": {
108
+ name: "senior-dev-security",
109
+ role: "OWASP, authz, sensitive data",
110
+ owns: [
111
+ "OWASP Top 10",
112
+ "Authentication and authorization",
113
+ "Sensitive data protection",
114
+ ],
115
+ conventions: ["*Controller.cs (with [ApiController])", "Auth*.cs"],
116
+ weight: 18,
117
+ dimension: "Security",
71
118
  },
72
- 'senior-qa': {
73
- name: 'senior-qa',
74
- role: 'Test coverage, strategy, reliability',
75
- owns: ['Test quality and coverage', 'Test strategy'],
76
- conventions: ['*Tests.cs', '*Test.cs', '*/Tests/*'],
119
+ "senior-qa": {
120
+ name: "senior-qa",
121
+ role: "Test coverage, strategy, reliability",
122
+ owns: ["Test quality and coverage", "Test strategy"],
123
+ conventions: ["*Tests.cs", "*Test.cs", "*/Tests/*"],
124
+ weight: 14,
125
+ dimension: "Testing & QA",
77
126
  },
78
127
  };
128
+ /**
129
+ * Default rubric weights derived from AGENTS. Sum of advisory dimensions = 100.
130
+ * Exposed as a separate constant so `.squad.yaml` overrides have a clean baseline
131
+ * to merge against without rebuilding from AGENTS.
132
+ */
133
+ export const DEFAULT_RUBRIC_WEIGHTS = Object.fromEntries(Object.entries(AGENTS).map(([name, def]) => [
134
+ name,
135
+ def.weight,
136
+ ]));
79
137
  export const SQUAD_BY_TYPE = {
80
138
  Feature: {
81
- core: ['po', 'senior-developer', 'senior-qa'],
139
+ core: ["product-owner", "senior-developer", "senior-qa"],
82
140
  conditional: [
83
- { agent: 'senior-dba', when: 'data touched' },
84
- { agent: 'senior-architect', when: 'new module' },
85
- { agent: 'senior-dev-security', when: 'endpoint touched' },
141
+ { agent: "senior-dba", when: "data touched" },
142
+ { agent: "senior-architect", when: "new module" },
143
+ { agent: "senior-dev-security", when: "endpoint touched" },
86
144
  ],
87
145
  },
88
- 'Bug Fix': {
89
- core: ['senior-developer', 'senior-qa'],
146
+ "Bug Fix": {
147
+ core: ["senior-developer", "senior-qa"],
90
148
  conditional: [
91
- { agent: 'senior-dba', when: 'query/cache' },
92
- { agent: 'senior-dev-security', when: 'security bug' },
149
+ { agent: "senior-dba", when: "query/cache" },
150
+ { agent: "senior-dev-security", when: "security bug" },
93
151
  ],
94
152
  },
95
153
  Refactor: {
96
- core: ['senior-architect', 'senior-dev-reviewer', 'senior-qa'],
97
- conditional: [{ agent: 'senior-developer', when: 'behavior changes' }],
154
+ core: ["senior-architect", "senior-dev-reviewer", "senior-qa"],
155
+ conditional: [{ agent: "senior-developer", when: "behavior changes" }],
98
156
  },
99
157
  Performance: {
100
- core: ['senior-developer', 'senior-dba'],
101
- conditional: [{ agent: 'senior-architect', when: 'structural' }],
158
+ core: ["senior-developer", "senior-dba"],
159
+ conditional: [{ agent: "senior-architect", when: "structural" }],
102
160
  },
103
161
  Security: {
104
- core: ['senior-dev-security', 'senior-developer'],
105
- conditional: [{ agent: 'senior-dev-reviewer', when: 'large code change' }],
162
+ core: ["senior-dev-security", "senior-developer"],
163
+ conditional: [{ agent: "senior-dev-reviewer", when: "large code change" }],
106
164
  },
107
- 'Business Rule': {
108
- core: ['po', 'senior-developer', 'senior-qa'],
109
- conditional: [{ agent: 'senior-dba', when: 'data-bound' }],
165
+ "Business Rule": {
166
+ core: ["product-owner", "senior-developer", "senior-qa"],
167
+ conditional: [{ agent: "senior-dba", when: "data-bound" }],
110
168
  },
111
169
  };
112
- const TS_EXT = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
113
- const TSX_EXT = ['.ts', '.tsx', '.jsx'];
114
- const PY_EXT = ['.py'];
115
- const GO_EXT = ['.go'];
170
+ const TS_EXT = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
171
+ const TSX_EXT = [".ts", ".tsx", ".jsx"];
172
+ const PY_EXT = [".py"];
173
+ const GO_EXT = [".go"];
116
174
  export const CONTENT_SIGNALS = [
117
175
  // .NET / C# (existing)
118
- { agent: 'senior-dba', pattern: /class\s+\w+\s*:\s*DbContext/, description: 'EF DbContext' },
119
- { agent: 'senior-dba', pattern: /:\s*IRepository</, description: 'Repository pattern' },
120
- { agent: 'senior-dba', pattern: /modelBuilder\.Entity</, description: 'EF model config' },
121
- { agent: 'senior-dba', pattern: /\b(HasMany|HasOne|HasIndex|HasKey|HasForeignKey)\s*\(/, description: 'EF relationship' },
122
- { agent: 'senior-dba', pattern: /\[Table\(/, description: 'EF Table attribute' },
123
- { agent: 'senior-dba', pattern: /\b(CREATE|ALTER|DROP)\s+TABLE\b/i, description: 'DDL' },
124
- { agent: 'senior-dba', pattern: /AddDbContext|UseSqlServer|UseNpgsql|UseSqlite|UseMySql/, description: 'EF provider registration' },
125
- { agent: 'senior-dba', pattern: /\bSELECT\b[\s\S]{0,200}\bFROM\b/i, description: 'Raw SQL query' },
126
- { agent: 'senior-dba', pattern: /\b(IDbConnection|SqlConnection|NpgsqlConnection)\b/, description: 'ADO.NET connection' },
127
- { agent: 'senior-dba', pattern: /Migration|migrationBuilder\./, description: 'EF migration' },
128
- { agent: 'senior-dev-security', pattern: /\[Authorize/, description: 'Authorize attribute' },
129
- { agent: 'senior-dev-security', pattern: /\[ApiController\]/, description: 'API controller' },
130
- { agent: 'senior-dev-security', pattern: /\[Http(Get|Post|Put|Delete|Patch)/, description: 'HTTP endpoint' },
131
- { agent: 'senior-dev-security', pattern: /\b(JwtBearer|OAuth|SignInManager|UserManager|IdentityUser)\b/, description: 'Auth surface' },
132
- { agent: 'senior-dev-security', pattern: /UseAuthentication|UseAuthorization/, description: 'Auth middleware' },
133
- { agent: 'senior-dev-security', pattern: /\b(BCrypt|PasswordHasher|HMACSHA|Rfc2898DeriveBytes)\b/, description: 'Crypto/password handling' },
134
- { agent: 'senior-architect', pattern: /services\.Add(Scoped|Transient|Singleton)\s*</, description: 'DI registration' },
135
- { agent: 'senior-architect', pattern: /WebApplication\.CreateBuilder/, description: 'Composition root' },
136
- { agent: 'senior-architect', pattern: /AddMediatR|AddAutoMapper|AddFluentValidation/, description: 'Cross-cutting registration' },
137
- { agent: 'senior-architect', pattern: /<Project\s+Sdk=/, description: 'csproj' },
138
- { agent: 'senior-qa', pattern: /\[Fact\]|\[Theory\]/, description: 'xUnit test' },
139
- { agent: 'senior-qa', pattern: /\[Test\]|\[TestCase\]/, description: 'NUnit test' },
140
- { agent: 'senior-qa', pattern: /\b(describe|it|test)\s*\(/, description: 'JS/TS test', ext_filter: TS_EXT },
141
- { agent: 'senior-qa', pattern: /Assert\.|Should\(\)|expect\s*\(/, description: 'Assertion' },
142
- { agent: 'senior-developer', pattern: /HttpClient|IHttpClientFactory/, description: 'HTTP client (.NET integration)' },
143
- { agent: 'senior-developer', pattern: /Polly|RetryPolicy|CircuitBreaker/, description: 'Resilience policy' },
144
- { agent: 'senior-developer', pattern: /ILogger<|Activity\.Current|MetricsCollector/, description: 'Observability' },
176
+ {
177
+ agent: "senior-dba",
178
+ pattern: /class\s+\w+\s*:\s*DbContext/,
179
+ description: "EF DbContext",
180
+ },
181
+ {
182
+ agent: "senior-dba",
183
+ pattern: /:\s*IRepository</,
184
+ description: "Repository pattern",
185
+ },
186
+ {
187
+ agent: "senior-dba",
188
+ pattern: /modelBuilder\.Entity</,
189
+ description: "EF model config",
190
+ },
191
+ {
192
+ agent: "senior-dba",
193
+ pattern: /\b(HasMany|HasOne|HasIndex|HasKey|HasForeignKey)\s*\(/,
194
+ description: "EF relationship",
195
+ },
196
+ {
197
+ agent: "senior-dba",
198
+ pattern: /\[Table\(/,
199
+ description: "EF Table attribute",
200
+ },
201
+ {
202
+ agent: "senior-dba",
203
+ pattern: /\b(CREATE|ALTER|DROP)\s+TABLE\b/i,
204
+ description: "DDL",
205
+ },
206
+ {
207
+ agent: "senior-dba",
208
+ pattern: /AddDbContext|UseSqlServer|UseNpgsql|UseSqlite|UseMySql/,
209
+ description: "EF provider registration",
210
+ },
211
+ {
212
+ agent: "senior-dba",
213
+ pattern: /\bSELECT\b[\s\S]{0,200}\bFROM\b/i,
214
+ description: "Raw SQL query",
215
+ },
216
+ {
217
+ agent: "senior-dba",
218
+ pattern: /\b(IDbConnection|SqlConnection|NpgsqlConnection)\b/,
219
+ description: "ADO.NET connection",
220
+ },
221
+ {
222
+ agent: "senior-dba",
223
+ pattern: /Migration|migrationBuilder\./,
224
+ description: "EF migration",
225
+ },
226
+ {
227
+ agent: "senior-dev-security",
228
+ pattern: /\[Authorize/,
229
+ description: "Authorize attribute",
230
+ },
231
+ {
232
+ agent: "senior-dev-security",
233
+ pattern: /\[ApiController\]/,
234
+ description: "API controller",
235
+ },
236
+ {
237
+ agent: "senior-dev-security",
238
+ pattern: /\[Http(Get|Post|Put|Delete|Patch)/,
239
+ description: "HTTP endpoint",
240
+ },
241
+ {
242
+ agent: "senior-dev-security",
243
+ pattern: /\b(JwtBearer|OAuth|SignInManager|UserManager|IdentityUser)\b/,
244
+ description: "Auth surface",
245
+ },
246
+ {
247
+ agent: "senior-dev-security",
248
+ pattern: /UseAuthentication|UseAuthorization/,
249
+ description: "Auth middleware",
250
+ },
251
+ {
252
+ agent: "senior-dev-security",
253
+ pattern: /\b(BCrypt|PasswordHasher|HMACSHA|Rfc2898DeriveBytes)\b/,
254
+ description: "Crypto/password handling",
255
+ },
256
+ {
257
+ agent: "senior-architect",
258
+ pattern: /services\.Add(Scoped|Transient|Singleton)\s*</,
259
+ description: "DI registration",
260
+ },
261
+ {
262
+ agent: "senior-architect",
263
+ pattern: /WebApplication\.CreateBuilder/,
264
+ description: "Composition root",
265
+ },
266
+ {
267
+ agent: "senior-architect",
268
+ pattern: /AddMediatR|AddAutoMapper|AddFluentValidation/,
269
+ description: "Cross-cutting registration",
270
+ },
271
+ {
272
+ agent: "senior-architect",
273
+ pattern: /<Project\s+Sdk=/,
274
+ description: "csproj",
275
+ },
276
+ {
277
+ agent: "senior-qa",
278
+ pattern: /\[Fact\]|\[Theory\]/,
279
+ description: "xUnit test",
280
+ },
281
+ {
282
+ agent: "senior-qa",
283
+ pattern: /\[Test\]|\[TestCase\]/,
284
+ description: "NUnit test",
285
+ },
286
+ {
287
+ agent: "senior-qa",
288
+ pattern: /\b(describe|it|test)\s*\(/,
289
+ description: "JS/TS test",
290
+ ext_filter: TS_EXT,
291
+ },
292
+ {
293
+ agent: "senior-qa",
294
+ pattern: /Assert\.|Should\(\)|expect\s*\(/,
295
+ description: "Assertion",
296
+ },
297
+ {
298
+ agent: "senior-developer",
299
+ pattern: /HttpClient|IHttpClientFactory/,
300
+ description: "HTTP client (.NET integration)",
301
+ },
302
+ {
303
+ agent: "senior-developer",
304
+ pattern: /Polly|RetryPolicy|CircuitBreaker/,
305
+ description: "Resilience policy",
306
+ },
307
+ {
308
+ agent: "senior-developer",
309
+ pattern: /ILogger<|Activity\.Current|MetricsCollector/,
310
+ description: "Observability",
311
+ },
145
312
  // TypeScript / Node
146
- { agent: 'senior-developer', pattern: /from\s+['"]express['"]/, description: 'Express import', ext_filter: TS_EXT },
147
- { agent: 'senior-dev-security', pattern: /\bRouter\s*\(\s*\)/, description: 'Express router', ext_filter: TS_EXT },
148
- { agent: 'senior-dba', pattern: /\bprisma\.\w+\.(findFirst|findMany|findUnique|create|update|delete|upsert)\b/, description: 'Prisma client query', ext_filter: TS_EXT },
149
- { agent: 'senior-dba', pattern: /from\s+['"]typeorm['"]|@Entity\s*\(/, description: 'TypeORM', ext_filter: TS_EXT },
150
- { agent: 'senior-dba', pattern: /from\s+['"]sequelize['"]|sequelize\.define\s*\(/, description: 'Sequelize', ext_filter: TS_EXT },
151
- { agent: 'senior-dba', pattern: /from\s+['"]mongoose['"]|mongoose\.Schema\s*\(/, description: 'Mongoose', ext_filter: TS_EXT },
152
- { agent: 'senior-dev-security', pattern: /from\s+['"]bcrypt(?:js)?['"]/, description: 'bcrypt import', ext_filter: TS_EXT },
153
- { agent: 'senior-dev-security', pattern: /\bpassport\.(use|authenticate)\s*\(/, description: 'Passport auth', ext_filter: TS_EXT },
154
- { agent: 'senior-dev-security', pattern: /from\s+['"]jsonwebtoken['"]|\bjwt\.(sign|verify)\s*\(/, description: 'JWT', ext_filter: TS_EXT },
155
- { agent: 'senior-developer', pattern: /\buseState\s*\(|\buseEffect\s*\(/, description: 'React hook', ext_filter: TSX_EXT },
156
- { agent: 'senior-developer', pattern: /from\s+['"]next\//, description: 'Next.js', ext_filter: TS_EXT },
313
+ {
314
+ agent: "senior-developer",
315
+ pattern: /from\s+['"]express['"]/,
316
+ description: "Express import",
317
+ ext_filter: TS_EXT,
318
+ },
319
+ {
320
+ agent: "senior-dev-security",
321
+ pattern: /\bRouter\s*\(\s*\)/,
322
+ description: "Express router",
323
+ ext_filter: TS_EXT,
324
+ },
325
+ {
326
+ agent: "senior-dba",
327
+ pattern: /\bprisma\.\w+\.(findFirst|findMany|findUnique|create|update|delete|upsert)\b/,
328
+ description: "Prisma client query",
329
+ ext_filter: TS_EXT,
330
+ },
331
+ {
332
+ agent: "senior-dba",
333
+ pattern: /from\s+['"]typeorm['"]|@Entity\s*\(/,
334
+ description: "TypeORM",
335
+ ext_filter: TS_EXT,
336
+ },
337
+ {
338
+ agent: "senior-dba",
339
+ pattern: /from\s+['"]sequelize['"]|sequelize\.define\s*\(/,
340
+ description: "Sequelize",
341
+ ext_filter: TS_EXT,
342
+ },
343
+ {
344
+ agent: "senior-dba",
345
+ pattern: /from\s+['"]mongoose['"]|mongoose\.Schema\s*\(/,
346
+ description: "Mongoose",
347
+ ext_filter: TS_EXT,
348
+ },
349
+ {
350
+ agent: "senior-dev-security",
351
+ pattern: /from\s+['"]bcrypt(?:js)?['"]/,
352
+ description: "bcrypt import",
353
+ ext_filter: TS_EXT,
354
+ },
355
+ {
356
+ agent: "senior-dev-security",
357
+ pattern: /\bpassport\.(use|authenticate)\s*\(/,
358
+ description: "Passport auth",
359
+ ext_filter: TS_EXT,
360
+ },
361
+ {
362
+ agent: "senior-dev-security",
363
+ pattern: /from\s+['"]jsonwebtoken['"]|\bjwt\.(sign|verify)\s*\(/,
364
+ description: "JWT",
365
+ ext_filter: TS_EXT,
366
+ },
367
+ {
368
+ agent: "senior-developer",
369
+ pattern: /\buseState\s*\(|\buseEffect\s*\(/,
370
+ description: "React hook",
371
+ ext_filter: TSX_EXT,
372
+ },
373
+ {
374
+ agent: "senior-developer",
375
+ pattern: /from\s+['"]next\//,
376
+ description: "Next.js",
377
+ ext_filter: TS_EXT,
378
+ },
157
379
  // Python
158
- { agent: 'senior-dba', pattern: /from\s+sqlalchemy/, description: 'SQLAlchemy', ext_filter: PY_EXT },
159
- { agent: 'senior-developer', pattern: /from\s+(django|flask|fastapi)\b/, description: 'Python web framework', ext_filter: PY_EXT },
160
- { agent: 'senior-dev-security', pattern: /@app\.route|@router\.(get|post|put|delete|patch)/, description: 'Python HTTP route', ext_filter: PY_EXT },
161
- { agent: 'senior-dba', pattern: /import\s+alembic|alembic\.config/, description: 'Alembic migration', ext_filter: PY_EXT },
162
- { agent: 'senior-qa', pattern: /import\s+pytest|^def\s+test_/m, description: 'pytest', ext_filter: PY_EXT },
163
- { agent: 'senior-qa', pattern: /import\s+unittest/, description: 'unittest', ext_filter: PY_EXT },
380
+ {
381
+ agent: "senior-dba",
382
+ pattern: /from\s+sqlalchemy/,
383
+ description: "SQLAlchemy",
384
+ ext_filter: PY_EXT,
385
+ },
386
+ {
387
+ agent: "senior-developer",
388
+ pattern: /from\s+(django|flask|fastapi)\b/,
389
+ description: "Python web framework",
390
+ ext_filter: PY_EXT,
391
+ },
392
+ {
393
+ agent: "senior-dev-security",
394
+ pattern: /@app\.route|@router\.(get|post|put|delete|patch)/,
395
+ description: "Python HTTP route",
396
+ ext_filter: PY_EXT,
397
+ },
398
+ {
399
+ agent: "senior-dba",
400
+ pattern: /import\s+alembic|alembic\.config/,
401
+ description: "Alembic migration",
402
+ ext_filter: PY_EXT,
403
+ },
404
+ {
405
+ agent: "senior-qa",
406
+ pattern: /import\s+pytest|^def\s+test_/m,
407
+ description: "pytest",
408
+ ext_filter: PY_EXT,
409
+ },
410
+ {
411
+ agent: "senior-qa",
412
+ pattern: /import\s+unittest/,
413
+ description: "unittest",
414
+ ext_filter: PY_EXT,
415
+ },
164
416
  // Go
165
- { agent: 'senior-dba', pattern: /\bgorm\.(Open|Model|DB)\b/, description: 'GORM', ext_filter: GO_EXT },
166
- { agent: 'senior-dba', pattern: /\bsqlx\.(Open|Connect|MustConnect)\b/, description: 'sqlx', ext_filter: GO_EXT },
167
- { agent: 'senior-dev-security', pattern: /\bgin\.(Default|New)\b|\bchi\.(Mux|NewRouter)\b|\becho\.New\b/, description: 'Go HTTP framework', ext_filter: GO_EXT },
417
+ {
418
+ agent: "senior-dba",
419
+ pattern: /\bgorm\.(Open|Model|DB)\b/,
420
+ description: "GORM",
421
+ ext_filter: GO_EXT,
422
+ },
423
+ {
424
+ agent: "senior-dba",
425
+ pattern: /\bsqlx\.(Open|Connect|MustConnect)\b/,
426
+ description: "sqlx",
427
+ ext_filter: GO_EXT,
428
+ },
429
+ {
430
+ agent: "senior-dev-security",
431
+ pattern: /\bgin\.(Default|New)\b|\bchi\.(Mux|NewRouter)\b|\becho\.New\b/,
432
+ description: "Go HTTP framework",
433
+ ext_filter: GO_EXT,
434
+ },
168
435
  ];
169
436
  export const PATH_HINTS = [
170
- { agent: 'senior-dba', pattern: /[\\/]Migrations[\\/]/i, description: 'migrations folder' },
171
- { agent: 'senior-dba', pattern: /\.(sql|psql)$/i, description: 'SQL file' },
172
- { agent: 'senior-dba', pattern: /Repository\.cs$/i, description: 'Repository naming' },
173
- { agent: 'senior-dba', pattern: /DbContext\.cs$/i, description: 'DbContext naming' },
174
- { agent: 'senior-dba', pattern: /[\\/]models[\\/]/i, description: 'models folder' },
175
- { agent: 'senior-dev-security', pattern: /Controller\.cs$/i, description: 'Controller naming' },
176
- { agent: 'senior-dev-security', pattern: /[\\/]Endpoints?[\\/]/i, description: 'endpoints folder' },
177
- { agent: 'senior-dev-security', pattern: /(Auth|Identity|Jwt)\w*\.cs$/i, description: 'auth file naming' },
178
- { agent: 'senior-developer', pattern: /[\\/](api|handlers|middleware|services)[\\/]/i, description: 'api/handlers/middleware/services folder' },
179
- { agent: 'senior-architect', pattern: /Program\.cs$|Startup\.cs$/i, description: 'composition root' },
180
- { agent: 'senior-architect', pattern: /\.csproj$|Directory\.Packages\.props$/i, description: 'project boundary' },
181
- { agent: 'senior-architect', pattern: /DependencyInjection\.cs$|ServiceCollectionExtensions\.cs$/i, description: 'DI extensions' },
182
- { agent: 'senior-qa', pattern: /[\\/]Tests?[\\/]/i, description: 'tests folder' },
183
- { agent: 'senior-qa', pattern: /\.(test|spec|tests)\.(ts|tsx|js|jsx|cs)$/i, description: 'test file naming' },
184
- { agent: 'senior-qa', pattern: /_test\.go$/i, description: 'Go test file naming' },
185
- { agent: 'senior-qa', pattern: /(?:^|[\\/])test_[\w-]+\.py$/i, description: 'Python pytest naming' },
437
+ {
438
+ agent: "senior-dba",
439
+ pattern: /[\\/]Migrations[\\/]/i,
440
+ description: "migrations folder",
441
+ },
442
+ { agent: "senior-dba", pattern: /\.(sql|psql)$/i, description: "SQL file" },
443
+ {
444
+ agent: "senior-dba",
445
+ pattern: /Repository\.cs$/i,
446
+ description: "Repository naming",
447
+ },
448
+ {
449
+ agent: "senior-dba",
450
+ pattern: /DbContext\.cs$/i,
451
+ description: "DbContext naming",
452
+ },
453
+ {
454
+ agent: "senior-dba",
455
+ pattern: /[\\/]models[\\/]/i,
456
+ description: "models folder",
457
+ },
458
+ {
459
+ agent: "senior-dev-security",
460
+ pattern: /Controller\.cs$/i,
461
+ description: "Controller naming",
462
+ },
463
+ {
464
+ agent: "senior-dev-security",
465
+ pattern: /[\\/]Endpoints?[\\/]/i,
466
+ description: "endpoints folder",
467
+ },
468
+ {
469
+ agent: "senior-dev-security",
470
+ pattern: /(Auth|Identity|Jwt)\w*\.cs$/i,
471
+ description: "auth file naming",
472
+ },
473
+ {
474
+ agent: "senior-developer",
475
+ pattern: /[\\/](api|handlers|middleware|services)[\\/]/i,
476
+ description: "api/handlers/middleware/services folder",
477
+ },
478
+ {
479
+ agent: "senior-architect",
480
+ pattern: /Program\.cs$|Startup\.cs$/i,
481
+ description: "composition root",
482
+ },
483
+ {
484
+ agent: "senior-architect",
485
+ pattern: /\.csproj$|Directory\.Packages\.props$/i,
486
+ description: "project boundary",
487
+ },
488
+ {
489
+ agent: "senior-architect",
490
+ pattern: /DependencyInjection\.cs$|ServiceCollectionExtensions\.cs$/i,
491
+ description: "DI extensions",
492
+ },
493
+ {
494
+ agent: "senior-qa",
495
+ pattern: /[\\/]Tests?[\\/]/i,
496
+ description: "tests folder",
497
+ },
498
+ {
499
+ agent: "senior-qa",
500
+ pattern: /\.(test|spec|tests)\.(ts|tsx|js|jsx|cs)$/i,
501
+ description: "test file naming",
502
+ },
503
+ {
504
+ agent: "senior-qa",
505
+ pattern: /_test\.go$/i,
506
+ description: "Go test file naming",
507
+ },
508
+ {
509
+ agent: "senior-qa",
510
+ pattern: /(?:^|[\\/])test_[\w-]+\.py$/i,
511
+ description: "Python pytest naming",
512
+ },
186
513
  ];
187
514
  /**
188
515
  * Returns true when the signal applies to the given file path.