@nerviq/cli 1.2.0 → 1.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nerviq/cli",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "The intelligent nervous system for AI coding agents — 673 checks across 8 platforms. Audit, align, and amplify.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -22,6 +22,7 @@
22
22
  const { containsEmbeddedSecret } = require('../secret-patterns');
23
23
  const { attachSourceUrls } = require('../source-urls');
24
24
  const { buildStackChecks } = require('../stack-checks');
25
+ const { isApiProject, isDatabaseProject, isAuthProject, isMonitoringRelevant } = require('../supplemental-checks');
25
26
 
26
27
  const FILLER_PATTERNS = [
27
28
  /\bbe helpful\b/i,
@@ -1480,168 +1481,168 @@ const AIDER_TECHNIQUES = {
1480
1481
  },
1481
1482
  aiderEndpointDocumentation: {
1482
1483
  id: 'AD-T13', name: 'API endpoint documentation present',
1483
- check: (ctx) => ctx.files.some(f => /openapi|swagger|api\.ya?ml|api\.json/i.test(f)),
1484
+ check: (ctx) => !isApiProject(ctx) ? null : ctx.files.some(f => /openapi|swagger|api\.ya?ml|api\.json/i.test(f)),
1484
1485
  impact: 'medium', rating: 3, category: 'api-design',
1485
1486
  fix: 'Add an OpenAPI/Swagger spec for Aider to understand the API surface.',
1486
1487
  template: null, file: () => null, line: () => null,
1487
1488
  },
1488
1489
  aiderApiVersioningMentioned: {
1489
1490
  id: 'AD-T14', name: 'API versioning strategy documented',
1490
- check: (ctx) => { const conv = conventionContent(ctx); if (!conv.trim()) return null; return /api.{0,10}version|\/v\d|versioning/i.test(conv); },
1491
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const conv = conventionContent(ctx); if (!conv.trim()) return null; return /api.{0,10}version|\/v\d|versioning/i.test(conv); },
1491
1492
  impact: 'medium', rating: 3, category: 'api-design',
1492
1493
  fix: 'Document API versioning in CONVENTIONS.md.',
1493
1494
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1494
1495
  },
1495
1496
  aiderErrorHandlingPatterns: {
1496
1497
  id: 'AD-T15', name: 'Error handling patterns in conventions',
1497
- check: (ctx) => { const conv = conventionContent(ctx); if (!conv.trim()) return null; return /error.{0,15}handl|exception|try.?catch|Result\s*</i.test(conv); },
1498
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const conv = conventionContent(ctx); if (!conv.trim()) return null; return /error.{0,15}handl|exception|try.?catch|Result\s*</i.test(conv); },
1498
1499
  impact: 'high', rating: 4, category: 'api-design',
1499
1500
  fix: 'Add error handling patterns to CONVENTIONS.md for Aider.',
1500
1501
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1501
1502
  },
1502
1503
  aiderRateLimitingAwareness: {
1503
1504
  id: 'AD-T16', name: 'Rate limiting awareness documented',
1504
- check: (ctx) => { const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /rate.?limit|throttl|429/i.test(docs); },
1505
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /rate.?limit|throttl|429/i.test(docs); },
1505
1506
  impact: 'medium', rating: 3, category: 'api-design',
1506
1507
  fix: 'Document rate limiting in CONVENTIONS.md.',
1507
1508
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1508
1509
  },
1509
1510
  aiderRequestValidation: {
1510
1511
  id: 'AD-T17', name: 'Request validation strategy documented',
1511
- check: (ctx) => { const conv = conventionContent(ctx); if (!conv.trim()) return null; return /validat|zod|yup|joi\b/i.test(conv); },
1512
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const conv = conventionContent(ctx); if (!conv.trim()) return null; return /validat|zod|yup|joi\b/i.test(conv); },
1512
1513
  impact: 'high', rating: 4, category: 'api-design',
1513
1514
  fix: 'Document request validation (Zod, Yup) in CONVENTIONS.md.',
1514
1515
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1515
1516
  },
1516
1517
  aiderResponseFormatConsistent: {
1517
1518
  id: 'AD-T18', name: 'Response format consistency documented',
1518
- check: (ctx) => { const conv = conventionContent(ctx); if (!conv.trim()) return null; return /response.{0,20}format|json.{0,10}response|envelope/i.test(conv); },
1519
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const conv = conventionContent(ctx); if (!conv.trim()) return null; return /response.{0,20}format|json.{0,10}response|envelope/i.test(conv); },
1519
1520
  impact: 'medium', rating: 3, category: 'api-design',
1520
1521
  fix: 'Document standard response format in CONVENTIONS.md.',
1521
1522
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1522
1523
  },
1523
1524
  aiderMigrationStrategyDocumented: {
1524
1525
  id: 'AD-T19', name: 'Database migration strategy documented',
1525
- check: (ctx) => ctx.files.some(f => /migrations?\//i.test(f)) || /migration|alembic|flyway/i.test(conventionContent(ctx)),
1526
+ check: (ctx) => !isDatabaseProject(ctx) ? null : ctx.files.some(f => /migrations?\//i.test(f)) || /migration|alembic|flyway/i.test(conventionContent(ctx)),
1526
1527
  impact: 'high', rating: 4, category: 'database',
1527
1528
  fix: 'Document migration strategy in CONVENTIONS.md.',
1528
1529
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1529
1530
  },
1530
1531
  aiderQueryOptimizationMentioned: {
1531
1532
  id: 'AD-T20', name: 'Query optimization guidance documented',
1532
- check: (ctx) => { const conv = conventionContent(ctx); if (!conv.trim()) return null; return /n\+1|query.{0,15}optim|index|eager.{0,10}load/i.test(conv); },
1533
+ check: (ctx) => { if (!isDatabaseProject(ctx)) return null; const conv = conventionContent(ctx); if (!conv.trim()) return null; return /n\+1|query.{0,15}optim|index|eager.{0,10}load/i.test(conv); },
1533
1534
  impact: 'medium', rating: 3, category: 'database',
1534
1535
  fix: 'Add N+1 prevention patterns to CONVENTIONS.md.',
1535
1536
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1536
1537
  },
1537
1538
  aiderConnectionPoolingConfigured: {
1538
1539
  id: 'AD-T21', name: 'Connection pooling documented',
1539
- check: (ctx) => { const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /connection.{0,15}pool|pool.{0,15}size/i.test(docs); },
1540
+ check: (ctx) => { if (!isDatabaseProject(ctx)) return null; const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /connection.{0,15}pool|pool.{0,15}size/i.test(docs); },
1540
1541
  impact: 'medium', rating: 3, category: 'database',
1541
1542
  fix: 'Document connection pooling in CONVENTIONS.md.',
1542
1543
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1543
1544
  },
1544
1545
  aiderBackupStrategyDocumented: {
1545
1546
  id: 'AD-T22', name: 'Database backup strategy documented',
1546
- check: (ctx) => { const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /backup|restore|point.?in.?time/i.test(docs); },
1547
+ check: (ctx) => { if (!isDatabaseProject(ctx)) return null; const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /backup|restore|point.?in.?time/i.test(docs); },
1547
1548
  impact: 'medium', rating: 3, category: 'database',
1548
1549
  fix: 'Document database backup strategy in README.md.',
1549
1550
  template: null, file: () => 'README.md', line: () => null,
1550
1551
  },
1551
1552
  aiderSchemaDocumentation: {
1552
1553
  id: 'AD-T23', name: 'Database schema documentation present',
1553
- check: (ctx) => ctx.files.some(f => /schema\.(prisma|sql|graphql)|erd|dbml/i.test(f)),
1554
+ check: (ctx) => !isDatabaseProject(ctx) ? null : ctx.files.some(f => /schema\.(prisma|sql|graphql)|erd|dbml/i.test(f)),
1554
1555
  impact: 'medium', rating: 3, category: 'database',
1555
1556
  fix: 'Add schema documentation so Aider understands the data model.',
1556
1557
  template: null, file: () => null, line: () => null,
1557
1558
  },
1558
1559
  aiderSeedDataMentioned: {
1559
1560
  id: 'AD-T24', name: 'Seed data strategy documented',
1560
- check: (ctx) => ctx.files.some(f => /seed\.(ts|js|sql|py)|fixtures\//i.test(f)) || /seed.{0,10}data/i.test(conventionContent(ctx)),
1561
+ check: (ctx) => !isDatabaseProject(ctx) ? null : ctx.files.some(f => /seed\.(ts|js|sql|py)|fixtures\//i.test(f)) || /seed.{0,10}data/i.test(conventionContent(ctx)),
1561
1562
  impact: 'low', rating: 2, category: 'database',
1562
1563
  fix: 'Add seed scripts and document local database setup.',
1563
1564
  template: null, file: () => null, line: () => null,
1564
1565
  },
1565
1566
  aiderAuthFlowDocumented: {
1566
1567
  id: 'AD-T25', name: 'Authentication flow documented in conventions',
1567
- check: (ctx) => { const conv = conventionContent(ctx); if (!conv.trim()) return null; return /auth.{0,15}flow|login.{0,15}flow|authenticate/i.test(conv); },
1568
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const conv = conventionContent(ctx); if (!conv.trim()) return null; return /auth.{0,15}flow|login.{0,15}flow|authenticate/i.test(conv); },
1568
1569
  impact: 'high', rating: 4, category: 'authentication',
1569
1570
  fix: 'Document authentication flow in CONVENTIONS.md for Aider.',
1570
1571
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1571
1572
  },
1572
1573
  aiderTokenHandlingGuidance: {
1573
1574
  id: 'AD-T26', name: 'Token handling guidance in conventions',
1574
- check: (ctx) => { const conv = conventionContent(ctx); if (!conv.trim()) return null; return /jwt|token.{0,15}refresh|access.{0,10}token|bearer/i.test(conv); },
1575
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const conv = conventionContent(ctx); if (!conv.trim()) return null; return /jwt|token.{0,15}refresh|access.{0,10}token|bearer/i.test(conv); },
1575
1576
  impact: 'high', rating: 4, category: 'authentication',
1576
1577
  fix: 'Document JWT/token patterns in CONVENTIONS.md.',
1577
1578
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1578
1579
  },
1579
1580
  aiderSessionManagementDocumented: {
1580
1581
  id: 'AD-T27', name: 'Session management documented',
1581
- check: (ctx) => { const conv = conventionContent(ctx); if (!conv.trim()) return null; return /session.{0,15}manag|cookie|next.?auth/i.test(conv); },
1582
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const conv = conventionContent(ctx); if (!conv.trim()) return null; return /session.{0,15}manag|cookie|next.?auth/i.test(conv); },
1582
1583
  impact: 'medium', rating: 3, category: 'authentication',
1583
1584
  fix: 'Document session management approach in CONVENTIONS.md.',
1584
1585
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1585
1586
  },
1586
1587
  aiderRbacPermissionsReferenced: {
1587
1588
  id: 'AD-T28', name: 'RBAC / permissions model referenced',
1588
- check: (ctx) => { const conv = conventionContent(ctx); if (!conv.trim()) return null; return /rbac|role.?based|permission|authorization/i.test(conv); },
1589
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const conv = conventionContent(ctx); if (!conv.trim()) return null; return /rbac|role.?based|permission|authorization/i.test(conv); },
1589
1590
  impact: 'high', rating: 4, category: 'authentication',
1590
1591
  fix: 'Document RBAC/permissions model in CONVENTIONS.md.',
1591
1592
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1592
1593
  },
1593
1594
  aiderOauthSsoMentioned: {
1594
1595
  id: 'AD-T29', name: 'OAuth/SSO configuration documented',
1595
- check: (ctx) => { const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /oauth|sso|saml|oidc/i.test(docs); },
1596
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /oauth|sso|saml|oidc/i.test(docs); },
1596
1597
  impact: 'medium', rating: 3, category: 'authentication',
1597
1598
  fix: 'Document OAuth/SSO provider in README.md.',
1598
1599
  template: null, file: () => 'README.md', line: () => null,
1599
1600
  },
1600
1601
  aiderCredentialRotationDocumented: {
1601
1602
  id: 'AD-T30', name: 'Credential rotation policy documented',
1602
- check: (ctx) => { const conv = conventionContent(ctx); if (!conv.trim()) return null; return /rotat.{0,10}secret|rotat.{0,10}key|credential.{0,10}rotat/i.test(conv); },
1603
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const conv = conventionContent(ctx); if (!conv.trim()) return null; return /rotat.{0,10}secret|rotat.{0,10}key|credential.{0,10}rotat/i.test(conv); },
1603
1604
  impact: 'medium', rating: 3, category: 'authentication',
1604
1605
  fix: 'Document credential rotation in CONVENTIONS.md.',
1605
1606
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1606
1607
  },
1607
1608
  aiderLoggingConfigured: {
1608
1609
  id: 'AD-T31', name: 'Logging framework configured',
1609
- check: (ctx) => /winston|pino|bunyan|morgan|loguru/i.test(ctx.fileContent('package.json') || '') || ctx.files.some(f => /log(ger|ging)\.config/i.test(f)),
1610
+ check: (ctx) => !isMonitoringRelevant(ctx) ? null : /winston|pino|bunyan|morgan|loguru/i.test(ctx.fileContent('package.json') || '') || ctx.files.some(f => /log(ger|ging)\.config/i.test(f)),
1610
1611
  impact: 'high', rating: 4, category: 'monitoring',
1611
1612
  fix: 'Add a logging framework and document log levels in CONVENTIONS.md.',
1612
1613
  template: 'aider-conventions', file: () => 'CONVENTIONS.md', line: () => null,
1613
1614
  },
1614
1615
  aiderErrorTrackingSetup: {
1615
1616
  id: 'AD-T32', name: 'Error tracking service configured',
1616
- check: (ctx) => /sentry|bugsnag|rollbar/i.test(ctx.fileContent('package.json') || ''),
1617
+ check: (ctx) => !isMonitoringRelevant(ctx) ? null : /sentry|bugsnag|rollbar/i.test(ctx.fileContent('package.json') || ''),
1617
1618
  impact: 'high', rating: 4, category: 'monitoring',
1618
1619
  fix: 'Set up error tracking (Sentry) to catch production errors.',
1619
1620
  template: null, file: () => null, line: () => null,
1620
1621
  },
1621
1622
  aiderApmMetricsMentioned: {
1622
1623
  id: 'AD-T33', name: 'APM / metrics platform documented',
1623
- check: (ctx) => { const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /datadog|newrelic|prometheus|grafana|apm|opentelemetry/i.test(docs); },
1624
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /datadog|newrelic|prometheus|grafana|apm|opentelemetry/i.test(docs); },
1624
1625
  impact: 'medium', rating: 3, category: 'monitoring',
1625
1626
  fix: 'Document APM platform in README.md.',
1626
1627
  template: null, file: () => 'README.md', line: () => null,
1627
1628
  },
1628
1629
  aiderHealthCheckEndpoint: {
1629
1630
  id: 'AD-T34', name: 'Health check endpoint documented',
1630
- check: (ctx) => { const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /health.?check|\/health|\/ping|\/status/i.test(docs); },
1631
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /health.?check|\/health|\/ping|\/status/i.test(docs); },
1631
1632
  impact: 'medium', rating: 3, category: 'monitoring',
1632
1633
  fix: 'Document health check endpoint in README.md.',
1633
1634
  template: null, file: () => 'README.md', line: () => null,
1634
1635
  },
1635
1636
  aiderAlertingReferenced: {
1636
1637
  id: 'AD-T35', name: 'Alerting strategy referenced',
1637
- check: (ctx) => { const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /alert|pagerduty|opsgenie|oncall|incident/i.test(docs); },
1638
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /alert|pagerduty|opsgenie|oncall|incident/i.test(docs); },
1638
1639
  impact: 'medium', rating: 3, category: 'monitoring',
1639
1640
  fix: 'Document alerting strategy in README.md.',
1640
1641
  template: null, file: () => 'README.md', line: () => null,
1641
1642
  },
1642
1643
  aiderLogRotationMentioned: {
1643
1644
  id: 'AD-T36', name: 'Log rotation / retention documented',
1644
- check: (ctx) => { const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /log.{0,15}rotat|log.{0,15}retent/i.test(docs); },
1645
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const docs = conventionContent(ctx) + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /log.{0,15}rotat|log.{0,15}retent/i.test(docs); },
1645
1646
  impact: 'low', rating: 2, category: 'monitoring',
1646
1647
  fix: 'Document log rotation policy in README.md.',
1647
1648
  template: null, file: () => 'README.md', line: () => null,
@@ -17,6 +17,7 @@ const { CursorProjectContext } = require('./context');
17
17
  const { EMBEDDED_SECRET_PATTERNS, containsEmbeddedSecret } = require('../secret-patterns');
18
18
  const { attachSourceUrls } = require('../source-urls');
19
19
  const { buildStackChecks } = require('../stack-checks');
20
+ const { isApiProject, isDatabaseProject, isAuthProject, isMonitoringRelevant } = require('../supplemental-checks');
20
21
  const { validateMdcFrontmatter, validateMcpEnvVars } = require('./config-parser');
21
22
 
22
23
  // ─── Shared helpers ─────────────────────────────────────────────────────────
@@ -1957,42 +1958,42 @@ const CURSOR_TECHNIQUES = {
1957
1958
  // ── API Design (CU-T13..T18) ──
1958
1959
  cursorEndpointDocumentation: {
1959
1960
  id: 'CU-T13', name: 'API endpoint documentation present',
1960
- check: (ctx) => ctx.files.some(f => /openapi|swagger|api\.ya?ml|api\.json/i.test(f)) || /openapi|swagger/i.test(ctx.fileContent('package.json') || ''),
1961
+ check: (ctx) => !isApiProject(ctx) ? null : ctx.files.some(f => /openapi|swagger|api\.ya?ml|api\.json/i.test(f)) || /openapi|swagger/i.test(ctx.fileContent('package.json') || ''),
1961
1962
  impact: 'medium', rating: 3, category: 'api-design',
1962
1963
  fix: 'Add an OpenAPI/Swagger spec so agents understand your API surface.',
1963
1964
  template: null, file: () => null, line: () => null,
1964
1965
  },
1965
1966
  cursorApiVersioningMentioned: {
1966
1967
  id: 'CU-T14', name: 'API versioning strategy documented',
1967
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /api.{0,10}version|\/v\d|versioning/i.test(docs); },
1968
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /api.{0,10}version|\/v\d|versioning/i.test(docs); },
1968
1969
  impact: 'medium', rating: 3, category: 'api-design',
1969
1970
  fix: 'Document API versioning strategy (URL versioning, header versioning) in CLAUDE.md.',
1970
1971
  template: null, file: () => 'CLAUDE.md', line: () => null,
1971
1972
  },
1972
1973
  cursorErrorHandlingPatterns: {
1973
1974
  id: 'CU-T15', name: 'Error handling patterns documented',
1974
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /error.{0,15}handl|exception|try.?catch|Result\s*<|error.{0,10}pattern/i.test(docs); },
1975
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /error.{0,15}handl|exception|try.?catch|Result\s*<|error.{0,10}pattern/i.test(docs); },
1975
1976
  impact: 'high', rating: 4, category: 'api-design',
1976
1977
  fix: 'Document error handling patterns in Cursor rules so agents use consistent error responses.',
1977
1978
  template: null, file: () => '.cursor/rules/', line: () => null,
1978
1979
  },
1979
1980
  cursorRateLimitingAwareness: {
1980
1981
  id: 'CU-T16', name: 'Rate limiting awareness documented',
1981
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /rate.?limit|throttl|429/i.test(docs); },
1982
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /rate.?limit|throttl|429/i.test(docs); },
1982
1983
  impact: 'medium', rating: 3, category: 'api-design',
1983
1984
  fix: 'Document rate limiting in CLAUDE.md so agents handle 429 responses and add retry logic.',
1984
1985
  template: null, file: () => 'CLAUDE.md', line: () => null,
1985
1986
  },
1986
1987
  cursorRequestValidation: {
1987
1988
  id: 'CU-T17', name: 'Request validation strategy documented',
1988
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /validat|zod|yup|joi\b|schema.{0,15}validat/i.test(docs); },
1989
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /validat|zod|yup|joi\b|schema.{0,15}validat/i.test(docs); },
1989
1990
  impact: 'high', rating: 4, category: 'api-design',
1990
1991
  fix: 'Document request validation library (Zod, Yup, Joi) in Cursor rules.',
1991
1992
  template: null, file: () => '.cursor/rules/', line: () => null,
1992
1993
  },
1993
1994
  cursorResponseFormatConsistent: {
1994
1995
  id: 'CU-T18', name: 'Response format consistency documented',
1995
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /response.{0,20}format|json.{0,10}response|api.{0,15}response|envelope/i.test(docs); },
1996
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /response.{0,20}format|json.{0,10}response|api.{0,15}response|envelope/i.test(docs); },
1996
1997
  impact: 'medium', rating: 3, category: 'api-design',
1997
1998
  fix: 'Document standard response format in Cursor rules so agents produce consistent API responses.',
1998
1999
  template: null, file: () => '.cursor/rules/', line: () => null,
@@ -2001,42 +2002,42 @@ const CURSOR_TECHNIQUES = {
2001
2002
  // ── Database (CU-T19..T24) ──
2002
2003
  cursorMigrationStrategyDocumented: {
2003
2004
  id: 'CU-T19', name: 'Database migration strategy documented',
2004
- check: (ctx) => ctx.files.some(f => /migrations?\//i.test(f)) || /migration|prisma migrate|alembic|flyway|knex.{0,10}migrate/i.test(allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '')),
2005
+ check: (ctx) => !isDatabaseProject(ctx) ? null : ctx.files.some(f => /migrations?\//i.test(f)) || /migration|prisma migrate|alembic|flyway|knex.{0,10}migrate/i.test(allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '')),
2005
2006
  impact: 'high', rating: 4, category: 'database',
2006
2007
  fix: 'Document database migration strategy in CLAUDE.md (Prisma, Alembic, Flyway).',
2007
2008
  template: null, file: () => 'CLAUDE.md', line: () => null,
2008
2009
  },
2009
2010
  cursorQueryOptimizationMentioned: {
2010
2011
  id: 'CU-T20', name: 'Query optimization guidance documented',
2011
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /n\+1|query.{0,15}optim|index|explain.{0,10}query|eager.{0,10}load/i.test(docs); },
2012
+ check: (ctx) => { if (!isDatabaseProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /n\+1|query.{0,15}optim|index|explain.{0,10}query|eager.{0,10}load/i.test(docs); },
2012
2013
  impact: 'medium', rating: 3, category: 'database',
2013
2014
  fix: 'Document N+1 prevention and query optimization patterns in Cursor rules.',
2014
2015
  template: null, file: () => '.cursor/rules/', line: () => null,
2015
2016
  },
2016
2017
  cursorConnectionPoolingConfigured: {
2017
2018
  id: 'CU-T21', name: 'Connection pooling documented',
2018
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /connection.{0,15}pool|pool.{0,15}size|pgbouncer|prisma.*pool/i.test(docs); },
2019
+ check: (ctx) => { if (!isDatabaseProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /connection.{0,15}pool|pool.{0,15}size|pgbouncer|prisma.*pool/i.test(docs); },
2019
2020
  impact: 'medium', rating: 3, category: 'database',
2020
2021
  fix: 'Document connection pooling configuration in CLAUDE.md to prevent connection exhaustion.',
2021
2022
  template: null, file: () => 'CLAUDE.md', line: () => null,
2022
2023
  },
2023
2024
  cursorBackupStrategyDocumented: {
2024
2025
  id: 'CU-T22', name: 'Database backup strategy documented',
2025
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /backup|restore|point.?in.?time|snapshot.{0,15}db/i.test(docs); },
2026
+ check: (ctx) => { if (!isDatabaseProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /backup|restore|point.?in.?time|snapshot.{0,15}db/i.test(docs); },
2026
2027
  impact: 'medium', rating: 3, category: 'database',
2027
2028
  fix: 'Document database backup and restore procedures in README.md.',
2028
2029
  template: null, file: () => 'README.md', line: () => null,
2029
2030
  },
2030
2031
  cursorSchemaDocumentation: {
2031
2032
  id: 'CU-T23', name: 'Database schema documentation present',
2032
- check: (ctx) => ctx.files.some(f => /schema\.(prisma|sql|graphql)|erd|dbml|entity.{0,15}diagram/i.test(f)) || ctx.files.some(f => /schema\.md/i.test(f)),
2033
+ check: (ctx) => !isDatabaseProject(ctx) ? null : ctx.files.some(f => /schema\.(prisma|sql|graphql)|erd|dbml|entity.{0,15}diagram/i.test(f)) || ctx.files.some(f => /schema\.md/i.test(f)),
2033
2034
  impact: 'medium', rating: 3, category: 'database',
2034
2035
  fix: 'Add schema documentation (schema.prisma, ERD, DBML) so agents understand the data model.',
2035
2036
  template: null, file: () => null, line: () => null,
2036
2037
  },
2037
2038
  cursorSeedDataMentioned: {
2038
2039
  id: 'CU-T24', name: 'Seed data strategy documented',
2039
- check: (ctx) => ctx.files.some(f => /seed\.(ts|js|sql|py)|fixtures\//i.test(f)) || /seed.{0,10}data|seed.{0,10}script|prisma.*seed/i.test(allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '')),
2040
+ check: (ctx) => !isDatabaseProject(ctx) ? null : ctx.files.some(f => /seed\.(ts|js|sql|py)|fixtures\//i.test(f)) || /seed.{0,10}data|seed.{0,10}script|prisma.*seed/i.test(allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '')),
2040
2041
  impact: 'low', rating: 2, category: 'database',
2041
2042
  fix: 'Add seed scripts and document how to populate a local database for development.',
2042
2043
  template: null, file: () => null, line: () => null,
@@ -2045,42 +2046,42 @@ const CURSOR_TECHNIQUES = {
2045
2046
  // ── Authentication (CU-T25..T30) ──
2046
2047
  cursorAuthFlowDocumented: {
2047
2048
  id: 'CU-T25', name: 'Authentication flow documented',
2048
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /auth.{0,15}flow|login.{0,15}flow|sign.?in|authenticate/i.test(docs); },
2049
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /auth.{0,15}flow|login.{0,15}flow|sign.?in|authenticate/i.test(docs); },
2049
2050
  impact: 'high', rating: 4, category: 'authentication',
2050
2051
  fix: 'Document the authentication flow in CLAUDE.md so agents implement auth correctly.',
2051
2052
  template: null, file: () => 'CLAUDE.md', line: () => null,
2052
2053
  },
2053
2054
  cursorTokenHandlingGuidance: {
2054
2055
  id: 'CU-T26', name: 'Token handling guidance documented',
2055
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /jwt|token.{0,15}refresh|access.{0,10}token|bearer|token.{0,15}storage/i.test(docs); },
2056
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /jwt|token.{0,15}refresh|access.{0,10}token|bearer|token.{0,15}storage/i.test(docs); },
2056
2057
  impact: 'high', rating: 4, category: 'authentication',
2057
2058
  fix: 'Document JWT/token handling patterns in Cursor rules (storage, refresh, expiration).',
2058
2059
  template: null, file: () => '.cursor/rules/', line: () => null,
2059
2060
  },
2060
2061
  cursorSessionManagementDocumented: {
2061
2062
  id: 'CU-T27', name: 'Session management documented',
2062
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /session.{0,15}manag|cookie.{0,15}session|next.?auth|lucia|auth\.js/i.test(docs); },
2063
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /session.{0,15}manag|cookie.{0,15}session|next.?auth|lucia|auth\.js/i.test(docs); },
2063
2064
  impact: 'medium', rating: 3, category: 'authentication',
2064
2065
  fix: 'Document session management approach in CLAUDE.md (cookies, server-side sessions, JWT).',
2065
2066
  template: null, file: () => 'CLAUDE.md', line: () => null,
2066
2067
  },
2067
2068
  cursorRbacPermissionsReferenced: {
2068
2069
  id: 'CU-T28', name: 'RBAC / permissions model referenced',
2069
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /rbac|role.?based|permission|authorization|can\('|ability/i.test(docs); },
2070
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /rbac|role.?based|permission|authorization|can\('|ability/i.test(docs); },
2070
2071
  impact: 'high', rating: 4, category: 'authentication',
2071
2072
  fix: 'Document the permissions/RBAC model in Cursor rules so agents respect access controls.',
2072
2073
  template: null, file: () => '.cursor/rules/', line: () => null,
2073
2074
  },
2074
2075
  cursorOauthSsoMentioned: {
2075
2076
  id: 'CU-T29', name: 'OAuth/SSO configuration documented',
2076
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /oauth|sso|saml|oidc|google.{0,10}auth|github.{0,10}auth/i.test(docs); },
2077
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /oauth|sso|saml|oidc|google.{0,10}auth|github.{0,10}auth/i.test(docs); },
2077
2078
  impact: 'medium', rating: 3, category: 'authentication',
2078
2079
  fix: 'Document OAuth/SSO provider configuration in README.md.',
2079
2080
  template: null, file: () => 'README.md', line: () => null,
2080
2081
  },
2081
2082
  cursorCredentialRotationDocumented: {
2082
2083
  id: 'CU-T30', name: 'Credential rotation policy documented',
2083
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /rotat.{0,10}secret|rotat.{0,10}key|credential.{0,10}rotat|secret.{0,10}expir/i.test(docs); },
2084
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || ''); if (!docs.trim()) return null; return /rotat.{0,10}secret|rotat.{0,10}key|credential.{0,10}rotat|secret.{0,10}expir/i.test(docs); },
2084
2085
  impact: 'medium', rating: 3, category: 'authentication',
2085
2086
  fix: 'Document credential rotation policy in Cursor rules (how often, automated or manual).',
2086
2087
  template: null, file: () => '.cursor/rules/', line: () => null,
@@ -2089,42 +2090,42 @@ const CURSOR_TECHNIQUES = {
2089
2090
  // ── Monitoring (CU-T31..T36) ──
2090
2091
  cursorLoggingConfigured: {
2091
2092
  id: 'CU-T31', name: 'Logging framework configured',
2092
- check: (ctx) => { const pkg = ctx.fileContent('package.json') || ''; return /winston|pino|bunyan|log4js|morgan|loglevel|structlog|loguru/i.test(pkg) || ctx.files.some(f => /log(ger|ging)\.config/i.test(f)); },
2093
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const pkg = ctx.fileContent('package.json') || ''; return /winston|pino|bunyan|log4js|morgan|loglevel|structlog|loguru/i.test(pkg) || ctx.files.some(f => /log(ger|ging)\.config/i.test(f)); },
2093
2094
  impact: 'high', rating: 4, category: 'monitoring',
2094
2095
  fix: 'Add a structured logging framework (Pino, Winston) and document log levels in Cursor rules.',
2095
2096
  template: null, file: () => 'package.json', line: () => null,
2096
2097
  },
2097
2098
  cursorErrorTrackingSetup: {
2098
2099
  id: 'CU-T32', name: 'Error tracking service configured',
2099
- check: (ctx) => { const pkg = ctx.fileContent('package.json') || ''; return /sentry|bugsnag|rollbar|honeybadger|raygun|airnav/i.test(pkg) || ctx.files.some(f => /sentry\.client|sentry\.server/i.test(f)); },
2100
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const pkg = ctx.fileContent('package.json') || ''; return /sentry|bugsnag|rollbar|honeybadger|raygun|airnav/i.test(pkg) || ctx.files.some(f => /sentry\.client|sentry\.server/i.test(f)); },
2100
2101
  impact: 'high', rating: 4, category: 'monitoring',
2101
2102
  fix: 'Set up error tracking (Sentry, Bugsnag) to catch runtime errors in production.',
2102
2103
  template: null, file: () => null, line: () => null,
2103
2104
  },
2104
2105
  cursorApmMetricsMentioned: {
2105
2106
  id: 'CU-T33', name: 'APM / metrics platform documented',
2106
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /datadog|newrelic|prometheus|grafana|opentelemetry|apm|metrics/i.test(docs); },
2107
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /datadog|newrelic|prometheus|grafana|opentelemetry|apm|metrics/i.test(docs); },
2107
2108
  impact: 'medium', rating: 3, category: 'monitoring',
2108
2109
  fix: 'Document APM/metrics platform in README.md (Datadog, Prometheus, OpenTelemetry).',
2109
2110
  template: null, file: () => 'README.md', line: () => null,
2110
2111
  },
2111
2112
  cursorHealthCheckEndpoint: {
2112
2113
  id: 'CU-T34', name: 'Health check endpoint documented',
2113
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /health.?check|\/health|\/ping|\/status|liveness|readiness/i.test(docs); },
2114
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /health.?check|\/health|\/ping|\/status|liveness|readiness/i.test(docs); },
2114
2115
  impact: 'medium', rating: 3, category: 'monitoring',
2115
2116
  fix: 'Document health check endpoint in README.md (/health, /ping) for load balancer integration.',
2116
2117
  template: null, file: () => 'README.md', line: () => null,
2117
2118
  },
2118
2119
  cursorAlertingReferenced: {
2119
2120
  id: 'CU-T35', name: 'Alerting strategy referenced',
2120
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /alert|pagerduty|opsgenie|oncall|on.?call|incident/i.test(docs); },
2121
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /alert|pagerduty|opsgenie|oncall|on.?call|incident/i.test(docs); },
2121
2122
  impact: 'medium', rating: 3, category: 'monitoring',
2122
2123
  fix: 'Document alerting strategy in README.md (PagerDuty, OpsGenie, on-call rotation).',
2123
2124
  template: null, file: () => 'README.md', line: () => null,
2124
2125
  },
2125
2126
  cursorLogRotationMentioned: {
2126
2127
  id: 'CU-T36', name: 'Log rotation / retention documented',
2127
- check: (ctx) => { const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /log.{0,15}rotat|log.{0,15}retent|logrotate|retention.{0,15}polic/i.test(docs); },
2128
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const docs = allRulesContent(ctx) + (ctx.fileContent('CLAUDE.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /log.{0,15}rotat|log.{0,15}retent|logrotate|retention.{0,15}polic/i.test(docs); },
2128
2129
  impact: 'low', rating: 2, category: 'monitoring',
2129
2130
  fix: 'Document log rotation/retention policy in README.md.',
2130
2131
  template: null, file: () => 'README.md', line: () => null,