Coordinating Parallel Engineering Work With Claude
I have written before about decomposing specs against team shape, and about the specific Claude Code primitives that make the decomposition…
Coordinating Parallel Engineering Work With Claude



I have written before about decomposing specs against team shape, and about the specific Claude Code primitives that make the decomposition real: skills, hooks, subagents, worktrees, and the spec index. That work answered how a single engineer or a tightly coupled pair takes a feature spec and breaks it into mini specs that an agent can run against. This piece sits on top of those. Earlier articles handled decomposition where agents do the parallel work. Here, the parallel workers are engineers, and the coordination problem is human.
The earlier articles got me to “here is how to break the work apart.” This one is about everything that has to happen between Monday morning, when the build kicks off, and Friday afternoon of integration week, so that the build actually closes, and how I size the parallel work so the milestone closes on the date the calendar promised. The prompts I run during a cycle are collected at the end of this piece, organized by purpose.
Where to cut work in multiple tasks
A parallel cut is the boundary between two pieces of work, where neither piece depends on the other to make progress. The shared point of reference is a pre-existing contract: when both streams depend on one, they can proceed independently.
The case to watch for is a stream that has to wait on another to define an interface first, since the waiting stream cannot start until the producer commits. You can work around this by using known contracts with mocked data.
The Claude Code piece walks through the decomposition mechanics that find these cuts. Claude is good at proposing cuts and bad at validating them, and the validation work is a four-pass conversation where I push back with system context Claude does not have. After three or four passes, the dependency graph is something I trust enough to plan against.
Everything below assumes the cut is real. The work this piece is about is what comes next.
The interface contract
Every edge in the dependency graph has a contract. Edges come in two flavors. A contract dependency means Stream A needs to know what Stream B’s interface looks like; a stub satisfying that interface is enough to unblock the consumer for the duration of the build. A runtime dependency is different. The consumer needs the producer’s actual running code, and no stub can take that place. Almost all the work of making parallel work actually parallel is converting runtime dependencies into contract dependencies. The contract document is what makes that conversion legible.
The contract document is a markdown file with a fixed shape. I have Claude generate the first draft from the dependency graph and the surrounding system context. The shape:
- Producer and consumer. Which stream owns the interface. Which streams depend on it. Multiple consumers are common; a contract with two producers usually means the boundary is wrong.
- The data shape. Field by field. Type, nullability, defaults, constraints. For nested objects, the same level of detail at every level. No “and so on” allowed.
- Behavior under each error condition. What the producer returns when the resource doesn’t exist. When the request is malformed. When the underlying dependency is down. The timeout. The consumer’s response to each case.
- The performance envelope. Latency at p50 and p99. Throughput in requests per second the producer commits to. What happens when the consumer exceeds it.
- The auth model. Service-to-service or user-scoped. Token format. Rotation policy.
- Backwards compatibility. Whether the contract is versioned. How additions are handled. How deprecations are signaled.
- Open questions. The decisions that need human judgment, flagged explicitly.
Open questions earn their keep. Claude flags the things it cannot decide on its own, and the flags become the agenda for the next morning’s meeting. A typical example, from a recent build:
Open question example: Should this endpoint return an empty list or a 404 when the resource does not exist? The choice affects how the consumer handles the response. An empty list lets the consumer treat “no results” and “not found” identically, which simplifies their code but loses information. A 404 forces the consumer to handle two cases, which is more code but matches HTTP semantics. Producers in this codebase have done both. Decision needed before either side starts.
A question like this takes thirty seconds for two engineers and a manager to answer. Asked in advance, it adds nothing to the timeline. Discovered during integration week, the same question becomes an emergency, because both sides have already shipped code that assumes the opposite answer.
A good contract document has somewhere between five and fifteen open questions. Fewer than five usually means Claude was being polite and accepting choices that need scrutiny. More than fifteen usually means the underlying design is not actually clear yet, and the contract is premature.
The contract review meeting
The most important fifteen minutes of the planning cycle is the contract review meeting. Two people from each stream, a manager, the open questions list. We go through every open question and resolve it on the spot. If we cannot resolve one in ninety seconds, it goes on a separate list, and the relevant streams are flagged to start work on the parts of their stream that do not depend on the answer.
The meeting works because Claude has done the prep. The questions are pre-formulated, the tradeoffs are pre-described, and the meeting becomes a sequence of small decisions instead of a long argument about what we are even talking about.
After the meeting, Claude takes the resolutions and edits the contract documents in place. The edits are checked into the repo. Every contract has a “decided” section at the bottom with the resolution and the date. That section lives in version control, not in a chat thread, after a cycle I lost a week to because a stream had built against a data model whose update lived in a thread the engineer wasn’t in. Decisions about a contract belong in the contract. If the contract changes later, the date moves, and the affected per-stream specs get regenerated.
What a contract turns into
The contract is text. It needs to become code that runs. Three artifacts come out of a signed contract, and Claude generates all three.
The first is a type definition or schema, in whatever language the producer and consumer share. TypeScript interfaces, Pydantic models, Protobuf, OpenAPI. The schema is checked in alongside the contract document.
The second is a consumer stub: a function or service that satisfies the contract well enough to compile and test against. The stub returns canned responses that match the schema, including the error cases. The consumer side of the parallel build runs against this stub for the entire build phase.
The third is a producer test harness, a set of test cases that exercise the contract’s stated behavior. When the producer ships their real implementation, this harness is what they run it against. Passing the harness is the signal that the producer’s stream is ready for integration.
The point of generating all three from the same contract is that there is no drift. If the contract changes, all three regenerate. When the consumer’s stub disagrees with the producer’s harness, the contract is wrong, not the code.
The per-stream spec
Each engineer gets one document. The spec includes the goal in plain language at the top, the contracts they produce and consume with links to canonical contract docs, their work units in order with acceptance criteria, the metrics they need to emit, the alarms they need to define and at what thresholds, the runbook entries that need to exist before integration week, and a checklist for pre-integration.
Claude generates the first draft of each spec from the dependency map, the contracts, and a short description of what each engineer is strong at. The drafts are produced in the same session, in parallel, and the cross-cutting concerns stay aligned because Claude is holding the whole graph at once. I read each spec end to end before sending. Catching a mistake here takes ten minutes per spec. Missing one shows up in integration week.
Acceptance criteria as testable conditions
The acceptance criterion is the unit of work, not the work unit. A work unit might be “implement the rate limiter.” The acceptance criteria for that unit are the testable conditions that say the work is done. From a recent spec:
Work unit: Implement the rate limiter for the public API.
Acceptance criteria:
1)A request that exceeds the limit returns 429 with a
Retry-Afterheader set to the seconds until the next available token.
- A request from an authenticated user counts against that user’s bucket; an anonymous request counts against an IP-derived bucket.
- Limits are configurable per route, with a default that matches the contract document.
- The limiter emits the four metrics defined in the metrics section, with the cardinality bounds documented there.
- Removing the rate limiter middleware from the chain causes the test suite in
tests/rate_limit/to fail.
The last criterion is the one engineers usually leave out. A test that does not fail when the code is missing is not really a test. Claude catches this when I prompt for it, so I prompt for it.
Metrics first
The metrics section comes with the spec, not after the implementation. For each metric, the spec lists the name, the type (counter, gauge, histogram), the dimensions, the cardinality bound for each dimension, the emission frequency, and the question the metric is meant to answer.
The cardinality bound is the part that matters. A counter on request_count with a user_id dimension is a cardinality bomb. A counter with a route_id dimension is fine. Claude is good at flagging cardinality risks if I prompt for it. The prompt is "for each metric, evaluate the cardinality of every dimension and flag anything unbounded or user-derived." The list that comes back is usually right.
The “question the metric answers” field forces the engineer to justify the metric. Without an answer to the sentence “this metric exists so that someone can answer the question…” the metric should not be there.
Alarms with threshold justification
Every alarm has a threshold. Every threshold has a justification. The justification is two sentences. The first says what the threshold means in business terms. The second prescribes the on-call engineer’s action when the alarm fires.
A weak alarm definition reads:
Latency p99 > 500ms for 5 minutes.
A working version reads:
Latency p99 > 500ms for 5 minutes. This means the API is slow enough that the consuming front-end will time out for one request in fifty. Page the on-call, who should check the dashboard linked in the runbook to determine if the cause is upstream, the database, or the service itself.
Claude drafts the alarms. The team reviews them. Bad alarms come in three flavors I see repeatedly: thresholds without justification, durations that don’t match the metric’s emission cadence, and severity that doesn’t match the impact. Good alarms tell a story that begins with a threshold and ends with an on-call engineer doing something specific.
The “What blocks you” check
The spec ends with a section called “What blocks you.” It should be empty. If the parallel cut is real, every engineer can sit down on Monday and start, because the contracts they consume are stubbed and the contracts they produce are clearly defined.
When the section is not empty, the cut is not real. Either there is a missed dependency in the planning, or a dependency cannot be stubbed for some reason. The first case is a planning failure fixed by going back to the dependency map. The second case is harder. It usually means the dependency's runtime behavior is too complex to mock, and the consumer needs the real thing to make progress. The version of this I have lost the most time to: a producer engineer was still designing the interface as he shipped it, and the consumer streams could not mock against a stable shape because the shape kept changing. When this happens, the streams need to be sequenced behind the producer, and the sequencing eats into the integration week budget.
The honest answer is that one or two streams in a build will have a non-empty “What blocks you” section. The goal is to know about them before Monday morning, not to discover them on Tuesday.
Example Integration Week
Integration week is scheduled before the build starts. It is part of the work, not something that happens afterward.
Stub removal and triage
Monday morning, every consumer stream removes its stub for the upstream contract and wires up the real producer. Then we run the integration tests. The order matters. If three streams all consume contract X, and X’s producer is not ready, those three are blocked Monday. So the producer-side streams check in by Friday of the build week with their harness results. If the harness is green, the consumer streams can proceed Monday. If not, Monday is spent on the producer side, not the consumer side.
The Monday triage is short. The integration tests either pass or they fail. The failures get logged with one of three labels: “contract mismatch” (the contract did not anticipate this case), “implementation bug” (the contract is right, the code is wrong), or “test bug” (the contract and code are right, the test is wrong). The labels matter because they route the work differently. Contract mismatches go to the contract review meeting Tuesday morning. Implementation bugs go to the relevant engineer. Test bugs go to whoever wrote the test.
Contract reality testing
The contracts get tested for real this week. Anything ambiguous in the contract document will surface here. The fixes are usually small in code and meaningful in design. A typical pattern: the contract said the producer would return an empty list when the resource was missing. The producer is returning a 404. Both interpretations were defensible from the contract document, which used the word “missing” without disambiguating. The contract gets edited, the choice gets documented, and one side or the other changes. Total time: a fifteen-minute meeting and two hours of code change.
When the fixes are not small, that is a signal. A contract that requires a multi-day rewrite during integration week is a contract that was not detailed enough at sign-off. The Friday retrospective will catch this and the next round will spend more time on the contract that failed.
Metrics review
Every stream emits metrics. Thursday morning we look at them together. The questions are always the same. Are the cardinalities right? Are the dimensions consistent across streams that emit related metrics? Is anything double-counted? Does any metric not have an answer to the “what question does this answer” check?
I paste the metric definitions from each stream into a single doc and have Claude look for inconsistencies. It finds them. Two streams emit a counter named request_count, with different dimensions. One stream emits a histogram with bucket boundaries that do not match the dashboarding tool's defaults, which means the dashboard will be misleading until someone notices. One stream has a metric that nobody can articulate a use for.
The output of metrics review is a short list of edits. The edits get made Thursday afternoon. The dashboards get updated to match.
Alarm review
Every alarm gets read aloud. Threshold, dimension, action, runbook link. The runbook link goes to a page that exists. The threshold has a justification. The action has an on-call engineer and a clear next step.
This part of the week is where alarms get cut. The patterns are consistent. An alarm without a clear remediation when it fires is noise. So is an alarm whose threshold sits below the level of real business impact. An alarm whose runbook link points to a “TBD” page is not noise so much as not ready to ship at all. Cutting alarms feels uncomfortable in the moment because engineers built them and want them to stay. The cut happens anyway, because every false positive in production is a small tax on the on-call engineer’s attention, and the tax compounds.
Retro and feed-forward
Friday morning is the milestone close. Friday afternoon is the retrospective. The retrospective has a fixed shape. We list the contracts that had to change during integration week, with what was unclear about each at sign-off. We list the metrics and alarms that got cut and the reasons. We note which streams finished early and could have absorbed more work, and which finished late along with where the time went. The last item is what to design out next round.
The retrospective doc goes back into Claude as input for the next planning cycle. The things that broke this time are the things to design out next time. After three or four cycles, the planning prompt has accumulated enough cycle-specific context that Claude’s first-draft contracts are noticeably better. The team’s voice ends up baked into the prompt over time.
What goes wrong mid-build
Even with the contracts signed and the per-stream specs distributed, things break during the build week. The most common failures are predictable.
A contract turns out to be wrong. An engineer building against the producer side realizes mid-week that the contract cannot be satisfied as written, usually because of an underlying constraint the planning missed. The fix is a contract change. A contract change in the middle of the build week is expensive because it ripples through every consumer stream, but contained because all the consumer code is text that Claude can analyze for impact in one session. The conversation looks like:
“Contract X is changing in the following way. List every consumer stream and the specific files that need to change.”
Claude produces the list. The build continues.
Sometimes a stream finishes early. The engineer comes to the manager and asks what to do. Check the integration week list and pull in a piece of work that would otherwise be done during integration. A stream that finishes early can write the integration tests for its own contract, draft the runbook for its own service, or help another stream that is behind. The mistake I have made before is to assign the engineer a new feature on the next milestone instead. That causes context-switching during integration week and weakens the milestone close.
When a stream falls behind, the first question is whether the stream is behind because the work was harder than expected or because a dependency was wrong. Harder work means the stream needs help, which comes from another engineer or from cutting scope. A wrong dependency means the contract is wrong, and the contract gets fixed first, because no amount of additional engineering effort on the consumer side will recover from a wrong contract.
A new requirement comes in mid-build. The product team realizes a feature needs to behave differently. The temptation is to absorb the change into the current build. The right answer is almost always to push the change to the next milestone, because adding it mid-build means the contracts change, which means the per-stream specs change, which means integration week turns into integration-and-redesign week. The exception is if the change is small and contained to a single stream. Even then I push back.
Why the contract is load-bearing
Parallel work runs in parallel only when nobody is waiting on anybody. Keeping people from waiting requires that the connections between work be written down before the work starts. Most attempts at parallel work skip this step because it feels like overhead. It is overhead. It is also the cheapest insurance available against integration week stretching into integration month.
Two failure modes show up repeatedly when teams skip the contracts.
The first is divergent mental models. Two engineers build against different versions of the same interface; one thinks the field is a string, the other thinks it is an enum with three values. Both ship green builds. Integration day, both break. The fix takes ten minutes once the divergence is found. Finding the divergence takes a day, because both sides have plausible-looking code and the bug only shows up at the seam.
The second is design-as-you-go. An engineer is asked to flesh out the contract during the build because the interface feels small. They make a reasonable choice. Two other engineers consume the interface and build around the choice. Three weeks in, the original engineer realizes the choice was wrong and changes it. Now three streams change. The week of integration absorbs all three changes badly. The fix here is harder than the mental-model version, because the producer made a defensible decision with the information they had, and the consequences of the decision are distributed across people who weren’t in the room when it was made.
A signed contract before the work starts looks like bureaucracy from the outside. From the inside, it is what keeps integration week to one week.
What Claude does and doesn’t do
Claude doesn’t know your system. It knows what you tell it about your system. The system surface area document is real work the first time and incremental work after that. It pays off across every planning cycle.
The team is also outside what Claude can see. It can guess at strengths from a sentence I write, but it does not know which engineer hates the queue layer and which one loves it.
What the business actually needs is the third blind spot. Claude can take a goal statement and produce a plan that achieves it. A bad goal statement still gets you a beautiful plan, only for the wrong thing. Or as one of my former supervisors would say, you could be directionally correct but off by a few degrees and at hundreds of miles an hour, wind up hundreds of miles from where you wanted to be.
The planning meeting itself is not replaceable. Claude replaces the second half of it, the part where someone takes notes and types up a doc. The first half, where the team argues about what we are actually trying to do, still happens. It is shorter now because the typing-up is fast, and the doc that comes out is more rigorous because the typing-up was done by something that does not get tired.
Neither is the contract review meeting. That fifteen minutes is the most important time of the cycle, and it has to happen with humans in the room. What Claude does is shape the meeting around explicit decisions instead of leaving the participants to discover what those decisions even are.
What this costs
The first round costs more than not doing it. Producing the dependency map, the contracts, the per-stream specs, all takes a day or two. Without Claude this would take a week, and the contracts would be thinner because the typing alone absorbs the time that should go to thinking.
Steady state, after a few cycles, planning takes maybe four hours. The contracts get reused across milestones. The system surface area document gets updated, not rewritten. Claude is fast at incremental work because the artifacts already exist.
This introduces certainty and routine. Engineers like knowing what they are building before Monday morning. The acceptance criteria are testable, which matters more than I expected. Integration week being on the calendar gives them something concrete to pace toward, instead of a vague sense that things will tighten up at the end. The cultural payoff may be bigger than the schedule payoff, and the schedule payoff is real.
How to estimate parallel streams
The team estimates in person-days. Each work unit gets a 50%-confidence estimate and a 90%-confidence upper bound. The 90% bound is what we plan against. The 50% estimate is for the engineer to know when they should ask for help.
Claude does the first-pass estimation across the whole dependency graph, in the same session as the contract drafts. The estimates come together because the contract surface area determines the size. A contract with three error cases takes meaningfully less time to implement than one with twelve, and Claude is good at reading that surface area when it has the contract documents in front of it.
The first cycle’s estimates are usually wrong by thirty to forty percent. After the post-cycle calibration prompt runs against the actuals, the next cycle’s estimates tighten to around fifteen percent error. After three cycles, most streams are within ten percent. The integration-week budget is the exception. It does not tighten the same way, because it depends on which contracts surface ambiguity during integration, and ambiguity is hard to predict. The right approach there is a generous buffer (twenty percent of the build-week budget) and the discipline to use it for integration rather than letting it absorb mid-build slippage.
The other thing the prompts do is keep estimates honest across streams. A team of engineers will systematically under-estimate the streams they like and over-estimate the streams they find boring. Claude has no preference. Its estimates are biased by the description in the spec, but the bias is consistent across streams, which is what matters for parallel planning. The relative ordering of stream sizes is right even when the absolute numbers are off, and the relative ordering is what determines which stream is the critical path and which streams have slack to absorb a slip.
Mid-build, run a pulse-check prompt against the team’s status reports. It projects each stream’s close date against the original estimate and identifies streams trending more than a day behind. The output recommends specific work units that could move from a behind-schedule stream to a stream with slack. Most cycles, no rebalancing is needed; the prompt comes back with “current trajectory meets the milestone.” The cycles where rebalancing is needed are the ones where you would have noticed the trouble two days later without the prompt, which is two days closer to integration week.
The cadence
Two weeks of parallel build. One week of integration. Then planning for the next two weeks, which takes a couple of days and overlaps with the tail of integration week. The team is in a roughly three-week loop. The loop has been holding for six months across four different milestones with different shapes.
Watch for whether the loop scales past six parallel workstreams. I suspect it does not, not without changing how the contracts are organized. Past six concurrent streams the contract surface area starts to outgrow what one person can hold in their head, even with Claude helping. The next problem is probably how to cluster contracts so that two sub-teams can run loops in parallel without colliding.
That is a problem for later.
The prompts I run
The prompts below are what I send Claude across a cycle. They have changed across iterations, and the versions here are the ones that have held up across four milestones. Bracketed placeholders are stand-ins for real values you would paste in. The order below is roughly the order I run them during a cycle.
Starting the cycle: the dependency map prompt
I'm planning a milestone with multiple engineers working in parallel. I need
a dependency map I can use to identify cuts where streams can run independently.
Goal (in product terms): [paragraph or PRFAQ]
Constraints: [deadline, team size, on-call rotation, sequencing requirements]
System surface area: [services, data stores, auth boundaries, existing contracts]
Team: [who's on it and what each person is strong at]
Produce a dependency graph as a markdown document with these sections:
1. Work units. A numbered list of every distinct unit of work. Each unit gets
a one-sentence description and a complexity estimate (S/M/L based on
contract surface area).
2. Edges. For every pair with a relationship, write the edge as either
"Unit X needs Unit Y to be DEFINED" (contract dependency, can be cut
with a stub) or "Unit X needs Unit Y to be RUNNING" (runtime dependency,
cannot be cut with a stub).
3. Cut analysis. Group the work units into proposed parallel streams such
that within each stream work is sequential and across streams the only
dependencies are contract dependencies. Flag every runtime dependency
that crosses streams as a problem to resolve.
4. Ambiguities. List anything in the goal or constraints that is unclear
enough to affect the graph. Don't assume; ask.
Be skeptical of cuts that look clean but probably aren't. Flag work units
where the runtime behavior is too complex to mock; those will need to be
sequenced rather than parallelized. Don't be polite.
Sizing the parallel streams
Given the dependency graph above, estimate the duration of each parallel
stream in person-days. For each stream:
1. Total person-days, with a 50%-confidence estimate and a 90%-confidence
upper bound.
2. The work units that contribute most to the upper bound.
3. Risk factors that could push the upper bound higher: unknowns in the
system, contracts with high open-question counts, dependencies on
external teams, work that nobody on the team has done before.
4. Whether this stream can absorb a 1-day or 2-day slip without affecting
the milestone close, given the other streams' estimates.
Then identify:
- The critical-path stream (the one most likely to dominate the cycle's
duration).
- The slack streams (those with the most buffer if rebalancing is needed
mid-build).
Use the 90% upper bound, not the 50% point estimate, when comparing to
the milestone deadline. If the 90% bound exceeds the deadline, flag it
and propose either a scope cut or an additional stream to parallelize
the critical-path work further.
Don't estimate optimistically. The bias toward optimism is the most common
estimation failure I want this prompt to avoid.
Drafting the contracts
For each contract dependency edge in the dependency graph above, produce a
contract document with this structure:
1. Producer and consumer. Which stream owns the interface, which streams
depend on it. Flag any case with multiple producers; that usually means
the contract boundary is wrong.
2. Data shape. Field by field: type, nullability, defaults, constraints.
For nested objects, the same level of detail at every level. No "and
so on"; if the shape is unclear, put it in open questions.
3. Behavior under each error condition. What the producer returns when
the resource doesn't exist, when the request is malformed, when the
underlying dependency is down, when the request times out. The consumer's
expected response in each case.
4. Performance envelope. Latency at p50 and p99, throughput in requests
per second the producer commits to, and what happens when the consumer
exceeds it.
5. Auth model. Service-to-service or user-scoped. Token format. Rotation
policy.
6. Backwards compatibility. Whether the contract is versioned, how additions
are handled, how deprecations are signaled.
7. Open questions. Decisions needing human judgment. For each: state the
question, describe the tradeoff, note what each side would change based
on the answer, flag urgency (must-decide-before-build, can-decide-during-
build, can-decide-at-integration).
Aim for between 5 and 15 open questions per contract. Fewer than 5 usually
means you accepted choices that need scrutiny. More than 15 means the
underlying design is not actually clear yet.
For each contract, also produce: a schema definition matching the surrounding
code's language, a consumer stub satisfying the contract for testing including
all error cases, and a producer test harness with test cases for every
behavior the contract specifies. Keep all three aligned with the contract
document so changes regenerate cleanly.
Generating the per-stream specs
For each stream in the dependency graph above, produce a per-stream spec
document with this structure:
1. Goal. The customer-facing outcome this stream contributes to, in plain
language. One paragraph.
2. Contracts produced. Every contract this stream owns, with link and
one-line summary.
3. Contracts consumed. Every contract this stream depends on, with link
and one-line summary. For each, note whether the consumer side will be
running against a stub during the build week.
4. Work units. Assigned work units in execution order. For each: one-sentence
description, acceptance criteria as testable conditions, person-day
estimate (50% and 90% bounds from the sizing prompt above).
5. Acceptance criteria. Each criterion must be a testable condition. For
every work unit, include at least one negative criterion of the form
"removing the implementation causes the test suite in [path] to fail."
A test that does not fail when the code is missing is not really a test.
6. Metrics. For each: name, type (counter/gauge/histogram), dimensions,
cardinality bound for each dimension (flag any unbounded or user-derived
dimension), emission frequency, and the question this metric answers
(if you can't finish the sentence "this metric exists so that someone
can answer the question..." the metric should not be there).
7. Alarms. For each: threshold with specific metric and dimension values,
duration, severity, two-sentence justification (first sentence: what
the threshold means in business terms; second sentence: what the on-call
should do when it fires), and runbook link to a page that exists with
a procedure (not "TBD").
8. Runbook entries. Pages that need to exist before integration week:
title, scenario, link.
9. Pre-integration checklist. What must be true before integration week
starts. Producer streams: harness green. Consumer streams: stub running,
integration tests written.
10. What blocks you. This section should be empty if the parallel cut is
real. If anything is here, the cut isn't real and the planning needs
to go back a step.
Generate all stream specs in this same session so cross-cutting concerns
stay aligned. Flag any work unit appearing in two streams. Flag any work
unit missing across all streams. Flag any metric named the same way in
two streams with different dimensions.
Auditing metric cardinality
Below are the metric definitions across all streams in this milestone:
[paste metrics sections from each per-stream spec]
For each metric, evaluate the cardinality of every dimension. Flag anything
unbounded or user-derived. For each problematic dimension:
- The metric name
- The dimension name
- Why it's a cardinality bomb
- A bounded replacement that answers the same underlying question
Then list any inconsistencies across streams: metrics named the same way
with different dimensions, dimensions named the same way with different
value semantics, histograms with bucket boundaries that don't match the
dashboarding tool's defaults.
Estimating the integration-week budget
Given the signed contracts and per-stream specs above, estimate the
integration-week effort in person-days. Break it down by:
1. Stub removal and initial integration test runs (Monday).
2. Contract reality testing (Tuesday and Wednesday). List the contracts
most likely to surface ambiguity during integration. For each, the
reasons it's high-risk.
3. Metrics review (Thursday morning).
4. Alarm review (Thursday afternoon).
5. Buffer for the contracts that will turn out to need changes mid-week.
For the contract reality testing estimate, use this heuristic: contracts
with their open-question count near 15 are higher risk, even if the
questions were all resolved at sign-off. Contracts where the data shape
includes nested objects more than 2 levels deep are higher risk. Contracts
with multiple consumers are higher risk because the divergence shows up
in more than one place.
Output: total person-days budget, broken down by day, with the high-risk
contracts called out specifically and a recommended assignment of which
engineer should be the primary on each high-risk contract during
integration week. Suggest a 20% buffer on top of the day-by-day estimate
unless the cycle has had three or more clean integrations in a row.
Mid-build pulse check and stream rebalancing
Below is the current state of each stream at the [day X] mark of the
build week:
[paste status: each stream's progress against its original estimates,
work units complete vs in-progress vs not started, any known issues]
Given the original per-stream specs and the dependency graph:
1. Project the close date for each stream against the original 90%-bound
estimate. Flag any stream tracking more than 1 day behind that bound.
2. For any behind-schedule stream, identify:
- Whether the slippage is from harder-than-expected work or from an
external blocker. - Whether the integration-week budget can absorb the slip.
- Which work units could be moved to a stream with slack, and what
the cost of the move would be (context-switching, ramp-up). - Which work units could be cut without affecting the milestone outcome.
3. For any ahead-of-schedule stream, suggest specific work units from the
integration-week list that could be pulled in: writing integration tests
for own contract, drafting own runbook, shadowing a behind-schedule
stream. Do not suggest next-milestone features; that causes context-
switching during integration week.
4. Recommend a specific rebalancing action, or "no action; current
trajectory meets the milestone."
Be skeptical of optimistic status. If a work unit has been "in progress"
for more than its 50%-bound estimate, treat it as at risk regardless of
what the engineer reports. If it has exceeded its 90% bound, treat it as
the cycle's critical issue and recommend escalation.
Mid-build contract changes
Contract X needs to change mid-build in the following way:
[describe the change: old behavior, new behavior, reason]
Given the per-stream specs and the surrounding code:
1. Every consumer stream affected by this change.
2. For each affected stream, the specific files that need to change.
3. For each file, the nature of the change in one sentence.
4. Total work in person-hours.
5. Any consumer with already-shipped code that will be hard to roll back.
Then update the contract document, regenerate the schema, regenerate the
consumer stub, regenerate the producer test harness.
Thursday metrics review
Below are the metric definitions actually emitted by each stream after
the build week:
[paste actual metric definitions from running services]
And the metric definitions in the per-stream specs:
[paste per-stream metric definitions]
Find:
1. Metrics in a spec but not actually emitted.
2. Metrics emitted but not in any spec.
3. Metrics with names matching across streams but inconsistent dimensions.
4. Histogram bucket boundaries that don't match the dashboarding tool's
defaults.
5. Any metric where the "question this answers" can't be articulated by
reading the metric name and dimensions.
For each finding, the specific edit and which stream owns it.
Feeding the retrospective into the next cycle
Below is the retrospective from the cycle that just closed:
[paste retrospective doc]
And the contracts and per-stream specs from that cycle:
[paste or link to artifacts]
For the next cycle's planning, identify:
1. Contract patterns to apply: what worked that should be standardized
in the contract template.
2. Anti-patterns to design out: contract sections that were ambiguous and
caused integration-week rework. Make these explicit in the next round.
3. Stream sizing observations: streams that finished early or late, with
the why. Adjust next round's distribution.
4. Metrics and alarms that got cut: the patterns that didn't survive review.
Avoid drafting these next time.
5. System surface area updates: anything we learned that should be added
to the surface area document for future planning.
Output: an updated planning prompt for the next cycle that incorporates
these observations as constraints and templates.
Calibrating estimates against actuals
Below are the original estimates from cycle N's planning and the actual
person-days each stream consumed:
[paste original 50% and 90% per-stream estimates]
[paste actual durations]
Compute:
1. The systematic bias factor: average actual / average 50%-estimate, and
average actual / average 90%-estimate, across all streams.
2. The variance: which streams were closest to their estimates and which
were furthest off. Look for patterns by engineer, by kind of work,
by stream size, by contract complexity.
3. The integration-week estimate vs actual: was the budget right, too low,
too high? If the buffer absorbed real slippage, was the buffer
appropriately sized?
4. Specific estimation lessons: types of work that were systematically
under-estimated, kinds of contracts that surfaced more ambiguity than
their open-question count predicted, streams whose engineers consistently
over- or under-estimate.
Output:
- An adjustment factor for next cycle's estimates by category of work,
with reasoning.
- Updates to the sizing prompt's instructions so future estimates reflect
the calibration.
- Updates to the integration-week budget prompt's heuristics if particular
contract patterns proved worse than the heuristic predicted.
These eleven prompts cover the cycle end to end. Six of them run during planning, before the build week starts. Two more come into play during the build week itself, the pulse check on a fixed cadence and the contract-change prompt only when something breaks. Thursday morning of integration week brings the metrics review. After the milestone closes, the retrospective and calibration prompts feed forward into the next cycle.
The prompts get edited every cycle, mostly to add lessons from the retrospective and the calibration. After three or four cycles, they stabilize.
By Joshua McDonald on May 12, 2026.
Exported from Medium on August 26, 2026.
Reader discussion