pumuki 6.3.172 → 6.3.174

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.
Files changed (120) hide show
  1. package/AGENTS.md +1 -16
  2. package/CHANGELOG.md +0 -101
  3. package/README.md +10 -14
  4. package/VERSION +1 -1
  5. package/core/facts/detectors/text/android.test.ts +0 -2827
  6. package/core/facts/detectors/text/android.ts +182 -5121
  7. package/core/facts/detectors/text/ios.test.ts +12 -290
  8. package/core/facts/detectors/text/ios.ts +28 -301
  9. package/core/facts/detectors/typescript/index.test.ts +139 -3733
  10. package/core/facts/detectors/typescript/index.ts +264 -4959
  11. package/core/facts/extractHeuristicFacts.ts +11 -328
  12. package/core/gate/evaluateRules.test.ts +0 -7
  13. package/core/gate/evaluateRules.ts +2 -1
  14. package/core/rules/presets/heuristics/android.test.ts +1 -399
  15. package/core/rules/presets/heuristics/android.ts +1 -1481
  16. package/core/rules/presets/heuristics/ios.test.ts +1 -11
  17. package/core/rules/presets/heuristics/ios.ts +0 -36
  18. package/core/rules/presets/heuristics/typescript.test.ts +2 -158
  19. package/core/rules/presets/heuristics/typescript.ts +0 -508
  20. package/core/rules/presets/iosEnterpriseRuleSet.test.ts +0 -5
  21. package/core/rules/presets/iosEnterpriseRuleSet.ts +5 -5
  22. package/docs/README.md +3 -3
  23. package/docs/operations/RELEASE_NOTES.md +1 -94
  24. package/docs/operations/framework-menu-consumer-walkthrough.md +15 -18
  25. package/docs/product/API_REFERENCE.md +1 -1
  26. package/docs/product/CONFIGURATION.md +0 -7
  27. package/docs/product/USAGE.md +1 -1
  28. package/docs/validation/README.md +1 -3
  29. package/docs/validation/ios-avdlee-parity-matrix.md +1 -1
  30. package/integrations/config/skillsCompilerTemplates.test.ts +0 -145
  31. package/integrations/config/skillsCompilerTemplates.ts +2 -1013
  32. package/integrations/config/skillsDetectorRegistry.ts +8 -523
  33. package/integrations/config/skillsMarkdownRules.ts +8 -1088
  34. package/integrations/config/skillsRuleSet.ts +3 -44
  35. package/integrations/evidence/buildEvidence.ts +5 -34
  36. package/integrations/evidence/platformSummary.test.ts +9 -73
  37. package/integrations/evidence/platformSummary.ts +7 -165
  38. package/integrations/evidence/repoState.ts +0 -3
  39. package/integrations/evidence/rulesCoverage.ts +0 -83
  40. package/integrations/evidence/schema.ts +0 -29
  41. package/integrations/evidence/writeEvidence.test.ts +0 -4
  42. package/integrations/evidence/writeEvidence.ts +2 -41
  43. package/integrations/gate/evaluateAiGate.ts +8 -312
  44. package/integrations/gate/remediationCatalog.ts +2 -20
  45. package/integrations/gate/stagePolicies.ts +18 -24
  46. package/integrations/git/astIntelligenceDualValidation.ts +2 -2
  47. package/integrations/git/gitAtomicity.ts +39 -284
  48. package/integrations/git/resolveGitRefs.ts +6 -35
  49. package/integrations/git/runPlatformGate.ts +143 -512
  50. package/integrations/git/runPlatformGateOutput.ts +8 -13
  51. package/integrations/git/stageRunners.ts +41 -25
  52. package/integrations/lifecycle/adapter.ts +0 -24
  53. package/integrations/lifecycle/audit.ts +16 -14
  54. package/integrations/lifecycle/cli.ts +20 -37
  55. package/integrations/lifecycle/cliSdd.ts +3 -4
  56. package/integrations/lifecycle/doctor.ts +1 -1
  57. package/integrations/lifecycle/packageInfo.ts +1 -118
  58. package/integrations/lifecycle/policyReconcile.ts +4 -27
  59. package/integrations/lifecycle/preWriteAutomation.ts +5 -5
  60. package/integrations/lifecycle/state.ts +1 -8
  61. package/integrations/lifecycle/watch.ts +8 -28
  62. package/integrations/mcp/aiGateCheck.ts +10 -194
  63. package/integrations/mcp/autoExecuteAiStart.ts +4 -7
  64. package/integrations/mcp/enterpriseServer.ts +3 -19
  65. package/integrations/mcp/preFlightCheck.ts +10 -89
  66. package/integrations/policy/gitAtomicityEnforcement.ts +2 -2
  67. package/integrations/policy/heuristicsEnforcement.ts +2 -2
  68. package/integrations/policy/policyProfiles.ts +18 -24
  69. package/integrations/policy/preWriteEnforcement.ts +1 -1
  70. package/integrations/policy/sddCompletenessEnforcement.ts +2 -2
  71. package/integrations/policy/skillsEnforcement.ts +47 -1
  72. package/integrations/policy/tddBddEnforcement.ts +2 -2
  73. package/integrations/sdd/evidenceScaffold.ts +8 -124
  74. package/integrations/tdd/contract.ts +0 -1
  75. package/integrations/tdd/enforcement.ts +0 -103
  76. package/integrations/tdd/types.ts +0 -6
  77. package/package.json +1 -1
  78. package/scripts/check-tracking-single-active.sh +1 -1
  79. package/scripts/framework-menu-advanced-view-lib.ts +0 -49
  80. package/scripts/framework-menu-consumer-actions-lib.ts +32 -32
  81. package/scripts/framework-menu-consumer-preflight-render.ts +0 -10
  82. package/scripts/framework-menu-consumer-preflight-run.ts +5 -31
  83. package/scripts/framework-menu-consumer-preflight-types.ts +0 -12
  84. package/scripts/framework-menu-consumer-runtime-actions.ts +5 -11
  85. package/scripts/framework-menu-consumer-runtime-audit.ts +28 -0
  86. package/scripts/framework-menu-consumer-runtime-evidence-classic.ts +42 -118
  87. package/scripts/framework-menu-consumer-runtime-lib.ts +0 -38
  88. package/scripts/framework-menu-consumer-runtime-menu.ts +15 -55
  89. package/scripts/framework-menu-consumer-runtime-types.ts +0 -4
  90. package/scripts/framework-menu-evidence-summary-read.ts +1 -17
  91. package/scripts/framework-menu-evidence-summary-types.ts +0 -3
  92. package/scripts/framework-menu-layout-data.ts +23 -3
  93. package/scripts/framework-menu-system-notifications-cause.ts +1 -24
  94. package/scripts/framework-menu-system-notifications-env.ts +0 -8
  95. package/scripts/framework-menu-system-notifications-gate.ts +2 -9
  96. package/scripts/framework-menu-system-notifications-macos-applescript-dialog.ts +1 -1
  97. package/scripts/framework-menu-system-notifications-macos-dialog-payload.ts +2 -14
  98. package/scripts/framework-menu-system-notifications-macos-swift-source.ts +1 -1
  99. package/scripts/framework-menu-system-notifications-payloads-blocked.ts +4 -128
  100. package/scripts/framework-menu-system-notifications-payloads.ts +1 -8
  101. package/scripts/framework-menu-system-notifications-remediation.ts +1 -15
  102. package/scripts/framework-menu-system-notifications-text.ts +1 -7
  103. package/scripts/framework-menu.ts +2 -37
  104. package/scripts/package-install-smoke-consumer-git-repo-lib.ts +1 -10
  105. package/scripts/package-install-smoke-consumer-npm-lib.ts +9 -46
  106. package/skills.lock.json +1244 -807
  107. package/integrations/evidence/trackingContract.ts +0 -17
  108. package/integrations/gate/blockingCause.ts +0 -40
  109. package/integrations/gate/governanceActionCatalog.ts +0 -296
  110. package/integrations/gate/runPlatformGateConfig.ts +0 -55
  111. package/integrations/gate/runPlatformGateDefaults.ts +0 -19
  112. package/integrations/lifecycle/bootstrapManifest.ts +0 -248
  113. package/integrations/lifecycle/cliGovernanceConsole.ts +0 -69
  114. package/integrations/lifecycle/governanceNextAction.ts +0 -181
  115. package/integrations/lifecycle/governanceObservationSnapshot.ts +0 -376
  116. package/integrations/lifecycle/trackingState.ts +0 -403
  117. package/integrations/mcp/alignedPlatformGate.ts +0 -248
  118. package/integrations/mcp/readMcpPrePushStdin.ts +0 -7
  119. package/scripts/build-ruralgo-s1-evidence-pack.ts +0 -85
  120. package/scripts/ruralgo-s1-evidence-pack-lib.ts +0 -200
@@ -32,8 +32,6 @@ export type SwiftPresentationSrpMatch = {
32
32
  lines: readonly number[];
33
33
  };
34
34
 
35
- export type SwiftXCTestSrpMatch = SwiftPresentationSrpMatch;
36
-
37
35
  export type SwiftConcreteDependencyDipMatch = {
38
36
  primary_node: SwiftSemanticNodeMatch;
39
37
  related_nodes: readonly SwiftSemanticNodeMatch[];
@@ -100,63 +98,6 @@ const hasSwiftSanitizedRegexMatch = (source: string, regex: RegExp): boolean =>
100
98
  return regex.test(sanitizeSwiftSourceForMultilineRegex(source));
101
99
  };
102
100
 
103
- type SwiftFunctionDeclaration = {
104
- signature: string;
105
- body: string;
106
- };
107
-
108
- const collectSwiftFunctionDeclarations = (source: string): readonly SwiftFunctionDeclaration[] => {
109
- const lines = source.split(/\r?\n/);
110
- const functions: SwiftFunctionDeclaration[] = [];
111
-
112
- for (let index = 0; index < lines.length; index += 1) {
113
- const firstLine = stripSwiftLineForSemanticScan(lines[index] ?? '');
114
- if (!/\bfunc\b/.test(firstLine)) {
115
- continue;
116
- }
117
-
118
- const signatureLines: string[] = [];
119
- let cursor = index;
120
- let openingLineIndex = -1;
121
- for (; cursor < lines.length && cursor < index + 24; cursor += 1) {
122
- const line = stripSwiftLineForSemanticScan(lines[cursor] ?? '');
123
- signatureLines.push(line);
124
- if (line.includes('{')) {
125
- openingLineIndex = cursor;
126
- break;
127
- }
128
- if (line.includes('}')) {
129
- break;
130
- }
131
- }
132
-
133
- if (openingLineIndex < 0) {
134
- continue;
135
- }
136
-
137
- const bodyLines: string[] = [];
138
- let braceDepth = 0;
139
- for (let bodyCursor = openingLineIndex; bodyCursor < lines.length; bodyCursor += 1) {
140
- const line = stripSwiftLineForSemanticScan(lines[bodyCursor] ?? '');
141
- braceDepth += countTokenOccurrences(line, '{');
142
- braceDepth -= countTokenOccurrences(line, '}');
143
- bodyLines.push(line);
144
- if (bodyCursor > openingLineIndex && braceDepth <= 0) {
145
- cursor = bodyCursor;
146
- break;
147
- }
148
- }
149
-
150
- functions.push({
151
- signature: signatureLines.join('\n'),
152
- body: bodyLines.join('\n'),
153
- });
154
- index = cursor;
155
- }
156
-
157
- return functions;
158
- };
159
-
160
101
  const hasSwiftUiModernizationSnapshotMatch = (source: string, entryId: string): boolean => {
161
102
  const entry = getIosSwiftUiModernizationEntry(entryId);
162
103
  if (!entry) {
@@ -536,17 +477,6 @@ export const hasSwiftForEachIndicesUsage = (source: string): boolean => {
536
477
  );
537
478
  };
538
479
 
539
- export const hasSwiftInlineFilteringInForEachUsage = (source: string): boolean => {
540
- return hasSwiftSanitizedRegexMatch(
541
- source,
542
- /\bForEach\s*\(\s*[A-Za-z_][A-Za-z0-9_.]*\s*\.\s*filter\s*\{/g
543
- );
544
- };
545
-
546
- export const hasSwiftExplicitColorStaticMemberUsage = (source: string): boolean => {
547
- return hasSwiftSanitizedRegexMatch(source, /\bColor\s*\.\s*[a-z][A-Za-z0-9_]*\b/g);
548
- };
549
-
550
480
  const isUserSearchIdentifier = (value: string): boolean => {
551
481
  return /^(?:query|search(?:Text|Term|Query|Value)?|filter(?:Text|Value)?|text|term|input)$/i.test(
552
482
  value
@@ -597,36 +527,6 @@ export const hasSwiftLegacySwiftUiObservableWrapperUsage = (source: string): boo
597
527
  return hasSwiftSanitizedRegexMatch(source, /@\s*(?:StateObject|ObservedObject)\b/);
598
528
  };
599
529
 
600
- export const hasSwiftStateWrapperWithoutPrivateUsage = (source: string): boolean => {
601
- const typeDeclarations = parseSwiftTypeDeclarations(source);
602
- if (typeDeclarations.length === 0) {
603
- return false;
604
- }
605
-
606
- const sourceLines = source.split(/\r?\n/);
607
- const stateWrapperPattern = /@\s*(?:State|StateObject)\b/;
608
-
609
- for (const typeDeclaration of typeDeclarations) {
610
- if (!typeDeclaration.conformances.includes('View')) {
611
- continue;
612
- }
613
-
614
- const hasViolation = visitSwiftTopLevelTypeBodyLines(sourceLines, typeDeclaration, ({ line }) => {
615
- if (!stateWrapperPattern.test(line)) {
616
- return false;
617
- }
618
-
619
- return !/\bprivate\b/.test(line);
620
- });
621
-
622
- if (hasViolation) {
623
- return true;
624
- }
625
- }
626
-
627
- return false;
628
- };
629
-
630
530
  const hasSwiftPassedValueWrapperInitialization = (
631
531
  source: string,
632
532
  options: {
@@ -788,10 +688,6 @@ const hasSwiftTestingSuiteAttributeUsage = (source: string): boolean => {
788
688
  return hasSwiftSanitizedRegexMatch(source, /\B@(?:Test|Suite)\b/);
789
689
  };
790
690
 
791
- const hasSwiftTestingFrameworkMarkerUsage = (source: string): boolean => {
792
- return hasSwiftTestingImportUsage(source) || hasSwiftTestingSuiteAttributeUsage(source);
793
- };
794
-
795
691
  const hasSwiftXCTestCaseSubclassUsage = (source: string): boolean => {
796
692
  return hasSwiftSanitizedRegexMatch(
797
693
  source,
@@ -804,59 +700,15 @@ const hasSwiftLegacyXCTestMethodUsage = (source: string): boolean => {
804
700
  .length > 0;
805
701
  };
806
702
 
807
- const hasSwiftMakeSutUsage = (source: string): boolean => {
808
- return hasSwiftSanitizedRegexMatch(source, /\bmakeSUT\s*\(/);
809
- };
810
-
811
- const hasSwiftMemoryLeakTrackingUsage = (source: string): boolean => {
812
- return hasSwiftSanitizedRegexMatch(source, /\btrackForMemoryLeaks\s*\(/);
813
- };
814
-
815
- const hasSwiftBrownfieldCompatibleXCTestUsage = (source: string): boolean => {
816
- if (!hasSwiftXCTestImportUsage(source) || !hasSwiftXCTestCaseSubclassUsage(source)) {
817
- return false;
818
- }
819
-
820
- if (!hasSwiftLegacyXCTestMethodUsage(source)) {
821
- return false;
822
- }
823
-
824
- if (hasSwiftTestingImportUsage(source) || hasSwiftTestingSuiteAttributeUsage(source)) {
825
- return false;
826
- }
827
-
828
- return hasSwiftMakeSutUsage(source) && hasSwiftMemoryLeakTrackingUsage(source);
829
- };
830
-
831
- const hasSwiftXCTestOnlyBrownfieldSuiteUsage = (source: string): boolean => {
832
- if (!hasSwiftXCTestImportUsage(source) || !hasSwiftXCTestCaseSubclassUsage(source)) {
833
- return false;
834
- }
835
-
836
- if (hasSwiftLegacyXCTestUiOrPerformanceUsage(source)) {
837
- return false;
838
- }
839
-
840
- return !hasSwiftTestingImportUsage(source) && !hasSwiftTestingSuiteAttributeUsage(source);
841
- };
842
-
843
703
  export const hasSwiftLegacyXCTestImportUsage = (source: string): boolean => {
844
704
  if (!hasSwiftXCTestImportUsage(source)) {
845
705
  return false;
846
706
  }
847
707
 
848
- if (!hasSwiftXCTestCaseSubclassUsage(source) || !hasSwiftLegacyXCTestMethodUsage(source)) {
849
- return false;
850
- }
851
-
852
708
  if (hasSwiftLegacyXCTestUiOrPerformanceUsage(source)) {
853
709
  return false;
854
710
  }
855
711
 
856
- if (hasSwiftXCTestOnlyBrownfieldSuiteUsage(source)) {
857
- return false;
858
- }
859
-
860
712
  return true;
861
713
  };
862
714
 
@@ -877,18 +729,14 @@ export const hasSwiftModernizableXCTestSuiteUsage = (source: string): boolean =>
877
729
  };
878
730
 
879
731
  export const hasSwiftMixedTestingFrameworksUsage = (source: string): boolean => {
880
- return hasSwiftXCTestCaseSubclassUsage(source) && hasSwiftTestingFrameworkMarkerUsage(source);
881
- };
882
-
883
- export const hasSwiftXCTestAssertionUsage = (source: string): boolean => {
884
- if (hasSwiftLegacyXCTestUiOrPerformanceUsage(source)) {
732
+ if (!hasSwiftXCTestImportUsage(source) || !hasSwiftXCTestCaseSubclassUsage(source)) {
885
733
  return false;
886
734
  }
887
735
 
888
- if (hasSwiftXCTestOnlyBrownfieldSuiteUsage(source)) {
889
- return false;
890
- }
736
+ return hasSwiftTestingImportUsage(source) || hasSwiftTestingSuiteAttributeUsage(source);
737
+ };
891
738
 
739
+ export const hasSwiftXCTestAssertionUsage = (source: string): boolean => {
892
740
  return (
893
741
  collectSwiftRegexLines(source, /\bXCTAssert[A-Za-z0-9_]*\s*\(/).length > 0 ||
894
742
  collectSwiftRegexLines(source, /\bXCTFail\s*\(/).length > 0
@@ -896,14 +744,6 @@ export const hasSwiftXCTestAssertionUsage = (source: string): boolean => {
896
744
  };
897
745
 
898
746
  export const hasSwiftXCTUnwrapUsage = (source: string): boolean => {
899
- if (hasSwiftLegacyXCTestUiOrPerformanceUsage(source)) {
900
- return false;
901
- }
902
-
903
- if (hasSwiftXCTestOnlyBrownfieldSuiteUsage(source)) {
904
- return false;
905
- }
906
-
907
747
  return collectSwiftRegexLines(source, /\bXCTUnwrap\s*\(/).length > 0;
908
748
  };
909
749
 
@@ -916,59 +756,40 @@ const hasSwiftConfirmationUsage = (source: string): boolean => {
916
756
  };
917
757
 
918
758
  export const hasSwiftWaitForExpectationsUsage = (source: string): boolean => {
919
- const legacyWaitPattern = /\bwait\s*\(\s*for\s*:|\bwaitForExpectations\s*\(/;
920
- return collectSwiftFunctionDeclarations(source).some((declaration) => {
921
- if (!/\basync\b/.test(declaration.signature)) {
922
- return false;
923
- }
924
- legacyWaitPattern.lastIndex = 0;
925
- return legacyWaitPattern.test(declaration.body);
926
- });
759
+ return hasSwiftSanitizedRegexMatch(
760
+ source,
761
+ /\bwait\s*\(\s*for\s*:|\bwaitForExpectations\s*\(/
762
+ );
927
763
  };
928
764
 
929
765
  export const hasSwiftLegacyExpectationDescriptionUsage = (source: string): boolean => {
930
- return collectSwiftFunctionDeclarations(source).some((declaration) => {
931
- if (!/\basync\b/.test(declaration.signature)) {
932
- return false;
933
- }
934
- if (!hasSwiftSanitizedRegexMatch(declaration.body, /\bexpectation\s*\(\s*description\s*:/)) {
935
- return false;
936
- }
937
- return !hasSwiftAwaitFulfillmentUsage(declaration.body) && !hasSwiftConfirmationUsage(declaration.body);
938
- });
939
- };
766
+ const hasLegacyExpectation = collectSwiftRegexLines(
767
+ source,
768
+ /\bexpectation\s*\(\s*description\s*:/
769
+ ).length > 0;
940
770
 
941
- const swiftManagedObjectBoundaryTypePattern = /\bNSManagedObject\b(?!ID\b|Context\b)/;
942
- const swiftStoredPropertyBoundaryPattern =
943
- /\b(?:var|let)\s+[A-Za-z_][A-Za-z0-9_]*\s*:\s*[^=\n]*\bNSManagedObject\b(?!ID\b|Context\b)/;
944
- const swiftManagedObjectSubclassPattern =
945
- /\b(?:final\s+)?class\s+[A-Za-z_][A-Za-z0-9_]*\s*:\s*NSManagedObject\b/;
771
+ if (!hasLegacyExpectation) {
772
+ return false;
773
+ }
946
774
 
947
- const hasSwiftManagedObjectBoundaryTypeUsage = (source: string): boolean => {
948
- return collectSwiftFunctionDeclarations(source).some((declaration) =>
949
- swiftManagedObjectBoundaryTypePattern.test(declaration.signature)
950
- );
775
+ if (hasSwiftAwaitFulfillmentUsage(source) || hasSwiftConfirmationUsage(source)) {
776
+ return false;
777
+ }
778
+
779
+ return true;
951
780
  };
952
781
 
953
782
  export const hasSwiftNSManagedObjectBoundaryUsage = (source: string): boolean => {
954
- if (hasSwiftManagedObjectBoundaryTypeUsage(source)) {
955
- return true;
956
- }
957
-
958
- return source.split(/\r?\n/).some((line) => {
959
- const sanitized = stripSwiftLineForSemanticScan(line);
960
- return (
961
- swiftStoredPropertyBoundaryPattern.test(sanitized) &&
962
- !swiftManagedObjectSubclassPattern.test(sanitized)
963
- );
964
- });
783
+ return hasSwiftSanitizedRegexMatch(
784
+ source,
785
+ /\bfunc\b[\s\S]{0,240}\([^)]*\bNSManagedObject\b(?!ID\b|Context\b)[^)]*\)|\b(?:var|let)\s+[A-Za-z_][A-Za-z0-9_]*\s*:\s*(?:\[[^\]]*NSManagedObject\b(?!ID\b|Context\b)[^\]]*\]|NSManagedObject\b(?!ID\b|Context\b))/g
786
+ );
965
787
  };
966
788
 
967
789
  export const hasSwiftNSManagedObjectAsyncBoundaryUsage = (source: string): boolean => {
968
- return collectSwiftFunctionDeclarations(source).some(
969
- (declaration) =>
970
- /\basync\b/.test(declaration.signature) &&
971
- swiftManagedObjectBoundaryTypePattern.test(declaration.signature)
790
+ return hasSwiftSanitizedRegexMatch(
791
+ source,
792
+ /\bfunc\b[\s\S]{0,240}\basync\b[\s\S]{0,200}(?:\([^)]*\bNSManagedObject\b(?!ID\b|Context\b)[^)]*\)|->\s*(?:\[[^\]]*NSManagedObject\b(?!ID\b|Context\b)[^\]]*\]|NSManagedObject\b(?!ID\b|Context\b)))/g
972
793
  );
973
794
  };
974
795
 
@@ -1290,100 +1111,6 @@ export const findSwiftPresentationSrpMatch = (
1290
1111
  };
1291
1112
  };
1292
1113
 
1293
- export const findSwiftXCTestSrpMatch = (source: string): SwiftXCTestSrpMatch | undefined => {
1294
- if (!hasSwiftXCTestCaseSubclassUsage(source)) {
1295
- return undefined;
1296
- }
1297
-
1298
- const classPattern = /\b(?:final\s+)?class\s+([A-Za-z0-9_]*Tests?)\s*:\s*XCTestCase\b/;
1299
- const classLines = collectSwiftRegexLines(source, classPattern);
1300
- if (classLines.length === 0) {
1301
- return undefined;
1302
- }
1303
-
1304
- const classLine = source.split(/\r?\n/)[classLines[0] - 1] ?? '';
1305
- const className = classLine.match(classPattern)?.[1];
1306
- if (!className) {
1307
- return undefined;
1308
- }
1309
-
1310
- const sourceLines = source.split(/\r?\n/);
1311
- const familyPatterns: ReadonlyArray<{
1312
- key: string;
1313
- name: string;
1314
- tokens: readonly string[];
1315
- }> = [
1316
- { key: 'configuration', name: 'configuration outcome tests', tokens: ['config', 'configuration', 'update', 'cache'] },
1317
- { key: 'session', name: 'session routing tests', tokens: ['session', 'login', 'auth', 'valid', 'invalid'] },
1318
- { key: 'onboarding', name: 'onboarding progress tests', tokens: ['onboarding', 'progress', 'completeonboarding'] },
1319
- { key: 'permissions', name: 'permissions routing tests', tokens: ['permission', 'camera', 'location', 'notification'] },
1320
- { key: 'tutorial', name: 'tutorial or feature discovery tests', tokens: ['tutorial', 'featurediscovery'] },
1321
- { key: 'splash', name: 'splash delay tests', tokens: ['splash', 'delay', 'start'] },
1322
- ];
1323
- const matchesFamily = (value: string, tokens: readonly string[]): boolean => {
1324
- const normalizedValue = value.toLowerCase();
1325
- return tokens.some((token) => normalizedValue.includes(token));
1326
- };
1327
-
1328
- const classFamilyKeys = new Set(
1329
- familyPatterns
1330
- .filter((entry) => matchesFamily(className, entry.tokens))
1331
- .map((entry) => entry.key)
1332
- );
1333
- const matchedFamilies = new Map<string, SwiftSemanticNodeMatch>();
1334
-
1335
- sourceLines.forEach((line, index) => {
1336
- const sanitizedLine = stripSwiftLineForSemanticScan(line);
1337
- const methodMatch = sanitizedLine.match(/\bfunc\s+(test[A-Za-z0-9_]+)\s*\(/);
1338
- const methodName = methodMatch?.[1];
1339
- if (!methodName) {
1340
- return;
1341
- }
1342
-
1343
- for (const family of familyPatterns) {
1344
- if (!matchesFamily(methodName, family.tokens)) {
1345
- continue;
1346
- }
1347
- if (classFamilyKeys.has(family.key)) {
1348
- continue;
1349
- }
1350
- if (!matchedFamilies.has(family.key)) {
1351
- matchedFamilies.set(family.key, {
1352
- kind: 'member',
1353
- name: family.name,
1354
- lines: [index + 1],
1355
- });
1356
- }
1357
- }
1358
- });
1359
-
1360
- const relatedNodes = [...matchedFamilies.values()];
1361
- if (relatedNodes.length < 2) {
1362
- return undefined;
1363
- }
1364
-
1365
- const relatedNodeNames = relatedNodes.map((node) => node.name).join(', ');
1366
- const allLines = sortedUniqueLines([
1367
- ...classLines,
1368
- ...relatedNodes.flatMap((node) => [...node.lines]),
1369
- ]);
1370
-
1371
- return {
1372
- primary_node: {
1373
- kind: 'class',
1374
- name: className,
1375
- lines: classLines,
1376
- },
1377
- related_nodes: relatedNodes,
1378
- why: `${className} mezcla ${relatedNodeNames} dentro del mismo XCTestCase, rompiendo SRP en la suite de tests.`,
1379
- impact:
1380
- 'La suite acumula múltiples razones de cambio, oculta regresiones por responsabilidad y hace más difícil aislar el baseline afectado antes de PRE_WRITE.',
1381
- expected_fix:
1382
- 'Divide la suite por responsabilidad observable: configuración, sesión, onboarding, permisos, tutorial o splash deben vivir en XCTestCase separados.',
1383
- lines: allLines,
1384
- };
1385
- };
1386
-
1387
1114
  export const findSwiftConcreteDependencyDipMatch = (
1388
1115
  source: string
1389
1116
  ): SwiftConcreteDependencyDipMatch | undefined => {
@@ -1474,7 +1201,7 @@ export const findSwiftOpenClosedSwitchMatch = (
1474
1201
  }
1475
1202
 
1476
1203
  const lines = source.split(/\r?\n/);
1477
- const discriminatorPattern = /\b(?:kind|type|mode|channel|variant|provider|route|flow|source|experience|outcome|state|status|configuration|config)\b/i;
1204
+ const discriminatorPattern = /\b(?:kind|type|mode|channel|variant|provider|route|flow|source|experience)\b/i;
1478
1205
  const switchPattern = /\bswitch\s+([A-Za-z_][A-Za-z0-9_\.]*)\s*\{/;
1479
1206
 
1480
1207
  for (let index = 0; index < lines.length; index += 1) {