Make Complete atomic and guard zero deadline

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-05-31 11:49:03 -04:00
parent 18108c3da3
commit a8216095de
2 changed files with 33 additions and 6 deletions
+13 -6
View File
@@ -71,12 +71,15 @@ func (c *Controller) Deadline() time.Time {
func (c *Controller) stateLocked() State {
st := State{RuntimeState: c.runtimeState}
if c.commitment != nil {
st.Commitment = &CommitmentView{
view := &CommitmentView{
NextAction: c.commitment.NextAction,
SuccessCondition: c.commitment.SuccessCondition,
TimeboxSecs: c.commitment.TimeboxSecs,
DeadlineUnixSecs: c.deadline.Unix(),
}
if !c.deadline.IsZero() {
view.DeadlineUnixSecs = c.deadline.Unix()
}
st.Commitment = view
}
return st
}
@@ -124,7 +127,9 @@ func (c *Controller) StartManualCommitment(nextAction, successCondition string,
return c.persistLocked()
}
// Complete moves Active -> Review and marks the commitment completed.
// Complete moves Active -> Review and marks the commitment completed. Both
// transitions are computed before any field is mutated, so a failure leaves
// state unchanged.
func (c *Controller) Complete() error {
c.mu.Lock()
defer c.mu.Unlock()
@@ -132,12 +137,14 @@ func (c *Controller) Complete() error {
if err != nil {
return err
}
c.runtimeState = next
if c.commitment != nil {
if s, e := statemachine.TransitionCommitment(c.commitment.State, statemachine.Complete); e == nil {
c.commitment.State = s
completed, err := statemachine.TransitionCommitment(c.commitment.State, statemachine.Complete)
if err != nil {
return err
}
c.commitment.State = completed
}
c.runtimeState = next
return c.persistLocked()
}