pumuki 6.3.129 → 6.3.130

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 (77) hide show
  1. package/AGENTS.md +16 -1
  2. package/CHANGELOG.md +9 -0
  3. package/README.md +14 -10
  4. package/VERSION +1 -1
  5. package/core/facts/detectors/text/android.test.ts +2583 -24
  6. package/core/facts/detectors/text/android.ts +4633 -34
  7. package/core/facts/detectors/typescript/index.test.ts +3639 -73
  8. package/core/facts/detectors/typescript/index.ts +4819 -270
  9. package/core/facts/extractHeuristicFacts.ts +271 -6
  10. package/core/rules/presets/heuristics/android.test.ts +314 -1
  11. package/core/rules/presets/heuristics/android.ts +1220 -50
  12. package/core/rules/presets/heuristics/typescript.test.ts +158 -2
  13. package/core/rules/presets/heuristics/typescript.ts +508 -0
  14. package/docs/README.md +3 -3
  15. package/docs/operations/RELEASE_NOTES.md +7 -1
  16. package/docs/operations/framework-menu-consumer-walkthrough.md +18 -15
  17. package/docs/product/API_REFERENCE.md +1 -1
  18. package/docs/product/USAGE.md +1 -1
  19. package/docs/validation/README.md +3 -1
  20. package/integrations/config/skillsCompilerTemplates.test.ts +131 -0
  21. package/integrations/config/skillsCompilerTemplates.ts +953 -7
  22. package/integrations/config/skillsDetectorRegistry.ts +451 -8
  23. package/integrations/config/skillsMarkdownRules.ts +884 -2
  24. package/integrations/evidence/buildEvidence.ts +29 -1
  25. package/integrations/evidence/platformSummary.test.ts +73 -9
  26. package/integrations/evidence/platformSummary.ts +165 -7
  27. package/integrations/evidence/repoState.ts +3 -0
  28. package/integrations/evidence/schema.ts +18 -0
  29. package/integrations/evidence/trackingContract.ts +17 -0
  30. package/integrations/evidence/writeEvidence.test.ts +3 -0
  31. package/integrations/evidence/writeEvidence.ts +29 -1
  32. package/integrations/gate/evaluateAiGate.ts +251 -8
  33. package/integrations/gate/governanceActionCatalog.ts +275 -0
  34. package/integrations/gate/remediationCatalog.ts +8 -0
  35. package/integrations/git/runPlatformGate.ts +9 -1
  36. package/integrations/lifecycle/adapter.ts +24 -0
  37. package/integrations/lifecycle/bootstrapManifest.ts +248 -0
  38. package/integrations/lifecycle/cliGovernanceConsole.ts +69 -0
  39. package/integrations/lifecycle/governanceNextAction.ts +171 -0
  40. package/integrations/lifecycle/governanceObservationSnapshot.ts +369 -0
  41. package/integrations/lifecycle/packageInfo.ts +118 -1
  42. package/integrations/lifecycle/state.ts +8 -1
  43. package/integrations/lifecycle/trackingState.ts +403 -0
  44. package/integrations/lifecycle/watch.ts +1 -1
  45. package/integrations/mcp/aiGateCheck.ts +194 -10
  46. package/integrations/mcp/alignedPlatformGate.ts +232 -0
  47. package/integrations/mcp/enterpriseServer.ts +19 -3
  48. package/integrations/mcp/preFlightCheck.ts +66 -3
  49. package/integrations/mcp/readMcpPrePushStdin.ts +7 -0
  50. package/package.json +1 -1
  51. package/scripts/build-ruralgo-s1-evidence-pack.ts +85 -0
  52. package/scripts/check-tracking-single-active.sh +1 -1
  53. package/scripts/framework-menu-advanced-view-lib.ts +49 -0
  54. package/scripts/framework-menu-consumer-actions-lib.ts +32 -32
  55. package/scripts/framework-menu-consumer-preflight-render.ts +10 -0
  56. package/scripts/framework-menu-consumer-preflight-run.ts +23 -0
  57. package/scripts/framework-menu-consumer-preflight-types.ts +12 -0
  58. package/scripts/framework-menu-consumer-runtime-actions.ts +11 -5
  59. package/scripts/framework-menu-consumer-runtime-audit.ts +0 -28
  60. package/scripts/framework-menu-consumer-runtime-evidence-classic.ts +118 -42
  61. package/scripts/framework-menu-consumer-runtime-lib.ts +38 -0
  62. package/scripts/framework-menu-consumer-runtime-menu.ts +55 -15
  63. package/scripts/framework-menu-consumer-runtime-types.ts +4 -0
  64. package/scripts/framework-menu-evidence-summary-read.ts +17 -1
  65. package/scripts/framework-menu-evidence-summary-types.ts +3 -0
  66. package/scripts/framework-menu-layout-data.ts +3 -23
  67. package/scripts/framework-menu-system-notifications-macos-applescript-dialog.ts +1 -1
  68. package/scripts/framework-menu-system-notifications-macos-dialog-payload.ts +14 -2
  69. package/scripts/framework-menu-system-notifications-macos-swift-source.ts +1 -1
  70. package/scripts/framework-menu-system-notifications-payloads-blocked.ts +128 -4
  71. package/scripts/framework-menu-system-notifications-payloads.ts +8 -1
  72. package/scripts/framework-menu-system-notifications-text.ts +7 -1
  73. package/scripts/framework-menu.ts +37 -2
  74. package/scripts/package-install-smoke-consumer-git-repo-lib.ts +10 -1
  75. package/scripts/package-install-smoke-consumer-npm-lib.ts +46 -9
  76. package/scripts/ruralgo-s1-evidence-pack-lib.ts +200 -0
  77. package/skills.lock.json +613 -698
@@ -26,73 +26,73 @@ export const createConsumerLegacyMenuActions = (
26
26
  return [
27
27
  {
28
28
  id: '1',
29
- label: 'Consumer preflight + gate: ALL tracked files (PRE_COMMIT · writes evidence)',
29
+ label: 'Full audit (repo analysis)',
30
30
  execute: params.runFullAudit,
31
31
  },
32
32
  {
33
33
  id: '2',
34
- label: 'Consumer preflight + gate: REPO+index contract (PRE_PUSH · disk skip risk if evidence tracked)',
34
+ label: 'Strict REPO+STAGING (CI/CD)',
35
35
  execute: params.runStrictRepoAndStaged,
36
36
  },
37
37
  {
38
38
  id: '3',
39
- label: 'Consumer preflight + gate: STAGED only (PRE_COMMIT)',
39
+ label: 'Strict STAGING only (dev)',
40
40
  execute: params.runStrictStagedOnly,
41
41
  },
42
42
  {
43
43
  id: '4',
44
- label: 'Consumer preflight + gate: working tree (PRE_PUSH policy · disk skip risk if evidence tracked)',
44
+ label: 'Standard CRITICAL/HIGH',
45
45
  execute: params.runStandardCriticalHigh,
46
46
  },
47
- {
48
- id: '11',
49
- label: 'Engine audit · STAGED only (no preflight · PRE_COMMIT)',
50
- execute: params.runEngineStagedNoPreflight,
51
- },
52
- {
53
- id: '12',
54
- label: 'Engine audit · UNSTAGED only (no preflight · PRE_COMMIT)',
55
- execute: params.runEngineUnstagedNoPreflight,
56
- },
57
- {
58
- id: '13',
59
- label: 'Engine audit · STAGED + UNSTAGED (no preflight · PRE_COMMIT)',
60
- execute: params.runEngineStagedAndUnstagedNoPreflight,
61
- },
62
- {
63
- id: '14',
64
- label: 'Engine audit · tracked repo files (AUTO runtime rules · PRE_COMMIT)',
65
- execute: params.runEngineFullRepoNoPreflight,
66
- },
67
47
  {
68
48
  id: '5',
69
- label: 'Legacy read-only pattern checks snapshot',
49
+ label: 'Pattern checks',
70
50
  execute: params.runPatternChecks,
71
51
  },
72
52
  {
73
53
  id: '6',
74
- label: 'Legacy read-only ESLint evidence snapshot',
54
+ label: 'ESLint Admin+Web',
75
55
  execute: params.runEslintAudit,
76
56
  },
77
57
  {
78
58
  id: '7',
79
- label: 'Legacy read-only AST snapshot',
59
+ label: 'AST Intelligence',
80
60
  execute: params.runAstIntelligence,
81
61
  },
82
62
  {
83
63
  id: '8',
84
- label: 'Export legacy read-only evidence snapshot',
64
+ label: 'Export Markdown',
85
65
  execute: params.runExportMarkdown,
86
66
  },
87
67
  {
88
68
  id: '9',
89
- label: 'Legacy read-only file diagnostics snapshot',
90
- execute: params.runFileDiagnostics,
69
+ label: 'Exit',
70
+ execute: async () => {},
91
71
  },
92
72
  {
93
73
  id: '10',
94
- label: 'Exit',
95
- execute: async () => {},
74
+ label: 'File diagnostics (top violated files)',
75
+ execute: params.runFileDiagnostics,
76
+ },
77
+ {
78
+ id: '11',
79
+ label: 'Engine audit · STAGED only (no preflight · PRE_COMMIT)',
80
+ execute: params.runEngineStagedNoPreflight,
81
+ },
82
+ {
83
+ id: '12',
84
+ label: 'Engine audit · UNSTAGED only (no preflight · PRE_COMMIT)',
85
+ execute: params.runEngineUnstagedNoPreflight,
86
+ },
87
+ {
88
+ id: '13',
89
+ label: 'Engine audit · STAGED + UNSTAGED (no preflight · PRE_COMMIT)',
90
+ execute: params.runEngineStagedAndUnstagedNoPreflight,
91
+ },
92
+ {
93
+ id: '14',
94
+ label: 'Engine audit · tracked repo files (AUTO runtime rules · PRE_COMMIT)',
95
+ execute: params.runEngineFullRepoNoPreflight,
96
96
  },
97
97
  ];
98
98
  };
@@ -1,5 +1,6 @@
1
1
  import { renderLegacyPanel, resolveLegacyPanelOuterWidth } from './framework-menu-legacy-audit-lib';
2
2
  import { buildConsumerPreflightBlockingCauseLines } from './framework-menu-consumer-preflight-hints';
3
+ import { buildGovernanceConsoleSummaryLines } from '../integrations/lifecycle/cliGovernanceConsole';
3
4
  import type {
4
5
  ConsumerPreflightRenderOptions,
5
6
  ConsumerPreflightResult,
@@ -19,6 +20,15 @@ const buildConsumerPreflightPanelLines = (
19
20
  `Evidence source: source=${evidence.source.source} path=${evidence.source.path} digest=${evidence.source.digest ?? 'null'} generated_at=${evidence.source.generated_at ?? 'null'}`,
20
21
  `Gate: ${preflight.status} (${preflight.result.violations.length} violations)`,
21
22
  ];
23
+ lines.push(
24
+ '',
25
+ ...buildGovernanceConsoleSummaryLines({
26
+ governanceObservation: preflight.governanceObservation,
27
+ governanceNextAction: preflight.governanceNextAction,
28
+ policyValidation: preflight.policyValidation,
29
+ experimentalFeatures: preflight.experimentalFeatures,
30
+ })
31
+ );
22
32
  lines.push(...buildConsumerPreflightBlockingCauseLines(preflight));
23
33
 
24
34
  if (preflight.hints.length > 0) {
@@ -2,6 +2,11 @@ import {
2
2
  evaluateAiGate,
3
3
  type AiGateCheckResult,
4
4
  } from '../integrations/gate/evaluateAiGate';
5
+ import { readLifecycleExperimentalFeaturesSnapshot } from '../integrations/lifecycle/experimentalFeaturesSnapshot';
6
+ import { LifecycleGitService } from '../integrations/lifecycle/gitService';
7
+ import { readGovernanceObservationSnapshot } from '../integrations/lifecycle/governanceObservationSnapshot';
8
+ import { readGovernanceNextAction } from '../integrations/lifecycle/governanceNextAction';
9
+ import { readLifecyclePolicyValidationSnapshot } from '../integrations/lifecycle/policyValidationSnapshot';
5
10
  import {
6
11
  emitSystemNotification,
7
12
  type PumukiCriticalNotificationEvent,
@@ -28,6 +33,7 @@ const defaultDependencies: ConsumerPreflightDependencies = {
28
33
  event: params.event,
29
34
  repoRoot: params.repoRoot,
30
35
  }),
36
+ readGovernanceNextAction,
31
37
  };
32
38
 
33
39
  const buildNotificationEvents = (
@@ -86,6 +92,19 @@ export const runConsumerPreflight = (
86
92
  repoRoot,
87
93
  stage: params.stage,
88
94
  });
95
+ const experimentalFeatures = readLifecycleExperimentalFeaturesSnapshot();
96
+ const policyValidation = readLifecyclePolicyValidationSnapshot(repoRoot);
97
+ const governanceObservation = readGovernanceObservationSnapshot({
98
+ repoRoot,
99
+ experimentalFeatures,
100
+ policyValidation,
101
+ git: new LifecycleGitService(),
102
+ });
103
+ const governanceNextAction = activeDependencies.readGovernanceNextAction({
104
+ repoRoot,
105
+ stage: params.stage,
106
+ governanceObservation,
107
+ });
89
108
  const hints = buildConsumerPreflightHints(result, params.stage);
90
109
  const notificationEvents = buildNotificationEvents(result);
91
110
  const notificationResults = notificationEvents.map((event) =>
@@ -99,6 +118,10 @@ export const runConsumerPreflight = (
99
118
  stage: params.stage,
100
119
  status: result.status,
101
120
  result,
121
+ governanceObservation,
122
+ governanceNextAction,
123
+ policyValidation,
124
+ experimentalFeatures,
102
125
  hints,
103
126
  notificationResults,
104
127
  };
@@ -2,6 +2,13 @@ import type {
2
2
  AiGateCheckResult,
3
3
  AiGateViolation,
4
4
  } from '../integrations/gate/evaluateAiGate';
5
+ import type {
6
+ GovernanceNextActionReader,
7
+ GovernanceNextActionSummary,
8
+ } from '../integrations/lifecycle/governanceNextAction';
9
+ import type { GovernanceObservationSnapshot } from '../integrations/lifecycle/governanceObservationSnapshot';
10
+ import type { LifecycleExperimentalFeaturesSnapshot } from '../integrations/lifecycle/experimentalFeaturesSnapshot';
11
+ import type { LifecyclePolicyValidationSnapshot } from '../integrations/lifecycle/policyValidationSnapshot';
5
12
  import type {
6
13
  PumukiCriticalNotificationEvent,
7
14
  SystemNotificationEmitResult,
@@ -13,6 +20,10 @@ export type ConsumerPreflightResult = {
13
20
  stage: ConsumerPreflightStage;
14
21
  status: AiGateCheckResult['status'];
15
22
  result: AiGateCheckResult;
23
+ governanceObservation: GovernanceObservationSnapshot;
24
+ governanceNextAction: GovernanceNextActionSummary;
25
+ policyValidation: LifecyclePolicyValidationSnapshot;
26
+ experimentalFeatures: LifecycleExperimentalFeaturesSnapshot;
16
27
  hints: ReadonlyArray<string>;
17
28
  notificationResults: ReadonlyArray<SystemNotificationEmitResult>;
18
29
  };
@@ -26,6 +37,7 @@ export type ConsumerPreflightDependencies = {
26
37
  event: PumukiCriticalNotificationEvent;
27
38
  repoRoot: string;
28
39
  }) => SystemNotificationEmitResult;
40
+ readGovernanceNextAction: GovernanceNextActionReader;
29
41
  };
30
42
 
31
43
  export type ConsumerPreflightRenderOptions = {
@@ -12,6 +12,7 @@ import {
12
12
  renderConsumerRuntimePatternChecks,
13
13
  renderConsumerRuntimeSummary,
14
14
  } from './framework-menu-consumer-runtime-audit';
15
+ import type { ConsumerPreflightResult } from './framework-menu-consumer-preflight-types';
15
16
  import type { ConsumerAction, ConsumerRuntimeEmitNotification, ConsumerRuntimeWrite } from './framework-menu-consumer-runtime-types';
16
17
 
17
18
  type ConsumerRuntimeActionDependencies = {
@@ -33,17 +34,20 @@ type ConsumerRuntimeActionDependencies = {
33
34
  setSummaryOverride: (
34
35
  summary: import('./framework-menu-evidence-summary-lib').FrameworkMenuEvidenceSummary | null
35
36
  ) => void;
37
+ clearLastPreflight: () => void;
38
+ setLastPreflight: (result: ConsumerPreflightResult | null) => void;
36
39
  };
37
40
 
38
41
  const runConsumerRuntimePreflight = async (
39
42
  dependencies: Pick<
40
43
  ConsumerRuntimeActionDependencies,
41
- 'repoRoot' | 'runPreflight' | 'useColor' | 'write'
44
+ 'repoRoot' | 'runPreflight' | 'useColor' | 'write' | 'setLastPreflight'
42
45
  >,
43
46
  stage: 'PRE_COMMIT' | 'PRE_PUSH'
44
47
  ): Promise<void> => {
45
48
  if (dependencies.runPreflight) {
46
49
  const rendered = await dependencies.runPreflight(stage);
50
+ dependencies.setLastPreflight(null);
47
51
  if (typeof rendered === 'string' && rendered.trim().length > 0) {
48
52
  dependencies.write(`\n${rendered}\n`);
49
53
  }
@@ -54,6 +58,7 @@ const runConsumerRuntimePreflight = async (
54
58
  stage,
55
59
  repoRoot: dependencies.repoRoot,
56
60
  });
61
+ dependencies.setLastPreflight(preflight);
57
62
  dependencies.write(
58
63
  `\n${formatConsumerPreflight(preflight, {
59
64
  color: dependencies.useColor(),
@@ -66,7 +71,6 @@ export const createConsumerRuntimeActions = (
66
71
  ): ReadonlyArray<ConsumerAction> =>
67
72
  createConsumerLegacyMenuActions({
68
73
  runFullAudit: async () => {
69
- await runConsumerRuntimePreflight(dependencies, 'PRE_COMMIT');
70
74
  await dependencies.runRepoGate();
71
75
  dependencies.clearSummaryOverride();
72
76
  notifyConsumerRuntimeAuditSummary(
@@ -82,7 +86,6 @@ export const createConsumerRuntimeActions = (
82
86
  );
83
87
  },
84
88
  runStrictRepoAndStaged: async () => {
85
- await runConsumerRuntimePreflight(dependencies, 'PRE_PUSH');
86
89
  const gateResult = await dependencies.runRepoAndStagedGate();
87
90
  if (gateResult?.blocked) {
88
91
  dependencies.setSummaryOverride(
@@ -112,7 +115,6 @@ export const createConsumerRuntimeActions = (
112
115
  }
113
116
  },
114
117
  runStrictStagedOnly: async () => {
115
- await runConsumerRuntimePreflight(dependencies, 'PRE_COMMIT');
116
118
  await dependencies.runStagedGate();
117
119
  dependencies.clearSummaryOverride();
118
120
  const summary = renderConsumerRuntimeSummary({
@@ -130,7 +132,6 @@ export const createConsumerRuntimeActions = (
130
132
  printConsumerRuntimeEmptyScopeHint({ write: dependencies.write }, summary, 'staged');
131
133
  },
132
134
  runStandardCriticalHigh: async () => {
133
- await runConsumerRuntimePreflight(dependencies, 'PRE_PUSH');
134
135
  await dependencies.runWorkingTreeGate();
135
136
  dependencies.clearSummaryOverride();
136
137
  const summary = renderConsumerRuntimeSummary({
@@ -218,15 +219,19 @@ export const createConsumerRuntimeActions = (
218
219
  );
219
220
  },
220
221
  runPatternChecks: async () => {
222
+ dependencies.clearLastPreflight();
221
223
  dependencies.write(`\n${renderConsumerRuntimePatternChecks(dependencies.repoRoot)}\n`);
222
224
  },
223
225
  runEslintAudit: async () => {
226
+ dependencies.clearLastPreflight();
224
227
  dependencies.write(`\n${renderConsumerRuntimeEslintAudit(dependencies.repoRoot)}\n`);
225
228
  },
226
229
  runAstIntelligence: async () => {
230
+ dependencies.clearLastPreflight();
227
231
  dependencies.write(`\n${renderConsumerRuntimeAstBreakdown(dependencies.repoRoot)}\n`);
228
232
  },
229
233
  runExportMarkdown: async () => {
234
+ dependencies.clearLastPreflight();
230
235
  const filePath = exportConsumerRuntimeMarkdown(
231
236
  dependencies.repoRoot,
232
237
  dependencies.getSummaryOverride()
@@ -234,6 +239,7 @@ export const createConsumerRuntimeActions = (
234
239
  dependencies.write(`\nLegacy read-only markdown exported: ${filePath}\n`);
235
240
  },
236
241
  runFileDiagnostics: async () => {
242
+ dependencies.clearLastPreflight();
237
243
  dependencies.write(`\n${renderConsumerRuntimeFileDiagnostics(dependencies.repoRoot)}\n`);
238
244
  },
239
245
  }) as ReadonlyArray<ConsumerAction>;
@@ -6,11 +6,8 @@ import {
6
6
  formatLegacyFileDiagnostics,
7
7
  formatLegacyPatternChecks,
8
8
  readLegacyAuditSummary,
9
- renderLegacyPanel,
10
- resolveLegacyPanelOuterWidth,
11
9
  } from './framework-menu-legacy-audit-lib';
12
10
  import {
13
- formatEvidenceSummaryForMenu,
14
11
  readEvidenceSummaryForMenu,
15
12
  type FrameworkMenuEvidenceSummary,
16
13
  } from './framework-menu-evidence-summary-lib';
@@ -33,31 +30,6 @@ export const renderConsumerRuntimeSummary = (
33
30
  dependencies: ConsumerRuntimeSummaryDependencies
34
31
  ): FrameworkMenuEvidenceSummary => {
35
32
  const summary = dependencies.summaryOverride ?? readEvidenceSummaryForMenu(dependencies.repoRoot);
36
- const lines = [
37
- formatEvidenceSummaryForMenu(summary),
38
- '',
39
- 'Consumer runtime snapshot',
40
- `Files scanned: ${summary.filesScanned}`,
41
- `Files affected: ${summary.filesAffected}`,
42
- ];
43
-
44
- if (summary.status === 'ok' && summary.topFindings.length > 0) {
45
- const primaryFinding = summary.topFindings[0];
46
- lines.push('', `Primary block: ${primaryFinding.ruleId}`);
47
- }
48
-
49
- if (summary.topFiles.length > 0) {
50
- lines.push(
51
- 'Top files',
52
- ...summary.topFiles.map((entry) => `- ${entry.file} (${entry.count})`)
53
- );
54
- }
55
-
56
- dependencies.write(`\n${renderLegacyPanel(lines, {
57
- width: resolveLegacyPanelOuterWidth(),
58
- color: dependencies.useColor(),
59
- })}\n`);
60
-
61
33
  const vintageSource =
62
34
  summary.status === 'ok' && !dependencies.summaryOverride
63
35
  ? readEvidenceSummaryForMenu(dependencies.repoRoot, {
@@ -1,6 +1,10 @@
1
1
  import type { EnterpriseEvidenceSeverity } from './framework-menu-evidence-summary-types';
2
2
  import type { FrameworkMenuEvidenceSummary } from './framework-menu-evidence-summary-lib';
3
- import { renderLegacyPanel, resolveLegacyPanelOuterWidth } from './framework-menu-legacy-audit-lib';
3
+ import {
4
+ readLegacyAuditSummary,
5
+ renderLegacyPanel,
6
+ resolveLegacyPanelOuterWidth,
7
+ } from './framework-menu-legacy-audit-lib';
4
8
  import { applyCliPalette, buildCliDesignTokens } from './framework-menu-ui-components-lib';
5
9
  import type { CliPaletteRole } from './framework-menu-ui-components-types';
6
10
 
@@ -17,20 +21,6 @@ const enterpriseSeverityToRole = (severity: EnterpriseEvidenceSeverity): CliPale
17
21
  return 'low';
18
22
  };
19
23
 
20
- const outcomeToRole = (outcome: string | null): CliPaletteRole => {
21
- const normalized = (outcome ?? '').trim().toUpperCase();
22
- if (normalized === 'BLOCK' || normalized === 'BLOCKED') {
23
- return 'critical';
24
- }
25
- if (normalized === 'WARN') {
26
- return 'statusWarning';
27
- }
28
- if (normalized === 'PASS' || normalized === 'ALLOW' || normalized === 'ALLOWED') {
29
- return 'goal';
30
- }
31
- return 'sectionTitle';
32
- };
33
-
34
24
  export const formatVintageEvidenceReportLines = (
35
25
  summary: FrameworkMenuEvidenceSummary,
36
26
  tokens: ReturnType<typeof buildCliDesignTokens>
@@ -54,54 +44,108 @@ export const formatVintageEvidenceReportLines = (
54
44
  MEDIUM: summary.bySeverity.WARN,
55
45
  LOW: summary.bySeverity.INFO,
56
46
  };
47
+ const total = Math.max(0, summary.totalFindings);
48
+ const scanned = Math.max(0, summary.filesScanned);
49
+ const healthPenalty = scanned > 0
50
+ ? Math.min(100, Math.round((total * 100) / Math.max(1, scanned)))
51
+ : 0;
52
+ const healthScore = Math.max(
53
+ 0,
54
+ Math.min(
55
+ 100,
56
+ 100
57
+ - healthPenalty
58
+ - (ent.CRITICAL > 0 ? 10 : 0)
59
+ - (ent.HIGH > 50 ? 10 : 0)
60
+ - (summary.bySeverity.ERROR > 0 ? 5 : 0)
61
+ )
62
+ );
63
+ const healthLabel = healthScore >= 80
64
+ ? 'Excellent'
65
+ : healthScore >= 60
66
+ ? 'Good'
67
+ : healthScore >= 40
68
+ ? 'Needs Improvement'
69
+ : 'Critical';
70
+ const legacy = readLegacyAuditSummary(process.cwd());
71
+ const patterns = legacy.status === 'ok'
72
+ ? legacy.patternChecks
73
+ : { todoFixme: 0, consoleLog: 0, anyType: 0, sqlRaw: 0 };
57
74
 
58
75
  const lines: string[] = [
59
- applyCliPalette('PUMUKIClassic evidence view (severities + platforms)', 'title', tokens),
76
+ applyCliPalette('Advanced Project Audit AST Intelligence & Quality Gate', 'title', tokens),
77
+ '',
78
+ applyCliPalette('═══════════════════════════════════════════════════════════════', 'title', tokens),
79
+ applyCliPalette('Summary', 'title', tokens),
80
+ applyCliPalette('═══════════════════════════════════════════════════════════════', 'title', tokens),
81
+ '',
82
+ applyCliPalette('QUICK SUMMARY', 'sectionTitle', tokens),
83
+ ` Files Scanned: ${summary.filesScanned}`,
84
+ ` Total Violations: ${summary.totalFindings}`,
85
+ ` ESLint Errors: ${summary.bySeverity.ERROR}`,
86
+ ` Critical Issues: ${ent.CRITICAL}`,
87
+ ` High Priority: ${ent.HIGH}`,
60
88
  '',
61
- `${applyCliPalette('Stage', 'sectionTitle', tokens)}: ${summary.stage ?? 'unknown'} ${applyCliPalette('Outcome', 'sectionTitle', tokens)}: ${applyCliPalette(String(summary.outcome ?? 'unknown'), outcomeToRole(summary.outcome), tokens)}`,
62
- `${applyCliPalette('Findings', 'sectionTitle', tokens)}: ${summary.totalFindings} ${applyCliPalette('Scanned', 'muted', tokens)}: ${summary.filesScanned} ${applyCliPalette('Affected', 'muted', tokens)}: ${summary.filesAffected}`,
89
+ ent.CRITICAL > 0 || ent.HIGH > 0 || summary.bySeverity.ERROR > 0
90
+ ? applyCliPalette(' STATUS: ACTION REQUIRED', 'critical', tokens)
91
+ : applyCliPalette(' STATUS: ALL CLEAR', 'goal', tokens),
63
92
  '',
64
- applyCliPalette('Enterprise severities', 'sectionTitle', tokens),
93
+ applyCliPalette('1. PATTERN CHECKS', 'sectionTitle', tokens),
94
+ '─────────────────────────────────────────────────────────────',
95
+ ` TODO_FIXME: ${patterns.todoFixme}`,
96
+ ` CONSOLE_LOG: ${patterns.consoleLog}`,
97
+ ` ANY_TYPE: ${patterns.anyType}`,
98
+ ` SQL_RAW: ${patterns.sqlRaw}`,
99
+ '',
100
+ applyCliPalette('2. ESLINT AUDIT RESULTS', 'sectionTitle', tokens),
101
+ '─────────────────────────────────────────────────────────────',
102
+ ` ESLint: errors=${summary.bySeverity.ERROR} warnings=${summary.bySeverity.WARN}`,
103
+ '',
104
+ applyCliPalette('3. AST INTELLIGENCE - SEVERITY BREAKDOWN (Repository)', 'sectionTitle', tokens),
105
+ '─────────────────────────────────────────────────────────────',
65
106
  ];
66
107
 
67
108
  const order: EnterpriseEvidenceSeverity[] = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW'];
68
109
  for (const band of order) {
69
110
  const count = ent[band] ?? 0;
70
- if (count === 0) {
71
- continue;
72
- }
111
+ const pct = total > 0 ? ` (${Math.round((count * 100) / total)}%)` : '';
73
112
  lines.push(
74
- ` ${applyCliPalette(`${band}:`, enterpriseSeverityToRole(band), tokens)} ${count}`
113
+ ` ${applyCliPalette(`${band}:`, enterpriseSeverityToRole(band), tokens)} ${count} violations${pct}`
75
114
  );
76
115
  }
77
116
 
78
- lines.push('', applyCliPalette('Legacy severities', 'sectionTitle', tokens));
79
- lines.push(
80
- ` ${applyCliPalette('CRITICAL', 'critical', tokens)} ${summary.bySeverity.CRITICAL} ` +
81
- `${applyCliPalette('ERROR', 'high', tokens)} ${summary.bySeverity.ERROR} ` +
82
- `${applyCliPalette('WARN', 'medium', tokens)} ${summary.bySeverity.WARN} ` +
83
- `${applyCliPalette('INFO', 'low', tokens)} ${summary.bySeverity.INFO}`
84
- );
85
-
117
+ lines.push('', applyCliPalette('4. PLATFORM-SPECIFIC ANALYSIS', 'sectionTitle', tokens));
118
+ lines.push('─────────────────────────────────────────────────────────────');
86
119
  if (summary.platformAuditRows && summary.platformAuditRows.length > 0) {
87
- lines.push('', applyCliPalette('Platforms (from evidence snapshot)', 'sectionTitle', tokens));
120
+ const hasOtherRules = summary.platformAuditRows.some((row) =>
121
+ row.platform === 'Other' && (row.violations > 0 || (row.activeRules ?? 0) > 0)
122
+ );
88
123
  for (const row of summary.platformAuditRows) {
124
+ const rulesSuffix =
125
+ typeof row.evaluatedRules === 'number' || typeof row.activeRules === 'number'
126
+ ? ` · rules evaluated=${row.evaluatedRules ?? 0}/${row.activeRules ?? 0}`
127
+ : '';
89
128
  lines.push(
90
- ` ${applyCliPalette(row.platform, 'rule', tokens)}: ${row.violations} violations`
129
+ ` ${applyCliPalette(row.platform, 'rule', tokens)}: ${row.violations} violations${rulesSuffix}`
91
130
  );
92
131
  }
93
- lines.push(
94
- applyCliPalette(
95
- 'Note: platform buckets are heuristic (path + ruleId); "Other" is not absence of iOS/Android work.',
96
- 'muted',
97
- tokens
98
- )
99
- );
132
+ if (hasOtherRules) {
133
+ lines.push(
134
+ applyCliPalette(
135
+ ' Other = cross-cutting/generic governance, evidence, BDD and shared-type rules.',
136
+ 'muted',
137
+ tokens
138
+ )
139
+ );
140
+ }
141
+ } else {
142
+ lines.push(' No platform summary available.');
100
143
  }
101
144
 
102
- lines.push('', applyCliPalette('Top violations (ranked)', 'sectionTitle', tokens));
145
+ lines.push('', applyCliPalette('5. TOP VIOLATIONS & REMEDIATION', 'sectionTitle', tokens));
146
+ lines.push('─────────────────────────────────────────────────────────────');
103
147
  if (summary.topFindings.length === 0) {
104
- lines.push(applyCliPalette(' (none)', 'goal', tokens));
148
+ lines.push(applyCliPalette(' No violations detected', 'goal', tokens));
105
149
  } else {
106
150
  for (const finding of summary.topFindings) {
107
151
  const role = enterpriseSeverityToRole(finding.severity);
@@ -114,6 +158,38 @@ export const formatVintageEvidenceReportLines = (
114
158
  }
115
159
  }
116
160
 
161
+ lines.push(
162
+ '',
163
+ applyCliPalette('6. EXECUTIVE SUMMARY', 'sectionTitle', tokens),
164
+ '─────────────────────────────────────────────────────────────',
165
+ ` Total violations detected: ${summary.totalFindings}`,
166
+ ` ESLint errors: ${summary.bySeverity.ERROR}`,
167
+ ` ESLint warnings: ${summary.bySeverity.WARN}`,
168
+ ` Critical issues: ${ent.CRITICAL}`,
169
+ ` High priority issues: ${ent.HIGH}`,
170
+ ` Files scanned: ${summary.filesScanned}`,
171
+ '',
172
+ ` Code Health Score: ${healthScore}% (${healthLabel})`,
173
+ '',
174
+ ent.CRITICAL > 0 || ent.HIGH > 0 || summary.bySeverity.ERROR > 0
175
+ ? applyCliPalette(' ACTION REQUIRED: Critical or high-severity issues detected.', 'critical', tokens)
176
+ : applyCliPalette(' No critical issues detected', 'goal', tokens),
177
+ '',
178
+ applyCliPalette('7. AUDIT METADATA', 'sectionTitle', tokens),
179
+ '─────────────────────────────────────────────────────────────',
180
+ ` Stage: ${summary.stage ?? 'unknown'}`,
181
+ ` Outcome: ${summary.outcome ?? 'unknown'}`,
182
+ ` Files scanned: ${summary.filesScanned}`,
183
+ '',
184
+ applyCliPalette('FINAL SUMMARY - VIOLATIONS BY SEVERITY', 'title', tokens),
185
+ ` CRITICAL: ${ent.CRITICAL}`,
186
+ ` HIGH: ${ent.HIGH}`,
187
+ ` MEDIUM: ${ent.MEDIUM}`,
188
+ ` LOW: ${ent.LOW}`,
189
+ '',
190
+ ` Total violations: ${summary.totalFindings}`
191
+ );
192
+
117
193
  return lines;
118
194
  };
119
195
 
@@ -5,6 +5,9 @@ import {
5
5
  resolveConsumerRuntimeUseColor,
6
6
  } from './framework-menu-consumer-runtime-audit';
7
7
  import type { FrameworkMenuEvidenceSummary } from './framework-menu-evidence-summary-lib';
8
+ import type { ConsumerPreflightResult } from './framework-menu-consumer-preflight-types';
9
+ import type { GovernanceConsoleSnapshot } from '../integrations/lifecycle/cliGovernanceConsole';
10
+ import { readLifecycleStatus } from '../integrations/lifecycle/status';
8
11
  import type {
9
12
  ConsumerAction,
10
13
  ConsumerMenuRuntime,
@@ -17,11 +20,28 @@ export type {
17
20
  ConsumerMenuRuntimeParams,
18
21
  } from './framework-menu-consumer-runtime-types';
19
22
 
23
+ const readMenuGovernanceConsoleSnapshot = (
24
+ repoRoot: string
25
+ ): GovernanceConsoleSnapshot | null => {
26
+ try {
27
+ const status = readLifecycleStatus({ cwd: repoRoot });
28
+ return {
29
+ governanceObservation: status.governanceObservation,
30
+ governanceNextAction: status.governanceNextAction,
31
+ policyValidation: status.policyValidation,
32
+ experimentalFeatures: status.experimentalFeatures,
33
+ };
34
+ } catch {
35
+ return null;
36
+ }
37
+ };
38
+
20
39
  export const createConsumerMenuRuntime = (
21
40
  params: ConsumerMenuRuntimeParams
22
41
  ): ConsumerMenuRuntime => {
23
42
  const repoRoot = process.cwd();
24
43
  let summaryOverride: FrameworkMenuEvidenceSummary | null = null;
44
+ let lastPreflight: ConsumerPreflightResult | null = null;
25
45
  const emitNotification =
26
46
  params.emitSystemNotification
27
47
  ?? ((payload: Parameters<typeof emitSystemNotification>[0]) =>
@@ -47,19 +67,37 @@ export const createConsumerMenuRuntime = (
47
67
  setSummaryOverride: (summary) => {
48
68
  summaryOverride = summary;
49
69
  },
70
+ clearLastPreflight: () => {
71
+ lastPreflight = null;
72
+ },
73
+ setLastPreflight: (result) => {
74
+ lastPreflight = result;
75
+ },
50
76
  });
51
77
 
52
78
  return {
53
79
  actions: actions as ReadonlyArray<ConsumerAction>,
54
80
  printMenu: () => {
81
+ const governanceConsole =
82
+ lastPreflight
83
+ ? {
84
+ governanceObservation: lastPreflight.governanceObservation,
85
+ governanceNextAction: lastPreflight.governanceNextAction,
86
+ policyValidation: lastPreflight.policyValidation,
87
+ experimentalFeatures: lastPreflight.experimentalFeatures,
88
+ }
89
+ : (params.readGovernanceConsole?.() ?? readMenuGovernanceConsoleSnapshot(repoRoot));
55
90
  printConsumerRuntimeMenu({
56
91
  actions,
57
92
  repoRoot,
58
93
  useColor,
59
94
  write: params.write,
95
+ preflight: lastPreflight,
96
+ governanceConsole,
60
97
  });
61
98
  },
62
99
  readCurrentSummary: () => summaryOverride,
100
+ readLastPreflight: () => lastPreflight,
63
101
  };
64
102
  };
65
103