pumuki 6.3.131 → 6.3.133

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 CHANGED
@@ -6,6 +6,22 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [6.3.133] - 2026-05-03
10
+
11
+ ### Fixed
12
+
13
+ - **Skills enforcement endurecido a bloqueo duro:** `PRE_WRITE`, `PRE_COMMIT` y `PRE_PUSH` ya no admiten bypass advisory para violaciones de skills.
14
+ - **Contrato de gate alineado de punta a punta:** `skillsEnforcement`, `evaluateAiGate`, `runPlatformGate` y el flujo CLI bloquean de forma consistente cuando falta cobertura, bundles o contrato de skills.
15
+ - **Release listo para repin:** esta versión está preparada para publicarse y repinear consumers como RuralGo sin cerrar más gaps funcionales para este fix.
16
+
17
+ ## [6.3.132] - 2026-05-03
18
+
19
+ ### Fixed
20
+
21
+ - **Reglas declarativas sin detector no bloquean el gate:** `unsupported_detector_rule_ids` se conserva en evidencia, pero deja de convertirse en `SKILLS_DETECTOR_MAPPING_INCOMPLETE_HIGH` cuando no hay reglas AUTO ejecutables sin detector.
22
+ - **Bloqueo solo para AUTO real:** el guard de cobertura de skills ahora bloquea exclusivamente `unsupported_auto_rule_ids`, evitando que doctrina declarativa de skills vuelva a parar consumers con `coverage_ratio=1`.
23
+ - **Regresión focalizada:** `runPlatformGate` cubre el caso en modo strict para asegurar que declarativas sin detector quedan como evidencia no bloqueante.
24
+
9
25
  ## [6.3.130] - 2026-05-03
10
26
 
11
27
  ### Fixed
package/VERSION CHANGED
@@ -1 +1 @@
1
- v6.3.130
1
+ v6.3.132
@@ -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-03 (v6.3.133)
8
+
9
+ - **Skills hard-blocking end-to-end:** `skillsEnforcement`, `evaluateAiGate`, `runPlatformGate` y el flujo CLI ya no dejan pasar advisory para violations de skills.
10
+ - **Repin recomendado:** publicar `pumuki@6.3.133`, repinear RuralGo y revalidar `status`, `doctor`, `audit --stage=PRE_WRITE --json` y hooks gestionados.
11
+ - **Contrato de release estable:** no hace falta cerrar más gaps funcionales para este fix; la solución ya quedó validada localmente y lo que falta es distribución.
12
+
7
13
  ### 2026-05-03 (v6.3.130)
8
14
 
9
15
  - **Menú consumer legacy recuperado:** `pumuki-framework` vuelve a mostrar la portada plana de 9 opciones y la salida clásica de auditoría.
@@ -0,0 +1,55 @@
1
+ import {
2
+ DEFAULT_DEGRADED_MODE_ACTION_ALLOW,
3
+ DEFAULT_DEGRADED_MODE_ACTION_BLOCK,
4
+ DEFAULT_GATE_AUDIT_MODE,
5
+ DEFAULT_LIST_SEPARATOR,
6
+ DEFAULT_MEMORY_SHADOW_DISPLAY_PRECISION,
7
+ DEFAULT_MEMORY_SHADOW_CONFIDENCE_ALLOW,
8
+ DEFAULT_MEMORY_SHADOW_CONFIDENCE_BLOCK,
9
+ DEFAULT_MEMORY_SHADOW_CONFIDENCE_WARN,
10
+ DEFAULT_MEMORY_SHADOW_CONFIDENCE_WARN_ADVISORY,
11
+ DEFAULT_RULES_COVERAGE_RATIO_DECIMALS,
12
+ LIFECYCLE_GATE_STAGES,
13
+ MAX_IOS_TEST_QUALITY_SAMPLE_FILES,
14
+ MAX_OBSERVED_CODE_PATHS_SAMPLE,
15
+ MAX_SCOPE_SAMPLE_PATHS,
16
+ } from './runPlatformGateDefaults';
17
+
18
+ const parseConfidence = (value: string | undefined, fallback: number): number => {
19
+ const parsed = Number.parseFloat(value ?? '');
20
+ return Number.isFinite(parsed) ? parsed : fallback;
21
+ };
22
+
23
+ export const LIST_SEPARATOR = DEFAULT_LIST_SEPARATOR;
24
+
25
+ export const MEMORY_SHADOW_CONFIDENCE_BLOCK = parseConfidence(
26
+ process.env.PUMUKI_MEMORY_SHADOW_CONFIDENCE_BLOCK,
27
+ DEFAULT_MEMORY_SHADOW_CONFIDENCE_BLOCK
28
+ );
29
+ export const MEMORY_SHADOW_CONFIDENCE_WARN = parseConfidence(
30
+ process.env.PUMUKI_MEMORY_SHADOW_CONFIDENCE_WARN,
31
+ DEFAULT_MEMORY_SHADOW_CONFIDENCE_WARN
32
+ );
33
+ export const MEMORY_SHADOW_CONFIDENCE_WARN_ADVISORY = parseConfidence(
34
+ process.env.PUMUKI_MEMORY_SHADOW_CONFIDENCE_WARN_ADVISORY,
35
+ DEFAULT_MEMORY_SHADOW_CONFIDENCE_WARN_ADVISORY
36
+ );
37
+ export const MEMORY_SHADOW_CONFIDENCE_ALLOW = parseConfidence(
38
+ process.env.PUMUKI_MEMORY_SHADOW_CONFIDENCE_ALLOW,
39
+ DEFAULT_MEMORY_SHADOW_CONFIDENCE_ALLOW
40
+ );
41
+
42
+ export const DEGRADED_MODE_ACTION_BLOCK =
43
+ process.env.PUMUKI_DEGRADED_MODE_ACTION_BLOCK?.trim() || DEFAULT_DEGRADED_MODE_ACTION_BLOCK;
44
+ export const DEGRADED_MODE_ACTION_ALLOW =
45
+ process.env.PUMUKI_DEGRADED_MODE_ACTION_ALLOW?.trim() || DEFAULT_DEGRADED_MODE_ACTION_ALLOW;
46
+
47
+ export {
48
+ DEFAULT_GATE_AUDIT_MODE,
49
+ DEFAULT_MEMORY_SHADOW_DISPLAY_PRECISION,
50
+ DEFAULT_RULES_COVERAGE_RATIO_DECIMALS,
51
+ LIFECYCLE_GATE_STAGES,
52
+ MAX_IOS_TEST_QUALITY_SAMPLE_FILES,
53
+ MAX_OBSERVED_CODE_PATHS_SAMPLE,
54
+ MAX_SCOPE_SAMPLE_PATHS,
55
+ };
@@ -0,0 +1,19 @@
1
+ export const DEFAULT_LIST_SEPARATOR = ', ';
2
+
3
+ export const DEFAULT_MEMORY_SHADOW_CONFIDENCE_BLOCK = 0.9;
4
+ export const DEFAULT_MEMORY_SHADOW_CONFIDENCE_WARN = 0.75;
5
+ export const DEFAULT_MEMORY_SHADOW_CONFIDENCE_WARN_ADVISORY = 0.7;
6
+ export const DEFAULT_MEMORY_SHADOW_CONFIDENCE_ALLOW = 0.65;
7
+
8
+ export const DEFAULT_DEGRADED_MODE_ACTION_BLOCK = 'block' as const;
9
+ export const DEFAULT_DEGRADED_MODE_ACTION_ALLOW = 'allow' as const;
10
+
11
+ export const DEFAULT_RULES_COVERAGE_RATIO_DECIMALS = 6;
12
+ export const DEFAULT_GATE_AUDIT_MODE = 'gate' as const;
13
+ export const DEFAULT_MEMORY_SHADOW_DISPLAY_PRECISION = 2;
14
+
15
+ export const MAX_IOS_TEST_QUALITY_SAMPLE_FILES = 3;
16
+ export const MAX_OBSERVED_CODE_PATHS_SAMPLE = 5;
17
+ export const MAX_SCOPE_SAMPLE_PATHS = 3;
18
+
19
+ export const LIFECYCLE_GATE_STAGES = ['PRE_COMMIT', 'PRE_PUSH', 'CI'] as const;
@@ -32,13 +32,29 @@ import { createEmptyEvaluationMetrics } from '../evidence/evaluationMetrics';
32
32
  import { createEmptySnapshotRulesCoverage } from '../evidence/rulesCoverage';
33
33
  import { enforceTddBddPolicy } from '../tdd/enforcement';
34
34
  import type { TddBddSnapshot } from '../tdd/types';
35
- import { resolveSkillsEnforcement } from '../policy/skillsEnforcement';
36
35
  import { applyTddBddEnforcement } from '../policy/tddBddEnforcement';
37
36
  import { collectAiGateRepoPolicyFindings } from './aiGateRepoPolicyFindings';
38
37
  import {
39
38
  filterFactsByPathPrefixes,
40
39
  resolveGateScopePathPrefixesFromEnv,
41
40
  } from './filterFactsByPathPrefixes';
41
+ import {
42
+ DEFAULT_MEMORY_SHADOW_DISPLAY_PRECISION,
43
+ DEGRADED_MODE_ACTION_ALLOW,
44
+ DEGRADED_MODE_ACTION_BLOCK,
45
+ DEFAULT_GATE_AUDIT_MODE,
46
+ DEFAULT_RULES_COVERAGE_RATIO_DECIMALS,
47
+ LIFECYCLE_GATE_STAGES,
48
+ MAX_IOS_TEST_QUALITY_SAMPLE_FILES,
49
+ MAX_OBSERVED_CODE_PATHS_SAMPLE,
50
+ MAX_SCOPE_SAMPLE_PATHS,
51
+ LIST_SEPARATOR,
52
+ MEMORY_SHADOW_CONFIDENCE_ALLOW,
53
+ MEMORY_SHADOW_CONFIDENCE_BLOCK,
54
+ MEMORY_SHADOW_CONFIDENCE_WARN,
55
+ MEMORY_SHADOW_CONFIDENCE_WARN_ADVISORY,
56
+ } from '../gate/runPlatformGateConfig';
57
+ import type { Severity } from '../../core/rules/Severity';
42
58
 
43
59
  export type OperationalMemoryShadowRecommendation = {
44
60
  recommendedOutcome: 'ALLOW' | 'WARN' | 'BLOCK';
@@ -80,13 +96,18 @@ const defaultServices: GateServices = {
80
96
  evidence: new EvidenceService(),
81
97
  };
82
98
 
99
+ const SEVERITY_CRITICAL: Severity = 'CRITICAL';
100
+ const SEVERITY_ERROR: Severity = 'ERROR';
101
+ const SEVERITY_WARN: Severity = 'WARN';
83
102
  const buildDefaultMemoryShadowRecommendation = (params: {
84
103
  findings: ReadonlyArray<Finding>;
85
104
  tddBddSnapshot?: TddBddSnapshot;
86
105
  }): OperationalMemoryShadowRecommendation | undefined => {
87
- const hasCritical = params.findings.some((finding) => finding.severity === 'CRITICAL');
88
- const hasError = params.findings.some((finding) => finding.severity === 'ERROR');
89
- const hasWarn = params.findings.some((finding) => finding.severity === 'WARN');
106
+ const hasCritical = params.findings.some(
107
+ (finding) => finding.severity === SEVERITY_CRITICAL
108
+ );
109
+ const hasError = params.findings.some((finding) => finding.severity === SEVERITY_ERROR);
110
+ const hasWarn = params.findings.some((finding) => finding.severity === SEVERITY_WARN);
90
111
  const reasonCodes: string[] = [];
91
112
 
92
113
  if (hasCritical || hasError) {
@@ -108,27 +129,27 @@ const buildDefaultMemoryShadowRecommendation = (params: {
108
129
  if (hasCritical || hasError || params.tddBddSnapshot?.status === 'blocked') {
109
130
  return {
110
131
  recommendedOutcome: 'BLOCK',
111
- confidence: 0.9,
132
+ confidence: MEMORY_SHADOW_CONFIDENCE_BLOCK,
112
133
  reasonCodes,
113
134
  };
114
135
  }
115
136
  if (hasWarn) {
116
137
  return {
117
138
  recommendedOutcome: 'WARN',
118
- confidence: 0.75,
139
+ confidence: MEMORY_SHADOW_CONFIDENCE_WARN,
119
140
  reasonCodes,
120
141
  };
121
142
  }
122
143
  if (params.tddBddSnapshot?.status === 'advisory') {
123
144
  return {
124
145
  recommendedOutcome: 'WARN',
125
- confidence: 0.7,
146
+ confidence: MEMORY_SHADOW_CONFIDENCE_WARN_ADVISORY,
126
147
  reasonCodes,
127
148
  };
128
149
  }
129
150
  return {
130
151
  recommendedOutcome: 'ALLOW',
131
- confidence: 0.65,
152
+ confidence: MEMORY_SHADOW_CONFIDENCE_ALLOW,
132
153
  reasonCodes,
133
154
  };
134
155
  };
@@ -202,7 +223,10 @@ const toRulesCoverageBlockingFinding = (params: {
202
223
  }
203
224
  const active = params.activeRuleIds.length;
204
225
  const evaluated = params.evaluatedRuleIds.length;
205
- const coverageRatio = active === 0 ? 1 : Number((evaluated / active).toFixed(6));
226
+ const coverageRatio =
227
+ active === 0
228
+ ? 1
229
+ : Number((evaluated / active).toFixed(DEFAULT_RULES_COVERAGE_RATIO_DECIMALS));
206
230
  const unevaluatedRuleIds = [...params.unevaluatedRuleIds].sort().join(', ');
207
231
 
208
232
  return {
@@ -228,17 +252,12 @@ const toSkillsUnsupportedAutoRulesBlockingFinding = (params: {
228
252
  return undefined;
229
253
  }
230
254
 
231
- const unsupportedRuleIds = [
232
- ...new Set([
233
- ...params.unsupportedAutoRuleIds,
234
- ...(params.unsupportedDetectorRuleIds ?? []),
235
- ]),
236
- ].sort();
255
+ const unsupportedRuleIds = [...new Set(params.unsupportedAutoRuleIds)].sort();
237
256
  if (unsupportedRuleIds.length === 0) {
238
257
  return undefined;
239
258
  }
240
259
 
241
- const unsupportedRuleIdsToken = unsupportedRuleIds.join(', ');
260
+ const unsupportedRuleIdsToken = unsupportedRuleIds.join(LIST_SEPARATOR);
242
261
 
243
262
  return {
244
263
  ruleId: 'governance.skills.detector-mapping.incomplete',
@@ -246,8 +265,8 @@ const toSkillsUnsupportedAutoRulesBlockingFinding = (params: {
246
265
  code: 'SKILLS_DETECTOR_MAPPING_INCOMPLETE_HIGH',
247
266
  message:
248
267
  `Skills detector mapping incomplete at ${params.stage}: ` +
249
- `unsupported_detector_rule_ids=[${unsupportedRuleIdsToken}]. ` +
250
- 'Map every skill rule to an intelligent AST detector before proceeding; DECLARATIVE is not an acceptable final coverage state.',
268
+ `unsupported_auto_rule_ids=[${unsupportedRuleIdsToken}]. ` +
269
+ 'Map every stage-applicable AUTO skill rule to an intelligent AST detector before proceeding.',
251
270
  filePath: '.ai_evidence.json',
252
271
  matchedBy: 'SkillsDetectorMappingGuard',
253
272
  source: 'skills-detector-mapping',
@@ -459,7 +478,9 @@ const toIosTestsQualityBlockingFinding = (params: {
459
478
  return undefined;
460
479
  }
461
480
 
462
- const sampleFiles = invalidFiles.slice(0, 3).join(' | ');
481
+ const sampleFiles = invalidFiles
482
+ .slice(0, MAX_IOS_TEST_QUALITY_SAMPLE_FILES)
483
+ .join(' | ');
463
484
  return {
464
485
  ruleId: 'governance.skills.ios-test-quality.incomplete',
465
486
  severity: 'ERROR',
@@ -485,7 +506,7 @@ const toActiveRulesEmptyForCodeChangesBlockingFinding = (params: {
485
506
  if (codePaths.length === 0) {
486
507
  return undefined;
487
508
  }
488
- const samplePaths = codePaths.slice(0, 5).join(', ');
509
+ const samplePaths = codePaths.slice(0, MAX_OBSERVED_CODE_PATHS_SAMPLE).join(', ');
489
510
  return {
490
511
  ruleId: 'governance.rules.active-rule-coverage.empty',
491
512
  severity: 'ERROR',
@@ -569,7 +590,7 @@ const toSkillsScopeComplianceBlockingFinding = (params: {
569
590
  if (!hasEvaluatedRules) {
570
591
  reasons.push(`evaluated_rules_prefix=${prefix} missing`);
571
592
  }
572
- const samplePaths = scopePaths.slice(0, 3).join(', ');
593
+ const samplePaths = scopePaths.slice(0, MAX_SCOPE_SAMPLE_PATHS).join(', ');
573
594
  missingScopes.push(`${scope}{${reasons.join('; ')} sample_paths=[${samplePaths}]}`);
574
595
  }
575
596
 
@@ -621,13 +642,13 @@ const toDegradedModeFinding = (params: {
621
642
  if (!degraded?.enabled) {
622
643
  return undefined;
623
644
  }
624
- if (degraded.action === 'block') {
645
+ if (degraded.action === DEGRADED_MODE_ACTION_BLOCK) {
625
646
  return {
626
647
  ruleId: 'governance.degraded-mode.blocked',
627
648
  severity: 'ERROR',
628
649
  code: degraded.code,
629
650
  message:
630
- `Degraded mode is active at ${params.stage} with fail-closed action=block. ` +
651
+ `Degraded mode is active at ${params.stage} with fail-closed action=${DEGRADED_MODE_ACTION_BLOCK}. ` +
631
652
  `reason=${degraded.reason} source=${degraded.source}.`,
632
653
  filePath: '.pumuki/degraded-mode.json',
633
654
  matchedBy: 'DegradedModeGuard',
@@ -639,7 +660,7 @@ const toDegradedModeFinding = (params: {
639
660
  severity: 'INFO',
640
661
  code: degraded.code,
641
662
  message:
642
- `Degraded mode is active at ${params.stage} with fail-open action=allow. ` +
663
+ `Degraded mode is active at ${params.stage} with fail-open action=${DEGRADED_MODE_ACTION_ALLOW}. ` +
643
664
  `reason=${degraded.reason} source=${degraded.source}.`,
644
665
  filePath: '.pumuki/degraded-mode.json',
645
666
  matchedBy: 'DegradedModeGuard',
@@ -780,7 +801,6 @@ const toCrossPlatformCriticalEnforcementBlockingFinding = (params: {
780
801
  .sort();
781
802
 
782
803
  if (criticalSkillRules.length === 0) {
783
- gaps.push(`${platform}{critical_profile_rules=missing}`);
784
804
  continue;
785
805
  }
786
806
 
@@ -824,35 +844,9 @@ const applySkillsFindingEnforcement = (
824
844
  if (!finding) {
825
845
  return undefined;
826
846
  }
827
- const skillsEnforcement = resolveSkillsEnforcement();
828
- if (skillsEnforcement.blocking) {
829
- return finding;
830
- }
831
847
  return {
832
848
  ...finding,
833
- severity: 'WARN',
834
- };
835
- };
836
-
837
- const toSoftPreCommitSkillsFinding = (params: {
838
- finding: Finding | undefined;
839
- enabled: boolean;
840
- observedCodePaths: ReadonlyArray<string>;
841
- }): Finding | undefined => {
842
- if (!params.finding) {
843
- return undefined;
844
- }
845
- if (!params.enabled || !shouldBlockFromFinding(params.finding)) {
846
- return params.finding;
847
- }
848
- return {
849
- ...params.finding,
850
- severity: 'WARN',
851
- code: `${params.finding.code}_SOFT_PRECOMMIT`,
852
- message:
853
- `${params.finding.message} ` +
854
- `Soft-enforced at PRE_COMMIT for low-risk scope (observed_code_paths=${params.observedCodePaths.length}). ` +
855
- 'Strict enforcement remains active at PRE_PUSH/CI.',
849
+ severity: 'ERROR',
856
850
  };
857
851
  };
858
852
 
@@ -874,7 +868,7 @@ export async function runPlatformGate(params: {
874
868
  ...params.dependencies,
875
869
  };
876
870
  const repoRoot = git.resolveRepoRoot();
877
- const auditMode = params.auditMode ?? 'gate';
871
+ const auditMode = params.auditMode ?? DEFAULT_GATE_AUDIT_MODE;
878
872
  const shouldShortCircuitSdd = params.sddShortCircuit ?? false;
879
873
  let sddDecision:
880
874
  | Pick<SddDecision, 'allowed' | 'code' | 'message'>
@@ -1087,15 +1081,12 @@ export async function runPlatformGate(params: {
1087
1081
  policyTrace: params.policyTrace,
1088
1082
  })
1089
1083
  : undefined;
1090
- const degradedModeFinding =
1091
- params.policy.stage === 'PRE_COMMIT' ||
1092
- params.policy.stage === 'PRE_PUSH' ||
1093
- params.policy.stage === 'CI'
1094
- ? toDegradedModeFinding({
1095
- stage: params.policy.stage,
1096
- policyTrace: params.policyTrace,
1097
- })
1098
- : undefined;
1084
+ const degradedModeFinding = LIFECYCLE_GATE_STAGES.includes(params.policy.stage)
1085
+ ? toDegradedModeFinding({
1086
+ stage: params.policy.stage,
1087
+ policyTrace: params.policyTrace,
1088
+ })
1089
+ : undefined;
1099
1090
  const astIntelligenceDualValidation:
1100
1091
  | AstIntelligenceDualValidationResult
1101
1092
  | undefined =
@@ -1125,7 +1116,8 @@ export async function runPlatformGate(params: {
1125
1116
  );
1126
1117
  }
1127
1118
  }
1128
- const degradedModeBlocks = params.policyTrace?.degraded?.action === 'block';
1119
+ const degradedModeBlocks =
1120
+ params.policyTrace?.degraded?.action === DEGRADED_MODE_ACTION_BLOCK;
1129
1121
  const rulesCoverage = coverage
1130
1122
  ? {
1131
1123
  stage: params.policy.stage,
@@ -1189,7 +1181,11 @@ export async function runPlatformGate(params: {
1189
1181
  coverage_ratio:
1190
1182
  coverage.activeRuleIds.length === 0
1191
1183
  ? 1
1192
- : Number((coverage.evaluatedRuleIds.length / coverage.activeRuleIds.length).toFixed(6)),
1184
+ : Number(
1185
+ (
1186
+ coverage.evaluatedRuleIds.length / coverage.activeRuleIds.length
1187
+ ).toFixed(DEFAULT_RULES_COVERAGE_RATIO_DECIMALS)
1188
+ ),
1193
1189
  }
1194
1190
  : createEmptySnapshotRulesCoverage(params.policy.stage);
1195
1191
  const brownfieldHotspotFindings = dependencies.evaluateBrownfieldHotspotFindings({
@@ -1214,37 +1210,9 @@ export async function runPlatformGate(params: {
1214
1210
  const hasNativeBlockingFinding = findings.some(
1215
1211
  (finding) => finding.severity === 'ERROR' || finding.severity === 'CRITICAL'
1216
1212
  );
1217
- const preCommitSoftSkillsEnabled = process.env.PUMUKI_PRE_COMMIT_SOFT_SKILLS !== '0';
1218
- const lowRiskPreCommitWindow = observedCodePaths.length > 0 && observedCodePaths.length <= 3;
1219
- const shouldSoftEnforceSkillsFindings =
1220
- params.policy.stage === 'PRE_COMMIT'
1221
- && preCommitSoftSkillsEnabled
1222
- && lowRiskPreCommitWindow
1223
- && !sddBlockingFinding
1224
- && !degradedModeBlocks
1225
- && !shouldBlockFromFinding(policyAsCodeBlockingFinding)
1226
- && !shouldBlockFromFinding(effectiveUnsupportedSkillsMappingFinding)
1227
- && !shouldBlockFromFinding(coverageBlockingFinding)
1228
- && !shouldBlockFromFinding(activeRulesEmptyForCodeChangesFinding)
1229
- && !shouldBlockFromFinding(effectiveIosTestsQualityFinding)
1230
- && !shouldBlockFromFinding(astIntelligenceDualFinding)
1231
- && !hasTddBddBlockingFinding
1232
- && !hasNativeBlockingFinding;
1233
- const effectivePlatformSkillsCoverageFinding = toSoftPreCommitSkillsFinding({
1234
- finding: effectivePlatformSkillsCoverageInput,
1235
- enabled: shouldSoftEnforceSkillsFindings,
1236
- observedCodePaths,
1237
- });
1238
- const effectiveCrossPlatformCriticalFinding = toSoftPreCommitSkillsFinding({
1239
- finding: effectiveCrossPlatformCriticalInput,
1240
- enabled: shouldSoftEnforceSkillsFindings,
1241
- observedCodePaths,
1242
- });
1243
- const effectiveSkillsScopeComplianceFinding = toSoftPreCommitSkillsFinding({
1244
- finding: effectiveSkillsScopeComplianceInput,
1245
- enabled: shouldSoftEnforceSkillsFindings,
1246
- observedCodePaths,
1247
- });
1213
+ const effectivePlatformSkillsCoverageFinding = effectivePlatformSkillsCoverageInput;
1214
+ const effectiveCrossPlatformCriticalFinding = effectiveCrossPlatformCriticalInput;
1215
+ const effectiveSkillsScopeComplianceFinding = effectiveSkillsScopeComplianceInput;
1248
1216
  const effectiveFindings = sddBlockingFinding
1249
1217
  ? [
1250
1218
  sddBlockingFinding,
@@ -1395,7 +1363,7 @@ export async function runPlatformGate(params: {
1395
1363
  if (params.silent !== true) {
1396
1364
  process.stdout.write(
1397
1365
  `[pumuki][memory-shadow] recommended=${memoryShadowRecommendation.recommendedOutcome}` +
1398
- ` confidence=${memoryShadowRecommendation.confidence.toFixed(2)}` +
1366
+ ` confidence=${memoryShadowRecommendation.confidence.toFixed(DEFAULT_MEMORY_SHADOW_DISPLAY_PRECISION)}` +
1399
1367
  ` reasons=${memoryShadowRecommendation.reasonCodes.join(',')}\n`
1400
1368
  );
1401
1369
  }
@@ -6,47 +6,7 @@ export type SkillsEnforcementResolution = {
6
6
  blocking: boolean;
7
7
  };
8
8
 
9
- const SKILLS_ENFORCEMENT_ENV = 'PUMUKI_SKILLS_ENFORCEMENT';
10
-
11
- const toSkillsEnforcementMode = (
12
- value: string | undefined
13
- ): SkillsEnforcementMode | null => {
14
- if (typeof value !== 'string') {
15
- return null;
16
- }
17
- const normalized = value.trim().toLowerCase();
18
- if (
19
- normalized === 'strict'
20
- || normalized === '1'
21
- || normalized === 'true'
22
- || normalized === 'yes'
23
- || normalized === 'on'
24
- ) {
25
- return 'strict';
26
- }
27
- if (
28
- normalized === 'advisory'
29
- || normalized === 'warn'
30
- || normalized === 'warning'
31
- || normalized === '0'
32
- || normalized === 'false'
33
- || normalized === 'no'
34
- || normalized === 'off'
35
- ) {
36
- return 'advisory';
37
- }
38
- return null;
39
- };
40
-
41
9
  export const resolveSkillsEnforcement = (): SkillsEnforcementResolution => {
42
- const modeFromEnv = toSkillsEnforcementMode(process.env[SKILLS_ENFORCEMENT_ENV]);
43
- if (modeFromEnv) {
44
- return {
45
- mode: modeFromEnv,
46
- source: 'env',
47
- blocking: modeFromEnv === 'strict',
48
- };
49
- }
50
10
  return {
51
11
  mode: 'strict',
52
12
  source: 'default',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.131",
3
+ "version": "6.3.133",
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": {