Stop reporting a blocker the task is no longer blocked on

F67. TaskCorrected cleared the standing question when a task resumed and
left Blocker and BlockReason in place, so task 29 ran through implement,
review and submission still reporting block_reason plan_mismatch. Every
surface that reads the projection rather than the event log showed a stop
that had already been answered.

The blocker has the same lifetime as the question beside it, and is now
cleared with it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVbaKucEYBjMqVeUgJUsc1
This commit is contained in:
2026-08-29 20:41:36 +04:00
parent cb80dd1952
commit 1330ad9943
2 changed files with 10 additions and 0 deletions
+4
View File
@@ -225,6 +225,10 @@ func TestHumanAnswerResumesTheSamePlanWithoutResealing(t *testing.T) {
if after.State != domain.StateQueued {
t.Fatalf("state = %s after the human answered, want queued", after.State)
}
// F67: the stop is over, so the projection must not keep reporting it.
if after.BlockReason != "" || after.Blocker != "" {
t.Fatalf("a resumed task still reports its blocker: %q %q", after.BlockReason, after.Blocker)
}
if after.PlanRef != planRef {
t.Fatal("answering the question replaced the plan")
}
+6
View File
@@ -588,8 +588,14 @@ func (s *Store) apply(e domain.Event) error {
// A question only stands while the task is blocked on it. Afterwards the
// answer is an ordinary standing decision and the log still holds the
// question, so keeping it on the task would put it in every later context.
//
// The blocker itself has the same lifetime and was outliving it (F67). A
// task resumed from a plan mismatch kept reporting block_reason
// plan_mismatch while it ran, so every surface reading the projection
// showed a stop that had already been answered.
if t.State != domain.StateBlocked {
t.DecisionRequest = nil
t.Blocker, t.BlockReason = "", ""
}
if phase, ok := p["lifecycle_phase"].(string); ok && phase != "" {
t.LifecyclePhase = phase