T-JV2A-adopt-augmented-books-desktop
Status: closed/done · Impact: high · Complexity: large
Bring the Augmented Books product itself — apps/tauri_desktop in the
source repo, a Tauri 2 + Vue 3 desktop app for reading interactive books —
into the monorepo as apps/augmented-books/, following the
apps/zoo/MIGRATION.md recipe. The dir is renamed because tauri_desktop
says nothing at the top level; the crate is already well-named
(augmented_books) and keeps its name.
Source: https://github.com/sksizer/augmented_books at pinned rev
acedcf77652e2e7c481e95123c486c2befe2c423.
| Location | Role today |
|---|---|
apps/zoo/MIGRATION.md | The adoption recipe this task follows: clean vendored copy, pnpm→Bun conversion, root Cargo membership, additive-only lock changes |
Cargo.toml | Root workspace members — needs two new explicit entries (the app crate and the runner builder; neither is covered by an existing glob) |
.moon/workspace.yml | projects.globs includes apps/* — the app registers by carrying its own moon.yml |
moon.yml | Documents the convention: tauri apps keep their own Bun workspaces (D-0016/D-0018) — this app does NOT join the root package.json workspaces |
lefthook.yml | Repo git-hook driver; the source repo’s husky/lint-staged setup is dropped, not carried |
Source app facts at the pinned rev:
apps/tauri_desktop/src-tauri/: crateaugmented_books(libaugmented_books_lib, extra binprepare-books). Deps includewasmtime 29+wasmtime-wasi(it hosts sandboxed WASM problem runners),zip,walkdir,reqwest 0.12 { blocking },serde_yaml,chrono. Norusqlite— nolinks = "sqlite3"conflict expected.apps/tauri_desktop/src-frontend/: Vue 3 + Vite (not Nuxt), pnpm, multi-entry (index.html,editor.html,settings.html), deps@nuxt/ui,sql.js,marked,tailwindcss. Generatedauto-imports.d.ts/components.d.tsare checked in.packages/runners/sqlite/: the WASM (WASI) sqlite problem runner the desktop app executes via wasmtime; itsbuilder/crate is a cargo workspace member in the source repo. Building the runner.wasmrequires the WASI SDK (seepackages/runners/README.mdthere).scripts/zip-books.sh(repo root there): zipscontent/books/*for distribution.content/books/does not exist at the pinned rev — carry the script, note the absent content dir in the app README.- Backend module conventions are documented in the source repo’s
README.mdanddocs/rust.md— carrydocs/with the app.
Proposed
Section titled “Proposed”apps/augmented-books/ package.json Bun workspace root (workspaces: ["src-frontend"]), own bun.lock moon.yml registers `augmented-books` (application/rust, tags: [tauri]) src-frontend/ Vue 3 + Vite frontend, converted pnpm→Bun src-tauri/ crate `augmented_books` — member of the ROOT cargo workspace runners/sqlite/ WASM sqlite runner (from packages/runners/sqlite), builder crate in root workspace scripts/ zip-books.sh + any book-content tooling the app references docs/ product docs carried overRoot Cargo.toml gains members apps/augmented-books/src-tauri and
apps/augmented-books/runners/sqlite/builder. The per-app Cargo.lock is
dropped; the root lock absorbs the tree additively.
Approach
Section titled “Approach”- Clone the pinned rev; copy
apps/tauri_desktop/→apps/augmented-books/,packages/runners/sqlite/→apps/augmented-books/runners/sqlite/, plusscripts/zip-books.shand the app-relevantdocs/. - Bun conversion per zoo recipe: drop
pnpm-lock.yaml/package-lock.jsonand anypackageManagerpin; translate the source root’s pnpmonlyBuiltDependencies(relevant subset) intotrustedDependencies; switchtauri.conf.jsonbefore{Dev,Build}Commandfrompnpm …tobun run …; generateapps/augmented-books/bun.lock. - Root cargo membership: add the two member entries. Opt into
{ workspace = true }only where the pin matches (tauri,tauri-build,serde,serde_json,tokio,anyhow,sha2,serde_yaml,chrono). Keep the app’s ownreqwestdeclaration — the workspace pin is deliberately TLS-free (default-features = false) and this app fetches remote catalogs; expect cargo feature-union to add TLS features to the shared reqwest build, which is compile-time only. wasmtime29 joins the lock additively. Verify no existing pin moves; if cargo forces a move, stop and record it in the PR rather than bumping silently.- Write
moon.yml(mirrorapps/zoo/moon.ymlshape) and relocate any backend lint/format/test scripts toapps/augmented-books/scripts/following the zoo/pumice pattern. - Do NOT carry husky/lint-staged — lefthook owns hooks here.
- Verify: root
cargo check -p augmented_books(+ builder crate), clippy,bun install+bun run build(vite) insrc-frontend. A fulltauri buildis a nice-to-have, not a gate. - App README: note the runner-build WASI SDK prerequisite and the absent
content/books/dir.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
apps/augmented-books/ | new | The vendored app (frontend, src-tauri, runners, scripts, docs) |
Cargo.toml | modify | members += apps/augmented-books/src-tauri, apps/augmented-books/runners/sqlite/builder |
Cargo.lock | modify | Additive absorption of the app + runner dep trees (wasmtime et al.) |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
cargo check -p augmented_booksand clippy pass from the repo root; the runnerbuildercrate checks clean. - AC-2:
bun install+bun run buildsucceed inapps/augmented-books/src-frontend/(all three HTML entries built). - AC-3: No
Cargo.lock,pnpm-lock.yaml, orpackage-lock.jsonexists anywhere underapps/augmented-books/. - AC-4:
moon query projectslistsaugmented-books. - AC-5: Root
Cargo.lockdiff is additive-only for existing pins; any forced move is called out in the PR body. - AC-6: The app README documents the WASI SDK prerequisite for
building runners and the missing
content/books/state.
Out of scope
Section titled “Out of scope”- Building/shipping the runner
.wasmin CI (WASI SDK provisioning is owner-gated). - Product/bundle-identifier renames — owner-gated, zoo precedent.
- Porting the frontend to Nuxt or to shared UI packages (
T-JCMLsurveys that). - The
@augmented/*TS packages — the frontend doesn’t consume them.
Dependencies
Section titled “Dependencies”- none — the app has no deps on the vendored TS packages, so it can land
in parallel with
T-LVLY.
Discovery context
Section titled “Discovery context”- Part of the augmented_books adoption (owner decision 2026-07-18). The source repo’s most recently active app (last commits 2026-02).
Post-mortem
Section titled “Post-mortem”Captured by /sdlc:task-work on 2026-07-19. PR: pending.
Acceptance criteria coverage
Section titled “Acceptance criteria coverage”- AC-1: auto —
cargo check -p augmented_books -p sqlite-runnerexits 0;cargo clippy -p augmented_booksclean (no warnings). - AC-2: auto —
bun install+bun run buildinsrc-frontend/pass (vue-tsc typecheck clean; vite built index/editor/settings entries). - AC-3: agent-manual —
git ls-files apps/augmented-booksshows no trackedCargo.lock/pnpm-lock.yaml/package-lock.json; added an app.gitignorefordist//target// wasm output. - AC-4: auto —
moon query projectslistsaugmented-books(sourceapps/augmented-books, tagtauri). - AC-5: agent-manual — root
Cargo.lockis additive except three semver-compatible within-minor unifications (toml 0.8.2→0.8.23,toml_datetime 0.6.3→0.6.11forced by wasmtime-cache 29;proc-macro-crate 2.0.2→2.0.0); no major pin moved. Called out in the PR body. - AC-6: agent-manual —
apps/augmented-books/README.mddocuments the WASI SDK prerequisite (+wasm32-wasip2target) and the absentcontent/books/dir at the pinned rev.
What worked
Section titled “What worked”- The
apps/zoo/MIGRATION.mdrecipe covered the whole conversion end-to-end, including the rusqlitelinks = "sqlite3"collision (the builder crate’srusqlite 0.31→0.32bump is the exact zoo precedent). sdlc quality runreportedOK 10/10on the first pass — the vendored code sits outside the SDLC-corpus gate scope and broke nothing.
Friction and automation gaps
Section titled “Friction and automation gaps”- Step 7’s baseline-gated gate failed with
baseline not foundwhen run from the worktree — the baseline is captured into the main repo’s.sdlc/quality-baselines/but the worktree’s default--baseline-dirresolves to the (empty) worktree.sdlc/; task-work Step 7 should pass an explicit--baseline-dir <main-repo>/.sdlc/quality-baselines, or capture should target a checkout-shared location. → T-OLTA-task-work-step7-worktree-baseline-dir - The task spec assumed “no rusqlite → no
links = sqlite3conflict,” but the runner’sbuildercrate carries rusqlite and the collision surfaced only atcargo check— dep-reconciliation specs should enumerate transitivelinks-bearing crates from vendored sub-crates, not just the top-level app crate. → T-LQB3-adoption-recipe-enumerates-links-crates origin/mainadvanced 18 commits between worktree creation and PR, making the pre-rebase two-dotCargo.lockdiff read as non-additive (phantom removals of already-merged crates). Handled by Step 9’s rebase; no action needed, but a reviewer reading the pre-rebase diff would misread it. (skipped — expected/handled, no action)
Spawned follow-up tasks
Section titled “Spawned follow-up tasks”- T-OLTA-task-work-step7-worktree-baseline-dir
(https://github.com/sksizer/dev/pull/921) [open/ready] —
Upstream-plugin (
sdlc-meta): task-work Step 7 resolves the quality baseline dir when run from a worktree. spawned. - T-LQB3-adoption-recipe-enumerates-links-crates
(https://github.com/sksizer/dev/pull/923) [open/ready] — Local:
app-adoption dep reconciliation enumerates transitive
links-bearing crates from vendored sub-crates. spawned.