Record accepted execution control decisions

This commit is contained in:
2026-11-14 16:59:50 +00:00
parent 3ace6ddb57
commit 5ad1b7aa6e

View File

@@ -1,9 +1,8 @@
# Execution Controls For Coordinated Turns # Execution Controls For Coordinated Turns
Status: proposed follow-up to v0.22.0. This document describes the target behavior Status: all four design decisions accepted; ready for API and staged
and implementation work; the significant choices at the end remain open. No code implementation planning from v0.22.0. No code changes are authorized by this
changes are authorized by this roadmap. Public names and signatures are not yet roadmap. Public names and signatures are not yet selected.
selected.
## Purpose ## Purpose
@@ -50,6 +49,10 @@ request when execution returns no result.
## Target End State ## Target End State
The selected approach is optional per-request controls honored by ordinary `Run`
and therefore by `Coordinate`. The accepted decisions below specify their
lifecycle; the coordinator does not delegate execution to an application executor.
### Optional Operation Timeout ### Optional Operation Timeout
An application can select a duration for each requested continuation. When that An application can select a duration for each requested continuation. When that
@@ -88,7 +91,7 @@ again. Retaining or modifying delivered details must not mutate the execution.
The application can retain them after provider failure or cancellation even when The application can retain them after provider failure or cancellation even when
no ordinary result or exchange is returned. If preparation fails, no complete no ordinary result or exchange is returned. If preparation fails, no complete
snapshot is required. Cancellation before notification does not promise delivery; snapshot is required. Cancellation before notification does not promise delivery;
its precise boundary is proposed in Open Decision 3. follow the context checks in [Decision 3](#3-what-is-the-prepared-details-callback-contract).
This access exposes logical prepared content, not raw HTTP envelopes or internal This access exposes logical prepared content, not raw HTTP envelopes or internal
structural-repair requests. Keep it separate from metadata-only observers and structural-repair requests. Keep it separate from metadata-only observers and
@@ -106,15 +109,15 @@ events or counting attempts twice.
Avoid changing the coordinator to an explicit public prepare/run sequence merely Avoid changing the coordinator to an explicit public prepare/run sequence merely
to obtain details: that would change ordinary admission and preparation-failure to obtain details: that would change ordinary admission and preparation-failure
observation behavior. Reuse the execution path and its existing ownership observation behavior. Reuse the execution path and its existing ownership
boundaries. Exact public controls and split-preparation semantics remain open boundaries. Follow the accepted split-preparation and callback semantics below;
below; do not silently ignore a newly supplied option on one entry point. do not silently ignore a newly supplied option on one entry point.
## Work From The Baseline ## Work From The Baseline
1. **Settle the public lifecycle.** Resolve the open decisions below and write 1. **Design the public API.** Write small ordinary-run, coordinated-turn, and
small ordinary-run, coordinated-turn, and split-preparation usage sketches. split-preparation usage sketches under the accepted lifecycle below. Specify
Specify omitted/zero/negative timeout handling using ordinary duration omitted/zero/negative timeout handling using ordinary duration conventions,
conventions, callback invocation timing, and retained callback cleanup. and express the selected callback timing and cleanup in the public contract.
Choose names and signatures without adding a broader lifecycle-hook framework. Choose names and signatures without adding a broader lifecycle-hook framework.
2. **Add operation-budget handling.** Establish and clean up the child scope at 2. **Add operation-budget handling.** Establish and clean up the child scope at
the selected execution boundary. Preserve earlier parent deadlines and public the selected execution boundary. Preserve earlier parent deadlines and public
@@ -126,7 +129,7 @@ below; do not silently ignore a newly supplied option on one entry point.
Preserve credential handling and release resources on cancellation or panic. Preserve credential handling and release resources on cancellation or panic.
Avoid snapshot-copy work when the capability is not selected. Avoid snapshot-copy work when the capability is not selected.
4. **Integrate and verify coordination.** Have ordinary execution honor the 4. **Integrate and verify coordination.** Have ordinary execution honor the
selected controls on the callback-returned request under the recommended API. selected controls on the callback-returned request under the accepted approach.
Preserve capture and observer composition; verify the next-turn callback runs Preserve capture and observer composition; verify the next-turn callback runs
with the parent context after admission and child-budget cleanup. with the parent context after admission and child-budget cleanup.
5. **Document and demonstrate.** Update public GoDoc, the 5. **Document and demonstrate.** Update public GoDoc, the
@@ -143,13 +146,14 @@ are needed. Keep implementation proportional to the two requested controls.
Use offline public-boundary tests and existing execution collaborators, with Use offline public-boundary tests and existing execution collaborators, with
controlled cancellation and synchronization rather than fragile timing margins. controlled cancellation and synchronization rather than fragile timing margins.
Cover the consumer request's [acceptance scenarios](audita-request.md#acceptance-scenarios) Cover the consumer request's [acceptance scenarios](audita-request.md#acceptance-scenarios)
and the lifecycle choices ultimately selected: and the accepted lifecycle choices:
- Successive turns receive fresh budgets: their combined duration may exceed one - Successive turns receive fresh budgets: their combined duration may exceed one
operation budget without exhausting either individual operation. operation budget without exhausting either individual operation.
- Preparation, admission waiting, retries, validation, and repair share the same - For ordinary and coordinated runs, preparation, admission waiting, retries,
operation deadline. Local expiry stops coordination without canceling parent validation, and repair share the same operation deadline. Local expiry stops
or sibling work; earlier parent cancellation/deadlines remain effective. coordination without canceling parent or sibling work; earlier parent
cancellation/deadlines remain effective.
- Next-turn assessment uses the parent context after release, including another - Next-turn assessment uses the parent context after release, including another
call to a backend with capacity one. Timeout identity survives public wrapping. call to a backend with capacity one. Timeout identity survives public wrapping.
- Prepared details precede generation, contain the assembled continuation, and - Prepared details precede generation, contain the assembled continuation, and
@@ -159,38 +163,50 @@ and the lifecycle choices ultimately selected:
observer lifecycle is introduced. Existing credential redaction remains intact. observer lifecycle is introduced. Existing credential redaction remains intact.
- Preparation failure, cancellation around notification, and callback panic follow - Preparation failure, cancellation around notification, and callback panic follow
the selected delivery rules and do not strand admission or retained resources. the selected delivery rules and do not strand admission or retained resources.
- Split preparation follows its documented budget and callback lifecycle. Neither - Split preparation uses its supplied context and retains the selected duration
discarded nor unsuccessfully claimed handles start execution notifications. for `RunPrepared`; idle time does not consume that execution budget. A shared
caller deadline can still bound both calls. Neither discarded nor unsuccessfully
claimed handles start execution notifications.
- The prepared notification receives detached details and the operation context,
has no error return, and runs synchronously within the operation budget.
- Local-budget expiry has a narrow inspectable identity while preserving standard
context matching; parent and provider deadlines are not mislabeled as local.
- Observers/groups retain ordinary facts on success and failure. No-option use, - Observers/groups retain ordinary facts on success and failure. No-option use,
completed-result delivery, and final-turn behavior remain compatible. completed-result delivery, and final-turn behavior remain compatible.
## Open Decisions ## Accepted Decisions
All four decisions below are accepted. No significant product decisions remain
open. Exact public names, signatures, timeout-value conventions, and the Go
representation of timeout identity remain for API and implementation planning.
### 1. Narrow Execution Controls Or Caller-Delegated Execution? ### 1. Narrow Execution Controls Or Caller-Delegated Execution?
**Recommendation:** add optional per-request execution controls honored by ordinary **Accepted approach:** add optional per-request execution controls honored by
`Run` and thus by `Coordinate`, including a timeout and prepared-details callback. ordinary `Run` and thus by `Coordinate`, including a timeout and
This keeps history, capture, admission, errors, and observers in their existing prepared-details callback. This keeps history, capture, admission, errors, and
owners and makes the capability useful outside coordination. A caller can select observers in their existing owners and makes the capability useful outside
different controls on each returned request; an additional coordinator-wide coordination. A caller can select different controls on each returned request;
configuration layer is not needed for the demonstrated use case. an additional coordinator-wide configuration layer is not needed for the
demonstrated use case.
**Viable alternative:** let the coordinator delegate a turn to a caller-provided **Alternative considered, not selected:** let the coordinator delegate a turn
executor or prepared-execution adapter. This would reuse Audita's existing adapter to a caller-provided executor or prepared-execution adapter. This would reuse
and accommodate other execution customizations. It also requires a larger contract Audita's existing adapter and accommodate other execution customizations. It
for exchange assembly, capture, observer composition, handle cleanup, and admission also requires a larger contract for exchange assembly, capture, observer
release. Prefer it only if concrete API sketches show it is materially simpler composition, handle cleanup, and admission release. The narrow controls meet
than the narrow controls, not merely more extensible. the demonstrated need with fewer ownership questions; caller-delegated
execution is not part of this feature.
### 2. What Does A Timeout Mean For Split Preparation And Execution? ### 2. What Does A Timeout Mean For Split Preparation And Execution?
**Recommendation:** bound each `Run` invocation from before preparation. For **Accepted approach:** bound each `Run` invocation from before preparation. For
`PrepareExecution`, retain the selected duration as an execution control and apply `PrepareExecution`, retain the selected duration as an execution control and
it when `RunPrepared` starts; preparation itself continues using its supplied apply it when `RunPrepared` starts; preparation itself continues using its
context. Do not retain a live timer across an idle prepared handle. Explicitly supplied context. Do not retain a live timer across an idle prepared handle.
explain that this bounds the remaining execution, not preparation already done. Explicitly explain that this bounds the remaining execution, not preparation
Callers needing one total budget across both calls can continue passing the same already done. Callers needing one total budget across both calls can continue
caller-created deadline context, as Audita does today. passing the same caller-created deadline context, as Audita does today.
This preserves the distinction between executing now and preparing for later, This preserves the distinction between executing now and preparing for later,
while letting a prepared handle carry the same selected execution controls. It while letting a prepared handle carry the same selected execution controls. It
@@ -198,21 +214,22 @@ requires clear documentation: the duration alone does not retroactively cover
split preparation. `Prepare` and `ValidateRequest` likewise do not become timed split preparation. `Prepare` and `ValidateRequest` likewise do not become timed
executions merely because they accept request-shaped input. executions merely because they accept request-shaped input.
**Viable alternative:** start a budget during `PrepareExecution` and carry its **Alternative considered, not selected:** start a budget during
remaining deadline into `RunPrepared`. This directly bounds preparation and `PrepareExecution` and carry its remaining deadline into `RunPrepared`. This
execution together without caller context plumbing. It also counts idle time, directly bounds preparation and execution together without caller context
requires timer/context ownership and discard semantics, and changes what a plumbing. It also counts idle time, requires timer/context ownership and
prepared handle retains. This is useful if a consumer needs a whole prepared discard semantics, and changes what a prepared handle retains. This is useful
operation lifetime, but exceeds the current coordinated-turn requirement. if a consumer needs a whole prepared operation lifetime, but exceeds the
current coordinated-turn requirement.
### 3. What Is The Prepared-Details Callback Contract? ### 3. What Is The Prepared-Details Callback Contract?
**Recommendation:** a synchronous notification receiving the operation context **Accepted approach:** a synchronous notification receiving the operation
and a detached prepared value, with no error return. Invoke it once after the context and a detached prepared value, with no error return. Invoke it once
snapshot is ready and before generation, only when execution proceeds to that after the snapshot is ready and before generation, only when execution proceeds
point. For prepared handles, retain the callback until execution and clear it to that point. For prepared handles, retain the callback until execution and
on claim/discard like the existing observer; inspection remains available earlier clear it on claim/discard like the existing observer; inspection remains
through `Details()` without triggering the notification. available earlier through `Details()` without triggering the notification.
Check context before notification and again before generation. Include callback Check context before notification and again before generation. Include callback
time in the operation budget and retain ordinary cooperative cancellation and time in the operation budget and retain ordinary cooperative cancellation and
@@ -227,31 +244,32 @@ capacity-one nested-execution behavior. Do not prohibit arbitrary callback work;
applications must account for the held capacity and operation budget. Releasing applications must account for the held capacity and operation budget. Releasing
and reacquiring admission solely for notification is not necessary for this scope. and reacquiring admission solely for notification is not necessary for this scope.
**Viable alternative:** let the callback return an error to veto generation. **Alternative considered, not selected:** let the callback return an error to
This supports mandatory audit persistence or an application pre-generation check, veto generation. This supports mandatory audit persistence or an application
with ordinary cleanup and error propagation. It also makes the callback an pre-generation check, with ordinary cleanup and error propagation. It also
execution gate and requires failure classification semantics absent from the makes the callback an execution gate and requires failure classification
optional-diagnostics request. Select it if that broader control has a concrete semantics absent from the optional-diagnostics request. The selected
consumer need; optional write failures can still be handled locally either way. notification satisfies that request; a generation veto would require a separate
demonstrated need.
### 4. How Precisely Should Local Timeout Errors Be Identified? ### 4. How Precisely Should Local Timeout Errors Be Identified?
**Recommendation:** preserve standard context matching and provide a narrow, **Accepted approach:** preserve standard context matching and provide a narrow,
inspectable operation-timeout identity when this newly selected budget causes inspectable operation-timeout identity when this newly selected budget causes
termination. Keep parent cancellation/deadlines and provider-local failures under termination. Keep parent cancellation/deadlines and provider-local failures
their existing identities. The marker must survive public wrapping and must not under their existing identities. The marker must survive public wrapping and
be inferred from any arbitrary `DeadlineExceeded` returned by a collaborator. must not be inferred from any arbitrary `DeadlineExceeded` returned by a
Choose its Go representation during API design; no new error-report hierarchy collaborator. Choose its Go representation during API design; no new
or terminal-event category is implied. error-report hierarchy or terminal-event category is implied.
This lets callers distinguish the requested local budget from an earlier parent This lets callers distinguish the requested local budget from an earlier parent
or provider deadline without retaining the internal child context. Define cause or provider deadline without retaining the internal child context. Define cause
selection around races using the child context's recorded cause; do not promise selection around races using the child context's recorded cause; do not promise
perfect ordering of independently simultaneous cancellations. perfect ordering of independently simultaneous cancellations.
**Viable alternative:** return only existing context errors and let callers **Alternative considered, not selected:** return only existing context errors
inspect their parent context. This is smaller and often sufficient when the and let callers inspect their parent context. This is smaller and often
parent remains active. However, `DeadlineExceeded` alone may also originate in sufficient when the parent remains active. However, `DeadlineExceeded` alone
a provider timeout, and a parent may become canceled before the caller inspects may also originate in a provider timeout, and a parent may become canceled
it. It supplies weaker attribution; choose it only if Audita confirms that this before the caller inspects it. That weaker attribution does not meet the
meets its classification requirement. selected distinction as directly as a narrow operation-timeout identity.