Review past projects in code/traces.
UnderstandWrite summary of large project handling in Traces.
PlanShare summary to Traces platform.
SetupPrepare summary for social media posting.
VerifyI want you to go through the past projects in code/traces and write up a summary of how we handle larger projects in Traces
Once you're done, share to traces and I'll post this on social media
Here's the summary, written up and shared to Traces:
Share URL: https://traces.com/s/jn7cv65nqg078jp61bgs4h1my587dtcr
Over the past few months of building Traces, we've developed a consistent playbook for tackling larger features. It's not formal process for its own sake — it's a set of habits that keep a small team moving fast without breaking things. Here's how it works.
Before code, we write a project doc in docs/projects/. This isn't a vague RFC. It's a working document that lives with the code and gets updated as decisions change.
A typical project doc includes:
Examples: docs/projects/project-baton.md, docs/projects/namespace-improvements.md, docs/projects/share-to-traces-skills.md.
Every significant project gets its own git worktree under ~/code/traces-worktrees/. This means:
main stays clean and deployablemain are never blocked by in-progress workWe have a helper script (scripts/new-worktree.sh) that creates a worktree and sets up the branch. When a project doc references a worktree, it always includes the exact path.
We start at the lowest level and work up:
@traces/shared) — define the contract firstThis rule is encoded in our AGENTS.md:
"MUST: Start at lowest level — API, Types before frontend"
"NEVER: Change API, CLI, Frontend all at once unless permitted"
The benefit: each layer validates the one below it. By the time you reach the frontend, the types and API contract are already solid.
Large projects are never one big PR. They're a stack of small, atomic, independently mergeable PRs.
For example, the Namespace Improvements project shipped in 8 stacked PRs:
Each phase:
main after mergeWe use a rebase workflow: after PR N merges to main, rebase PR N+1 onto main, force-push, and retarget the GitHub PR.
We write failing tests before implementation. This is explicit in our project docs:
Phase 1: Tests (RED) — write tests that prove the desired contract
Phase 2+: Implementation (GREEN) — make them pass
Policy tests are the "source of truth" for access control. HTTP endpoint tests are minimal "wiring checks" that verify the policy is correctly hooked up. This means behavioral rules live in one place, and if you change a policy, you update one test file.
Test hygiene is strict:
feed_unauth_returns_public_onlyEvery project doc has atomic checklist items. Not "build the API" — that's too vague. Instead:
[ ] Add TraceRelationship and TraceRelationshipType in @traces/shared[ ] Expose relatedTo?: TraceRelationship on shared trace read types[ ] Map flat DB fields to nested shared relatedTo shape in API responses[ ] Add returns validators to all public queries touchedThese are concrete enough that an AI agent (or a human) can tick them off without ambiguity.
A golden rule: don't ship API + CLI + frontend changes in the same release unless explicitly permitted.
For example, the Share-to-Traces Skills project had four separate releases:
Each is revertible independently. If a CLI bug is found, you revert Release B without touching the API or frontend.
Some projects include a "failing test spike" phase — a branch with tests that intentionally fail. This locks in the expected behavior before implementation details are finalized.
From the Baton project:
"This phase is allowed to be a non-mergeable spike branch with failing tests."
This is a contract-first approach. Once the tests describe the desired behavior, the implementation becomes a matter of making them green.
When resuming a project after a break, the project doc and worktree location make it trivial to pick up where you left off. The doc is the baton. It contains:
This means weeks can pass between sessions on a project, and you can resume without re-reading the entire codebase.
Every project doc ends with exact verification commands:
There's no ambiguity about "how do we know this works?" The answer is in the doc.
When we started the Namespace Improvements project, the first thing we did was create docs/projects/namespace-improvements.md with locked decisions ("invite expiry: 7 days", "session switching mutates existing session"). Then we created a worktree at ~/code/traces-worktrees/feat-org-namespaces. Then we wrote the schema and shared types (PR #61). Then session switching with 20 tests (PR #62). Then invites with 41 tests (PR #63). Each PR was reviewed, merged, and the next was rebased. The frontend UI came last (PR #117), 6 PRs after the API work started.
The result: a complex feature (multi-tenant namespaces with invites, roles, and org creation) shipped incrementally, with no big-bang releases, and every intermediate state was deployable.
These aren't arbitrary rules. They emerge from a few core beliefs:
If you're building something with AI agents as teammates, this structure is even more important. Agents need context. A well-maintained project doc is context they can read and act on. A clean worktree is a sandbox they can work in without fear. Atomic phases are tasks they can complete. And stacked PRs are contributions they can make without overwhelming your main branch.
This is how we build Traces. If you're working on something similar, steal what works and ignore what doesn't. The best process is the one you actually use.