pumuki 6.3.113 → 6.3.115

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 (99) hide show
  1. package/CHANGELOG.md +52 -5
  2. package/README.md +4 -2
  3. package/VERSION +1 -1
  4. package/core/facts/detectors/typescript/index.test.ts +0 -229
  5. package/core/facts/detectors/typescript/index.ts +0 -278
  6. package/core/facts/extractHeuristicFacts.ts +0 -4
  7. package/core/rules/presets/heuristics/typescript.test.ts +1 -21
  8. package/core/rules/presets/heuristics/typescript.ts +0 -72
  9. package/docs/README.md +13 -9
  10. package/docs/codex-skills/backend-enterprise-rules.md +3 -3
  11. package/docs/operations/RELEASE_NOTES.md +41 -4
  12. package/docs/product/API_REFERENCE.md +1 -1
  13. package/docs/product/HOW_IT_WORKS.md +6 -0
  14. package/docs/product/INSTALLATION.md +1 -1
  15. package/docs/product/USAGE.md +42 -5
  16. package/docs/tracking/plan-curso-pumuki-stack-my-architecture.md +100 -44
  17. package/docs/validation/README.md +6 -3
  18. package/integrations/config/skillsDetectorRegistry.ts +0 -24
  19. package/integrations/config/skillsMarkdownRules.ts +0 -57
  20. package/integrations/evidence/buildEvidence.ts +0 -24
  21. package/integrations/evidence/repoState.ts +9 -7
  22. package/integrations/evidence/schema.ts +0 -18
  23. package/integrations/evidence/writeEvidence.ts +0 -24
  24. package/integrations/gate/evaluateAiGate.ts +8 -251
  25. package/integrations/gate/remediationCatalog.ts +0 -8
  26. package/integrations/git/GitService.ts +44 -5
  27. package/integrations/git/aiGateRepoPolicyFindings.ts +86 -17
  28. package/integrations/git/runPlatformGate.ts +1 -9
  29. package/integrations/git/runPlatformGateFacts.ts +19 -1
  30. package/integrations/git/runPlatformGateOutput.ts +41 -42
  31. package/integrations/lifecycle/adapter.templates.json +1 -0
  32. package/integrations/lifecycle/adapter.ts +0 -24
  33. package/integrations/lifecycle/audit.ts +101 -0
  34. package/integrations/lifecycle/cli.ts +120 -99
  35. package/integrations/lifecycle/cliSdd.ts +4 -26
  36. package/integrations/lifecycle/doctor.ts +40 -102
  37. package/integrations/lifecycle/index.ts +2 -0
  38. package/integrations/lifecycle/install.ts +0 -21
  39. package/integrations/lifecycle/packageInfo.ts +1 -118
  40. package/integrations/lifecycle/state.ts +1 -8
  41. package/integrations/lifecycle/status.ts +40 -59
  42. package/integrations/lifecycle/watch.ts +1 -1
  43. package/integrations/mcp/aiGateCheck.ts +10 -194
  44. package/integrations/mcp/autoExecuteAiStart.ts +116 -92
  45. package/integrations/mcp/enterpriseServer.ts +7 -23
  46. package/integrations/mcp/enterpriseStdioServer.cli.ts +4 -31
  47. package/integrations/mcp/preFlightCheck.ts +5 -67
  48. package/integrations/platform/detectPlatforms.ts +37 -0
  49. package/integrations/sdd/policy.ts +28 -20
  50. package/package.json +1 -1
  51. package/scripts/check-tracking-single-active.sh +1 -1
  52. package/scripts/consumer-menu-matrix-baseline-report-lib.ts +13 -38
  53. package/scripts/consumer-postinstall-resolve-args.cjs +44 -0
  54. package/scripts/consumer-postinstall.cjs +76 -21
  55. package/scripts/framework-menu-advanced-view-lib.ts +0 -49
  56. package/scripts/framework-menu-consumer-actions-lib.ts +28 -4
  57. package/scripts/framework-menu-consumer-preflight-hints.ts +5 -2
  58. package/scripts/framework-menu-consumer-preflight-render.ts +0 -10
  59. package/scripts/framework-menu-consumer-preflight-run.ts +0 -23
  60. package/scripts/framework-menu-consumer-preflight-types.ts +0 -12
  61. package/scripts/framework-menu-consumer-runtime-actions.ts +87 -17
  62. package/scripts/framework-menu-consumer-runtime-audit.ts +36 -2
  63. package/scripts/framework-menu-consumer-runtime-evidence-classic.ts +140 -0
  64. package/scripts/framework-menu-consumer-runtime-lib.ts +2 -38
  65. package/scripts/framework-menu-consumer-runtime-menu.ts +4 -31
  66. package/scripts/framework-menu-consumer-runtime-types.ts +3 -5
  67. package/scripts/framework-menu-evidence-summary-lib.ts +1 -0
  68. package/scripts/framework-menu-evidence-summary-read.ts +57 -5
  69. package/scripts/framework-menu-evidence-summary-severity.ts +3 -1
  70. package/scripts/framework-menu-evidence-summary-types.ts +7 -0
  71. package/scripts/framework-menu-gate-lib.ts +9 -0
  72. package/scripts/framework-menu-layout-data.ts +5 -0
  73. package/scripts/framework-menu-matrix-baseline-lib.ts +15 -14
  74. package/scripts/framework-menu-matrix-canary-lib.ts +22 -1
  75. package/scripts/framework-menu-matrix-evidence-lib.ts +1 -0
  76. package/scripts/framework-menu-matrix-evidence-types.ts +13 -1
  77. package/scripts/framework-menu-matrix-runner-lib.ts +35 -0
  78. package/scripts/framework-menu-system-notifications-cause.ts +0 -3
  79. package/scripts/framework-menu-system-notifications-macos-swift-source.ts +24 -204
  80. package/scripts/framework-menu-system-notifications-macos.ts +4 -0
  81. package/scripts/framework-menu-system-notifications-payloads-blocked.ts +1 -1
  82. package/scripts/framework-menu-system-notifications-text.ts +1 -7
  83. package/scripts/framework-menu.ts +3 -24
  84. package/scripts/package-install-smoke-consumer-git-repo-lib.ts +1 -10
  85. package/scripts/package-install-smoke-consumer-npm-lib.ts +9 -46
  86. package/scripts/pumuki-full-surface-smoke-lib.ts +37 -0
  87. package/scripts/pumuki-full-surface-smoke.ts +346 -0
  88. package/scripts/pumuki-smoke-installed-wrapper.cjs +31 -0
  89. package/integrations/evidence/trackingContract.ts +0 -17
  90. package/integrations/gate/governanceActionCatalog.ts +0 -275
  91. package/integrations/lifecycle/bootstrapManifest.ts +0 -248
  92. package/integrations/lifecycle/cliGovernanceConsole.ts +0 -69
  93. package/integrations/lifecycle/governanceNextAction.ts +0 -171
  94. package/integrations/lifecycle/governanceObservationSnapshot.ts +0 -369
  95. package/integrations/lifecycle/trackingState.ts +0 -403
  96. package/integrations/mcp/alignedPlatformGate.ts +0 -232
  97. package/integrations/mcp/readMcpPrePushStdin.ts +0 -7
  98. package/scripts/build-ruralgo-s1-evidence-pack.ts +0 -85
  99. package/scripts/ruralgo-s1-evidence-pack-lib.ts +0 -200
@@ -9,6 +9,10 @@ export type ConsumerLegacyMenuContext = {
9
9
  runStrictRepoAndStaged: () => Promise<void>;
10
10
  runStrictStagedOnly: () => Promise<void>;
11
11
  runStandardCriticalHigh: () => Promise<void>;
12
+ runEngineStagedNoPreflight: () => Promise<void>;
13
+ runEngineUnstagedNoPreflight: () => Promise<void>;
14
+ runEngineStagedAndUnstagedNoPreflight: () => Promise<void>;
15
+ runEngineFullRepoNoPreflight: () => Promise<void>;
12
16
  runPatternChecks: () => Promise<void>;
13
17
  runEslintAudit: () => Promise<void>;
14
18
  runAstIntelligence: () => Promise<void>;
@@ -22,24 +26,44 @@ export const createConsumerLegacyMenuActions = (
22
26
  return [
23
27
  {
24
28
  id: '1',
25
- label: 'Read-only full audit (repo analysis · PRE_COMMIT)',
29
+ label: 'Consumer preflight + gate: ALL tracked files (PRE_COMMIT · writes evidence)',
26
30
  execute: params.runFullAudit,
27
31
  },
28
32
  {
29
33
  id: '2',
30
- label: 'Read-only strict REPO+STAGING (CI/CD · PRE_PUSH)',
34
+ label: 'Consumer preflight + gate: REPO+index contract (PRE_PUSH · disk skip risk if evidence tracked)',
31
35
  execute: params.runStrictRepoAndStaged,
32
36
  },
33
37
  {
34
38
  id: '3',
35
- label: 'Read-only strict STAGING only (dev · PRE_COMMIT)',
39
+ label: 'Consumer preflight + gate: STAGED only (PRE_COMMIT)',
36
40
  execute: params.runStrictStagedOnly,
37
41
  },
38
42
  {
39
43
  id: '4',
40
- label: 'Read-only audit of STAGED+UNSTAGED working tree (PRE_PUSH policy)',
44
+ label: 'Consumer preflight + gate: working tree (PRE_PUSH policy · disk skip risk if evidence tracked)',
41
45
  execute: params.runStandardCriticalHigh,
42
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 · FULL tracked repo (no preflight · PRE_COMMIT)',
65
+ execute: params.runEngineFullRepoNoPreflight,
66
+ },
43
67
  {
44
68
  id: '5',
45
69
  label: 'Legacy read-only pattern checks snapshot',
@@ -7,7 +7,8 @@ import type {
7
7
  } from './framework-menu-consumer-preflight-types';
8
8
 
9
9
  export const ACTIONABLE_HINTS_BY_CODE: Readonly<Record<string, string>> = {
10
- EVIDENCE_MISSING: 'ejecuta una auditoría (1/2/3/4) para regenerar .ai_evidence.json.',
10
+ EVIDENCE_MISSING:
11
+ 'ejecuta una auditoría (1/2/3/4 o motor 11–14) para regenerar .ai_evidence.json.',
11
12
  EVIDENCE_INVALID: 'regenera .ai_evidence.json desde una opción de auditoría.',
12
13
  EVIDENCE_STALE: 'refresca evidencia antes de continuar con commit/push.',
13
14
  EVIDENCE_TIMESTAMP_INVALID: 'regenera evidencia para obtener un timestamp válido.',
@@ -54,7 +55,9 @@ export const buildConsumerPreflightHints = (
54
55
  const actionableHintsByCode = resolveActionableHintsByCode(dependencies);
55
56
 
56
57
  if (hasViolationCode(violations, 'EVIDENCE_MISSING')) {
57
- hints.push('Evidence missing: ejecuta una auditoría (1/2/3/4) para regenerar .ai_evidence.json.');
58
+ hints.push(
59
+ 'Evidence missing: ejecuta una auditoría (1/2/3/4 o motor 11–14) para regenerar .ai_evidence.json.'
60
+ );
58
61
  handledCodes.add('EVIDENCE_MISSING');
59
62
  }
60
63
  if (hasViolationCode(violations, 'EVIDENCE_INVALID')) {
@@ -1,6 +1,5 @@
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';
4
3
  import type {
5
4
  ConsumerPreflightRenderOptions,
6
5
  ConsumerPreflightResult,
@@ -20,15 +19,6 @@ const buildConsumerPreflightPanelLines = (
20
19
  `Evidence source: source=${evidence.source.source} path=${evidence.source.path} digest=${evidence.source.digest ?? 'null'} generated_at=${evidence.source.generated_at ?? 'null'}`,
21
20
  `Gate: ${preflight.status} (${preflight.result.violations.length} violations)`,
22
21
  ];
23
- lines.push(
24
- '',
25
- ...buildGovernanceConsoleSummaryLines({
26
- governanceObservation: preflight.governanceObservation,
27
- governanceNextAction: preflight.governanceNextAction,
28
- policyValidation: preflight.policyValidation,
29
- experimentalFeatures: preflight.experimentalFeatures,
30
- })
31
- );
32
22
  lines.push(...buildConsumerPreflightBlockingCauseLines(preflight));
33
23
 
34
24
  if (preflight.hints.length > 0) {
@@ -2,11 +2,6 @@ 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';
10
5
  import {
11
6
  emitSystemNotification,
12
7
  type PumukiCriticalNotificationEvent,
@@ -33,7 +28,6 @@ const defaultDependencies: ConsumerPreflightDependencies = {
33
28
  event: params.event,
34
29
  repoRoot: params.repoRoot,
35
30
  }),
36
- readGovernanceNextAction,
37
31
  };
38
32
 
39
33
  const buildNotificationEvents = (
@@ -92,19 +86,6 @@ export const runConsumerPreflight = (
92
86
  repoRoot,
93
87
  stage: params.stage,
94
88
  });
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
- });
108
89
  const hints = buildConsumerPreflightHints(result, params.stage);
109
90
  const notificationEvents = buildNotificationEvents(result);
110
91
  const notificationResults = notificationEvents.map((event) =>
@@ -118,10 +99,6 @@ export const runConsumerPreflight = (
118
99
  stage: params.stage,
119
100
  status: result.status,
120
101
  result,
121
- governanceObservation,
122
- governanceNextAction,
123
- policyValidation,
124
- experimentalFeatures,
125
102
  hints,
126
103
  notificationResults,
127
104
  };
@@ -2,13 +2,6 @@ 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';
12
5
  import type {
13
6
  PumukiCriticalNotificationEvent,
14
7
  SystemNotificationEmitResult,
@@ -20,10 +13,6 @@ export type ConsumerPreflightResult = {
20
13
  stage: ConsumerPreflightStage;
21
14
  status: AiGateCheckResult['status'];
22
15
  result: AiGateCheckResult;
23
- governanceObservation: GovernanceObservationSnapshot;
24
- governanceNextAction: GovernanceNextActionSummary;
25
- policyValidation: LifecyclePolicyValidationSnapshot;
26
- experimentalFeatures: LifecycleExperimentalFeaturesSnapshot;
27
16
  hints: ReadonlyArray<string>;
28
17
  notificationResults: ReadonlyArray<SystemNotificationEmitResult>;
29
18
  };
@@ -37,7 +26,6 @@ export type ConsumerPreflightDependencies = {
37
26
  event: PumukiCriticalNotificationEvent;
38
27
  repoRoot: string;
39
28
  }) => SystemNotificationEmitResult;
40
- readGovernanceNextAction: GovernanceNextActionReader;
41
29
  };
42
30
 
43
31
  export type ConsumerPreflightRenderOptions = {
@@ -5,13 +5,13 @@ import {
5
5
  exportConsumerRuntimeMarkdown,
6
6
  notifyConsumerRuntimeAuditSummary,
7
7
  printConsumerRuntimeEmptyScopeHint,
8
+ printPrePushTrackedEvidenceDiskHint,
8
9
  renderConsumerRuntimeAstBreakdown,
9
10
  renderConsumerRuntimeEslintAudit,
10
11
  renderConsumerRuntimeFileDiagnostics,
11
12
  renderConsumerRuntimePatternChecks,
12
13
  renderConsumerRuntimeSummary,
13
14
  } from './framework-menu-consumer-runtime-audit';
14
- import type { ConsumerPreflightResult } from './framework-menu-consumer-preflight-types';
15
15
  import type { ConsumerAction, ConsumerRuntimeEmitNotification, ConsumerRuntimeWrite } from './framework-menu-consumer-runtime-types';
16
16
 
17
17
  type ConsumerRuntimeActionDependencies = {
@@ -21,7 +21,9 @@ type ConsumerRuntimeActionDependencies = {
21
21
  runRepoGate: () => Promise<ConsumerRuntimeGateResult | void>;
22
22
  runRepoAndStagedGate: () => Promise<ConsumerRuntimeGateResult | void>;
23
23
  runStagedGate: () => Promise<ConsumerRuntimeGateResult | void>;
24
+ runUnstagedGate: () => Promise<ConsumerRuntimeGateResult | void>;
24
25
  runWorkingTreeGate: () => Promise<ConsumerRuntimeGateResult | void>;
26
+ runWorkingTreePreCommitGate: () => Promise<ConsumerRuntimeGateResult | void>;
25
27
  runPreflight?: (
26
28
  stage: 'PRE_COMMIT' | 'PRE_PUSH'
27
29
  ) => Promise<string | void> | string | void;
@@ -31,20 +33,17 @@ type ConsumerRuntimeActionDependencies = {
31
33
  setSummaryOverride: (
32
34
  summary: import('./framework-menu-evidence-summary-lib').FrameworkMenuEvidenceSummary | null
33
35
  ) => void;
34
- clearLastPreflight: () => void;
35
- setLastPreflight: (result: ConsumerPreflightResult | null) => void;
36
36
  };
37
37
 
38
38
  const runConsumerRuntimePreflight = async (
39
39
  dependencies: Pick<
40
40
  ConsumerRuntimeActionDependencies,
41
- 'repoRoot' | 'runPreflight' | 'useColor' | 'write' | 'setLastPreflight'
41
+ 'repoRoot' | 'runPreflight' | 'useColor' | 'write'
42
42
  >,
43
43
  stage: 'PRE_COMMIT' | 'PRE_PUSH'
44
44
  ): Promise<void> => {
45
45
  if (dependencies.runPreflight) {
46
46
  const rendered = await dependencies.runPreflight(stage);
47
- dependencies.setLastPreflight(null);
48
47
  if (typeof rendered === 'string' && rendered.trim().length > 0) {
49
48
  dependencies.write(`\n${rendered}\n`);
50
49
  }
@@ -55,7 +54,6 @@ const runConsumerRuntimePreflight = async (
55
54
  stage,
56
55
  repoRoot: dependencies.repoRoot,
57
56
  });
58
- dependencies.setLastPreflight(preflight);
59
57
  dependencies.write(
60
58
  `\n${formatConsumerPreflight(preflight, {
61
59
  color: dependencies.useColor(),
@@ -93,18 +91,25 @@ export const createConsumerRuntimeActions = (
93
91
  } else {
94
92
  dependencies.clearSummaryOverride();
95
93
  }
94
+ const summary = renderConsumerRuntimeSummary({
95
+ repoRoot: dependencies.repoRoot,
96
+ write: dependencies.write,
97
+ useColor: dependencies.useColor,
98
+ summaryOverride: dependencies.getSummaryOverride(),
99
+ });
96
100
  notifyConsumerRuntimeAuditSummary(
97
101
  {
98
102
  emitNotification: dependencies.emitNotification,
99
103
  repoRoot: dependencies.repoRoot,
100
104
  },
101
- renderConsumerRuntimeSummary({
102
- repoRoot: dependencies.repoRoot,
103
- write: dependencies.write,
104
- useColor: dependencies.useColor,
105
- summaryOverride: dependencies.getSummaryOverride(),
106
- })
105
+ summary
107
106
  );
107
+ if (
108
+ !gateResult?.blocked
109
+ && (summary.outcome === 'PASS' || summary.outcome === 'WARN')
110
+ ) {
111
+ printPrePushTrackedEvidenceDiskHint({ write: dependencies.write });
112
+ }
108
113
  },
109
114
  runStrictStagedOnly: async () => {
110
115
  await runConsumerRuntimePreflight(dependencies, 'PRE_COMMIT');
@@ -140,22 +145,88 @@ export const createConsumerRuntimeActions = (
140
145
  },
141
146
  summary
142
147
  );
148
+ if (summary.outcome === 'PASS' || summary.outcome === 'WARN') {
149
+ printPrePushTrackedEvidenceDiskHint({ write: dependencies.write });
150
+ }
143
151
  printConsumerRuntimeEmptyScopeHint({ write: dependencies.write }, summary, 'workingTree');
144
152
  },
153
+ runEngineStagedNoPreflight: async () => {
154
+ await dependencies.runStagedGate();
155
+ dependencies.clearSummaryOverride();
156
+ const summary = renderConsumerRuntimeSummary({
157
+ repoRoot: dependencies.repoRoot,
158
+ write: dependencies.write,
159
+ useColor: dependencies.useColor,
160
+ });
161
+ notifyConsumerRuntimeAuditSummary(
162
+ {
163
+ emitNotification: dependencies.emitNotification,
164
+ repoRoot: dependencies.repoRoot,
165
+ },
166
+ summary
167
+ );
168
+ printConsumerRuntimeEmptyScopeHint({ write: dependencies.write }, summary, 'staged');
169
+ },
170
+ runEngineUnstagedNoPreflight: async () => {
171
+ await dependencies.runUnstagedGate();
172
+ dependencies.clearSummaryOverride();
173
+ const summary = renderConsumerRuntimeSummary({
174
+ repoRoot: dependencies.repoRoot,
175
+ write: dependencies.write,
176
+ useColor: dependencies.useColor,
177
+ });
178
+ notifyConsumerRuntimeAuditSummary(
179
+ {
180
+ emitNotification: dependencies.emitNotification,
181
+ repoRoot: dependencies.repoRoot,
182
+ },
183
+ summary
184
+ );
185
+ printConsumerRuntimeEmptyScopeHint({ write: dependencies.write }, summary, 'unstaged');
186
+ },
187
+ runEngineStagedAndUnstagedNoPreflight: async () => {
188
+ await dependencies.runWorkingTreePreCommitGate();
189
+ dependencies.clearSummaryOverride();
190
+ const summary = renderConsumerRuntimeSummary({
191
+ repoRoot: dependencies.repoRoot,
192
+ write: dependencies.write,
193
+ useColor: dependencies.useColor,
194
+ });
195
+ notifyConsumerRuntimeAuditSummary(
196
+ {
197
+ emitNotification: dependencies.emitNotification,
198
+ repoRoot: dependencies.repoRoot,
199
+ },
200
+ summary
201
+ );
202
+ printConsumerRuntimeEmptyScopeHint({ write: dependencies.write }, summary, 'workingTree');
203
+ },
204
+ runEngineFullRepoNoPreflight: async () => {
205
+ await dependencies.runRepoGate();
206
+ dependencies.clearSummaryOverride();
207
+ const summary = renderConsumerRuntimeSummary({
208
+ repoRoot: dependencies.repoRoot,
209
+ write: dependencies.write,
210
+ useColor: dependencies.useColor,
211
+ });
212
+ notifyConsumerRuntimeAuditSummary(
213
+ {
214
+ emitNotification: dependencies.emitNotification,
215
+ repoRoot: dependencies.repoRoot,
216
+ },
217
+ summary
218
+ );
219
+ },
145
220
  runPatternChecks: async () => {
146
- dependencies.clearLastPreflight();
147
221
  dependencies.write(`\n${renderConsumerRuntimePatternChecks(dependencies.repoRoot)}\n`);
148
222
  },
149
223
  runEslintAudit: async () => {
150
- dependencies.clearLastPreflight();
151
224
  dependencies.write(`\n${renderConsumerRuntimeEslintAudit(dependencies.repoRoot)}\n`);
152
225
  },
153
226
  runAstIntelligence: async () => {
154
- dependencies.clearLastPreflight();
155
227
  dependencies.write(`\n${renderConsumerRuntimeAstBreakdown(dependencies.repoRoot)}\n`);
156
228
  },
157
229
  runExportMarkdown: async () => {
158
- dependencies.clearLastPreflight();
159
230
  const filePath = exportConsumerRuntimeMarkdown(
160
231
  dependencies.repoRoot,
161
232
  dependencies.getSummaryOverride()
@@ -163,7 +234,6 @@ export const createConsumerRuntimeActions = (
163
234
  dependencies.write(`\nLegacy read-only markdown exported: ${filePath}\n`);
164
235
  },
165
236
  runFileDiagnostics: async () => {
166
- dependencies.clearLastPreflight();
167
237
  dependencies.write(`\n${renderConsumerRuntimeFileDiagnostics(dependencies.repoRoot)}\n`);
168
238
  },
169
239
  }) as ReadonlyArray<ConsumerAction>;
@@ -14,6 +14,7 @@ import {
14
14
  readEvidenceSummaryForMenu,
15
15
  type FrameworkMenuEvidenceSummary,
16
16
  } from './framework-menu-evidence-summary-lib';
17
+ import { renderVintageEvidenceReport } from './framework-menu-consumer-runtime-evidence-classic';
17
18
  import type {
18
19
  ConsumerRuntimeBlockedGate,
19
20
  ConsumerRuntimeNotificationDependencies,
@@ -56,9 +57,36 @@ export const renderConsumerRuntimeSummary = (
56
57
  width: resolveLegacyPanelOuterWidth(),
57
58
  color: dependencies.useColor(),
58
59
  })}\n`);
60
+
61
+ const vintageSource =
62
+ summary.status === 'ok' && !dependencies.summaryOverride
63
+ ? readEvidenceSummaryForMenu(dependencies.repoRoot, {
64
+ topFindingsLimit: 45,
65
+ topFileLocationsLimit: 15,
66
+ topFilesLimit: 10,
67
+ })
68
+ : summary;
69
+ renderVintageEvidenceReport({
70
+ write: dependencies.write,
71
+ summary: vintageSource,
72
+ useColor: dependencies.useColor,
73
+ });
59
74
  return summary;
60
75
  };
61
76
 
77
+ export const printPrePushTrackedEvidenceDiskHint = (params: {
78
+ write: ConsumerRuntimeSummaryDependencies['write'];
79
+ }): void => {
80
+ params.write(
81
+ '\n' +
82
+ [
83
+ 'ℹ PRE_PUSH + `.ai_evidence.json` tracked: on PASS/WARN the gate may skip rewriting the file on disk',
84
+ ' (avoids dirty tracked evidence). Local dev: PUMUKI_PRE_PUSH_ALWAYS_WRITE_TRACKED_EVIDENCE=1 forces disk write.',
85
+ ].join('\n') +
86
+ '\n'
87
+ );
88
+ };
89
+
62
90
  export const buildConsumerRuntimeBlockedSummary = (
63
91
  blocked: ConsumerRuntimeBlockedGate
64
92
  ): FrameworkMenuEvidenceSummary => ({
@@ -116,12 +144,18 @@ export const printConsumerRuntimeEmptyScopeHint = (
116
144
  }
117
145
  if (scope === 'staged') {
118
146
  dependencies.write(
119
- '\nℹ Scope vacío (staged): no hay archivos soportados en staged para auditar. Resultado PASS por alcance vacío; usa 1 o 2 para validar repo completo.\n'
147
+ '\nℹ Scope vacío (staged): no hay archivos soportados en staged para auditar. Resultado PASS por alcance vacío; usa 1, 2 o 14 (repo completo) según necesidad.\n'
148
+ );
149
+ return;
150
+ }
151
+ if (scope === 'unstaged') {
152
+ dependencies.write(
153
+ '\nℹ Scope vacío (unstaged): no hay cambios sin stage ni untracked auditable. Resultado PASS por alcance vacío; usa 1, 14 u opciones 11–13 según el alcance que necesites.\n'
120
154
  );
121
155
  return;
122
156
  }
123
157
  dependencies.write(
124
- '\nℹ Scope vacío (working tree): no hay archivos soportados en staged/unstaged para auditar. Resultado PASS por alcance vacío; usa 1 o 2 para validar repo completo.\n'
158
+ '\nℹ Scope vacío (working tree): no hay archivos soportados en staged/unstaged para auditar. Resultado PASS por alcance vacío; usa 1, 2, 13 o 14 según el alcance que necesites.\n'
125
159
  );
126
160
  };
127
161
 
@@ -0,0 +1,140 @@
1
+ import type { EnterpriseEvidenceSeverity } from './framework-menu-evidence-summary-types';
2
+ import type { FrameworkMenuEvidenceSummary } from './framework-menu-evidence-summary-lib';
3
+ import { renderLegacyPanel, resolveLegacyPanelOuterWidth } from './framework-menu-legacy-audit-lib';
4
+ import { applyCliPalette, buildCliDesignTokens } from './framework-menu-ui-components-lib';
5
+ import type { CliPaletteRole } from './framework-menu-ui-components-types';
6
+
7
+ const enterpriseSeverityToRole = (severity: EnterpriseEvidenceSeverity): CliPaletteRole => {
8
+ if (severity === 'CRITICAL') {
9
+ return 'critical';
10
+ }
11
+ if (severity === 'HIGH') {
12
+ return 'high';
13
+ }
14
+ if (severity === 'MEDIUM') {
15
+ return 'medium';
16
+ }
17
+ return 'low';
18
+ };
19
+
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
+ export const formatVintageEvidenceReportLines = (
35
+ summary: FrameworkMenuEvidenceSummary,
36
+ tokens: ReturnType<typeof buildCliDesignTokens>
37
+ ): string[] => {
38
+ if (summary.status !== 'ok') {
39
+ return [
40
+ applyCliPalette('PUMUKI — Classic evidence view', 'title', tokens),
41
+ applyCliPalette(
42
+ summary.status === 'missing'
43
+ ? 'No .ai_evidence.json — run an engine audit (1, 11–14) first.'
44
+ : 'Invalid .ai_evidence.json — regenerate from a gate run.',
45
+ 'muted',
46
+ tokens
47
+ ),
48
+ ];
49
+ }
50
+
51
+ const ent = summary.byEnterpriseSeverity ?? {
52
+ CRITICAL: summary.bySeverity.CRITICAL,
53
+ HIGH: summary.bySeverity.ERROR,
54
+ MEDIUM: summary.bySeverity.WARN,
55
+ LOW: summary.bySeverity.INFO,
56
+ };
57
+
58
+ const lines: string[] = [
59
+ applyCliPalette('PUMUKI — Classic evidence view (severities + platforms)', 'title', tokens),
60
+ '',
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}`,
63
+ '',
64
+ applyCliPalette('Enterprise severities', 'sectionTitle', tokens),
65
+ ];
66
+
67
+ const order: EnterpriseEvidenceSeverity[] = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW'];
68
+ for (const band of order) {
69
+ const count = ent[band] ?? 0;
70
+ if (count === 0) {
71
+ continue;
72
+ }
73
+ lines.push(
74
+ ` ${applyCliPalette(`${band}:`, enterpriseSeverityToRole(band), tokens)} ${count}`
75
+ );
76
+ }
77
+
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
+
86
+ if (summary.platformAuditRows && summary.platformAuditRows.length > 0) {
87
+ lines.push('', applyCliPalette('Platforms (from evidence snapshot)', 'sectionTitle', tokens));
88
+ for (const row of summary.platformAuditRows) {
89
+ lines.push(
90
+ ` ${applyCliPalette(row.platform, 'rule', tokens)}: ${row.violations} violations`
91
+ );
92
+ }
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
+ );
100
+ }
101
+
102
+ lines.push('', applyCliPalette('Top violations (ranked)', 'sectionTitle', tokens));
103
+ if (summary.topFindings.length === 0) {
104
+ lines.push(applyCliPalette(' (none)', 'goal', tokens));
105
+ } else {
106
+ for (const finding of summary.topFindings) {
107
+ const role = enterpriseSeverityToRole(finding.severity);
108
+ lines.push(
109
+ ` ${applyCliPalette(`[${finding.severity}]`, role, tokens)} ${finding.ruleId}`
110
+ );
111
+ lines.push(
112
+ ` ${applyCliPalette(`${finding.file}:${finding.line}`, 'muted', tokens)}`
113
+ );
114
+ }
115
+ }
116
+
117
+ return lines;
118
+ };
119
+
120
+ export const renderVintageEvidenceReport = (params: {
121
+ write: (text: string) => void;
122
+ summary: FrameworkMenuEvidenceSummary;
123
+ useColor: () => boolean;
124
+ }): void => {
125
+ if (process.env.PUMUKI_MENU_VINTAGE_REPORT === '0') {
126
+ return;
127
+ }
128
+ const tokens = buildCliDesignTokens({
129
+ width: resolveLegacyPanelOuterWidth(),
130
+ color: params.useColor(),
131
+ });
132
+
133
+ const lines = formatVintageEvidenceReportLines(params.summary, tokens);
134
+ params.write(
135
+ `\n${renderLegacyPanel(lines, {
136
+ width: resolveLegacyPanelOuterWidth(),
137
+ color: params.useColor(),
138
+ })}\n`
139
+ );
140
+ };
@@ -5,9 +5,6 @@ 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';
11
8
  import type {
12
9
  ConsumerAction,
13
10
  ConsumerMenuRuntime,
@@ -20,28 +17,11 @@ export type {
20
17
  ConsumerMenuRuntimeParams,
21
18
  } from './framework-menu-consumer-runtime-types';
22
19
 
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
-
39
20
  export const createConsumerMenuRuntime = (
40
21
  params: ConsumerMenuRuntimeParams
41
22
  ): ConsumerMenuRuntime => {
42
23
  const repoRoot = process.cwd();
43
24
  let summaryOverride: FrameworkMenuEvidenceSummary | null = null;
44
- let lastPreflight: ConsumerPreflightResult | null = null;
45
25
  const emitNotification =
46
26
  params.emitSystemNotification
47
27
  ?? ((payload: Parameters<typeof emitSystemNotification>[0]) =>
@@ -55,7 +35,9 @@ export const createConsumerMenuRuntime = (
55
35
  runRepoGate: params.runRepoGate,
56
36
  runRepoAndStagedGate: params.runRepoAndStagedGate,
57
37
  runStagedGate: params.runStagedGate,
38
+ runUnstagedGate: params.runUnstagedGate,
58
39
  runWorkingTreeGate: params.runWorkingTreeGate,
40
+ runWorkingTreePreCommitGate: params.runWorkingTreePreCommitGate,
59
41
  runPreflight: params.runPreflight,
60
42
  emitNotification,
61
43
  clearSummaryOverride: () => {
@@ -65,37 +47,19 @@ export const createConsumerMenuRuntime = (
65
47
  setSummaryOverride: (summary) => {
66
48
  summaryOverride = summary;
67
49
  },
68
- clearLastPreflight: () => {
69
- lastPreflight = null;
70
- },
71
- setLastPreflight: (result) => {
72
- lastPreflight = result;
73
- },
74
50
  });
75
51
 
76
52
  return {
77
53
  actions: actions as ReadonlyArray<ConsumerAction>,
78
54
  printMenu: () => {
79
- const governanceConsole =
80
- lastPreflight
81
- ? {
82
- governanceObservation: lastPreflight.governanceObservation,
83
- governanceNextAction: lastPreflight.governanceNextAction,
84
- policyValidation: lastPreflight.policyValidation,
85
- experimentalFeatures: lastPreflight.experimentalFeatures,
86
- }
87
- : (params.readGovernanceConsole?.() ?? readMenuGovernanceConsoleSnapshot(repoRoot));
88
55
  printConsumerRuntimeMenu({
89
56
  actions,
90
57
  repoRoot,
91
58
  useColor,
92
59
  write: params.write,
93
- preflight: lastPreflight,
94
- governanceConsole,
95
60
  });
96
61
  },
97
62
  readCurrentSummary: () => summaryOverride,
98
- readLastPreflight: () => lastPreflight,
99
63
  };
100
64
  };
101
65