feat(native): familiar contract and analytics reads - #86
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The PR description indicates required conformance/contract lock re-pins are intentionally not included, so CI will remain failing until that follow-up lands.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR wires the newly promoted Cave client-v1 reads for familiar contract and analytics into Chat’s native command boundary and TypeScript SDK boundary, keeping the native command guardrails (capabilities/schema/build-script/spec-guards) in sync.
Changes:
- Add two new Tauri commands (
cave_familiar_contract,cave_familiar_analytics) plus correspondingCaveReadPathrouting/validation and analytics query-string construction. - Extend the TypeScript boundary with
QueryAdapter.familiarContract/familiarAnalytics, widenCaveReadClient, and add native transport invocations with input canonicalization. - Update capabilities/schema/build guards and vendored SDK tarball lock integrity entries.
File summaries
| File | Description |
|---|---|
| src/specification-guards.test.ts | Extends Phase 1 guard expectations to include the two new native commands/permissions. |
| src/lib/sdk/query-adapter.ts | Adds adapter methods and caching channels for familiar contract/analytics reads. |
| src/lib/sdk/query-adapter.test.ts | Adds read-client mocks for the new adapter methods. |
| src/lib/sdk/native-boundary.ts | Adds canonicalization + managed-transport methods invoking the new native commands. |
| src/lib/sdk/connection-controller.ts | Extends CaveReadClient pick to include the new read methods. |
| src/chat-shell.test.tsx | Updates test adapter stub to include the new QueryAdapter methods. |
| src/app.test.tsx | Updates test adapter stub to include the new QueryAdapter methods. |
| src-tauri/src/transport.rs | Adds CaveReadPath variants, validation, endpoint pathing, query builder, and Rust unit tests. |
| src-tauri/src/lib.rs | Exports/registers the two new commands and updates smoke-test expectations. |
| src-tauri/src/commands.rs | Implements the two new #[tauri::command] functions that route into cave_read. |
| src-tauri/gen/schemas/desktop-schema.json | Regenerates desktop schema to include allow/deny permissions for new commands. |
| src-tauri/capabilities/default.json | Adds default allow-permissions for the two new commands. |
| src-tauri/build.rs | Updates command list used for build-time guard generation. |
| pnpm-lock.yaml | Updates integrity entries for the repacked vendored SDK tarballs. |
Review details
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
- Files reviewed: 13/16 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.
|
Added Stage 1 Task 4 on top of Task 3's native reads: the Still not included: wiring 🤖 Generated with Claude Code |
|
Added a new, separate Stage 1 shell on top of the data-source seam: I read 7 new tests (happy path, conversation switching, tab gating both ways, an all-failing source). Full local suite green — typecheck, lint, format,
🤖 Generated with Claude Code |
d32e794 to
d4e10b1
Compare
|
Split into #89, which lands the half that does not need a new SDK: the native The blocker here was that this branch replaces the vendored
The Contract canary checks out the SDK at the pinned revision and verifies the Moved to draft. Once #89 lands, rebase this onto The code itself verified clean throughout: |
|
Carrying one review finding from #89 over here, since it lands with Copilot flagged that Once |
…89) Splits #86 so the Stage 1 work that does not need a new SDK can land now. #86 replaced the vendored cave-client and sdk-core tarballs without re-pinning contract-canary.lock.json, which pins each artifact by size and SHA-256. The Contract canary checks out the SDK at the pinned revision and verifies the vendored artifacts against it, so merging that branch would have turned main's canary red. Re-pinning honestly needs a releaseManifest, which needs the authorized release cut, so the vendor bump waits. Lands here: the native familiar contract and analytics read paths, the data-source seam and its mock implementation, the capability additions, and the reads shell. Vendored artifacts and pnpm-lock.yaml are byte-identical to main. Waits for the SDK bump on #86: mappers.ts, cave-source.ts, and the familiar transport in native-boundary.ts, which between them need six symbols the pinned tarball does not export. Nothing in the app imports either module yet, so removing them cost no wiring. Also addresses the review: six tests covering the query adapter's new familiarContract and familiarAnalytics methods, and two descriptions that contradicted their code. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KacEJmkX5GhkViPUhx9Mie
Stage 1 Task 3 of the familiars integration plan
(docs/superpowers/plans/2026-09-02-familiars-integration.md): add the two
new Cave client-v1 reads Cave and the SDK already promoted today
(coven-cave #5288, sdk #104/#105) to Chat's native command boundary.
- src-tauri: two new commands, `cave_familiar_contract` and
`cave_familiar_analytics`, mirroring the existing per-id read shape
(`cave_get_conversation`). New `CaveReadPath::FamiliarContract`/
`::FamiliarAnalytics` variants build `/api/client/v1/familiars/:id/
{contract,analytics}`, with a `validate_canonical_familiar_id` bound
matching Cave's own familiar-id charset and an analytics query builder
bounded to Cave's `window`/`recent` parameters. New Rust unit tests cover
id-segment encoding and out-of-bound window/recent rejection. Guard
arrays (build.rs, capabilities/default.json, lib.rs, commands.rs) and
the regenerated desktop schema stay in lockstep with
specification-guards.test.ts.
- TypeScript SDK boundary: `QueryAdapter.familiarContract`/
`familiarAnalytics` (cached like the other detail reads),
`CaveReadClient` widened to the two new `CaveClient` methods, and the
native transport implementation using the SDK's newly-exported
`canonicalFamiliarContractData`/`canonicalFamiliarAnalyticsData`
envelope helpers.
- vendor/opencoven-sdk: re-packed `cave-client-0.1.0.tgz` and
`sdk-core-0.1.0.tgz` from current `OpenCoven/sdk` main (commit
d24b2ef), which already carries `familiarContract`/`familiarAnalytics`
as unreleased changesets.
Deliberately NOT included: `contract-canary.lock.json` and
`phase1-conformance.lock.json` are not re-pinned to the new SDK/Cave
revisions. Re-pinning requires the SDK repo's `create-release-artifacts.mjs`,
which is gated by `release.config.json` `publishingEnabled: false`, and
per `docs/workflows/client-v1-cross-repository-conformance.md` the whole
chain is deliberately "no offline acceptance mode": a live, protected
GitHub Actions environment (`client-v1-conformance`) with a named required
reviewer. That re-pin needs to happen through the real protected workflow,
not by hand here. Follow-up commit once that authority exists.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ueGDYGKGaMzNq5mTE6ogG
Stage 1 Task 4 of the familiars integration plan
(docs/superpowers/plans/2026-09-02-familiars-integration.md), built on top
of the previous commit's native contract/analytics reads. Against the mock
source only -- no shell wiring here (Task 5) and no dependency on the
contract-canary lock re-pin.
- src/familiars/source.ts: the `FamiliarsSource` interface and its Stage 1
view types (`FamiliarSummary`, `FamiliarDetail` with ward/identity/
report, `FamiliarActivity`, `ConversationSummary`, `ThreadMessage`) and
the `Capability` union from the integration design's data model and
capability-gating tables.
- src/familiars/mappers.ts (+ tests): the only module that knows the shape
of a `CaveCanonicalFamiliar`, `CaveFamiliarContract`, or
`CaveExecutionWindow` -- pure functions from SDK wire types to the view
types above, tested against literal SDK-fixture-shaped objects (renames,
optional-field omission, the window-not-served and null-completion-rate
cases).
- src/familiars/cave-source.ts (+ tests): `CaveFamiliarsSource`, a thin
fetch-then-map over `QueryAdapter` (already carrying `familiarContract`/
`familiarAnalytics` from the previous commit) -- no caching or retry
logic of its own, non-ok `QueryResult`s pass straight through unmapped.
- src/familiars/mock-source.ts (+ tests): `MockFamiliarsSource` wrapping
today's `src/demo/familiars-data.ts` and `mock-familiars.ts` into the
same view types. The demo's `FamActivity` is presentation-shaped
("100%", "1m 36s") because it matches the design mockup verbatim, so
reconstructing numeric fields from it is necessarily best-effort;
reasoning/hold/image/divider messages are dropped rather than faked,
since Cave does not serve rich content, attachments, or attention items
until Stage 3/4.
- src/familiars/capabilities.ts (+ tests): `availabilityFor(control,
capabilities)`, covering every row of the design's gating table.
Not included: wiring `FamiliarsShell` to either source (Task 5), or
`ChatShell` retirement (Task 6) -- those come once Task 3's lock re-pin
unblocks a real `CaveFamiliarsSource` in production.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ueGDYGKGaMzNq5mTE6ogG
d4e10b1 to
9864c0e
Compare
|
Rebased onto `main` now that #89 has landed. This reduces to exactly the deferred remainder, as expected:
`src/familiars/source.ts`, `mock-source.ts`, and `mock-source.test.ts` conflicted against #89's already-landed (and reviewed/fixed) versions — took `main`'s version for all three per the plan, so this branch carries no diff on them anymore. `contract-canary.lock.json` still isn't re-pinned — still waiting on the authorized SDK release cut. Verified locally: typecheck clean, lint/format clean, `src/familiars/*` 46/46, full unit suite 523/525 (2 failures are the same known pre-existing environment flake in `phase1-schema-v2-evidence.test.ts`, unrelated to this diff). Still draft, still blocked on the canary re-pin — this is just housekeeping so the branch reflects exactly what's left. 🤖 Generated with Claude Code |
…here #89 landed the seam without cave-source.ts or mappers.ts, so the comment on main says one implementation exists and that the Cave-backed one arrives with the SDK bump. This branch is that bump, and it reintroduces both files, so the comment would otherwise describe as absent two modules sitting beside it. Restores the wording #89 replaced. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KacEJmkX5GhkViPUhx9Mie
|
Filed the |
Summary
Stage 1 Task 3 of
docs/superpowers/plans/2026-09-02-familiars-integration.md: wires the two new Cave client-v1 reads —familiars.contract.readandfamiliars.analytics.read— into Chat's native command boundary. Cave promoted these routes today (coven-cave#5288,feat(client-v1): serve familiar contract and analytics) and the SDK already ships matching managed-transport methods onmain(sdk#104/#105, still unreleased changesets).src-tauri: two new commands,cave_familiar_contractandcave_familiar_analytics, mirroring the existing per-id read shape (cave_get_conversation). NewCaveReadPath::FamiliarContract/::FamiliarAnalyticsvariants build/api/client/v1/familiars/:id/{contract,analytics}, with avalidate_canonical_familiar_idbound matching Cave's own familiar-id charset (^[a-z0-9][a-z0-9_-]{0,63}$, case-insensitive) and a query builder bounded to Cave'swindow(7d/14d/8w/all) andrecent(0–100) parameters. New Rust unit tests cover id-segment encoding and out-of-bound window/recent rejection. Guard arrays (build.rs,capabilities/default.json,lib.rs,commands.rs) and the regeneratedgen/schemas/desktop-schema.jsonstay in lockstep withspecification-guards.test.ts.QueryAdapter.familiarContract/familiarAnalytics(cached the same way as the other detail reads),CaveReadClientwidened to the two newCaveClientmethods, and the native transport implementation using the SDK's newly-exportedcanonicalFamiliarContractData/canonicalFamiliarAnalyticsDataenvelope helpers.vendor/opencoven-sdk: re-packedcave-client-0.1.0.tgzandsdk-core-0.1.0.tgzfrom currentOpenCoven/sdkmain (d24b2ef), which already carriesfamiliarContract/familiarAnalytics.Deliberately not included — needs your action
contract-canary.lock.jsonandphase1-conformance.lock.jsonare not re-pinned to the new SDK/Cave revisions in this PR. Re-pinning requires the SDK repo'screate-release-artifacts.mjs, which is hard-gated byrelease.config.json'spublishingEnabled: false, and perdocs/workflows/client-v1-cross-repository-conformance.mdthe whole chain is deliberately "no offline acceptance mode": it needs a live, protected GitHub Actions environment (client-v1-conformance) with a named required reviewer (your account). I can't produce or fake those hashes locally — doing so would either fail CI or forge an unverified supply-chain claim.This PR will not be CI-green as-is —
Phase 1 real-authority conformanceand anycontract-canarycheck will fail on the stale lock until the re-pin lands. Once you run/approve the protected SDK release workflow at the new revision, I'll follow up with the lock re-pin commit (matching the pattern of #69–#72) and this can go green and merge.Validation (local, everything except the protected conformance pipeline)
cargo check/test/clippy/fmt— 111 tests pass, clippy clean, fmt cleanpnpm typecheck— passespnpm lint/pnpm format:check— passes (7 pre-existing CSS specificity warnings, unrelated baseline)pnpm exec vitest run src/specification-guards.test.ts src/lib/sdk/query-adapter.test.ts src/app.test.tsx src/chat-shell.test.tsx— 92/92 passpnpm test:unit:normal— 471 passed, 1 pre-existing unrelated flake (phase1-schema-v2-evidence.test.ts, a subprocess-spawn timeout reproduced identically on a clean unmodifiedmaincheckout — not caused by this change)🤖 Generated with Claude Code
https://claude.ai/code/session_016ueGDYGKGaMzNq5mTE6ogG