Files
zopu-code/docs/TECH.md

16 KiB

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

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

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:

packages/
├── signals/
├── work/
├── design/
├── planning/
├── kits/
├── resolver/
├── verification/
├── artifacts/
├── results/
├── knowledge/
├── runtimes/
├── harnesses/
└── integrations/

Each domain SHOULD separate:

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:

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

Proposed
→ Defining
→ AwaitingDefinitionApproval
→ Designing
→ AwaitingDesignApproval
→ Ready
→ ExecutingSlice
→ VerifyingSlice
→ AwaitingSliceReview
→ IntegratedVerification
→ Review
→ Releasing
→ Observing
→ Completed

Side/terminal states:

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:

ProcessMessage
AcceptSignal
CreateWork
ApproveDefinition
ApproveDesign
StartNextSlice
RecordHarnessEvent
CompleteAttempt
StartVerification
RecordVerificationCheck
CreateRepairAttempt
PublishPullRequest
RecordHumanDecision
CompleteWork

Example events:

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:

<workId>:<commandType>:<logicalVersion>

External artifact creation stores provider ID before transition completion to prevent duplicate PRs/deployments.

7. Effect service boundaries

Keep domain/application code provider-neutral.

interface HarnessRuntime {
  open(input: OpenHarnessInput): Effect.Effect<HarnessSession, HarnessError>
  prompt(id: string, content: string): Effect.Effect<void, HarnessError>
  events(id: string): Stream.Stream<HarnessEvent, HarnessError>
  approve(input: PermissionDecision): Effect.Effect<void, HarnessError>
  abort(id: string): Effect.Effect<void, HarnessError>
  close(id: string): Effect.Effect<void, HarnessError>
}

interface SandboxRuntime {
  create(spec: SandboxSpec): Effect.Effect<SandboxLease, SandboxError>
  exec(lease: SandboxLease, cmd: Command): Effect.Effect<CommandResult, SandboxError>
  readFile(lease: SandboxLease, path: string): Effect.Effect<Uint8Array, SandboxError>
  writeFile(lease: SandboxLease, path: string, body: Uint8Array): Effect.Effect<void, SandboxError>
  pause(lease: SandboxLease): Effect.Effect<void, SandboxError>
  resume(id: string): Effect.Effect<SandboxLease, SandboxError>
  terminate(lease: SandboxLease): Effect.Effect<void, SandboxError>
}

interface SourceControl {
  prepareWorktree(input: WorktreeInput): Effect.Effect<Worktree, GitError>
  diff(worktree: Worktree): Effect.Effect<DiffArtifact, GitError>
  commit(input: CommitInput): Effect.Effect<CommitArtifact, GitError>
  push(input: PushInput): Effect.Effect<BranchArtifact, GitError>
  createPullRequest(input: PullRequestInput): Effect.Effect<PullRequestArtifact, GitError>
}

interface VerificationRuntime {
  execute(plan: VerificationPlan, env: EnvironmentRef):
    Effect.Effect<VerificationResult, VerificationError>
}

Also define:

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:

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:

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:

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:

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:

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:

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:

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:

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

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:

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.