# A small code change can have a large consequence

> Follow a payment decision through its data, operational holds and downstream effects to judge the real scope of a change, rather than using the size of its implementation as a measure of risk.

Paper: 06.1
Published: 2026-11-05
Canonical: https://harten.io/papers/06-1-a-small-code-change-can-have-a-large-consequence/

Cover illustration: [View the title image](https://harten.io/media/papers/covers/v1/06-1-a-small-code-change-can-have-a-large-consequence.jpg?v=e2123e37c4e6). Illustrative cover artwork, not an application screenshot or a record of measured results.

## What This Paper Examines

A small function can decide whether a payment proceeds, whether an operator must investigate it and what other systems believe has happened. This paper follows one such decision through an illustrative payments application, examining what its result means to each consumer. A refused payment is not necessarily the same as an incomplete assessment, and acceptance for processing is not confirmation that money has moved. These distinctions change what an engineer needs to build and verify, even when the replacement code is short. By the end, the reader should be able to describe the actual scope of the change and give an engineer or agent a task that includes its required behaviour, dependencies and limits.

## A Boolean With Several Different Consumers

Imagine an engineer looking at a validation routine in an established payments application. It reads an account status, a payment amount and a set of exception codes, then returns a boolean: a true or false value indicating whether an instruction can proceed automatically. The team intends to implement that decision in a new application. The apparent task is small enough to describe in a few lines, and an AI coding assistant could produce a candidate implementation quickly.

For an ordinary instruction, the meaning seems straightforward. A positive result allows processing to continue. A negative result sends the instruction to a manual-review queue. But the value is also used elsewhere. A scheduled process selects payments for settlement, an operational report counts referred instructions and a customer notification derives its wording from the resulting status. A value that looks local in the source participates in several decisions outside the function.

The engineer now has a different investigation to undertake. When the scheduled process reads that status, does it mean the payment has passed its initial checks, or that it is ready to be sent? When an operator sees a referral, can they tell why it arrived and what they are expected to do? The source may show where the value is assigned without explaining all the meanings that people and other processes have attached to it. Those meanings need to be established before the replacement gives them a different representation.

The programme's requirement is not simply to reproduce the boolean. It needs the future application to make the right decision, preserve the controls that still matter and give its consumers enough information to act correctly. The new implementation can represent that decision differently. It must first establish which meanings the old value has been carrying and which of them the organisation intends to retain.

In [Modernisation should be sliced by risk, not repository structure](https://harten.io/papers/06-modernisation-should-be-sliced-by-risk-not-repository-structure/), I examined how that understanding should shape the delivery plan. Here, I want to stay with the investigation of one apparently small task. Before deciding which work to do first, we need to know what that work can actually change. A repository boundary tells us where the source lives, but not how far a decision travels or who experiences the consequences when it is wrong.

![An illustrative validation decision and its stored status feed four different consumers: a scheduled settlement process, an operational queue, an operational report and a customer notification. Each depends on a particular meaning of the result. The links may run through stored data or messages rather than direct function calls.](/assets/papers/06-1-validation-result-and-consumers.svg)

*Figure 1. The engineer needs to follow both the result and the meaning assigned to it. A stored status can affect a later process even when that process never calls the validation routine directly. These are illustrative dependencies, not a sequence in which all four consumers must run.* [View the diagram at full size](https://harten.io/assets/papers/06-1-validation-result-and-consumers.svg).

## The Difference Between a Refusal and an Unknown Result

The negative result needs investigation first. Does it mean that the instruction definitely requires manual review, or that the system could not complete its checks? An account that is known to be restricted is different from an account-status service that did not respond. In the first case, the application has information that prevents automatic processing. In the second, it lacks the information needed to decide. Treating both as the same boolean may be an inherited simplification rather than an appropriate requirement for the replacement.

Suppose a timeout causes the new application to refer instructions to an operator. That might be the agreed behaviour, but the team should establish whether operators can resolve those referrals and how quickly. If they need the same unavailable account information, moving the instruction to their queue has not supplied an answer. During a dependency failure, many such instructions could arrive together. Customers may experience delays even though the application has avoided an incorrect automatic approval.

The operational question is therefore part of the engineering scope. What information will the operator receive, what action can they take, and what happens to the instruction when the dependency becomes available again? These are not details to leave until somebody designs the queue screen. They determine whether referral is a workable response and whether an instruction could be processed twice or left waiting after its original assessment failed.

Alternatively, the service owner may require a temporary unresolved state, with a bounded retry before referral. That is a design choice to approve, not something an agent should infer from an exception handler. The future specification needs to distinguish a rejected instruction, a held instruction and an assessment that could not be completed wherever those distinctions affect subsequent behaviour. It also needs to establish who or what is responsible for the next attempt.

I would not insist on a particular return type in a paper about planning. I would insist that engineers can explain what each result means to the people and systems consuming it. A richer outcome might make that meaning easier to preserve. A boolean can still be adequate where the surrounding contract supplies the necessary context. The decision should follow the service's requirements rather than a preference for cleaner-looking code.

## Acceptance for Processing and Confirmation of Settlement

The settlement process introduces another distinction. In our example, validation establishes whether an instruction may proceed to the next stage. It does not prove that money has moved or that an external settlement system has accepted the instruction. A customer notification that says the payment is complete would therefore need a different basis from a successful validation result. Otherwise the replacement can calculate correctly and still tell the customer something that has not happened.

An engineer investigating the change needs more than the callers of the function. They need to follow the stored result, the later query or message that consumes it and the meaning assigned to that information. A shared database can conceal the relationship because the producer and consumer do not call one another directly. A scheduled task can make the effect appear well after the original calculation has finished. Searching only for direct references to the validator would leave those relationships unexplained.

The purpose of tracing this path is not to rewrite every consumer in the first piece of work. Some may remain behind an agreed interface while the replacement is built. Others may need a different representation of the decision. The team should know which arrangement it has chosen and what evidence supports compatibility. Leaving a consumer unchanged is itself a design choice when the information it receives has changed meaning.

The new application may also remove an old workaround. Perhaps operators currently use a report to distinguish accepted instructions from settled payments because the interface conflates the two. The replacement can provide those states clearly and retire the report when its remaining purpose has been accounted for. [How to decide which behaviours need to survive the migration](https://harten.io/papers/04-1-how-to-decide-which-behaviours-need-to-survive-the-migration/) develops that judgement in more detail. The planning consequence here is that the control must remain covered even when its old mechanism disappears.

## The Hold That Arrives During Calculation

The meaning of the result also depends on when it is used. Suppose the replacement reads an instruction before an operator records a hold. It then returns a positive result using the earlier information. For this example, the approved requirement is explicit: an active operational hold prevents automatic release, and only an authorised action can remove it. The calculation must not be allowed to overwrite that intervention simply because the ordinary account and amount checks passed.

The flagship paper follows this timing case in detail. For the engineer defining this task, the important consequence is what must be included in the work. Checking the arithmetic and exception codes is insufficient. The team must establish how the application recognises that the relevant state has changed and prevents a later process from acting on a stale permission. The resulting state must also remain understandable to operations.

The application might make the relevant state check and decision together, or reject a result when the version of its inputs no longer matches the current instruction. The appropriate mechanism depends on the design. What must be settled independently is the required behaviour. We examined the architectural implications in [A target architecture must explain its trade-offs](https://harten.io/papers/05-2-a-target-architecture-must-explain-its-trade-offs/); here, the question is whether that behaviour has actually been included in the task assigned to the engineer or agent.

## Payment Limits Shared Across Both Applications

Once the behaviour is understood, the team may propose a limited first introduction. Processing only low-value instructions sounds sensible because it can reduce the consequence of an individual mistake. It is not enough to establish the total exposure. The number of instructions, the period before detection and the effects on shared account state all matter to the particular release.

Suppose the service applies a daily limit across instructions from the same account. Some instructions are handled by the old application and others by the replacement. Each individual instruction may be within the permitted amount, while their combined total exceeds the account's daily limit. Both applications therefore need to use the agreed authoritative account position. Sending a small percentage of requests to the new application does not, by itself, provide either implementation with a complete view.

The team may need account-level ownership, a shared authoritative check or another deliberately designed arrangement. A group selected by payment amount may still share limits, queues and downstream capacity with everyone else. A group selected by account may be easier to reason about, but could create different operational and data-transfer requirements. I would ask what the proposed population actually isolates before describing it as a contained release.

A controlled verification exercise can investigate those interactions without moving production responsibility. The team can construct several related instructions, vary their order and introduce an operational hold while processing is in progress. The intended outcome comes from the approved requirements. The exercise then tests whether the candidate implementation preserves it under the conditions that make the boundary difficult.

## The Evidence Needed for a Proportionate Review

For this change, I would want the review to follow the significant consequences rather than the size of the code difference. The ordinary path should demonstrate that a valid instruction receives the intended result. The hold case should demonstrate that an authorised intervention is not overwritten by a stale calculation. The unavailable-dependency case should show the agreed unresolved or referral behaviour, and the downstream checks should confirm that acceptance is not mistaken for settlement. Related instructions need to exercise the shared account limit, not just pass their checks individually.

That is not a request to enumerate every conceivable failure before writing code. The investigation should identify the conditions that could materially change the decision to proceed. Where a dependency is uncertain, the team can make that uncertainty explicit and choose the next useful test. Where an established contract and existing evidence are adequate, they should be reused rather than rediscovered for the sake of ceremony.

The record should also distinguish what was observed from what was inferred. A source query can show that a batch process reads a status field. It may not establish whether that process is active in production or whether an operator supplements it manually. Configuration, execution evidence and operational review may be needed to resolve those questions. An AI-generated dependency explanation can identify a relationship to investigate; it cannot, on that basis alone, establish how the service is currently operated.

This keeps the scrutiny proportionate. A low-consequence change with a clear contract may need a small review. A short condition that influences release of funds needs closer attention to its approved meaning and effects. Both can move quickly when the team has retained the relevant knowledge and a reliable way to test the behaviour.

## A Work Package That Includes the Required Behaviour

The original task might have said only that the payment validator should be rebuilt. After this investigation, I would describe the work more concretely: implement the agreed assessment for a defined payment category in the new application, demonstrate the treatment of operational holds, unavailable inputs and shared account limits, and show how the resulting decision reaches its consumers without issuing a live settlement instruction.

That gives the work an outcome and a limit. Engineers can choose how to implement it within the agreed architecture. They can use controlled settlement responses while establishing the internal path, provided that substitution is visible and the real integration remains an explicit later check. The old application continues to operate the live service. The programme has not committed itself to extracting the old validator or transferring payment responsibility before the replacement is ready.

The work is complete when the agreed behaviour has been demonstrated for its stated scope and the findings are available to the next team. An unresolved question outside that scope may still prevent a later step. A question that undermines the behaviour this task was meant to establish cannot be treated in the same way. The team should neither conceal it behind a successful build nor keep extending a completed task because unrelated parts of the replacement remain unfinished.

The result also provides a better basis for estimation. The team now knows that the work includes state freshness, operational explanation, shared limits and downstream meaning, rather than only a small function. An honest estimate of that scope is more useful than an attractive estimate that leaves the same work to emerge later as integration defects.

## The Investigation an Engineer Can Delegate to AI

AI can make the tracing work more practical. An agent can search for uses of the validation result, compare representations across components, identify candidate exception paths and prepare tests for the cases an engineer wants to examine. It can produce an alternative implementation that is not tied to the shape of the inherited function. These are useful contributions to building a genuinely new application.

The risk is that the agent's local explanation becomes the boundary of the task. It may find the obvious callers and miss a database consumer, interpret an unfamiliar status as redundant or generate tests that reproduce its own interpretation of the boolean. A candidate implementation and matching tests can then appear coherent while leaving an operational requirement unexamined. Expected outcomes need to come from the agreed requirements and reviewed cases, not merely from what the generated code already does.

The engineer should therefore inspect the consequential relationships and the evidence behind them. An agent can identify that a hold appears to override an ordinary result, show the relevant source and prepare a proposed requirement. The person responsible for the service confirms whether that is the intended future control. Once agreed, the agent can implement and test against it without returning for approval of every mechanical edit. Investigation, approval of the requirement and permission to affect live payments remain different responsibilities.

In this example, the useful instruction to an agent is no longer simply to rebuild the validator. It includes the meanings of an incomplete assessment and an accepted payment, the treatment of operational holds, the shared account limit and the consumers that need compatible information. That gives the agent room to solve the implementation while making clear what its work must demonstrate. Faster code generation is useful here because the team has established what the code is meant to achieve beyond the function itself.

## Choosing the First Piece of Work

We began with a small validation function. By following its result, we found operational holds, timing-dependent inputs, manual-review capacity, settlement meaning and shared account state. Those findings do not automatically make the change unacceptable. They tell us what the work needs to include and which assumptions should be examined before responsibility moves.

The next choice is where to begin. The validator may be a useful starting point, but so might a deployment path, a reference-data capability or an integration exercise, depending on what the programme still needs to establish. A good first step should resolve something that matters to the intended replacement and leave a result the later work can use.

That is the question developed in **06.2, Choose the first slice for what it teaches you**. Having established the consequences of a change, we can compare possible starting points for what they allow the programme to learn, build and decide next.

---

*The payments service, its requirements and the proposed checks are illustrative. This paper develops the Series 06 example rather than reporting a customer incident, measured risk reduction or completed implementation.*

*This paper is part of The Modernisation Control Papers, the first major sequence within The Harten Papers. [Read the complete series on harten.io](https://harten.io/papers/).*
