@boyingliu01/xp-gate 0.8.1 → 0.8.2
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/hooks/pre-commit +26 -23
- package/hooks/pre-push +7 -3
- package/lib/__tests__/ui-detector.test.ts +94 -0
- package/lib/init.js +44 -0
- package/lib/ui-detector.ts +3 -3
- 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 +147 -4
- package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +1 -1
- package/plugins/opencode/package.json +1 -1
- 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 +147 -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 +147 -4
- package/skills/test-specification-alignment/AGENTS.md +1 -1
|
@@ -247,6 +247,7 @@ ISOLATE → AUTO-ESTIMATE → THINK → PLAN → [GITHOOKS-GATE] → BUILD → R
|
|
|
247
247
|
| 步骤 | 动作 | 说明 |
|
|
248
248
|
|------|------|------|
|
|
249
249
|
| 0 | **检测当前环境** | 运行 `git rev-parse --git-dir` 和 `git rev-parse --git-common-dir`。如果 `GIT_DIR != GIT_COMMON`:已在 worktree 中 → 输出 "Already in isolated worktree" → 进入 Phase 0 |
|
|
250
|
+
| 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
251
|
| 1 | **检查保护分支** | 获取当前分支名 `git branch --show-current`。保护分支列表: `main, master, develop, trunk, mainline`。保护分支 → 强制创建 worktree。非保护分支 → 依然创建 worktree(推荐,不阻断) |
|
|
251
252
|
| 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
253
|
| 3 | **项目 setup** | 在 worktree 目录下: 检测项目类型: `package.json` → `npm install`, `go.mod` → `go mod download`, `pyproject.toml` → `pip/poetry install` |
|
|
@@ -485,6 +486,25 @@ Phase 2 第一步必须执行 DELPHI-GATE 检查。没有 delphi-review APPROVED
|
|
|
485
486
|
- 更新 `CHANGELOG.md` 添加本次变更记录(含变更类型说明:skill-only / code / mixed)
|
|
486
487
|
- 验证:`git diff VERSION` 确认版本号已变更,未变更 → 阻断
|
|
487
488
|
- **此规则与变更类型无关** — 纯 skill 变更(仅 .md 文件)也必须 bump PATCH,确保每次 sprint 都触发 npm 发布
|
|
489
|
+
- **📋 VERSION CHANGESET(Issue #142)**: 每次 VERSION bump 必须创建原子化的 changeset 记录,确保版本变更可追溯、可审计
|
|
490
|
+
- 在 `.sprint-state/changesets/` 目录下创建 JSON 文件,文件名格式: `changeset-{YYYYMMDDHHMMSS}.json`
|
|
491
|
+
- changeset 字段:
|
|
492
|
+
```json
|
|
493
|
+
{
|
|
494
|
+
"id": "cs_xxxxxxxx",
|
|
495
|
+
"created_at": "2026-06-07T12:00:00Z",
|
|
496
|
+
"sprint_id": "sprint-2026-06-07-01",
|
|
497
|
+
"old_version": "0.8.1.2",
|
|
498
|
+
"new_version": "0.8.2.0",
|
|
499
|
+
"change_type": "patch|minor|major",
|
|
500
|
+
"description": "brief description of changes in this bump",
|
|
501
|
+
"files_changed": ["VERSION", "CHANGELOG.md", "package.json", "src/npm-package/package.json", "plugins/claude-code/.claude-plugin/plugin.json", "plugins/opencode/package.json"],
|
|
502
|
+
"semver_note": "npm semver 3-digit: 0.8.2"
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
- changeset 创建时机:VERSION 更新后、`sync-version.sh` 执行后、commit 前
|
|
506
|
+
- changeset 随 commit 一起提交,形成版本变更的完整审计链
|
|
507
|
+
- **用途**: 回滚时通过 changeset 精确还原版本号、CI/CD 自动确定发布范围、审核时追踪每次 bump 的原因
|
|
488
508
|
- **`finishing-a-development-branch`** (superpowers) — 结构化完成流:4 选项(merge / PR / discard / keep)
|
|
489
509
|
- `ship` (gstack) — 创建 PR(PR 路径时使用)
|
|
490
510
|
- Phase 6 输出:PR URL(用于 Phase 7 输入)
|
|
@@ -535,7 +555,10 @@ Phase 2 第一步必须执行 DELPHI-GATE 检查。没有 delphi-review APPROVED
|
|
|
535
555
|
6. **更新 `.sprint-state/sprint-state.json`**:
|
|
536
556
|
- `phase: 8`
|
|
537
557
|
- `status: "merged"` 或 `"completed"`
|
|
538
|
-
7.
|
|
558
|
+
7. **释放 Sprint Lock(Issue #144)**:
|
|
559
|
+
- `rm -f .sprint-state/sprint.lock`
|
|
560
|
+
- 验证锁已删除: `[ ! -f .sprint-state/sprint.lock ] || echo "[WARN] sprint lock 未能删除,请手动清理"`
|
|
561
|
+
8. **输出 Cleanup Report + Sprint Summary**
|
|
539
562
|
|
|
540
563
|
**执行顺序依赖**:
|
|
541
564
|
```
|
|
@@ -619,7 +642,7 @@ Phase 2 第一步必须执行 DELPHI-GATE 检查。没有 delphi-review APPROVED
|
|
|
619
642
|
不包含前一 Phase 的完整对话、中间文件、失败尝试。
|
|
620
643
|
|
|
621
644
|
**特殊场景**:
|
|
622
|
-
- `--resume-from <phase>`:跳过前置 Phase,直接从指定 Phase
|
|
645
|
+
- `--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
646
|
- `--no-isolate`:跳过 Phase -1 ISOLATE,直接在当前分支执行。Phase 0 无 `phase--1-summary` 可用,上下文继承来源为用户原始需求 + 当前 git 状态。所有后续 Phase 的 worktree enforcement 不适用(无 worktree),但仍需保持代码隔离。
|
|
624
647
|
- `next_phase_context` 中的 `{path}` 等变量占位符在实际写入时被替换为具体值。示例中的 `{path}` 应替换为实际 worktree 路径(如 `.worktrees/sprint/sprint-2026-06-01-01`)。
|
|
625
648
|
|
|
@@ -681,6 +704,9 @@ next_phase_context: "Worktree created at {path}. All subsequent edits MUST use t
|
|
|
681
704
|
Orchestrator dispatch 下一 Phase 前必须执行验证:
|
|
682
705
|
|
|
683
706
|
```bash
|
|
707
|
+
# === Phase Transition Gate ===
|
|
708
|
+
|
|
709
|
+
# 1. Phase summary file validation
|
|
684
710
|
SUMMARY=".sprint-state/phase-outputs/phase-${N}-summary.md"
|
|
685
711
|
[ -f "$SUMMARY" ] || { echo "[BLOCK] phase-${N}-summary 不存在"; exit 1; }
|
|
686
712
|
FRONTMARKERS=$(grep -c "^---" "$SUMMARY" 2>/dev/null || echo 0)
|
|
@@ -693,11 +719,118 @@ grep -q "^outputs:" "$SUMMARY" || { echo "[BLOCK] 缺少 outputs 字段"; exit 1
|
|
|
693
719
|
grep -q "^next_phase_context:" "$SUMMARY" || { echo "[BLOCK] 缺少 next_phase_context"; exit 1; }
|
|
694
720
|
CHARS=$(wc -c < "$SUMMARY" | tr -d ' ')
|
|
695
721
|
[ "$CHARS" -le 40000 ] || { echo "[BLOCK] 摘要超出大小限制 (${CHARS}/40000 chars)"; exit 1; }
|
|
722
|
+
|
|
723
|
+
# 2. sprint-state.json enforcement check (Issue #146)
|
|
724
|
+
SPRINT_STATE=".sprint-state/sprint-state.json"
|
|
725
|
+
[ -f "$SPRINT_STATE" ] || { echo "[BLOCK] sprint-state.json 不存在"; exit 1; }
|
|
726
|
+
|
|
727
|
+
# Verify phase_history includes current phase with completed_at
|
|
728
|
+
PHASE_HISTORY_CHECK=$(grep -c "\"phase\": $N" "$SPRINT_STATE" 2>/dev/null || echo 0)
|
|
729
|
+
[ "$PHASE_HISTORY_CHECK" -gt 0 ] || {
|
|
730
|
+
echo "[BLOCK] sprint-state.json phase_history 缺少 phase $N 的记录"
|
|
731
|
+
echo "[ACTION] 在 dispatch 下一 Phase 前更新 sprint-state.json:"
|
|
732
|
+
echo " - phase: $N"
|
|
733
|
+
echo " - phase_history: 追加 {phase:N, status:completed, completed_at:<ISO8601>}"
|
|
734
|
+
echo " - outputs: 追加当前 phase 的输出文件"
|
|
735
|
+
exit 1
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
# Verify completed_at is set (not null)
|
|
739
|
+
COMPLETED_AT_VALUE=$(grep -A3 "\"phase\": $N" "$SPRINT_STATE" 2>/dev/null | grep "completed_at" | head -1 | grep -o '"[^"]*"$' | tr -d '"')
|
|
740
|
+
[ "$COMPLETED_AT_VALUE" != "null" ] && [ -n "$COMPLETED_AT_VALUE" ] || {
|
|
741
|
+
echo "[BLOCK] sprint-state.json phase $N 的 completed_at 未设置 (null)"
|
|
742
|
+
echo "[ACTION] 设置 completed_at 为当前时间 (ISO 8601):"
|
|
743
|
+
echo " date -u +%Y-%m-%dT%H:%M:%SZ"
|
|
744
|
+
exit 1
|
|
745
|
+
}
|
|
696
746
|
```
|
|
697
747
|
|
|
698
748
|
**由 orchestrator 强制执行**,不依赖 subagent 自觉遵守。
|
|
699
749
|
验证失败 → BLOCK,不可 dispatch 下一 Phase。
|
|
700
750
|
|
|
751
|
+
### RESUME GATE / --resume-from 断点校验(Issue #148)
|
|
752
|
+
|
|
753
|
+
当使用 `--resume-from <phase>` 时,在执行 Phase Transition Gate 之前,
|
|
754
|
+
orchestrator MUST 先执行以下断点校验。任何一项失败 → BLOCK,拒绝恢复。
|
|
755
|
+
|
|
756
|
+
```bash
|
|
757
|
+
SPRINT_STATE=".sprint-state/sprint-state.json"
|
|
758
|
+
[ -f "$SPRINT_STATE" ] || { echo "[BLOCK] sprint-state.json 不存在,无法恢复"; exit 1; }
|
|
759
|
+
|
|
760
|
+
# 1. Sprint ID 一致性:确认 resume 的目标 sprint 与 sprint-state.json 匹配
|
|
761
|
+
SPRINT_ID=$(grep -o '"id": "[^"]*"' "$SPRINT_STATE" | head -1 | cut -d'"' -f4)
|
|
762
|
+
CURRENT_SPRINT_ID=$(echo "$TASK_DESCRIPTION" | md5sum | head -8 2>/dev/null || echo "unknown")
|
|
763
|
+
# 实际 sprint id 由 Phase -1 生成,此处仅验证文件存在且包含 id 字段
|
|
764
|
+
[ -n "$SPRINT_ID" ] || { echo "[BLOCK] sprint-state.json 缺少 id 字段"; exit 1; }
|
|
765
|
+
|
|
766
|
+
# 2. 阶段顺序校验:--resume-from 的 phase 必须是最后已完成 phase 的后继
|
|
767
|
+
LAST_COMPLETED_PHASE=$(grep -o '"phase": [0-9]' "$SPRINT_STATE" | tail -1 | awk '{print $2}')
|
|
768
|
+
RESUME_PHASE=$((RESUME_PHASE)) # orchestrator 将 --resume-from 参数值转为整数
|
|
769
|
+
[ "$RESUME_PHASE" -gt "$LAST_COMPLETED_PHASE" ] || {
|
|
770
|
+
echo "[BLOCK] --resume-from phase ($RESUME_PHASE) 必须在最后已完成 phase ($LAST_COMPLETED_PHASE) 之后"
|
|
771
|
+
exit 1
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
# 3. Git 状态校验:isolation branch 仍然可达
|
|
775
|
+
ISOLATION_BRANCH=$(grep -o '"branch": "[^"]*"' "$SPRINT_STATE" | head -1 | cut -d'"' -f4)
|
|
776
|
+
ISOLATION_COMMIT=$(grep -o '"created_from_commit": "[^"]*"' "$SPRINT_STATE" | head -1 | cut -d'"' -f4)
|
|
777
|
+
if [ -n "$ISOLATION_BRANCH" ]; then
|
|
778
|
+
git rev-parse --verify "$ISOLATION_BRANCH" >/dev/null 2>&1 || {
|
|
779
|
+
echo "[BLOCK] isolation branch '$ISOLATION_BRANCH' 已不存在(可能被删除或 force push 覆盖)"
|
|
780
|
+
exit 1
|
|
781
|
+
}
|
|
782
|
+
fi
|
|
783
|
+
if [ -n "$ISOLATION_COMMIT" ]; then
|
|
784
|
+
git cat-file -e "${ISOLATION_COMMIT}^{commit}" 2>/dev/null || {
|
|
785
|
+
echo "[WARN] isolation commit $ISOLATION_COMMIT 不可达(可能被 GC 或 rebase 清理),恢复后可能状态不一致"
|
|
786
|
+
# WARN 而非 BLOCK — 可继续但有风险
|
|
787
|
+
}
|
|
788
|
+
fi
|
|
789
|
+
|
|
790
|
+
# 4. 文件时效性校验:前置摘要文件的 mtime 不晚于其生成 phase 的完成时间
|
|
791
|
+
RESUME_PREREQ_PHASE=$((RESUME_PHASE - 1))
|
|
792
|
+
PREREQ_FILE=".sprint-state/phase-outputs/phase-${RESUME_PREREQ_PHASE}-summary.md"
|
|
793
|
+
[ -f "$PREREQ_FILE" ] || { echo "[BLOCK] 前置摘要文件 ${PREREQ_FILE} 不存在"; exit 1; }
|
|
794
|
+
|
|
795
|
+
# 提取前置 phase 的完成时间
|
|
796
|
+
PREREQ_COMPLETED_AT=$(grep -A3 "\"phase\": $RESUME_PREREQ_PHASE" "$SPRINT_STATE" 2>/dev/null | grep "completed_at" | head -1 | cut -d'"' -f4)
|
|
797
|
+
if [ -n "$PREREQ_COMPLETED_AT" ] && [ "$PREREQ_COMPLETED_AT" != "null" ]; then
|
|
798
|
+
FILE_MTIME=$(stat -c %Y "$PREREQ_FILE" 2>/dev/null || stat -f %m "$PREREQ_FILE" 2>/dev/null)
|
|
799
|
+
COMPLETED_EPOCH=$(date -d "$PREREQ_COMPLETED_AT" +%s 2>/dev/null || echo "")
|
|
800
|
+
if [ -n "$FILE_MTIME" ] && [ -n "$COMPLETED_EPOCH" ]; then
|
|
801
|
+
# 容忍 60 秒时钟偏差
|
|
802
|
+
[ "$FILE_MTIME" -le $((COMPLETED_EPOCH + 60)) ] || {
|
|
803
|
+
echo "[WARN] 前置摘要文件 ${PREREQ_FILE} 在 phase $RESUME_PREREQ_PHASE 完成后被修改(mtime: $(date -d @$FILE_MTIME '+%Y-%m-%d %H:%M:%S'), completed_at: $PREREQ_COMPLETED_AT)"
|
|
804
|
+
echo "[ACTION] 继续恢复前请确认修改是预期的。输入 'confirm' 继续,其他取消:"
|
|
805
|
+
read USER_CONFIRM
|
|
806
|
+
[ "$USER_CONFIRM" = "confirm" ] || { echo "[BLOCK] 用户取消恢复"; exit 1; }
|
|
807
|
+
}
|
|
808
|
+
fi
|
|
809
|
+
fi
|
|
810
|
+
|
|
811
|
+
# 5. specification.yaml 时效性校验(仅 --resume-from build)
|
|
812
|
+
SPEC_FILE="specification.yaml"
|
|
813
|
+
if [ "$RESUME_PHASE" -ge 2 ] && [ -f "$SPEC_FILE" ]; then
|
|
814
|
+
SPEC_MTIME=$(stat -c %Y "$SPEC_FILE" 2>/dev/null || stat -f %m "$SPEC_FILE" 2>/dev/null)
|
|
815
|
+
PLAN_COMPLETED_AT=$(grep -A3 '"phase": 1' "$SPRINT_STATE" 2>/dev/null | grep "completed_at" | head -1 | cut -d'"' -f4)
|
|
816
|
+
if [ -n "$SPEC_MTIME" ] && [ -n "$PLAN_COMPLETED_AT" ] && [ "$PLAN_COMPLETED_AT" != "null" ]; then
|
|
817
|
+
PLAN_EPOCH=$(date -d "$PLAN_COMPLETED_AT" +%s 2>/dev/null || echo "")
|
|
818
|
+
if [ -n "$PLAN_EPOCH" ] && [ "$SPEC_MTIME" -gt $((PLAN_EPOCH + 60)) ]; then
|
|
819
|
+
echo "[WARN] specification.yaml 在 Plan phase 完成后被修改"
|
|
820
|
+
echo "[ACTION] 继续恢复前请确认 specification.yaml 的修改是预期的。输入 'confirm' 继续:"
|
|
821
|
+
read USER_CONFIRM
|
|
822
|
+
[ "$USER_CONFIRM" = "confirm" ] || { echo "[BLOCK] 用户取消恢复"; exit 1; }
|
|
823
|
+
fi
|
|
824
|
+
fi
|
|
825
|
+
fi
|
|
826
|
+
|
|
827
|
+
echo "✅ RESUME GATE PASSED — 断点校验通过"
|
|
828
|
+
# 继续执行 Phase Transition Gate
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
验证失败 → BLOCK,不可执行 `--resume-from`。
|
|
832
|
+
orchestrator 必须展示失败原因并建议用户启动新 Sprint 或手动修复后重试。
|
|
833
|
+
|
|
701
834
|
### WORKTREE ENFORCEMENT(Issue #84)
|
|
702
835
|
|
|
703
836
|
Phase -1 执行完毕后,**所有后续操作(Phase 0 到 Phase 8)的文件编辑、命令执行 MUST 在 worktree 目录下执行**:
|
|
@@ -796,12 +929,20 @@ Sprint state is persisted as JSON in `.sprint-state/sprint-state.json`:
|
|
|
796
929
|
|
|
797
930
|
### --resume-from(从某阶段继续)
|
|
798
931
|
|
|
932
|
+
**前置校验**:MUST 执行 RESUME GATE(见上节)后才可 dispatch 下一 Phase。
|
|
933
|
+
|
|
799
934
|
```bash
|
|
800
935
|
/sprint-flow "继续 Sprint" --resume-from build --spec specification.yaml
|
|
801
|
-
# →
|
|
936
|
+
# → 1. 执行 RESUME GATE(校验 sprint-state + git 状态 + 文件时效性)
|
|
937
|
+
# → 2. 执行 Phase Transition Gate(校验摘要文件格式)
|
|
938
|
+
# → 3. 从 Build 恢复,但必须已有 specification.yaml + .sprint-state/delphi-reviewed.json (verdict: APPROVED)
|
|
802
939
|
# 适用场景:中断恢复,使用已通过 delphi-review 的 specification.yaml
|
|
803
940
|
```
|
|
804
941
|
|
|
942
|
+
**已知限制**:
|
|
943
|
+
- `--resume-from` 校验为**尽力而为**:git commit 可被 GC 回收、文件 mtime 可被 `git checkout` 修改
|
|
944
|
+
- 校验失败时 orchestrator 应输出完整诊断日志,建议用户启动新 Sprint 而非手动修补
|
|
945
|
+
|
|
805
946
|
### --phase(只执行单个阶段)
|
|
806
947
|
|
|
807
948
|
```bash
|
|
@@ -954,7 +1095,9 @@ Sprint 结束时 (Phase 6 完成):
|
|
|
954
1095
|
|
|
955
1096
|
# 第二次:三天后继续
|
|
956
1097
|
/sprint-flow "继续开发" --resume-from build --spec docs/specification.yaml
|
|
957
|
-
# →
|
|
1098
|
+
# → 1. RESUME GATE:校验 sprint-state + git + 文件时效性(三天前生成的文件可能 stale)
|
|
1099
|
+
# → 2. Phase Transition Gate:校验摘要文件格式
|
|
1100
|
+
# → 3. 从 Build 入口恢复,但必须已有 specification.yaml + .sprint-state/delphi-reviewed.json (verdict: APPROVED)
|
|
958
1101
|
```
|
|
959
1102
|
|
|
960
1103
|
### 示例 3:语言特定
|
|
@@ -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
|
|
@@ -247,6 +247,7 @@ ISOLATE → AUTO-ESTIMATE → THINK → PLAN → [GITHOOKS-GATE] → BUILD → R
|
|
|
247
247
|
| 步骤 | 动作 | 说明 |
|
|
248
248
|
|------|------|------|
|
|
249
249
|
| 0 | **检测当前环境** | 运行 `git rev-parse --git-dir` 和 `git rev-parse --git-common-dir`。如果 `GIT_DIR != GIT_COMMON`:已在 worktree 中 → 输出 "Already in isolated worktree" → 进入 Phase 0 |
|
|
250
|
+
| 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
251
|
| 1 | **检查保护分支** | 获取当前分支名 `git branch --show-current`。保护分支列表: `main, master, develop, trunk, mainline`。保护分支 → 强制创建 worktree。非保护分支 → 依然创建 worktree(推荐,不阻断) |
|
|
251
252
|
| 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
253
|
| 3 | **项目 setup** | 在 worktree 目录下: 检测项目类型: `package.json` → `npm install`, `go.mod` → `go mod download`, `pyproject.toml` → `pip/poetry install` |
|
|
@@ -485,6 +486,25 @@ Phase 2 第一步必须执行 DELPHI-GATE 检查。没有 delphi-review APPROVED
|
|
|
485
486
|
- 更新 `CHANGELOG.md` 添加本次变更记录(含变更类型说明:skill-only / code / mixed)
|
|
486
487
|
- 验证:`git diff VERSION` 确认版本号已变更,未变更 → 阻断
|
|
487
488
|
- **此规则与变更类型无关** — 纯 skill 变更(仅 .md 文件)也必须 bump PATCH,确保每次 sprint 都触发 npm 发布
|
|
489
|
+
- **📋 VERSION CHANGESET(Issue #142)**: 每次 VERSION bump 必须创建原子化的 changeset 记录,确保版本变更可追溯、可审计
|
|
490
|
+
- 在 `.sprint-state/changesets/` 目录下创建 JSON 文件,文件名格式: `changeset-{YYYYMMDDHHMMSS}.json`
|
|
491
|
+
- changeset 字段:
|
|
492
|
+
```json
|
|
493
|
+
{
|
|
494
|
+
"id": "cs_xxxxxxxx",
|
|
495
|
+
"created_at": "2026-06-07T12:00:00Z",
|
|
496
|
+
"sprint_id": "sprint-2026-06-07-01",
|
|
497
|
+
"old_version": "0.8.1.2",
|
|
498
|
+
"new_version": "0.8.2.0",
|
|
499
|
+
"change_type": "patch|minor|major",
|
|
500
|
+
"description": "brief description of changes in this bump",
|
|
501
|
+
"files_changed": ["VERSION", "CHANGELOG.md", "package.json", "src/npm-package/package.json", "plugins/claude-code/.claude-plugin/plugin.json", "plugins/opencode/package.json"],
|
|
502
|
+
"semver_note": "npm semver 3-digit: 0.8.2"
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
- changeset 创建时机:VERSION 更新后、`sync-version.sh` 执行后、commit 前
|
|
506
|
+
- changeset 随 commit 一起提交,形成版本变更的完整审计链
|
|
507
|
+
- **用途**: 回滚时通过 changeset 精确还原版本号、CI/CD 自动确定发布范围、审核时追踪每次 bump 的原因
|
|
488
508
|
- **`finishing-a-development-branch`** (superpowers) — 结构化完成流:4 选项(merge / PR / discard / keep)
|
|
489
509
|
- `ship` (gstack) — 创建 PR(PR 路径时使用)
|
|
490
510
|
- Phase 6 输出:PR URL(用于 Phase 7 输入)
|
|
@@ -535,7 +555,10 @@ Phase 2 第一步必须执行 DELPHI-GATE 检查。没有 delphi-review APPROVED
|
|
|
535
555
|
6. **更新 `.sprint-state/sprint-state.json`**:
|
|
536
556
|
- `phase: 8`
|
|
537
557
|
- `status: "merged"` 或 `"completed"`
|
|
538
|
-
7.
|
|
558
|
+
7. **释放 Sprint Lock(Issue #144)**:
|
|
559
|
+
- `rm -f .sprint-state/sprint.lock`
|
|
560
|
+
- 验证锁已删除: `[ ! -f .sprint-state/sprint.lock ] || echo "[WARN] sprint lock 未能删除,请手动清理"`
|
|
561
|
+
8. **输出 Cleanup Report + Sprint Summary**
|
|
539
562
|
|
|
540
563
|
**执行顺序依赖**:
|
|
541
564
|
```
|
|
@@ -619,7 +642,7 @@ Phase 2 第一步必须执行 DELPHI-GATE 检查。没有 delphi-review APPROVED
|
|
|
619
642
|
不包含前一 Phase 的完整对话、中间文件、失败尝试。
|
|
620
643
|
|
|
621
644
|
**特殊场景**:
|
|
622
|
-
- `--resume-from <phase>`:跳过前置 Phase,直接从指定 Phase
|
|
645
|
+
- `--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
646
|
- `--no-isolate`:跳过 Phase -1 ISOLATE,直接在当前分支执行。Phase 0 无 `phase--1-summary` 可用,上下文继承来源为用户原始需求 + 当前 git 状态。所有后续 Phase 的 worktree enforcement 不适用(无 worktree),但仍需保持代码隔离。
|
|
624
647
|
- `next_phase_context` 中的 `{path}` 等变量占位符在实际写入时被替换为具体值。示例中的 `{path}` 应替换为实际 worktree 路径(如 `.worktrees/sprint/sprint-2026-06-01-01`)。
|
|
625
648
|
|
|
@@ -681,6 +704,9 @@ next_phase_context: "Worktree created at {path}. All subsequent edits MUST use t
|
|
|
681
704
|
Orchestrator dispatch 下一 Phase 前必须执行验证:
|
|
682
705
|
|
|
683
706
|
```bash
|
|
707
|
+
# === Phase Transition Gate ===
|
|
708
|
+
|
|
709
|
+
# 1. Phase summary file validation
|
|
684
710
|
SUMMARY=".sprint-state/phase-outputs/phase-${N}-summary.md"
|
|
685
711
|
[ -f "$SUMMARY" ] || { echo "[BLOCK] phase-${N}-summary 不存在"; exit 1; }
|
|
686
712
|
FRONTMARKERS=$(grep -c "^---" "$SUMMARY" 2>/dev/null || echo 0)
|
|
@@ -693,11 +719,118 @@ grep -q "^outputs:" "$SUMMARY" || { echo "[BLOCK] 缺少 outputs 字段"; exit 1
|
|
|
693
719
|
grep -q "^next_phase_context:" "$SUMMARY" || { echo "[BLOCK] 缺少 next_phase_context"; exit 1; }
|
|
694
720
|
CHARS=$(wc -c < "$SUMMARY" | tr -d ' ')
|
|
695
721
|
[ "$CHARS" -le 40000 ] || { echo "[BLOCK] 摘要超出大小限制 (${CHARS}/40000 chars)"; exit 1; }
|
|
722
|
+
|
|
723
|
+
# 2. sprint-state.json enforcement check (Issue #146)
|
|
724
|
+
SPRINT_STATE=".sprint-state/sprint-state.json"
|
|
725
|
+
[ -f "$SPRINT_STATE" ] || { echo "[BLOCK] sprint-state.json 不存在"; exit 1; }
|
|
726
|
+
|
|
727
|
+
# Verify phase_history includes current phase with completed_at
|
|
728
|
+
PHASE_HISTORY_CHECK=$(grep -c "\"phase\": $N" "$SPRINT_STATE" 2>/dev/null || echo 0)
|
|
729
|
+
[ "$PHASE_HISTORY_CHECK" -gt 0 ] || {
|
|
730
|
+
echo "[BLOCK] sprint-state.json phase_history 缺少 phase $N 的记录"
|
|
731
|
+
echo "[ACTION] 在 dispatch 下一 Phase 前更新 sprint-state.json:"
|
|
732
|
+
echo " - phase: $N"
|
|
733
|
+
echo " - phase_history: 追加 {phase:N, status:completed, completed_at:<ISO8601>}"
|
|
734
|
+
echo " - outputs: 追加当前 phase 的输出文件"
|
|
735
|
+
exit 1
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
# Verify completed_at is set (not null)
|
|
739
|
+
COMPLETED_AT_VALUE=$(grep -A3 "\"phase\": $N" "$SPRINT_STATE" 2>/dev/null | grep "completed_at" | head -1 | grep -o '"[^"]*"$' | tr -d '"')
|
|
740
|
+
[ "$COMPLETED_AT_VALUE" != "null" ] && [ -n "$COMPLETED_AT_VALUE" ] || {
|
|
741
|
+
echo "[BLOCK] sprint-state.json phase $N 的 completed_at 未设置 (null)"
|
|
742
|
+
echo "[ACTION] 设置 completed_at 为当前时间 (ISO 8601):"
|
|
743
|
+
echo " date -u +%Y-%m-%dT%H:%M:%SZ"
|
|
744
|
+
exit 1
|
|
745
|
+
}
|
|
696
746
|
```
|
|
697
747
|
|
|
698
748
|
**由 orchestrator 强制执行**,不依赖 subagent 自觉遵守。
|
|
699
749
|
验证失败 → BLOCK,不可 dispatch 下一 Phase。
|
|
700
750
|
|
|
751
|
+
### RESUME GATE / --resume-from 断点校验(Issue #148)
|
|
752
|
+
|
|
753
|
+
当使用 `--resume-from <phase>` 时,在执行 Phase Transition Gate 之前,
|
|
754
|
+
orchestrator MUST 先执行以下断点校验。任何一项失败 → BLOCK,拒绝恢复。
|
|
755
|
+
|
|
756
|
+
```bash
|
|
757
|
+
SPRINT_STATE=".sprint-state/sprint-state.json"
|
|
758
|
+
[ -f "$SPRINT_STATE" ] || { echo "[BLOCK] sprint-state.json 不存在,无法恢复"; exit 1; }
|
|
759
|
+
|
|
760
|
+
# 1. Sprint ID 一致性:确认 resume 的目标 sprint 与 sprint-state.json 匹配
|
|
761
|
+
SPRINT_ID=$(grep -o '"id": "[^"]*"' "$SPRINT_STATE" | head -1 | cut -d'"' -f4)
|
|
762
|
+
CURRENT_SPRINT_ID=$(echo "$TASK_DESCRIPTION" | md5sum | head -8 2>/dev/null || echo "unknown")
|
|
763
|
+
# 实际 sprint id 由 Phase -1 生成,此处仅验证文件存在且包含 id 字段
|
|
764
|
+
[ -n "$SPRINT_ID" ] || { echo "[BLOCK] sprint-state.json 缺少 id 字段"; exit 1; }
|
|
765
|
+
|
|
766
|
+
# 2. 阶段顺序校验:--resume-from 的 phase 必须是最后已完成 phase 的后继
|
|
767
|
+
LAST_COMPLETED_PHASE=$(grep -o '"phase": [0-9]' "$SPRINT_STATE" | tail -1 | awk '{print $2}')
|
|
768
|
+
RESUME_PHASE=$((RESUME_PHASE)) # orchestrator 将 --resume-from 参数值转为整数
|
|
769
|
+
[ "$RESUME_PHASE" -gt "$LAST_COMPLETED_PHASE" ] || {
|
|
770
|
+
echo "[BLOCK] --resume-from phase ($RESUME_PHASE) 必须在最后已完成 phase ($LAST_COMPLETED_PHASE) 之后"
|
|
771
|
+
exit 1
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
# 3. Git 状态校验:isolation branch 仍然可达
|
|
775
|
+
ISOLATION_BRANCH=$(grep -o '"branch": "[^"]*"' "$SPRINT_STATE" | head -1 | cut -d'"' -f4)
|
|
776
|
+
ISOLATION_COMMIT=$(grep -o '"created_from_commit": "[^"]*"' "$SPRINT_STATE" | head -1 | cut -d'"' -f4)
|
|
777
|
+
if [ -n "$ISOLATION_BRANCH" ]; then
|
|
778
|
+
git rev-parse --verify "$ISOLATION_BRANCH" >/dev/null 2>&1 || {
|
|
779
|
+
echo "[BLOCK] isolation branch '$ISOLATION_BRANCH' 已不存在(可能被删除或 force push 覆盖)"
|
|
780
|
+
exit 1
|
|
781
|
+
}
|
|
782
|
+
fi
|
|
783
|
+
if [ -n "$ISOLATION_COMMIT" ]; then
|
|
784
|
+
git cat-file -e "${ISOLATION_COMMIT}^{commit}" 2>/dev/null || {
|
|
785
|
+
echo "[WARN] isolation commit $ISOLATION_COMMIT 不可达(可能被 GC 或 rebase 清理),恢复后可能状态不一致"
|
|
786
|
+
# WARN 而非 BLOCK — 可继续但有风险
|
|
787
|
+
}
|
|
788
|
+
fi
|
|
789
|
+
|
|
790
|
+
# 4. 文件时效性校验:前置摘要文件的 mtime 不晚于其生成 phase 的完成时间
|
|
791
|
+
RESUME_PREREQ_PHASE=$((RESUME_PHASE - 1))
|
|
792
|
+
PREREQ_FILE=".sprint-state/phase-outputs/phase-${RESUME_PREREQ_PHASE}-summary.md"
|
|
793
|
+
[ -f "$PREREQ_FILE" ] || { echo "[BLOCK] 前置摘要文件 ${PREREQ_FILE} 不存在"; exit 1; }
|
|
794
|
+
|
|
795
|
+
# 提取前置 phase 的完成时间
|
|
796
|
+
PREREQ_COMPLETED_AT=$(grep -A3 "\"phase\": $RESUME_PREREQ_PHASE" "$SPRINT_STATE" 2>/dev/null | grep "completed_at" | head -1 | cut -d'"' -f4)
|
|
797
|
+
if [ -n "$PREREQ_COMPLETED_AT" ] && [ "$PREREQ_COMPLETED_AT" != "null" ]; then
|
|
798
|
+
FILE_MTIME=$(stat -c %Y "$PREREQ_FILE" 2>/dev/null || stat -f %m "$PREREQ_FILE" 2>/dev/null)
|
|
799
|
+
COMPLETED_EPOCH=$(date -d "$PREREQ_COMPLETED_AT" +%s 2>/dev/null || echo "")
|
|
800
|
+
if [ -n "$FILE_MTIME" ] && [ -n "$COMPLETED_EPOCH" ]; then
|
|
801
|
+
# 容忍 60 秒时钟偏差
|
|
802
|
+
[ "$FILE_MTIME" -le $((COMPLETED_EPOCH + 60)) ] || {
|
|
803
|
+
echo "[WARN] 前置摘要文件 ${PREREQ_FILE} 在 phase $RESUME_PREREQ_PHASE 完成后被修改(mtime: $(date -d @$FILE_MTIME '+%Y-%m-%d %H:%M:%S'), completed_at: $PREREQ_COMPLETED_AT)"
|
|
804
|
+
echo "[ACTION] 继续恢复前请确认修改是预期的。输入 'confirm' 继续,其他取消:"
|
|
805
|
+
read USER_CONFIRM
|
|
806
|
+
[ "$USER_CONFIRM" = "confirm" ] || { echo "[BLOCK] 用户取消恢复"; exit 1; }
|
|
807
|
+
}
|
|
808
|
+
fi
|
|
809
|
+
fi
|
|
810
|
+
|
|
811
|
+
# 5. specification.yaml 时效性校验(仅 --resume-from build)
|
|
812
|
+
SPEC_FILE="specification.yaml"
|
|
813
|
+
if [ "$RESUME_PHASE" -ge 2 ] && [ -f "$SPEC_FILE" ]; then
|
|
814
|
+
SPEC_MTIME=$(stat -c %Y "$SPEC_FILE" 2>/dev/null || stat -f %m "$SPEC_FILE" 2>/dev/null)
|
|
815
|
+
PLAN_COMPLETED_AT=$(grep -A3 '"phase": 1' "$SPRINT_STATE" 2>/dev/null | grep "completed_at" | head -1 | cut -d'"' -f4)
|
|
816
|
+
if [ -n "$SPEC_MTIME" ] && [ -n "$PLAN_COMPLETED_AT" ] && [ "$PLAN_COMPLETED_AT" != "null" ]; then
|
|
817
|
+
PLAN_EPOCH=$(date -d "$PLAN_COMPLETED_AT" +%s 2>/dev/null || echo "")
|
|
818
|
+
if [ -n "$PLAN_EPOCH" ] && [ "$SPEC_MTIME" -gt $((PLAN_EPOCH + 60)) ]; then
|
|
819
|
+
echo "[WARN] specification.yaml 在 Plan phase 完成后被修改"
|
|
820
|
+
echo "[ACTION] 继续恢复前请确认 specification.yaml 的修改是预期的。输入 'confirm' 继续:"
|
|
821
|
+
read USER_CONFIRM
|
|
822
|
+
[ "$USER_CONFIRM" = "confirm" ] || { echo "[BLOCK] 用户取消恢复"; exit 1; }
|
|
823
|
+
fi
|
|
824
|
+
fi
|
|
825
|
+
fi
|
|
826
|
+
|
|
827
|
+
echo "✅ RESUME GATE PASSED — 断点校验通过"
|
|
828
|
+
# 继续执行 Phase Transition Gate
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
验证失败 → BLOCK,不可执行 `--resume-from`。
|
|
832
|
+
orchestrator 必须展示失败原因并建议用户启动新 Sprint 或手动修复后重试。
|
|
833
|
+
|
|
701
834
|
### WORKTREE ENFORCEMENT(Issue #84)
|
|
702
835
|
|
|
703
836
|
Phase -1 执行完毕后,**所有后续操作(Phase 0 到 Phase 8)的文件编辑、命令执行 MUST 在 worktree 目录下执行**:
|
|
@@ -796,12 +929,20 @@ Sprint state is persisted as JSON in `.sprint-state/sprint-state.json`:
|
|
|
796
929
|
|
|
797
930
|
### --resume-from(从某阶段继续)
|
|
798
931
|
|
|
932
|
+
**前置校验**:MUST 执行 RESUME GATE(见上节)后才可 dispatch 下一 Phase。
|
|
933
|
+
|
|
799
934
|
```bash
|
|
800
935
|
/sprint-flow "继续 Sprint" --resume-from build --spec specification.yaml
|
|
801
|
-
# →
|
|
936
|
+
# → 1. 执行 RESUME GATE(校验 sprint-state + git 状态 + 文件时效性)
|
|
937
|
+
# → 2. 执行 Phase Transition Gate(校验摘要文件格式)
|
|
938
|
+
# → 3. 从 Build 恢复,但必须已有 specification.yaml + .sprint-state/delphi-reviewed.json (verdict: APPROVED)
|
|
802
939
|
# 适用场景:中断恢复,使用已通过 delphi-review 的 specification.yaml
|
|
803
940
|
```
|
|
804
941
|
|
|
942
|
+
**已知限制**:
|
|
943
|
+
- `--resume-from` 校验为**尽力而为**:git commit 可被 GC 回收、文件 mtime 可被 `git checkout` 修改
|
|
944
|
+
- 校验失败时 orchestrator 应输出完整诊断日志,建议用户启动新 Sprint 而非手动修补
|
|
945
|
+
|
|
805
946
|
### --phase(只执行单个阶段)
|
|
806
947
|
|
|
807
948
|
```bash
|
|
@@ -954,7 +1095,9 @@ Sprint 结束时 (Phase 6 完成):
|
|
|
954
1095
|
|
|
955
1096
|
# 第二次:三天后继续
|
|
956
1097
|
/sprint-flow "继续开发" --resume-from build --spec docs/specification.yaml
|
|
957
|
-
# →
|
|
1098
|
+
# → 1. RESUME GATE:校验 sprint-state + git + 文件时效性(三天前生成的文件可能 stale)
|
|
1099
|
+
# → 2. Phase Transition Gate:校验摘要文件格式
|
|
1100
|
+
# → 3. 从 Build 入口恢复,但必须已有 specification.yaml + .sprint-state/delphi-reviewed.json (verdict: APPROVED)
|
|
958
1101
|
```
|
|
959
1102
|
|
|
960
1103
|
### 示例 3:语言特定
|