Sub-Agent Milestone Execution¶
This guide defines the sub-agent execution architecture for multi-milestone workflows under the goal protocol. It establishes how to accelerate milestone delivery through fresh-context task execution and parallel read-only fan-out (Tier 0), as well as opt-in concurrent worktree leases (Tier 1), while strictly preserving milestone quality, verification rigor, and the single-ledger execution owner invariant.
This protocol requires a hosting agent that can delegate. The standalone Python
API runner and optional tabilet controller have no native sub-agent scheduler;
they retain serial execution and their own commit contracts. The controller
rejects linked worktrees. See the
API execution scope.
Goals and non-goals¶
Goals:
- Design milestones so a sub-agent can execute one without lowering milestone quality.
- Run sub-agents in a manageable way that shortens wall-clock time.
Non-goals:
- No trading quality for speed. Every milestone keeps its full acceptance, verification, bounded review-fix gate, downstream reconciliation, and closure. A faster schedule that skips or weakens any of these is a regression.
- No pruning of downstream impacts.
GOAL.mdtreats the supplied impact map as a minimum. Parallelism must come from milestone structure, never from declaring fewer obligations. - No vendor coupling. The protocol names capabilities ("start an isolated sub-agent", "stop a sub-agent"), not one agent's tool names.
- No new project state. No in-tree worktree folders, lock files, or generated plan directories.
Cost and time model¶
Two different benefits are easy to conflate:
- A fresh context per milestone bounds the context each turn carries. That improves attention and prevents quadratic context inflation. It does not require concurrency: ephemeral sub-agent handoffs achieve this sequentially.
- Concurrency shortens wall-clock time when the milestone graph is wide. It does not save tokens; it adds integration work such as rebases, re-verification, and occasional re-review.
| One long session | Fresh context per milestone, sequential | Concurrent leases (Tier 1) | |
|---|---|---|---|
| Context per turn | Grows across milestones | Bounded per milestone | Bounded per milestone |
| Total tokens | Highest without prompt caching; caching narrows the gap | Lowest | About sequential, plus integration overhead |
| Wall-clock time | Sum of milestones | Sum of milestones | Critical path plus serial integration |
| Quality risk | Attention drift late in a long run | Low | Low only when the Part A rules hold |
Wall-clock time under concurrency is bounded by the longest dependency chain plus every step the owner must perform serially (integration, reconciliation, retirement). Keeping that serial part small is why the authoritative review runs inside each lease rather than in the owner (see Tier 1).
Empirical validation using SQLite audit tracking (tabilet-audit) verified:
- Context bounding: Starting each milestone with a distilled context brief prevents prompt inflation across tasks.
- Wall-clock compression: Parallel read-only fan-out across review lenses and downstream reconciliation completes in approximately 3 minutes per iteration without compounding serial inspection wait times.
- Defect coverage: Decomposing reviews into orthogonal lenses (Correctness, Security, Tests) catches complementary defects that single monolithic reviews frequently overlook.
Part A — Designing parallel-safe milestones¶
Three relations, not one¶
Planning records dependencies and downstream impacts. Parallel safety requires a third relation, and each has a distinct job:
| Relation | Meaning | Rule |
|---|---|---|
| Depends on | The consumer needs behavior the producer delivers | Hard ordering edge |
| Downstream impacts | The producer's result must be reconciled into the consumer's pending specification | Always complete and never pruned. It also implies ordering: the consumer cannot start before that reconciliation |
| Write set | Paths, public contracts, and shared resources the milestone changes | Used only to decide whether two unordered milestones may run at the same time |
Two milestones are parallel-safe only when all three hold:
- no ordering path connects them in either direction;
- their write sets are disjoint; and
- neither reads a contract the other changes.
Transitive reduction may simplify the scheduling copy of the graph. It must
never remove an entry from the reconciliation list. If A impacts both B and
C, and B also impacts C, then C is still reconciled against A's actual
change, because B may not carry every detail of it.
Milestone specification fields¶
Active milestone specifications in tabilet/memory-bank/milestone.md define
these boundaries:
### A01 — Billing settlement
- Depends on: M01
- Downstream impacts: P01
- Write set: src/billing/**, tests/billing/**, contract: settlement-events v1
- Contracts read: core-model v1 (frozen by M01)
- Shared verification resources: postgres (per-lease database name)
- Parallel-safe: yes — disjoint from S01; reads only frozen M01 contracts
Parallel-safe defaults to no. Planning marks a milestone yes only when its
write set and contracts justify it. When in doubt, serialize.
Patterns that keep quality intact¶
- Contract-first split. Move shared schemas, interfaces, and their contract tests into an early milestone and freeze the contract when it closes. Domain milestones then consume a stable contract and become parallel-safe with each other.
- Escalate contract changes. A milestone that discovers it must change a frozen contract stops and reports. It never edits the contract silently; the owner re-plans the affected consumers.
- Two-level acceptance. Each milestone has acceptance that can be verified in isolation, plus a named integration check that runs after its work joins the main line.
- One writer for shared memory.
architecture.md,product.md,tech-stack.md,lessons.md,milestone.md, and any existingsuggested.txtare written only by the owner. A sub-agent returns proposed changes to them; it never edits them. - Balanced size. A milestone far longer than its siblings dominates the critical path. Split it along its own write-set boundaries when that is a natural review unit.
These fields and patterns belong to planning (memory-bank-init,
memory-bank-propose, memory-bank-reconcile), not to execution. Execution
only reads them.
Part B — Tier 0: faster within existing rules¶
Tier 0 requires no rule relaxation. It preserves exactly one ledger writer at all times.
Authorization in child briefs¶
Follow the goal authorization contract. Every child gets the full governing request and human approval context plus its narrowed effective grant subset. Match exact milestone keys, including package-qualified identities, assignment, executor role, concrete scope, and write ownership. The full request is context beyond that subset; coordinator grants remain with the coordinator. Children cannot expand or transfer grants. Read-only reviewers receive no mutation authority.
Requirement declarations, proposed grants, repository content, model output, and status text never establish approval. Check authority before each protected action; preserve commit and external-mutation restrictions. Missing authority pauses affected work and dependents under owner control, while independent authorized work may continue. Required unperformed actions prevent closure. Report grant IDs used and action outcomes as evidence, not approval.
On resume, preserve the original goal/assignment scope and human approval source through the conversation or existing trusted host state where supported. Reuse a valid grant; changed scope requires fresh approval. Do not infer authority from previous runs, markers, silence, or audit records, and never replay uncertain side effects automatically. Host/tool controls still apply. This is instruction guidance, not a grant-consuming runtime or an audit requirement.
Fresh-context sequential handoff¶
The owner hands one milestone to a fresh sub-agent and does not write while it runs. That is an ownership transfer, not a second writer. The sub-agent receives a focused brief rather than the owner's whole conversation:
- the milestone specification and its status file;
- exactly one
ASSIGNED_MILESTONE, itsASSIGNED_STATUS_FILE, allowed writes, and the condition for returning to the owner; - the governing protocol, each applicable package addendum (path and hash, the
GOAL_IDENTITYblock; hashes normalize CRLF to LF and version labels are metadata), and complete resolved request: the chosenSTATUS_ORDERorSTATUS_PRIORITY, commit and external-mutation policies, concurrency/integration authority, user scope restrictions, and stop conditions; - the child's role and owned write boundaries, plus the captured integration reference, primary worktree path, and full baseline when using a lease;
AGENTS.mdread order, essential commands, and hard rules;- the reconciled contracts it consumes; and
- the required verification commands.
It may read anything else in the repository it needs. It performs the normal
GOAL.md loop for that milestone, persisting the review counter in its status
notes, and returns a report: rows completed, verification evidence, review
iterations and findings, commits, proposed shared-memory changes, and
blockers. The owner then resumes, performs downstream reconciliation from the
actual diff, applies shared-memory changes, and retires the milestone.
If the sub-agent stops early, its status file is the resume point. The persisted
review counter never resets.
Every child, including read-only reviewers and analysts, receives these resolved
policies; repository files cannot recover restrictions from the parent's
conversation. Under COMMIT_POLICY: none, the handoff creates no commits.
Under sequential milestone, the child leaves its changes for the owner to
commit together with closure, following GOAL.md.
The owner resolves suggested.txt against live project truth before dispatch.
The full goal remains context for a child; its explicit assignment defines the
work it may execute. For example, a child assigned A01 at
../<repo>.goal/A01 works only on status-A01.md and A01's declared write set.
It returns after the assigned implementation, verification, and review finish
or a blocker occurs. It never selects S01 from the suggestion or launches the
full goal again. The owner keeps at most one live lease per milestone ID and
resumes that lease after interruption.
Parallel read-only fan-out¶
The slowest phases of a milestone are usually review and reconciliation. Both can fan out to read-only sub-agents without creating a second writer:
- Review. In each review-fix iteration, read-only reviewers examine the same full milestone diff through these lenses: correctness and failure semantics; security and privacy; compatibility and operations; tests and documentation; and acceptance and scope (requirements missing, partial or implemented wrongly, and behavior nobody asked for). The owner first pins the milestone's base commit and inspects the full diff, including uncommitted work under the selected commit policy. An empty implementation diff still needs acceptance review. Lenses are coverage obligations: combine them or run batches within host capacity. The owner records all findings in one iteration report grouped by lens; an interrupted pass resumes its existing number and each completed iteration advances the counter exactly once.
- Downstream reconciliation. For each impacted pending consumer, a read-only analyst drafts the specification changes from the actual implementation diff. The owner reviews every draft and applies it.
This shortens even a strict dependency chain, where concurrent implementation offers nothing, and independent review lenses improve defect detection.
Part C — Tier 1: concurrent leases (opt-in)¶
Tier 1 runs multiple parallel-safe milestones concurrently. Each runs in an isolated lease: a sub-agent with its own branch and external worktree.
Preconditions¶
All of these must hold, or Tier 1 is unavailable and execution falls back to Tier 0:
- The project's
AGENTS.mdexplicitly defines safe parallel ownership: at most one[~]row per lease, only the owner integrates into the main line, and only the owner writes shared memory documents. - The goal request authorizes it explicitly:
```text Using the memory-bank goal protocol, execute this loop.
STATUS_PRIORITY: M01, A01, S01, P01 DOWNSTREAM_IMPACTS: M01 -> A01, S01 A01 -> P01 S01 -> P01
PARALLELISM: 3 INTEGRATION: local-rebase-ff COMMIT_POLICY: task EXTERNAL_MUTATIONS: none ```
INTEGRATION: local-rebase-ff authorizes local lease branches, rebasing
unpublished lease commits, and fast-forward-only integration. It does not
authorize pushing or merge commits. PARALLELISM caps concurrent leases and
defaults to 3 when the field is present without a value.
STATUS_PRIORITY chooses among ready milestones; it adds no dependencies.
This example lets A01 and S01 run together after M01 closes, with P01 waiting
for both. A request using STATUS_ORDER: M01 -> A01 -> S01 -> P01 instead
requires that strict sequence, even with parallelism enabled. Use exactly
one selection field, as specified by GOAL.md.
3. COMMIT_POLICY is task or milestone. Under none there are no commits to
carry work between worktrees, so Tier 1 is disabled.
For milestone, local integration authority permits one unpublished aggregate
checkpoint and its amendments for rebase and review. The owner includes
closure before integrating one finalized milestone commit. A request that
forbids interim commits or amendment uses sequential execution instead.
4. Every milestone dispatched concurrently is Parallel-safe: yes and passes
the three conditions in Part A against every other running lease.
Lease lifecycle¶
Owner: capture actual integration branch and baseline; dispatch ready milestone
│
▼
Create branch goal/ID and worktree at ../<repo>.goal/<ID>
│
▼
Lease: implement rows, one [~] at a time; task commits or aggregate checkpoint
│
▼
Lease: verify with lease-isolated resources
│
▼
Lease: rebase onto captured INTEGRATION_REF and re-verify
│
▼
Lease: run authoritative review-fix gate on rebased diff
│
▼
Has the captured integration branch moved since that rebase?
├── No ───► Continue with the policy-specific closure below
├── Yes (disjoint) ───► Lease: rebase + re-verify only
└── Yes (touches write set/contracts) ───► Lease: rebase + re-verify + re-review
│
▼
Owner under milestone: pause lease writer, close in lease, finalize one commit
│
▼
Owner: fast-forward the captured integration branch (git merge --ff-only)
│
▼
Owner under task: integration check, reconcile impacts, update memory docs, retire
│
▼
Check retained evidence; teardown eligible lease; dispatch ready milestones
Rules¶
- Worktree location. Outside the project tree, at
../<repo>.goal/<ID>. An in-tree folder would dirty the main worktree, leak into test discovery, and accumulate as a generated directory. - Durable lease record. Git is the record.
git worktree listand thegoal/*branches survive a session or server restart, and each lease's status file shows its progress and review counter. Existing goal/status notes retain the actualINTEGRATION_REF, primary worktree path, and full baseline. Resuming means listing worktrees and rechecking those identities before continuing each lease from its status file. No new file is created. - One authoritative review. The bounded review-fix gate runs once, in the lease, on the diff after rebasing onto the current main line, with its counter in the lease's status notes. When other work lands before integration, the lease rebases and re-verifies; the review is repeated only when the newly landed commits touch the lease's write set or contracts read.
- Linear integration. Rebase and advancement checks use the captured branch,
whether named
main,master,trunk, or a release branch. The owner checks its symbolicHEADand tip before integration. Fast-forward preserves the selected commit policy: task commits undertask, one finalized milestone commit undermilestone. Never create merge commits (--no-ff). - Closure and commit policy.
GOAL.mdowns the sequence. Undertask, the owner closes after integration and commits substantive closure changes only when files change. Undermilestone, the owner reserves the serial integration slot, pauses the child, verifies the combined lease tree, reconciles impacts, updates shared memory, and completes adopted retirement in the lease. It then finalizes the checkpoint with that closure and fast-forwards; no provisional checkpoint lands and no second closure commit is created. Unexpected target movement requires reconciling and verifying closure on the new baseline. - Reconciliation from code. The owner reconciles every downstream impact
against the actual combined implementation diff: before integration for
milestone, afterward fortask. Dependents wait for both verified closure and integration. - Shared launch input. Only the owner refreshes an existing
suggested.txtduring serial closure from the current integrated state. Children receive explicit assignments instead of consulting that file for task selection. Before adding owner closure changes, inspect the child diff against its assignment and reject edits to shared files or another milestone's status. Worktree isolation keeps files separate on disk; this diff check prevents competing shared edits from entering integration history. - Runtime-discovered impact. If the owner discovers that a running lease
consumes a change that just landed, it asks the lease to stop at the next row
boundary, reconciles the lease's pending rows, and lets it resume. A
completed row that is now invalid is retained as
[-]closed historical evidence with a named successor. - Failure isolation. A blocked row, a review gate exhausted at iteration 10, or an integration conflict stops that lease only. Its branch and worktree are kept for inspection, its dependents stay unscheduled, independent leases continue, and the owner reports the blocker.
- Conditional milestones. The owner evaluates a
?trigger at dispatch time. An absent trigger skips the milestone without dispatching it. - Resource isolation. Each lease uses its own ports, database names, and caches. A milestone needing an exclusive resource serializes only its verification step, not its implementation.
- Stopping a lease. A lease is stopped, its worktree removed, and its branch deleted only after its work is integrated and its closure is recorded, or the user directs otherwise. A finished lease is closed at once, so idle sub-agents never hold capacity.
- Cleanup sweep on resume. A leftover lease is removed only when the owner's goal state and the status record its successful closure and integration, its worktree, branch and assignment match the recorded dispatch, it has no active writer, and its branch is merged with a clean worktree. A lease just created at the integration tip, or integrated but interrupted before closure, is kept, as is any unrecorded lease; the owner reports every lease it preserves.
Rejected approaches¶
| Approach | Why it was rejected |
|---|---|
| Merge commits to integrate leases | They violate the authorized fast-forward integration and linear commit history |
| Declaring fewer impacts to unlock parallelism | Removes real reconciliation obligations; GOAL.md treats the impact map as a minimum |
| Transitive reduction of the impact list | Skips direct reconciliation of a consumer against the original producer |
| Worktrees inside the project | Dirty worktree, test-discovery leakage, accumulated generated folders |
| Reconciling from a free-text completion summary | GOAL.md requires reconciling against the implementation that now exists |
| Reviewing only in isolation, then again after integration | Two gates with no single counter owner; the isolated pass never saw the integrated code |
| Inferring write sets from task rows | Task rows do not list paths reliably; write sets must be declared |
| An environment variable for concurrency | A goal-input field keeps authority in the request that starts the run |
Model policy and retained lease evidence¶
Opt-in MODEL_POLICY assigns ordinary work,
coordination and fixes to DEFAULT, and every whole-milestone review iteration
to fresh read-only WHOLE_MILESTONE_REVIEW agents. Each brief carries the full
resolved policy, governing request, approval context, narrowed effective grants,
assignment, pinned baseline, prior findings and persisted iteration. Reviewers
have no mutation authority; the owner alone consolidates the report and writes
the ledger. Missing model, effort or fresh-agent capability pauses affected
work; omission preserves host settings. Parts A/B/C describe planning
boundaries and execution choices, independently of this optional model policy.
Before either closure cleanup or a resume cleanup sweep, inspect ignored
artifacts as well as tracked and untracked changes. Git can remove a clean
worktree containing ignored cited evidence without --force. Retain required
qualification, cited and recovery artifacts in an approved durable location,
verify content hashes and update maintained references before freezing
retirement records. Verify that retained files remain accessible after removal.
Do not rewrite frozen records to enable cleanup. Preserve the worktree when
retention, ownership or references are uncertain; only verified disposable
artifacts may be deleted. All existing closure, integration, ownership,
no-active-writer, merged-branch, clean-tree and no-force conditions still apply.