Two Birds Innovation System architecture

What runs, and what talks to what.

The working map of the stack behind the products. One operator, four machines, no team.

Manually updated, last touched 2026-10-03. On 2026-09-28 each status below was checked against the task scheduler, logs, ports and repository. On 2026-10-03 only these were re-checked: the m73 fleet rows, the intake and transcribe task results, the Kokoro port and the ADR count; every other row still reflects 2026-09-28. This is a dated snapshot, not an automatically refreshed status feed.

← Back to the case study
Status key running, verified running, degraded not running planned / not built

Signal flow

CaptureVoice, phone, inbox, browser. Input arrives asynchronously and is never trusted to be complete.
QueueEverything lands as a durable row or file first. Nothing is processed in the same breath it is received.
Orchestrate: Symphonica(Multi-Harness Build Orchestrator)Routes coding work across Claude Code, Codex, OpenCode Go and Antigravity by real-time capacity, so work keeps moving when one tool hits a usage limit, then reviews and lands the result automatically. Built in-house; not yet trusted for unattended use.
VerifyGates run before anything is called done. A failed gate blocks the claim, not just the log.
PublishStatic output to Pages. Git is the transport; there is no deploy server.

Components

Manually updated, last verified 2026-09-28 (partial re-check 2026-10-03, see the note at the top). Not a live feed.

Capture

Voice input local

Dictation into the CLI. Primary interface — most work starts spoken, not typed.

Kokoro TTS :8880

Local speech synthesis. Not running: nothing is listening on port 8880 on the primary host (checked live 2026-09-28). The designated always-on host was not rechecked this pass.

Magpie telegram

Idea intake from phone. Both intake channels (Telegram and Gmail) reported status ok in the 15:10 run on 2026-09-28, with nothing to process. On 2026-09-28 the scheduler's last result for the task showed a refused start (RI-052); on 2026-10-03 its last run (02:10) returned result 0. RI-052 stays open until the cause is confirmed.

Perch capture

Raw video capture with local transcription. The transcribe job is now registered and its watcher logged "no pending captures" at 15:05 on 2026-09-28. On 2026-09-28 its last scheduler result was a refused start (RI-052); on 2026-10-03 its last run (02:05) returned result 0. RI-052 stays open until the cause is confirmed.

Orchestration

Claude Code 4 hosts

One of the engines in the execution layer, and the one that orchestrates and judges. Same repo, same rules file, different machines. Sessions are stateless; the repo is the memory. Honest fleet state, from the 2026-10-02 drift probe: this laptop is current; the always-on Linux host (m73) was brought to origin on 2026-10-02 and was 12 commits behind again by that afternoon, because its GitHub login is invalid and it can only be updated by hand; one machine was offline and one refused the probe; the overnight supervisor was last reported disabled or missing on the EliteBook and the ThinkPad.

Symphonica Building(Multi-Harness Build Orchestrator)

Routes coding work across Claude Code, Codex, OpenCode Go and Antigravity (Gemini) by capacity, so work keeps moving when one tool hits a usage limit. Heavy unattended work is deliberately kept off the primary paid accounts (policy filed 2026-09-21). The routing gateway (OmniRoute) answers on the always-on host. The unattended loop is not yet trusted: last night it attempted 0 sprints because every runnable sprint was blocked by a safety gate, and an Antigravity run hit a prepaid-credit wall on 2026-09-21.

Model routing

The orchestrating model decides; cheaper models execute work whose shape is already determined; the tier is chosen per unit of work, not per session. Since 2026-09-21 a written policy keeps heavy or autonomous execution off the primary paid accounts and routes it through other subscriptions.

Native dynamic workflows decided 2026-09-21

Chosen on 2026-09-21 as the primary single-harness orchestrator after a written review of Orca, Hermes Agent, Omarchy, Goose and Ruflo, none of which cleared the stack's locked constraints.

Codex headless dispatch ChatGPT seat

Runs a sprint on a separate ChatGPT-authenticated engine inside a throwaway clone, so a bad run cannot touch the live repository. Proven end to end; results are never auto-merged.

Antigravity / Gemini SDK

Runs headless sprints through Google's agent SDK; several ran 2026-09-21 to 2026-09-24. Not free: it draws a prepaid balance and hit an HTTP 402 credits-depleted wall on 2026-09-21. Not usable on the primary laptop today because no API key is set there.

OpenCode Go browser route

Multi-model subscription route, authorised only for browser-driving tasks. Browser dispatch failed three distinct ways in one night on 2026-09-24 (RI-044); a persistent authenticated profile was built afterward.

Agent browser hidden, persistent profile

A dedicated, already-signed-in Chrome profile kept alive by a scheduled task, so automation can drive real sites without spending model tokens on a visible browser. Running 2026-09-28; its window is parked off-screen.

Direct Drive upload since 2026-09-27

Files go to Google Drive straight from disk with the existing OAuth tokens, not through a model's context. Replaces a base64 route that was slow and costly.

NotebookLM link MCP

Not connected. The login-detection fault after Google's rebrand to notebook.google.com was traced to the upstream tool and swapped for a patched fork on 2026-09-28; the server still timed out on connect in the session that followed (RI-050).

Sprint queue markdown

A flat file is the work queue. An instruction that is not a queue entry does not execute, which is a failure mode this stack has hit repeatedly.

Subagents

Scoped roles for review, briefing, and job tailoring. Dispatched with a durability clause so partial work survives a session cap.

Fleet resource guard m73

Out-of-memory prevention daemon on the Linux box, live-fire tested 2026-08-23 (terminated a deliberate 4.3GB test allocation; journald evidence recorded). Windows-side rollout is staged, not yet installed.

Scheduled work

Overnight build daily 02:00

Lighthouse, health checks, freshness. Ran 2026-09-28 at 02:00 with task result 0 and a build-complete commit at 02:07. The August task-terminated pattern has not recurred.

Talon daily 06:00

Job scan, scoring, and archive of full postings. Daily scan committed 2026-09-28; the scheduled task ran clean (result 0) the same afternoon. Writes a tracked health record every run.

Cloud agents gh actions

Scheduled cloud runs failed for five days in August on a missing credential, fixed 10 Aug. Not verifiable today: the CLI could not read the run list, and the health check flags its own alarm record as 9 days old, so its "ok" cannot be trusted.

Heartbeat registry

Built since the last update, and only partly working. A capability registry and heartbeat files now exist; the 2026-09-28 health check reports 10 of 24 heartbeat-checked capabilities unprovable or dead. Absence of a heartbeat should alarm; for those ten it does not yet.

Data spine

Git markdown source of truth

Session state, sprint queue, job pipeline, incident ledger, decision records. Plain files, versioned, greppable, no database to lose.

Notion mirrored

Human-facing backlog and idea vault. Read through nightly markdown mirrors so a plan downgrade cannot break reads.

Decision records

81

Cloudflare D1

First relational store in the stack, for a product that cannot be static. Schema written, not deployed.

Verification

Session health check

65 checks at session start (2026-09-28 run), each marked ok, warn or flag. Its own blind spot is documented: it once folded non-critical workflow failures into an OK line, and it read a dead task as a "stale log".

Live-outcome gate

Playwright against the live URL. A product sprint cannot be marked done on a green build alone; it needs proof from production.

Wiring audit

Checks that credentialed capabilities are actually invoked. Reported 7 orphaned capabilities on 2026-09-28. Its definition of "wired" is a substring match against prose docs, so it can report green on something that never runs.

Incident ledger

52 numbered reliability issues with root causes; 40 still open. A nightly check now reads the open items, which closes the gap earlier versions of this page named. An independent review found one recurring shape in a minority of them (7 of 52): a fix at the source that never reached what was built from it.

Surfaces

Command Deck cf pages

One permanent URL for current state. Regenerated from source each deploy and discards what is stale — a view, never a log.

Products static

Accessibility-first training platform, business diagnostic, job-search tooling, civic rental tool. All flat files on Pages.

Nudge poc

Single-file client-only app. Reminders written as calendar events because a static host cannot run a schedule.

Always-on host

A small Linux box that takes the gateway and the resource guard off the laptop. It exists and answers. Its checkout was reconciled on 2026-10-02 (it had been over a thousand commits behind) and its overnight supervisor timer is now enabled, but the loop is idle, so it is not yet carrying scheduled jobs. It was 12 commits behind again that afternoon: its GitHub token is invalid, so it drifts until someone replaces it.

How they talk

One rule holds the whole thing together: every hand-off is a file or a row, never a live call between components. A producer writes and exits. A consumer reads on its own schedule. Nothing waits on anything, so a dead component leaves visible evidence instead of a hung process.
FromToInterfaceWhy this way
TelegramIdea vaultpoll → JSONL → API Poll-and-exit, not a long-lived listener. A listener has no home in a run-and-exit scheduler, which is exactly how this one died.
Job boardsPipelineATS JSON → markdown row Public ATS endpoints read directly, bypassing JS-walled listings. The flat file is authoritative; the dashboard is a render of it.
Any jobHealth checktracked JSON record Liveness is proven by a timestamp that stops advancing, never inferred from inside the pipeline being checked.
RepoCommand Deckbuild script → static HTML Regenerated per deploy so the page cannot drift from source. A stale render is impossible by construction.
NotionAgentsnightly markdown mirror Reads go to the mirror, writes go to the API. Survives plan changes that would otherwise remove bulk-query access.
SessionNext sessionstate file + git log No shared memory between sessions or machines. Continuity is a file that every model, on every host, can read cold.
BrowserForm endpointthird-party POST Static hosting means no server to receive a form. CORS-safe third parties fill the gap rather than adding a backend.
AppPhonecalendar file A static host cannot run a schedule or send mail, so the reminder is handed to the device's own calendar to fire.

Constraints the design answers to

Static by default

No servers in the critical path. A backend is introduced only with a filed decision record saying why, and scoped to one product.

Sovereign by default

Local or open-source first. Every paid dependency is named individually rather than assumed, so the exit path stays known.

One operator

Anything requiring a human is a bottleneck of one. Work that a script or an agent can do is never queued for a person.

Evidence over assertion

"It runs automatically" is proven by the scheduler, not the repo. This map was built that way, which is why three components are red.