Lesson 1 of 6
Split work by dependency and write set
Turn three tracker features into a written plan with owners, checks, write sets, and an honest parallel-versus-sequential split before any worker starts.
Confirm the Module 2 baseline before you split work
No previous purchase is required. Download the complete Module 3 starter ZIP. Unzip into a new ~/agent-lab/task-tracker folder (create ~/agent-lab first). Use current Node 22 (22.22.2 or newer). The ZIP includes the Feature/FeatureApi extension point, safe storage, regression tests, three worker configurations, and brief/handoff templates.
cd ~/agent-lab/task-tracker
npm install
npm test
npm run typecheck
cp AGENTS.md.example AGENTS.md
git init
git add .
git commit -m "Verified Module 3 baseline"
git status --short
git rev-parse HEAD
Expect passing tests/typecheck and empty status after the commit. Record the SHA. This is a Vite + TypeScript reference baseline, not a byte-for-byte migration of Module 2. Its Task.done boolean and task-tracker/tasks/v1 storage key differ from Module 2's status envelope; prior saved tasks do not migrate. It preserves the safety rule: corrupt bytes remain untouched, blocked saves never claim success. Keep Module 2 in its own folder.
Experienced learners may adapt their Module 2 app instead, but must implement this same FeatureApi contract and rerun the safety regressions before splitting work.
Call work parallel only when write sets are disjoint
Sequential work waits because task B consumes an output of task A. Parallel work is stricter than “the features sound unrelated.” Two tasks may run in parallel only if neither depends on the other’s output and their write sets are disjoint — the files each task is allowed to change. Tasks also conflict if they share a dev-server port or an untracked secret.
Write the write set down. If two sets intersect, pick one: sequence the tasks; extract an interface task that owns the shared file first; or declare a merge point and plan to reconcile it when you integrate. Unrelated product ideas that both edit src/main.ts are not automatically parallel. The write-set rule is yours to enforce. OpenCode has no task graph and no scheduler that will notice the overlap for you.
Freeze shared types before feature workers start
Do one small sequential task first: freeze the interfaces the features share. For this tracker that is the Task type, store signatures, and the Feature registration shape. Optional fields go on once, in the interface task, then stay still:
export type Task = {
id: string;
title: string;
done: boolean;
due?: string; // ISO date YYYY-MM-DD
tags?: string[];
};
After that, due dates, tags, and search can live in their own files. It will not remove every conflict: src/main.ts still holds const features: Feature[] = [], so each worker that registers a module will touch that list. Treat src/main.ts as a planned merge point, not as proof that nothing can run in parallel. Feature modules stay disjoint; the registry list is the honesty note for later.
The downloaded src/types.ts already defines Feature and FeatureApi. api.getTasks() returns copied tasks; api.commit(next) saves before replacing visible state and returns false on failure; api.today is the local date; api.rerender() updates filters without saving. A badge returns text or null, and visible returns a boolean. Inspect these exact signatures and record the interface SHA before workers branch. Do not bypass commit with direct localStorage writes.
Use the Plan agent to map files — it does not launch workers
OpenCode ships two primary agents, Build and Plan. Plan is restricted: file edits and bash default to ask, so it is the safe place to look before anyone writes. Press Tab to cycle primary agents. Stay on Plan. Paste a read-only prompt that lists due dates, tags, and search, asks which files would change, and flags any file more than one feature would touch. Tell it not to write code.
Compare its table with find src -type f | sort. Shared files become either the interface task or a named merge point in your plan. Plan is one agent giving analysis. It does not dispatch workers, pass messages, or own a worktree. Built-in subagents (General, Explore, Scout) are also not a parallel scheduler. The workers start only after isolation and a written brief.