# Zopu Work OS — Technical Architecture > **Related:** `agent-context.md` defines agent rules; `dev-loop.md` defines orchestration; `glossary.md` defines terms. > **Status:** Working technical source of truth > **Audience:** engineers and implementation agents > **Read after:** `product.md` > **Principle:** durable intent/state is separate from disposable execution. ## 1. System topology ```text Web / desktop / mobile │ Convex queries, mutations, storage ▼ Convex application backend ├── authentication and tenancy ├── normalized product data ├── conversation turn queue └── reactive client projections │ service-authenticated dispatch ▼ FLUE orchestration service ├── model calls ├── typed tools └── canonical Flue persistence in Convex │ later execution commands ▼ Rivet Engine + AgentOS (post-Slice 1) └── sandboxes, harnesses, and durable execution ``` Clients MUST communicate only with Convex. FLUE and future Rivet/AgentOS services are private workers: Convex admits durable commands, invokes the worker, and stores the product-facing result before clients observe it. ### Ownership | Layer | Owns | |---|---| | Convex | authentication, normalized product records, command admission, reactive reads | | FLUE | private programmable orchestration and domain-specific agents | | Rivet actors (later) | serialized execution ownership, recovery, timers, leases | | Harness | bounded coding/tool loop | | Sandbox/runtime | filesystem, processes, network, isolation | | Git | source revision history | | Artifact store | durable outputs/evidence | | External systems | collaboration, delivery, monitoring | No client, harness, sandbox, or FLUE process owns product state. ### Slice 1 relational core ```text organizations ──< organizationMembers organizations ──< projects ──< projectContextDocuments organizations ──1 conversations ──< conversationTurns conversationTurns ──< conversationMessages ──< conversationAttachments projects ──< signals ──< signalConstraints signals ──< signalSources >── conversationMessages projects ──< works signals ──< signalWorkAttachments >── works works ──< workEvents ``` Convex mutations provide atomic transactions and optimistic serializability. Foreign-key integrity and uniqueness are enforced in the owning mutations; composite indexes back every identity and relation lookup. Flue's adapter tables remain isolated infrastructure persistence and are not product-domain relations. ## 2. Domain boundaries Recommended packages: ```text packages/ ├── signals/ ├── work/ ├── design/ ├── planning/ ├── kits/ ├── resolver/ ├── verification/ ├── artifacts/ ├── results/ ├── knowledge/ ├── runtimes/ ├── harnesses/ └── integrations/ ``` Each domain SHOULD separate: ```text domain/ pure state, schemas, invariants application/ use cases and orchestration ports/ Effect services adapters/ infrastructure implementations ``` Avoid package proliferation in v0; logical boundaries may begin as folders. ## 3. Core records Minimal durable model: ```ts type Id = string interface Message { id: Id projectId: Id content: string createdAt: number } interface Signal { id: Id projectId: Id sourceType: string sourceId: string sourcePayloadRef?: string summary: string fingerprint: string status: "candidate" | "accepted" | "dismissed" } interface Work { id: Id projectId: Id title: string objective: string risk: "low" | "medium" | "high" status: WorkStatus definitionVersion?: number designVersion?: number createdAt: number updatedAt: number } interface Step { id: Id workId: Id sliceId?: Id kind: "design" | "implement" | "verify" | "integrate" | "publish" | "observe" objective: string dependsOn: readonly Id[] status: StepStatus } interface Run { id: Id workId: Id stepId: Id kitVersion: string status: RunStatus } interface Attempt { id: Id runId: Id number: number harness: string runtime: string sourceRevision: string status: AttemptStatus startedAt?: number endedAt?: number } interface Artifact { id: Id workId: Id stepId?: Id runId?: Id attemptId?: Id type: string uri?: string contentHash?: string sourceRevision?: string environmentId?: string metadata: unknown } interface Question { id: Id workId: Id stepId?: Id attemptId?: Id prompt: string recommendation?: string alternatives: readonly string[] status: "open" | "answered" | "withdrawn" answer?: string } ``` All external/model payloads MUST be decoded with schemas at boundaries. ## 4. Work state machine ```text Proposed → Defining → AwaitingDefinitionApproval → Designing → AwaitingDesignApproval → Ready → ExecutingSlice → VerifyingSlice → AwaitingSliceReview → IntegratedVerification → Review → Releasing → Observing → Completed ``` Side/terminal states: ```text NeedsInput | Blocked | Replanning | Failed | Cancelled ``` Transitions require explicit commands plus evidence. State MUST NOT be inferred from the latest text message. ## 5. Actor model Start small. ### ProjectActor Owns: - project configuration; - repository/runtime policies; - active Work index; - integration endpoints; - project-level Signal routing. ### WorkActor Initial central aggregate: - Work Definition and versions; - Design Packet and versions; - slice/step graph; - Resolver state; - approvals/questions; - artifact references; - result. It serializes lifecycle transitions and commands. ### AttemptActor Owns one execution attempt: - runtime lease/sandbox ID; - harness session; - scoped credentials; - event stream/checkpoints; - cancellation; - attempt timeout; - normalized outcome. ### VerificationActor Split from WorkActor after v0 verification is stable. Owns plan, checks, evidence, verdict. ### IntegrationActor Added when multiple slices/branches exist. Owns branch composition, conflicts, integrated revision, integrated checks. ### ResultActor Added after delivery observation exists. Owns rollout observation, original success signals, final outcome, learning proposals. Do not create an actor per document or tool call. Create actors for durable identity, serialized ownership, independent failure/recovery, or timers. ## 6. Commands, events, and idempotency Use command/event vocabulary rather than mutable agent prose. Example commands: ```text ProcessMessage AcceptSignal CreateWork ApproveDefinition ApproveDesign StartNextSlice RecordHarnessEvent CompleteAttempt StartVerification RecordVerificationCheck CreateRepairAttempt PublishPullRequest RecordHumanDecision CompleteWork ``` Example events: ```text SignalCreated SignalAttached WorkProposed DefinitionGenerated DefinitionApproved DesignGenerated DesignApproved SliceStarted AttemptStarted AttemptCompleted VerificationPassed VerificationFailed QuestionOpened QuestionAnswered PullRequestCreated WorkCompleted ``` Every side-effecting command MUST include an idempotency key. Suggested key: ```text :: ``` External artifact creation stores provider ID before transition completion to prevent duplicate PRs/deployments. ## 7. Effect service boundaries Keep domain/application code provider-neutral. ```ts interface HarnessRuntime { open(input: OpenHarnessInput): Effect.Effect prompt(id: string, content: string): Effect.Effect events(id: string): Stream.Stream approve(input: PermissionDecision): Effect.Effect abort(id: string): Effect.Effect close(id: string): Effect.Effect } interface SandboxRuntime { create(spec: SandboxSpec): Effect.Effect exec(lease: SandboxLease, cmd: Command): Effect.Effect readFile(lease: SandboxLease, path: string): Effect.Effect writeFile(lease: SandboxLease, path: string, body: Uint8Array): Effect.Effect pause(lease: SandboxLease): Effect.Effect resume(id: string): Effect.Effect terminate(lease: SandboxLease): Effect.Effect } interface SourceControl { prepareWorktree(input: WorktreeInput): Effect.Effect diff(worktree: Worktree): Effect.Effect commit(input: CommitInput): Effect.Effect push(input: PushInput): Effect.Effect createPullRequest(input: PullRequestInput): Effect.Effect } interface VerificationRuntime { execute(plan: VerificationPlan, env: EnvironmentRef): Effect.Effect } ``` Also define: ```text ArtifactStore | SecretBroker | EventJournal | PreviewRuntime | RuntimePolicy ``` Use `Layer` for adapters, `Scope` for leases/processes, `Stream` for events, `Schedule` for bounded retries, and supervised fibers for long-running consumers. Pin Effect version and isolate beta API churn. ## 8. FLUE responsibilities Use FLUE for domain-specific agents/workflows: - conversation response and Signal proposal; - Work Definition compiler; - impact analysis; - architecture/program design; - vertical-slice planning; - Resolver decision support; - verification-plan generation; - maintainability review; - result/learning synthesis. FLUE output MUST be typed proposals/commands, validated by application policy. FLUE MUST NOT directly: - mutate arbitrary database tables; - bypass actor lifecycle; - grant itself tools; - merge/deploy outside policy; - mark Work complete without evidence. ## 9. Harness strategy Harness is replaceable: ```text HarnessRuntime ├── OmpHarnessLive ├── OpenCodeHarnessLive ├── CodexHarnessLive ├── PiHarnessLive └── FlueHarnessLive ``` v0 selects one harness. Prefer mature coding harnesses for repository exploration/edit/test loops; use custom FLUE agents for product-specific reasoning. Zopu owns Work, branches, worktrees, budgets, approvals, artifacts, and completion. Harness owns one bounded implementation loop. ## 10. Runtime strategy ### CubeSandbox Best for full Linux execution: - native binaries; - Bun/Node/Python; - browsers; - databases/services; - project builds/tests; - pause/resume; - strong isolation. Use E2B-compatible SDK behind `SandboxRuntime`. OMP runs as a process inside the Cube microVM. ### AgentOS Best for: - lightweight durable agent environments; - ACP-integrated software; - actor-adjacent orchestration; - context/files/networking that fit runtime limits. Use an attached full sandbox when native/heavy tooling is needed. ### Persistent project machine Later optimization for long-lived caches, large repositories, and developer-customized environments. Use Git worktrees per active Work. Do not make it the only isolation boundary. ### Runtime selection The Resolver requests capabilities: ```text writable repo, Bun, browser, PostgreSQL, 8 GB RAM, network policy ``` `RuntimePolicy` chooses provider. Product logic never branches on Cube/AgentOS directly. ## 11. Repository isolation Initial safe model: ```text one project repository mirror one Git worktree per active Work/slice one mutating attempt per worktree ``` Rules: - attempts receive scoped worktrees; - parallel mutating attempts use separate branches; - credentials are short-lived and repository-scoped; - host home directories are never mounted; - model credentials are run-scoped; - untrusted code runs in sandbox; - output commits record base and candidate SHA. ## 12. Planning and design artifacts Required for standard work: ```text WorkDefinition ImpactMap DesignPacket VerticalSlicePlan VerificationPlan ``` Program design SHOULD include: - expected file-tree delta; - expected call-flow delta; - key types/signatures; - dependency direction; - invariants; - security/data boundaries; - known deviations. The verifier compares candidate code against this design, but metrics are evidence, not absolute truth. ## 13. Verification architecture Verification layers: ```text Static ├── format/lint/typecheck ├── dependency policy ├── secret scan └── static security Behavior ├── unit ├── integration ├── contract └── property tests where useful Product ├── browser/user flow ├── screenshots/video ├── accessibility └── visual checks Operational ├── build/start/health ├── migration/rollback ├── logs └── resource limits Design ├── expected vs actual files/interfaces ├── dependency graph delta ├── design deviations └── maintainability review ``` A `VerificationResult` MUST bind checks to candidate commit and environment. Repair loop: ```text failure evidence → bounded repair attempt → clean verification rerun ``` Tests added by the implementation SHOULD fail on the base revision and pass on the candidate when practical. ## 14. Delivery and integration Publishing order: ```text slice checks pass → integrated candidate created → impacted checks on integrated SHA → commit/push → PR → review package ``` Never create a “verified PR” from a different SHA than the verified candidate. Review package: - original intent; - approved definition/design; - slice narrative; - meaningful diffs; - screenshots/video; - verification evidence; - deviations/risks; - exact commit/PR. Manual merge remains policy in v0. ## 15. Preview and release Preview is an artifact, not an open random port. `PreviewRuntime` may use: - sandbox-exposed app; - agentOS Apps for compatible generated HTTP apps; - external staging/deployment. Production release requires explicit policy, rollout plan, health signals, and rollback trigger. ## 16. Security baseline - private control-plane endpoints; - authenticated Cube/Rivet APIs; - scoped runtime tokens; - no long-lived model/Git secrets in workspace files; - network egress policy; - artifact access authorization; - immutable audit trail for approvals; - tool allowlist per Kit; - destructive tools denied by default; - merge/deploy human-gated initially; - cleanup of terminated sandboxes and credentials. ## 17. Observability Record product-level events, not only infrastructure logs. Required dimensions: ```text projectId workId sliceId runId attemptId actorId kitVersion harness runtime model baseSha candidateSha ``` Track: - state-transition latency; - attempt duration/outcome; - retries/replans; - verification checks; - human wait time; - token/compute cost; - duplicate side effects; - abandoned/stale Work; - post-release failures. Raw harness logs are retained as artifacts; UI consumes normalized events. ## 18. Initial deployment shape ```text Web + API + Convex │ ▼ Bun/Effect daemon │ ▼ Rivet cluster/actors │ ├── FLUE agents/workflows └── SandboxRuntime └── CubeSandbox on dedicated/VDS host └── OMP + repo + tests ``` Keep Cube control APIs private; expose only authorized preview paths. Rivet and execution daemon may share the VPS initially but remain separate deployable processes. ## 19. Technical acceptance for v0 The architecture is proven when one real repository supports: ```text message → Signal → approved Work → approved Design Packet → one slice → isolated harness run → independent verification → verified commit → real PR → human response/resume ``` With: - durable recovery; - no duplicate Work/PR; - bounded retries; - exact evidence; - cancellation; - explicit terminal states.