@boyingliu01/xp-gate 0.29.0 → 0.30.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.
Files changed (47) hide show
  1. package/gate-3.sh +18 -1
  2. package/hooks/gate-3.sh +18 -1
  3. package/hooks/hook-module-resolution.sh +39 -0
  4. package/hooks/pre-commit +118 -39
  5. package/hooks/pre-push +26 -2
  6. package/lib/__tests__/doctor-module-resolution-parity.test.js +79 -11
  7. package/lib/__tests__/sprint-state-manager.test.js +31 -0
  8. package/lib/doctor.js +60 -27
  9. package/lib/hook-module-resolution.js +127 -0
  10. package/lib/mattpocock-license-verdict.json +1 -1
  11. package/lib/retro.js +24 -7
  12. package/lib/sprint-state-manager.js +14 -6
  13. package/mock-policy/AGENTS.md +3 -3
  14. package/mutation/AGENTS.md +3 -3
  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 +3 -3
  18. package/plugins/claude-code/skills/grill-with-docs/SKILL.md +1 -0
  19. package/plugins/claude-code/skills/grilling/SKILL.md +1 -0
  20. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +3 -3
  21. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +3 -3
  22. package/plugins/dsh/package.json +1 -1
  23. package/plugins/dsh/skills/delphi-review/AGENTS.md +3 -3
  24. package/plugins/dsh/skills/grill-with-docs/SKILL.md +1 -0
  25. package/plugins/dsh/skills/grilling/SKILL.md +1 -0
  26. package/plugins/dsh/skills/sprint-flow/AGENTS.md +3 -3
  27. package/plugins/dsh/skills/test-specification-alignment/AGENTS.md +3 -3
  28. package/plugins/opencode/package.json +1 -1
  29. package/plugins/opencode/skills/delphi-review/AGENTS.md +3 -3
  30. package/plugins/opencode/skills/grill-with-docs/SKILL.md +1 -0
  31. package/plugins/opencode/skills/grilling/SKILL.md +1 -0
  32. package/plugins/opencode/skills/sprint-flow/AGENTS.md +3 -3
  33. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +3 -3
  34. package/plugins/qoder/plugin.json +1 -1
  35. package/plugins/qoder/skills/batch-grill-me/SKILL.md +9 -2
  36. package/plugins/qoder/skills/delphi-review/AGENTS.md +3 -3
  37. package/plugins/qoder/skills/grill-with-docs/SKILL.md +2 -2
  38. package/plugins/qoder/skills/grilling/SKILL.md +23 -5
  39. package/plugins/qoder/skills/sprint-flow/AGENTS.md +3 -3
  40. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +3 -3
  41. package/principles/AGENTS.md +3 -3
  42. package/scripts/sync-package-content.js +3 -1
  43. package/skills/delphi-review/AGENTS.md +3 -3
  44. package/skills/grill-with-docs/SKILL.md +1 -0
  45. package/skills/grilling/SKILL.md +1 -0
  46. package/skills/sprint-flow/AGENTS.md +3 -3
  47. package/skills/test-specification-alignment/AGENTS.md +3 -3
package/lib/doctor.js CHANGED
@@ -15,6 +15,9 @@ const {
15
15
  } = require('./shared-paths.js');
16
16
  const { checkUpgrade, formatUpgradeMsg } = require('./check-version.js');
17
17
  const { GATE_CLI_TOOLS, checkCliTool, getToolInstallCmd, checkBash } = require('./detect-deps.js');
18
+ // #505: the single source of truth for module resolution order. The hook reads a
19
+ // generated shell projection of this same module.
20
+ const { RESOLUTION_ORDER } = require('./hook-module-resolution.js');
18
21
  const {
19
22
  diagnoseTuiRegistration, diagnoseInstalledSkills,
20
23
  fixTuiRegistration, ensureTuiRegistration, readTuiJson,
@@ -398,6 +401,16 @@ function pathsEquivalent(a, b) {
398
401
  */
399
402
  const DRIFT_COMPARED_HOOKS = ['pre-commit', 'pre-push', 'post-merge'];
400
403
 
404
+ /**
405
+ * Non-hook files that must sit beside the installed hooks.
406
+ *
407
+ * These are not Git entry points, so they are not in DRIFT_COMPARED_HOOKS, but
408
+ * the hooks source them and die without them:
409
+ * - hook-module-resolution.sh (#505): pre-commit aborts FATAL when the module
410
+ * resolution order is missing. It is generated from lib/hook-module-resolution.js.
411
+ */
412
+ const HOOK_SUPPORT_FILES = ['hook-module-resolution.sh'];
413
+
401
414
  /**
402
415
  * Compare the hooks that actually execute (the installed copy under
403
416
  * core.hooksPath) against the repository's source-of-truth `githooks/` (#451).
@@ -546,35 +559,35 @@ function listExecutedModules(installedAdapterDir) {
546
559
  const found = [];
547
560
  const seen = new Set();
548
561
 
549
- let entries;
550
- try {
551
- entries = fs.readdirSync(installedAdapterDir, { withFileTypes: true });
552
- } catch {
553
- return found;
554
- }
562
+ // #505: the tier order is DATA, not a second implementation. The hook reads a
563
+ // generated shell projection of the same module; both reference
564
+ // RESOLUTION_ORDER, so "which copy executes" has one answer. Previously this
565
+ // function re-derived the order by hand and a parity test was the only thing
566
+ // keeping it honest.
567
+ //
568
+ // Tiers are walked in order; a name is reported once, from the first tier that
569
+ // resolves it — matching the hook, which stops at the first existing file.
570
+ for (const tier of RESOLUTION_ORDER) {
571
+ // Only the two ADAPTER_DIR-rooted tiers describe the installed adapter dir.
572
+ if (tier.base !== 'ADAPTER_DIR') continue;
573
+ // `{name}.sh` (flat) -> the dir itself; `adapters/{name}.sh` -> <dir>/adapters.
574
+ const dir = tier.template.includes('/')
575
+ ? path.join(installedAdapterDir, tier.template.split('/{name}.sh')[0])
576
+ : installedAdapterDir;
555
577
 
556
- for (const entry of entries) {
557
- if (!entry.isFile() || !entry.name.endsWith('.sh')) continue;
558
- const file = path.join(installedAdapterDir, entry.name);
559
- if (seen.has(entry.name)) continue;
560
- seen.add(entry.name);
561
- found.push({ name: entry.name, file });
562
- }
578
+ let entries;
579
+ try {
580
+ entries = fs.readdirSync(dir, { withFileTypes: true });
581
+ } catch {
582
+ continue;
583
+ }
563
584
 
564
- // Nested copies only count for names with no flat counterpart, because that
565
- // is exactly the fallback resolve_adapter_path() takes.
566
- const nestedDir = path.join(installedAdapterDir, 'adapters');
567
- let nestedEntries = [];
568
- try {
569
- nestedEntries = fs.readdirSync(nestedDir, { withFileTypes: true });
570
- } catch {
571
- nestedEntries = [];
572
- }
573
- for (const entry of nestedEntries) {
574
- if (!entry.isFile() || !entry.name.endsWith('.sh')) continue;
575
- if (seen.has(entry.name)) continue;
576
- seen.add(entry.name);
577
- found.push({ name: entry.name, file: path.join(nestedDir, entry.name) });
585
+ for (const entry of entries) {
586
+ if (!entry.isFile() || !entry.name.endsWith('.sh')) continue;
587
+ if (seen.has(entry.name)) continue;
588
+ seen.add(entry.name);
589
+ found.push({ name: entry.name, file: path.join(dir, entry.name) });
590
+ }
578
591
  }
579
592
 
580
593
  return found;
@@ -1153,6 +1166,26 @@ function syncGlobalHooksFromRepo(ctx = {}) {
1153
1166
  }
1154
1167
  }
1155
1168
 
1169
+ // Hook support files (#505): sourced by the hooks but not Git entry points, so
1170
+ // they need the same copy treatment or an upgraded install dies at the source
1171
+ // line. Treated like the hooks themselves (always refreshed, no refusal) —
1172
+ // they hold no machine-local content.
1173
+ for (const name of HOOK_SUPPORT_FILES) {
1174
+ const source = path.join(repoHooks, name);
1175
+ if (!fs.existsSync(source)) continue;
1176
+ const target = path.join(installedHooks, name);
1177
+ try {
1178
+ if (fs.existsSync(target) && filesAreIdentical(source, target)) {
1179
+ skipped.push(name);
1180
+ continue;
1181
+ }
1182
+ fs.copyFileSync(source, target);
1183
+ synced.push(name);
1184
+ } catch (err) {
1185
+ errors.push(`${name}: ${err.message}`);
1186
+ }
1187
+ }
1188
+
1156
1189
  // lib/ shared libraries: pre-commit sources lib/*.sh, so a synced hook file
1157
1190
  // without its libraries dies at the source line on the machine (#488).
1158
1191
  const repoLib = path.join(repoHooks, 'lib');
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Single source of truth for hook module resolution order (#505).
4
+ *
5
+ * THE PROBLEM THIS SOLVES
6
+ * The order in which a hook finds its modules (adapter-common.sh, gate-*.sh,
7
+ * lib/*.sh, language adapters) used to be written out twice: once in shell
8
+ * (`resolve_adapter_path()` and the `GATE_DIR` cascade in githooks/pre-commit)
9
+ * and once in JavaScript (`listExecutedModules()` in lib/doctor.js). The two must
10
+ * agree or doctor reports a different module surface than the one that actually
11
+ * executes — exactly the divergence behind #495/#500. A parity test pinned the
12
+ * behaviour, but a test only fails AFTER someone writes the wrong thing; the
13
+ * order itself was still duplicated.
14
+ *
15
+ * THE FIX
16
+ * The order lives here, in RESOLUTION_ORDER, as data. Both sides read it:
17
+ * - JS: require('./hook-module-resolution.js') (doctor.js)
18
+ * - SH: the hook sources hook-module-resolution.sh, GENERATED from this file
19
+ * by `node scripts/generate-hook-resolution.sh` (run by sync-package-content).
20
+ * A change to the order reaches the shell automatically; drifting requires
21
+ * deliberately ignoring the generator.
22
+ *
23
+ * SCOPE NOTE: this is the ADAPTER/GATE lookup order only. It does not change
24
+ * which files are installed or how they are copied.
25
+ */
26
+
27
+ /**
28
+ * Ordered resolution tiers. The first tier that contains the requested file wins.
29
+ *
30
+ * `base` names which directory variable supplies the root; `template` is the path
31
+ * relative to it, with `{name}` standing for the module basename.
32
+ *
33
+ * `tier_id` is stable and is what shell and JS compare on, so both can report the
34
+ * same tier for the same file without string-matching paths.
35
+ */
36
+ const RESOLUTION_ORDER = Object.freeze([
37
+ Object.freeze({
38
+ tier_id: 'adapter_flat',
39
+ base: 'ADAPTER_DIR',
40
+ template: '{name}.sh',
41
+ comment: 'Global install layout: modules sit flat next to adapter-common.sh',
42
+ }),
43
+ Object.freeze({
44
+ tier_id: 'adapter_nested',
45
+ base: 'ADAPTER_DIR',
46
+ template: 'adapters/{name}.sh',
47
+ comment: 'Nested layout under the adapter dir',
48
+ }),
49
+ Object.freeze({
50
+ tier_id: 'project_nested',
51
+ base: 'PROJECT_GITHOOKS',
52
+ template: 'adapters/{name}.sh',
53
+ comment: 'Project githooks adapters/',
54
+ }),
55
+ Object.freeze({
56
+ tier_id: 'script_nested',
57
+ base: 'SCRIPT_DIR',
58
+ template: 'adapters/{name}.sh',
59
+ comment: 'Hook directory fallback',
60
+ }),
61
+ ]);
62
+
63
+ /**
64
+ * Order used when resolving GATE scripts. Gates are looked up flat first
65
+ * (co-located with adapter-common.sh), then in the project githooks root.
66
+ */
67
+ const GATE_RESOLUTION_ORDER = Object.freeze([
68
+ Object.freeze({
69
+ tier_id: 'gate_adapter_dir',
70
+ base: 'ADAPTER_DIR',
71
+ template: '{name}',
72
+ comment: 'Gates co-located with adapter-common.sh',
73
+ }),
74
+ Object.freeze({
75
+ tier_id: 'gate_project',
76
+ base: 'PROJECT_GITHOOKS',
77
+ template: '{name}',
78
+ comment: 'Project githooks/',
79
+ }),
80
+ Object.freeze({
81
+ tier_id: 'gate_script_dir',
82
+ base: 'SCRIPT_DIR',
83
+ template: '{name}',
84
+ comment: 'Hook directory fallback',
85
+ }),
86
+ ]);
87
+
88
+ /**
89
+ * Order in which the hook picks the directory that holds adapter-common.sh
90
+ * (ADAPTER_DIR). Same reasoning as RESOLUTION_ORDER: this cascade decides which
91
+ * tree every later lookup searches, so it must have one definition.
92
+ *
93
+ * `probe` is the file whose presence in `base` makes that tier win.
94
+ */
95
+ const ADAPTER_DIR_ORDER = Object.freeze([
96
+ Object.freeze({
97
+ tier_id: 'global',
98
+ base: 'GLOBAL_ADAPTER_DIR',
99
+ probe: 'adapter-common.sh',
100
+ comment: '~/.config/xp-gate/adapters — global install',
101
+ }),
102
+ Object.freeze({
103
+ tier_id: 'project',
104
+ base: 'PROJECT_GITHOOKS',
105
+ probe: 'adapter-common.sh',
106
+ comment: '<repo>/githooks — per-project init',
107
+ }),
108
+ Object.freeze({
109
+ tier_id: 'script',
110
+ base: 'SCRIPT_DIR',
111
+ probe: 'adapter-common.sh',
112
+ comment: 'Hook directory fallback',
113
+ }),
114
+ ]);
115
+
116
+ /**
117
+ * The probe file used to decide which tier supplies gate scripts. It is the
118
+ * first gate, so it is present wherever the gate suite is installed.
119
+ */
120
+ const GATE_PROBE = 'gate-3.sh';
121
+
122
+ module.exports = {
123
+ RESOLUTION_ORDER,
124
+ GATE_RESOLUTION_ORDER,
125
+ ADAPTER_DIR_ORDER,
126
+ GATE_PROBE,
127
+ };
@@ -2,6 +2,6 @@
2
2
  "verdict": "PASS",
3
3
  "license_type": "MIT",
4
4
  "sha256": "0e7ac423bf2c6e223b7c5b156f8cf72da49d748e56a1641402c31f22ad07dbb5",
5
- "checked_at": "2026-10-19T16:16:19.910Z",
5
+ "checked_at": "2026-10-20T10:37:54.490Z",
6
6
  "source": "network"
7
7
  }
package/lib/retro.js CHANGED
@@ -23,6 +23,29 @@ const { execSync } = require('child_process');
23
23
  */
24
24
  const MAX_SANE_DURATION_MS = 2 * 60 * 60 * 1000;
25
25
 
26
+ /**
27
+ * Whether an audit entry's duration_ms is a trustworthy sample.
28
+ *
29
+ * `e.duration_ms || 0` used to fold null into ZERO, which both dragged the mean
30
+ * down and hid that the sample was missing — the same class of lie as the
31
+ * epoch-sized values that started this line of work.
32
+ *
33
+ * BOTH signals must be honoured, not just one:
34
+ * - duration_anomaly: entries written before #475 carry an explicit flag.
35
+ * Dropping this check silently re-admitted every legacy poisoned sample, and
36
+ * the fixture average came out 33433ms instead of 150ms.
37
+ * - non-finite / out-of-range: a poisoned start now writes null or a
38
+ * nonsensical value outright, so those are excluded too.
39
+ *
40
+ * @param {{duration_ms?: number|null, duration_anomaly?: boolean}} entry
41
+ * @returns {boolean}
42
+ */
43
+ function isUsableDuration(entry) {
44
+ if (entry.duration_anomaly) return false;
45
+ const ms = entry.duration_ms;
46
+ return Number.isFinite(ms) && ms >= 0 && ms <= MAX_SANE_DURATION_MS;
47
+ }
48
+
26
49
  /**
27
50
  * Get git commit subjects within a date window.
28
51
  * @param {string} dir - Repository root
@@ -113,13 +136,7 @@ function buildReport(opts) {
113
136
  L.push('## Activity Summary');
114
137
  const gateEntries = audit.filter(e => e.gate_id);
115
138
  const passed = gateEntries.filter(e => e.passed).length;
116
- // REQ-B: a duration is only usable when it is a finite non-negative number.
117
- // `e.duration_ms || 0` used to fold null into ZERO, which both dragged the
118
- // mean down and hid the fact that the sample was missing — the same class of
119
- // lie as the epoch-sized values this sprint removed. The legacy
120
- // duration_anomaly flag is no longer the only signal: a poisoned start now
121
- // writes null outright, so anything null must be excluded and counted.
122
- const measurable = gateEntries.filter(e => Number.isFinite(e.duration_ms) && e.duration_ms >= 0 && e.duration_ms <= MAX_SANE_DURATION_MS);
139
+ const measurable = gateEntries.filter(isUsableDuration);
123
140
  const excluded = gateEntries.length - measurable.length;
124
141
  const nullDurations = gateEntries.filter(e => e.duration_ms === null).length;
125
142
  const avgMs = measurable.length > 0
@@ -30,16 +30,24 @@ function applyHistoryEntry(state, phase, phaseName, status) {
30
30
  }
31
31
 
32
32
  entry.status = status;
33
- if (status === 'in_progress' && !entry.started_at) {
33
+ // Stamp started_at on FIRST sight of any status, not only on `in_progress`.
34
+ // Phases are routinely moved straight from pending to completed (the `--render`
35
+ // path, and any sprint where the agent does not explicitly mark in_progress),
36
+ // so gating this on `in_progress` left started_at unset and duration_seconds
37
+ // permanently null — the empty-duration column on the status panel.
38
+ if (!entry.started_at) {
34
39
  entry.started_at = new Date().toISOString();
35
40
  }
36
41
  if (status === 'completed' || status === 'skipped') {
37
42
  entry.completed_at = new Date().toISOString();
38
- if (entry.started_at) {
39
- const startMs = new Date(entry.started_at).getTime();
40
- const endMs = new Date(entry.completed_at).getTime();
41
- entry.duration_seconds = Math.round((endMs - startMs) / 1000);
42
- }
43
+ const startMs = new Date(entry.started_at).getTime();
44
+ const endMs = new Date(entry.completed_at).getTime();
45
+ // Never emit NaN/negative: a bad or future started_at degrades to 0, which
46
+ // the audit treats as "unknown" rather than inventing a number.
47
+ const elapsed = endMs - startMs;
48
+ entry.duration_seconds = Number.isFinite(elapsed) && elapsed >= 0
49
+ ? Math.round(elapsed / 1000)
50
+ : 0;
43
51
  }
44
52
  return entry;
45
53
  }
@@ -1,9 +1,9 @@
1
1
  # SRC/MOCK-POLICY KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-19
4
- **Commit:** 88bfe6a6
3
+ **Generated:** 2026-10-20
4
+ **Commit:** 81dd7464
5
5
  **Branch:** main
6
- **Version:** 0.29.0.0
6
+ **Version:** 0.30.0.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.
@@ -1,9 +1,9 @@
1
1
  # SRC/MUTATION KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-19
4
- **Commit:** 88bfe6a6
3
+ **Generated:** 2026-10-20
4
+ **Commit:** 81dd7464
5
5
  **Branch:** main
6
- **Version:** 0.29.0.0
6
+ **Version:** 0.30.0.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.29.0",
3
+ "version": "0.30.0",
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"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xp-gate",
3
- "version": "0.29.0",
3
+ "version": "0.30.0",
4
4
  "displayName": "XP-Gate",
5
5
  "description": "Extreme Programming quality gates + AI workflow skills for Claude Code. Includes 12 pre-commit gates (Gate 0-11), 8 pre-push gates, Sprint Flow (6 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-10-19
4
- **Commit:** 88bfe6a6
3
+ **Generated:** 2026-10-20
4
+ **Commit:** 81dd7464
5
5
  **Branch:** main
6
- **Version:** 0.29.0.0
6
+ **Version:** 0.30.0.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,5 +1,6 @@
1
1
  ---
2
2
  name: grill-with-docs
3
+ version: 1.1.0
3
4
  description: A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.
4
5
  disable-model-invocation: true
5
6
  ---
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  name: grilling
3
+ version: 1.1.0
3
4
  description: Grill the user relentlessly about a plan, decision, or idea. Use when the user wants to stress-test their thinking, or uses any 'grill' trigger phrases.
4
5
  ---
5
6
 
@@ -1,9 +1,9 @@
1
1
  # SKILLS/SPRINT-FLOW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-19
4
- **Commit:** 88bfe6a6
3
+ **Generated:** 2026-10-20
4
+ **Commit:** 81dd7464
5
5
  **Branch:** main
6
- **Version:** 0.29.0.0
6
+ **Version:** 0.30.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.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-19
4
- **Commit:** 88bfe6a6
3
+ **Generated:** 2026-10-20
4
+ **Commit:** 81dd7464
5
5
  **Branch:** main
6
- **Version:** 0.29.0.0
6
+ **Version:** 0.30.0.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": "@boyingliu01/dsh-plugin-xp-gate",
3
- "version": "0.29.0",
3
+ "version": "0.30.0",
4
4
  "description": "XP-Gate deterministic quality gates + AI workflow skills as a DeepSeek Harness (DSH) native plugin: gate-check / gate-principles / gate-arch tools + 12 SKILL.md skills",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -1,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-19
4
- **Commit:** 88bfe6a6
3
+ **Generated:** 2026-10-20
4
+ **Commit:** 81dd7464
5
5
  **Branch:** main
6
- **Version:** 0.29.0.0
6
+ **Version:** 0.30.0.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,5 +1,6 @@
1
1
  ---
2
2
  name: grill-with-docs
3
+ version: 1.1.0
3
4
  description: A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.
4
5
  disable-model-invocation: true
5
6
  ---
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  name: grilling
3
+ version: 1.1.0
3
4
  description: Grill the user relentlessly about a plan, decision, or idea. Use when the user wants to stress-test their thinking, or uses any 'grill' trigger phrases.
4
5
  ---
5
6
 
@@ -1,9 +1,9 @@
1
1
  # SKILLS/SPRINT-FLOW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-19
4
- **Commit:** 88bfe6a6
3
+ **Generated:** 2026-10-20
4
+ **Commit:** 81dd7464
5
5
  **Branch:** main
6
- **Version:** 0.29.0.0
6
+ **Version:** 0.30.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.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-19
4
- **Commit:** 88bfe6a6
3
+ **Generated:** 2026-10-20
4
+ **Commit:** 81dd7464
5
5
  **Branch:** main
6
- **Version:** 0.29.0.0
6
+ **Version:** 0.30.0.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": "@boyingliu01/opencode-plugin",
3
- "version": "0.29.0",
3
+ "version": "0.30.0",
4
4
  "type": "module",
5
5
  "main": "index.ts",
6
6
  "description": "XP-Gate quality gates + AI workflow skills + Sprint Flow TUI sidebar for OpenCode",
@@ -1,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-19
4
- **Commit:** 88bfe6a6
3
+ **Generated:** 2026-10-20
4
+ **Commit:** 81dd7464
5
5
  **Branch:** main
6
- **Version:** 0.29.0.0
6
+ **Version:** 0.30.0.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,5 +1,6 @@
1
1
  ---
2
2
  name: grill-with-docs
3
+ version: 1.1.0
3
4
  description: A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.
4
5
  disable-model-invocation: true
5
6
  ---
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  name: grilling
3
+ version: 1.1.0
3
4
  description: Grill the user relentlessly about a plan, decision, or idea. Use when the user wants to stress-test their thinking, or uses any 'grill' trigger phrases.
4
5
  ---
5
6
 
@@ -1,9 +1,9 @@
1
1
  # SKILLS/SPRINT-FLOW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-19
4
- **Commit:** 88bfe6a6
3
+ **Generated:** 2026-10-20
4
+ **Commit:** 81dd7464
5
5
  **Branch:** main
6
- **Version:** 0.29.0.0
6
+ **Version:** 0.30.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.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-19
4
- **Commit:** 88bfe6a6
3
+ **Generated:** 2026-10-20
4
+ **Commit:** 81dd7464
5
5
  **Branch:** main
6
- **Version:** 0.29.0.0
6
+ **Version:** 0.30.0.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.29.0",
3
+ "version": "0.30.0",
4
4
  "displayName": "XP-Gate",
5
5
  "description": "Extreme Programming quality gates + AI workflow skills for Qoder. Includes 12 pre-commit gates (Gate 0-11), 8 pre-push gates, Sprint Flow (6 phases), and Delphi multi-expert review (>=90% consensus).",
6
6
  "author": {
@@ -1,10 +1,17 @@
1
1
  ---
2
2
  name: batch-grill-me
3
- version: 1.0.0
4
- description: A relentless interview that asks every frontier question at once, round by round.
3
+ version: 1.1.0
4
+ description: A relentless interview that asks every frontier question at once, round by round. Thin alias of `grilling` (#540) — upstream mattpocock/skills absorbed this protocol into grilling; XP-Gate keeps this name as the sprint-flow Phase 2 entry point so orchestration docs stay stable.
5
5
  disable-model-invocation: true
6
6
  ---
7
7
 
8
+ > **Disposition (#540):** upstream deleted the standalone batch-grill-me skill — its round-based
9
+ > frontier protocol now IS upstream `grilling`. This file is intentionally a thin alias: keep it
10
+ > as the canonical sprint-flow reference name; protocol changes land in `skills/grilling/SKILL.md`
11
+ > (the single source), not here.
12
+
13
+ The protocol is identical to [`grilling`](../grilling/SKILL.md): read and follow that skill. Summary:
14
+
8
15
  Interview the user relentlessly until you reach a shared understanding. Map this as a **design tree**: every decision branches into the decisions that hang off it.
9
16
 
10
17
  Work the tree in **rounds**. The **frontier** is every decision whose prerequisites are already settled — the questions you can ask *now* without guessing at answers you haven't heard yet. Ask the whole frontier in one round: number each question and give your recommended answer. Then wait for the user's answers before the next round.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-19
4
- **Commit:** 88bfe6a6
3
+ **Generated:** 2026-10-20
4
+ **Commit:** 81dd7464
5
5
  **Branch:** main
6
- **Version:** 0.29.0.0
6
+ **Version:** 0.30.0.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,8 +1,8 @@
1
1
  ---
2
2
  name: grill-with-docs
3
- version: 1.0.0
3
+ version: 1.1.0
4
4
  description: A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.
5
5
  disable-model-invocation: true
6
6
  ---
7
7
 
8
- Run a `/grilling` session, using the `/domain-modeling` skill.
8
+ Call the Skill tool twice, for "grilling" and "domain-modeling".