fix(lib): ExtractWorkspace now recurses into subdirectories

Was skipping directories entirely (`if entry.IsDir() { continue }`),
so .core/reference/ and its contents were never extracted.
Replaced fs.ReadDir loop with fs.WalkDir to handle nested dirs.

Added tests: CreatesFiles, CreatesSubdirectories, TemplateSubstitution.

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Snider 2026-03-22 08:10:56 +00:00
parent e8ca0d856f
commit 3c5e6d6498
2 changed files with 111 additions and 19 deletions

View file

@ -139,31 +139,39 @@ type WorkspaceData struct {
// Template names: "default", "security", "review".
func ExtractWorkspace(tmplName, targetDir string, data *WorkspaceData) error {
wsDir := "workspace/" + tmplName
entries, err := fs.ReadDir(workspaceFS, wsDir)
if err != nil {
return err
}
if err := os.MkdirAll(targetDir, 0755); err != nil {
return err
}
for _, entry := range entries {
if entry.IsDir() {
continue
return fs.WalkDir(workspaceFS, wsDir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
name := entry.Name()
content, err := fs.ReadFile(workspaceFS, wsDir+"/"+name)
// Get relative path from template root
rel, err := filepath.Rel(wsDir, path)
if err != nil || rel == "." {
return nil
}
targetPath := filepath.Join(targetDir, rel)
if d.IsDir() {
return os.MkdirAll(targetPath, 0755)
}
content, err := fs.ReadFile(workspaceFS, path)
if err != nil {
return err
}
// Process .tmpl files through text/template
outputName := name
if core.HasSuffix(name, ".tmpl") {
outputName = core.TrimSuffix(name, ".tmpl")
tmpl, err := template.New(name).Parse(string(content))
outputName := filepath.Base(targetPath)
if core.HasSuffix(outputName, ".tmpl") {
outputName = core.TrimSuffix(outputName, ".tmpl")
targetPath = filepath.Join(filepath.Dir(targetPath), outputName)
tmpl, err := template.New(outputName).Parse(string(content))
if err != nil {
return err
}
@ -174,12 +182,8 @@ func ExtractWorkspace(tmplName, targetDir string, data *WorkspaceData) error {
content = buf.Bytes()
}
if err := os.WriteFile(filepath.Join(targetDir, outputName), content, 0644); err != nil {
return err
}
}
return nil
return os.WriteFile(targetPath, content, 0644)
})
}
// --- List Functions ---

88
pkg/lib/lib_test.go Normal file
View file

@ -0,0 +1,88 @@
package lib
import (
"os"
"path/filepath"
"testing"
)
func TestExtractWorkspace_CreatesFiles(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)
}
// Check top-level template files exist
for _, name := range []string{"CODEX.md", "CLAUDE.md", "PROMPT.md", "TODO.md", "CONTEXT.md"} {
path := filepath.Join(dir, name)
if _, err := os.Stat(path); os.IsNotExist(err) {
t.Errorf("expected %s to exist", name)
}
}
}
func TestExtractWorkspace_CreatesSubdirectories(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)
}
// Check .core/reference/ directory exists with files
refDir := filepath.Join(dir, ".core", "reference")
if _, err := os.Stat(refDir); os.IsNotExist(err) {
t.Fatalf(".core/reference/ directory not created")
}
// Check AX spec exists
axSpec := filepath.Join(refDir, "RFC-025-AGENT-EXPERIENCE.md")
if _, err := os.Stat(axSpec); os.IsNotExist(err) {
t.Errorf("AX spec not extracted: %s", axSpec)
}
// Check Core source files exist
entries, err := os.ReadDir(refDir)
if err != nil {
t.Fatalf("failed to read reference dir: %v", err)
}
goFiles := 0
for _, e := range entries {
if filepath.Ext(e.Name()) == ".go" {
goFiles++
}
}
if goFiles == 0 {
t.Error("no .go files in .core/reference/")
}
// Check docs subdirectory
docsDir := filepath.Join(refDir, "docs")
if _, err := os.Stat(docsDir); os.IsNotExist(err) {
t.Errorf(".core/reference/docs/ not created")
}
}
func TestExtractWorkspace_TemplateSubstitution(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)
}
// TODO.md should contain the task
content, err := os.ReadFile(filepath.Join(dir, "TODO.md"))
if err != nil {
t.Fatalf("failed to read TODO.md: %v", err)
}
if len(content) == 0 {
t.Error("TODO.md is empty")
}
}