@boyingliu01/xp-gate 0.35.0 → 0.35.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.
Files changed (37) hide show
  1. package/bin/xp-gate.js +23 -0
  2. package/hooks/pre-commit +92 -0
  3. package/lib/__tests__/doctor-drift-direction.test.js +104 -0
  4. package/lib/__tests__/gate-coverage.test.js +137 -0
  5. package/lib/__tests__/rework.test.js +127 -0
  6. package/lib/__tests__/test-alignment.test.ts +45 -4
  7. package/lib/doctor.js +82 -8
  8. package/lib/gate-audit.ts +8 -0
  9. package/lib/gate-coverage.js +315 -0
  10. package/lib/mattpocock-license-verdict.json +1 -1
  11. package/lib/rework.js +262 -0
  12. package/lib/test-alignment.ts +27 -7
  13. package/mock-policy/AGENTS.md +2 -2
  14. package/mutation/AGENTS.md +2 -2
  15. package/package.json +1 -1
  16. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  17. package/plugins/claude-code/skills/delphi-review/AGENTS.md +2 -2
  18. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +2 -2
  19. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +2 -2
  20. package/plugins/dsh/package.json +1 -1
  21. package/plugins/dsh/skills/delphi-review/AGENTS.md +2 -2
  22. package/plugins/dsh/skills/sprint-flow/AGENTS.md +2 -2
  23. package/plugins/dsh/skills/test-specification-alignment/AGENTS.md +2 -2
  24. package/plugins/opencode/package.json +1 -1
  25. package/plugins/opencode/skills/delphi-review/AGENTS.md +2 -2
  26. package/plugins/opencode/skills/sprint-flow/AGENTS.md +2 -2
  27. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +2 -2
  28. package/plugins/qoder/plugin.json +1 -1
  29. package/plugins/qoder/skills/delphi-review/AGENTS.md +2 -2
  30. package/plugins/qoder/skills/sprint-flow/AGENTS.md +2 -2
  31. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +2 -2
  32. package/principles/AGENTS.md +2 -2
  33. package/scripts/__tests__/sync-package-content-isolation.test.js +73 -0
  34. package/scripts/__tests__/sync-package-content.test.js +109 -2
  35. package/skills/delphi-review/AGENTS.md +2 -2
  36. package/skills/sprint-flow/AGENTS.md +2 -2
  37. package/skills/test-specification-alignment/AGENTS.md +2 -2
@@ -27,6 +27,37 @@ function writeDoc(filePath, content) {
27
27
  fs.writeFileSync(filePath, content, 'utf8');
28
28
  }
29
29
 
30
+ /**
31
+ * Copy the canonical source trees a sync run READS into `destRoot` (#645).
32
+ *
33
+ * The sync script mirrors githooks/, skills/, plugins/ and every src/ module into
34
+ * the package. Seeding the whole of `src/` except the package itself keeps this
35
+ * list from rotting: syncModules() gains a module, this helper needs no edit.
36
+ * Only reads from the real checkout -- nothing is ever written back to it.
37
+ */
38
+ function seedCanonicalSources(realRoot, destRoot) {
39
+ const real = realRoot || path.resolve(__dirname, '..', '..', '..', '..');
40
+ const dest = destRoot;
41
+ for (const tree of ['githooks', 'skills', 'plugins']) {
42
+ const from = path.join(real, tree);
43
+ if (fs.existsSync(from)) fs.cpSync(from, path.join(dest, tree), { recursive: true });
44
+ }
45
+ const srcRoot = path.join(real, 'src');
46
+ for (const name of fs.readdirSync(srcRoot)) {
47
+ // The package itself is the DESTINATION of the sync, not a canonical source;
48
+ // copying it would let the test compare a mirror against a stale mirror.
49
+ if (name === 'npm-package') continue;
50
+ const from = path.join(srcRoot, name);
51
+ if (fs.statSync(from).isDirectory()) {
52
+ fs.cpSync(from, path.join(dest, 'src', name), { recursive: true });
53
+ }
54
+ }
55
+ fs.mkdirSync(path.join(dest, 'src', 'npm-package', 'scripts'), { recursive: true });
56
+ for (const rel of ['scripts/sync-package-content.js', 'package.json']) {
57
+ fs.copyFileSync(path.join(srcRoot, 'npm-package', rel), path.join(dest, 'src', 'npm-package', rel));
58
+ }
59
+ }
60
+
30
61
  describe('checkDocsDrift', () => {
31
62
  let tempDir;
32
63
  let preCommitPath;
@@ -269,12 +300,56 @@ describe('syncGateScripts', () => {
269
300
  * @covers AC-450-01, AC-450-02, AC-450-03, AC-450-04
270
301
  */
271
302
  describe('syncHooks', () => {
272
- const WORKTREE_PATH = path.resolve(__dirname, '..', '..', '..', '..');
303
+ // #645: run the sync against a THROWAWAY worktree, never the checkout.
304
+ //
305
+ // This block used to spawn the real sync script with
306
+ // cwd: path.resolve(__dirname, '..', '..', '..', '..')
307
+ // -- four levels up from src/npm-package/scripts/__tests__ is the REPOSITORY
308
+ // ROOT, not a temp dir -- so the script's writes landed in the repo and CI's
309
+ // Gate 5 failed at vitest-worktree-guard with
310
+ // Work tree polluted by the test run: M src/npm-package/mock-policy/gate-m3.ts
311
+ //
312
+ // The pollution was CONDITIONAL (the writes are idempotent, so it only dirties
313
+ // the tree when the checked-out commit carries a stale mirror), which made it
314
+ // look flaky and encouraged "just re-run it" -- hiding the cause. The guard
315
+ // catches the consequence; a temp cwd removes the cause.
316
+ const REAL_REPO_ROOT = path.resolve(__dirname, '..', '..', '..', '..');
317
+ const TMP_WORKTREE = fs.mkdtempSync(path.join(os.tmpdir(), 'xp-gate-sync-hooks-'));
318
+ const WORKTREE_PATH = TMP_WORKTREE;
273
319
  const PKG_ROOT = path.join(WORKTREE_PATH, 'src', 'npm-package');
274
320
  const HOOKS_DIR = path.join(PKG_ROOT, 'hooks');
275
321
  const syncScript = path.join(WORKTREE_PATH, 'src', 'npm-package', 'scripts', 'sync-package-content.js');
276
322
  const nodeExe = process.execPath;
277
323
 
324
+ /**
325
+ * Lay out just enough of the repo shape inside the temp root for the sync script
326
+ * to read its canonical sources and write its mirrors. Copies only the trees the
327
+ * script touches: githooks/ (the hook source of truth) and the packages it
328
+ * mirrors into. The REAL checkout is only ever READ.
329
+ */
330
+ function seedTempWorktree() {
331
+ seedCanonicalSources(REAL_REPO_ROOT, WORKTREE_PATH);
332
+ fs.mkdirSync(path.join(PKG_ROOT, 'scripts'), { recursive: true });
333
+ fs.copyFileSync(
334
+ path.join(REAL_REPO_ROOT, 'src', 'npm-package', 'scripts', 'sync-package-content.js'),
335
+ syncScript,
336
+ );
337
+ // The script resolves its package root relative to its own location, so it
338
+ // must sit at <temp>/src/npm-package/scripts/ exactly as in the real tree.
339
+ fs.copyFileSync(
340
+ path.join(REAL_REPO_ROOT, 'src', 'npm-package', 'package.json'),
341
+ path.join(PKG_ROOT, 'package.json'),
342
+ );
343
+ }
344
+
345
+ beforeAll(() => {
346
+ seedTempWorktree();
347
+ });
348
+
349
+ afterAll(() => {
350
+ fs.rmSync(TMP_WORKTREE, { recursive: true, force: true });
351
+ });
352
+
278
353
  // Ensure hooks are re-synced once before tests run; share the result.
279
354
  let syncOk = false;
280
355
  beforeAll(() => {
@@ -473,9 +548,41 @@ describe('checkAdapterDrift', () => {
473
548
  const { spawnSync } = require('child_process');
474
549
 
475
550
  describe('sync-package-content subprocess invocation', () => {
476
- const WORKTREE_PATH = path.resolve(__dirname, '..', '..', '..', '..');
551
+ // #645: same rule as the syncHooks block above -- a test may not write into the
552
+ // repository. `path.resolve(__dirname, '..', '..', '..', '..')` IS the repo root,
553
+ // so spawning the sync script with it as cwd copied mirrors over the checkout and
554
+ // CI's Gate 5 failed at vitest-worktree-guard.
555
+ //
556
+ // This block additionally DELETES package directories to prove the sync
557
+ // recreates them, which is precisely the operation that must never touch a real
558
+ // checkout. Everything therefore runs inside a throwaway tree seeded from the
559
+ // real sources (read-only).
560
+ const REAL_REPO_ROOT = path.resolve(__dirname, '..', '..', '..', '..');
561
+ const TMP_WORKTREE = fs.mkdtempSync(path.join(os.tmpdir(), 'xp-gate-sync-sub-'));
562
+ const WORKTREE_PATH = TMP_WORKTREE;
477
563
  const PKG_ROOT = path.join(WORKTREE_PATH, 'src', 'npm-package');
478
564
  const REPO_ROOT = path.join(WORKTREE_PATH);
565
+
566
+ function seedTempWorktree() {
567
+ seedCanonicalSources(REAL_REPO_ROOT, WORKTREE_PATH);
568
+ fs.mkdirSync(path.join(PKG_ROOT, 'scripts'), { recursive: true });
569
+ fs.copyFileSync(
570
+ path.join(REAL_REPO_ROOT, 'src', 'npm-package', 'scripts', 'sync-package-content.js'),
571
+ path.join(PKG_ROOT, 'scripts', 'sync-package-content.js'),
572
+ );
573
+ fs.copyFileSync(
574
+ path.join(REAL_REPO_ROOT, 'src', 'npm-package', 'package.json'),
575
+ path.join(PKG_ROOT, 'package.json'),
576
+ );
577
+ }
578
+
579
+ beforeAll(() => {
580
+ seedTempWorktree();
581
+ });
582
+
583
+ afterAll(() => {
584
+ fs.rmSync(TMP_WORKTREE, { recursive: true, force: true });
585
+ });
479
586
  const CORE_SKILLS = [
480
587
  'admin-template-guidelines',
481
588
  'delphi-review',
@@ -1,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-10-30
4
- **Commit:** c8a73b2a
4
+ **Commit:** 0a400e4c
5
5
  **Branch:** main
6
- **Version:** 0.35.0.0
6
+ **Version:** 0.35.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, exactly 3 experts with distinct executable model IDs). Supports design, requirements, and code-walkthrough modes.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/SPRINT-FLOW KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-10-30
4
- **Commit:** c8a73b2a
4
+ **Commit:** 0a400e4c
5
5
  **Branch:** main
6
- **Version:** 0.35.0.0
6
+ **Version:** 0.35.2.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.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-10-30
4
- **Commit:** c8a73b2a
4
+ **Commit:** 0a400e4c
5
5
  **Branch:** main
6
- **Version:** 0.35.0.0
6
+ **Version:** 0.35.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.