Skip to content

feat: bring Uhura into the repo as the sibling client language (RFD 0022)#5

Closed
softmarshmallow wants to merge 1 commit into
mainfrom
uhura-import
Closed

feat: bring Uhura into the repo as the sibling client language (RFD 0022)#5
softmarshmallow wants to merge 1 commit into
mainfrom
uhura-import

Conversation

@softmarshmallow

Copy link
Copy Markdown
Member

What

Brings Uhura — a declarative UI language and deterministic headless experience runtime — into this repo as a nested Cargo workspace under uhura/, with Spock as its canonical backend provider.

Uhura fills the client-language slot Spock's own doctrine deliberately leaves vacant (RFD 0010, "generate types, never the client"; RFD 0009's borrow-first wall). It's a separate language with its own grammar, checker, and runtime, wired to Spock through the port seam — not part of Spock's surface.

Why here

The fit is designed-in on both sides. Uhura's design doc already names Spock as its intended real provider (its architecture diagram reads fixture driver ⇄ future Spock adapter; §9.6 is "The Spock-replaceability argument"). Both projects independently dogfooded the same Instagram product from opposite ends — Spock the backend (examples/instagram/, 19 tables / 43 fns), Uhura the client experience. Each is the other's missing half.

This PR is repo setup only — no runtime wire yet. The integration itself (contract projection + adapter) is recorded as direction in RFD 0022, to land later.

Contents

  • uhura/ — nested Cargo workspace: own rust-toolchain.toml (exact 1.92.0 pin), Cargo.lock, per-crate clippy purity denylists, path-filtered CI workflow (.github/workflows/uhura.yml), wasm build.
  • docs/rfd/0022-uhura-the-client-language.md — the integration direction: contract projection (Spock Contract → Uhura port contracts, with the timestamp/float type decisions left open), adapter obligations (owns wall-clock, transport, X-Spock-Actor), and the determinism boundary (Spock's wall-clock ids/timestamps vs Uhura's forbidden-inputs list).
  • rust-toolchain.toml (root) — pins the Spock workspace to 1.92.0 to match uhura; Spock builds/tests green on it (was floating on stable). Bump both files together.
  • examples/instagram-uhura/ — the Uhura client slice, at repo root beside examples/instagram/ (the Spock backend slice). Kept as distinct folders until the languages are wired; merge into one instagram/ domain is planned (RFD 0022 §7). Canonical PRD stays examples/instagram/PRD.md (language-neutral).

Notes

  • uhura/ is a nested workspace — Spock's root Cargo.toml lists members explicitly, so cargo doesn't absorb it, and uhura keeps its own edition (2024), resolver (3), and toolchain. Two Cargo.locks / target/s by design.
  • Uhura inherits the repo's MIT license; its crates stay publish = false.
  • Trade-off recorded: moving uhura's example corpus to the shared repo-root examples/ relaxes uhura's former "independently extractable" invariant (corpus now lives outside uhura/).

Test plan

Acceptance gate green in the new location:

  • cargo fmt --all --check — clean (both workspaces)
  • cargo clippy --workspace --all-targets --locked -- -D warnings — clean
  • UHURA_REQUIRE_PARITY=1 cargo test --workspace --locked (from uhura/) — 33 suites / 118 tests / 0 ignored, acceptance battery passes with native↔wasm parity byte-identical (parity enforced, not skipped)
  • cargo test --workspace (Spock root) — green on the pinned 1.92.0
  • CLI dogfood at the new path: uhura-cli check ../examples/instagram-uhura and trace ... --script=demo both pass

CI won't build wasm parity by default — UHURA_REQUIRE_PARITY=1 in CI remains deferred (uhura's own debt).

…022)

Import Uhura — a declarative UI language and deterministic headless
experience runtime — as a nested Cargo workspace under uhura/, with Spock
as its canonical backend provider. Uhura fills the client-language slot
Spock's doctrine deliberately leaves vacant (RFD 0010, "generate types,
never the client"): a separate language with its own grammar, checker, and
runtime, wired to Spock through the port seam.

- uhura/: nested Cargo workspace (own rust-toolchain 1.92.0 pin, Cargo.lock,
  per-crate clippy purity denylists), path-filtered CI workflow, wasm build.
- docs/rfd/0022: records the integration direction — contract projection
  (Spock Contract -> Uhura port contracts), adapter obligations, and the
  determinism boundary. No integration code lands yet; this is repo setup.
- rust-toolchain.toml: pin the root workspace to 1.92.0 to match uhura;
  Spock builds and tests green on it (was floating on stable).
- examples/instagram-uhura/: the Uhura client slice for the Instagram
  domain, at repo root beside examples/instagram/ (the Spock backend slice).
  Kept as distinct folders until the languages are wired; merge into one
  instagram/ domain planned (RFD 0022 section 7). Canonical PRD stays
  examples/instagram/PRD.md (language-neutral).

Full acceptance gate green in the new location: fmt, clippy -D warnings,
33 suites / 118 tests / 0 ignored, native<->wasm parity byte-identical
under UHURA_REQUIRE_PARITY=1.
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 216 files, which is 66 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9277f09f-8a07-46af-bad1-b0beeb48d220

📥 Commits

Reviewing files that changed from the base of the PR and between 8a89813 and 0752ea8.

⛔ Files ignored due to path filters (36)
  • examples/instagram-uhura/fixtures/assets/avatar-ayla.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/avatar-june.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/avatar-kenji.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/avatar-lena.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/avatar-marco.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/avatar-mira.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/avatar-nils.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/avatar-priya.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/avatar-theo.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/media-ayla-ferry.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/media-june-lookbook.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/media-kenji-copper.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/media-lena-glaze.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/media-marco-baja-1.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/media-marco-baja-2.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/media-marco-baja-3.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/media-nils-aurora-poster.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/media-priya-starter.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/media-theo-court.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-lena-1.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-lena-2.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-lena-3.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-lena-4.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-lena-5.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-lena-6.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-lena-7.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-lena-8.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-lena-9.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-mira-1.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-mira-2.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-mira-3.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-mira-4.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-mira-5.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/fixtures/assets/thumb-mira-6.jpg is excluded by !**/*.jpg
  • examples/instagram-uhura/uhura.lock is excluded by !**/*.lock
  • uhura/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (216)
  • .claude/launch.json
  • .github/workflows/uhura.yml
  • .gitignore
  • README.md
  • docs/rfd/0022-uhura-the-client-language.md
  • examples/README.md
  • examples/instagram-uhura/README.md
  • examples/instagram-uhura/app/feed/page.examples.uhura
  • examples/instagram-uhura/app/feed/page.uhura
  • examples/instagram-uhura/app/profile/[user]/page.examples.uhura
  • examples/instagram-uhura/app/profile/[user]/page.uhura
  • examples/instagram-uhura/catalog/base.toml
  • examples/instagram-uhura/components/bottom-nav.examples.uhura
  • examples/instagram-uhura/components/bottom-nav.uhura
  • examples/instagram-uhura/components/comment-row.examples.uhura
  • examples/instagram-uhura/components/comment-row.uhura
  • examples/instagram-uhura/components/notice-bar.examples.uhura
  • examples/instagram-uhura/components/notice-bar.uhura
  • examples/instagram-uhura/components/post-card.examples.uhura
  • examples/instagram-uhura/components/post-card.uhura
  • examples/instagram-uhura/components/profile-header.examples.uhura
  • examples/instagram-uhura/components/profile-header.uhura
  • examples/instagram-uhura/components/stories-tray.examples.uhura
  • examples/instagram-uhura/components/stories-tray.uhura
  • examples/instagram-uhura/fixtures/assets/manifest.toml
  • examples/instagram-uhura/fixtures/scripts/comment-ok.toml
  • examples/instagram-uhura/fixtures/scripts/demo.toml
  • examples/instagram-uhura/fixtures/scripts/feed-empty.toml
  • examples/instagram-uhura/fixtures/scripts/feed-failed.toml
  • examples/instagram-uhura/fixtures/scripts/like-ok.toml
  • examples/instagram-uhura/fixtures/scripts/like-refused.toml
  • examples/instagram-uhura/fixtures/scripts/paginate.toml
  • examples/instagram-uhura/fixtures/standard.toml
  • examples/instagram-uhura/ports/comments.port.toml
  • examples/instagram-uhura/ports/feed.port.toml
  • examples/instagram-uhura/ports/profile.port.toml
  • examples/instagram-uhura/styles/theme.css
  • examples/instagram-uhura/surfaces/comments-sheet.examples.uhura
  • examples/instagram-uhura/surfaces/comments-sheet.uhura
  • examples/instagram-uhura/uhura.toml
  • rust-toolchain.toml
  • uhura/.gitignore
  • uhura/Cargo.toml
  • uhura/README.md
  • uhura/crates/uhura-base/Cargo.toml
  • uhura/crates/uhura-base/clippy.toml
  • uhura/crates/uhura-base/src/canonical.rs
  • uhura/crates/uhura-base/src/codes.rs
  • uhura/crates/uhura-base/src/diagnostic.rs
  • uhura/crates/uhura-base/src/envelope.rs
  • uhura/crates/uhura-base/src/lib.rs
  • uhura/crates/uhura-base/src/span.rs
  • uhura/crates/uhura-base/src/value.rs
  • uhura/crates/uhura-check/Cargo.toml
  • uhura/crates/uhura-check/clippy.toml
  • uhura/crates/uhura-check/src/catalog.rs
  • uhura/crates/uhura-check/src/examples.rs
  • uhura/crates/uhura-check/src/fixture.rs
  • uhura/crates/uhura-check/src/infer.rs
  • uhura/crates/uhura-check/src/lib.rs
  • uhura/crates/uhura-check/src/lower.rs
  • uhura/crates/uhura-check/src/manifest.rs
  • uhura/crates/uhura-check/src/markup.rs
  • uhura/crates/uhura-check/src/pipeline.rs
  • uhura/crates/uhura-check/src/preview.rs
  • uhura/crates/uhura-check/src/replay.rs
  • uhura/crates/uhura-check/src/resolve.rs
  • uhura/crates/uhura-check/src/style.rs
  • uhura/crates/uhura-check/src/types.rs
  • uhura/crates/uhura-check/tests/contracts_corpus.rs
  • uhura/crates/uhura-cli/Cargo.toml
  • uhura/crates/uhura-cli/src/bin/gen_assets.rs
  • uhura/crates/uhura-cli/src/cmd/check.rs
  • uhura/crates/uhura-cli/src/cmd/dev.rs
  • uhura/crates/uhura-cli/src/cmd/fmt.rs
  • uhura/crates/uhura-cli/src/cmd/mod.rs
  • uhura/crates/uhura-cli/src/cmd/project.rs
  • uhura/crates/uhura-cli/src/cmd/trace.rs
  • uhura/crates/uhura-cli/src/fsio.rs
  • uhura/crates/uhura-cli/src/lib.rs
  • uhura/crates/uhura-cli/src/main.rs
  • uhura/crates/uhura-core/Cargo.toml
  • uhura/crates/uhura-core/clippy.toml
  • uhura/crates/uhura-core/src/decode.rs
  • uhura/crates/uhura-core/src/eval.rs
  • uhura/crates/uhura-core/src/event.rs
  • uhura/crates/uhura-core/src/ir.rs
  • uhura/crates/uhura-core/src/lib.rs
  • uhura/crates/uhura-core/src/state.rs
  • uhura/crates/uhura-core/src/step.rs
  • uhura/crates/uhura-core/src/trace.rs
  • uhura/crates/uhura-core/src/view.rs
  • uhura/crates/uhura-core/tests/txn_matrix.rs
  • uhura/crates/uhura-fixture/Cargo.toml
  • uhura/crates/uhura-fixture/clippy.toml
  • uhura/crates/uhura-fixture/src/driver.rs
  • uhura/crates/uhura-fixture/src/lib.rs
  • uhura/crates/uhura-fixture/src/script.rs
  • uhura/crates/uhura-fixture/tests/driver.rs
  • uhura/crates/uhura-port/Cargo.toml
  • uhura/crates/uhura-port/clippy.toml
  • uhura/crates/uhura-port/src/contract.rs
  • uhura/crates/uhura-port/src/envelope.rs
  • uhura/crates/uhura-port/src/lib.rs
  • uhura/crates/uhura-port/src/load.rs
  • uhura/crates/uhura-port/src/types.rs
  • uhura/crates/uhura-project/Cargo.toml
  • uhura/crates/uhura-project/clippy.toml
  • uhura/crates/uhura-project/src/icons.rs
  • uhura/crates/uhura-project/src/lib.rs
  • uhura/crates/uhura-syntax/Cargo.toml
  • uhura/crates/uhura-syntax/clippy.toml
  • uhura/crates/uhura-syntax/src/ast.rs
  • uhura/crates/uhura-syntax/src/css.rs
  • uhura/crates/uhura-syntax/src/cursor.rs
  • uhura/crates/uhura-syntax/src/format.rs
  • uhura/crates/uhura-syntax/src/lib.rs
  • uhura/crates/uhura-syntax/src/parser/dsl.rs
  • uhura/crates/uhura-syntax/src/parser/examples.rs
  • uhura/crates/uhura-syntax/src/parser/expr.rs
  • uhura/crates/uhura-syntax/src/parser/markup.rs
  • uhura/crates/uhura-syntax/src/parser/mod.rs
  • uhura/crates/uhura-syntax/src/parser/stream.rs
  • uhura/crates/uhura-syntax/src/token.rs
  • uhura/crates/uhura-syntax/tests/common/normative_sources.rs
  • uhura/crates/uhura-syntax/tests/fmt_roundtrip.rs
  • uhura/crates/uhura-syntax/tests/parse_normative.rs
  • uhura/crates/uhura-tests/Cargo.toml
  • uhura/crates/uhura-tests/goldens/m2/instagram-ir.json
  • uhura/crates/uhura-tests/goldens/m2/reject-alt-xor-decorative.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-class-rooting-violation.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-controlled-promotion.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-event-on-layout.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-missing-availability-arm.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-nested-interactive.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-non-exhaustive-union-match.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-unbound-required-prop.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-undeclared-component-emit.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-undefined-class-warning.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-unguarded-projection-read.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-unkeyed-each.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-unknown-element.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-unknown-icon.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-unreachable-handler.txt
  • uhura/crates/uhura-tests/goldens/m2/reject-unresolved-name-did-you-mean.txt
  • uhura/crates/uhura-tests/goldens/m3/v-bottom-nav-feed-active.json
  • uhura/crates/uhura-tests/goldens/m3/v-bottom-nav-profile-active.json
  • uhura/crates/uhura-tests/goldens/m3/v-comment-row-pending.json
  • uhura/crates/uhura-tests/goldens/m3/v-comment-row-settled.json
  • uhura/crates/uhura-tests/goldens/m3/v-comments-sheet-empty.json
  • uhura/crates/uhura-tests/goldens/m3/v-comments-sheet-populated.json
  • uhura/crates/uhura-tests/goldens/m3/v-feed-empty.json
  • uhura/crates/uhura-tests/goldens/m3/v-feed-exhausted.json
  • uhura/crates/uhura-tests/goldens/m3/v-feed-failed.json
  • uhura/crates/uhura-tests/goldens/m3/v-feed-first-page.json
  • uhura/crates/uhura-tests/goldens/m3/v-feed-loading.json
  • uhura/crates/uhura-tests/goldens/m3/v-notice-bar-refusal.json
  • uhura/crates/uhura-tests/goldens/m3/v-post-card-carousel-liked.json
  • uhura/crates/uhura-tests/goldens/m3/v-post-card-image-post.json
  • uhura/crates/uhura-tests/goldens/m3/v-post-card-like-pending.json
  • uhura/crates/uhura-tests/goldens/m3/v-post-card-video-poster.json
  • uhura/crates/uhura-tests/goldens/m3/v-profile-header-lena.json
  • uhura/crates/uhura-tests/goldens/m3/v-profile-lena-posts.json
  • uhura/crates/uhura-tests/goldens/m3/v-profile-loading.json
  • uhura/crates/uhura-tests/goldens/m3/v-profile-self.json
  • uhura/crates/uhura-tests/goldens/m3/v-stories-tray-tray.json
  • uhura/crates/uhura-tests/goldens/m4/trace-comment-ok.jsonl
  • uhura/crates/uhura-tests/goldens/m4/trace-feed-empty.jsonl
  • uhura/crates/uhura-tests/goldens/m4/trace-feed-failed.jsonl
  • uhura/crates/uhura-tests/goldens/m4/trace-like-ok.jsonl
  • uhura/crates/uhura-tests/goldens/m4/trace-like-refused.jsonl
  • uhura/crates/uhura-tests/goldens/m4/trace-paginate.jsonl
  • uhura/crates/uhura-tests/goldens/m4/v-comments-sheet-composing.json
  • uhura/crates/uhura-tests/goldens/m4/v-comments-sheet-pending-append.json
  • uhura/crates/uhura-tests/goldens/m4/v-feed-appended.json
  • uhura/crates/uhura-tests/goldens/m4/v-feed-comments-open.json
  • uhura/crates/uhura-tests/goldens/m4/v-feed-like-pending.json
  • uhura/crates/uhura-tests/goldens/m4/v-feed-like-refused.json
  • uhura/crates/uhura-tests/goldens/m4/v-feed-load-failed.json
  • uhura/crates/uhura-tests/goldens/m4/v-feed-load-pending.json
  • uhura/crates/uhura-tests/goldens/m4/v-profile-tagged-empty.json
  • uhura/crates/uhura-tests/src/lib.rs
  • uhura/crates/uhura-tests/tests/acceptance_feed.rs
  • uhura/crates/uhura-tests/tests/common/corpus.rs
  • uhura/crates/uhura-tests/tests/m2_gates.rs
  • uhura/crates/uhura-tests/tests/m3_gates.rs
  • uhura/crates/uhura-tests/tests/m4_gates.rs
  • uhura/crates/uhura-tests/tests/purity.rs
  • uhura/crates/uhura-wasm/Cargo.toml
  • uhura/crates/uhura-wasm/src/lib.rs
  • uhura/crates/uhura-wasm/tests/abi_contract.rs
  • uhura/docs/README.md
  • uhura/docs/rfcs/0001-project-foundation.md
  • uhura/docs/rfcs/README.md
  • uhura/docs/spec/README.md
  • uhura/docs/working-group/README.md
  • uhura/docs/working-group/frame-stress-test-handoff.md
  • uhura/docs/working-group/instagram-spike-design.md
  • uhura/rust-toolchain.toml
  • uhura/scripts/build-wasm.sh
  • uhura/scripts/parity.mjs
  • uhura/shell/appliers.js
  • uhura/shell/focus.js
  • uhura/shell/index.html
  • uhura/shell/jsconfig.json
  • uhura/shell/main.js
  • uhura/shell/overlay.js
  • uhura/shell/pump.js
  • uhura/shell/reconciler.js
  • uhura/shell/scroll.js
  • uhura/shell/shell.css
  • uhura/shell/surfaces.js
  • uhura/shell/textfield.js
  • uhura/shell/ticks.js
  • uhura/shell/types.js
  • uhura/shell/wasm.d.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch uhura-import

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@softmarshmallow

Copy link
Copy Markdown
Member Author

Superseded: Uhura will live in its own dedicated repository rather than as a nested workspace here.

The workspace has been imported to https://github.com/gridaco/uhura (promoted to the repo root, with the Instagram corpus under examples/instagram-uhura/; acceptance gate green on the 1.92.0 pin). Keeping it separate avoids the nested-workspace costs this PR carried (dual toolchain pins, path-filtered CI, the relaxed "independently extractable" invariant).

The port seam stays provider-neutral; the Spock↔Uhura integration direction (contract projection + adapter) can be reopened as its own RFD when the runtime wire is actually built. Closing without merge — main is untouched.

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.

1 participant