@boyingliu01/xp-gate 0.29.0 → 0.30.1
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/gate-3.sh +18 -1
- package/hooks/gate-3.sh +18 -1
- package/hooks/hook-module-resolution.sh +39 -0
- package/hooks/pre-commit +118 -39
- package/hooks/pre-push +26 -2
- package/lib/__tests__/doctor-module-resolution-parity.test.js +79 -11
- package/lib/__tests__/sprint-state-manager.test.js +31 -0
- package/lib/doctor.js +60 -27
- package/lib/hook-module-resolution.js +127 -0
- package/lib/mattpocock-license-verdict.json +1 -1
- package/lib/retro.js +24 -7
- package/lib/sprint-state-manager.js +14 -6
- package/mock-policy/AGENTS.md +3 -3
- package/mutation/AGENTS.md +3 -3
- package/package.json +3 -3
- 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/grill-with-docs/SKILL.md +1 -0
- package/plugins/claude-code/skills/grilling/SKILL.md +1 -0
- 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/grill-with-docs/SKILL.md +1 -0
- package/plugins/dsh/skills/grilling/SKILL.md +1 -0
- 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/grill-with-docs/SKILL.md +1 -0
- package/plugins/opencode/skills/grilling/SKILL.md +1 -0
- 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/batch-grill-me/SKILL.md +9 -2
- package/plugins/qoder/skills/delphi-review/AGENTS.md +3 -3
- package/plugins/qoder/skills/grill-with-docs/SKILL.md +2 -2
- package/plugins/qoder/skills/grilling/SKILL.md +23 -5
- 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/scripts/sync-package-content.js +3 -1
- package/skills/delphi-review/AGENTS.md +3 -3
- package/skills/grill-with-docs/SKILL.md +1 -0
- package/skills/grilling/SKILL.md +1 -0
- package/skills/sprint-flow/AGENTS.md +3 -3
- 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
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
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
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
}
|
|
578
|
+
let entries;
|
|
579
|
+
try {
|
|
580
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
581
|
+
} catch {
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
563
584
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
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
|
+
};
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
}
|
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-20
|
|
4
|
+
**Commit:** 70160987
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.30.1.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-20
|
|
4
|
+
**Commit:** 70160987
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.30.1.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.
|
|
3
|
+
"version": "0.30.1",
|
|
4
4
|
"description": "AI-driven development workflow: 6 quality gates + Delphi review + Sprint Flow",
|
|
5
5
|
"bin": {
|
|
6
|
-
"xp-gate": "
|
|
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.
|
|
3
|
+
"version": "0.30.1",
|
|
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-20
|
|
4
|
+
**Commit:** 70160987
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.30.1.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-20
|
|
4
|
+
**Commit:** 70160987
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.30.1.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-20
|
|
4
|
+
**Commit:** 70160987
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.30.1.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.
|
|
3
|
+
"version": "0.30.1",
|
|
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-20
|
|
4
|
+
**Commit:** 70160987
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.30.1.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-20
|
|
4
|
+
**Commit:** 70160987
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.30.1.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-20
|
|
4
|
+
**Commit:** 70160987
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.30.1.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-20
|
|
4
|
+
**Commit:** 70160987
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.30.1.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-20
|
|
4
|
+
**Commit:** 70160987
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.30.1.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-20
|
|
4
|
+
**Commit:** 70160987
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.30.1.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.
|
|
3
|
+
"version": "0.30.1",
|
|
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.
|
|
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-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-20
|
|
4
|
+
**Commit:** 70160987
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.30.1.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.
|
|
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
|
-
|
|
8
|
+
Call the Skill tool twice, for "grilling" and "domain-modeling".
|