feat(v0.5): add launch_dir field to TaskMeta
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,9 @@ import (
|
||||
|
||||
// TaskMeta represents the task.yaml schema.
|
||||
// The Type field is v0.3+; older workspaces without this field are treated as "task"
|
||||
// (see EffectiveType). Field order in this struct is the YAML output order.
|
||||
// (see EffectiveType). LaunchDir is v0.5+; empty for tasks and pre-v0.5 projects,
|
||||
// defaults to the project slug for new projects. Field order in this struct is
|
||||
// the YAML output order.
|
||||
type TaskMeta struct {
|
||||
ID string `yaml:"id"`
|
||||
Slug string `yaml:"slug"`
|
||||
@@ -26,6 +28,7 @@ type TaskMeta struct {
|
||||
Agent string `yaml:"agent"`
|
||||
WorkspacePath string `yaml:"workspace_path"`
|
||||
ArchivedAt *time.Time `yaml:"archived_at"`
|
||||
LaunchDir string `yaml:"launch_dir,omitempty"`
|
||||
}
|
||||
|
||||
// EffectiveType returns "task" or "project". An empty or missing Type field
|
||||
|
||||
@@ -255,3 +255,56 @@ func TestMetaArchive(t *testing.T) {
|
||||
t.Errorf("ArchivedAt: got %v, want %v", got.ArchivedAt, archiveTime)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetaLaunchDirRoundTrip(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
path := filepath.Join(tmp, "task.yaml")
|
||||
|
||||
meta := &TaskMeta{
|
||||
ID: "test",
|
||||
Slug: "demo",
|
||||
Title: "demo",
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Second),
|
||||
UpdatedAt: time.Now().UTC().Truncate(time.Second),
|
||||
Status: "active",
|
||||
Category: "projects",
|
||||
Type: "project",
|
||||
Mode: "local",
|
||||
Agent: "claude",
|
||||
LaunchDir: "demo",
|
||||
}
|
||||
if err := WriteMeta(path, meta); err != nil {
|
||||
t.Fatalf("WriteMeta: %v", err)
|
||||
}
|
||||
got, err := ReadMeta(path)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadMeta: %v", err)
|
||||
}
|
||||
if got.LaunchDir != "demo" {
|
||||
t.Errorf("LaunchDir round-trip: got %q, want %q", got.LaunchDir, "demo")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetaLaunchDirOmittedWhenEmpty(t *testing.T) {
|
||||
// Backward compat: a task workspace with no LaunchDir must not serialize
|
||||
// a launch_dir key (keeps on-disk task.yaml clean for pre-v0.5 shape).
|
||||
tmp := t.TempDir()
|
||||
path := filepath.Join(tmp, "task.yaml")
|
||||
meta := &TaskMeta{
|
||||
ID: "t", Slug: "t", Title: "t",
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Second),
|
||||
UpdatedAt: time.Now().UTC().Truncate(time.Second),
|
||||
Status: "active", Category: "general", Type: "task",
|
||||
Mode: "local", Agent: "claude",
|
||||
}
|
||||
if err := WriteMeta(path, meta); err != nil {
|
||||
t.Fatalf("WriteMeta: %v", err)
|
||||
}
|
||||
body, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadFile: %v", err)
|
||||
}
|
||||
if strings.Contains(string(body), "launch_dir") {
|
||||
t.Errorf("empty LaunchDir must not serialize launch_dir key; got:\n%s", body)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user