pumuki 6.3.70 → 6.3.72

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 (45) hide show
  1. package/AGENTS.md +269 -0
  2. package/CHANGELOG.md +666 -0
  3. package/README.md +32 -0
  4. package/docs/README.md +7 -2
  5. package/docs/operations/RELEASE_NOTES.md +15 -0
  6. package/docs/product/CONFIGURATION.md +12 -0
  7. package/docs/product/USAGE.md +24 -3
  8. package/docs/tracking/plan-curso-pumuki-stack-my-architecture.md +111 -0
  9. package/integrations/evidence/buildEvidence.ts +15 -0
  10. package/integrations/evidence/operationalHints.ts +110 -0
  11. package/integrations/evidence/schema.ts +16 -0
  12. package/integrations/evidence/writeEvidence.ts +3 -0
  13. package/integrations/gate/remediationCatalog.ts +40 -0
  14. package/integrations/git/GitService.ts +25 -0
  15. package/integrations/git/filterFactsByPathPrefixes.ts +61 -0
  16. package/integrations/git/runPlatformGate.ts +12 -4
  17. package/integrations/git/runPlatformGateFacts.ts +7 -0
  18. package/integrations/git/stageRunners.ts +82 -28
  19. package/integrations/lifecycle/cli.ts +32 -3
  20. package/integrations/lifecycle/doctor.ts +112 -0
  21. package/integrations/mcp/aiGateCheck.ts +2 -11
  22. package/integrations/mcp/preFlightCheck.ts +2 -1
  23. package/integrations/sdd/openSpecCli.ts +12 -3
  24. package/package.json +4 -1
  25. package/scripts/consumer-menu-matrix-baseline-report-lib.ts +13 -38
  26. package/scripts/framework-menu-consumer-actions-lib.ts +28 -4
  27. package/scripts/framework-menu-consumer-preflight-hints.ts +5 -2
  28. package/scripts/framework-menu-consumer-runtime-actions.ts +86 -6
  29. package/scripts/framework-menu-consumer-runtime-audit.ts +36 -2
  30. package/scripts/framework-menu-consumer-runtime-evidence-classic.ts +140 -0
  31. package/scripts/framework-menu-consumer-runtime-lib.ts +2 -0
  32. package/scripts/framework-menu-consumer-runtime-types.ts +3 -1
  33. package/scripts/framework-menu-evidence-summary-lib.ts +1 -0
  34. package/scripts/framework-menu-evidence-summary-read.ts +57 -5
  35. package/scripts/framework-menu-evidence-summary-severity.ts +3 -1
  36. package/scripts/framework-menu-evidence-summary-types.ts +7 -0
  37. package/scripts/framework-menu-gate-lib.ts +9 -0
  38. package/scripts/framework-menu-layout-data.ts +5 -0
  39. package/scripts/framework-menu-matrix-baseline-lib.ts +15 -14
  40. package/scripts/framework-menu-matrix-canary-lib.ts +22 -1
  41. package/scripts/framework-menu-matrix-evidence-lib.ts +1 -0
  42. package/scripts/framework-menu-matrix-evidence-types.ts +13 -1
  43. package/scripts/framework-menu-matrix-runner-lib.ts +35 -0
  44. package/scripts/framework-menu-system-notifications-macos.ts +4 -0
  45. package/scripts/framework-menu.ts +3 -0
@@ -9,6 +9,7 @@ export type MenuStage = 'PRE_COMMIT' | 'PRE_PUSH' | 'CI';
9
9
 
10
10
  export type MenuScope =
11
11
  | { kind: 'staged' }
12
+ | { kind: 'unstaged' }
12
13
  | { kind: 'repo' }
13
14
  | { kind: 'repoAndStaged' }
14
15
  | { kind: 'workingTree' }
@@ -141,6 +142,14 @@ export const runWorkingTreePrePushGateSilent = async (): Promise<void> => {
141
142
  await runMenuAuditGate(gateParams);
142
143
  };
143
144
 
145
+ export const runUnstagedGateSilent = async (): Promise<void> => {
146
+ const gateParams = buildMenuGateParams({
147
+ stage: 'PRE_COMMIT',
148
+ scope: { kind: 'unstaged' },
149
+ });
150
+ await runMenuAuditGate(gateParams);
151
+ };
152
+
144
153
  const runMenuAuditGate = async (
145
154
  gateParams: ReturnType<typeof buildMenuGateParams>
146
155
  ): Promise<void> => {
@@ -6,6 +6,11 @@ export const CONSUMER_MENU_LAYOUT: ReadonlyArray<MenuLayoutGroup> = [
6
6
  title: 'Read-Only Gate Flows',
7
7
  itemIds: ['1', '2', '3', '4'],
8
8
  },
9
+ {
10
+ key: 'engine-working-tree-no-preflight',
11
+ title: 'Engine · working tree (no preflight)',
12
+ itemIds: ['11', '12', '13', '14'],
13
+ },
9
14
  {
10
15
  key: 'export',
11
16
  title: 'Legacy Read-Only Export',
@@ -1,10 +1,11 @@
1
1
  import {
2
2
  runConsumerMenuMatrix,
3
3
  } from './framework-menu-matrix-runner-lib';
4
- import type {
5
- ConsumerMenuMatrixReport,
6
- ConsumerMenuMatrixOptionReport,
7
- MatrixOptionId,
4
+ import {
5
+ MATRIX_MENU_OPTION_IDS,
6
+ type ConsumerMenuMatrixReport,
7
+ type ConsumerMenuMatrixOptionReport,
8
+ type MatrixOptionId,
8
9
  } from './framework-menu-matrix-evidence-lib';
9
10
 
10
11
  export type MatrixOptionDrift = {
@@ -22,7 +23,13 @@ export type ConsumerMenuMatrixBaselineReport = {
22
23
  analysis: ConsumerMenuMatrixBaselineAnalysis;
23
24
  };
24
25
 
25
- const OPTION_IDS: ReadonlyArray<MatrixOptionId> = ['1', '2', '3', '4', '9'];
26
+ const EMPTY_DRIFT: MatrixOptionDrift = { stable: true, driftFields: [] };
27
+
28
+ const seedMatrixOptionDrift = (): Record<MatrixOptionId, MatrixOptionDrift> => {
29
+ return Object.fromEntries(
30
+ MATRIX_MENU_OPTION_IDS.map((optionId) => [optionId, { ...EMPTY_DRIFT }])
31
+ ) as Record<MatrixOptionId, MatrixOptionDrift>;
32
+ };
26
33
 
27
34
  const OPTION_FIELDS: ReadonlyArray<keyof ConsumerMenuMatrixOptionReport> = [
28
35
  'stage',
@@ -57,18 +64,12 @@ const computeOptionDrift = (
57
64
  export const analyzeConsumerMenuMatrixBaseline = (
58
65
  rounds: ReadonlyArray<ConsumerMenuMatrixReport>
59
66
  ): ConsumerMenuMatrixBaselineAnalysis => {
60
- const byOption = OPTION_IDS.reduce<Record<MatrixOptionId, MatrixOptionDrift>>((acc, optionId) => {
67
+ const byOption = MATRIX_MENU_OPTION_IDS.reduce<Record<MatrixOptionId, MatrixOptionDrift>>((acc, optionId) => {
61
68
  acc[optionId] = computeOptionDrift(rounds, optionId);
62
69
  return acc;
63
- }, {
64
- '1': { stable: true, driftFields: [] },
65
- '2': { stable: true, driftFields: [] },
66
- '3': { stable: true, driftFields: [] },
67
- '4': { stable: true, driftFields: [] },
68
- '9': { stable: true, driftFields: [] },
69
- });
70
+ }, seedMatrixOptionDrift());
70
71
 
71
- const stable = OPTION_IDS.every((optionId) => byOption[optionId].stable);
72
+ const stable = MATRIX_MENU_OPTION_IDS.every((optionId) => byOption[optionId].stable);
72
73
 
73
74
  return {
74
75
  stable,
@@ -6,6 +6,8 @@ import {
6
6
  runRepoAndStagedPrePushGateSilent,
7
7
  runRepoGateSilent,
8
8
  runStagedGateSilent,
9
+ runUnstagedGateSilent,
10
+ runWorkingTreeGateSilent,
9
11
  runWorkingTreePrePushGateSilent,
10
12
  } from './framework-menu-gate-lib';
11
13
  import { readMatrixOptionReport, type MatrixOptionId } from './framework-menu-matrix-evidence-lib';
@@ -70,6 +72,25 @@ const runGateByOption = async (option: MatrixOptionId): Promise<void> => {
70
72
  }
71
73
  if (option === '4') {
72
74
  await runWorkingTreePrePushGateSilent();
75
+ return;
76
+ }
77
+ if (option === '9') {
78
+ return;
79
+ }
80
+ if (option === '11') {
81
+ await runStagedGateSilent();
82
+ return;
83
+ }
84
+ if (option === '12') {
85
+ await runUnstagedGateSilent();
86
+ return;
87
+ }
88
+ if (option === '13') {
89
+ await runWorkingTreeGateSilent();
90
+ return;
91
+ }
92
+ if (option === '14') {
93
+ await runRepoGateSilent();
73
94
  }
74
95
  };
75
96
 
@@ -104,7 +125,7 @@ export const runConsumerMenuCanary = async (params?: {
104
125
  scenario.canarySource,
105
126
  'utf8'
106
127
  );
107
- if (scenario.option === '1' || scenario.option === '2') {
128
+ if (scenario.option === '1' || scenario.option === '2' || scenario.option === '3' || scenario.option === '11') {
108
129
  stageCanaryPath(repoRoot, canaryRelativePath);
109
130
  }
110
131
 
@@ -8,6 +8,7 @@ export type {
8
8
  MatrixOptionDiagnosis,
9
9
  MatrixOptionId,
10
10
  } from './framework-menu-matrix-evidence-types';
11
+ export { MATRIX_MENU_OPTION_IDS } from './framework-menu-matrix-evidence-types';
11
12
  export { toMatrixOptionReport } from './framework-menu-matrix-evidence-diagnosis';
12
13
 
13
14
  export const readMatrixOptionReport = (
@@ -1,4 +1,16 @@
1
- export type MatrixOptionId = '1' | '2' | '3' | '4' | '9';
1
+ export const MATRIX_MENU_OPTION_IDS = [
2
+ '1',
3
+ '2',
4
+ '3',
5
+ '4',
6
+ '9',
7
+ '11',
8
+ '12',
9
+ '13',
10
+ '14',
11
+ ] as const;
12
+
13
+ export type MatrixOptionId = (typeof MATRIX_MENU_OPTION_IDS)[number];
2
14
  export type MatrixOptionDiagnosis =
3
15
  | 'scope-empty'
4
16
  | 'repo-clean'
@@ -3,6 +3,8 @@ import {
3
3
  runRepoAndStagedPrePushGateSilent,
4
4
  runRepoGateSilent,
5
5
  runStagedGateSilent,
6
+ runUnstagedGateSilent,
7
+ runWorkingTreeGateSilent,
6
8
  runWorkingTreePrePushGateSilent,
7
9
  } from './framework-menu-gate-lib';
8
10
  import {
@@ -24,6 +26,8 @@ export type ConsumerMenuMatrixRunnerDependencies = {
24
26
  runRepoGateSilent: () => Promise<void>;
25
27
  runRepoAndStagedPrePushGateSilent: () => Promise<void>;
26
28
  runStagedGateSilent: () => Promise<void>;
29
+ runUnstagedGateSilent: () => Promise<void>;
30
+ runWorkingTreeGateSilent: () => Promise<void>;
27
31
  runWorkingTreePrePushGateSilent: () => Promise<void>;
28
32
  readMatrixOptionReport: (repoRoot: string, optionId: MatrixOptionId) => ConsumerMenuMatrixOptionReport;
29
33
  };
@@ -32,6 +36,8 @@ const createDefaultDependencies = (): ConsumerMenuMatrixRunnerDependencies => ({
32
36
  runRepoGateSilent,
33
37
  runRepoAndStagedPrePushGateSilent,
34
38
  runStagedGateSilent,
39
+ runUnstagedGateSilent,
40
+ runWorkingTreeGateSilent,
35
41
  runWorkingTreePrePushGateSilent,
36
42
  readMatrixOptionReport,
37
43
  });
@@ -84,6 +90,31 @@ export const runConsumerMenuMatrix = async (params?: {
84
90
  }
85
91
  })();
86
92
 
93
+ const option11 = await runOption(
94
+ '11',
95
+ repoRoot,
96
+ dependencies.runStagedGateSilent,
97
+ dependencies.readMatrixOptionReport
98
+ );
99
+ const option12 = await runOption(
100
+ '12',
101
+ repoRoot,
102
+ dependencies.runUnstagedGateSilent,
103
+ dependencies.readMatrixOptionReport
104
+ );
105
+ const option13 = await runOption(
106
+ '13',
107
+ repoRoot,
108
+ dependencies.runWorkingTreeGateSilent,
109
+ dependencies.readMatrixOptionReport
110
+ );
111
+ const option14 = await runOption(
112
+ '14',
113
+ repoRoot,
114
+ dependencies.runRepoGateSilent,
115
+ dependencies.readMatrixOptionReport
116
+ );
117
+
87
118
  return {
88
119
  byOption: {
89
120
  '1': option1,
@@ -91,6 +122,10 @@ export const runConsumerMenuMatrix = async (params?: {
91
122
  '3': option3,
92
123
  '4': option4,
93
124
  '9': option9,
125
+ '11': option11,
126
+ '12': option12,
127
+ '13': option13,
128
+ '14': option14,
94
129
  },
95
130
  };
96
131
  } finally {
@@ -5,6 +5,7 @@ import {
5
5
  type SystemNotificationCommandRunnerWithOutput,
6
6
  type SystemNotificationsConfig,
7
7
  } from './framework-menu-system-notifications-types';
8
+ import { isTruthyEnvValue } from './framework-menu-system-notifications-env';
8
9
  import { resolveBlockedDialogEnabled } from './framework-menu-system-notifications-macos-dialog-enabled';
9
10
  import { emitMacOsBannerStage } from './framework-menu-system-notifications-macos-banner-stage';
10
11
  import { emitMacOsBlockedDialogStage } from './framework-menu-system-notifications-macos-blocked-stage';
@@ -19,6 +20,9 @@ const shouldSkipMacOsBannerForInteractiveBlockedDialog = (params: {
19
20
  config: SystemNotificationsConfig;
20
21
  env: NodeJS.ProcessEnv;
21
22
  }): boolean => {
23
+ if (!isTruthyEnvValue(params.env.PUMUKI_MACOS_GATE_BLOCKED_BANNER_DEDUPE)) {
24
+ return false;
25
+ }
22
26
  if (params.event.kind !== 'gate.blocked') {
23
27
  return false;
24
28
  }
@@ -16,6 +16,7 @@ import {
16
16
  runWorkingTreeGateSilent,
17
17
  runRepoAndStagedPrePushGateSilent,
18
18
  runWorkingTreePrePushGateSilent,
19
+ runUnstagedGateSilent,
19
20
  } from './framework-menu-gate-lib';
20
21
  import { createFrameworkMenuPrompts } from './framework-menu-prompts';
21
22
  import { resolveDefaultRangeFrom } from './framework-menu-runners';
@@ -62,7 +63,9 @@ const menu = async (): Promise<void> => {
62
63
  runRepoGate: runRepoGateSilent,
63
64
  runRepoAndStagedGate: runRepoAndStagedPrePushGateSilent,
64
65
  runStagedGate: runStagedGateSilent,
66
+ runUnstagedGate: runUnstagedGateSilent,
65
67
  runWorkingTreeGate: runWorkingTreePrePushGateSilent,
68
+ runWorkingTreePreCommitGate: runWorkingTreeGateSilent,
66
69
  write: (text) => {
67
70
  output.write(text);
68
71
  },