diff --git a/SPECIFICATION.md b/SPECIFICATION.md index 4d31878..a479c90 100644 --- a/SPECIFICATION.md +++ b/SPECIFICATION.md @@ -435,7 +435,40 @@ field3: "string value" ### 5.2 Standard Task Fields -#### 5.2.1 `task_name` (optional) +#### 5.2.1 `id` (optional) +- **Type:** String +- **Purpose:** Unique identifier for the task +- **Note:** Metadata only, does not affect task matching or filtering + +```yaml +--- +id: task-12345 +--- +``` + +#### 5.2.2 `name` (optional) +- **Type:** String +- **Purpose:** Human-readable name for the task +- **Note:** Metadata only, does not affect task matching or filtering + +```yaml +--- +name: Fix Critical Bug +--- +``` + +#### 5.2.3 `description` (optional) +- **Type:** String +- **Purpose:** Description of what the task does +- **Note:** Metadata only, does not affect task matching or filtering + +```yaml +--- +description: Fix the critical bug affecting user authentication +--- +``` + +#### 5.2.4 `task_name` (optional) - **Type:** String - **Purpose:** Metadata identifier for the task - **Note:** Tasks are matched by filename, not this field @@ -446,7 +479,7 @@ task_name: fix-bug --- ``` -#### 5.2.2 `resume` (optional) +#### 5.2.5 `resume` (optional) - **Type:** Boolean - **Purpose:** Indicates if task is for resuming work - **Default:** `false` @@ -458,7 +491,7 @@ resume: true --- ``` -#### 5.2.3 `languages` (optional) +#### 5.2.6 `languages` (optional) - **Type:** Array of strings (recommended) or string - **Purpose:** Metadata about programming languages - **Note:** Metadata only, does not auto-filter rules @@ -472,7 +505,7 @@ languages: --- ``` -#### 5.2.4 `agent` (optional) +#### 5.2.7 `agent` (optional) - **Type:** String - **Purpose:** Target agent, acts as default selector - **Values:** `cursor`, `copilot`, `claude`, `gemini`, `opencode`, `augment`, `windsurf`, `codex` @@ -483,7 +516,7 @@ agent: cursor --- ``` -#### 5.2.5 `model` (optional) +#### 5.2.8 `model` (optional) - **Type:** String - **Purpose:** AI model identifier (metadata only) @@ -493,7 +526,7 @@ model: anthropic.claude-sonnet-4-20250514-v1-0 --- ``` -#### 5.2.6 `single_shot` (optional) +#### 5.2.9 `single_shot` (optional) - **Type:** Boolean - **Purpose:** Indicates single vs. multi-execution - **Note:** Metadata only @@ -504,7 +537,7 @@ single_shot: true --- ``` -#### 5.2.7 `timeout` (optional) +#### 5.2.10 `timeout` (optional) - **Type:** String (Go time.Duration format) - **Purpose:** Task execution timeout - **Note:** Metadata only @@ -515,7 +548,7 @@ timeout: 10m --- ``` -#### 5.2.8 `selectors` (optional) +#### 5.2.11 `selectors` (optional) - **Type:** Map of key-value pairs - **Purpose:** Auto-filter rules for this task - **Supports:** Scalar values and arrays (OR logic) @@ -537,7 +570,7 @@ selectors: --- ``` -#### 5.2.9 `expand` (optional) +#### 5.2.12 `expand` (optional) - **Type:** Boolean - **Purpose:** Control parameter expansion - **Default:** `true` @@ -550,7 +583,40 @@ expand: false ### 5.3 Standard Rule Fields -#### 5.3.1 `languages` (optional) +#### 5.3.1 `id` (optional) +- **Type:** String +- **Purpose:** Unique identifier for the rule +- **Note:** Metadata only, does not affect rule matching or filtering + +```yaml +--- +id: rule-12345 +--- +``` + +#### 5.3.2 `name` (optional) +- **Type:** String +- **Purpose:** Human-readable name for the rule +- **Note:** Metadata only, does not affect rule matching or filtering + +```yaml +--- +name: Go Implementation Standards +--- +``` + +#### 5.3.3 `description` (optional) +- **Type:** String +- **Purpose:** Description of what the rule provides +- **Note:** Metadata only, does not affect rule matching or filtering + +```yaml +--- +description: Standards and best practices for Go implementation +--- +``` + +#### 5.3.4 `languages` (optional) - **Type:** Array or string - **Purpose:** Filter rules by programming language - **Values:** Lowercase language names @@ -562,7 +628,7 @@ languages: --- ``` -#### 5.3.2 `stage` (optional) +#### 5.3.5 `stage` (optional) - **Type:** String - **Purpose:** Filter by development stage - **Common values:** `planning`, `implementation`, `testing`, `review` @@ -573,7 +639,7 @@ stage: implementation --- ``` -#### 5.3.3 `agent` (optional) +#### 5.3.6 `agent` (optional) - **Type:** String - **Purpose:** Target specific agent @@ -583,7 +649,7 @@ agent: cursor --- ``` -#### 5.3.4 `mcp_server` (optional) +#### 5.3.7 `mcp_server` (optional) - **Type:** Object - **Purpose:** Model Context Protocol server configuration @@ -1554,6 +1620,9 @@ Potential future additions while maintaining backward compatibility: | Field | Type | Required | Purpose | |-------|------|----------|---------| +| `id` | string | No | Unique identifier (metadata) | +| `name` | string | No | Human-readable name (metadata) | +| `description` | string | No | Task description (metadata) | | `task_name` | string | No | Metadata identifier | | `resume` | boolean | No | Resume mode indicator | | `languages` | array/string | No | Programming languages (metadata) | @@ -1568,11 +1637,24 @@ Potential future additions while maintaining backward compatibility: | Field | Type | Required | Purpose | |-------|------|----------|---------| +| `id` | string | No | Unique identifier (metadata) | +| `name` | string | No | Human-readable name (metadata) | +| `description` | string | No | Rule description (metadata) | | `languages` | array/string | No | Language filter | | `stage` | string | No | Development stage filter | | `agent` | string | No | Agent filter | | `mcp_server` | object | No | MCP server config | +### Command Fields + +| Field | Type | Required | Purpose | +|-------|------|----------|---------| +| `id` | string | No | Unique identifier (metadata) | +| `name` | string | No | Human-readable name (metadata) | +| `description` | string | No | Command description (metadata) | +| `expand` | boolean | No | Parameter expansion control | +| `selectors` | object | No | Auto-filter rules | + ### Skill Fields | Field | Type | Required | Purpose | diff --git a/docs/reference/file-formats.md b/docs/reference/file-formats.md index 47eed71..69137d9 100644 --- a/docs/reference/file-formats.md +++ b/docs/reference/file-formats.md @@ -29,6 +29,48 @@ Content can include ${parameter_placeholders}. ### Frontmatter Fields +#### `id` (optional, standard field) + +**Type:** String +**Purpose:** Unique identifier for the task. This field is metadata only and does not affect task matching or filtering. + +**Example:** +```yaml +--- +id: task-12345 +--- +``` + +**Note:** The `id` field is purely informational and can be used to track tasks in external systems or for auditing purposes. + +#### `name` (optional, standard field) + +**Type:** String +**Purpose:** Human-readable name for the task. This field is metadata only and does not affect task matching or filtering. + +**Example:** +```yaml +--- +name: Fix Critical Authentication Bug +--- +``` + +**Note:** The `name` field is useful for display purposes and documentation, but tasks are still matched by their filename. + +#### `description` (optional, standard field) + +**Type:** String +**Purpose:** Description of what the task does. This field is metadata only and does not affect task matching or filtering. + +**Example:** +```yaml +--- +description: Fix the critical bug affecting user authentication in the login flow +--- +``` + +**Note:** The `description` field provides additional context about the task's purpose and goals. + #### `task_name` (optional) **Type:** String @@ -439,6 +481,48 @@ This content will be substituted when the command is referenced. ### Frontmatter Fields (optional) +#### `id` (optional, standard field) + +**Type:** String +**Purpose:** Unique identifier for the command. This field is metadata only and does not affect command matching or filtering. + +**Example:** +```yaml +--- +id: cmd-12345 +--- +``` + +**Note:** The `id` field is useful for tracking commands in external systems. + +#### `name` (optional, standard field) + +**Type:** String +**Purpose:** Human-readable name for the command. This field is metadata only and does not affect command matching or filtering. + +**Example:** +```yaml +--- +name: Database Setup +--- +``` + +**Note:** The `name` field helps identify the command's purpose in documentation. + +#### `description` (optional, standard field) + +**Type:** String +**Purpose:** Description of what the command does. This field is metadata only and does not affect command matching or filtering. + +**Example:** +```yaml +--- +description: Sets up PostgreSQL database with authentication +--- +``` + +**Note:** The `description` field provides context about the command's functionality. + #### `expand` (optional) **Type:** Boolean @@ -563,6 +647,48 @@ All frontmatter fields are optional and used for filtering. **Standard fields for rules:** +#### `id` (optional, standard field) + +**Type:** String +**Purpose:** Unique identifier for the rule. This field is metadata only and does not affect rule matching or filtering. + +**Example:** +```yaml +--- +id: rule-12345 +--- +``` + +**Note:** The `id` field is useful for tracking rules in external systems or for documentation purposes. + +#### `name` (optional, standard field) + +**Type:** String +**Purpose:** Human-readable name for the rule. This field is metadata only and does not affect rule matching or filtering. + +**Example:** +```yaml +--- +name: Go Implementation Standards +--- +``` + +**Note:** The `name` field helps identify the rule's purpose in documentation and tooling. + +#### `description` (optional, standard field) + +**Type:** String +**Purpose:** Description of what the rule provides. This field is metadata only and does not affect rule matching or filtering. + +**Example:** +```yaml +--- +description: Standards and best practices for implementing Go code +--- +``` + +**Note:** The `description` field provides context about what guidance the rule offers. + #### `task_names` (rule selector) Specifies which task(s) this rule applies to. Can be a string or array. The field name is `task_names` (plural). diff --git a/examples/agents/commands/example-command-with-standard-fields.md b/examples/agents/commands/example-command-with-standard-fields.md new file mode 100644 index 0000000..5e228cd --- /dev/null +++ b/examples/agents/commands/example-command-with-standard-fields.md @@ -0,0 +1,16 @@ +--- +id: cmd-example-001 +name: Example Command with Standard Fields +description: This command demonstrates the use of id, name, and description standard frontmatter fields +expand: true +--- + +# Example Command + +This command demonstrates the new standard frontmatter fields: +- `id`: A unique identifier for the command +- `name`: A human-readable name +- `description`: A description of what the command does + +These fields are metadata only and do not affect command matching. +Commands are still referenced using slash syntax like `/example-command-with-standard-fields`. diff --git a/examples/agents/rules/example-rule-with-standard-fields.md b/examples/agents/rules/example-rule-with-standard-fields.md new file mode 100644 index 0000000..d05a86b --- /dev/null +++ b/examples/agents/rules/example-rule-with-standard-fields.md @@ -0,0 +1,18 @@ +--- +id: rule-example-001 +name: Example Rule with Standard Fields +description: This rule demonstrates the use of id, name, and description standard frontmatter fields +languages: + - go +stage: implementation +--- + +# Example Rule + +This rule demonstrates the new standard frontmatter fields: +- `id`: A unique identifier for the rule +- `name`: A human-readable name +- `description`: A description of what the rule provides + +These fields are metadata only and do not affect rule filtering. +Rules are still filtered using the `languages` and `stage` fields. diff --git a/examples/agents/tasks/example-with-standard-fields.md b/examples/agents/tasks/example-with-standard-fields.md index ec38f96..0ec2ed9 100644 --- a/examples/agents/tasks/example-with-standard-fields.md +++ b/examples/agents/tasks/example-with-standard-fields.md @@ -1,4 +1,7 @@ --- +id: task-example-001 +name: Example Task with Standard Frontmatter Fields +description: This task demonstrates all standard frontmatter fields supported by the coding-context CLI task_name: example-with-standard-fields agent: cursor language: go @@ -11,7 +14,17 @@ selectors: # Example Task with Standard Frontmatter Fields -This task demonstrates all standard frontmatter fields supported by the coding-context CLI. +This task demonstrates all standard frontmatter fields supported by the coding-context CLI, including the newly added `id`, `name`, and `description` fields. + +## New Standard Fields (Metadata Only) + +These are the new standard fields that have been added: + +- **id**: `task-example-001` - A unique identifier for the task +- **name**: `Example Task with Standard Frontmatter Fields` - A human-readable name +- **description**: See frontmatter - A description of what the task does + +These fields are metadata only and do not affect task matching or filtering. ## Standard Fields (Default Selectors) diff --git a/pkg/codingcontext/markdown/frontmatter.go b/pkg/codingcontext/markdown/frontmatter.go index bb9f2ad..259253d 100644 --- a/pkg/codingcontext/markdown/frontmatter.go +++ b/pkg/codingcontext/markdown/frontmatter.go @@ -16,6 +16,18 @@ type BaseFrontMatter struct { type TaskFrontMatter struct { BaseFrontMatter `yaml:",inline"` + // ID is an optional unique identifier for the task + // Metadata only, does not affect task matching or filtering + ID string `yaml:"id,omitempty" json:"id,omitempty"` + + // Name is an optional human-readable name for the task + // Metadata only, does not affect task matching or filtering + Name string `yaml:"name,omitempty" json:"name,omitempty"` + + // Description is an optional description of what the task does + // Metadata only, does not affect task matching or filtering + Description string `yaml:"description,omitempty" json:"description,omitempty"` + // Agent specifies the default agent if not specified via -a flag // This is not used for selecting tasks or rules, only as a default Agent string `yaml:"agent,omitempty" json:"agent,omitempty"` @@ -75,6 +87,18 @@ func (t *TaskFrontMatter) UnmarshalJSON(data []byte) error { type CommandFrontMatter struct { BaseFrontMatter `yaml:",inline"` + // ID is an optional unique identifier for the command + // Metadata only, does not affect command matching or filtering + ID string `yaml:"id,omitempty" json:"id,omitempty"` + + // Name is an optional human-readable name for the command + // Metadata only, does not affect command matching or filtering + Name string `yaml:"name,omitempty" json:"name,omitempty"` + + // Description is an optional description of what the command does + // Metadata only, does not affect command matching or filtering + Description string `yaml:"description,omitempty" json:"description,omitempty"` + // ExpandParams controls whether parameter expansion should occur // Defaults to true if not specified ExpandParams *bool `yaml:"expand,omitempty" json:"expand,omitempty"` @@ -110,6 +134,18 @@ func (c *CommandFrontMatter) UnmarshalJSON(data []byte) error { type RuleFrontMatter struct { BaseFrontMatter `yaml:",inline"` + // ID is an optional unique identifier for the rule + // Metadata only, does not affect rule matching or filtering + ID string `yaml:"id,omitempty" json:"id,omitempty"` + + // Name is an optional human-readable name for the rule + // Metadata only, does not affect rule matching or filtering + Name string `yaml:"name,omitempty" json:"name,omitempty"` + + // Description is an optional description of what the rule provides + // Metadata only, does not affect rule matching or filtering + Description string `yaml:"description,omitempty" json:"description,omitempty"` + // TaskNames specifies which task(s) this rule applies to // Array of task names for OR logic TaskNames []string `yaml:"task_names,omitempty" json:"task_names,omitempty"` diff --git a/pkg/codingcontext/markdown/frontmatter_command_test.go b/pkg/codingcontext/markdown/frontmatter_command_test.go new file mode 100644 index 0000000..a75de73 --- /dev/null +++ b/pkg/codingcontext/markdown/frontmatter_command_test.go @@ -0,0 +1,170 @@ +package markdown + +import ( + "testing" + + "github.com/goccy/go-yaml" +) + +func TestCommandFrontMatter_Marshal(t *testing.T) { + tests := []struct { + name string + command CommandFrontMatter + want string + }{ + { + name: "minimal command", + command: CommandFrontMatter{}, + want: "{}\n", + }, + { + name: "command with standard id, name, description", + command: CommandFrontMatter{ + ID: "cmd-123", + Name: "Standard Command", + Description: "This is a standard command with metadata", + }, + want: `id: cmd-123 +name: Standard Command +description: This is a standard command with metadata +`, + }, + { + name: "command with expand false", + command: CommandFrontMatter{ + ID: "cmd-456", + Name: "No Expand Command", + Description: "Command with expansion disabled", + ExpandParams: func() *bool { + b := false + return &b + }(), + }, + want: `id: cmd-456 +name: No Expand Command +description: Command with expansion disabled +expand: false +`, + }, + { + name: "command with selectors", + command: CommandFrontMatter{ + ID: "cmd-789", + Name: "Selector Command", + Description: "Command with selectors", + Selectors: map[string]any{ + "database": "postgres", + "feature": "auth", + }, + }, + want: `id: cmd-789 +name: Selector Command +description: Command with selectors +selectors: + database: postgres + feature: auth +`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := yaml.Marshal(&tt.command) + if err != nil { + t.Fatalf("Marshal() error = %v", err) + } + if string(got) != tt.want { + t.Errorf("Marshal() = %q, want %q", string(got), tt.want) + } + }) + } +} + +func TestCommandFrontMatter_Unmarshal(t *testing.T) { + tests := []struct { + name string + yaml string + want CommandFrontMatter + wantErr bool + }{ + { + name: "command with standard id, name, description", + yaml: `id: cmd-abc +name: Named Command +description: A command with standard fields +`, + want: CommandFrontMatter{ + ID: "cmd-abc", + Name: "Named Command", + Description: "A command with standard fields", + }, + }, + { + name: "command with expand false", + yaml: `id: cmd-def +name: No Expand +description: No expansion +expand: false +`, + want: CommandFrontMatter{ + ID: "cmd-def", + Name: "No Expand", + Description: "No expansion", + ExpandParams: func() *bool { + b := false + return &b + }(), + }, + }, + { + name: "command with selectors", + yaml: `id: cmd-ghi +name: Selector Command +description: Has selectors +selectors: + database: postgres + feature: auth +`, + want: CommandFrontMatter{ + ID: "cmd-ghi", + Name: "Selector Command", + Description: "Has selectors", + Selectors: map[string]any{ + "database": "postgres", + "feature": "auth", + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var got CommandFrontMatter + err := yaml.Unmarshal([]byte(tt.yaml), &got) + if (err != nil) != tt.wantErr { + t.Fatalf("Unmarshal() error = %v, wantErr %v", err, tt.wantErr) + } + if err != nil { + return + } + + // Compare fields individually + if got.ID != tt.want.ID { + t.Errorf("ID = %q, want %q", got.ID, tt.want.ID) + } + if got.Name != tt.want.Name { + t.Errorf("Name = %q, want %q", got.Name, tt.want.Name) + } + if got.Description != tt.want.Description { + t.Errorf("Description = %q, want %q", got.Description, tt.want.Description) + } + if (got.ExpandParams == nil) != (tt.want.ExpandParams == nil) { + t.Errorf("ExpandParams nil mismatch: got %v, want %v", got.ExpandParams == nil, tt.want.ExpandParams == nil) + } else if got.ExpandParams != nil && tt.want.ExpandParams != nil { + if *got.ExpandParams != *tt.want.ExpandParams { + t.Errorf("ExpandParams = %v, want %v", *got.ExpandParams, *tt.want.ExpandParams) + } + } + }) + } +} diff --git a/pkg/codingcontext/markdown/frontmatter_rule_test.go b/pkg/codingcontext/markdown/frontmatter_rule_test.go index 6424383..f7c24b7 100644 --- a/pkg/codingcontext/markdown/frontmatter_rule_test.go +++ b/pkg/codingcontext/markdown/frontmatter_rule_test.go @@ -18,6 +18,18 @@ func TestRuleFrontMatter_Marshal(t *testing.T) { rule: RuleFrontMatter{}, want: "{}\n", }, + { + name: "rule with standard id, name, description", + rule: RuleFrontMatter{ + ID: "rule-789", + Name: "Standard Rule", + Description: "This is a standard rule with metadata", + }, + want: `id: rule-789 +name: Standard Rule +description: This is a standard rule with metadata +`, + }, { name: "rule with task_names", rule: RuleFrontMatter{ @@ -48,9 +60,12 @@ agent: cursor { name: "rule with all fields", rule: RuleFrontMatter{ - TaskNames: []string{"test-task"}, - Languages: []string{"go", "python"}, - Agent: "copilot", + ID: "all-fields-rule", + Name: "Complete Rule", + Description: "A rule with all fields", + TaskNames: []string{"test-task"}, + Languages: []string{"go", "python"}, + Agent: "copilot", MCPServer: mcp.MCPServerConfig{ Type: mcp.TransportTypeStdio, Command: "database-server", @@ -58,7 +73,10 @@ agent: cursor }, RuleName: "test-rule", }, - want: `task_names: + want: `id: all-fields-rule +name: Complete Rule +description: A rule with all fields +task_names: - test-task languages: - go @@ -95,6 +113,18 @@ func TestRuleFrontMatter_Unmarshal(t *testing.T) { want RuleFrontMatter wantErr bool }{ + { + name: "rule with standard id, name, description", + yaml: `id: rule-987 +name: Named Rule +description: A rule with standard fields +`, + want: RuleFrontMatter{ + ID: "rule-987", + Name: "Named Rule", + Description: "A rule with standard fields", + }, + }, { name: "rule with task_names and languages", yaml: `task_names: @@ -147,6 +177,15 @@ languages: } // Compare fields individually + if got.ID != tt.want.ID { + t.Errorf("ID = %q, want %q", got.ID, tt.want.ID) + } + if got.Name != tt.want.Name { + t.Errorf("Name = %q, want %q", got.Name, tt.want.Name) + } + if got.Description != tt.want.Description { + t.Errorf("Description = %q, want %q", got.Description, tt.want.Description) + } if got.Agent != tt.want.Agent { t.Errorf("Agent = %q, want %q", got.Agent, tt.want.Agent) } diff --git a/pkg/codingcontext/markdown/frontmatter_task_test.go b/pkg/codingcontext/markdown/frontmatter_task_test.go index c84d874..fca64bb 100644 --- a/pkg/codingcontext/markdown/frontmatter_task_test.go +++ b/pkg/codingcontext/markdown/frontmatter_task_test.go @@ -21,23 +21,45 @@ func TestTaskFrontMatter_Marshal(t *testing.T) { }, want: "task_name: test-task\n", }, + { + name: "task with standard id, name, description", + task: TaskFrontMatter{ + BaseFrontMatter: BaseFrontMatter{ + Content: map[string]any{"task_name": "standard-task"}, + }, + ID: "task-123", + Name: "Standard Test Task", + Description: "This is a test task with standard fields", + }, + want: `task_name: standard-task +id: task-123 +name: Standard Test Task +description: This is a test task with standard fields +`, + }, { name: "task with all fields", task: TaskFrontMatter{ BaseFrontMatter: BaseFrontMatter{ Content: map[string]any{"task_name": "full-task"}, }, - Agent: "cursor", - Languages: []string{"go"}, - Model: "gpt-4", - SingleShot: true, - Timeout: "10m", - Resume: false, + ID: "full-123", + Name: "Full Task", + Description: "A task with all fields", + Agent: "cursor", + Languages: []string{"go"}, + Model: "gpt-4", + SingleShot: true, + Timeout: "10m", + Resume: false, Selectors: map[string]any{ "stage": "implementation", }, }, want: `task_name: full-task +id: full-123 +name: Full Task +description: A task with all fields agent: cursor languages: - go @@ -94,6 +116,22 @@ func TestTaskFrontMatter_Unmarshal(t *testing.T) { }, }, }, + { + name: "task with standard id, name, description", + yaml: `task_name: standard-task +id: task-456 +name: Standard Task +description: This is a standard task +`, + want: TaskFrontMatter{ + BaseFrontMatter: BaseFrontMatter{ + Content: map[string]any{"task_name": "standard-task"}, + }, + ID: "task-456", + Name: "Standard Task", + Description: "This is a standard task", + }, + }, { name: "task with single language", yaml: `task_name: test-task @@ -124,6 +162,9 @@ languages: { name: "full task", yaml: `task_name: full-task +id: full-456 +name: Full Task +description: A complete task agent: cursor languages: - go @@ -137,11 +178,14 @@ selectors: BaseFrontMatter: BaseFrontMatter{ Content: map[string]any{"task_name": "full-task"}, }, - Agent: "cursor", - Languages: []string{"go"}, - Model: "gpt-4", - SingleShot: true, - Timeout: "10m", + ID: "full-456", + Name: "Full Task", + Description: "A complete task", + Agent: "cursor", + Languages: []string{"go"}, + Model: "gpt-4", + SingleShot: true, + Timeout: "10m", Selectors: map[string]any{ "stage": "implementation", }, @@ -166,6 +210,15 @@ selectors: if gotTaskName != wantTaskName { t.Errorf("TaskName = %q, want %q", gotTaskName, wantTaskName) } + if got.ID != tt.want.ID { + t.Errorf("ID = %q, want %q", got.ID, tt.want.ID) + } + if got.Name != tt.want.Name { + t.Errorf("Name = %q, want %q", got.Name, tt.want.Name) + } + if got.Description != tt.want.Description { + t.Errorf("Description = %q, want %q", got.Description, tt.want.Description) + } if got.Agent != tt.want.Agent { t.Errorf("Agent = %q, want %q", got.Agent, tt.want.Agent) }