@boyingliu01/xp-gate 0.8.1 → 0.8.4
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/adapters/java.sh +1 -1
- package/adapters/plugins/book299-20132-python/README.md +21 -0
- package/adapters/plugins/book299-20132-python/plugin.yml +21 -0
- package/adapters/plugins/book299-20132-python/rules/exception/gen-0023.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/logging/gen-0071.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0001.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0002.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0003.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0004.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0005.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0006.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0007.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0008.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0009.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0010.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0011.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0012.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0013.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0014.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0015.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0016.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0017.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0018.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0019.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0020.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0021.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0022.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0024.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0025.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0026.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0027.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0028.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0029.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0030.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0031.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0032.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0033.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0034.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0035.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0036.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0037.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0038.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0039.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0040.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0041.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0042.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0043.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0044.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0045.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0046.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0047.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0048.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0049.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0050.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0051.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0052.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0053.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0054.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0055.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0056.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0057.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0058.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0059.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0060.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0061.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0062.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0063.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0064.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0065.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0066.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0067.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0068.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0069.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0070.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0072.yml +14 -0
- package/adapters/plugins/book299-20132-python/rules/style/gen-0073.yml +14 -0
- package/adapters/plugins/book299-20132-python/scripts/install-gradle.sh +4 -0
- package/adapters/plugins/book299-20132-python/scripts/install-maven.sh +20 -0
- package/adapters/plugins/book299-4081-c/README.md +21 -0
- package/adapters/plugins/book299-4081-c/plugin.yml +21 -0
- package/adapters/plugins/book299-4081-c/rules/collection/c/345/273/272-5-12.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/collection/c/345/273/272-5-8.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/concurrency/c/350/247/204-4-19.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/concurrency/c/350/247/204-4-20.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/exception/c/350/247/204-4-11.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/exception/c/350/247/204-4-12.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/exception/c/350/247/204-4-6.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/exception/c/350/247/204-4-8.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/exception/c/350/247/204-4-9.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/performance/c/345/273/272-5-13.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/performance/c/345/273/272-5-6.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/performance/c/345/273/272-5-7.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/performance/c/350/247/204-4-14.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/performance/c/350/247/204-4-2.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/resource/c/345/273/272-4-2.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/security/c/350/247/204-4-13.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/216/237-1-1.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/216/237-1-2.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/216/237-1-3.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/216/237-1-4.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-2-1.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-2-2.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-2-3.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-2-4.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-1.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-2.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-3.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-4.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-5.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-6.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-7.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-8.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-4-1.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-4-3.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-1.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-10.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-11.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-2.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-3.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-4.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-5.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-9.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-1.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-10.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-11.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-12.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-13.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-14.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-16.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-17.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-18.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-19.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-2.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-20.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-3.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-4.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-5.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-6.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-7.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-8.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-9.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-1.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-10.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-11.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-12.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-13.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-14.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-15.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-16.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-17.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-18.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-19.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-2.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-20.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-21.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-22.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-3.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-4.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-5.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-6.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-7.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-8.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-9.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-1.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-10.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-15.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-16.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-17.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-18.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-3.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-4.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-5.yml +14 -0
- package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-7.yml +14 -0
- package/adapters/plugins/book299-4081-c/scripts/install-gradle.sh +4 -0
- package/adapters/plugins/book299-4081-c/scripts/install-maven.sh +20 -0
- package/adapters/plugins/book299-4083-javascriptes5/README.md +21 -0
- package/adapters/plugins/book299-4083-javascriptes5/plugin.yml +21 -0
- package/adapters/plugins/book299-4083-javascriptes5/rules/security/gen-0001.yml +14 -0
- package/adapters/plugins/book299-4083-javascriptes5/rules/security/gen-0002.yml +14 -0
- package/adapters/plugins/book299-4083-javascriptes5/rules/security/gen-0003.yml +14 -0
- package/adapters/plugins/book299-4083-javascriptes5/scripts/install-gradle.sh +4 -0
- package/adapters/plugins/book299-4083-javascriptes5/scripts/install-maven.sh +20 -0
- package/adapters/plugins/p3c-java/README.md +66 -0
- package/adapters/plugins/p3c-java/plugin.yml +30 -0
- package/adapters/plugins/p3c-java/scripts/install-gradle-p3c.sh +45 -0
- package/adapters/plugins/p3c-java/scripts/install-maven-p3c.sh +98 -0
- package/adapters/plugins/p3c-java/templates/gradle/xp-gate-p3c-gradle.gradle +68 -0
- package/adapters/plugins/p3c-java/templates/maven/xp-gate-p3c-profile.xml +81 -0
- package/adapters/plugins/whalecloud-java/README.md +98 -0
- package/adapters/plugins/whalecloud-java/plugin.yml +45 -0
- package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-001.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-002.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-003.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-004.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-005.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-006.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-007.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-008.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-009.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-010.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-011.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-012.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-001.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-002.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-003.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-004.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-005.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-006.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-007.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-008.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-009.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-010.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-011.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-012.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-013.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-014.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/exception/wc-except-001.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/exception/wc-except-002.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/exception/wc-except-003.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/exception/wc-except-004.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/exception/wc-except-005.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/exception/wc-except-006.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/exception/wc-except-007.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/exception/wc-except-008.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/exception/wc-except-009.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/exception/wc-except-010.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/exception/wc-except-011.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/logging/wc-log-001.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/logging/wc-log-002.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/logging/wc-log-003.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/logging/wc-log-004.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/logging/wc-log-005.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/logging/wc-log-006.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/logging/wc-log-007.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-001.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-002.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-003.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-004.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-005.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-006.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-007.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-008.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/resource/wc-reso-001.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/resource/wc-reso-002.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/resource/wc-reso-003.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/resource/wc-reso-004.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/resource/wc-reso-005.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/resource/wc-reso-006.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/security/wc-secu-001.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/security/wc-secu-002.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/security/wc-secu-003.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/security/wc-secu-004.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/security/wc-secu-005.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-001.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-002.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-003.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-004.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-005.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-006.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-007.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-008.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-009.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-010.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-011.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-012.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-013.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-014.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-015.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-016.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-017.yml +17 -0
- package/adapters/plugins/whalecloud-java/rules/style/wc-style-018.yml +17 -0
- package/adapters/plugins/whalecloud-java/scripts/install-gradle-whalecloud.sh +97 -0
- package/adapters/plugins/whalecloud-java/scripts/install-maven-whalecloud.sh +201 -0
- package/adapters/plugins/whalecloud-java/templates/gradle/xp-gate-whalecloud-gradle.gradle +73 -0
- package/adapters/plugins/whalecloud-java/templates/maven/xp-gate-whalecloud-profile.xml +148 -0
- package/bin/xp-gate.js +111 -129
- package/hooks/pre-commit +31 -27
- package/hooks/pre-push +7 -3
- package/lib/__tests__/baseline.test.js +123 -0
- package/lib/__tests__/migrate.test.js +20 -0
- package/lib/__tests__/ui-detector.test.ts +94 -0
- package/lib/__tests__/uninstall.test.js +36 -0
- package/lib/__tests__/update-skill.test.js +11 -0
- package/lib/baseline.js +392 -0
- package/lib/doctor.js +127 -141
- package/lib/gate-audit.ts +25 -8
- package/lib/init.js +57 -2
- package/lib/migrate.js +74 -73
- package/lib/ui-detector.ts +3 -3
- package/lib/uninstall.js +63 -31
- package/lib/update-skill.js +32 -34
- package/package.json +1 -1
- package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-code/skills/delphi-review/AGENTS.md +1 -1
- package/plugins/claude-code/skills/ralph-loop/SKILL.md +41 -3
- package/plugins/claude-code/skills/sprint-flow/AGENTS.md +1 -1
- package/plugins/claude-code/skills/sprint-flow/SKILL.md +178 -4
- package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +1 -1
- package/plugins/opencode/package.json +28 -4
- package/plugins/opencode/scripts/prepack.cjs +85 -0
- package/plugins/opencode/skills/delphi-review/AGENTS.md +1 -1
- package/plugins/opencode/skills/ralph-loop/SKILL.md +41 -3
- package/plugins/opencode/skills/sprint-flow/AGENTS.md +1 -1
- package/plugins/opencode/skills/sprint-flow/SKILL.md +178 -4
- package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +1 -1
- package/plugins/qoder/skills/delphi-review/AGENTS.md +1 -1
- package/plugins/qoder/skills/ralph-loop/SKILL.md +41 -3
- package/plugins/qoder/skills/sprint-flow/AGENTS.md +1 -1
- package/plugins/qoder/skills/sprint-flow/SKILL.md +147 -4
- package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +1 -1
- package/skills/delphi-review/AGENTS.md +1 -1
- package/skills/ralph-loop/SKILL.md +41 -3
- package/skills/sprint-flow/AGENTS.md +1 -1
- package/skills/sprint-flow/SKILL.md +178 -4
- package/skills/test-specification-alignment/AGENTS.md +1 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @test REQ-152 Baseline CLI handler
|
|
3
|
+
* @intent Verify baseline create/show/reset/diff commands
|
|
4
|
+
* @covers AC-152
|
|
5
|
+
*/
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const os = require('os');
|
|
9
|
+
|
|
10
|
+
const { handleBaseline, showBaseline } = require('../baseline.js');
|
|
11
|
+
|
|
12
|
+
describe('baseline.js - CLI handler', () => {
|
|
13
|
+
let tmpDir;
|
|
14
|
+
const originalCwd = process.cwd;
|
|
15
|
+
|
|
16
|
+
afterAll(() => {
|
|
17
|
+
process.cwd = originalCwd;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'baseline-cli-test-'));
|
|
22
|
+
process.cwd = () => tmpDir;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('handleBaseline - help', () => {
|
|
26
|
+
it('prints usage when no subcommand given', async () => {
|
|
27
|
+
const logs = [];
|
|
28
|
+
const origLog = console.log;
|
|
29
|
+
console.log = (...args) => logs.push(args.join(' '));
|
|
30
|
+
|
|
31
|
+
const code = await handleBaseline([]);
|
|
32
|
+
expect(code).toBe(0);
|
|
33
|
+
expect(logs.some(l => l.includes('Usage'))).toBe(true);
|
|
34
|
+
|
|
35
|
+
console.log = origLog;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('prints usage for --help', async () => {
|
|
39
|
+
const logs = [];
|
|
40
|
+
const origLog = console.log;
|
|
41
|
+
console.log = (...args) => logs.push(args.join(' '));
|
|
42
|
+
|
|
43
|
+
const code = await handleBaseline(['--help']);
|
|
44
|
+
expect(code).toBe(0);
|
|
45
|
+
expect(logs.some(l => l.includes('Usage'))).toBe(true);
|
|
46
|
+
|
|
47
|
+
console.log = origLog;
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('handleBaseline - unknown subcommand', () => {
|
|
52
|
+
it('returns error for unknown subcommand', async () => {
|
|
53
|
+
const logs = [];
|
|
54
|
+
const errs = [];
|
|
55
|
+
const origLog = console.log;
|
|
56
|
+
const origErr = console.error;
|
|
57
|
+
console.log = (...args) => logs.push(args.join(' '));
|
|
58
|
+
console.error = (...args) => errs.push(args.join(' '));
|
|
59
|
+
|
|
60
|
+
const code = await handleBaseline(['unknown-cmd']);
|
|
61
|
+
expect(code).toBe(1);
|
|
62
|
+
expect(errs.some(l => l.includes('Unknown baseline subcommand'))).toBe(true);
|
|
63
|
+
|
|
64
|
+
console.log = origLog;
|
|
65
|
+
console.error = origErr;
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('showBaseline - no baseline file', () => {
|
|
70
|
+
it('shows message when no baseline exists', () => {
|
|
71
|
+
const logs = [];
|
|
72
|
+
const origLog = console.log;
|
|
73
|
+
console.log = (...args) => logs.push(args.join(' '));
|
|
74
|
+
|
|
75
|
+
const code = showBaseline();
|
|
76
|
+
expect(code).toBe(1);
|
|
77
|
+
expect(logs.some(l => l.includes('No baseline'))).toBe(true);
|
|
78
|
+
|
|
79
|
+
console.log = origLog;
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('showBaseline - with baseline file', () => {
|
|
84
|
+
it('shows summary when baseline exists', () => {
|
|
85
|
+
const baselinePath = path.join(tmpDir, '.xp-gate', 'lint-baseline.json');
|
|
86
|
+
fs.mkdirSync(path.dirname(baselinePath), { recursive: true });
|
|
87
|
+
fs.writeFileSync(baselinePath, JSON.stringify({
|
|
88
|
+
'src/app.ts': {
|
|
89
|
+
eslint: { warnings: 3, errors: 1 },
|
|
90
|
+
totalWarnings: 3,
|
|
91
|
+
lastAnalyzed: '2026-06-01T12:00:00.000Z',
|
|
92
|
+
},
|
|
93
|
+
}));
|
|
94
|
+
|
|
95
|
+
const logs = [];
|
|
96
|
+
const origLog = console.log;
|
|
97
|
+
console.log = (...args) => logs.push(args.join(' '));
|
|
98
|
+
|
|
99
|
+
const code = showBaseline();
|
|
100
|
+
expect(code).toBe(0);
|
|
101
|
+
expect(logs.some(l => l.includes('3'))).toBe(true);
|
|
102
|
+
expect(logs.some(l => l.includes('ESLint'))).toBe(true);
|
|
103
|
+
|
|
104
|
+
console.log = origLog;
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('shows empty message for baseline with no entries', () => {
|
|
108
|
+
const baselinePath = path.join(tmpDir, '.xp-gate', 'lint-baseline.json');
|
|
109
|
+
fs.mkdirSync(path.dirname(baselinePath), { recursive: true });
|
|
110
|
+
fs.writeFileSync(baselinePath, '{}');
|
|
111
|
+
|
|
112
|
+
const logs = [];
|
|
113
|
+
const origLog = console.log;
|
|
114
|
+
console.log = (...args) => logs.push(args.join(' '));
|
|
115
|
+
|
|
116
|
+
const code = showBaseline();
|
|
117
|
+
expect(code).toBe(0);
|
|
118
|
+
expect(logs.some(l => l.includes('empty'))).toBe(true);
|
|
119
|
+
|
|
120
|
+
console.log = origLog;
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
|
@@ -193,6 +193,26 @@ describe('migrate', () => {
|
|
|
193
193
|
|
|
194
194
|
// === Print summary ===
|
|
195
195
|
|
|
196
|
+
// === Phase isolation: removing npmrc should not affect cache check ===
|
|
197
|
+
|
|
198
|
+
it('phases are isolated: npmrc cleanup and cache check operate independently', async () => {
|
|
199
|
+
// Only npmrc has github packages lines, no cache dir
|
|
200
|
+
fs.writeFileSync(npmrcPath(), [
|
|
201
|
+
'//npm.pkg.github.com/:_authToken=ghp_abc123',
|
|
202
|
+
'registry=https://registry.npmjs.org/'
|
|
203
|
+
].join('\n') + '\n');
|
|
204
|
+
|
|
205
|
+
const { migrate } = require('../migrate');
|
|
206
|
+
const result = await migrate([]);
|
|
207
|
+
|
|
208
|
+
expect(result).toBe(0);
|
|
209
|
+
// npmrc should be cleaned
|
|
210
|
+
const content = fs.readFileSync(npmrcPath(), 'utf8');
|
|
211
|
+
expect(content).not.toContain('npm.pkg.github.com');
|
|
212
|
+
// Should report no old cache (dir doesn't exist)
|
|
213
|
+
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('No old cache'));
|
|
214
|
+
});
|
|
215
|
+
|
|
196
216
|
it('prints full summary of actions taken', async () => {
|
|
197
217
|
fs.writeFileSync(npmrcPath(), [
|
|
198
218
|
'//npm.pkg.github.com/:_authToken=ghp_abc123',
|
|
@@ -357,4 +357,98 @@ describe('ui-detector', () => {
|
|
|
357
357
|
expect(isExcluded('src/Button.test.tsx', ['**/*.test.*'])).toBe(true);
|
|
358
358
|
});
|
|
359
359
|
});
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* @test #172 ui-detector CLI coverage
|
|
363
|
+
* @intent Cover CLI entry points (runCli, runPushMode, processOutput, runCheckBranch, runDefault)
|
|
364
|
+
* via real subprocess execution with NODE_V8_COVERAGE to merge coverage profiles.
|
|
365
|
+
* @covers ui-detector-cli-push-mode, ui-detector-cli-check-branch, ui-detector-cli-default-mode
|
|
366
|
+
*/
|
|
367
|
+
describe('CLI integration (subprocess)', () => {
|
|
368
|
+
const { spawnSync: realSpawnSync } = require('child_process') as typeof import('child_process');
|
|
369
|
+
const path = require('path') as typeof import('path');
|
|
370
|
+
const fs = require('fs') as typeof import('fs');
|
|
371
|
+
const os = require('os') as typeof import('os');
|
|
372
|
+
|
|
373
|
+
const UI_DETECTOR_PATH = path.resolve(__dirname, '../ui-detector.ts');
|
|
374
|
+
|
|
375
|
+
function runCli(args: string[], stdin?: string, cwd?: string): { code: number; stdout: string; stderr: string } {
|
|
376
|
+
const coverageDir = process.env.NODE_V8_COVERAGE ?? path.join(process.cwd(), 'coverage', '.tmp');
|
|
377
|
+
const result = realSpawnSync('npx', ['tsx', UI_DETECTOR_PATH, ...args], {
|
|
378
|
+
cwd: cwd ?? process.cwd(),
|
|
379
|
+
encoding: 'utf-8',
|
|
380
|
+
input: stdin,
|
|
381
|
+
env: { ...process.env, NODE_V8_COVERAGE: coverageDir },
|
|
382
|
+
});
|
|
383
|
+
return {
|
|
384
|
+
code: result.status ?? -1,
|
|
385
|
+
stdout: result.stdout ?? '',
|
|
386
|
+
stderr: result.stderr ?? '',
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
it('runs default mode with --check-branch flag (HEAD-based detection)', () => {
|
|
391
|
+
const { code, stdout } = runCli(['--check-branch']);
|
|
392
|
+
expect(code).toBeGreaterThanOrEqual(0);
|
|
393
|
+
expect(code).toBeLessThanOrEqual(1);
|
|
394
|
+
const parsed = JSON.parse(stdout);
|
|
395
|
+
expect(parsed).toHaveProperty('isUiSprint');
|
|
396
|
+
expect(parsed).toHaveProperty('matchedFiles');
|
|
397
|
+
expect(parsed).toHaveProperty('matchedRules');
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it('runs push-mode via stdin', () => {
|
|
401
|
+
const { code, stdout } = runCli(['--push-mode'], 'views/index.html');
|
|
402
|
+
expect([0, 1]).toContain(code);
|
|
403
|
+
const parsed = JSON.parse(stdout);
|
|
404
|
+
expect(parsed.isUiSprint).toBe(true);
|
|
405
|
+
expect(parsed.matchedFiles).toContain('views/index.html');
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it('runs push-mode with stdin input', () => {
|
|
409
|
+
const { code, stdout } = runCli(['--push-mode'], 'views/login.njk\nsrc/auth.ts\n');
|
|
410
|
+
expect([0, 1]).toContain(code);
|
|
411
|
+
const parsed = JSON.parse(stdout);
|
|
412
|
+
expect(parsed.isUiSprint).toBe(true);
|
|
413
|
+
expect(parsed.matchedFiles).toContain('views/login.njk');
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it('runs push-mode with non-UI files (exit 1)', () => {
|
|
417
|
+
const { code, stdout } = runCli(['--push-mode'], 'src/auth.ts\nsrc/db.ts\n');
|
|
418
|
+
expect(code).toBe(1);
|
|
419
|
+
const parsed = JSON.parse(stdout);
|
|
420
|
+
expect(parsed.isUiSprint).toBe(false);
|
|
421
|
+
expect(parsed.matchedFiles).toEqual([]);
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
it('respects .ui-gate-ignore in push-mode', () => {
|
|
425
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'ui-detector-ignore-'));
|
|
426
|
+
try {
|
|
427
|
+
fs.writeFileSync(path.join(tmp, '.ui-gate-ignore'), 'legacy/**\n');
|
|
428
|
+
const { code, stdout } = runCli(['--push-mode'], 'legacy/views/index.html', tmp);
|
|
429
|
+
expect(code).toBe(1);
|
|
430
|
+
const parsed = JSON.parse(stdout);
|
|
431
|
+
expect(parsed.isUiSprint).toBe(false);
|
|
432
|
+
} finally {
|
|
433
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it('processes renamed files in push-mode', () => {
|
|
438
|
+
const { code, stdout } = runCli(['--push-mode'], 'src/a.tsx \u2192 src/components/B.tsx');
|
|
439
|
+
expect([0, 1]).toContain(code);
|
|
440
|
+
const parsed = JSON.parse(stdout);
|
|
441
|
+
expect(parsed.matchedFiles).toContain('src/components/B.tsx');
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
it('runs default mode (detectUiSprint in current repo)', () => {
|
|
445
|
+
const { code, stdout } = runCli([]);
|
|
446
|
+
expect([0, 1]).toContain(code);
|
|
447
|
+
const parsed = JSON.parse(stdout);
|
|
448
|
+
expect(parsed).toHaveProperty('isUiSprint');
|
|
449
|
+
expect(parsed).toHaveProperty('matchedFiles');
|
|
450
|
+
expect(parsed).toHaveProperty('matchedRules');
|
|
451
|
+
});
|
|
452
|
+
});
|
|
360
453
|
});
|
|
454
|
+
|
|
@@ -577,6 +577,42 @@ describe('uninstall', () => {
|
|
|
577
577
|
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('adapter-common.sh'));
|
|
578
578
|
});
|
|
579
579
|
|
|
580
|
+
// === Execution loop: mixed item types plan ===
|
|
581
|
+
|
|
582
|
+
it('executes mixed-type plan (file + dir + gitconfig items) correctly', async () => {
|
|
583
|
+
setupGlobalInstall();
|
|
584
|
+
const expectedHooksPath = globalHooksDir();
|
|
585
|
+
mockExecGlobalHooksPath(expectedHooksPath);
|
|
586
|
+
const { uninstall } = require('../uninstall');
|
|
587
|
+
|
|
588
|
+
const result = await uninstall([]);
|
|
589
|
+
|
|
590
|
+
expect(result).toBe(0);
|
|
591
|
+
|
|
592
|
+
// Gitconfig type unset core.hooksPath
|
|
593
|
+
expect(execSpy).toHaveBeenCalledWith(
|
|
594
|
+
expect.stringContaining('git config --global --unset core.hooksPath'),
|
|
595
|
+
expect.any(Object)
|
|
596
|
+
);
|
|
597
|
+
// Dir items removed: global hooks, adapters, template
|
|
598
|
+
expect(fs.existsSync(globalHooksDir())).toBe(false);
|
|
599
|
+
expect(fs.existsSync(globalAdaptersDir())).toBe(false);
|
|
600
|
+
expect(fs.existsSync(templateDir())).toBe(false);
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
it('skips non-existent file items in execution loop gracefully', async () => {
|
|
604
|
+
setupLocalInstall();
|
|
605
|
+
// Delete one file before uninstall
|
|
606
|
+
fs.unlinkSync(path.join(projectHooksDir(), 'pre-commit'));
|
|
607
|
+
mockExecSuccess();
|
|
608
|
+
const { uninstall } = require('../uninstall');
|
|
609
|
+
|
|
610
|
+
const result = await uninstall([]);
|
|
611
|
+
expect(result).toBe(0);
|
|
612
|
+
// Should not crash — remaining items still processed
|
|
613
|
+
expect(fs.existsSync(path.join(projectHooksDir(), 'pre-push'))).toBe(false);
|
|
614
|
+
});
|
|
615
|
+
|
|
580
616
|
it('saves rollback snapshot before destructive operations', async () => {
|
|
581
617
|
setupLocalInstall();
|
|
582
618
|
mockExecSuccess();
|
|
@@ -263,6 +263,17 @@ describe('update-skill', () => {
|
|
|
263
263
|
expect(errorSpy).toHaveBeenCalledWith('Error: foo is not installed');
|
|
264
264
|
});
|
|
265
265
|
|
|
266
|
+
// === Mode handler isolation: check/all/single operate independently ===
|
|
267
|
+
|
|
268
|
+
it('check and all modes handle empty config without crashing (edge cases)', async () => {
|
|
269
|
+
// No config file at all — getConfig returns {}
|
|
270
|
+
const { updateSkill } = require('../update-skill');
|
|
271
|
+
expect(await updateSkill(null, { check: true })).toBe(0);
|
|
272
|
+
expect(await updateSkill(null, { all: true })).toBe(0);
|
|
273
|
+
expect(await updateSkill('anything')).toBe(1);
|
|
274
|
+
expect(errorSpy).toHaveBeenCalledWith('Error: anything is not installed');
|
|
275
|
+
});
|
|
276
|
+
|
|
266
277
|
it('getConfig parses valid config (single-name path succeeds)', async () => {
|
|
267
278
|
writeConfig({ foo: { version: '1.0.0' } });
|
|
268
279
|
const { updateSkill } = require('../update-skill');
|
package/lib/baseline.js
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* baseline.js — `xp-gate baseline` CLI handler
|
|
3
|
+
*
|
|
4
|
+
* Manages per-project lint baselines stored in .xp-gate/lint-baseline.json.
|
|
5
|
+
*
|
|
6
|
+
* Commands:
|
|
7
|
+
* xp-gate baseline create — Full-repo scan → save baseline
|
|
8
|
+
* xp-gate baseline show — Display current baseline
|
|
9
|
+
* xp-gate baseline reset — Force re-scan and replace baseline
|
|
10
|
+
* xp-gate baseline diff — Diff current state against stored baseline
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const { execSync } = require('child_process');
|
|
16
|
+
|
|
17
|
+
function getXpGateDir() {
|
|
18
|
+
return path.join(process.cwd(), '.xp-gate');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getBaselineFile() {
|
|
22
|
+
return path.join(getXpGateDir(), 'lint-baseline.json');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function ensureDir(dirPath) {
|
|
26
|
+
if (!fs.existsSync(dirPath)) {
|
|
27
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function parseArgs(subargs) {
|
|
32
|
+
return {
|
|
33
|
+
tool: subargs[0] || null,
|
|
34
|
+
rest: subargs.slice(1),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Run a lint tool and return its JSON output.
|
|
40
|
+
*/
|
|
41
|
+
function runToolJson(toolCmd, pipeToJsonFlag) {
|
|
42
|
+
try {
|
|
43
|
+
const cmd = `${toolCmd} ${pipeToJsonFlag}`;
|
|
44
|
+
return execSync(cmd, { encoding: 'utf8', maxBuffer: 10 * 1024 * 1024 }).trim();
|
|
45
|
+
} catch (e) {
|
|
46
|
+
// Lint tools exit non-zero when they find issues - that's expected
|
|
47
|
+
if (e.stdout) return e.stdout.trim();
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Collect all source files for a given language.
|
|
54
|
+
*/
|
|
55
|
+
function findFilesByExt(extensions) {
|
|
56
|
+
try {
|
|
57
|
+
const patterns = extensions.map(e => `"**/*${e}"`).join(' ');
|
|
58
|
+
const result = execSync(`git ls-files ${patterns}`, {
|
|
59
|
+
encoding: 'utf8',
|
|
60
|
+
maxBuffer: 5 * 1024 * 1024,
|
|
61
|
+
}).trim();
|
|
62
|
+
return result ? result.split('\n') : [];
|
|
63
|
+
} catch {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Create baseline: scan all source files with available lint tools.
|
|
70
|
+
* Called by: xp-gate baseline create|reset
|
|
71
|
+
*/
|
|
72
|
+
async function createBaseline() {
|
|
73
|
+
ensureDir(getXpGateDir());
|
|
74
|
+
|
|
75
|
+
const baseline = {};
|
|
76
|
+
|
|
77
|
+
// TypeScript/JavaScript — ESLint
|
|
78
|
+
const tsFiles = findFilesByExt(['.ts', '.tsx', '.js', '.jsx']);
|
|
79
|
+
if (tsFiles.length > 0) {
|
|
80
|
+
try {
|
|
81
|
+
const eslintConfigExists = fs.existsSync('.eslintrc.json') ||
|
|
82
|
+
fs.existsSync('.eslintrc.js') ||
|
|
83
|
+
fs.existsSync('.eslintrc.cjs') ||
|
|
84
|
+
fs.existsSync('eslint.config.js');
|
|
85
|
+
const eslintBin = fs.existsSync('node_modules/.bin/eslint') ? 'node_modules/.bin/eslint' : null;
|
|
86
|
+
|
|
87
|
+
if (eslintConfigExists && (eslintBin || execSync('npx eslint --version', { encoding: 'utf8' }))) {
|
|
88
|
+
const eslintCmd = eslintBin || 'npx eslint';
|
|
89
|
+
const output = runToolJson(`${eslintCmd} ${tsFiles.join(' ')}`, '-f json --no-warn-ignored');
|
|
90
|
+
if (output && output !== '[]') {
|
|
91
|
+
const parsed = JSON.parse(output);
|
|
92
|
+
for (const fileResult of parsed) {
|
|
93
|
+
const relativePath = fileResult.filePath;
|
|
94
|
+
const fileName = tsFiles.find(f => relativePath.endsWith(f));
|
|
95
|
+
if (!fileName) continue;
|
|
96
|
+
|
|
97
|
+
baseline[fileName] = {
|
|
98
|
+
eslint: {
|
|
99
|
+
warnings: fileResult.warningCount || 0,
|
|
100
|
+
errors: fileResult.errorCount || 0,
|
|
101
|
+
},
|
|
102
|
+
totalWarnings: fileResult.warningCount || 0,
|
|
103
|
+
lastAnalyzed: new Date().toISOString(),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
} catch {
|
|
109
|
+
// ESLint unavailable — skip
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Python — ruff
|
|
114
|
+
const pyFiles = findFilesByExt(['.py']);
|
|
115
|
+
if (pyFiles.length > 0) {
|
|
116
|
+
try {
|
|
117
|
+
execSync('ruff --version', { encoding: 'utf8' });
|
|
118
|
+
const output = runToolJson(`ruff check ${pyFiles.join(' ')}`, '--output-format json');
|
|
119
|
+
if (output && output !== '[]') {
|
|
120
|
+
const parsed = JSON.parse(output);
|
|
121
|
+
for (const fileResult of parsed) {
|
|
122
|
+
if (!baseline[fileResult.file]) {
|
|
123
|
+
const messages = fileResult.messages || [];
|
|
124
|
+
baseline[fileResult.file] = {
|
|
125
|
+
ruff: { warnings: messages.length, errors: 0 },
|
|
126
|
+
totalWarnings: messages.length,
|
|
127
|
+
lastAnalyzed: new Date().toISOString(),
|
|
128
|
+
};
|
|
129
|
+
} else {
|
|
130
|
+
const messages = fileResult.messages || [];
|
|
131
|
+
baseline[fileResult.file].ruff = { warnings: messages.length, errors: 0 };
|
|
132
|
+
baseline[fileResult.file].totalWarnings += messages.length;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} catch {
|
|
137
|
+
// Ruff unavailable — skip
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Go — golangci-lint
|
|
142
|
+
const goFiles = findFilesByExt(['.go']);
|
|
143
|
+
if (goFiles.length > 0) {
|
|
144
|
+
try {
|
|
145
|
+
execSync('golangci-lint --version', { encoding: 'utf8' });
|
|
146
|
+
const output = runToolJson('golangci-lint run', '--out-format json');
|
|
147
|
+
if (output) {
|
|
148
|
+
const parsed = JSON.parse(output).Issues || [];
|
|
149
|
+
const warningsByFile = {};
|
|
150
|
+
for (const issue of parsed) {
|
|
151
|
+
const matchedFile = goFiles.find(f => issue.file.endsWith(f));
|
|
152
|
+
if (!matchedFile) continue;
|
|
153
|
+
if (!warningsByFile[matchedFile]) {
|
|
154
|
+
warningsByFile[matchedFile] = { warnings: 0, errors: 0 };
|
|
155
|
+
}
|
|
156
|
+
if (issue.severity === 'error') {
|
|
157
|
+
warningsByFile[matchedFile].errors++;
|
|
158
|
+
} else {
|
|
159
|
+
warningsByFile[matchedFile].warnings++;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
for (const [file, counts] of Object.entries(warningsByFile)) {
|
|
163
|
+
if (baseline[file]) {
|
|
164
|
+
baseline[file].golangci = counts;
|
|
165
|
+
baseline[file].totalWarnings += counts.warnings;
|
|
166
|
+
} else {
|
|
167
|
+
baseline[file] = {
|
|
168
|
+
golangci: counts,
|
|
169
|
+
totalWarnings: counts.warnings,
|
|
170
|
+
lastAnalyzed: new Date().toISOString(),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
} catch {
|
|
176
|
+
// golangci-lint unavailable — skip
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Shell — shellcheck
|
|
181
|
+
const shFiles = findFilesByExt(['.sh']);
|
|
182
|
+
if (shFiles.length > 0) {
|
|
183
|
+
try {
|
|
184
|
+
execSync('shellcheck --version', { encoding: 'utf8' });
|
|
185
|
+
const output = runToolJson(`shellcheck -f json ${shFiles.join(' ')}`, '');
|
|
186
|
+
if (output && output !== '[]') {
|
|
187
|
+
const parsed = JSON.parse(output);
|
|
188
|
+
const warningsByFile = {};
|
|
189
|
+
for (const item of parsed) {
|
|
190
|
+
const matchedFile = shFiles.find(f => item.file.endsWith(f));
|
|
191
|
+
if (!matchedFile) continue;
|
|
192
|
+
if (!warningsByFile[matchedFile]) {
|
|
193
|
+
warningsByFile[matchedFile] = { warnings: 0, errors: 0 };
|
|
194
|
+
}
|
|
195
|
+
if (item.level === 'error') {
|
|
196
|
+
warningsByFile[matchedFile].errors++;
|
|
197
|
+
} else {
|
|
198
|
+
warningsByFile[matchedFile].warnings++;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
for (const [file, counts] of Object.entries(warningsByFile)) {
|
|
202
|
+
if (baseline[file]) {
|
|
203
|
+
baseline[file].shellcheck = counts;
|
|
204
|
+
baseline[file].totalWarnings += counts.warnings;
|
|
205
|
+
} else {
|
|
206
|
+
baseline[file] = {
|
|
207
|
+
shellcheck: counts,
|
|
208
|
+
totalWarnings: counts.warnings,
|
|
209
|
+
lastAnalyzed: new Date().toISOString(),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
} catch {
|
|
215
|
+
// shellcheck unavailable — skip
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
fs.writeFileSync(getBaselineFile(), JSON.stringify(baseline, null, 2));
|
|
220
|
+
return baseline;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Show current baseline.
|
|
225
|
+
*/
|
|
226
|
+
function showBaseline() {
|
|
227
|
+
if (!fs.existsSync(getBaselineFile())) {
|
|
228
|
+
console.log('No baseline found. Run `xp-gate baseline create` to initialize.');
|
|
229
|
+
return 1;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const data = JSON.parse(fs.readFileSync(getBaselineFile(), 'utf8'));
|
|
233
|
+
const files = Object.keys(data);
|
|
234
|
+
|
|
235
|
+
if (files.length === 0) {
|
|
236
|
+
console.log('Baseline is empty (no lint issues found on last scan).');
|
|
237
|
+
return 0;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const totalWarnings = files.reduce((s, f) => s + data[f].totalWarnings, 0);
|
|
241
|
+
let eslintCount = 0;
|
|
242
|
+
let ruffCount = 0;
|
|
243
|
+
let golangciCount = 0;
|
|
244
|
+
let shellcheckCount = 0;
|
|
245
|
+
|
|
246
|
+
for (const entry of Object.values(data)) {
|
|
247
|
+
if (entry.eslint) eslintCount++;
|
|
248
|
+
if (entry.ruff) ruffCount++;
|
|
249
|
+
if (entry.golangci) golangciCount++;
|
|
250
|
+
if (entry.shellcheck) shellcheckCount++;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
console.log('Lint Baseline:');
|
|
254
|
+
console.log(` Created: ${data[files[0]]?.lastAnalyzed?.slice(0, 10) || 'N/A'}`);
|
|
255
|
+
console.log(` Files tracked: ${files.length}`);
|
|
256
|
+
console.log(` Total warnings: ${totalWarnings}`);
|
|
257
|
+
if (eslintCount > 0) console.log(` ESLint: ${eslintCount} files`);
|
|
258
|
+
if (ruffCount > 0) console.log(` Ruff: ${ruffCount} files`);
|
|
259
|
+
if (golangciCount > 0) console.log(` golangci-lint: ${golangciCount} files`);
|
|
260
|
+
if (shellcheckCount > 0) console.log(` ShellCheck: ${shellcheckCount} files`);
|
|
261
|
+
|
|
262
|
+
return 0;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Reset baseline: force re-scan and replace.
|
|
267
|
+
*/
|
|
268
|
+
async function resetBaseline() {
|
|
269
|
+
const baseline = await createBaseline();
|
|
270
|
+
console.log(`Baseline reset. ${Object.keys(baseline).length} files tracked.`);
|
|
271
|
+
return 0;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Diff current lint state against stored baseline.
|
|
276
|
+
*/
|
|
277
|
+
async function diffBaseline() {
|
|
278
|
+
if (!fs.existsSync(getBaselineFile())) {
|
|
279
|
+
console.log('No baseline found. Run `xp-gate baseline create` first.');
|
|
280
|
+
return 1;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const oldBaseline = JSON.parse(fs.readFileSync(getBaselineFile(), 'utf8'));
|
|
284
|
+
const currentBaseline = await createBaseline();
|
|
285
|
+
|
|
286
|
+
const allFiles = new Set([
|
|
287
|
+
...Object.keys(oldBaseline),
|
|
288
|
+
...Object.keys(currentBaseline),
|
|
289
|
+
]);
|
|
290
|
+
|
|
291
|
+
let totalWarningsDelta = 0;
|
|
292
|
+
const increased = [];
|
|
293
|
+
const decreased = [];
|
|
294
|
+
const added = [];
|
|
295
|
+
const removed = [];
|
|
296
|
+
|
|
297
|
+
for (const file of allFiles) {
|
|
298
|
+
const oldW = oldBaseline[file]?.totalWarnings || 0;
|
|
299
|
+
const newW = currentBaseline[file]?.totalWarnings || 0;
|
|
300
|
+
const delta = newW - oldW;
|
|
301
|
+
|
|
302
|
+
totalWarningsDelta += delta;
|
|
303
|
+
|
|
304
|
+
if (!oldBaseline[file] && currentBaseline[file]) {
|
|
305
|
+
added.push(` + ${file} (${newW} warnings)`);
|
|
306
|
+
} else if (oldBaseline[file] && !currentBaseline[file]) {
|
|
307
|
+
removed.push(` - ${file} (all ${oldW} warnings cleared)`);
|
|
308
|
+
} else if (delta > 0) {
|
|
309
|
+
increased.push(` ↑ ${file} (${oldW} → ${newW}, +${delta})`);
|
|
310
|
+
} else if (delta < 0) {
|
|
311
|
+
decreased.push(` ↓ ${file} (${oldW} → ${newW}, ${delta})`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
console.log('Lint Baseline Diff:');
|
|
316
|
+
console.log(` Total warnings delta: ${totalWarningsDelta >= 0 ? '+' : ''}${totalWarningsDelta}`);
|
|
317
|
+
|
|
318
|
+
if (added.length > 0) {
|
|
319
|
+
console.log(`\nFiles added (${added.length}):`);
|
|
320
|
+
added.forEach(l => console.log(l));
|
|
321
|
+
}
|
|
322
|
+
if (removed.length > 0) {
|
|
323
|
+
console.log(`\nFiles removed (${removed.length}):`);
|
|
324
|
+
removed.forEach(l => console.log(l));
|
|
325
|
+
}
|
|
326
|
+
if (increased.length > 0) {
|
|
327
|
+
console.log(`\nWarnings increased (${increased.length}):`);
|
|
328
|
+
increased.forEach(l => console.log(l));
|
|
329
|
+
}
|
|
330
|
+
if (decreased.length > 0) {
|
|
331
|
+
console.log(`\nWarnings decreased (${decreased.length}):`);
|
|
332
|
+
decreased.forEach(l => console.log(l));
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (added.length === 0 && removed.length === 0 && increased.length === 0 && decreased.length === 0) {
|
|
336
|
+
console.log(' No change from baseline.');
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return totalWarningsDelta > 0 ? 1 : 0;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Main handler called from xp-gate CLI.
|
|
344
|
+
* @param {string[]} subargs CLI sub-arguments
|
|
345
|
+
* @returns {Promise<number>} exit code
|
|
346
|
+
*/
|
|
347
|
+
async function handleBaseline(subargs) {
|
|
348
|
+
const { tool, rest } = parseArgs(subargs);
|
|
349
|
+
|
|
350
|
+
switch (tool) {
|
|
351
|
+
case 'create':
|
|
352
|
+
console.log('Creating lint baseline...');
|
|
353
|
+
const created = await createBaseline();
|
|
354
|
+
console.log(`✅ Baseline created — ${Object.keys(created).length} files tracked.`);
|
|
355
|
+
return 0;
|
|
356
|
+
|
|
357
|
+
case 'show':
|
|
358
|
+
return showBaseline();
|
|
359
|
+
|
|
360
|
+
case 'reset':
|
|
361
|
+
console.log('Resetting lint baseline...');
|
|
362
|
+
return resetBaseline();
|
|
363
|
+
|
|
364
|
+
case 'diff':
|
|
365
|
+
return diffBaseline();
|
|
366
|
+
|
|
367
|
+
case 'help':
|
|
368
|
+
case '--help':
|
|
369
|
+
case null:
|
|
370
|
+
console.log(`Usage: xp-gate baseline <subcommand>
|
|
371
|
+
|
|
372
|
+
Subcommands:
|
|
373
|
+
create Scan all source files and save lint baseline
|
|
374
|
+
show Display current lint baseline summary
|
|
375
|
+
reset Force re-scan and replace baseline
|
|
376
|
+
diff Compare current lint state against baseline
|
|
377
|
+
|
|
378
|
+
Examples:
|
|
379
|
+
xp-gate baseline create
|
|
380
|
+
xp-gate baseline show
|
|
381
|
+
xp-gate baseline reset
|
|
382
|
+
xp-gate baseline diff`);
|
|
383
|
+
return 0;
|
|
384
|
+
|
|
385
|
+
default:
|
|
386
|
+
console.error(`Unknown baseline subcommand: ${tool}`);
|
|
387
|
+
console.error('Run `xp-gate baseline --help` for usage.');
|
|
388
|
+
return 1;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
module.exports = { handleBaseline, createBaseline, showBaseline, resetBaseline, diffBaseline };
|