Skip to content

[codex] sync v0.0.27 retained features#131

Merged
harrryyd merged 119 commits into
mainfrom
sync/t3code-v0.0.27
Jun 20, 2026
Merged

[codex] sync v0.0.27 retained features#131
harrryyd merged 119 commits into
mainfrom
sync/t3code-v0.0.27

Conversation

@harrryyd

Copy link
Copy Markdown
Owner

What changed

Syncs the v0.0.27 retained feature set onto sync/t3code-v0.0.27 and removes active behavior from the legacy manager/review paths while keeping compatibility data decodable.

Key changes in scope:

  • add WebSocket RPC scope coverage and startup wiring for the retained feature set
  • preserve legacy orchestration schemas/events for decode and migration compatibility while making removed manager-specific paths inert in the projector and deciders
  • harden GitHub label/source-control behavior and Grok/provider registry handling
  • hydrate trimmed thread state from persisted messages so /clear N and related history behavior stay correct
  • clean up stale removed keybinding commands from persisted config on startup
  • fix the Todo panel nested interactive markup defect found in the live browser pass
  • remove the obsolete debugging note that described deleted manager/review behavior

Why it changed

The sync branch had drift between the retained v0.0.27 behavior and current runtime wiring. That drift showed up in a few places:

  • retained RPC methods and provider flows were not consistently wired end to end
  • removed manager/review concepts were still influencing some live orchestration code paths
  • persisted user state could carry deleted keybinding commands forward
  • the Todo panel had invalid nested interactive HTML that surfaced during real browser validation

This change brings the branch back in line with the retained feature set while keeping on-disk state and legacy events readable.

Impact

Users on this branch should get:

  • stable WebSocket boot and retained RPC access control
  • cleaner provider/settings behavior during live startup
  • correct thread history hydration after trims
  • automatic cleanup of removed fork-related keybindings from persisted config
  • no browser-console or network issues on the providers/settings path from the Todo markup regression

Root cause

This branch was a broad synchronization handoff. The main failures were integration drift rather than one isolated defect: contract/schema changes, runtime authorization wiring, persisted compatibility state, and UI behavior had diverged enough that unit tests alone were not sufficient.

Validation

  • ./node_modules/.bin/vp check
  • ./node_modules/.bin/vp run typecheck
  • ./node_modules/.bin/vp run lint:mobile
  • bun run test
  • bun run test src/wsRpcScopes.test.ts from apps/server
  • node scratchpad/e2e-smoke.ts from apps/server
  • node scratchpad/e2e-browser-probe.ts '<pairing-url>' from apps/web
  • copied-state migration check confirming migrations 31-35 and pairing CLI compatibility against an isolated copied base dir

Notes

vp check still reports the pre-existing 9 react/no-unstable-nested-components warnings outside this sync scope. vp run lint:mobile completed with the expected local-tool skips because swiftlint, ktlint, and detekt are not installed in this environment.

adambuchweitz and others added 30 commits May 22, 2026 07:02
…tgg#2840)

Co-authored-by: codex <codex@users.noreply.github.com>
…#2854)

Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: Julius Marminge <julius@macmini.local>
Co-authored-by: Yash Singh <saiansh2525@gmail.com>
Co-authored-by: codex <codex@users.noreply.github.com>
…#2858)

Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Julius Marminge <jmarminge@gmail.com>
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
harrryyd and others added 25 commits June 20, 2026 14:29
* feat: Todo Panel create items per category + WebSocket sync (#47)

- Add createItem to todoStore with correct defaults (status=todo, sortOrder, timestamps)
- Add CreateItemMutation schema to TodoMutation union
- Add + button per category header with inline composer (Enter creates, Escape cancels)
- Render items sorted by createdAt within categories with status icons
- Items persist automatically through existing todo.mutate handler

* fix: use toSorted, constrain CreateItemMutation.title to TrimmedNonEmptyString
- Add completedAt field to TodoItem schema
- Add cycleItemStatus: todo → in_progress → done → todo with completedAt tracking
- Add archiveDoneItems: spills oldest done items beyond 10 to archive
- Add CycleItemStatusMutation to TodoMutation union
- Add appendToArchive for atomic archive file writes
- Done section at bottom shows last 10 completed items with category badges
- Clickable status icons cycle through states and persist via mutate
- 12 new tests (6 cycleItemStatus + 6 archiveDoneItems)
* feat: Todo Panel drag to reorder + recategorize (#49)

- Add reorderItems and update reorderCategories in todoStore
- Add ReorderItemsMutation and ReorderCategoriesMutation to TodoMutation union
- Add DndContext/SortableContext with @dnd-kit for drag-and-drop
- Items draggable within and across categories with visual feedback
- Category headers draggable for reordering with grip handle
- Drag overlay shows dragged item/category during drag
- Done items NOT draggable
- Single mutate() call commits drag results
- 72 new todoStore tests for reorder logic

* fix: sort by sortOrder, remove dead code, add onDragCancel, fix DragStartEvent type

- Change display sort from createdAt to sortOrder to preserve drag positions
- Remove dead finalToItems variable and simplify affected items logic
- Fix event type from any to DragStartEvent
- Add onDragCancel handler to clear drag overlay state
- Add updateDescription to todoStore
- Add UpdateItemDescriptionMutation to TodoMutation union
- Add ItemDetailPanel with react-markdown + remark-gfm rendering
- Side peek extends beyond sidebar width (additive, no overlay)
- Click description to edit in textarea, Escape/blur saves
- Editing indicator, empty placeholder handling
- 5 new todoStore tests
- Add setItemJiraLink and deleteItem to todoStore
- Add SetItemJiraLinkMutation and DeleteItemMutation to TodoMutation union
- Items inherit category JIRA link for display if own link not set
- Explicit item JIRA link overrides inherited category link
- Right-click context menu on items: Edit JIRA Link, Delete
- Delete shows confirmation dialog
- 15 new tests for setItemJiraLink, deleteItem, and applyMutation
…64)

- First-time empty state shows centered prompt when no categories exist
- Items get lighter variant of category color as subtle background
- Empty/whitespace-only item titles rejected at store level (createItem guard)
- Enter on empty title keeps input open instead of silently closing
- Category name truncation and collapse state preservation verified
- 3 new edge case tests
- Add composerRef and focusComposer to useCallback dependency arrays in ChatView
- Replace spread + conditional with Object.assign for immutable copies
- Extract deferredResolver test helper, deduplicate resolver init
- Fix React key warning in MessagesTimeline (use criterion as key)
- Remove unused ManagerRuntimeContext import
- Wrap TodoPanel DndContext in relative container
- Apply right-full instead of left-full to prevent overflow
- Add browser tests for rendering, interactions, and detail panel
- Set viewport size in vitest browser config
#75)

- Adds scripts/dev.sh for automatic T3CODE_HOME isolation per worktree
- Documents isolated dev server usage in AGENTS.md
* feat: bulk unarchive/delete for archived threads with multi-select

Add multi-select (Cmd/Shift+Click) to the Archived Threads settings
panel with bulk Unarchive and Delete via right-click context menu.

- New getOrphanedWorktreePathsForThreads() pure function with tests
- bulkUnarchiveThreads and bulkDeleteThreads hooks in useThreadActions
- Worktree orphan detection and confirmation dialog for bulk delete
- Reuses existing threadSelectionStore for selection state

* fix: address PR review — deduplicate dispatch, cross-env safety, shared multi-select hook

Fixes from standards and spec review:
- Extract _dispatchThreadUnarchive/_dispatchThreadDelete helpers shared by single/bulk
- Group bulk targets by environmentId for cross-env safety
- Move clearSelection into bulk function bodies (not caller)
- Include environmentId in bulkDeleteThreads threadShells/projects params
- Extract useMultiSelectClick shared hook (removes inline logic duplication)
- Lazy-compute worktree/project data inside context menu handler (removes 3 memoized arrays)
- Priority field (low/medium/high) with color badges and context menu
- Double-click to rename items inline
- JIRA base URL config for shorthand issue key resolution
- Category collapse state persisted
- Improved markdown styling for descriptions
- New mutations: setItemPriority, renameItem, setJiraBaseUrl, toggleCategory
- Reject empty names in createCategory/renameCategory
- ADR for background review agent worktrees
* fix: add missing Review option to compact composer runtime mode menu (#116)

* fix: thread ServerConfig baseDir through todo persistence (#111)

Remove hardcoded ~/.t3code path from todoPersistence.ts. Instead,
resolve the todos directory from ServerConfig-derived paths, matching
the pattern used by keybindings, serverSettings, and all other
persistence modules.

- Add todosDir to ServerDerivedPaths, deriveServerPaths, and
  ensureServerDirectories in config.ts
- Remove Os.homedir() hardcode from todoPersistence.ts; accept
  todoDir parameter
- Pass config.todosDir from ws.ts to readTodos, writeTodos, and
  appendToArchive
* feat: /clear + /clear N — core context trim infrastructure (#83)

- Add thread.context.trim command + thread.trim-point-created event schemas in contracts
- Add ContextTrimPoint to OrchestrationThread read model
- Implement decider: validate thread, compute trim boundary, emit events + session stop
- Implement projector: append trim point to thread's contextTrimPoints array
- Wire provider session restart via thread.session-stop-requested event
- Parse /clear and /clear N in standalone slash command parser
- Register /clear in ChatComposer autocomplete menu
- Create ContextTrimPointDivider component (collapsed 'Earlier messages' bar)
- Update deriveTimelineEntries to produce context-trim entries
- Update deriveMessagesTimelineRows to produce context-trim divider rows
- Render ContextTrimPointDivider in MessagesTimeline
- Add tests: contracts schema parsing, composer parsing, timeline derivation, row logic

* fix: address review feedback — remove comments, fix imports, add decider/projector/composer tests

- Remove all inline comments from decider context-trim case (convention match)
- Replace inline import with top-level ContextTrimPoint import
- Fix prunedTurnIds typing from string[] to TurnId[]
- Remove unused id/createdAt props from ContextTrimPointDividerProps
- Add decider.contextTrim.test.ts: 6 tests (messages, empty, keepN, survive, missing thread, full clear)
- Add projector tests: trim point append, unknown thread, sort order
- Add composer slash command search tests for /clear
- Fix pre-existing brace mismatch in ipc.ts EnvironmentApi interface

* fix: correct prunedMessageCount assertion (7 messages, not 6)
* feat: expand/collapse earlier messages behind context trim divider (#84)

- Add expanded/onToggle props to ContextTrimPointDivider with Show/Hide text toggle
- Add hidden flag to MessagesTimelineRow types for pre-trim messages
- Update deriveMessagesTimelineRows to compute per-row visibility based on trim state
- Lift expandedTrimPointIds state to MessagesTimeline with Set-based tracking
- Apply opacity-30 dimming with transition to hidden message/plan/work rows
- Support multiple independent dividers each controlling their own section
- Add tests: logic tests for hidden rows + component tests for dimmed styling

* fix: nearest-trim algorithm + test for trim-1 expanded + trim-2 collapsed

- Fix deriveMessagesTimelineRows to find nearest trim (not just any collapsed trim)
- Add test for trim-1 expanded + trim-2 collapsed scenario (independent divider control)
* feat: /new — archive current thread + create new inheriting one (#85)

- Add thread.archive-and-new command + thread.archived-and-new-created event schemas
- Implement decider: validate thread not archived, generate new thread ID, emit events + session stop
- Implement projector: mark old thread archived, create new thread inheriting project/worktree/branch
- Parse /new in standalone slash command parser
- Register /new in ChatComposer autocomplete menu
- Dispatch thread.archive-and-new in ChatView with client-side newThreadId generation
- Add orchestrationEventEffects handler: promote new thread, clean up archived terminal state
- Add tests: contracts schemas, decider validation, projector inheritance, composer parsing

* fix: add test coverage for thread.archived-and-new-created event effects + /new slash search

- Add orchestrationEventEffects test: archived thread cleanup + new thread promotion
- Add composerSlashCommandSearch test for /new command
…86) (#102)

- Add requireTurnNotActive invariant: rejects commands when latestTurn.state is 'running'
- Add guardrail to thread.context.trim and thread.archive-and-new decider cases
- Add placeholder for thread.context.summarize guardrail (issue #87)
- Client-side: show warning toast when trying to /clear or /new during active turn
- Client-side: disable /clear and /new in composer menu when turn is active
- Add disabled field to ComposerCommandItem slash-command type
- Tests: decider rejection during active turn, acceptance when idle/completed
* feat: /compact — provider compaction + summary banner (#87)

- Add thread.context.compact + thread.context.summarize command schemas
- Add thread.context-compacted + thread.context-summarized event schemas
- Add optional summary field to ContextTrimPoint and ThreadContextTrimCommand
- Decider: validate and emit events for compact and summarize commands
- Decider: include summary in trim point when provided via thread.context.trim
- ProviderAdapter: add compactThread method to interface
- CodexSessionRuntime: implement compactThread via thread/compact/start RPC
- Claude/OpenCode/Cursor adapters: return unsupported error for compactThread
- ProviderService: delegate compactThread to adapter
- ProviderCommandReactor: process thread.context.compact — call provider, emit summarize + trim
- Composer: parse /compact, register in autocomplete, dispatch in ChatView
- ContextSummaryBanner component: blue-tinted 'Context compacted' callout
- MessagesTimeline: render summary banner above trim divider when summary present
- Tests: contracts schemas, decider validation, composer parsing

* Add token usage bug report for ClaudeAdapter
- Add thread.context.compact + thread.context.summarize command schemas
- Add thread.context-compacted + thread.context-summarized event schemas
- Add optional summary field to ContextTrimPoint and ThreadContextTrimCommand
- Decider: validate and emit events for compact and summarize commands
- Decider: include summary in trim point when provided via thread.context.trim
- ProviderAdapter: add compactThread method to interface
- CodexSessionRuntime: implement compactThread via thread/compact/start RPC
- Claude/OpenCode/Cursor adapters: return unsupported error for compactThread
- ProviderService: delegate compactThread to adapter
- ProviderCommandReactor: process thread.context.compact — call provider, emit summarize + trim
- Composer: parse /compact, register in autocomplete, dispatch in ChatView
- ContextSummaryBanner component: blue-tinted 'Context compacted' callout
- MessagesTimeline: render summary banner above trim divider when summary present
- Tests: contracts schemas, decider validation, composer parsing
- Capture token usage from message_start/message_delta stream events
- Stop emitting token-usage events from task_progress/task_notification
- Accumulated totals still tracked as totalProcessedTokens for cost
…auth pairing create (#112) (#119)

[23:57:26.334] INFO (#28): Running all migrations...
[23:57:26.338] INFO (#28): Migrations ran successfully { migrations: [] }
[23:57:26.343] ERROR (#3): AuthControlPlaneError: Failed to create pairing link.
    at file:///opt/homebrew/lib/node_modules/t3/dist/bin.mjs:7523:57
    at file:///opt/homebrew/lib/node_modules/t3/node_modules/effect/dist/internal/effect.js:1309:96
    at ~effect/Utils/internal (file:///opt/homebrew/lib/node_modules/t3/node_modules/effect/dist/Utils.js:69:12) {
  [cause]: BootstrapCredentialError: Failed to issue pairing credential.
      at internalBootstrapCredentialError (file:///opt/homebrew/lib/node_modules/t3/dist/bin.mjs:5165:63)
      at file:///opt/homebrew/lib/node_modules/t3/dist/bin.mjs:5193:61
      at file:///opt/homebrew/lib/node_modules/t3/node_modules/effect/dist/internal/effect.js:1309:96
      at ~effect/Utils/internal (file:///opt/homebrew/lib/node_modules/t3/node_modules/effect/dist/Utils.js:69:12) {
    [cause]: PersistenceSqlError: SQL error in AuthPairingLinkRepository.create:query: Failed to execute AuthPairingLinkRepository.create:query
        at file:///opt/homebrew/lib/node_modules/t3/dist/bin.mjs:4963:20
        at file:///opt/homebrew/lib/node_modules/t3/dist/bin.mjs:5018:136
        at file:///opt/homebrew/lib/node_modules/t3/node_modules/effect/dist/internal/effect.js:1309:96
        at ~effect/Utils/internal (file:///opt/homebrew/lib/node_modules/t3/node_modules/effect/dist/Utils.js:69:12) {
      [cause]: effect/sql/SqlError: Failed to prepare statement
          at Object.catch (file:///opt/homebrew/lib/node_modules/t3/dist/NodeSqliteClient-CDn28qdX.mjs:68:23)
          at file:///opt/homebrew/lib/node_modules/t3/node_modules/effect/dist/internal/effect.js:680:49
          at ~effect/Utils/internal (file:///opt/homebrew/lib/node_modules/t3/node_modules/effect/dist/Utils.js:69:12) {
        [cause]: effect/sql/SqlError/UnknownError: Failed to prepare statement
            at classifySqliteError (file:///opt/homebrew/lib/node_modules/t3/node_modules/effect/dist/unstable/sql/SqlError.js:270:10)
            at Object.catch (file:///opt/homebrew/lib/node_modules/t3/dist/NodeSqliteClient-CDn28qdX.mjs:68:46)
            at file:///opt/homebrew/lib/node_modules/t3/node_modules/effect/dist/internal/effect.js:680:49
            at ~effect/Utils/internal (file:///opt/homebrew/lib/node_modules/t3/node_modules/effect/dist/Utils.js:69:12) {
          [cause]: Error: table auth_pairing_links has no column named role
              at try (file:///opt/homebrew/lib/node_modules/t3/dist/NodeSqliteClient-CDn28qdX.mjs:67:19)
              at ~effect/Utils/internal (file:///opt/homebrew/lib/node_modules/t3/node_modules/effect/dist/Utils.js:69:12)
        }
      }
    }
  }
} now:
- Prints the resolved state directory in both JSON ( field) and
  text output, so users can verify which DB the token was written to
- Emits an advisory warning in text mode when  is absent,
  reminding that dev servers read from the  subdirectory

This prevents silently-invalid tokens caused by the  vs
subdirectory split in .
… from unvalidated merges (#114)

* fix: WebSocket RPC hang — nested Effect.gen deadlock in request fiber

Root cause: yield*-ing an Effect.gen from inside another Effect.gen
within the HTTP request fiber caused the inner generator to never
start executing. The first yield* statement inside makeWsRpcContext
never ran, silently hanging every /ws connection after auth.

Fix:
- Replaced Effect.gen in makeWsRpcContext with flat pipeline
  composition (Effect.flatMap/Effect.andThen chaining)
- Moved Effect.context<never>() capture to startup via a new
  WsAppServices service that pre-builds the full app-level context
  once at boot
- Fixed vendored Effect API mismatches: Context.Tag -> Context.Service,
  removed nonexistent Effect.tapErrorCause calls

Also includes layer-wiring fixes for startup services and auth
session infrastructure.

* refactor(server): simplify WS RPC route layer, drop WsAppServices indirection

Replace the hand-built RPC context map (WsAppServices + makeWsRpcContext)
with WsRpcGroup.toLayer(makeWsRpcHandlers(session)) provided directly to
RpcServer.toHttpEffectWebsocket. Remove the debug self-test route/layer and
the [DEBUG-ws-rpc] instrumentation added while chasing the WS hang, and the
ws-rpc-context-debug scratchpad probe.

Also simplify todoPersistence JSON parsing (error mapping now lives at the
ws.ts call site) and drop console.debug socket logging from the client WS
protocol layer.

* fix(server): declare WS RPC scopes for fork-added methods; fail fast on gaps

Root cause of the broken app (providers stuck on 'Checking provider
status', empty model picker, permanent 5s reconnect loop): commit 8834e51
introduced per-method WS RPC scope enforcement (RPC_REQUIRED_SCOPE) covering
only upstream methods. Eight fork-added methods (todo.load/mutate,
projects.list/add/remove, mcp.listServers/toggleServer,
changeRequest.runBatchAgents) were missing from the map, so calling any of
them threw at request time. That throw surfaced as a connection-level RPC
protocol defect and tore down the entire WebSocket; the web app calls
todo.load on every boot, killing every connection immediately.

- Add the eight missing scope declarations
- Validate the map against WsRpcGroup at boot (fail fast at startup instead
  of throwing per-request)
- Add a regression test asserting every WsRpcGroup method has a declared
  scope (wsRpcScopes.test.ts)

* fix(server): revert merge-splice corruption in ProviderRegistry.test.ts

Commit 8834e51 accidentally spliced ~630 duplicated lines into the middle
of the 'includes probed claude slash commands' test: a fragment of one test
plus full copies of six tests that already exist earlier in the file. The
resulting parse errors made tsgo skip semantic checking of the entire
package, masking ~450 type errors. Restore the file to its pre-splice
content (every spliced-in test already exists verbatim above).

* fix: repair typecheck across contracts, shared, client-runtime, and web

Fallout cleanup from the unvalidated merge series (40a6235..8fc126c).
Brings packages/contracts, packages/shared, packages/client-runtime, and
apps/web to a clean tsgo --noEmit.

Real runtime bugs fixed along the way:
- DiffPanel.tsx: isReviewMode TDZ crash (used before declaration)
- ChatView.tsx: invalid route '/thread/$threadId' (route does not exist)
- DiffCommentPanel.tsx: invalid 'iso' time-format argument
- localApi.test.ts: file did not parse (merge damage); mock rpcClient was
  missing the changeRequest method group

Type-level fixes:
- contracts: recursive ReviewComment schema; EnvironmentApi.changeRequest
  now reuses canonical schema-derived types instead of hand-duplicated
  structural types that had drifted (missing replies/agentStatus, plain
  string vs branded ThreadId)
- client-runtime: contextTrimPoints threading in threadDetailReducer
- shared: vitest -> vite-plus/test imports, crypto lint suppressions
- web: contextTrimPoints required on Thread (fixtures + derivation),
  exactOptionalPropertyTypes alignment in environmentApi/useReviewComments

* test: add e2e smoke harnesses for server boot and real browser flow

- apps/server/scratchpad/e2e-smoke.ts: boots the real server in-process
  (temp baseDir, desktop bootstrap token), authenticates, opens a real /ws
  connection, and exercises getConfig, todo.load, subscribeServerConfig,
  project.create, thread.create, thread.turn.start, subscribeShell.
  Exit 0 = pass. Designed to run unmodified across 40a6235..HEAD.
- apps/server/scratchpad/attach-smoke.ts: same RPC checks against an
  already-running server (URL + pairing token).
- e2e-browser-probe.ts (web + server copies): Playwright headless probe of
  the real dev pairing flow; asserts /settings/providers is not stuck on
  'Checking provider status' and dumps console/network/WS-frame diagnostics.

These caught the WS scope-map regression that unit tests missed; candidate
for promotion into a CI smoke gate.

* fix(server): repair pre-existing typecheck errors from unvalidated merges

Fixes ~210 typecheck errors across: orchestration deciders (Crypto service
requirement, PlannedOrchestrationEvent construction, fixture contextTrimPoints),
BackgroundAgentService (effect v4 API migration: Effect.catchAll → catch,
Option.fromNullable, Effect.async → callback, Stream.runForEach types),
ProviderCommandReactor, CodexSessionRuntime (compactThread stub),
EnvironmentAuth (session type widening), review/sourceControl providers, and
orchestration test fixtures.

Remaining: 241 errors concentrated in server.test.ts, bin.test.ts, ws.ts,
and BackgroundAgentService.test.ts.

* fix(server): add missing EnvironmentAuthorizationError to fork-added RPC contracts

Fix ws.ts handler errors caused by the WS RPC refactor (c335137). After the
refactor to WsRpcGroup.toLayer(), the raw error types of handlers became
visible, exposing that fork-added RPC contracts (mcp.listServers,
mcp.toggleServer, todo.load, todo.mutate) were missing
EnvironmentAuthorizationError in their error unions, and changeRequest
handlers were leaking PersistenceDecodeError | PersistenceSqlError from
projection queries.

- Add EnvironmentAuthorizationError to mcp and todos RPC error unions
  (matching the pattern used by all upstream methods)
- Convert persistence infrastructure errors to defects via Effect.orDie
  in changeRequest handlers that query getThreadShellById
- Provide FileSystem in todos handler scope
- Fix readonly-array vs mutable-array TodosData conversion

* fix(server): fix remaining 275 pre-existing typecheck errors + 53 test failures

Effect v4 migrations (v3→v4 API surface changes):
- ReviewDraftStore.ts: Option.fromNullable → fromNullishOr, catchAll → catch
- BackgroundAgentService.test.ts: Context.Service mock patterns for v4,
  effect v4 suppression rules (TS377024, TS377072, TS377057)

Fixture drift from merged features:
- server.test.ts, projector.test.ts, OrchestrationEngine.test.ts:
  contextTrimPoints required on all thread fixtures (new field from /compact)
- server.test.ts: Layer.mock() for 3 new production services
  (SourceControlDiscovery, ProviderMaintenanceRunner, BackgroundAgentService)
- BackgroundAgentService.test.ts: ExecuteGitInput/ExecuteGitResult types,
  removed 14 deprecated GitVcsDriver methods from mocks

Missing implementations:
- SourceControlProviderRegistry: getPullRequestReviews/createPullRequestReview
  stubs for unsupported providers
- TestProviderAdapter.integration.ts: compactThread stub

Typing fixes:
- GitHubCli.ts: JSON parse result casts for commit/author properties
- exactOptionalPropertyTypes across all touched test fixtures

* fix(mobile): add contextTrimPoints to threadActivity test fixture

Fix vp run typecheck failure where makeThread factory omitted the
required contextTrimPoints field on OrchestrationThread.

* style: apply auto-formatting from vp check --fix

* docs: postmortem for WS RPC hang — root cause, fixes applied, known issues

Documents both debugging sessions: the handoff session that identified and
fixed the root cause (8 missing WS RPC scope declarations), and this
continuation session that repaired 449 pre-existing typecheck errors + 53
test failures across the codebase, built e2e smoke harnesses, and brought
vp check + vp run typecheck to zero failures.

* docs: add test suite catalogue to AGENTS.md

Documents all unit test suites, the e2e smoke harness, attach smoke,
browser probe, and WS RPC scope regression test — with commands and
coverage descriptions.

* fix: remove console.debug calls from wsRpcProtocol.ts to pass typecheck, formatting fixes
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Jun 20, 2026
@harrryyd
harrryyd marked this pull request as ready for review June 20, 2026 05:46
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@harrryyd
harrryyd merged commit 2d71986 into main Jun 20, 2026
7 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.