pumuki 6.3.97 → 6.3.99
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/AGENTS.md +269 -0
- package/CHANGELOG.md +697 -0
- package/README.md +4 -2
- package/VERSION +1 -1
- package/docs/README.md +13 -9
- package/docs/operations/RELEASE_NOTES.md +12 -76
- package/docs/product/HOW_IT_WORKS.md +6 -0
- package/docs/product/INSTALLATION.md +1 -1
- package/docs/product/USAGE.md +41 -4
- package/docs/tracking/plan-curso-pumuki-stack-my-architecture.md +118 -0
- package/docs/validation/README.md +6 -3
- package/integrations/config/skillsCustomRules.ts +18 -99
- package/integrations/evidence/buildEvidence.ts +0 -24
- package/integrations/evidence/repoState.ts +0 -3
- package/integrations/evidence/schema.ts +0 -18
- package/integrations/evidence/writeEvidence.ts +0 -24
- package/integrations/gate/evaluateAiGate.ts +15 -232
- package/integrations/gate/remediationCatalog.ts +0 -8
- package/integrations/git/GitService.ts +44 -5
- package/integrations/git/aiGateRepoPolicyFindings.ts +0 -4
- package/integrations/git/runPlatformGate.ts +1 -9
- package/integrations/git/runPlatformGateFacts.ts +19 -1
- package/integrations/git/runPlatformGateOutput.ts +27 -36
- package/integrations/lifecycle/adapter.templates.json +7 -13
- package/integrations/lifecycle/adapter.ts +0 -24
- package/integrations/lifecycle/artifacts.ts +1 -6
- package/integrations/lifecycle/audit.ts +101 -0
- package/integrations/lifecycle/cli.ts +110 -70
- package/integrations/lifecycle/cliSdd.ts +13 -8
- package/integrations/lifecycle/doctor.ts +16 -48
- package/integrations/lifecycle/hookManager.ts +0 -77
- package/integrations/lifecycle/index.ts +2 -0
- package/integrations/lifecycle/install.ts +0 -21
- package/integrations/lifecycle/npmService.ts +3 -155
- package/integrations/lifecycle/policyValidationSnapshot.ts +8 -2
- package/integrations/lifecycle/preWriteAutomation.ts +7 -77
- package/integrations/lifecycle/state.ts +1 -8
- package/integrations/lifecycle/status.ts +2 -29
- package/integrations/mcp/aiGateCheck.ts +26 -206
- package/integrations/mcp/autoExecuteAiStart.ts +87 -94
- package/integrations/mcp/enterpriseServer.ts +7 -23
- package/integrations/mcp/enterpriseStdioServer.cli.ts +4 -31
- package/integrations/mcp/preFlightCheck.ts +5 -51
- package/integrations/platform/detectPlatforms.ts +37 -0
- package/integrations/policy/experimentalFeatures.ts +1 -1
- package/integrations/sdd/evidenceScaffold.ts +2 -109
- package/package.json +10 -2
- package/scripts/check-tracking-single-active.sh +1 -1
- package/scripts/consumer-menu-matrix-baseline-report-lib.ts +13 -38
- package/scripts/consumer-postinstall-resolve-args.cjs +44 -0
- package/scripts/consumer-postinstall.cjs +76 -21
- package/scripts/framework-menu-advanced-view-lib.ts +0 -15
- package/scripts/framework-menu-consumer-actions-lib.ts +28 -4
- package/scripts/framework-menu-consumer-preflight-hints.ts +5 -2
- package/scripts/framework-menu-consumer-preflight-render.ts +0 -10
- package/scripts/framework-menu-consumer-preflight-run.ts +0 -23
- package/scripts/framework-menu-consumer-preflight-types.ts +0 -12
- package/scripts/framework-menu-consumer-runtime-actions.ts +87 -17
- package/scripts/framework-menu-consumer-runtime-audit.ts +36 -2
- package/scripts/framework-menu-consumer-runtime-evidence-classic.ts +140 -0
- package/scripts/framework-menu-consumer-runtime-lib.ts +2 -10
- package/scripts/framework-menu-consumer-runtime-menu.ts +4 -18
- package/scripts/framework-menu-consumer-runtime-types.ts +3 -3
- package/scripts/framework-menu-evidence-summary-lib.ts +1 -0
- package/scripts/framework-menu-evidence-summary-read.ts +57 -5
- package/scripts/framework-menu-evidence-summary-severity.ts +3 -1
- package/scripts/framework-menu-evidence-summary-types.ts +7 -0
- package/scripts/framework-menu-gate-lib.ts +9 -0
- package/scripts/framework-menu-layout-data.ts +5 -0
- package/scripts/framework-menu-matrix-baseline-lib.ts +15 -14
- package/scripts/framework-menu-matrix-canary-lib.ts +22 -1
- package/scripts/framework-menu-matrix-evidence-lib.ts +1 -0
- package/scripts/framework-menu-matrix-evidence-types.ts +13 -1
- package/scripts/framework-menu-matrix-runner-lib.ts +35 -0
- package/scripts/framework-menu-system-notifications-cause.ts +0 -24
- package/scripts/framework-menu-system-notifications-macos-swift-source.ts +24 -204
- package/scripts/framework-menu-system-notifications-macos.ts +4 -0
- package/scripts/framework-menu-system-notifications-payloads-blocked.ts +1 -1
- package/scripts/framework-menu-system-notifications-remediation.ts +13 -24
- package/scripts/framework-menu-system-notifications-text.ts +1 -7
- package/scripts/framework-menu.ts +3 -2
- package/scripts/package-install-smoke-consumer-git-repo-lib.ts +1 -10
- package/scripts/package-install-smoke-consumer-npm-lib.ts +9 -46
- package/scripts/pumuki-full-surface-smoke-lib.ts +37 -0
- package/scripts/pumuki-full-surface-smoke.ts +346 -0
- package/scripts/pumuki-smoke-installed-wrapper.cjs +31 -0
- package/integrations/evidence/trackingContract.ts +0 -150
- package/integrations/gate/governanceActionCatalog.ts +0 -275
- package/integrations/lifecycle/bootstrapManifest.ts +0 -248
- package/integrations/lifecycle/cliGovernanceConsole.ts +0 -69
- package/integrations/lifecycle/governanceNextAction.ts +0 -164
- package/integrations/lifecycle/governanceObservationSnapshot.ts +0 -613
- package/integrations/mcp/alignedPlatformGate.ts +0 -232
- package/integrations/mcp/readMcpPrePushStdin.ts +0 -7
- package/scripts/build-ruralgo-s1-evidence-pack.ts +0 -85
- package/scripts/ruralgo-s1-evidence-pack-lib.ts +0 -200
|
@@ -19,6 +19,11 @@ export type GateScope =
|
|
|
19
19
|
kind: 'workingTree';
|
|
20
20
|
extensions?: string[];
|
|
21
21
|
}
|
|
22
|
+
| {
|
|
23
|
+
kind: 'unstaged';
|
|
24
|
+
extensions?: string[];
|
|
25
|
+
includeUntracked?: boolean;
|
|
26
|
+
}
|
|
22
27
|
| {
|
|
23
28
|
kind: 'range';
|
|
24
29
|
fromRef: string;
|
|
@@ -26,7 +31,17 @@ export type GateScope =
|
|
|
26
31
|
extensions?: string[];
|
|
27
32
|
};
|
|
28
33
|
|
|
29
|
-
const
|
|
34
|
+
export const DEFAULT_FACT_FILE_EXTENSIONS: ReadonlyArray<string> = [
|
|
35
|
+
'.swift',
|
|
36
|
+
'.ts',
|
|
37
|
+
'.tsx',
|
|
38
|
+
'.js',
|
|
39
|
+
'.jsx',
|
|
40
|
+
'.kt',
|
|
41
|
+
'.kts',
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const DEFAULT_EXTENSIONS = DEFAULT_FACT_FILE_EXTENSIONS;
|
|
30
45
|
|
|
31
46
|
export const countScannedFilesFromFacts = (facts: ReadonlyArray<Fact>): number => {
|
|
32
47
|
const contentPaths = new Set<string>();
|
|
@@ -66,6 +81,9 @@ export const resolveFactsForGateScope = async (params: {
|
|
|
66
81
|
if (params.scope.kind === 'workingTree') {
|
|
67
82
|
return params.git.getStagedAndUnstagedFacts(extensions);
|
|
68
83
|
}
|
|
84
|
+
if (params.scope.kind === 'unstaged') {
|
|
85
|
+
return params.git.getUnstagedFacts(extensions, params.scope.includeUntracked);
|
|
86
|
+
}
|
|
69
87
|
|
|
70
88
|
return getFactsForCommitRange({
|
|
71
89
|
fromRef: params.scope.fromRef,
|
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
import type { Finding } from '../../core/gate/Finding';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
const BLOCK_NEXT_ACTION_BY_CODE: Readonly<Record<string, string>> = {
|
|
4
|
+
SDD_SESSION_MISSING:
|
|
5
|
+
'npx --yes --package pumuki@latest pumuki sdd session --open --change=<id>',
|
|
6
|
+
SDD_SESSION_INVALID:
|
|
7
|
+
'npx --yes --package pumuki@latest pumuki sdd session --refresh --ttl-minutes=90',
|
|
8
|
+
PRE_PUSH_UPSTREAM_MISSING:
|
|
9
|
+
'git push --set-upstream origin <branch>',
|
|
10
|
+
PRE_PUSH_UPSTREAM_MISALIGNED:
|
|
11
|
+
'git branch --unset-upstream && git push --set-upstream origin <branch>',
|
|
12
|
+
EVIDENCE_STALE:
|
|
13
|
+
'npx --yes --package pumuki@latest pumuki-pre-commit',
|
|
14
|
+
EVIDENCE_BRANCH_MISMATCH:
|
|
15
|
+
'npx --yes --package pumuki@latest pumuki-pre-commit',
|
|
16
|
+
GIT_ATOMICITY_TOO_MANY_FILES:
|
|
17
|
+
'git restore --staged . && separa cambios en commits más pequeños',
|
|
18
|
+
GIT_ATOMICITY_TOO_MANY_SCOPES:
|
|
19
|
+
'Revisa scope_files del bloqueo y aplica: git restore --staged . && git add <scope>/ && git commit -m "<tipo>: <scope>"',
|
|
20
|
+
ACTIVE_RULE_IDS_EMPTY_FOR_CODE_CHANGES_HIGH:
|
|
21
|
+
'Reconcilia policy/skills y reintenta PRE_COMMIT: npx --yes --package pumuki@latest pumuki policy reconcile --strict --json && npx --yes --package pumuki@latest pumuki-pre-commit',
|
|
22
|
+
SKILLS_SKILLS_FRONTEND_NO_SOLID_VIOLATIONS:
|
|
23
|
+
'Aplica refactor incremental: extrae 1 componente/hook por commit y vuelve a ejecutar PRE_COMMIT.',
|
|
24
|
+
};
|
|
3
25
|
|
|
4
26
|
const severityWeight = (severity: string): number => {
|
|
5
27
|
switch (severity.toUpperCase()) {
|
|
@@ -72,49 +94,18 @@ const formatFinding = (finding: Finding): string => {
|
|
|
72
94
|
return `[${severity}] ${finding.ruleId}: ${finding.message} -> ${location}`;
|
|
73
95
|
};
|
|
74
96
|
|
|
75
|
-
const
|
|
76
|
-
switch (code) {
|
|
77
|
-
case 'GIT_ATOMICITY_TOO_MANY_FILES':
|
|
78
|
-
return 'git restore --staged . && separa cambios en commits más pequeños';
|
|
79
|
-
case 'GIT_ATOMICITY_TOO_MANY_SCOPES':
|
|
80
|
-
return 'Revisa scope_files del bloqueo y aplica: git restore --staged . && git add <scope>/ && git commit -m "<tipo>: <scope>"';
|
|
81
|
-
default:
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export const printGateFindings = (
|
|
87
|
-
findings: ReadonlyArray<Finding>,
|
|
88
|
-
params?: { stage?: 'PRE_COMMIT' | 'PRE_PUSH' | 'CI' }
|
|
89
|
-
): void => {
|
|
97
|
+
export const printGateFindings = (findings: ReadonlyArray<Finding>): void => {
|
|
90
98
|
if (findings.length === 0) {
|
|
91
99
|
return;
|
|
92
100
|
}
|
|
93
101
|
const primary = resolvePrimaryFinding(findings);
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
fallback: {
|
|
98
|
-
reason_code: primary.code,
|
|
99
|
-
instruction: 'Corrige el bloqueante primario y vuelve a ejecutar la validación del stage actual.',
|
|
100
|
-
next_action: {
|
|
101
|
-
kind: 'info',
|
|
102
|
-
message:
|
|
103
|
-
resolveAtomicityFallback(primary.code)
|
|
104
|
-
?? 'Corrige el bloqueante primario y vuelve a ejecutar el mismo comando.',
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
});
|
|
108
|
-
const nextAction = action.next_action.command ?? action.next_action.message;
|
|
102
|
+
const nextAction =
|
|
103
|
+
BLOCK_NEXT_ACTION_BY_CODE[primary.code]
|
|
104
|
+
?? 'Corrige el bloqueante primario y vuelve a ejecutar el mismo comando.';
|
|
109
105
|
process.stdout.write(
|
|
110
106
|
`[pumuki][block-summary] primary=${primary.code} severity=${primary.severity.toUpperCase()} rule=${primary.ruleId}\n`
|
|
111
107
|
);
|
|
112
|
-
process.stdout.write(`[pumuki][block-summary] reason_code=${action.reason_code}\n`);
|
|
113
|
-
process.stdout.write(`[pumuki][block-summary] instruction=${action.instruction}\n`);
|
|
114
108
|
process.stdout.write(`[pumuki][block-summary] next_action=${nextAction}\n`);
|
|
115
|
-
if (action.next_action.command) {
|
|
116
|
-
process.stdout.write(`[pumuki][block-summary] command=${action.next_action.command}\n`);
|
|
117
|
-
}
|
|
118
109
|
for (const finding of findings) {
|
|
119
110
|
process.stdout.write(`${formatFinding(finding)}\n`);
|
|
120
111
|
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"mcp": {
|
|
21
21
|
"enterprise": {
|
|
22
|
-
"command": "
|
|
22
|
+
"command": "npx --yes --package pumuki@latest pumuki-mcp-enterprise-stdio"
|
|
23
23
|
},
|
|
24
24
|
"evidence": {
|
|
25
25
|
"command": "npx --yes --package pumuki@latest pumuki-mcp-evidence-stdio"
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"repo": [
|
|
32
32
|
{
|
|
33
33
|
"path": ".pumuki/adapter.json",
|
|
34
|
+
"mode": "json-merge",
|
|
34
35
|
"payload": {
|
|
35
36
|
"hooks": {
|
|
36
37
|
"pre_write": {
|
|
@@ -48,7 +49,7 @@
|
|
|
48
49
|
},
|
|
49
50
|
"mcp": {
|
|
50
51
|
"enterprise": {
|
|
51
|
-
"command": "
|
|
52
|
+
"command": "npx --yes --package pumuki@latest pumuki-mcp-enterprise-stdio"
|
|
52
53
|
},
|
|
53
54
|
"evidence": {
|
|
54
55
|
"command": "npx --yes --package pumuki@latest pumuki-mcp-evidence-stdio"
|
|
@@ -85,10 +86,7 @@
|
|
|
85
86
|
"--package",
|
|
86
87
|
"pumuki@latest",
|
|
87
88
|
"pumuki-mcp-enterprise-stdio"
|
|
88
|
-
]
|
|
89
|
-
"env": {
|
|
90
|
-
"PUMUKI_EXPERIMENTAL_MCP_ENTERPRISE": "advisory"
|
|
91
|
-
}
|
|
89
|
+
]
|
|
92
90
|
},
|
|
93
91
|
"pumuki-evidence": {
|
|
94
92
|
"command": "npx",
|
|
@@ -116,10 +114,7 @@
|
|
|
116
114
|
"--package",
|
|
117
115
|
"pumuki@latest",
|
|
118
116
|
"pumuki-mcp-enterprise-stdio"
|
|
119
|
-
]
|
|
120
|
-
"env": {
|
|
121
|
-
"PUMUKI_EXPERIMENTAL_MCP_ENTERPRISE": "advisory"
|
|
122
|
-
}
|
|
117
|
+
]
|
|
123
118
|
},
|
|
124
119
|
"pumuki-evidence": {
|
|
125
120
|
"command": "npx",
|
|
@@ -183,7 +178,7 @@
|
|
|
183
178
|
"postCommand": "npx --yes --package pumuki@latest pumuki-pre-commit",
|
|
184
179
|
"pushCommand": "npx --yes --package pumuki@latest pumuki-pre-push",
|
|
185
180
|
"ciCommand": "npx --yes --package pumuki@latest pumuki-ci",
|
|
186
|
-
"mcpCommand": "
|
|
181
|
+
"mcpCommand": "npx --yes --package pumuki@latest pumuki-mcp-enterprise-stdio"
|
|
187
182
|
}
|
|
188
183
|
},
|
|
189
184
|
{
|
|
@@ -201,7 +196,6 @@
|
|
|
201
196
|
],
|
|
202
197
|
"disabledTools": [],
|
|
203
198
|
"env": {
|
|
204
|
-
"PUMUKI_EXPERIMENTAL_MCP_ENTERPRISE": "advisory",
|
|
205
199
|
"PUMUKI_ENTERPRISE_MCP_PORT": "0",
|
|
206
200
|
"PUMUKI_ENTERPRISE_MCP_HOST": "127.0.0.1"
|
|
207
201
|
},
|
|
@@ -247,7 +241,7 @@
|
|
|
247
241
|
},
|
|
248
242
|
"mcp": {
|
|
249
243
|
"enterprise": {
|
|
250
|
-
"command": "
|
|
244
|
+
"command": "npx --yes --package pumuki@latest pumuki-mcp-enterprise-stdio"
|
|
251
245
|
},
|
|
252
246
|
"evidence": {
|
|
253
247
|
"command": "npx --yes --package pumuki@latest pumuki-mcp-evidence-stdio"
|
|
@@ -2,7 +2,6 @@ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
3
|
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
4
4
|
import { LifecycleGitService, type ILifecycleGitService } from './gitService';
|
|
5
|
-
import { writeLifecycleBootstrapManifest } from './bootstrapManifest';
|
|
6
5
|
|
|
7
6
|
export type AdapterAgent = string;
|
|
8
7
|
|
|
@@ -12,10 +11,6 @@ export type LifecycleAdapterInstallResult = {
|
|
|
12
11
|
dryRun: boolean;
|
|
13
12
|
written: boolean;
|
|
14
13
|
changedFiles: ReadonlyArray<string>;
|
|
15
|
-
bootstrapManifest: {
|
|
16
|
-
path: string;
|
|
17
|
-
changed: boolean;
|
|
18
|
-
};
|
|
19
14
|
};
|
|
20
15
|
|
|
21
16
|
type AdapterTemplate = {
|
|
@@ -159,30 +154,11 @@ export const runLifecycleAdapterInstall = (params: {
|
|
|
159
154
|
writeFileSync(absolutePath, nextContents, 'utf8');
|
|
160
155
|
}
|
|
161
156
|
|
|
162
|
-
let bootstrapManifest = {
|
|
163
|
-
path: join(repoRoot, '.pumuki', 'bootstrap-manifest.json'),
|
|
164
|
-
changed: false,
|
|
165
|
-
};
|
|
166
|
-
if (!dryRun) {
|
|
167
|
-
const manifestWrite = writeLifecycleBootstrapManifest({
|
|
168
|
-
git,
|
|
169
|
-
repoRoot,
|
|
170
|
-
});
|
|
171
|
-
bootstrapManifest = {
|
|
172
|
-
path: manifestWrite.path,
|
|
173
|
-
changed: manifestWrite.changed,
|
|
174
|
-
};
|
|
175
|
-
if (manifestWrite.changed) {
|
|
176
|
-
changedFiles.push('.pumuki/bootstrap-manifest.json');
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
157
|
return {
|
|
181
158
|
repoRoot,
|
|
182
159
|
agent: params.agent,
|
|
183
160
|
dryRun,
|
|
184
161
|
written: !dryRun,
|
|
185
162
|
changedFiles,
|
|
186
|
-
bootstrapManifest,
|
|
187
163
|
};
|
|
188
164
|
};
|
|
@@ -11,12 +11,7 @@ import {
|
|
|
11
11
|
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
12
12
|
import type { ILifecycleGitService } from './gitService';
|
|
13
13
|
|
|
14
|
-
const PUMUKI_ARTIFACTS = [
|
|
15
|
-
'.ai_evidence.json',
|
|
16
|
-
'.AI_EVIDENCE.json',
|
|
17
|
-
'.pumuki/adapter.json',
|
|
18
|
-
'.pumuki/bootstrap-manifest.json',
|
|
19
|
-
] as const;
|
|
14
|
+
const PUMUKI_ARTIFACTS = ['.ai_evidence.json', '.AI_EVIDENCE.json'] as const;
|
|
20
15
|
const RUNTIME_ARTIFACT_IGNORE_ENTRIES = [...PUMUKI_ARTIFACTS, '.pumuki/'] as const;
|
|
21
16
|
const RUNTIME_ARTIFACT_IGNORE_BEGIN = '# >>> pumuki-runtime-artifacts >>>';
|
|
22
17
|
const RUNTIME_ARTIFACT_IGNORE_END = '# <<< pumuki-runtime-artifacts <<<';
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { readEvidence } from '../evidence/readEvidence';
|
|
2
|
+
import { GitService } from '../git/GitService';
|
|
3
|
+
import { hasAllowedExtension } from '../git/gitDiffUtils';
|
|
4
|
+
import { runPlatformGate } from '../git/runPlatformGate';
|
|
5
|
+
import { evaluatePlatformGateFindings } from '../git/runPlatformGateEvaluation';
|
|
6
|
+
import { DEFAULT_FACT_FILE_EXTENSIONS } from '../git/runPlatformGateFacts';
|
|
7
|
+
import { resolvePolicyForStage } from '../gate/stagePolicies';
|
|
8
|
+
|
|
9
|
+
export type LifecycleAuditStage = 'PRE_COMMIT' | 'PRE_PUSH' | 'CI';
|
|
10
|
+
|
|
11
|
+
export type LifecycleAuditResult = {
|
|
12
|
+
command: 'pumuki audit';
|
|
13
|
+
repo_root: string;
|
|
14
|
+
stage: LifecycleAuditStage;
|
|
15
|
+
scope: { kind: 'repo' };
|
|
16
|
+
audit_mode: 'gate' | 'engine';
|
|
17
|
+
gate_exit_code: number;
|
|
18
|
+
files_scanned: number | null;
|
|
19
|
+
untracked_matching_extensions_count: number;
|
|
20
|
+
snapshot_outcome: string | null;
|
|
21
|
+
policy_reconcile_hint: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const POLICY_RECONCILE_HINT =
|
|
25
|
+
'If .pumuki/policy-as-code.json signatures drift after a pumuki upgrade, run: pumuki policy reconcile --apply';
|
|
26
|
+
|
|
27
|
+
const countUntrackedMatchingExtensions = (
|
|
28
|
+
git: GitService,
|
|
29
|
+
extensions: ReadonlyArray<string>
|
|
30
|
+
): number => {
|
|
31
|
+
const repoRoot = git.resolveRepoRoot();
|
|
32
|
+
const raw = git.runGit(['ls-files', '--others', '--exclude-standard'], repoRoot);
|
|
33
|
+
return raw
|
|
34
|
+
.split('\n')
|
|
35
|
+
.map((line) => line.trim())
|
|
36
|
+
.filter((line) => line.length > 0)
|
|
37
|
+
.filter((path) => hasAllowedExtension(path, extensions)).length;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const runLifecycleAudit = async (params: {
|
|
41
|
+
stage: LifecycleAuditStage;
|
|
42
|
+
auditMode: 'gate' | 'engine';
|
|
43
|
+
}): Promise<LifecycleAuditResult> => {
|
|
44
|
+
const git = new GitService();
|
|
45
|
+
const repoRoot = git.resolveRepoRoot();
|
|
46
|
+
const resolved = resolvePolicyForStage(params.stage, repoRoot);
|
|
47
|
+
const extensions = DEFAULT_FACT_FILE_EXTENSIONS;
|
|
48
|
+
const untrackedMatchingExtensionsCount = countUntrackedMatchingExtensions(git, extensions);
|
|
49
|
+
|
|
50
|
+
const gateParams =
|
|
51
|
+
params.auditMode === 'engine'
|
|
52
|
+
? {
|
|
53
|
+
policy: resolved.policy,
|
|
54
|
+
policyTrace: resolved.trace,
|
|
55
|
+
scope: { kind: 'repo' as const },
|
|
56
|
+
silent: true,
|
|
57
|
+
auditMode: 'engine' as const,
|
|
58
|
+
dependencies: {
|
|
59
|
+
evaluatePlatformGateFindings: (
|
|
60
|
+
evalParams: Parameters<typeof evaluatePlatformGateFindings>[0]
|
|
61
|
+
) =>
|
|
62
|
+
evaluatePlatformGateFindings(evalParams, {
|
|
63
|
+
loadHeuristicsConfig: () => ({
|
|
64
|
+
astSemanticEnabled: true,
|
|
65
|
+
typeScriptScope: 'all',
|
|
66
|
+
}),
|
|
67
|
+
}),
|
|
68
|
+
printGateFindings: () => {},
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
: {
|
|
72
|
+
policy: resolved.policy,
|
|
73
|
+
policyTrace: resolved.trace,
|
|
74
|
+
scope: { kind: 'repo' as const },
|
|
75
|
+
silent: true,
|
|
76
|
+
auditMode: 'gate' as const,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const gateExitCode = await runPlatformGate(gateParams);
|
|
80
|
+
const evidence = readEvidence(repoRoot);
|
|
81
|
+
const filesScanned =
|
|
82
|
+
typeof evidence?.snapshot.files_scanned === 'number' &&
|
|
83
|
+
Number.isFinite(evidence.snapshot.files_scanned)
|
|
84
|
+
? evidence.snapshot.files_scanned
|
|
85
|
+
: null;
|
|
86
|
+
const snapshotOutcome =
|
|
87
|
+
typeof evidence?.snapshot.outcome === 'string' ? evidence.snapshot.outcome : null;
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
command: 'pumuki audit',
|
|
91
|
+
repo_root: repoRoot,
|
|
92
|
+
stage: params.stage,
|
|
93
|
+
scope: { kind: 'repo' },
|
|
94
|
+
audit_mode: params.auditMode,
|
|
95
|
+
gate_exit_code: gateExitCode,
|
|
96
|
+
files_scanned: filesScanned,
|
|
97
|
+
untracked_matching_extensions_count: untrackedMatchingExtensionsCount,
|
|
98
|
+
snapshot_outcome: snapshotOutcome,
|
|
99
|
+
policy_reconcile_hint: POLICY_RECONCILE_HINT,
|
|
100
|
+
};
|
|
101
|
+
};
|