Skip to content

refactor: centralize resolution, unify auth detection, harden agent/config#14

Merged
alexkroman merged 5 commits into
mainfrom
claude/bug-prone-areas-yKETs
Jun 5, 2026
Merged

refactor: centralize resolution, unify auth detection, harden agent/config#14
alexkroman merged 5 commits into
mainfrom
claude/bug-prone-areas-yKETs

Conversation

@alexkroman

Copy link
Copy Markdown
Collaborator
  • context: AppState owns profile/env/session resolution as the single source of
    truth; the module-level resolve_* helpers delegate to it, so precedence rules
    no longer drift across call sites.
  • errors: fold the agent-only structural auth checks (WebSocket 1008, HTTP
    401/403) into is_auth_failure so REST, streaming, and the voice agent classify
    rejected credentials identically; drop the duplicate _is_auth_rejection.
  • agent/session: guard the cross-thread duplex flags (ready/muted) with a lock so
    the receive-loop -> capture-thread handoff is explicit, not GIL-incidental;
    document the capture_error and audio _out/_out_state thread ownership.
  • config: write config.toml atomically (temp file + os.replace) so a crash or
    concurrent reader can't leave truncated, invalid TOML.

Adds tests for each.

claude added 5 commits June 5, 2026 07:34
…onfig

- context: AppState owns profile/env/session resolution as the single source of
  truth; the module-level resolve_* helpers delegate to it, so precedence rules
  no longer drift across call sites.
- errors: fold the agent-only structural auth checks (WebSocket 1008, HTTP
  401/403) into is_auth_failure so REST, streaming, and the voice agent classify
  rejected credentials identically; drop the duplicate _is_auth_rejection.
- agent/session: guard the cross-thread duplex flags (ready/muted) with a lock so
  the receive-loop -> capture-thread handoff is explicit, not GIL-incidental;
  document the capture_error and audio _out/_out_state thread ownership.
- config: write config.toml atomically (temp file + os.replace) so a crash or
  concurrent reader can't leave truncated, invalid TOML.

Adds tests for each.
Five wrappers around the assemblyai SDK duplicated the same try/except shape
(map auth failures to auth_failure(), everything else to APIError). Collapse it
into a single _sdk_errors() context manager so the classification lives in one
place; CLIError and BrokenPipeError still pass through untouched. Behavior is
unchanged (tests assert on exception type, not message).
- agent/session: replace the 11-branch dispatch() if/elif chain (CC 20) with an
  _EVENT_HANDLERS table of small per-event methods (CC 2).
- config_builder: extract the issubclass ladder out of _derive_kind into
  _scalar_kind (CC 15 -> ~8); replace coerce_value's kind chain with a _COERCERS
  table of per-kind functions (CC 14 -> ~2).
- client: replace select_transcript_field's field chain (CC 12) with a
  _FIELD_RENDERERS dispatch table plus small render helpers (CC 1).

Behavior unchanged; full suite green. Average CC 2.57 -> 2.41.
Enforce the complexity work so it can't silently regress:
  --max-absolute B : no function may exceed cyclomatic complexity 10
  --max-modules  B : no file's average may exceed grade B
  --max-average  A : project-wide average stays grade A (<= 5)

To clear the strict per-function bar, refactor run_session (the last C-rated
function, CC 13) down to B by extracting _open_ws and _auth_or_api_error; the
threading/error structure is unchanged. Adds xenon to the dev dependency group.
Three quality gates that push changes to fix rather than skip:

1. diff-cover patch coverage (check.sh): every line changed vs origin/main must be
   covered (--fail-under=100), closing the loophole where new code rides on the
   project-wide 90% gate. Emits coverage.xml from the pytest step.
2. ruff PGH/ERA/TRY/TD/FIX: ban blanket # noqa / # type: ignore, commented-out
   code, exception anti-patterns, and untracked TODO/FIXME markers. TRY003 is
   ignored (the CLIError hierarchy is built on descriptive messages).
3. pytest filterwarnings = error: a deprecation or resource leak now fails the
   build instead of scrolling past.

Issues these surfaced, fixed here:
- auth/loopback: the OAuth callback server leaked its listening socket
  (shutdown() doesn't close it) — caught by warnings-as-errors; add server_close().
- client.validate_key: moved the success return out of the try (TRY300).
- environments: reworded the production-values TODO into a factual NOTE.
- client: added tests for the utterances output field (was untested) to hit 100%
  patch coverage.

Adds diff-cover to the dev group.
@alexkroman alexkroman merged commit 8738c58 into main Jun 5, 2026
13 checks passed
@alexkroman alexkroman deleted the claude/bug-prone-areas-yKETs branch June 5, 2026 08:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants