Skip to content

Orgabot is in private alpha. Request access, or join our Discord.

← All documentation
Reference

Architecture

The repository's four independent subprojects, the framework source map, the two seams that must stay swappable, and the commands that gate a change.

Four independent subprojects, no root package

There is no root `package.json`: each subproject builds and tests on its own.

DirectoryWhat it is
framework/The TypeScript control plane and the orgabot CLI. Nearly all logic lives here.
app/The native macOS menu-bar voice app (Swift 6 / SwiftPM, OrgaVoice).
site/This marketing and documentation site (Vite + React 19 + Tailwind 4, Firebase Hosting).
orgabot-skills/Claude Code agent skills for operating Orgabot, installed by symlink.
# framework/
npm run build       # tsc -p tsconfig.json
npm run typecheck   # strict tsc --noEmit
npm test            # vitest run
npx vitest run test/reviewer.test.ts
npx vitest run -t "verification failure"

# app/
swift build && swift test

# site/
npm run dev         # vite dev server on :3001
npm run build       # tsc -b && vite build
npm test            # node --test

After changing framework source, npm run build && npm test in framework/ is the expected pre-commit gate.

The framework source map

PathResponsibility
domain/types.ts, events/events.tsCore entities and the append-only audit log
intent/Transcript normalization, intent parsing, project resolution
projects/The registry, with root-boundary defense; project memory and detection
broker/Policy-checked command execution: destructive-pattern refusal, redaction, egress
git/Real worktree/diff/commit (worktree.ts) and GitHub/PR operations (github.ts)
verify/gates.tsIndependent verification gates and the baseline-failure distinction
workers/The WorkerAdapter contract, the mock worker, the reviewer
workers/claudeCode/The Claude Code adapter, with stream parsing isolated in streamInterpreter.ts
orchestrator/planner.ts, the in-memory orchestrator, durable step functions, worker execution
orchestration/, missions/Routing, decomposition, objectives, persistence, follow-up, steering, recovery
organizations/, context/, analytics/Org state and authority, scoped context and memory, usage and budgets
lifecycle/The authoritative ADR 0055 mission lifecycle journal; every other mission record projects from it
workflow/The ADR 0062 engine: workflow definitions as data, the gate model and gate decisions, policy, promotion and release execution, event sinks, and pure timeline replay
opstore/The local SQLite operational store: read-only repositories, the durable change outbox, the store-only domain writers, and backup/restore
issues/, incidents/, firebase/Issue ingestion and observation, CI-failure triage, and the read-only Firebase App Hosting connector
restate/The durable workflow: durableCtx.ts, missionWorkflow.ts, binding.ts, server.ts
dashboard/, github/The ops dashboard and the GitHub webhook ingestion feeding it. dashboard/requestHandler.ts is guards then route table then 404; every endpoint lives in a family module under dashboard/routes/, and every page fragment under dashboard/ui/
cli/CLI entry points. orgabot.ts wires the process; cli/commands/ holds the command table and one module per family

The two seams that must stay swappable

`WorkerAdapter` (src/workers/adapter.ts). The mock worker and the real adapters are fully interchangeable under the orchestrator; a new worker plugs in here. The Claude Code adapter deliberately isolates brittle claude --output-format stream-json parsing in a pure, unit-tested streamInterpreter.ts, and spawner.ts is a narrow process interface so tests inject a fake claude rather than spawning one.

`DurableCtx` (src/restate/durableCtx.ts). The minimal durable-execution interface the mission workflow is written against. Restate is one implementation; the test fake is another. The orchestrator owns all mission, task, approval, and audit state, so the runtime only drives it.

Durability is proven, not asserted: resume tests assert that journaled steps do not re-execute (the worker is opened once, its cost is not re-charged) and that a mid-flight worker resume restarts at the exact next event index.

Conventions

  • ES modules ("type": "module"); relative imports carry the .js extension even from .ts sources (NodeNext). TypeScript is strict.
  • Tests are vitest under framework/test/, one file per unit, plus orchestrator.e2e.test.ts which drives the whole loop against real git and the real Node test runner.
  • Prefer pure helpers so tests need no real git or network. The Claude adapter has a file-writing fake, and a live test gated behind ORGABOT_LIVE_CLAUDE=1.
  • The dashboard HTML lives in String.raw templates in the fragment modules under src/dashboard/ui/, which src/dashboard/ui.ts concatenates in document order. A stray backtick in any of those templates breaks the entire CLI, so avoid backticks when editing a fragment. The order of the join is load-bearing: the page carries one browser script that is a single shared scope.
  • The dashboard is long-running and does not hot-reload; dashboard changes need a restart.

Per-repo operating reference

orgabot project init <project> generates an ORGABOT.md in the target repository: a capped, repository-controlled operating reference injected into every mission brief for that repo. It is context, not authority: it cannot grant tools, waive gates, or change policy.

Orgabot reads that reference as ORGABOT.md first and then ORKA.md, first match and never merged, so a repository that still carries the older ORKA.md keeps working with nothing to change. A repository that already has one is regenerated in place under the name it already carries: project init never adds a second reference beside an existing one. If a repository does end up carrying both, the newer one wins whole and orgabot doctor reports the duplicate.