@boyingliu01/xp-gate 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/xp-gate.js +15 -1
- package/lib/__tests__/delphi-setup.test.js +203 -0
- package/lib/__tests__/doctor-delphi.test.js +244 -0
- package/lib/__tests__/qoder-delphi-agents.test.js +31 -0
- package/lib/delphi-setup.js +155 -0
- package/lib/doctor.js +269 -1
- package/lib/init.js +4 -1
- package/lib/mattpocock-license-verdict.json +1 -1
- 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/.delphi-config.json.example +24 -1
- package/plugins/claude-code/skills/delphi-review/AGENTS.md +3 -3
- package/plugins/claude-code/skills/delphi-review/SKILL.md +43 -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/.delphi-config.json.example +24 -1
- package/plugins/dsh/skills/delphi-review/AGENTS.md +3 -3
- package/plugins/dsh/skills/delphi-review/SKILL.md +43 -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/.delphi-config.json.example +24 -1
- package/plugins/opencode/skills/delphi-review/AGENTS.md +3 -3
- package/plugins/opencode/skills/delphi-review/SKILL.md +43 -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/delphi-review/.delphi-config.json.example +24 -1
- package/plugins/qoder/skills/delphi-review/AGENTS.md +3 -3
- package/plugins/qoder/skills/delphi-review/SKILL.md +43 -0
- 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/delphi-external-review.cjs +166 -14
- package/skills/delphi-review/.delphi-config.json.example +24 -1
- package/skills/delphi-review/AGENTS.md +3 -3
- package/skills/delphi-review/SKILL.md +43 -0
- package/skills/sprint-flow/AGENTS.md +3 -3
- package/skills/test-specification-alignment/AGENTS.md +3 -3
package/lib/doctor.js
CHANGED
|
@@ -2643,8 +2643,276 @@ function formatDoctorJson(checks, issues) {
|
|
|
2643
2643
|
};
|
|
2644
2644
|
}
|
|
2645
2645
|
|
|
2646
|
+
// ── doctor delphi (#414 REQ-3/REQ-6) ───────────────────────────────────
|
|
2647
|
+
// Diagnoses the Delphi review chain end to end. Each check exists because a
|
|
2648
|
+
// real failure was silent: drifted agent bindings looked like a working setup
|
|
2649
|
+
// (B2), a stale skill copy made reinstall = downgrade (B4), and a missing
|
|
2650
|
+
// runner script surfaced only as a failed review (B3).
|
|
2651
|
+
async function doctorDelphi(options = {}) {
|
|
2652
|
+
const { configPath, npmLatest } = options;
|
|
2653
|
+
const checks = [];
|
|
2654
|
+
const add = (name, status, detail) => checks.push({ name, status, detail });
|
|
2655
|
+
|
|
2656
|
+
// 1. Node >= 18: the runner gates on it and exits 1 mid-review otherwise.
|
|
2657
|
+
const nodeMajor = parseInt(process.versions.node.split('.')[0], 10);
|
|
2658
|
+
add('Node.js >= 18', nodeMajor >= 18 ? 'PASS' : 'FAIL',
|
|
2659
|
+
`current: ${process.versions.node}`);
|
|
2660
|
+
|
|
2661
|
+
// 2. Qoder agent bindings: present, parseable, three distinct ids, matching
|
|
2662
|
+
// what this version ships. A stale binding is a repair, not an error to
|
|
2663
|
+
// retype: the detail names delphi-setup. Project-level agents (from
|
|
2664
|
+
// `delphi-setup --local --project`) take precedence when a complete set
|
|
2665
|
+
// exists there, so the doctor agrees with the repair command (#414 R1 FC-09).
|
|
2666
|
+
const { readQoderModelId } = require('./init.js');
|
|
2667
|
+
const roles = ['architecture', 'technical', 'feasibility'];
|
|
2668
|
+
const homeAgentsDir = path.join(HOME_DIR, '.qoder', 'agents');
|
|
2669
|
+
// Injectable for tests; defaults to the cwd the doctor runs from.
|
|
2670
|
+
const projectAgentsDir = path.join(options.projectDir || process.cwd(), '.qoder', 'agents');
|
|
2671
|
+
const homeComplete = roles.every((r) => fs.existsSync(path.join(homeAgentsDir, `delphi-${r}.md`)));
|
|
2672
|
+
const projectComplete = roles.every((r) => fs.existsSync(path.join(projectAgentsDir, `delphi-${r}.md`)));
|
|
2673
|
+
const agentsDir = projectComplete ? projectAgentsDir : homeAgentsDir;
|
|
2674
|
+
const agentsSource = projectComplete
|
|
2675
|
+
? `project-level ${agentsDir}`
|
|
2676
|
+
: `user-level ${agentsDir}`;
|
|
2677
|
+
const agentIds = [];
|
|
2678
|
+
let agentsStatus = 'PASS';
|
|
2679
|
+
const agentDetails = [agentsSource];
|
|
2680
|
+
for (const role of roles) {
|
|
2681
|
+
const agentPath = path.join(agentsDir, `delphi-${role}.md`);
|
|
2682
|
+
if (!fs.existsSync(agentPath)) {
|
|
2683
|
+
agentsStatus = 'FAIL';
|
|
2684
|
+
agentDetails.push(`delphi-${role}.md missing (run: xp-gate init --global, or delphi-setup --local --project for project scope)`);
|
|
2685
|
+
continue;
|
|
2686
|
+
}
|
|
2687
|
+
const id = readQoderModelId(agentPath);
|
|
2688
|
+
if (id === null) {
|
|
2689
|
+
agentsStatus = 'FAIL';
|
|
2690
|
+
agentDetails.push(`delphi-${role}.md has no quoted model binding (repair: xp-gate delphi-setup)`);
|
|
2691
|
+
continue;
|
|
2692
|
+
}
|
|
2693
|
+
const bundledId = readQoderModelId(path.join(PKG_DIR, 'plugins', 'qoder', 'agents', `delphi-${role}.md`));
|
|
2694
|
+
if (bundledId === null) {
|
|
2695
|
+
// A bundle without a parseable template is install corruption: skipping
|
|
2696
|
+
// the comparison would hide it behind a healthy-looking id (#414 R1 FC-08).
|
|
2697
|
+
agentsStatus = 'FAIL';
|
|
2698
|
+
agentDetails.push(`delphi-${role}: bundled template missing/unreadable — reinstall xp-gate`);
|
|
2699
|
+
continue;
|
|
2700
|
+
}
|
|
2701
|
+
if (bundledId !== id) {
|
|
2702
|
+
agentDetails.push(`delphi-${role}: ${id} (this version ships ${bundledId} — repair: xp-gate delphi-setup)`);
|
|
2703
|
+
} else {
|
|
2704
|
+
agentDetails.push(`delphi-${role}: ${id}`);
|
|
2705
|
+
}
|
|
2706
|
+
agentIds.push(id);
|
|
2707
|
+
}
|
|
2708
|
+
// Report every problem class independently: missing files, unparseable
|
|
2709
|
+
// bindings and duplicates can coexist, and each has a different remedy
|
|
2710
|
+
// (#414 R1 MI-02).
|
|
2711
|
+
if (agentIds.length !== roles.length) agentsStatus = 'FAIL';
|
|
2712
|
+
if (new Set(agentIds).size !== agentIds.length) {
|
|
2713
|
+
agentsStatus = 'FAIL';
|
|
2714
|
+
agentDetails.push('duplicate model binding across experts — three DISTINCT ids are required');
|
|
2715
|
+
}
|
|
2716
|
+
add('Qoder Delphi agent bindings', agentsStatus, agentDetails.join('; ') || 'all three bound');
|
|
2717
|
+
|
|
2718
|
+
// 3. Skill install parity: a drifted installed copy is how "reinstall from
|
|
2719
|
+
// an old local repo" became a downgrade (#414 B4). Every bundled file is
|
|
2720
|
+
// compared, not just SKILL.md — the install script copies *.json and
|
|
2721
|
+
// references/ too, and B4-style drift hits those equally (#414 R1 MI-03).
|
|
2722
|
+
const platform = detectPlatform();
|
|
2723
|
+
const installedSkillDir = platform === 'qoder'
|
|
2724
|
+
? path.join(HOME_DIR, '.qoder', 'skills', 'delphi-review')
|
|
2725
|
+
: platform === 'claude-code'
|
|
2726
|
+
? path.join(HOME_DIR, '.claude', 'skills', 'delphi-review')
|
|
2727
|
+
: path.join(HOME_DIR, '.config', 'opencode', 'skills', 'delphi-review');
|
|
2728
|
+
// Injectable for tests (#414 R3 FC-01/FC-02): the empty-bundle branch is a
|
|
2729
|
+
// real failure mode and must be drivable without mutating the package.
|
|
2730
|
+
const bundledSkillDir = options.bundledSkillDir || path.join(PKG_DIR, 'skills', 'delphi-review');
|
|
2731
|
+
const sha256 = (p) => require('crypto').createHash('sha256').update(fs.readFileSync(p)).digest('hex');
|
|
2732
|
+
const listBundledSkillFiles = (dir, base = dir, out = []) => {
|
|
2733
|
+
if (!fs.existsSync(dir)) return out;
|
|
2734
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
2735
|
+
const p = path.join(dir, entry.name);
|
|
2736
|
+
if (entry.isDirectory()) listBundledSkillFiles(p, base, out);
|
|
2737
|
+
else out.push(path.relative(base, p));
|
|
2738
|
+
}
|
|
2739
|
+
return out;
|
|
2740
|
+
};
|
|
2741
|
+
if (!fs.existsSync(path.join(installedSkillDir, 'SKILL.md'))) {
|
|
2742
|
+
add('Delphi skill install parity', 'FAIL',
|
|
2743
|
+
`not installed at ${installedSkillDir} (install: xp-gate install-skill delphi-review)`);
|
|
2744
|
+
} else {
|
|
2745
|
+
const bundledFiles = listBundledSkillFiles(bundledSkillDir);
|
|
2746
|
+
if (bundledFiles.length === 0) {
|
|
2747
|
+
// An installed copy next to an empty bundle is install corruption —
|
|
2748
|
+
// "0 files match" must never read as healthy (#414 R2 MN-R2-01). The
|
|
2749
|
+
// bundled dir ships inside the installed package itself, so an
|
|
2750
|
+
// unreachable one is a broken install, not a transient condition
|
|
2751
|
+
// (#414 R3 FC-05): FAILing is the doctor's job here.
|
|
2752
|
+
add('Delphi skill install parity', 'FAIL',
|
|
2753
|
+
`bundled skill directory missing or empty: ${bundledSkillDir} — reinstall xp-gate`);
|
|
2754
|
+
} else {
|
|
2755
|
+
const drifted = [];
|
|
2756
|
+
for (const rel of bundledFiles) {
|
|
2757
|
+
const installedPath = path.join(installedSkillDir, rel);
|
|
2758
|
+
const bundledPath = path.join(bundledSkillDir, rel);
|
|
2759
|
+
if (!fs.existsSync(installedPath)) {
|
|
2760
|
+
drifted.push(`${rel}: missing`);
|
|
2761
|
+
} else if (sha256(installedPath) !== sha256(bundledPath)) {
|
|
2762
|
+
drifted.push(`${rel}: differs from bundle`);
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
if (drifted.length > 0) {
|
|
2766
|
+
add('Delphi skill install parity', 'FAIL',
|
|
2767
|
+
`${drifted.length} file(s) differ from the ${getCliVersionSafe()} bundle: `
|
|
2768
|
+
+ `${drifted.slice(0, 5).join('; ')}${drifted.length > 5 ? '; ...' : ''} `
|
|
2769
|
+
+ '(reinstall: xp-gate install-skill delphi-review --force)');
|
|
2770
|
+
} else {
|
|
2771
|
+
add('Delphi skill install parity', 'PASS',
|
|
2772
|
+
`${bundledFiles.length} file(s) match the bundle`);
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
// 4. Runner script locate: the runner must be findable from the places a
|
|
2778
|
+
// review actually starts.
|
|
2779
|
+
const runnerCandidates = [
|
|
2780
|
+
['package bundle', path.join(PKG_DIR, 'scripts', 'delphi-external-review.cjs')],
|
|
2781
|
+
['project', path.join(process.cwd(), 'scripts', 'delphi-external-review.cjs')],
|
|
2782
|
+
['installed skill', path.join(installedSkillDir, 'scripts', 'delphi-external-review.cjs')],
|
|
2783
|
+
];
|
|
2784
|
+
const foundRunner = runnerCandidates.filter(([, p]) => fs.existsSync(p));
|
|
2785
|
+
add('delphi-external-review runner', foundRunner.length > 0 ? 'PASS' : 'FAIL',
|
|
2786
|
+
foundRunner.length > 0
|
|
2787
|
+
? foundRunner.map(([label, p]) => `${label}: ${p}`).join('; ')
|
|
2788
|
+
: 'not found in package bundle, project, or installed skill');
|
|
2789
|
+
|
|
2790
|
+
// 5. Config ping: parseable, three distinct callable models. A duplicate
|
|
2791
|
+
// model here is a review that will BLOCK later — say so now.
|
|
2792
|
+
const cfgPath = configPath || path.join(process.cwd(), '.delphi-config.json');
|
|
2793
|
+
if (!fs.existsSync(cfgPath)) {
|
|
2794
|
+
add('Delphi config (.delphi-config.json)', 'FAIL',
|
|
2795
|
+
`${cfgPath} not found (copy .delphi-config.json.example from the skill directory)`);
|
|
2796
|
+
} else {
|
|
2797
|
+
try {
|
|
2798
|
+
const raw = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
|
|
2799
|
+
const profileName = raw.active_profile || 'default';
|
|
2800
|
+
const profile = raw.profiles && raw.profiles[profileName];
|
|
2801
|
+
if (!profile) {
|
|
2802
|
+
add('Delphi config (.delphi-config.json)', 'FAIL', `profile "${profileName}" not found`);
|
|
2803
|
+
} else {
|
|
2804
|
+
const experts = profile.experts || {};
|
|
2805
|
+
const models = roles.map((r) => experts[r] && experts[r].model);
|
|
2806
|
+
const providers = profile.providers || {};
|
|
2807
|
+
const missingRoles = roles.filter((r, i) => !models[i]);
|
|
2808
|
+
const duplicates = models.filter((m, i) => m && models.indexOf(m) !== i);
|
|
2809
|
+
const badProviders = roles.filter((r) => {
|
|
2810
|
+
const e = experts[r];
|
|
2811
|
+
return !e || !providers[e.provider]
|
|
2812
|
+
|| !providers[e.provider].base_url
|
|
2813
|
+
|| String(providers[e.provider].base_url).indexOf('http') !== 0;
|
|
2814
|
+
});
|
|
2815
|
+
if (missingRoles.length > 0 || duplicates.length > 0 || badProviders.length > 0) {
|
|
2816
|
+
const problems = [];
|
|
2817
|
+
if (missingRoles.length > 0) problems.push(`missing experts: ${missingRoles.join(', ')}`);
|
|
2818
|
+
if (duplicates.length > 0) problems.push(`duplicate models: ${[...new Set(duplicates)].join(', ')}`);
|
|
2819
|
+
if (badProviders.length > 0) problems.push(`unusable provider binding: ${badProviders.join(', ')}`);
|
|
2820
|
+
add('Delphi config (.delphi-config.json)', 'FAIL', problems.join('; '));
|
|
2821
|
+
} else {
|
|
2822
|
+
add('Delphi config (.delphi-config.json)', 'PASS',
|
|
2823
|
+
`profile "${profileName}": ${models.join(' / ')}`);
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
} catch (err) {
|
|
2827
|
+
add('Delphi config (.delphi-config.json)', 'FAIL', `unparseable: ${err.message}`);
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2831
|
+
// 6. Version consistency (#414 REQ-6): local files first. The npm-latest
|
|
2832
|
+
// probe is opt-in (options.probeNpmLatest) or pre-supplied
|
|
2833
|
+
// (options.npmLatest) — the doctor never blocks on the network, which is
|
|
2834
|
+
// what an offline CI or restricted shell would otherwise hit (#414 R1 FC-03).
|
|
2835
|
+
const localVersion = getCliVersionSafe();
|
|
2836
|
+
let versionStatus = 'PASS';
|
|
2837
|
+
let versionDetail = `xp-gate ${localVersion}`;
|
|
2838
|
+
if (npmLatest === undefined && options.probeNpmLatest === true) {
|
|
2839
|
+
try {
|
|
2840
|
+
versionDetail += `; npm latest probe: ${execWithTimeout('npm view @boyingliu01/xp-gate version', 8000).trim()}`;
|
|
2841
|
+
} catch {
|
|
2842
|
+
versionStatus = 'SKIP';
|
|
2843
|
+
versionDetail += '; npm latest probe unavailable (offline?) — skipped';
|
|
2844
|
+
}
|
|
2845
|
+
} else if (typeof npmLatest === 'string' && npmLatest !== localVersion) {
|
|
2846
|
+
versionStatus = 'FAIL';
|
|
2847
|
+
versionDetail += `; npm latest ${npmLatest} differs from local ${localVersion} — update (npm install -g @boyingliu01/xp-gate@latest) or verify which side is stale`;
|
|
2848
|
+
} else if (npmLatest === null || options.probeNpmLatest !== true) {
|
|
2849
|
+
versionDetail += '; npm latest probe skipped (pass --npm-check or options.probeNpmLatest to run it)';
|
|
2850
|
+
}
|
|
2851
|
+
add('Delphi version consistency', versionStatus, versionDetail);
|
|
2852
|
+
|
|
2853
|
+
// 7. DSH native-channel readiness (#443 REQ-6): only meaningful when a DSH
|
|
2854
|
+
// home exists. The two-layer switch (preset capability + host setting)
|
|
2855
|
+
// defaults to disabled, and a review that assumes native will silently run
|
|
2856
|
+
// three same-model seats.
|
|
2857
|
+
const dshHome = path.join(HOME_DIR, '.dsh');
|
|
2858
|
+
if (!fs.existsSync(dshHome)) {
|
|
2859
|
+
add('DSH subagent model selection', 'SKIP', `no ${dshHome} — not a DSH environment`);
|
|
2860
|
+
} else {
|
|
2861
|
+
const settingsCandidates = [
|
|
2862
|
+
path.join(dshHome, 'settings.json'),
|
|
2863
|
+
path.join(dshHome, 'settings', 'settings.json'),
|
|
2864
|
+
path.join(dshHome, 'config.json'),
|
|
2865
|
+
];
|
|
2866
|
+
const settingsFile = settingsCandidates.find((p) => fs.existsSync(p));
|
|
2867
|
+
if (!settingsFile) {
|
|
2868
|
+
add('DSH subagent model selection', 'FAIL',
|
|
2869
|
+
`${dshHome} exists but no settings file found — subagent model selection defaults to disabled (#443)`);
|
|
2870
|
+
} else {
|
|
2871
|
+
try {
|
|
2872
|
+
const settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
|
|
2873
|
+
const selection = settings.subagentModelSelection;
|
|
2874
|
+
const allowed = selection && Array.isArray(selection.allowedModels) ? selection.allowedModels : [];
|
|
2875
|
+
const ids = allowed.map((m) => (typeof m === 'string' ? m : m && m.id)).filter(Boolean);
|
|
2876
|
+
if (selection && selection.enabled === true && new Set(ids).size >= 3) {
|
|
2877
|
+
add('DSH subagent model selection', 'PASS', `${settingsFile}: enabled, ${new Set(ids).size} distinct allowed models`);
|
|
2878
|
+
} else if (selection && selection.enabled === true) {
|
|
2879
|
+
add('DSH subagent model selection', 'FAIL',
|
|
2880
|
+
`${settingsFile}: enabled but only ${new Set(ids).size} distinct allowedModels (need ≥3) — native channel unusable`);
|
|
2881
|
+
} else {
|
|
2882
|
+
// The switch shipping off is the platform default, not a defect:
|
|
2883
|
+
// only an operator who explicitly enables it and under-provisions
|
|
2884
|
+
// allowedModels has a real misconfiguration (#414 R1 FC-07).
|
|
2885
|
+
add('DSH subagent model selection', 'SKIP',
|
|
2886
|
+
`${settingsFile}: native model selection disabled (platform default) — the external channel is the contract path (#443)`);
|
|
2887
|
+
}
|
|
2888
|
+
} catch (err) {
|
|
2889
|
+
add('DSH subagent model selection', 'SKIP', `${settingsFile} unparseable: ${err.message}`);
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2893
|
+
|
|
2894
|
+
for (const check of checks) {
|
|
2895
|
+
const mark = check.status === 'PASS' ? '✓' : check.status === 'SKIP' ? '○' : '✗';
|
|
2896
|
+
console.log(` ${mark} ${check.name}: ${check.detail || check.status}`);
|
|
2897
|
+
}
|
|
2898
|
+
const failed = checks.filter((c) => c.status === 'FAIL').length;
|
|
2899
|
+
console.log('');
|
|
2900
|
+
console.log(failed === 0
|
|
2901
|
+
? ' Delphi review chain: healthy.'
|
|
2902
|
+
: ` Delphi review chain: ${failed} check(s) FAILED.`);
|
|
2903
|
+
return failed === 0 ? 0 : 1;
|
|
2904
|
+
}
|
|
2905
|
+
|
|
2906
|
+
function getCliVersionSafe() {
|
|
2907
|
+
try {
|
|
2908
|
+
return require('../package.json').version || '0.0.0';
|
|
2909
|
+
} catch {
|
|
2910
|
+
return '0.0.0';
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
|
|
2646
2914
|
module.exports = {
|
|
2647
|
-
doctor, isXpGateFile, SIGNATURES,
|
|
2915
|
+
doctor, doctorDelphi, isXpGateFile, SIGNATURES,
|
|
2648
2916
|
fixVersionMismatch,
|
|
2649
2917
|
fixTemplateDirMismatch,
|
|
2650
2918
|
fixMissingHooks,
|
package/lib/init.js
CHANGED
|
@@ -922,4 +922,7 @@ function injectKarpathyPrinciples(projectRoot) {
|
|
|
922
922
|
}
|
|
923
923
|
}
|
|
924
924
|
|
|
925
|
-
|
|
925
|
+
// setupGlobal is exported so the global-install wiring (agents deployed to the
|
|
926
|
+
// real HOME) can be audited under a sandboxed HOME, not just asserted to exist
|
|
927
|
+
// — the historical miss was "local deployed, global did not" (#417, #429).
|
|
928
|
+
module.exports = { init, promptBootstrap, installModuleRuntimeDeps, deployQoderDelphiAgents, configureQoderDelphiAgents, readQoderModelId, setupGlobal };
|
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-14
|
|
4
|
+
**Commit:** e466ce16
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.24.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Mock layering policy enforcement — Gate M3 of pre-push hook. Ensures integration tests use real implementations for internal dependencies, mock external dependencies, and annotate pending mocks with removal plans. Combines project scope scanning, mock decision engine, and per-file validation into a single pipeline.
|
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-14
|
|
4
|
+
**Commit:** e466ce16
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.24.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**Gate M** (incremental mutation testing) + **Gate M2** helpers (test-layer detection used by `src/mock-policy/`). Pre-push quality gate. TypeScript-only; uses Stryker.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xp-gate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"displayName": "XP-Gate",
|
|
5
5
|
"description": "Extreme Programming quality gates + AI workflow skills for Claude Code. Includes 12 pre-commit gates (Gate 0-11), 8 pre-push gates, Sprint Flow (6 phases), and Delphi multi-expert review (>=90% consensus).",
|
|
6
6
|
"author": {
|
|
@@ -66,5 +66,28 @@
|
|
|
66
66
|
"max_review_rounds": 5,
|
|
67
67
|
"distinct_models_required": true,
|
|
68
68
|
"cross_provider_required": true
|
|
69
|
-
}
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
"$comment_seat_fields": [
|
|
72
|
+
"Optional per-seat fields (#481). The prompt ceiling is a seat x model route",
|
|
73
|
+
"property, not a global constant: max_prompt_bytes (UTF-8 bytes, default 40000)",
|
|
74
|
+
"is the hard pre-send gate; prompt_calibration carries the measured bounds used",
|
|
75
|
+
"to classify a pre-response drop as SIZE_EXCEEDED instead of a network fault.",
|
|
76
|
+
"Recalibrate (binary search 3-5 probes in [last_pass, last_fail]) whenever the",
|
|
77
|
+
"model or gateway changes. See docs/plans/2026-10-14-sprint-c-design.md section 2.",
|
|
78
|
+
"Example expert entry:",
|
|
79
|
+
" \"architecture\": {",
|
|
80
|
+
" \"provider\": \"bailian-tp\",",
|
|
81
|
+
" \"model\": \"qwen-plus\",",
|
|
82
|
+
" \"seat_id\": \"architecture\",",
|
|
83
|
+
" \"max_prompt_bytes\": 26624,",
|
|
84
|
+
" \"prompt_calibration\": {",
|
|
85
|
+
" \"measured_at\": \"2026-10-05\",",
|
|
86
|
+
" \"model_id\": \"qwen-plus\",",
|
|
87
|
+
" \"gateway\": \"bailian\",",
|
|
88
|
+
" \"last_pass_bytes\": 26624,",
|
|
89
|
+
" \"last_fail_bytes\": 36897",
|
|
90
|
+
" }",
|
|
91
|
+
" }"
|
|
92
|
+
]
|
|
70
93
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-14
|
|
4
|
+
**Commit:** e466ce16
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.24.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, exactly 3 experts with distinct executable model IDs). Supports design, requirements, and code-walkthrough modes.
|
|
@@ -329,6 +329,15 @@ Each round MUST output a structured round marker:
|
|
|
329
329
|
|
|
330
330
|
#### Qoder 平台(Custom Agent 模式 — 只能做到同模型三角色)
|
|
331
331
|
|
|
332
|
+
**通道契约(native-first + external fallback,#414)**:每轮评审开始先探测 native 通道——三个 Custom Agent(`delphi-architecture/technical/feasibility`)是否存在且绑定互异(`xp-gate doctor delphi` 一条命令给出全部判定)。但 **native 通道已被实测证伪**(见下):subagent 派发采纳 agent 提示词、丢弃 model 绑定,三席永远是会话模型。因此 Qoder 的通道决策表实际收敛为:
|
|
333
|
+
|
|
334
|
+
| 探测结果 | 通道 | 处置 |
|
|
335
|
+
|---|---|---|
|
|
336
|
+
| 需要 distinct-models 证据的评审 | **external** | `.delphi-config.json` + `scripts/delphi-external-review.cjs`(外部 provider 三模型) |
|
|
337
|
+
| 仅需同模型三角色自查(不计入共识证据) | native | 三 Custom Agent 并行,报告中注明「同模型自查,不构成多模型凭据」 |
|
|
338
|
+
|
|
339
|
+
降级证据落盘 `delphi-reviewed.json`:`channel`(native/external)、`fallback_reason`(如 `qoder_native_drops_model_binding`)、`probe_evidence`(doctor/日志摘录)。两通道同不变量:三专家齐全、`requested_model` 互异(external)、consensus ≥90%、**无单专家路径**。
|
|
340
|
+
|
|
332
341
|
Qoder 的内置模型**没有本地推理端点**:推理请求由 Qoder 客户端经服务端代理发出,凭证是一次性 job token。所以不能照搬 OpenCode 的 `base_url + api_key` 直连方式;Qoder 侧内置模型的唯一入口是 **Custom Agent** —— 每个专家一个独立 agent 文件,frontmatter 用 `model` 字段声明模型。
|
|
333
342
|
|
|
334
343
|
**契约结论(先说结论)**:这条路径**不满足**"三个不同可执行模型 ID"契约。2026-09-23 做过一次排除混杂因素的复测:先把 `~/.qoder/agents/delphi-*.md` 三份文件绑成三个不同的 0.1× 内置模型(`qfmodel` / `dfmodel` / `gfmodel`;架构角与会话模型同名,所以真正有判别力的是技术角与可行性角),**再**新开会话——新 CLI 进程,`session.config.loaded` 记录 `model: "qfmodel"`,注册表加载的必然是已修好的绑定——然后只派发三个 subagent,各回一句话、不调工具。结果:三个独立的 `is_subagent: true` turn,`turn.started` / `model.request.started` / `model.response.completed` 三处的 `model` 全为会话模型 `qfmodel`,`dfmodel` / `gfmodel` 出现 0 次;同时三份回复分别命中架构 / 技术 / 可行性视角,说明角色提示词确实生效、agent 也确实被加载。即 `subagent_type` 派发路径采纳 Custom Agent 的提示词,但**丢弃**它的 `model` 绑定。
|
|
@@ -408,6 +417,20 @@ delphi-review(
|
|
|
408
417
|
> (1) `dsh-tool-subagent` 的 `modelSelectionSettings: true`(仅能力开关),
|
|
409
418
|
> (2) 宿主设置 `SubagentModelSelectionConfig.enabled = true` 且 `allowedModels` ≥3 个不同模型。
|
|
410
419
|
> 该路线依赖宿主配置,CI / 一次性会话不可靠,故不作为默认路径。
|
|
420
|
+
|
|
421
|
+
**DSH 双通道契约(native-first + external fallback,#443)**:评审开始先探测 native 通道,两层开关缺一不可——
|
|
422
|
+
|
|
423
|
+
| 探测步骤 | 方法 | 判定 |
|
|
424
|
+
|---|---|---|
|
|
425
|
+
| ① 工具 schema | 当前会话 `subagent` 工具的参数里是否暴露 `provider` / `model` 字段 | 无 → native 不可用(`enabled` 默认 `false`) |
|
|
426
|
+
| ② 模型清单 | `list_subagent_models` 工具是否注册;可用时返回条数是否 ≥3 且互异 | 未注册或 <3 条 → native 不可用 |
|
|
427
|
+
| ③ 运行时兜底 | 上述任一不满足时调用 subagent 会抛 `child model selection is disabled` | 直接判定,不试错 |
|
|
428
|
+
|
|
429
|
+
- **native 可用**:三个专家并行派发,每个显式传 `model`(取自 `allowedModels` 三个互异条目);`resolved_model` 以平台日志/回执为准,无日志时按 #437 过渡标准注明「执行层验证待平台支持」。
|
|
430
|
+
- **native 不可用**:降级 **external**(本 skill 的 `delphi-review` 插件工具,或 `.delphi-config.json` + `scripts/delphi-external-review.cjs`)。缺 API key 时必须给出明确指引(导出环境变量),不得静默失败。
|
|
431
|
+
- 降级证据落盘 `delphi-reviewed.json`:`channel`、`fallback_reason`(如 `dsh_subagent_model_selection_disabled`)、`probe_evidence`(①②③ 的实测摘录)。
|
|
432
|
+
- 两通道同不变量:三专家齐全、`requested_model` 互异、consensus ≥90%、**无单专家路径**。
|
|
433
|
+
- 可用性探测可用 `xp-gate doctor delphi` 复核(DSH 环境下含 `subagentModelSelection` 持久化设置检查)。
|
|
411
434
|
#### WorkBuddy 平台(Expert 团队模式)
|
|
412
435
|
|
|
413
436
|
WorkBuddy 侧以 Team 型专家团(示例:`delphi-review-team`,安装在 `~/.workbuddy/plugins/marketplaces/my-experts/plugins/`,创建方式见 [docs/platform-workbuddy.md](../../docs/platform-workbuddy.md))承载评审,触发本技能后按此路由执行:
|
|
@@ -432,6 +455,26 @@ WorkBuddy 侧以 Team 型专家团(示例:`delphi-review-team`,安装在 `
|
|
|
432
455
|
|
|
433
456
|
**成本**:3 专家合计 x0.17/轮;主理人选 local 会话模型则零 credits。
|
|
434
457
|
|
|
458
|
+
### 席位 prompt 上限与降序裁剪(强制 — #481)
|
|
459
|
+
|
|
460
|
+
prompt 字节上限是 **席位×模型路由 属性**,不是全局安全值(2026-10-05 实测:同一网关下
|
|
461
|
+
`g-glm-5.3-flash` 席 32-39KB 连续 6 次断连,他席 36KB 一次通过)。编排规则:
|
|
462
|
+
|
|
463
|
+
1. **发送前硬闸**:runner 按 expert 条目的 `max_prompt_bytes`(默认 40000 字节,UTF-8 计)
|
|
464
|
+
拒发超限请求,输出 `error_type: "prompt_budget_exceeded"`。
|
|
465
|
+
2. **失败分类**:响应前断连且字节数超过该席位标定的 `last_pass_bytes` →
|
|
466
|
+
`error_type: "SIZE_EXCEEDED"`(不是网络故障,重试同一 payload 无意义);
|
|
467
|
+
其余失败输出 `network_error` / `retryable_error`,编排层按 `error_type` 字段断言,不解析散文。
|
|
468
|
+
3. **超限时按降序裁剪,每步只做一步**:
|
|
469
|
+
① 去附录(探针填充、日志附录、非必需长引用)→ ② 去非本轮 AC 原文 →
|
|
470
|
+
③ 去测试清单(枚举 → 计数)→ ④ 拆分两次调用(按 diff 对半,同报告合并)→
|
|
471
|
+
⑤ 仍失败 → `PROCESS_BLOCK` 交人裁定。**不得以两席结果冒充 3/3 共识。**
|
|
472
|
+
4. **标定**:上限按「固定语义核心 + 确定性填充附录」构造探针,在
|
|
473
|
+
`[last_pass, last_fail]` 区间二分 3-5 次测得;记录行含
|
|
474
|
+
`seat_id × model_id × gateway × max_passing_bytes × measured_at`;
|
|
475
|
+
模型或网关变更即重标。协议全文与种子标定表见
|
|
476
|
+
[docs/plans/2026-10-14-sprint-c-design.md](../../docs/plans/2026-10-14-sprint-c-design.md) §2。
|
|
477
|
+
|
|
435
478
|
### 共识阈值
|
|
436
479
|
|
|
437
480
|
| 阈值 | 说明 |
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-14
|
|
4
|
+
**Commit:** e466ce16
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.24.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-14
|
|
4
|
+
**Commit:** e466ce16
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.24.0.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.24.0",
|
|
4
4
|
"description": "XP-Gate deterministic quality gates + AI workflow skills as a DeepSeek Harness (DSH) native plugin: gate-check / gate-principles / gate-arch tools + 12 SKILL.md skills",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -66,5 +66,28 @@
|
|
|
66
66
|
"max_review_rounds": 5,
|
|
67
67
|
"distinct_models_required": true,
|
|
68
68
|
"cross_provider_required": true
|
|
69
|
-
}
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
"$comment_seat_fields": [
|
|
72
|
+
"Optional per-seat fields (#481). The prompt ceiling is a seat x model route",
|
|
73
|
+
"property, not a global constant: max_prompt_bytes (UTF-8 bytes, default 40000)",
|
|
74
|
+
"is the hard pre-send gate; prompt_calibration carries the measured bounds used",
|
|
75
|
+
"to classify a pre-response drop as SIZE_EXCEEDED instead of a network fault.",
|
|
76
|
+
"Recalibrate (binary search 3-5 probes in [last_pass, last_fail]) whenever the",
|
|
77
|
+
"model or gateway changes. See docs/plans/2026-10-14-sprint-c-design.md section 2.",
|
|
78
|
+
"Example expert entry:",
|
|
79
|
+
" \"architecture\": {",
|
|
80
|
+
" \"provider\": \"bailian-tp\",",
|
|
81
|
+
" \"model\": \"qwen-plus\",",
|
|
82
|
+
" \"seat_id\": \"architecture\",",
|
|
83
|
+
" \"max_prompt_bytes\": 26624,",
|
|
84
|
+
" \"prompt_calibration\": {",
|
|
85
|
+
" \"measured_at\": \"2026-10-05\",",
|
|
86
|
+
" \"model_id\": \"qwen-plus\",",
|
|
87
|
+
" \"gateway\": \"bailian\",",
|
|
88
|
+
" \"last_pass_bytes\": 26624,",
|
|
89
|
+
" \"last_fail_bytes\": 36897",
|
|
90
|
+
" }",
|
|
91
|
+
" }"
|
|
92
|
+
]
|
|
70
93
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-14
|
|
4
|
+
**Commit:** e466ce16
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.24.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, exactly 3 experts with distinct executable model IDs). Supports design, requirements, and code-walkthrough modes.
|
|
@@ -329,6 +329,15 @@ Each round MUST output a structured round marker:
|
|
|
329
329
|
|
|
330
330
|
#### Qoder 平台(Custom Agent 模式 — 只能做到同模型三角色)
|
|
331
331
|
|
|
332
|
+
**通道契约(native-first + external fallback,#414)**:每轮评审开始先探测 native 通道——三个 Custom Agent(`delphi-architecture/technical/feasibility`)是否存在且绑定互异(`xp-gate doctor delphi` 一条命令给出全部判定)。但 **native 通道已被实测证伪**(见下):subagent 派发采纳 agent 提示词、丢弃 model 绑定,三席永远是会话模型。因此 Qoder 的通道决策表实际收敛为:
|
|
333
|
+
|
|
334
|
+
| 探测结果 | 通道 | 处置 |
|
|
335
|
+
|---|---|---|
|
|
336
|
+
| 需要 distinct-models 证据的评审 | **external** | `.delphi-config.json` + `scripts/delphi-external-review.cjs`(外部 provider 三模型) |
|
|
337
|
+
| 仅需同模型三角色自查(不计入共识证据) | native | 三 Custom Agent 并行,报告中注明「同模型自查,不构成多模型凭据」 |
|
|
338
|
+
|
|
339
|
+
降级证据落盘 `delphi-reviewed.json`:`channel`(native/external)、`fallback_reason`(如 `qoder_native_drops_model_binding`)、`probe_evidence`(doctor/日志摘录)。两通道同不变量:三专家齐全、`requested_model` 互异(external)、consensus ≥90%、**无单专家路径**。
|
|
340
|
+
|
|
332
341
|
Qoder 的内置模型**没有本地推理端点**:推理请求由 Qoder 客户端经服务端代理发出,凭证是一次性 job token。所以不能照搬 OpenCode 的 `base_url + api_key` 直连方式;Qoder 侧内置模型的唯一入口是 **Custom Agent** —— 每个专家一个独立 agent 文件,frontmatter 用 `model` 字段声明模型。
|
|
333
342
|
|
|
334
343
|
**契约结论(先说结论)**:这条路径**不满足**"三个不同可执行模型 ID"契约。2026-09-23 做过一次排除混杂因素的复测:先把 `~/.qoder/agents/delphi-*.md` 三份文件绑成三个不同的 0.1× 内置模型(`qfmodel` / `dfmodel` / `gfmodel`;架构角与会话模型同名,所以真正有判别力的是技术角与可行性角),**再**新开会话——新 CLI 进程,`session.config.loaded` 记录 `model: "qfmodel"`,注册表加载的必然是已修好的绑定——然后只派发三个 subagent,各回一句话、不调工具。结果:三个独立的 `is_subagent: true` turn,`turn.started` / `model.request.started` / `model.response.completed` 三处的 `model` 全为会话模型 `qfmodel`,`dfmodel` / `gfmodel` 出现 0 次;同时三份回复分别命中架构 / 技术 / 可行性视角,说明角色提示词确实生效、agent 也确实被加载。即 `subagent_type` 派发路径采纳 Custom Agent 的提示词,但**丢弃**它的 `model` 绑定。
|
|
@@ -408,6 +417,20 @@ delphi-review(
|
|
|
408
417
|
> (1) `dsh-tool-subagent` 的 `modelSelectionSettings: true`(仅能力开关),
|
|
409
418
|
> (2) 宿主设置 `SubagentModelSelectionConfig.enabled = true` 且 `allowedModels` ≥3 个不同模型。
|
|
410
419
|
> 该路线依赖宿主配置,CI / 一次性会话不可靠,故不作为默认路径。
|
|
420
|
+
|
|
421
|
+
**DSH 双通道契约(native-first + external fallback,#443)**:评审开始先探测 native 通道,两层开关缺一不可——
|
|
422
|
+
|
|
423
|
+
| 探测步骤 | 方法 | 判定 |
|
|
424
|
+
|---|---|---|
|
|
425
|
+
| ① 工具 schema | 当前会话 `subagent` 工具的参数里是否暴露 `provider` / `model` 字段 | 无 → native 不可用(`enabled` 默认 `false`) |
|
|
426
|
+
| ② 模型清单 | `list_subagent_models` 工具是否注册;可用时返回条数是否 ≥3 且互异 | 未注册或 <3 条 → native 不可用 |
|
|
427
|
+
| ③ 运行时兜底 | 上述任一不满足时调用 subagent 会抛 `child model selection is disabled` | 直接判定,不试错 |
|
|
428
|
+
|
|
429
|
+
- **native 可用**:三个专家并行派发,每个显式传 `model`(取自 `allowedModels` 三个互异条目);`resolved_model` 以平台日志/回执为准,无日志时按 #437 过渡标准注明「执行层验证待平台支持」。
|
|
430
|
+
- **native 不可用**:降级 **external**(本 skill 的 `delphi-review` 插件工具,或 `.delphi-config.json` + `scripts/delphi-external-review.cjs`)。缺 API key 时必须给出明确指引(导出环境变量),不得静默失败。
|
|
431
|
+
- 降级证据落盘 `delphi-reviewed.json`:`channel`、`fallback_reason`(如 `dsh_subagent_model_selection_disabled`)、`probe_evidence`(①②③ 的实测摘录)。
|
|
432
|
+
- 两通道同不变量:三专家齐全、`requested_model` 互异、consensus ≥90%、**无单专家路径**。
|
|
433
|
+
- 可用性探测可用 `xp-gate doctor delphi` 复核(DSH 环境下含 `subagentModelSelection` 持久化设置检查)。
|
|
411
434
|
#### WorkBuddy 平台(Expert 团队模式)
|
|
412
435
|
|
|
413
436
|
WorkBuddy 侧以 Team 型专家团(示例:`delphi-review-team`,安装在 `~/.workbuddy/plugins/marketplaces/my-experts/plugins/`,创建方式见 [docs/platform-workbuddy.md](../../docs/platform-workbuddy.md))承载评审,触发本技能后按此路由执行:
|
|
@@ -432,6 +455,26 @@ WorkBuddy 侧以 Team 型专家团(示例:`delphi-review-team`,安装在 `
|
|
|
432
455
|
|
|
433
456
|
**成本**:3 专家合计 x0.17/轮;主理人选 local 会话模型则零 credits。
|
|
434
457
|
|
|
458
|
+
### 席位 prompt 上限与降序裁剪(强制 — #481)
|
|
459
|
+
|
|
460
|
+
prompt 字节上限是 **席位×模型路由 属性**,不是全局安全值(2026-10-05 实测:同一网关下
|
|
461
|
+
`g-glm-5.3-flash` 席 32-39KB 连续 6 次断连,他席 36KB 一次通过)。编排规则:
|
|
462
|
+
|
|
463
|
+
1. **发送前硬闸**:runner 按 expert 条目的 `max_prompt_bytes`(默认 40000 字节,UTF-8 计)
|
|
464
|
+
拒发超限请求,输出 `error_type: "prompt_budget_exceeded"`。
|
|
465
|
+
2. **失败分类**:响应前断连且字节数超过该席位标定的 `last_pass_bytes` →
|
|
466
|
+
`error_type: "SIZE_EXCEEDED"`(不是网络故障,重试同一 payload 无意义);
|
|
467
|
+
其余失败输出 `network_error` / `retryable_error`,编排层按 `error_type` 字段断言,不解析散文。
|
|
468
|
+
3. **超限时按降序裁剪,每步只做一步**:
|
|
469
|
+
① 去附录(探针填充、日志附录、非必需长引用)→ ② 去非本轮 AC 原文 →
|
|
470
|
+
③ 去测试清单(枚举 → 计数)→ ④ 拆分两次调用(按 diff 对半,同报告合并)→
|
|
471
|
+
⑤ 仍失败 → `PROCESS_BLOCK` 交人裁定。**不得以两席结果冒充 3/3 共识。**
|
|
472
|
+
4. **标定**:上限按「固定语义核心 + 确定性填充附录」构造探针,在
|
|
473
|
+
`[last_pass, last_fail]` 区间二分 3-5 次测得;记录行含
|
|
474
|
+
`seat_id × model_id × gateway × max_passing_bytes × measured_at`;
|
|
475
|
+
模型或网关变更即重标。协议全文与种子标定表见
|
|
476
|
+
[docs/plans/2026-10-14-sprint-c-design.md](../../docs/plans/2026-10-14-sprint-c-design.md) §2。
|
|
477
|
+
|
|
435
478
|
### 共识阈值
|
|
436
479
|
|
|
437
480
|
| 阈值 | 说明 |
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-14
|
|
4
|
+
**Commit:** e466ce16
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.24.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
4
|
-
**Commit:**
|
|
3
|
+
**Generated:** 2026-10-14
|
|
4
|
+
**Commit:** e466ce16
|
|
5
5
|
**Branch:** main
|
|
6
|
-
**Version:** 0.
|
|
6
|
+
**Version:** 0.24.0.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|