Skip to content

CHANGELOG

Chuyue Wang edited this page May 19, 2026 · 5 revisions

Changelog

All notable changes to Cortex. The format follows Keep a Changelog and the project adheres to Semantic Versioning.

[v0.2.1] — 2026-05-19

The v0.2.x series replaces the v0.1.x release with an architectural-grade rewrite of the LLM stack, a project-wide adversarial audit (56 of 56 findings closed across two sessions plus two Architectural Debts), and the first user-facing polish layer. This tag is the snapshot ready for portfolio review.

Highlights since v0.1.0

  • Anthropic SDK migration. Cortex now talks to Claude exclusively through the Anthropic SDK with three pluggable transports — AWS Bedrock (default), GCP Vertex AI, and the direct Anthropic API — selected by a single CORTEX_LLM__PROVIDER env var and mirrored into ANTHROPIC_PROVIDER at startup. Legacy CORTEX_LLM__MODE values map to the rule-based fallback rather than raising, so 0.1.x .env files boot cleanly. Logical model tiers (sonnet-4-6, haiku-4-5, opus-4-7) resolve to provider-specific IDs at call time. Removed: Azure OpenAI, self-hosted Qwen, local Ollama clients.
  • Debt-1 — Schema codegen drift gate. Pydantic models in cortex/libs/schemas/ are the single source of truth for the daemon ↔ browser-extension wire format; cortex/scripts/generate_ts_schemas.py emits cortex/apps/browser_extension/types/generated/cortex_schemas.d.ts with an AUTOGENERATED — DO NOT EDIT BY HAND header. Both the pre-commit hook and the schema-codegen-check CI job reject any drift. Six findings (F42–F45 family) collapse into a class of bug that's now structurally impossible.
  • Debt-2 — Capability-token auth. Every mutating HTTP route now requires Authorization: Bearer <token> (with the legacy X-Cortex-Auth-Token header still accepted as a fallback) and the WebSocket connection opens with an AUTH handshake before IDENTIFY; pre-AUTH frames close with code 1011. The 256-bit token lives at ~/Library/Application Support/Cortex/auth.token (0600) and is rotatable from the desktop Settings UI. SHUTDOWN payloads carry a defence-in-depth inline token check.
  • F19 — End-to-end correlation IDs. Every mutating request is stamped with a UUID surfaced as X-Cortex-Request-ID on responses and injected into structured logs via structlog.contextvars. The dashboard error toast quotes the cid back so users can copy it into a support ticket.
  • Phase I — Performance work. Capture loop sub-samples MediaPipe; parallel WS broadcast with a hard budget; lazy mediapipe + keyring imports for sub-2s startup; content-script-only LeetCode observer.
  • Phase J — User-facing polish. Onboarding now detects Continuity Cameras and surfaces a "Why we need this" expander on every card; daemon errors raise a top-bar toast with cid quote-back; empty states for both biometrics and advanced tabs; overlay micro- interactions (scale-in + fade-in) that honour the macOS Reduce Motion accessibility preference; a11y sweep with explicit focus policy + accessible names on previously-overlooked surfaces.

Engineering signals shipped this series

  • 56 of 56 Ledger findings closed (audit/findings.md + audit/execution-log.md).
  • CI matrix expanded to four required gates: schema-codegen drift, ruff + mypy strict + pytest, eval-regression baseline (synthetic- trace replay with 3 % relative tolerance), and explicit dependency hygiene via dependabot.
  • 124 pytest files, 1,334 test functions, 17 vitest specs.
  • Atomic-write discipline retrofitted onto every persisted artifact (handover snapshots, causal reports, project config, ML classifier, cost ledger, session recorder) so SIGKILL or disk-full no longer truncates state.
  • Multi-layer kill chain (WS → HTTP → native-msg → SIGTERM → SIGKILL) documented and regression-tested for the stop button.
  • Open-source meta layer added: LICENSE (MIT, Steven Wang), NOTICE (third-party attribution incl. MediaPipe FaceLandmarker), SECURITY.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md, SUPPORT.md, .github/ISSUE_TEMPLATE/*, .github/PULL_REQUEST_TEMPLATE.md, .github/dependabot.yml, Makefile, .editorconfig. README restructured for portfolio readability.

Phase J — user-facing polish

This release closes the audit's user-facing polish layer that sits on top of the foundational fixes (Phase A through Phase H). The hostile auditor wouldn't flag any of it; a real first-time user would notice all of it.

Added

  • Onboarding refinement. The first-run wizard now (a) detects a paired iPhone / iPad Continuity Camera and surfaces an inline "we will skip your iPhone camera" callout on the Camera card, and (b) renders a "Why we need this" expand-on-click chevron on every card with rationale copy explaining where the data lives (e.g. "video stream never leaves your Mac", "Bedrock token stays in the macOS Keychain"). Expander buttons carry accessible names so VoiceOver announces them semantically.
  • Top-bar error toast with cid quote-back. Daemon errors now surface in a dashboard top-bar toast that shows the F19 correlation id (rendered in the mono font as ref: <cid>) selectable so the user can copy it into a support ticket. Auto-dismisses after 8 s; a manual close button is always available. Hooked to a new DaemonBridge.error_occurred(str, str, str) Signal so any daemon callback that has a correlation context bound can surface a toast.
  • Empty states. Before the first capture frame arrives, both the consumer biometrics card ("Start a session to see your biometrics.") and the developer-debug advanced tab ("Start a session to populate signal quality, heart-rate trace, and state scores.") render explicit empty-state placeholders. The flag is sticky — a transient WS disconnect does not collapse the UI back to an empty state because the cached numerics are more useful than a placeholder.
  • Overlay micro-interactions. The intervention overlay plays a subtle scale-in (250 ms, OutCubic) on the headline and a fade-in (180 ms, InOutSine) on the causal-explanation row when the overlay appears. The two read as one continuous motion (the fade starts exactly when the headline tween finishes). Strictly purposeful: the dismiss button and micro-step checkboxes are not animated; the breathing pacer keeps its existing rhythm.
  • Reduce Motion support. mac_native.prefers_reduced_motion consults NSWorkspace.accessibilityDisplayShouldReduceMotion; when the user has the System Settings → Accessibility → Display → Reduce motion preference enabled, the overlay's tweens are skipped and the end state is applied directly.
  • A11y sweep on remaining surfaces. Segmented-control tab buttons, the dashboard Connect / Stop buttons, the connections-panel back button, and every _primary_button on the connections panel now carry setFocusPolicy(Qt.StrongFocus) so they participate in the keyboard tab cycle on every Qt build (macOS Qt sometimes inherits WheelFocus which silently excludes a button from tabbing). Segmented-control buttons gain explicit accessible names + a descriptive long-form description for VoiceOver.

Known limitations (residual a11y, intentionally deferred)

These are documented here so a future polish pass (or the v0.3 audit) can pick them up; they did not block the Phase J close-out.

  • VoiceOver rotor item announcement on the biometrics numerics (P3). The Cormorant numerics (BPM / HRV / BLK) are decorative font glyphs; VoiceOver reads them as raw text. A future commit could wrap each numeric in a QAccessibleWidget subclass that surfaces a semantic "62 beats per minute" string for screen readers. The current behaviour is not WCAG-failing — the labels above the numerics provide context — but it is not as rich as the visual affordance.
  • High-contrast mode (P2). Cortex respects the system light/dark appearance but does not yet honour the macOS Increase Contrast accessibility preference. Under increased contrast, the warm greyscale label tints would benefit from a flatter palette. The token registry is already structured to support a third tier (SEMANTIC_HIGH_CONTRAST), so the work is plumbing rather than design.
  • Live-region announcements on state transitions (P3). When Cortex detects an overwhelm transition, VoiceOver does not announce the new state — the dashboard's state pill updates but is not registered as a live region. A future commit should setAccessibleRole(QAccessible.Role.StaticText) on the state pill and emit QAccessibleEvent.UpdateContents on every state change.
  • Reduce Motion on non-overlay surfaces (P3). The Phase J pass honours Reduce Motion on the overlay tweens only. The dashboard's HR-trace plot, the breathing pacer, the focus-ring transitions, and the connections-panel status pill colour transitions are not yet gated by prefers_reduced_motion. They are all small (≤ 200 ms, easing curves) and below the typical perceptual threshold for motion sensitivity, but a thorough Reduce Motion pass would gate them too.

Verification

QT_QPA_PLATFORM=offscreen pytest \
    cortex/tests/unit/test_dashboard_toast.py \
    cortex/tests/unit/test_dashboard_empty_state.py \
    cortex/tests/unit/test_onboarding_hints.py \
    cortex/tests/unit/test_overlay_animation.py -q
# 26 passed

Manual QA: start daemon, open onboarding, click each "Why?" chevron, confirm rationale appears. Plug in an iPhone, reopen onboarding, see the Continuity callout on the Camera card. Trigger an overlay, watch the headline scale-in then the causal row fade-in. Toggle System Settings → Accessibility → Display → Reduce motion, trigger again, confirm both elements appear without tweens.


The pre-Phase-J audit work (Phase A through Phase H) is tracked in audit/findings.md (the 56-finding ledger) and audit/execution-log.md (the per-commit log). This CHANGELOG starts with Phase J because that is the release boundary at which the audit closes out.

Clone this wiki locally