pumuki 6.3.260 → 6.3.262

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
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [6.3.262] - 2026-05-14
4
+
5
+ - iOS: `skills.ios.no-force-cast` now emits actionable AST-style evidence for Swift `as!` expressions, including exact lines, primary/related nodes and remediation toward conditional casts or typed boundaries.
6
+
7
+ ## [6.3.261] - 2026-05-14
8
+
9
+ - iOS: `skills.ios.no-force-try` now emits actionable AST-style evidence for Swift `try!` expressions, including exact lines, primary/related nodes and remediation toward explicit error handling.
10
+
3
11
  ## [6.3.260] - 2026-05-14
4
12
 
5
13
  - iOS: `skills.ios.no-force-unwrap` now emits actionable AST-style evidence for Swift postfix force unwraps, including exact lines, primary/related nodes and remediation toward guarded optional handling.
@@ -25,6 +25,8 @@ import {
25
25
  hasSwiftEmptyCatchUsage,
26
26
  hasSwiftForEachIndicesUsage,
27
27
  hasSwiftForEachSelfIdentityUsage,
28
+ collectSwiftForceCastLines,
29
+ collectSwiftForceTryLines,
28
30
  hasSwiftForceCastUsage,
29
31
  hasSwiftFontWeightBoldUsage,
30
32
  hasSwiftFixedFontSizeUsage,
@@ -452,6 +454,8 @@ func load() {
452
454
  `;
453
455
  assert.equal(hasSwiftForceTryUsage(positive), true);
454
456
  assert.equal(hasSwiftForceTryUsage(negative), false);
457
+ assert.deepEqual(collectSwiftForceTryLines(positive), [3]);
458
+ assert.deepEqual(collectSwiftForceTryLines(negative), []);
455
459
  });
456
460
 
457
461
  test('hasSwiftForceCastUsage detecta as! y descarta as?', () => {
@@ -463,6 +467,8 @@ let model = payload as? User
463
467
  `;
464
468
  assert.equal(hasSwiftForceCastUsage(positive), true);
465
469
  assert.equal(hasSwiftForceCastUsage(negative), false);
470
+ assert.deepEqual(collectSwiftForceCastLines(positive), [2]);
471
+ assert.deepEqual(collectSwiftForceCastLines(negative), []);
466
472
  });
467
473
 
468
474
  test('hasSwiftCallbackStyleSignature detecta firmas callback con @escaping', () => {
@@ -1553,6 +1553,10 @@ export const hasSwiftForceTryUsage = (source: string): boolean => {
1553
1553
  });
1554
1554
  };
1555
1555
 
1556
+ export const collectSwiftForceTryLines = (source: string): readonly number[] => {
1557
+ return sortedUniqueLines(collectSwiftRegexLines(source, /\btry\s*!/));
1558
+ };
1559
+
1556
1560
  export const hasSwiftForceCastUsage = (source: string): boolean => {
1557
1561
  return scanCodeLikeSource(source, ({ source: swiftSource, index, current }) => {
1558
1562
  if (current !== 'a' || !hasIdentifierAt(swiftSource, index, 'as')) {
@@ -1564,6 +1568,10 @@ export const hasSwiftForceCastUsage = (source: string): boolean => {
1564
1568
  });
1565
1569
  };
1566
1570
 
1571
+ export const collectSwiftForceCastLines = (source: string): readonly number[] => {
1572
+ return sortedUniqueLines(collectSwiftRegexLines(source, /\bas\s*!/));
1573
+ };
1574
+
1567
1575
  export const hasSwiftCallbackStyleSignature = (source: string): boolean => {
1568
1576
  return scanCodeLikeSource(source, ({ source: swiftSource, index, current }) => {
1569
1577
  if (current !== '@' || !swiftSource.startsWith('@escaping', index)) {
@@ -644,8 +644,8 @@ const textDetectorRegistry: ReadonlyArray<TextDetectorRegistryEntry> = [
644
644
  { platform: 'ios', pathCheck: isIOSCartfilePath, excludePaths: [], detect: detectsTrackedFilePresence, ruleId: 'heuristics.ios.dependencies.carthage.ast', code: 'HEURISTICS_IOS_DEPENDENCIES_CARTHAGE_AST', message: 'AST heuristic detected Carthage dependency files in an iOS project; Swift Package Manager remains the preferred baseline for new code.' },
645
645
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftForceUnwrap, locateLines: TextIOS.collectSwiftForceUnwrapLines, primaryNode: (lines) => ({ kind: 'member', name: 'force unwrap postfix !', lines }), relatedNodes: (lines) => [{ kind: 'member', name: 'replacement: guarded optional binding or explicit failure path', lines }], why: 'Force unwrap turns optional handling into a runtime crash path instead of a checked domain, UI or infrastructure decision.', impact: 'A nil value can terminate the app outside the error boundary, making production behavior non-deterministic and hard to recover or test.', expected_fix: 'Replace postfix ! with guard let, if let, nil coalescing, throwing validation, or an explicit fallback. In modern Swift tests prefer #require when the unwrap is part of an assertion contract.', ruleId: 'heuristics.ios.force-unwrap.ast', code: 'HEURISTICS_IOS_FORCE_UNWRAP_AST', message: 'AST heuristic detected force unwrap usage.' },
646
646
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftAnyViewUsage, ruleId: 'heuristics.ios.anyview.ast', code: 'HEURISTICS_IOS_ANYVIEW_AST', message: 'AST heuristic detected AnyView usage.' },
647
- { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftForceTryUsage, ruleId: 'heuristics.ios.force-try.ast', code: 'HEURISTICS_IOS_FORCE_TRY_AST', message: 'AST heuristic detected force try usage.' },
648
- { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftForceCastUsage, ruleId: 'heuristics.ios.force-cast.ast', code: 'HEURISTICS_IOS_FORCE_CAST_AST', message: 'AST heuristic detected force cast usage.' },
647
+ { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftForceTryUsage, locateLines: TextIOS.collectSwiftForceTryLines, primaryNode: (lines) => ({ kind: 'call', name: 'force try expression try!', lines }), relatedNodes: (lines) => [{ kind: 'call', name: 'replacement: do/catch or throwing boundary', lines }], why: 'Force try converts a throwable operation into an unconditional runtime crash instead of preserving the typed error boundary.', impact: 'A recoverable domain, network, persistence or decoding error can terminate the app and bypass user-facing recovery, telemetry and tests.', expected_fix: 'Replace try! with do/catch, try await propagation, throws on the current boundary, or a guarded fallback that handles the error explicitly.', ruleId: 'heuristics.ios.force-try.ast', code: 'HEURISTICS_IOS_FORCE_TRY_AST', message: 'AST heuristic detected force try usage.' },
648
+ { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftForceCastUsage, locateLines: TextIOS.collectSwiftForceCastLines, primaryNode: (lines) => ({ kind: 'call', name: 'force cast expression as!', lines }), relatedNodes: (lines) => [{ kind: 'call', name: 'replacement: conditional cast or typed boundary', lines }], why: 'Force cast converts a type mismatch into an unconditional runtime crash instead of preserving a checked domain or presentation boundary.', impact: 'Unexpected payloads, dependency substitutions or navigation models can terminate the app instead of producing a recoverable validation path.', expected_fix: 'Replace as! with as?, guard let, pattern matching, generic constraints, protocol boundaries, or a typed mapper that validates the runtime value explicitly.', ruleId: 'heuristics.ios.force-cast.ast', code: 'HEURISTICS_IOS_FORCE_CAST_AST', message: 'AST heuristic detected force cast usage.' },
649
649
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath, isApprovedIOSBridgePath], detect: TextIOS.hasSwiftCallbackStyleSignature, ruleId: 'heuristics.ios.callback-style.ast', code: 'HEURISTICS_IOS_CALLBACK_STYLE_AST', message: 'AST heuristic detected callback-style API signature outside bridge layers.' },
650
650
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftDispatchQueueUsage, ruleId: 'heuristics.ios.dispatchqueue.ast', code: 'HEURISTICS_IOS_DISPATCHQUEUE_AST', message: 'AST heuristic detected DispatchQueue usage.' },
651
651
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftDispatchGroupUsage, ruleId: 'heuristics.ios.dispatchgroup.ast', code: 'HEURISTICS_IOS_DISPATCHGROUP_AST', message: 'AST heuristic detected DispatchGroup usage.' },
@@ -6,6 +6,14 @@ This file keeps only the operational highlights and rollout notes that matter wh
6
6
 
7
7
  ## 2026-04 (CLI stability and macOS notifications)
8
8
 
9
+ ### 2026-05-14 (v6.3.262)
10
+
11
+ - Published `pumuki@6.3.262` with AST-style line/node evidence for `skills.ios.no-force-cast`, making `as!` crashes remediable through conditional casts, typed boundaries or explicit mappers.
12
+
13
+ ### 2026-05-14 (v6.3.261)
14
+
15
+ - Published `pumuki@6.3.261` with AST-style line/node evidence for `skills.ios.no-force-try`, making `try!` crashes remediable through `do/catch`, throwing boundaries or explicit fallback handling.
16
+
9
17
  ### 2026-05-14 (v6.3.260)
10
18
 
11
19
  - Published `pumuki@6.3.260` with AST-style line/node evidence for `skills.ios.no-force-unwrap`, making postfix `!` crashes remediable through guarded optional handling or explicit failure paths.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.260",
3
+ "version": "6.3.262",
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": {