fix(local): answer the familiar reads that standalone mode cannot serve - #91
Merged
Conversation
main does not typecheck. #89 added familiarContract and familiarAnalytics to QueryAdapter; #61 added createLocalQueryAdapter implementing that interface. Neither conflicted textually and each passed CI alone, because #61's run predated #89's merge, so the two were never typechecked together. Both reads answer service_unavailable. A familiar's contract and its execution analytics are Cave's to report -- what a familiar has been granted, and what it has since done -- and a device holding only local conversations has neither record. Returning an empty contract instead would read as "this familiar is permitted nothing", which is a different claim from "nobody asked Cave". Extends the existing status sweep to both members, so a future addition to the interface is caught by a test rather than by main going red, and adds a focused test for the codes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KacEJmkX5GhkViPUhx9Mie
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The changes correctly implement the newly required interface members and add targeted tests to prevent regressions while preserving the local adapter’s established status semantics.
Pull request overview
This PR fixes a TypeScript interface mismatch between the standalone/local QueryAdapter implementation and the expanded QueryAdapter surface (added in #89) by implementing the new familiar reads in the local adapter with a consistent service_unavailable response.
Changes:
- Add
familiarContractandfamiliarAnalyticsto the local query adapter, returning{ status: 'error', code: 'service_unavailable' }in standalone mode. - Extend the local adapter surface test suite to cover the new methods and ensure they never emit nonterminal statuses.
File summaries
| File | Description |
|---|---|
| src/lib/local/local-query-adapter.ts | Implements the new familiar reads for standalone/local mode by returning service_unavailable. |
| src/lib/local/local-chat.test.ts | Adds focused assertions for the new reads and includes them in the “never emits loading/stale/reconcile_required” sweep. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
maindoes not typecheck.npx tsc --noEmitonb5c3756reports 8 errors.Cause
A semantic conflict, with no textual conflict for git to report:
familiarContractandfamiliarAnalyticsto theQueryAdapterinterface (
src/lib/sdk/query-adapter.ts).src/lib/local/local-query-adapter.ts, which implementsQueryAdapterfor standalone mode.#61's CI ran before #89 merged, so the two were never typechecked together. Both
were green on their own;
mainwent red the moment #61 landed on top of #89.Fix
Both reads answer
service_unavailable.A familiar's contract and its execution analytics are Cave's to report — what a
familiar has been granted, and what it has since done. A device holding only
local conversations has neither record. Returning an empty contract instead
would render as "this familiar is permitted nothing", which is a different claim
from "nobody asked Cave", and the shell prints the code to the user verbatim.
service_unavailableis already this file's code for a read it cannot complete(
toErrorResult, for anything that is not aChatStoreError).Tests
The suite already had an exhaustive sweep asserting the local adapter never
emits
loading,stale, orreconcile_required, but it enumerated the membersby hand and so silently stopped covering the interface when it grew. Both new
members are added to it, so the next addition is caught by a failing test rather
than by
maingoing red. A focused test pins the two codes.tsc --noEmit— 0 errorslocal-chat.test.ts— 28 passed (was 27)Not labelled
ci:full: the break is TypeScript-only and Web checks covers itungated, so there is no reason to spend the macOS and Windows runners here.
mainruns the full set after merge.🤖 Generated with Claude Code
https://claude.ai/code/session_01KacEJmkX5GhkViPUhx9Mie