steerdev 1.0.59__tar.gz → 1.0.60__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.
- {steerdev-1.0.59 → steerdev-1.0.60}/PKG-INFO +1 -1
- {steerdev-1.0.59 → steerdev-1.0.60}/pyproject.toml +1 -1
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/agent_loop.py +11 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/cli.py +27 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/config/models.py +20 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/prompt/builder.py +15 -3
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/prompt/templates.py +10 -3
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/runner.py +66 -24
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/skills/steerdev-merge-into-canal-skill/SKILL.md +6 -5
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/skills/steerdev-single-task-merge-skill/SKILL.md +10 -40
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/skills/steerdev-wave-tasks-merge-skill/SKILL.md +10 -22
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/steerdev.yaml +5 -0
- steerdev-1.0.60/src/steerdev_agent/workspace/preparation.py +243 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_config.py +29 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_conflict_mitigation.py +2 -0
- steerdev-1.0.60/tests/test_preparation.py +358 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/.github/workflows/pre-commit.yml +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/.github/workflows/publish.yml +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/.gitignore +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/.pre-commit-config.yaml +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/AGENTS.md +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/CLAUDE.md +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/README.md +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/scripts/pre-commit-version-bump.sh +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/snapshots/steerdev-agent-v1/Dockerfile +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/snapshots/steerdev-agent-v1/start-agent.sh +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/__init__.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/__init__.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/activity.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/agents.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/canals.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/client.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/commands.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/configs.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/context.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/events.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/hooks.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/implementation_plan.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/merger.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/messages.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/prd.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/reports.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/runs.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/sessions.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/specs.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/tasks.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/workflow_runs.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/api/workflows.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/config/__init__.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/config/platform.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/config/settings.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/evidence.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/evidence_assets.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/executor/__init__.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/executor/base.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/executor/claude.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/executor/stream.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/handlers/__init__.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/handlers/prd.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/integration.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/prompt/__init__.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/prompt/workflow_template.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/py.typed +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/retry.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/__init__.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/claude_setup.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/repo_setup.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/ci/canal-integration.yml +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/claude_md_section.md +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/settings.json +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/skills/steerdev-activity-skill/SKILL.md +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/skills/steerdev-canal-workflow-skill/SKILL.md +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/skills/steerdev-context-skill/SKILL.md +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/skills/steerdev-git-workflow-skill/SKILL.md +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/skills/steerdev-progress-logging-skill/SKILL.md +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/skills/steerdev-specs-management-skill/SKILL.md +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/skills/steerdev-task-management-skill/SKILL.md +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/setup/templates/worktrunk.config.toml +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/update_check.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/version.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/workflow/__init__.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/workflow/context.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/workflow/executor.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/workflow/memory.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/workspace/__init__.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/workspace/project_manager.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/workspace/tool_detection.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/src/steerdev_agent/worktree.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/__init__.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_agent_loop.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_agent_loop_extended.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_agents_api.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_api_client.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_claude_executor.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_claude_setup.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_client_methods.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_commands_api.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_config_extended.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_context_search.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_executor.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_platform_config.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_prompt.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_reports_client.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_retry.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_runner_merge_modes.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_runner_worktrees.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_stream_parser.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_tasks.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_version.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_workflow_context.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_workflow_memory.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_workflow_prompt_template.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_workflow_runs_api.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_workspace.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_workspace_extended.py +0 -0
- {steerdev-1.0.59 → steerdev-1.0.60}/tests/test_worktree.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: steerdev
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.60
|
|
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
|
|
@@ -36,6 +36,7 @@ from steerdev_agent.api.sessions import SessionCreateRequest, SessionsClient
|
|
|
36
36
|
from steerdev_agent.api.tasks import TasksClient
|
|
37
37
|
from steerdev_agent.config.models import (
|
|
38
38
|
AgentLoopConfig,
|
|
39
|
+
BranchConfig,
|
|
39
40
|
EvidenceConfig,
|
|
40
41
|
ExecutorConfig,
|
|
41
42
|
RetryConfig,
|
|
@@ -77,6 +78,7 @@ class CommandExecutor:
|
|
|
77
78
|
_workflow_id: str | None
|
|
78
79
|
_enable_waves: bool
|
|
79
80
|
_enable_canals: bool
|
|
81
|
+
_branch_config: BranchConfig
|
|
80
82
|
_worktree_config: WorktreeConfig
|
|
81
83
|
_evidence_config: EvidenceConfig
|
|
82
84
|
_agent_loop_config: AgentLoopConfig
|
|
@@ -181,6 +183,7 @@ class CommandExecutor:
|
|
|
181
183
|
evidence_config=self._evidence_config,
|
|
182
184
|
executor_config=self._executor_config,
|
|
183
185
|
force_workflow_id=None,
|
|
186
|
+
branch_config=self._branch_config,
|
|
184
187
|
shutdown_event=self._shutdown_event,
|
|
185
188
|
agent_id=self._agent_id,
|
|
186
189
|
)
|
|
@@ -498,6 +501,7 @@ class AgentLoop(CommandExecutor):
|
|
|
498
501
|
worktree_config: WorktreeConfig | None = None,
|
|
499
502
|
evidence_config: EvidenceConfig | None = None,
|
|
500
503
|
retry_config: RetryConfig | None = None,
|
|
504
|
+
branch_config: BranchConfig | None = None,
|
|
501
505
|
) -> None:
|
|
502
506
|
self.project_id = project_id
|
|
503
507
|
self.agent_name = agent_name
|
|
@@ -509,6 +513,7 @@ class AgentLoop(CommandExecutor):
|
|
|
509
513
|
self._agent_loop_config = agent_loop_config or AgentLoopConfig()
|
|
510
514
|
self._executor_config = executor_config or ExecutorConfig()
|
|
511
515
|
self._retry_config = retry_config or RetryConfig()
|
|
516
|
+
self._branch_config = branch_config or BranchConfig()
|
|
512
517
|
self._workflow_id = force_workflow_id
|
|
513
518
|
self._enable_waves = enable_waves
|
|
514
519
|
self._enable_canals = enable_canals
|
|
@@ -865,6 +870,7 @@ class WorkspaceAgentLoop(CommandExecutor):
|
|
|
865
870
|
worktree_config: WorktreeConfig | None = None,
|
|
866
871
|
evidence_config: EvidenceConfig | None = None,
|
|
867
872
|
retry_config: RetryConfig | None = None,
|
|
873
|
+
branch_config: BranchConfig | None = None,
|
|
868
874
|
) -> None:
|
|
869
875
|
self.workspace_path = Path(workspace_path)
|
|
870
876
|
self.agent_name = agent_name
|
|
@@ -875,6 +881,7 @@ class WorkspaceAgentLoop(CommandExecutor):
|
|
|
875
881
|
self._agent_loop_config = agent_loop_config or AgentLoopConfig()
|
|
876
882
|
self._executor_config = executor_config or ExecutorConfig()
|
|
877
883
|
self._retry_config = retry_config or RetryConfig()
|
|
884
|
+
self._branch_config = branch_config or BranchConfig()
|
|
878
885
|
self._workspace_config = workspace_config or WorkspaceConfig()
|
|
879
886
|
self._workflow_id = force_workflow_id
|
|
880
887
|
self._enable_waves = enable_waves
|
|
@@ -1287,6 +1294,7 @@ async def run_agent_loop(
|
|
|
1287
1294
|
worktree_config: WorktreeConfig | None = None,
|
|
1288
1295
|
evidence_config: EvidenceConfig | None = None,
|
|
1289
1296
|
retry_config: RetryConfig | None = None,
|
|
1297
|
+
branch_config: BranchConfig | None = None,
|
|
1290
1298
|
) -> None:
|
|
1291
1299
|
"""Run the project-scoped agent loop.
|
|
1292
1300
|
|
|
@@ -1308,6 +1316,7 @@ async def run_agent_loop(
|
|
|
1308
1316
|
worktree_config=worktree_config,
|
|
1309
1317
|
evidence_config=evidence_config,
|
|
1310
1318
|
retry_config=retry_config,
|
|
1319
|
+
branch_config=branch_config,
|
|
1311
1320
|
)
|
|
1312
1321
|
await agent.start()
|
|
1313
1322
|
|
|
@@ -1328,6 +1337,7 @@ async def run_workspace_agent_loop(
|
|
|
1328
1337
|
worktree_config: WorktreeConfig | None = None,
|
|
1329
1338
|
evidence_config: EvidenceConfig | None = None,
|
|
1330
1339
|
retry_config: RetryConfig | None = None,
|
|
1340
|
+
branch_config: BranchConfig | None = None,
|
|
1331
1341
|
) -> None:
|
|
1332
1342
|
"""Run the workspace (multi-project) agent loop.
|
|
1333
1343
|
|
|
@@ -1349,5 +1359,6 @@ async def run_workspace_agent_loop(
|
|
|
1349
1359
|
worktree_config=worktree_config,
|
|
1350
1360
|
evidence_config=evidence_config,
|
|
1351
1361
|
retry_config=retry_config,
|
|
1362
|
+
branch_config=branch_config,
|
|
1352
1363
|
)
|
|
1353
1364
|
await agent.start()
|
|
@@ -1719,6 +1719,13 @@ def run(
|
|
|
1719
1719
|
help="Delay between retries in seconds (default: from config or 3600)",
|
|
1720
1720
|
),
|
|
1721
1721
|
] = None,
|
|
1722
|
+
default_branch: Annotated[
|
|
1723
|
+
str | None,
|
|
1724
|
+
typer.Option(
|
|
1725
|
+
"--default-branch",
|
|
1726
|
+
help="Default branch for sync/rebase/PR targets (default: from config or 'main')",
|
|
1727
|
+
),
|
|
1728
|
+
] = None,
|
|
1722
1729
|
) -> None:
|
|
1723
1730
|
"""Run the agent for a project!
|
|
1724
1731
|
|
|
@@ -1820,6 +1827,11 @@ def run(
|
|
|
1820
1827
|
if retry_delay is not None:
|
|
1821
1828
|
retry_config.delay_seconds = retry_delay
|
|
1822
1829
|
|
|
1830
|
+
# Resolve branch config: CLI > config > default
|
|
1831
|
+
resolved_branch_config = config.branches.model_copy()
|
|
1832
|
+
if default_branch is not None:
|
|
1833
|
+
resolved_branch_config.default_branch = default_branch
|
|
1834
|
+
|
|
1823
1835
|
try:
|
|
1824
1836
|
result = asyncio.run(
|
|
1825
1837
|
run_agent(
|
|
@@ -1838,6 +1850,7 @@ def run(
|
|
|
1838
1850
|
force_workflow_id=resolved_workflow_id,
|
|
1839
1851
|
dry_run=dry_run,
|
|
1840
1852
|
retry_config=retry_config,
|
|
1853
|
+
branch_config=resolved_branch_config,
|
|
1841
1854
|
)
|
|
1842
1855
|
)
|
|
1843
1856
|
|
|
@@ -1998,6 +2011,13 @@ def agent(
|
|
|
1998
2011
|
help="Submit evidence reports after task completion (default: from config or enabled)",
|
|
1999
2012
|
),
|
|
2000
2013
|
] = None,
|
|
2014
|
+
default_branch: Annotated[
|
|
2015
|
+
str | None,
|
|
2016
|
+
typer.Option(
|
|
2017
|
+
"--default-branch",
|
|
2018
|
+
help="Default branch for sync/rebase/PR targets (default: from config or 'main')",
|
|
2019
|
+
),
|
|
2020
|
+
] = None,
|
|
2001
2021
|
) -> None:
|
|
2002
2022
|
"""Run the agent in persistent mode.
|
|
2003
2023
|
|
|
@@ -2075,6 +2095,11 @@ def agent(
|
|
|
2075
2095
|
if retry_delay is not None:
|
|
2076
2096
|
retry_config.delay_seconds = retry_delay
|
|
2077
2097
|
|
|
2098
|
+
# Resolve branch config: CLI > config > default
|
|
2099
|
+
resolved_branch_config = config.branches.model_copy()
|
|
2100
|
+
if default_branch is not None:
|
|
2101
|
+
resolved_branch_config.default_branch = default_branch
|
|
2102
|
+
|
|
2078
2103
|
# Resolve workspace path: CLI > config
|
|
2079
2104
|
resolved_workspace = workspace or config.workspace.workspace_dir
|
|
2080
2105
|
|
|
@@ -2099,6 +2124,7 @@ def agent(
|
|
|
2099
2124
|
worktree_config=resolved_worktree_config,
|
|
2100
2125
|
evidence_config=resolved_evidence_config,
|
|
2101
2126
|
retry_config=retry_config,
|
|
2127
|
+
branch_config=resolved_branch_config,
|
|
2102
2128
|
)
|
|
2103
2129
|
)
|
|
2104
2130
|
except KeyboardInterrupt:
|
|
@@ -2140,6 +2166,7 @@ def agent(
|
|
|
2140
2166
|
worktree_config=resolved_worktree_config,
|
|
2141
2167
|
evidence_config=resolved_evidence_config,
|
|
2142
2168
|
retry_config=retry_config,
|
|
2169
|
+
branch_config=resolved_branch_config,
|
|
2143
2170
|
)
|
|
2144
2171
|
)
|
|
2145
2172
|
except KeyboardInterrupt:
|
|
@@ -246,6 +246,22 @@ class CanalConfig(BaseModel):
|
|
|
246
246
|
]
|
|
247
247
|
|
|
248
248
|
|
|
249
|
+
class BranchConfig(BaseModel):
|
|
250
|
+
"""Branch configuration for git operations.
|
|
251
|
+
|
|
252
|
+
Controls which branch is used for pre-flight sync, rebase targets, and PR base.
|
|
253
|
+
Users set default_branch to whatever their project uses — main, dev, develop, etc.
|
|
254
|
+
"""
|
|
255
|
+
|
|
256
|
+
default_branch: Annotated[
|
|
257
|
+
str,
|
|
258
|
+
Field(
|
|
259
|
+
default="main",
|
|
260
|
+
description="Default branch for sync, rebase, and PR targets (e.g. main, dev, develop)",
|
|
261
|
+
),
|
|
262
|
+
]
|
|
263
|
+
|
|
264
|
+
|
|
249
265
|
class EvidenceConfig(BaseModel):
|
|
250
266
|
"""Evidence report configuration.
|
|
251
267
|
|
|
@@ -341,6 +357,10 @@ class SteerDevConfig(BaseModel):
|
|
|
341
357
|
CanalConfig,
|
|
342
358
|
Field(default_factory=CanalConfig, description="Canal workflow configuration"),
|
|
343
359
|
]
|
|
360
|
+
branches: Annotated[
|
|
361
|
+
BranchConfig,
|
|
362
|
+
Field(default_factory=BranchConfig, description="Branch configuration for git operations"),
|
|
363
|
+
]
|
|
344
364
|
workspace: Annotated[
|
|
345
365
|
WorkspaceConfig,
|
|
346
366
|
Field(default_factory=WorkspaceConfig, description="Workspace agent configuration"),
|
|
@@ -68,6 +68,10 @@ class PromptContext(BaseModel):
|
|
|
68
68
|
resume_message: str | None = Field(
|
|
69
69
|
default=None, description="Message for resume (if resuming session)"
|
|
70
70
|
)
|
|
71
|
+
default_branch: str | None = Field(
|
|
72
|
+
default=None,
|
|
73
|
+
description="Default branch for git operations (e.g. main, dev). Falls back to 'main'.",
|
|
74
|
+
)
|
|
71
75
|
|
|
72
76
|
|
|
73
77
|
class PromptBuilder:
|
|
@@ -105,7 +109,7 @@ class PromptBuilder:
|
|
|
105
109
|
|
|
106
110
|
# Build components
|
|
107
111
|
project_info = self._build_project_info(context.project)
|
|
108
|
-
task_info = self._build_task_info(context.task, context.project)
|
|
112
|
+
task_info = self._build_task_info(context.task, context.project, context.default_branch)
|
|
109
113
|
instructions = self._build_instructions(context)
|
|
110
114
|
|
|
111
115
|
# Add workflow phase if present
|
|
@@ -157,12 +161,14 @@ class PromptBuilder:
|
|
|
157
161
|
self,
|
|
158
162
|
task: TaskContext | None,
|
|
159
163
|
project: ProjectContext | None,
|
|
164
|
+
default_branch: str | None = None,
|
|
160
165
|
) -> str:
|
|
161
166
|
"""Build task information section.
|
|
162
167
|
|
|
163
168
|
Args:
|
|
164
169
|
task: Task context or None.
|
|
165
170
|
project: Project context for working directory fallback.
|
|
171
|
+
default_branch: Default branch for git operations (falls back to "main").
|
|
166
172
|
|
|
167
173
|
Returns:
|
|
168
174
|
Formatted task information.
|
|
@@ -204,8 +210,14 @@ class PromptBuilder:
|
|
|
204
210
|
wave_section += f"\n\n**Tasks in This Wave:**\n{task.wave.wave_tasks_summary}"
|
|
205
211
|
task_info = f"{task_info}{wave_section}"
|
|
206
212
|
|
|
207
|
-
# Add git pre-flight sync instructions
|
|
208
|
-
|
|
213
|
+
# Add git branch configuration and pre-flight sync instructions
|
|
214
|
+
branch = default_branch or "main"
|
|
215
|
+
task_info = (
|
|
216
|
+
f"{task_info}\n\n{self.templates.GIT_BRANCH_CONFIG.format(default_branch=branch)}"
|
|
217
|
+
)
|
|
218
|
+
task_info = (
|
|
219
|
+
f"{task_info}\n{self.templates.GIT_PREFLIGHT_SYNC.format(default_branch=branch)}"
|
|
220
|
+
)
|
|
209
221
|
|
|
210
222
|
return task_info
|
|
211
223
|
|
|
@@ -246,13 +246,20 @@ Create tasks that can be completed by a single developer in a reasonable time (1
|
|
|
246
246
|
Larger work should be broken into multiple tasks.
|
|
247
247
|
"""
|
|
248
248
|
|
|
249
|
-
# Git pre-flight sync instructions injected into task prompts
|
|
249
|
+
# Git pre-flight sync instructions injected into task prompts.
|
|
250
|
+
# Parameterized with {default_branch} — call .format(default_branch=...) before use.
|
|
250
251
|
GIT_PREFLIGHT_SYNC = """## Git Pre-flight Sync
|
|
251
252
|
Before starting this task, ensure you are on an up-to-date default branch:
|
|
252
253
|
1. `git stash push -m "steerdev-preflight" 2>/dev/null || true`
|
|
253
|
-
2. `git checkout
|
|
254
|
-
3. If ff-only fails: `git fetch origin && git reset --hard origin/
|
|
254
|
+
2. `git checkout {default_branch} && git pull origin {default_branch} --ff-only`
|
|
255
|
+
3. If ff-only fails: `git fetch origin && git reset --hard origin/{default_branch}`
|
|
255
256
|
Only skip this if you are continuing mid-wave on an existing wave branch.
|
|
257
|
+
"""
|
|
258
|
+
|
|
259
|
+
# Git branch configuration note injected into task prompts
|
|
260
|
+
GIT_BRANCH_CONFIG = """## Git Branch Configuration
|
|
261
|
+
- Default branch: `{default_branch}`
|
|
262
|
+
Use this branch for all fetch, rebase, and merge operations.
|
|
256
263
|
"""
|
|
257
264
|
|
|
258
265
|
# Phase context instructions appended to phase prompts
|
|
@@ -19,7 +19,13 @@ from steerdev_agent.api.events import EventsClient
|
|
|
19
19
|
from steerdev_agent.api.runs import RunCreateRequest, RunsClient
|
|
20
20
|
from steerdev_agent.api.sessions import SessionCreateRequest, SessionsClient
|
|
21
21
|
from steerdev_agent.api.tasks import TasksClient
|
|
22
|
-
from steerdev_agent.config.models import
|
|
22
|
+
from steerdev_agent.config.models import (
|
|
23
|
+
BranchConfig,
|
|
24
|
+
EvidenceConfig,
|
|
25
|
+
ExecutorConfig,
|
|
26
|
+
RetryConfig,
|
|
27
|
+
WorktreeConfig,
|
|
28
|
+
)
|
|
23
29
|
from steerdev_agent.executor import ExecutorFactory
|
|
24
30
|
from steerdev_agent.executor.base import AgentExecutor, EventType, StreamEvent
|
|
25
31
|
from steerdev_agent.executor.claude import ClaudeExecutorError
|
|
@@ -277,6 +283,7 @@ class Runner:
|
|
|
277
283
|
force_workflow_id: str | None = None,
|
|
278
284
|
dry_run: bool = False,
|
|
279
285
|
retry_config: RetryConfig | None = None,
|
|
286
|
+
branch_config: BranchConfig | None = None,
|
|
280
287
|
shutdown_event: asyncio.Event | None = None,
|
|
281
288
|
agent_id: str | None = None,
|
|
282
289
|
) -> None:
|
|
@@ -314,6 +321,7 @@ class Runner:
|
|
|
314
321
|
self.workflow_id = force_workflow_id
|
|
315
322
|
self.dry_run = dry_run
|
|
316
323
|
self._retry_config = retry_config or RetryConfig()
|
|
324
|
+
self._branch_config = branch_config or BranchConfig()
|
|
317
325
|
self._shutdown_event = shutdown_event
|
|
318
326
|
|
|
319
327
|
# Executor configuration
|
|
@@ -723,6 +731,7 @@ class Runner:
|
|
|
723
731
|
linear_identifier=task.get("linear_identifier"),
|
|
724
732
|
wave=wave_context,
|
|
725
733
|
),
|
|
734
|
+
default_branch=self._branch_config.default_branch,
|
|
726
735
|
)
|
|
727
736
|
prompt = self._prompt_builder.build(context)
|
|
728
737
|
|
|
@@ -753,25 +762,45 @@ class Runner:
|
|
|
753
762
|
if self._sessions_client and not self.dry_run:
|
|
754
763
|
await self._sessions_client.mark_running(session_id)
|
|
755
764
|
|
|
756
|
-
#
|
|
765
|
+
# Prepare workspace (git fetch, checkout, branch creation)
|
|
757
766
|
effective_working_dir = self.working_directory
|
|
758
767
|
worktree_branch: str | None = None
|
|
759
768
|
legacy_worktree_name: str | None = None
|
|
760
769
|
|
|
761
|
-
if self._worktree_config.enabled:
|
|
762
|
-
|
|
763
|
-
|
|
770
|
+
if self._worktree_config.enabled and self._worktree_config.provider == "claude":
|
|
771
|
+
# Legacy: pass --worktree to Claude CLI (bypasses preparation)
|
|
772
|
+
legacy_worktree_name = compute_worktree_name(task_id, wave_context)
|
|
773
|
+
console.print(f"[dim]Using legacy worktree: {legacy_worktree_name}[/dim]")
|
|
774
|
+
else:
|
|
775
|
+
from steerdev_agent.workspace.preparation import WorkspacePreparation
|
|
764
776
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
777
|
+
preparation = WorkspacePreparation(
|
|
778
|
+
working_directory=self.working_directory,
|
|
779
|
+
worktree_config=self._worktree_config,
|
|
780
|
+
branch_config=self._branch_config,
|
|
781
|
+
)
|
|
782
|
+
prep_result = await preparation.prepare(task, wave_context)
|
|
783
|
+
if not prep_result.success:
|
|
784
|
+
error_msg = f"Workspace preparation failed: {prep_result.error}"
|
|
785
|
+
logger.error(error_msg)
|
|
786
|
+
if self._sessions_client and not self.dry_run:
|
|
787
|
+
await self._sessions_client.mark_failed(
|
|
788
|
+
session_id, metadata={"error": error_msg}
|
|
789
|
+
)
|
|
790
|
+
return {
|
|
791
|
+
"success": False,
|
|
792
|
+
"error": error_msg,
|
|
793
|
+
"events_sent": self._events_sent,
|
|
794
|
+
}
|
|
795
|
+
effective_working_dir = prep_result.working_directory
|
|
796
|
+
if prep_result.is_worktree:
|
|
797
|
+
worktree_branch = prep_result.branch_name
|
|
798
|
+
console.print(
|
|
799
|
+
f"[dim]Workspace ready: {effective_working_dir} "
|
|
800
|
+
f"(branch: {prep_result.branch_name})[/dim]"
|
|
801
|
+
)
|
|
802
|
+
for warning in prep_result.warnings:
|
|
803
|
+
console.print(f"[yellow]Warning: {warning}[/yellow]")
|
|
775
804
|
|
|
776
805
|
# Create executor using factory
|
|
777
806
|
self._executor = ExecutorFactory.create(
|
|
@@ -948,19 +977,29 @@ class Runner:
|
|
|
948
977
|
resolved_wf_id = workflow_id or self.workflow_id
|
|
949
978
|
console.print(f"[dim]Using workflow: {resolved_wf_id}[/dim]")
|
|
950
979
|
|
|
951
|
-
#
|
|
980
|
+
# Prepare workspace (git fetch, checkout, branch creation)
|
|
952
981
|
effective_working_dir = self.working_directory
|
|
953
982
|
worktree_branch: str | None = None
|
|
954
983
|
|
|
955
|
-
|
|
956
|
-
from steerdev_agent.worktree import WorktrunkClient, compute_branch_name
|
|
984
|
+
from steerdev_agent.workspace.preparation import WorkspacePreparation
|
|
957
985
|
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
986
|
+
preparation = WorkspacePreparation(
|
|
987
|
+
working_directory=self.working_directory,
|
|
988
|
+
worktree_config=self._worktree_config,
|
|
989
|
+
branch_config=self._branch_config,
|
|
990
|
+
)
|
|
991
|
+
prep_result = await preparation.prepare(task, wave_context)
|
|
992
|
+
if not prep_result.success:
|
|
993
|
+
error_msg = f"Workspace preparation failed: {prep_result.error}"
|
|
994
|
+
logger.error(error_msg)
|
|
995
|
+
return {"success": False, "error": error_msg}
|
|
996
|
+
effective_working_dir = prep_result.working_directory
|
|
997
|
+
if prep_result.is_worktree:
|
|
998
|
+
worktree_branch = prep_result.branch_name
|
|
999
|
+
console.print(
|
|
1000
|
+
f"[dim]Workspace ready: {effective_working_dir} "
|
|
1001
|
+
f"(branch: {prep_result.branch_name})[/dim]"
|
|
1002
|
+
)
|
|
964
1003
|
|
|
965
1004
|
# Build task context for workflow
|
|
966
1005
|
task_context = build_workflow_task_context(
|
|
@@ -1354,6 +1393,7 @@ async def run_agent(
|
|
|
1354
1393
|
force_workflow_id: str | None = None,
|
|
1355
1394
|
dry_run: bool = False,
|
|
1356
1395
|
retry_config: RetryConfig | None = None,
|
|
1396
|
+
branch_config: BranchConfig | None = None,
|
|
1357
1397
|
) -> dict[str, Any]:
|
|
1358
1398
|
"""Run the steerdev agent.
|
|
1359
1399
|
|
|
@@ -1377,6 +1417,7 @@ async def run_agent(
|
|
|
1377
1417
|
force_workflow_id: Workflow ID override for multi-phase execution.
|
|
1378
1418
|
dry_run: If True, print the command without executing it.
|
|
1379
1419
|
retry_config: Retry configuration for failed tasks.
|
|
1420
|
+
branch_config: Branch configuration for git operations.
|
|
1380
1421
|
|
|
1381
1422
|
Returns:
|
|
1382
1423
|
Run result metadata.
|
|
@@ -1399,6 +1440,7 @@ async def run_agent(
|
|
|
1399
1440
|
force_workflow_id=force_workflow_id,
|
|
1400
1441
|
dry_run=dry_run,
|
|
1401
1442
|
retry_config=retry_config,
|
|
1443
|
+
branch_config=branch_config,
|
|
1402
1444
|
)
|
|
1403
1445
|
|
|
1404
1446
|
# Install signal handler that kills the subprocess immediately on Ctrl+C
|
|
@@ -18,20 +18,20 @@ Use this skill when a workflow phase tells you to merge the **current task branc
|
|
|
18
18
|
|
|
19
19
|
## Pre-check
|
|
20
20
|
|
|
21
|
-
Before merging into a canal, verify your current branch has been pushed and has a PR. Do NOT switch branches or sync to
|
|
21
|
+
Before merging into a canal, verify your current branch has been pushed and has a PR. Do NOT switch branches or sync to the default branch — this skill operates on the current task/wave branch.
|
|
22
22
|
|
|
23
23
|
## Rebase Before Canal Merge
|
|
24
24
|
|
|
25
|
-
Before merging into the canal, ensure your branch is up to date
|
|
25
|
+
Before merging into the canal, ensure your branch is up to date. Refer to the **Git Branch Configuration** section in your prompt for the project's default branch name.
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
git fetch origin
|
|
29
|
-
git merge-tree --write-tree origin
|
|
28
|
+
git fetch origin <default-branch>
|
|
29
|
+
git merge-tree --write-tree origin/<default-branch> HEAD
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
- **If clean** (exit 0): Rebase and force-push with lease:
|
|
33
33
|
```bash
|
|
34
|
-
git rebase origin
|
|
34
|
+
git rebase origin/<default-branch>
|
|
35
35
|
git push --force-with-lease origin HEAD
|
|
36
36
|
```
|
|
37
37
|
- **If conflicts**: Attempt rebase. If it fails on files you did not modify, abort (`git rebase --abort`) and re-queue the task:
|
|
@@ -75,6 +75,7 @@ steerdev canal pr CANAL_ID
|
|
|
75
75
|
- Do not force-push to resolve canal conflicts
|
|
76
76
|
- Do not manually resolve canal merge conflicts outside the supported tooling
|
|
77
77
|
- If canal merge fails, report the blocker with task comments or status updates
|
|
78
|
+
- Replace `<default-branch>` in commands above with the actual branch name from the Git Branch Configuration section
|
|
78
79
|
|
|
79
80
|
## Example
|
|
80
81
|
|
|
@@ -14,36 +14,16 @@ Use this skill when a workflow phase tells you to complete **one task on one bra
|
|
|
14
14
|
- One pull request
|
|
15
15
|
- One task result update that includes the PR URL
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## Workspace Ready
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
The CLI has already prepared your workspace: fetched the latest changes, synced to the default branch, and created or checked out your task branch. **Do not run pre-flight sync steps** — proceed directly to implementation.
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
If NOT in a worktrunk worktree, sync before creating your task branch:
|
|
24
|
-
|
|
25
|
-
1. Stash any uncommitted changes (if any):
|
|
26
|
-
```bash
|
|
27
|
-
git stash push -m "steerdev-preflight" 2>/dev/null || true
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
2. Switch to the default branch and pull latest:
|
|
31
|
-
```bash
|
|
32
|
-
git checkout main && git pull origin main --ff-only
|
|
33
|
-
```
|
|
34
|
-
If `main` doesn't exist, try `master`. If `--ff-only` fails (local main diverged), force-reset:
|
|
35
|
-
```bash
|
|
36
|
-
git fetch origin && git reset --hard origin/main
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
3. Now proceed to create your task branch from the up-to-date default branch.
|
|
40
|
-
|
|
41
|
-
**Why:** The agent may still be on a previous task's branch. Without this step, new branches are created from stale code, causing desync with merged PRs.
|
|
21
|
+
Refer to the **Git Branch Configuration** section in your prompt for the project's default branch name.
|
|
42
22
|
|
|
43
23
|
## Workflow
|
|
44
24
|
|
|
45
25
|
1. Ensure the task is already marked `started`
|
|
46
|
-
2. Create or switch to the task branch (
|
|
26
|
+
2. Create or switch to the task branch (if not already on it):
|
|
47
27
|
|
|
48
28
|
```bash
|
|
49
29
|
steerdev git branch TASK_ID [--name NAME]
|
|
@@ -56,26 +36,26 @@ This fetches the task from the API and builds the branch name automatically:
|
|
|
56
36
|
|
|
57
37
|
3. Implement the requested changes
|
|
58
38
|
4. Commit with a conventional commit message that explains why the change exists
|
|
59
|
-
5. Rebase onto the latest
|
|
39
|
+
5. Rebase onto the latest default branch before pushing:
|
|
60
40
|
|
|
61
41
|
```bash
|
|
62
|
-
git fetch origin
|
|
42
|
+
git fetch origin <default-branch>
|
|
63
43
|
```
|
|
64
44
|
|
|
65
45
|
Dry-run merge check (requires git 2.38+):
|
|
66
46
|
```bash
|
|
67
|
-
git merge-tree --write-tree origin
|
|
47
|
+
git merge-tree --write-tree origin/<default-branch> HEAD
|
|
68
48
|
```
|
|
69
49
|
|
|
70
50
|
- **If exit code 0** (clean merge): Rebase and push:
|
|
71
51
|
```bash
|
|
72
|
-
git rebase origin
|
|
52
|
+
git rebase origin/<default-branch>
|
|
73
53
|
git push -u origin HEAD
|
|
74
54
|
```
|
|
75
55
|
|
|
76
56
|
- **If exit code non-zero** (conflicts detected): Attempt rebase:
|
|
77
57
|
```bash
|
|
78
|
-
git rebase origin
|
|
58
|
+
git rebase origin/<default-branch>
|
|
79
59
|
```
|
|
80
60
|
- If rebase succeeds after resolving conflicts in files you modified: `git push --force-with-lease origin HEAD`
|
|
81
61
|
- If conflicts are in files you did NOT modify: abort the rebase (`git rebase --abort`) and re-queue the task for a fresh attempt:
|
|
@@ -95,22 +75,12 @@ steerdev git pr --title "TITLE" --task-id TASK_ID [--body "BODY"]
|
|
|
95
75
|
7. Update the task result with the PR URL
|
|
96
76
|
8. Log completion in the root `docs/` progress files
|
|
97
77
|
|
|
98
|
-
## Branch Naming Convention
|
|
99
|
-
|
|
100
|
-
Branch names should link to the external ticket tracker (e.g. Linear) for traceability on GitHub:
|
|
101
|
-
|
|
102
|
-
| Has External ID? | Format | Example |
|
|
103
|
-
|---|---|---|
|
|
104
|
-
| Yes | `task/<TICKET-ID>-<slug>` | `task/PROJ-123-add-user-auth` |
|
|
105
|
-
| No | `task/<short-uuid>-<slug>` | `task/abc12345-add-user-auth` |
|
|
106
|
-
|
|
107
|
-
**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.
|
|
108
|
-
|
|
109
78
|
## Conventions
|
|
110
79
|
|
|
111
80
|
- Always use `steerdev git branch` to create branches (it resolves the external ticket ID automatically)
|
|
112
81
|
- Create exactly one PR for the task
|
|
113
82
|
- Include the PR URL in the task result summary
|
|
83
|
+
- Replace `<default-branch>` in commands above with the actual branch name from the Git Branch Configuration section
|
|
114
84
|
|
|
115
85
|
## Example
|
|
116
86
|
|
|
@@ -14,28 +14,15 @@ Use this skill when a workflow phase tells you to complete **multiple related ta
|
|
|
14
14
|
- One shared pull request for the wave
|
|
15
15
|
- All related tasks updated with the same PR URL
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## Workspace Ready
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
The CLI has already prepared your workspace: fetched the latest changes, synced to the default branch (for new waves), or stayed on the current wave branch (for continuing waves). **Do not run pre-flight sync steps** — proceed directly to implementation.
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
If NOT in a worktrunk worktree, check if you need to sync before creating the wave branch:
|
|
24
|
-
|
|
25
|
-
- **Starting a new wave** (not on `wave/<N>` branch yet): Sync to default branch first:
|
|
26
|
-
```bash
|
|
27
|
-
git stash push -m "steerdev-preflight" 2>/dev/null || true
|
|
28
|
-
git checkout main && git pull origin main --ff-only
|
|
29
|
-
```
|
|
30
|
-
If `--ff-only` fails: `git fetch origin && git reset --hard origin/main`
|
|
31
|
-
|
|
32
|
-
- **Continuing a wave** (already on `wave/<N>` branch): Do NOT switch to main. Stay on the wave branch and continue with the next task.
|
|
33
|
-
|
|
34
|
-
**Why:** The agent may still be on a previous task/wave branch. New waves must branch from updated main. Mid-wave tasks must stay on the wave branch.
|
|
21
|
+
Refer to the **Git Branch Configuration** section in your prompt for the project's default branch name.
|
|
35
22
|
|
|
36
23
|
## Workflow
|
|
37
24
|
|
|
38
|
-
1. Create or switch to the shared wave branch (
|
|
25
|
+
1. Create or switch to the shared wave branch (if not already on it):
|
|
39
26
|
|
|
40
27
|
```bash
|
|
41
28
|
git checkout -b wave/<wave-number>
|
|
@@ -54,26 +41,26 @@ git commit -m "[PROJ-123] feat: add user endpoint"
|
|
|
54
41
|
git commit -m "[task:abc12345] feat: add user endpoint"
|
|
55
42
|
```
|
|
56
43
|
|
|
57
|
-
3. After the wave work is ready for review, rebase onto the latest
|
|
44
|
+
3. After the wave work is ready for review, rebase onto the latest default branch:
|
|
58
45
|
|
|
59
46
|
```bash
|
|
60
|
-
git fetch origin
|
|
47
|
+
git fetch origin <default-branch>
|
|
61
48
|
```
|
|
62
49
|
|
|
63
50
|
Dry-run merge check (requires git 2.38+):
|
|
64
51
|
```bash
|
|
65
|
-
git merge-tree --write-tree origin
|
|
52
|
+
git merge-tree --write-tree origin/<default-branch> HEAD
|
|
66
53
|
```
|
|
67
54
|
|
|
68
55
|
- **If exit code 0** (clean merge): Rebase and push:
|
|
69
56
|
```bash
|
|
70
|
-
git rebase origin
|
|
57
|
+
git rebase origin/<default-branch>
|
|
71
58
|
git push -u origin HEAD
|
|
72
59
|
```
|
|
73
60
|
|
|
74
61
|
- **If exit code non-zero** (conflicts detected): Attempt rebase:
|
|
75
62
|
```bash
|
|
76
|
-
git rebase origin
|
|
63
|
+
git rebase origin/<default-branch>
|
|
77
64
|
```
|
|
78
65
|
- If rebase succeeds after resolving conflicts in files you modified: `git push --force-with-lease origin HEAD`
|
|
79
66
|
- If conflicts are in files you did NOT modify: abort the rebase (`git rebase --abort`) and re-queue the current task:
|
|
@@ -110,6 +97,7 @@ Run `steerdev tasks get TASK_ID` to find the task's `linear_identifier` before c
|
|
|
110
97
|
- Do not create per-task PRs inside the wave
|
|
111
98
|
- Keep commits traceable by including the external ticket ID (or internal ID fallback) in each commit
|
|
112
99
|
- Include the shared PR URL in every related task result
|
|
100
|
+
- Replace `<default-branch>` in commands above with the actual branch name from the Git Branch Configuration section
|
|
113
101
|
|
|
114
102
|
## Example
|
|
115
103
|
|
|
@@ -72,6 +72,11 @@ worktrees:
|
|
|
72
72
|
# Commands to run in pre-merge hook (empty = use worktrunk.config.toml defaults)
|
|
73
73
|
pre_merge_checks: []
|
|
74
74
|
|
|
75
|
+
# Branch configuration for git operations
|
|
76
|
+
branches:
|
|
77
|
+
# Default branch for sync, rebase, and PR targets (e.g. main, dev, develop)
|
|
78
|
+
default_branch: main
|
|
79
|
+
|
|
75
80
|
# Evidence reports: submit a review-ready report after each task/workflow
|
|
76
81
|
evidence:
|
|
77
82
|
enabled: true
|