thuban 0.3.3 → 0.4.0
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/README.md +2 -0
- package/dist/LICENSE +21 -0
- package/dist/README.md +187 -0
- package/dist/cli.js +2 -0
- package/dist/packages/crucible/.golden/golden-master.json +414 -0
- package/dist/packages/crucible/badge-generator.js +1 -0
- package/dist/packages/crucible/banner.js +1 -0
- package/dist/packages/crucible/ci-integration.js +1 -0
- package/dist/packages/crucible/golden-master.js +1 -0
- package/dist/packages/crucible/index.js +1 -0
- package/dist/packages/crucible/kenny-mode.js +1 -0
- package/dist/packages/crucible/leaderboard.js +1 -0
- package/dist/packages/crucible/mutation-engine.js +1 -0
- package/dist/packages/crucible/pattern-learner.js +1 -0
- package/dist/packages/crucible/report-generator.js +1 -0
- package/dist/packages/crucible/rule-loader.js +1 -0
- package/dist/packages/crucible/seeding-engine.js +1 -0
- package/dist/packages/crucible/seeds/csharp/seed-001.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-002.cs +24 -0
- package/dist/packages/crucible/seeds/csharp/seed-003.cs +30 -0
- package/dist/packages/crucible/seeds/csharp/seed-004.cs +31 -0
- package/dist/packages/crucible/seeds/csharp/seed-005.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-006.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-007.cs +34 -0
- package/dist/packages/crucible/seeds/csharp/seed-008.cs +23 -0
- package/dist/packages/crucible/seeds/csharp/seed-009.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-010.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-011.cs +32 -0
- package/dist/packages/crucible/seeds/csharp/seed-012.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-013.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-014.cs +26 -0
- package/dist/packages/crucible/seeds/csharp/seed-015.cs +33 -0
- package/dist/packages/crucible/seeds/csharp/seed-016.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-017.cs +22 -0
- package/dist/packages/crucible/seeds/csharp/seed-018.cs +26 -0
- package/dist/packages/crucible/seeds/csharp/seed-019.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-020.cs +22 -0
- package/dist/packages/crucible/seeds/csharp/seed-021.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-022.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-023.cs +33 -0
- package/dist/packages/crucible/seeds/csharp/seed-024.cs +31 -0
- package/dist/packages/crucible/seeds/csharp/seed-025.cs +31 -0
- package/dist/packages/crucible/seeds/csharp/seed-026.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-027.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-028.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-029.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-030.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-031.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-032.cs +30 -0
- package/dist/packages/crucible/seeds/csharp/seed-033.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-034.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-035.cs +32 -0
- package/dist/packages/crucible/seeds/csharp/seed-036.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-037.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-038.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-039.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-040.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-041.cs +33 -0
- package/dist/packages/crucible/seeds/csharp/seed-042.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-043.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-044.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-045.cs +30 -0
- package/dist/packages/crucible/seeds/csharp/seed-046.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-047.cs +26 -0
- package/dist/packages/crucible/seeds/csharp/seed-048.cs +31 -0
- package/dist/packages/crucible/seeds/csharp/seed-049.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-050.cs +30 -0
- package/dist/packages/crucible/seeds/csharp/seed-051.cs +34 -0
- package/dist/packages/crucible/seeds/csharp/seed-052.cs +36 -0
- package/dist/packages/crucible/seeds/go/seed-001.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-002.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-003.go +31 -0
- package/dist/packages/crucible/seeds/go/seed-004.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-005.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-006.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-007.go +24 -0
- package/dist/packages/crucible/seeds/go/seed-008.go +25 -0
- package/dist/packages/crucible/seeds/go/seed-009.go +30 -0
- package/dist/packages/crucible/seeds/go/seed-010.go +35 -0
- package/dist/packages/crucible/seeds/go/seed-011.go +24 -0
- package/dist/packages/crucible/seeds/go/seed-012.go +24 -0
- package/dist/packages/crucible/seeds/go/seed-013.go +31 -0
- package/dist/packages/crucible/seeds/go/seed-014.go +35 -0
- package/dist/packages/crucible/seeds/go/seed-015.go +25 -0
- package/dist/packages/crucible/seeds/go/seed-016.go +19 -0
- package/dist/packages/crucible/seeds/go/seed-017.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-018.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-019.go +22 -0
- package/dist/packages/crucible/seeds/go/seed-020.go +31 -0
- package/dist/packages/crucible/seeds/go/seed-021.go +22 -0
- package/dist/packages/crucible/seeds/go/seed-022.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-023.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-024.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-025.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-026.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-027.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-028.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-029.go +28 -0
- package/dist/packages/crucible/seeds/go/seed-030.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-031.go +28 -0
- package/dist/packages/crucible/seeds/go/seed-032.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-033.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-034.go +22 -0
- package/dist/packages/crucible/seeds/go/seed-035.go +32 -0
- package/dist/packages/crucible/seeds/go/seed-036.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-037.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-038.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-039.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-040.go +37 -0
- package/dist/packages/crucible/seeds/go/seed-041.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-042.go +32 -0
- package/dist/packages/crucible/seeds/go/seed-043.go +35 -0
- package/dist/packages/crucible/seeds/go/seed-044.go +25 -0
- package/dist/packages/crucible/seeds/go/seed-045.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-046.go +34 -0
- package/dist/packages/crucible/seeds/go/seed-047.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-048.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-049.go +24 -0
- package/dist/packages/crucible/seeds/go/seed-050.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-051.go +38 -0
- package/dist/packages/crucible/seeds/go/seed-052.go +27 -0
- package/dist/packages/crucible/seeds/java/seed-001.java +23 -0
- package/dist/packages/crucible/seeds/java/seed-002.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-003.java +28 -0
- package/dist/packages/crucible/seeds/java/seed-004.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-005.java +33 -0
- package/dist/packages/crucible/seeds/java/seed-006.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-007.java +21 -0
- package/dist/packages/crucible/seeds/java/seed-008.java +29 -0
- package/dist/packages/crucible/seeds/java/seed-009.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-010.java +30 -0
- package/dist/packages/crucible/seeds/java/seed-011.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-012.java +20 -0
- package/dist/packages/crucible/seeds/java/seed-013.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-014.java +23 -0
- package/dist/packages/crucible/seeds/java/seed-015.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-016.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-017.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-018.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-019.java +38 -0
- package/dist/packages/crucible/seeds/java/seed-020.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-021.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-022.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-023.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-024.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-025.java +27 -0
- package/dist/packages/crucible/seeds/java/seed-026.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-027.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-028.java +21 -0
- package/dist/packages/crucible/seeds/java/seed-029.java +28 -0
- package/dist/packages/crucible/seeds/java/seed-030.java +27 -0
- package/dist/packages/crucible/seeds/java/seed-031.java +23 -0
- package/dist/packages/crucible/seeds/java/seed-032.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-033.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-034.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-035.java +29 -0
- package/dist/packages/crucible/seeds/java/seed-036.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-037.java +30 -0
- package/dist/packages/crucible/seeds/java/seed-038.java +29 -0
- package/dist/packages/crucible/seeds/java/seed-039.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-040.java +31 -0
- package/dist/packages/crucible/seeds/java/seed-041.java +20 -0
- package/dist/packages/crucible/seeds/java/seed-042.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-043.java +31 -0
- package/dist/packages/crucible/seeds/java/seed-044.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-045.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-046.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-047.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-048.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-049.java +28 -0
- package/dist/packages/crucible/seeds/java/seed-050.java +29 -0
- package/dist/packages/crucible/seeds/java/seed-051.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-052.java +32 -0
- package/dist/packages/crucible/seeds/js/seed-001.js +27 -0
- package/dist/packages/crucible/seeds/js/seed-002.js +28 -0
- package/dist/packages/crucible/seeds/js/seed-003.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-004.js +28 -0
- package/dist/packages/crucible/seeds/js/seed-005.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-006.js +28 -0
- package/dist/packages/crucible/seeds/js/seed-007.js +26 -0
- package/dist/packages/crucible/seeds/js/seed-008.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-009.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-010.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-011.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-012.js +32 -0
- package/dist/packages/crucible/seeds/js/seed-013.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-014.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-015.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-016.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-017.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-018.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-019.js +32 -0
- package/dist/packages/crucible/seeds/js/seed-020.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-021.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-022.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-023.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-024.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-025.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-026.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-027.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-028.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-029.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-030.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-031.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-032.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-033.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-034.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-035.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-036.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-037.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-038.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-039.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-040.js +35 -0
- package/dist/packages/crucible/seeds/js/seed-041.js +32 -0
- package/dist/packages/crucible/seeds/js/seed-042.js +32 -0
- package/dist/packages/crucible/seeds/js/seed-043.js +27 -0
- package/dist/packages/crucible/seeds/js/seed-044.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-045.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-046.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-047.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-048.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-049.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-050.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-051.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-052.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-053.js +26 -0
- package/dist/packages/crucible/seeds/js/seed-054.js +35 -0
- package/dist/packages/crucible/seeds/js/seed-055.js +33 -0
- package/dist/packages/crucible/seeds/kotlin/seed-001.kt +24 -0
- package/dist/packages/crucible/seeds/kotlin/seed-002.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-003.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-004.kt +24 -0
- package/dist/packages/crucible/seeds/kotlin/seed-005.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-006.kt +21 -0
- package/dist/packages/crucible/seeds/kotlin/seed-007.kt +23 -0
- package/dist/packages/crucible/seeds/kotlin/seed-008.kt +25 -0
- package/dist/packages/crucible/seeds/kotlin/seed-009.kt +21 -0
- package/dist/packages/crucible/seeds/kotlin/seed-010.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-011.kt +22 -0
- package/dist/packages/crucible/seeds/kotlin/seed-012.kt +25 -0
- package/dist/packages/crucible/seeds/kotlin/seed-013.kt +30 -0
- package/dist/packages/crucible/seeds/kotlin/seed-014.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-015.kt +24 -0
- package/dist/packages/crucible/seeds/kotlin/seed-016.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-017.kt +33 -0
- package/dist/packages/crucible/seeds/kotlin/seed-018.kt +31 -0
- package/dist/packages/crucible/seeds/kotlin/seed-019.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-020.kt +31 -0
- package/dist/packages/crucible/seeds/kotlin/seed-021.kt +34 -0
- package/dist/packages/crucible/seeds/kotlin/seed-022.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-023.kt +20 -0
- package/dist/packages/crucible/seeds/kotlin/seed-024.kt +23 -0
- package/dist/packages/crucible/seeds/kotlin/seed-025.kt +23 -0
- package/dist/packages/crucible/seeds/kotlin/seed-026.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-027.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-028.kt +24 -0
- package/dist/packages/crucible/seeds/kotlin/seed-029.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-030.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-031.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-032.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-033.kt +30 -0
- package/dist/packages/crucible/seeds/kotlin/seed-034.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-035.kt +33 -0
- package/dist/packages/crucible/seeds/kotlin/seed-036.kt +25 -0
- package/dist/packages/crucible/seeds/kotlin/seed-037.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-038.kt +25 -0
- package/dist/packages/crucible/seeds/kotlin/seed-039.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-040.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-041.kt +31 -0
- package/dist/packages/crucible/seeds/kotlin/seed-042.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-043.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-044.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-045.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-046.kt +33 -0
- package/dist/packages/crucible/seeds/kotlin/seed-047.kt +32 -0
- package/dist/packages/crucible/seeds/kotlin/seed-048.kt +20 -0
- package/dist/packages/crucible/seeds/kotlin/seed-049.kt +23 -0
- package/dist/packages/crucible/seeds/kotlin/seed-050.kt +19 -0
- package/dist/packages/crucible/seeds/php/seed-001.php +23 -0
- package/dist/packages/crucible/seeds/php/seed-002.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-003.php +25 -0
- package/dist/packages/crucible/seeds/php/seed-004.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-005.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-006.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-007.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-008.php +19 -0
- package/dist/packages/crucible/seeds/php/seed-009.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-010.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-011.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-012.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-013.php +23 -0
- package/dist/packages/crucible/seeds/php/seed-014.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-015.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-016.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-017.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-018.php +17 -0
- package/dist/packages/crucible/seeds/php/seed-019.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-020.php +19 -0
- package/dist/packages/crucible/seeds/php/seed-021.php +22 -0
- package/dist/packages/crucible/seeds/php/seed-022.php +15 -0
- package/dist/packages/crucible/seeds/php/seed-023.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-024.php +22 -0
- package/dist/packages/crucible/seeds/php/seed-025.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-026.php +22 -0
- package/dist/packages/crucible/seeds/php/seed-027.php +15 -0
- package/dist/packages/crucible/seeds/php/seed-028.php +15 -0
- package/dist/packages/crucible/seeds/php/seed-029.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-030.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-031.php +23 -0
- package/dist/packages/crucible/seeds/php/seed-032.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-033.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-034.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-035.php +22 -0
- package/dist/packages/crucible/seeds/php/seed-036.php +17 -0
- package/dist/packages/crucible/seeds/php/seed-037.php +19 -0
- package/dist/packages/crucible/seeds/php/seed-038.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-039.php +15 -0
- package/dist/packages/crucible/seeds/php/seed-040.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-041.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-042.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-043.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-044.php +25 -0
- package/dist/packages/crucible/seeds/php/seed-045.php +25 -0
- package/dist/packages/crucible/seeds/php/seed-046.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-047.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-048.php +19 -0
- package/dist/packages/crucible/seeds/php/seed-049.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-050.php +20 -0
- package/dist/packages/crucible/seeds/python/seed-001.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-002.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-003.py +31 -0
- package/dist/packages/crucible/seeds/python/seed-004.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-005.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-006.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-007.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-008.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-009.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-010.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-011.py +30 -0
- package/dist/packages/crucible/seeds/python/seed-012.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-013.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-014.py +40 -0
- package/dist/packages/crucible/seeds/python/seed-015.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-016.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-017.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-018.py +30 -0
- package/dist/packages/crucible/seeds/python/seed-019.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-020.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-021 2.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-021 3.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-021.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-022 2.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-022 3.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-022.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-023 2.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-023 3.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-023.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-024 2.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-024 3.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-024.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-025 2.py +40 -0
- package/dist/packages/crucible/seeds/python/seed-025 3.py +40 -0
- package/dist/packages/crucible/seeds/python/seed-025.py +40 -0
- package/dist/packages/crucible/seeds/python/seed-026 2.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-026 3.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-026.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-027 2.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-027 3.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-027.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-028 2.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-028 3.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-028.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-029.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-030 2.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-030 3.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-030.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-031 2.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-031 3.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-031.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-032.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-033.py +32 -0
- package/dist/packages/crucible/seeds/python/seed-034.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-035.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-036 2.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-036 3.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-036.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-037 2.py +41 -0
- package/dist/packages/crucible/seeds/python/seed-037 3.py +41 -0
- package/dist/packages/crucible/seeds/python/seed-037.py +41 -0
- package/dist/packages/crucible/seeds/python/seed-038 2.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-038 3.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-038.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-039 2.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-039 3.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-039.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-040 2.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-040 3.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-040.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-041 2.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-041 3.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-041.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-042 2.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-042 3.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-042.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-043 2.py +32 -0
- package/dist/packages/crucible/seeds/python/seed-043 3.py +32 -0
- package/dist/packages/crucible/seeds/python/seed-043.py +32 -0
- package/dist/packages/crucible/seeds/python/seed-044 2.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-044 3.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-044.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-045 2.py +36 -0
- package/dist/packages/crucible/seeds/python/seed-045 3.py +36 -0
- package/dist/packages/crucible/seeds/python/seed-045.py +36 -0
- package/dist/packages/crucible/seeds/python/seed-046 2.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-046 3.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-046.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-047 2.py +44 -0
- package/dist/packages/crucible/seeds/python/seed-047 3.py +44 -0
- package/dist/packages/crucible/seeds/python/seed-047.py +44 -0
- package/dist/packages/crucible/seeds/python/seed-048 2.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-048 3.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-048.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-049 2.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-049 3.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-049.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-050 2.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-050 3.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-050.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-051 2.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-051 3.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-051.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-052 2.py +41 -0
- package/dist/packages/crucible/seeds/python/seed-052 3.py +41 -0
- package/dist/packages/crucible/seeds/python/seed-052.py +41 -0
- package/dist/packages/crucible/seeds/ruby/seed-001 2.rb +15 -0
- package/dist/packages/crucible/seeds/ruby/seed-001 3.rb +15 -0
- package/dist/packages/crucible/seeds/ruby/seed-001.rb +15 -0
- package/dist/packages/crucible/seeds/ruby/seed-002 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-002 3.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-002.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-003 2.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-003 3.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-003.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-004 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-004 3.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-004.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-005 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-005 3.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-005.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-006 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-006 3.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-006.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-007 2.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-007 3.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-007.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-008 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-008 3.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-008.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-009 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-009 3.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-009.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-010 2.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-010 3.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-010.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-011 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-011 3.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-011.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-012 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-012 3.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-012.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-013 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-013 3.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-013.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-014 2.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-014 3.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-014.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-015 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-015 3.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-015.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-016 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-016 3.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-016.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-017 2.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-017 3.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-017.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-018 2.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-018 3.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-018.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-019 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-019 3.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-019.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-020 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-020 3.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-020.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-021 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-021 3.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-021.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-022 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-022 3.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-022.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-023 2.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-023 3.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-023.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-024 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-024 3.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-024.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-025 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-025 3.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-025.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-026 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-026 3.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-026.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-027 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-027 3.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-027.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-028 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-028 3.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-028.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-029 2.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-029 3.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-029.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-030 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-030 3.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-030.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-031 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-031 3.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-031.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-032 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-032 3.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-032.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-033 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-033 3.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-033.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-034 2.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-034 3.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-034.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-035 2.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-035 3.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-035.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-036 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-036 3.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-036.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-037 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-037 3.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-037.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-038 2.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-038 3.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-038.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-039 2.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-039 3.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-039.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-040 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-040 3.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-040.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-041 2.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-041 3.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-041.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-042 2.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-042 3.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-042.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-043 2.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-043 3.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-043.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-044 2.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-044 3.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-044.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-045 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-045 3.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-045.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-046 2.rb +27 -0
- package/dist/packages/crucible/seeds/ruby/seed-046 3.rb +27 -0
- package/dist/packages/crucible/seeds/ruby/seed-046.rb +27 -0
- package/dist/packages/crucible/seeds/ruby/seed-047 2.rb +26 -0
- package/dist/packages/crucible/seeds/ruby/seed-047 3.rb +26 -0
- package/dist/packages/crucible/seeds/ruby/seed-047.rb +26 -0
- package/dist/packages/crucible/seeds/ruby/seed-048 2.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-048 3.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-048.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-049 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-049 3.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-049.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-050 2.rb +27 -0
- package/dist/packages/crucible/seeds/ruby/seed-050 3.rb +27 -0
- package/dist/packages/crucible/seeds/ruby/seed-050.rb +27 -0
- package/dist/packages/crucible/seeds/rust/seed-001 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-001 3.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-001.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-002 2.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-002 3.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-002.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-003 2.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-003 3.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-003.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-004 2.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-004 3.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-004.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-005 2.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-005 3.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-005.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-006 2.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-006 3.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-006.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-007 2.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-007 3.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-007.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-008 2.rs +19 -0
- package/dist/packages/crucible/seeds/rust/seed-008 3.rs +19 -0
- package/dist/packages/crucible/seeds/rust/seed-008.rs +19 -0
- package/dist/packages/crucible/seeds/rust/seed-009 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-009 3.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-009.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-010 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-010 3.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-010.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-011 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-011 3.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-011.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-012 2.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-012 3.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-012.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-013 2.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-013 3.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-013.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-014 2.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-014 3.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-014.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-015 2.rs +33 -0
- package/dist/packages/crucible/seeds/rust/seed-015 3.rs +33 -0
- package/dist/packages/crucible/seeds/rust/seed-015.rs +33 -0
- package/dist/packages/crucible/seeds/rust/seed-016 2.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-016 3.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-016.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-017 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-017 3.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-017.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-018 2.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-018 3.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-018.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-019 2.rs +36 -0
- package/dist/packages/crucible/seeds/rust/seed-019 3.rs +36 -0
- package/dist/packages/crucible/seeds/rust/seed-019.rs +36 -0
- package/dist/packages/crucible/seeds/rust/seed-020 2.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-020 3.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-020.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-021 2.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-021 3.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-021.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-022 2.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-022 3.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-022.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-023 2.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-023 3.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-023.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-024 2.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-024 3.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-024.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-025 2.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-025 3.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-025.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-026 2.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-026 3.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-026.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-027 2.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-027 3.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-027.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-028 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-028 3.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-028.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-029 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-029 3.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-029.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-030 2.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-030 3.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-030.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-031 2.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-031 3.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-031.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-032 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-032 3.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-032.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-033 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-033 3.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-033.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-034 2.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-034 3.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-034.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-035 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-035 3.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-035.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-036 2.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-036 3.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-036.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-037 2.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-037 3.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-037.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-038 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-038 3.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-038.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-039 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-039 3.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-039.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-040 2.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-040 3.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-040.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-041 2.rs +32 -0
- package/dist/packages/crucible/seeds/rust/seed-041 3.rs +32 -0
- package/dist/packages/crucible/seeds/rust/seed-041.rs +32 -0
- package/dist/packages/crucible/seeds/rust/seed-042 2.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-042 3.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-042.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-043 2.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-043 3.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-043.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-044 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-044 3.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-044.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-045 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-045 3.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-045.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-046 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-046 3.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-046.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-047 2.rs +34 -0
- package/dist/packages/crucible/seeds/rust/seed-047 3.rs +34 -0
- package/dist/packages/crucible/seeds/rust/seed-047.rs +34 -0
- package/dist/packages/crucible/seeds/rust/seed-048 2.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-048 3.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-048.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-049 2.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-049 3.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-049.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-050 2.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-050 3.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-050.rs +23 -0
- package/dist/packages/crucible/seeds/ts/seed-001 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-001 3.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-001.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-002 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-002 3.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-002.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-003 2.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-003 3.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-003.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-004 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-004 3.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-004.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-005 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-005 3.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-005.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-006 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-006 3.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-006.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-007 2.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-007 3.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-007.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-008 2.ts +40 -0
- package/dist/packages/crucible/seeds/ts/seed-008 3.ts +40 -0
- package/dist/packages/crucible/seeds/ts/seed-008.ts +40 -0
- package/dist/packages/crucible/seeds/ts/seed-009 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-009 3.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-009.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-010 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-010 3.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-010.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-011 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-011 3.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-011.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-012 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-012 3.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-012.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-013 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-013 3.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-013.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-014 2.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-014 3.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-014.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-015 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-015 3.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-015.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-016 2.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-016 3.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-016.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-017 2.ts +44 -0
- package/dist/packages/crucible/seeds/ts/seed-017 3.ts +44 -0
- package/dist/packages/crucible/seeds/ts/seed-017.ts +44 -0
- package/dist/packages/crucible/seeds/ts/seed-018 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-018 3.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-018.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-019 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-019 3.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-019.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-020 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-020 3.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-020.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-021 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-021 3.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-021.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-022 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-022 3.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-022.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-023 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-023 3.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-023.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-024 2.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-024 3.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-024.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-025 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-025 3.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-025.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-026 2.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-026 3.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-026.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-027 2.ts +30 -0
- package/dist/packages/crucible/seeds/ts/seed-027 3.ts +30 -0
- package/dist/packages/crucible/seeds/ts/seed-027.ts +30 -0
- package/dist/packages/crucible/seeds/ts/seed-028 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-028 3.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-028.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-029 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-029 3.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-029.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-030 2.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-030 3.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-030.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-031 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-031 3.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-031.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-032 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-032 3.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-032.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-033 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-033 3.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-033.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-034 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-034 3.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-034.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-035 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-035 3.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-035.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-036 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-036 3.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-036.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-037 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-037 3.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-037.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-038 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-038 3.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-038.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-039 2.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-039 3.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-039.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-040 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-040 3.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-040.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-041 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-041 3.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-041.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-042 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-042 3.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-042.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-043 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-043 3.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-043.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-044 2.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-044 3.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-044.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-045 2.ts +39 -0
- package/dist/packages/crucible/seeds/ts/seed-045 3.ts +39 -0
- package/dist/packages/crucible/seeds/ts/seed-045.ts +39 -0
- package/dist/packages/crucible/seeds/ts/seed-046 2.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-046 3.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-046.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-047 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-047 3.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-047.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-048 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-048 3.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-048.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-049 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-049 3.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-049.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-050 2.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-050 3.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-050.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-051 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-051 3.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-051.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-052 2.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-052 3.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-052.ts +36 -0
- package/dist/packages/crucible/self-attack.js +1 -0
- package/dist/packages/scanner/ai-confidence-scorer.js +1 -0
- package/dist/packages/scanner/alert-manager.js +1 -0
- package/dist/packages/scanner/ast-analyzer.js +1 -0
- package/dist/packages/scanner/baseline-manager.js +1 -0
- package/dist/packages/scanner/cfg-analyzer.js +1 -0
- package/dist/packages/scanner/code-scanner.js +1 -0
- package/dist/packages/scanner/codebase-passport.js +1 -0
- package/dist/packages/scanner/copy-paste-detector.js +1 -0
- package/dist/packages/scanner/dependency-graph.js +1 -0
- package/dist/packages/scanner/drift-detector.js +1 -0
- package/dist/packages/scanner/executive-report.js +1 -0
- package/dist/packages/scanner/export-verifier.js +1 -0
- package/dist/packages/scanner/file-collector.js +1 -0
- package/dist/packages/scanner/file-watcher.js +1 -0
- package/dist/packages/scanner/ghost-code-detector.js +1 -0
- package/dist/packages/scanner/go-ast-analyzer.js +1 -0
- package/dist/packages/scanner/hallucination-detector.js +1 -0
- package/dist/packages/scanner/health-checker.js +1 -0
- package/dist/packages/scanner/html-report.js +1 -0
- package/dist/packages/scanner/index.js +1 -0
- package/dist/packages/scanner/license-manager.js +1 -0
- package/dist/packages/scanner/master-health-checker.js +1 -0
- package/dist/packages/scanner/monitor-notifier.js +1 -0
- package/dist/packages/scanner/monitor-service.js +1 -0
- package/dist/packages/scanner/monitor-store.js +1 -0
- package/dist/packages/scanner/pre-commit-gate.js +1 -0
- package/dist/packages/scanner/python-ast-analyzer.js +1 -0
- package/dist/packages/scanner/scan-diff.js +1 -0
- package/dist/packages/scanner/scan-runner.js +1 -0
- package/dist/packages/scanner/secret-scanner.js +1 -0
- package/dist/packages/scanner/sentinel-core.js +1 -0
- package/dist/packages/scanner/sentinel-knowledge.js +1 -0
- package/dist/packages/scanner/taint-tracker.js +1 -0
- package/dist/packages/scanner/tech-debt-analyzer.js +1 -0
- package/dist/packages/scanner/tech-debt-cost.js +1 -0
- package/dist/packages/scanner/widget-generator.js +1 -0
- package/package.json +15 -7
- package/cli.js +0 -2627
- package/packages/scanner/ai-confidence-scorer.js +0 -260
- package/packages/scanner/alert-manager.js +0 -398
- package/packages/scanner/baseline-manager.js +0 -109
- package/packages/scanner/code-scanner.js +0 -758
- package/packages/scanner/codebase-passport.js +0 -299
- package/packages/scanner/copy-paste-detector.js +0 -276
- package/packages/scanner/dependency-graph.js +0 -541
- package/packages/scanner/drift-detector.js +0 -423
- package/packages/scanner/executive-report.js +0 -774
- package/packages/scanner/file-collector.js +0 -64
- package/packages/scanner/file-watcher.js +0 -323
- package/packages/scanner/ghost-code-detector.js +0 -301
- package/packages/scanner/hallucination-detector.js +0 -822
- package/packages/scanner/health-checker.js +0 -586
- package/packages/scanner/html-report.js +0 -634
- package/packages/scanner/index.js +0 -100
- package/packages/scanner/license-manager.js +0 -331
- package/packages/scanner/master-health-checker.js +0 -513
- package/packages/scanner/monitor-notifier.js +0 -64
- package/packages/scanner/monitor-service.js +0 -103
- package/packages/scanner/monitor-store.js +0 -117
- package/packages/scanner/pre-commit-gate.js +0 -216
- package/packages/scanner/scan-diff.js +0 -50
- package/packages/scanner/scan-runner.js +0 -172
- package/packages/scanner/secret-scanner.js +0 -612
- package/packages/scanner/secret-scanner.test.js +0 -103
- package/packages/scanner/sentinel-core.js +0 -616
- package/packages/scanner/sentinel-knowledge.js +0 -322
- package/packages/scanner/tech-debt-analyzer.js +0 -583
- package/packages/scanner/tech-debt-cost.js +0 -194
- package/packages/scanner/widget-generator.js +0 -415
|
@@ -1,822 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @thuban-dna
|
|
3
|
-
* @purpose Detect AI hallucinations, phantom imports, invented APIs, and code drift
|
|
4
|
-
* @module thuban
|
|
5
|
-
* @layer application
|
|
6
|
-
* @imports-from fs, path
|
|
7
|
-
* @exports-to cli, tech-debt-analyzer, code-scanner
|
|
8
|
-
* @side-effects File system reads, Console output
|
|
9
|
-
* @critical-for Core differentiator — no other tool detects AI-generated code issues
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const fs = require('fs');
|
|
13
|
-
const path = require('path');
|
|
14
|
-
|
|
15
|
-
class HallucinationDetector {
|
|
16
|
-
constructor(config = {}) {
|
|
17
|
-
this.config = {
|
|
18
|
-
rootPath: config.rootPath || process.cwd(),
|
|
19
|
-
...config
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
// Known Node.js built-in modules
|
|
23
|
-
this.builtins = new Set([
|
|
24
|
-
'assert', 'async_hooks', 'buffer', 'child_process', 'cluster',
|
|
25
|
-
'console', 'constants', 'crypto', 'dgram', 'diagnostics_channel',
|
|
26
|
-
'dns', 'domain', 'events', 'fs', 'http', 'http2', 'https',
|
|
27
|
-
'inspector', 'module', 'net', 'os', 'path', 'perf_hooks',
|
|
28
|
-
'process', 'punycode', 'querystring', 'readline', 'repl',
|
|
29
|
-
'stream', 'string_decoder', 'sys', 'timers', 'tls', 'trace_events',
|
|
30
|
-
'tty', 'url', 'util', 'v8', 'vm', 'wasi', 'worker_threads', 'zlib',
|
|
31
|
-
'node:fs', 'node:path', 'node:os', 'node:crypto', 'node:http',
|
|
32
|
-
'node:https', 'node:events', 'node:util', 'node:stream',
|
|
33
|
-
'node:child_process', 'node:url', 'node:querystring', 'node:buffer',
|
|
34
|
-
'node:net', 'node:tls', 'node:dns', 'node:readline', 'node:zlib',
|
|
35
|
-
'node:worker_threads', 'node:cluster', 'node:vm', 'node:assert',
|
|
36
|
-
'node:timers', 'node:timers/promises', 'node:test',
|
|
37
|
-
'fs/promises', 'stream/promises', 'timers/promises', 'dns/promises',
|
|
38
|
-
'readline/promises',
|
|
39
|
-
]);
|
|
40
|
-
|
|
41
|
-
// Common phantom packages that LLMs hallucinate
|
|
42
|
-
this.phantomPackages = new Set([
|
|
43
|
-
'node-fetch-extra', 'express-async', 'mongoose-v2',
|
|
44
|
-
'react-native-web-view', 'axios-retry-enhanced',
|
|
45
|
-
'lodash-extended', 'moment-timezone-v2', 'socket.io-extra',
|
|
46
|
-
'graphql-tools-v2', 'next-auth-v5', 'prisma-client-v2',
|
|
47
|
-
'tailwind-utils', 'react-query-v4', 'jest-extended-v2',
|
|
48
|
-
]);
|
|
49
|
-
|
|
50
|
-
// Common hallucinated API patterns (methods that don't exist)
|
|
51
|
-
this.phantomAPIs = [
|
|
52
|
-
{ pattern: /fs\.readFileAsync\s*\(/, suggestion: 'Use fs.promises.readFile() or fs.readFileSync()', name: 'fs.readFileAsync', id: 'HALL_API001' },
|
|
53
|
-
{ pattern: /fs\.writeFileAsync\s*\(/, suggestion: 'Use fs.promises.writeFile() or fs.writeFileSync()', name: 'fs.writeFileAsync', id: 'HALL_API002' },
|
|
54
|
-
{ pattern: /fs\.existsAsync\s*\(/, suggestion: 'Use fs.promises.access() or fs.existsSync()', name: 'fs.existsAsync', id: 'HALL_API003' },
|
|
55
|
-
{ pattern: /path\.exists\s*\(/, suggestion: 'Use fs.existsSync() — path module has no exists()', name: 'path.exists', id: 'HALL_API004' },
|
|
56
|
-
{ pattern: /path\.isFile\s*\(/, suggestion: 'Use fs.statSync().isFile() — path module has no isFile()', name: 'path.isFile', id: 'HALL_API005' },
|
|
57
|
-
{ pattern: /path\.isDirectory\s*\(/, suggestion: 'Use fs.statSync().isDirectory()', name: 'path.isDirectory', id: 'HALL_API006' },
|
|
58
|
-
{ pattern: /console\.success\s*\(/, suggestion: 'Use console.log() — console.success() does not exist', name: 'console.success', id: 'HALL_API007' },
|
|
59
|
-
{ pattern: /console\.verbose\s*\(/, suggestion: 'Use console.log() or console.debug()', name: 'console.verbose', id: 'HALL_API008' },
|
|
60
|
-
{ pattern: /JSON\.tryParse\s*\(/, suggestion: 'Use try/catch with JSON.parse()', name: 'JSON.tryParse', id: 'HALL_API009' },
|
|
61
|
-
{ pattern: /JSON\.safeStringify\s*\(/, suggestion: 'Use JSON.stringify() with a replacer', name: 'JSON.safeStringify', id: 'HALL_API010' },
|
|
62
|
-
{ pattern: /Array\.flatten\s*\(/, suggestion: 'Use Array.prototype.flat()', name: 'Array.flatten', id: 'HALL_API011' },
|
|
63
|
-
{ pattern: /Object\.deepClone\s*\(/, suggestion: 'Use structuredClone() or JSON.parse(JSON.stringify())', name: 'Object.deepClone', id: 'HALL_API012' },
|
|
64
|
-
{ pattern: /Object\.deepMerge\s*\(/, suggestion: 'Use a library like lodash.merge or write a custom function', name: 'Object.deepMerge', id: 'HALL_API013' },
|
|
65
|
-
{ pattern: /String\.prototype\.replaceAll\s*&&.*polyfill/i, suggestion: 'replaceAll() is native since ES2021 — no polyfill needed', name: 'replaceAll polyfill', id: 'HALL_API014' },
|
|
66
|
-
{ pattern: /require\s*\(\s*['"]fs\/sync['"]\s*\)/, suggestion: 'fs/sync is not a real module — use fs directly', name: 'fs/sync', id: 'HALL_API015' },
|
|
67
|
-
{ pattern: /require\s*\(\s*['"]http\/server['"]\s*\)/, suggestion: 'http/server is not a real module — use http.createServer()', name: 'http/server', id: 'HALL_API016' },
|
|
68
|
-
{ pattern: /process\.env\.get\s*\(/, suggestion: 'Use process.env.VAR_NAME — process.env is a plain object, not a Map', name: 'process.env.get()', id: 'HALL_API017' },
|
|
69
|
-
{ pattern: /process\.exit\s*\(\s*['"]/, suggestion: 'process.exit() takes a number, not a string', name: 'process.exit(string)', id: 'HALL_API018' },
|
|
70
|
-
];
|
|
71
|
-
|
|
72
|
-
// ─── Python phantom APIs ────────────────────────────────
|
|
73
|
-
this.pythonPhantomAPIs = [
|
|
74
|
-
{ pattern: /os\.path\.exists_sync\s*\(/, suggestion: 'Use os.path.exists() — exists_sync does not exist in Python', name: 'os.path.exists_sync', id: 'PY_HALL001' },
|
|
75
|
-
{ pattern: /json\.tryParse\s*\(/, suggestion: 'Use json.loads() with try/except', name: 'json.tryParse', id: 'PY_HALL002' },
|
|
76
|
-
{ pattern: /\w+\.flatMap\s*\(/, suggestion: 'Python lists have no flatMap — use list comprehension or itertools.chain.from_iterable()', name: 'list.flatMap', id: 'PY_HALL003' },
|
|
77
|
-
{ pattern: /\w+\.merge\s*\((?!.*\bself\b)/, suggestion: 'Use {**dict1, **dict2} or dict1 | dict2 (3.9+)', name: 'dict.merge', id: 'PY_HALL004' },
|
|
78
|
-
{ pattern: /\w+\.format_map\s*\(/, suggestion: 'str.format_map exists but is rarely correct — did you mean .format()?', name: 'string.format_map misuse', id: 'PY_HALL005' },
|
|
79
|
-
{ pattern: /from\s+collections\s+import\s+OrderedDict.*#.*maintain\s+order/i, suggestion: 'Regular dict maintains order since Python 3.7 — OrderedDict is unnecessary', name: 'Unnecessary OrderedDict', id: 'PY_HALL006' },
|
|
80
|
-
{ pattern: /async\s+def\s+\w+.*asyncio\.sleep\s*\(\s*0\s*\)\s*#.*yield/i, suggestion: 'asyncio.sleep(0) to yield is a code smell — review async design', name: 'asyncio.sleep(0) hack', id: 'PY_HALL007' },
|
|
81
|
-
{ pattern: /import\s+tensorflow\.v2/, suggestion: 'tensorflow.v2 is not a real module — use import tensorflow', name: 'tensorflow.v2', id: 'PY_HALL008' },
|
|
82
|
-
{ pattern: /from\s+sklearn\.model_selection\s+import\s+train_test_split_v2/, suggestion: 'train_test_split_v2 does not exist — use train_test_split', name: 'sklearn v2 hallucination', id: 'PY_HALL009' },
|
|
83
|
-
{ pattern: /requests\.async_get\s*\(/, suggestion: 'requests has no async_get — use aiohttp or httpx', name: 'requests.async_get', id: 'PY_HALL010' },
|
|
84
|
-
];
|
|
85
|
-
|
|
86
|
-
this.pythonDeprecated = [
|
|
87
|
-
{ pattern: /from\s+distutils/, suggestion: 'distutils removed in Python 3.12 — use setuptools', since: 'Python 3.12', name: 'distutils', id: 'PY_DEPR001' },
|
|
88
|
-
{ pattern: /from\s+imp\s+import/, suggestion: 'imp removed in Python 3.12 — use importlib', since: 'Python 3.12', name: 'imp module', id: 'PY_DEPR002' },
|
|
89
|
-
{ pattern: /asyncio\.get_event_loop\(\)/, suggestion: 'Deprecated in 3.10+ — use asyncio.run() or get_running_loop()', since: 'Python 3.10', name: 'asyncio.get_event_loop()', id: 'PY_DEPR003' },
|
|
90
|
-
{ pattern: /collections\.MutableMapping/, suggestion: 'Moved to collections.abc.MutableMapping in Python 3.3+', since: 'Python 3.9', name: 'collections.MutableMapping', id: 'PY_DEPR004' },
|
|
91
|
-
{ pattern: /optparse\.OptionParser/, suggestion: 'optparse deprecated since Python 3.2 — use argparse', since: 'Python 3.2', name: 'optparse', id: 'PY_DEPR005' },
|
|
92
|
-
{ pattern: /cgi\.parse_header\s*\(/, suggestion: 'cgi module deprecated in Python 3.11, removed in 3.13', since: 'Python 3.11', name: 'cgi module', id: 'PY_DEPR006' },
|
|
93
|
-
{ pattern: /from\s+typing\s+import\s+(List|Dict|Tuple|Set)\b/, suggestion: 'Use built-in list, dict, tuple, set for type hints (Python 3.9+)', since: 'Python 3.9', name: 'typing.List/Dict/Tuple', id: 'PY_DEPR007' },
|
|
94
|
-
{ pattern: /unittest\.makeSuite\s*\(/, suggestion: 'makeSuite deprecated — use TestLoader.loadTestsFromTestCase', since: 'Python 3.11', name: 'unittest.makeSuite', id: 'PY_DEPR008' },
|
|
95
|
-
];
|
|
96
|
-
|
|
97
|
-
this.pythonSmells = [
|
|
98
|
-
{ pattern: /print\s*\(\s*f?['"]\s*debug/i, id: 'PY_SMELL001', name: 'Debug Print', message: 'Debug print statement left in code' },
|
|
99
|
-
{ pattern: /except\s*:\s*$|except\s+Exception\s*:\s*\n\s*pass/m, id: 'PY_SMELL002', name: 'Bare Except', message: 'Bare except or swallowed exception — hides real errors' },
|
|
100
|
-
{ pattern: /#\s*TODO:?\s*(implement|add|fix|complete|finish)/i, id: 'PY_SMELL003', name: 'Placeholder TODO', message: 'AI-generated placeholder — likely unfinished' },
|
|
101
|
-
{ pattern: /raise\s+NotImplementedError\s*\(?\s*\)?/, id: 'PY_SMELL004', name: 'Not Implemented', message: 'Stub implementation — function body was not generated' },
|
|
102
|
-
{ pattern: /['"]your.api.key.here['"]|['"]sk-[.]{3,}['"]/i, id: 'PY_SMELL005', name: 'Dummy Credential', message: 'Placeholder credential — will fail at runtime' },
|
|
103
|
-
{ pattern: /localhost:\d{4}(?!.*(?:dev|test|local|development))/i, id: 'PY_SMELL006', name: 'Hardcoded Localhost', message: 'Hardcoded localhost URL — will fail in production' },
|
|
104
|
-
{ pattern: /import\s+\*/, id: 'PY_SMELL007', name: 'Wildcard Import', message: 'Wildcard import — pollutes namespace, hides dependencies' },
|
|
105
|
-
];
|
|
106
|
-
|
|
107
|
-
// ─── Go deprecated APIs (formerly labelled phantom — they exist but are removed) ─
|
|
108
|
-
this.goDeprecated = [
|
|
109
|
-
{ pattern: /ioutil\.ReadFile\s*\(/, suggestion: 'ioutil removed in Go 1.16 — use os.ReadFile()', since: 'Go 1.16', name: 'ioutil.ReadFile', id: 'GO_DEPR001' },
|
|
110
|
-
{ pattern: /ioutil\.WriteFile\s*\(/, suggestion: 'ioutil removed in Go 1.16 — use os.WriteFile()', since: 'Go 1.16', name: 'ioutil.WriteFile', id: 'GO_DEPR002' },
|
|
111
|
-
{ pattern: /ioutil\.TempDir\s*\(/, suggestion: 'ioutil removed in Go 1.16 — use os.MkdirTemp()', since: 'Go 1.16', name: 'ioutil.TempDir', id: 'GO_DEPR003' },
|
|
112
|
-
{ pattern: /ioutil\.ReadAll\s*\(/, suggestion: 'ioutil removed in Go 1.16 — use io.ReadAll()', since: 'Go 1.16', name: 'ioutil.ReadAll', id: 'GO_DEPR004' },
|
|
113
|
-
{ pattern: /strings\.Title\s*\(/, suggestion: 'strings.Title deprecated in Go 1.18 — use cases.Title from golang.org/x/text', since: 'Go 1.18', name: 'strings.Title', id: 'GO_DEPR005' },
|
|
114
|
-
];
|
|
115
|
-
|
|
116
|
-
this.goSmells = [
|
|
117
|
-
{ pattern: /\/\/\s*TODO:?\s*(implement|add|fix|complete|finish)/i, id: 'GO_SMELL001', name: 'Placeholder TODO', message: 'AI-generated placeholder — likely unfinished' },
|
|
118
|
-
{ pattern: /panic\s*\(\s*["']not implemented["']\s*\)/, id: 'GO_SMELL002', name: 'Panic Not Implemented', message: 'Stub implementation — will panic at runtime' },
|
|
119
|
-
{ pattern: /localhost:\d{4}(?!.*(?:dev|test|local|development))/i, id: 'GO_SMELL003', name: 'Hardcoded Localhost', message: 'Hardcoded localhost URL — will fail in production' },
|
|
120
|
-
];
|
|
121
|
-
|
|
122
|
-
// ─── Rust phantom APIs ──────────────────────────────────
|
|
123
|
-
this.rustPhantomAPIs = [
|
|
124
|
-
{ pattern: /std::fs::File::open_async\s*\(/, suggestion: 'Use tokio::fs::File::open() for async file I/O', name: 'File::open_async', id: 'RS_HALL001' },
|
|
125
|
-
{ pattern: /Vec::flatten\s*\(/, suggestion: 'Use .into_iter().flatten() — Vec has no flatten() method', name: 'Vec::flatten', id: 'RS_HALL002' },
|
|
126
|
-
{ pattern: /HashMap::get_or_default\s*\(/, suggestion: 'Use .get().unwrap_or(&default) or entry().or_insert()', name: 'HashMap::get_or_default', id: 'RS_HALL003' },
|
|
127
|
-
{ pattern: /String::from_utf8_lossy_owned\s*\(/, suggestion: 'Use String::from_utf8_lossy().into_owned()', name: 'String::from_utf8_lossy_owned', id: 'RS_HALL004' },
|
|
128
|
-
{ pattern: /\.async_iter\s*\(/, suggestion: 'Use futures::stream::iter() from the futures crate', name: '.async_iter()', id: 'RS_HALL005' },
|
|
129
|
-
{ pattern: /std::net::TcpStream::connect_async\s*\(/, suggestion: 'Use tokio::net::TcpStream::connect()', name: 'TcpStream::connect_async', id: 'RS_HALL006' },
|
|
130
|
-
{ pattern: /std::thread::sleep_async\s*\(/, suggestion: 'Use tokio::time::sleep() for async sleep', name: 'thread::sleep_async', id: 'RS_HALL007' },
|
|
131
|
-
{ pattern: /Vec::remove_all\s*\(/, suggestion: 'Use .retain(|x| condition) or .clear()', name: 'Vec::remove_all', id: 'RS_HALL008' },
|
|
132
|
-
{ pattern: /str::split_whitespace_n\s*\(/, suggestion: 'Use .splitn(n, char::is_whitespace) instead', name: 'str::split_whitespace_n', id: 'RS_HALL009' },
|
|
133
|
-
{ pattern: /\.map_async\s*\(/, suggestion: 'Use futures::future::join_all() or tokio::task::spawn', name: '.map_async()', id: 'RS_HALL010' },
|
|
134
|
-
];
|
|
135
|
-
|
|
136
|
-
this.rustDeprecated = [
|
|
137
|
-
{ pattern: /std::sync::ONCE_INIT/, suggestion: 'std::sync::ONCE_INIT removed — use Once::new()', since: 'Rust 1.38', name: 'ONCE_INIT', id: 'RS_DEPR001' },
|
|
138
|
-
{ pattern: /\bstd::mem::uninitialized\s*\(/, suggestion: 'std::mem::uninitialized() removed — use MaybeUninit::uninit()', since: 'Rust 1.39', name: 'mem::uninitialized', id: 'RS_DEPR002' },
|
|
139
|
-
{ pattern: /\btry!\s*\(/, suggestion: 'try!() macro removed — use the ? operator', since: 'Rust 2018', name: 'try!() macro', id: 'RS_DEPR003' },
|
|
140
|
-
{ pattern: /extern\s+crate\s+std\s*;/, suggestion: 'extern crate std is implicit since Rust 2018 edition', since: 'Rust 2018', name: 'extern crate std', id: 'RS_DEPR004' },
|
|
141
|
-
{ pattern: /extern\s+crate\s+alloc\s*;/, suggestion: 'extern crate alloc is implicit in 2018+ edition', since: 'Rust 2018', name: 'extern crate alloc', id: 'RS_DEPR005' },
|
|
142
|
-
{ pattern: /std::error::Error::cause\s*\(/, suggestion: '.cause() deprecated — use .source() instead', since: 'Rust 1.33', name: 'Error::cause()', id: 'RS_DEPR006' },
|
|
143
|
-
];
|
|
144
|
-
|
|
145
|
-
this.rustSmells = [
|
|
146
|
-
{ pattern: /todo!\s*\(\s*\)/, id: 'RS_SMELL001', name: 'todo! macro', message: 'todo!() macro — will panic at runtime' },
|
|
147
|
-
{ pattern: /unimplemented!\s*\(\s*\)/, id: 'RS_SMELL002', name: 'unimplemented! macro', message: 'unimplemented!() macro — will panic at runtime' },
|
|
148
|
-
{ pattern: /\/\/\s*TODO:?\s*(implement|add|fix|complete|finish)/i, id: 'RS_SMELL003', name: 'Placeholder TODO', message: 'AI-generated placeholder — likely unfinished' },
|
|
149
|
-
{ pattern: /unwrap\(\).*unwrap\(\)/, id: 'RS_SMELL004', name: 'Double Unwrap', message: 'Chained unwrap() — will panic on None/Err' },
|
|
150
|
-
{ pattern: /localhost:\d{4}(?!.*(?:dev|test|local|development))/i, id: 'RS_SMELL005', name: 'Hardcoded Localhost', message: 'Hardcoded localhost URL — will fail in production' },
|
|
151
|
-
{ pattern: /unsafe\s*\{/, id: 'RS_SMELL006', name: 'Unsafe Block', message: 'unsafe block — verify memory safety guarantees' },
|
|
152
|
-
{ pattern: /\.unwrap\(\)\s*;/, id: 'RS_SMELL007', name: 'Bare unwrap()', message: '.unwrap() will panic on None/Err — use ? or match' },
|
|
153
|
-
{ pattern: /println!\s*\(\s*["'].*[Dd]ebug/, id: 'RS_SMELL008', name: 'Debug println!', message: 'Debug println! left in code — use the log crate' },
|
|
154
|
-
{ pattern: /eprintln!\s*\(\s*["'].*[Dd]ebug/, id: 'RS_SMELL009', name: 'Debug eprintln!', message: 'Debug eprintln! left in code — use the log crate' },
|
|
155
|
-
{ pattern: /#\[allow\(dead_code\)\]/, id: 'RS_SMELL010', name: 'Suppressed Dead Code', message: '#[allow(dead_code)] suppresses warnings — remove unused code' },
|
|
156
|
-
];
|
|
157
|
-
|
|
158
|
-
// ─── Java smells ─────────────────────────────────────────
|
|
159
|
-
this.javaSmells = [
|
|
160
|
-
{ pattern: /System\.out\.println\s*\(.*debug/i, id: 'JAVA_SMELL001', name: 'Debug Println', message: 'Debug System.out.println — use a logger' },
|
|
161
|
-
{ pattern: /\/\/\s*TODO:?\s*(implement|add|fix|complete|finish)/i, id: 'JAVA_SMELL002', name: 'Placeholder TODO', message: 'AI-generated placeholder — likely unfinished' },
|
|
162
|
-
{ pattern: /throw\s+new\s+(?:Runtime)?Exception\s*\(\s*["']Not\s+implemented["']/i, id: 'JAVA_SMELL003', name: 'Not Implemented', message: 'Stub implementation — will throw at runtime' },
|
|
163
|
-
{ pattern: /catch\s*\(\s*Exception\s+\w+\s*\)\s*\{\s*\}/, id: 'JAVA_SMELL004', name: 'Empty Catch', message: 'Empty catch block — swallows all exceptions' },
|
|
164
|
-
{ pattern: /localhost:\d{4}(?!.*(?:dev|test|local|development))/i, id: 'JAVA_SMELL005', name: 'Hardcoded Localhost', message: 'Hardcoded localhost URL — will fail in production' },
|
|
165
|
-
];
|
|
166
|
-
|
|
167
|
-
// ─── C# smells (separate from Java) ─────────────────────
|
|
168
|
-
this.csharpSmells = [
|
|
169
|
-
{ pattern: /Console\.WriteLine\s*\(.*[Dd]ebug/i, id: 'CS_SMELL001', name: 'Debug WriteLine', message: 'Debug Console.WriteLine — use ILogger or Debug.Write' },
|
|
170
|
-
{ pattern: /\/\/\s*TODO:?\s*(implement|add|fix|complete|finish)/i, id: 'CS_SMELL002', name: 'Placeholder TODO', message: 'AI-generated placeholder — likely unfinished' },
|
|
171
|
-
{ pattern: /throw\s+new\s+(?:NotImplementedException)\s*\(/, id: 'CS_SMELL003', name: 'Not Implemented', message: 'Stub implementation — will throw at runtime' },
|
|
172
|
-
{ pattern: /catch\s*\(\s*Exception\s+\w+\s*\)\s*\{\s*\}/, id: 'CS_SMELL004', name: 'Empty Catch', message: 'Empty catch block — swallows all exceptions' },
|
|
173
|
-
{ pattern: /localhost:\d{4}(?!.*(?:dev|test|local|development))/i, id: 'CS_SMELL005', name: 'Hardcoded Localhost', message: 'Hardcoded localhost URL — will fail in production' },
|
|
174
|
-
];
|
|
175
|
-
|
|
176
|
-
// ─── Kotlin phantom APIs ──────────────────────────────────
|
|
177
|
-
this.kotlinPhantomAPIs = [
|
|
178
|
-
{ pattern: /\.flatMap\s*\{[^}]*\}(?!.*asSequence)/, suggestion: 'Use .flatMap { } — verify this is not confusing sequence vs list behavior', name: 'flatMap confusion', id: 'KT_HALL001' },
|
|
179
|
-
{ pattern: /listOf\(\)\.stream\s*\(/, suggestion: 'Kotlin lists have no .stream() — use .asSequence() or direct collection ops', name: 'listOf().stream()', id: 'KT_HALL002' },
|
|
180
|
-
{ pattern: /String\.format\s*\(/, suggestion: 'Prefer Kotlin string templates "$variable" over String.format()', name: 'String.format Java-style', id: 'KT_HALL003' },
|
|
181
|
-
{ pattern: /\bObject\s*\(\s*\)/, suggestion: 'Kotlin uses Any() not Object() — or use object keyword for singletons', name: 'Object() Java-style', id: 'KT_HALL004' },
|
|
182
|
-
{ pattern: /\.forEach\s*\(\s*::println\s*\)(?!.*debug)/i, suggestion: 'println is for debug output — use a logger', name: 'println via forEach', id: 'KT_HALL005' },
|
|
183
|
-
{ pattern: /coroutineScope\s*\{\s*launch\s*\{[^}]*\}\s*\}(?!\s*\.join)/, suggestion: 'Unjoined coroutine in coroutineScope may cause issues — ensure structured concurrency', name: 'Unawaited launch', id: 'KT_HALL006' },
|
|
184
|
-
{ pattern: /Dispatchers\.IO\s*\+\s*Dispatchers/, suggestion: 'Combining Dispatchers is not valid — use one dispatcher at a time', name: 'Combined Dispatchers', id: 'KT_HALL007' },
|
|
185
|
-
{ pattern: /\.toList\(\)\.stream\(\)/, suggestion: 'Use Kotlin sequences (.asSequence()) instead of .toList().stream()', name: 'toList().stream()', id: 'KT_HALL008' },
|
|
186
|
-
{ pattern: /companion object.*getInstance/i, suggestion: 'Kotlin idiom for singletons is object keyword, not companion object + getInstance()', name: 'Java-style singleton', id: 'KT_HALL009' },
|
|
187
|
-
{ pattern: /lateinit var.*\?/, suggestion: 'lateinit properties cannot be nullable — remove ? or use by lazy {}', name: 'lateinit nullable', id: 'KT_HALL010' },
|
|
188
|
-
];
|
|
189
|
-
|
|
190
|
-
this.kotlinDeprecated = [
|
|
191
|
-
{ pattern: /\bapply\s+plugin:\s*['"]kotlin-android-extensions['"]/, suggestion: 'kotlin-android-extensions deprecated — use view binding or Jetpack ViewBinding', since: 'Kotlin 1.8', name: 'kotlin-android-extensions', id: 'KT_DEPR001' },
|
|
192
|
-
{ pattern: /\bkotlinx\.android\.synthetic/, suggestion: 'Synthetic imports deprecated — use view binding or findViewById', since: 'Kotlin 1.8', name: 'Synthetic imports', id: 'KT_DEPR002' },
|
|
193
|
-
{ pattern: /\bCoroutineScope\(EmptyCoroutineContext\)/, suggestion: 'EmptyCoroutineContext coroutine scope is error-prone — use viewModelScope or lifecycleScope', since: 'Kotlin Coroutines 1.6', name: 'EmptyCoroutineContext scope', id: 'KT_DEPR003' },
|
|
194
|
-
{ pattern: /\bBuildersKt\.launch\b/, suggestion: 'Internal BuildersKt APIs are deprecated — use coroutineScope { launch {} }', since: 'Kotlin Coroutines 1.5', name: 'BuildersKt.launch', id: 'KT_DEPR004' },
|
|
195
|
-
{ pattern: /\basyncLazy\s*\{/, suggestion: 'asyncLazy {} is not a standard Kotlin API — use lazy {} or async {}', since: 'Kotlin 1.6', name: 'asyncLazy', id: 'KT_DEPR005' },
|
|
196
|
-
];
|
|
197
|
-
|
|
198
|
-
this.kotlinSmells = [
|
|
199
|
-
{ pattern: /\bprintln\s*\(/, id: 'KT_SMELL001', name: 'Debug println', message: 'println() is for debug output — use a proper logger' },
|
|
200
|
-
{ pattern: /\/\/\s*TODO:?\s*(implement|add|fix|complete|finish)/i, id: 'KT_SMELL002', name: 'Placeholder TODO', message: 'AI-generated placeholder — likely unfinished' },
|
|
201
|
-
{ pattern: /TODO\s*\(\s*\)/, id: 'KT_SMELL003', name: 'TODO() stub', message: 'TODO() will throw NotImplementedError at runtime' },
|
|
202
|
-
{ pattern: /!!\s*\./, id: 'KT_SMELL004', name: 'Non-null assertion chain', message: '!! non-null assertion — will throw NullPointerException if null' },
|
|
203
|
-
{ pattern: /\bas\s+\w+\b(?!.*\?)/, suggestion: 'Unsafe cast — prefer safe cast (as? Type) with null check', id: 'KT_SMELL005', name: 'Unsafe cast', message: 'Unsafe cast with as — will throw ClassCastException if wrong type' },
|
|
204
|
-
{ pattern: /localhost:\d{4}(?!.*(?:dev|test|local|development))/i, id: 'KT_SMELL006', name: 'Hardcoded Localhost', message: 'Hardcoded localhost URL — will fail in production' },
|
|
205
|
-
{ pattern: /catch\s*\(\s*e:\s*Exception\s*\)\s*\{\s*\}/, id: 'KT_SMELL007', name: 'Empty Catch', message: 'Empty catch block — swallows all exceptions' },
|
|
206
|
-
{ pattern: /throw\s+NotImplementedError\s*\(/, id: 'KT_SMELL008', name: 'Not Implemented', message: 'Stub implementation — will throw at runtime' },
|
|
207
|
-
];
|
|
208
|
-
|
|
209
|
-
// ─── PHP phantom APIs ─────────────────────────────────────
|
|
210
|
-
this.phpPhantomAPIs = [
|
|
211
|
-
{ pattern: /array_flatten\s*\(/, suggestion: 'PHP has no array_flatten() — use array_merge(...$array) or a recursive function', name: 'array_flatten', id: 'PHP_HALL001' },
|
|
212
|
-
{ pattern: /str_contains_all\s*\(/, suggestion: 'PHP has no str_contains_all() — use multiple str_contains() calls', name: 'str_contains_all', id: 'PHP_HALL002' },
|
|
213
|
-
{ pattern: /array_unique_values\s*\(/, suggestion: 'PHP has no array_unique_values() — use array_values(array_unique())', name: 'array_unique_values', id: 'PHP_HALL003' },
|
|
214
|
-
{ pattern: /\$pdo->fetchAll\s*\(/, suggestion: 'fetchAll() is on PDOStatement not PDO — call $stmt->fetchAll()', name: 'PDO::fetchAll', id: 'PHP_HALL004' },
|
|
215
|
-
{ pattern: /json_decode_safe\s*\(/, suggestion: 'PHP has no json_decode_safe() — wrap json_decode() with json_last_error() check', name: 'json_decode_safe', id: 'PHP_HALL005' },
|
|
216
|
-
{ pattern: /str_replace_all\s*\(/, suggestion: 'PHP has no str_replace_all() — use str_replace() which already replaces all occurrences', name: 'str_replace_all', id: 'PHP_HALL006' },
|
|
217
|
-
{ pattern: /array_map_keys\s*\(/, suggestion: 'PHP has no array_map_keys() — use array_combine(array_map(...), array_keys())', name: 'array_map_keys', id: 'PHP_HALL007' },
|
|
218
|
-
{ pattern: /\$request->getJson\s*\(/, suggestion: 'Not a standard PHP function — use json_decode(file_get_contents("php://input"))', name: '$request->getJson', id: 'PHP_HALL008' },
|
|
219
|
-
{ pattern: /Date::now\s*\(/, suggestion: 'PHP has no Date::now() — use new DateTime() or time()', name: 'Date::now', id: 'PHP_HALL009' },
|
|
220
|
-
{ pattern: /\bawait\s+/, suggestion: 'PHP has no await keyword — use synchronous code or ReactPHP for async', name: 'await keyword', id: 'PHP_HALL010' },
|
|
221
|
-
];
|
|
222
|
-
|
|
223
|
-
this.phpDeprecated = [
|
|
224
|
-
{ pattern: /\bmysql_connect\s*\(/, suggestion: 'mysql_* functions removed in PHP 7 — use PDO or MySQLi', since: 'PHP 7.0', name: 'mysql_connect', id: 'PHP_DEPR001' },
|
|
225
|
-
{ pattern: /\bmysql_query\s*\(/, suggestion: 'mysql_* functions removed in PHP 7 — use PDO or MySQLi', since: 'PHP 7.0', name: 'mysql_query', id: 'PHP_DEPR002' },
|
|
226
|
-
{ pattern: /\bmysql_fetch_array\s*\(/, suggestion: 'mysql_* functions removed in PHP 7 — use PDO or MySQLi', since: 'PHP 7.0', name: 'mysql_fetch_array', id: 'PHP_DEPR003' },
|
|
227
|
-
{ pattern: /\bereg\s*\(/, suggestion: 'ereg() removed in PHP 7 — use preg_match()', since: 'PHP 7.0', name: 'ereg()', id: 'PHP_DEPR004' },
|
|
228
|
-
{ pattern: /\bsplit\s*\(/, suggestion: 'split() removed in PHP 7 — use preg_split() or explode()', since: 'PHP 7.0', name: 'split()', id: 'PHP_DEPR005' },
|
|
229
|
-
{ pattern: /\bcreate_function\s*\(/, suggestion: 'create_function() removed in PHP 8 — use anonymous functions (closures)', since: 'PHP 8.0', name: 'create_function', id: 'PHP_DEPR006' },
|
|
230
|
-
{ pattern: /\bmagic_quotes_gpc\b/, suggestion: 'magic_quotes_gpc removed in PHP 7 — sanitize inputs manually', since: 'PHP 7.0', name: 'magic_quotes_gpc', id: 'PHP_DEPR007' },
|
|
231
|
-
{ pattern: /\beach\s*\(/, suggestion: 'each() deprecated in PHP 7.2, removed in PHP 8 — use foreach', since: 'PHP 8.0', name: 'each()', id: 'PHP_DEPR008' },
|
|
232
|
-
{ pattern: /\bmcrypt_/, suggestion: 'mcrypt removed in PHP 7.2 — use OpenSSL functions', since: 'PHP 7.2', name: 'mcrypt functions', id: 'PHP_DEPR009' },
|
|
233
|
-
];
|
|
234
|
-
|
|
235
|
-
this.phpSmells = [
|
|
236
|
-
{ pattern: /\beval\s*\(/, id: 'PHP_SMELL001', name: 'eval() Usage', message: 'eval() is dangerous — code injection risk' },
|
|
237
|
-
{ pattern: /\bextract\s*\(\s*\$_(?:GET|POST|REQUEST)/, id: 'PHP_SMELL002', name: 'extract() from superglobal', message: 'extract($_GET/_POST) — variable injection vulnerability' },
|
|
238
|
-
{ pattern: /\$\$\w+/, id: 'PHP_SMELL003', name: 'Variable variable', message: 'Variable variables ($$var) — hard to trace and injection risk' },
|
|
239
|
-
{ pattern: /\bshell_exec\s*\(/, id: 'PHP_SMELL004', name: 'shell_exec()', message: 'shell_exec() — remote code execution risk if input unsanitized' },
|
|
240
|
-
{ pattern: /\bsystem\s*\(/, id: 'PHP_SMELL005', name: 'system()', message: 'system() — remote code execution risk if input unsanitized' },
|
|
241
|
-
{ pattern: /\bpassthru\s*\(/, id: 'PHP_SMELL006', name: 'passthru()', message: 'passthru() — remote code execution risk if input unsanitized' },
|
|
242
|
-
{ pattern: /\/\/\s*TODO:?\s*(implement|add|fix|complete|finish)/i, id: 'PHP_SMELL007', name: 'Placeholder TODO', message: 'AI-generated placeholder — likely unfinished' },
|
|
243
|
-
{ pattern: /localhost:\d{4}(?!.*(?:dev|test|local|development))/i, id: 'PHP_SMELL008', name: 'Hardcoded Localhost', message: 'Hardcoded localhost URL — will fail in production' },
|
|
244
|
-
{ pattern: /\$_(?:GET|POST|REQUEST)\[.*\].*SELECT.*\./i, id: 'PHP_SMELL009', name: 'SQL Injection Risk', message: 'User input directly in SQL string — use prepared statements' },
|
|
245
|
-
{ pattern: /\bvar_dump\s*\(/, id: 'PHP_SMELL010', name: 'Debug var_dump', message: 'var_dump() is for debug only — remove before production' },
|
|
246
|
-
];
|
|
247
|
-
|
|
248
|
-
// ─── Ruby phantom APIs ────────────────────────────────────
|
|
249
|
-
this.rubyPhantomAPIs = [
|
|
250
|
-
{ pattern: /\.flatten_map\s*\{/, suggestion: 'Ruby has no .flatten_map — use .flat_map { }', name: '.flatten_map', id: 'RB_HALL001' },
|
|
251
|
-
{ pattern: /Array\.of\s*\(/, suggestion: 'Ruby has no Array.of() — use Array() or []', name: 'Array.of()', id: 'RB_HALL002' },
|
|
252
|
-
{ pattern: /Hash\.from_array\s*\(/, suggestion: 'Ruby has no Hash.from_array() — use array.to_h or Hash[array]', name: 'Hash.from_array', id: 'RB_HALL003' },
|
|
253
|
-
{ pattern: /\.async\s*\{/, suggestion: 'Ruby has no .async {} — use Thread.new or concurrent-ruby gem', name: '.async block', id: 'RB_HALL004' },
|
|
254
|
-
{ pattern: /String\.format\s*\(/, suggestion: 'Ruby has no String.format() — use string interpolation or % operator', name: 'String.format', id: 'RB_HALL005' },
|
|
255
|
-
{ pattern: /\bpromise\s*\{/, suggestion: 'Ruby has no built-in promise {} — use concurrent-ruby gem or Thread', name: 'promise block', id: 'RB_HALL006' },
|
|
256
|
-
{ pattern: /\.try!\s*\(/, suggestion: 'Ruby has no .try!() — use &. (safe navigation) or Rails .try()', name: '.try!()', id: 'RB_HALL007' },
|
|
257
|
-
{ pattern: /JSON\.safe_parse\s*\(/, suggestion: 'Ruby has no JSON.safe_parse — use JSON.parse with rescue', name: 'JSON.safe_parse', id: 'RB_HALL008' },
|
|
258
|
-
{ pattern: /ActiveRecord::Base\.execute\s*\(/, suggestion: 'ActiveRecord::Base has no .execute() — use connection.execute() or where()', name: 'Base.execute', id: 'RB_HALL009' },
|
|
259
|
-
{ pattern: /\.collect_map\s*\{/, suggestion: 'Ruby has no .collect_map — use .map { }.flatten(1) or .flat_map', name: '.collect_map', id: 'RB_HALL010' },
|
|
260
|
-
];
|
|
261
|
-
|
|
262
|
-
this.rubyDeprecated = [
|
|
263
|
-
{ pattern: /\brequire\s+['"]thread['"]/, suggestion: 'require "thread" is deprecated — Thread is now built-in without require', since: 'Ruby 2.0', name: 'require "thread"', id: 'RB_DEPR001' },
|
|
264
|
-
{ pattern: /\bObject#type\b|\.type\s*==/, suggestion: '.type is deprecated — use .class or .is_a?', since: 'Ruby 1.8', name: 'Object#type', id: 'RB_DEPR002' },
|
|
265
|
-
{ pattern: /\bERB::Util\.html_escape\b/, suggestion: 'ERB::Util.html_escape deprecated — use CGI.escapeHTML or h() in views', since: 'Ruby 2.6', name: 'ERB::Util.html_escape', id: 'RB_DEPR003' },
|
|
266
|
-
{ pattern: /\bFile\.exists\?\s*\(/, suggestion: 'File.exists? deprecated — use File.exist? (no s)', since: 'Ruby 2.2', name: 'File.exists?', id: 'RB_DEPR004' },
|
|
267
|
-
{ pattern: /\bDir\.exists\?\s*\(/, suggestion: 'Dir.exists? deprecated — use Dir.exist? (no s)', since: 'Ruby 2.2', name: 'Dir.exists?', id: 'RB_DEPR005' },
|
|
268
|
-
{ pattern: /\bObject#returning\b|\s+returning\s+/, suggestion: 'Object#returning removed from Rails core — use tap { |obj| }', since: 'Rails 3.0', name: 'Object#returning', id: 'RB_DEPR006' },
|
|
269
|
-
];
|
|
270
|
-
|
|
271
|
-
this.rubySmells = [
|
|
272
|
-
{ pattern: /\bputs\s+(?!STDOUT)/, id: 'RB_SMELL001', name: 'Debug puts', message: 'puts is for debug output — use Rails logger or a logging library' },
|
|
273
|
-
{ pattern: /\bp\s+\w/, id: 'RB_SMELL002', name: 'Debug p()', message: 'p() is for debug output — remove before production' },
|
|
274
|
-
{ pattern: /\beval\s*\(/, id: 'RB_SMELL003', name: 'eval() Usage', message: 'eval() is dangerous — code injection risk' },
|
|
275
|
-
{ pattern: /\bsystem\s*\(/, id: 'RB_SMELL004', name: 'system() Shell Call', message: 'system() call — command injection risk if input unsanitized' },
|
|
276
|
-
{ pattern: /`[^`]+`/, id: 'RB_SMELL005', name: 'Backtick Shell Exec', message: 'Backtick shell execution — command injection risk' },
|
|
277
|
-
{ pattern: /\bexec\s*\(/, id: 'RB_SMELL006', name: 'exec() call', message: 'exec() replaces the process — ensure this is intentional' },
|
|
278
|
-
{ pattern: /\brescue\s*$|\brescue\s+Exception\b/, id: 'RB_SMELL007', name: 'Bare rescue', message: 'Bare rescue catches all exceptions including fatal ones — be specific' },
|
|
279
|
-
{ pattern: /["'].*#\{.*sql.*\}.*["']/i, id: 'RB_SMELL008', name: 'SQL String Interpolation', message: 'SQL built with string interpolation — use parameterized queries' },
|
|
280
|
-
{ pattern: /\/\/\s*TODO:?\s*(implement|add|fix|complete|finish)/i, id: 'RB_SMELL009', name: 'Placeholder TODO', message: 'AI-generated placeholder — likely unfinished' },
|
|
281
|
-
{ pattern: /raise\s+NotImplementedError/, id: 'RB_SMELL010', name: 'Not Implemented', message: 'Stub implementation — will raise at runtime' },
|
|
282
|
-
];
|
|
283
|
-
|
|
284
|
-
// Language extensions mapping
|
|
285
|
-
this.jsExtensions = new Set(['.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs']);
|
|
286
|
-
this.pyExtensions = new Set(['.py', '.pyw']);
|
|
287
|
-
this.goExtensions = new Set(['.go']);
|
|
288
|
-
this.rustExtensions = new Set(['.rs']);
|
|
289
|
-
this.javaExtensions = new Set(['.java', '.kt']);
|
|
290
|
-
this.csharpExtensions = new Set(['.cs']);
|
|
291
|
-
this.phpExtensions = new Set(['.php']);
|
|
292
|
-
this.rubyExtensions = new Set(['.rb']);
|
|
293
|
-
|
|
294
|
-
// Patterns suggesting AI-generated code with common issues
|
|
295
|
-
this.aiCodeSmells = [
|
|
296
|
-
{ pattern: /\/\/\s*TODO:?\s*(implement|add|fix|complete|finish)\s*(this|here|later)/i, id: 'AI_SMELL001', name: 'Placeholder TODO', message: 'AI-generated placeholder — likely unfinished implementation' },
|
|
297
|
-
{ pattern: /throw new Error\(['"]Not implemented['"]\)/, id: 'AI_SMELL002', name: 'Not Implemented', message: 'Stub implementation — function body was not generated' },
|
|
298
|
-
{ pattern: /\/\/\s*\.\.\.\s*(rest|remaining|more|other|additional)/i, id: 'AI_SMELL003', name: 'Truncated Code', message: 'AI output was truncated — code is incomplete' },
|
|
299
|
-
{ pattern: /\/\/\s*(your|replace|insert|put)\s+(code|logic|implementation|api[_\s]?key)/i, id: 'AI_SMELL004', name: 'Template Placeholder', message: 'Template placeholder left in code — needs real implementation' },
|
|
300
|
-
{ pattern: /['"]your-api-key-here['"]|['"]sk-[.]{3,}['"]|['"]xxx+['"]/i, id: 'AI_SMELL005', name: 'Dummy Credential', message: 'Placeholder credential — will fail at runtime' },
|
|
301
|
-
{ pattern: /example\.com|test@test\.com|john@doe\.com|foo@bar\.com/i, id: 'AI_SMELL006', name: 'Example Domain', message: 'Example domain/email in production code' },
|
|
302
|
-
{ pattern: /localhost:\d{4}(?!.*(?:dev|test|local|development))/i, id: 'AI_SMELL007', name: 'Hardcoded Localhost', message: 'Hardcoded localhost URL — will fail in production' },
|
|
303
|
-
];
|
|
304
|
-
|
|
305
|
-
// Deprecated/removed Node.js APIs that LLMs still suggest
|
|
306
|
-
this.deprecatedAPIs = [
|
|
307
|
-
{ pattern: /new Buffer\s*\(/, suggestion: 'Use Buffer.from(), Buffer.alloc(), or Buffer.allocUnsafe()', since: 'Node 6', name: 'new Buffer()', id: 'DEPR_API001' },
|
|
308
|
-
{ pattern: /require\s*\(\s*['"]sys['"]\s*\)/, suggestion: 'Use require("util") — sys was removed in Node 1.0', since: 'Node 1.0', name: 'require("sys")', id: 'DEPR_API002' },
|
|
309
|
-
{ pattern: /fs\.exists\s*\((?!Sync)/, suggestion: 'Use fs.access() or fs.stat() — fs.exists() is deprecated', since: 'Node 1.0', name: 'fs.exists()', id: 'DEPR_API003' },
|
|
310
|
-
{ pattern: /domain\.create\s*\(/, suggestion: 'Use async_hooks or try/catch — domain module is deprecated', since: 'Node 4', name: 'domain.create()', id: 'DEPR_API004', fixable: false },
|
|
311
|
-
{ pattern: /require\s*\(\s*['"]punycode['"]\s*\)/, suggestion: 'Use userland punycode package — built-in is deprecated', since: 'Node 7', name: 'require("punycode")', id: 'DEPR_API005', fixable: false },
|
|
312
|
-
{ pattern: /url\.parse\s*\(/, suggestion: 'Use new URL() — url.parse() is legacy', since: 'Node 11', name: 'url.parse()', id: 'DEPR_API006' },
|
|
313
|
-
{ pattern: /querystring\.(parse|stringify)\s*\(/, suggestion: 'Use URLSearchParams — querystring is legacy', since: 'Node 14', name: 'querystring', id: 'DEPR_API007', fixable: false },
|
|
314
|
-
{ pattern: /util\.isArray\s*\(/, suggestion: 'Use Array.isArray() — util type checks are deprecated', since: 'Node 4', name: 'util.isArray()', id: 'DEPR_API008' },
|
|
315
|
-
{ pattern: /util\.isFunction\s*\(/, suggestion: 'Use typeof fn === "function"', since: 'Node 4', name: 'util.isFunction()', id: 'DEPR_API009' },
|
|
316
|
-
{ pattern: /util\.pump\s*\(/, suggestion: 'Use stream.pipeline() — util.pump() was removed', since: 'Node 1.0', name: 'util.pump()', id: 'DEPR_API010', fixable: false },
|
|
317
|
-
];
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Full hallucination scan across all files
|
|
322
|
-
*/
|
|
323
|
-
async scan(files) {
|
|
324
|
-
const startTime = Date.now();
|
|
325
|
-
const results = {
|
|
326
|
-
phantomImports: [],
|
|
327
|
-
phantomAPIs: [],
|
|
328
|
-
aiSmells: [],
|
|
329
|
-
deprecatedAPIs: [],
|
|
330
|
-
unresolvedDeps: [],
|
|
331
|
-
stats: {
|
|
332
|
-
filesScanned: 0,
|
|
333
|
-
totalIssues: 0,
|
|
334
|
-
scanTime: 0,
|
|
335
|
-
},
|
|
336
|
-
};
|
|
337
|
-
|
|
338
|
-
// Load package.json dependencies
|
|
339
|
-
const declaredDeps = this._loadDeclaredDeps();
|
|
340
|
-
|
|
341
|
-
// Load .thubanrc.json ignore rules
|
|
342
|
-
const ignoreFiles = this._loadIgnoreRules();
|
|
343
|
-
|
|
344
|
-
for (const file of files) {
|
|
345
|
-
try {
|
|
346
|
-
const ext = path.extname(file).toLowerCase();
|
|
347
|
-
const isJS = this.jsExtensions.has(ext);
|
|
348
|
-
const isPython = this.pyExtensions.has(ext);
|
|
349
|
-
const isGo = this.goExtensions.has(ext);
|
|
350
|
-
const isRust = this.rustExtensions.has(ext);
|
|
351
|
-
const isJava = this.javaExtensions.has(ext);
|
|
352
|
-
const isCSharp = this.csharpExtensions.has(ext);
|
|
353
|
-
const isPHP = this.phpExtensions.has(ext);
|
|
354
|
-
const isRuby = this.rubyExtensions.has(ext);
|
|
355
|
-
|
|
356
|
-
if (!isJS && !isPython && !isGo && !isRust && !isJava && !isCSharp && !isPHP && !isRuby) continue;
|
|
357
|
-
|
|
358
|
-
const relPath = path.relative(this.config.rootPath, file);
|
|
359
|
-
|
|
360
|
-
// Skip files in the ignore list
|
|
361
|
-
if (ignoreFiles.some(pattern => relPath.includes(pattern) || file.includes(pattern))) continue;
|
|
362
|
-
|
|
363
|
-
const content = fs.readFileSync(file, 'utf-8');
|
|
364
|
-
const lines = content.split('\n');
|
|
365
|
-
|
|
366
|
-
// Build set of lines with thuban-ignore comments
|
|
367
|
-
const ignoredLines = new Set();
|
|
368
|
-
for (let i = 0; i < lines.length; i++) {
|
|
369
|
-
if (lines[i].includes('thuban-ignore')) {
|
|
370
|
-
ignoredLines.add(i + 1); // 1-based
|
|
371
|
-
ignoredLines.add(i + 2); // Also ignore next line
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// Skip files that are pattern definition files (contain regex pattern arrays)
|
|
376
|
-
// These files define what to look for, not actual violations
|
|
377
|
-
const isPatternFile = this._isPatternDefinitionFile(content);
|
|
378
|
-
|
|
379
|
-
results.stats.filesScanned++;
|
|
380
|
-
|
|
381
|
-
// ─── Language-specific checks ──────────────────────
|
|
382
|
-
if (isJS) {
|
|
383
|
-
// 1. Phantom imports — packages that don't exist
|
|
384
|
-
this._checkPhantomImports(relPath, content, lines, declaredDeps, results, ignoredLines);
|
|
385
|
-
// 2. Phantom APIs — methods that don't exist on known objects
|
|
386
|
-
if (!isPatternFile) {
|
|
387
|
-
this._checkPhantomAPIs(relPath, content, lines, results, ignoredLines);
|
|
388
|
-
}
|
|
389
|
-
// 3. AI code smells
|
|
390
|
-
this._checkAISmells(relPath, content, lines, results, ignoredLines);
|
|
391
|
-
// 4. Deprecated APIs
|
|
392
|
-
if (!isPatternFile) {
|
|
393
|
-
this._checkDeprecatedAPIs(relPath, content, lines, results, ignoredLines);
|
|
394
|
-
}
|
|
395
|
-
} else if (isPython) {
|
|
396
|
-
this._checkLanguagePatterns(relPath, content, lines, results, ignoredLines, this.pythonPhantomAPIs, 'phantomAPIs');
|
|
397
|
-
this._checkLanguagePatterns(relPath, content, lines, results, ignoredLines, this.pythonDeprecated, 'deprecatedAPIs');
|
|
398
|
-
this._checkLanguageSmells(relPath, content, lines, results, ignoredLines, this.pythonSmells);
|
|
399
|
-
} else if (isPHP) {
|
|
400
|
-
this._checkLanguagePatterns(relPath, content, lines, results, ignoredLines, this.phpPhantomAPIs, 'phantomAPIs');
|
|
401
|
-
this._checkLanguagePatterns(relPath, content, lines, results, ignoredLines, this.phpDeprecated, 'deprecatedAPIs');
|
|
402
|
-
this._checkLanguageSmells(relPath, content, lines, results, ignoredLines, this.phpSmells);
|
|
403
|
-
} else if (isRuby) {
|
|
404
|
-
this._checkLanguagePatterns(relPath, content, lines, results, ignoredLines, this.rubyPhantomAPIs, 'phantomAPIs');
|
|
405
|
-
this._checkLanguagePatterns(relPath, content, lines, results, ignoredLines, this.rubyDeprecated, 'deprecatedAPIs');
|
|
406
|
-
this._checkLanguageSmells(relPath, content, lines, results, ignoredLines, this.rubySmells);
|
|
407
|
-
} else if (isGo) {
|
|
408
|
-
this._checkLanguagePatterns(relPath, content, lines, results, ignoredLines, this.goDeprecated, 'deprecatedAPIs');
|
|
409
|
-
this._checkLanguageSmells(relPath, content, lines, results, ignoredLines, this.goSmells);
|
|
410
|
-
} else if (isRust) {
|
|
411
|
-
this._checkLanguagePatterns(relPath, content, lines, results, ignoredLines, this.rustPhantomAPIs, 'phantomAPIs');
|
|
412
|
-
this._checkLanguagePatterns(relPath, content, lines, results, ignoredLines, this.rustDeprecated, 'deprecatedAPIs');
|
|
413
|
-
this._checkLanguageSmells(relPath, content, lines, results, ignoredLines, this.rustSmells);
|
|
414
|
-
} else if (isJava) {
|
|
415
|
-
// Java and Kotlin share javaExtensions (.java, .kt)
|
|
416
|
-
const isKotlin = ext === '.kt';
|
|
417
|
-
if (isKotlin) {
|
|
418
|
-
this._checkLanguagePatterns(relPath, content, lines, results, ignoredLines, this.kotlinPhantomAPIs, 'phantomAPIs');
|
|
419
|
-
this._checkLanguagePatterns(relPath, content, lines, results, ignoredLines, this.kotlinDeprecated, 'deprecatedAPIs');
|
|
420
|
-
this._checkLanguageSmells(relPath, content, lines, results, ignoredLines, this.kotlinSmells);
|
|
421
|
-
} else {
|
|
422
|
-
this._checkLanguageSmells(relPath, content, lines, results, ignoredLines, this.javaSmells);
|
|
423
|
-
}
|
|
424
|
-
} else if (isCSharp) {
|
|
425
|
-
this._checkLanguageSmells(relPath, content, lines, results, ignoredLines, this.csharpSmells);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
} catch (e) { /* skip unreadable */ }
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
results.stats.totalIssues =
|
|
432
|
-
results.phantomImports.length +
|
|
433
|
-
results.phantomAPIs.length +
|
|
434
|
-
results.aiSmells.length +
|
|
435
|
-
results.deprecatedAPIs.length +
|
|
436
|
-
results.unresolvedDeps.length;
|
|
437
|
-
|
|
438
|
-
results.stats.scanTime = Date.now() - startTime;
|
|
439
|
-
|
|
440
|
-
return results;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
/**
|
|
444
|
-
* Generic language pattern checker (for phantom APIs and deprecated APIs)
|
|
445
|
-
*/
|
|
446
|
-
_checkLanguagePatterns(relPath, content, lines, results, ignoredLines, patterns, resultKey) {
|
|
447
|
-
for (let i = 0; i < lines.length; i++) {
|
|
448
|
-
if (ignoredLines.has(i + 1)) continue;
|
|
449
|
-
const line = lines[i];
|
|
450
|
-
for (const check of patterns) {
|
|
451
|
-
if (check.pattern.test(line)) {
|
|
452
|
-
const entry = {
|
|
453
|
-
file: relPath,
|
|
454
|
-
line: i + 1,
|
|
455
|
-
name: check.name,
|
|
456
|
-
id: check.id,
|
|
457
|
-
};
|
|
458
|
-
if (check.suggestion) entry.suggestion = check.suggestion;
|
|
459
|
-
if (check.since) {
|
|
460
|
-
entry.since = check.since;
|
|
461
|
-
entry.fix = check.suggestion;
|
|
462
|
-
}
|
|
463
|
-
if (resultKey === 'deprecatedAPIs') {
|
|
464
|
-
results.deprecatedAPIs.push(entry);
|
|
465
|
-
} else {
|
|
466
|
-
results.phantomAPIs.push(entry);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* Generic language smell checker
|
|
475
|
-
*/
|
|
476
|
-
_checkLanguageSmells(relPath, content, lines, results, ignoredLines, smells) {
|
|
477
|
-
for (let i = 0; i < lines.length; i++) {
|
|
478
|
-
if (ignoredLines.has(i + 1)) continue;
|
|
479
|
-
const line = lines[i];
|
|
480
|
-
for (const smell of smells) {
|
|
481
|
-
if (smell.pattern.test(line)) {
|
|
482
|
-
results.aiSmells.push({
|
|
483
|
-
file: relPath,
|
|
484
|
-
line: i + 1,
|
|
485
|
-
id: smell.id,
|
|
486
|
-
name: smell.name,
|
|
487
|
-
message: smell.message,
|
|
488
|
-
type: 'ai_smell',
|
|
489
|
-
severity: 'medium',
|
|
490
|
-
});
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
/**
|
|
497
|
-
* Format results for terminal output
|
|
498
|
-
*/
|
|
499
|
-
formatReport(results) {
|
|
500
|
-
const C = {
|
|
501
|
-
reset: '\x1b[0m', bold: '\x1b[1m',
|
|
502
|
-
red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m',
|
|
503
|
-
cyan: '\x1b[36m', gray: '\x1b[90m', magenta: '\x1b[35m',
|
|
504
|
-
};
|
|
505
|
-
|
|
506
|
-
let output = '';
|
|
507
|
-
output += `\n${C.magenta} ╔══════════════════════════════════════════════╗${C.reset}\n`;
|
|
508
|
-
output += `${C.magenta} ║${C.bold} THUBAN HALLUCINATION REPORT ${C.reset}${C.magenta}║${C.reset}\n`;
|
|
509
|
-
output += `${C.magenta} ╚══════════════════════════════════════════════╝${C.reset}\n\n`;
|
|
510
|
-
|
|
511
|
-
if (results.stats.totalIssues === 0) {
|
|
512
|
-
output += ` ${C.green}${C.bold}No hallucinations detected.${C.reset} ${C.gray}Clean codebase.${C.reset}\n\n`;
|
|
513
|
-
return output;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// Phantom imports
|
|
517
|
-
if (results.phantomImports.length > 0) {
|
|
518
|
-
output += ` ${C.red}${C.bold}Phantom Imports (${results.phantomImports.length})${C.reset}\n`;
|
|
519
|
-
output += ` ${C.gray}Packages that don't exist in package.json or node_modules${C.reset}\n\n`;
|
|
520
|
-
for (const item of results.phantomImports.slice(0, 10)) {
|
|
521
|
-
output += ` ${C.red}✗${C.reset} ${C.cyan}${item.file}${C.reset}:${item.line}\n`;
|
|
522
|
-
output += ` ${C.yellow}${item.module}${C.reset} ${C.gray}— ${item.reason}${C.reset}\n`;
|
|
523
|
-
}
|
|
524
|
-
if (results.phantomImports.length > 10) {
|
|
525
|
-
output += ` ${C.gray}... and ${results.phantomImports.length - 10} more${C.reset}\n`;
|
|
526
|
-
}
|
|
527
|
-
output += '\n';
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// Phantom APIs
|
|
531
|
-
if (results.phantomAPIs.length > 0) {
|
|
532
|
-
output += ` ${C.red}${C.bold}Phantom APIs (${results.phantomAPIs.length})${C.reset}\n`;
|
|
533
|
-
output += ` ${C.gray}Methods/properties that don't exist on their objects${C.reset}\n\n`;
|
|
534
|
-
for (const item of results.phantomAPIs.slice(0, 10)) {
|
|
535
|
-
const ruleId = item.id ? `${C.gray}[${item.id}]${C.reset} ` : '';
|
|
536
|
-
output += ` ${C.red}✗${C.reset} ${ruleId}${C.cyan}${item.file}${C.reset}:${item.line}\n`;
|
|
537
|
-
output += ` ${C.yellow}${item.name}${C.reset} ${C.gray}— ${item.suggestion}${C.reset}\n`;
|
|
538
|
-
output += ` ${C.gray}Suppress: // thuban-ignore ${item.id || 'HALL_API'}${C.reset}\n`;
|
|
539
|
-
}
|
|
540
|
-
if (results.phantomAPIs.length > 10) {
|
|
541
|
-
output += ` ${C.gray}... and ${results.phantomAPIs.length - 10} more${C.reset}\n`;
|
|
542
|
-
}
|
|
543
|
-
output += '\n';
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
// AI code smells
|
|
547
|
-
if (results.aiSmells.length > 0) {
|
|
548
|
-
output += ` ${C.yellow}${C.bold}AI Code Smells (${results.aiSmells.length})${C.reset}\n`;
|
|
549
|
-
output += ` ${C.gray}Patterns typical of AI-generated code that needs review${C.reset}\n\n`;
|
|
550
|
-
for (const item of results.aiSmells.slice(0, 10)) {
|
|
551
|
-
output += ` ${C.yellow}!${C.reset} ${C.cyan}${item.file}${C.reset}:${item.line}\n`;
|
|
552
|
-
output += ` ${C.gray}${item.message}${C.reset}\n`;
|
|
553
|
-
}
|
|
554
|
-
if (results.aiSmells.length > 10) {
|
|
555
|
-
output += ` ${C.gray}... and ${results.aiSmells.length - 10} more${C.reset}\n`;
|
|
556
|
-
}
|
|
557
|
-
output += '\n';
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
// Deprecated APIs
|
|
561
|
-
if (results.deprecatedAPIs.length > 0) {
|
|
562
|
-
output += ` ${C.yellow}${C.bold}Deprecated APIs (${results.deprecatedAPIs.length})${C.reset}\n`;
|
|
563
|
-
output += ` ${C.gray}APIs that LLMs still suggest but are deprecated or removed${C.reset}\n\n`;
|
|
564
|
-
for (const item of results.deprecatedAPIs.slice(0, 10)) {
|
|
565
|
-
output += ` ${C.yellow}⚠${C.reset} ${C.cyan}${item.file}${C.reset}:${item.line}\n`;
|
|
566
|
-
output += ` ${C.yellow}${item.name}${C.reset} ${C.gray}(deprecated since ${item.since})${C.reset}\n`;
|
|
567
|
-
output += ` ${C.green}→${C.reset} ${C.gray}${item.suggestion}${C.reset}\n`;
|
|
568
|
-
}
|
|
569
|
-
if (results.deprecatedAPIs.length > 10) {
|
|
570
|
-
output += ` ${C.gray}... and ${results.deprecatedAPIs.length - 10} more${C.reset}\n`;
|
|
571
|
-
}
|
|
572
|
-
output += '\n';
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
// Summary
|
|
576
|
-
output += ` ${C.bold}Summary:${C.reset} ${C.cyan}${results.stats.filesScanned}${C.reset} files scanned, `;
|
|
577
|
-
output += `${results.stats.totalIssues > 0 ? C.red : C.green}${results.stats.totalIssues}${C.reset} hallucination issues found `;
|
|
578
|
-
output += `${C.gray}(${results.stats.scanTime}ms)${C.reset}\n\n`;
|
|
579
|
-
|
|
580
|
-
return output;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
// ─── Private Methods ─────────────────────────────────────
|
|
584
|
-
|
|
585
|
-
_loadDeclaredDeps() {
|
|
586
|
-
const deps = new Set();
|
|
587
|
-
// Collect all package.json files — root + subdirectories (monorepo support)
|
|
588
|
-
this._packageJsonPaths = new Map(); // dir -> Set<dep names>
|
|
589
|
-
this._collectPackageJsonDeps(this.config.rootPath, deps, 0);
|
|
590
|
-
return deps;
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
/**
|
|
594
|
-
* Recursively collect deps from all package.json files in the project.
|
|
595
|
-
* Handles monorepos: workspaces, packages/*, apps/*, etc.
|
|
596
|
-
* Max depth prevents scanning into node_modules.
|
|
597
|
-
*/
|
|
598
|
-
_collectPackageJsonDeps(dir, globalDeps, depth) {
|
|
599
|
-
if (depth > 5) return; // Don't go too deep
|
|
600
|
-
try {
|
|
601
|
-
const pkgPath = path.join(dir, 'package.json');
|
|
602
|
-
if (fs.existsSync(pkgPath)) {
|
|
603
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
604
|
-
const localDeps = new Set();
|
|
605
|
-
for (const name of Object.keys(pkg.dependencies || {})) { globalDeps.add(name); localDeps.add(name); }
|
|
606
|
-
for (const name of Object.keys(pkg.devDependencies || {})) { globalDeps.add(name); localDeps.add(name); }
|
|
607
|
-
for (const name of Object.keys(pkg.peerDependencies || {})) { globalDeps.add(name); localDeps.add(name); }
|
|
608
|
-
this._packageJsonPaths.set(dir, localDeps);
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// Scan subdirectories for more package.json files
|
|
612
|
-
// Skip node_modules, .git, dist, build, coverage
|
|
613
|
-
const skipDirs = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.cache', 'vendor']);
|
|
614
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
615
|
-
for (const entry of entries) {
|
|
616
|
-
if (entry.isDirectory() && !skipDirs.has(entry.name) && !entry.name.startsWith('.')) {
|
|
617
|
-
this._collectPackageJsonDeps(path.join(dir, entry.name), globalDeps, depth + 1);
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
} catch (e) { /* skip unreadable dirs */ }
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
_checkPhantomImports(relPath, content, lines, declaredDeps, results, ignoredLines = new Set()) {
|
|
624
|
-
// Match require() and import statements
|
|
625
|
-
const requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
626
|
-
const importRegex = /import\s+.*?from\s+['"]([^'"]+)['"]/g;
|
|
627
|
-
const dynamicImportRegex = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
628
|
-
|
|
629
|
-
const allImportRegexes = [requireRegex, importRegex, dynamicImportRegex];
|
|
630
|
-
|
|
631
|
-
for (const regex of allImportRegexes) {
|
|
632
|
-
let match;
|
|
633
|
-
while ((match = regex.exec(content)) !== null) {
|
|
634
|
-
const moduleName = match[1];
|
|
635
|
-
|
|
636
|
-
// Skip relative imports
|
|
637
|
-
if (moduleName.startsWith('.') || moduleName.startsWith('/')) continue;
|
|
638
|
-
|
|
639
|
-
// Skip builtins
|
|
640
|
-
const baseModule = moduleName.split('/')[0];
|
|
641
|
-
if (this.builtins.has(moduleName) || this.builtins.has(baseModule)) continue;
|
|
642
|
-
|
|
643
|
-
// Skip scoped packages base
|
|
644
|
-
const scopedBase = moduleName.startsWith('@')
|
|
645
|
-
? moduleName.split('/').slice(0, 2).join('/')
|
|
646
|
-
: baseModule;
|
|
647
|
-
|
|
648
|
-
// Check if declared in any package.json (root or workspace)
|
|
649
|
-
if (!declaredDeps.has(scopedBase)) {
|
|
650
|
-
// Check if it physically exists in any node_modules (root or nearest parent)
|
|
651
|
-
const nmExists = this._findInNodeModules(file, scopedBase);
|
|
652
|
-
if (!nmExists) {
|
|
653
|
-
// Find line number
|
|
654
|
-
const lineIdx = this._findLineNumber(content, match.index);
|
|
655
|
-
|
|
656
|
-
// Skip if on an ignored line
|
|
657
|
-
if (ignoredLines.has(lineIdx)) continue;
|
|
658
|
-
|
|
659
|
-
// Check if it's a known phantom
|
|
660
|
-
const isKnownPhantom = this.phantomPackages.has(moduleName);
|
|
661
|
-
|
|
662
|
-
results.phantomImports.push({
|
|
663
|
-
file: relPath,
|
|
664
|
-
line: lineIdx,
|
|
665
|
-
module: moduleName,
|
|
666
|
-
reason: isKnownPhantom
|
|
667
|
-
? 'Known AI-hallucinated package — does not exist on npm'
|
|
668
|
-
: 'Not in package.json and not in node_modules',
|
|
669
|
-
severity: isKnownPhantom ? 'critical' : 'high',
|
|
670
|
-
fixable: false,
|
|
671
|
-
});
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
_checkPhantomAPIs(relPath, content, lines, results, ignoredLines = new Set()) {
|
|
679
|
-
for (const api of this.phantomAPIs) {
|
|
680
|
-
let match;
|
|
681
|
-
const regex = new RegExp(api.pattern.source, api.pattern.flags + (api.pattern.flags.includes('g') ? '' : 'g'));
|
|
682
|
-
while ((match = regex.exec(content)) !== null) {
|
|
683
|
-
const lineIdx = this._findLineNumber(content, match.index);
|
|
684
|
-
if (ignoredLines.has(lineIdx)) continue;
|
|
685
|
-
// Skip if inside a string literal or regex pattern (common in pattern definition files)
|
|
686
|
-
const line = lines[lineIdx - 1] || '';
|
|
687
|
-
if (this._isInsidePattern(line, match[0])) continue;
|
|
688
|
-
results.phantomAPIs.push({
|
|
689
|
-
file: relPath,
|
|
690
|
-
line: lineIdx,
|
|
691
|
-
name: api.name,
|
|
692
|
-
id: api.id,
|
|
693
|
-
suggestion: api.suggestion,
|
|
694
|
-
severity: 'high',
|
|
695
|
-
fixable: true,
|
|
696
|
-
fixAction: 'replace_phantom_api',
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
_checkAISmells(relPath, content, lines, results, ignoredLines = new Set()) {
|
|
703
|
-
for (const smell of this.aiCodeSmells) {
|
|
704
|
-
let match;
|
|
705
|
-
const regex = new RegExp(smell.pattern.source, smell.pattern.flags + (smell.pattern.flags.includes('g') ? '' : 'g'));
|
|
706
|
-
while ((match = regex.exec(content)) !== null) {
|
|
707
|
-
const lineIdx = this._findLineNumber(content, match.index);
|
|
708
|
-
if (ignoredLines.has(lineIdx)) continue;
|
|
709
|
-
results.aiSmells.push({
|
|
710
|
-
file: relPath,
|
|
711
|
-
line: lineIdx,
|
|
712
|
-
id: smell.id,
|
|
713
|
-
name: smell.name,
|
|
714
|
-
message: smell.message,
|
|
715
|
-
severity: 'warning',
|
|
716
|
-
code: lines[lineIdx - 1]?.trim().substring(0, 100),
|
|
717
|
-
});
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
_checkDeprecatedAPIs(relPath, content, lines, results, ignoredLines = new Set()) {
|
|
723
|
-
for (const api of this.deprecatedAPIs) {
|
|
724
|
-
let match;
|
|
725
|
-
const regex = new RegExp(api.pattern.source, api.pattern.flags + (api.pattern.flags.includes('g') ? '' : 'g'));
|
|
726
|
-
while ((match = regex.exec(content)) !== null) {
|
|
727
|
-
const lineIdx = this._findLineNumber(content, match.index);
|
|
728
|
-
if (ignoredLines.has(lineIdx)) continue;
|
|
729
|
-
const line = lines[lineIdx - 1] || '';
|
|
730
|
-
if (this._isInsidePattern(line, match[0])) continue;
|
|
731
|
-
results.deprecatedAPIs.push({
|
|
732
|
-
file: relPath,
|
|
733
|
-
line: lineIdx,
|
|
734
|
-
name: api.name,
|
|
735
|
-
id: api.id,
|
|
736
|
-
suggestion: api.suggestion,
|
|
737
|
-
since: api.since,
|
|
738
|
-
severity: 'warning',
|
|
739
|
-
fixable: true,
|
|
740
|
-
fixAction: 'update_deprecated_api',
|
|
741
|
-
});
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
_findLineNumber(content, charIndex) {
|
|
747
|
-
let line = 1;
|
|
748
|
-
for (let i = 0; i < charIndex && i < content.length; i++) {
|
|
749
|
-
if (content[i] === '\n') line++;
|
|
750
|
-
}
|
|
751
|
-
return line;
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
/**
|
|
755
|
-
* Detect if a file is a pattern definition file (like this detector itself)
|
|
756
|
-
* These files contain regex patterns that reference the APIs they detect
|
|
757
|
-
*/
|
|
758
|
-
_isPatternDefinitionFile(content) {
|
|
759
|
-
// Count regex pattern definitions — if file has many, it's likely a detector/rule file
|
|
760
|
-
const regexPatterns = (content.match(/pattern:\s*\//g) || []).length;
|
|
761
|
-
const phantomRefs = (content.match(/phantom|hallucin/gi) || []).length;
|
|
762
|
-
return regexPatterns > 5 && phantomRefs > 2;
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
/**
|
|
766
|
-
* Check if a match is inside a regex pattern, string literal, or comment
|
|
767
|
-
*/
|
|
768
|
-
_isInsidePattern(line, matchText) {
|
|
769
|
-
const trimmed = line.trim();
|
|
770
|
-
// Inside a regex pattern definition
|
|
771
|
-
if (/pattern:\s*\//.test(trimmed)) return true;
|
|
772
|
-
// Inside a comment
|
|
773
|
-
if (trimmed.startsWith('//') || trimmed.startsWith('*')) return true;
|
|
774
|
-
// Inside a string that's defining a name/suggestion/message
|
|
775
|
-
if (/(?:name|suggestion|message|description):\s*['"]/.test(trimmed)) return true;
|
|
776
|
-
return false;
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
/**
|
|
780
|
-
* Load ignore rules from .thubanrc.json
|
|
781
|
-
*/
|
|
782
|
-
_loadIgnoreRules() {
|
|
783
|
-
const ignoreFiles = [];
|
|
784
|
-
try {
|
|
785
|
-
const rcPath = path.join(this.config.rootPath, '.thubanrc.json');
|
|
786
|
-
const rc = JSON.parse(fs.readFileSync(rcPath, 'utf-8'));
|
|
787
|
-
if (rc.hallucination?.ignore) {
|
|
788
|
-
ignoreFiles.push(...rc.hallucination.ignore);
|
|
789
|
-
}
|
|
790
|
-
if (rc.ignore) {
|
|
791
|
-
ignoreFiles.push(...rc.ignore);
|
|
792
|
-
}
|
|
793
|
-
} catch (e) { /* no config file */ }
|
|
794
|
-
return ignoreFiles;
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
/**
|
|
798
|
-
* Walk up directory tree from file location to project root,
|
|
799
|
-
* checking each node_modules directory for the package.
|
|
800
|
-
* This handles monorepos where deps are installed at workspace level.
|
|
801
|
-
*/
|
|
802
|
-
_findInNodeModules(filePath, packageName) {
|
|
803
|
-
let dir = path.dirname(filePath);
|
|
804
|
-
const root = this.config.rootPath;
|
|
805
|
-
|
|
806
|
-
// Walk up from file to root, checking each node_modules
|
|
807
|
-
while (dir.length >= root.length) {
|
|
808
|
-
const nmPath = path.join(dir, 'node_modules', packageName);
|
|
809
|
-
try {
|
|
810
|
-
if (fs.existsSync(nmPath)) return true;
|
|
811
|
-
} catch (e) { /* skip */ }
|
|
812
|
-
|
|
813
|
-
const parent = path.dirname(dir);
|
|
814
|
-
if (parent === dir) break; // reached filesystem root
|
|
815
|
-
dir = parent;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
return false;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
module.exports = HallucinationDetector;
|