agentic-team-templates 0.13.2 → 0.15.0

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 (54) hide show
  1. package/README.md +6 -1
  2. package/package.json +1 -1
  3. package/src/index.js +91 -13
  4. package/src/index.test.js +95 -1
  5. package/templates/cpp-expert/.cursorrules/concurrency.md +211 -0
  6. package/templates/cpp-expert/.cursorrules/error-handling.md +170 -0
  7. package/templates/cpp-expert/.cursorrules/memory-and-ownership.md +220 -0
  8. package/templates/cpp-expert/.cursorrules/modern-cpp.md +211 -0
  9. package/templates/cpp-expert/.cursorrules/overview.md +87 -0
  10. package/templates/cpp-expert/.cursorrules/performance.md +223 -0
  11. package/templates/cpp-expert/.cursorrules/testing.md +230 -0
  12. package/templates/cpp-expert/.cursorrules/tooling.md +312 -0
  13. package/templates/cpp-expert/CLAUDE.md +242 -0
  14. package/templates/csharp-expert/.cursorrules/aspnet-core.md +311 -0
  15. package/templates/csharp-expert/.cursorrules/async-patterns.md +206 -0
  16. package/templates/csharp-expert/.cursorrules/dependency-injection.md +206 -0
  17. package/templates/csharp-expert/.cursorrules/error-handling.md +235 -0
  18. package/templates/csharp-expert/.cursorrules/language-features.md +204 -0
  19. package/templates/csharp-expert/.cursorrules/overview.md +92 -0
  20. package/templates/csharp-expert/.cursorrules/performance.md +251 -0
  21. package/templates/csharp-expert/.cursorrules/testing.md +282 -0
  22. package/templates/csharp-expert/.cursorrules/tooling.md +254 -0
  23. package/templates/csharp-expert/CLAUDE.md +360 -0
  24. package/templates/java-expert/.cursorrules/concurrency.md +209 -0
  25. package/templates/java-expert/.cursorrules/error-handling.md +205 -0
  26. package/templates/java-expert/.cursorrules/modern-java.md +216 -0
  27. package/templates/java-expert/.cursorrules/overview.md +81 -0
  28. package/templates/java-expert/.cursorrules/performance.md +239 -0
  29. package/templates/java-expert/.cursorrules/persistence.md +262 -0
  30. package/templates/java-expert/.cursorrules/spring-boot.md +262 -0
  31. package/templates/java-expert/.cursorrules/testing.md +272 -0
  32. package/templates/java-expert/.cursorrules/tooling.md +301 -0
  33. package/templates/java-expert/CLAUDE.md +325 -0
  34. package/templates/javascript-expert/.cursorrules/overview.md +5 -3
  35. package/templates/javascript-expert/.cursorrules/typescript-deep-dive.md +348 -0
  36. package/templates/javascript-expert/CLAUDE.md +34 -3
  37. package/templates/kotlin-expert/.cursorrules/coroutines.md +237 -0
  38. package/templates/kotlin-expert/.cursorrules/error-handling.md +149 -0
  39. package/templates/kotlin-expert/.cursorrules/frameworks.md +227 -0
  40. package/templates/kotlin-expert/.cursorrules/language-features.md +231 -0
  41. package/templates/kotlin-expert/.cursorrules/overview.md +77 -0
  42. package/templates/kotlin-expert/.cursorrules/performance.md +185 -0
  43. package/templates/kotlin-expert/.cursorrules/testing.md +213 -0
  44. package/templates/kotlin-expert/.cursorrules/tooling.md +258 -0
  45. package/templates/kotlin-expert/CLAUDE.md +276 -0
  46. package/templates/swift-expert/.cursorrules/concurrency.md +230 -0
  47. package/templates/swift-expert/.cursorrules/error-handling.md +213 -0
  48. package/templates/swift-expert/.cursorrules/language-features.md +246 -0
  49. package/templates/swift-expert/.cursorrules/overview.md +88 -0
  50. package/templates/swift-expert/.cursorrules/performance.md +260 -0
  51. package/templates/swift-expert/.cursorrules/swiftui.md +260 -0
  52. package/templates/swift-expert/.cursorrules/testing.md +286 -0
  53. package/templates/swift-expert/.cursorrules/tooling.md +285 -0
  54. package/templates/swift-expert/CLAUDE.md +275 -0
package/README.md CHANGED
@@ -148,13 +148,17 @@ npx agentic-team-templates --reset --force
148
148
  | Template | Description |
149
149
  |----------|-------------|
150
150
  | `blockchain` | Smart contracts, DeFi protocols, and Web3 applications (Solidity, Foundry, Viem) |
151
+ | `cpp-expert` | Principal-level C++ engineering (modern C++, RAII, concurrency, templates, performance) |
152
+ | `csharp-expert` | Principal-level C# engineering (async, DI, EF Core, ASP.NET Core, testing) |
151
153
  | `cli-tools` | Command-line applications and developer tools (Cobra, Commander, Click) |
152
154
  | `data-engineering` | Data platforms and pipelines (ETL, data modeling, data quality) |
153
155
  | `devops-sre` | DevOps and SRE practices (incident management, observability, SLOs, chaos engineering) |
154
156
  | `documentation` | Technical documentation standards (READMEs, API docs, ADRs, code comments) |
155
157
  | `fullstack` | Full-stack web applications (Next.js, Nuxt, SvelteKit, Remix) |
156
158
  | `golang-expert` | Principal-level Go engineering (concurrency, stdlib, production patterns, testing) |
157
- | `javascript-expert` | Principal-level JavaScript engineering across Node.js, React, vanilla JS, and testing |
159
+ | `kotlin-expert` | Principal-level Kotlin engineering (coroutines, multiplatform, Ktor, Spring Boot, testing) |
160
+ | `javascript-expert` | Principal-level JavaScript & TypeScript engineering (Node.js, React, type system, testing) |
161
+ | `java-expert` | Principal-level Java engineering (JVM, Spring Boot, concurrency, JPA, testing) |
158
162
  | `ml-ai` | Machine learning and AI systems (model development, deployment, monitoring) |
159
163
  | `mobile` | Mobile applications (React Native, Flutter, native iOS/Android) |
160
164
  | `platform-engineering` | Internal developer platforms, infrastructure automation, reliability engineering |
@@ -162,6 +166,7 @@ npx agentic-team-templates --reset --force
162
166
  | `python-expert` | Principal-level Python engineering (type system, async, testing, FastAPI, Django) |
163
167
  | `qa-engineering` | Quality assurance programs for confident, rapid software delivery |
164
168
  | `rust-expert` | Principal-level Rust engineering (ownership, concurrency, unsafe, traits, async) |
169
+ | `swift-expert` | Principal-level Swift engineering (concurrency, SwiftUI, protocols, testing, Apple platforms) |
165
170
  | `testing` | Comprehensive testing practices (TDD, test design, CI/CD integration, performance testing) |
166
171
  | `utility-agent` | AI agent utilities with context management and hallucination prevention |
167
172
  | `web-backend` | Backend APIs and services (REST, GraphQL, microservices) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-team-templates",
3
- "version": "0.13.2",
3
+ "version": "0.15.0",
4
4
  "description": "AI coding assistant templates for Cursor IDE. Pre-configured rules and guidelines that help AI assistants write better code. - use at your own risk",
5
5
  "keywords": [
6
6
  "cursor",
package/src/index.js CHANGED
@@ -24,6 +24,14 @@ const TEMPLATES = {
24
24
  description: 'Smart contracts, DeFi protocols, and Web3 applications (Solidity, Foundry, Viem)',
25
25
  rules: ['defi-patterns.md', 'gas-optimization.md', 'overview.md', 'security.md', 'smart-contracts.md', 'testing.md', 'web3-integration.md']
26
26
  },
27
+ 'cpp-expert': {
28
+ description: 'Principal-level C++ engineering (modern C++, RAII, concurrency, templates, performance)',
29
+ rules: ['concurrency.md', 'error-handling.md', 'memory-and-ownership.md', 'modern-cpp.md', 'overview.md', 'performance.md', 'testing.md', 'tooling.md']
30
+ },
31
+ 'csharp-expert': {
32
+ description: 'Principal-level C# engineering (async, DI, EF Core, ASP.NET Core, testing)',
33
+ rules: ['aspnet-core.md', 'async-patterns.md', 'dependency-injection.md', 'error-handling.md', 'language-features.md', 'overview.md', 'performance.md', 'testing.md', 'tooling.md']
34
+ },
27
35
  'cli-tools': {
28
36
  description: 'Command-line applications and developer tools (Cobra, Commander, Click)',
29
37
  rules: ['architecture.md', 'arguments.md', 'distribution.md', 'error-handling.md', 'overview.md', 'testing.md', 'user-experience.md']
@@ -48,9 +56,17 @@ const TEMPLATES = {
48
56
  description: 'Principal-level Go engineering (concurrency, stdlib, production patterns, testing)',
49
57
  rules: ['concurrency.md', 'error-handling.md', 'interfaces-and-types.md', 'overview.md', 'performance.md', 'production-patterns.md', 'stdlib-and-tooling.md', 'testing.md']
50
58
  },
59
+ 'java-expert': {
60
+ description: 'Principal-level Java engineering (JVM, Spring Boot, concurrency, JPA, testing)',
61
+ rules: ['concurrency.md', 'error-handling.md', 'modern-java.md', 'overview.md', 'performance.md', 'persistence.md', 'spring-boot.md', 'testing.md', 'tooling.md']
62
+ },
51
63
  'javascript-expert': {
52
- description: 'Principal-level JavaScript engineering across Node.js, React, vanilla JS, and testing',
53
- rules: ['language-deep-dive.md', 'node-patterns.md', 'overview.md', 'performance.md', 'react-patterns.md', 'testing.md', 'tooling.md']
64
+ description: 'Principal-level JavaScript & TypeScript engineering (Node.js, React, type system, testing)',
65
+ rules: ['language-deep-dive.md', 'node-patterns.md', 'overview.md', 'performance.md', 'react-patterns.md', 'testing.md', 'tooling.md', 'typescript-deep-dive.md']
66
+ },
67
+ 'kotlin-expert': {
68
+ description: 'Principal-level Kotlin engineering (coroutines, multiplatform, Ktor, Spring Boot, testing)',
69
+ rules: ['coroutines.md', 'error-handling.md', 'frameworks.md', 'language-features.md', 'overview.md', 'performance.md', 'testing.md', 'tooling.md']
54
70
  },
55
71
  'ml-ai': {
56
72
  description: 'Machine learning and AI systems (model development, deployment, monitoring)',
@@ -80,6 +96,10 @@ const TEMPLATES = {
80
96
  description: 'Principal-level Rust engineering (ownership, concurrency, unsafe, traits, async)',
81
97
  rules: ['concurrency.md', 'ecosystem-and-tooling.md', 'error-handling.md', 'overview.md', 'ownership-and-borrowing.md', 'performance-and-unsafe.md', 'testing.md', 'traits-and-generics.md']
82
98
  },
99
+ 'swift-expert': {
100
+ description: 'Principal-level Swift engineering (concurrency, SwiftUI, protocols, testing, Apple platforms)',
101
+ rules: ['concurrency.md', 'error-handling.md', 'language-features.md', 'overview.md', 'performance.md', 'swiftui.md', 'testing.md', 'tooling.md']
102
+ },
83
103
  'testing': {
84
104
  description: 'Comprehensive testing practices (TDD, test design, CI/CD integration, performance testing)',
85
105
  rules: ['advanced-techniques.md', 'ci-cd-integration.md', 'overview.md', 'performance-testing.md', 'quality-metrics.md', 'reliability.md', 'tdd-methodology.md', 'test-data.md', 'test-design.md', 'test-types.md']
@@ -98,6 +118,36 @@ const TEMPLATES = {
98
118
  }
99
119
  };
100
120
 
121
+ // Shorthand aliases for language expert templates
122
+ const TEMPLATE_ALIASES = {
123
+ 'js': 'javascript-expert',
124
+ 'javascript': 'javascript-expert',
125
+ 'ts': 'javascript-expert',
126
+ 'typescript': 'javascript-expert',
127
+ 'go': 'golang-expert',
128
+ 'golang': 'golang-expert',
129
+ 'py': 'python-expert',
130
+ 'python': 'python-expert',
131
+ 'rs': 'rust-expert',
132
+ 'rust': 'rust-expert',
133
+ 'swift': 'swift-expert',
134
+ 'kotlin': 'kotlin-expert',
135
+ 'kt': 'kotlin-expert',
136
+ 'java': 'java-expert',
137
+ 'cpp': 'cpp-expert',
138
+ 'csharp': 'csharp-expert',
139
+ 'cs': 'csharp-expert',
140
+ };
141
+
142
+ /**
143
+ * Resolve a template alias to its canonical name
144
+ * @param {string} name - Template name or alias
145
+ * @returns {string} Canonical template name
146
+ */
147
+ function resolveTemplateAlias(name) {
148
+ return TEMPLATE_ALIASES[name] || name;
149
+ }
150
+
101
151
  const SHARED_RULES = [
102
152
  'code-quality.md',
103
153
  'communication.md',
@@ -195,7 +245,19 @@ ${colors.yellow('IDE Targets:')}
195
245
  claude CLAUDE.md file (Claude Code, Cursor with Claude)
196
246
  codex .github/copilot-instructions.md (GitHub Copilot)
197
247
 
248
+ ${colors.yellow('Shorthand Aliases:')}
249
+ js, ts, javascript, typescript → javascript-expert
250
+ go, golang → golang-expert
251
+ py, python → python-expert
252
+ rs, rust → rust-expert
253
+ swift → swift-expert
254
+ kotlin, kt → kotlin-expert
255
+ java → java-expert
256
+ cpp → cpp-expert
257
+ csharp, cs → csharp-expert
258
+
198
259
  ${colors.yellow('Examples:')}
260
+ npx cursor-templates js
199
261
  npx cursor-templates web-frontend
200
262
  npx cursor-templates web-frontend --ide=cursor
201
263
  npx cursor-templates web-frontend --ide=claude --ide=codex
@@ -217,13 +279,24 @@ ${colors.dim('CLAUDE.md: missing sections are intelligently merged (not overwrit
217
279
  }
218
280
 
219
281
  function printTemplates() {
282
+ // Build reverse map: canonical name -> list of aliases
283
+ const aliasesByTemplate = {};
284
+ for (const [alias, canonical] of Object.entries(TEMPLATE_ALIASES)) {
285
+ if (!aliasesByTemplate[canonical]) {
286
+ aliasesByTemplate[canonical] = [];
287
+ }
288
+ aliasesByTemplate[canonical].push(alias);
289
+ }
290
+
220
291
  console.log(colors.yellow('Available Templates:\n'));
221
-
292
+
222
293
  for (const [name, info] of Object.entries(TEMPLATES)) {
223
- console.log(` ${colors.green(name)}`);
294
+ const aliases = aliasesByTemplate[name];
295
+ const aliasSuffix = aliases ? ` ${colors.dim(`(aliases: ${aliases.join(', ')})`)}` : '';
296
+ console.log(` ${colors.green(name)}${aliasSuffix}`);
224
297
  console.log(` ${info.description}\n`);
225
298
  }
226
-
299
+
227
300
  console.log(colors.blue('Shared rules (always included):'));
228
301
  for (const rule of SHARED_RULES) {
229
302
  console.log(` - ${rule.replace('.md', '')}`);
@@ -1358,10 +1431,13 @@ export async function run(args) {
1358
1431
  }
1359
1432
 
1360
1433
  printBanner();
1361
-
1434
+
1362
1435
  // Check for updates (non-blocking, fails silently)
1363
1436
  await checkForUpdates();
1364
1437
 
1438
+ // Resolve template aliases to canonical names
1439
+ const resolvedTemplates = templates.map(resolveTemplateAlias);
1440
+
1365
1441
  // Use default IDEs if none specified
1366
1442
  const targetIdes = ides.length > 0 ? ides : DEFAULT_IDES;
1367
1443
 
@@ -1371,7 +1447,7 @@ export async function run(args) {
1371
1447
  console.error(colors.red('Error: Cannot use --remove and --reset together\n'));
1372
1448
  process.exit(1);
1373
1449
  }
1374
- if (templates.length > 0) {
1450
+ if (resolvedTemplates.length > 0) {
1375
1451
  console.error(colors.red('Error: --reset does not accept template arguments\n'));
1376
1452
  console.error(colors.dim('Use --remove <templates...> to remove specific templates.\n'));
1377
1453
  process.exit(1);
@@ -1390,14 +1466,14 @@ export async function run(args) {
1390
1466
 
1391
1467
  // Handle remove mode
1392
1468
  if (removeMode) {
1393
- if (templates.length === 0) {
1469
+ if (resolvedTemplates.length === 0) {
1394
1470
  console.error(colors.red('Error: No templates specified for removal\n'));
1395
1471
  console.error(colors.dim('Usage: npx cursor-templates --remove <templates...>\n'));
1396
1472
  printTemplates();
1397
1473
  process.exit(1);
1398
1474
  }
1399
1475
 
1400
- for (const template of templates) {
1476
+ for (const template of resolvedTemplates) {
1401
1477
  if (!TEMPLATES[template]) {
1402
1478
  console.error(colors.red(`Error: Unknown template '${template}'\n`));
1403
1479
  printTemplates();
@@ -1412,18 +1488,18 @@ export async function run(args) {
1412
1488
  console.log(colors.yellow('FORCE MODE - Modified files will be removed\n'));
1413
1489
  }
1414
1490
 
1415
- await remove(process.cwd(), templates, dryRun, force, skipConfirm, targetIdes);
1491
+ await remove(process.cwd(), resolvedTemplates, dryRun, force, skipConfirm, targetIdes);
1416
1492
  return;
1417
1493
  }
1418
1494
 
1419
1495
  // Install mode (default)
1420
- if (templates.length === 0) {
1496
+ if (resolvedTemplates.length === 0) {
1421
1497
  console.error(colors.red('Error: No templates specified\n'));
1422
1498
  printHelp();
1423
1499
  process.exit(1);
1424
1500
  }
1425
1501
 
1426
- for (const template of templates) {
1502
+ for (const template of resolvedTemplates) {
1427
1503
  if (!TEMPLATES[template]) {
1428
1504
  console.error(colors.red(`Error: Unknown template '${template}'\n`));
1429
1505
  printTemplates();
@@ -1440,7 +1516,7 @@ export async function run(args) {
1440
1516
  }
1441
1517
 
1442
1518
  // Install to current directory
1443
- install(process.cwd(), templates, dryRun, force, targetIdes);
1519
+ install(process.cwd(), resolvedTemplates, dryRun, force, targetIdes);
1444
1520
  }
1445
1521
 
1446
1522
  // Export internals for testing
@@ -1450,11 +1526,13 @@ export const _internals = {
1450
1526
  REPO_URL,
1451
1527
  CHANGELOG_URL,
1452
1528
  TEMPLATES,
1529
+ TEMPLATE_ALIASES,
1453
1530
  SHARED_RULES,
1454
1531
  SUPPORTED_IDES,
1455
1532
  DEFAULT_IDES,
1456
1533
  compareVersions,
1457
1534
  checkForUpdates,
1535
+ resolveTemplateAlias,
1458
1536
  filesMatch,
1459
1537
  parseMarkdownSections,
1460
1538
  generateSectionSignature,
package/src/index.test.js CHANGED
@@ -8,10 +8,12 @@ const {
8
8
  PACKAGE_NAME,
9
9
  CURRENT_VERSION,
10
10
  TEMPLATES,
11
+ TEMPLATE_ALIASES,
11
12
  SHARED_RULES,
12
13
  SUPPORTED_IDES,
13
14
  DEFAULT_IDES,
14
15
  compareVersions,
16
+ resolveTemplateAlias,
15
17
  filesMatch,
16
18
  parseMarkdownSections,
17
19
  generateSectionSignature,
@@ -74,13 +76,17 @@ describe('Constants', () => {
74
76
  it('should have all expected templates', () => {
75
77
  const expectedTemplates = [
76
78
  'blockchain',
79
+ 'cpp-expert',
80
+ 'csharp-expert',
77
81
  'cli-tools',
78
82
  'data-engineering',
79
83
  'devops-sre',
80
84
  'documentation',
81
85
  'fullstack',
82
86
  'golang-expert',
87
+ 'java-expert',
83
88
  'javascript-expert',
89
+ 'kotlin-expert',
84
90
  'ml-ai',
85
91
  'mobile',
86
92
  'platform-engineering',
@@ -88,6 +94,7 @@ describe('Constants', () => {
88
94
  'python-expert',
89
95
  'qa-engineering',
90
96
  'rust-expert',
97
+ 'swift-expert',
91
98
  'testing',
92
99
  'utility-agent',
93
100
  'web-backend',
@@ -145,6 +152,50 @@ describe('Constants', () => {
145
152
  expect(DEFAULT_IDES).toEqual(SUPPORTED_IDES);
146
153
  });
147
154
  });
155
+
156
+ describe('TEMPLATE_ALIASES', () => {
157
+ it('all alias values should be valid TEMPLATES keys', () => {
158
+ for (const [alias, canonical] of Object.entries(TEMPLATE_ALIASES)) {
159
+ expect(TEMPLATES).toHaveProperty(canonical,
160
+ expect.anything(),
161
+ );
162
+ }
163
+ });
164
+
165
+ it('should include expected shorthand aliases', () => {
166
+ expect(TEMPLATE_ALIASES['js']).toBe('javascript-expert');
167
+ expect(TEMPLATE_ALIASES['ts']).toBe('javascript-expert');
168
+ expect(TEMPLATE_ALIASES['go']).toBe('golang-expert');
169
+ expect(TEMPLATE_ALIASES['py']).toBe('python-expert');
170
+ expect(TEMPLATE_ALIASES['rs']).toBe('rust-expert');
171
+ expect(TEMPLATE_ALIASES['kt']).toBe('kotlin-expert');
172
+ });
173
+ });
174
+
175
+ describe('resolveTemplateAlias', () => {
176
+ it('should resolve known aliases to canonical names', () => {
177
+ expect(resolveTemplateAlias('js')).toBe('javascript-expert');
178
+ expect(resolveTemplateAlias('typescript')).toBe('javascript-expert');
179
+ expect(resolveTemplateAlias('go')).toBe('golang-expert');
180
+ expect(resolveTemplateAlias('golang')).toBe('golang-expert');
181
+ expect(resolveTemplateAlias('py')).toBe('python-expert');
182
+ expect(resolveTemplateAlias('rs')).toBe('rust-expert');
183
+ expect(resolveTemplateAlias('kotlin')).toBe('kotlin-expert');
184
+ expect(resolveTemplateAlias('kt')).toBe('kotlin-expert');
185
+ });
186
+
187
+ it('should pass through unknown names unchanged', () => {
188
+ expect(resolveTemplateAlias('web-frontend')).toBe('web-frontend');
189
+ expect(resolveTemplateAlias('blockchain')).toBe('blockchain');
190
+ expect(resolveTemplateAlias('nonexistent')).toBe('nonexistent');
191
+ });
192
+
193
+ it('should pass through canonical template names unchanged', () => {
194
+ expect(resolveTemplateAlias('javascript-expert')).toBe('javascript-expert');
195
+ expect(resolveTemplateAlias('golang-expert')).toBe('golang-expert');
196
+ expect(resolveTemplateAlias('python-expert')).toBe('python-expert');
197
+ });
198
+ });
148
199
  });
149
200
 
150
201
  // ============================================================================
@@ -1014,7 +1065,50 @@ describe('CLI Argument Parsing', () => {
1014
1065
  it('should accept -y shorthand for yes', async () => {
1015
1066
  await run(['web-frontend']);
1016
1067
  await run(['--reset', '-y']);
1017
-
1068
+
1069
+ expect(exitSpy).not.toHaveBeenCalled();
1070
+ });
1071
+
1072
+ it('should resolve shorthand alias "js" to javascript-expert', async () => {
1073
+ await run(['js', '--dry-run']);
1074
+
1075
+ expect(exitSpy).not.toHaveBeenCalled();
1076
+ });
1077
+
1078
+ it('should resolve shorthand alias "go" to golang-expert', async () => {
1079
+ await run(['go', '--dry-run']);
1080
+
1081
+ expect(exitSpy).not.toHaveBeenCalled();
1082
+ });
1083
+
1084
+ it('should resolve shorthand alias "py" to python-expert', async () => {
1085
+ await run(['py', '--dry-run']);
1086
+
1087
+ expect(exitSpy).not.toHaveBeenCalled();
1088
+ });
1089
+
1090
+ it('should resolve shorthand alias "rs" to rust-expert', async () => {
1091
+ await run(['rs', '--dry-run']);
1092
+
1093
+ expect(exitSpy).not.toHaveBeenCalled();
1094
+ });
1095
+
1096
+ it('should resolve shorthand alias "kt" to kotlin-expert', async () => {
1097
+ await run(['kt', '--dry-run']);
1098
+
1099
+ expect(exitSpy).not.toHaveBeenCalled();
1100
+ });
1101
+
1102
+ it('should resolve aliases in --remove mode', async () => {
1103
+ await run(['go']);
1104
+ await run(['--remove', 'go', '--yes']);
1105
+
1106
+ expect(exitSpy).not.toHaveBeenCalled();
1107
+ });
1108
+
1109
+ it('should still accept canonical template names', async () => {
1110
+ await run(['javascript-expert', '--dry-run']);
1111
+
1018
1112
  expect(exitSpy).not.toHaveBeenCalled();
1019
1113
  });
1020
1114
  });
@@ -0,0 +1,211 @@
1
+ # C++ Concurrency
2
+
3
+ The C++ memory model is the law. Every concurrent access must be explicitly synchronized.
4
+
5
+ ## std::thread and std::jthread
6
+
7
+ ```cpp
8
+ // std::jthread (C++20) — automatically joins on destruction
9
+ void process_data(std::stop_token stop, std::span<const Item> items) {
10
+ for (const auto& item : items) {
11
+ if (stop.stop_requested()) return;
12
+ process(item);
13
+ }
14
+ }
15
+
16
+ auto worker = std::jthread(process_data, data);
17
+ // Automatically joins when worker goes out of scope
18
+ // Can request stop: worker.request_stop();
19
+
20
+ // Never use std::thread without join/detach — it calls std::terminate
21
+ ```
22
+
23
+ ## Mutex and Locking
24
+
25
+ ```cpp
26
+ // RAII locking — always
27
+ class ThreadSafeCounter {
28
+ mutable std::mutex mutex_;
29
+ int count_ = 0;
30
+
31
+ public:
32
+ void increment() {
33
+ std::lock_guard lock(mutex_);
34
+ ++count_;
35
+ }
36
+
37
+ int get() const {
38
+ std::lock_guard lock(mutex_);
39
+ return count_;
40
+ }
41
+ };
42
+
43
+ // Multiple mutexes — use std::scoped_lock to avoid deadlock
44
+ void transfer(Account& from, Account& to, int amount) {
45
+ std::scoped_lock lock(from.mutex_, to.mutex_); // Deadlock-free
46
+ from.balance_ -= amount;
47
+ to.balance_ += amount;
48
+ }
49
+
50
+ // Read-heavy workloads — use shared_mutex
51
+ class Cache {
52
+ mutable std::shared_mutex mutex_;
53
+ std::unordered_map<std::string, Value> data_;
54
+
55
+ public:
56
+ auto get(const std::string& key) const -> std::optional<Value> {
57
+ std::shared_lock lock(mutex_); // Multiple readers OK
58
+ auto it = data_.find(key);
59
+ return it != data_.end() ? std::optional{it->second} : std::nullopt;
60
+ }
61
+
62
+ void set(const std::string& key, Value value) {
63
+ std::unique_lock lock(mutex_); // Exclusive write
64
+ data_[key] = std::move(value);
65
+ }
66
+ };
67
+ ```
68
+
69
+ ## Atomics
70
+
71
+ ```cpp
72
+ // Lock-free operations for simple types
73
+ std::atomic<int> counter{0};
74
+ counter.fetch_add(1, std::memory_order_relaxed); // Fastest for counters
75
+
76
+ // Flags
77
+ std::atomic<bool> ready{false};
78
+ // Producer:
79
+ data = prepare();
80
+ ready.store(true, std::memory_order_release);
81
+ // Consumer:
82
+ while (!ready.load(std::memory_order_acquire)) { /* spin or yield */ }
83
+ use(data); // Guaranteed to see prepared data
84
+
85
+ // std::atomic_ref (C++20) for non-atomic variables
86
+ int value = 0;
87
+ std::atomic_ref ref{value};
88
+ ref.fetch_add(1);
89
+ ```
90
+
91
+ ## Condition Variables
92
+
93
+ ```cpp
94
+ template <typename T>
95
+ class BoundedQueue {
96
+ std::queue<T> queue_;
97
+ mutable std::mutex mutex_;
98
+ std::condition_variable not_empty_;
99
+ std::condition_variable not_full_;
100
+ size_t max_size_;
101
+
102
+ public:
103
+ explicit BoundedQueue(size_t max_size) : max_size_{max_size} {}
104
+
105
+ void push(T item) {
106
+ std::unique_lock lock(mutex_);
107
+ not_full_.wait(lock, [this] { return queue_.size() < max_size_; });
108
+ queue_.push(std::move(item));
109
+ not_empty_.notify_one();
110
+ }
111
+
112
+ auto pop() -> T {
113
+ std::unique_lock lock(mutex_);
114
+ not_empty_.wait(lock, [this] { return !queue_.empty(); });
115
+ auto item = std::move(queue_.front());
116
+ queue_.pop();
117
+ not_full_.notify_one();
118
+ return item;
119
+ }
120
+
121
+ auto try_pop(std::chrono::milliseconds timeout) -> std::optional<T> {
122
+ std::unique_lock lock(mutex_);
123
+ if (!not_empty_.wait_for(lock, timeout, [this] { return !queue_.empty(); })) {
124
+ return std::nullopt;
125
+ }
126
+ auto item = std::move(queue_.front());
127
+ queue_.pop();
128
+ not_full_.notify_one();
129
+ return item;
130
+ }
131
+ };
132
+ ```
133
+
134
+ ## Async and Futures
135
+
136
+ ```cpp
137
+ // std::async for fire-and-forget parallel work
138
+ auto future = std::async(std::launch::async, [] {
139
+ return expensive_computation();
140
+ });
141
+
142
+ auto result = future.get(); // Blocks until ready
143
+
144
+ // Parallel independent work
145
+ auto user_future = std::async(std::launch::async, [&] { return fetch_user(id); });
146
+ auto orders_future = std::async(std::launch::async, [&] { return fetch_orders(id); });
147
+
148
+ auto user = user_future.get();
149
+ auto orders = orders_future.get();
150
+ ```
151
+
152
+ ## Parallel Algorithms (C++17)
153
+
154
+ ```cpp
155
+ #include <execution>
156
+
157
+ // Parallel sort
158
+ std::sort(std::execution::par, data.begin(), data.end());
159
+
160
+ // Parallel transform-reduce
161
+ auto total = std::transform_reduce(
162
+ std::execution::par,
163
+ orders.begin(), orders.end(),
164
+ 0.0, // Initial value
165
+ std::plus<>{}, // Reduce
166
+ [](const Order& o) { return o.total(); } // Transform
167
+ );
168
+
169
+ // Parallel for_each
170
+ std::for_each(std::execution::par_unseq, items.begin(), items.end(),
171
+ [](auto& item) { item.process(); });
172
+ ```
173
+
174
+ ## Thread Safety Rules
175
+
176
+ 1. **Immutable data is thread-safe** — share freely via `const` references
177
+ 2. **Every mutable shared state needs synchronization** — no exceptions
178
+ 3. **Prefer lock-free data structures** when correctness is provable
179
+ 4. **Hold locks for the minimum time** — compute outside the critical section
180
+ 5. **Never hold two locks simultaneously** unless using `std::scoped_lock`
181
+ 6. **Use `std::atomic` for single variables**, mutex for compound operations
182
+
183
+ ## Anti-Patterns
184
+
185
+ ```cpp
186
+ // Never: lock and forget
187
+ mutex_.lock();
188
+ do_work(); // If this throws, mutex stays locked forever
189
+ mutex_.unlock();
190
+ // Use: std::lock_guard or std::unique_lock (RAII)
191
+
192
+ // Never: double-checked locking without atomics
193
+ if (!instance) {
194
+ std::lock_guard lock(mutex);
195
+ if (!instance) instance = new Singleton(); // Data race!
196
+ }
197
+ // Use: std::call_once or static local (Meyers singleton)
198
+
199
+ static Singleton& instance() {
200
+ static Singleton s; // Thread-safe in C++11+
201
+ return s;
202
+ }
203
+
204
+ // Never: volatile for synchronization
205
+ volatile int flag; // volatile != atomic in C++
206
+ // Use: std::atomic<int> flag;
207
+
208
+ // Never: busy-waiting without yield
209
+ while (!ready.load()) {} // Burns CPU
210
+ // Use: condition_variable, or at least std::this_thread::yield()
211
+ ```