Merge pull request #543 from kaitranntt/kai/feat/538-stream-d-hardening

chore(hardening): add debt inventory and async I/O kickoff (stream D)
This commit is contained in:
Kai (Tam Nhu) Tran authored and GitHub committed 2026-02-12 16:21:18 +07:00
commit a2520d2ed8
9 files changed
+1152 -3

No files matched your search

+45
View File
@@ -0,0 +1,45 @@
# Hardening Debt Burndown Tracker
Last Updated: 2026-02-12
Owner: Stream D (`#542`)
## Scope
Maintainability hardening groundwork with low-risk changes:
- Inventory legacy shims/compatibility markers
- Inventory sync filesystem usage, especially runtime hotpaths
- Incrementally migrate hotpath sync I/O to async I/O with tests
## How to Measure
Run:
```bash
bun run report:hardening
```
Generated artifacts:
- `docs/reports/hardening-inventory.json`
- `docs/reports/hardening-inventory.md`
## Kickoff Baseline (Issue #542 Stream D)
The current baseline is sourced from `docs/reports/hardening-inventory.json` after running `bun run report:hardening`.
Baseline captured: `2026-02-12`.
| Metric | Baseline |
|---|---:|
| Sync fs occurrences (all) | 835 |
| Sync fs files affected (all) | 100 |
| Sync fs occurrences (runtime hotpaths) | 724 |
| Sync fs files affected (runtime hotpaths) | 89 |
| Legacy shim markers | 131 |
| Legacy shim files affected | 56 |
## Initial Async I/O Migration Log
| Date | Area | Change | Safety Notes |
|---|---|---|---|
| 2026-02-12 | `src/web-server/jsonl-parser.ts` | Migrated `parseProjectDirectory()` directory listing from sync `readdirSync` to async `fs.promises.readdir` | Existing behavior kept (same filtering/fallback); covered by `tests/unit/jsonl-parser.test.ts` |
+11 -1
View File
@@ -1,6 +1,6 @@
# CCS Project Roadmap
Last Updated: 2026-02-04
Last Updated: 2026-02-12
Forward-looking roadmap documenting current priorities, GitHub issues, and future feature plans.
@@ -39,6 +39,15 @@ All major modularization work is complete. The codebase evolved from monolithic
## Current Status
### Maintainability Hardening Kickoff
- Issue owner: Stream D for **#542**
- Automated inventory command: `bun run report:hardening`
- Generated report artifacts:
- `docs/reports/hardening-inventory.json`
- `docs/reports/hardening-inventory.md`
- Debt burndown tracker: [Hardening Debt Burndown Tracker](./hardening-debt-burndown.md)
### Remaining Large Files (Acceptable)
**CLI** (complex core logic):
@@ -215,4 +224,5 @@ The check mode supports a maintainability regression gate that blocks increases
- [Codebase Summary](./codebase-summary.md) - Current structure
- [Code Standards](./code-standards.md) - Patterns and conventions
- [System Architecture](./system-architecture.md) - Architecture diagrams
- [Hardening Debt Burndown Tracker](./hardening-debt-burndown.md) - Legacy shim + sync-fs debt tracking
- [CLAUDE.md](../CLAUDE.md) - AI development guidance
+470
View File
@@ -0,0 +1,470 @@
{
"scope": "src/**/*.{ts,tsx,js,jsx,mjs,cjs}",
"syncFs": {
"totalOccurrences": 835,
"filesAffected": 100,
"hotpathOccurrences": 724,
"hotpathFilesAffected": 89,
"topHotpathFiles": [
{
"file": "src/management/shared-manager.ts",
"count": 60,
"calls": [
"copyFileSync",
"cpSync",
"existsSync",
"lstatSync",
"mkdirSync",
"readdirSync",
"readFileSync",
"readlinkSync",
"rmSync",
"statSync",
"symlinkSync",
"unlinkSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/utils/claude-symlink-manager.ts",
"count": 27,
"calls": [
"copyFileSync",
"existsSync",
"lstatSync",
"mkdirSync",
"readdirSync",
"readlinkSync",
"renameSync",
"rmSync",
"statSync",
"symlinkSync",
"unlinkSync"
],
"markers": []
},
{
"file": "src/utils/shell-completion.ts",
"count": 23,
"calls": [
"appendFileSync",
"copyFileSync",
"existsSync",
"mkdirSync",
"readFileSync",
"statSync"
],
"markers": []
},
{
"file": "src/web-server/routes/settings-routes.ts",
"count": 23,
"calls": [
"copyFileSync",
"existsSync",
"mkdirSync",
"readFileSync",
"renameSync",
"statSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/utils/claude-dir-installer.ts",
"count": 21,
"calls": [
"copyFileSync",
"cpSync",
"existsSync",
"lstatSync",
"mkdirSync",
"readdirSync",
"renameSync",
"rmSync",
"statSync",
"unlinkSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/cliproxy/binary/version-cache.ts",
"count": 20,
"calls": [
"existsSync",
"mkdirSync",
"readFileSync",
"unlinkSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/management/recovery-manager.ts",
"count": 20,
"calls": [
"copyFileSync",
"existsSync",
"mkdirSync",
"renameSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/web-server/routes/cliproxy-stats-routes.ts",
"count": 20,
"calls": [
"closeSync",
"existsSync",
"fstatSync",
"mkdirSync",
"openSync",
"readdirSync",
"readFileSync",
"readSync",
"renameSync",
"statSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/web-server/routes/misc-routes.ts",
"count": 20,
"calls": [
"copyFileSync",
"existsSync",
"mkdirSync",
"readdirSync",
"readFileSync",
"renameSync",
"statSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/web-server/routes/persist-routes.ts",
"count": 17,
"calls": [
"closeSync",
"copyFileSync",
"existsSync",
"lstatSync",
"openSync",
"readdirSync",
"readSync",
"renameSync",
"unlinkSync",
"writeFileSync"
],
"markers": []
}
],
"topFilesOverall": [
{
"file": "src/management/shared-manager.ts",
"count": 60,
"calls": [
"copyFileSync",
"cpSync",
"existsSync",
"lstatSync",
"mkdirSync",
"readdirSync",
"readFileSync",
"readlinkSync",
"rmSync",
"statSync",
"symlinkSync",
"unlinkSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/config/migration-manager.ts",
"count": 27,
"calls": [
"copyFileSync",
"existsSync",
"mkdirSync",
"readdirSync",
"readFileSync",
"renameSync",
"rmdirSync",
"unlinkSync"
],
"markers": []
},
{
"file": "src/utils/claude-symlink-manager.ts",
"count": 27,
"calls": [
"copyFileSync",
"existsSync",
"lstatSync",
"mkdirSync",
"readdirSync",
"readlinkSync",
"renameSync",
"rmSync",
"statSync",
"symlinkSync",
"unlinkSync"
],
"markers": []
},
{
"file": "src/utils/shell-completion.ts",
"count": 23,
"calls": [
"appendFileSync",
"copyFileSync",
"existsSync",
"mkdirSync",
"readFileSync",
"statSync"
],
"markers": []
},
{
"file": "src/web-server/routes/settings-routes.ts",
"count": 23,
"calls": [
"copyFileSync",
"existsSync",
"mkdirSync",
"readFileSync",
"renameSync",
"statSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/utils/claude-dir-installer.ts",
"count": 21,
"calls": [
"copyFileSync",
"cpSync",
"existsSync",
"lstatSync",
"mkdirSync",
"readdirSync",
"renameSync",
"rmSync",
"statSync",
"unlinkSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/cliproxy/binary/version-cache.ts",
"count": 20,
"calls": [
"existsSync",
"mkdirSync",
"readFileSync",
"unlinkSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/copilot/copilot-package-manager.ts",
"count": 20,
"calls": [
"existsSync",
"mkdirSync",
"readFileSync",
"rmSync",
"unlinkSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/management/recovery-manager.ts",
"count": 20,
"calls": [
"copyFileSync",
"existsSync",
"mkdirSync",
"renameSync",
"writeFileSync"
],
"markers": []
},
{
"file": "src/web-server/routes/cliproxy-stats-routes.ts",
"count": 20,
"calls": [
"closeSync",
"existsSync",
"fstatSync",
"mkdirSync",
"openSync",
"readdirSync",
"readFileSync",
"readSync",
"renameSync",
"statSync",
"writeFileSync"
],
"markers": []
}
]
},
"legacyShim": {
"totalMarkers": 131,
"filesAffected": 56,
"topFiles": [
{
"file": "src/utils/config-manager.ts",
"count": 13,
"calls": [],
"markers": [
"* Get config file path (legacy JSON path)",
"* Precedence: --config-dir flag > CCS_DIR env > CCS_HOME env (legacy, appends .ccs) > ~/.ccs default",
"* Read and parse config (legacy compatibility)",
"* Returns Config with profiles from unified config.yaml or legacy config.json.",
"* Returns config.yaml in unified mode, config.json in legacy mode.",
"* then falls back to config.json for backward compatibility.",
"// Convert unified cliproxy variants to legacy format",
"// Convert unified profiles to legacy format for compatibility",
"// If not found in unified config, try legacy config.json as fallback",
"// Legacy config is invalid JSON - that's OK in unified mode",
"// Legacy mode - read from config.json only",
"// Legacy mode: read config.json",
"// Merge legacy profiles into available list (avoid duplicates)"
]
},
{
"file": "src/auth/profile-detector.ts",
"count": 11,
"calls": [],
"markers": [
"* - Legacy JSON format (config.json, profiles.json) as fallback",
"* 2. User-defined CLIProxy variants (config.cliproxy section) [legacy]",
"* 3. Settings-based profiles (config.profiles section) [legacy]",
"* 4. Account-based profiles (profiles.json) [legacy]",
"* Priority: settings-based profiles (glm/kimi) checked FIRST for backward compatibility.",
"// Check if account-based default exists (legacy)",
"// Fall back to legacy config",
"// Fall back to legacy config display",
"// Fall through to legacy if not found in unified config",
"// Priority 3: Check settings-based profiles (glm, kimi) - LEGACY FALLBACK",
"// Priority 4: Check account-based profiles (work, personal) - LEGACY FALLBACK"
]
},
{
"file": "src/config/unified-config-loader.ts",
"count": 9,
"calls": [],
"markers": [
"* 'json' if only legacy config exists,",
"* Check if legacy config.json exists",
"* Get path to legacy config.json",
"* Provides fallback to legacy JSON format for backward compatibility.",
"// Legacy field for backwards compatibility",
"// Legacy fields (deprecated)",
"// Legacy fields (keep for backwards compatibility during read)",
"partial.websearch?.gemini?.enabled ?? // Legacy fallback",
"partial.websearch?.gemini?.timeout ?? // Legacy fallback"
]
},
{
"file": "src/commands/setup-command.ts",
"count": 7,
"calls": [],
"markers": [
"* 3. Legacy config.json profiles (GLM, Kimi)",
"* 4. Legacy profiles.json accounts",
"// Also check legacy config.json for existing profiles",
"// Has legacy accounts - NOT first time",
"// Has legacy profiles - NOT first time",
"// Legacy config exists but is invalid - ignore and continue",
"// Legacy profiles exists but is invalid - ignore and continue"
]
},
{
"file": "src/management/checks/config-check.ts",
"count": 6,
"calls": [],
"markers": [
"* - Prefers config.yaml (v2) over config.json (legacy)",
"// Fallback to config.json (legacy format)",
"// Inform if legacy config.json also exists (purely informational, not a check)",
"console.log(` ${info('config.json'.padEnd(22))} Legacy (ignored)`);",
"console.log(` ${ok('config.json'.padEnd(22))} Valid (legacy)`);",
"info: 'Valid (legacy)',"
]
},
{
"file": "src/web-server/routes/account-routes.ts",
"count": 6,
"calls": [],
"markers": [
"* Uses ProfileRegistry to read from both legacy (profiles.json)",
"// Add legacy profiles first",
"// Delete from appropriate config (unified and/or legacy)",
"// Get default from unified config first, fallback to legacy",
"// Get profiles from both legacy and unified config (same logic as CLI)",
"// Use unified config if in unified mode, otherwise use legacy"
]
},
{
"file": "src/config/migration-manager.ts",
"count": 5,
"calls": [],
"markers": [
"* Check if there are legacy profiles that haven't been migrated to config.yaml.",
"* Handles migration from legacy JSON config (v1) to unified YAML config (v2).",
"`Profile \"${name}\" exists in both configs with different settings - keeping existing (${existingSettings}), skipping legacy (${pathStr})`",
"console.log(infoBox('Migrated legacy profiles to config.yaml', 'SUCCESS'));",
"console.log(infoBox('Migration failed - using legacy config', 'WARNING'));"
]
},
{
"file": "src/api/services/profile-writer.ts",
"count": 4,
"calls": [],
"markers": [
"* Supports both unified YAML config and legacy JSON config.",
"/** Create settings.json file for API profile (legacy format) */",
"/** Remove API profile from legacy config */",
"/** Update config.json with new API profile (legacy format) */"
]
},
{
"file": "src/cliproxy/quota-fetcher-gemini-cli.ts",
"count": 4,
"calls": [],
"markers": [
"// Legacy pattern: gemini-email.json",
"// Must match account AND be gemini type (or legacy gemini- prefix)",
"// Try exact legacy match first",
"`gemini-${sanitizedId}.json`, // Legacy format"
]
},
{
"file": "src/auth/profile-registry.ts",
"count": 3,
"calls": [],
"markers": [
"* Get all profiles merged from both legacy and unified config.",
"* Get resolved default profile from unified config first, fallback to legacy.",
"// Start with legacy profiles"
]
}
],
"explicitShimFiles": [
"src/cliproxy/openai-compat-manager.ts"
]
}
}
+48
View File
@@ -0,0 +1,48 @@
# Hardening Inventory Report
Scope: `src/**/*.{ts,tsx,js,jsx,mjs,cjs}`
## Summary
| Metric | Value |
|---|---:|
| Sync fs occurrences (all) | 835 |
| Sync fs files affected (all) | 100 |
| Sync fs occurrences (runtime hotpaths) | 724 |
| Sync fs files affected (runtime hotpaths) | 89 |
| Legacy shim markers | 131 |
| Legacy shim files affected | 56 |
## Top Runtime Hotpath Sync fs Files
| File | Sync Calls | API Names |
|---|---:|---|
| `src/management/shared-manager.ts` | 60 | copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, readlinkSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync |
| `src/utils/claude-symlink-manager.ts` | 27 | copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, readlinkSync, renameSync, rmSync, statSync, symlinkSync, unlinkSync |
| `src/utils/shell-completion.ts` | 23 | appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, statSync |
| `src/web-server/routes/settings-routes.ts` | 23 | copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, statSync, writeFileSync |
| `src/utils/claude-dir-installer.ts` | 21 | copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync |
| `src/cliproxy/binary/version-cache.ts` | 20 | existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync |
| `src/management/recovery-manager.ts` | 20 | copyFileSync, existsSync, mkdirSync, renameSync, writeFileSync |
| `src/web-server/routes/cliproxy-stats-routes.ts` | 20 | closeSync, existsSync, fstatSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, renameSync, statSync, writeFileSync |
| `src/web-server/routes/misc-routes.ts` | 20 | copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, statSync, writeFileSync |
| `src/web-server/routes/persist-routes.ts` | 17 | closeSync, copyFileSync, existsSync, lstatSync, openSync, readdirSync, readSync, renameSync, unlinkSync, writeFileSync |
## Top Legacy Shim Marker Files
| File | Marker Count |
|---|---:|
| `src/utils/config-manager.ts` | 13 |
| `src/auth/profile-detector.ts` | 11 |
| `src/config/unified-config-loader.ts` | 9 |
| `src/commands/setup-command.ts` | 7 |
| `src/management/checks/config-check.ts` | 6 |
| `src/web-server/routes/account-routes.ts` | 6 |
| `src/config/migration-manager.ts` | 5 |
| `src/api/services/profile-writer.ts` | 4 |
| `src/cliproxy/quota-fetcher-gemini-cli.ts` | 4 |
| `src/auth/profile-registry.ts` | 3 |
## Explicit Shim/Re-export Files
- `src/cliproxy/openai-compat-manager.ts`