Commit Graph
4495 Commits
Author SHA1 Message Date
github-actions[bot] a5149b39e9 chore(release): 8.5.0-dev.1 2026-06-22 17:43:36 +00:00
Kai (Tam Nhu) Tran 5f5d41948c Merge pull request #1583 from kaitranntt/kai/fix/cli-qa-ux-errors
fix(cli): UX and logistical fixes from a full feature-QA pass
2026-06-22 13:39:28 -04:00
Tam Nhu Tran 819d43914a fix(dispatch): restore copilot and legacy-cursor arg passthrough
Routing every non-flag token after 'copilot'/'legacy-cursor' to the subcommand
handler turned the legacy profile/prompt passthrough into an 'Unknown subcommand'
error. Route only known subcommands (matching prior behavior); other args pass
through to the copilot/cursor bridge flow. Bar keeps its unknown-subcommand exit
code (it has no passthrough).
2026-06-22 13:10:59 -04:00
Tam Nhu Tran d8cd2f94b5 fix(cliproxy): keep --help working for all subcommands
The earlier help-gating overcorrected: scoping global help to 'no real
subcommand' meant 'cliproxy status --help' (and list/quota) ran the command and
ignored --help. Restore global help on --help/-h anywhere (order-insensitive),
carving out only 'routing affinity --help', which renders its own help.
2026-06-22 13:10:59 -04:00
Tam Nhu Tran 310f4f6e52 fix(cliproxy): show global help regardless of flag order before --help
Top-level cliproxy help was order-sensitive: 'cliproxy --verbose --help' fell
through to dispatch instead of showing help. Fire global help whenever there is
no real subcommand (no args or a leading flag) and --help/-h appears anywhere;
real subcommands still handle their own --help.
2026-06-22 12:18:50 -04:00
Tam Nhu Tran 40d7617cc1 fix(auth): re-export interface-only barrel symbols as types for bun dev runs
The auth commands barrel re-exported 4 interface-only symbols (AuthCommandArgs,
ProfileOutput, ListOutput, CommandContext) via a value 'export {}', which bun's
per-file transpile cannot resolve at runtime (the tsc dist elides them, so users
were unaffected). Split them into 'export type {}' so 'bun run dev' / source runs
work.
2026-06-22 12:06:58 -04:00
Tam Nhu Tran 5e4a90b3e5 fix(cli): warn on tokens --variant without --api-key; list bar serve in help
'ccs tokens --variant <x>' without --api-key was a silent no-op; now it explains
that --variant only applies with --api-key. Add the existing 'serve' subcommand
to the bar help Commands list.
2026-06-22 12:06:58 -04:00
Tam Nhu Tran a5feefe45a fix(cliproxy): honor status --verbose and document --provider/diag in help
handleProxyStatus now respects --verbose (was parsed but ignored). Document the
existing --provider option on default/pause/resume and the 'diag' alias for
doctor in the cliproxy help text.
2026-06-22 12:06:58 -04:00
Tam Nhu Tran 016c47ec9a chore(lint): refresh throw-error baseline for shifted and converted throws 2026-06-22 12:06:58 -04:00
Tam Nhu Tran e4c91d2853 fix(persist): accurate symlink guard message on backup read
The guard fires on the backup READ step; use a typed ConfigError whose message
matches the actual step (refusing to read), not a misleading 'refusing to write'.
2026-06-22 12:06:58 -04:00
Tam Nhu Tran 9d5b33382b fix(cliproxy): gate binary download log, fix pool message prefix and routing affinity help
Only log 'Binary not found, downloading...' when a download will actually happen
(after the allowInstall guard). Stop double-prefixing pool enable/disable
messages that already carry [OK]/[!]. Route 'cliproxy routing affinity --help'
to affinity help instead of the generic cliproxy help.
2026-06-22 12:06:58 -04:00
Tam Nhu Tran 8cfd13ba96 fix(doctor): keep diagnostics running on corrupt config or unreadable auth
loadUnifiedConfig() printed the YAML error on every call (3-4x per run); print it
once per path per process. Run each doctor check group defensively so a thrown
check (corrupt config, EACCES auth dir) records an error and the SUMMARY/ERRORS
sections with recovery hints still render instead of crashing mid-run. Trim
embedded parser snippets to one line so they no longer leak into the summary
table or repeat across checks.
2026-06-22 12:06:58 -04:00
Tam Nhu Tran 2900743767 fix(dispatch): route unknown bar/copilot/cursor subcommands and survive corrupt config
Pre-dispatch only routed known subcommand tokens, so unknown bar/copilot/cursor
subcommands never reached their handlers (no error, no non-zero exit). Route them
through. Also wrap autoMigrate() so a corrupt config.yaml no longer crashes
startup, and print only the first line of a best-effort recovery failure.
2026-06-22 12:06:58 -04:00
Tam Nhu Tran 9258aed1ff fix(cli): clearer profile/proxy/api errors and rich not-found suggestions
Move resolveProfileAndTarget() inside the try block in ccs.ts so a missing
profile shows suggestions/available-profiles instead of a generic error. Use a
typed ProfileError for proxy start on an unknown profile (drops the irrelevant
install hint). api create: honor --yes for the OpenRouter model browser, show
ccs-codex/ccsx aliases for --target codex, and allow ANTHROPIC_EXTRA_MODELS on
import.
2026-06-22 12:06:58 -04:00
Tam Nhu Tran 191396149f fix(auth): de-duplicate error output and validate legacy profiles in default
exitWithError() already prints '[X] <msg>', so the preceding console.log(fail())
calls double-printed every auth error. Remove the redundant logs and fold richer
hints (e.g. --force) into the single exitWithError message. Also make
'auth default' accept a profile registered only in legacy profiles.json under
unified mode.
2026-06-22 12:06:58 -04:00
semantic-release-bot e44babd8cc chore(release): 8.5.0 [skip ci]
## [8.5.0](https://github.com/kaitranntt/ccs/compare/v8.4.0...v8.5.0) (2026-06-21)

### Features

* **api:** add Fireworks AI provider preset ([#1543](https://github.com/kaitranntt/ccs/issues/1543)) ([a472c44](https://github.com/kaitranntt/ccs/commit/a472c440156fc549c500c649ea0033220fb97e61))
* **bar:** live Codex usage sync with force refresh and spend-chart periods ([6ed5b2d](https://github.com/kaitranntt/ccs/commit/6ed5b2d62b8a3c08a2e23478c6d4078e2ebf501c))
* **config:** add opt-in output limits for spawned CLI ([#1544](https://github.com/kaitranntt/ccs/issues/1544)) ([499aec8](https://github.com/kaitranntt/ccs/commit/499aec8a9ba9eeb27c1d183a27b3336f4e8794e8))
* **errors:** P4 typed-error taxonomy adoption (0->91% locked) + erasable-syntax fix ([7234ef8](https://github.com/kaitranntt/ccs/commit/7234ef8fcf5e3cba0c42f2bf48e075dbe33b00d4))
* **hardening:** P1 maintainability metrics baseline + freshness gate ([#1561](https://github.com/kaitranntt/ccs/issues/1561)) ([95a2864](https://github.com/kaitranntt/ccs/commit/95a2864ef3492f96098c689e16086f6e1db012d2))
* **lint:** P7 enforcement gates (no-new-throw-error + max-lines) + docs ([2f94f35](https://github.com/kaitranntt/ccs/commit/2f94f35ec35bc3710c3ab1d6f1019f704e58d4c7))
* **logging:** P2 traceability foundation - requestId wrap, daemon forwarding (#NNN) ([5e1b864](https://github.com/kaitranntt/ccs/commit/5e1b8640ab517109732affd32b430ca0b769996a)), closes [#NNN](https://github.com/kaitranntt/ccs/issues/NNN)
* **logging:** P3 hotpath console.error migration + redaction gate (928->267) ([87aeb8f](https://github.com/kaitranntt/ccs/commit/87aeb8f19331b07ed056ec49913a23b5dad417e6))

### Bug Fixes

* avoid echoing invalid channel token values ([#1542](https://github.com/kaitranntt/ccs/issues/1542)) ([e3566ed](https://github.com/kaitranntt/ccs/commit/e3566ed7650b6930fd5515527831c4a3f0924cbb))
* avoid quadratic cliproxy usage hydration ([#1537](https://github.com/kaitranntt/ccs/issues/1537)) ([f74561f](https://github.com/kaitranntt/ccs/commit/f74561fe9b48c478c002daec39b8797f1dd0ede6))
* **bar:** authenticate reused local server probes ([#1546](https://github.com/kaitranntt/ccs/issues/1546)) ([f25a101](https://github.com/kaitranntt/ccs/commit/f25a1015ed35df91ed6f145e29eaa111da6b8727))
* **bar:** avoid blocking on lower-priority probes ([#1548](https://github.com/kaitranntt/ccs/issues/1548)) ([8bd289b](https://github.com/kaitranntt/ccs/commit/8bd289bfae3e60c460ad4442d5ef46da51d43d14))
* **bar:** distinguish native Codex subscription rows ([#1552](https://github.com/kaitranntt/ccs/issues/1552)) ([ba7a2ab](https://github.com/kaitranntt/ccs/commit/ba7a2abb799515447c30c99b75ef43b9362793ea))
* **bar:** preserve Gatekeeper quarantine on install ([#1534](https://github.com/kaitranntt/ccs/issues/1534)) ([c776e18](https://github.com/kaitranntt/ccs/commit/c776e184344132ad9b5bf6d7fcca88d8251e9414))
* **bar:** tolerate duplicate rows in alert pruning ([#1553](https://github.com/kaitranntt/ccs/issues/1553)) ([84ff4d5](https://github.com/kaitranntt/ccs/commit/84ff4d57a4a03ce3dfe105fab3b25c95bc45c0e5))
* **bar:** verify CCS Bar release archive digest ([#1532](https://github.com/kaitranntt/ccs/issues/1532)) ([d2848d3](https://github.com/kaitranntt/ccs/commit/d2848d39317950b36ac7038fcf22cb8e953787f9))
* bound Codex rollout tail reads ([#1547](https://github.com/kaitranntt/ccs/issues/1547)) ([06e8309](https://github.com/kaitranntt/ccs/commit/06e83091bec3cf4dff344019d02f836fdb7d2c13))
* **browser:** preserve profile-bound DevTools discovery ([#1541](https://github.com/kaitranntt/ccs/issues/1541)) ([ab6c59b](https://github.com/kaitranntt/ccs/commit/ab6c59ba354361d011e3004b9706a5ebe05ebf76))
* **cliproxy:** guard unsupported Qwen account auth ([b6ef4e5](https://github.com/kaitranntt/ccs/commit/b6ef4e5782f0dcd6dda3419c9b545dea6bfa1dcb))
* **cliproxy:** use root URL for Claude provider ([#1554](https://github.com/kaitranntt/ccs/issues/1554)) ([49a7b9d](https://github.com/kaitranntt/ccs/commit/49a7b9dc857bce7525e0b9a6be8d797b6841ca1f))
* **codex:** sanitize config override probes ([#1535](https://github.com/kaitranntt/ccs/issues/1535)) ([db44845](https://github.com/kaitranntt/ccs/commit/db44845857b62352058b07900de6c04c36c5ba27))
* **config:** update provider default models ([20e315b](https://github.com/kaitranntt/ccs/commit/20e315ba3f5f165602ec89a38e94b2c9249e7ab8))
* **cursor:** redact daemon token from dashboard start ([#1540](https://github.com/kaitranntt/ccs/issues/1540)) ([b85a3de](https://github.com/kaitranntt/ccs/commit/b85a3de26e45ffcfcd4db0f3216a41326a05f285))
* degrade WebSearch launch provisioning failures ([#1571](https://github.com/kaitranntt/ccs/issues/1571)) ([1a03985](https://github.com/kaitranntt/ccs/commit/1a0398579a974efa8adaa65446c51c5f512efa77))
* enforce tier lock during quota preflight ([#1550](https://github.com/kaitranntt/ccs/issues/1550)) ([361328c](https://github.com/kaitranntt/ccs/commit/361328c788e13fa471a1f6ced5c44411a131d503))
* handle auth-protected bar launch probes ([#1551](https://github.com/kaitranntt/ccs/issues/1551)) ([c040986](https://github.com/kaitranntt/ccs/commit/c0409862d2ab89682dae0987f872db745d798763))
* harden macOS bar launch descriptor ([#1533](https://github.com/kaitranntt/ccs/issues/1533)) ([10aff10](https://github.com/kaitranntt/ccs/commit/10aff10a67fbe7f4a9835aca8e394e3b62ae2a0c))
* harden release issue parsing ([#1536](https://github.com/kaitranntt/ccs/issues/1536)) ([74dd2f3](https://github.com/kaitranntt/ccs/commit/74dd2f38ccc1adcb4c7cd7fb825f14121b0d96b2))
* honor default target for Claude passthrough ([#1539](https://github.com/kaitranntt/ccs/issues/1539)) ([473aa08](https://github.com/kaitranntt/ccs/commit/473aa082f66a843edcea0d7ab9e9f94a2b585b67))
* ignore malformed bar analytics date keys ([#1556](https://github.com/kaitranntt/ccs/issues/1556)) ([e37a87c](https://github.com/kaitranntt/ccs/commit/e37a87c3a250c5f08793b119d7c0d41e1227bbcd))
* **logging:** harden structured trace redaction ([1462823](https://github.com/kaitranntt/ccs/commit/1462823be8c67895e81009aab0259263ae8b4097))
* **macos-bar:** launch dashboard without shell ([#1549](https://github.com/kaitranntt/ccs/issues/1549)) ([50f136a](https://github.com/kaitranntt/ccs/commit/50f136a1f0223fd4c39789ffdd273c30b1ad6b06))
* **proxy:** keep undici timeouts above the upstream request timeout ([#1524](https://github.com/kaitranntt/ccs/issues/1524)) ([8f9795b](https://github.com/kaitranntt/ccs/commit/8f9795bce24123786722d592d18dff8be59cc8d0))
* **usage:** price updated provider defaults ([34123a6](https://github.com/kaitranntt/ccs/commit/34123a62a69c7e5acd621fc54da901a6975f1709))

### Documentation

* **hardening:** finalize epic metrics + progress log (P1-P7) ([2d48488](https://github.com/kaitranntt/ccs/commit/2d484884752a6fd79ca1a891c62450333c15a4fe))

### Code Refactoring

* P5 god-file splits (test-backed, public API preserved) ([919be3c](https://github.com/kaitranntt/ccs/commit/919be3c722eed9f56f028a4929bf2ac8944d080d))
* P6 god-file splits (quota-fetcher + quota-fetcher-gemini-cli; 4 deferred) ([aecc1f7](https://github.com/kaitranntt/ccs/commit/aecc1f7217d192383d18c059690e38b47985ba18))

### Tests

* **bar:** harden bar-probe auth coverage; drop dead proxy shim ([#1555](https://github.com/kaitranntt/ccs/issues/1555)) ([3fa4a34](https://github.com/kaitranntt/ccs/commit/3fa4a342f974c3a346ba9b9d2ad3f429ae1eda0c))

### CI

* **bar:** auto-build and publish CCS Bar on main via self-hosted macOS runner ([b3a9abf](https://github.com/kaitranntt/ccs/commit/b3a9abffbce1c62957720e3fda9a83204f34757f))
2026-06-21 17:41:16 +00:00
Kai (Tam Nhu) Tran f9047d00a8 Merge pull request #1580 from kaitranntt/dev
feat: promote dev to main (CCS Bar v1.7.0, maintainability epic, provider fixes)
2026-06-21 13:37:22 -04:00
github-actions[bot] f43cad0fbc chore(release): 8.4.0-dev.17 2026-06-21 02:27:10 +00:00
Kai (Tam Nhu) Tran c97037230a Merge pull request #1579 from kaitranntt/kai/ci/bar-auto-release
ci(bar): auto-build and publish CCS Bar on main via self-hosted macOS runner
2026-06-20 22:23:02 -04:00
Tam Nhu Tran b3a9abffbc ci(bar): auto-build and publish CCS Bar on main via self-hosted macOS runner
Releasing the macOS bar app was fully manual (run package_app.sh on a Mac, then
gh release upload --clobber), so Swift-side changes never reached users until
someone remembered to rebuild and re-upload the floating ccs-bar-latest asset.

Add a tightly-scoped Bar Release workflow that does it automatically:
- triggers ONLY on push to main touching macos-bar/**, or manual dispatch, so
  regular PRs, dev pushes, and non-bar changes never start it
- runs ONLY on the dedicated self-hosted macOS runner (label ccs-bar); the Linux
  CI runners never match it and it never competes for them
- least-privilege contents:write, single-flight via concurrency

Version is sourced from a new macos-bar/VERSION single-line file (the workflow
reads it; the asset is always the latest build regardless). package_app.sh now
defaults to that file when no version arg is passed, so the local manual path and
CI share one source of truth. Documents the release process in docs/ccs-bar.md.
2026-06-20 22:17:40 -04:00
github-actions[bot] a843709135 chore(release): 8.4.0-dev.16 2026-06-20 23:58:01 +00:00
Kai (Tam Nhu) Tran 458f836a07 Merge pull request #1578 from kaitranntt/kai/feat/ccs-bar-codex-sync-spend-chart
feat(bar): live Codex usage sync with force refresh and spend-chart periods
2026-06-20 19:54:00 -04:00
Tam Nhu Tran 6ed5b2d62b feat(bar): live Codex usage sync with force refresh and spend-chart periods
Codex quota in the menu bar came only from frozen local session logs, so it
showed stale data ("older session") that no refresh could update. Fetch it live
from the same source the dashboard uses, under the existing Claude-style safety
controls (10-min TTL, in-flight coalescing, 429 backoff, circuit breaker,
serve-stale), falling back to local logs when offline or rate-limited. A success
with no usable 5h/weekly window keeps the local reading rather than caching a
contentless row. The footer refresh and a new inline button on the Codex card
force a live pull past the open debounce, and a forced /summary re-pulls native
rows while serving the last-known cached rows if the live pull overruns its
budget, so the Claude/Codex cards never blank mid-refresh.

The spend strip gains a Today / 7d / 30d selector (default 7d), a taller chart,
and bottom time-axis labels (local hours for today, weekday for 7d, dates for
30d). The analytics endpoint now exposes a 24-bucket hourly series for today,
converted from the pipeline's UTC hour keys to the user's local clock so the
intra-day chart matches the dashboard.
2026-06-20 18:37:18 -04:00
github-actions[bot] 9977c49fab chore(release): 8.4.0-dev.15 2026-06-20 20:27:30 +00:00
Kai (Tam Nhu) Tran e37a87c3a2 fix: ignore malformed bar analytics date keys (#1556)
* fix: ignore malformed bar analytics date keys

* style: apply prettier formatting to dynamic imports
2026-06-20 16:23:22 -04:00
github-actions[bot] b811cacaef chore(release): 8.4.0-dev.14 2026-06-19 14:04:17 +00:00
Kai (Tam Nhu) Tran 6e64a3ac6e Merge pull request #1573 from tiennm99/fix/update-provider-model-templates
fix(config): update provider default models
2026-06-19 10:00:20 -04:00
Tam Nhu Tran 34123a62a6 fix(usage): price updated provider defaults 2026-06-19 09:57:49 -04:00
tiennm99 20e315ba3f fix(config): update provider default models 2026-06-19 17:36:06 +07:00
github-actions[bot] 48e1c8976d chore(release): 8.4.0-dev.13 2026-06-19 03:00:30 +00:00
Kai (Tam Nhu) Tran 1a0398579a fix: degrade WebSearch launch provisioning failures (#1571) 2026-06-18 22:56:20 -04:00
github-actions[bot] 813a7a043a chore(release): 8.4.0-dev.12 2026-06-19 01:38:29 +00:00
Kai (Tam Nhu) Tran b6ef4e5782 fix(cliproxy): guard unsupported Qwen account auth 2026-06-18 21:34:27 -04:00
github-actions[bot] 5b6c3e87e9 chore(release): 8.4.0-dev.11 2026-06-18 23:52:27 +00:00
Kai (Tam Nhu) Tran 2a14904a23 Merge pull request #1568 from kaitranntt/kai/feat/maintainability-traceability-epic
Maintainability & Traceability Epic (P1-P7)
2026-06-18 19:48:25 -04:00
Tam Nhu Tran 1462823be8 fix(logging): harden structured trace redaction
Redact StageOptions error payloads and summarize debug launch args.

Propagate request IDs through Cursor daemon and dashboard completion logs.

Mark remaining P2/P3 maintainability targets as partial instead of overclaiming.
2026-06-18 18:48:13 -04:00
Tam Nhu Tran 2d48488475 docs(hardening): finalize epic metrics + progress log (P1-P7) 2026-06-18 18:48:13 -04:00
Tam Nhu Tran aecc1f7217 refactor: P6 god-file splits (quota-fetcher + quota-fetcher-gemini-cli; 4 deferred)
Epic P6 (partial: 2 of 6 targets). These two files have strong existing
per-provider test coverage, so the characterization-first requirement is met
by the safety net; both are split test-backed.

- src/cliproxy/quota/quota-fetcher.ts (1106 -> barrel 29 + 9 submodules, max
  254 LOC): status-classifier (the clean extract), http-client, auth-file-reader,
  project-lookup, available-models-fetcher, account-quota-fetcher,
  all-accounts-fetcher, types, constants.
- src/cliproxy/quota/quota-fetcher-gemini-cli.ts (1179 -> barrel 27 + 11
  submodules, max 334 LOC): token-parsing, auth-file-discovery,
  supplementary-metadata, error-parsing, bucket-building, managed-request,
  shared-utils, types, constants, index.

Public API preserved verbatim (incl. __testExports). All P3 structured logging
preserved through the splits. Regenerated eslint-rules/throw-error-baseline.json
(throws moved to new module paths).

Remaining P6 targets (characterization-first, deferred): oauth-handler.ts,
cursor-executor.ts, tool-sanitization-proxy.ts, + 1. Each needs dedicated
characterization-test work before splitting; tracked in the epic plan.

Metric: files > 400 LOC 91 -> 89. validate + validate:ci-parity green.
2026-06-18 18:48:13 -04:00
Tam Nhu Tran 2f94f35ec3 feat(lint): P7 enforcement gates (no-new-throw-error + max-lines) + docs
Epic P7. Locks in the epic's gains with ESLint gates so the adoption work
does not regress.

- ccs/no-new-throw-error (error): custom flat-config rule that flags NEW
  throw new Error(...) outside a generated baseline allowlist. Forces the
  typed-error taxonomy (src/errors/error-types.ts). Existing 338 sites are
  grandfathered in eslint-rules/throw-error-baseline.json; only NEW violations
  error. Rule normalizes the filename to repo-root-relative to match baseline
  keys regardless of how ESLint reports paths.
- max-lines (warn, 400, skipBlankLines/skipComments): warns on files over
  400 LOC (goal of P5/P6 god-file splits). Currently 51 warnings on the
  not-yet-split god-files (P6 territory).
- scripts/generate-throw-error-baseline.js: emits the allowlist from raw
  source (superset of real throws; never undercounts). Run after intentionally
  grandfathering a site, or quarterly to prune.
- tests/unit/eslint-rules/no-throw-new-error.test.ts: rule logic (flags
  off-allowlist, passes on-allowlist/typed/rethrow, line-sensitivity).
- docs/code-standards.md: Lint Enforcement Gates section.
- docs/logging-contract.md: error.code -> ExitCode table (from P4).

validate + validate:ci-parity green.
2026-06-18 18:48:13 -04:00
Tam Nhu Tran 919be3c722 refactor: P5 god-file splits (test-backed, public API preserved)
Epic P5. Splits 4 test-backed god-files into focused submodules using the
Monster File Splitting methodology; each original file is now a thin barrel
re-exporting the full public surface, so consumers are unchanged.

- src/management/shared-manager.ts (1631 -> barrel 21 + 10 submodules,
  max 337 LOC): fs-helpers, symlink-helpers, plugin-metadata-normalizer,
  plugin-layout-internals, shared-dir-linker, project-context-sync,
  project-memory-sync, migrations, orchestrator, types.
- src/web-server/routes/cliproxy-stats-routes.ts (1216 -> barrel 23 + 8
  submodules, max 290 LOC): shared, quota-helpers, version-helpers,
  restart-route, quota-routes, error-log-routes, config-routes, router.
- src/commands/persist-command.ts (1071 -> barrel + 8 submodules, max 258):
  types, arg-parsing, secure-file, backup-rotation, secret-detection,
  receipt, help, handler.
- src/commands/cliproxy/quota-subcommand.ts (1130 -> barrel + 14 submodules,
  max 303): types, format-helpers, codex/claude-window-helpers, provider-runtime,
  handlers, per-provider sections.

Public API preserved verbatim (default + named exports). All P3 structured
logging and P4 typed errors preserved through the splits. Each resulting file
< 400 LOC. Existing tests (shared-manager x4, cliproxy-stats x4, persist x2,
quota-subcommand x1) green, unchanged.

Metric: files > 400 LOC 95 -> 91. validate + validate:ci-parity green.
2026-06-18 18:48:13 -04:00
Tam Nhu Tran 7234ef8fcf feat(errors): P4 typed-error taxonomy adoption (0->91% locked) + erasable-syntax fix
Epic P4. Migrates plain throw new Error to the typed-error classes in the four
locked subdomains, and makes the taxonomy erasable-syntax-compatible so it can
be adopted across UI-reachable code.

Migration (cliproxy/auth, web-server/routes, auth):
- 21 of 23 throws in the locked subdomains now use typed subclasses
  (ProfileError, AuthError, ConfigError, ValidationError, ProviderError).
- Typed adoption in locked subdomains: 0/23 -> 21/23 (91.3%), > 40% target.
- Overall typed adoption: 0.9% -> 8.6%.
- Messages preserved exactly (message-based tests stable). Exit codes now
  differentiate via handleError (ProfileError=7, AuthError=4, ConfigError=2,
  ProviderError=6). ccs doctor 0/1 contract untouched (outside scope).

Erasable-syntax fix (unblocks the migration in the UI build graph):
- exit-codes.ts: enum ExitCode -> const object + union type (value and type
  usage both preserved; no Object.values(ExitCode) consumers).
- error-types.ts: constructor parameter properties -> explicit readonly field
  declarations + body assignment.
- The web UI build enforces erasableSyntaxOnly (ui/tsconfig.app.json) and
  reaches src/errors via the @shared -> src/auth graph; pre-erasable
  error-types blocked the build once profile-registry adopted typed errors.

Compat audit: docs/reports/typed-error-exit-code-compat-audit.md (Q1 resolved:
migrate freely; only documented contract is ccs doctor, which is untouched).
Behavior-lock: src/errors/__tests__/typed-error-migration-exit-codes.test.ts
(taxonomy -> exit-code mapping, instanceof chains, context fields).

validate + validate:ci-parity green (incl. UI build).
2026-06-18 18:48:12 -04:00
Tam Nhu Tran 87aeb8f193 feat(logging): P3 hotpath console.error migration + redaction gate (928->267)
Epic P3. Migrates hotpath console.error/warn to the structured logger
(diagnostics) or process.stderr.write (user-facing), and adds a redaction
safety gate so the migration cannot leak credentials.

Redaction gate (MR1):
- log-redaction: scrub known credential token shapes (sk-ant, sk-, xoxb,
  ghp, glpat, AIza, JWT bodies, api_key=, Bearer/Basic/Token scheme) in
  string values, Error.message, AND the log message string (defense-in-depth).
- logger: message now passes through maskSecretTokens.

tool-sanitization-proxy: deleted the private file-logging subsystem
(initLogFile/writeLog/log/warn, logFilePath, debugMode); 13 call sites now
route through the existing createLogger('cliproxy:tool-sanitization-proxy').

Sweep (~120 diagnostic -> structured createLogger; ~540 user-facing -> stderr):
- diagnostics converted across proxy, web-server/routes, glmt pipeline, quota
  fetchers, executors, delegation, session-bridge, https-tunnel-proxy.
- user-facing CLI output (flows, arg-parser usage, installers, prompts, adapter
  launch errors, error display) moved to process.stderr.write (preserves stderr).
- src/utils/error-manager.ts reclassified CLI-UX-exempt (user-facing display).

Metric: hotpath console.error 928 -> 267 (71%); createLogger files 35 -> 64.
Residual 267 is user-facing CLI output (not diagnostics); documented in
docs/hardening-debt-burndown.md. Redaction gate makes further conversion safe.

Tests: hotpath-redaction-regression (12 token shapes); updated delegation-handler,
arg-parser, model-warnings spies (console.error -> process.stderr.write).
validate + validate:ci-parity green.
2026-06-18 18:48:12 -04:00
Tam Nhu Tran 5e1b8640ab feat(logging): P2 traceability foundation - requestId wrap, daemon forwarding (#NNN)
Epic P2. Closes the three real traceability gaps so every diagnostic log can
carry a requestId from origin (ccs.ts main) through HTTP edges and spawned
daemons.

- log-context: add REQUEST_ID_HEADER/ENV/PATTERN, resolveRequestIdFromEnv,
  forwardRequestIdEnv. runWithRequestId now reuses a forwarded CCS_REQUEST_ID
  when well-formed (child re-anchor), else mints fresh.
- request-logging-middleware: wrap the Express dashboard handler chain in
  withRequestContext so downstream route-handler logs carry requestId (mirrors
  src/proxy/server/proxy-server.ts, which is untouched prior art).
- forward CCS_REQUEST_ID at the 4 child-daemon spawn sites: delegation
  headless-executor, cursor-daemon, cursor-profile-executor, copilot-executor.
- cursor-daemon-entry: re-anchor via runWithRequestId so daemon startup logs
  correlate with the spawning CLI invocation (ALS does not cross spawn).
- logger adoption toe-hold: delegation/session-manager (load/save failures) and
  docker/supervisord-lifecycle (restart failure) now use createLogger.

api/channels/shared have no touchable diagnostic console.error (CLI-UX only or
pure data); dispatcher's only diagnostic is in pre-dispatch.ts, owned by plan
#1165. Those defer to P3's full per-site sweep.

Tests: request-context-middleware (handler log requestId === header),
request-id-forwarding (env resolve/reject, re-anchor, forwardRequestIdEnv).
validate + validate:ci-parity green.
2026-06-18 18:48:12 -04:00
Tam Nhu Tran 95a2864ef3 feat(hardening): P1 maintainability metrics baseline + freshness gate (#1561)
Epic P1. Adds maintainability-metrics script (typed-error adoption, createLogger coverage, hotpath console.error, files>400 LOC), merges maintainability block into hardening-inventory report, adds 30-day freshness gate to ci-parity-gate.sh, re-baselines burndown 2026-06-18. Local validate + validate:ci-parity green.
2026-06-18 18:48:12 -04:00
github-actions[bot] 27f4e89ad1 chore(release): 8.4.0-dev.10 2026-06-16 14:27:50 +00:00
Kai (Tam Nhu) Tran 49a7b9dc85 fix(cliproxy): use root URL for Claude provider (#1554)
Built-in Claude provider now uses the CLIProxy root URL instead of /api/provider/claude (which 404'd since base CLIProxy registers /v1/messages at root). Repairs stale local Claude settings, keeps non-Claude providers on their scoped routes, and applies the same root-URL rule to the ccs api create --cliproxy-provider claude bridge path via a shared buildCliproxyProviderPath helper. Closes #1545.
2026-06-16 10:23:48 -04:00
github-actions[bot] 81e9bdea5d chore(release): 8.4.0-dev.9 2026-06-16 13:34:13 +00:00
Kai (Tam Nhu) Tran 3fa4a342f9 test(bar): harden bar-probe auth coverage; drop dead proxy shim (#1555)
* test(bar): cover socket-level 401/403 auth detection and liveness-poll rogue rejection

Add two new describe blocks to bar-command.test.ts:

1. `defaultFindRunningServer: socket-level 401/403 classifies authRequired=true`
   Drives `net.connect` via mock.module('net') to verify that status lines
   401 and 403 off the wire set authRequired=true.  A correct-token 200 must
   not set authRequired.  Prior tests bypassed the real status-line parser by
   injecting authRequired via deps; these tests couple to the actual branch.

2. `defaultWaitForServerLive: rogue 200 without matching token is rejected`
   Uses the same net mock pattern to verify that a 200 carrying a wrong
   x-ccs-bar-token never causes the liveness poll to resolve (rogue reflector
   cannot pass).  Correct token resolves immediately.

Export `defaultWaitForServerLive` from launch-subcommand.ts so the direct
unit test can import it without forcing a full handleBarLaunch invocation.

Both test groups are behavior-coupled: removing the relevant branch in
production causes the tests to fail (verified under mutation).

* refactor(bar): drop dead ensureLoopbackNoProxy proxy shim

The probe now uses raw net.connect() which never consults proxy env vars
(undici was fully removed in an earlier PR).  ensureLoopbackNoProxy()
permanently mutated process-wide NO_PROXY/no_proxy on every discovery call
with no effect on the actual network path.

Verified zero remaining references to ensureLoopbackNoProxy outside the
declaration and call site that are now removed.
2026-06-16 09:30:01 -04:00
github-actions[bot] a649c9568a chore(release): 8.4.0-dev.8 2026-06-16 13:12:21 +00:00
Kai (Tam Nhu) Tran f25a1015ed fix(bar): authenticate reused local server probes (#1546)
Closes a spoofed-loopback-200 bar.json poisoning vector with a per-user 0600 capability token. The real bar server echoes its file-derived token on /bar/* responses; the launch probe verifies the echoed token against the locally-read file (fail-closed) before reusing a server, so a rogue loopback process that cannot read the token file is rejected.
2026-06-16 09:08:21 -04:00