@nerviq/cli 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,6 +30,7 @@ const { WindsurfProjectContext } = require('./context');
30
30
  const { EMBEDDED_SECRET_PATTERNS, containsEmbeddedSecret } = require('../secret-patterns');
31
31
  const { attachSourceUrls } = require('../source-urls');
32
32
  const { buildStackChecks } = require('../stack-checks');
33
+ const { isApiProject, isDatabaseProject, isAuthProject, isMonitoringRelevant } = require('../supplemental-checks');
33
34
  const { tryParseJson, validateMcpEnvVars } = require('./config-parser');
34
35
 
35
36
  // ─── Shared helpers ─────────────────────────────────────────────────────────
@@ -1917,168 +1918,168 @@ const WINDSURF_TECHNIQUES = {
1917
1918
  },
1918
1919
  wsEndpointDocumentation: {
1919
1920
  id: 'WS-T13', name: 'API endpoint documentation present',
1920
- check: (ctx) => ctx.files.some(f => /openapi|swagger|api\.ya?ml|api\.json/i.test(f)),
1921
+ check: (ctx) => !isApiProject(ctx) ? null : ctx.files.some(f => /openapi|swagger|api\.ya?ml|api\.json/i.test(f)),
1921
1922
  impact: 'medium', rating: 3, category: 'api-design',
1922
1923
  fix: 'Add an OpenAPI/Swagger spec so Cascade understands the API surface.',
1923
1924
  template: null, file: () => null, line: () => null,
1924
1925
  },
1925
1926
  wsApiVersioningMentioned: {
1926
1927
  id: 'WS-T14', name: 'API versioning strategy documented',
1927
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /api.{0,10}version|\/v\d|versioning/i.test(docs); },
1928
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /api.{0,10}version|\/v\d|versioning/i.test(docs); },
1928
1929
  impact: 'medium', rating: 3, category: 'api-design',
1929
1930
  fix: 'Document API versioning strategy in AGENTS.md.',
1930
1931
  template: null, file: () => 'AGENTS.md', line: () => null,
1931
1932
  },
1932
1933
  wsErrorHandlingPatterns: {
1933
1934
  id: 'WS-T15', name: 'Error handling patterns documented',
1934
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /error.{0,15}handl|exception|try.?catch|Result\s*</i.test(docs); },
1935
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /error.{0,15}handl|exception|try.?catch|Result\s*</i.test(docs); },
1935
1936
  impact: 'high', rating: 4, category: 'api-design',
1936
1937
  fix: 'Document error handling patterns in .windsurfrules for Cascade.',
1937
1938
  template: null, file: () => '.windsurfrules', line: () => null,
1938
1939
  },
1939
1940
  wsRateLimitingAwareness: {
1940
1941
  id: 'WS-T16', name: 'Rate limiting awareness documented',
1941
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /rate.?limit|throttl|429/i.test(docs); },
1942
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /rate.?limit|throttl|429/i.test(docs); },
1942
1943
  impact: 'medium', rating: 3, category: 'api-design',
1943
1944
  fix: 'Document rate limiting in AGENTS.md for Cascade to handle 429 errors.',
1944
1945
  template: null, file: () => 'AGENTS.md', line: () => null,
1945
1946
  },
1946
1947
  wsRequestValidation: {
1947
1948
  id: 'WS-T17', name: 'Request validation strategy documented',
1948
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /validat|zod|yup|joi\b/i.test(docs); },
1949
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /validat|zod|yup|joi\b/i.test(docs); },
1949
1950
  impact: 'high', rating: 4, category: 'api-design',
1950
1951
  fix: 'Document request validation library (Zod, Yup) in .windsurfrules.',
1951
1952
  template: null, file: () => '.windsurfrules', line: () => null,
1952
1953
  },
1953
1954
  wsResponseFormatConsistent: {
1954
1955
  id: 'WS-T18', name: 'Response format consistency documented',
1955
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /response.{0,20}format|json.{0,10}response|envelope/i.test(docs); },
1956
+ check: (ctx) => { if (!isApiProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /response.{0,20}format|json.{0,10}response|envelope/i.test(docs); },
1956
1957
  impact: 'medium', rating: 3, category: 'api-design',
1957
1958
  fix: 'Document standard response format in .windsurfrules.',
1958
1959
  template: null, file: () => '.windsurfrules', line: () => null,
1959
1960
  },
1960
1961
  wsMigrationStrategyDocumented: {
1961
1962
  id: 'WS-T19', name: 'Database migration strategy documented',
1962
- check: (ctx) => ctx.files.some(f => /migrations?\//i.test(f)) || /migration|prisma migrate|alembic/i.test((ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || '')),
1963
+ check: (ctx) => !isDatabaseProject(ctx) ? null : ctx.files.some(f => /migrations?\//i.test(f)) || /migration|prisma migrate|alembic/i.test((ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || '')),
1963
1964
  impact: 'high', rating: 4, category: 'database',
1964
1965
  fix: 'Document database migration strategy in AGENTS.md.',
1965
1966
  template: null, file: () => 'AGENTS.md', line: () => null,
1966
1967
  },
1967
1968
  wsQueryOptimizationMentioned: {
1968
1969
  id: 'WS-T20', name: 'Query optimization guidance documented',
1969
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /n\+1|query.{0,15}optim|index|eager.{0,10}load/i.test(docs); },
1970
+ check: (ctx) => { if (!isDatabaseProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /n\+1|query.{0,15}optim|index|eager.{0,10}load/i.test(docs); },
1970
1971
  impact: 'medium', rating: 3, category: 'database',
1971
1972
  fix: 'Document N+1 prevention patterns in .windsurfrules.',
1972
1973
  template: null, file: () => '.windsurfrules', line: () => null,
1973
1974
  },
1974
1975
  wsConnectionPoolingConfigured: {
1975
1976
  id: 'WS-T21', name: 'Connection pooling documented',
1976
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /connection.{0,15}pool|pool.{0,15}size/i.test(docs); },
1977
+ check: (ctx) => { if (!isDatabaseProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /connection.{0,15}pool|pool.{0,15}size/i.test(docs); },
1977
1978
  impact: 'medium', rating: 3, category: 'database',
1978
1979
  fix: 'Document database connection pooling in AGENTS.md.',
1979
1980
  template: null, file: () => 'AGENTS.md', line: () => null,
1980
1981
  },
1981
1982
  wsBackupStrategyDocumented: {
1982
1983
  id: 'WS-T22', name: 'Database backup strategy documented',
1983
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /backup|restore|point.?in.?time/i.test(docs); },
1984
+ check: (ctx) => { if (!isDatabaseProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /backup|restore|point.?in.?time/i.test(docs); },
1984
1985
  impact: 'medium', rating: 3, category: 'database',
1985
1986
  fix: 'Document database backup and restore in README.md.',
1986
1987
  template: null, file: () => 'README.md', line: () => null,
1987
1988
  },
1988
1989
  wsSchemaDocumentation: {
1989
1990
  id: 'WS-T23', name: 'Database schema documentation present',
1990
- check: (ctx) => ctx.files.some(f => /schema\.(prisma|sql|graphql)|erd|dbml/i.test(f)),
1991
+ check: (ctx) => !isDatabaseProject(ctx) ? null : ctx.files.some(f => /schema\.(prisma|sql|graphql)|erd|dbml/i.test(f)),
1991
1992
  impact: 'medium', rating: 3, category: 'database',
1992
1993
  fix: 'Add schema documentation (schema.prisma, ERD) for Cascade.',
1993
1994
  template: null, file: () => null, line: () => null,
1994
1995
  },
1995
1996
  wsSeedDataMentioned: {
1996
1997
  id: 'WS-T24', name: 'Seed data strategy documented',
1997
- check: (ctx) => ctx.files.some(f => /seed\.(ts|js|sql|py)|fixtures\//i.test(f)) || /seed.{0,10}data|seed.{0,10}script/i.test((ctx.fileContent('AGENTS.md') || '')),
1998
+ 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/i.test((ctx.fileContent('AGENTS.md') || '')),
1998
1999
  impact: 'low', rating: 2, category: 'database',
1999
2000
  fix: 'Add seed scripts and document local database setup in AGENTS.md.',
2000
2001
  template: null, file: () => null, line: () => null,
2001
2002
  },
2002
2003
  wsAuthFlowDocumented: {
2003
2004
  id: 'WS-T25', name: 'Authentication flow documented',
2004
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /auth.{0,15}flow|login.{0,15}flow|authenticate/i.test(docs); },
2005
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /auth.{0,15}flow|login.{0,15}flow|authenticate/i.test(docs); },
2005
2006
  impact: 'high', rating: 4, category: 'authentication',
2006
2007
  fix: 'Document authentication flow in AGENTS.md for Cascade.',
2007
2008
  template: null, file: () => 'AGENTS.md', line: () => null,
2008
2009
  },
2009
2010
  wsTokenHandlingGuidance: {
2010
2011
  id: 'WS-T26', name: 'Token handling guidance documented',
2011
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /jwt|token.{0,15}refresh|access.{0,10}token|bearer/i.test(docs); },
2012
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /jwt|token.{0,15}refresh|access.{0,10}token|bearer/i.test(docs); },
2012
2013
  impact: 'high', rating: 4, category: 'authentication',
2013
2014
  fix: 'Document JWT/token handling in .windsurfrules.',
2014
2015
  template: null, file: () => '.windsurfrules', line: () => null,
2015
2016
  },
2016
2017
  wsSessionManagementDocumented: {
2017
2018
  id: 'WS-T27', name: 'Session management documented',
2018
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /session.{0,15}manag|cookie|next.?auth|lucia/i.test(docs); },
2019
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /session.{0,15}manag|cookie|next.?auth|lucia/i.test(docs); },
2019
2020
  impact: 'medium', rating: 3, category: 'authentication',
2020
2021
  fix: 'Document session management in .windsurfrules.',
2021
2022
  template: null, file: () => '.windsurfrules', line: () => null,
2022
2023
  },
2023
2024
  wsRbacPermissionsReferenced: {
2024
2025
  id: 'WS-T28', name: 'RBAC / permissions model referenced',
2025
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /rbac|role.?based|permission|authorization/i.test(docs); },
2026
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /rbac|role.?based|permission|authorization/i.test(docs); },
2026
2027
  impact: 'high', rating: 4, category: 'authentication',
2027
2028
  fix: 'Document RBAC/permissions model in .windsurfrules for Cascade.',
2028
2029
  template: null, file: () => '.windsurfrules', line: () => null,
2029
2030
  },
2030
2031
  wsOauthSsoMentioned: {
2031
2032
  id: 'WS-T29', name: 'OAuth/SSO configuration documented',
2032
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /oauth|sso|saml|oidc|google.{0,10}auth/i.test(docs); },
2033
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /oauth|sso|saml|oidc|google.{0,10}auth/i.test(docs); },
2033
2034
  impact: 'medium', rating: 3, category: 'authentication',
2034
2035
  fix: 'Document OAuth/SSO provider in README.md.',
2035
2036
  template: null, file: () => 'README.md', line: () => null,
2036
2037
  },
2037
2038
  wsCredentialRotationDocumented: {
2038
2039
  id: 'WS-T30', name: 'Credential rotation policy documented',
2039
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /rotat.{0,10}secret|rotat.{0,10}key|credential.{0,10}rotat/i.test(docs); },
2040
+ check: (ctx) => { if (!isAuthProject(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('.windsurfrules') || ''); if (!docs.trim()) return null; return /rotat.{0,10}secret|rotat.{0,10}key|credential.{0,10}rotat/i.test(docs); },
2040
2041
  impact: 'medium', rating: 3, category: 'authentication',
2041
2042
  fix: 'Document credential rotation in AGENTS.md.',
2042
2043
  template: null, file: () => 'AGENTS.md', line: () => null,
2043
2044
  },
2044
2045
  wsLoggingConfigured: {
2045
2046
  id: 'WS-T31', name: 'Logging framework configured',
2046
- check: (ctx) => /winston|pino|bunyan|morgan|loguru/i.test(ctx.fileContent('package.json') || '') || ctx.files.some(f => /log(ger|ging)\.config/i.test(f)),
2047
+ 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)),
2047
2048
  impact: 'high', rating: 4, category: 'monitoring',
2048
2049
  fix: 'Add a structured logging framework (Pino, Winston) and document log levels.',
2049
2050
  template: null, file: () => 'package.json', line: () => null,
2050
2051
  },
2051
2052
  wsErrorTrackingSetup: {
2052
2053
  id: 'WS-T32', name: 'Error tracking service configured',
2053
- check: (ctx) => /sentry|bugsnag|rollbar|honeybadger/i.test(ctx.fileContent('package.json') || '') || ctx.files.some(f => /sentry\.client|sentry\.server/i.test(f)),
2054
+ check: (ctx) => !isMonitoringRelevant(ctx) ? null : /sentry|bugsnag|rollbar|honeybadger/i.test(ctx.fileContent('package.json') || '') || ctx.files.some(f => /sentry\.client|sentry\.server/i.test(f)),
2054
2055
  impact: 'high', rating: 4, category: 'monitoring',
2055
2056
  fix: 'Set up error tracking (Sentry) to catch runtime errors.',
2056
2057
  template: null, file: () => null, line: () => null,
2057
2058
  },
2058
2059
  wsApmMetricsMentioned: {
2059
2060
  id: 'WS-T33', name: 'APM / metrics platform documented',
2060
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /datadog|newrelic|prometheus|grafana|opentelemetry|apm/i.test(docs); },
2061
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /datadog|newrelic|prometheus|grafana|opentelemetry|apm/i.test(docs); },
2061
2062
  impact: 'medium', rating: 3, category: 'monitoring',
2062
2063
  fix: 'Document APM platform in README.md.',
2063
2064
  template: null, file: () => 'README.md', line: () => null,
2064
2065
  },
2065
2066
  wsHealthCheckEndpoint: {
2066
2067
  id: 'WS-T34', name: 'Health check endpoint documented',
2067
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /health.?check|\/health|\/ping|\/status/i.test(docs); },
2068
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /health.?check|\/health|\/ping|\/status/i.test(docs); },
2068
2069
  impact: 'medium', rating: 3, category: 'monitoring',
2069
2070
  fix: 'Document health check endpoint in README.md.',
2070
2071
  template: null, file: () => 'README.md', line: () => null,
2071
2072
  },
2072
2073
  wsAlertingReferenced: {
2073
2074
  id: 'WS-T35', name: 'Alerting strategy referenced',
2074
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /alert|pagerduty|opsgenie|oncall|incident/i.test(docs); },
2075
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /alert|pagerduty|opsgenie|oncall|incident/i.test(docs); },
2075
2076
  impact: 'medium', rating: 3, category: 'monitoring',
2076
2077
  fix: 'Document alerting strategy in README.md.',
2077
2078
  template: null, file: () => 'README.md', line: () => null,
2078
2079
  },
2079
2080
  wsLogRotationMentioned: {
2080
2081
  id: 'WS-T36', name: 'Log rotation / retention documented',
2081
- check: (ctx) => { const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /log.{0,15}rotat|log.{0,15}retent|retention.{0,15}polic/i.test(docs); },
2082
+ check: (ctx) => { if (!isMonitoringRelevant(ctx)) return null; const docs = (ctx.fileContent('AGENTS.md') || '') + (ctx.fileContent('README.md') || ''); if (!docs.trim()) return null; return /log.{0,15}rotat|log.{0,15}retent|retention.{0,15}polic/i.test(docs); },
2082
2083
  impact: 'low', rating: 2, category: 'monitoring',
2083
2084
  fix: 'Document log rotation policy in README.md.',
2084
2085
  template: null, file: () => 'README.md', line: () => null,