fix(ax): make runner status writes explicit

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-03-30 16:33:14 +00:00
parent be3e68ec0f
commit f34aedff05
5 changed files with 37 additions and 22 deletions

View file

@ -102,16 +102,24 @@ func ReadStatusResult(wsDir string) core.Result {
// WriteStatus writes `status.json` for one workspace directory.
//
// runner.WriteStatus("/srv/core/workspace/core/go-io/task-5", &runner.WorkspaceStatus{Status: "running", Agent: "codex"})
func WriteStatus(wsDir string, st *WorkspaceStatus) {
if st == nil {
return
// r := runner.WriteStatus("/srv/core/workspace/core/go-io/task-5", &runner.WorkspaceStatus{Status: "running", Agent: "codex"})
// core.Println(r.OK)
func WriteStatus(wsDir string, status *WorkspaceStatus) core.Result {
if status == nil {
return core.Result{Value: core.E("runner.WriteStatus", "status is required", nil), OK: false}
}
status := agenticWorkspaceStatusFromRunner(st)
if status == nil {
return
agenticStatus := agenticWorkspaceStatusFromRunner(status)
if agenticStatus == nil {
return core.Result{Value: core.E("runner.WriteStatus", "status conversion failed", nil), OK: false}
}
status.UpdatedAt = time.Now()
fs.WriteAtomic(agentic.WorkspaceStatusPath(wsDir), core.JSONMarshalString(status))
agenticStatus.UpdatedAt = time.Now()
if r := fs.WriteAtomic(agentic.WorkspaceStatusPath(wsDir), core.JSONMarshalString(agenticStatus)); !r.OK {
err, _ := r.Value.(error)
if err == nil {
return core.Result{Value: core.E("runner.WriteStatus", "failed to write status", nil), OK: false}
}
return core.Result{Value: core.E("runner.WriteStatus", "failed to write status", err), OK: false}
}
return core.Result{OK: true}
}

View file

@ -61,16 +61,18 @@ func ExampleWriteStatus() {
dir := fsys.TempDir("runner-paths")
defer fsys.DeleteAll(dir)
WriteStatus(dir, &WorkspaceStatus{
result := WriteStatus(dir, &WorkspaceStatus{
Status: "running",
Agent: "codex",
Repo: "go-io",
})
core.Println(result.OK)
st, err := ReadStatus(dir)
core.Println(err == nil)
core.Println(st.Status)
// Output:
// true
// true
// running
}

View file

@ -140,7 +140,7 @@ func TestPaths_ReadStatus_Ugly(t *testing.T) {
func TestPaths_WriteStatus_Good(t *testing.T) {
wsDir := t.TempDir()
WriteStatus(wsDir, &WorkspaceStatus{
result := WriteStatus(wsDir, &WorkspaceStatus{
Status: "running",
Agent: "codex",
Repo: "go-io",
@ -148,6 +148,7 @@ func TestPaths_WriteStatus_Good(t *testing.T) {
Branch: "agent/ax-cleanup",
Runs: 1,
})
assert.True(t, result.OK)
st, err := ReadStatus(wsDir)
require.NoError(t, err)
@ -165,7 +166,8 @@ func TestPaths_WriteStatus_Good(t *testing.T) {
func TestPaths_WriteStatus_Bad(t *testing.T) {
wsDir := t.TempDir()
WriteStatus(wsDir, nil)
result := WriteStatus(wsDir, nil)
assert.False(t, result.OK)
assert.False(t, agentic.LocalFs().Read(agentic.WorkspaceStatusPath(wsDir)).OK)
}
@ -173,13 +175,13 @@ func TestPaths_WriteStatus_Bad(t *testing.T) {
func TestPaths_WriteStatus_Ugly(t *testing.T) {
wsDir := t.TempDir()
WriteStatus(wsDir, &WorkspaceStatus{
assert.True(t, WriteStatus(wsDir, &WorkspaceStatus{
Status: "running",
Agent: "codex",
Repo: "go-io",
Task: "First run",
})
WriteStatus(wsDir, &WorkspaceStatus{
}).OK)
assert.True(t, WriteStatus(wsDir, &WorkspaceStatus{
Status: "completed",
Agent: "claude",
Repo: "go-io",
@ -187,7 +189,7 @@ func TestPaths_WriteStatus_Ugly(t *testing.T) {
Branch: "agent/ax-cleanup",
StartedAt: time.Now(),
Runs: 3,
})
}).OK)
st, err := ReadStatus(wsDir)
require.NoError(t, err)

View file

@ -278,7 +278,10 @@ func (s *Service) drainOne() bool {
st.Status = "running"
st.PID = pid
st.Runs++
WriteStatus(wsDir, st)
if r := WriteStatus(wsDir, st); !r.OK {
core.Error("drainOne: failed to write workspace status", "workspace", wsName, "reason", core.Sprint(r.Value))
continue
}
s.TrackWorkspace(wsName, st)
core.Info("drainOne: spawned", "pid", pid, "workspace", wsName)

View file

@ -345,12 +345,12 @@ func TestRunner_HydrateWorkspaces_Good_DeepWorkspaceName(t *testing.T) {
wsDir := core.JoinPath(root, "workspace", "core", "go-io", "task-5")
fs.EnsureDir(wsDir)
WriteStatus(wsDir, &WorkspaceStatus{
require.True(t, WriteStatus(wsDir, &WorkspaceStatus{
Status: "running",
Agent: "codex",
Repo: "go-io",
PID: 99999999,
})
}).OK)
svc := New()
svc.hydrateWorkspaces()
@ -367,7 +367,7 @@ func TestRunner_HydrateWorkspaces_Good_DeepWorkspaceName(t *testing.T) {
func TestRunner_WriteReadStatus_Good(t *testing.T) {
dir := t.TempDir()
st := &WorkspaceStatus{Status: "running", Agent: "codex", Repo: "go-io", PID: 999}
WriteStatus(dir, st)
require.True(t, WriteStatus(dir, st).OK)
got, err := ReadStatus(dir)
require.NoError(t, err)
@ -383,8 +383,8 @@ func TestRunner_ReadStatus_Bad_NoFile(t *testing.T) {
func TestRunner_WriteReadStatus_Ugly_OverwriteExisting(t *testing.T) {
dir := t.TempDir()
WriteStatus(dir, &WorkspaceStatus{Status: "running"})
WriteStatus(dir, &WorkspaceStatus{Status: "completed"})
require.True(t, WriteStatus(dir, &WorkspaceStatus{Status: "running"}).OK)
require.True(t, WriteStatus(dir, &WorkspaceStatus{Status: "completed"}).OK)
got, err := ReadStatus(dir)
require.NoError(t, err)