From d2929c6defcae48f20068730b09e8ab8586f3527 Mon Sep 17 00:00:00 2001 From: CL Kao Date: Fri, 17 Jul 2026 21:40:17 +0800 Subject: [PATCH] docs(dispatch): clarify entity path base --- internal/dispatch/build.go | 3 ++- .../dispatch/build_json_ergonomics_test.go | 25 +++++++++++++++++++ internal/dispatch/dispatch.go | 7 +++--- internal/dispatch/help_test.go | 18 +++++++++++++ 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/internal/dispatch/build.go b/internal/dispatch/build.go index 2f87ff88c..e381a2af5 100644 --- a/internal/dispatch/build.go +++ b/internal/dispatch/build.go @@ -1047,7 +1047,8 @@ func emitBuildSchema(stdout io.Writer) int { "const": schemaVersion, }, "entity_path": map[string]any{ - "type": "string", + "type": "string", + "description": "Absolute path or path relative to the caller's current working directory; never relative to workflow_dir. Identifies the project-root/state-checkout entity, not a code-worktree copy (for example, docs/dev/.spacedock-state/example/index.md).", }, "workflow_dir": map[string]any{ "type": "string", diff --git a/internal/dispatch/build_json_ergonomics_test.go b/internal/dispatch/build_json_ergonomics_test.go index bd9ac35c8..1e4d06446 100644 --- a/internal/dispatch/build_json_ergonomics_test.go +++ b/internal/dispatch/build_json_ergonomics_test.go @@ -271,6 +271,31 @@ func TestBuildSchemaAndValidateOnly(t *testing.T) { }) } +func TestBuildSchemaDocumentsEntityPathBase(t *testing.T) { + native := runNativePreservingHostEnv("", "build", "--print-schema") + if native.exit != 0 { + t.Fatalf("print-schema exit=%d stderr=%s", native.exit, native.stderr) + } + + var schema map[string]any + if err := json.Unmarshal([]byte(native.stdout), &schema); err != nil { + t.Fatalf("schema is not valid JSON: %v\n%s", err, native.stdout) + } + props, ok := schema["properties"].(map[string]any) + if !ok { + t.Fatalf("schema missing properties object:\n%s", native.stdout) + } + entityPath, ok := props["entity_path"].(map[string]any) + if !ok { + t.Fatalf("schema missing entity_path property:\n%s", native.stdout) + } + + const want = "Absolute path or path relative to the caller's current working directory; never relative to workflow_dir. Identifies the project-root/state-checkout entity, not a code-worktree copy (for example, docs/dev/.spacedock-state/example/index.md)." + if got := entityPath["description"]; got != want { + t.Fatalf("entity_path description = %q, want %q", got, want) + } +} + func buildHostFixture(t *testing.T) (string, string) { t.Helper() root := t.TempDir() diff --git a/internal/dispatch/dispatch.go b/internal/dispatch/dispatch.go index 55a95fd84..7f6eb0749 100644 --- a/internal/dispatch/dispatch.go +++ b/internal/dispatch/dispatch.go @@ -302,13 +302,14 @@ Flags: Stdin JSON fields: schema_version Dispatch schema version. The current supported value is 2. - entity_path Path to the entity file for this dispatch. + entity_path May be absolute or relative to the caller's current working directory; never relative to workflow_dir. + Identifies the project-root/state-checkout entity, not a code-worktree copy. workflow_dir Workflow directory for the dispatch request. stage Stage name to dispatch. checklist Array of checklist strings for the dispatched worker. -Example: - {"schema_version":2,"entity_path":"thing.md","workflow_dir":".","stage":"implementation","checklist":["DONE: run tests"]} +Split-root example (called from the project root): + {"schema_version":2,"entity_path":"docs/dev/.spacedock-state/example/index.md","workflow_dir":"docs/dev","stage":"implementation","checklist":["DONE: run tests"]} `) } diff --git a/internal/dispatch/help_test.go b/internal/dispatch/help_test.go index ce0cc2105..f82658469 100644 --- a/internal/dispatch/help_test.go +++ b/internal/dispatch/help_test.go @@ -33,6 +33,24 @@ func TestDispatchBuildHelpBeforeRequiredFlags(t *testing.T) { } } +func TestDispatchBuildHelpDocumentsEntityPathBase(t *testing.T) { + res := runNative("", "build", "--help") + if res.exit != 0 { + t.Fatalf("dispatch build --help exit=%d, want 0\nstderr=%q", res.exit, res.stderr) + } + if res.stderr != "" { + t.Fatalf("dispatch build --help stderr=%q, want empty", res.stderr) + } + + assertContainsAll(t, res.stdout, + "absolute or relative to the caller's current working directory", + "never relative to workflow_dir", + "project-root/state-checkout entity, not a code-worktree copy", + `"entity_path":"docs/dev/.spacedock-state/example/index.md"`, + `"workflow_dir":"docs/dev"`, + ) +} + func TestDispatchShowStageDefHelpBeforeRequiredFlags(t *testing.T) { for _, helpFlag := range []string{"--help", "-h"} { t.Run(helpFlag, func(t *testing.T) {