@boyingliu01/xp-gate 0.30.0 → 0.30.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 (33) hide show
  1. package/bin/xp-gate.js +8 -0
  2. package/gate-3.sh +30 -6
  3. package/hooks/gate-3.sh +30 -6
  4. package/lib/__tests__/crap-cli.test.js +76 -0
  5. package/lib/__tests__/crap.test.js +137 -0
  6. package/lib/__tests__/retro-gate-m.test.js +144 -0
  7. package/lib/crap-cli.js +191 -0
  8. package/lib/crap.js +196 -0
  9. package/lib/mattpocock-license-verdict.json +1 -1
  10. package/lib/retro.js +139 -2
  11. package/mock-policy/AGENTS.md +2 -2
  12. package/mutation/AGENTS.md +2 -2
  13. package/package.json +3 -3
  14. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  15. package/plugins/claude-code/skills/delphi-review/AGENTS.md +2 -2
  16. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +2 -2
  17. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +2 -2
  18. package/plugins/dsh/package.json +1 -1
  19. package/plugins/dsh/skills/delphi-review/AGENTS.md +2 -2
  20. package/plugins/dsh/skills/sprint-flow/AGENTS.md +2 -2
  21. package/plugins/dsh/skills/test-specification-alignment/AGENTS.md +2 -2
  22. package/plugins/opencode/package.json +1 -1
  23. package/plugins/opencode/skills/delphi-review/AGENTS.md +2 -2
  24. package/plugins/opencode/skills/sprint-flow/AGENTS.md +2 -2
  25. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +2 -2
  26. package/plugins/qoder/plugin.json +1 -1
  27. package/plugins/qoder/skills/delphi-review/AGENTS.md +2 -2
  28. package/plugins/qoder/skills/sprint-flow/AGENTS.md +2 -2
  29. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +2 -2
  30. package/principles/AGENTS.md +2 -2
  31. package/skills/delphi-review/AGENTS.md +2 -2
  32. package/skills/sprint-flow/AGENTS.md +2 -2
  33. package/skills/test-specification-alignment/AGENTS.md +2 -2
package/lib/crap.js ADDED
@@ -0,0 +1,196 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * CRAP advisory ranking (#404 P1-2).
5
+ *
6
+ * CRAP(m) = comp(m)^2 * (1 - cov(m)) + comp(m)
7
+ *
8
+ * Uncle Bob's combined signal: complexity is only half the story, because a
9
+ * gnarly function with dense tests is cheap to change while a simple one with
10
+ * none is not. This module produces a RANKING for navigation. It is explicitly
11
+ * not a gate -- see README/issue #404 for why.
12
+ *
13
+ * Three constraints came out of measuring the indicator on this repo before
14
+ * writing it, each of which changes the design:
15
+ *
16
+ * 1. Coverage is per FILE in the artifact the gates already produce
17
+ * (coverage-final.json). Function-level positions could not be joined to
18
+ * lizard's reliably (8.4% match rate measured), so cov(m) here is the
19
+ * enclosing file's coverage. That over-smooths within a file; it is
20
+ * acceptable for ranking and not acceptable for a pass/fail verdict.
21
+ *
22
+ * 2. 21.8% of non-mirror source files are never loaded by any test and so have
23
+ * no coverage at all. Treating those as 0% would push every untested file to
24
+ * the top of the ranking purely for being unmeasured; treating them as 100%
25
+ * would hide them. They are reported separately as `unmeasured`.
26
+ *
27
+ * 3. src/npm-package/** is a generated mirror (canonical source is
28
+ * plugins/* / the repo root) and is overwritten at publish. Ranking it would
29
+ * direct refactoring at a file that does not survive. Excluded by default.
30
+ */
31
+
32
+ const fs = require('fs');
33
+ const path = require('path');
34
+
35
+ /** Repository-relative paths whose canonical source lives elsewhere. */
36
+ const MIRROR_PREFIXES = ['src/npm-package/'];
37
+
38
+ function isMirrorPath(filePath) {
39
+ if (!filePath) return false;
40
+ const normalized = String(filePath).split('\\').join('/').replace(/^\.\//, '');
41
+ return MIRROR_PREFIXES.some((prefix) => normalized.startsWith(prefix));
42
+ }
43
+
44
+ /**
45
+ * CRAP for one function.
46
+ *
47
+ * @param {number} comp cyclomatic complexity
48
+ * @param {number|null} cov coverage ratio in [0,1], or null when unmeasured
49
+ * @returns {number|null} null when coverage is unknown -- deliberately NOT a
50
+ * number, so an unmeasured function cannot be ranked at all
51
+ */
52
+ function computeCrap(comp, cov) {
53
+ if (cov === null || cov === undefined || Number.isNaN(cov)) return null;
54
+ if (!Number.isFinite(comp)) return null;
55
+
56
+ // Out-of-range coverage does occur in real istanbul output (a file counted at
57
+ // >100% after source-map folding). Clamping keeps the score monotonic and
58
+ // never negative, which a negative CRAP would violate by sorting below honest
59
+ // clean functions.
60
+ const clamped = Math.min(1, Math.max(0, cov));
61
+ return comp * comp * (1 - clamped) + comp;
62
+ }
63
+
64
+ /** Normalise a path to the repo-relative form used by the coverage artifact. */
65
+ function toRepoRelative(filePath) {
66
+ return String(filePath).split('\\').join('/').replace(/^\.\//, '');
67
+ }
68
+
69
+ /**
70
+ * Attach each function's file coverage and CRAP score.
71
+ *
72
+ * @param {Array<{file:string,name:string,ccn:number}>} functions
73
+ * @param {Map<string, number>} coverage repo-relative path -> ratio
74
+ * @returns {Array<object>} each with `cov` and `crap` (either may be null)
75
+ */
76
+ function joinCoverage(functions, coverage) {
77
+ return functions.map((fn) => {
78
+ const key = toRepoRelative(fn.file);
79
+ const cov = coverage instanceof Map ? coverage.get(key) : undefined;
80
+ const known = cov === undefined ? null : cov;
81
+ return { ...fn, file: key, cov: known, crap: computeCrap(fn.ccn, known) };
82
+ });
83
+ }
84
+
85
+ /**
86
+ * Build the advisory report.
87
+ *
88
+ * @param {Array<object>} functions joined functions (may carry null cov)
89
+ * @param {{threshold?: number, top?: number, mirrors?: boolean}} options
90
+ * `mirrors: true` also ranks the generated mirror tree; default false.
91
+ */
92
+ function buildCrapReport(functions, options = {}) {
93
+ const threshold = Number.isFinite(options.threshold) ? options.threshold : 6;
94
+ const excludeMirrors = options.mirrors !== true;
95
+
96
+ const scored = [];
97
+ let unmeasured = 0;
98
+
99
+ for (const fn of functions) {
100
+ if (excludeMirrors && isMirrorPath(fn.file)) continue;
101
+
102
+ if (fn.cov === null || fn.cov === undefined) {
103
+ unmeasured += 1;
104
+ continue;
105
+ }
106
+ const crap = fn.crap === null || fn.crap === undefined ? computeCrap(fn.ccn, fn.cov) : fn.crap;
107
+ if (crap === null) {
108
+ unmeasured += 1;
109
+ continue;
110
+ }
111
+ scored.push({ ...fn, crap });
112
+ }
113
+
114
+ scored.sort((a, b) => b.crap - a.crap || a.file.localeCompare(b.file));
115
+
116
+ const hotspots = scored.filter((s) => s.crap >= threshold);
117
+ const limited = Number.isFinite(options.top) && options.top >= 0 ? hotspots.slice(0, options.top) : hotspots;
118
+
119
+ return {
120
+ hotspots: limited,
121
+ measured: scored.length,
122
+ unmeasured,
123
+ threshold,
124
+ advisory: true,
125
+ blocking: false,
126
+ };
127
+ }
128
+
129
+ /**
130
+ * Read per-file coverage ratios out of an istanbul coverage-final.json.
131
+ * Missing or unreadable input yields an empty map, which surfaces as "every
132
+ * function unmeasured" rather than as a silently perfect score.
133
+ */
134
+ function readFileCoverage(coverageFile) {
135
+ const coverage = new Map();
136
+ let raw;
137
+ try {
138
+ raw = fs.readFileSync(coverageFile, 'utf8');
139
+ } catch {
140
+ return coverage;
141
+ }
142
+
143
+ let parsed;
144
+ try {
145
+ parsed = JSON.parse(raw);
146
+ } catch {
147
+ return coverage;
148
+ }
149
+
150
+ const root = process.cwd();
151
+ for (const [absPath, entry] of Object.entries(parsed)) {
152
+ if (!entry || !entry.s) continue;
153
+ const counts = Object.values(entry.s);
154
+ if (!counts.length) continue;
155
+ const covered = counts.filter((c) => c > 0).length;
156
+ const rel = path.isAbsolute(absPath)
157
+ ? toRepoRelative(path.relative(root, absPath))
158
+ : toRepoRelative(absPath);
159
+ coverage.set(rel, covered / counts.length);
160
+ }
161
+ return coverage;
162
+ }
163
+
164
+ /**
165
+ * Parse lizard's CSV into functions with a repo-relative file and a CCN.
166
+ * Column order: NLOC,CCN,token,PARAM,length,location,file,name,signature,...
167
+ */
168
+ function parseLizardCsv(csvText) {
169
+ const functions = [];
170
+ for (const line of String(csvText || '').split(/\r?\n/)) {
171
+ if (!line.trim()) continue;
172
+ const cells = line.match(/("([^"]|"")*"|[^,]*)(,|$)/g);
173
+ if (!cells || cells.length < 8) continue;
174
+ const clean = (i) => cells[i].replace(/,$/, '').replace(/^"|"$/g, '');
175
+
176
+ const ccn = Number(clean(1));
177
+ if (!Number.isFinite(ccn)) continue; // header row
178
+
179
+ functions.push({
180
+ file: toRepoRelative(clean(6)),
181
+ name: clean(7),
182
+ ccn,
183
+ });
184
+ }
185
+ return functions;
186
+ }
187
+
188
+ module.exports = {
189
+ computeCrap,
190
+ joinCoverage,
191
+ buildCrapReport,
192
+ isMirrorPath,
193
+ readFileCoverage,
194
+ parseLizardCsv,
195
+ MIRROR_PREFIXES,
196
+ };
@@ -2,6 +2,6 @@
2
2
  "verdict": "PASS",
3
3
  "license_type": "MIT",
4
4
  "sha256": "0e7ac423bf2c6e223b7c5b156f8cf72da49d748e56a1641402c31f22ad07dbb5",
5
- "checked_at": "2026-10-20T10:37:54.490Z",
5
+ "checked_at": "2026-10-20T12:36:08.136Z",
6
6
  "source": "network"
7
7
  }
package/lib/retro.js CHANGED
@@ -116,13 +116,133 @@ function readSprintHistory(dir, sprintFilter) {
116
116
  return results;
117
117
  }
118
118
 
119
+ /**
120
+ * Read Gate M rows out of the pre-push journals (#404 P1-3).
121
+ *
122
+ * Gate M lives in `.xp-gate/reports/pre-push/*.json`, not in the audit log: the
123
+ * audit log only sees the 12 pre-commit gates. Reading it here is the only way
124
+ * a retrospective can say anything about mutation testing at all.
125
+ *
126
+ * @param {string} dir - Repository root
127
+ * @returns {object[]} One entry per journal that carried a Gate M row
128
+ */
129
+ function readGateMRuns(dir) {
130
+ const journalDir = path.join(dir, '.xp-gate', 'reports', 'pre-push');
131
+ if (!fs.existsSync(journalDir)) return [];
132
+
133
+ const runs = [];
134
+ for (const f of fs.readdirSync(journalDir).filter(n => n.endsWith('.json'))) {
135
+ let journal;
136
+ try {
137
+ journal = JSON.parse(fs.readFileSync(path.join(journalDir, f), 'utf8'));
138
+ } catch {
139
+ continue;
140
+ }
141
+ const rows = Array.isArray(journal.gates) ? journal.gates : [];
142
+ // The TS gate is "M"; the per-language variants are M-Python/M-Go/... and
143
+ // are counted separately by the caller when it wants them.
144
+ const row = rows.find(r => r && r.id === 'M');
145
+ if (!row) continue;
146
+ const details = row.details && typeof row.details === 'object' ? row.details : {};
147
+ runs.push({
148
+ timestamp: journal.timestamp || '',
149
+ status: row.status || 'UNKNOWN',
150
+ skipReason: details.skip_reason || '',
151
+ durationMs: details.duration_ms != null && details.duration_ms !== '' ? Number(details.duration_ms) : null,
152
+ score: details.mutation_score != null && details.mutation_score !== '' ? Number(details.mutation_score) : null,
153
+ });
154
+ }
155
+ return runs;
156
+ }
157
+
158
+ /**
159
+ * Summarise Gate M runs for the report.
160
+ * @param {object[]} runs - Output of readGateMRuns
161
+ * @returns {object} Counts plus measured score/duration samples
162
+ */
163
+ function summariseGateM(runs) {
164
+ const total = runs.length;
165
+ const skipped = runs.filter(r => r.status === 'SKIP').length;
166
+ const timedOut = runs.filter(r => r.status === 'TIMEOUT').length;
167
+ // The journals write "BLOCKED" (pre-push's literal), not "BLOCK". Matching
168
+ // only one spelling silently reported 5 real mutation blocks as zero, which
169
+ // is the exact failure mode this whole issue is about.
170
+ const blocked = runs.filter(r => r.status === 'BLOCK' || r.status === 'BLOCKED').length;
171
+ const passed = runs.filter(r => r.status === 'PASS').length;
172
+ // A journal row that predates the #404 fix has an empty details object; that
173
+ // is "this run told us nothing", not "this run scored zero".
174
+ const measured = runs.filter(r => Number.isFinite(r.score));
175
+ const durations = runs.filter(r => Number.isFinite(r.durationMs)).map(r => r.durationMs);
176
+ const reasons = {};
177
+ for (const r of runs) {
178
+ if (r.status !== 'SKIP' && r.status !== 'TIMEOUT') continue;
179
+ const key = r.skipReason || '(no reason recorded)';
180
+ reasons[key] = (reasons[key] || 0) + 1;
181
+ }
182
+ return { total, skipped, timedOut, blocked, passed, measured, durations, reasons };
183
+ }
184
+
185
+ /**
186
+ * Build the Gate M retrospective section.
187
+ * @param {object[]} runs - Output of readGateMRuns
188
+ * @returns {string[]} Markdown lines
189
+ */
190
+ function buildGateMSection(runs) {
191
+ const L = [];
192
+ L.push('## Gate M (Mutation Testing) (#404)');
193
+
194
+ if (runs.length === 0) {
195
+ L.push('No pre-push journals found — Gate M has never been measured here.');
196
+ L.push('');
197
+ return L;
198
+ }
199
+
200
+ const s = summariseGateM(runs);
201
+ const pct = n => `${((n / s.total) * 100).toFixed(1)}%`;
202
+
203
+ L.push(`- Runs recorded: ${s.total} (PASS ${s.passed}, BLOCK ${s.blocked}, TIMEOUT ${s.timedOut}, SKIP ${s.skipped})`);
204
+ L.push(`- Skip rate: ${pct(s.skipped)}; timeout rate: ${pct(s.timedOut)}`);
205
+
206
+ if (s.measured.length > 0) {
207
+ const scores = s.measured.map(r => r.score).sort((a, b) => a - b);
208
+ const median = scores[Math.floor(scores.length / 2)];
209
+ const p10 = scores[Math.floor(scores.length * 0.1)];
210
+ const p90 = scores[Math.min(scores.length - 1, Math.floor(scores.length * 0.9))];
211
+ L.push(`- Mutation score over ${scores.length} measured run(s): median ${median.toFixed(1)}%, p10 ${p10.toFixed(1)}%, p90 ${p90.toFixed(1)}%`);
212
+ } else {
213
+ // Printing "median 0%" or omitting the line would both read as a healthy
214
+ // result. There is no sample, and the report must say exactly that.
215
+ L.push('- Mutation score: no measured runs — the score has never been recorded in this window.');
216
+ }
217
+
218
+ if (s.durations.length > 0) {
219
+ const sorted = [...s.durations].sort((a, b) => a - b);
220
+ const p50 = sorted[Math.floor(sorted.length / 2)];
221
+ const max = sorted[sorted.length - 1];
222
+ L.push(`- Duration over ${sorted.length} measured run(s): p50 ${p50}ms, max ${max}ms`);
223
+ } else {
224
+ L.push('- Duration: no measured runs.');
225
+ }
226
+
227
+ const reasonKeys = Object.keys(s.reasons);
228
+ if (reasonKeys.length > 0) {
229
+ L.push('- Why it did not run:');
230
+ for (const key of reasonKeys.sort((a, b) => s.reasons[b] - s.reasons[a])) {
231
+ L.push(` - ${key}: ${s.reasons[key]}`);
232
+ }
233
+ }
234
+
235
+ L.push('');
236
+ return L;
237
+ }
238
+
119
239
  /**
120
240
  * Build the Markdown retrospective report.
121
241
  * @param {object} opts - Report data
122
242
  * @returns {string} Markdown report
123
243
  */
124
244
  function buildReport(opts) {
125
- const { days, commits, audit, quality, sprints } = opts;
245
+ const { days, commits, audit, quality, sprints, gateMRuns = [] } = opts;
126
246
  const now = new Date();
127
247
  const start = new Date(now.getTime() - days * 86400000);
128
248
  const L = [];
@@ -201,6 +321,9 @@ function buildReport(opts) {
201
321
  }
202
322
  L.push('');
203
323
 
324
+ // Gate M (Mutation Testing) — #404 P1-3
325
+ L.push(...buildGateMSection(gateMRuns));
326
+
204
327
  // Quality Trend
205
328
  L.push('## Quality Trend');
206
329
  if (quality.length === 0) {
@@ -238,6 +361,7 @@ async function handleRetro(args = []) {
238
361
  const audit = readAuditEntries(dir);
239
362
  const quality = readQualityHistory(dir);
240
363
  const sprints = readSprintHistory(dir, sprintFilter);
364
+ const gateMRuns = readGateMRuns(dir);
241
365
 
242
366
  if (jsonFlag) {
243
367
  const gateEntries = audit.filter(e => e.gate_id);
@@ -249,11 +373,24 @@ async function handleRetro(args = []) {
249
373
  rework_rates: sprints.filter(s => s.metrics?.rework_rate != null).map(s => ({ id: s.id, rate: s.metrics.rework_rate })),
250
374
  evidence_skipped: audit.filter(e => e.event === 'evidence_skipped'),
251
375
  quality: quality.map(q => ({ timestamp: q.timestamp, score: q.score })),
376
+ gate_m: (() => {
377
+ const s = summariseGateM(gateMRuns);
378
+ return {
379
+ runs: s.total,
380
+ passed: s.passed,
381
+ blocked: s.blocked,
382
+ timed_out: s.timedOut,
383
+ skipped: s.skipped,
384
+ skip_reasons: s.reasons,
385
+ measured_scores: s.measured.map(r => r.score),
386
+ measured_durations_ms: s.durations,
387
+ };
388
+ })(),
252
389
  }, null, 2));
253
390
  return 0;
254
391
  }
255
392
 
256
- console.log(buildReport({ days, commits, audit, quality, sprints }));
393
+ console.log(buildReport({ days, commits, audit, quality, sprints, gateMRuns }));
257
394
  return 0;
258
395
  }
259
396
 
@@ -1,9 +1,9 @@
1
1
  # SRC/MOCK-POLICY KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-10-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.2.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
3
  **Generated:** 2026-10-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.2.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,9 +1,9 @@
1
1
  {
2
2
  "name": "@boyingliu01/xp-gate",
3
- "version": "0.30.0",
3
+ "version": "0.30.2",
4
4
  "description": "AI-driven development workflow: 6 quality gates + Delphi review + Sprint Flow",
5
5
  "bin": {
6
- "xp-gate": "./bin/xp-gate.js"
6
+ "xp-gate": "bin/xp-gate.js"
7
7
  },
8
8
  "files": [
9
9
  "bin/",
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "repository": {
34
34
  "type": "git",
35
- "url": "https://github.com/boyingliu01/xp-gate"
35
+ "url": "git+https://github.com/boyingliu01/xp-gate.git"
36
36
  },
37
37
  "publishConfig": {
38
38
  "registry": "https://registry.npmjs.org",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xp-gate",
3
- "version": "0.30.0",
3
+ "version": "0.30.2",
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
3
  **Generated:** 2026-10-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.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-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.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-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.2.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.30.0",
3
+ "version": "0.30.2",
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
3
  **Generated:** 2026-10-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.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-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.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-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.2.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.30.0",
3
+ "version": "0.30.2",
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
3
  **Generated:** 2026-10-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.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-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.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-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.2.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.30.0",
3
+ "version": "0.30.2",
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,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-10-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.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-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.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-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.2.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
  # PRINCIPLES CHECKER MODULE
2
2
 
3
3
  **Generated:** 2026-10-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.2.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Clean Code & SOLID principles checker — **Gate 4** of pre-commit. 14 rules × 9 language adapters, SARIF 2.1.0 output. Houses the **Boy Scout Rule** enforcement engine (Gate 6) and warning-baseline storage.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
3
  **Generated:** 2026-10-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.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-20
4
- **Commit:** 81dd7464
4
+ **Commit:** 9fab5b3b
5
5
  **Branch:** main
6
- **Version:** 0.30.0.0
6
+ **Version:** 0.30.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.