@boyingliu01/xp-gate 0.12.1 → 0.12.3
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/bin/xp-gate.js +22 -0
- package/gate-3.sh +68 -0
- package/gate-4.sh +80 -0
- package/gate-7.sh +45 -0
- package/gate-8.sh +56 -0
- package/gate-9.sh +130 -0
- package/lib/__tests__/update-hooks.test.js +573 -0
- package/lib/update-hooks.js +288 -0
- package/mock-policy/AGENTS.md +3 -3
- package/mutation/AGENTS.md +3 -3
- package/package.json +7 -2
- package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-code/skills/delphi-review/AGENTS.md +6 -6
- package/plugins/claude-code/skills/delphi-review/SKILL.md +34 -12
- package/plugins/claude-code/skills/sprint-flow/AGENTS.md +3 -3
- package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +3 -3
- package/plugins/opencode/package.json +1 -1
- package/plugins/opencode/skills/delphi-review/AGENTS.md +6 -6
- package/plugins/opencode/skills/delphi-review/SKILL.md +34 -12
- package/plugins/opencode/skills/sprint-flow/AGENTS.md +3 -3
- package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +3 -3
- package/plugins/qoder/plugin.json +1 -1
- package/plugins/qoder/skills/delphi-review/AGENTS.md +6 -6
- package/plugins/qoder/skills/delphi-review/SKILL.md +198 -264
- package/plugins/qoder/skills/sprint-flow/AGENTS.md +3 -3
- package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +3 -3
- package/principles/AGENTS.md +3 -3
- package/skills/delphi-review/AGENTS.md +6 -6
- package/skills/delphi-review/SKILL.md +34 -12
- package/skills/sprint-flow/AGENTS.md +3 -3
- package/skills/test-specification-alignment/AGENTS.md +3 -3
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @test REQ-265 update-hooks command
|
|
3
|
+
* @intent Sync latest hook versions from xp-gate package to project or global directory
|
|
4
|
+
* @covers AC-265-01, AC-265-02, AC-265-03, AC-265-04
|
|
5
|
+
*/
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { GLOBAL_HOOKS_DIR, GLOBAL_ADAPTERS_DIR } = require('./shared-paths.js');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Get the xp-gate package root directory (src/npm-package/).
|
|
12
|
+
* @returns {string}
|
|
13
|
+
*/
|
|
14
|
+
function getPackageRoot() {
|
|
15
|
+
return path.resolve(__dirname, '..');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get the project's git hooks directory.
|
|
20
|
+
* @throws {Error} If not in a git repository
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
23
|
+
function getProjectHooksDir() {
|
|
24
|
+
const gitDir = path.join(process.cwd(), '.git');
|
|
25
|
+
if (!fs.existsSync(gitDir)) {
|
|
26
|
+
throw new Error('Not a Git repository: .git directory not found');
|
|
27
|
+
}
|
|
28
|
+
return path.join(gitDir, 'hooks');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Detect locally modified hook files by comparing source and destination contents.
|
|
33
|
+
* @param {string} srcDir - Package root directory
|
|
34
|
+
* @param {string} hooksDestDir - Destination hooks directory
|
|
35
|
+
* @param {string} adaptersDestDir - Destination adapters directory
|
|
36
|
+
* @returns {string[]} List of locally modified file names
|
|
37
|
+
*/
|
|
38
|
+
function detectLocalModifications(srcDir, hooksDestDir, adaptersDestDir) {
|
|
39
|
+
const modified = [];
|
|
40
|
+
|
|
41
|
+
// Check hook files: pre-commit, pre-push
|
|
42
|
+
['pre-commit', 'pre-push'].forEach(hook => {
|
|
43
|
+
const srcPath = path.join(srcDir, 'hooks', hook);
|
|
44
|
+
const destPath = path.join(hooksDestDir, hook);
|
|
45
|
+
if (fs.existsSync(destPath) && fs.existsSync(srcPath)) {
|
|
46
|
+
const srcContent = fs.readFileSync(srcPath, 'utf8');
|
|
47
|
+
const destContent = fs.readFileSync(destPath, 'utf8');
|
|
48
|
+
if (srcContent !== destContent) {
|
|
49
|
+
modified.push(hook);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Check adapter-common.sh
|
|
55
|
+
const adapterCommonSrc = path.join(srcDir, 'adapter-common.sh');
|
|
56
|
+
const adapterCommonDest = path.join(adaptersDestDir, 'adapter-common.sh');
|
|
57
|
+
if (fs.existsSync(adapterCommonDest) && fs.existsSync(adapterCommonSrc)) {
|
|
58
|
+
const srcContent = fs.readFileSync(adapterCommonSrc, 'utf8');
|
|
59
|
+
const destContent = fs.readFileSync(adapterCommonDest, 'utf8');
|
|
60
|
+
if (srcContent !== destContent) {
|
|
61
|
+
modified.push('adapter-common.sh');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Check adapters/*.sh
|
|
66
|
+
const srcAdaptersDir = path.join(srcDir, 'adapters');
|
|
67
|
+
if (fs.existsSync(srcAdaptersDir)) {
|
|
68
|
+
fs.readdirSync(srcAdaptersDir).forEach(f => {
|
|
69
|
+
if (f.endsWith('.sh')) {
|
|
70
|
+
const srcPath = path.join(srcAdaptersDir, f);
|
|
71
|
+
const destPath = path.join(adaptersDestDir, 'adapters', f);
|
|
72
|
+
if (fs.existsSync(destPath) && fs.existsSync(srcPath)) {
|
|
73
|
+
const srcContent = fs.readFileSync(srcPath, 'utf8');
|
|
74
|
+
const destContent = fs.readFileSync(destPath, 'utf8');
|
|
75
|
+
if (srcContent !== destContent) {
|
|
76
|
+
modified.push(`adapters/${f}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Check gate-*.sh scripts
|
|
84
|
+
if (fs.existsSync(srcDir)) {
|
|
85
|
+
fs.readdirSync(srcDir).forEach(f => {
|
|
86
|
+
if (f.startsWith('gate-') && f.endsWith('.sh')) {
|
|
87
|
+
const srcPath = path.join(srcDir, f);
|
|
88
|
+
const destPath = path.join(adaptersDestDir, f);
|
|
89
|
+
if (fs.existsSync(destPath) && fs.existsSync(srcPath)) {
|
|
90
|
+
const srcContent = fs.readFileSync(srcPath, 'utf8');
|
|
91
|
+
const destContent = fs.readFileSync(destPath, 'utf8');
|
|
92
|
+
if (srcContent !== destContent) {
|
|
93
|
+
modified.push(f);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return modified;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Atomically copy a file: write to .tmp then rename. Create .bak backup if enabled.
|
|
105
|
+
* @param {string} src - Source file path
|
|
106
|
+
* @param {string} dest - Destination file path
|
|
107
|
+
* @param {boolean} dryRun - If true, only log what would happen
|
|
108
|
+
* @param {boolean} noBackup - If true, skip backup creation
|
|
109
|
+
* @param {string} label - Human-readable label for logging
|
|
110
|
+
* @returns {boolean} Whether the file was copied
|
|
111
|
+
*/
|
|
112
|
+
function atomicCopyFile(src, dest, dryRun, noBackup, label) {
|
|
113
|
+
if (!fs.existsSync(src)) {
|
|
114
|
+
console.warn(` ⚠ ${label} not found, skipping`);
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (dryRun) {
|
|
119
|
+
console.log(` would update: ${label}`);
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Ensure destination directory exists
|
|
124
|
+
const destDir = path.dirname(dest);
|
|
125
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
126
|
+
|
|
127
|
+
// Create backup if enabled
|
|
128
|
+
if (!noBackup && fs.existsSync(dest)) {
|
|
129
|
+
fs.copyFileSync(dest, `${dest}.bak`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Atomic write: temp file + rename
|
|
133
|
+
const tmpDest = `${dest}.tmp`;
|
|
134
|
+
fs.copyFileSync(src, tmpDest);
|
|
135
|
+
fs.renameSync(tmpDest, dest);
|
|
136
|
+
fs.chmodSync(dest, 0o755);
|
|
137
|
+
console.log(` ✓ ${label}`);
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Copy hook files (pre-commit, pre-push) from package to destination.
|
|
143
|
+
* @param {string} srcDir - Package root directory
|
|
144
|
+
* @param {string} destDir - Destination hooks directory
|
|
145
|
+
* @param {boolean} dryRun
|
|
146
|
+
* @param {boolean} noBackup
|
|
147
|
+
*/
|
|
148
|
+
function copyHooks(srcDir, destDir, dryRun, noBackup) {
|
|
149
|
+
const hooksSrcDir = path.join(srcDir, 'hooks');
|
|
150
|
+
['pre-commit', 'pre-push'].forEach(hook => {
|
|
151
|
+
const src = path.join(hooksSrcDir, hook);
|
|
152
|
+
const dest = path.join(destDir, hook);
|
|
153
|
+
atomicCopyFile(src, dest, dryRun, noBackup, hook);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Copy adapter files (adapter-common.sh + adapters/*.sh) from package to destination.
|
|
159
|
+
* @param {string} srcDir - Package root directory
|
|
160
|
+
* @param {string} destDir - Destination directory (githooks/ for local, adapters/ for global)
|
|
161
|
+
* @param {boolean} dryRun
|
|
162
|
+
* @param {boolean} noBackup
|
|
163
|
+
*/
|
|
164
|
+
function copyAdapters(srcDir, destDir, dryRun, noBackup) {
|
|
165
|
+
// Copy adapter-common.sh from package root
|
|
166
|
+
const adapterCommonSrc = path.join(srcDir, 'adapter-common.sh');
|
|
167
|
+
const adapterCommonDest = path.join(destDir, 'adapter-common.sh');
|
|
168
|
+
atomicCopyFile(adapterCommonSrc, adapterCommonDest, dryRun, noBackup, 'adapter-common.sh');
|
|
169
|
+
|
|
170
|
+
// Copy adapters/*.sh
|
|
171
|
+
const srcAdaptersDir = path.join(srcDir, 'adapters');
|
|
172
|
+
if (fs.existsSync(srcAdaptersDir)) {
|
|
173
|
+
fs.readdirSync(srcAdaptersDir).forEach(f => {
|
|
174
|
+
if (f.endsWith('.sh')) {
|
|
175
|
+
const src = path.join(srcAdaptersDir, f);
|
|
176
|
+
const dest = path.join(destDir, 'adapters', f);
|
|
177
|
+
atomicCopyFile(src, dest, dryRun, noBackup, `adapters/${f}`);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Copy gate-*.sh scripts from package root to destination.
|
|
185
|
+
* @param {string} srcDir - Package root directory
|
|
186
|
+
* @param {string} destDir - Destination directory
|
|
187
|
+
* @param {boolean} dryRun
|
|
188
|
+
* @param {boolean} noBackup
|
|
189
|
+
*/
|
|
190
|
+
function copyGateScripts(srcDir, destDir, dryRun, noBackup) {
|
|
191
|
+
if (!fs.existsSync(srcDir)) return;
|
|
192
|
+
fs.readdirSync(srcDir).forEach(f => {
|
|
193
|
+
if (f.startsWith('gate-') && f.endsWith('.sh')) {
|
|
194
|
+
const src = path.join(srcDir, f);
|
|
195
|
+
const dest = path.join(destDir, f);
|
|
196
|
+
atomicCopyFile(src, dest, dryRun, noBackup, f);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Main entry point: sync latest hook versions from xp-gate package to project or global directory.
|
|
203
|
+
*
|
|
204
|
+
* @param {Object} options
|
|
205
|
+
* @param {boolean} [options.global=false] - Update global hooks (~/.config/xp-gate/)
|
|
206
|
+
* @param {boolean} [options.force=false] - Skip local modification detection
|
|
207
|
+
* @param {boolean} [options.dryRun=false] - Show what would be updated without writing
|
|
208
|
+
* @param {boolean} [options.noBackup=false] - Skip creating .bak backup files
|
|
209
|
+
* @param {string} [options.scope='all'] - Selectively update: 'hooks', 'adapters', or 'all'
|
|
210
|
+
* @returns {number} Exit code (0 = success, 1 = error/warn)
|
|
211
|
+
*/
|
|
212
|
+
function updateHooks(options = {}) {
|
|
213
|
+
const { global = false, force = false, dryRun = false, noBackup = false, scope = 'all' } = options;
|
|
214
|
+
|
|
215
|
+
// Use module.exports.getPackageRoot() so tests can mock via mod.getPackageRoot
|
|
216
|
+
const srcDir = (module.exports && module.exports.getPackageRoot)
|
|
217
|
+
? module.exports.getPackageRoot()
|
|
218
|
+
: getPackageRoot();
|
|
219
|
+
|
|
220
|
+
// Determine destination directories based on mode
|
|
221
|
+
let hooksDestDir;
|
|
222
|
+
let adaptersDestDir;
|
|
223
|
+
|
|
224
|
+
if (global) {
|
|
225
|
+
hooksDestDir = GLOBAL_HOOKS_DIR;
|
|
226
|
+
adaptersDestDir = GLOBAL_ADAPTERS_DIR;
|
|
227
|
+
} else {
|
|
228
|
+
hooksDestDir = getProjectHooksDir();
|
|
229
|
+
// For local mode, adapters go to project's githooks/ directory
|
|
230
|
+
adaptersDestDir = path.join(process.cwd(), 'githooks');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Ensure destination directories exist
|
|
234
|
+
fs.mkdirSync(hooksDestDir, { recursive: true });
|
|
235
|
+
fs.mkdirSync(adaptersDestDir, { recursive: true });
|
|
236
|
+
fs.mkdirSync(path.join(adaptersDestDir, 'adapters'), { recursive: true });
|
|
237
|
+
|
|
238
|
+
console.log(`XP-Gate Update Hooks`);
|
|
239
|
+
console.log(`====================`);
|
|
240
|
+
console.log(`Mode: ${global ? 'Global' : 'Local'}`);
|
|
241
|
+
console.log(`Source: ${srcDir}`);
|
|
242
|
+
console.log(`Hooks destination: ${hooksDestDir}`);
|
|
243
|
+
console.log(`Adapters destination: ${adaptersDestDir}`);
|
|
244
|
+
console.log(`Scope: ${scope}`);
|
|
245
|
+
if (dryRun) console.log(`Dry run: yes (no files will be modified)`);
|
|
246
|
+
console.log('');
|
|
247
|
+
|
|
248
|
+
// Detect local modifications and warn (unless force or dryRun)
|
|
249
|
+
if (!force && !dryRun) {
|
|
250
|
+
const localMods = detectLocalModifications(srcDir, hooksDestDir, adaptersDestDir);
|
|
251
|
+
if (localMods.length > 0) {
|
|
252
|
+
console.warn(`[WARN] Detected ${localMods.length} locally modified file(s):`);
|
|
253
|
+
localMods.forEach(f => console.warn(` - ${f}`));
|
|
254
|
+
console.warn('Use --force to overwrite, or manually backup first.');
|
|
255
|
+
return 1;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Copy files based on scope
|
|
260
|
+
if (scope === 'all' || scope === 'hooks') {
|
|
261
|
+
console.log('Updating hooks...');
|
|
262
|
+
copyHooks(srcDir, hooksDestDir, dryRun, noBackup);
|
|
263
|
+
}
|
|
264
|
+
if (scope === 'all' || scope === 'adapters') {
|
|
265
|
+
console.log('Updating adapters...');
|
|
266
|
+
copyAdapters(srcDir, adaptersDestDir, dryRun, noBackup);
|
|
267
|
+
}
|
|
268
|
+
if (scope === 'all') {
|
|
269
|
+
console.log('Updating gate scripts...');
|
|
270
|
+
copyGateScripts(srcDir, adaptersDestDir, dryRun, noBackup);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (!dryRun) {
|
|
274
|
+
console.log('\nUpdate complete!');
|
|
275
|
+
}
|
|
276
|
+
return 0;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
module.exports = {
|
|
280
|
+
updateHooks,
|
|
281
|
+
detectLocalModifications,
|
|
282
|
+
copyHooks,
|
|
283
|
+
copyAdapters,
|
|
284
|
+
copyGateScripts,
|
|
285
|
+
atomicCopyFile,
|
|
286
|
+
getPackageRoot,
|
|
287
|
+
getProjectHooksDir,
|
|
288
|
+
};
|
package/mock-policy/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SRC/MOCK-POLICY KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-03
|
|
4
|
+
**Commit:** 83b39b6
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Mock layering policy enforcement — Gate M3 of pre-push hook. Ensures integration tests use real implementations for internal dependencies, mock external dependencies, and annotate pending mocks with removal plans. Combines project scope scanning, mock decision engine, and per-file validation into a single pipeline.
|
package/mutation/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SRC/MUTATION KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-03
|
|
4
|
+
**Commit:** 83b39b6
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**Gate M** (incremental mutation testing) + **Gate M2** helpers (test-layer detection used by `src/mock-policy/`). Pre-push quality gate. TypeScript-only; uses Stryker.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boyingliu01/xp-gate",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"description": "AI-driven development workflow: 6 quality gates + Delphi review + Sprint Flow",
|
|
5
5
|
"bin": {
|
|
6
6
|
"xp-gate": "./bin/xp-gate.js"
|
|
@@ -16,7 +16,12 @@
|
|
|
16
16
|
"principles/",
|
|
17
17
|
"mutation/",
|
|
18
18
|
"mock-policy/",
|
|
19
|
-
"build-integrity/"
|
|
19
|
+
"build-integrity/",
|
|
20
|
+
"gate-3.sh",
|
|
21
|
+
"gate-4.sh",
|
|
22
|
+
"gate-7.sh",
|
|
23
|
+
"gate-8.sh",
|
|
24
|
+
"gate-9.sh"
|
|
20
25
|
],
|
|
21
26
|
"exports": {
|
|
22
27
|
"./tui": "./plugins/opencode/tui-plugin.ts"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xp-gate",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"displayName": "XP-Gate",
|
|
5
5
|
"description": "Extreme Programming quality gates + AI workflow skills for Claude Code. Includes 10 quality gates (Gate 0-9), Sprint Flow (11 phases), and Delphi multi-expert review (>=90% consensus).",
|
|
6
6
|
"author": {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-03
|
|
4
|
+
**Commit:** 83b39b6
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, 3 experts from ≥2 providers, domestic models only). Supports design + code-walkthrough modes.
|
|
@@ -32,9 +32,9 @@ skills/delphi-review/
|
|
|
32
32
|
- 3 experts anonymous in Round 1 (no cross-expert bias)
|
|
33
33
|
- ≥90% consensus threshold (was 95%, now unified to 90%)
|
|
34
34
|
- Max 5 rounds before forcing decision
|
|
35
|
-
- Cross-provider required: experts from ≥2 different providers
|
|
36
|
-
-
|
|
37
|
-
-
|
|
35
|
+
- Cross-provider required: experts from ≥2 different providers (model list read from `opencode.json` agent config, not hardcoded)
|
|
36
|
+
- Model selection: reads `delphi-reviewer-*` agent `model` fields from `opencode.json`
|
|
37
|
+
- No hardcoded model lists — models defined by user's `opencode.json` configuration
|
|
38
38
|
- Code-walkthrough mode: triggered on git push, stores result in .code-walkthrough-result.json
|
|
39
39
|
- Code-walkthrough skipped on main/master pushes (by design)
|
|
40
40
|
|
|
@@ -88,22 +88,44 @@ Permitted variants (all satisfy L1 trigger):
|
|
|
88
88
|
| 2 专家(默认) | A(架构) + B(实现) | 代码变更、小型设计 |
|
|
89
89
|
| 3 专家 | A(架构) + B(实现) + C(可行性) | 架构决策、需求文档 |
|
|
90
90
|
|
|
91
|
-
###
|
|
91
|
+
### 模型选择策略(强制 — 从 opencode.json 读取)
|
|
92
92
|
|
|
93
|
-
**MUST
|
|
93
|
+
**MUST 从 `opencode.json` 的 agent 配置中读取模型**,**严禁** hardcode 模型名称。
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
| 阿里 Qwen | `qwen3.6-plus`, `qwen3.5-plus` |
|
|
100
|
-
| 智谱 GLM | `glm-5.1`, `glm-5.0` |
|
|
101
|
-
| MiniMax | `minimax-m2.7`, `minimax-m2.5` |
|
|
95
|
+
模型选择流程:
|
|
96
|
+
1. 读取 `opencode.json` 中 `agent` 字段下 `delphi-reviewer-architecture`、`delphi-reviewer-technical`、`delphi-reviewer-feasibility` 三个 agent 定义
|
|
97
|
+
2. 提取每个 agent 的 `model` 字段(格式:`provider/model-name`)
|
|
98
|
+
3. 分别作为 Expert A(架构)、Expert B(技术)、Expert C(可行性) 的模型
|
|
102
99
|
|
|
103
100
|
**关键原则**:
|
|
104
|
-
- ✅ 三个专家必须来自 **至少 2
|
|
105
|
-
- ❌
|
|
106
|
-
- ❌
|
|
101
|
+
- ✅ 三个专家必须来自 **至少 2 家不同 provider**(通过 `model` 字段的 `provider/` 前缀判断)
|
|
102
|
+
- ❌ 禁止 hardcode 模型名称(模型列表以 `opencode.json` 为准)
|
|
103
|
+
- ❌ 禁止三个专家全部使用同一 provider 的模型
|
|
104
|
+
|
|
105
|
+
**`opencode.json` agent 配置示例**(参考 `opencode.json.delphi.example`):
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"agent": {
|
|
109
|
+
"delphi-reviewer-architecture": {
|
|
110
|
+
"description": "...",
|
|
111
|
+
"mode": "subagent",
|
|
112
|
+
"model": "deepseek/deepseek-chat",
|
|
113
|
+
"tools": { "read": true, "bash": true, "write": false, "edit": false }
|
|
114
|
+
},
|
|
115
|
+
"delphi-reviewer-technical": {
|
|
116
|
+
"mode": "subagent",
|
|
117
|
+
"model": "bailian-coding-plan/qwen3.6-plus",
|
|
118
|
+
"tools": { "read": true, "bash": true, "write": false, "edit": false }
|
|
119
|
+
},
|
|
120
|
+
"delphi-reviewer-feasibility": {
|
|
121
|
+
"mode": "subagent",
|
|
122
|
+
"model": "deepseek/deepseek-chat",
|
|
123
|
+
"tools": { "read": true, "bash": true, "write": false, "edit": false }
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
> 上例中 3 个专家使用了 2 个不同 provider(deepseek + bailian-coding-plan),满足跨 provider 要求。**实际模型名称以你的 `opencode.json` 配置为准,无需在 SKILL.md 维护模型列表。**
|
|
107
129
|
|
|
108
130
|
### 共识阈值
|
|
109
131
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-03
|
|
4
|
+
**Commit:** 83b39b6
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**11-phase** development pipeline: ISOLATE → AUTO-ESTIMATE → THINK → PLAN → BUILD → REVIEW → SHIP → LAND → USER ACCEPTANCE → FEEDBACK → CLEANUP. Phase 2 default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE in Phase 1: design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-03
|
|
4
|
+
**Commit:** 83b39b6
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-03
|
|
4
|
+
**Commit:** 83b39b6
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, 3 experts from ≥2 providers, domestic models only). Supports design + code-walkthrough modes.
|
|
@@ -32,9 +32,9 @@ skills/delphi-review/
|
|
|
32
32
|
- 3 experts anonymous in Round 1 (no cross-expert bias)
|
|
33
33
|
- ≥90% consensus threshold (was 95%, now unified to 90%)
|
|
34
34
|
- Max 5 rounds before forcing decision
|
|
35
|
-
- Cross-provider required: experts from ≥2 different providers
|
|
36
|
-
-
|
|
37
|
-
-
|
|
35
|
+
- Cross-provider required: experts from ≥2 different providers (model list read from `opencode.json` agent config, not hardcoded)
|
|
36
|
+
- Model selection: reads `delphi-reviewer-*` agent `model` fields from `opencode.json`
|
|
37
|
+
- No hardcoded model lists — models defined by user's `opencode.json` configuration
|
|
38
38
|
- Code-walkthrough mode: triggered on git push, stores result in .code-walkthrough-result.json
|
|
39
39
|
- Code-walkthrough skipped on main/master pushes (by design)
|
|
40
40
|
|
|
@@ -88,22 +88,44 @@ Permitted variants (all satisfy L1 trigger):
|
|
|
88
88
|
| 2 专家(默认) | A(架构) + B(实现) | 代码变更、小型设计 |
|
|
89
89
|
| 3 专家 | A(架构) + B(实现) + C(可行性) | 架构决策、需求文档 |
|
|
90
90
|
|
|
91
|
-
###
|
|
91
|
+
### 模型选择策略(强制 — 从 opencode.json 读取)
|
|
92
92
|
|
|
93
|
-
**MUST
|
|
93
|
+
**MUST 从 `opencode.json` 的 agent 配置中读取模型**,**严禁** hardcode 模型名称。
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
| 阿里 Qwen | `qwen3.6-plus`, `qwen3.5-plus` |
|
|
100
|
-
| 智谱 GLM | `glm-5.1`, `glm-5.0` |
|
|
101
|
-
| MiniMax | `minimax-m2.7`, `minimax-m2.5` |
|
|
95
|
+
模型选择流程:
|
|
96
|
+
1. 读取 `opencode.json` 中 `agent` 字段下 `delphi-reviewer-architecture`、`delphi-reviewer-technical`、`delphi-reviewer-feasibility` 三个 agent 定义
|
|
97
|
+
2. 提取每个 agent 的 `model` 字段(格式:`provider/model-name`)
|
|
98
|
+
3. 分别作为 Expert A(架构)、Expert B(技术)、Expert C(可行性) 的模型
|
|
102
99
|
|
|
103
100
|
**关键原则**:
|
|
104
|
-
- ✅ 三个专家必须来自 **至少 2
|
|
105
|
-
- ❌
|
|
106
|
-
- ❌
|
|
101
|
+
- ✅ 三个专家必须来自 **至少 2 家不同 provider**(通过 `model` 字段的 `provider/` 前缀判断)
|
|
102
|
+
- ❌ 禁止 hardcode 模型名称(模型列表以 `opencode.json` 为准)
|
|
103
|
+
- ❌ 禁止三个专家全部使用同一 provider 的模型
|
|
104
|
+
|
|
105
|
+
**`opencode.json` agent 配置示例**(参考 `opencode.json.delphi.example`):
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"agent": {
|
|
109
|
+
"delphi-reviewer-architecture": {
|
|
110
|
+
"description": "...",
|
|
111
|
+
"mode": "subagent",
|
|
112
|
+
"model": "deepseek/deepseek-chat",
|
|
113
|
+
"tools": { "read": true, "bash": true, "write": false, "edit": false }
|
|
114
|
+
},
|
|
115
|
+
"delphi-reviewer-technical": {
|
|
116
|
+
"mode": "subagent",
|
|
117
|
+
"model": "bailian-coding-plan/qwen3.6-plus",
|
|
118
|
+
"tools": { "read": true, "bash": true, "write": false, "edit": false }
|
|
119
|
+
},
|
|
120
|
+
"delphi-reviewer-feasibility": {
|
|
121
|
+
"mode": "subagent",
|
|
122
|
+
"model": "deepseek/deepseek-chat",
|
|
123
|
+
"tools": { "read": true, "bash": true, "write": false, "edit": false }
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
> 上例中 3 个专家使用了 2 个不同 provider(deepseek + bailian-coding-plan),满足跨 provider 要求。**实际模型名称以你的 `opencode.json` 配置为准,无需在 SKILL.md 维护模型列表。**
|
|
107
129
|
|
|
108
130
|
### 共识阈值
|
|
109
131
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-03
|
|
4
|
+
**Commit:** 83b39b6
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**11-phase** development pipeline: ISOLATE → AUTO-ESTIMATE → THINK → PLAN → BUILD → REVIEW → SHIP → LAND → USER ACCEPTANCE → FEEDBACK → CLEANUP. Phase 2 default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE in Phase 1: design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-03
|
|
4
|
+
**Commit:** 83b39b6
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xp-gate",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"displayName": "XP-Gate",
|
|
5
5
|
"description": "Extreme Programming quality gates + AI workflow skills for Qoder. Includes 10 quality gates (Gate 0-9), Sprint Flow (11 phases), and Delphi multi-expert review (>=90% consensus).",
|
|
6
6
|
"author": {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-03
|
|
4
|
+
**Commit:** 83b39b6
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.12.
|
|
6
|
+
**Version:** 0.12.3.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, 3 experts from ≥2 providers, domestic models only). Supports design + code-walkthrough modes.
|
|
@@ -32,9 +32,9 @@ skills/delphi-review/
|
|
|
32
32
|
- 3 experts anonymous in Round 1 (no cross-expert bias)
|
|
33
33
|
- ≥90% consensus threshold (was 95%, now unified to 90%)
|
|
34
34
|
- Max 5 rounds before forcing decision
|
|
35
|
-
- Cross-provider required: experts from ≥2 different providers
|
|
36
|
-
-
|
|
37
|
-
-
|
|
35
|
+
- Cross-provider required: experts from ≥2 different providers (model list read from `opencode.json` agent config, not hardcoded)
|
|
36
|
+
- Model selection: reads `delphi-reviewer-*` agent `model` fields from `opencode.json`
|
|
37
|
+
- No hardcoded model lists — models defined by user's `opencode.json` configuration
|
|
38
38
|
- Code-walkthrough mode: triggered on git push, stores result in .code-walkthrough-result.json
|
|
39
39
|
- Code-walkthrough skipped on main/master pushes (by design)
|
|
40
40
|
|