@boyingliu01/xp-gate 0.9.3 → 0.9.4
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/__tests__/baseline.test.js +89 -0
- package/lib/__tests__/doctor-helpers.test.js +139 -0
- package/lib/__tests__/upgrade-exec.test.js +42 -33
- package/lib/baseline.js +75 -48
- package/lib/doctor.js +180 -93
- package/lib/install-skill.js +81 -62
- package/lib/shared-phase-constants.d.ts +17 -0
- package/lib/shared-phase-constants.js +63 -0
- package/lib/shared-utils.js +14 -3
- package/lib/sprint-status.js +75 -83
- package/lib/upgrade.js +128 -85
- package/mock-policy/AGENTS.md +3 -3
- package/mutation/AGENTS.md +3 -3
- 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/opencode/__tests__/xp-gate-update.test.ts +133 -4
- package/plugins/opencode/index.ts +28 -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/opencode/tui-plugin.ts +44 -75
- 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/lib/sprint-status.js
CHANGED
|
@@ -9,22 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
const path = require('path');
|
|
12
|
-
|
|
13
|
-
const PHASE_NAMES = {
|
|
14
|
-
'-1': 'ISOLATE',
|
|
15
|
-
'-0.5': 'AUTO-ESTIMATE',
|
|
16
|
-
'0': 'THINK',
|
|
17
|
-
'1': 'PLAN',
|
|
18
|
-
'2': 'BUILD',
|
|
19
|
-
'3': 'REVIEW',
|
|
20
|
-
'4': 'USER ACCEPT',
|
|
21
|
-
'5': 'FEEDBACK',
|
|
22
|
-
'6': 'SHIP',
|
|
23
|
-
'7': 'LAND',
|
|
24
|
-
'8': 'CLEANUP',
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const PHASE_ORDER = ['-1', '-0.5', '0', '1', '2', '3', '4', '5', '6', '7', '8'];
|
|
12
|
+
const { PHASE_NAMES, PHASE_ORDER, getLatestTimestamp, isStale } = require('./shared-phase-constants');
|
|
28
13
|
|
|
29
14
|
/**
|
|
30
15
|
* Read and parse sprint-state.json from a project directory.
|
|
@@ -70,29 +55,78 @@ function formatDuration(seconds) {
|
|
|
70
55
|
}
|
|
71
56
|
|
|
72
57
|
/**
|
|
73
|
-
*
|
|
58
|
+
* Format the sprint header lines (task description, ID, branch).
|
|
59
|
+
* @param {object} state - Sprint state object
|
|
60
|
+
* @param {string} branch - Branch name
|
|
61
|
+
* @returns {string[]} Header lines
|
|
62
|
+
*/
|
|
63
|
+
function buildHeader(state, branch) {
|
|
64
|
+
return [
|
|
65
|
+
`Sprint: ${state.task_description}`,
|
|
66
|
+
`ID: ${state.id || 'unknown'} | Branch: ${branch}`,
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Format the metrics line (tests, coverage).
|
|
72
|
+
* @param {object} metrics - Sprint metrics object
|
|
73
|
+
* @returns {string|null} Metrics line or null if no metrics
|
|
74
|
+
*/
|
|
75
|
+
function buildMetricsLine(metrics) {
|
|
76
|
+
const parts = [];
|
|
77
|
+
if (metrics.tests_passed != null) {
|
|
78
|
+
parts.push(`Tests: ${metrics.tests_passed} passed${metrics.tests_failed ? `, ${metrics.tests_failed} failed` : ''}`);
|
|
79
|
+
}
|
|
80
|
+
if (metrics.coverage_pct != null) {
|
|
81
|
+
parts.push(`Coverage: ${metrics.coverage_pct}%`);
|
|
82
|
+
}
|
|
83
|
+
return parts.length > 0 ? `Metrics: ${parts.join(' | ')}` : null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Build a phase lookup map from phase_history array.
|
|
74
88
|
* @param {object} state - Sprint state object
|
|
75
|
-
* @returns {
|
|
89
|
+
* @returns {object} Map of phase key → phase history entry
|
|
76
90
|
*/
|
|
77
|
-
function
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (isNaN(started)) return false;
|
|
81
|
-
// Check latest phase_history timestamp (started_at or completed_at)
|
|
82
|
-
let latest = started;
|
|
83
|
-
if (Array.isArray(state.phase_history) && state.phase_history.length > 0) {
|
|
91
|
+
function buildPhaseLookup(state) {
|
|
92
|
+
const map = {};
|
|
93
|
+
if (Array.isArray(state.phase_history)) {
|
|
84
94
|
for (const ph of state.phase_history) {
|
|
85
|
-
|
|
86
|
-
const t = new Date(ph.completed_at).getTime();
|
|
87
|
-
if (!isNaN(t) && t > latest) latest = t;
|
|
88
|
-
}
|
|
89
|
-
if (ph.started_at) {
|
|
90
|
-
const t = new Date(ph.started_at).getTime();
|
|
91
|
-
if (!isNaN(t) && t > latest) latest = t;
|
|
92
|
-
}
|
|
95
|
+
map[String(ph.phase)] = ph;
|
|
93
96
|
}
|
|
94
97
|
}
|
|
95
|
-
return
|
|
98
|
+
return map;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Format a single phase row line.
|
|
103
|
+
* @param {string} key - Phase key (e.g. '0', '1')
|
|
104
|
+
* @param {object|undefined} history - Phase history entry
|
|
105
|
+
* @param {number} maxNameLen - Max phase name length for padding
|
|
106
|
+
* @returns {string} Formatted phase line
|
|
107
|
+
*/
|
|
108
|
+
function formatPhaseLine(key, history, maxNameLen) {
|
|
109
|
+
const name = history?.phase_name || PHASE_NAMES[key] || key;
|
|
110
|
+
const status = history?.status || 'pending';
|
|
111
|
+
const icon = statusIcon(status);
|
|
112
|
+
const dur = formatDuration(history?.duration_seconds);
|
|
113
|
+
const statusLabel = status === 'completed' ? 'Completed' :
|
|
114
|
+
status === 'in_progress' ? 'In Progress' : 'Pending';
|
|
115
|
+
return ` Phase ${key.padStart(4)} ${name.padEnd(maxNameLen + 1)} ${icon} ${dur.padEnd(5)} ${statusLabel}`;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Format REQ-level progress sub-lines for a phase (typically BUILD).
|
|
120
|
+
* @param {object|undefined} history - Phase history entry with optional reqs
|
|
121
|
+
* @returns {string[]} Array of REQ progress lines (may be empty)
|
|
122
|
+
*/
|
|
123
|
+
function formatReqLines(history) {
|
|
124
|
+
if (!history?.reqs) return [];
|
|
125
|
+
const lines = [];
|
|
126
|
+
for (const [reqId, req] of Object.entries(history.reqs)) {
|
|
127
|
+
lines.push(` ${statusIcon(req.status)} ${reqId} ${req.name}`);
|
|
128
|
+
}
|
|
129
|
+
return lines;
|
|
96
130
|
}
|
|
97
131
|
|
|
98
132
|
/**
|
|
@@ -105,77 +139,35 @@ function formatSprintTable(state) {
|
|
|
105
139
|
return 'No active sprint in this directory';
|
|
106
140
|
}
|
|
107
141
|
|
|
108
|
-
const lines = [];
|
|
109
142
|
const branch = state.isolation?.branch || 'unknown';
|
|
110
143
|
const metrics = state.metrics || {};
|
|
144
|
+
const lines = buildHeader(state, branch);
|
|
111
145
|
|
|
112
|
-
|
|
113
|
-
lines.push(
|
|
114
|
-
lines.push(`ID: ${state.id || 'unknown'} | Branch: ${branch}`);
|
|
115
|
-
|
|
116
|
-
// Metrics line (if available)
|
|
117
|
-
const metricParts = [];
|
|
118
|
-
if (metrics.tests_passed != null) {
|
|
119
|
-
metricParts.push(`Tests: ${metrics.tests_passed} passed${metrics.tests_failed ? `, ${metrics.tests_failed} failed` : ''}`);
|
|
120
|
-
}
|
|
121
|
-
if (metrics.coverage_pct != null) {
|
|
122
|
-
metricParts.push(`Coverage: ${metrics.coverage_pct}%`);
|
|
123
|
-
}
|
|
124
|
-
if (metricParts.length > 0) {
|
|
125
|
-
lines.push(`Metrics: ${metricParts.join(' | ')}`);
|
|
126
|
-
}
|
|
146
|
+
const metricsLine = buildMetricsLine(metrics);
|
|
147
|
+
if (metricsLine) lines.push(metricsLine);
|
|
127
148
|
|
|
128
|
-
// Stale warning
|
|
129
149
|
if (isStale(state)) {
|
|
130
150
|
lines.push('⚠️ State may be stale (last updated >1h ago)');
|
|
131
151
|
}
|
|
132
|
-
|
|
133
152
|
lines.push('');
|
|
134
153
|
|
|
135
|
-
|
|
136
|
-
const historyByPhase = {};
|
|
137
|
-
if (Array.isArray(state.phase_history)) {
|
|
138
|
-
for (const ph of state.phase_history) {
|
|
139
|
-
historyByPhase[String(ph.phase)] = ph;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
154
|
+
const historyByPhase = buildPhaseLookup(state);
|
|
142
155
|
|
|
143
|
-
// Calculate column widths dynamically
|
|
144
156
|
let maxNameLen = 'Phase'.length;
|
|
145
157
|
for (const key of PHASE_ORDER) {
|
|
146
|
-
const
|
|
147
|
-
const name = history?.phase_name || PHASE_NAMES[key] || key;
|
|
158
|
+
const name = historyByPhase[key]?.phase_name || PHASE_NAMES[key] || key;
|
|
148
159
|
if (name.length > maxNameLen) maxNameLen = name.length;
|
|
149
160
|
}
|
|
150
161
|
|
|
151
|
-
// Separator line
|
|
152
162
|
const sep = '─'.repeat(maxNameLen + 40);
|
|
153
|
-
|
|
154
163
|
lines.push(sep);
|
|
155
164
|
|
|
156
165
|
for (const key of PHASE_ORDER) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const status = history?.status || 'pending';
|
|
160
|
-
const icon = statusIcon(status);
|
|
161
|
-
const dur = formatDuration(history?.duration_seconds);
|
|
162
|
-
const statusLabel = status === 'completed' ? 'Completed' :
|
|
163
|
-
status === 'in_progress' ? 'In Progress' : 'Pending';
|
|
164
|
-
|
|
165
|
-
const line = ` Phase ${key.padStart(4)} ${name.padEnd(maxNameLen + 1)} ${icon} ${dur.padEnd(5)} ${statusLabel}`;
|
|
166
|
-
lines.push(line);
|
|
167
|
-
|
|
168
|
-
// REQ-level progress for BUILD phase
|
|
169
|
-
if (history?.reqs) {
|
|
170
|
-
for (const [reqId, req] of Object.entries(history.reqs)) {
|
|
171
|
-
const reqIcon = statusIcon(req.status);
|
|
172
|
-
lines.push(` ${reqIcon} ${reqId} ${req.name}`);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
166
|
+
lines.push(formatPhaseLine(key, historyByPhase[key], maxNameLen));
|
|
167
|
+
lines.push(...formatReqLines(historyByPhase[key]));
|
|
175
168
|
}
|
|
176
169
|
|
|
177
170
|
lines.push(sep);
|
|
178
|
-
|
|
179
171
|
return lines.join('\n');
|
|
180
172
|
}
|
|
181
173
|
|
package/lib/upgrade.js
CHANGED
|
@@ -1,105 +1,116 @@
|
|
|
1
|
-
const { execSync } = require('child_process');
|
|
1
|
+
const { execSync, spawn } = require('child_process');
|
|
2
2
|
const { checkUpgrade, formatUpgradeMsg, clearCache, getLocalVersion, getPackageName } = require('./check-version.js');
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* xp-gate upgrade --preview — single-line JSON for plugin consumption
|
|
10
|
-
* xp-gate upgrade --apply — auto-upgrade via npm install -g
|
|
11
|
-
*
|
|
12
|
-
* @param {string[]} args
|
|
13
|
-
* @returns {Promise<number>} exit code
|
|
5
|
+
* Handle checkUpgrade() failure.
|
|
6
|
+
* @param {Error} err
|
|
7
|
+
* @param {boolean} isPreview
|
|
8
|
+
* @returns {number} exit code (always 1)
|
|
14
9
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// --- check for upgrade ---
|
|
21
|
-
let result;
|
|
22
|
-
try {
|
|
23
|
-
result = await checkUpgrade(pkgName);
|
|
24
|
-
} catch (err) {
|
|
25
|
-
if (isPreview) {
|
|
26
|
-
console.log(JSON.stringify({ error: 'check failed', detail: err.message }));
|
|
27
|
-
} else {
|
|
28
|
-
console.error('Unable to check for updates (check error).');
|
|
29
|
-
}
|
|
30
|
-
return 1;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Guard: if checkUpgrade returned null remote (network issue)
|
|
34
|
-
if (!result.remote) {
|
|
35
|
-
if (isPreview) {
|
|
36
|
-
console.log(JSON.stringify({
|
|
37
|
-
local: result.local || 'unknown',
|
|
38
|
-
remote: null,
|
|
39
|
-
outdated: false,
|
|
40
|
-
lagDays: 0,
|
|
41
|
-
error: 'Unable to check for updates (network issue)',
|
|
42
|
-
}));
|
|
43
|
-
} else {
|
|
44
|
-
console.error('Unable to check for updates (network issue).');
|
|
45
|
-
}
|
|
46
|
-
return 0;
|
|
10
|
+
function handleCheckError(err, isPreview) {
|
|
11
|
+
if (isPreview) {
|
|
12
|
+
console.log(JSON.stringify({ error: 'check failed', detail: err.message }));
|
|
13
|
+
} else {
|
|
14
|
+
console.error('Unable to check for updates (check error).');
|
|
47
15
|
}
|
|
16
|
+
return 1;
|
|
17
|
+
}
|
|
48
18
|
|
|
49
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Handle null remote (network issue) after checkUpgrade().
|
|
21
|
+
* @param {{ local: string|null }} result
|
|
22
|
+
* @param {boolean} isPreview
|
|
23
|
+
* @returns {number} exit code (always 0)
|
|
24
|
+
*/
|
|
25
|
+
function handleNullRemote(result, isPreview) {
|
|
50
26
|
if (isPreview) {
|
|
51
|
-
const releaseUrl = result.outdated
|
|
52
|
-
? `https://github.com/boyingliu01/xp-gate/releases/tag/v${result.remote}`
|
|
53
|
-
: null;
|
|
54
27
|
console.log(JSON.stringify({
|
|
55
|
-
local: result.local,
|
|
56
|
-
remote:
|
|
57
|
-
outdated:
|
|
58
|
-
lagDays:
|
|
59
|
-
|
|
60
|
-
publishedAt: result.publishedAt || null,
|
|
28
|
+
local: result.local || 'unknown',
|
|
29
|
+
remote: null,
|
|
30
|
+
outdated: false,
|
|
31
|
+
lagDays: 0,
|
|
32
|
+
error: 'Unable to check for updates (network issue)',
|
|
61
33
|
}));
|
|
62
|
-
|
|
34
|
+
} else {
|
|
35
|
+
console.error('Unable to check for updates (network issue).');
|
|
63
36
|
}
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Handle --preview mode: emit single-line JSON.
|
|
42
|
+
* @param {{ local: string, remote: string, outdated: boolean, lagDays: number, publishedAt?: string }} result
|
|
43
|
+
* @returns {number} exit code (always 0)
|
|
44
|
+
*/
|
|
45
|
+
function handlePreviewMode(result) {
|
|
46
|
+
const releaseUrl = result.outdated
|
|
47
|
+
? `https://github.com/boyingliu01/xp-gate/releases/tag/v${result.remote}`
|
|
48
|
+
: null;
|
|
49
|
+
console.log(JSON.stringify({
|
|
50
|
+
local: result.local,
|
|
51
|
+
remote: result.remote,
|
|
52
|
+
outdated: result.outdated,
|
|
53
|
+
lagDays: result.lagDays,
|
|
54
|
+
releaseUrl,
|
|
55
|
+
publishedAt: result.publishedAt || null,
|
|
56
|
+
}));
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
64
59
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Handle --apply mode: auto-upgrade via npm install -g.
|
|
62
|
+
* @param {{ local: string, remote: string, outdated: boolean }} result
|
|
63
|
+
* @param {string} pkgName
|
|
64
|
+
* @returns {Promise<number>} exit code
|
|
65
|
+
*/
|
|
66
|
+
async function handleApplyMode(result, pkgName) {
|
|
67
|
+
if (!result.outdated) {
|
|
68
|
+
if (result.local) {
|
|
69
|
+
console.log(`\u2713 xp-gate v${result.local} is up to date`);
|
|
70
|
+
} else {
|
|
71
|
+
console.log('xp-gate is up to date.');
|
|
74
72
|
}
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
console.log(`Upgrading xp-gate from v${result.local} to v${result.remote}...`);
|
|
77
|
+
try {
|
|
78
|
+
const child = spawn('npm', ['install', '-g', `${pkgName}@${result.remote}`], {
|
|
79
|
+
stdio: 'inherit',
|
|
80
|
+
timeout: 120000,
|
|
81
|
+
});
|
|
82
|
+
await new Promise((resolve, reject) => {
|
|
83
|
+
child.on('close', (code) => {
|
|
84
|
+
if (code === 0) resolve();
|
|
85
|
+
else reject(new Error(`npm install exited with code ${code}`));
|
|
81
86
|
});
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
return 1;
|
|
87
|
+
child.on('error', reject);
|
|
88
|
+
});
|
|
89
|
+
clearCache();
|
|
90
|
+
console.log(`\u2713 Upgraded to v${result.remote}`);
|
|
91
|
+
return 0;
|
|
92
|
+
} catch (err) {
|
|
93
|
+
const msg = err.message || '';
|
|
94
|
+
if (msg.includes('EACCES') || msg.includes('permission') || msg.includes('EPERM')) {
|
|
95
|
+
console.error(`Permission denied. Try: sudo npm install -g ${pkgName}`);
|
|
96
|
+
} else if (msg.includes('ETIMEDOUT')) {
|
|
97
|
+
console.error('npm install timed out. Check your network and try again.');
|
|
98
|
+
console.error(` Retry: npm install -g ${pkgName}@latest`);
|
|
99
|
+
} else {
|
|
100
|
+
console.error('Upgrade failed:');
|
|
101
|
+
console.error(` ${msg}`);
|
|
102
|
+
console.error(` Retry manually: npm install -g ${pkgName}@latest`);
|
|
99
103
|
}
|
|
104
|
+
return 1;
|
|
100
105
|
}
|
|
106
|
+
}
|
|
101
107
|
|
|
102
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Handle default mode: human-readable output.
|
|
110
|
+
* @param {{ local: string, remote: string, outdated: boolean, lagDays: number, publishedAt?: string }} result
|
|
111
|
+
* @returns {number} exit code (always 0)
|
|
112
|
+
*/
|
|
113
|
+
function handleDefaultMode(result) {
|
|
103
114
|
if (!result.outdated) {
|
|
104
115
|
if (result.local) {
|
|
105
116
|
console.log(`\u2713 xp-gate v${result.local} is up to date`);
|
|
@@ -113,4 +124,36 @@ async function upgrade(args) {
|
|
|
113
124
|
return 0;
|
|
114
125
|
}
|
|
115
126
|
|
|
127
|
+
/**
|
|
128
|
+
* xp-gate upgrade command handler.
|
|
129
|
+
*
|
|
130
|
+
* Modes:
|
|
131
|
+
* xp-gate upgrade — human-readable output
|
|
132
|
+
* xp-gate upgrade --preview — single-line JSON for plugin consumption
|
|
133
|
+
* xp-gate upgrade --apply — auto-upgrade via npm install -g
|
|
134
|
+
*
|
|
135
|
+
* @param {string[]} args
|
|
136
|
+
* @returns {Promise<number>} exit code
|
|
137
|
+
*/
|
|
138
|
+
async function upgrade(args) {
|
|
139
|
+
const isPreview = args.includes('--preview');
|
|
140
|
+
const isApply = args.includes('--apply');
|
|
141
|
+
const pkgName = getPackageName();
|
|
142
|
+
|
|
143
|
+
let result;
|
|
144
|
+
try {
|
|
145
|
+
result = await checkUpgrade(pkgName);
|
|
146
|
+
} catch (err) {
|
|
147
|
+
return handleCheckError(err, isPreview);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (!result.remote) {
|
|
151
|
+
return handleNullRemote(result, isPreview);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (isPreview) return handlePreviewMode(result);
|
|
155
|
+
if (isApply) return handleApplyMode(result, pkgName);
|
|
156
|
+
return handleDefaultMode(result);
|
|
157
|
+
}
|
|
158
|
+
|
|
116
159
|
module.exports = { upgrade };
|
package/mock-policy/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SRC/MOCK-POLICY KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-06-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-06-19
|
|
4
|
+
**Commit:** b67f7f9
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.9.
|
|
6
|
+
**Version:** 0.9.4.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-06-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-06-19
|
|
4
|
+
**Commit:** b67f7f9
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.9.
|
|
6
|
+
**Version:** 0.9.4.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": "xp-gate",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"displayName": "XP-Gate",
|
|
5
5
|
"description": "Extreme Programming quality gates + AI workflow skills for Claude Code. Includes 10 quality gates (Gate 0-9), Sprint Flow (11 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-06-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-06-19
|
|
4
|
+
**Commit:** b67f7f9
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.9.
|
|
6
|
+
**Version:** 0.9.4.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, 3 experts from ≥2 providers, domestic models only). Supports design + code-walkthrough modes.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-06-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-06-19
|
|
4
|
+
**Commit:** b67f7f9
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.9.
|
|
6
|
+
**Version:** 0.9.4.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**11-phase** development pipeline: ISOLATE → AUTO-ESTIMATE → THINK → PLAN → BUILD → REVIEW → USER ACCEPTANCE → FEEDBACK → SHIP → LAND → CLEANUP. Phase 2 default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE in Phase 1: 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-06-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-06-19
|
|
4
|
+
**Commit:** b67f7f9
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.9.
|
|
6
|
+
**Version:** 0.9.4.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|