Skip to content

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

Closed
BunsDev wants to merge 1 commit into
mainfrom
feat/native-familiar-reads
Closed

feat(native): familiar contract and analytics reads#84
BunsDev wants to merge 1 commit into
mainfrom
feat/native-familiar-reads

Conversation

@BunsDev

@BunsDev BunsDev commented Sep 3, 2026

Copy link
Copy Markdown
Member

Summary

Stage 1, Task 3 (steps 1–2) of the Familiars surface integration — plan of record: docs/superpowers/plans/2026-09-02-familiars-integration.md.

Adds the two native commands for the familiar detail reads Cave promoted into Client v1 (OpenCoven/coven-cave#5288) and the SDK now serves (OpenCoven/sdk#104, #105):

Command Route
cave_get_familiar_contract GET /api/client/v1/familiars/:id/contract
cave_get_familiar_analytics GET /api/client/v1/familiars/:id/analytics

Each follows the same bounded path as every canonical read: one CaveReadPath variant with validated parameters, one command taking handle and operation, one capability permission, and one entry in each reviewed command table (build.rs, commands.rs, lib.rs, capabilities/default.json, the generated desktop schema, and specification-guards.test.ts).

Bounds

Familiar ids are held to the slug allow-list Cave itself enforces ([a-z0-9][a-z0-9_-]{0,63}), which is deliberately narrower than a conversation id: . and ~ are legal there and not here, because Cave's allow-list does not carry them. An id this host would have to percent-encode is one Cave could never name, so it is refused before the wire rather than sent to be refused.

Analytics narrowing is bounded the same way. Cave refuses an unknown window or an out-of-range recent rather than correcting it, so the same values are refused here; and the query carries only what the caller set, because an implied default would become a refusal at the other end.

Scope

The webview binding for these commands is not in this PR. It imports canonicalFamiliarContractData / canonicalFamiliarAnalyticsData from the SDK, which requires bumping the vendored tarballs — and that is blocked on an SDK release-candidate cut (see below). The host is complete and exercised by its own tests in the meantime; nothing in the webview calls these commands yet.

Validation

  • cargo test — 112 passed, including 3 new: the familiar-id allow-list (accepted and refused shapes, incl. .., a/b, dot.name, -leading, 65 chars), the analytics narrowing bounds, and route/query construction.
  • cargo clippy --all-targets --all-features -- -D warnings clean; cargo fmt --check clean.
  • specification-guards 50/50 — the three command/permission/schema guards failed first, then passed once implemented.
  • pnpm typecheck clean; unit suite 473 passed / 61 skipped across 31 files.

Follow-up (blocked, needs a decision)

Task 3 step 3 vendors the new SDK tarballs and re-pins contract-canary.lock.json / phase1-conformance.lock.json. That is blocked: since OpenCoven/sdk#74, create-release-artifacts.mjs is publication-only and refuses while publishingEnabled: false. The canary passes today only because the pinned acc38488 predates that change, so re-pinning to any newer SDK revision requires an authorized release-candidate cut (RELEASING.md §1–4).

Add the two native commands for the familiar detail reads Cave promoted into
Client v1 (OpenCoven/coven-cave#5288) and the SDK now serves
(OpenCoven/sdk#104):

  cave_get_familiar_contract    GET /api/client/v1/familiars/:id/contract
  cave_get_familiar_analytics   GET /api/client/v1/familiars/:id/analytics

Both go through the same bounded path every canonical read uses: one
CaveReadPath variant with validated parameters, one command taking `handle`
and `operation`, one capability permission, and one entry in each reviewed
command table.

A familiar id is held to the slug allow-list Cave itself enforces, which is
narrower than a conversation id: `.` and `~` are legal there and not here,
because Cave's own allow-list does not carry them. An id this host would have
to percent-encode is one Cave could never name, so it is refused before the
wire rather than sent to be refused.

The analytics narrowing is bounded the same way. Cave refuses an unknown
window or an out-of-range recent count rather than correcting it, so the same
values are refused here, and the query carries only what the caller asked for
-- an implied default would become a refusal at the other end.

The webview binding for these commands lands with the vendored SDK bump; the
host is complete and exercised by its own tests in the meantime.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KacEJmkX5GhkViPUhx9Mie
Copilot AI lite review requested due to automatic review settings September 3, 2026 08:35

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.

🟢 Approval recommended

The new commands follow the existing validated native boundary pattern and the supporting guard/capability/schema/test updates appear complete and internally consistent.

Pull request overview

This PR adds Stage 1 “read” support in the Tauri native host for the Familiars surface integration, exposing two new Cave client-v1 read commands (contract + analytics) behind the same constrained/validated native boundary pattern used by existing canonical reads.

Changes:

  • Added CaveReadPath variants + validation + route/query construction for familiar contract and analytics reads in the native transport.
  • Added two new Tauri commands (cave_get_familiar_contract, cave_get_familiar_analytics) and registered them in the reviewed command tables.
  • Extended capabilities / generated schema / specification guard tests to include the new commands and permissions.
File summaries
File Description
src/specification-guards.test.ts Extends the guard expectations to include the two new commands and allow-permissions.
src-tauri/src/transport.rs Adds validated read-path variants plus query construction for familiar analytics narrowing and routes for both endpoints, with unit tests.
src-tauri/src/lib.rs Exports and registers the two new commands in the Tauri invoke handler and smoke test command list.
src-tauri/src/commands.rs Implements the two new Tauri commands and adds them to the registered command list.
src-tauri/gen/schemas/desktop-schema.json Adds allow/deny permission const entries for the two commands to the generated schema.
src-tauri/capabilities/default.json Adds the two allow-permissions to the default capability set.
src-tauri/build.rs Extends the reviewed native command table for permission/schema generation alignment.
Review details
  • Files reviewed: 7/7 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

Superseded by #86, which includes this same Stage 1 Task 3 work (native cave_familiar_contract/cave_familiar_analytics commands, same bounded id/window/recent validation) plus the Task 4 data-source seam and Task 5 reads shell built on top of it. Closing to avoid two independent implementations of the same native commands landing in parallel.

🤖 Generated with Claude Code

@BunsDev BunsDev closed this Sep 4, 2026
@BunsDev
BunsDev deleted the feat/native-familiar-reads branch September 4, 2026 03:56
BunsDev added a commit that referenced this pull request Sep 4, 2026
…ine speed

The windows-supervisor-behavior job is red on main. It is not red because of
anything this suite exists to catch.

Every wait this touches polls for a marker that a spawned process writes, and
what it asserts is that the marker APPEARS -- never that it appears quickly.
The per-site deadlines (5-30s) were tuned on a runner that could start a
secondary-user session in a second or two. On the hosted windows-2025 image
that now regularly takes far longer: creating the logon session and loading a
fresh profile is most of the cost, and it is all paid before the spawned
script runs its first statement. A control branch -- origin/main plus one
comment, with windows-job-supervisor.{cs,test.ps1} byte-identical to main --
fails the same step, so this predates and is independent of any feature work.

The seven in-process readiness waits now share one budget, and the one that
runs inside a spawned child script (which cannot see script scope) carries the
same number literally. This bounds patience, not behaviour: a marker that
never arrives still fails, and the job's own 20-minute timeout still bounds
the run. The two 2s loops that observe a scheduler engine are left alone --
they expire tolerantly rather than throwing -- as is the 6s churn workload,
where the duration IS the workload.

Also name the cause when something throws. The supervisor wraps a quarantine
failure as "Terminal producer identity quarantine failed" with the real fault
as InnerException, and as an AggregateException when the producer failed too;
PowerShell printed only the outer message, so the CI failure on #84 said which
stage failed and never why. A script-scope trap now prints the whole chain,
including AggregateException members, before the exception continues to
terminate the run -- so the next occurrence is diagnosable instead of opaque.

Verified with pwsh 7.6.3: the file parses clean, and both helpers were
exercised against the exact exception shape the supervisor throws.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KacEJmkX5GhkViPUhx9Mie
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:full Run the macOS and Windows CI jobs on this pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants