Flow-Forward Is Easy. Flow-Back Is Where Teams Break.

Meshie · 2026-10-23 · 8 min read · ai · product-development · operations

Every team has a chain: intent, acceptance criteria, build, production. Changes move down it all day without friction — that is what the chain is for. The ones that break teams are the changes that need to move back up it, and almost never do.

The chain only has one easy direction

Flow-forward is the happy path and it is well tooled: a decision becomes a criterion, the criterion becomes a ticket, the ticket becomes code and a test. Every step has a handoff, an owner, and somewhere to put the artefact.

Flow-back has none of that. A developer three days in discovers the criterion is impossible as written; a support thread reveals that the "done" everyone signed off on was wrong about what users do. What happens next is almost always the same: the person fixes it in place, adjusts the test to match, and moves on. The decision genuinely changed — and the only record of it is a diff and a Slack thread that scrolls away by Thursday.

Six months later someone asks why the product behaves this way, and the artefact that should answer says something else, confidently. That is worse than no document, because a stale artefact gets believed.

Two kinds of change, one routing question

The reflex fix is "keep everything in sync." Teams try it, find it costs more than the work it documents, and quietly abandon it — which is why most product orgs have both a sync ritual and a drawer full of fiction.

The affordable discipline is narrower. Route the change by what it actually altered:

One question separates them cleanly:

Could a reasonable person reading the upstream artefact next month make a wrong decision because of this change?

If yes, it flows back. If no, leave the artefact alone — and mean it. Half the reason teams stop updating documents is that they were asked to update them for changes that did not matter, until the ritual stopped predicting anything.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 200" role="img">
  <title>A change that alters intent has to flow back up the chain; one that alters only mechanism stops where it was made</title>

  <text x="2" y="24" font-size="11" fill="var(--text-muted)">Flow-forward — intent becomes work</text>

  <rect x="2" y="38" width="170" height="52" rx="10" fill="var(--primary-50)" stroke="var(--primary-600)" />
  <text x="87" y="69" text-anchor="middle" font-size="14" fill="var(--ink-1)">Intent</text>

  <rect x="208" y="38" width="170" height="52" rx="10" fill="var(--primary-50)" stroke="var(--primary-600)" />
  <text x="293" y="69" text-anchor="middle" font-size="14" fill="var(--ink-1)">Acceptance criteria</text>

  <rect x="414" y="38" width="170" height="52" rx="10" fill="var(--sand-1)" stroke="var(--border)" />
  <text x="499" y="69" text-anchor="middle" font-size="14" fill="var(--ink-1)">Build</text>

  <rect x="620" y="38" width="170" height="52" rx="10" fill="var(--sand-1)" stroke="var(--border)" />
  <text x="705" y="69" text-anchor="middle" font-size="14" fill="var(--ink-1)">Production</text>

  <path d="M172 64 H198 M378 64 H404 M584 64 H610" stroke="var(--text-muted)" stroke-width="1.5" fill="none" />
  <path d="M198 59 l10 5 -10 5 z M404 59 l10 5 -10 5 z M610 59 l10 5 -10 5 z" fill="var(--text-muted)" />

  <path d="M460 90 V124 H293 V100" stroke="var(--primary-600)" stroke-width="1.5" fill="none" />
  <path d="M288 100 l5 -10 5 10 z" fill="var(--primary-600)" />
  <text x="288" y="142" font-size="11" fill="var(--primary-600)">Intent changed — flows back to the criterion</text>

  <path d="M540 90 V168" stroke="var(--text-muted)" stroke-width="1.5" fill="none" />
  <path d="M518 168 H562" stroke="var(--text-muted)" stroke-width="3" fill="none" />
  <text x="574" y="172" font-size="11" fill="var(--text-muted)">Mechanism changed — stops here</text>
</svg>

File the ticket where the change lands, not where you found it

The second failure is quieter and does more damage: teams capture the ticket at the point of discovery rather than the point of change. A developer finds the criterion is wrong and files "fix validation on the email field" — honest about the symptom, silent about the decision. It closes, and the criterion that caused it is still upstream waiting to mislead the next reader.

The rule that fixes it: file the ticket where the change lands, and link it from where it was found. One discovery often produces two tickets — one upstream to revise the criterion, one downstream to implement it — with the upstream one blocking. That ordering is not bureaucracy. It is the only thing that forces someone to say out loud whether the promise moved.

Found in What changed Ticket lands Update
Build — criterion is contradictory The promise Upstream, blocking the build Criteria, then the PRD line behind them
Build — a cleaner implementation Mechanism Stays in the build ticket The test. Nothing else
Design review — a step nobody specified Scope Upstream, as a new criterion Criteria and the design
Production — users do something unanticipated Intent A new upstream item, not a bug The opportunity or PRD
Production — behaviour contradicts the spec Mechanism Bug ticket The test that should have caught it

Your artefacts are the context window now

This used to be a human comprehension problem. It is now an input problem.

When an agent picks up a ticket, your artefacts are its context. The harness — whatever assembles what the model sees — pulls from the repo, the tickets, the criteria, the conventions file at the root. It can tell which of those are retrievable. It cannot tell which are current.

And an agent that meets two artefacts disagreeing does not raise its hand. It picks one, fluently, and produces something that reads exactly as plausible as the correct answer. Inconsistency used to surface as an argument in a meeting; now it surfaces as confident output. Consistency stopped being hygiene and became a correctness property of the harness — the blast radius of a stale paragraph is no longer one confused reader, it is every run that retrieves it.

We are not above this. Our own conventions file called a particular API surface dev-only for months after it had gone live in production. A human skims that and shrugs; an agent reasoning about blast radius takes it as fact and plans accordingly.

It cuts the other way too. When someone accepts or rejects an agent's proposal, that verdict is itself a change in intent — the moment the team decided what "done" means here. It belongs in a queue with a clock on it rather than a thread, and it has to flow back to the criterion it just redefined.

One fact, one home

The repair is not more diligence. It is fewer copies. Give every fact one authoritative home, then make everything else derive from it, pin to it, or point at it — in that order of preference.

Derive it. The strongest move is to delete the copy. Our issue enums lived in three hand-maintained lists, and by the time anyone looked they had drifted: a bulk-edit dialog was offering six status names that were not valid values at all. The fix was not a sync checklist. All three lists now read off the generated schema client, so adding a value reaches every one of them without anybody remembering to.

Pin it. Sometimes duplication is the right call: our marketing site keeps its own copy of the app's design tokens so the two release trains stay independent. The duplication is fine; the ambiguity would not be. So one copy is declared canonical and a test fails on drift — cheaper than a convention, and unlike a convention it tells you the day it breaks rather than the quarter after.

Point at it. When you can neither derive nor pin, say where the truth lives rather than restating it. "Check the deployed service" stays correct indefinitely; the same value transcribed into a document is correct until the next deploy. A sentence that defers outlives one that asserts.

The same instinct shaped Meshworq's decision ledger. The obvious design was a new table every decision path wrote to; we skipped it, because four places already recorded their own verdicts and a fifth meant dual-write drift plus a history starting the day we shipped. The ledger is a read model over columns that already existed. The fewer copies of a fact, the fewer can be stale.

What remains after that is a shelf of documents you genuinely cannot keep current, and trying is how the practice loses credibility. Let those age — but make them say so. The dangerous artefact is the one asserting a present-tense fact with no claim about when it was last checked. A date is not enough: it says when someone typed the thing, not when anyone verified it. "Still true as of" is the small sentence that turns a trap back into a record.

The takeaway

Flow-forward needs process. Flow-back needs a judgement, every time, from whoever found the change: did the promise move, or only the mechanism? Answer that, file the ticket where the change lands rather than where you tripped over it, and give every fact one home so there is nothing to keep in sync.

That is cheap enough to actually do, which is the only property that matters — and it is no longer just housekeeping, because the artefacts you keep consistent are the ones your agents reason from.

← All Field Notes