steerdev 1.0.35__tar.gz → 1.0.37__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. {steerdev-1.0.35 → steerdev-1.0.37}/PKG-INFO +1 -1
  2. {steerdev-1.0.35 → steerdev-1.0.37}/pyproject.toml +1 -1
  3. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/cli.py +56 -13
  4. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/prompt/builder.py +4 -0
  5. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/prompt/templates.py +4 -0
  6. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/runner.py +1 -0
  7. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/skills/steerdev-merge-into-canal-skill/SKILL.md +2 -0
  8. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/skills/steerdev-single-task-merge-skill/SKILL.md +21 -3
  9. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/skills/steerdev-task-management-skill/SKILL.md +5 -1
  10. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/skills/steerdev-wave-tasks-merge-skill/SKILL.md +27 -5
  11. {steerdev-1.0.35 → steerdev-1.0.37}/.github/workflows/pre-commit.yml +0 -0
  12. {steerdev-1.0.35 → steerdev-1.0.37}/.github/workflows/publish.yml +0 -0
  13. {steerdev-1.0.35 → steerdev-1.0.37}/.gitignore +0 -0
  14. {steerdev-1.0.35 → steerdev-1.0.37}/.pre-commit-config.yaml +0 -0
  15. {steerdev-1.0.35 → steerdev-1.0.37}/AGENTS.md +0 -0
  16. {steerdev-1.0.35 → steerdev-1.0.37}/CLAUDE.md +0 -0
  17. {steerdev-1.0.35 → steerdev-1.0.37}/README.md +0 -0
  18. {steerdev-1.0.35 → steerdev-1.0.37}/scripts/pre-commit-version-bump.sh +0 -0
  19. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/__init__.py +0 -0
  20. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/agent_loop.py +0 -0
  21. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/__init__.py +0 -0
  22. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/activity.py +0 -0
  23. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/agents.py +0 -0
  24. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/canals.py +0 -0
  25. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/client.py +0 -0
  26. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/commands.py +0 -0
  27. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/configs.py +0 -0
  28. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/context.py +0 -0
  29. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/events.py +0 -0
  30. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/hooks.py +0 -0
  31. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/implementation_plan.py +0 -0
  32. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/messages.py +0 -0
  33. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/prd.py +0 -0
  34. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/runs.py +0 -0
  35. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/sessions.py +0 -0
  36. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/specs.py +0 -0
  37. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/tasks.py +0 -0
  38. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/workflow_runs.py +0 -0
  39. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/api/workflows.py +0 -0
  40. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/config/__init__.py +0 -0
  41. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/config/models.py +0 -0
  42. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/config/platform.py +0 -0
  43. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/config/settings.py +0 -0
  44. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/executor/__init__.py +0 -0
  45. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/executor/base.py +0 -0
  46. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/executor/claude.py +0 -0
  47. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/executor/stream.py +0 -0
  48. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/handlers/__init__.py +0 -0
  49. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/handlers/prd.py +0 -0
  50. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/integration.py +0 -0
  51. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/prompt/__init__.py +0 -0
  52. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/prompt/workflow_template.py +0 -0
  53. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/py.typed +0 -0
  54. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/retry.py +0 -0
  55. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/__init__.py +0 -0
  56. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/claude_setup.py +0 -0
  57. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/repo_setup.py +0 -0
  58. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/ci/canal-integration.yml +0 -0
  59. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/claude_md_section.md +0 -0
  60. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/settings.json +0 -0
  61. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/skills/steerdev-activity-skill/SKILL.md +0 -0
  62. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/skills/steerdev-canal-workflow-skill/SKILL.md +0 -0
  63. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/skills/steerdev-context-skill/SKILL.md +0 -0
  64. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/skills/steerdev-git-workflow-skill/SKILL.md +0 -0
  65. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/skills/steerdev-progress-logging-skill/SKILL.md +0 -0
  66. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/skills/steerdev-specs-management-skill/SKILL.md +0 -0
  67. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/setup/templates/steerdev.yaml +0 -0
  68. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/update_check.py +0 -0
  69. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/version.py +0 -0
  70. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/workflow/__init__.py +0 -0
  71. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/workflow/context.py +0 -0
  72. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/workflow/executor.py +0 -0
  73. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/workflow/memory.py +0 -0
  74. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/workspace/__init__.py +0 -0
  75. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/workspace/project_manager.py +0 -0
  76. {steerdev-1.0.35 → steerdev-1.0.37}/src/steerdev_agent/workspace/tool_detection.py +0 -0
  77. {steerdev-1.0.35 → steerdev-1.0.37}/tests/__init__.py +0 -0
  78. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_agent_loop.py +0 -0
  79. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_agent_loop_extended.py +0 -0
  80. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_agents_api.py +0 -0
  81. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_api_client.py +0 -0
  82. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_claude_executor.py +0 -0
  83. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_claude_setup.py +0 -0
  84. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_client_methods.py +0 -0
  85. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_commands_api.py +0 -0
  86. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_config.py +0 -0
  87. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_config_extended.py +0 -0
  88. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_context_search.py +0 -0
  89. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_executor.py +0 -0
  90. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_platform_config.py +0 -0
  91. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_prompt.py +0 -0
  92. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_retry.py +0 -0
  93. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_runner_merge_modes.py +0 -0
  94. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_stream_parser.py +0 -0
  95. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_tasks.py +0 -0
  96. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_version.py +0 -0
  97. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_workflow_context.py +0 -0
  98. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_workflow_memory.py +0 -0
  99. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_workflow_prompt_template.py +0 -0
  100. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_workspace.py +0 -0
  101. {steerdev-1.0.35 → steerdev-1.0.37}/tests/test_workspace_extended.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: steerdev
3
- Version: 1.0.35
3
+ Version: 1.0.37
4
4
  Summary: Backend task runner for steerdev.com - orchestrates CLI coding agents with activity reporting
5
5
  Project-URL: Homepage, https://github.com/pentoai/steerdev-agent
6
6
  Project-URL: Repository, https://github.com/pentoai/steerdev-agent
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "steerdev"
3
- version = "1.0.35"
3
+ version = "1.0.37"
4
4
  description = "Backend task runner for steerdev.com - orchestrates CLI coding agents with activity reporting"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -1145,40 +1145,83 @@ git_app = typer.Typer(
1145
1145
  app.add_typer(git_app)
1146
1146
 
1147
1147
 
1148
+ def _slugify(text: str, max_length: int = 48) -> str:
1149
+ """Convert text to a git-safe branch slug.
1150
+
1151
+ Lowercases, replaces non-alphanumeric chars with hyphens, collapses
1152
+ consecutive hyphens, and trims to max_length.
1153
+ """
1154
+ import re
1155
+
1156
+ slug = text.lower().strip()
1157
+ slug = re.sub(r"[^a-z0-9]+", "-", slug)
1158
+ slug = slug.strip("-")
1159
+ # Trim to max_length without cutting mid-word
1160
+ if len(slug) > max_length:
1161
+ slug = slug[:max_length].rsplit("-", 1)[0]
1162
+ return slug
1163
+
1164
+
1148
1165
  @git_app.command("branch")
1149
1166
  def git_branch(
1150
1167
  task_id: Annotated[
1151
1168
  str | None,
1152
- typer.Argument(help="Task ID to create branch for (uses first 8 chars)"),
1169
+ typer.Argument(help="Task ID to create branch for"),
1153
1170
  ] = None,
1154
1171
  name: Annotated[
1155
1172
  str | None,
1156
- typer.Option("--name", "-n", help="Custom branch name suffix"),
1173
+ typer.Option(
1174
+ "--name",
1175
+ "-n",
1176
+ help="Custom branch name slug (overrides auto-slug)",
1177
+ ),
1157
1178
  ] = None,
1158
1179
  ) -> None:
1159
1180
  """Create a task branch with steerdev naming convention.
1160
1181
 
1161
- Creates a branch named `task/<task-id-short>` or `task/<task-id-short>-<name>`.
1162
- Uses the first 8 characters of the task ID for the branch name.
1182
+ Fetches the task from the API to resolve the external ticket identifier
1183
+ (e.g. Linear ID) and auto-generates a descriptive branch name.
1184
+
1185
+ Branch naming priority:
1186
+ 1. External ticket ID + slug: task/<LINEAR-ID>-<slug>
1187
+ 2. External ticket ID only: task/<LINEAR-ID>
1188
+ 3. Fallback (no ticket ID): task/<short-uuid>[-<slug>]
1163
1189
 
1164
1190
  Example:
1165
1191
  steerdev git branch abc12345-...
1166
- # Creates: task/abc12345
1192
+ # Fetches task, finds Linear ID "PROJ-123", title "Add user auth"
1193
+ # Creates: task/PROJ-123-add-user-auth
1194
+
1195
+ steerdev git branch abc12345-... --name custom-slug
1196
+ # Creates: task/PROJ-123-custom-slug
1167
1197
 
1168
- steerdev git branch abc12345-... --name auth-flow
1169
- # Creates: task/abc12345-auth-flow
1198
+ # If no Linear ID exists, falls back to short UUID:
1199
+ # Creates: task/abc12345-add-user-auth
1170
1200
  """
1171
1201
  import subprocess
1172
1202
 
1203
+ from steerdev_agent.api.tasks import TasksClient
1204
+
1173
1205
  if not task_id:
1174
1206
  console.print("[red]Error: Task ID is required[/red]")
1175
1207
  raise typer.Exit(1)
1176
1208
 
1177
- # Use first 8 chars of task ID
1178
- short_id = task_id[:8]
1179
- branch_name = f"task/{short_id}"
1180
- if name:
1181
- branch_name = f"task/{short_id}-{name}"
1209
+ # Fetch task to get external identifier and title
1210
+ linear_id: str | None = None
1211
+ task_title: str | None = None
1212
+ with TasksClient() as client:
1213
+ if client.check_api_key():
1214
+ task = client.get_task(task_id)
1215
+ if task:
1216
+ linear_id = task.get("linear_identifier")
1217
+ task_title = task.get("title")
1218
+
1219
+ # Build branch name: prefer external ticket ID over internal UUID
1220
+ prefix = linear_id or task_id[:8]
1221
+
1222
+ # Determine the slug: explicit --name, or auto-generated from title
1223
+ slug = name or (_slugify(task_title) if task_title else None)
1224
+ branch_name = f"task/{prefix}-{slug}" if slug else f"task/{prefix}"
1182
1225
 
1183
1226
  try:
1184
1227
  # Check if branch already exists
@@ -1200,7 +1243,7 @@ def git_branch(
1200
1243
  Panel(
1201
1244
  f"[bold green]Branch created[/bold green]\n\n"
1202
1245
  f"Branch: {branch_name}\n"
1203
- f"Task ID: {task_id}",
1246
+ f"Task ID: {task_id}" + (f"\nLinear ID: {linear_id}" if linear_id else ""),
1204
1247
  title="Success",
1205
1248
  border_style="green",
1206
1249
  )
@@ -38,6 +38,9 @@ class TaskContext(BaseModel):
38
38
  status: str = Field(default="unstarted", description="Task status")
39
39
  priority: int = Field(default=3, description="Task priority (1=urgent, 4=low)")
40
40
  working_directory: str | None = Field(default=None, description="Task working directory")
41
+ linear_identifier: str | None = Field(
42
+ default=None, description="External ticket ID (e.g. Linear PROJ-123)"
43
+ )
41
44
  spec: str | None = Field(default=None, description="Technical specification")
42
45
  metadata: dict[str, Any] | None = Field(default=None, description="Additional metadata")
43
46
  wave: WaveContext | None = Field(
@@ -181,6 +184,7 @@ class PromptBuilder:
181
184
  priority=task.priority,
182
185
  status=task.status,
183
186
  working_directory=working_dir,
187
+ linear_identifier=task.linear_identifier,
184
188
  )
185
189
 
186
190
  # Add spec if present
@@ -22,6 +22,7 @@ class PromptTemplates:
22
22
 
23
23
  **Title:** {title}
24
24
  **ID:** {task_id}
25
+ **Ticket:** {ticket_id}
25
26
  **Priority:** {priority}
26
27
  **Status:** {status}
27
28
 
@@ -299,6 +300,7 @@ Include what you accomplished, key decisions, files changed, and anything the ne
299
300
  priority: int = 3,
300
301
  status: str = "unstarted",
301
302
  working_directory: str = ".",
303
+ linear_identifier: str | None = None,
302
304
  ) -> str:
303
305
  """Format task information.
304
306
 
@@ -309,6 +311,7 @@ Include what you accomplished, key decisions, files changed, and anything the ne
309
311
  priority: Task priority (1-4).
310
312
  status: Task status.
311
313
  working_directory: Working directory.
314
+ linear_identifier: External ticket ID (e.g. Linear PROJ-123).
312
315
 
313
316
  Returns:
314
317
  Formatted task information.
@@ -319,6 +322,7 @@ Include what you accomplished, key decisions, files changed, and anything the ne
319
322
  return cls.TASK_PROMPT.format(
320
323
  title=title,
321
324
  task_id=task_id,
325
+ ticket_id=linear_identifier or "N/A",
322
326
  priority=priority_display,
323
327
  status=status,
324
328
  prompt=prompt,
@@ -489,6 +489,7 @@ class Runner:
489
489
  status=task.get("status", "unstarted"),
490
490
  priority=task.get("priority", 3),
491
491
  working_directory=task.get("working_directory"),
492
+ linear_identifier=task.get("linear_identifier"),
492
493
  wave=wave_context,
493
494
  ),
494
495
  )
@@ -1,5 +1,7 @@
1
1
  # Merge Into Canal Skill
2
2
 
3
+ > **IMPORTANT: This skill is opt-in only.** Only use it when the `--canals` flag was explicitly passed to `steerdev run` or `steerdev agent`. If you are unsure whether canals are enabled, use `steerdev-wave-tasks-merge-skill` or `steerdev-single-task-merge-skill` instead.
4
+
3
5
  Use this skill when a workflow phase tells you to merge the **current task branch or wave branch into a canal**.
4
6
 
5
7
  ## When to Use
@@ -6,7 +6,7 @@ Use this skill when a workflow phase tells you to complete **one task on one bra
6
6
 
7
7
  - The workflow prompt explicitly references `single-task-merge`
8
8
  - `--no-waves` is active, or no wave context is present
9
- - `--no-canals` is active
9
+ - Canals are not explicitly enabled for this project (canal mode requires `--canals` flag and explicit setup)
10
10
 
11
11
  ## Expected Outcome
12
12
 
@@ -45,6 +45,11 @@ Before creating your task branch, ensure you're starting from an up-to-date defa
45
45
  steerdev git branch TASK_ID [--name NAME]
46
46
  ```
47
47
 
48
+ This fetches the task from the API and builds the branch name automatically:
49
+ - If the task has an external ticket ID (e.g. Linear `PROJ-123`): `task/PROJ-123-<slug-from-title>`
50
+ - If no external ID exists: `task/<short-uuid>-<slug-from-title>`
51
+ - Use `--name` to override the auto-generated slug
52
+
48
53
  3. Implement the requested changes
49
54
  4. Commit with a conventional commit message that explains why the change exists
50
55
  5. Push the current branch:
@@ -62,9 +67,20 @@ steerdev git pr --title "TITLE" --task-id TASK_ID [--body "BODY"]
62
67
  7. Update the task result with the PR URL
63
68
  8. Log completion in the root `docs/` progress files
64
69
 
70
+ ## Branch Naming Convention
71
+
72
+ Branch names should link to the external ticket tracker (e.g. Linear) for traceability on GitHub:
73
+
74
+ | Has External ID? | Format | Example |
75
+ |---|---|---|
76
+ | Yes | `task/<TICKET-ID>-<slug>` | `task/PROJ-123-add-user-auth` |
77
+ | No | `task/<short-uuid>-<slug>` | `task/abc12345-add-user-auth` |
78
+
79
+ **Why this matters:** GitHub integrations (Linear, Jira, etc.) match ticket IDs in branch names to link PRs/branches back to issues. Using internal UUIDs breaks this linkage.
80
+
65
81
  ## Conventions
66
82
 
67
- - Branch naming should follow `task/<short-task-id>` unless the workflow prompt says otherwise
83
+ - Always use `steerdev git branch` to create branches (it resolves the external ticket ID automatically)
68
84
  - Create exactly one PR for the task
69
85
  - Include the PR URL in the task result summary
70
86
 
@@ -73,10 +89,12 @@ steerdev git pr --title "TITLE" --task-id TASK_ID [--body "BODY"]
73
89
  ```bash
74
90
  steerdev tasks update abc12345... --status started
75
91
  steerdev git branch abc12345...
92
+ # → Creates: task/PROJ-123-add-user-authentication (if Linear ID exists)
93
+ # → Creates: task/abc12345-add-user-authentication (fallback)
76
94
  # ... implement changes ...
77
95
  git add .
78
96
  git commit -m "feat: add user authentication"
79
97
  git push -u origin HEAD
80
- steerdev git pr --title "Add user authentication" --task-id abc12345...
98
+ steerdev git pr --title "PROJ-123: Add user authentication" --task-id abc12345...
81
99
  steerdev tasks update abc12345... --result "PR: https://github.com/org/repo/pull/42"
82
100
  ```
@@ -120,7 +120,11 @@ Create a new task for discovered work items.
120
120
  4. Implement the requested change.
121
121
  5. Verify web/UI changes visually with `agent-browser`.
122
122
  6. Add task comments when useful for blockers, handoffs, or status notes.
123
- 7. Update the task result and status when the active workflow reaches completion.
123
+ 7. Merge and create a PR using the appropriate merge skill:
124
+ - **Wave tasks** (task has wave context): use `steerdev-wave-tasks-merge-skill`
125
+ - **Standalone tasks** (no wave context): use `steerdev-single-task-merge-skill`
126
+ - **Canal merge** (`steerdev-merge-into-canal-skill`): only when `--canals` was explicitly passed — do NOT use this by default
127
+ 8. Update the task result and status when the active workflow reaches completion.
124
128
 
125
129
  **IMPORTANT**: Always write progress logs. See the **steerdev-progress-logging-skill** for details.
126
130
 
@@ -6,7 +6,7 @@ Use this skill when a workflow phase tells you to complete **multiple related ta
6
6
 
7
7
  - The workflow prompt explicitly references `wave-tasks-merge`
8
8
  - `--waves` is active and wave context is present
9
- - `--no-canals` is active
9
+ - Canals are not explicitly enabled for this project (canal mode requires `--canals` flag and explicit setup)
10
10
 
11
11
  ## Expected Outcome
12
12
 
@@ -40,7 +40,15 @@ git checkout -b wave/<wave-number>
40
40
  2. For each task in the wave:
41
41
  - Mark the task `started`
42
42
  - Implement the requested change
43
- - Commit with a task-prefixed conventional commit, such as `[task:<id>] feat: ...`
43
+ - Commit with a task-prefixed conventional commit. **Use the external ticket ID when available** (e.g. Linear ID), falling back to the internal short ID:
44
+
45
+ ```bash
46
+ # With external ticket ID (preferred):
47
+ git commit -m "[PROJ-123] feat: add user endpoint"
48
+
49
+ # Fallback (no external ID):
50
+ git commit -m "[task:abc12345] feat: add user endpoint"
51
+ ```
44
52
 
45
53
  3. After the wave work is ready for review, push the shared branch:
46
54
 
@@ -57,26 +65,40 @@ steerdev git pr --title "Wave <N>: <description>" --body "..."
57
65
  5. Update all related tasks with the shared PR URL
58
66
  6. Log progress and completion in the root `docs/` progress files
59
67
 
68
+ ## Commit Prefix Convention
69
+
70
+ Use external ticket IDs in commits so GitHub integrations can link commits to issues:
71
+
72
+ | Has External ID? | Commit Prefix | Example |
73
+ |---|---|---|
74
+ | Yes | `[<TICKET-ID>]` | `[PROJ-123] feat: add user endpoint` |
75
+ | No | `[task:<short-uuid>]` | `[task:abc12345] feat: add user endpoint` |
76
+
77
+ Run `steerdev tasks get TASK_ID` to find the task's `linear_identifier` before committing.
78
+
60
79
  ## Conventions
61
80
 
62
81
  - Use one branch per wave: `wave/<wave-number>`
63
82
  - Do not create per-task PRs inside the wave
64
- - Keep commits traceable by including `[task:<id>]` in each task-specific commit
83
+ - Keep commits traceable by including the external ticket ID (or internal ID fallback) in each commit
65
84
  - Include the shared PR URL in every related task result
66
85
 
67
86
  ## Example
68
87
 
69
88
  ```bash
70
89
  git checkout -b wave/3
90
+
71
91
  steerdev tasks update task-aaa... --status started
92
+ # Check: steerdev tasks get task-aaa... → Linear ID: PROJ-123
72
93
  # ... implement task 1 ...
73
94
  git add .
74
- git commit -m "[task:task-aaa] feat: add user endpoint"
95
+ git commit -m "[PROJ-123] feat: add user endpoint"
75
96
 
76
97
  steerdev tasks update task-bbb... --status started
98
+ # Check: steerdev tasks get task-bbb... → Linear ID: PROJ-124
77
99
  # ... implement task 2 ...
78
100
  git add .
79
- git commit -m "[task:task-bbb] fix: validate email format"
101
+ git commit -m "[PROJ-124] fix: validate email format"
80
102
 
81
103
  git push -u origin HEAD
82
104
  steerdev git pr --title "Wave 3: User management improvements" --body "..."
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes