@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
package/lib/ui-detector.ts
CHANGED
|
@@ -210,21 +210,21 @@ function processOutput(input: string, repoRoot: string): void {
|
|
|
210
210
|
.map(parseRenamedFile)
|
|
211
211
|
.filter((f) => f.length > 0);
|
|
212
212
|
const result = collectUiMatches(files, repoRoot);
|
|
213
|
-
|
|
213
|
+
|
|
214
214
|
console.log(JSON.stringify(result, null, 2));
|
|
215
215
|
process.exit(result.isUiSprint ? 0 : 1);
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
function runCheckBranch(_repoRoot: string): void {
|
|
219
219
|
const result = detectUiSprint('HEAD');
|
|
220
|
-
|
|
220
|
+
|
|
221
221
|
console.log(JSON.stringify(result, null, 2));
|
|
222
222
|
process.exit(result.isUiSprint ? 0 : 1);
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
function runDefault(_repoRoot: string): void {
|
|
226
226
|
const result = detectUiSprint();
|
|
227
|
-
|
|
227
|
+
|
|
228
228
|
console.log(JSON.stringify(result, null, 2));
|
|
229
229
|
process.exit(result.isUiSprint ? 0 : 1);
|
|
230
230
|
}
|
package/lib/uninstall.js
CHANGED
|
@@ -260,6 +260,68 @@ function buildPlan(mode) {
|
|
|
260
260
|
return plan;
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
+
/**
|
|
264
|
+
* Remove a single file item with ownership verification.
|
|
265
|
+
* @returns {boolean} true on success, false on skip (not xp-gate owned)
|
|
266
|
+
*/
|
|
267
|
+
function removeFile(item, config) {
|
|
268
|
+
const manifestEntry = config.manifest && config.manifest.files
|
|
269
|
+
? config.manifest.files[item.manifestKey]
|
|
270
|
+
: null;
|
|
271
|
+
|
|
272
|
+
if (!verifyFileOwnership(item.path, manifestEntry, item.signature)) {
|
|
273
|
+
if (fs.existsSync(item.path)) {
|
|
274
|
+
console.warn(` Warning: ${item.label} does not contain xp-gate signature — skipping`);
|
|
275
|
+
}
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
fs.unlinkSync(item.path);
|
|
280
|
+
console.log(` Removed ${item.label}`);
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Remove a directory item.
|
|
286
|
+
* @returns {boolean} true if dir existed and was removed, false otherwise
|
|
287
|
+
*/
|
|
288
|
+
function removeDir(item) {
|
|
289
|
+
if (!fs.existsSync(item.path)) return false;
|
|
290
|
+
fs.rmSync(item.path, { recursive: true, force: true });
|
|
291
|
+
console.log(` Removed ${item.label}`);
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Unset core.hooksPath if it matches the expected xp-gate path.
|
|
297
|
+
* @returns {boolean} true if unset was performed or already unset, false on mismatch
|
|
298
|
+
*/
|
|
299
|
+
function unsetGitConfigIfMatch(item) {
|
|
300
|
+
const currentPath = getCurrentHooksPath();
|
|
301
|
+
if (currentPath === null || currentPath === '') {
|
|
302
|
+
console.log(` ${item.label} — not set`);
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
if (currentPath === item.expectedPath) {
|
|
306
|
+
unsetHooksPath();
|
|
307
|
+
console.log(` Unset ${item.label}`);
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
console.warn(` Warning: core.hooksPath (${currentPath}) does not match xp-gate path — skipping unset`);
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Execute a single plan item (file/dir/gitconfig).
|
|
316
|
+
* @returns {boolean} true on success, false on skip/failure
|
|
317
|
+
*/
|
|
318
|
+
function executePlanItem(item, config) {
|
|
319
|
+
if (item.type === 'file') return removeFile(item, config);
|
|
320
|
+
if (item.type === 'dir') return removeDir(item);
|
|
321
|
+
if (item.type === 'gitconfig' && item.action === 'unset-hooks-path') return unsetGitConfigIfMatch(item);
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
|
|
263
325
|
/**
|
|
264
326
|
* @param {string[]} args CLI arguments
|
|
265
327
|
* @returns {number} exit code (0 = success, 1 = error)
|
|
@@ -337,37 +399,7 @@ async function uninstall(args) {
|
|
|
337
399
|
|
|
338
400
|
for (const item of plan) {
|
|
339
401
|
try {
|
|
340
|
-
|
|
341
|
-
const manifestEntry = config.manifest && config.manifest.files
|
|
342
|
-
? config.manifest.files[item.manifestKey]
|
|
343
|
-
: null;
|
|
344
|
-
|
|
345
|
-
if (!verifyFileOwnership(item.path, manifestEntry, item.signature)) {
|
|
346
|
-
if (fs.existsSync(item.path)) {
|
|
347
|
-
console.warn(` Warning: ${item.label} does not contain xp-gate signature — skipping`);
|
|
348
|
-
}
|
|
349
|
-
continue;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
fs.unlinkSync(item.path);
|
|
353
|
-
console.log(` Removed ${item.label}`);
|
|
354
|
-
} else if (item.type === 'dir') {
|
|
355
|
-
if (fs.existsSync(item.path)) {
|
|
356
|
-
fs.rmSync(item.path, { recursive: true, force: true });
|
|
357
|
-
console.log(` Removed ${item.label}`);
|
|
358
|
-
}
|
|
359
|
-
} else if (item.type === 'gitconfig' && item.action === 'unset-hooks-path') {
|
|
360
|
-
const currentPath = getCurrentHooksPath();
|
|
361
|
-
if (currentPath === null || currentPath === '') {
|
|
362
|
-
// Already unset
|
|
363
|
-
console.log(` ${item.label} — not set`);
|
|
364
|
-
} else if (currentPath === item.expectedPath) {
|
|
365
|
-
unsetHooksPath();
|
|
366
|
-
console.log(` Unset ${item.label}`);
|
|
367
|
-
} else {
|
|
368
|
-
console.warn(` Warning: core.hooksPath (${currentPath}) does not match xp-gate path — skipping unset`);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
402
|
+
hadErrors = !executePlanItem(item, config) || hadErrors;
|
|
371
403
|
} catch (e) {
|
|
372
404
|
console.warn(` Warning: Could not remove ${item.label}: ${e.message}`);
|
|
373
405
|
hadErrors = true;
|
package/lib/update-skill.js
CHANGED
|
@@ -8,57 +8,55 @@ const HOME = process.env.HOME || process.env.USERPROFILE || os.homedir();
|
|
|
8
8
|
const CONFIG_DIR = path.join(HOME, '.config', 'xp-gate');
|
|
9
9
|
const SKILLS_DIR = path.join(HOME, '.config', 'opencode', 'skills');
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const skills = config.installedSkills || {};
|
|
18
|
-
|
|
19
|
-
for (const [skillName, info] of Object.entries(skills)) {
|
|
20
|
-
console.log(` ${skillName}: ${info.version || 'unknown'}`);
|
|
21
|
-
}
|
|
22
|
-
console.log('Update check complete');
|
|
23
|
-
return 0;
|
|
11
|
+
function handleCheckMode() {
|
|
12
|
+
console.log('Checking for updates...');
|
|
13
|
+
const config = getConfig();
|
|
14
|
+
const skills = config.installedSkills || {};
|
|
15
|
+
for (const [skillName, info] of Object.entries(skills)) {
|
|
16
|
+
console.log(` ${skillName}: ${info.version || 'unknown'}`);
|
|
24
17
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
18
|
+
console.log('Update check complete');
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function handleAllMode(verbose) {
|
|
23
|
+
const config = getConfig();
|
|
24
|
+
const skills = config.installedSkills || {};
|
|
25
|
+
console.log('Updating all skills...');
|
|
26
|
+
let hasErrors = false;
|
|
27
|
+
for (const skillName of Object.keys(skills)) {
|
|
28
|
+
try {
|
|
29
|
+
await updateSingleSkill(skillName, verbose);
|
|
30
|
+
} catch (err) {
|
|
31
|
+
console.error(`Failed to update ${skillName}: ${err.message}`);
|
|
32
|
+
hasErrors = true;
|
|
40
33
|
}
|
|
41
|
-
|
|
42
|
-
return hasErrors ? 1 : 0;
|
|
43
34
|
}
|
|
44
|
-
|
|
35
|
+
return hasErrors ? 1 : 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function handleSingleMode(name, verbose) {
|
|
45
39
|
if (!name) {
|
|
46
40
|
console.error('Error: Skill name required');
|
|
47
41
|
console.error('Usage: xp-gate update-skill <name> or --all');
|
|
48
42
|
return 1;
|
|
49
43
|
}
|
|
50
|
-
|
|
51
44
|
const config = getConfig();
|
|
52
45
|
const skills = config.installedSkills || {};
|
|
53
|
-
|
|
54
46
|
if (!skills[name]) {
|
|
55
47
|
console.error(`Error: ${name} is not installed`);
|
|
56
48
|
return 1;
|
|
57
49
|
}
|
|
58
|
-
|
|
59
50
|
return updateSingleSkill(name, verbose);
|
|
60
51
|
}
|
|
61
52
|
|
|
53
|
+
async function updateSkill(name, options = {}) {
|
|
54
|
+
const { all = false, check = false, verbose = false } = options;
|
|
55
|
+
if (check) return handleCheckMode();
|
|
56
|
+
if (all) return handleAllMode(verbose);
|
|
57
|
+
return handleSingleMode(name, verbose);
|
|
58
|
+
}
|
|
59
|
+
|
|
62
60
|
async function updateSingleSkill(name, verbose) {
|
|
63
61
|
console.log(`Updating ${name}...`);
|
|
64
62
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xp-gate",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.4",
|
|
4
4
|
"displayName": "XP-Gate",
|
|
5
5
|
"description": "Extreme Programming quality gates + AI workflow skills for Claude Code. Includes 6 quality gates, Sprint Flow, and Delphi multi-expert review.",
|
|
6
6
|
"author": {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
**Generated:** 2026-05-30
|
|
4
4
|
**Commit:** 4517f2b
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** v0.
|
|
6
|
+
**Version:** v0.8.1
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Delphi Consensus Review — multi-round anonymous expert review (≥91% threshold, 3 experts from ≥2 providers, domestic models only). Supports design + code-walkthrough modes.
|
|
@@ -323,6 +323,16 @@ Phase 0, 1, 3-6 行为完全不变。
|
|
|
323
323
|
- 注入:当前 REQ + AC + permanent learnings + contextual learnings (最近 3 条)
|
|
324
324
|
- 注入:AGENTS.md + git log --oneline -5 + 测试基础设施摘要
|
|
325
325
|
|
|
326
|
+
3. **Pre-REQ snapshot(Issue #137)**
|
|
327
|
+
- 在 dispatch subagent 前记录当前 git HEAD,用于 TDD 合规的基线对比
|
|
328
|
+
```bash
|
|
329
|
+
# 保存当前 HEAD 作为 TDD 验证基线
|
|
330
|
+
PRE_REQ_HASH=$(git rev-parse HEAD)
|
|
331
|
+
echo "[TDD-BASELINE] Pre-REQ snapshot: $PRE_REQ_HASH"
|
|
332
|
+
# 记录到临时文件(subagent 只读基线,避免污染)
|
|
333
|
+
echo "$PRE_REQ_HASH" > .sprint-state/last-req-baseline.txt
|
|
334
|
+
```
|
|
335
|
+
|
|
326
336
|
3. **Dispatch build subagent**
|
|
327
337
|
- 使用 `task(category="unspecified-high", load_skills=["test-driven-development"], timeout=300)`
|
|
328
338
|
- 强制 TDD 流程:RED → GREEN → REFACTOR
|
|
@@ -330,7 +340,34 @@ Phase 0, 1, 3-6 行为完全不变。
|
|
|
330
340
|
|
|
331
341
|
4. **Run full regression tests**
|
|
332
342
|
- L1: typecheck + lint on changed files
|
|
333
|
-
- L1b:
|
|
343
|
+
- **L1b: 客观测试先行验证(Issue #137)** — 使用 git diff 验证新增测试行数占总新增行数比例
|
|
344
|
+
```bash
|
|
345
|
+
# 从基线读取 pre-REQ HEAD,支持跨多个 commit 的 REQ
|
|
346
|
+
PRE_BASELINE=$(cat .sprint-state/last-req-baseline.txt 2>/dev/null || echo "HEAD~1")
|
|
347
|
+
GIT_DIFF=$(git diff "$PRE_BASELINE"..HEAD --stat --diff-filter=AM 2>/dev/null)
|
|
348
|
+
# 提取新增测试行数(*.test.*, *.spec.*, __tests__/* 等)
|
|
349
|
+
TEST_LINES=$(echo "$GIT_DIFF" | grep -E '\.(test|spec)\.[a-z]+|__tests__/' | grep -oP '\d+(?= insertion)' | paste -sd+ | bc || echo 0)
|
|
350
|
+
# 提取总新增行数
|
|
351
|
+
TOTAL_LINES=$(echo "$GIT_DIFF" | grep -oP '\d+(?= insertion)' | paste -sd+ | bc || echo 0)
|
|
352
|
+
# 计算比率
|
|
353
|
+
if [ "$TOTAL_LINES" -gt 0 ]; then
|
|
354
|
+
RATIO=$((TEST_LINES * 100 / TOTAL_LINES))
|
|
355
|
+
echo "[TDD-CHECK] Test lines: $TEST_LINES / Total lines: $TOTAL_LINES = ${RATIO}%"
|
|
356
|
+
[ "$RATIO" -ge 40 ] || {
|
|
357
|
+
echo "[TDD-FAIL] Test-first ratio ${RATIO}% < 40% threshold"
|
|
358
|
+
echo "[TDD-FAIL] Expected ≥ 40% test lines. Retry with tests written first."
|
|
359
|
+
exit 1
|
|
360
|
+
}
|
|
361
|
+
else
|
|
362
|
+
echo "[TDD-CHECK] No new lines in diff (possibly no changes or first commit)"
|
|
363
|
+
fi
|
|
364
|
+
```
|
|
365
|
+
- **L1b-alt: 测试文件存在验证** — 当 diff 为空或无新增行时,降级检查测试文件是否出现在 changeset 中
|
|
366
|
+
```bash
|
|
367
|
+
HAS_TEST_FILES=$(echo "$GIT_DIFF" | grep -c -E '\.(test|spec)\.[a-z]+|__tests__/' || echo 0)
|
|
368
|
+
[ "$HAS_TEST_FILES" -gt 0 ] || { echo "[TDD-FAIL] No test files found in changeset"; exit 1; }
|
|
369
|
+
echo "[TDD-CHECK] Test files present in changeset: $HAS_TEST_FILES file(s)"
|
|
370
|
+
```
|
|
334
371
|
- **L2: 全量测试运行**(不只是 @test 当前 REQ 的测试)
|
|
335
372
|
- L3: 检查整体覆盖率 ≥ 80%
|
|
336
373
|
|
|
@@ -438,9 +475,10 @@ REQ-001 开始 → 检查 test-utils.ts → 不存在
|
|
|
438
475
|
- [ ] Test infrastructure confirmed ready
|
|
439
476
|
|
|
440
477
|
**TDD Compliance**:
|
|
441
|
-
- [ ] Tests written BEFORE implementation
|
|
442
|
-
- [ ] Test/implementation ratio ≥ 40%
|
|
478
|
+
- [ ] Tests written BEFORE implementation (verified via `git diff HEAD~1 --stat --diff-filter=AM`)
|
|
479
|
+
- [ ] Test/implementation ratio ≥ 40% (L1b check: test_lines / total_lines ≥ 40%)
|
|
443
480
|
- [ ] Mock usage justified (if >30% mock density)
|
|
481
|
+
- [ ] Test files present in changeset (L1b-alt fallback)
|
|
444
482
|
|
|
445
483
|
**Verification Layers**:
|
|
446
484
|
- [ ] L1: typecheck + lint pass
|
|
@@ -12,6 +12,7 @@ description: >
|
|
|
12
12
|
- "start sprint"
|
|
13
13
|
- "一键开发"
|
|
14
14
|
- "/sprint-flow"
|
|
15
|
+
触发后第一行输出: `Sprint Flow: ISOLATE → AUTO-ESTIMATE → THINK → PLAN → BUILD → REVIEW → USER ACCEPTANCE → FEEDBACK → SHIP → LAND → CLEANUP`
|
|
15
16
|
用法: /sprint-flow "[需求描述]"
|
|
16
17
|
示例: /sprint-flow "开发访谈机器人,支持多轮对话"
|
|
17
18
|
可选参数:
|
|
@@ -236,6 +237,36 @@ ISOLATE → AUTO-ESTIMATE → THINK → PLAN → [GITHOOKS-GATE] → BUILD → R
|
|
|
236
237
|
|
|
237
238
|
## 各 Phase 调用的 Skills
|
|
238
239
|
|
|
240
|
+
### ⚠️ 强制输出格式规范(Mandatory Output Format)
|
|
241
|
+
|
|
242
|
+
**执行每个 Phase 时,必须以以下固定格式输出阶段标题**,不可省略、不可合并、不可替换:
|
|
243
|
+
|
|
244
|
+
```markdown
|
|
245
|
+
## Phase -1: ISOLATE (隔离)
|
|
246
|
+
## Phase -0.5: AUTO-ESTIMATE (规模评估)
|
|
247
|
+
## Phase 0: THINK (思考)
|
|
248
|
+
## Phase 1: PLAN (规划)
|
|
249
|
+
## Phase 2: BUILD (构建)
|
|
250
|
+
## Phase 3: REVIEW (评审)
|
|
251
|
+
## Phase 4: USER ACCEPTANCE (用户验收)
|
|
252
|
+
## Phase 5: FEEDBACK (反馈)
|
|
253
|
+
## Phase 6: SHIP (发布)
|
|
254
|
+
## Phase 7: LAND (部署)
|
|
255
|
+
## Phase 8: CLEANUP (清理)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**规则**:
|
|
259
|
+
1. 每个 Phase **开始执行时必须首先输出**对应的 `## Phase X: NAME` 标题行(作为该 Phase 输出的第一行)
|
|
260
|
+
2. **禁止省略** "Phase" 关键词(如不能只写 "ISOLATE" 或 "## -1")
|
|
261
|
+
3. **禁止合并**多个 Phase 的输出(每个 Phase 必须有独立标题)
|
|
262
|
+
4. **格式必须精确匹配**:`## Phase ` + 数字 + `: ` + 大写英文名 + ` (中文名)`
|
|
263
|
+
5. 跳过某个 Phase(如 `--resume-from build` 跳过了 -1, -0.5, 0, 1)时,不输出被跳过 Phase 的标题
|
|
264
|
+
6. 触发 `/sprint-flow` 后,**第一行输出应包含工作流阶段概览**:
|
|
265
|
+
|
|
266
|
+
```
|
|
267
|
+
Sprint Flow: ISOLATE → AUTO-ESTIMATE → THINK → PLAN → BUILD → REVIEW → USER ACCEPTANCE → FEEDBACK → SHIP → LAND → CLEANUP
|
|
268
|
+
```
|
|
269
|
+
|
|
239
270
|
### Phase -1: ISOLATE(git worktree 隔离)
|
|
240
271
|
|
|
241
272
|
**执行时机**: `/sprint-flow` 启动后、Phase 0 THINK 之前。**自动执行**。
|
|
@@ -247,6 +278,7 @@ ISOLATE → AUTO-ESTIMATE → THINK → PLAN → [GITHOOKS-GATE] → BUILD → R
|
|
|
247
278
|
| 步骤 | 动作 | 说明 |
|
|
248
279
|
|------|------|------|
|
|
249
280
|
| 0 | **检测当前环境** | 运行 `git rev-parse --git-dir` 和 `git rev-parse --git-common-dir`。如果 `GIT_DIR != GIT_COMMON`:已在 worktree 中 → 输出 "Already in isolated worktree" → 进入 Phase 0 |
|
|
281
|
+
| 0.5 | **Sprint Lock 检测(Issue #144)** | 检查 `.sprint-state/sprint.lock` 是否存在: `[ -f .sprint-state/sprint.lock ]`。如果存在: 读取锁内容,检查是否 stale(超过 24 小时或 worktree 目录不存在)→ stale → 输出 `[WARN] 发现过期 sprint lock,将覆盖` → 更新锁。非 stale → 输出 `[BLOCK] 已有活跃 sprint (ID: {sprint_id}, started: {started_at})。请先完成当前 sprint 或手动删除 .sprint-state/sprint.lock` → 退出。锁不存在 → 创建锁: `echo '{"sprint_id":"sprint-YYYY-MM-DD-NN","started_at":"<ISO8601>"}' > .sprint-state/sprint.lock` |
|
|
250
282
|
| 1 | **检查保护分支** | 获取当前分支名 `git branch --show-current`。保护分支列表: `main, master, develop, trunk, mainline`。保护分支 → 强制创建 worktree。非保护分支 → 依然创建 worktree(推荐,不阻断) |
|
|
251
283
|
| 2 | **创建 worktree** | 创建目录: `mkdir -p .worktrees/sprint`。检测已有 NN 编号: `ls .worktrees/sprint/ 2>/dev/null | grep -oE '[0-9]{2}$' | sort -n | tail -1`(取最后两位数字,数值排序,取最大),NN = 结果 + 1(无结果则从 01 开始)。运行 `git worktree add .worktrees/sprint/sprint-YYYY-MM-DD-NN -b sprint/YYYY-MM-DD-NN`。**注意**: `cd` 在 AI agent 单次工具调用中不保持状态,步骤 3-6 必须通过 `workdir` 参数或 `&&` 链式命令在新 worktree 目录下执行 |
|
|
252
284
|
| 3 | **项目 setup** | 在 worktree 目录下: 检测项目类型: `package.json` → `npm install`, `go.mod` → `go mod download`, `pyproject.toml` → `pip/poetry install` |
|
|
@@ -485,6 +517,25 @@ Phase 2 第一步必须执行 DELPHI-GATE 检查。没有 delphi-review APPROVED
|
|
|
485
517
|
- 更新 `CHANGELOG.md` 添加本次变更记录(含变更类型说明:skill-only / code / mixed)
|
|
486
518
|
- 验证:`git diff VERSION` 确认版本号已变更,未变更 → 阻断
|
|
487
519
|
- **此规则与变更类型无关** — 纯 skill 变更(仅 .md 文件)也必须 bump PATCH,确保每次 sprint 都触发 npm 发布
|
|
520
|
+
- **📋 VERSION CHANGESET(Issue #142)**: 每次 VERSION bump 必须创建原子化的 changeset 记录,确保版本变更可追溯、可审计
|
|
521
|
+
- 在 `.sprint-state/changesets/` 目录下创建 JSON 文件,文件名格式: `changeset-{YYYYMMDDHHMMSS}.json`
|
|
522
|
+
- changeset 字段:
|
|
523
|
+
```json
|
|
524
|
+
{
|
|
525
|
+
"id": "cs_xxxxxxxx",
|
|
526
|
+
"created_at": "2026-06-07T12:00:00Z",
|
|
527
|
+
"sprint_id": "sprint-2026-06-07-01",
|
|
528
|
+
"old_version": "0.8.1.2",
|
|
529
|
+
"new_version": "0.8.2.0",
|
|
530
|
+
"change_type": "patch|minor|major",
|
|
531
|
+
"description": "brief description of changes in this bump",
|
|
532
|
+
"files_changed": ["VERSION", "CHANGELOG.md", "package.json", "src/npm-package/package.json", "plugins/claude-code/.claude-plugin/plugin.json", "plugins/opencode/package.json"],
|
|
533
|
+
"semver_note": "npm semver 3-digit: 0.8.2"
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
- changeset 创建时机:VERSION 更新后、`sync-version.sh` 执行后、commit 前
|
|
537
|
+
- changeset 随 commit 一起提交,形成版本变更的完整审计链
|
|
538
|
+
- **用途**: 回滚时通过 changeset 精确还原版本号、CI/CD 自动确定发布范围、审核时追踪每次 bump 的原因
|
|
488
539
|
- **`finishing-a-development-branch`** (superpowers) — 结构化完成流:4 选项(merge / PR / discard / keep)
|
|
489
540
|
- `ship` (gstack) — 创建 PR(PR 路径时使用)
|
|
490
541
|
- Phase 6 输出:PR URL(用于 Phase 7 输入)
|
|
@@ -535,7 +586,10 @@ Phase 2 第一步必须执行 DELPHI-GATE 检查。没有 delphi-review APPROVED
|
|
|
535
586
|
6. **更新 `.sprint-state/sprint-state.json`**:
|
|
536
587
|
- `phase: 8`
|
|
537
588
|
- `status: "merged"` 或 `"completed"`
|
|
538
|
-
7.
|
|
589
|
+
7. **释放 Sprint Lock(Issue #144)**:
|
|
590
|
+
- `rm -f .sprint-state/sprint.lock`
|
|
591
|
+
- 验证锁已删除: `[ ! -f .sprint-state/sprint.lock ] || echo "[WARN] sprint lock 未能删除,请手动清理"`
|
|
592
|
+
8. **输出 Cleanup Report + Sprint Summary**
|
|
539
593
|
|
|
540
594
|
**执行顺序依赖**:
|
|
541
595
|
```
|
|
@@ -619,7 +673,7 @@ Phase 2 第一步必须执行 DELPHI-GATE 检查。没有 delphi-review APPROVED
|
|
|
619
673
|
不包含前一 Phase 的完整对话、中间文件、失败尝试。
|
|
620
674
|
|
|
621
675
|
**特殊场景**:
|
|
622
|
-
- `--resume-from <phase>`:跳过前置 Phase,直接从指定 Phase
|
|
676
|
+
- `--resume-from <phase>`:跳过前置 Phase,直接从指定 Phase 启动。**MUST 先执行 RESUME GATE(Issue #148)** 校验 sprint 状态、git 可达性和文件时效性,再执行 Phase Transition Gate 校验摘要文件格式。例如 `--resume-from build` 要求 `phase-1-summary.md` 和 `specification.yaml` 已存在且非 stale。
|
|
623
677
|
- `--no-isolate`:跳过 Phase -1 ISOLATE,直接在当前分支执行。Phase 0 无 `phase--1-summary` 可用,上下文继承来源为用户原始需求 + 当前 git 状态。所有后续 Phase 的 worktree enforcement 不适用(无 worktree),但仍需保持代码隔离。
|
|
624
678
|
- `next_phase_context` 中的 `{path}` 等变量占位符在实际写入时被替换为具体值。示例中的 `{path}` 应替换为实际 worktree 路径(如 `.worktrees/sprint/sprint-2026-06-01-01`)。
|
|
625
679
|
|
|
@@ -681,6 +735,9 @@ next_phase_context: "Worktree created at {path}. All subsequent edits MUST use t
|
|
|
681
735
|
Orchestrator dispatch 下一 Phase 前必须执行验证:
|
|
682
736
|
|
|
683
737
|
```bash
|
|
738
|
+
# === Phase Transition Gate ===
|
|
739
|
+
|
|
740
|
+
# 1. Phase summary file validation
|
|
684
741
|
SUMMARY=".sprint-state/phase-outputs/phase-${N}-summary.md"
|
|
685
742
|
[ -f "$SUMMARY" ] || { echo "[BLOCK] phase-${N}-summary 不存在"; exit 1; }
|
|
686
743
|
FRONTMARKERS=$(grep -c "^---" "$SUMMARY" 2>/dev/null || echo 0)
|
|
@@ -693,11 +750,118 @@ grep -q "^outputs:" "$SUMMARY" || { echo "[BLOCK] 缺少 outputs 字段"; exit 1
|
|
|
693
750
|
grep -q "^next_phase_context:" "$SUMMARY" || { echo "[BLOCK] 缺少 next_phase_context"; exit 1; }
|
|
694
751
|
CHARS=$(wc -c < "$SUMMARY" | tr -d ' ')
|
|
695
752
|
[ "$CHARS" -le 40000 ] || { echo "[BLOCK] 摘要超出大小限制 (${CHARS}/40000 chars)"; exit 1; }
|
|
753
|
+
|
|
754
|
+
# 2. sprint-state.json enforcement check (Issue #146)
|
|
755
|
+
SPRINT_STATE=".sprint-state/sprint-state.json"
|
|
756
|
+
[ -f "$SPRINT_STATE" ] || { echo "[BLOCK] sprint-state.json 不存在"; exit 1; }
|
|
757
|
+
|
|
758
|
+
# Verify phase_history includes current phase with completed_at
|
|
759
|
+
PHASE_HISTORY_CHECK=$(grep -c "\"phase\": $N" "$SPRINT_STATE" 2>/dev/null || echo 0)
|
|
760
|
+
[ "$PHASE_HISTORY_CHECK" -gt 0 ] || {
|
|
761
|
+
echo "[BLOCK] sprint-state.json phase_history 缺少 phase $N 的记录"
|
|
762
|
+
echo "[ACTION] 在 dispatch 下一 Phase 前更新 sprint-state.json:"
|
|
763
|
+
echo " - phase: $N"
|
|
764
|
+
echo " - phase_history: 追加 {phase:N, status:completed, completed_at:<ISO8601>}"
|
|
765
|
+
echo " - outputs: 追加当前 phase 的输出文件"
|
|
766
|
+
exit 1
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
# Verify completed_at is set (not null)
|
|
770
|
+
COMPLETED_AT_VALUE=$(grep -A3 "\"phase\": $N" "$SPRINT_STATE" 2>/dev/null | grep "completed_at" | head -1 | grep -o '"[^"]*"$' | tr -d '"')
|
|
771
|
+
[ "$COMPLETED_AT_VALUE" != "null" ] && [ -n "$COMPLETED_AT_VALUE" ] || {
|
|
772
|
+
echo "[BLOCK] sprint-state.json phase $N 的 completed_at 未设置 (null)"
|
|
773
|
+
echo "[ACTION] 设置 completed_at 为当前时间 (ISO 8601):"
|
|
774
|
+
echo " date -u +%Y-%m-%dT%H:%M:%SZ"
|
|
775
|
+
exit 1
|
|
776
|
+
}
|
|
696
777
|
```
|
|
697
778
|
|
|
698
779
|
**由 orchestrator 强制执行**,不依赖 subagent 自觉遵守。
|
|
699
780
|
验证失败 → BLOCK,不可 dispatch 下一 Phase。
|
|
700
781
|
|
|
782
|
+
### RESUME GATE / --resume-from 断点校验(Issue #148)
|
|
783
|
+
|
|
784
|
+
当使用 `--resume-from <phase>` 时,在执行 Phase Transition Gate 之前,
|
|
785
|
+
orchestrator MUST 先执行以下断点校验。任何一项失败 → BLOCK,拒绝恢复。
|
|
786
|
+
|
|
787
|
+
```bash
|
|
788
|
+
SPRINT_STATE=".sprint-state/sprint-state.json"
|
|
789
|
+
[ -f "$SPRINT_STATE" ] || { echo "[BLOCK] sprint-state.json 不存在,无法恢复"; exit 1; }
|
|
790
|
+
|
|
791
|
+
# 1. Sprint ID 一致性:确认 resume 的目标 sprint 与 sprint-state.json 匹配
|
|
792
|
+
SPRINT_ID=$(grep -o '"id": "[^"]*"' "$SPRINT_STATE" | head -1 | cut -d'"' -f4)
|
|
793
|
+
CURRENT_SPRINT_ID=$(echo "$TASK_DESCRIPTION" | md5sum | head -8 2>/dev/null || echo "unknown")
|
|
794
|
+
# 实际 sprint id 由 Phase -1 生成,此处仅验证文件存在且包含 id 字段
|
|
795
|
+
[ -n "$SPRINT_ID" ] || { echo "[BLOCK] sprint-state.json 缺少 id 字段"; exit 1; }
|
|
796
|
+
|
|
797
|
+
# 2. 阶段顺序校验:--resume-from 的 phase 必须是最后已完成 phase 的后继
|
|
798
|
+
LAST_COMPLETED_PHASE=$(grep -o '"phase": [0-9]' "$SPRINT_STATE" | tail -1 | awk '{print $2}')
|
|
799
|
+
RESUME_PHASE=$((RESUME_PHASE)) # orchestrator 将 --resume-from 参数值转为整数
|
|
800
|
+
[ "$RESUME_PHASE" -gt "$LAST_COMPLETED_PHASE" ] || {
|
|
801
|
+
echo "[BLOCK] --resume-from phase ($RESUME_PHASE) 必须在最后已完成 phase ($LAST_COMPLETED_PHASE) 之后"
|
|
802
|
+
exit 1
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
# 3. Git 状态校验:isolation branch 仍然可达
|
|
806
|
+
ISOLATION_BRANCH=$(grep -o '"branch": "[^"]*"' "$SPRINT_STATE" | head -1 | cut -d'"' -f4)
|
|
807
|
+
ISOLATION_COMMIT=$(grep -o '"created_from_commit": "[^"]*"' "$SPRINT_STATE" | head -1 | cut -d'"' -f4)
|
|
808
|
+
if [ -n "$ISOLATION_BRANCH" ]; then
|
|
809
|
+
git rev-parse --verify "$ISOLATION_BRANCH" >/dev/null 2>&1 || {
|
|
810
|
+
echo "[BLOCK] isolation branch '$ISOLATION_BRANCH' 已不存在(可能被删除或 force push 覆盖)"
|
|
811
|
+
exit 1
|
|
812
|
+
}
|
|
813
|
+
fi
|
|
814
|
+
if [ -n "$ISOLATION_COMMIT" ]; then
|
|
815
|
+
git cat-file -e "${ISOLATION_COMMIT}^{commit}" 2>/dev/null || {
|
|
816
|
+
echo "[WARN] isolation commit $ISOLATION_COMMIT 不可达(可能被 GC 或 rebase 清理),恢复后可能状态不一致"
|
|
817
|
+
# WARN 而非 BLOCK — 可继续但有风险
|
|
818
|
+
}
|
|
819
|
+
fi
|
|
820
|
+
|
|
821
|
+
# 4. 文件时效性校验:前置摘要文件的 mtime 不晚于其生成 phase 的完成时间
|
|
822
|
+
RESUME_PREREQ_PHASE=$((RESUME_PHASE - 1))
|
|
823
|
+
PREREQ_FILE=".sprint-state/phase-outputs/phase-${RESUME_PREREQ_PHASE}-summary.md"
|
|
824
|
+
[ -f "$PREREQ_FILE" ] || { echo "[BLOCK] 前置摘要文件 ${PREREQ_FILE} 不存在"; exit 1; }
|
|
825
|
+
|
|
826
|
+
# 提取前置 phase 的完成时间
|
|
827
|
+
PREREQ_COMPLETED_AT=$(grep -A3 "\"phase\": $RESUME_PREREQ_PHASE" "$SPRINT_STATE" 2>/dev/null | grep "completed_at" | head -1 | cut -d'"' -f4)
|
|
828
|
+
if [ -n "$PREREQ_COMPLETED_AT" ] && [ "$PREREQ_COMPLETED_AT" != "null" ]; then
|
|
829
|
+
FILE_MTIME=$(stat -c %Y "$PREREQ_FILE" 2>/dev/null || stat -f %m "$PREREQ_FILE" 2>/dev/null)
|
|
830
|
+
COMPLETED_EPOCH=$(date -d "$PREREQ_COMPLETED_AT" +%s 2>/dev/null || echo "")
|
|
831
|
+
if [ -n "$FILE_MTIME" ] && [ -n "$COMPLETED_EPOCH" ]; then
|
|
832
|
+
# 容忍 60 秒时钟偏差
|
|
833
|
+
[ "$FILE_MTIME" -le $((COMPLETED_EPOCH + 60)) ] || {
|
|
834
|
+
echo "[WARN] 前置摘要文件 ${PREREQ_FILE} 在 phase $RESUME_PREREQ_PHASE 完成后被修改(mtime: $(date -d @$FILE_MTIME '+%Y-%m-%d %H:%M:%S'), completed_at: $PREREQ_COMPLETED_AT)"
|
|
835
|
+
echo "[ACTION] 继续恢复前请确认修改是预期的。输入 'confirm' 继续,其他取消:"
|
|
836
|
+
read USER_CONFIRM
|
|
837
|
+
[ "$USER_CONFIRM" = "confirm" ] || { echo "[BLOCK] 用户取消恢复"; exit 1; }
|
|
838
|
+
}
|
|
839
|
+
fi
|
|
840
|
+
fi
|
|
841
|
+
|
|
842
|
+
# 5. specification.yaml 时效性校验(仅 --resume-from build)
|
|
843
|
+
SPEC_FILE="specification.yaml"
|
|
844
|
+
if [ "$RESUME_PHASE" -ge 2 ] && [ -f "$SPEC_FILE" ]; then
|
|
845
|
+
SPEC_MTIME=$(stat -c %Y "$SPEC_FILE" 2>/dev/null || stat -f %m "$SPEC_FILE" 2>/dev/null)
|
|
846
|
+
PLAN_COMPLETED_AT=$(grep -A3 '"phase": 1' "$SPRINT_STATE" 2>/dev/null | grep "completed_at" | head -1 | cut -d'"' -f4)
|
|
847
|
+
if [ -n "$SPEC_MTIME" ] && [ -n "$PLAN_COMPLETED_AT" ] && [ "$PLAN_COMPLETED_AT" != "null" ]; then
|
|
848
|
+
PLAN_EPOCH=$(date -d "$PLAN_COMPLETED_AT" +%s 2>/dev/null || echo "")
|
|
849
|
+
if [ -n "$PLAN_EPOCH" ] && [ "$SPEC_MTIME" -gt $((PLAN_EPOCH + 60)) ]; then
|
|
850
|
+
echo "[WARN] specification.yaml 在 Plan phase 完成后被修改"
|
|
851
|
+
echo "[ACTION] 继续恢复前请确认 specification.yaml 的修改是预期的。输入 'confirm' 继续:"
|
|
852
|
+
read USER_CONFIRM
|
|
853
|
+
[ "$USER_CONFIRM" = "confirm" ] || { echo "[BLOCK] 用户取消恢复"; exit 1; }
|
|
854
|
+
fi
|
|
855
|
+
fi
|
|
856
|
+
fi
|
|
857
|
+
|
|
858
|
+
echo "✅ RESUME GATE PASSED — 断点校验通过"
|
|
859
|
+
# 继续执行 Phase Transition Gate
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
验证失败 → BLOCK,不可执行 `--resume-from`。
|
|
863
|
+
orchestrator 必须展示失败原因并建议用户启动新 Sprint 或手动修复后重试。
|
|
864
|
+
|
|
701
865
|
### WORKTREE ENFORCEMENT(Issue #84)
|
|
702
866
|
|
|
703
867
|
Phase -1 执行完毕后,**所有后续操作(Phase 0 到 Phase 8)的文件编辑、命令执行 MUST 在 worktree 目录下执行**:
|
|
@@ -796,12 +960,20 @@ Sprint state is persisted as JSON in `.sprint-state/sprint-state.json`:
|
|
|
796
960
|
|
|
797
961
|
### --resume-from(从某阶段继续)
|
|
798
962
|
|
|
963
|
+
**前置校验**:MUST 执行 RESUME GATE(见上节)后才可 dispatch 下一 Phase。
|
|
964
|
+
|
|
799
965
|
```bash
|
|
800
966
|
/sprint-flow "继续 Sprint" --resume-from build --spec specification.yaml
|
|
801
|
-
# →
|
|
967
|
+
# → 1. 执行 RESUME GATE(校验 sprint-state + git 状态 + 文件时效性)
|
|
968
|
+
# → 2. 执行 Phase Transition Gate(校验摘要文件格式)
|
|
969
|
+
# → 3. 从 Build 恢复,但必须已有 specification.yaml + .sprint-state/delphi-reviewed.json (verdict: APPROVED)
|
|
802
970
|
# 适用场景:中断恢复,使用已通过 delphi-review 的 specification.yaml
|
|
803
971
|
```
|
|
804
972
|
|
|
973
|
+
**已知限制**:
|
|
974
|
+
- `--resume-from` 校验为**尽力而为**:git commit 可被 GC 回收、文件 mtime 可被 `git checkout` 修改
|
|
975
|
+
- 校验失败时 orchestrator 应输出完整诊断日志,建议用户启动新 Sprint 而非手动修补
|
|
976
|
+
|
|
805
977
|
### --phase(只执行单个阶段)
|
|
806
978
|
|
|
807
979
|
```bash
|
|
@@ -954,7 +1126,9 @@ Sprint 结束时 (Phase 6 完成):
|
|
|
954
1126
|
|
|
955
1127
|
# 第二次:三天后继续
|
|
956
1128
|
/sprint-flow "继续开发" --resume-from build --spec docs/specification.yaml
|
|
957
|
-
# →
|
|
1129
|
+
# → 1. RESUME GATE:校验 sprint-state + git + 文件时效性(三天前生成的文件可能 stale)
|
|
1130
|
+
# → 2. Phase Transition Gate:校验摘要文件格式
|
|
1131
|
+
# → 3. 从 Build 入口恢复,但必须已有 specification.yaml + .sprint-state/delphi-reviewed.json (verdict: APPROVED)
|
|
958
1132
|
```
|
|
959
1133
|
|
|
960
1134
|
### 示例 3:语言特定
|
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xp-gate/opencode-plugin",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"private": true,
|
|
3
|
+
"version": "0.8.4",
|
|
5
4
|
"type": "module",
|
|
6
5
|
"main": "index.ts",
|
|
7
6
|
"description": "XP-Gate quality gates + AI workflow skills for OpenCode",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/boyingliu01/xp-gate",
|
|
10
|
+
"directory": "plugins/opencode"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"registry": "https://registry.npmjs.org",
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"index.ts",
|
|
18
|
+
"skills/",
|
|
19
|
+
"tsconfig.json",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
8
22
|
"scripts": {
|
|
9
|
-
"
|
|
23
|
+
"prepack": "node scripts/prepack.cjs",
|
|
10
24
|
"check": "tsc --noEmit"
|
|
11
25
|
},
|
|
12
26
|
"dependencies": {
|
|
@@ -14,5 +28,15 @@
|
|
|
14
28
|
},
|
|
15
29
|
"devDependencies": {
|
|
16
30
|
"typescript": "^5.4.0"
|
|
17
|
-
}
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"opencode",
|
|
34
|
+
"plugin",
|
|
35
|
+
"xp-gate",
|
|
36
|
+
"quality-gates",
|
|
37
|
+
"code-review",
|
|
38
|
+
"sprint-flow"
|
|
39
|
+
],
|
|
40
|
+
"author": "boyingliu01",
|
|
41
|
+
"license": "MIT"
|
|
18
42
|
}
|