fix(delegation): improve profile discovery and CI workflow (#310)

* fix(doctor): use dynamic profile discovery for delegation check

Replace hardcoded ['glm', 'kimi'] list with DelegationValidator.getReadyProfiles()
to detect all configured *.settings.json profiles including mm, or1, g7, etc.

* fix(ci): exclude bot comments from triggering AI review

Bot progress comments were triggering new workflow runs,
which cancelled in-progress reviews due to concurrency group.
Added check for github.event.comment.user.type != 'Bot'.

* chore(release): 7.18.0-dev.1 [skip ci]

* fix(delegation): only check profiles defined in config.yaml

Previously getReadyProfiles() scanned all *.settings.json files,
including orphan files (ghcp, kiro) not in config.yaml.

Now reads from config.yaml:
- profiles section (excluding 'default')
- cliproxy.providers section

Fixes doctor showing 11 profiles instead of configured 9.

* chore(release): 7.18.0-dev.2 [skip ci]

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Kai (Tam Nhu) Tran
2026-01-09 00:18:30 -06:00
committed by GitHub
co-authored by github-actions[bot] <github-actions[bot]@users.noreply.github.com>
parent f290aae4cb
commit affdaead80
4 changed files with 36 additions and 20 deletions
+30 -8
View File
@@ -139,27 +139,49 @@ export class DelegationValidator {
}
/**
* Get all delegation-ready profiles
* Get all delegation-ready profiles from config.yaml
* Only returns profiles explicitly defined in config, not orphan settings files
* @returns List of profile names ready for delegation
*/
static getReadyProfiles(): string[] {
const homeDir = os.homedir();
const ccsDir = path.join(homeDir, '.ccs');
const configPath = path.join(ccsDir, 'config.yaml');
if (!fs.existsSync(ccsDir)) {
return [];
}
const profiles: string[] = [];
const entries = fs.readdirSync(ccsDir, { withFileTypes: true });
// Look for *.settings.json files
for (const entry of entries) {
if (entry.isFile() && entry.name.endsWith('.settings.json')) {
const profileName = entry.name.replace('.settings.json', '');
if (this.isReady(profileName)) {
profiles.push(profileName);
// Get profiles from config.yaml (excludes 'default' which uses ~/.claude/settings.json)
if (fs.existsSync(configPath)) {
try {
const yaml = require('js-yaml');
const content = fs.readFileSync(configPath, 'utf8');
const config = yaml.load(content) as Record<string, unknown>;
if (config.profiles && typeof config.profiles === 'object') {
for (const profileName of Object.keys(config.profiles as object)) {
if (profileName !== 'default' && this.isReady(profileName)) {
profiles.push(profileName);
}
}
}
// Also check CLIProxy providers (gemini, codex, agy, etc.)
if (config.cliproxy && typeof config.cliproxy === 'object') {
const cliproxy = config.cliproxy as Record<string, unknown>;
if (Array.isArray(cliproxy.providers)) {
for (const provider of cliproxy.providers) {
if (typeof provider === 'string' && this.isReady(provider)) {
profiles.push(provider);
}
}
}
}
} catch {
// Config parse error, fall back to empty
}
}