@nerviq/cli 1.17.3 → 1.19.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.
- package/LICENSE +23 -23
- package/README.md +4 -4
- package/bin/cli.js +61 -274
- package/package.json +60 -60
- package/src/activity.js +1039 -1039
- package/src/adoption-advisor.js +299 -299
- package/src/aider/config-parser.js +166 -166
- package/src/aider/context.js +158 -158
- package/src/aider/deep-review.js +316 -316
- package/src/aider/domain-packs.js +303 -303
- package/src/aider/freshness.js +93 -93
- package/src/aider/governance.js +253 -253
- package/src/aider/interactive.js +334 -334
- package/src/aider/mcp-packs.js +329 -329
- package/src/aider/patch.js +214 -214
- package/src/aider/plans.js +186 -186
- package/src/aider/premium.js +360 -360
- package/src/aider/setup.js +404 -404
- package/src/aider/techniques.js +16 -16
- package/src/analyze.js +951 -951
- package/src/anti-patterns.js +485 -485
- package/src/audit/instruction-files.js +180 -180
- package/src/audit/recommendations.js +577 -577
- package/src/auto-suggest.js +154 -154
- package/src/badge.js +13 -13
- package/src/behavioral-drift.js +801 -801
- package/src/benchmark.js +67 -67
- package/src/catalog.js +103 -103
- package/src/certification.js +128 -128
- package/src/codex/config-parser.js +183 -183
- package/src/codex/context.js +223 -223
- package/src/codex/deep-review.js +493 -493
- package/src/codex/domain-packs.js +394 -394
- package/src/codex/freshness.js +84 -84
- package/src/codex/governance.js +192 -192
- package/src/codex/interactive.js +618 -618
- package/src/codex/mcp-packs.js +914 -914
- package/src/codex/patch.js +209 -209
- package/src/codex/plans.js +251 -251
- package/src/codex/premium.js +614 -614
- package/src/codex/setup.js +591 -591
- package/src/context.js +320 -320
- package/src/continuous-ops.js +681 -681
- package/src/copilot/activity.js +309 -309
- package/src/copilot/config-parser.js +280 -226
- package/src/copilot/context.js +218 -197
- package/src/copilot/deep-review.js +346 -346
- package/src/copilot/domain-packs.js +372 -372
- package/src/copilot/freshness.js +57 -57
- package/src/copilot/governance.js +222 -222
- package/src/copilot/interactive.js +406 -406
- package/src/copilot/mcp-packs.js +826 -826
- package/src/copilot/plans.js +253 -253
- package/src/copilot/premium.js +451 -451
- package/src/copilot/setup.js +488 -488
- package/src/copilot/techniques.js +219 -78
- package/src/cost-tracking.js +61 -61
- package/src/cursor/activity.js +301 -301
- package/src/cursor/config-parser.js +265 -265
- package/src/cursor/context.js +256 -256
- package/src/cursor/deep-review.js +334 -334
- package/src/cursor/domain-packs.js +368 -368
- package/src/cursor/freshness.js +65 -65
- package/src/cursor/governance.js +229 -229
- package/src/cursor/interactive.js +391 -391
- package/src/cursor/mcp-packs.js +828 -828
- package/src/cursor/plans.js +254 -254
- package/src/cursor/premium.js +469 -469
- package/src/cursor/setup.js +488 -488
- package/src/dashboard.js +493 -493
- package/src/deep-review.js +428 -428
- package/src/deprecation.js +98 -98
- package/src/diff-only.js +280 -280
- package/src/doctor.js +119 -119
- package/src/domain-pack-expansion.js +1033 -1033
- package/src/domain-packs.js +387 -387
- package/src/feedback.js +178 -178
- package/src/fix-engine.js +783 -0
- package/src/fix-prompts.js +122 -122
- package/src/formatters/sarif.js +115 -115
- package/src/freshness.js +74 -74
- package/src/gemini/config-parser.js +275 -275
- package/src/gemini/context.js +221 -221
- package/src/gemini/deep-review.js +559 -559
- package/src/gemini/domain-packs.js +393 -393
- package/src/gemini/freshness.js +66 -66
- package/src/gemini/governance.js +201 -201
- package/src/gemini/interactive.js +860 -860
- package/src/gemini/mcp-packs.js +915 -915
- package/src/gemini/plans.js +269 -269
- package/src/gemini/premium.js +760 -760
- package/src/gemini/setup.js +692 -692
- package/src/gemini/techniques.js +14 -14
- package/src/governance.js +72 -72
- package/src/harmony/add.js +68 -68
- package/src/harmony/advisor.js +333 -333
- package/src/harmony/canon.js +565 -565
- package/src/harmony/cli.js +591 -591
- package/src/harmony/drift.js +401 -401
- package/src/harmony/governance.js +313 -313
- package/src/harmony/memory.js +239 -239
- package/src/harmony/sync.js +475 -475
- package/src/harmony/watch.js +370 -370
- package/src/hook-validation.js +342 -342
- package/src/index.js +271 -271
- package/src/init.js +184 -184
- package/src/instruction-surfaces.js +185 -185
- package/src/integrations.js +144 -144
- package/src/interactive.js +118 -118
- package/src/locales/en.json +1 -1
- package/src/locales/es.json +1 -1
- package/src/mcp-packs.js +830 -830
- package/src/mcp-server.js +726 -726
- package/src/mcp-validation.js +337 -337
- package/src/nerviq-sync.json +7 -7
- package/src/opencode/config-parser.js +109 -109
- package/src/opencode/context.js +247 -247
- package/src/opencode/deep-review.js +313 -313
- package/src/opencode/domain-packs.js +262 -262
- package/src/opencode/freshness.js +66 -66
- package/src/opencode/governance.js +159 -159
- package/src/opencode/interactive.js +392 -392
- package/src/opencode/mcp-packs.js +705 -705
- package/src/opencode/patch.js +184 -184
- package/src/opencode/plans.js +231 -231
- package/src/opencode/premium.js +413 -413
- package/src/opencode/setup.js +449 -449
- package/src/opencode/techniques.js +27 -27
- package/src/operating-profile.js +574 -574
- package/src/org.js +152 -152
- package/src/permission-rules.js +218 -218
- package/src/plans.js +839 -839
- package/src/platform-change-manifest.js +86 -86
- package/src/plugins.js +110 -110
- package/src/policy-layers.js +210 -210
- package/src/profiles.js +124 -124
- package/src/prompt-injection.js +74 -74
- package/src/public-api.js +173 -173
- package/src/recommendation-rules.js +84 -84
- package/src/repo-archetype.js +386 -386
- package/src/secret-patterns.js +39 -39
- package/src/server.js +527 -527
- package/src/setup/analysis.js +607 -607
- package/src/setup/runtime.js +172 -172
- package/src/setup.js +677 -677
- package/src/shared/capabilities.js +194 -194
- package/src/source-urls.js +132 -132
- package/src/stack-checks.js +565 -565
- package/src/supplemental-checks.js +13 -13
- package/src/synergy/adaptive.js +261 -261
- package/src/synergy/compensation.js +137 -137
- package/src/synergy/evidence.js +193 -193
- package/src/synergy/learning.js +199 -199
- package/src/synergy/patterns.js +227 -227
- package/src/synergy/ranking.js +83 -83
- package/src/synergy/report.js +165 -165
- package/src/synergy/routing.js +146 -146
- package/src/techniques/api.js +407 -407
- package/src/techniques/automation.js +316 -316
- package/src/techniques/compliance.js +257 -257
- package/src/techniques/hygiene.js +294 -294
- package/src/techniques/instructions.js +243 -243
- package/src/techniques/observability.js +226 -226
- package/src/techniques/optimization.js +142 -142
- package/src/techniques/quality.js +318 -318
- package/src/techniques/security.js +237 -237
- package/src/techniques/shared.js +443 -443
- package/src/techniques/stacks.js +2294 -2294
- package/src/techniques/tools.js +106 -106
- package/src/techniques/workflow.js +413 -413
- package/src/techniques.js +81 -81
- package/src/terminology.js +73 -73
- package/src/token-estimate.js +35 -35
- package/src/usage-patterns.js +99 -99
- package/src/verification-metadata.js +145 -145
- package/src/watch.js +247 -247
- package/src/windsurf/activity.js +302 -302
- package/src/windsurf/config-parser.js +267 -267
- package/src/windsurf/context.js +249 -249
- package/src/windsurf/deep-review.js +337 -337
- package/src/windsurf/domain-packs.js +370 -370
- package/src/windsurf/freshness.js +36 -36
- package/src/windsurf/governance.js +231 -231
- package/src/windsurf/interactive.js +388 -388
- package/src/windsurf/mcp-packs.js +792 -792
- package/src/windsurf/plans.js +247 -247
- package/src/windsurf/premium.js +468 -468
- package/src/windsurf/setup.js +471 -471
- package/src/windsurf/techniques.js +17 -17
- package/src/workspace.js +375 -375
|
@@ -1,226 +1,226 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Observability technique fragments.
|
|
3
|
-
* Generated mechanically from the legacy techniques.js monolith during HR-09.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const {
|
|
7
|
-
hasFrontendSignals,
|
|
8
|
-
hasProjectFile,
|
|
9
|
-
readProjectFiles,
|
|
10
|
-
isFlutterProject,
|
|
11
|
-
isSwiftProject,
|
|
12
|
-
isKotlinProject,
|
|
13
|
-
} = require('./shared');
|
|
14
|
-
|
|
15
|
-
module.exports = {
|
|
16
|
-
otelConfigured: {
|
|
17
|
-
id: 130001,
|
|
18
|
-
name: 'OpenTelemetry SDK configured',
|
|
19
|
-
check: (ctx) => {
|
|
20
|
-
const pkg = ctx.fileContent('package.json') || '';
|
|
21
|
-
const req = readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i);
|
|
22
|
-
const goMod = ctx.fileContent('go.mod') || '';
|
|
23
|
-
const cargo = ctx.fileContent('Cargo.toml') || '';
|
|
24
|
-
const deps = [pkg, req, goMod, cargo].join('\n');
|
|
25
|
-
return /opentelemetry|@opentelemetry\/sdk|otel/i.test(deps) ||
|
|
26
|
-
ctx.files.some(f => /otel.*config|opentelemetry.*config/i.test(f));
|
|
27
|
-
},
|
|
28
|
-
impact: 'high',
|
|
29
|
-
category: 'observability',
|
|
30
|
-
fix: 'Add OpenTelemetry SDK to your project for unified traces, metrics, and logs collection.',
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
prometheusMetrics: {
|
|
34
|
-
id: 130002,
|
|
35
|
-
name: 'Prometheus metrics configured',
|
|
36
|
-
check: (ctx) => {
|
|
37
|
-
const pkg = ctx.fileContent('package.json') || '';
|
|
38
|
-
const req = readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i);
|
|
39
|
-
const goMod = ctx.fileContent('go.mod') || '';
|
|
40
|
-
const cargo = ctx.fileContent('Cargo.toml') || '';
|
|
41
|
-
const deps = [pkg, req, goMod, cargo].join('\n');
|
|
42
|
-
if (/prom-client|prometheus_client|prometheus\/client_golang|prometheus/i.test(deps)) return true;
|
|
43
|
-
const code = readProjectFiles(ctx, /\.(js|ts|py|go|rs|java)$/i);
|
|
44
|
-
return /\/metrics\b/.test(code);
|
|
45
|
-
},
|
|
46
|
-
impact: 'high',
|
|
47
|
-
category: 'observability',
|
|
48
|
-
fix: 'Add a Prometheus client library and expose a /metrics endpoint for monitoring.',
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
structuredLogging: {
|
|
52
|
-
id: 130003,
|
|
53
|
-
name: 'Structured logging library',
|
|
54
|
-
check: (ctx) => {
|
|
55
|
-
const pkg = ctx.fileContent('package.json') || '';
|
|
56
|
-
const req = readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i);
|
|
57
|
-
const goMod = ctx.fileContent('go.mod') || '';
|
|
58
|
-
const cargo = ctx.fileContent('Cargo.toml') || '';
|
|
59
|
-
const deps = [pkg, req, goMod, cargo].join('\n');
|
|
60
|
-
return /winston|pino|bunyan|structlog|python-json-logger|slog|log\/slog|tracing|tracing-subscriber|logback|log4j/i.test(deps);
|
|
61
|
-
},
|
|
62
|
-
impact: 'high',
|
|
63
|
-
category: 'observability',
|
|
64
|
-
fix: 'Use a structured logging library (winston, pino, structlog, slog, tracing) for machine-readable logs.',
|
|
65
|
-
},
|
|
66
|
-
|
|
67
|
-
distributedTracing: {
|
|
68
|
-
id: 130004,
|
|
69
|
-
name: 'Distributed tracing configured',
|
|
70
|
-
check: (ctx) => {
|
|
71
|
-
const pkg = ctx.fileContent('package.json') || '';
|
|
72
|
-
const req = readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i);
|
|
73
|
-
const goMod = ctx.fileContent('go.mod') || '';
|
|
74
|
-
const cargo = ctx.fileContent('Cargo.toml') || '';
|
|
75
|
-
const deps = [pkg, req, goMod, cargo].join('\n');
|
|
76
|
-
if (/jaeger|zipkin|opentelemetry-api|@opentelemetry\/api|dd-trace|datadog-apm/i.test(deps)) return true;
|
|
77
|
-
return ctx.files.some(f => /jaeger|zipkin|tracing.*config/i.test(f));
|
|
78
|
-
},
|
|
79
|
-
impact: 'high',
|
|
80
|
-
category: 'observability',
|
|
81
|
-
fix: 'Add a distributed tracing library (Jaeger, Zipkin, OpenTelemetry) for cross-service request tracking.',
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
healthEndpoint: {
|
|
85
|
-
id: 130005,
|
|
86
|
-
name: 'Health check endpoint',
|
|
87
|
-
check: (ctx) => {
|
|
88
|
-
const code = readProjectFiles(ctx, /\.(js|ts|py|go|rs|java|rb)$/i);
|
|
89
|
-
const configs = readProjectFiles(ctx, /\.(ya?ml|json|toml)$/i);
|
|
90
|
-
return /['"\/]health[z]?['"]\s*[,):]|\/health[z]?\b|healthCheck|health_check|livenessProbe|readinessProbe/i.test(code + configs);
|
|
91
|
-
},
|
|
92
|
-
impact: 'high',
|
|
93
|
-
category: 'observability',
|
|
94
|
-
fix: 'Add a /health or /healthz endpoint for load balancer and orchestrator health checks.',
|
|
95
|
-
},
|
|
96
|
-
|
|
97
|
-
alertingConfigured: {
|
|
98
|
-
id: 130006,
|
|
99
|
-
name: 'Alerting system configured',
|
|
100
|
-
check: (ctx) => {
|
|
101
|
-
const pkg = ctx.fileContent('package.json') || '';
|
|
102
|
-
const deps = [pkg, readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i)].join('\n');
|
|
103
|
-
const configs = readProjectFiles(ctx, /\.(ya?ml|json|toml)$/i);
|
|
104
|
-
return /alertmanager|pagerduty|opsgenie|victorops|alert.*rule/i.test(deps + configs) ||
|
|
105
|
-
ctx.files.some(f => /alert.*rule|alertmanager/i.test(f));
|
|
106
|
-
},
|
|
107
|
-
impact: 'medium',
|
|
108
|
-
category: 'observability',
|
|
109
|
-
fix: 'Configure alerting (Alertmanager, PagerDuty, OpsGenie) to get notified of production issues.',
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
dashboardDefined: {
|
|
113
|
-
id: 130007,
|
|
114
|
-
name: 'Monitoring dashboard defined',
|
|
115
|
-
check: (ctx) => {
|
|
116
|
-
const pkg = ctx.fileContent('package.json') || '';
|
|
117
|
-
return ctx.files.some(f => /grafana\/.*\.json|\.dashboard\.json/i.test(f)) ||
|
|
118
|
-
/grafana|@grafana/i.test(pkg) ||
|
|
119
|
-
hasProjectFile(ctx, /grafana/i);
|
|
120
|
-
},
|
|
121
|
-
impact: 'medium',
|
|
122
|
-
category: 'observability',
|
|
123
|
-
fix: 'Add Grafana dashboard JSON files or configure dashboard-as-code for production monitoring.',
|
|
124
|
-
},
|
|
125
|
-
|
|
126
|
-
logAggregation: {
|
|
127
|
-
id: 130008,
|
|
128
|
-
name: 'Log aggregation configured',
|
|
129
|
-
check: (ctx) => {
|
|
130
|
-
const pkg = ctx.fileContent('package.json') || '';
|
|
131
|
-
const req = readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i);
|
|
132
|
-
const configs = readProjectFiles(ctx, /\.(ya?ml|json|toml)$/i);
|
|
133
|
-
const all = [pkg, req, configs].join('\n');
|
|
134
|
-
return /elasticsearch|elastic\.co|logstash|kibana|loki|grafana-loki|cloudwatch.*log|datadog|fluentd|fluent-bit|filebeat/i.test(all);
|
|
135
|
-
},
|
|
136
|
-
impact: 'medium',
|
|
137
|
-
category: 'observability',
|
|
138
|
-
fix: 'Configure log aggregation (ELK, Loki, CloudWatch, Datadog) for centralized log analysis.',
|
|
139
|
-
},
|
|
140
|
-
|
|
141
|
-
errorTrackingService: {
|
|
142
|
-
id: 130031,
|
|
143
|
-
name: 'Error tracking service configured',
|
|
144
|
-
check: (ctx) => {
|
|
145
|
-
const pkg = ctx.fileContent('package.json') || '';
|
|
146
|
-
const req = readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i);
|
|
147
|
-
const goMod = ctx.fileContent('go.mod') || '';
|
|
148
|
-
const cargo = ctx.fileContent('Cargo.toml') || '';
|
|
149
|
-
const deps = [pkg, req, goMod, cargo].join('\n');
|
|
150
|
-
return /@sentry\/|sentry-sdk|sentry_sdk|bugsnag|rollbar|datadog.*apm|dd-trace|getsentry/i.test(deps);
|
|
151
|
-
},
|
|
152
|
-
impact: 'high',
|
|
153
|
-
category: 'error-tracking',
|
|
154
|
-
fix: 'Add an error tracking service (Sentry, Bugsnag, Rollbar, Datadog APM) to catch production errors.',
|
|
155
|
-
},
|
|
156
|
-
|
|
157
|
-
errorBoundaries: {
|
|
158
|
-
id: 130032,
|
|
159
|
-
name: 'Error boundaries in frontend',
|
|
160
|
-
check: (ctx) => {
|
|
161
|
-
if (!hasFrontendSignals(ctx)) return null;
|
|
162
|
-
const components = readProjectFiles(ctx, /\.(jsx|tsx|vue|svelte|js|ts)$/i);
|
|
163
|
-
if (!components) return null;
|
|
164
|
-
return /ErrorBoundary|errorHandler|onErrorCaptured|componentDidCatch|getDerivedStateFromError|error\.vue|_error\.(jsx|tsx|js|ts)/i.test(components);
|
|
165
|
-
},
|
|
166
|
-
impact: 'high',
|
|
167
|
-
category: 'error-tracking',
|
|
168
|
-
fix: 'Add error boundaries (React ErrorBoundary, Vue errorHandler) to gracefully handle frontend errors.',
|
|
169
|
-
},
|
|
170
|
-
|
|
171
|
-
unhandledRejection: {
|
|
172
|
-
id: 130033,
|
|
173
|
-
name: 'Unhandled rejection/exception handler',
|
|
174
|
-
check: (ctx) => {
|
|
175
|
-
const code = readProjectFiles(ctx, /\.(js|ts|py|go|rs)$/i);
|
|
176
|
-
return /unhandledRejection|uncaughtException|sys\.excepthook|recover\(\)|panic.*handler|set_hook.*panic/i.test(code);
|
|
177
|
-
},
|
|
178
|
-
impact: 'high',
|
|
179
|
-
category: 'error-tracking',
|
|
180
|
-
fix: 'Add handlers for unhandledRejection and uncaughtException to prevent silent failures.',
|
|
181
|
-
},
|
|
182
|
-
|
|
183
|
-
errorReporting: {
|
|
184
|
-
id: 130034,
|
|
185
|
-
name: 'Error notification/reporting pattern',
|
|
186
|
-
check: (ctx) => {
|
|
187
|
-
const code = readProjectFiles(ctx, /\.(js|ts|py|go|rs|java|rb)$/i);
|
|
188
|
-
return /error.*webhook|error.*slack|error.*notify|alert.*error|captureException|captureMessage|notify.*error/i.test(code);
|
|
189
|
-
},
|
|
190
|
-
impact: 'medium',
|
|
191
|
-
category: 'error-tracking',
|
|
192
|
-
fix: 'Add error reporting patterns (webhook, Slack alerts, Sentry capture) to get notified of failures.',
|
|
193
|
-
},
|
|
194
|
-
|
|
195
|
-
errorBudgetSlo: {
|
|
196
|
-
id: 130035,
|
|
197
|
-
name: 'SLO/SLA or error budget defined',
|
|
198
|
-
check: (ctx) => {
|
|
199
|
-
const docs = readProjectFiles(ctx, /\.(md|txt|rst|ya?ml|json|toml)$/i);
|
|
200
|
-
return /\bslo\b|\bsla\b|error.budget|service.level|uptime.*target|availability.*target/i.test(docs);
|
|
201
|
-
},
|
|
202
|
-
impact: 'medium',
|
|
203
|
-
category: 'error-tracking',
|
|
204
|
-
fix: 'Define SLOs, SLAs, or error budgets in your docs to set clear reliability targets.',
|
|
205
|
-
},
|
|
206
|
-
|
|
207
|
-
crashReporting: {
|
|
208
|
-
id: 130036,
|
|
209
|
-
name: 'Crash reporting for mobile',
|
|
210
|
-
check: (ctx) => {
|
|
211
|
-
const hasMobile = isFlutterProject(ctx) || isSwiftProject(ctx) || isKotlinProject(ctx) ||
|
|
212
|
-
/react-native|expo/i.test(ctx.fileContent('package.json') || '');
|
|
213
|
-
if (!hasMobile) return null;
|
|
214
|
-
const deps = [
|
|
215
|
-
ctx.fileContent('package.json') || '',
|
|
216
|
-
ctx.fileContent('pubspec.yaml') || '',
|
|
217
|
-
ctx.fileContent('Podfile') || '',
|
|
218
|
-
readProjectFiles(ctx, /(^|\/)build\.gradle(\.kts)?$/i),
|
|
219
|
-
].join('\n');
|
|
220
|
-
return /crashlytics|sentry.*native|@sentry\/react-native|bugsnag.*react-native|firebase.*crash/i.test(deps);
|
|
221
|
-
},
|
|
222
|
-
impact: 'high',
|
|
223
|
-
category: 'error-tracking',
|
|
224
|
-
fix: 'Add crash reporting (Crashlytics, Sentry Native) to track mobile app crashes in production.',
|
|
225
|
-
},
|
|
226
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Observability technique fragments.
|
|
3
|
+
* Generated mechanically from the legacy techniques.js monolith during HR-09.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
hasFrontendSignals,
|
|
8
|
+
hasProjectFile,
|
|
9
|
+
readProjectFiles,
|
|
10
|
+
isFlutterProject,
|
|
11
|
+
isSwiftProject,
|
|
12
|
+
isKotlinProject,
|
|
13
|
+
} = require('./shared');
|
|
14
|
+
|
|
15
|
+
module.exports = {
|
|
16
|
+
otelConfigured: {
|
|
17
|
+
id: 130001,
|
|
18
|
+
name: 'OpenTelemetry SDK configured',
|
|
19
|
+
check: (ctx) => {
|
|
20
|
+
const pkg = ctx.fileContent('package.json') || '';
|
|
21
|
+
const req = readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i);
|
|
22
|
+
const goMod = ctx.fileContent('go.mod') || '';
|
|
23
|
+
const cargo = ctx.fileContent('Cargo.toml') || '';
|
|
24
|
+
const deps = [pkg, req, goMod, cargo].join('\n');
|
|
25
|
+
return /opentelemetry|@opentelemetry\/sdk|otel/i.test(deps) ||
|
|
26
|
+
ctx.files.some(f => /otel.*config|opentelemetry.*config/i.test(f));
|
|
27
|
+
},
|
|
28
|
+
impact: 'high',
|
|
29
|
+
category: 'observability',
|
|
30
|
+
fix: 'Add OpenTelemetry SDK to your project for unified traces, metrics, and logs collection.',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
prometheusMetrics: {
|
|
34
|
+
id: 130002,
|
|
35
|
+
name: 'Prometheus metrics configured',
|
|
36
|
+
check: (ctx) => {
|
|
37
|
+
const pkg = ctx.fileContent('package.json') || '';
|
|
38
|
+
const req = readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i);
|
|
39
|
+
const goMod = ctx.fileContent('go.mod') || '';
|
|
40
|
+
const cargo = ctx.fileContent('Cargo.toml') || '';
|
|
41
|
+
const deps = [pkg, req, goMod, cargo].join('\n');
|
|
42
|
+
if (/prom-client|prometheus_client|prometheus\/client_golang|prometheus/i.test(deps)) return true;
|
|
43
|
+
const code = readProjectFiles(ctx, /\.(js|ts|py|go|rs|java)$/i);
|
|
44
|
+
return /\/metrics\b/.test(code);
|
|
45
|
+
},
|
|
46
|
+
impact: 'high',
|
|
47
|
+
category: 'observability',
|
|
48
|
+
fix: 'Add a Prometheus client library and expose a /metrics endpoint for monitoring.',
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
structuredLogging: {
|
|
52
|
+
id: 130003,
|
|
53
|
+
name: 'Structured logging library',
|
|
54
|
+
check: (ctx) => {
|
|
55
|
+
const pkg = ctx.fileContent('package.json') || '';
|
|
56
|
+
const req = readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i);
|
|
57
|
+
const goMod = ctx.fileContent('go.mod') || '';
|
|
58
|
+
const cargo = ctx.fileContent('Cargo.toml') || '';
|
|
59
|
+
const deps = [pkg, req, goMod, cargo].join('\n');
|
|
60
|
+
return /winston|pino|bunyan|structlog|python-json-logger|slog|log\/slog|tracing|tracing-subscriber|logback|log4j/i.test(deps);
|
|
61
|
+
},
|
|
62
|
+
impact: 'high',
|
|
63
|
+
category: 'observability',
|
|
64
|
+
fix: 'Use a structured logging library (winston, pino, structlog, slog, tracing) for machine-readable logs.',
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
distributedTracing: {
|
|
68
|
+
id: 130004,
|
|
69
|
+
name: 'Distributed tracing configured',
|
|
70
|
+
check: (ctx) => {
|
|
71
|
+
const pkg = ctx.fileContent('package.json') || '';
|
|
72
|
+
const req = readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i);
|
|
73
|
+
const goMod = ctx.fileContent('go.mod') || '';
|
|
74
|
+
const cargo = ctx.fileContent('Cargo.toml') || '';
|
|
75
|
+
const deps = [pkg, req, goMod, cargo].join('\n');
|
|
76
|
+
if (/jaeger|zipkin|opentelemetry-api|@opentelemetry\/api|dd-trace|datadog-apm/i.test(deps)) return true;
|
|
77
|
+
return ctx.files.some(f => /jaeger|zipkin|tracing.*config/i.test(f));
|
|
78
|
+
},
|
|
79
|
+
impact: 'high',
|
|
80
|
+
category: 'observability',
|
|
81
|
+
fix: 'Add a distributed tracing library (Jaeger, Zipkin, OpenTelemetry) for cross-service request tracking.',
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
healthEndpoint: {
|
|
85
|
+
id: 130005,
|
|
86
|
+
name: 'Health check endpoint',
|
|
87
|
+
check: (ctx) => {
|
|
88
|
+
const code = readProjectFiles(ctx, /\.(js|ts|py|go|rs|java|rb)$/i);
|
|
89
|
+
const configs = readProjectFiles(ctx, /\.(ya?ml|json|toml)$/i);
|
|
90
|
+
return /['"\/]health[z]?['"]\s*[,):]|\/health[z]?\b|healthCheck|health_check|livenessProbe|readinessProbe/i.test(code + configs);
|
|
91
|
+
},
|
|
92
|
+
impact: 'high',
|
|
93
|
+
category: 'observability',
|
|
94
|
+
fix: 'Add a /health or /healthz endpoint for load balancer and orchestrator health checks.',
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
alertingConfigured: {
|
|
98
|
+
id: 130006,
|
|
99
|
+
name: 'Alerting system configured',
|
|
100
|
+
check: (ctx) => {
|
|
101
|
+
const pkg = ctx.fileContent('package.json') || '';
|
|
102
|
+
const deps = [pkg, readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i)].join('\n');
|
|
103
|
+
const configs = readProjectFiles(ctx, /\.(ya?ml|json|toml)$/i);
|
|
104
|
+
return /alertmanager|pagerduty|opsgenie|victorops|alert.*rule/i.test(deps + configs) ||
|
|
105
|
+
ctx.files.some(f => /alert.*rule|alertmanager/i.test(f));
|
|
106
|
+
},
|
|
107
|
+
impact: 'medium',
|
|
108
|
+
category: 'observability',
|
|
109
|
+
fix: 'Configure alerting (Alertmanager, PagerDuty, OpsGenie) to get notified of production issues.',
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
dashboardDefined: {
|
|
113
|
+
id: 130007,
|
|
114
|
+
name: 'Monitoring dashboard defined',
|
|
115
|
+
check: (ctx) => {
|
|
116
|
+
const pkg = ctx.fileContent('package.json') || '';
|
|
117
|
+
return ctx.files.some(f => /grafana\/.*\.json|\.dashboard\.json/i.test(f)) ||
|
|
118
|
+
/grafana|@grafana/i.test(pkg) ||
|
|
119
|
+
hasProjectFile(ctx, /grafana/i);
|
|
120
|
+
},
|
|
121
|
+
impact: 'medium',
|
|
122
|
+
category: 'observability',
|
|
123
|
+
fix: 'Add Grafana dashboard JSON files or configure dashboard-as-code for production monitoring.',
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
logAggregation: {
|
|
127
|
+
id: 130008,
|
|
128
|
+
name: 'Log aggregation configured',
|
|
129
|
+
check: (ctx) => {
|
|
130
|
+
const pkg = ctx.fileContent('package.json') || '';
|
|
131
|
+
const req = readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i);
|
|
132
|
+
const configs = readProjectFiles(ctx, /\.(ya?ml|json|toml)$/i);
|
|
133
|
+
const all = [pkg, req, configs].join('\n');
|
|
134
|
+
return /elasticsearch|elastic\.co|logstash|kibana|loki|grafana-loki|cloudwatch.*log|datadog|fluentd|fluent-bit|filebeat/i.test(all);
|
|
135
|
+
},
|
|
136
|
+
impact: 'medium',
|
|
137
|
+
category: 'observability',
|
|
138
|
+
fix: 'Configure log aggregation (ELK, Loki, CloudWatch, Datadog) for centralized log analysis.',
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
errorTrackingService: {
|
|
142
|
+
id: 130031,
|
|
143
|
+
name: 'Error tracking service configured',
|
|
144
|
+
check: (ctx) => {
|
|
145
|
+
const pkg = ctx.fileContent('package.json') || '';
|
|
146
|
+
const req = readProjectFiles(ctx, /(^|\/)requirements[^/]*\.txt$/i);
|
|
147
|
+
const goMod = ctx.fileContent('go.mod') || '';
|
|
148
|
+
const cargo = ctx.fileContent('Cargo.toml') || '';
|
|
149
|
+
const deps = [pkg, req, goMod, cargo].join('\n');
|
|
150
|
+
return /@sentry\/|sentry-sdk|sentry_sdk|bugsnag|rollbar|datadog.*apm|dd-trace|getsentry/i.test(deps);
|
|
151
|
+
},
|
|
152
|
+
impact: 'high',
|
|
153
|
+
category: 'error-tracking',
|
|
154
|
+
fix: 'Add an error tracking service (Sentry, Bugsnag, Rollbar, Datadog APM) to catch production errors.',
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
errorBoundaries: {
|
|
158
|
+
id: 130032,
|
|
159
|
+
name: 'Error boundaries in frontend',
|
|
160
|
+
check: (ctx) => {
|
|
161
|
+
if (!hasFrontendSignals(ctx)) return null;
|
|
162
|
+
const components = readProjectFiles(ctx, /\.(jsx|tsx|vue|svelte|js|ts)$/i);
|
|
163
|
+
if (!components) return null;
|
|
164
|
+
return /ErrorBoundary|errorHandler|onErrorCaptured|componentDidCatch|getDerivedStateFromError|error\.vue|_error\.(jsx|tsx|js|ts)/i.test(components);
|
|
165
|
+
},
|
|
166
|
+
impact: 'high',
|
|
167
|
+
category: 'error-tracking',
|
|
168
|
+
fix: 'Add error boundaries (React ErrorBoundary, Vue errorHandler) to gracefully handle frontend errors.',
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
unhandledRejection: {
|
|
172
|
+
id: 130033,
|
|
173
|
+
name: 'Unhandled rejection/exception handler',
|
|
174
|
+
check: (ctx) => {
|
|
175
|
+
const code = readProjectFiles(ctx, /\.(js|ts|py|go|rs)$/i);
|
|
176
|
+
return /unhandledRejection|uncaughtException|sys\.excepthook|recover\(\)|panic.*handler|set_hook.*panic/i.test(code);
|
|
177
|
+
},
|
|
178
|
+
impact: 'high',
|
|
179
|
+
category: 'error-tracking',
|
|
180
|
+
fix: 'Add handlers for unhandledRejection and uncaughtException to prevent silent failures.',
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
errorReporting: {
|
|
184
|
+
id: 130034,
|
|
185
|
+
name: 'Error notification/reporting pattern',
|
|
186
|
+
check: (ctx) => {
|
|
187
|
+
const code = readProjectFiles(ctx, /\.(js|ts|py|go|rs|java|rb)$/i);
|
|
188
|
+
return /error.*webhook|error.*slack|error.*notify|alert.*error|captureException|captureMessage|notify.*error/i.test(code);
|
|
189
|
+
},
|
|
190
|
+
impact: 'medium',
|
|
191
|
+
category: 'error-tracking',
|
|
192
|
+
fix: 'Add error reporting patterns (webhook, Slack alerts, Sentry capture) to get notified of failures.',
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
errorBudgetSlo: {
|
|
196
|
+
id: 130035,
|
|
197
|
+
name: 'SLO/SLA or error budget defined',
|
|
198
|
+
check: (ctx) => {
|
|
199
|
+
const docs = readProjectFiles(ctx, /\.(md|txt|rst|ya?ml|json|toml)$/i);
|
|
200
|
+
return /\bslo\b|\bsla\b|error.budget|service.level|uptime.*target|availability.*target/i.test(docs);
|
|
201
|
+
},
|
|
202
|
+
impact: 'medium',
|
|
203
|
+
category: 'error-tracking',
|
|
204
|
+
fix: 'Define SLOs, SLAs, or error budgets in your docs to set clear reliability targets.',
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
crashReporting: {
|
|
208
|
+
id: 130036,
|
|
209
|
+
name: 'Crash reporting for mobile',
|
|
210
|
+
check: (ctx) => {
|
|
211
|
+
const hasMobile = isFlutterProject(ctx) || isSwiftProject(ctx) || isKotlinProject(ctx) ||
|
|
212
|
+
/react-native|expo/i.test(ctx.fileContent('package.json') || '');
|
|
213
|
+
if (!hasMobile) return null;
|
|
214
|
+
const deps = [
|
|
215
|
+
ctx.fileContent('package.json') || '',
|
|
216
|
+
ctx.fileContent('pubspec.yaml') || '',
|
|
217
|
+
ctx.fileContent('Podfile') || '',
|
|
218
|
+
readProjectFiles(ctx, /(^|\/)build\.gradle(\.kts)?$/i),
|
|
219
|
+
].join('\n');
|
|
220
|
+
return /crashlytics|sentry.*native|@sentry\/react-native|bugsnag.*react-native|firebase.*crash/i.test(deps);
|
|
221
|
+
},
|
|
222
|
+
impact: 'high',
|
|
223
|
+
category: 'error-tracking',
|
|
224
|
+
fix: 'Add crash reporting (Crashlytics, Sentry Native) to track mobile app crashes in production.',
|
|
225
|
+
},
|
|
226
|
+
};
|