@boyingliu01/xp-gate 0.30.4 → 0.30.5
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/lib/mattpocock-license-verdict.json +1 -1
- package/mock-policy/AGENTS.md +3 -3
- package/mutation/AGENTS.md +3 -3
- package/mutation/__tests__/gate-m-survivors.test.ts +34 -0
- package/mutation/__tests__/mutation-mirror.test.ts +49 -0
- package/mutation/__tests__/update-baseline.test.ts +7 -3
- package/mutation/gate-m.ts +50 -9
- package/mutation/types.ts +9 -3
- package/mutation/update-baseline.ts +24 -7
- package/package.json +1 -1
- 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/test-specification-alignment/AGENTS.md +3 -3
- package/plugins/dsh/package.json +1 -1
- package/plugins/dsh/skills/delphi-review/AGENTS.md +3 -3
- package/plugins/dsh/skills/sprint-flow/AGENTS.md +3 -3
- package/plugins/dsh/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/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/skills/delphi-review/AGENTS.md +3 -3
- package/skills/sprint-flow/AGENTS.md +3 -3
- package/skills/test-specification-alignment/AGENTS.md +3 -3
package/mock-policy/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SRC/MOCK-POLICY KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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.
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import { describe, it, expect } from 'vitest';
|
|
18
18
|
import {
|
|
19
19
|
summarizeSurvivors,
|
|
20
|
+
buildMutationScores,
|
|
20
21
|
type StrykerReportLike,
|
|
21
22
|
type SurvivorSummary,
|
|
22
23
|
} from '../gate-m';
|
|
@@ -131,3 +132,36 @@ describe('AC-544: Gate M survivor detail', () => {
|
|
|
131
132
|
})).toBeNull();
|
|
132
133
|
});
|
|
133
134
|
});
|
|
135
|
+
|
|
136
|
+
describe('buildMutationScores carries the real counts (#544)', () => {
|
|
137
|
+
it('reports measured mutant counts instead of hardcoded zeros', () => {
|
|
138
|
+
// The original defect: the score was real and the three counts beside it
|
|
139
|
+
// were literal zeros, which reads as "measured, no survivors". A consumer
|
|
140
|
+
// that trusts `survived: 0` concludes the module is adequately tested.
|
|
141
|
+
const scores = buildMutationScores({ 'a.ts': 78.4 }, {
|
|
142
|
+
'a.ts': { mutants: 30, killed: 25, survived: 5 },
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
expect(scores['a.ts']).toEqual({ score: 78.4, mutants: 30, killed: 25, survived: 5 });
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('leaves counts absent when they were never measured', () => {
|
|
149
|
+
// Absent must stay absent -- not fabricated as zero.
|
|
150
|
+
const scores = buildMutationScores({ 'a.ts': 50 }, {});
|
|
151
|
+
|
|
152
|
+
expect(scores['a.ts'].score).toBe(50);
|
|
153
|
+
expect(scores['a.ts'].mutants).toBeUndefined();
|
|
154
|
+
expect(scores['a.ts'].survived).toBeUndefined();
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('keeps a genuinely zero-survivor file at zero', () => {
|
|
158
|
+
// The distinction this whole change is about: measured zero is a real,
|
|
159
|
+
// meaningful value and must survive the trip.
|
|
160
|
+
const scores = buildMutationScores({ 'clean.ts': 100 }, {
|
|
161
|
+
'clean.ts': { mutants: 12, killed: 12, survived: 0 },
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
expect(scores['clean.ts'].survived).toBe(0);
|
|
165
|
+
expect(scores['clean.ts'].mutants).toBe(12);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @test #544 - the shipped mutation module stays a mirror of the source module
|
|
3
|
+
* @intent src/npm-package/mutation/ is published to npm ("mutation/" is in the
|
|
4
|
+
* package `files` list) but has no automated mirror check, unlike the
|
|
5
|
+
* hooks and adapters which check-hook-mirror.sh diffs. It IS maintained
|
|
6
|
+
* as a byte-identical copy today, so a fix applied only to src/mutation/
|
|
7
|
+
* would ship stale code to every consumer -- exactly the v0.27.3 failure
|
|
8
|
+
* (#542) where a mirror-only fix was rolled back at publish. This guard
|
|
9
|
+
* makes that class of drift red instead of silent, and it is what caught
|
|
10
|
+
* the hardcoded zero counts still living in the package copy.
|
|
11
|
+
* @covers REQ-MUT-001 AC-001
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { describe, it, expect } from 'vitest';
|
|
15
|
+
import fs from 'fs';
|
|
16
|
+
import path from 'path';
|
|
17
|
+
|
|
18
|
+
// This file lives at src/mutation/__tests__/, so the repo root is three levels
|
|
19
|
+
// up (unlike scripts/__tests__/, which is two).
|
|
20
|
+
const ROOT = path.resolve(__dirname, '..', '..', '..');
|
|
21
|
+
const SRC = path.join(ROOT, 'src', 'mutation');
|
|
22
|
+
const PKG = path.join(ROOT, 'src', 'npm-package', 'mutation');
|
|
23
|
+
|
|
24
|
+
/** Files that must be identical in both trees. */
|
|
25
|
+
const MIRRORED = ['gate-m.ts', 'update-baseline.ts', 'types.ts', 'detect-ai-test.ts', 'init-baseline.ts', 'stryker-types.ts'];
|
|
26
|
+
|
|
27
|
+
describe('src/npm-package/mutation mirrors src/mutation', () => {
|
|
28
|
+
it.each(MIRRORED)('%s is byte-identical in both trees', (file) => {
|
|
29
|
+
const a = fs.readFileSync(path.join(SRC, file), 'utf8');
|
|
30
|
+
const b = fs.readFileSync(path.join(PKG, file), 'utf8');
|
|
31
|
+
expect(b, `${file} has drifted: edit src/mutation/${file} and copy it over`).toBe(a);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('the mirror list is non-empty and every entry exists (anti-vacuity)', () => {
|
|
35
|
+
expect(MIRRORED.length).toBeGreaterThan(3);
|
|
36
|
+
for (const f of MIRRORED) {
|
|
37
|
+
expect(fs.existsSync(path.join(SRC, f)), `missing source ${f}`).toBe(true);
|
|
38
|
+
expect(fs.existsSync(path.join(PKG, f)), `missing mirror ${f}`).toBe(true);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('the package copy carries the #544 fix, not the zero-filling original', () => {
|
|
43
|
+
// Anchor on the defect itself so this cannot pass with a stale-but-identical
|
|
44
|
+
// pair of pre-fix files.
|
|
45
|
+
const shipped = fs.readFileSync(path.join(PKG, 'gate-m.ts'), 'utf8');
|
|
46
|
+
expect(shipped).not.toContain('mutants: 0, killed: 0, survived: 0');
|
|
47
|
+
expect(shipped).toContain('MutantCounts');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -225,12 +225,16 @@ describe('update-baseline.ts - Mutation Baseline Update CLI', () => {
|
|
|
225
225
|
const written = JSON.parse(
|
|
226
226
|
(mockFs.default.writeFile as ReturnType<typeof vi.fn>).mock.calls[0][1] as string
|
|
227
227
|
);
|
|
228
|
+
// #544: a new entry built from a score alone must NOT be seeded with
|
|
229
|
+
// mutants/killed/survived = 0. This assertion previously pinned those
|
|
230
|
+
// zeros as the expected behaviour, which made "nobody measured this file"
|
|
231
|
+
// indistinguishable from "measured, zero survivors" in every baseline
|
|
232
|
+
// written from the CLI. The fields are omitted instead.
|
|
228
233
|
expect(written.scores['src/new.ts']).toEqual({
|
|
229
234
|
score: 72.0,
|
|
230
|
-
mutants: 0,
|
|
231
|
-
killed: 0,
|
|
232
|
-
survived: 0
|
|
233
235
|
});
|
|
236
|
+
expect(written.scores['src/new.ts'].mutants).toBeUndefined();
|
|
237
|
+
expect(written.scores['src/new.ts'].survived).toBeUndefined();
|
|
234
238
|
// Old entry should still be present
|
|
235
239
|
expect(written.scores['src/old.ts'].score).toBe(60.0);
|
|
236
240
|
});
|
package/mutation/gate-m.ts
CHANGED
|
@@ -438,8 +438,9 @@ async function runAllRunners(
|
|
|
438
438
|
groups: Map<string, string[]>,
|
|
439
439
|
timeoutMs: number,
|
|
440
440
|
cwd: string
|
|
441
|
-
): Promise<Record<string, number | null
|
|
441
|
+
): Promise<{ scores: Record<string, number | null>; counts: Record<string, MutantCounts> }> {
|
|
442
442
|
const fileScores: Record<string, number | null> = {};
|
|
443
|
+
const counts: Record<string, MutantCounts> = {};
|
|
443
444
|
|
|
444
445
|
for (const [, files] of Array.from(groups.entries())) {
|
|
445
446
|
const ext = path.extname(files[0]);
|
|
@@ -455,10 +456,10 @@ async function runAllRunners(
|
|
|
455
456
|
}
|
|
456
457
|
|
|
457
458
|
const result = await runner.run({ files, timeoutMs, cwd });
|
|
458
|
-
applyMutationResult(result, files, fileScores);
|
|
459
|
+
applyMutationResult(result, files, fileScores, counts);
|
|
459
460
|
}
|
|
460
461
|
|
|
461
|
-
return fileScores;
|
|
462
|
+
return { scores: fileScores, counts };
|
|
462
463
|
}
|
|
463
464
|
|
|
464
465
|
/**
|
|
@@ -481,6 +482,7 @@ function applyMutationResult(
|
|
|
481
482
|
outcome: MutationRunOutcome,
|
|
482
483
|
files: string[],
|
|
483
484
|
scores: Record<string, number | null>,
|
|
485
|
+
counts: Record<string, MutantCounts>,
|
|
484
486
|
): void {
|
|
485
487
|
if (outcome.timedOut || outcome.error || !outcome.report) {
|
|
486
488
|
for (const f of files) scores[f] = null;
|
|
@@ -490,11 +492,26 @@ function applyMutationResult(
|
|
|
490
492
|
if (outcome.report.files) {
|
|
491
493
|
for (const [fileKey, fileReport] of Object.entries(outcome.report.files)) {
|
|
492
494
|
scores[fileKey] = fileReport.mutationScore;
|
|
495
|
+
// #544: keep the outcome counts the reporter already gave us. Dropping
|
|
496
|
+
// them here is what forced buildMutationScores to invent zeros later.
|
|
497
|
+
counts[fileKey] = {
|
|
498
|
+
mutants: fileReport.nrOfMutants,
|
|
499
|
+
killed: fileReport.nrOfKilledMutants,
|
|
500
|
+
survived: fileReport.nrOfSurvivedMutants,
|
|
501
|
+
};
|
|
493
502
|
}
|
|
494
503
|
return;
|
|
495
504
|
}
|
|
496
505
|
|
|
497
|
-
|
|
506
|
+
const totals: MutantCounts = {
|
|
507
|
+
mutants: outcome.report.nrOfMutants,
|
|
508
|
+
killed: outcome.report.nrOfKilledMutants,
|
|
509
|
+
survived: outcome.report.nrOfSurvivedMutants,
|
|
510
|
+
};
|
|
511
|
+
for (const f of files) {
|
|
512
|
+
scores[f] = outcome.report.mutationScore;
|
|
513
|
+
counts[f] = totals;
|
|
514
|
+
}
|
|
498
515
|
}
|
|
499
516
|
|
|
500
517
|
// ── Main gateway ──
|
|
@@ -514,10 +531,33 @@ function logThresholdDetails(thresholds: FileThreshold[], baseline: MutationBase
|
|
|
514
531
|
}
|
|
515
532
|
}
|
|
516
533
|
|
|
517
|
-
|
|
534
|
+
/**
|
|
535
|
+
* Per-file mutant outcome counts, as reported by the runner. Absent fields mean
|
|
536
|
+
* "the runner did not say", which is different from a measured zero -- the whole
|
|
537
|
+
* point of #544 is that those two must not collapse into each other.
|
|
538
|
+
*/
|
|
539
|
+
export interface MutantCounts {
|
|
540
|
+
mutants?: number;
|
|
541
|
+
killed?: number;
|
|
542
|
+
survived?: number;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
export function buildMutationScores(
|
|
546
|
+
fileScores: Record<string, number>,
|
|
547
|
+
counts: Record<string, MutantCounts> = {},
|
|
548
|
+
): Record<string, MutationScore> {
|
|
518
549
|
const scores: Record<string, MutationScore> = {};
|
|
519
550
|
for (const [file, score] of Object.entries(fileScores)) {
|
|
520
|
-
|
|
551
|
+
const c = counts[file];
|
|
552
|
+
const entry: MutationScore = { score } as MutationScore;
|
|
553
|
+
// Only attach what the runner actually reported. Writing `survived: 0` for
|
|
554
|
+
// an unmeasured file is what made a skipped run look like a clean one.
|
|
555
|
+
if (c) {
|
|
556
|
+
if (c.mutants !== undefined) entry.mutants = c.mutants;
|
|
557
|
+
if (c.killed !== undefined) entry.killed = c.killed;
|
|
558
|
+
if (c.survived !== undefined) entry.survived = c.survived;
|
|
559
|
+
}
|
|
560
|
+
scores[file] = entry;
|
|
521
561
|
}
|
|
522
562
|
return scores;
|
|
523
563
|
}
|
|
@@ -619,7 +659,8 @@ export async function runGateM(options: GateMOptions): Promise<GateMResult> {
|
|
|
619
659
|
logThresholdDetails(thresholds, baseline);
|
|
620
660
|
|
|
621
661
|
const groups = groupByRunner(sourceFiles);
|
|
622
|
-
const fileScoresNullable
|
|
662
|
+
const { scores: fileScoresNullable, counts: mutantCounts } =
|
|
663
|
+
await runAllRunners(groups, options.timeoutMs, process.cwd());
|
|
623
664
|
|
|
624
665
|
const { fileScores, timeoutFiles } = partitionScores(fileScoresNullable);
|
|
625
666
|
if (timeoutFiles.length > 0) {
|
|
@@ -637,12 +678,12 @@ export async function runGateM(options: GateMOptions): Promise<GateMResult> {
|
|
|
637
678
|
}
|
|
638
679
|
|
|
639
680
|
if (evalResult.blocked) {
|
|
640
|
-
return buildResult('block', evaluableThresholds.length, buildMutationScores(fileScores), warnings, errors);
|
|
681
|
+
return buildResult('block', evaluableThresholds.length, buildMutationScores(fileScores, mutantCounts), warnings, errors);
|
|
641
682
|
}
|
|
642
683
|
if (evaluableThresholds.length === 0) {
|
|
643
684
|
return buildResult('skip', 0, {}, warnings, errors);
|
|
644
685
|
}
|
|
645
|
-
return buildResult('pass', evaluableThresholds.length, buildMutationScores(fileScores), warnings, errors);
|
|
686
|
+
return buildResult('pass', evaluableThresholds.length, buildMutationScores(fileScores, mutantCounts), warnings, errors);
|
|
646
687
|
}
|
|
647
688
|
|
|
648
689
|
interface PartitionedScores {
|
package/mutation/types.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
export interface MutationScore {
|
|
2
2
|
score: number;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Mutant outcome counts. Optional on purpose (#544): a runner that did not
|
|
5
|
+
* report them must leave them absent, so a consumer can tell "not measured"
|
|
6
|
+
* from "measured zero". They used to be hardcoded to 0, which made every
|
|
7
|
+
* unmeasured file read as a clean one.
|
|
8
|
+
*/
|
|
9
|
+
mutants?: number;
|
|
10
|
+
killed?: number;
|
|
11
|
+
survived?: number;
|
|
6
12
|
}
|
|
7
13
|
|
|
8
14
|
export interface MutationBaseline {
|
|
@@ -3,9 +3,14 @@ import path from 'path';
|
|
|
3
3
|
|
|
4
4
|
interface MutationScoreEntry {
|
|
5
5
|
score: number;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Optional (#544): a baseline entry built from a score alone has no mutant
|
|
8
|
+
* counts, and inventing zeros would record a clean file that was never
|
|
9
|
+
* measured.
|
|
10
|
+
*/
|
|
11
|
+
mutants?: number;
|
|
12
|
+
killed?: number;
|
|
13
|
+
survived?: number;
|
|
9
14
|
}
|
|
10
15
|
|
|
11
16
|
interface MutationBaseline {
|
|
@@ -92,11 +97,13 @@ function updateBaseline(
|
|
|
92
97
|
score: parseFloat(score.toFixed(1))
|
|
93
98
|
};
|
|
94
99
|
} else {
|
|
100
|
+
// #544: do not seed the baseline with zeros. This path only has a score
|
|
101
|
+
// from the hand-edited/CLI score list and no mutant counts at all, so
|
|
102
|
+
// writing mutants/killed/survived = 0 would record "measured, no
|
|
103
|
+
// survivors" for a file nobody measured. Absent means unknown, and the
|
|
104
|
+
// fields are optional on MutationScoreEntry for exactly this reason.
|
|
95
105
|
updatedScores[filePath] = {
|
|
96
106
|
score: parseFloat(score.toFixed(1)),
|
|
97
|
-
mutants: 0,
|
|
98
|
-
killed: 0,
|
|
99
|
-
survived: 0
|
|
100
107
|
};
|
|
101
108
|
}
|
|
102
109
|
}
|
|
@@ -127,7 +134,17 @@ async function removeDeletedFiles(baseline: MutationBaseline): Promise<MutationB
|
|
|
127
134
|
}
|
|
128
135
|
|
|
129
136
|
async function saveBaseline(baseline: MutationBaseline, baselinePath: string): Promise<void> {
|
|
130
|
-
|
|
137
|
+
// A failed write used to propagate as a bare rejection from deep inside the
|
|
138
|
+
// CLI's top-level await, producing an unhandled-rejection stack with no
|
|
139
|
+
// indication of WHICH file could not be written -- and on a permission or
|
|
140
|
+
// disk-full error the baseline silently stayed stale while the run looked
|
|
141
|
+
// complete. Report the path and the reason, then fail loudly.
|
|
142
|
+
try {
|
|
143
|
+
await fs.writeFile(baselinePath, JSON.stringify(baseline, null, 2));
|
|
144
|
+
} catch (err) {
|
|
145
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
146
|
+
throw new Error(`Failed to write mutation baseline to ${baselinePath}: ${reason}`);
|
|
147
|
+
}
|
|
131
148
|
}
|
|
132
149
|
|
|
133
150
|
async function main(): Promise<void> {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xp-gate",
|
|
3
|
-
"version": "0.30.
|
|
3
|
+
"version": "0.30.5",
|
|
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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|
package/plugins/dsh/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boyingliu01/dsh-plugin-xp-gate",
|
|
3
|
-
"version": "0.30.
|
|
3
|
+
"version": "0.30.5",
|
|
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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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.
|
|
3
|
+
"version": "0.30.5",
|
|
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
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|
package/principles/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# PRINCIPLES CHECKER MODULE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-21
|
|
4
|
+
**Commit:** 4e1f8be0
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.30.
|
|
6
|
+
**Version:** 0.30.5.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|