@nerviq/cli 1.18.0 → 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 +2 -2
- package/bin/cli.js +130 -130
- package/package.json +1 -1
- 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/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/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 -783
- 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
package/src/doctor.js
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
* Checks: Node version, dependencies, platform detection, freshness gates.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
'use strict';
|
|
9
|
-
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
const path = require('path');
|
|
12
|
-
const { version } = require('../package.json');
|
|
13
|
-
const { validateDeclaredMcpServers } = require('./mcp-validation');
|
|
14
|
-
const { validateDeclaredHooks } = require('./hook-validation');
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const { version } = require('../package.json');
|
|
13
|
+
const { validateDeclaredMcpServers } = require('./mcp-validation');
|
|
14
|
+
const { validateDeclaredHooks } = require('./hook-validation');
|
|
15
15
|
|
|
16
16
|
const COLORS = {
|
|
17
17
|
reset: '\x1b[0m',
|
|
@@ -27,11 +27,11 @@ function c(text, color) {
|
|
|
27
27
|
return `${COLORS[color] || ''}${text}${COLORS.reset}`;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
const PLATFORM_SIGNALS = {
|
|
31
|
-
claude: ['CLAUDE.md', '.claude/CLAUDE.md', '.claude/settings.json', '.mcp.json'],
|
|
32
|
-
codex: ['AGENTS.md', '.codex/', '.codex/config.toml'],
|
|
33
|
-
cursor: ['.cursor/rules/', '.cursor/mcp.json', '.cursorrules'],
|
|
34
|
-
copilot: ['.github/copilot-instructions.md', '.github/', '.vscode/mcp.json'],
|
|
30
|
+
const PLATFORM_SIGNALS = {
|
|
31
|
+
claude: ['CLAUDE.md', '.claude/CLAUDE.md', '.claude/settings.json', '.mcp.json'],
|
|
32
|
+
codex: ['AGENTS.md', '.codex/', '.codex/config.toml'],
|
|
33
|
+
cursor: ['.cursor/rules/', '.cursor/mcp.json', '.cursorrules'],
|
|
34
|
+
copilot: ['.github/copilot-instructions.md', '.github/', '.vscode/mcp.json'],
|
|
35
35
|
gemini: ['GEMINI.md', '.gemini/', '.gemini/settings.json'],
|
|
36
36
|
windsurf: ['.windsurf/', '.windsurfrules', '.windsurf/rules/'],
|
|
37
37
|
aider: ['.aider.conf.yml', '.aider.model.settings.yml'],
|
|
@@ -164,59 +164,59 @@ function checkGitRepo(dir) {
|
|
|
164
164
|
|
|
165
165
|
// ─── Main doctor function ────────────────────────────────────────────────────
|
|
166
166
|
|
|
167
|
-
async function runDoctor({ dir = process.cwd(), json = false, verbose = false } = {}) {
|
|
168
|
-
const startMs = Date.now();
|
|
169
|
-
|
|
170
|
-
const checks = [
|
|
167
|
+
async function runDoctor({ dir = process.cwd(), json = false, verbose = false } = {}) {
|
|
168
|
+
const startMs = Date.now();
|
|
169
|
+
|
|
170
|
+
const checks = [
|
|
171
171
|
checkNodeVersion(),
|
|
172
172
|
checkDeps(),
|
|
173
173
|
checkJestInstalled(),
|
|
174
174
|
checkCliPermissions(),
|
|
175
175
|
checkGitRepo(dir),
|
|
176
176
|
checkPlatformDetection(dir),
|
|
177
|
-
];
|
|
178
|
-
|
|
179
|
-
const detectedPlatforms = (checks.find(c => c.detected) || {}).detected || [];
|
|
180
|
-
const freshnessChecks = checkFreshnessGates();
|
|
181
|
-
const mcpSummary = await validateDeclaredMcpServers({ dir, detectedPlatforms });
|
|
182
|
-
const hookSummary = validateDeclaredHooks({ dir, detectedPlatforms });
|
|
183
|
-
|
|
184
|
-
const totalPass = checks.filter(c => c.status === 'pass').length;
|
|
185
|
-
const totalWarn = checks.filter(c => c.status === 'warn').length;
|
|
186
|
-
const totalFail = checks.filter(c => c.status === 'fail').length;
|
|
187
|
-
|
|
188
|
-
const freshPass = freshnessChecks.filter(f => f.status === 'pass').length;
|
|
189
|
-
const freshWarn = freshnessChecks.filter(f => f.status !== 'pass').length;
|
|
190
|
-
|
|
191
|
-
const overallOk = totalFail === 0 && mcpSummary.fail === 0 && hookSummary.fail === 0;
|
|
192
|
-
const elapsed = Date.now() - startMs;
|
|
193
|
-
|
|
194
|
-
if (json) {
|
|
195
|
-
return JSON.stringify({
|
|
196
|
-
nerviq: version,
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
const detectedPlatforms = (checks.find(c => c.detected) || {}).detected || [];
|
|
180
|
+
const freshnessChecks = checkFreshnessGates();
|
|
181
|
+
const mcpSummary = await validateDeclaredMcpServers({ dir, detectedPlatforms });
|
|
182
|
+
const hookSummary = validateDeclaredHooks({ dir, detectedPlatforms });
|
|
183
|
+
|
|
184
|
+
const totalPass = checks.filter(c => c.status === 'pass').length;
|
|
185
|
+
const totalWarn = checks.filter(c => c.status === 'warn').length;
|
|
186
|
+
const totalFail = checks.filter(c => c.status === 'fail').length;
|
|
187
|
+
|
|
188
|
+
const freshPass = freshnessChecks.filter(f => f.status === 'pass').length;
|
|
189
|
+
const freshWarn = freshnessChecks.filter(f => f.status !== 'pass').length;
|
|
190
|
+
|
|
191
|
+
const overallOk = totalFail === 0 && mcpSummary.fail === 0 && hookSummary.fail === 0;
|
|
192
|
+
const elapsed = Date.now() - startMs;
|
|
193
|
+
|
|
194
|
+
if (json) {
|
|
195
|
+
return JSON.stringify({
|
|
196
|
+
nerviq: version,
|
|
197
197
|
node: process.version,
|
|
198
198
|
dir,
|
|
199
199
|
overallOk,
|
|
200
200
|
checks,
|
|
201
|
-
freshnessChecks,
|
|
202
|
-
mcpChecks: mcpSummary.checks,
|
|
203
|
-
hookChecks: hookSummary.checks,
|
|
204
|
-
totalPass,
|
|
205
|
-
totalWarn,
|
|
206
|
-
totalFail,
|
|
207
|
-
freshPass,
|
|
208
|
-
freshWarn,
|
|
209
|
-
mcpDeclared: mcpSummary.declared,
|
|
210
|
-
mcpPass: mcpSummary.pass,
|
|
211
|
-
mcpWarn: mcpSummary.warn,
|
|
212
|
-
mcpFail: mcpSummary.fail,
|
|
213
|
-
hookDeclared: hookSummary.declared,
|
|
214
|
-
hookPass: hookSummary.pass,
|
|
215
|
-
hookWarn: hookSummary.warn,
|
|
216
|
-
hookFail: hookSummary.fail,
|
|
217
|
-
elapsed,
|
|
218
|
-
}, null, 2);
|
|
219
|
-
}
|
|
201
|
+
freshnessChecks,
|
|
202
|
+
mcpChecks: mcpSummary.checks,
|
|
203
|
+
hookChecks: hookSummary.checks,
|
|
204
|
+
totalPass,
|
|
205
|
+
totalWarn,
|
|
206
|
+
totalFail,
|
|
207
|
+
freshPass,
|
|
208
|
+
freshWarn,
|
|
209
|
+
mcpDeclared: mcpSummary.declared,
|
|
210
|
+
mcpPass: mcpSummary.pass,
|
|
211
|
+
mcpWarn: mcpSummary.warn,
|
|
212
|
+
mcpFail: mcpSummary.fail,
|
|
213
|
+
hookDeclared: hookSummary.declared,
|
|
214
|
+
hookPass: hookSummary.pass,
|
|
215
|
+
hookWarn: hookSummary.warn,
|
|
216
|
+
hookFail: hookSummary.fail,
|
|
217
|
+
elapsed,
|
|
218
|
+
}, null, 2);
|
|
219
|
+
}
|
|
220
220
|
|
|
221
221
|
const lines = [''];
|
|
222
222
|
lines.push(c(` nerviq doctor v${version}`, 'bold'));
|
|
@@ -234,9 +234,9 @@ async function runDoctor({ dir = process.cwd(), json = false, verbose = false }
|
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
// Platform detection detail
|
|
237
|
-
if (detectedPlatforms.length > 0) {
|
|
238
|
-
lines.push('');
|
|
239
|
-
lines.push(c(' Detected Platforms', 'bold'));
|
|
237
|
+
if (detectedPlatforms.length > 0) {
|
|
238
|
+
lines.push('');
|
|
239
|
+
lines.push(c(' Detected Platforms', 'bold'));
|
|
240
240
|
for (const p of detectedPlatforms) {
|
|
241
241
|
lines.push(` ${c('✓', 'green')} ${p}`);
|
|
242
242
|
}
|
|
@@ -245,67 +245,67 @@ async function runDoctor({ dir = process.cwd(), json = false, verbose = false }
|
|
|
245
245
|
// Freshness
|
|
246
246
|
lines.push('');
|
|
247
247
|
lines.push(c(' Freshness Gates', 'bold'));
|
|
248
|
-
for (const f of freshnessChecks) {
|
|
249
|
-
const icon = f.status === 'pass' ? c('✓', 'green') : c('⚠', 'yellow');
|
|
250
|
-
const label = f.platform.padEnd(12);
|
|
251
|
-
lines.push(` ${icon} ${label} ${c(f.detail || f.status, f.status === 'pass' ? 'dim' : 'yellow')}`);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
lines.push('');
|
|
255
|
-
lines.push(c(' MCP Servers', 'bold'));
|
|
256
|
-
if (mcpSummary.checks.length === 0) {
|
|
257
|
-
lines.push(c(' No declared MCP servers found in the detected project surfaces.', 'dim'));
|
|
258
|
-
} else {
|
|
259
|
-
for (const item of mcpSummary.checks) {
|
|
260
|
-
const icon = item.status === 'pass'
|
|
261
|
-
? c('✓', 'green')
|
|
262
|
-
: item.status === 'warn'
|
|
263
|
-
? c('⚠', 'yellow')
|
|
264
|
-
: c('✗', 'red');
|
|
265
|
-
const label = `${item.platform}/${item.scope}`.padEnd(16);
|
|
266
|
-
lines.push(` ${icon} ${label} ${item.serverName} ${c(item.detail, item.status === 'pass' ? 'dim' : item.status === 'warn' ? 'yellow' : 'red')}`);
|
|
267
|
-
if (verbose && item.source) {
|
|
268
|
-
lines.push(c(` Source: ${item.source}`, 'dim'));
|
|
269
|
-
}
|
|
270
|
-
if (item.fix && (verbose || item.status === 'fail')) {
|
|
271
|
-
lines.push(c(` Fix: ${item.fix}`, item.status === 'fail' ? 'yellow' : 'dim'));
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
lines.push('');
|
|
277
|
-
lines.push(c(' Hook Runtime', 'bold'));
|
|
278
|
-
if (hookSummary.checks.length === 0) {
|
|
279
|
-
lines.push(c(' No declared hooks found in the detected project surfaces.', 'dim'));
|
|
280
|
-
} else {
|
|
281
|
-
for (const item of hookSummary.checks) {
|
|
282
|
-
const icon = item.status === 'pass'
|
|
283
|
-
? c('✓', 'green')
|
|
284
|
-
: item.status === 'warn'
|
|
285
|
-
? c('⚠', 'yellow')
|
|
286
|
-
: c('✗', 'red');
|
|
287
|
-
const label = `${item.platform}/${item.validationMode}`.padEnd(16);
|
|
288
|
-
lines.push(` ${icon} ${label} ${item.label} ${c(item.detail, item.status === 'pass' ? 'dim' : item.status === 'warn' ? 'yellow' : 'red')}`);
|
|
289
|
-
if (verbose && item.script) {
|
|
290
|
-
lines.push(c(` Script: ${item.script}`, 'dim'));
|
|
291
|
-
}
|
|
292
|
-
if (verbose && item.executable) {
|
|
293
|
-
lines.push(c(` Runtime: ${item.executable}`, 'dim'));
|
|
294
|
-
}
|
|
295
|
-
if (item.fix && (verbose || item.status === 'fail')) {
|
|
296
|
-
lines.push(c(` Fix: ${item.fix}`, item.status === 'fail' ? 'yellow' : 'dim'));
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
lines.push('');
|
|
302
|
-
lines.push(c(' Summary', 'bold'));
|
|
303
|
-
lines.push(` Checks: ${c(String(totalPass), 'green')} pass ${totalWarn > 0 ? c(String(totalWarn), 'yellow') + ' warn ' : ''}${totalFail > 0 ? c(String(totalFail), 'red') + ' fail' : ''}`);
|
|
304
|
-
lines.push(` Freshness: ${c(String(freshPass), 'green')} fresh ${freshWarn > 0 ? c(String(freshWarn), 'yellow') + ' stale/unverified' : ''}`);
|
|
305
|
-
lines.push(` MCP: ${c(String(mcpSummary.pass), 'green')} pass ${mcpSummary.warn > 0 ? c(String(mcpSummary.warn), 'yellow') + ' warn ' : ''}${mcpSummary.fail > 0 ? c(String(mcpSummary.fail), 'red') + ' fail' : ''}${c(`(${mcpSummary.declared} declared)`, 'dim')}`);
|
|
306
|
-
lines.push(` Hooks: ${c(String(hookSummary.pass), 'green')} pass ${hookSummary.warn > 0 ? c(String(hookSummary.warn), 'yellow') + ' warn ' : ''}${hookSummary.fail > 0 ? c(String(hookSummary.fail), 'red') + ' fail' : ''}${c(`(${hookSummary.declared} declared)`, 'dim')}`);
|
|
307
|
-
lines.push(` Status: ${overallOk ? c('✓ Healthy', 'green') : c('✗ Issues found', 'red')}`);
|
|
308
|
-
lines.push(` Duration: ${elapsed}ms`);
|
|
248
|
+
for (const f of freshnessChecks) {
|
|
249
|
+
const icon = f.status === 'pass' ? c('✓', 'green') : c('⚠', 'yellow');
|
|
250
|
+
const label = f.platform.padEnd(12);
|
|
251
|
+
lines.push(` ${icon} ${label} ${c(f.detail || f.status, f.status === 'pass' ? 'dim' : 'yellow')}`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
lines.push('');
|
|
255
|
+
lines.push(c(' MCP Servers', 'bold'));
|
|
256
|
+
if (mcpSummary.checks.length === 0) {
|
|
257
|
+
lines.push(c(' No declared MCP servers found in the detected project surfaces.', 'dim'));
|
|
258
|
+
} else {
|
|
259
|
+
for (const item of mcpSummary.checks) {
|
|
260
|
+
const icon = item.status === 'pass'
|
|
261
|
+
? c('✓', 'green')
|
|
262
|
+
: item.status === 'warn'
|
|
263
|
+
? c('⚠', 'yellow')
|
|
264
|
+
: c('✗', 'red');
|
|
265
|
+
const label = `${item.platform}/${item.scope}`.padEnd(16);
|
|
266
|
+
lines.push(` ${icon} ${label} ${item.serverName} ${c(item.detail, item.status === 'pass' ? 'dim' : item.status === 'warn' ? 'yellow' : 'red')}`);
|
|
267
|
+
if (verbose && item.source) {
|
|
268
|
+
lines.push(c(` Source: ${item.source}`, 'dim'));
|
|
269
|
+
}
|
|
270
|
+
if (item.fix && (verbose || item.status === 'fail')) {
|
|
271
|
+
lines.push(c(` Fix: ${item.fix}`, item.status === 'fail' ? 'yellow' : 'dim'));
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
lines.push('');
|
|
277
|
+
lines.push(c(' Hook Runtime', 'bold'));
|
|
278
|
+
if (hookSummary.checks.length === 0) {
|
|
279
|
+
lines.push(c(' No declared hooks found in the detected project surfaces.', 'dim'));
|
|
280
|
+
} else {
|
|
281
|
+
for (const item of hookSummary.checks) {
|
|
282
|
+
const icon = item.status === 'pass'
|
|
283
|
+
? c('✓', 'green')
|
|
284
|
+
: item.status === 'warn'
|
|
285
|
+
? c('⚠', 'yellow')
|
|
286
|
+
: c('✗', 'red');
|
|
287
|
+
const label = `${item.platform}/${item.validationMode}`.padEnd(16);
|
|
288
|
+
lines.push(` ${icon} ${label} ${item.label} ${c(item.detail, item.status === 'pass' ? 'dim' : item.status === 'warn' ? 'yellow' : 'red')}`);
|
|
289
|
+
if (verbose && item.script) {
|
|
290
|
+
lines.push(c(` Script: ${item.script}`, 'dim'));
|
|
291
|
+
}
|
|
292
|
+
if (verbose && item.executable) {
|
|
293
|
+
lines.push(c(` Runtime: ${item.executable}`, 'dim'));
|
|
294
|
+
}
|
|
295
|
+
if (item.fix && (verbose || item.status === 'fail')) {
|
|
296
|
+
lines.push(c(` Fix: ${item.fix}`, item.status === 'fail' ? 'yellow' : 'dim'));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
lines.push('');
|
|
302
|
+
lines.push(c(' Summary', 'bold'));
|
|
303
|
+
lines.push(` Checks: ${c(String(totalPass), 'green')} pass ${totalWarn > 0 ? c(String(totalWarn), 'yellow') + ' warn ' : ''}${totalFail > 0 ? c(String(totalFail), 'red') + ' fail' : ''}`);
|
|
304
|
+
lines.push(` Freshness: ${c(String(freshPass), 'green')} fresh ${freshWarn > 0 ? c(String(freshWarn), 'yellow') + ' stale/unverified' : ''}`);
|
|
305
|
+
lines.push(` MCP: ${c(String(mcpSummary.pass), 'green')} pass ${mcpSummary.warn > 0 ? c(String(mcpSummary.warn), 'yellow') + ' warn ' : ''}${mcpSummary.fail > 0 ? c(String(mcpSummary.fail), 'red') + ' fail' : ''}${c(`(${mcpSummary.declared} declared)`, 'dim')}`);
|
|
306
|
+
lines.push(` Hooks: ${c(String(hookSummary.pass), 'green')} pass ${hookSummary.warn > 0 ? c(String(hookSummary.warn), 'yellow') + ' warn ' : ''}${hookSummary.fail > 0 ? c(String(hookSummary.fail), 'red') + ' fail' : ''}${c(`(${hookSummary.declared} declared)`, 'dim')}`);
|
|
307
|
+
lines.push(` Status: ${overallOk ? c('✓ Healthy', 'green') : c('✗ Issues found', 'red')}`);
|
|
308
|
+
lines.push(` Duration: ${elapsed}ms`);
|
|
309
309
|
lines.push('');
|
|
310
310
|
|
|
311
311
|
if (!overallOk) {
|