Skip to content

feat(native): familiar contract and analytics reads - #86

Draft
BunsDev wants to merge 3 commits into
mainfrom
feat/familiars-source-stage1
Draft

feat(native): familiar contract and analytics reads#86
BunsDev wants to merge 3 commits into
mainfrom
feat/familiars-source-stage1

Conversation

@BunsDev

@BunsDev BunsDev commented Sep 3, 2026

Copy link
Copy Markdown
Member

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.read and familiars.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 on main (sdk #104/#105, still unreleased changesets).

  • 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 (^[a-z0-9][a-z0-9_-]{0,63}$, case-insensitive) and a query builder bounded to Cave's window (7d/14d/8w/all) and recent (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 regenerated gen/schemas/desktop-schema.json stay in lockstep with specification-guards.test.ts.
  • TypeScript SDK boundary: QueryAdapter.familiarContract/familiarAnalytics (cached the same way as 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 (d24b2ef), which already carries familiarContract/familiarAnalytics.

Deliberately not included — needs your action

contract-canary.lock.json and phase1-conformance.lock.json are not re-pinned to the new SDK/Cave revisions in this PR. Re-pinning requires the SDK repo's create-release-artifacts.mjs, which is hard-gated by release.config.json's publishingEnabled: false, and per docs/workflows/client-v1-cross-repository-conformance.md the 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-isPhase 1 real-authority conformance and any contract-canary check 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 clean
  • pnpm typecheck — passes
  • pnpm 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 pass
  • pnpm 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 unmodified main checkout — not caused by this change)

🤖 Generated with Claude Code

https://claude.ai/code/session_016ueGDYGKGaMzNq5mTE6ogG

Copilot AI lite review requested due to automatic review settings September 3, 2026 22:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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 corresponding CaveReadPath routing/validation and analytics query-string construction.
  • Extend the TypeScript boundary with QueryAdapter.familiarContract / familiarAnalytics, widen CaveReadClient, 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.

@BunsDev

BunsDev commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

Added Stage 1 Task 4 on top of Task 3's native reads: the FamiliarsSource seam, MockFamiliarsSource, CaveFamiliarsSource, mappers, and capability gating (src/familiars/) — 39 new tests, all passing, fully independent of the lock re-pin blocker described above (no shell wiring, no lock/CI dependency). CaveFamiliarsSource is ready to go the moment Task 3's protected re-pin lands; nothing further needed on this piece.

Still not included: wiring FamiliarsShell to either source (Task 5) and ChatShell retirement (Task 6) — those come after Task 3 unblocks.

🤖 Generated with Claude Code

@BunsDev

BunsDev commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

Added a new, separate Stage 1 shell on top of the data-source seam: FamiliarsReadsShell (src/familiars/reads-shell.tsx), reachable at ?demo=familiars-reads against MockFamiliarsSource.

I read src/demo/familiars-shell.tsx closely before wiring anything and found it's not actually reducible to FamiliarsSource — it renders reasoning cards, held actions, image cards, @-mention guest replies, summoning, and a screen overlay (all Stage 2–4), plus fields Cave's Stage 1 contract never serves (emoji, soul text, memory). Converting that component in place would mean either inventing data or silently downgrading the shipped demo, so instead this is a new, smaller component: sidebar/thread/inspector driven entirely by FamiliarsSource, showing only what Stage 1 can honestly serve, with every other control rendering a one-line "not available yet" notice via availabilityFor. The existing ?demo=chat demo is untouched.

7 new tests (happy path, conversation switching, tab gating both ways, an all-failing source). Full local suite green — typecheck, lint, format, pnpm test:unit:normal (519/519 this run), and the e2e smoke spec including the new route.

CaveFamiliarsSource plugs into this shell mechanically already; flipping main.tsx/app.tsx to it and retiring ChatShell still wait on the Task 3 lock re-pin, so the first real render is against verified reads.

🤖 Generated with Claude Code

@BunsDev BunsDev added the ci:full Run the macOS and Windows CI jobs on this pull request label Sep 4, 2026
@BunsDev
BunsDev force-pushed the feat/familiars-source-stage1 branch 3 times, most recently from d32e794 to d4e10b1 Compare September 4, 2026 07:06
@BunsDev
BunsDev marked this pull request as draft September 4, 2026 07:32
@BunsDev

BunsDev commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

Split into #89, which lands the half that does not need a new SDK: the native
familiar read paths, the data-source seam and mock implementation, the
capability additions, and the reads shell.

The blocker here was that this branch replaces the vendored cave-client and
sdk-core tarballs without re-pinning contract-canary.lock.json:

vendored file this branch lock expects
sdk-core-0.1.0.tgz 33,332 · dc86c6d4c8 33,284 · 9a574e8bd5
cave-client-0.1.0.tgz 85,426 · de16ce13f2 81,543 · c44544adf8

The Contract canary checks out the SDK at the pinned revision and verifies the
vendored artifacts against it, so merging as-is would have turned main's
canary red — it had not caught this yet only because CI was queued. Re-pinning
requires a releaseManifest, which requires the authorized SDK release cut.

Moved to draft. Once #89 lands, rebase this onto main and it becomes exactly
the deferred remainder: mappers.ts, cave-source.ts, the familiar transport
in native-boundary.ts, the vendor bump, and the canary re-pin — landing
together when the release cut makes those tarballs pinnable.

The code itself verified clean throughout: cargo test 111 passed, clippy 0
issues, heavy 243, normal 517. This is a provenance split, not a quality one.

@BunsDev

BunsDev commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

Carrying one review finding from #89 over here, since it lands with cave-source.ts.

Copilot flagged that reads-shell.tsx maps not_ready to "Loading…", while
QueryResult's not_ready also means "disposed / no ready client". In #89 the
shell is driven only by MockFamiliarsSource, which never returns not_ready,
so the only reachable case there is the shell's own pre-fetch initial state
(the NOT_READY constant), where "Loading…" is correct.

Once CaveFamiliarsSource drives the shell through QueryAdapter, the
disconnected case becomes reachable and "Loading…" would tell users a request is
in progress while the app is actually disconnected. Worth distinguishing the two
then — either a separate initial sentinel in the shell, or a distinct message for
the adapter's not_ready.

BunsDev added a commit that referenced this pull request Sep 4, 2026
…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
BunsDev and others added 2 commits September 4, 2026 03:30
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
@BunsDev
BunsDev force-pushed the feat/familiars-source-stage1 branch from d4e10b1 to 9864c0e Compare September 4, 2026 08:33
@BunsDev

BunsDev commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

Rebased onto `main` now that #89 has landed. This reduces to exactly the deferred remainder, as expected:

  • `src/familiars/mappers.ts` (+ test)
  • `src/familiars/cave-source.ts` (+ test)
  • the familiar transport in `src/lib/sdk/native-boundary.ts`
  • `vendor/opencoven-sdk/{cave-client,sdk-core}-0.1.0.tgz` + `pnpm-lock.yaml`

`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

@BunsDev BunsDev removed the ci:full Run the macOS and Windows CI jobs on this pull request label Sep 4, 2026
…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
@BunsDev

BunsDev commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

Filed the not_ready copy finding as #90 against main, since #89 absorbed reads-shell.tsx and this branch no longer touches the file — tracking it here would have let it merge past the problem. Not a blocker for #86; best fixed with, or just after, the change that makes CaveFamiliarsSource drive the shell, when the state is actually reachable in a test.

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