pumuki 6.3.72 → 6.3.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/VERSION +1 -1
- package/docs/README.md +1 -1
- package/docs/operations/RELEASE_NOTES.md +12 -1
- package/docs/product/USAGE.md +2 -5
- package/docs/tracking/plan-curso-pumuki-stack-my-architecture.md +56 -105
- package/integrations/gate/governanceActionCatalog.ts +230 -0
- package/integrations/git/runPlatformGate.ts +9 -1
- package/integrations/git/runPlatformGateFacts.ts +1 -7
- package/integrations/git/runPlatformGateOutput.ts +36 -27
- package/integrations/lifecycle/adapter.templates.json +3 -0
- package/integrations/lifecycle/audit.ts +101 -0
- package/integrations/lifecycle/cli.ts +80 -8
- package/integrations/lifecycle/doctor.ts +64 -1
- package/integrations/lifecycle/governanceNextAction.ts +164 -0
- package/integrations/lifecycle/governanceObservationSnapshot.ts +288 -0
- package/integrations/lifecycle/index.ts +2 -0
- package/integrations/lifecycle/status.ts +29 -2
- package/integrations/mcp/autoExecuteAiStart.ts +86 -84
- package/integrations/mcp/preFlightCheck.ts +41 -5
- package/integrations/platform/detectPlatforms.ts +37 -0
- package/package.json +8 -1
- package/scripts/build-ruralgo-s1-evidence-pack.ts +85 -0
- package/scripts/consumer-menu-matrix-baseline-report-lib.ts +38 -13
- package/scripts/consumer-postinstall-resolve-args.cjs +38 -0
- package/scripts/consumer-postinstall.cjs +10 -1
- package/scripts/framework-menu-consumer-actions-lib.ts +4 -28
- package/scripts/framework-menu-consumer-preflight-hints.ts +2 -5
- package/scripts/framework-menu-consumer-preflight-render.ts +6 -0
- package/scripts/framework-menu-consumer-preflight-run.ts +19 -0
- package/scripts/framework-menu-consumer-preflight-types.ts +8 -0
- package/scripts/framework-menu-consumer-runtime-actions.ts +6 -86
- package/scripts/framework-menu-consumer-runtime-audit.ts +2 -36
- package/scripts/framework-menu-consumer-runtime-lib.ts +0 -2
- package/scripts/framework-menu-consumer-runtime-types.ts +1 -3
- package/scripts/framework-menu-evidence-summary-lib.ts +0 -1
- package/scripts/framework-menu-evidence-summary-read.ts +5 -57
- package/scripts/framework-menu-evidence-summary-severity.ts +1 -3
- package/scripts/framework-menu-evidence-summary-types.ts +0 -7
- package/scripts/framework-menu-gate-lib.ts +0 -9
- package/scripts/framework-menu-layout-data.ts +0 -5
- package/scripts/framework-menu-matrix-baseline-lib.ts +14 -15
- package/scripts/framework-menu-matrix-canary-lib.ts +1 -22
- package/scripts/framework-menu-matrix-evidence-lib.ts +0 -1
- package/scripts/framework-menu-matrix-evidence-types.ts +1 -13
- package/scripts/framework-menu-matrix-runner-lib.ts +0 -35
- package/scripts/framework-menu-system-notifications-macos.ts +0 -4
- package/scripts/framework-menu.ts +0 -3
- package/scripts/pumuki-full-surface-smoke-lib.ts +37 -0
- package/scripts/pumuki-full-surface-smoke.ts +261 -0
- package/scripts/pumuki-smoke-installed-wrapper.cjs +31 -0
- package/scripts/ruralgo-s1-evidence-pack-lib.ts +200 -0
- package/scripts/framework-menu-consumer-runtime-evidence-classic.ts +0 -140
|
@@ -14,7 +14,6 @@ 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';
|
|
18
17
|
import type {
|
|
19
18
|
ConsumerRuntimeBlockedGate,
|
|
20
19
|
ConsumerRuntimeNotificationDependencies,
|
|
@@ -57,36 +56,9 @@ export const renderConsumerRuntimeSummary = (
|
|
|
57
56
|
width: resolveLegacyPanelOuterWidth(),
|
|
58
57
|
color: dependencies.useColor(),
|
|
59
58
|
})}\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
|
-
});
|
|
74
59
|
return summary;
|
|
75
60
|
};
|
|
76
61
|
|
|
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
|
-
|
|
90
62
|
export const buildConsumerRuntimeBlockedSummary = (
|
|
91
63
|
blocked: ConsumerRuntimeBlockedGate
|
|
92
64
|
): FrameworkMenuEvidenceSummary => ({
|
|
@@ -144,18 +116,12 @@ export const printConsumerRuntimeEmptyScopeHint = (
|
|
|
144
116
|
}
|
|
145
117
|
if (scope === 'staged') {
|
|
146
118
|
dependencies.write(
|
|
147
|
-
'\nℹ Scope vacío (staged): no hay archivos soportados en staged para auditar. Resultado PASS por alcance vacío; usa 1
|
|
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'
|
|
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'
|
|
154
120
|
);
|
|
155
121
|
return;
|
|
156
122
|
}
|
|
157
123
|
dependencies.write(
|
|
158
|
-
'\nℹ Scope vacío (working tree): no hay archivos soportados en staged/unstaged para auditar. Resultado PASS por alcance vacío; usa 1
|
|
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'
|
|
159
125
|
);
|
|
160
126
|
};
|
|
161
127
|
|
|
@@ -35,9 +35,7 @@ export const createConsumerMenuRuntime = (
|
|
|
35
35
|
runRepoGate: params.runRepoGate,
|
|
36
36
|
runRepoAndStagedGate: params.runRepoAndStagedGate,
|
|
37
37
|
runStagedGate: params.runStagedGate,
|
|
38
|
-
runUnstagedGate: params.runUnstagedGate,
|
|
39
38
|
runWorkingTreeGate: params.runWorkingTreeGate,
|
|
40
|
-
runWorkingTreePreCommitGate: params.runWorkingTreePreCommitGate,
|
|
41
39
|
runPreflight: params.runPreflight,
|
|
42
40
|
emitNotification,
|
|
43
41
|
clearSummaryOverride: () => {
|
|
@@ -33,9 +33,7 @@ export type ConsumerMenuRuntimeParams = {
|
|
|
33
33
|
runRepoGate: () => Promise<ConsumerRuntimeGateResult | void>;
|
|
34
34
|
runRepoAndStagedGate: () => Promise<ConsumerRuntimeGateResult | void>;
|
|
35
35
|
runStagedGate: () => Promise<ConsumerRuntimeGateResult | void>;
|
|
36
|
-
runUnstagedGate: () => Promise<ConsumerRuntimeGateResult | void>;
|
|
37
36
|
runWorkingTreeGate: () => Promise<ConsumerRuntimeGateResult | void>;
|
|
38
|
-
runWorkingTreePreCommitGate: () => Promise<ConsumerRuntimeGateResult | void>;
|
|
39
37
|
runPreflight?: (
|
|
40
38
|
stage: 'PRE_COMMIT' | 'PRE_PUSH'
|
|
41
39
|
) => Promise<string | void> | string | void;
|
|
@@ -49,7 +47,7 @@ export type ConsumerMenuRuntime = {
|
|
|
49
47
|
readCurrentSummary: () => FrameworkMenuEvidenceSummary | null;
|
|
50
48
|
};
|
|
51
49
|
|
|
52
|
-
export type ConsumerRuntimeScope = 'staged' | '
|
|
50
|
+
export type ConsumerRuntimeScope = 'staged' | 'workingTree';
|
|
53
51
|
|
|
54
52
|
export type ConsumerRuntimeSummaryDependencies = {
|
|
55
53
|
repoRoot: string;
|
|
@@ -3,6 +3,5 @@ export type {
|
|
|
3
3
|
EvidenceSeverity,
|
|
4
4
|
FrameworkMenuEvidenceSummary,
|
|
5
5
|
} from './framework-menu-evidence-summary-types';
|
|
6
|
-
export type { ReadEvidenceSummaryForMenuOptions } from './framework-menu-evidence-summary-read';
|
|
7
6
|
export { readEvidenceSummaryForMenu } from './framework-menu-evidence-summary-read';
|
|
8
7
|
export { formatEvidenceSummaryForMenu } from './framework-menu-evidence-summary-format';
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
EvidenceSnapshot,
|
|
3
|
-
FrameworkMenuEvidencePlatformRow,
|
|
4
|
-
FrameworkMenuEvidenceSummary,
|
|
5
|
-
} from './framework-menu-evidence-summary-types';
|
|
1
|
+
import type { FrameworkMenuEvidenceSummary } from './framework-menu-evidence-summary-types';
|
|
6
2
|
import { readEvidenceSummaryFile } from './framework-menu-evidence-summary-file';
|
|
7
3
|
import {
|
|
8
4
|
asFindings,
|
|
@@ -20,55 +16,9 @@ import {
|
|
|
20
16
|
toTopFiles,
|
|
21
17
|
} from './framework-menu-evidence-summary-severity';
|
|
22
18
|
|
|
23
|
-
export type ReadEvidenceSummaryForMenuOptions = {
|
|
24
|
-
topFindingsLimit?: number;
|
|
25
|
-
topFileLocationsLimit?: number;
|
|
26
|
-
topFilesLimit?: number;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const sumLegacySeverityBand = (row: { by_severity?: unknown }): number => {
|
|
30
|
-
const bands = row.by_severity;
|
|
31
|
-
if (!bands || typeof bands !== 'object') {
|
|
32
|
-
return 0;
|
|
33
|
-
}
|
|
34
|
-
const b = bands as Record<string, unknown>;
|
|
35
|
-
const keys = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW'] as const;
|
|
36
|
-
let total = 0;
|
|
37
|
-
for (const key of keys) {
|
|
38
|
-
const value = b[key];
|
|
39
|
-
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
40
|
-
total += value;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return total;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const parsePlatformAuditRows = (
|
|
47
|
-
snapshot: EvidenceSnapshot
|
|
48
|
-
): ReadonlyArray<FrameworkMenuEvidencePlatformRow> => {
|
|
49
|
-
const raw = snapshot.platforms;
|
|
50
|
-
if (!Array.isArray(raw)) {
|
|
51
|
-
return [];
|
|
52
|
-
}
|
|
53
|
-
const rows: FrameworkMenuEvidencePlatformRow[] = [];
|
|
54
|
-
for (const entry of raw) {
|
|
55
|
-
if (!entry || typeof entry !== 'object') {
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
const platform = toStringOrNull((entry as { platform?: unknown }).platform) ?? 'Other';
|
|
59
|
-
const violations = sumLegacySeverityBand(entry as { by_severity?: unknown });
|
|
60
|
-
rows.push({ platform, violations });
|
|
61
|
-
}
|
|
62
|
-
return rows;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
19
|
export const readEvidenceSummaryForMenu = (
|
|
66
|
-
repoRoot: string = process.cwd()
|
|
67
|
-
options?: ReadEvidenceSummaryForMenuOptions
|
|
20
|
+
repoRoot: string = process.cwd()
|
|
68
21
|
): FrameworkMenuEvidenceSummary => {
|
|
69
|
-
const topFindingsLimit = options?.topFindingsLimit ?? 10;
|
|
70
|
-
const topFileLocationsLimit = options?.topFileLocationsLimit ?? 10;
|
|
71
|
-
const topFilesLimit = options?.topFilesLimit ?? 5;
|
|
72
22
|
const evidence = readEvidenceSummaryFile(repoRoot);
|
|
73
23
|
|
|
74
24
|
if (evidence.status === 'missing') {
|
|
@@ -115,13 +65,12 @@ export const readEvidenceSummaryForMenu = (
|
|
|
115
65
|
evidence.snapshot.files_affected ?? evidence.snapshot.filesAffected
|
|
116
66
|
);
|
|
117
67
|
const topFileLocations = countFiles({ findings, repoRoot })
|
|
118
|
-
.slice(0,
|
|
68
|
+
.slice(0, 10)
|
|
119
69
|
.map((entry) => ({
|
|
120
70
|
file: entry.file,
|
|
121
71
|
line: entry.line,
|
|
122
72
|
}));
|
|
123
|
-
const topFindings = buildTopFindings({ findings, repoRoot, maxItems:
|
|
124
|
-
const platformAuditRows = parsePlatformAuditRows(evidence.snapshot);
|
|
73
|
+
const topFindings = buildTopFindings({ findings, repoRoot, maxItems: 10 });
|
|
125
74
|
|
|
126
75
|
return {
|
|
127
76
|
status: 'ok',
|
|
@@ -132,9 +81,8 @@ export const readEvidenceSummaryForMenu = (
|
|
|
132
81
|
filesAffected,
|
|
133
82
|
bySeverity,
|
|
134
83
|
byEnterpriseSeverity,
|
|
135
|
-
topFiles: toTopFiles({ findings, repoRoot
|
|
84
|
+
topFiles: toTopFiles({ findings, repoRoot }),
|
|
136
85
|
topFileLocations,
|
|
137
86
|
topFindings,
|
|
138
|
-
...(platformAuditRows.length > 0 ? { platformAuditRows } : {}),
|
|
139
87
|
};
|
|
140
88
|
};
|
|
@@ -50,9 +50,7 @@ export const countFindingsBySeverity = (
|
|
|
50
50
|
export const toTopFiles = (params: {
|
|
51
51
|
findings: ReadonlyArray<EvidenceFinding>;
|
|
52
52
|
repoRoot: string;
|
|
53
|
-
maxItems?: number;
|
|
54
53
|
}): ReadonlyArray<{ file: string; count: number }> => {
|
|
55
|
-
const maxItems = params.maxItems ?? 5;
|
|
56
54
|
const filesMap = new Map<string, number>();
|
|
57
55
|
for (const finding of params.findings) {
|
|
58
56
|
const rawFile = toStringOrNull(finding.file);
|
|
@@ -68,7 +66,7 @@ export const toTopFiles = (params: {
|
|
|
68
66
|
|
|
69
67
|
return [...filesMap.entries()]
|
|
70
68
|
.sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0]))
|
|
71
|
-
.slice(0,
|
|
69
|
+
.slice(0, 5)
|
|
72
70
|
.map(([file, count]) => ({ file, count }));
|
|
73
71
|
};
|
|
74
72
|
|
|
@@ -18,18 +18,12 @@ export type EvidenceSnapshot = {
|
|
|
18
18
|
stage?: unknown;
|
|
19
19
|
outcome?: unknown;
|
|
20
20
|
findings?: unknown;
|
|
21
|
-
platforms?: unknown;
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
export type EvidenceSeverityMetrics = {
|
|
25
24
|
by_enterprise_severity?: unknown;
|
|
26
25
|
};
|
|
27
26
|
|
|
28
|
-
export type FrameworkMenuEvidencePlatformRow = {
|
|
29
|
-
platform: string;
|
|
30
|
-
violations: number;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
27
|
export type FrameworkMenuEvidenceSummary = {
|
|
34
28
|
status: 'ok' | 'missing' | 'invalid';
|
|
35
29
|
stage: string | null;
|
|
@@ -47,5 +41,4 @@ export type FrameworkMenuEvidenceSummary = {
|
|
|
47
41
|
file: string;
|
|
48
42
|
line: number;
|
|
49
43
|
}>;
|
|
50
|
-
platformAuditRows?: ReadonlyArray<FrameworkMenuEvidencePlatformRow>;
|
|
51
44
|
};
|
|
@@ -9,7 +9,6 @@ export type MenuStage = 'PRE_COMMIT' | 'PRE_PUSH' | 'CI';
|
|
|
9
9
|
|
|
10
10
|
export type MenuScope =
|
|
11
11
|
| { kind: 'staged' }
|
|
12
|
-
| { kind: 'unstaged' }
|
|
13
12
|
| { kind: 'repo' }
|
|
14
13
|
| { kind: 'repoAndStaged' }
|
|
15
14
|
| { kind: 'workingTree' }
|
|
@@ -142,14 +141,6 @@ export const runWorkingTreePrePushGateSilent = async (): Promise<void> => {
|
|
|
142
141
|
await runMenuAuditGate(gateParams);
|
|
143
142
|
};
|
|
144
143
|
|
|
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
|
-
|
|
153
144
|
const runMenuAuditGate = async (
|
|
154
145
|
gateParams: ReturnType<typeof buildMenuGateParams>
|
|
155
146
|
): Promise<void> => {
|
|
@@ -6,11 +6,6 @@ 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
|
-
},
|
|
14
9
|
{
|
|
15
10
|
key: 'export',
|
|
16
11
|
title: 'Legacy Read-Only Export',
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runConsumerMenuMatrix,
|
|
3
3
|
} from './framework-menu-matrix-runner-lib';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type MatrixOptionId,
|
|
4
|
+
import type {
|
|
5
|
+
ConsumerMenuMatrixReport,
|
|
6
|
+
ConsumerMenuMatrixOptionReport,
|
|
7
|
+
MatrixOptionId,
|
|
9
8
|
} from './framework-menu-matrix-evidence-lib';
|
|
10
9
|
|
|
11
10
|
export type MatrixOptionDrift = {
|
|
@@ -23,13 +22,7 @@ export type ConsumerMenuMatrixBaselineReport = {
|
|
|
23
22
|
analysis: ConsumerMenuMatrixBaselineAnalysis;
|
|
24
23
|
};
|
|
25
24
|
|
|
26
|
-
const
|
|
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
|
-
};
|
|
25
|
+
const OPTION_IDS: ReadonlyArray<MatrixOptionId> = ['1', '2', '3', '4', '9'];
|
|
33
26
|
|
|
34
27
|
const OPTION_FIELDS: ReadonlyArray<keyof ConsumerMenuMatrixOptionReport> = [
|
|
35
28
|
'stage',
|
|
@@ -64,12 +57,18 @@ const computeOptionDrift = (
|
|
|
64
57
|
export const analyzeConsumerMenuMatrixBaseline = (
|
|
65
58
|
rounds: ReadonlyArray<ConsumerMenuMatrixReport>
|
|
66
59
|
): ConsumerMenuMatrixBaselineAnalysis => {
|
|
67
|
-
const byOption =
|
|
60
|
+
const byOption = OPTION_IDS.reduce<Record<MatrixOptionId, MatrixOptionDrift>>((acc, optionId) => {
|
|
68
61
|
acc[optionId] = computeOptionDrift(rounds, optionId);
|
|
69
62
|
return acc;
|
|
70
|
-
},
|
|
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
|
+
});
|
|
71
70
|
|
|
72
|
-
const stable =
|
|
71
|
+
const stable = OPTION_IDS.every((optionId) => byOption[optionId].stable);
|
|
73
72
|
|
|
74
73
|
return {
|
|
75
74
|
stable,
|
|
@@ -6,8 +6,6 @@ import {
|
|
|
6
6
|
runRepoAndStagedPrePushGateSilent,
|
|
7
7
|
runRepoGateSilent,
|
|
8
8
|
runStagedGateSilent,
|
|
9
|
-
runUnstagedGateSilent,
|
|
10
|
-
runWorkingTreeGateSilent,
|
|
11
9
|
runWorkingTreePrePushGateSilent,
|
|
12
10
|
} from './framework-menu-gate-lib';
|
|
13
11
|
import { readMatrixOptionReport, type MatrixOptionId } from './framework-menu-matrix-evidence-lib';
|
|
@@ -72,25 +70,6 @@ const runGateByOption = async (option: MatrixOptionId): Promise<void> => {
|
|
|
72
70
|
}
|
|
73
71
|
if (option === '4') {
|
|
74
72
|
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();
|
|
94
73
|
}
|
|
95
74
|
};
|
|
96
75
|
|
|
@@ -125,7 +104,7 @@ export const runConsumerMenuCanary = async (params?: {
|
|
|
125
104
|
scenario.canarySource,
|
|
126
105
|
'utf8'
|
|
127
106
|
);
|
|
128
|
-
if (scenario.option === '1' || scenario.option === '2'
|
|
107
|
+
if (scenario.option === '1' || scenario.option === '2') {
|
|
129
108
|
stageCanaryPath(repoRoot, canaryRelativePath);
|
|
130
109
|
}
|
|
131
110
|
|
|
@@ -8,7 +8,6 @@ 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';
|
|
12
11
|
export { toMatrixOptionReport } from './framework-menu-matrix-evidence-diagnosis';
|
|
13
12
|
|
|
14
13
|
export const readMatrixOptionReport = (
|
|
@@ -1,16 +1,4 @@
|
|
|
1
|
-
export
|
|
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];
|
|
1
|
+
export type MatrixOptionId = '1' | '2' | '3' | '4' | '9';
|
|
14
2
|
export type MatrixOptionDiagnosis =
|
|
15
3
|
| 'scope-empty'
|
|
16
4
|
| 'repo-clean'
|
|
@@ -3,8 +3,6 @@ import {
|
|
|
3
3
|
runRepoAndStagedPrePushGateSilent,
|
|
4
4
|
runRepoGateSilent,
|
|
5
5
|
runStagedGateSilent,
|
|
6
|
-
runUnstagedGateSilent,
|
|
7
|
-
runWorkingTreeGateSilent,
|
|
8
6
|
runWorkingTreePrePushGateSilent,
|
|
9
7
|
} from './framework-menu-gate-lib';
|
|
10
8
|
import {
|
|
@@ -26,8 +24,6 @@ export type ConsumerMenuMatrixRunnerDependencies = {
|
|
|
26
24
|
runRepoGateSilent: () => Promise<void>;
|
|
27
25
|
runRepoAndStagedPrePushGateSilent: () => Promise<void>;
|
|
28
26
|
runStagedGateSilent: () => Promise<void>;
|
|
29
|
-
runUnstagedGateSilent: () => Promise<void>;
|
|
30
|
-
runWorkingTreeGateSilent: () => Promise<void>;
|
|
31
27
|
runWorkingTreePrePushGateSilent: () => Promise<void>;
|
|
32
28
|
readMatrixOptionReport: (repoRoot: string, optionId: MatrixOptionId) => ConsumerMenuMatrixOptionReport;
|
|
33
29
|
};
|
|
@@ -36,8 +32,6 @@ const createDefaultDependencies = (): ConsumerMenuMatrixRunnerDependencies => ({
|
|
|
36
32
|
runRepoGateSilent,
|
|
37
33
|
runRepoAndStagedPrePushGateSilent,
|
|
38
34
|
runStagedGateSilent,
|
|
39
|
-
runUnstagedGateSilent,
|
|
40
|
-
runWorkingTreeGateSilent,
|
|
41
35
|
runWorkingTreePrePushGateSilent,
|
|
42
36
|
readMatrixOptionReport,
|
|
43
37
|
});
|
|
@@ -90,31 +84,6 @@ export const runConsumerMenuMatrix = async (params?: {
|
|
|
90
84
|
}
|
|
91
85
|
})();
|
|
92
86
|
|
|
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
|
-
|
|
118
87
|
return {
|
|
119
88
|
byOption: {
|
|
120
89
|
'1': option1,
|
|
@@ -122,10 +91,6 @@ export const runConsumerMenuMatrix = async (params?: {
|
|
|
122
91
|
'3': option3,
|
|
123
92
|
'4': option4,
|
|
124
93
|
'9': option9,
|
|
125
|
-
'11': option11,
|
|
126
|
-
'12': option12,
|
|
127
|
-
'13': option13,
|
|
128
|
-
'14': option14,
|
|
129
94
|
},
|
|
130
95
|
};
|
|
131
96
|
} finally {
|
|
@@ -5,7 +5,6 @@ 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';
|
|
9
8
|
import { resolveBlockedDialogEnabled } from './framework-menu-system-notifications-macos-dialog-enabled';
|
|
10
9
|
import { emitMacOsBannerStage } from './framework-menu-system-notifications-macos-banner-stage';
|
|
11
10
|
import { emitMacOsBlockedDialogStage } from './framework-menu-system-notifications-macos-blocked-stage';
|
|
@@ -20,9 +19,6 @@ const shouldSkipMacOsBannerForInteractiveBlockedDialog = (params: {
|
|
|
20
19
|
config: SystemNotificationsConfig;
|
|
21
20
|
env: NodeJS.ProcessEnv;
|
|
22
21
|
}): boolean => {
|
|
23
|
-
if (!isTruthyEnvValue(params.env.PUMUKI_MACOS_GATE_BLOCKED_BANNER_DEDUPE)) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
22
|
if (params.event.kind !== 'gate.blocked') {
|
|
27
23
|
return false;
|
|
28
24
|
}
|
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
runWorkingTreeGateSilent,
|
|
17
17
|
runRepoAndStagedPrePushGateSilent,
|
|
18
18
|
runWorkingTreePrePushGateSilent,
|
|
19
|
-
runUnstagedGateSilent,
|
|
20
19
|
} from './framework-menu-gate-lib';
|
|
21
20
|
import { createFrameworkMenuPrompts } from './framework-menu-prompts';
|
|
22
21
|
import { resolveDefaultRangeFrom } from './framework-menu-runners';
|
|
@@ -63,9 +62,7 @@ const menu = async (): Promise<void> => {
|
|
|
63
62
|
runRepoGate: runRepoGateSilent,
|
|
64
63
|
runRepoAndStagedGate: runRepoAndStagedPrePushGateSilent,
|
|
65
64
|
runStagedGate: runStagedGateSilent,
|
|
66
|
-
runUnstagedGate: runUnstagedGateSilent,
|
|
67
65
|
runWorkingTreeGate: runWorkingTreePrePushGateSilent,
|
|
68
|
-
runWorkingTreePreCommitGate: runWorkingTreeGateSilent,
|
|
69
66
|
write: (text) => {
|
|
70
67
|
output.write(text);
|
|
71
68
|
},
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { dirname, join } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
|
|
4
|
+
export type SmokeBinStrategy = 'source' | 'installed';
|
|
5
|
+
|
|
6
|
+
export const resolveBinStrategy = (raw: string | undefined): SmokeBinStrategy => {
|
|
7
|
+
const normalized = (raw ?? 'source').trim().toLowerCase();
|
|
8
|
+
if (normalized === 'installed' || normalized === 'consumer') {
|
|
9
|
+
return 'installed';
|
|
10
|
+
}
|
|
11
|
+
return 'source';
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type SmokeLayout = {
|
|
15
|
+
pumukiPackageRoot: string;
|
|
16
|
+
smokeCwd: string;
|
|
17
|
+
binStrategy: SmokeBinStrategy;
|
|
18
|
+
binRoot: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const resolveSmokeLayout = (params: {
|
|
22
|
+
scriptFileUrl: string;
|
|
23
|
+
env: NodeJS.ProcessEnv;
|
|
24
|
+
}): SmokeLayout => {
|
|
25
|
+
const pumukiPackageRoot = join(dirname(fileURLToPath(params.scriptFileUrl)), '..');
|
|
26
|
+
const smokeCwd =
|
|
27
|
+
(params.env.PUMUKI_SMOKE_REPO_ROOT ?? pumukiPackageRoot).trim() || pumukiPackageRoot;
|
|
28
|
+
const binStrategy = resolveBinStrategy(params.env.PUMUKI_SMOKE_BIN_STRATEGY);
|
|
29
|
+
const binRoot =
|
|
30
|
+
binStrategy === 'installed'
|
|
31
|
+
? join(smokeCwd, 'node_modules', 'pumuki')
|
|
32
|
+
: pumukiPackageRoot;
|
|
33
|
+
return { pumukiPackageRoot, smokeCwd, binStrategy, binRoot };
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const installedBinMarkerPath = (layout: SmokeLayout): string =>
|
|
37
|
+
join(layout.binRoot, 'bin', 'pumuki.js');
|