@neurcode-ai/cli 0.9.50 → 0.9.60

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.
Files changed (61) hide show
  1. package/dist/commands/fix.d.ts.map +1 -1
  2. package/dist/commands/fix.js +307 -31
  3. package/dist/commands/fix.js.map +1 -1
  4. package/dist/commands/verify.d.ts.map +1 -1
  5. package/dist/commands/verify.js +264 -13
  6. package/dist/commands/verify.js.map +1 -1
  7. package/dist/daemon/server.d.ts +23 -0
  8. package/dist/daemon/server.d.ts.map +1 -0
  9. package/dist/daemon/server.js +226 -0
  10. package/dist/daemon/server.js.map +1 -0
  11. package/dist/index.js +8 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/intent-engine/coverage.d.ts +69 -0
  14. package/dist/intent-engine/coverage.d.ts.map +1 -0
  15. package/dist/intent-engine/coverage.js +140 -0
  16. package/dist/intent-engine/coverage.js.map +1 -0
  17. package/dist/intent-engine/flow-rules.d.ts +21 -0
  18. package/dist/intent-engine/flow-rules.d.ts.map +1 -0
  19. package/dist/intent-engine/flow-rules.js +83 -0
  20. package/dist/intent-engine/flow-rules.js.map +1 -0
  21. package/dist/intent-engine/flow-validator.d.ts +29 -0
  22. package/dist/intent-engine/flow-validator.d.ts.map +1 -0
  23. package/dist/intent-engine/flow-validator.js +202 -0
  24. package/dist/intent-engine/flow-validator.js.map +1 -0
  25. package/dist/intent-engine/graph.d.ts +33 -0
  26. package/dist/intent-engine/graph.d.ts.map +1 -0
  27. package/dist/intent-engine/graph.js +67 -0
  28. package/dist/intent-engine/graph.js.map +1 -0
  29. package/dist/intent-engine/index.d.ts +35 -0
  30. package/dist/intent-engine/index.d.ts.map +1 -0
  31. package/dist/intent-engine/index.js +94 -0
  32. package/dist/intent-engine/index.js.map +1 -0
  33. package/dist/intent-engine/indexer.d.ts +18 -0
  34. package/dist/intent-engine/indexer.d.ts.map +1 -0
  35. package/dist/intent-engine/indexer.js +100 -0
  36. package/dist/intent-engine/indexer.js.map +1 -0
  37. package/dist/intent-engine/matcher.d.ts +35 -0
  38. package/dist/intent-engine/matcher.d.ts.map +1 -0
  39. package/dist/intent-engine/matcher.js +522 -0
  40. package/dist/intent-engine/matcher.js.map +1 -0
  41. package/dist/intent-engine/parser.d.ts +12 -0
  42. package/dist/intent-engine/parser.d.ts.map +1 -0
  43. package/dist/intent-engine/parser.js +93 -0
  44. package/dist/intent-engine/parser.js.map +1 -0
  45. package/dist/intent-engine/regression.d.ts +32 -0
  46. package/dist/intent-engine/regression.d.ts.map +1 -0
  47. package/dist/intent-engine/regression.js +166 -0
  48. package/dist/intent-engine/regression.js.map +1 -0
  49. package/dist/intent-engine/requirements.d.ts +22 -0
  50. package/dist/intent-engine/requirements.d.ts.map +1 -0
  51. package/dist/intent-engine/requirements.js +147 -0
  52. package/dist/intent-engine/requirements.js.map +1 -0
  53. package/dist/intent-engine/state.d.ts +44 -0
  54. package/dist/intent-engine/state.d.ts.map +1 -0
  55. package/dist/intent-engine/state.js +83 -0
  56. package/dist/intent-engine/state.js.map +1 -0
  57. package/dist/utils/ai-debt-budget.d.ts +3 -2
  58. package/dist/utils/ai-debt-budget.d.ts.map +1 -1
  59. package/dist/utils/ai-debt-budget.js +83 -2
  60. package/dist/utils/ai-debt-budget.js.map +1 -1
  61. package/package.json +1 -1
@@ -56,6 +56,7 @@ const project_root_1 = require("../utils/project-root");
56
56
  const brain_context_1 = require("../utils/brain-context");
57
57
  const scope_telemetry_1 = require("../utils/scope-telemetry");
58
58
  const plan_sync_1 = require("../utils/plan-sync");
59
+ const intent_engine_1 = require("../intent-engine");
59
60
  const policy_packs_1 = require("../utils/policy-packs");
60
61
  const custom_policy_rules_1 = require("../utils/custom-policy-rules");
61
62
  const policy_exceptions_1 = require("../utils/policy-exceptions");
@@ -952,9 +953,79 @@ function toCanonicalVerifyOutput(payload) {
952
953
  source: 'expedite',
953
954
  })),
954
955
  ]);
955
- const blockingItems = expediteModeUsed ? expediteBlockingItems : defaultBlockingItems;
956
- const advisoryItems = expediteModeUsed ? expediteItems : defaultAdvisoryItems;
956
+ // ── Intent issues and summary from engine ───────────────────────────────
957
+ const rawIntentIssues = Array.isArray(payload.intentIssues) ? payload.intentIssues : [];
958
+ const intentDomains = Array.isArray(payload.intentDomains) ? payload.intentDomains : [];
959
+ const intentSummary = (payload.intentSummary ?? null);
960
+ const rawFlowIssues = Array.isArray(payload.flowIssues) ? payload.flowIssues : [];
961
+ const rawRegressions = Array.isArray(payload.regressions) ? payload.regressions : [];
962
+ // High-severity intent issues become blocking; medium become advisory.
963
+ const intentBlockingTriageItems = rawIntentIssues
964
+ .filter((i) => i.severity === 'high')
965
+ .map((i) => ({
966
+ file: (i.files?.[0]) ?? 'intent-analysis',
967
+ message: i.message,
968
+ policy: i.rule,
969
+ severity: 'high',
970
+ source: 'violation',
971
+ }));
972
+ const intentAdvisoryTriageItems = rawIntentIssues
973
+ .filter((i) => i.severity === 'medium')
974
+ .map((i) => ({
975
+ file: (i.files?.[0]) ?? 'intent-analysis',
976
+ message: i.message,
977
+ policy: i.rule,
978
+ severity: 'warning',
979
+ source: 'warning',
980
+ }));
981
+ // V5: flow issues — high → blocking, medium → advisory
982
+ const flowBlockingTriageItems = rawFlowIssues
983
+ .filter((i) => i.severity === 'high')
984
+ .map((i) => ({
985
+ file: (i.files?.[0]) ?? 'flow-analysis',
986
+ message: i.message,
987
+ policy: i.rule,
988
+ severity: 'high',
989
+ source: 'violation',
990
+ }));
991
+ const flowAdvisoryTriageItems = rawFlowIssues
992
+ .filter((i) => i.severity === 'medium')
993
+ .map((i) => ({
994
+ file: (i.files?.[0]) ?? 'flow-analysis',
995
+ message: i.message,
996
+ policy: i.rule,
997
+ severity: 'warning',
998
+ source: 'warning',
999
+ }));
1000
+ let blockingItems = expediteModeUsed ? expediteBlockingItems : defaultBlockingItems;
1001
+ let advisoryItems = expediteModeUsed ? expediteItems : defaultAdvisoryItems;
1002
+ if (intentBlockingTriageItems.length > 0) {
1003
+ blockingItems = dedupeTriageItems([...blockingItems, ...intentBlockingTriageItems]);
1004
+ }
1005
+ if (intentAdvisoryTriageItems.length > 0) {
1006
+ advisoryItems = dedupeTriageItems([...advisoryItems, ...intentAdvisoryTriageItems]);
1007
+ }
1008
+ if (flowBlockingTriageItems.length > 0) {
1009
+ blockingItems = dedupeTriageItems([...blockingItems, ...flowBlockingTriageItems]);
1010
+ }
1011
+ if (flowAdvisoryTriageItems.length > 0) {
1012
+ advisoryItems = dedupeTriageItems([...advisoryItems, ...flowAdvisoryTriageItems]);
1013
+ }
1014
+ // V6: regressions — always blocking
1015
+ const regressionBlockingTriageItems = rawRegressions.map((r) => ({
1016
+ file: 'regression-analysis',
1017
+ message: r.message,
1018
+ policy: r.rule,
1019
+ severity: 'high',
1020
+ source: 'violation',
1021
+ }));
1022
+ if (regressionBlockingTriageItems.length > 0) {
1023
+ blockingItems = dedupeTriageItems([...regressionBlockingTriageItems, ...blockingItems]);
1024
+ }
1025
+ const grade = verdict === 'PASS' ? 'A' : verdict === 'WARN' ? 'C' : 'F';
957
1026
  return {
1027
+ grade,
1028
+ score: violations.length === 0 && warnings.length === 0 && scopeIssues.length === 0 ? 100 : 0,
958
1029
  verdict,
959
1030
  summary: {
960
1031
  totalFilesChanged,
@@ -969,6 +1040,11 @@ function toCanonicalVerifyOutput(payload) {
969
1040
  advisoryCount: advisoryItems.length,
970
1041
  blockingItems,
971
1042
  advisoryItems,
1043
+ intentIssues: rawIntentIssues,
1044
+ intentDomains,
1045
+ intentSummary,
1046
+ flowIssues: rawFlowIssues,
1047
+ regressions: rawRegressions,
972
1048
  expediteModeUsed,
973
1049
  expediteCount: expediteModeUsed ? expediteItems.length : 0,
974
1050
  expediteItems: expediteModeUsed ? expediteItems : [],
@@ -1090,20 +1166,32 @@ function toAiDebtSummary(evaluation) {
1090
1166
  observed: item.observed,
1091
1167
  budget: item.budget,
1092
1168
  message: item.message,
1169
+ ...(item.files && item.files.length > 0 ? { files: item.files } : {}),
1093
1170
  })),
1094
1171
  };
1095
1172
  }
1173
+ const ARCH_VIOLATION_CODES = new Set(['db_in_ui', 'missing_validation']);
1096
1174
  function toAiDebtReportViolations(summary) {
1097
1175
  if (summary.mode === 'off' || summary.violations.length === 0) {
1098
1176
  return [];
1099
1177
  }
1100
- const severity = summary.mode === 'enforce' ? 'block' : 'warn';
1101
- return summary.violations.map((item) => ({
1102
- rule: `ai_debt:${item.code}`,
1103
- file: '.neurcode/ai-debt-budget.json',
1104
- severity,
1105
- message: item.message,
1106
- }));
1178
+ const defaultSeverity = summary.mode === 'enforce' ? 'block' : 'warn';
1179
+ const result = [];
1180
+ for (const item of summary.violations) {
1181
+ // Architectural violations are always advisory (warn) — heuristic detection, not a hard block
1182
+ const severity = ARCH_VIOLATION_CODES.has(item.code) ? 'warn' : defaultSeverity;
1183
+ const rule = ARCH_VIOLATION_CODES.has(item.code) ? item.code : `ai_debt:${item.code}`;
1184
+ const files = item.files && item.files.length > 0 ? item.files : null;
1185
+ if (files) {
1186
+ for (const file of files) {
1187
+ result.push({ rule, file, severity, message: item.message });
1188
+ }
1189
+ }
1190
+ else {
1191
+ result.push({ rule, file: '.neurcode/ai-debt-budget.json', severity, message: item.message });
1192
+ }
1193
+ }
1194
+ return result;
1107
1195
  }
1108
1196
  function parseSigningKeyRing(raw) {
1109
1197
  if (!raw || !raw.trim()) {
@@ -1902,6 +1990,14 @@ async function verifyCommand(options) {
1902
1990
  emitCanonicalVerifyJson({
1903
1991
  ...payload,
1904
1992
  expediteMode: expediteModeEnabled,
1993
+ // Intent engine results injected so every code-path gets them.
1994
+ intentIssues: payload.intentIssues ?? intentEngineIssues,
1995
+ intentDomains: payload.intentDomains ?? intentEngineDomains,
1996
+ intentSummary: payload.intentSummary ?? intentEngineSummary,
1997
+ // V5: flow issues injected alongside intent issues
1998
+ flowIssues: payload.flowIssues ?? intentEngineFlowIssues,
1999
+ // V6: regressions always injected
2000
+ regressions: payload.regressions ?? intentEngineRegressions,
1905
2001
  });
1906
2002
  };
1907
2003
  if (!isGitRepository(projectRoot)) {
@@ -2939,6 +3035,11 @@ async function verifyCommand(options) {
2939
3035
  let governanceResult = null;
2940
3036
  let planFilesForVerification = [];
2941
3037
  let intentConstraintsForVerification;
3038
+ let intentEngineIssues = [];
3039
+ let intentEngineDomains = [];
3040
+ let intentEngineSummary = null;
3041
+ let intentEngineFlowIssues = [];
3042
+ let intentEngineRegressions = [];
2942
3043
  try {
2943
3044
  // Step A: Get Modified Files (already have from diffFiles)
2944
3045
  const modifiedFiles = diffFiles.map(f => f.path);
@@ -2982,6 +3083,23 @@ async function verifyCommand(options) {
2982
3083
  }
2983
3084
  planFilesForVerification = [...new Set([...planFiles, ...localPlanExpectedFiles])];
2984
3085
  intentConstraintsForVerification = originalIntent || undefined;
3086
+ // ── Intent-Aware Engine ─────────────────────────────────────────────
3087
+ // Run once we have both diffFiles and the resolved intent text.
3088
+ // Stored in outer scope so all emitCanonicalVerifyJson call sites can
3089
+ // include the result in their payloads without repeating the computation.
3090
+ if (intentConstraintsForVerification && diffFiles.length > 0) {
3091
+ try {
3092
+ const engineResult = (0, intent_engine_1.runIntentEngine)(intentConstraintsForVerification, diffFiles, projectRoot);
3093
+ intentEngineIssues = engineResult.intentIssues;
3094
+ intentEngineDomains = engineResult.checkedDomains;
3095
+ intentEngineSummary = engineResult.intentSummary;
3096
+ intentEngineFlowIssues = engineResult.flowIssues;
3097
+ intentEngineRegressions = engineResult.regressions;
3098
+ }
3099
+ catch {
3100
+ // Non-fatal: intent engine errors must never break verification
3101
+ }
3102
+ }
2985
3103
  governanceResult = (0, governance_1.evaluateGovernance)({
2986
3104
  projectRoot,
2987
3105
  task: governanceTask,
@@ -3085,6 +3203,9 @@ async function verifyCommand(options) {
3085
3203
  mode: 'plan_enforced',
3086
3204
  policyOnly: false,
3087
3205
  aiDebt: aiDebtSummaryForScope,
3206
+ intentIssues: intentEngineIssues,
3207
+ intentDomains: intentEngineDomains,
3208
+ intentSummary: intentEngineSummary,
3088
3209
  ...(expediteModeEnabled ? { expediteMode: true } : {}),
3089
3210
  ...(governanceResult
3090
3211
  ? buildGovernancePayload(governanceResult, orgGovernanceSettings, {
@@ -3160,6 +3281,42 @@ async function verifyCommand(options) {
3160
3281
  if (governanceResult) {
3161
3282
  displayGovernanceInsights(governanceResult, { explain: options.explain });
3162
3283
  }
3284
+ // ── Intent Status in scope-violation path ──────────────────────
3285
+ if (intentEngineSummary) {
3286
+ const s = intentEngineSummary;
3287
+ const domainLabel = s.domain.charAt(0).toUpperCase() + s.domain.slice(1);
3288
+ const confColor = s.confidence === 'HIGH' ? chalk.green : s.confidence === 'MEDIUM' ? chalk.yellow : chalk.red;
3289
+ const wCovPct = s.weightedCoverage != null ? Math.round(s.weightedCoverage * 100) : s.coveragePct;
3290
+ const filled = Math.round((wCovPct / 100) * 20);
3291
+ const bar = chalk.cyan('█'.repeat(filled)) + chalk.dim('░'.repeat(20 - filled));
3292
+ const sysStatus = s.status;
3293
+ const statusLabel = sysStatus === 'CRITICAL' ? chalk.bold.red('[CRITICAL]') : sysStatus === 'AT RISK' ? chalk.bold.yellow('[AT RISK]') : chalk.bold.green('[SECURE]');
3294
+ console.log(chalk.bold('\n━━━ INTENT STATUS ━━━━━━━━━━━━━━━━━━━━━━'));
3295
+ console.log(` ${statusLabel} ${chalk.bold(`${domainLabel} Implementation:`)} ${bar} ${chalk.bold(`${wCovPct}%`)} (weighted)`);
3296
+ console.log(` Confidence: ${confColor(s.confidence)}`);
3297
+ const critMissing = s.criticalMissing ?? [];
3298
+ const otherMissing = s.missing.filter((k) => !critMissing.includes(k));
3299
+ if (critMissing.length > 0) {
3300
+ console.log(` ${chalk.bold.red('Critical missing:')}`);
3301
+ critMissing.forEach((k) => { const label = k.split('-').map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' '); console.log(chalk.red(` ✗ ${label}`)); });
3302
+ }
3303
+ if (otherMissing.length > 0) {
3304
+ console.log(` ${chalk.bold.yellow('Missing:')}`);
3305
+ otherMissing.forEach((k) => { const label = k.split('-').map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' '); console.log(chalk.yellow(` • ${label}`)); });
3306
+ }
3307
+ if (critMissing.length === 0 && otherMissing.length === 0) {
3308
+ console.log(` Missing: ${chalk.green('none — all components detected')}`);
3309
+ }
3310
+ console.log(chalk.bold('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
3311
+ }
3312
+ if (intentEngineRegressions.length > 0) {
3313
+ console.log(chalk.bold.red('\n━━━ REGRESSION ANALYSIS ━━━━━━━━━━━━━━━━━'));
3314
+ intentEngineRegressions.forEach((reg) => {
3315
+ const icon = reg.type === 'coverage-regression' ? '📉' : reg.type === 'critical-regression' ? '🔴' : reg.type === 'flow-regression' ? '⛓' : '⚠';
3316
+ console.log(` ${chalk.red('[REGRESSION]')} ${icon} ${reg.message}`);
3317
+ });
3318
+ console.log(chalk.bold.red('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
3319
+ }
3163
3320
  console.log('');
3164
3321
  await recordVerificationIfRequested(options, config, {
3165
3322
  grade: 'F',
@@ -4014,7 +4171,7 @@ async function verifyCommand(options) {
4014
4171
  message: effectiveMessage,
4015
4172
  bloatFiles: displayBloatFiles,
4016
4173
  bloatCount: displayBloatFiles.length,
4017
- }, policyViolations, expediteModeEnabled);
4174
+ }, policyViolations, expediteModeEnabled, intentEngineIssues, intentEngineSummary, intentEngineFlowIssues, intentEngineRegressions);
4018
4175
  if (governanceResult) {
4019
4176
  displayGovernanceInsights(governanceResult, { explain: options.explain });
4020
4177
  }
@@ -4544,7 +4701,7 @@ function displayChangeContractDrift(summary, options = { advisory: false }) {
4544
4701
  /**
4545
4702
  * Display verification results in a formatted report card
4546
4703
  */
4547
- function displayVerifyResults(result, policyViolations, expediteModeUsed = false) {
4704
+ function displayVerifyResults(result, policyViolations, expediteModeUsed = false, intentIssuesForDisplay = [], intentSummaryForDisplay = null, flowIssuesForDisplay = [], regressionsForDisplay = []) {
4548
4705
  // ── Header ────────────────────────────────────────────────────────────────
4549
4706
  const headerLabel = result.verdict === 'PASS'
4550
4707
  ? chalk.bold.green('\n✅ VERIFICATION PASSED')
@@ -4552,6 +4709,60 @@ function displayVerifyResults(result, policyViolations, expediteModeUsed = false
4552
4709
  ? chalk.bold.yellow('\n⚠️ VERIFICATION PASSED WITH WARNINGS')
4553
4710
  : chalk.bold.red('\n❌ VERIFICATION FAILED');
4554
4711
  console.log(headerLabel);
4712
+ // ── Intent Status block ──────────────────────────────────────────────────
4713
+ if (intentSummaryForDisplay) {
4714
+ const s = intentSummaryForDisplay;
4715
+ const domainLabel = s.domain.charAt(0).toUpperCase() + s.domain.slice(1);
4716
+ const confColor = s.confidence === 'HIGH'
4717
+ ? chalk.green
4718
+ : s.confidence === 'MEDIUM'
4719
+ ? chalk.yellow
4720
+ : chalk.red;
4721
+ // V4: weighted coverage bar
4722
+ const wCovPct = s.weightedCoverage != null
4723
+ ? Math.round(s.weightedCoverage * 100)
4724
+ : s.coveragePct;
4725
+ const barWidth = 20;
4726
+ const filled = Math.round((wCovPct / 100) * barWidth);
4727
+ const bar = chalk.cyan('█'.repeat(filled)) + chalk.dim('░'.repeat(barWidth - filled));
4728
+ // V4: system status label
4729
+ const sysStatus = s.status;
4730
+ const statusLabel = sysStatus === 'CRITICAL'
4731
+ ? chalk.bold.red('[CRITICAL]')
4732
+ : sysStatus === 'AT RISK'
4733
+ ? chalk.bold.yellow('[AT RISK]')
4734
+ : chalk.bold.green('[SECURE]');
4735
+ console.log(chalk.bold('\n━━━ INTENT STATUS ━━━━━━━━━━━━━━━━━━━━━━'));
4736
+ console.log(` ${statusLabel} ${chalk.bold(`${domainLabel} Implementation:`)} ${bar} ${chalk.bold(`${wCovPct}%`)} (weighted)`);
4737
+ console.log(` Confidence: ${confColor(s.confidence)}`);
4738
+ if (s.foundList.length > 0) {
4739
+ const foundLabels = s.foundList
4740
+ .map((k) => k.split('-').map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' '))
4741
+ .slice(0, 4);
4742
+ console.log(` Found: ${chalk.green(foundLabels.join(', '))}${s.foundList.length > 4 ? chalk.dim(` +${s.foundList.length - 4} more`) : ''}`);
4743
+ }
4744
+ // V4: show critical missing and non-critical missing separately
4745
+ const critMissing = s.criticalMissing ?? [];
4746
+ const otherMissing = s.missing.filter((k) => !critMissing.includes(k));
4747
+ if (critMissing.length > 0) {
4748
+ console.log(` ${chalk.bold.red('Critical missing:')}`);
4749
+ critMissing.forEach((k) => {
4750
+ const label = k.split('-').map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
4751
+ console.log(chalk.red(` ✗ ${label}`));
4752
+ });
4753
+ }
4754
+ if (otherMissing.length > 0) {
4755
+ console.log(` ${chalk.bold.yellow('Missing:')}`);
4756
+ otherMissing.forEach((k) => {
4757
+ const label = k.split('-').map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
4758
+ console.log(chalk.yellow(` • ${label}`));
4759
+ });
4760
+ }
4761
+ if (critMissing.length === 0 && otherMissing.length === 0) {
4762
+ console.log(` Missing: ${chalk.green('none — all components detected')}`);
4763
+ }
4764
+ console.log(chalk.bold('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
4765
+ }
4555
4766
  // ── Triage items ──────────────────────────────────────────────────────────
4556
4767
  const maxBlockingItems = 20;
4557
4768
  const maxAdvisoryItems = 8;
@@ -4667,11 +4878,51 @@ function displayVerifyResults(result, policyViolations, expediteModeUsed = false
4667
4878
  });
4668
4879
  console.log(chalk.dim(' Note: Expedite Mode used'));
4669
4880
  }
4670
- if (blockingItems.length === 0 && advisoryItems.length === 0 && expediteItems.length === 0) {
4881
+ // ── Intent issues ─────────────────────────────────────────────────────────
4882
+ if (intentIssuesForDisplay.length > 0) {
4883
+ console.log(chalk.magenta(`\nINTENT ISSUES (${intentIssuesForDisplay.length})`));
4884
+ intentIssuesForDisplay.forEach((issue) => {
4885
+ const label = issue.severity === 'high' ? chalk.red('[HIGH]') : chalk.yellow('[MEDIUM]');
4886
+ const typeLabel = issue.type === 'missing' ? 'Missing' : issue.type === 'misplaced' ? 'Misplaced' : 'Partial';
4887
+ console.log(` ${label} ${typeLabel}: ${issue.message}`);
4888
+ });
4889
+ }
4890
+ // ── Flow Validation ───────────────────────────────────────────────────────
4891
+ if (flowIssuesForDisplay.length > 0) {
4892
+ console.log(chalk.bold('\n━━━ FLOW VALIDATION ━━━━━━━━━━━━━━━━━━━━━'));
4893
+ flowIssuesForDisplay.forEach((issue) => {
4894
+ const label = issue.severity === 'high' ? chalk.red('[HIGH]') : chalk.yellow('[MEDIUM]');
4895
+ const typeIcon = issue.type === 'missing-flow' ? '⛓' : issue.type === 'misplaced-flow' ? '⚠' : '⊘';
4896
+ console.log(` ${label} ${typeIcon} ${issue.message}`);
4897
+ if (issue.files && issue.files.length > 0) {
4898
+ const display = issue.files.slice(0, 3);
4899
+ console.log(chalk.dim(` → ${display.join(', ')}${issue.files.length > 3 ? ` +${issue.files.length - 3} more` : ''}`));
4900
+ }
4901
+ });
4902
+ console.log(chalk.bold('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
4903
+ }
4904
+ // ── Regression Analysis ───────────────────────────────────────────────────
4905
+ if (regressionsForDisplay.length > 0) {
4906
+ console.log(chalk.bold.red('\n━━━ REGRESSION ANALYSIS ━━━━━━━━━━━━━━━━━'));
4907
+ regressionsForDisplay.forEach((reg) => {
4908
+ const icon = reg.type === 'coverage-regression' ? '📉' :
4909
+ reg.type === 'critical-regression' ? '🔴' :
4910
+ reg.type === 'flow-regression' ? '⛓' : '⚠';
4911
+ console.log(` ${chalk.red('[REGRESSION]')} ${icon} ${reg.message}`);
4912
+ });
4913
+ console.log(chalk.bold.red('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
4914
+ }
4915
+ const hasAnyIssue = blockingItems.length > 0 ||
4916
+ advisoryItems.length > 0 ||
4917
+ expediteItems.length > 0 ||
4918
+ intentIssuesForDisplay.length > 0 ||
4919
+ flowIssuesForDisplay.length > 0 ||
4920
+ regressionsForDisplay.length > 0;
4921
+ if (!hasAnyIssue) {
4671
4922
  console.log(chalk.green('\nNo issues detected.'));
4672
4923
  }
4673
4924
  // ── Next step ─────────────────────────────────────────────────────────────
4674
- if (blockingItems.length > 0 || advisoryItems.length > 0 || expediteItems.length > 0) {
4925
+ if (hasAnyIssue) {
4675
4926
  console.log(chalk.bold('\nNext step:'));
4676
4927
  console.log(` ${chalk.cyan('neurcode fix')}`);
4677
4928
  console.log(chalk.dim(' or: neurcode fix --apply-safe (auto-apply high-confidence patches)'));