Reconcile docs with reality; fix module graph, token compare, health #1
@@ -612,9 +612,14 @@ func (s *Store) apply(e domain.Event) error {
|
||||
if t.State != domain.StateBlocked {
|
||||
t.DecisionRequest = nil
|
||||
t.Blocker, t.BlockReason = "", ""
|
||||
// The human's answer outranks the plan and stands as an ordinary
|
||||
// decision, so the contradiction it settled is no longer live.
|
||||
t.PlanMismatch = nil
|
||||
// The contradiction is cleared only by the correction that answers the
|
||||
// stop, never by any other event that happens to find the task
|
||||
// unblocked. This block runs for every event, and clearing it here
|
||||
// unconditionally erased the contradiction at the very rotation the
|
||||
// reopen causes, which is exactly when the planner needs it.
|
||||
if e.Type == "TaskCorrected" {
|
||||
t.PlanMismatch = nil
|
||||
}
|
||||
}
|
||||
if phase, ok := p["lifecycle_phase"].(string); ok && phase != "" {
|
||||
t.LifecyclePhase = phase
|
||||
|
||||
@@ -723,3 +723,72 @@ func TestBlockRetainsLeaseEpochForALaterReopen(t *testing.T) {
|
||||
t.Fatalf("last lease epoch %q, want %q", after.LastLeaseEpoch, epoch)
|
||||
}
|
||||
}
|
||||
|
||||
// F66's projection has to survive the rotation the reopen causes. The session
|
||||
// that reported the contradiction hands off, a successor leases, and only then
|
||||
// is the planning context rendered. Live on run 21, the field was gone by
|
||||
// then: the reopen recorded it and the rotation lost it.
|
||||
func TestTheContradictionSurvivesTheRotationItCauses(t *testing.T) {
|
||||
s, err := Open(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b := []byte(`{"source":"s","external_id":"x","project":"p"}`)
|
||||
if err := s.Append(domain.Event{ID: "create", Type: "TaskCreated", TaskID: "t", Version: 1, Payload: b, Surface: string(authz.System)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := s.Lease("t", "h", time.Minute); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Frame to implement, the shortest legal route to the phase a mismatch
|
||||
// can be reported from.
|
||||
task, _ := s.Task("t")
|
||||
toImplement, _ := json.Marshal(map[string]any{"phase": "implement", "from": "frame"})
|
||||
if err := s.Append(domain.Event{ID: "impl", Type: domain.EventWorkPhaseChanged, TaskID: "t", Version: task.Version + 1, Payload: toImplement, Surface: string(authz.System)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
task, _ = s.Task("t")
|
||||
m, _ := json.Marshal(map[string]any{
|
||||
"plan_ref": "plan-a", "phase_id": "phase-2",
|
||||
"at_sha": "0123456789012345678901234567890123456789",
|
||||
"observed": "the body is assembled inline",
|
||||
"contradicts": "the plan says one helper returns it",
|
||||
"harness_id": task.Lease.HarnessID,
|
||||
"lease_epoch": task.Lease.Epoch,
|
||||
"requested_action": "replan",
|
||||
})
|
||||
if err := s.Append(domain.Event{ID: "mismatch", Type: domain.EventPlanMismatchRecorded, TaskID: "t", Version: task.Version + 1, Payload: m, Surface: string(authz.System)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, _ := s.Task("t"); got.PlanMismatch == nil {
|
||||
t.Fatal("the contradiction was not projected at all")
|
||||
}
|
||||
|
||||
// The reopen, then the rotation it causes.
|
||||
task, _ = s.Task("t")
|
||||
ph, _ := json.Marshal(map[string]any{"phase": "plan", "from": "implement", "reopen": domain.EventPlanMismatchRecorded, "reopen_phase_id": "phase-2"})
|
||||
if err := s.Append(domain.Event{ID: "reopen", Type: domain.EventWorkPhaseChanged, TaskID: "t", Version: task.Version + 1, Payload: ph, Surface: string(authz.System)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ref, err := s.PutArtifact([]byte("handoff"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
task, _ = s.Task("t")
|
||||
rel, _ := json.Marshal(map[string]any{"handoff_ref": ref, "anchor_sha": "0123456789012345678901234567890123456789", "harness_id": task.Lease.HarnessID, "lease_epoch": task.Lease.Epoch, "expected_version": task.Version})
|
||||
if err := s.Append(domain.Event{ID: "release", Type: "TaskReleased", TaskID: "t", Version: task.Version + 1, Payload: rel, Surface: string(authz.System)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := s.Lease("t", "h", time.Minute); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// This is the moment the planning context is rendered.
|
||||
got, _ := s.Task("t")
|
||||
if got.PlanMismatch == nil {
|
||||
t.Fatal("the planner is convened to settle a contradiction it is no longer told about")
|
||||
}
|
||||
if got.PlanMismatch.PhaseID != "phase-2" {
|
||||
t.Fatalf("the contradiction changed across the rotation: %+v", got.PlanMismatch)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user