pumuki 6.3.348 → 6.3.350

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.
@@ -228,6 +228,7 @@ const normalizeScopedRuleEngineFindings = (params: {
228
228
  scope: GateScope;
229
229
  stage: GatePolicy['stage'];
230
230
  changedLinesByPath: ReadonlyMap<string, ReadonlySet<number>>;
231
+ stagedPaths: ReadonlyArray<string>;
231
232
  }): ReadonlyArray<Finding> => {
232
233
  if (
233
234
  (params.scope.kind !== 'staged' && params.scope.kind !== 'repoAndStaged') ||
@@ -236,10 +237,17 @@ const normalizeScopedRuleEngineFindings = (params: {
236
237
  return params.findings;
237
238
  }
238
239
 
240
+ const stagedPathSet = new Set(params.stagedPaths.map(toNormalizedPath));
239
241
  return params.findings.map((finding) => {
240
242
  if (!isAstRuleFinding(finding)) {
241
243
  return finding;
242
244
  }
245
+ const outsideStagedFileSet =
246
+ params.scope.kind === 'staged' &&
247
+ params.stagedPaths.length > 0 &&
248
+ typeof finding.filePath === 'string' &&
249
+ finding.filePath.length > 0 &&
250
+ !stagedPathSet.has(toNormalizedPath(finding.filePath));
243
251
  const outsideChangedLines = isFindingOutsideChangedLines(
244
252
  finding,
245
253
  params.changedLinesByPath
@@ -248,7 +256,7 @@ const normalizeScopedRuleEngineFindings = (params: {
248
256
  finding,
249
257
  params.changedLinesByPath
250
258
  );
251
- if (!outsideChangedLines && !tooBroadForDiffBlock) {
259
+ if (!outsideStagedFileSet && !outsideChangedLines && !tooBroadForDiffBlock) {
252
260
  return finding;
253
261
  }
254
262
  return {
@@ -257,12 +265,16 @@ const normalizeScopedRuleEngineFindings = (params: {
257
265
  severity: 'INFO',
258
266
  message:
259
267
  `${finding.message} ` +
260
- (tooBroadForDiffBlock
261
- ? 'Finding is file-level/broad and cannot prove the violation was introduced by the staged diff; tracked as advisory for this atomic slice.'
262
- : 'Baseline brownfield outside the staged diff; tracked as advisory for this atomic slice.'),
268
+ (outsideStagedFileSet
269
+ ? 'Baseline brownfield outside the staged file set; tracked as advisory for this atomic slice.'
270
+ : tooBroadForDiffBlock
271
+ ? 'Finding is file-level/broad and cannot prove the violation was introduced by the staged diff; tracked as advisory for this atomic slice.'
272
+ : 'Baseline brownfield outside the staged diff; tracked as advisory for this atomic slice.'),
263
273
  expected_fix:
264
274
  finding.expected_fix ??
265
- (tooBroadForDiffBlock
275
+ (outsideStagedFileSet
276
+ ? 'Plan a dedicated brownfield remediation slice for the non-staged file, or include it explicitly in the atomic commit.'
277
+ : tooBroadForDiffBlock
266
278
  ? 'Emit a precise AST/nodal finding with line-level evidence for the changed node, or plan a dedicated brownfield remediation slice for this file-level debt.'
267
279
  : 'Plan a dedicated brownfield remediation slice for this pre-existing finding.'),
268
280
  };
@@ -1213,6 +1225,7 @@ export async function runPlatformGate(params: {
1213
1225
  scope: params.scope,
1214
1226
  stage: params.policy.stage,
1215
1227
  changedLinesByPath: stagedChangedLinesByPath,
1228
+ stagedPaths,
1216
1229
  });
1217
1230
  const findings = normalizeNonBlockingSwiftTestingMigrationWarnings([
1218
1231
  ...aiGateRepoPolicyFindings,
@@ -169,17 +169,6 @@ export const readPreWriteLeaseStatus = (params: {
169
169
  };
170
170
  }
171
171
 
172
- if (lease.head !== resolveHead(params)) {
173
- return {
174
- valid: false,
175
- code: 'PRE_WRITE_LEASE_HEAD_MISMATCH',
176
- path,
177
- lease,
178
- changedCodePaths,
179
- message: 'PRE_WRITE lease was issued for a different HEAD.',
180
- };
181
- }
182
-
183
172
  if (Date.parse(lease.expires_at) <= (params.now ?? new Date()).getTime()) {
184
173
  return {
185
174
  valid: false,
@@ -218,6 +207,17 @@ export const readPreWriteLeaseStatus = (params: {
218
207
  };
219
208
  }
220
209
 
210
+ if (lease.head !== resolveHead(params)) {
211
+ return {
212
+ valid: false,
213
+ code: 'PRE_WRITE_LEASE_HEAD_MISMATCH',
214
+ path,
215
+ lease,
216
+ changedCodePaths,
217
+ message: 'PRE_WRITE lease was issued for a different HEAD.',
218
+ };
219
+ }
220
+
221
221
  if (lease.pre_change_code_changes_count !== 0 || lease.pre_change_code_paths.length !== 0) {
222
222
  return {
223
223
  valid: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.348",
3
+ "version": "6.3.350",
4
4
  "description": "Enterprise-grade AST Intelligence System with multi-platform support (iOS, Android, Backend, Frontend) and Feature-First + DDD + Clean Architecture enforcement. Includes dynamic violations API for intelligent querying.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -18,6 +18,28 @@ const formatTopFiles = (topFiles: ReadonlyArray<{ file: string; count: number }>
18
18
  .join(', ')}`;
19
19
  };
20
20
 
21
+ const formatPlatforms = (
22
+ platformRows: FrameworkMenuEvidenceSummary['platformAuditRows']
23
+ ): string => {
24
+ if (!platformRows || platformRows.length === 0) {
25
+ return 'Platforms: none';
26
+ }
27
+ return `Platforms: ${platformRows
28
+ .map((entry) => `${entry.platform}=${entry.violations}`)
29
+ .join(', ')}`;
30
+ };
31
+
32
+ const formatTopFindings = (
33
+ topFindings: FrameworkMenuEvidenceSummary['topFindings']
34
+ ): string => {
35
+ if (topFindings.length === 0) {
36
+ return 'Top findings: none';
37
+ }
38
+ return `Top findings: ${topFindings
39
+ .map((entry) => `[${entry.severity}] ${entry.ruleId} -> ${entry.file}:${entry.line}`)
40
+ .join('; ')}`;
41
+ };
42
+
21
43
  export const formatEvidenceSummaryForMenu = (
22
44
  summary: FrameworkMenuEvidenceSummary
23
45
  ): string => {
@@ -45,5 +67,7 @@ export const formatEvidenceSummaryForMenu = (
45
67
  `Severities (enterprise): critical=${byEnterpriseSeverity.CRITICAL} high=${byEnterpriseSeverity.HIGH} medium=${byEnterpriseSeverity.MEDIUM} low=${byEnterpriseSeverity.LOW}`,
46
68
  `Severities (legacy): critical=${summary.bySeverity.CRITICAL} error=${summary.bySeverity.ERROR} warn=${summary.bySeverity.WARN} info=${summary.bySeverity.INFO}`,
47
69
  formatTopFiles(summary.topFiles),
70
+ formatPlatforms(summary.platformAuditRows),
71
+ formatTopFindings(summary.topFindings),
48
72
  ].join('\n');
49
73
  };