From 651783e1f558408144d1fd2fa3279c61ffdc3d26 Mon Sep 17 00:00:00 2001 From: Snider Date: Sat, 18 Apr 2026 08:32:10 +0100 Subject: [PATCH] feat(agent): gpt-5.4-mini/mature pass 1 Commit: Co-Authored-By: Virgil --- .core/TODO.md | 2 ++ pkg/agentic/prep.go | 29 +++++++++++++++++++++++++++++ pkg/agentic/prep_test.go | 12 ++++++++++++ 3 files changed, 43 insertions(+) diff --git a/.core/TODO.md b/.core/TODO.md index e69de29..66e7e31 100644 --- a/.core/TODO.md +++ b/.core/TODO.md @@ -0,0 +1,2 @@ +- @bug pkg/agentic/deps.go:59 — `go.work` is written without checking the result, so dependency cloning can fail silently. +- @bug pkg/agentic/prep.go:835 — the PHP-specific `CODEX.md` overwrite ignores write failures, leaving prep to continue with a partial workspace. diff --git a/pkg/agentic/prep.go b/pkg/agentic/prep.go index 6b261f3..d5d2209 100644 --- a/pkg/agentic/prep.go +++ b/pkg/agentic/prep.go @@ -796,6 +796,9 @@ func (s *PrepSubsystem) prepWorkspace(ctx context.Context, _ *mcp.CallToolReques } return nil, PrepOutput{}, core.E("prepWorkspace", "extract default workspace template", nil) } + if err := ensureWorkspaceTaskFile(workspaceDir); err != nil { + return nil, PrepOutput{}, err + } if !resumed { if r := process.RunIn(ctx, ".", "git", "clone", repoPath, repoDir); !r.OK { @@ -1021,6 +1024,32 @@ func (s *PrepSubsystem) buildPrompt(ctx context.Context, input PrepInput, branch return promptBuilder.String(), memoryCount, consumerCount } +// ensureWorkspaceTaskFile("/srv/.core/workspace/core/go-io/task-42") +// keeps TODO.md present for the prompt and the local agent shell wrapper. +func ensureWorkspaceTaskFile(workspaceDir string) error { + todoPath := core.JoinPath(workspaceDir, "TODO.md") + if readResult := fs.Read(todoPath); readResult.OK && core.Trim(readResult.Value.(string)) != "" { + return nil + } + + templateResult := lib.WorkspaceFile("default", "TODO.md.tmpl") + if !templateResult.OK { + if err, ok := templateResult.Value.(error); ok { + return core.E("prepWorkspace", "load TODO.md template", err) + } + return core.E("prepWorkspace", "load TODO.md template", nil) + } + + if writeResult := fs.Write(todoPath, templateResult.Value.(string)); !writeResult.OK { + if err, ok := writeResult.Value.(error); ok { + return core.E("prepWorkspace", "write TODO.md", err) + } + return core.E("prepWorkspace", "write TODO.md", nil) + } + + return nil +} + // writePromptSnapshot stores an immutable prompt snapshot for a workspace. // // snapshot := writePromptSnapshot("/srv/.core/workspace/core/go-io/task-42", "TASK: Fix tests") diff --git a/pkg/agentic/prep_test.go b/pkg/agentic/prep_test.go index 4e14caa..0519dbf 100644 --- a/pkg/agentic/prep_test.go +++ b/pkg/agentic/prep_test.go @@ -1228,6 +1228,12 @@ func TestPrep_PrepWorkspace_Good(t *testing.T) { promptSnapshotPath := core.JoinPath(WorkspaceMetaDir(out.WorkspaceDir), "prompt-versions", core.Concat(out.PromptVersion, ".json")) require.True(t, fs.Exists(promptSnapshotPath)) + + todoPath := core.JoinPath(out.WorkspaceDir, "TODO.md") + require.True(t, fs.Exists(todoPath)) + todoResult := fs.Read(todoPath) + require.True(t, todoResult.OK) + assert.NotEmpty(t, core.Trim(todoResult.Value.(string))) } func TestPrep_TestPrepWorkspace_Good(t *testing.T) { @@ -1274,6 +1280,12 @@ func TestPrep_TestPrepWorkspace_Good(t *testing.T) { require.NoError(t, err) assert.True(t, out.Success) assert.NotEmpty(t, out.WorkspaceDir) + + todoPath := core.JoinPath(out.WorkspaceDir, "TODO.md") + require.True(t, fs.Exists(todoPath)) + todoResult := fs.Read(todoPath) + require.True(t, todoResult.OK) + assert.NotEmpty(t, core.Trim(todoResult.Value.(string))) } func TestPrep_TestPrepWorkspace_Bad(t *testing.T) {