fix(ax): make workspace extraction Result-native

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-03-30 19:14:14 +00:00 committed by Snider
parent e826d672b0
commit b8466fb56d
6 changed files with 84 additions and 48 deletions

View file

@ -224,8 +224,11 @@ func (s *PrepSubsystem) cmdExtract(opts core.Options) core.Result {
}
core.Print(nil, "extracting template %q to %s", tmpl, target)
if err := lib.ExtractWorkspace(tmpl, target, data); err != nil {
return core.Result{Value: err, OK: false}
if result := lib.ExtractWorkspace(tmpl, target, data); !result.OK {
if err, ok := result.Value.(error); ok {
return core.Result{Value: core.E("agentic.cmdExtract", core.Concat("extract workspace template ", tmpl), err), OK: false}
}
return core.Result{Value: core.E("agentic.cmdExtract", core.Concat("extract workspace template ", tmpl), nil), OK: false}
}
fsys := s.Core().Fs()

View file

@ -466,12 +466,17 @@ func (s *PrepSubsystem) prepWorkspace(ctx context.Context, _ *mcp.CallToolReques
}
// Extract default workspace template (go.work etc.)
lib.ExtractWorkspace("default", wsDir, &lib.WorkspaceData{
if result := lib.ExtractWorkspace("default", wsDir, &lib.WorkspaceData{
Repo: input.Repo,
Branch: "",
Task: input.Task,
Agent: input.Agent,
})
}); !result.OK {
if err, ok := result.Value.(error); ok {
return nil, PrepOutput{}, core.E("prepWorkspace", "extract default workspace template", err)
}
return nil, PrepOutput{}, core.E("prepWorkspace", "extract default workspace template", nil)
}
if !resumed {
// Clone repo into repo/

View file

@ -18,7 +18,8 @@
// r := lib.Task("code/review") // r.Value.(string)
// r := lib.Persona("secops/dev") // r.Value.(string)
// r := lib.Flow("go") // r.Value.(string)
// lib.ExtractWorkspace("default", "/tmp/ws", data)
// r := lib.ExtractWorkspace("default", "/tmp/ws", data)
// core.Println(r.OK)
package lib
import (
@ -264,32 +265,51 @@ type WorkspaceData struct {
// ExtractWorkspace creates an agent workspace from a template.
// Template names: "default", "security", "review".
//
// lib.ExtractWorkspace("default", "/tmp/ws", &lib.WorkspaceData{
// r := lib.ExtractWorkspace("default", "/tmp/ws", &lib.WorkspaceData{
// Repo: "go-io", Task: "fix tests", Agent: "codex",
// })
func ExtractWorkspace(tmplName, targetDir string, data *WorkspaceData) error {
// core.Println(r.OK)
func ExtractWorkspace(tmplName, targetDir string, data *WorkspaceData) core.Result {
if result := ensureMounted(); !result.OK {
if err, ok := result.Value.(error); ok {
return err
return core.Result{
Value: core.E("lib.ExtractWorkspace", core.Concat("mount workspace template ", tmplName), err),
OK: false,
}
}
return core.Result{
Value: core.E("lib.ExtractWorkspace", core.Concat("mount workspace template ", tmplName), nil),
OK: false,
}
return core.E("lib.ExtractWorkspace", core.Concat("mount workspace template ", tmplName), nil)
}
r := workspaceFS.Sub(tmplName)
if !r.OK {
if err, ok := r.Value.(error); ok {
return err
return core.Result{
Value: core.E("lib.ExtractWorkspace", core.Concat("template not found: ", tmplName), err),
OK: false,
}
}
return core.Result{
Value: core.E("lib.ExtractWorkspace", core.Concat("template not found: ", tmplName), nil),
OK: false,
}
return core.E("ExtractWorkspace", core.Concat("template not found: ", tmplName), nil)
}
result := core.Extract(r.Value.(*core.Embed).FS(), targetDir, data)
if !result.OK {
if err, ok := result.Value.(error); ok {
return err
return core.Result{
Value: core.E("lib.ExtractWorkspace", core.Concat("extract workspace template ", tmplName), err),
OK: false,
}
}
return core.Result{
Value: core.E("lib.ExtractWorkspace", core.Concat("extract workspace template ", tmplName), nil),
OK: false,
}
return core.E("lib.ExtractWorkspace", core.Concat("extract workspace template ", tmplName), nil)
}
return nil
return core.Result{Value: targetDir, OK: true}
}
// WorkspaceFile reads a single file from a workspace template.

View file

@ -103,9 +103,9 @@ func ExampleExtractWorkspace() {
dir := (&core.Fs{}).NewUnrestricted().TempDir("example-ws")
defer (&core.Fs{}).NewUnrestricted().DeleteAll(dir)
err := ExtractWorkspace("default", dir, &WorkspaceData{
r := ExtractWorkspace("default", dir, &WorkspaceData{
Repo: "go-io", Task: "fix tests",
})
core.Println(err == nil)
core.Println(r.OK)
// Output: true
}

View file

@ -53,6 +53,30 @@ func corruptLibMountForTest(t *testing.T) {
})
}
func requireExtractWorkspaceOK(t *testing.T, result core.Result) string {
t.Helper()
if !result.OK {
t.Fatalf("ExtractWorkspace failed: %v", result.Value)
}
path, ok := result.Value.(string)
if !ok {
t.Fatalf("ExtractWorkspace returned %T, want string", result.Value)
}
return path
}
func requireExtractWorkspaceError(t *testing.T, result core.Result) error {
t.Helper()
if result.OK {
t.Fatalf("ExtractWorkspace unexpectedly succeeded: %#v", result.Value)
}
err, ok := result.Value.(error)
if !ok {
t.Fatalf("ExtractWorkspace returned %T, want error", result.Value)
}
return err
}
// --- Prompt ---
func TestLib_Prompt_Good(t *testing.T) {
@ -489,10 +513,7 @@ func TestLib_ExtractWorkspace_Good(t *testing.T) {
dir := t.TempDir()
data := &WorkspaceData{Repo: "test-repo", Task: "test task"}
err := ExtractWorkspace("default", dir, data)
if err != nil {
t.Fatalf("ExtractWorkspace failed: %v", err)
}
requireExtractWorkspaceOK(t, ExtractWorkspace("default", dir, data))
for _, name := range []string{"CODEX.md", "CLAUDE.md", "PROMPT.md", "TODO.md", "CONTEXT.md", "go.work"} {
if !testFs.Exists(core.JoinPath(dir, name)) {
@ -505,10 +526,7 @@ func TestLib_ExtractWorkspaceSubdirs_Good(t *testing.T) {
dir := t.TempDir()
data := &WorkspaceData{Repo: "test-repo", Task: "test task"}
err := ExtractWorkspace("default", dir, data)
if err != nil {
t.Fatalf("ExtractWorkspace failed: %v", err)
}
requireExtractWorkspaceOK(t, ExtractWorkspace("default", dir, data))
refDir := core.JoinPath(dir, ".core", "reference")
if !testFs.IsDir(refDir) {
@ -535,10 +553,7 @@ func TestLib_ExtractWorkspaceTemplate_Good(t *testing.T) {
dir := t.TempDir()
data := &WorkspaceData{Repo: "my-repo", Task: "fix the bug"}
err := ExtractWorkspace("default", dir, data)
if err != nil {
t.Fatalf("ExtractWorkspace failed: %v", err)
}
requireExtractWorkspaceOK(t, ExtractWorkspace("default", dir, data))
r := testFs.Read(core.JoinPath(dir, "TODO.md"))
if !r.OK {
@ -550,27 +565,18 @@ func TestLib_ExtractWorkspaceTemplate_Good(t *testing.T) {
}
func TestLib_ExtractWorkspace_Bad(t *testing.T) {
err := ExtractWorkspace("missing-template", t.TempDir(), &WorkspaceData{Repo: "test-repo"})
if err == nil {
t.Fatal("ExtractWorkspace should fail for an unknown template")
}
requireExtractWorkspaceError(t, ExtractWorkspace("missing-template", t.TempDir(), &WorkspaceData{Repo: "test-repo"}))
}
func TestLib_ExtractWorkspace_Ugly(t *testing.T) {
err := ExtractWorkspace("default", t.TempDir(), nil)
if err == nil {
t.Fatal("ExtractWorkspace should fail when template data is nil")
}
requireExtractWorkspaceError(t, ExtractWorkspace("default", t.TempDir(), nil))
}
func TestLib_ExtractWorkspace_Good_AXConventions(t *testing.T) {
dir := t.TempDir()
data := &WorkspaceData{Repo: "test-repo", Task: "align AX docs"}
err := ExtractWorkspace("default", dir, data)
if err != nil {
t.Fatalf("ExtractWorkspace failed: %v", err)
}
requireExtractWorkspaceOK(t, ExtractWorkspace("default", dir, data))
r := testFs.Read(core.JoinPath(dir, "CODEX.md"))
if !r.OK {
@ -624,9 +630,7 @@ func TestLib_ExtractWorkspace_Good_ReferenceHeaders(t *testing.T) {
dir := t.TempDir()
data := &WorkspaceData{Repo: "test-repo", Task: "carry SPDX headers into workspace references"}
if err := ExtractWorkspace("default", dir, data); err != nil {
t.Fatalf("ExtractWorkspace failed: %v", err)
}
requireExtractWorkspaceOK(t, ExtractWorkspace("default", dir, data))
refDir := core.JoinPath(dir, ".core", "reference")
goFiles := core.PathGlob(core.JoinPath(refDir, "*.go"))
@ -643,9 +647,7 @@ func TestLib_ExtractWorkspace_Good_ReferenceUsageExamples(t *testing.T) {
dir := t.TempDir()
data := &WorkspaceData{Repo: "test-repo", Task: "carry AX usage examples into workspace references"}
if err := ExtractWorkspace("default", dir, data); err != nil {
t.Fatalf("ExtractWorkspace failed: %v", err)
}
requireExtractWorkspaceOK(t, ExtractWorkspace("default", dir, data))
cases := map[string][]string{
core.JoinPath(dir, ".core", "reference", "array.go"): {

View file

@ -134,9 +134,15 @@ func (s *Service) scaffoldTemplate(opts Options, projType ProjectType, tmplName
return core.Result{Value: opts.Path, OK: true}
}
if err := lib.ExtractWorkspace(tmplName, opts.Path, data); err != nil {
if result := lib.ExtractWorkspace(tmplName, opts.Path, data); !result.OK {
if err, ok := result.Value.(error); ok {
return core.Result{
Value: core.E("setup.scaffoldTemplate", core.Concat("extract workspace template ", tmplName), err),
OK: false,
}
}
return core.Result{
Value: core.E("setup.scaffoldTemplate", core.Concat("extract workspace template ", tmplName), err),
Value: core.E("setup.scaffoldTemplate", core.Concat("extract workspace template ", tmplName), nil),
OK: false,
}
}