Skip to content

From an idea in a chat window to a repo the robot can build

A chat window is a good place to start a project. It is a bad place to keep a project.

The difference matters. In chat, you can describe the product, argue with the assistant, throw away weak designs, and find the shape of the thing. But if the result stays in scrollback, the next agent cannot reliably use it. The project has no source of truth, no audit trail, and no stable way to turn "build the next piece" into work that can be reviewed.

This project solved that problem in three steps:

  1. Use chat for exploration, then land the decisions as versioned docs.
  2. Put the docs, tickets, and code in a git repo so every change has a trail.
  3. Run work through an orchestrator so agents build from tickets, not from a vague prompt.

That is the on-ramp. It is not magic, and it is not specific to board games. The current repo happens to be a multi-device board-game platform, but the useful pattern is the process around it: durable context first, then ticket-shaped work, then a governed run loop.

Start in chat, then write the decisions down

The first pass can be conversational. For this project, the early questions were basic product and architecture questions: What does a phone do? What does the TV show? Where does private information live? What can a client be trusted to send? What is a game engine responsible for?

Those answers cannot live only in chat. In this repo they landed in ordinary files:

  • docs/overview/PROJECT_BRIEF.md is the architecture brief. It is where the project-level invariants belong: server authority, role-filtered views, device profiles instead of person accounts, and the broad shape of the app.
  • docs/overview/ROADMAP.md is the phase plan. It says what gets built in what order.
  • docs/overview/IDEAS.md is the parking lot. It keeps real-but-not-now ideas separate from committed work.
  • docs/overview/STRATEGY.md is business and positioning thinking, kept away from implementation contracts.

The exact filenames matter less than the split of responsibility. A future agent needs to know which file owns architecture, which file owns schedule, and which file is only a parking lot. If every decision is smeared across one long note, the agent has to guess which parts are current.

The repo config makes this explicit. workflow/project.config.json has paths.project_brief and paths.roadmap keys so the workflow knows where the project brief and roadmap live. The orchestrator does not have to infer the project's memory from a folder name; the path is part of the configuration.

This is the first useful conversion: chat becomes project state. The assistant can help draft it, but the important part is that the result is a file the next run can read.

Make the repo the contract

Once the decisions are files, the repo becomes more than a place to store code. It becomes the contract an agent works against.

Two layout choices matter early.

First, docs are partitioned by purpose. Project policy and architecture live under docs/overview/. Server guidance lives under docs/server/. Client guidance lives under docs/client/. Game-specific design lives under docs/games/<slug>/. Workflow machinery owns workflow/docs/.

That partitioning is practical. Tickets declare their edit surface in a ## Touches section. The batch planner and the cross-cut buckets in workflow/project.config.json use those paths to avoid running colliding work at the same time. A doc layout is not just tidiness when autonomous agents are editing it; it is scheduler input.

Second, the project separates the human planning checkout from the worker checkouts. The project rules name the two roots:

  • ~/source/boardgameui/ is the authoring clone, where chat-driven planning and ticket authoring happen.
  • ~/source/bgui/ is the ticket-clone root. Worker clones are created under it as ticket-<ticket-name> directories.

That split exists because mixing the two is a real failure mode. If a ticket run uses the same checkout where a person is editing plans, the agent can collide with half-finished human work. In this repo, workflow/project.config.json keeps paths.work_dir and paths.clone_base_dir pointed at ~/source/bgui so worker clones stay outside the authoring checkout.

The repo also carries the rules. CLAUDE.md and AGENTS.md tell agents what they may and may not do. One rule is especially relevant to the on-ramp: in a normal chat, the default response to a requested repo change is to draft a ticket, not to hand-edit main. That rule sounds heavy until you need to answer a simple question later: what was asked, what changed, what passed, and what did the agent learn?

Without the repo contract, those answers are buried in chat. With it, they are files.

Turn requests into tickets

The ticket is the unit of work. It is not a clever prompt. It is a small contract on disk.

A backlog ticket lives under tickets/backlog/. It carries frontmatter such as state: confirmed, priority:, group:, and agent hints. Its body names the goal, the reason, the context files to read first, the scope, the files it may touch, the acceptance criteria, and the verification commands.

The useful parts are concrete:

  • ## Context tells the implementing agent which files to read before writing.
  • ## Depends on makes scheduling explicit. If a ticket consumes another ticket's output, it names that predecessor.
  • ## Touches lists the path surface the work is allowed to edit.
  • ## Acceptance criteria says what must be true when the work is done.
  • ## Verification commands gives the exact commands the agent must run.

That shape changes the conversation. Instead of "AI, go improve the article," the repo can say: read these files, change these two paths, preserve valid frontmatter, update the DevBlog mirror, and run these three lints. The agent has a bounded job, and review has a bounded artifact.

Run records are the other half of the contract. A ticket run writes a sibling file next to the ticket, for example:

tickets/backlog/blog-refresh-from-idea-to-buildable-repo.md
tickets/backlog/blog-refresh-from-idea-to-buildable-repo.run.md

The run record says what happened: surprises, dead ends, prevention opportunities, verification, and outcome. That matters because the diff cannot tell you why the agent chose one path over another. Six weeks later, the run record is usually the fastest way to answer "what did this run learn?"

Let a deterministic orchestrator drive the loop

The live workflow in this repo is driven through the workflow dispatcher, workflow/scripts/dev.sh, usually reached through project-facing commands and the provider command files. The dispatcher owns the lifecycle around an agent: select work, spawn a disposable clone, run the implement stage, run review, ship, merge, archive, and clean up.

That distinction is important. The agent writes the change. The orchestrator controls the stage boundaries, state files, clone paths, checks, and merge flow. The project deliberately keeps that spine deterministic because the spine is where silent corruption is expensive.

A normal ticket run is not "one long chat that does everything." It is a set of bounded stages. The implement stage reads the ticket and writes the code plus run record. Review runs the configured preflight checks and review surfaces. Ship opens the PR. Merge waits for green checks and handles the final merge path. State is written under .state/ while the run is live, and the durable summary lands in the ticket's .run.md sibling.

The review configuration is not generic advice. In this project, workflow/project.config.json lists the always checks, soft checks, and client-changed checks. The ticket itself can also name exact verification commands such as:

bash scripts/dev.sh lint-doc-tags docs/blog/from-idea-to-buildable-repo.md docs/devblog/from-idea-to-buildable-repo.md
bash scripts/dev.sh lint-devblog-mirror
bash scripts/dev.sh lint-ascii docs/blog/from-idea-to-buildable-repo.md docs/devblog/from-idea-to-buildable-repo.md

That is the practical move from "an AI wrote something" to "the project accepted the work." The agent does not get to decide that the work is good because the prose sounds finished. The repo has checks, and the orchestrator runs them.

Where Tempo fits

The current workflow grew inside this repo as shell scripts and project-specific contracts. Tempo is the Go port and product surface being built beside it.

That status needs to be stated carefully. Tempo is real code: tempo/main.go defines commands such as bootstrap, codemap, backlog-list, status, ticket, run, review, ship, group-run, and parity. It also embeds starter assets under tempo/assets/bootstrap/ and exposes tempo bootstrap to write starter workflow docs, config, and codemap defaults into another project.

Tempo also carries the same boundary discipline as the shell workflow. Its codemap and analysis engines are Python, but they run through a tempo-owned runtime. Its live ticket adapter is opt-in: by default, tempo ticket uses a deterministic static runner so tests do not depend on paid model calls. When a real engine is selected with --engine, the adapter requires the engine to end with a machine-readable TEMPO_RESULT line containing fields such as terminal_state, outcome, and cause.

The parity story is equally explicit. tempo parity compares ported surfaces against committed golden output and lists known gaps. The current parity code covers read surfaces and deterministic lifecycle-decision surfaces with fake agent, git, and GitHub layers. It does not claim that live bash ticket/review/ ship execution, real agent output quality, GitHub merge behavior, or notification delivery are fully covered by parity.

That makes Tempo a good example for this article. The on-ramp is no longer only a set of hand-built files in one repo; it is being packaged into a command that can bootstrap another project. But this repo still says where the line is: current project execution continues through the workflow dispatcher, and Tempo's coverage grows by named surfaces instead of by pretending the port is finished.

What this setup does not give you

It does not remove setup cost. You need project rules, a brief, a roadmap, runtime config, ticket templates, review checks, and clone conventions. For a throwaway weekend script, that is too much machinery.

It does not keep docs fresh by itself. The repo has rules and checks that make drift visible, but a stale brief is still dangerous because agents will treat it as context. Durable context has to be maintained.

It does not remove the need to judge the result. The orchestrator can make work reviewable. It cannot make the product decision for you. If you cannot tell whether the behavior is right, shipping it faster is not automatically progress.

It also does not mean every project needs this exact scaffold. The transferable part is smaller: keep decisions in versioned files, make work ticket-shaped, separate planning and worker clones, run checks through a deterministic orchestrator, and write down what happened.

That is enough to change what the AI is doing. It is no longer only answering in a chat window. It is reading the repo, executing a ticket, leaving a diff, and recording the run. That is the point where an idea becomes something the robot can build.