pumuki 6.3.127 → 6.3.128

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/VERSION CHANGED
@@ -1 +1 @@
1
- v6.3.127
1
+ v6.3.128
@@ -21,13 +21,25 @@ export type SkillsRuleSetLoadResult = {
21
21
  mappedHeuristicRuleIds: ReadonlySet<string>;
22
22
  requiresHeuristicFacts: boolean;
23
23
  unsupportedAutoRuleIds?: ReadonlyArray<string>;
24
+ registryCoverage?: {
25
+ contract: 'AUTO_RUNTIME_RULES_FOR_STAGE';
26
+ stage: Exclude<GateStage, 'STAGED'>;
27
+ registryTotals: {
28
+ total: number;
29
+ auto: number;
30
+ declarative: number;
31
+ };
32
+ stageApplicableAutoRuleIds: ReadonlyArray<string>;
33
+ declarativeRuleIds: ReadonlyArray<string>;
34
+ excludedDeclarativeReason: string;
35
+ };
24
36
  };
25
37
 
26
38
  const STAGE_RANK: Record<Exclude<GateStage, 'STAGED'>, number> = {
27
- PRE_WRITE: 30,
28
- PRE_COMMIT: 30,
39
+ PRE_WRITE: 10,
40
+ PRE_COMMIT: 20,
29
41
  PRE_PUSH: 30,
30
- CI: 30,
42
+ CI: 40,
31
43
  };
32
44
 
33
45
  const PLATFORM_KEYS: ReadonlyArray<keyof DetectedPlatforms> = [
@@ -445,31 +457,7 @@ const toRuleDefinition = (params: {
445
457
  };
446
458
  }
447
459
 
448
- // Declarative rules remain explicit, but AUTO rules without mapping are
449
- // excluded from runtime rule conversion and reported separately.
450
- return {
451
- id: params.rule.id,
452
- description: params.rule.description,
453
- severity,
454
- platform: params.rule.platform,
455
- locked: params.rule.locked ?? true,
456
- confidence: params.rule.confidence,
457
- when: {
458
- kind: 'FileContent',
459
- regex: ['a^'],
460
- },
461
- then: {
462
- kind: 'Finding',
463
- message: `[Declarative] ${params.rule.description}`,
464
- code: `${toCode(params.rule.id)}_DECLARATIVE`,
465
- source: runtimeIrSource,
466
- },
467
- scope: resolveScopeForPlatform(
468
- params.rule.platform,
469
- params.repoRoot,
470
- params.observedFilePaths
471
- ),
472
- };
460
+ return undefined;
473
461
  };
474
462
 
475
463
  const hasDetectedPlatforms = (detectedPlatforms?: DetectedPlatforms): boolean => {
@@ -546,11 +534,23 @@ export const loadSkillsRuleSetForStage = (
546
534
  const rulesById = new Map<string, RuleDefinition>();
547
535
  const mappedHeuristicRuleIds = new Set<string>();
548
536
  const unsupportedAutoRuleIds = new Set<string>();
537
+ const registryRuleIds = new Set<string>();
538
+ const registryAutoRuleIds = new Set<string>();
539
+ const registryDeclarativeRuleIds = new Set<string>();
540
+ const stageApplicableAutoRuleIds = new Set<string>();
549
541
 
550
542
  for (const bundle of activeBundles) {
551
543
  const bundlePolicy = policy?.bundles[bundle.name];
552
544
 
553
545
  for (const compiledRule of bundle.rules) {
546
+ registryRuleIds.add(compiledRule.id);
547
+ const evaluationMode = resolveRuleEvaluationMode(compiledRule);
548
+ if (evaluationMode === 'AUTO') {
549
+ registryAutoRuleIds.add(compiledRule.id);
550
+ } else {
551
+ registryDeclarativeRuleIds.add(compiledRule.id);
552
+ }
553
+
554
554
  if (
555
555
  !isRulePlatformActive({
556
556
  rule: compiledRule,
@@ -561,7 +561,13 @@ export const loadSkillsRuleSetForStage = (
561
561
  }
562
562
 
563
563
  const mappedRuleIds = resolveMappedHeuristicRuleIdsForCompiledRule(compiledRule);
564
- const evaluationMode = resolveRuleEvaluationMode(compiledRule);
564
+ if (!stageApplies(stage, compiledRule.stage)) {
565
+ continue;
566
+ }
567
+ if (evaluationMode !== 'AUTO') {
568
+ continue;
569
+ }
570
+ stageApplicableAutoRuleIds.add(compiledRule.id);
565
571
  if (evaluationMode === 'AUTO' && mappedRuleIds.length === 0) {
566
572
  unsupportedAutoRuleIds.add(compiledRule.id);
567
573
  continue;
@@ -596,5 +602,18 @@ export const loadSkillsRuleSetForStage = (
596
602
  mappedHeuristicRuleIds,
597
603
  requiresHeuristicFacts: mappedHeuristicRuleIds.size > 0,
598
604
  unsupportedAutoRuleIds: [...unsupportedAutoRuleIds].sort(),
605
+ registryCoverage: {
606
+ contract: 'AUTO_RUNTIME_RULES_FOR_STAGE',
607
+ stage,
608
+ registryTotals: {
609
+ total: registryRuleIds.size,
610
+ auto: registryAutoRuleIds.size,
611
+ declarative: registryDeclarativeRuleIds.size,
612
+ },
613
+ stageApplicableAutoRuleIds: [...stageApplicableAutoRuleIds].sort(),
614
+ declarativeRuleIds: [...registryDeclarativeRuleIds].sort(),
615
+ excludedDeclarativeReason:
616
+ 'DECLARATIVE skills are registry contract/policy rules. They are not executed as PRE_COMMIT runtime detectors; only AUTO rules applicable to the current stage are evaluated.',
617
+ },
599
618
  };
600
619
  };
@@ -34,6 +34,9 @@ export const createEmptySnapshotRulesCoverage = (
34
34
  stage: GateStage
35
35
  ): SnapshotRulesCoverage => ({
36
36
  stage,
37
+ contract: 'AUTO_RUNTIME_RULES_FOR_STAGE',
38
+ scope_note:
39
+ 'No runtime rules were evaluated for this stage. DECLARATIVE registry rules are not runtime detectors.',
37
40
  active_rule_ids: [],
38
41
  evaluated_rule_ids: [],
39
42
  matched_rule_ids: [],
@@ -60,6 +63,11 @@ export const normalizeSnapshotRulesCoverage = (
60
63
  const matchedRuleIds = normalizeStringArray(value.matched_rule_ids);
61
64
  const unevaluatedRuleIds = normalizeStringArray(value.unevaluated_rule_ids);
62
65
  const unsupportedAutoRuleIds = normalizeStringArray(value.unsupported_auto_rule_ids ?? []);
66
+ const stageApplicableAutoRuleIds = normalizeStringArray(
67
+ value.stage_applicable_auto_rule_ids ?? []
68
+ );
69
+ const declarativeRuleIds = normalizeStringArray(value.declarative_rule_ids ?? []);
70
+ const registryTotals = value.registry_totals;
63
71
 
64
72
  const derivedCounts = {
65
73
  active: activeRuleIds.length,
@@ -83,6 +91,15 @@ export const normalizeSnapshotRulesCoverage = (
83
91
  ),
84
92
  };
85
93
 
94
+ if (registryTotals) {
95
+ counts.registry_total = normalizeCount(registryTotals.total);
96
+ counts.registry_auto = normalizeCount(registryTotals.auto);
97
+ counts.registry_declarative = normalizeCount(registryTotals.declarative);
98
+ }
99
+ if (stageApplicableAutoRuleIds.length > 0) {
100
+ counts.stage_applicable_auto = stageApplicableAutoRuleIds.length;
101
+ }
102
+
86
103
  if (unsupportedAutoCount > 0) {
87
104
  counts.unsupported_auto = unsupportedAutoCount;
88
105
  }
@@ -94,6 +111,10 @@ export const normalizeSnapshotRulesCoverage = (
94
111
 
95
112
  const normalized: SnapshotRulesCoverage = {
96
113
  stage,
114
+ contract: value.contract ?? 'AUTO_RUNTIME_RULES_FOR_STAGE',
115
+ scope_note:
116
+ value.scope_note ??
117
+ 'rules_coverage reports AUTO runtime rules applicable to this stage, not total DECLARATIVE registry surface.',
97
118
  active_rule_ids: activeRuleIds,
98
119
  evaluated_rule_ids: evaluatedRuleIds,
99
120
  matched_rule_ids: matchedRuleIds,
@@ -102,6 +123,26 @@ export const normalizeSnapshotRulesCoverage = (
102
123
  coverage_ratio: coverageRatio,
103
124
  };
104
125
 
126
+ if (registryTotals) {
127
+ normalized.registry_totals = {
128
+ total: normalizeCount(registryTotals.total),
129
+ auto: normalizeCount(registryTotals.auto),
130
+ declarative: normalizeCount(registryTotals.declarative),
131
+ };
132
+ }
133
+
134
+ if (stageApplicableAutoRuleIds.length > 0) {
135
+ normalized.stage_applicable_auto_rule_ids = stageApplicableAutoRuleIds;
136
+ }
137
+
138
+ if (declarativeRuleIds.length > 0) {
139
+ normalized.declarative_rule_ids = declarativeRuleIds;
140
+ }
141
+
142
+ if (typeof value.declarative_excluded_reason === 'string') {
143
+ normalized.declarative_excluded_reason = value.declarative_excluded_reason;
144
+ }
145
+
105
146
  if (unsupportedAutoRuleIds.length > 0 || unsupportedAutoCount > 0) {
106
147
  normalized.unsupported_auto_rule_ids = unsupportedAutoRuleIds;
107
148
  }
@@ -47,16 +47,30 @@ export type SnapshotEvaluationMetrics = {
47
47
 
48
48
  export type SnapshotRulesCoverage = {
49
49
  stage: GateStage;
50
+ contract?: 'AUTO_RUNTIME_RULES_FOR_STAGE';
51
+ scope_note?: string;
50
52
  active_rule_ids: string[];
51
53
  evaluated_rule_ids: string[];
52
54
  matched_rule_ids: string[];
53
55
  unevaluated_rule_ids: string[];
54
56
  unsupported_auto_rule_ids?: string[];
57
+ registry_totals?: {
58
+ total: number;
59
+ auto: number;
60
+ declarative: number;
61
+ };
62
+ stage_applicable_auto_rule_ids?: string[];
63
+ declarative_rule_ids?: string[];
64
+ declarative_excluded_reason?: string;
55
65
  counts: {
56
66
  active: number;
57
67
  evaluated: number;
58
68
  matched: number;
59
69
  unevaluated: number;
70
+ registry_total?: number;
71
+ registry_auto?: number;
72
+ registry_declarative?: number;
73
+ stage_applicable_auto?: number;
60
74
  unsupported_auto?: number;
61
75
  };
62
76
  coverage_ratio: number;
@@ -1115,10 +1115,24 @@ export async function runPlatformGate(params: {
1115
1115
  const rulesCoverage = coverage
1116
1116
  ? {
1117
1117
  stage: params.policy.stage,
1118
+ contract: skillsRuleSet.registryCoverage?.contract ?? 'AUTO_RUNTIME_RULES_FOR_STAGE',
1119
+ scope_note:
1120
+ 'rules_coverage reports AUTO runtime rules applicable to this stage; it does not claim full DECLARATIVE registry execution.',
1118
1121
  active_rule_ids: [...coverage.activeRuleIds],
1119
1122
  evaluated_rule_ids: [...coverage.evaluatedRuleIds],
1120
1123
  matched_rule_ids: [...coverage.matchedRuleIds],
1121
1124
  unevaluated_rule_ids: [...coverage.unevaluatedRuleIds],
1125
+ ...(skillsRuleSet.registryCoverage
1126
+ ? {
1127
+ registry_totals: skillsRuleSet.registryCoverage.registryTotals,
1128
+ stage_applicable_auto_rule_ids: [
1129
+ ...skillsRuleSet.registryCoverage.stageApplicableAutoRuleIds,
1130
+ ],
1131
+ declarative_rule_ids: [...skillsRuleSet.registryCoverage.declarativeRuleIds],
1132
+ declarative_excluded_reason:
1133
+ skillsRuleSet.registryCoverage.excludedDeclarativeReason,
1134
+ }
1135
+ : {}),
1122
1136
  ...((skillsRuleSet.unsupportedAutoRuleIds?.length ?? 0) > 0
1123
1137
  ? {
1124
1138
  unsupported_auto_rule_ids: [...(skillsRuleSet.unsupportedAutoRuleIds ?? [])],
@@ -1129,6 +1143,16 @@ export async function runPlatformGate(params: {
1129
1143
  evaluated: coverage.evaluatedRuleIds.length,
1130
1144
  matched: coverage.matchedRuleIds.length,
1131
1145
  unevaluated: coverage.unevaluatedRuleIds.length,
1146
+ ...(skillsRuleSet.registryCoverage
1147
+ ? {
1148
+ registry_total: skillsRuleSet.registryCoverage.registryTotals.total,
1149
+ registry_auto: skillsRuleSet.registryCoverage.registryTotals.auto,
1150
+ registry_declarative:
1151
+ skillsRuleSet.registryCoverage.registryTotals.declarative,
1152
+ stage_applicable_auto:
1153
+ skillsRuleSet.registryCoverage.stageApplicableAutoRuleIds.length,
1154
+ }
1155
+ : {}),
1132
1156
  ...((skillsRuleSet.unsupportedAutoRuleIds?.length ?? 0) > 0
1133
1157
  ? {
1134
1158
  unsupported_auto: (skillsRuleSet.unsupportedAutoRuleIds ?? []).length,
@@ -1,5 +1,5 @@
1
1
  import { readEvidence } from '../evidence/readEvidence';
2
- import type { AiEvidenceV2_1, SnapshotFinding } from '../evidence/schema';
2
+ import type { AiEvidenceV2_1, SnapshotFinding, SnapshotRulesCoverage } from '../evidence/schema';
3
3
  import { GitService, type IGitService } from '../git/GitService';
4
4
  import { hasAllowedExtension } from '../git/gitDiffUtils';
5
5
  import { runPlatformGate } from '../git/runPlatformGate';
@@ -31,6 +31,18 @@ export type LifecycleAuditResult = {
31
31
  snapshot_outcome: string | null;
32
32
  findings_count: number;
33
33
  blocking_findings_count: number;
34
+ rules_coverage: SnapshotRulesCoverage | null;
35
+ rule_id_normalization: {
36
+ contract: 'registry_or_declared_runtime_normalization';
37
+ registry_rule_ids_count: number;
38
+ finding_rule_ids_count: number;
39
+ entries: ReadonlyArray<{
40
+ runtime_rule_id: string;
41
+ registry_rule_id: string | null;
42
+ status: 'registry_1_to_1' | 'runtime_derived';
43
+ normalization: string;
44
+ }>;
45
+ };
34
46
  findings: ReadonlyArray<LifecycleAuditFinding>;
35
47
  policy_reconcile_hint: string;
36
48
  };
@@ -114,6 +126,39 @@ const extractAuditFindings = (params: {
114
126
  return [];
115
127
  };
116
128
 
129
+ const buildRuleIdNormalization = (params: {
130
+ findings: ReadonlyArray<LifecycleAuditFinding>;
131
+ rulesCoverage: SnapshotRulesCoverage | undefined;
132
+ }): LifecycleAuditResult['rule_id_normalization'] => {
133
+ const registryRuleIds = new Set([
134
+ ...(params.rulesCoverage?.stage_applicable_auto_rule_ids ?? []),
135
+ ...(params.rulesCoverage?.declarative_rule_ids ?? []),
136
+ ]);
137
+ const findingRuleIds = [...new Set(params.findings.map((finding) => finding.ruleId))].sort();
138
+ return {
139
+ contract: 'registry_or_declared_runtime_normalization',
140
+ registry_rule_ids_count: registryRuleIds.size,
141
+ finding_rule_ids_count: findingRuleIds.length,
142
+ entries: findingRuleIds.map((ruleId) => {
143
+ if (registryRuleIds.has(ruleId)) {
144
+ return {
145
+ runtime_rule_id: ruleId,
146
+ registry_rule_id: ruleId,
147
+ status: 'registry_1_to_1',
148
+ normalization: 'finding ruleId is an exact skills registry rule id',
149
+ };
150
+ }
151
+ return {
152
+ runtime_rule_id: ruleId,
153
+ registry_rule_id: null,
154
+ status: 'runtime_derived',
155
+ normalization:
156
+ 'finding ruleId is emitted by baseline/runtime governance outside the skills registry; see rules_coverage for the AUTO skills scope evaluated at this stage',
157
+ };
158
+ }),
159
+ };
160
+ };
161
+
117
162
  export const runLifecycleAudit = async (params: {
118
163
  stage: LifecycleAuditStage;
119
164
  auditMode: 'gate' | 'engine';
@@ -192,6 +237,11 @@ export const runLifecycleAudit = async (params: {
192
237
  snapshot_outcome: snapshotOutcome,
193
238
  findings_count: findings.length,
194
239
  blocking_findings_count: findings.filter((finding) => finding.blocking).length,
240
+ rules_coverage: evidence?.snapshot.rules_coverage ?? null,
241
+ rule_id_normalization: buildRuleIdNormalization({
242
+ findings,
243
+ rulesCoverage: evidence?.snapshot.rules_coverage,
244
+ }),
195
245
  findings,
196
246
  policy_reconcile_hint: POLICY_RECONCILE_HINT,
197
247
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.127",
3
+ "version": "6.3.128",
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": {
@@ -61,7 +61,7 @@ export const createConsumerLegacyMenuActions = (
61
61
  },
62
62
  {
63
63
  id: '14',
64
- label: 'Engine audit · FULL tracked repo (no preflight · PRE_COMMIT)',
64
+ label: 'Engine audit · tracked repo files (AUTO runtime rules · PRE_COMMIT)',
65
65
  execute: params.runEngineFullRepoNoPreflight,
66
66
  },
67
67
  {