A team on one feature (shared feature lanes)¶
Most day-to-day work in TOVIO is trunk-based: you land
stacked changes straight
onto main, and most of what Git would call "feature branches" simply disappear. But sometimes a
team needs to build one large feature together, off to the side — kept out of main until it's
cohesive enough to ship into a release. And several teams may be doing exactly that, each on a different
feature, at the same time.
That is a shared feature lane, and TOVIO makes it a first-class, low-friction pattern — because a lane is just a shared landing target, not a workspace anyone has to "be on." This guide shows how two developers (or a whole team) collaborate on one feature in isolation, how several such teams run in parallel, and how a finished feature is promoted into a release.
Built and tested; release evidence remains open
The offline single-developer pieces (commit, land, lane, stacks) run on the core today.
Sharing a lane across a team — sync, the Forge, lane protection, proposals — is built and passes
its hermetic --features tls test suite. Production binaries passed the distinct-Docker-host exercise
under a real operator CA; public-release, broader HA/load, hosted-parity, and external evidence remain
Phase 5 gates.
When to reach for a feature lane
Prefer trunk + feature flags + short stacks when you can — it carries the least integration debt.
Reach for a shared feature lane when a feature is (a) genuinely multi-developer, (b) not safe to
expose on main incrementally even behind a flag, and (c) meant to land into a release as a unit.
The shape¶
A feature lane (feature/payments) is a shared landing target the whole feature-team lands onto —
the feature's own integration line, isolated from main:
flowchart LR
subgraph TEAM[" Payments team "]
A["Alice<br/>chg:a1 → chg:a2"]
B["Bob<br/>chg:b1"]
end
A -. "land --into feature/payments" .-> FB(["feature/payments<br/>(shared integration line)"])
B -. "land --into feature/payments" .-> FB
FB == "promote when ready" ==> M(["main → release/2.5"])
classDef ptr fill:#eef,stroke:#557;
class FB,M ptr;
- Each developer still works in their own changes (stacks welcome). They just land onto
feature/paymentsinstead ofmain. - The feature stays off
mainuntil the team promotes it —mainnever sees the half-finished feature. - Other teams do the same on their own lane (
feature/search,feature/inventory), in parallel, without stepping on each other.
1. Create the feature lane¶
tovio lane <name> creates a lane at the current tip, so switch to trunk first:
$ tovio switch main
$ tovio lane feature/payments # a shared landing target, cut from trunk
$ tovio sync # publish it so the team can land onto it
Keep the gate light on a feature lane so the team moves fast, while main and release/* stay
strictly protected. Protection lives in the policy manifest and is declared with tovio policy
protect (lane protection):
$ tovio policy protect main --require-review --min-approvals 2 --required-checks build-check,semantic-check
$ tovio policy protect "feature/*" # conflict-free only: stay buildable, no review or CI ceremony
Read back, the manifest carries one protected_branch block per pattern (the on-disk vocabulary keeps
the word branch):
# strict on main; lighter on the feature line
[[protected_branch]]
pattern = "main"
require_conflict_free = true
required_checks = ["build-check", "semantic-check"]
# (require_review: min_approvals = 2 — main becomes Forge-advanced only; cleared-reviewer coverage also applies)
[[protected_branch]]
pattern = "feature/*"
require_conflict_free = true # stay buildable, but no review/CI ceremony to land here
An unprotected feature lane is also fine — you can even land changes that still carry conflicts onto it, since only a protected lane requires conflict-free (land).
2. Each developer's loop — land onto the feature, not main¶
Everyone keeps their normal everyday loop; the only difference is the land target:
# ...edit... (auto-tracked; a change opens automatically — no `add`)
$ tovio commit -m "add Stripe webhook verifier" # finalize your change → chg:xxx
$ tovio land my-lane --into feature/payments # land onto the FEATURE line, not main
$ tovio sync # share; teammates pull it
Because lane refs are CRDTs, two developers landing onto feature/payments at the same moment
converge — never "rejected" or "diverged history." A genuine content overlap becomes a stored
conflict object that someone resolves once, not a blocked push. And
landing the base of a stack cascades the rebase to the changes above it, Change IDs
preserved.
Build directly on a teammate's in-flight change
Bob's UI depends on Alice's not-yet-landed API change? He stacks on it and syncs; TOVIO records the
dependency. If a teammate's change upstream of yours still has an unresolved conflict, tovio sync
--isolate builds you against the last-known-clean version and re-materializes when their
resolution syncs — so nobody on the team is ever blocked by anyone else's conflict. See
Team workflows §10 and clone & sync.
3. Keep the feature current with trunk (manage the drift)¶
A feature lane that sits still while main moves accrues integration debt. Periodically fold trunk's
progress into the feature. There is no separate merge verb — tovio land integrates one lane into
another, storing (never throwing) any conflict:
$ tovio land main --into feature/payments # bring trunk's advances into the feature line
# resolve any conflict ONCE — the resolution travels with the change and won't come back
Your own lane, cut from feature/payments, tracks it as its upstream: auto-sync folds the feature
lane's advances into your lane automatically whenever that merge is conflict-free
(clone & sync). The longer a feature diverges from trunk, the more the fold costs —
which is why the idiom is to keep features short-lived and land trunk in often.
4. Several teams, several features, in parallel¶
Running many at once needs nothing special:
flowchart LR
M(["main (trunk)"]) --> FP(["feature/payments"])
M --> FS(["feature/search"])
M --> FI(["feature/inventory"])
FP == promote ==> R(["release/2.5"])
FS == promote ==> R
classDef ptr fill:#eef,stroke:#557;
class M,FP,FS,FI,R ptr;
- Each feature has its own lane (its own CRDT ref), so a land on one never collides with another.
- The path-scoped land cascade means a land only rebases descendants whose file-set overlaps — payments and search, touching different areas of a monorepo, don't thrash each other. (See Branching workflows.)
- Optionally scope each team's code or secrets by path with a read policy, so only that team can read them — the same repo, safely partitioned (Permissions).
- An AI agent on a feature gets a capability token scoped to that feature's paths and lane, so it can't wander into another team's work.
5. Promote the finished feature into a release¶
When the feature is done, you integrate it forward — onto main, then through your
environment / release flow. You don't lose the history: every
change keeps its stable chg: id, so the promotion is fully traceable.
A review-required main is advanced only by the Forge — no client, not even a local tovio land
--into main, can publish it. So the promotion goes through a proposal: push the feature lane, propose
its tip change onto main, collect the approvals the manifest requires (including a cleared reviewer for
any protected path), and the Forge lands it.
$ tovio sync # publish the feature lane's tip
$ tovio change propose chg:a2 --target main --remote forge.example.dev:7743
# ...CI posts build-check + semantic-check; two eligible reviewers approve
# (`tovio review chg:a2 --approve --proposal prop:… --remote forge.example.dev:7743`)...
# ...the Forge lands the approved proposal (its dashboard and GitHub-compatible merge both drive that step)...
$ tovio sync # bring the advanced main down
$ tovio land main --into release/2.5 # promote forward into the release line
$ tovio tag v2.5.0 # immutable release marker
- The strict
main/releasegate refuses a conflicted or non-buildable set, so a half-finished feature cannot slip into a release (lane protection). - Any conflict you already resolved once on the feature lane re-applies on promotion — you don't re-resolve it (the conflict algebra).
- After promotion the feature lane has done its job: delete it (
tovio lane --delete feature/payments, fully undoable), or keep it to backport a fix (the samechg:id lands onrelease/2.5andmain, traceably).
Caveats & the idiomatic recommendation¶
- Long-lived feature lanes accrue integration debt. TOVIO lowers it (auto-rebase cascade, resolve-once conflicts, stable IDs, conflict-free auto-integration) but doesn't repeal it.
- Prefer trunk + feature flags + short-lived lanes. Reach for a shared feature lane when a feature genuinely must stay off trunk until it's a releasable unit — then land trunk in often and promote as soon as it's cohesive.
mainandrelease/*stay strictly protected; a feature lane can be lightly gated (or unprotected) so the team moves fast.
Where to go next¶
- Team workflows & diagrams — the visual map of clone → change → review → land → release.
- Lane protection — configure the per-lane gate (strict for
main, light for a feature). - Propose and review — the proposal + redacted-review flow used to promote a feature.
- Branching workflows — environments, releases, and the Git-Flow mapping.
- Checking in: change vs lane — why
commit(the change) andland(the lane) are two separate verbs.
Last reviewed September 9, 2026
Suggest an improvement to this page Not for security reports — see disclosure