@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.
- package/LICENSE +19 -17
- package/package.json +2 -2
- package/src/aider/techniques.js +25 -24
- package/src/cursor/techniques.js +25 -24
- package/src/opencode/techniques.js +25 -24
- package/src/supplemental-checks.js +817 -767
- package/src/windsurf/techniques.js +25 -24
|
@@ -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,
|