Addresses review findings before Slice 5 sandbox work. Resolver primitives: - resolveOutcome maps an attempt outcome to retry-or-terminal; removed the no-op isTerminalClassification. - WORK_STATUS_FOR_OUTCOME preserves real terminal Work status instead of collapsing everything back to ready. - Lifecycle: completed is terminal, cancelled reopens only to ready, and the invalid awaiting-design-approval -> awaiting-definition-approval reopening is gone. Execution (workExecution.ts): - finishAttempt replaces completeAttempt: auto-retries within the kit budget and settles Work at the real classification (Succeeded->completed, PermanentFailure/BudgetExhausted->failed, NeedsInput->needs-input, Blocked->blocked). No Work stays silently runnable after a failure. - startSimulatedExecution validates sliceId against the current approved Design (foreign ids rejected; defaults to the first slice) and advances slice status running -> completed/ready. - retrySimulatedExecution is now an explicit user restart with a retryable- state guard, not the automatic resolver path. - reconcileExpiredAttempts is bounded: a dead lease terminates as Blocked, resumes within budget or settles the Run/Work so nothing runs forever. - crons.ts runs the reconciler every 30s, string-referenced so it does not depend on the stale codegen. Planning (workPlanning.ts): - saveDefinition/saveDesign reject revision while a Run is executing. - submitQuestion validates and persists a durable workQuestions row instead of discarding planner questions. - Design revision invalidates active design approvals. Verification: primitives 69 tests (+4), backend 22 tests (+10) covering retry/cancel/failure/restart, slice validation, reconciliation, the revision guard, and question persistence. Root typecheck, web+agents build, and the configured Ultracite gate (53 files) all pass. package.json: the recurring check gate now covers workExecution, workPlanning, crons, resolver, and work-lifecycle.
code
This project was created with Better-T-Stack, a modern TypeScript stack that combines React, React Router, Convex, and more.
Features
- TypeScript - For type safety and improved developer experience
- React Router - Declarative routing for React
- React Native - Build mobile apps using React
- Expo - Tools for React Native development
- TailwindCSS - Utility-first CSS for rapid UI development
- Shared UI package - shadcn/ui primitives live in
packages/ui - Convex - Reactive backend-as-a-service platform
- Agent daemon - Bun/Effect service that leases Convex commands and dispatches them to AgentOS/RivetKit actors
- Authentication - Better-Auth
- Electrobun - Lightweight desktop shell for web frontends
- OpenTUI - Terminal interface in
apps/tui - Oxlint - Oxlint + Oxfmt (linting & formatting)
- Vite+ - Unified Vite toolchain, workspace task runner, linting, and formatting
Getting Started
First, install the dependencies:
bun install
Convex Setup
This project uses Convex as a backend. You'll need to set up Convex before running the app:
bun run dev:setup
Follow the prompts to create a new Convex project and connect it to your application.
Copy environment variables from packages/backend/.env.local to apps/*/.env.
Then, run the development server:
bun run dev
Open http://localhost:5173 in your browser to see the web application. Use the Expo Go app to run the mobile application. Your app will connect to the Convex cloud backend automatically.
Daemon setup
The daemon is a separate Bun process that connects to Convex, claims queued daemonCommands, and runs AgentOS actor actions. Copy apps/daemon/.env.example to apps/daemon/.env, replace the placeholder CONVEX_URL, then run:
bun run dev:daemon
Build the compiled daemon binary with bun run build:daemon; the output is apps/daemon/dist/code-daemon.
UI Customization
React web apps in this stack share shadcn/ui primitives through packages/ui.
- Change design tokens and global styles in
packages/ui/src/styles/globals.css - Update shared primitives in
packages/ui/src/components/* - Adjust shadcn aliases or style config in
packages/ui/components.jsonandapps/web/components.json
Add more shared components
Run this from the project root to add more primitives to the shared UI package:
npx shadcn@latest add accordion dialog popover sheet table -c packages/ui
Import shared components like this:
import { Button } from "@code/ui/components/button";
Add app-specific blocks
If you want to add app-specific blocks instead of shared primitives, run the shadcn CLI from apps/web.
Git Hooks and Formatting
- Optional native Vite+ hooks:
bun run hooks:setup - Docs: Vite+ commit hooks
- Run checks:
bun run check
Project Structure
code/
├── apps/
│ ├── web/ # Web application (React + React Router)
│ ├── native/ # Mobile application (React Native, Expo)
│ ├── desktop/ # Electrobun shell around the web build
│ ├── tui/ # OpenTUI terminal client
│ ├── daemon/ # Bun/Effect daemon for AgentOS command execution
├── packages/
│ ├── backend/ # Convex backend functions and schema
│ ├── primitives/ # Shared Effect services, including AgentOS helpers
│ ├── env/ # Runtime environment validation
│ ├── ui/ # Shared shadcn/ui components and styles
├── repos/ # Vendored upstream references; excluded from normal tooling
Available Scripts
bun run dev: Start all applications in development modebun run build: Build all applicationsbun run dev:web: Start only the web applicationbun run dev:server: Start the Convex development serverbun run dev:setup: Setup and configure your Convex projectbun run check-types: Check TypeScript types across all appsbun run dev:native: Start the React Native/Expo development serverbun run dev:tui: Start the terminal UIbun run check: Run Vite+ format/lint checks and workspace TypeScript checksbun run lint: Run Vite+ lint checksbun run format: Run Vite+ formattingbun run fix: Apply Ultracite fixesbun run staged: Run Vite+ checks against staged filesbun run hooks:setup: Install Vite+ native Git hooks withvp configbun run dev:desktop: Start the Electrobun desktop app with HMRbun run build:desktop: Build the stable Electrobun desktop appbun run build:desktop:canary: Build the canary Electrobun desktop appbun run dev:daemon: Start the daemon with Bun watch modebun run build:daemon: Compile the daemon binarybun run docs:update [commit-or-range]: Ask a detected coding-agent CLI to update first-party documentation for a commit or revision range; use--dry-runto inspect the promptbun run subtree list: List configured vendored Git subtreesbun run subtree status [name]: Inspect subtree metadata and local dirtinessbun run subtree preview <name>: Fetch and display upstream commits not yet represented by the subtreebun run subtree update <name> --yes: Safely pull a configured subtree with squash semantics