pumuki 6.3.332 → 6.3.333

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.
@@ -14,6 +14,13 @@ export type EvidenceBlockingCause = {
14
14
  const isBlockingSeverity = (severity: string): boolean =>
15
15
  severity.toUpperCase() === 'CRITICAL' || severity.toUpperCase() === 'ERROR';
16
16
 
17
+ const isNonBlockingSwiftTestingMigrationWarning = (params: {
18
+ ruleId?: string;
19
+ severity: string;
20
+ }): boolean =>
21
+ params.ruleId === 'skills.ios.prefer-swift-testing'
22
+ && params.severity.toUpperCase() === 'WARN';
23
+
17
24
  const toFindingBlockingCause = (finding: SnapshotFinding): EvidenceBlockingCause => ({
18
25
  ruleId: finding.ruleId,
19
26
  code: finding.code,
@@ -56,7 +63,14 @@ export const extractEvidenceBlockingCauses = (
56
63
 
57
64
  for (const finding of evidence.snapshot.findings) {
58
65
  const explicitlyBlocking = finding.blocking === true;
59
- if (finding.blocking === false || (!explicitlyBlocking && !isBlockingSeverity(finding.severity))) {
66
+ if (
67
+ finding.blocking === false
68
+ || isNonBlockingSwiftTestingMigrationWarning({
69
+ ruleId: finding.ruleId,
70
+ severity: finding.severity,
71
+ })
72
+ || (!explicitlyBlocking && !isBlockingSeverity(finding.severity))
73
+ ) {
60
74
  continue;
61
75
  }
62
76
  const cause = toFindingBlockingCause(finding);
@@ -69,9 +83,14 @@ export const extractEvidenceBlockingCauses = (
69
83
 
70
84
  for (const violation of evidence.ai_gate.violations) {
71
85
  const explicitlyBlocking = violation.blocking === true;
86
+ const severity = resolveViolationSeverity(violation);
72
87
  if (
73
88
  violation.blocking === false ||
74
- (!explicitlyBlocking && !isBlockingSeverity(resolveViolationSeverity(violation)))
89
+ isNonBlockingSwiftTestingMigrationWarning({
90
+ ruleId: violation.ruleId,
91
+ severity,
92
+ }) ||
93
+ (!explicitlyBlocking && !isBlockingSeverity(severity))
75
94
  ) {
76
95
  continue;
77
96
  }
@@ -486,6 +486,28 @@ const resolvePreWriteCriticalSkillsRules = (params: {
486
486
  return ruleIds;
487
487
  };
488
488
 
489
+ const hasRuleCoverage = (
490
+ coverage: NonNullable<Extract<EvidenceReadResult, { kind: 'valid' }>['evidence']['snapshot']['rules_coverage']>,
491
+ ruleId: string
492
+ ): boolean =>
493
+ coverage.active_rule_ids.includes(ruleId) && coverage.evaluated_rule_ids.includes(ruleId);
494
+
495
+ const hasEquivalentCriticalRuleCoverage = (
496
+ coverage: NonNullable<Extract<EvidenceReadResult, { kind: 'valid' }>['evidence']['snapshot']['rules_coverage']>,
497
+ ruleId: string
498
+ ): boolean => {
499
+ if (ruleId !== 'skills.ios.critical-test-quality') {
500
+ return false;
501
+ }
502
+ return hasRuleCoverage(coverage, 'skills.ios.prefer-swift-testing');
503
+ };
504
+
505
+ const hasRequiredCriticalRuleCoverage = (
506
+ coverage: NonNullable<Extract<EvidenceReadResult, { kind: 'valid' }>['evidence']['snapshot']['rules_coverage']>,
507
+ ruleId: string
508
+ ): boolean =>
509
+ hasRuleCoverage(coverage, ruleId) || hasEquivalentCriticalRuleCoverage(coverage, ruleId);
510
+
489
511
  const isPlatformPath = (platform: PreWriteSkillsPlatform, filePath: string): boolean => {
490
512
  const normalized = normalizeChangedPath(filePath).toLowerCase();
491
513
  if (platform === 'ios') {
@@ -757,9 +779,7 @@ const collectPreWritePlatformSkillsViolations = (params: {
757
779
  continue;
758
780
  }
759
781
  const missingCriticalRuleIds = requiredCriticalRuleIds.filter((ruleId) => {
760
- const hasActive = params.coverage.active_rule_ids.includes(ruleId);
761
- const hasEvaluated = params.coverage.evaluated_rule_ids.includes(ruleId);
762
- return !hasActive || !hasEvaluated;
782
+ return !hasRequiredCriticalRuleCoverage(params.coverage, ruleId);
763
783
  });
764
784
  if (missingCriticalRuleIds.length === 0) {
765
785
  continue;
@@ -1051,9 +1071,7 @@ const toSkillsContractAssessment = (params: {
1051
1071
  );
1052
1072
  const missingCriticalRuleIds = coverage
1053
1073
  ? requiredCriticalRuleIds.filter((ruleId) => {
1054
- const hasActive = coverage.active_rule_ids.includes(ruleId);
1055
- const hasEvaluated = coverage.evaluated_rule_ids.includes(ruleId);
1056
- return !hasActive || !hasEvaluated;
1074
+ return !hasRequiredCriticalRuleCoverage(coverage, ruleId);
1057
1075
  })
1058
1076
  : [...requiredCriticalRuleIds];
1059
1077
  const transversalCriticalCovered =
@@ -3,6 +3,7 @@ import { isAbsolute, resolve } from 'node:path';
3
3
  import type { Fact } from '../../core/facts/Fact';
4
4
  import type { Finding } from '../../core/gate/Finding';
5
5
  import { readTddBddEvidence } from './contract';
6
+ import type { TddSlice } from './contract';
6
7
  import { classifyTddBddScope } from './scope';
7
8
  import type { TddBddSnapshot } from './types';
8
9
  import { resolveActiveTddBddWaiver } from './waiver';
@@ -78,6 +79,14 @@ const isTimelineOrdered = (timestamps: ReadonlyArray<string | undefined>): boole
78
79
  return true;
79
80
  };
80
81
 
82
+ const selectEnforcedEvidenceSlices = (slices: ReadonlyArray<TddSlice>): ReadonlyArray<TddSlice> => {
83
+ if (slices.length <= 1) {
84
+ return slices;
85
+ }
86
+ const latestSlice = slices[slices.length - 1];
87
+ return latestSlice ? [latestSlice] : [];
88
+ };
89
+
81
90
  export const enforceTddBddPolicy = (params: {
82
91
  facts: ReadonlyArray<Fact>;
83
92
  repoRoot: string;
@@ -222,7 +231,9 @@ export const enforceTddBddPolicy = (params: {
222
231
  verify: 'missing',
223
232
  };
224
233
 
225
- if (evidenceRead.evidence.slices.length === 0) {
234
+ const enforcedSlices = selectEnforcedEvidenceSlices(evidenceRead.evidence.slices);
235
+
236
+ if (enforcedSlices.length === 0) {
226
237
  sliceFindings.push(
227
238
  buildFinding({
228
239
  ruleId: 'generic_tdd_vertical_required',
@@ -233,7 +244,7 @@ export const enforceTddBddPolicy = (params: {
233
244
  );
234
245
  }
235
246
 
236
- for (const slice of evidenceRead.evidence.slices) {
247
+ for (const slice of enforcedSlices) {
237
248
  const sliceErrorsBefore = sliceFindings.length;
238
249
 
239
250
  if (seenSliceIds.has(slice.id)) {
@@ -355,7 +366,7 @@ export const enforceTddBddPolicy = (params: {
355
366
  }
356
367
  }
357
368
 
358
- const invalidSlices = Math.max(0, evidenceRead.evidence.slices.length - validSlices);
369
+ const invalidSlices = Math.max(0, enforcedSlices.length - validSlices);
359
370
  const hasBlockingFindings = sliceFindings.some(
360
371
  (finding) => finding.severity === 'ERROR' || finding.severity === 'CRITICAL'
361
372
  );
@@ -369,7 +380,7 @@ export const enforceTddBddPolicy = (params: {
369
380
  ...baseSnapshot.evidence,
370
381
  state: 'valid',
371
382
  version: evidenceRead.evidence.version,
372
- slices_total: evidenceRead.evidence.slices.length,
383
+ slices_total: enforcedSlices.length,
373
384
  slices_valid: validSlices,
374
385
  slices_invalid: invalidSlices,
375
386
  integrity_ok: evidenceRead.integrity.valid,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.332",
3
+ "version": "6.3.333",
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": {