Separate probabilistic development from deterministic shipping
I want a coding agent to explore alternatives. I want a release controller to make the same decision when it sees the same accepted inputs.
Those are different jobs. Development benefits from search: several implementations, competing explanations, a new test when the first hypothesis fails. Shipping needs a narrower contract. Which commit was reviewed? Which tests belong to it? Which base will receive it? Has this exact attempt already ended? If the answer is missing, who owns the next decision?
In our release-pipeline work, I separated those responsibilities into a controller and fixed executors. The controller admits candidates, derives an attempt identity and decides whether that identity is eligible to proceed. The executor owns a specified sequence of integration and deployment actions. A model can help build either component. Its opinion is not an extra release state.
The useful result is an architecture with inspectable decisions. One source-bound offline exercise now covers 77 cases around admission, identity, retries, damaged state and quarantine. That gives me concrete boundaries to discuss without turning a passing local exercise into a claim about a live deployment.
Separate exploration from the release decision
During implementation, a failed test can legitimately trigger another design. A reviewer can reject the first approach and ask for a smaller change. An agent can gather more evidence or consult a stronger model. The work product is still a candidate.
A shipping controller has a different responsibility. It receives an identified candidate and evidence produced by other owners. It checks whether the candidate meets the release contract. When a condition is absent, it should identify the missing condition. It should not quietly become another development agent, generate a repair, run a different collection of tests and then certify the result it just changed.
That boundary reduces the number of meanings attached to “ship.” A candidate can be refused because its review is incomplete. An attempt can be held because release state is unreadable. An executor can report that the base moved. Each outcome points to a different next action.
I still want repair automation. I give it a development identity and send its output back through admission. That keeps a repair from inheriting the authority of the release attempt that discovered the problem. It also makes the cost visible: the organization can distinguish a release execution from another round of development.
Bind evidence to the exact candidate
The admission function begins with a lane and its tip commit. It asks the gate for a contract over that pair. In the extracted implementation, a failed clause or a contract with fewer than seven returned clauses prevents admission.
The number seven is a configured floor in this implementation, not a universal definition of release safety. The important design question is who owns the contract and whether the result is complete. A tuple of seven arbitrary true values cannot establish an authentic review. Our offline gate deliberately supplies synthetic facts so we can exercise the controller's response; the real gate needs its own evidence and tests.
The owning-test record is a separate requirement. Admission selects records whose SHA matches the candidate's exact tip. A PASS for another commit does not help. A neighboring FAIL for the same commit keeps the candidate out even when a PASS also exists. Record ordering cannot make an unfavorable result disappear.
That is a specific evidence policy. Another organization might introduce an authenticated supersession mechanism for obsolete records. This implementation does not infer one from append order. If the organization wants to replace an old failure with a new accepted result, that needs an explicit policy and identity rather than a convenient last-row assumption.
An advisory precheck saying “pass” also does not become an owning-test receipt. I keep the quick signal useful while preserving the stronger obligation. A preliminary check can help an operator decide what to investigate; it cannot silently satisfy a different owner's acceptance requirement.
Derive the attempt identity from accepted inputs
A release name is a label. I need an identity that changes when the release's relevant inputs change.
The controller derives a key from the repository, integration base, sorted lane-and-tip pairs and gate version. The retained function is small enough to read directly:
def attempt_key(repo, base, admitted, gv=None):
pairs = sorted((c['lane'], c['tip']) for c in admitted)
return hashlib.sha256(json.dumps([repo, base, pairs, gv or gate_version()]).encode()).hexdigest()[:24]
Sorting makes input ordering irrelevant. Reordering two accepted candidates should not create a new opportunity to repeat the same release attempt. Changing a candidate tip, its lane, the base, the repository or the gate version does change the key.
The key is 24 hexadecimal characters in this implementation. That is an identifier derived from a digest, not a signature and not proof that the inputs were authorized. It also preserves duplicate lane-and-tip entries; sorting does not deduplicate them. The source of admitted candidates must maintain whatever uniqueness contract the release system requires.
Including the gate version prevents a revised acceptance policy from sharing an identity with an attempt judged under a different policy. That version still needs a trustworthy definition. An injected string is sufficient for testing key sensitivity, but production needs to bind it to the actual acceptance implementation and configuration being used.
Count an unfinished start as an attempt
The difficult retry is the one that never produced a result.
A controller records a start, then the process dies. Maybe the executor never launched. Maybe it changed something and the machine failed before recording the outcome. Treating the next observation as “new inputs” erases the attempt that created the uncertainty.
The retained journal distinguishes start rows from result rows. For a given key, the retry rule counts the greater of the number of starts and the number of results. A start without a result therefore consumes an attempt. The configured allowance is two infrastructure retries, meaning an initial attempt plus two retries: three total, not two.
The rule permits retryable classes named infrastructure, held and unfinished. After the allowance is exhausted, the same inputs need a person. That is a bounded recovery policy around uncertain work. It does not prove that repeating the executor is harmless. An executor that charges a customer, sends a message or performs another external effect still needs an operation identity and a reconciliation contract appropriate to that effect.
A new integration base creates a different release identity, but it does not absolve an unresolved external operation. I keep those two levels distinct: a release attempt key answers which integration attempt this is; a payment or notification identity answers whether that particular effect already happened.
Keep terminal results terminal
Some results end the attempt for those inputs. The implementation treats every result class outside the three retryable classes as final. That includes shipped, failed, nothing, main-moved and model-call-refused, as well as an unknown class.
A later infrastructure row cannot reopen an earlier final result. The rule looks for any final result for the key before considering retries. This matters when records arrive through different paths or an operator inspects a mixed history. A final outcome should not become retryable merely because the last line looks recoverable.
Unknown result classes also become final under this rule. That is conservative about automatic repetition, but it creates an operational obligation: someone must interpret the unfamiliar result. Treating an unknown class as terminal does not mean treating the overall task as successful. The state needs a named owner, retained evidence and an explicit route back into development or reconciliation.
I want dashboards to preserve that distinction. “No automatic retry” is a scheduling decision. “The customer received the intended result” is an outcome claim. Collapsing them into a green status would destroy the information the controller worked to retain.
Distinguish absent state from damaged state
A missing journal is a valid empty history for this local protocol. A present journal containing torn JSON or a non-object row is a different fact.
The Journal reader raises a typed corruption error for the damaged case. The plan catches that error and returns held. A truncated quarantine file follows the same path. Neither becomes an empty structure that admits all candidates.
This is a small implementation choice with a large consequence. If unreadable history means “nothing happened,” a storage failure can grant fresh permission to repeat old work. If unreadable quarantine means “nothing is quarantined,” damage can release the exact candidate a previous failure isolated.
The offline exercise creates those files in an owned scratch directory, writes several malformed representations and observes the actual exceptions and held plans. It also checks missing files, valid append/read behavior and quarantine round trips. Those are behavioral checks of the local format contract.
They do not qualify crash durability. The append implementation does not, by itself, establish an fsync protocol, concurrent-writer serialization, tamper resistance or an atomic reservation spanning planning and execution. Those are separate design obligations if the controller's deployment requires them.
Quarantine a failed input without freezing the whole lane
A failed candidate can appear in later combinations. If the next attempt changes the base or adds another accepted candidate, it gets another key. Without an input-level exclusion, the known-bad candidate could return as a passenger in a new attempt.
The retained plan therefore collects quarantined lane-and-tip pairs separately from attempt history. A matching pair is refused before admission. A new tip on the same lane is eligible to be evaluated under the normal contract.
That scope matters operationally. Quarantining the entire lane would also block a repaired commit. Quarantining only the previous attempt key would allow the same failed input into a different combination. Pair-scoped quarantine separates those two problems: the attempt history controls repetition of a particular integration, while quarantine controls reuse of an identified candidate.
Attribution remains a harder responsibility. The offline plan consumes a quarantine record; it does not prove the executor correctly blamed the candidate or that the operator who created the record had authority. A good failure packet should retain the candidate, observed failure, attribution evidence, owner and the condition for re-entry. The narrow controller cannot manufacture those facts from a failed process status.
Let holds and modes retain their meaning
An eligible candidate is not sufficient to run. The plan also consumes release holds and the repository's configured mode.
A hold produces a held outcome even when candidates otherwise pass. With no admitted candidates, the outcome is nothing. A missing or malformed integration base prevents a runnable plan. A configured plan-only repository produces would-run instead of run. A terminal history for the derived key produces skip.
These are useful typed decisions because they point to different owners. A review refusal returns to the candidate owner. A release hold belongs to the hold owner. A missing base requires a repository-state investigation. A plan-only mode is an operating policy, not a failure for an agent to repair away.
I would expose those facts together: candidate identity, admission reasons, holds, base, key, mode and retry explanation. The operator should be able to compare two evaluations and see which input changed the decision. A fluent summary can sit above that record, but it must not replace the record.
A runnable plan is still a plan. There is a time between observing eligibility and performing an effect. A production executor needs a defined recheck or reservation protocol for the facts that can change in that interval. This exercise does not create that atomicity by returning the word run.
Make the executor boundary real
A fixed command list helps make shipping inspectable. It is not sufficient to establish that the entire execution environment is deterministic or unable to call a model.
The source includes executor preflight and a guarded execution design. Our source-bound exercise injects the preflight result and never invokes the executor. That gives the exercise a clear job: verify that a refusal prevents admission and that accepted preflight facts let the other admission conditions matter.
To qualify the real boundary, I would inspect every effective route: subprocesses, nested scripts, remote hosts, absolute executable paths, credentials, network access and any helper that can initiate development work. A lexical scan of declared scripts cannot stand in for complete control over those routes. Nor does an environment variable become evidence that the protected execution context exists.
The architectural goal is a constrained release lane with explicit inputs and externally enforced capabilities. Deterministic shipping still depends on mutable external systems, so the practical promise is repeatable decisions, bounded actions and attributable outcomes. It is not mathematical determinism over the internet.
The same separation helps with cost. A release controller should not unexpectedly start another long model conversation because an executor encountered a repairable problem. It can return a typed failure packet to development. The resulting repair gets its own budget and acceptance cycle.
Review the decision table before adding automation
I start with one candidate and trace it across five questions: which evidence admits it, which inputs identify the attempt, which history allows repetition, which input-level failures exclude it and which external observation proves the intended release happened.
Then I vary one fact at a time. Keep the marker pass and remove the owning receipt. Add a FAIL beside a PASS. Reverse the accepted candidate ordering. Leave a start without a result. Put a retryable row after a final result. Damage the quarantine file. Replace the quarantined tip with a new one.
Those probes tell an operator more than another impressive agent demonstration. They reveal whether the shipping system preserves the distinctions its recovery procedure depends on. They also give an independent reviewer specific fault hypotheses to challenge without requiring that reviewer to trust the author's explanation.
For CTOs, the operating benefit is ownership. Development owns finding a correct candidate. Review and testing own their evidence. Release control owns the eligibility decision. The executor owns specified actions. Acceptance owns whether the customer-facing result is satisfactory. A supervisor can coordinate those roles while keeping their authority separate.
Choose one current release path and write that table. If “the agent handles it” spans several of those owners, split the states until the next action and its evidence are explicit. That is a useful foundation for adding more automation.
How this was verified
This essay uses nine complete, verbatim definitions from gorunner commit c7a93e832e8d7897d5b47403560ec91d20eb2c27, with per-definition hashes and retained design/owning-test context. The source-only packet was committed before the author exercise.
The offline exercise runs 77 cases against compiled source bytes with real local journal files. Gate contracts, receipt rows, candidate discovery, holds, base lookup, gate version and executor preflight are injected facts. Three syntax-valid author fault controls fail assertions; the restored exercise exits zero. An independent reviewer pinned 29 mutations before reading the exercise; the initial exercise caught all 29 with a clean control. The retained receipt binds the source and exercise hashes. Four original admission tests also passed against byte-identical pinned source, with 70 other tests deselected; no executor test ran. These numbers describe case coverage, not deployment reliability, production defects prevented or throughput.
The historical design document and module header contain advisory-precheck language that differs from the actual admission function. This essay follows the executable requirement: ledger PASS or the explicit tested adapter, with exact-tip FAIL dominant. Current activation, authentic upstream evidence, executor isolation, concurrent controller safety, crash durability, external effects and production readback are not established by this exercise.
