A draft pull request says, "Fix checkout timeout," and proposes an automatic retry. A reviewer can understand the suggested code and still cannot answer the important question: what happens if the first payment request reached the provider, but its response never reached the browser?

The missing information is not syntax. It is the boundary between an observation, a hypothesis, a decision, and a claim of verification.

Technical communication for developers is the practice of making those boundaries visible. It helps another engineer decide whether to approve a change, investigate an incident, or safely continue the work without guessing what the author knew.

This article uses one hypothetical checkout incident to produce four practical artifacts: a useful bug handoff, a reviewable pull request, a durable decision note, and a progress update. The example is a writing exercise, not a report from a production payment system.

Start with evidence, not the proposed fix

Imagine a user reports that clicking Pay sometimes leaves the checkout screen spinning. Someone opens a ticket:

Checkout broken. API is slow. Add a retry.

This is three different claims compressed into one sentence. "Spinning" might be an observation. "API is slow" is a possible explanation. "Add a retry" is a proposed intervention. Neither explanation nor fix follows automatically from the symptom.

Before discussing implementation, separate what is known from what is not:

TypeExample in this hypothetical caseWhat it allows a teammate to conclude
ObservationThe UI keeps showing a loading state after a request times out in the browser.The client did not observe completion.
HypothesisThe network response may have been lost after the provider processed the request.This failure mode needs investigation.
DecisionDo not add an unconditional payment retry until the provider's attempt and idempotency behavior are understood.A risky implementation is intentionally deferred.
VerificationNo provider-side reconciliation or replay test has been run.The payment outcome remains unknown.

The distinction matters because a client-side timeout is not evidence that a charge failed. A new request could represent a different payment attempt, depending on the provider and integration. For example, Stripe's low-level error guidance explains that network failures can leave a client uncertain whether the server received a request, and its idempotency documentation describes provider-specific retry behavior. Stripe is an example, not the provider in this hypothetical incident. The right recovery behavior must come from the actual integration's API contract and request history, not from a general rule about retries.

A useful handoff might be:

Symptom: Checkout remains in a loading state after the browser request times out.

Known: The browser did not receive a successful response. We have not confirmed the provider's final payment state.

Risk to investigate: Repeating the charge request without reconciliation may be unsafe.

Next action: Capture a redacted request identifier, inspect the provider's attempt status, and confirm the documented retry or idempotency behavior before changing client logic.

Notice what this does not say. It does not declare the payment failed, diagnose the provider as slow, or pretend the next action has already succeeded. It gives the next engineer a bounded investigation.

Write a pull request around the decision a reviewer must make

Suppose the team is considering a change to recover the UI after a timeout, but has not yet confirmed the provider's retry and reconciliation contract. A description like "Handle checkout errors; tested locally" would obscure both the proposed behavior and that outstanding investigation.

Instead, make the PR answer five questions:

  1. Problem: What user-visible failure or engineering constraint is being addressed?
  2. Scope: What behavior changes, and what intentionally stays unchanged?
  3. Reasoning: Why was this approach chosen over a relevant alternative?
  4. Evidence: Which exact checks were run, and which were not?
  5. Risk: What could still fail, and how would the team detect or reverse it?

Here is an illustrative PR proposal, not a completed implementation. The unanswered provider question and unchecked validation steps are intentional:

Title: Proposal: Restore a recoverable checkout state after timeout
Status: Design proposal; no implementation or validation claimed

Problem
The checkout UI can stay in a loading state when the browser
does not receive the response to a payment attempt.

Proposed change
- Show a recoverable, non-success state after the client times out.
- Preserve the existing payment attempt identifier for follow-up.
- Do not create another charge attempt automatically.

Provisional decision
A timeout cannot establish the provider's final payment state.
Hold any retry behavior until the provider-specific contract is verified.

Validation to perform
[ ] Simulate a dropped response after provider acceptance.
[ ] Confirm the UI does not submit a second charge by itself.
[ ] Verify recovery and status messaging with keyboard navigation.
[ ] Confirm provider status lookup and failure paths.

Not yet verified
The exact provider endpoint's reconciliation and idempotency contract,
its behavior after a lost response, and production monitoring.

Rollback plan, if implemented
Revert the client UI change if it causes incorrect recovery states.
Do not alter or delete server-side payment attempt records.

This is a proposed change specification, not a claim that these actions have been implemented or that the test boxes passed. A real PR should replace placeholders with actual commands, trace links, environments, and results.

Google's public guidance on writing change descriptions emphasizes recording both what changed and why, including decisions that the code alone cannot reveal. Its review checklist also considers behavior, design, tests, complexity, and documentation. These are useful review questions, not mandatory rules for every repository.

The test section is especially important when a failure seems environment-dependent. A local pass should not be described as CI verification; the Playwright CI debugging guide walks through why those observations can differ.

Put context where someone will look for it later

A comment, commit message, PR description, and README serve different readers. Duplicating the entire story in all four places creates maintenance work. Put information where it can answer the next likely question.

ArtifactThe question it should answer
Code commentWhy does this unusual behavior or constraint exist here?
Commit messageWhat changed in this unit of history, and why if not obvious?
Pull requestIs this change justified, sufficiently checked, and safe to review?
Decision noteWhat alternatives and tradeoffs shaped the lasting approach?
README or task guideHow does someone set up, use, or operate the system?

A local comment might be appropriate beside an intentionally absent retry:

// A browser timeout does not establish the payment outcome.
// Reconcile the existing attempt before permitting another charge.

This is an illustrative policy comment, not runnable payment-handling code. It is useful only if the implementation and provider contract actually enforce that rule. Otherwise, it is misleading documentation attached to unsafe behavior.

For a commit, a subject such as fix(checkout): recover UI after timeout identifies the change more clearly than fix stuff. If the reason is not obvious from the diff, a short body can explain the constraint. The Git commit documentation recommends a short subject followed, when useful, by a more detailed body. Conventional Commits is one optional shared format, not a requirement for understandable history.

For a long-lived architectural decision, record the options the team actually considered and the condition that would cause reconsideration. The checkout scenario has an unresolved provider contract, so the example decision note should keep that limitation visible:

Decision note: Checkout timeout recovery (illustrative)
Status: Provisional; implementation not approved
Context: A client timeout leaves the provider-side outcome unknown.
Options: (1) Submit another charge request automatically.
         (2) Retain the attempt and use the provider-supported
             status or idempotent retry mechanism after verification.
Decision: Do not add an unconditional charge retry. Investigate
          the provider's exact contract before choosing a recovery path.
Tradeoff: Delaying recovery may increase user friction; submitting
          an unsafe request could create an unintended second attempt.
Evidence needed: Provider API documentation, attempt trace, and a
                 controlled lost-response test.
Revisit when: The provider contract is confirmed, or the integration
              changes its request semantics.

This is not an approved architecture record. It demonstrates how to preserve an open decision, rather than dressing up an assumption as a settled design.

A README is the wrong place for a timeline of every debugging attempt. It is better suited to a reproducible setup, usage steps, operational constraints, and links to the source of truth. The Diátaxis framework distinguishes tutorials, task-oriented how-to guides, reference material, and explanation because readers use each for different purposes. That distinction helps keep operational instructions separate from design reasoning.

Report uncertainty without making the update useless

Technical updates often fail in one of two ways: vague confidence ("almost fixed") or an unfiltered dump of logs. Both push the decision back to the reader.

An actionable status update says what changed, what evidence supports it, what remains unresolved, and who owns the next check. For example:

Checkout timeout investigation (hypothetical)

Observed: The browser request times out; the provider outcome is unknown.

Change so far: The initial unconditional retry proposal has not been approved or deployed. The safer recovery approach remains a proposal.

Decision pending: Which status lookup or idempotent retry behavior the provider supports.

Next check: Inspect attempt records and simulate a lost response using the provider's documented test environment.

Next check owner: Unassigned. The checkout integration maintainer needs to be identified.

Release status: No recovery change approved. No production resolution is being claimed.

A status update should be dated and assigned to a real person in an actual incident. This fictional example deliberately marks ownership as unassigned instead of inventing an incident timestamp, test result, or responsible engineer.

Different audiences need different detail. A reviewer needs the decision and evidence. An on-call engineer needs the current user impact, containment, and next action. A product stakeholder needs the user-facing consequence and confidence level without losing the central uncertainty. The facts should stay consistent even when the explanation changes.

Ask for review comments that can be acted on

"Bad approach" gives little information. A useful review comment identifies the behavior, why it matters, and the decision needed:

In the timeout handler, this calls the charge endpoint again without checking the first attempt's status. Can we confirm the provider's idempotency behavior and add a test for a lost response before enabling the retry?

That is a question anchored to a visible implementation risk, not a claim that the author is careless. If the provider guarantees safe idempotent retries with a correctly reused key, the answer may justify a different design. The point is to expose the assumption.

Likewise, authors can respond with evidence rather than defensiveness: "The provider documentation specifies X for this endpoint, and test Y covers a dropped response" is useful only when X and Y are real and linked. "Works for me" does not resolve the concern.

When reviewing style or naming, distinguish preferences from correctness. Google's review guidance treats style nits differently from issues affecting design, behavior, or maintainability. Teams can adopt their own conventions, but comments should make priority clear.

A five-minute communication check before handing off work

Before sending the ticket, PR, or status update, ask:

  • Could someone distinguish what I observed from what I suspect?
  • Is the requested decision or next action explicit?
  • Can the reader find the evidence and reproduce the relevant check?
  • Have I stated a material risk, limitation, or untested path?
  • Will this still make sense to someone who was not in the meeting?

You do not need a long document for every change. A typo fix may need a one-line explanation. A payment recovery change needs more context because its consequences and unknowns are different. The measure is not how much was written, but how little another engineer must guess before acting safely.