@boyingliu01/xp-gate 0.14.30 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/java.sh +33 -4
- package/gate-9.sh +22 -48
- package/hooks/gate-9.sh +22 -48
- package/hooks/pre-commit +102 -44
- package/hooks/pre-push +1 -33
- package/lib/__tests__/doctor.test.js +34 -31
- package/lib/detect-deps.js +12 -0
- package/mock-policy/AGENTS.md +3 -3
- package/mutation/AGENTS.md +3 -3
- package/package.json +2 -2
- package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-code/skills/delphi-review/AGENTS.md +3 -3
- package/plugins/claude-code/skills/sprint-flow/AGENTS.md +3 -3
- package/plugins/claude-code/skills/sprint-flow/SKILL.md +1 -0
- package/plugins/claude-code/skills/sprint-flow/references/phase-3-build.md +71 -0
- 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 +3 -3
- package/plugins/opencode/skills/sprint-flow/AGENTS.md +3 -3
- package/plugins/opencode/skills/sprint-flow/SKILL.md +1 -0
- package/plugins/opencode/skills/sprint-flow/references/phase-3-build.md +71 -0
- 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 +3 -3
- 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/principles/adapters/python.ts +39 -6
- package/scripts/__tests__/sync-package-content.test.js +36 -17
- package/scripts/sync-package-content.js +5 -4
- package/skills/delphi-review/AGENTS.md +3 -3
- package/skills/sprint-flow/AGENTS.md +3 -3
- package/skills/sprint-flow/SKILL.md +1 -0
- package/skills/sprint-flow/references/phase-3-build.md +71 -0
- package/skills/test-specification-alignment/AGENTS.md +3 -3
|
@@ -377,34 +377,35 @@ describe('sync-package-content subprocess invocation', () => {
|
|
|
377
377
|
'to-issues',
|
|
378
378
|
];
|
|
379
379
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
380
|
+
/**
|
|
381
|
+
* afterAll: Ensure package directories are restored after all tests.
|
|
382
|
+
* Prevents race condition where other test files (e.g. doctor.test.js)
|
|
383
|
+
* read from src/npm-package/adapters/ while sync tests temporarily delete it.
|
|
384
|
+
*/
|
|
385
|
+
afterAll(() => {
|
|
386
|
+
const syncScript = path.join(WORKTREE_PATH, 'src', 'npm-package', 'scripts', 'sync-package-content.js');
|
|
387
|
+
spawnSync(process.execPath, [syncScript], {
|
|
388
|
+
cwd: WORKTREE_PATH,
|
|
389
|
+
stdio: 'pipe',
|
|
387
390
|
});
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
function restorePackageDirectories() {
|
|
391
|
-
// Restore from backup if they existed before test
|
|
392
|
-
// Since we just tested them being empty, just ensure they exist after sync
|
|
393
|
-
}
|
|
391
|
+
});
|
|
394
392
|
|
|
395
393
|
it('sync-package-content.js copies skills from repo to package', () => {
|
|
396
394
|
const syncScript = path.join(WORKTREE_PATH, 'src', 'npm-package', 'scripts', 'sync-package-content.js');
|
|
397
395
|
const nodeExe = process.execPath;
|
|
398
396
|
|
|
399
|
-
//
|
|
400
|
-
cleanupPackageDirectories();
|
|
401
|
-
|
|
402
|
-
// Run sync as subprocess
|
|
397
|
+
// Run sync as subprocess (overwrites existing files — no need to delete first)
|
|
403
398
|
const result = spawnSync(nodeExe, [syncScript], {
|
|
404
399
|
cwd: WORKTREE_PATH,
|
|
405
400
|
stdio: 'pipe',
|
|
401
|
+
timeout: 15000,
|
|
406
402
|
});
|
|
407
403
|
|
|
404
|
+
if (result.status !== 0) {
|
|
405
|
+
console.error('sync stderr:', result.stderr?.toString() || '(empty)');
|
|
406
|
+
console.error('sync stdout:', result.stdout?.toString() || '(empty)');
|
|
407
|
+
}
|
|
408
|
+
|
|
408
409
|
expect(result.status).toBe(0, 'sync script should exit with status 0');
|
|
409
410
|
|
|
410
411
|
// Verify skills were copied from repo to package
|
|
@@ -432,8 +433,14 @@ describe('sync-package-content subprocess invocation', () => {
|
|
|
432
433
|
const result = spawnSync(nodeExe, [syncScript], {
|
|
433
434
|
cwd: WORKTREE_PATH,
|
|
434
435
|
stdio: 'pipe',
|
|
436
|
+
timeout: 15000,
|
|
435
437
|
});
|
|
436
438
|
|
|
439
|
+
if (result.status !== 0) {
|
|
440
|
+
console.error('sync stderr:', result.stderr?.toString() || '(empty)');
|
|
441
|
+
console.error('sync stdout:', result.stdout?.toString() || '(empty)');
|
|
442
|
+
}
|
|
443
|
+
|
|
437
444
|
expect(result.status).toBe(0, 'sync script should exit with status 0');
|
|
438
445
|
|
|
439
446
|
// Verify plugin manifests were copied
|
|
@@ -454,8 +461,14 @@ describe('sync-package-content subprocess invocation', () => {
|
|
|
454
461
|
const result = spawnSync(nodeExe, [syncScript], {
|
|
455
462
|
cwd: WORKTREE_PATH,
|
|
456
463
|
stdio: 'pipe',
|
|
464
|
+
timeout: 15000,
|
|
457
465
|
});
|
|
458
466
|
|
|
467
|
+
if (result.status !== 0) {
|
|
468
|
+
console.error('sync stderr:', result.stderr?.toString() || '(empty)');
|
|
469
|
+
console.error('sync stdout:', result.stdout?.toString() || '(empty)');
|
|
470
|
+
}
|
|
471
|
+
|
|
459
472
|
expect(result.status).toBe(0, 'sync script should exit with status 0');
|
|
460
473
|
|
|
461
474
|
// Verify adapters directory exists and has files
|
|
@@ -480,8 +493,14 @@ describe('sync-package-content subprocess invocation', () => {
|
|
|
480
493
|
const result = spawnSync(nodeExe, [syncScript], {
|
|
481
494
|
cwd: WORKTREE_PATH,
|
|
482
495
|
stdio: 'pipe',
|
|
496
|
+
timeout: 15000,
|
|
483
497
|
});
|
|
484
498
|
|
|
499
|
+
if (result.status !== 0) {
|
|
500
|
+
console.error('sync stderr:', result.stderr?.toString() || '(empty)');
|
|
501
|
+
console.error('sync stdout:', result.stdout?.toString() || '(empty)');
|
|
502
|
+
}
|
|
503
|
+
|
|
485
504
|
expect(result.status).toBe(0, 'sync script should exit with status 0');
|
|
486
505
|
|
|
487
506
|
// Verify package.json dependencies remained empty
|
|
@@ -64,7 +64,7 @@ function copyDir(src, dest) {
|
|
|
64
64
|
|
|
65
65
|
function syncSkills() {
|
|
66
66
|
const destRoot = path.join(PKG_ROOT, 'skills');
|
|
67
|
-
rmrf
|
|
67
|
+
// In-place copy (no rmrf) to avoid race condition with parallel test readers.
|
|
68
68
|
fs.mkdirSync(destRoot, { recursive: true });
|
|
69
69
|
let copied = 0;
|
|
70
70
|
for (const name of CORE_SKILLS) {
|
|
@@ -80,7 +80,7 @@ function syncSkills() {
|
|
|
80
80
|
|
|
81
81
|
function injectCanonicalSkills(pluginDest) {
|
|
82
82
|
const skillsDest = path.join(pluginDest, 'skills');
|
|
83
|
-
rmrf
|
|
83
|
+
// In-place copy (no rmrf) to avoid race condition with parallel test readers.
|
|
84
84
|
fs.mkdirSync(skillsDest, { recursive: true });
|
|
85
85
|
for (const name of CORE_SKILLS) {
|
|
86
86
|
const src = path.join(REPO_ROOT, 'skills', name);
|
|
@@ -97,7 +97,7 @@ function injectCanonicalSkills(pluginDest) {
|
|
|
97
97
|
|
|
98
98
|
function syncPlugins() {
|
|
99
99
|
const destRoot = path.join(PKG_ROOT, 'plugins');
|
|
100
|
-
rmrf
|
|
100
|
+
// In-place copy (no rmrf) to avoid race condition with parallel test readers.
|
|
101
101
|
fs.mkdirSync(destRoot, { recursive: true });
|
|
102
102
|
let copied = 0;
|
|
103
103
|
for (const name of PLUGINS) {
|
|
@@ -139,7 +139,8 @@ function syncAdapters() {
|
|
|
139
139
|
console.error(`[sync] SKIP adapters (missing): ${srcRoot}`);
|
|
140
140
|
return 0;
|
|
141
141
|
}
|
|
142
|
-
rmrf
|
|
142
|
+
// In-place copy (no rmrf) to avoid race condition where parallel tests
|
|
143
|
+
// (e.g. doctor.test.js) read from destRoot during the delete-recreate window.
|
|
143
144
|
fs.mkdirSync(destRoot, { recursive: true });
|
|
144
145
|
const entries = fs.readdirSync(srcRoot, { withFileTypes: true });
|
|
145
146
|
let copied = 0;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-23
|
|
4
|
+
**Commit:** 1d581aa
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.15.0.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.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-23
|
|
4
|
+
**Commit:** 1d581aa
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.15.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -269,6 +269,7 @@ next_phase_context: [key info for next phase]
|
|
|
269
269
|
| Clean up CLOSE without backing up sprint-state first | `.sprint-state/` is inside worktree; it's lost on worktree removal. CLOSE step 1 MUST back up to repo-tracked path first |
|
|
270
270
|
| Keep adding random changes after verification failures | Max 3 fix cycles; if still failing, BLOCK and request user decision |
|
|
271
271
|
| Enter next phase without generating Phase Summary | Every phase MUST write `.sprint-state/phase-outputs/phase-{N}-summary.md` and pass transition gate |
|
|
272
|
+
| Complete implementation change without running verification | After every file edit/refactor/feature, MUST run `npm test` + `npm run lint` + `npx tsc --noEmit` and record the structured verification event (see `phase-3-build.md` §In-Session Verification) |
|
|
272
273
|
|
|
273
274
|
---
|
|
274
275
|
|
|
@@ -144,6 +144,77 @@ This enforcement is instructional (LLM follows SKILL.md instructions), not progr
|
|
|
144
144
|
|
|
145
145
|
---
|
|
146
146
|
|
|
147
|
+
## In-Session Verification (MANDATORY — v0.14.31+)
|
|
148
|
+
|
|
149
|
+
**Purpose**: Ensure every implementation change is immediately verified and recorded, enabling Better Loop Harness (and other observability tools) to capture normalized change→validation event pairs.
|
|
150
|
+
|
|
151
|
+
**Problem it solves**: Without explicit in-session verification, Agents may edit files and move on without running tests or linters. This creates unverified changes that are invisible to post-hoc review tools, breaking the traceability chain between "what changed" and "was it validated".
|
|
152
|
+
|
|
153
|
+
### Mandatory Verification Protocol
|
|
154
|
+
|
|
155
|
+
After **every** implementation change (file edit, refactor, new feature, bug fix), the Agent MUST execute the following sequence BEFORE claiming the change is complete:
|
|
156
|
+
|
|
157
|
+
1. **Run tests**: `npm test` or `npx vitest run` (or project-specific test command)
|
|
158
|
+
2. **Run linter**: `npm run lint` or `npx eslint .` (or project-specific lint command)
|
|
159
|
+
3. **Type-check** (TypeScript projects): `npx tsc --noEmit`
|
|
160
|
+
4. **Record the result**: Append a structured verification event (see format below)
|
|
161
|
+
|
|
162
|
+
### Verification Event Format
|
|
163
|
+
|
|
164
|
+
Each verification event MUST be recorded as a structured JSON object. Agents should output this to stdout or append to `.sprint-state/phase-outputs/verification-events.jsonl`:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"timestamp": "2026-07-22T10:30:00Z",
|
|
169
|
+
"change": {
|
|
170
|
+
"type": "edit|refactor|feature|bugfix",
|
|
171
|
+
"files": ["src/lib/auth.ts", "src/lib/auth.test.ts"],
|
|
172
|
+
"description": "Implement validateToken() for expired token handling"
|
|
173
|
+
},
|
|
174
|
+
"verification": {
|
|
175
|
+
"tests": { "command": "npx vitest run src/lib/auth.test.ts", "status": "pass|fail", "summary": "4 passed, 0 failed" },
|
|
176
|
+
"lint": { "command": "npm run lint", "status": "pass|fail|warn", "summary": "0 errors, 2 warnings" },
|
|
177
|
+
"typecheck": { "command": "npx tsc --noEmit", "status": "pass|fail|skip", "summary": "No type errors" }
|
|
178
|
+
},
|
|
179
|
+
"outcome": "verified|failed|partial",
|
|
180
|
+
"req": "REQ-003"
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Integration with ralph-loop
|
|
185
|
+
|
|
186
|
+
When using ralph-loop mode (default BUILD strategy), each REQ iteration MUST include verification as the final step before marking the REQ complete:
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
ralph-loop iteration:
|
|
190
|
+
1. [TDD-RED] Write failing test
|
|
191
|
+
2. [TDD-GREEN] Implement minimal code to pass
|
|
192
|
+
3. [TDD-REFACTOR] Clean up while keeping tests green
|
|
193
|
+
4. [VERIFY] Run tests + lint + typecheck ← MANDATORY
|
|
194
|
+
5. [RECORD] Append verification event ← MANDATORY
|
|
195
|
+
6. Mark REQ complete and continue to next
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Anti-Patterns
|
|
199
|
+
|
|
200
|
+
| ❌ Error | ✅ Correct |
|
|
201
|
+
|----------|----------|
|
|
202
|
+
| Edit file → claim done → move to next task | Edit file → run tests + lint → record result → claim done |
|
|
203
|
+
| "Tests should pass" (assertion without evidence) | "Tests passed: 4 passed, 0 failed (npx vitest run)" |
|
|
204
|
+
| Run tests only at end of entire BUILD phase | Run tests after every individual change/REQ |
|
|
205
|
+
| Skip type-check because "I didn't touch types" | Always run `tsc --noEmit` on TypeScript projects |
|
|
206
|
+
|
|
207
|
+
### Harness Integration
|
|
208
|
+
|
|
209
|
+
Better Loop Harness captures change and verification events by inspecting session history. The structured verification events above serve as the canonical signal that:
|
|
210
|
+
- A change occurred (the `change` field)
|
|
211
|
+
- The change was validated (the `verification` field)
|
|
212
|
+
- The outcome is attributable (the `outcome` field ties result to specific change)
|
|
213
|
+
|
|
214
|
+
Without these events, the Harness can only infer changes from file diffs and has no verification signal, resulting in lower "改动验证" (Change Verification) dimension scores.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
147
218
|
## TDD 强制执行
|
|
148
219
|
|
|
149
220
|
### Gate 5a-BLOCK: 新增文件测试强制
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-07-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-07-23
|
|
4
|
+
**Commit:** 1d581aa
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.15.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|