Commit Graph
283 Commits
Author SHA1 Message Date
Sergey Galuza 00a4dceb94 fix(shared-manager): publish adopted settings by replacement
Adoption moved the canonical settings.json aside with rename() and left
the path empty until publication, roughly 100 ms later. Claude Code or a
second `ccs` starting inside that window found no file and seeded an
empty placeholder; publication then failed with EEXIST because link() is
no-replace, and the rollback published a backup and unlinked the claim,
destroying the only remaining copy of the user's settings. Recovering
meant digging through sidecar files by hand.

Publish by replacement instead: write a temp file next to the canonical
inode and rename() it over the target, so the path always holds a regular
file and no placeholder can be seeded. A compare-and-swap guard on
(ino, mtime, size) runs immediately before the rename and refuses to
publish when the canonical inode changed since it was read, so a writer
that got there first is still never clobbered. The pre-image backup is
published before the replacement, keeping the old content recoverable if
publication is interrupted.

Drops the canonical claim entirely along with restoreCanonicalClaim, and
folds the two identical sidecar publishers into one helper.
recoverOrphanedCanonicalClaim stays, since claims written by older
versions may still be on disk.

New tests cover both writers seen in the incident: Claude Code seeding
`{}` with a trailing newline, and a second `ccs` seeding the 2-byte
variant from shared-dir-linker. Four tests that pinned the claim-based
design were rewritten, among them `preserves a canonical write that
lands during no-replace publication`, whose intent is now enforced by
the CAS guard instead of by an EEXIST from a no-replace link.

Built [OnSteroids](https://onsteroids.ai)
2026-08-23 08:32:26 +02:00
Tam Nhu Tran b9190a6e57 docs: refresh hardening inventory counts 2026-08-19 16:35:27 -04:00
Tam Nhu Tran c8098532a6 chore(hardening): refresh source inventory 2026-08-10 22:13:29 -04:00
Tam Nhu Tran 192b27fbb2 chore(hardening): refresh source inventory 2026-08-10 22:13:29 -04:00
Tam Nhu Tran 5f9db033e7 chore: merge origin/dev into issue #1688
# Conflicts:
#	docs/reports/hardening-inventory.json
#	docs/reports/hardening-inventory.md
2026-08-08 22:29:46 -04:00
Tam Nhu Tran 0ddeb09955 chore(dev): merge v8.8.1-dev.20 for issue 1686 2026-08-08 22:09:27 -04:00
Tam Nhu Tran ce8ad269f0 chore(merge): sync dev release v8.8.1-dev.19 2026-08-08 21:48:56 -04:00
Tam Nhu Tran 4d5449a493 Merge remote-tracking branch 'origin/dev' into kai/review/pr-1691
# Conflicts:
#	docs/reports/hardening-inventory.json
#	docs/reports/hardening-inventory.md
2026-08-08 21:31:32 -04:00
Tam Nhu Tran 6841025bb4 feat(auth): share canonical Claude memory
Refs #1688
2026-08-08 21:17:32 -04:00
Tam Nhu Tran 3e38208b37 docs(readme): clarify supported proxy runtimes
Refs #1686
2026-08-08 21:17:24 -04:00
Tam Nhu Tran 379008383e chore(reports): refresh hardening inventory
Refs #1685
2026-08-08 21:17:12 -04:00
Tam Nhu Tran da2de60015 fix(bar): bound native credential and quota waits 2026-08-08 21:12:28 -04:00
poomscandClaude Fable 5 a5a5b742e4 fix(bar): stop false re-auth on non-default native subscription profiles
Fixes the two collector-side root causes of #1601:

1. Claude per-profile credential reads were file-only, but on macOS Claude
   Code stores the OAuth token for an isolated CLAUDE_CONFIG_DIR in a
   per-directory Keychain item ("Claude Code-credentials-<sha256(dir)[0..8]>").
   The .credentials.json file never exists, so every isolated profile was
   parked with needsReauth:true forever. The reader now falls back to that
   Keychain item (file-first, same security-CLI read the shipped global
   fallback already performs; TTL-gated so it is not on every /summary).

2. Non-default profiles were cache-only forever, so they could never leave
   the parked state even with valid credentials. getNativeAccountRows now
   gives each surface ONE rotating live slot: the stalest eligible
   non-default profile is refreshed per pass, skipping profiles inside
   breaker/reauth cooldowns. Every account converges to real quota within a
   few polls while the per-pass upstream budget stays constant (<= 2 calls
   per surface regardless of profile count). Codex named profiles with valid
   auth but sparse payloads now yield an active quota-less row instead of a
   false needsReauth row.

Non-default rows keep paused:true (dimmed) even when freshly refreshed so
only the default renders active and rows do not flicker between polls.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 14:18:00 +07:00
poomscandClaude Fable 5 34608ce291 feat(bar): support --port for ccs bar with sticky port persistence
ccs bar always forced the dashboard onto port 3000 (first free of a
hardcoded candidate list), which collides with other local dev servers, and
bar.json was rewritten to 3000 on every launch.

- `ccs bar [launch] --port N` runs the server on exactly N: reuses a live
  server already on N, moves a running server from another port (SIGTERM via
  server.pid, wait for exit), errors clearly when N is busy or the value is
  invalid.
- The chosen port is persisted into launch.json args, so the Swift app
  self-starts the server on the same port.
- Without --port, launch and serve now try the port recorded in bar.json
  first (sticky), so the server keeps coming back on the port the user last
  chose instead of reverting to 3000.
- Bare flags (`ccs bar --port N`) route to the launch subcommand; --port is
  documented in `ccs bar --help`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 14:09:58 +07:00
Tam Nhu Tran b022d362dd chore(hardening): refresh filesystem inventory 2026-08-02 20:21:19 -04:00
Tam Nhu Tran 8d7446e3ff chore(hardening): refresh Gemini auth inventory 2026-07-29 14:24:20 -04:00
Tam Nhu Tran 32c8c7b767 chore(hardening): refresh routing inventory 2026-07-29 14:02:52 -04:00
Tam Nhu Tran cd9569e726 chore(hardening): refresh context window inventory 2026-07-29 13:46:53 -04:00
Tam Nhu Tran d6346f0663 chore(hardening): refresh source inventory 2026-07-29 13:28:57 -04:00
Tam Nhu Tran f89f136a1b docs: clarify disabled WebSearch launch behavior 2026-07-29 13:22:21 -04:00
Kai (Tam Nhu) Tran 3ad78b43e7 Merge pull request #1674 from kaitranntt/kai/fix/1670-concurrent-account-locks
fix(cliproxy): retry contended state locks
2026-07-29 13:12:32 -04:00
Kai (Tam Nhu) Tran 16abf18075 Merge pull request #1673 from jeffersongoncalves/feat/i18n-pt-br
feat(i18n): add Brazilian Portuguese (pt-BR) locale
2026-07-29 13:01:58 -04:00
Tam Nhu Tran 348d230298 docs: document Brazilian Portuguese locale 2026-07-29 12:56:42 -04:00
Tam Nhu Tran 794983ca13 chore(reports): refresh hardening inventory 2026-07-29 12:53:00 -04:00
Kenneth Wong cd59c49ae8 chore(reports): refresh hardening inventory 2026-07-27 19:41:19 +08:00
Kai (Tam Nhu) Tran b09f8191f3 Merge pull request #1669 from kaitranntt/kai/docs/1666-pruning-freshness
docs: prune stale guides and enforce freshness
2026-07-26 22:09:35 -04:00
Kai (Tam Nhu) Tran a8217bf18d Merge pull request #1668 from kaitranntt/kai/docs/1665-architecture-contracts
docs: reconcile architecture and engineering contracts
2026-07-26 22:09:17 -04:00
Tam Nhu Tran 306a8276b3 fix(metrics): enforce exact runtime inventory 2026-07-26 09:36:00 -04:00
Tam Nhu Tran 426dc541a9 docs(roadmap): replace historical trackers with live guidance 2026-07-26 09:36:00 -04:00
Tam Nhu Tran 75e715eebd docs(hygiene): remove superseded local guides 2026-07-26 09:35:42 -04:00
Tam Nhu Tran 4485fd6406 docs(macos): consolidate CCS Bar maintainer guidance 2026-07-26 09:35:42 -04:00
Tam Nhu Tran fd0d4362b3 docs(config): preserve active developer contracts 2026-07-26 09:35:42 -04:00
Tam Nhu Tran deb1ed0e67 docs(readme): route user guides to canonical docs 2026-07-26 09:35:42 -04:00
Tam Nhu Tran 51e8062995 docs(operations): refresh runtime contracts 2026-07-26 09:35:10 -04:00
Tam Nhu Tran ebe1746459 docs(architecture): reconcile provider and target contracts 2026-07-26 09:35:00 -04:00
Tam Nhu Tran b918783293 docs(product): refresh product and release contracts 2026-07-26 09:34:48 -04:00
Tam Nhu Tran 721ca5fc33 docs(architecture): replace volatile maintainer snapshots 2026-07-26 09:34:09 -04:00
Tam Nhu Tran 3bb2d56778 docs(ai): define documentation truth hierarchy 2026-07-26 09:33:56 -04:00
Kai (Tam Nhu) Tran f066188f0a Merge pull request #1656 from minhbi245/chore/refresh-hardening-inventory
chore(reports): refresh hardening inventory
2026-07-22 14:40:58 -04:00
Kai (Tam Nhu) Tran 3608bf71a1 feat: rebrand CCS as Claude Codex Switch (#1658)
Closes #1657
2026-07-22 14:23:42 -04:00
milesnguyen2405 9ddb3429d4 chore(reports): refresh hardening inventory
The maintainability metrics artifact aged past the 30-day freshness
gate in scripts/ci-parity-gate.sh, so validate:ci-parity fails for
every contributor branch until the committed copy is regenerated.
2026-07-22 23:24:35 +07:00
minhbi245 54a2b4759b feat(cliproxy): add xAI Grok provider 2026-07-17 00:02:12 +07:00
Tam Nhu Tran 3103af5355 docs(codex-auth): document shared plugin cache 2026-07-15 10:24:13 -04:00
Kai (Tam Nhu) Tran 23b2c3d6af fix: restrict bar release workflow to main (#1612) 2026-06-30 12:21:33 -04:00
Kai (Tam Nhu) Tran 9dd9bf2978 feat(websearch): add agy provider and deprecate gemini cli fallback (#1607)
Google retired the gemini CLI on 2026-06-18, so the gemini websearch fallback no longer
works. Add agy (Antigravity) as the primary CLI websearch provider end to end: runtime spawn
in websearch-transformer.cjs (agy --dangerously-skip-permissions --print-timeout Ns -p),
detection (agy.ts), config schema and defaults, hook env, status, dashboard persistence, and docs.

The legacy gemini provider stays present but is marked deprecated for enterprise users who
retain access. Image analysis already supported the agy provider (no change). The CLIProxy
gemini quota fetcher (Gemini API OAuth, not the cli binary) is untouched.

Validation: typecheck, lint, and the websearch + config + web-server unit suites pass.
2026-06-27 10:01:25 -04:00
Kai (Tam Nhu) Tran 87eb4f2154 Merge pull request #1414 from cerebrixos/tuning-engines-provider
Add Tuning Engines provider
2026-06-22 17:18:57 -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
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 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