From 03a0fb27ca8ed41326f306c5364e1228117f72b0 Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Wed, 11 Mar 2026 10:51:05 +0700 Subject: [PATCH 1/2] fix(ci): remove maintainability baseline gate blocking releases The maintainability gate (process.exit count + sync FS API count) was a raw grep counter that provided no actionable signal for a CLI tool. It blocked the v7.53.0 stable release because new features naturally increased the counts beyond the baseline. Removed: - scripts/maintainability-baseline.js - scripts/maintainability-check.js - docs/metrics/maintainability-baseline.json - All maintainability:* npm scripts - Gate references from release, dev-release, and CI workflows Quality gates retained: typecheck, eslint, prettier, full test suite. --- .github/workflows/ci.yml | 2 +- .github/workflows/dev-release.yml | 5 +- .github/workflows/release.yml | 2 +- docs/metrics/maintainability-baseline.json | 9 - package.json | 6 +- scripts/maintainability-baseline.js | 308 --------------------- scripts/maintainability-check.js | 163 ----------- 7 files changed, 4 insertions(+), 491 deletions(-) delete mode 100644 docs/metrics/maintainability-baseline.json delete mode 100644 scripts/maintainability-baseline.js delete mode 100644 scripts/maintainability-check.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4041af2..3cc7fc24 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,5 +30,5 @@ jobs: - name: Build package run: bun run build:all - - name: Validate (typecheck + lint + format + maintainability [warn on PR] + tests) + - name: Validate (typecheck + lint + format + tests) run: bun run validate diff --git a/.github/workflows/dev-release.yml b/.github/workflows/dev-release.yml index e61a5661..1c12c76e 100644 --- a/.github/workflows/dev-release.yml +++ b/.github/workflows/dev-release.yml @@ -48,10 +48,7 @@ jobs: - name: Build run: bun run build:all - - name: Validate (typecheck + lint + format + maintainability [warn] + tests) - env: - # Dev channel should surface maintainability regressions without blocking every merge. - CCS_MAINTAINABILITY_MODE: warn + - name: Validate (typecheck + lint + format + tests) run: bun run validate - name: Release diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index caaaed21..3bec763a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,7 +43,7 @@ jobs: - name: Build package run: bun run build:all - - name: Validate (typecheck + lint + format + maintainability [strict] + tests) + - name: Validate (typecheck + lint + format + tests) run: bun run validate - name: Release diff --git a/docs/metrics/maintainability-baseline.json b/docs/metrics/maintainability-baseline.json deleted file mode 100644 index 31a9b4e8..00000000 --- a/docs/metrics/maintainability-baseline.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "sourceDirectory": "src", - "largeFileThresholdLoc": 350, - "typeScriptFileCount": 390, - "locInSrc": 83786, - "processExitReferenceCount": 185, - "synchronousFsApiReferenceCount": 894, - "largeFileCountOver350Loc": 61 -} diff --git a/package.json b/package.json index a351e3b1..40c70904 100644 --- a/package.json +++ b/package.json @@ -65,13 +65,9 @@ "lint:fix": "eslint src/ --fix", "format": "prettier --write src/", "format:check": "prettier --check src/", - "validate": "bun run typecheck && bun run lint:fix && bun run format:check && bun run maintainability:check && bun run test:all", + "validate": "bun run typecheck && bun run lint:fix && bun run format:check && bun run test:all", "validate:ci-parity": "bash scripts/ci-parity-gate.sh", "verify:bundle": "node scripts/verify-bundle.js", - "maintainability:baseline": "node scripts/maintainability-baseline.js --out docs/metrics/maintainability-baseline.json", - "maintainability:check": "node scripts/maintainability-check.js", - "maintainability:check:strict": "node scripts/maintainability-check.js --strict", - "maintainability:check:warn": "node scripts/maintainability-check.js --warn", "test": "bun run build && bun run test:all", "test:ci": "bun run test:all", "test:all": "bun test tests/unit tests/integration tests/npm", diff --git a/scripts/maintainability-baseline.js b/scripts/maintainability-baseline.js deleted file mode 100644 index e249ad8f..00000000 --- a/scripts/maintainability-baseline.js +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/env node - -const { execFileSync } = require('child_process'); -const fs = require('fs'); -const path = require('path'); - -const PROJECT_ROOT = path.resolve(__dirname, '..'); -const SRC_DIR = path.join(PROJECT_ROOT, 'src'); -const DEFAULT_BASELINE_PATH = path.join( - PROJECT_ROOT, - 'docs', - 'metrics', - 'maintainability-baseline.json' -); - -const TYPESCRIPT_EXTENSIONS = new Set(['.ts', '.tsx', '.cts', '.mts']); -const LARGE_FILE_THRESHOLD_LOC = 350; - -const FS_SYNC_APIS = [ - 'accessSync', - 'appendFileSync', - 'chmodSync', - 'chownSync', - 'closeSync', - 'copyFileSync', - 'cpSync', - 'existsSync', - 'fchmodSync', - 'fchownSync', - 'fdatasyncSync', - 'fstatSync', - 'fsyncSync', - 'ftruncateSync', - 'futimesSync', - 'lchmodSync', - 'lchownSync', - 'linkSync', - 'lstatSync', - 'lutimesSync', - 'mkdirSync', - 'mkdtempSync', - 'openSync', - 'opendirSync', - 'readFileSync', - 'readdirSync', - 'readlinkSync', - 'readSync', - 'realpathSync', - 'renameSync', - 'rmSync', - 'rmdirSync', - 'statSync', - 'symlinkSync', - 'truncateSync', - 'unlinkSync', - 'utimesSync', - 'writeFileSync', - 'writeSync', - 'writevSync', -]; - -const PROCESS_EXIT_PATTERN = /\bprocess\s*\.\s*exit\b/g; -const FS_SYNC_PATTERN = new RegExp(`\\b(?:${FS_SYNC_APIS.join('|')})\\b`, 'g'); - -function printUsage() { - console.log( - [ - 'Usage:', - ' node scripts/maintainability-baseline.js', - ' node scripts/maintainability-baseline.js --out [path]', - ' node scripts/maintainability-baseline.js --check [path]', - '', - 'Defaults:', - ` baseline path: ${path.relative(PROJECT_ROOT, DEFAULT_BASELINE_PATH)}`, - ].join('\n') - ); -} - -function parseArgs(argv) { - const options = { - outPath: null, - checkPath: null, - }; - - for (let index = 0; index < argv.length; index += 1) { - const arg = argv[index]; - - if (arg === '--help' || arg === '-h') { - printUsage(); - process.exit(0); - } - - if (arg === '--out' || arg === '--write') { - const nextArg = argv[index + 1]; - if (nextArg && !nextArg.startsWith('--')) { - options.outPath = nextArg; - index += 1; - } else { - options.outPath = path.relative(process.cwd(), DEFAULT_BASELINE_PATH); - } - continue; - } - - if (arg === '--check') { - const nextArg = argv[index + 1]; - if (nextArg && !nextArg.startsWith('--')) { - options.checkPath = nextArg; - index += 1; - } else { - options.checkPath = path.relative(process.cwd(), DEFAULT_BASELINE_PATH); - } - continue; - } - - throw new Error(`Unknown argument: ${arg}`); - } - - return options; -} - -function collectTrackedFilesFromGit() { - let output; - try { - output = execFileSync('git', ['ls-files', '-z', '--', 'src'], { - cwd: PROJECT_ROOT, - encoding: 'utf8', - stdio: ['ignore', 'pipe', 'ignore'], - }); - } catch { - throw new Error( - 'Unable to enumerate tracked files via git. Run this command from a git checkout with git installed.' - ); - } - - if (!output) { - return []; - } - - return output - .split('\0') - .filter(Boolean) - .sort((left, right) => left.localeCompare(right)) - .map(relativePath => path.resolve(PROJECT_ROOT, relativePath)) - .filter(filePath => { - const relativeToSrc = path.relative(SRC_DIR, filePath); - if (relativeToSrc.startsWith('..') || path.isAbsolute(relativeToSrc)) { - return false; - } - - const stats = fs.statSync(filePath); - if (!stats.isFile()) { - throw new Error(`Tracked path is not a file: ${path.relative(PROJECT_ROOT, filePath)}`); - } - - return true; - }); -} - -function collectFilesInSrc() { - return collectTrackedFilesFromGit(); -} - -function countLines(content) { - if (content.length === 0) { - return 0; - } - - const lineBreakMatches = content.match(/\r\n|\n|\r/g); - const lineBreakCount = lineBreakMatches ? lineBreakMatches.length : 0; - const endsWithLineBreak = content.endsWith('\n') || content.endsWith('\r'); - - return endsWithLineBreak ? lineBreakCount : lineBreakCount + 1; -} - -function countMatches(content, pattern) { - const matches = content.match(pattern); - return matches ? matches.length : 0; -} - -function collectMetrics() { - if (!fs.existsSync(SRC_DIR)) { - throw new Error(`Directory not found: ${SRC_DIR}`); - } - - const files = collectFilesInSrc(); - - let typeScriptFileCount = 0; - let locInSrc = 0; - let processExitReferenceCount = 0; - let synchronousFsApiReferenceCount = 0; - let largeFileCountOver350Loc = 0; - - for (const filePath of files) { - const content = fs.readFileSync(filePath, 'utf8'); - const loc = countLines(content); - const extension = path.extname(filePath).toLowerCase(); - const isTypeScriptFile = TYPESCRIPT_EXTENSIONS.has(extension); - - locInSrc += loc; - processExitReferenceCount += countMatches(content, PROCESS_EXIT_PATTERN); - synchronousFsApiReferenceCount += countMatches(content, FS_SYNC_PATTERN); - - if (isTypeScriptFile) { - typeScriptFileCount += 1; - if (loc > LARGE_FILE_THRESHOLD_LOC) { - largeFileCountOver350Loc += 1; - } - } - } - - return { - sourceDirectory: 'src', - largeFileThresholdLoc: LARGE_FILE_THRESHOLD_LOC, - typeScriptFileCount, - locInSrc, - processExitReferenceCount, - synchronousFsApiReferenceCount, - largeFileCountOver350Loc, - }; -} - -function writeMetrics(outPath, metrics) { - const resolvedOutPath = path.resolve(process.cwd(), outPath); - fs.mkdirSync(path.dirname(resolvedOutPath), { recursive: true }); - fs.writeFileSync(resolvedOutPath, `${JSON.stringify(metrics, null, 2)}\n`, 'utf8'); -} - -function runCheck(checkPath, currentMetrics) { - const resolvedCheckPath = path.resolve(process.cwd(), checkPath); - const baselineContent = fs.readFileSync(resolvedCheckPath, 'utf8'); - const baselineMetrics = JSON.parse(baselineContent); - - if (baselineMetrics.sourceDirectory !== currentMetrics.sourceDirectory) { - throw new Error( - `Baseline sourceDirectory mismatch: expected "${currentMetrics.sourceDirectory}", got "${baselineMetrics.sourceDirectory}"` - ); - } - - if (baselineMetrics.largeFileThresholdLoc !== currentMetrics.largeFileThresholdLoc) { - throw new Error( - `Baseline largeFileThresholdLoc mismatch: expected ${currentMetrics.largeFileThresholdLoc}, got ${baselineMetrics.largeFileThresholdLoc}` - ); - } - - const gatedKeys = [ - 'processExitReferenceCount', - 'synchronousFsApiReferenceCount', - ]; - - const violations = []; - for (const key of gatedKeys) { - if (typeof baselineMetrics[key] !== 'number') { - throw new Error(`Baseline is missing numeric metric: ${key}`); - } - - if (currentMetrics[key] > baselineMetrics[key]) { - violations.push({ - metric: key, - baseline: baselineMetrics[key], - current: currentMetrics[key], - }); - } - } - - return { - gate: 'maintainability-baseline', - baselinePath: path.relative(PROJECT_ROOT, resolvedCheckPath), - passed: violations.length === 0, - comparedMetrics: gatedKeys, - baseline: { - typeScriptFileCount: baselineMetrics.typeScriptFileCount, - locInSrc: baselineMetrics.locInSrc, - processExitReferenceCount: baselineMetrics.processExitReferenceCount, - synchronousFsApiReferenceCount: baselineMetrics.synchronousFsApiReferenceCount, - largeFileCountOver350Loc: baselineMetrics.largeFileCountOver350Loc, - }, - current: { - typeScriptFileCount: currentMetrics.typeScriptFileCount, - locInSrc: currentMetrics.locInSrc, - processExitReferenceCount: currentMetrics.processExitReferenceCount, - synchronousFsApiReferenceCount: currentMetrics.synchronousFsApiReferenceCount, - largeFileCountOver350Loc: currentMetrics.largeFileCountOver350Loc, - }, - violations, - }; -} - -function main() { - const options = parseArgs(process.argv.slice(2)); - const metrics = collectMetrics(); - - if (options.outPath) { - writeMetrics(options.outPath, metrics); - } - - if (options.checkPath) { - const checkResult = runCheck(options.checkPath, metrics); - console.log(JSON.stringify(checkResult, null, 2)); - if (!checkResult.passed) { - process.exit(1); - } - return; - } - - console.log(JSON.stringify(metrics, null, 2)); -} - -main(); diff --git a/scripts/maintainability-check.js b/scripts/maintainability-check.js deleted file mode 100644 index 8971ef84..00000000 --- a/scripts/maintainability-check.js +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/env node - -const { execFileSync, spawnSync } = require('child_process'); -const path = require('path'); - -const PROJECT_ROOT = path.resolve(__dirname, '..'); -const BASELINE_FILE = path.join('docs', 'metrics', 'maintainability-baseline.json'); -const BASELINE_SCRIPT = path.join(PROJECT_ROOT, 'scripts', 'maintainability-baseline.js'); - -const PROTECTED_BRANCHES = new Set(['main', 'dev']); -const HOTFIX_PREFIXES = ['hotfix/', 'kai/hotfix-']; - -function hasFlag(name) { - return process.argv.slice(2).includes(name); -} - -function detectBranchName() { - try { - return execFileSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { - cwd: PROJECT_ROOT, - encoding: 'utf8', - stdio: ['ignore', 'pipe', 'ignore'], - }).trim(); - } catch { - return ''; - } -} - -function isProtectedBranch(branchName) { - if (!branchName) { - return false; - } - - if (PROTECTED_BRANCHES.has(branchName)) { - return true; - } - - return HOTFIX_PREFIXES.some(prefix => branchName.startsWith(prefix)); -} - -function detectMode() { - if (hasFlag('--strict')) { - return 'strict'; - } - - if (hasFlag('--warn')) { - return 'warn'; - } - - if (hasFlag('--off')) { - return 'off'; - } - - const explicitMode = (process.env.CCS_MAINTAINABILITY_MODE || '').toLowerCase().trim(); - if (explicitMode === 'strict' || explicitMode === 'warn' || explicitMode === 'off') { - return explicitMode; - } - - const eventName = process.env.GITHUB_EVENT_NAME || ''; - if (eventName === 'pull_request' || eventName === 'pull_request_target') { - return 'warn'; - } - - const gitHubRef = process.env.GITHUB_REF || ''; - if (gitHubRef.startsWith('refs/heads/')) { - const branchFromRef = gitHubRef.slice('refs/heads/'.length); - if (isProtectedBranch(branchFromRef)) { - return 'strict'; - } - } - - return isProtectedBranch(detectBranchName()) ? 'strict' : 'warn'; -} - -function runBaselineCheck() { - return spawnSync('node', [BASELINE_SCRIPT, '--check', BASELINE_FILE], { - cwd: PROJECT_ROOT, - encoding: 'utf8', - stdio: ['ignore', 'pipe', 'pipe'], - }); -} - -function writeStreams(result) { - if (result.stdout) { - process.stdout.write(result.stdout); - } - if (result.stderr) { - process.stderr.write(result.stderr); - } -} - -function tryParseJson(stdout) { - if (!stdout) { - return null; - } - - try { - return JSON.parse(stdout); - } catch { - return null; - } -} - -function formatViolations(violations) { - if (!Array.isArray(violations) || violations.length === 0) { - return []; - } - - return violations.map(violation => { - if (!violation || typeof violation !== 'object') { - return '- unknown violation'; - } - - const metric = violation.metric || 'unknown'; - const baseline = typeof violation.baseline === 'number' ? violation.baseline : 'n/a'; - const current = typeof violation.current === 'number' ? violation.current : 'n/a'; - return `- ${metric}: baseline=${baseline}, current=${current}`; - }); -} - -function main() { - const mode = detectMode(); - - if (mode === 'off') { - console.log('[i] Maintainability gate disabled (mode=off).'); - process.exit(0); - } - - const result = runBaselineCheck(); - if (mode === 'strict') { - writeStreams(result); - process.exit(result.status === null ? 1 : result.status); - } - - if (result.status === 0) { - writeStreams(result); - process.exit(0); - } - - const parsed = tryParseJson(result.stdout); - const branchName = detectBranchName(); - - console.log('[!] Maintainability regression detected (warning-only mode).'); - if (branchName) { - console.log(`[i] Branch: ${branchName}`); - } - - if (parsed && Array.isArray(parsed.violations) && parsed.violations.length > 0) { - console.log('[i] Violations:'); - for (const line of formatViolations(parsed.violations)) { - console.log(line); - } - } else { - writeStreams(result); - } - - console.log('[i] This is non-blocking on PR/feature branches to support parallel workflow.'); - console.log( - '[i] Use strict mode when needed: bun run maintainability:check:strict' - ); -} - -main(); From 59a2eaf1c69399a476cad15b6ca910eea6a31f8f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 11 Mar 2026 03:53:39 +0000 Subject: [PATCH 2/2] chore(release): 7.53.0 [skip ci] ## [7.53.0](https://github.com/kaitranntt/ccs/compare/v7.52.2...v7.53.0) (2026-03-11) ### Features * add API profile lifecycle discover/copy/export/import parity ([02c8174](https://github.com/kaitranntt/ccs/commit/02c81743a09cc54447f953e5b4d4f95ad85f1ad9)) * **api:** add Anthropic direct API key support ([fedb4d4](https://github.com/kaitranntt/ccs/commit/fedb4d4cde4c9027f95364e66daa77b700a5c470)), closes [#688](https://github.com/kaitranntt/ccs/issues/688) * **api:** add llama.cpp support as local model provider ([0ca6428](https://github.com/kaitranntt/ccs/commit/0ca6428554be9057926988ef4af0b95a958ca17e)), closes [#690](https://github.com/kaitranntt/ccs/issues/690) * **auth:** add --bare flag and MCP server sync for profiles ([bc9b044](https://github.com/kaitranntt/ccs/commit/bc9b04444e0dbeb3db72b4814ca6694595abf0cd)), closes [#691](https://github.com/kaitranntt/ccs/issues/691) [#692](https://github.com/kaitranntt/ccs/issues/692) ### Bug Fixes * **api:** complete anthropic direct profile support ([1f29fa0](https://github.com/kaitranntt/ccs/commit/1f29fa0b6ab366e558eadbe050e79e294f2eaa43)) * **auth:** preserve bare profile behavior across runtime and sync ([8f8684c](https://github.com/kaitranntt/ccs/commit/8f8684ce852f527a019e0a32d94922d15b078633)) * **ci:** remove LOC count from maintainability gate ([d3ede45](https://github.com/kaitranntt/ccs/commit/d3ede45c9612bb2415d24798fe43d6cba188f142)) * **ci:** remove maintainability baseline gate blocking releases ([03a0fb2](https://github.com/kaitranntt/ccs/commit/03a0fb27ca8ed41326f306c5364e1228117f72b0)) * clarify CLIProxy dashboard install lifecycle ([a4b626a](https://github.com/kaitranntt/ccs/commit/a4b626aedef2a0cf690a955bf4abd31c5284047a)) * **cliproxy:** handle Claude OAuth quota 401 ([7e8f9e8](https://github.com/kaitranntt/ccs/commit/7e8f9e82c113490d95b0a9f9bedf627bc11dc76a)) * **cliproxy:** poll paste-callback auth urls ([b25b165](https://github.com/kaitranntt/ccs/commit/b25b1653b047c588a95c6f4e47aa3214e0e370aa)) * **cliproxy:** preserve Claude fallback when quota is unavailable ([6ed95a2](https://github.com/kaitranntt/ccs/commit/6ed95a2a861f1031d0d49cd8d53a2ccd5c4214a6)) * **cliproxy:** preserve kiro paste-callback start route ([86ca180](https://github.com/kaitranntt/ccs/commit/86ca18003a033be976b787811db16bf38bf82a91)) * **cliproxy:** sync claude 4.6 selector defaults ([3d183fe](https://github.com/kaitranntt/ccs/commit/3d183fe0e891886bbd51a3c5b30b301e966cce03)) * **cliproxy:** use management auth-url route in paste callback ([6fcd924](https://github.com/kaitranntt/ccs/commit/6fcd924b1c8743484823b958ff403c4c37379eab)) * **cliproxy:** use management oauth-callback in paste flow ([fa02702](https://github.com/kaitranntt/ccs/commit/fa027022a8faf886c7f5891ec8cb2d3879c783e8)) * **codex:** standardize haiku defaults on gpt-5.1-codex-mini ([f4a7d4d](https://github.com/kaitranntt/ccs/commit/f4a7d4dc2c84b094192dba30522c475ced3293d6)) * complete codex tool sanitization coverage ([4baed01](https://github.com/kaitranntt/ccs/commit/4baed01d4905ecf3fbbfb2f4e8ac7dca34ebf907)) * **config:** align claude defaults across catalogs ([bea3084](https://github.com/kaitranntt/ccs/commit/bea3084d5e4f7bc691503cffee8a235f94c3b87d)) * **config:** update claude base models to latest ([09aeec5](https://github.com/kaitranntt/ccs/commit/09aeec57633828f9225591e090d8f442abc9d322)) * **config:** use correct codex haiku model ID (gpt-5-codex-mini) ([8a9751a](https://github.com/kaitranntt/ccs/commit/8a9751a819e41c527ec413e988b18f48df62332a)), closes [#602](https://github.com/kaitranntt/ccs/issues/602) * confirm risky cliproxy installs in dashboard ([aed7beb](https://github.com/kaitranntt/ccs/commit/aed7beb075c2f31263423005c34e690af3463039)) * **copilot:** surface upstream model limits ([8a5ed65](https://github.com/kaitranntt/ccs/commit/8a5ed656eec08ccaae44ddde72cb0ca954b05875)) * harden profile lifecycle validation and dashboard UX flows ([d6fc5dd](https://github.com/kaitranntt/ccs/commit/d6fc5dd64c3232e9c95a54b0e433f3e057fd7fa4)) * **hooks:** handle thinking blocks in image analyzer response parsing ([0060c77](https://github.com/kaitranntt/ccs/commit/0060c77c257a64c57f4c704d2f32af415434022f)), closes [#511](https://github.com/kaitranntt/ccs/issues/511) * improve quota diagnostics and oauth refresh handling ([fc3600e](https://github.com/kaitranntt/ccs/commit/fc3600e9228790179c8c51162924187ec994c49a)) * restart CLIProxy after dashboard version install ([e14df1f](https://github.com/kaitranntt/ccs/commit/e14df1fe05ce1fcbe515f6b1d969132ace91ed24)) * stop untracked CLIProxy installs safely ([ad01196](https://github.com/kaitranntt/ccs/commit/ad01196964bfdbdd0696cc845f3b3d3901b3be2f)) * strip unsupported gemini and codex tool fields ([8cfd86f](https://github.com/kaitranntt/ccs/commit/8cfd86f1d18356b6bfef931d24c1745e11e1db62)) * sync error code docs links ([2be5c5a](https://github.com/kaitranntt/ccs/commit/2be5c5a706bc659491decd66c3f21a8839f35e9c)) * **ui:** update copilot default claude model ([4d0ded3](https://github.com/kaitranntt/ccs/commit/4d0ded339f12abb4fec1c8596fac07c67581351f)) * **ui:** use preset apiKeyPlaceholder when creating profiles ([6078de7](https://github.com/kaitranntt/ccs/commit/6078de78f2a7e31ec141a49c057a8b4cb1a6d601)) ### Tests * cover llama.cpp help parity ([9bcb195](https://github.com/kaitranntt/ccs/commit/9bcb195e7c82a85e94e9de39530f185efad60ecd)) * **hooks:** add image analyzer regression coverage ([5097375](https://github.com/kaitranntt/ccs/commit/50973752bac0eabea57e76e5d0c64b460fd525a7)) ### CI * harden AI review for external PRs ([becfc57](https://github.com/kaitranntt/ccs/commit/becfc573c9a63b7b53153882973aca8be9b3b4cf)) --- CHANGELOG.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b4c60ed..50746769 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,52 @@ +## [7.53.0](https://github.com/kaitranntt/ccs/compare/v7.52.2...v7.53.0) (2026-03-11) + +### Features + +* add API profile lifecycle discover/copy/export/import parity ([02c8174](https://github.com/kaitranntt/ccs/commit/02c81743a09cc54447f953e5b4d4f95ad85f1ad9)) +* **api:** add Anthropic direct API key support ([fedb4d4](https://github.com/kaitranntt/ccs/commit/fedb4d4cde4c9027f95364e66daa77b700a5c470)), closes [#688](https://github.com/kaitranntt/ccs/issues/688) +* **api:** add llama.cpp support as local model provider ([0ca6428](https://github.com/kaitranntt/ccs/commit/0ca6428554be9057926988ef4af0b95a958ca17e)), closes [#690](https://github.com/kaitranntt/ccs/issues/690) +* **auth:** add --bare flag and MCP server sync for profiles ([bc9b044](https://github.com/kaitranntt/ccs/commit/bc9b04444e0dbeb3db72b4814ca6694595abf0cd)), closes [#691](https://github.com/kaitranntt/ccs/issues/691) [#692](https://github.com/kaitranntt/ccs/issues/692) + +### Bug Fixes + +* **api:** complete anthropic direct profile support ([1f29fa0](https://github.com/kaitranntt/ccs/commit/1f29fa0b6ab366e558eadbe050e79e294f2eaa43)) +* **auth:** preserve bare profile behavior across runtime and sync ([8f8684c](https://github.com/kaitranntt/ccs/commit/8f8684ce852f527a019e0a32d94922d15b078633)) +* **ci:** remove LOC count from maintainability gate ([d3ede45](https://github.com/kaitranntt/ccs/commit/d3ede45c9612bb2415d24798fe43d6cba188f142)) +* **ci:** remove maintainability baseline gate blocking releases ([03a0fb2](https://github.com/kaitranntt/ccs/commit/03a0fb27ca8ed41326f306c5364e1228117f72b0)) +* clarify CLIProxy dashboard install lifecycle ([a4b626a](https://github.com/kaitranntt/ccs/commit/a4b626aedef2a0cf690a955bf4abd31c5284047a)) +* **cliproxy:** handle Claude OAuth quota 401 ([7e8f9e8](https://github.com/kaitranntt/ccs/commit/7e8f9e82c113490d95b0a9f9bedf627bc11dc76a)) +* **cliproxy:** poll paste-callback auth urls ([b25b165](https://github.com/kaitranntt/ccs/commit/b25b1653b047c588a95c6f4e47aa3214e0e370aa)) +* **cliproxy:** preserve Claude fallback when quota is unavailable ([6ed95a2](https://github.com/kaitranntt/ccs/commit/6ed95a2a861f1031d0d49cd8d53a2ccd5c4214a6)) +* **cliproxy:** preserve kiro paste-callback start route ([86ca180](https://github.com/kaitranntt/ccs/commit/86ca18003a033be976b787811db16bf38bf82a91)) +* **cliproxy:** sync claude 4.6 selector defaults ([3d183fe](https://github.com/kaitranntt/ccs/commit/3d183fe0e891886bbd51a3c5b30b301e966cce03)) +* **cliproxy:** use management auth-url route in paste callback ([6fcd924](https://github.com/kaitranntt/ccs/commit/6fcd924b1c8743484823b958ff403c4c37379eab)) +* **cliproxy:** use management oauth-callback in paste flow ([fa02702](https://github.com/kaitranntt/ccs/commit/fa027022a8faf886c7f5891ec8cb2d3879c783e8)) +* **codex:** standardize haiku defaults on gpt-5.1-codex-mini ([f4a7d4d](https://github.com/kaitranntt/ccs/commit/f4a7d4dc2c84b094192dba30522c475ced3293d6)) +* complete codex tool sanitization coverage ([4baed01](https://github.com/kaitranntt/ccs/commit/4baed01d4905ecf3fbbfb2f4e8ac7dca34ebf907)) +* **config:** align claude defaults across catalogs ([bea3084](https://github.com/kaitranntt/ccs/commit/bea3084d5e4f7bc691503cffee8a235f94c3b87d)) +* **config:** update claude base models to latest ([09aeec5](https://github.com/kaitranntt/ccs/commit/09aeec57633828f9225591e090d8f442abc9d322)) +* **config:** use correct codex haiku model ID (gpt-5-codex-mini) ([8a9751a](https://github.com/kaitranntt/ccs/commit/8a9751a819e41c527ec413e988b18f48df62332a)), closes [#602](https://github.com/kaitranntt/ccs/issues/602) +* confirm risky cliproxy installs in dashboard ([aed7beb](https://github.com/kaitranntt/ccs/commit/aed7beb075c2f31263423005c34e690af3463039)) +* **copilot:** surface upstream model limits ([8a5ed65](https://github.com/kaitranntt/ccs/commit/8a5ed656eec08ccaae44ddde72cb0ca954b05875)) +* harden profile lifecycle validation and dashboard UX flows ([d6fc5dd](https://github.com/kaitranntt/ccs/commit/d6fc5dd64c3232e9c95a54b0e433f3e057fd7fa4)) +* **hooks:** handle thinking blocks in image analyzer response parsing ([0060c77](https://github.com/kaitranntt/ccs/commit/0060c77c257a64c57f4c704d2f32af415434022f)), closes [#511](https://github.com/kaitranntt/ccs/issues/511) +* improve quota diagnostics and oauth refresh handling ([fc3600e](https://github.com/kaitranntt/ccs/commit/fc3600e9228790179c8c51162924187ec994c49a)) +* restart CLIProxy after dashboard version install ([e14df1f](https://github.com/kaitranntt/ccs/commit/e14df1fe05ce1fcbe515f6b1d969132ace91ed24)) +* stop untracked CLIProxy installs safely ([ad01196](https://github.com/kaitranntt/ccs/commit/ad01196964bfdbdd0696cc845f3b3d3901b3be2f)) +* strip unsupported gemini and codex tool fields ([8cfd86f](https://github.com/kaitranntt/ccs/commit/8cfd86f1d18356b6bfef931d24c1745e11e1db62)) +* sync error code docs links ([2be5c5a](https://github.com/kaitranntt/ccs/commit/2be5c5a706bc659491decd66c3f21a8839f35e9c)) +* **ui:** update copilot default claude model ([4d0ded3](https://github.com/kaitranntt/ccs/commit/4d0ded339f12abb4fec1c8596fac07c67581351f)) +* **ui:** use preset apiKeyPlaceholder when creating profiles ([6078de7](https://github.com/kaitranntt/ccs/commit/6078de78f2a7e31ec141a49c057a8b4cb1a6d601)) + +### Tests + +* cover llama.cpp help parity ([9bcb195](https://github.com/kaitranntt/ccs/commit/9bcb195e7c82a85e94e9de39530f185efad60ecd)) +* **hooks:** add image analyzer regression coverage ([5097375](https://github.com/kaitranntt/ccs/commit/50973752bac0eabea57e76e5d0c64b460fd525a7)) + +### CI + +* harden AI review for external PRs ([becfc57](https://github.com/kaitranntt/ccs/commit/becfc573c9a63b7b53153882973aca8be9b3b4cf)) + ## [7.52.2](https://github.com/kaitranntt/ccs/compare/v7.52.1...v7.52.2) (2026-03-04) ### Bug Fixes diff --git a/package.json b/package.json index 40c70904..34bddfe6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "7.52.2-dev.13", + "version": "7.53.0", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli",