pumuki 6.3.149 → 6.3.151
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.
|
@@ -4,6 +4,12 @@ This file tracks the active deterministic framework line used in this repository
|
|
|
4
4
|
Canonical release chronology lives in `CHANGELOG.md`.
|
|
5
5
|
This file keeps only the operational highlights and rollout notes that matter while running the framework.
|
|
6
6
|
|
|
7
|
+
### 2026-05-05 (v6.3.150)
|
|
8
|
+
|
|
9
|
+
- **RuralGo PUMUKI-INC-061:** las notificaciones de bloqueo ya recomiendan `policy reconcile --strict --apply --json` cuando la remediación real requiere converger policy-as-code.
|
|
10
|
+
- **UX sin loop falso:** `EVIDENCE_GATE_BLOCKED` y gaps de skills/policy dejan de mostrar un comando dry-run que no puede desbloquear el repo por sí solo.
|
|
11
|
+
- **Rollout:** publicar `pumuki@6.3.150`, repinear primero RuralGo y revalidar un bloqueo de governance verificando el comando visible.
|
|
12
|
+
|
|
7
13
|
### 2026-05-05 (v6.3.145)
|
|
8
14
|
|
|
9
15
|
- **RuralGo PUMUKI-INC-124:** `skills.ios.critical-test-quality` deja de bloquear tests XCTest de UI automation/performance cuando usan `XCUIApplication`, `XCTMetric` o `measure`.
|
|
@@ -447,6 +447,88 @@ const collectStagedPaths = (git: IGitService, repoRoot: string): ReadonlyArray<s
|
|
|
447
447
|
}
|
|
448
448
|
};
|
|
449
449
|
|
|
450
|
+
const toBlockingFindingsForPaths = (
|
|
451
|
+
findings: ReadonlyArray<Finding>,
|
|
452
|
+
paths: ReadonlySet<string>
|
|
453
|
+
): ReadonlyArray<Finding> => {
|
|
454
|
+
return findings.filter((finding) => {
|
|
455
|
+
if (finding.severity !== 'ERROR' && finding.severity !== 'CRITICAL') {
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
458
|
+
const path = finding.filePath ? toNormalizedPath(finding.filePath) : '';
|
|
459
|
+
return path.length > 0 && paths.has(path);
|
|
460
|
+
});
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const buildHeadFactsForPaths = (params: {
|
|
464
|
+
git: IGitService;
|
|
465
|
+
repoRoot: string;
|
|
466
|
+
paths: ReadonlyArray<string>;
|
|
467
|
+
}): ReadonlyArray<Fact> => {
|
|
468
|
+
const facts: Fact[] = [];
|
|
469
|
+
for (const path of params.paths) {
|
|
470
|
+
try {
|
|
471
|
+
const content = params.git.runGit(['show', `HEAD:${path}`], params.repoRoot);
|
|
472
|
+
facts.push({
|
|
473
|
+
kind: 'FileChange',
|
|
474
|
+
path,
|
|
475
|
+
changeType: 'modified',
|
|
476
|
+
source: 'git:staged:HEAD',
|
|
477
|
+
});
|
|
478
|
+
facts.push({
|
|
479
|
+
kind: 'FileContent',
|
|
480
|
+
path,
|
|
481
|
+
content,
|
|
482
|
+
source: 'git:staged:HEAD',
|
|
483
|
+
});
|
|
484
|
+
} catch {
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return facts;
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
const toRemediationProgressAllowedFinding = (params: {
|
|
492
|
+
stage: Exclude<GateStage, 'STAGED'>;
|
|
493
|
+
currentBlockingCount: number;
|
|
494
|
+
previousBlockingCount: number;
|
|
495
|
+
paths: ReadonlyArray<string>;
|
|
496
|
+
ruleIds: ReadonlyArray<string>;
|
|
497
|
+
}): Finding => {
|
|
498
|
+
const samplePaths = params.paths.slice(0, MAX_SCOPE_SAMPLE_PATHS).join(LIST_SEPARATOR);
|
|
499
|
+
const sampleRuleIds = params.ruleIds.slice(0, MAX_SCOPE_SAMPLE_PATHS).join(LIST_SEPARATOR);
|
|
500
|
+
return {
|
|
501
|
+
ruleId: 'governance.remediation.progress.allowed',
|
|
502
|
+
severity: 'INFO',
|
|
503
|
+
code: 'REMEDIATION_PROGRESS_ALLOWED',
|
|
504
|
+
message:
|
|
505
|
+
`Remediation progress allowed at ${params.stage}: ` +
|
|
506
|
+
`previous_blocking_findings=${params.previousBlockingCount} ` +
|
|
507
|
+
`current_blocking_findings=${params.currentBlockingCount} ` +
|
|
508
|
+
`paths=[${samplePaths}] remediated_rule_ids=[${sampleRuleIds}]. ` +
|
|
509
|
+
'Feature work remains blocked until global skills enforcement is complete.',
|
|
510
|
+
filePath: '.ai_evidence.json',
|
|
511
|
+
matchedBy: 'RemediationProgressGuard',
|
|
512
|
+
source: 'remediation-progress',
|
|
513
|
+
blocking: false,
|
|
514
|
+
};
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
const toRemediationProgressAdvisoryFinding = (finding: Finding): Finding => ({
|
|
518
|
+
...finding,
|
|
519
|
+
severity: 'INFO',
|
|
520
|
+
code:
|
|
521
|
+
finding.code === 'SKILLS_GLOBAL_ENFORCEMENT_INCOMPLETE_CRITICAL'
|
|
522
|
+
? 'SKILLS_GLOBAL_ENFORCEMENT_INCOMPLETE_REMEDIATION_ADVISORY'
|
|
523
|
+
: finding.code === 'TDD_BDD_EVIDENCE_STALE'
|
|
524
|
+
? 'TDD_BDD_EVIDENCE_STALE_REMEDIATION_ADVISORY'
|
|
525
|
+
: finding.code,
|
|
526
|
+
message:
|
|
527
|
+
`${finding.message} Remediation progress mode converted this blocker to advisory ` +
|
|
528
|
+
'because the staged diff reduces existing supported-detector findings and introduces none.',
|
|
529
|
+
blocking: false,
|
|
530
|
+
});
|
|
531
|
+
|
|
450
532
|
const shouldAugmentStagedSkillsContractFactsWithRepoFacts = (params: {
|
|
451
533
|
scope: GateScope;
|
|
452
534
|
facts: ReadonlyArray<Fact>;
|
|
@@ -1305,16 +1387,91 @@ export async function runPlatformGate(params: {
|
|
|
1305
1387
|
const hasNativeBlockingFinding = findings.some(
|
|
1306
1388
|
(finding) => finding.severity === 'ERROR' || finding.severity === 'CRITICAL'
|
|
1307
1389
|
);
|
|
1390
|
+
const stagedCodePaths = stagedPaths.filter((path) => isObservedCodePath(path));
|
|
1391
|
+
const stagedCodePathSet = new Set(stagedCodePaths);
|
|
1392
|
+
const currentBlockingFindingsForStagedPaths = toBlockingFindingsForPaths(
|
|
1393
|
+
findings,
|
|
1394
|
+
stagedCodePathSet
|
|
1395
|
+
);
|
|
1396
|
+
const previousFactsForStagedPaths =
|
|
1397
|
+
isStrictEnforcementStage(params.policy.stage) &&
|
|
1398
|
+
params.scope.kind === 'staged' &&
|
|
1399
|
+
stagedCodePaths.length > 0 &&
|
|
1400
|
+
currentBlockingFindingsForStagedPaths.length === 0
|
|
1401
|
+
? buildHeadFactsForPaths({
|
|
1402
|
+
git,
|
|
1403
|
+
repoRoot,
|
|
1404
|
+
paths: stagedCodePaths,
|
|
1405
|
+
})
|
|
1406
|
+
: [];
|
|
1407
|
+
const previousEvaluationForStagedPaths =
|
|
1408
|
+
previousFactsForStagedPaths.length > 0
|
|
1409
|
+
? dependencies.evaluatePlatformGateFindings({
|
|
1410
|
+
facts: previousFactsForStagedPaths,
|
|
1411
|
+
stage: params.policy.stage,
|
|
1412
|
+
repoRoot,
|
|
1413
|
+
})
|
|
1414
|
+
: undefined;
|
|
1415
|
+
const previousBlockingFindingsForStagedPaths = previousEvaluationForStagedPaths
|
|
1416
|
+
? toBlockingFindingsForPaths(
|
|
1417
|
+
previousEvaluationForStagedPaths.findings,
|
|
1418
|
+
stagedCodePathSet
|
|
1419
|
+
)
|
|
1420
|
+
: [];
|
|
1421
|
+
const remediationProgressFinding =
|
|
1422
|
+
previousBlockingFindingsForStagedPaths.length > currentBlockingFindingsForStagedPaths.length &&
|
|
1423
|
+
currentBlockingFindingsForStagedPaths.length === 0
|
|
1424
|
+
? toRemediationProgressAllowedFinding({
|
|
1425
|
+
stage: params.policy.stage as Exclude<GateStage, 'STAGED'>,
|
|
1426
|
+
currentBlockingCount: currentBlockingFindingsForStagedPaths.length,
|
|
1427
|
+
previousBlockingCount: previousBlockingFindingsForStagedPaths.length,
|
|
1428
|
+
paths: stagedCodePaths,
|
|
1429
|
+
ruleIds: [
|
|
1430
|
+
...new Set(
|
|
1431
|
+
previousBlockingFindingsForStagedPaths.map((finding) => finding.ruleId)
|
|
1432
|
+
),
|
|
1433
|
+
].sort(),
|
|
1434
|
+
})
|
|
1435
|
+
: undefined;
|
|
1436
|
+
const remediationProgressAllowsGlobalGap = remediationProgressFinding !== undefined;
|
|
1437
|
+
const effectiveTddBddFindings = remediationProgressAllowsGlobalGap
|
|
1438
|
+
? tddBddEvaluation.findings.map((finding) =>
|
|
1439
|
+
finding.code === 'TDD_BDD_EVIDENCE_STALE'
|
|
1440
|
+
? toRemediationProgressAdvisoryFinding(finding)
|
|
1441
|
+
: finding
|
|
1442
|
+
)
|
|
1443
|
+
: tddBddEvaluation.findings;
|
|
1444
|
+
const effectiveTddBddSnapshot =
|
|
1445
|
+
remediationProgressAllowsGlobalGap &&
|
|
1446
|
+
tddBddSnapshot?.status === 'blocked' &&
|
|
1447
|
+
tddBddEvaluation.findings.length > 0 &&
|
|
1448
|
+
tddBddEvaluation.findings.every((finding) => finding.code === 'TDD_BDD_EVIDENCE_STALE')
|
|
1449
|
+
? {
|
|
1450
|
+
...tddBddSnapshot,
|
|
1451
|
+
status: 'advisory' as const,
|
|
1452
|
+
evidence: {
|
|
1453
|
+
...tddBddSnapshot.evidence,
|
|
1454
|
+
errors: ['TDD_BDD_EVIDENCE_STALE_REMEDIATION_ADVISORY'],
|
|
1455
|
+
},
|
|
1456
|
+
}
|
|
1457
|
+
: tddBddSnapshot;
|
|
1458
|
+
const effectiveHasTddBddBlockingFinding = effectiveTddBddFindings.some(
|
|
1459
|
+
(finding) => finding.severity === 'ERROR' || finding.severity === 'CRITICAL'
|
|
1460
|
+
);
|
|
1308
1461
|
const effectivePlatformSkillsCoverageFinding = effectivePlatformSkillsCoverageInput;
|
|
1309
1462
|
const effectiveCrossPlatformCriticalFinding = effectiveCrossPlatformCriticalInput;
|
|
1310
1463
|
const effectiveSkillsScopeComplianceFinding = effectiveSkillsScopeComplianceInput;
|
|
1464
|
+
const effectiveUnsupportedDetectorSkillsFindingForOutcome =
|
|
1465
|
+
remediationProgressAllowsGlobalGap && effectiveUnsupportedDetectorSkillsFinding
|
|
1466
|
+
? toRemediationProgressAdvisoryFinding(effectiveUnsupportedDetectorSkillsFinding)
|
|
1467
|
+
: effectiveUnsupportedDetectorSkillsFinding;
|
|
1311
1468
|
const effectiveFindings = sddBlockingFinding
|
|
1312
1469
|
? [
|
|
1313
1470
|
sddBlockingFinding,
|
|
1314
1471
|
...(degradedModeFinding ? [degradedModeFinding] : []),
|
|
1315
1472
|
...(policyAsCodeBlockingFinding ? [policyAsCodeBlockingFinding] : []),
|
|
1316
1473
|
...(effectiveUnsupportedSkillsMappingFinding ? [effectiveUnsupportedSkillsMappingFinding] : []),
|
|
1317
|
-
...(
|
|
1474
|
+
...(effectiveUnsupportedDetectorSkillsFindingForOutcome ? [effectiveUnsupportedDetectorSkillsFindingForOutcome] : []),
|
|
1318
1475
|
...(effectivePlatformSkillsCoverageFinding ? [effectivePlatformSkillsCoverageFinding] : []),
|
|
1319
1476
|
...(effectiveCrossPlatformCriticalFinding ? [effectiveCrossPlatformCriticalFinding] : []),
|
|
1320
1477
|
...(effectiveSkillsScopeComplianceFinding ? [effectiveSkillsScopeComplianceFinding] : []),
|
|
@@ -1323,11 +1480,12 @@ export async function runPlatformGate(params: {
|
|
|
1323
1480
|
...(astIntelligenceDualFinding ? [astIntelligenceDualFinding] : []),
|
|
1324
1481
|
...(coverageBlockingFinding ? [coverageBlockingFinding] : []),
|
|
1325
1482
|
...brownfieldHotspotFindings,
|
|
1326
|
-
...
|
|
1483
|
+
...effectiveTddBddFindings,
|
|
1484
|
+
...(remediationProgressFinding ? [remediationProgressFinding] : []),
|
|
1327
1485
|
...findings,
|
|
1328
1486
|
]
|
|
1329
1487
|
: effectiveUnsupportedSkillsMappingFinding
|
|
1330
|
-
||
|
|
1488
|
+
|| effectiveUnsupportedDetectorSkillsFindingForOutcome
|
|
1331
1489
|
|| effectivePlatformSkillsCoverageFinding
|
|
1332
1490
|
|| effectiveCrossPlatformCriticalFinding
|
|
1333
1491
|
|| effectiveSkillsScopeComplianceFinding
|
|
@@ -1338,12 +1496,13 @@ export async function runPlatformGate(params: {
|
|
|
1338
1496
|
|| brownfieldHotspotFindings.length > 0
|
|
1339
1497
|
|| policyAsCodeBlockingFinding
|
|
1340
1498
|
|| degradedModeFinding
|
|
1341
|
-
||
|
|
1499
|
+
|| effectiveTddBddFindings.length > 0
|
|
1500
|
+
|| remediationProgressFinding
|
|
1342
1501
|
? [
|
|
1343
1502
|
...(degradedModeFinding ? [degradedModeFinding] : []),
|
|
1344
1503
|
...(policyAsCodeBlockingFinding ? [policyAsCodeBlockingFinding] : []),
|
|
1345
1504
|
...(effectiveUnsupportedSkillsMappingFinding ? [effectiveUnsupportedSkillsMappingFinding] : []),
|
|
1346
|
-
...(
|
|
1505
|
+
...(effectiveUnsupportedDetectorSkillsFindingForOutcome ? [effectiveUnsupportedDetectorSkillsFindingForOutcome] : []),
|
|
1347
1506
|
...(effectivePlatformSkillsCoverageFinding ? [effectivePlatformSkillsCoverageFinding] : []),
|
|
1348
1507
|
...(effectiveCrossPlatformCriticalFinding ? [effectiveCrossPlatformCriticalFinding] : []),
|
|
1349
1508
|
...(effectiveSkillsScopeComplianceFinding ? [effectiveSkillsScopeComplianceFinding] : []),
|
|
@@ -1352,20 +1511,22 @@ export async function runPlatformGate(params: {
|
|
|
1352
1511
|
...(astIntelligenceDualFinding ? [astIntelligenceDualFinding] : []),
|
|
1353
1512
|
...(coverageBlockingFinding ? [coverageBlockingFinding] : []),
|
|
1354
1513
|
...brownfieldHotspotFindings,
|
|
1355
|
-
...
|
|
1514
|
+
...effectiveTddBddFindings,
|
|
1515
|
+
...(remediationProgressFinding ? [remediationProgressFinding] : []),
|
|
1356
1516
|
...findings,
|
|
1357
1517
|
]
|
|
1358
1518
|
: brownfieldHotspotFindings.length > 0
|
|
1359
1519
|
? [...brownfieldHotspotFindings, ...findings]
|
|
1360
1520
|
: findings;
|
|
1361
1521
|
const hasAstIntelligenceBlockingFinding = shouldBlockFromFinding(astIntelligenceDualFinding);
|
|
1362
|
-
const
|
|
1522
|
+
const gateDecisionFindings = effectiveFindings.filter((finding) => finding.blocking !== false);
|
|
1523
|
+
const decision = dependencies.evaluateGate([...gateDecisionFindings], params.policy);
|
|
1363
1524
|
const baseGateOutcome =
|
|
1364
1525
|
sddBlockingFinding ||
|
|
1365
1526
|
degradedModeBlocks ||
|
|
1366
1527
|
shouldBlockFromFinding(policyAsCodeBlockingFinding) ||
|
|
1367
1528
|
shouldBlockFromFinding(effectiveUnsupportedSkillsMappingFinding) ||
|
|
1368
|
-
shouldBlockFromFinding(
|
|
1529
|
+
shouldBlockFromFinding(effectiveUnsupportedDetectorSkillsFindingForOutcome) ||
|
|
1369
1530
|
shouldBlockFromFinding(effectivePlatformSkillsCoverageFinding) ||
|
|
1370
1531
|
shouldBlockFromFinding(effectiveCrossPlatformCriticalFinding) ||
|
|
1371
1532
|
shouldBlockFromFinding(effectiveSkillsScopeComplianceFinding) ||
|
|
@@ -1374,9 +1535,9 @@ export async function runPlatformGate(params: {
|
|
|
1374
1535
|
hasAstIntelligenceBlockingFinding ||
|
|
1375
1536
|
shouldBlockFromFinding(coverageBlockingFinding) ||
|
|
1376
1537
|
brownfieldHotspotFindings.some((finding) => shouldBlockFromFinding(finding)) ||
|
|
1377
|
-
|
|
1538
|
+
effectiveHasTddBddBlockingFinding
|
|
1378
1539
|
? 'BLOCK'
|
|
1379
|
-
: (decision.outcome === 'PASS' &&
|
|
1540
|
+
: (decision.outcome === 'PASS' && effectiveTddBddSnapshot?.status === 'advisory'
|
|
1380
1541
|
? 'WARN'
|
|
1381
1542
|
: decision.outcome);
|
|
1382
1543
|
const gateWaiverStage =
|
|
@@ -1426,7 +1587,7 @@ export async function runPlatformGate(params: {
|
|
|
1426
1587
|
try {
|
|
1427
1588
|
memoryShadowRecommendation = dependencies.buildMemoryShadowRecommendation({
|
|
1428
1589
|
findings: findingsWithWaiver,
|
|
1429
|
-
...(
|
|
1590
|
+
...(effectiveTddBddSnapshot ? { tddBddSnapshot: effectiveTddBddSnapshot } : {}),
|
|
1430
1591
|
});
|
|
1431
1592
|
} catch (error) {
|
|
1432
1593
|
const rawReason = error instanceof Error ? error.message : String(error);
|
|
@@ -1477,7 +1638,7 @@ export async function runPlatformGate(params: {
|
|
|
1477
1638
|
filesScanned,
|
|
1478
1639
|
evaluationMetrics,
|
|
1479
1640
|
rulesCoverage,
|
|
1480
|
-
...(
|
|
1641
|
+
...(effectiveTddBddSnapshot ? { tddBdd: effectiveTddBddSnapshot } : {}),
|
|
1481
1642
|
...(memoryShadow ? { memoryShadow } : {}),
|
|
1482
1643
|
repoRoot,
|
|
1483
1644
|
detectedPlatforms,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.151",
|
|
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": {
|
|
@@ -64,7 +64,7 @@ export const resolveBlockedCommand = (params: {
|
|
|
64
64
|
case 'EVIDENCE_CROSS_PLATFORM_CRITICAL_ENFORCEMENT_INCOMPLETE':
|
|
65
65
|
return `${buildPinnedPumukiCommand({
|
|
66
66
|
repoRoot: params.repoRoot,
|
|
67
|
-
executableAndArgs: 'pumuki policy reconcile --strict --json',
|
|
67
|
+
executableAndArgs: 'pumuki policy reconcile --strict --apply --json',
|
|
68
68
|
})} && ${buildPinnedPumukiCommand({
|
|
69
69
|
repoRoot: params.repoRoot,
|
|
70
70
|
executableAndArgs: `pumuki sdd validate --stage=${params.event.stage} --json`,
|
|
@@ -79,7 +79,7 @@ export const resolveBlockedCommand = (params: {
|
|
|
79
79
|
case 'EVIDENCE_GATE_BLOCKED':
|
|
80
80
|
return `${buildPinnedPumukiCommand({
|
|
81
81
|
repoRoot: params.repoRoot,
|
|
82
|
-
executableAndArgs: 'pumuki policy reconcile --strict --json',
|
|
82
|
+
executableAndArgs: 'pumuki policy reconcile --strict --apply --json',
|
|
83
83
|
})} && ${buildPinnedPumukiCommand({
|
|
84
84
|
repoRoot: params.repoRoot,
|
|
85
85
|
executableAndArgs: `pumuki sdd validate --stage=${params.event.stage} --json`,
|
|
@@ -41,7 +41,7 @@ const BLOCKED_REMEDIATION_BY_CODE: Readonly<Record<string, string>> = {
|
|
|
41
41
|
TRACKING_CANONICAL_IN_PROGRESS_INVALID: TRACKING_BLOCKED_REMEDIATION,
|
|
42
42
|
TRACKING_CANONICAL_SOURCE_CONFLICT: TRACKING_BLOCKED_REMEDIATION,
|
|
43
43
|
ACTIVE_RULE_IDS_EMPTY_FOR_CODE_CHANGES_HIGH:
|
|
44
|
-
'Ejecuta `pumuki policy reconcile --strict --json` y revalida antes de continuar.',
|
|
44
|
+
'Ejecuta `pumuki policy reconcile --strict --apply --json` y revalida antes de continuar.',
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
const BLOCKED_REMEDIATION_MAX_LENGTH_BY_VARIANT: Readonly<Record<BlockedRemediationVariant, number>> = {
|