Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions .claude/skills/dev-orchestrator/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,15 @@ that instructs Claude to invoke `Skill(skill="dev-orchestrator")` for dev/invest

## Execution Instructions

**YOUR NEXT ACTION after reading this skill MUST be a Bash tool call that
executes `run_recipe_by_name("smart-orchestrator")`.**
**YOUR NEXT ACTION after reading this skill MUST include a Bash tool call that
executes `run_recipe_by_name("smart-orchestrator")`.** If your runtime requires
a `report_intent` call (e.g. Copilot CLI), emit it **in parallel** with the
Bash launch — both tool calls in the same response. The constraint is that no
*other* substantive action (reading files, calling TodoWrite, invoking Agent,
or typing a response) may precede or replace the Bash launch.

If you find yourself doing anything else — reading more files, calling
TodoWrite, invoking Agent, or typing a response — you are bypassing the
workflow. Stop. Go back. Run the recipe runner.
If you find yourself doing anything else instead of launching the recipe
runner, you are bypassing the workflow. Stop. Go back. Run the recipe runner.

Development and Investigation tasks have exactly ONE execution path: the
recipe runner. There is no "Option B." There is no "I'll follow the steps
Expand All @@ -116,7 +119,8 @@ When this skill is activated:

### REQUIRED: Execute via Recipe Runner — IMMEDIATELY

Your very next tool call must launch the recipe runner. **CRITICAL**: Claude
Your next tool call(s) must include the recipe runner launch (alongside
`report_intent` if your runtime requires it). **CRITICAL**: Claude
Code's `run_in_background` kills processes after ~10 minutes. Recipe
workstreams can take hours. You MUST use a tmux session for execution:

Expand Down Expand Up @@ -145,6 +149,24 @@ print(f'Recipe result: {result}')
- `tmux new-session -d` — detached session, no timeout, survives disconnects
- Monitor with: `tail -f /tmp/recipe-runner-output.log` or `tmux attach -t recipe-runner`

**Restarting a stale tmux session**: Some runtimes (e.g. Copilot CLI) block
`tmux kill-session` because it does not target a numeric PID. Use one of these
shell-policy-safe alternatives instead:

```bash
# Option A (preferred): use a unique session name per run to avoid collisions
tmux new-session -d -s "recipe-$(date +%s)" "..."

# Option B: locate the tmux server PID and terminate with numeric kill
tmux list-sessions -F '#{pid}' 2>/dev/null | xargs -I{} kill {}

# Option C: let tmux itself handle it — send exit to all panes
tmux send-keys -t recipe-runner "exit" Enter 2>/dev/null; sleep 1
```

If using Option A, update the `tail -f` / `tmux attach` commands to use the
same session name.

**DO NOT use `run_in_background`** for recipe execution — it will be killed
after ~10 minutes (Issue #2909).

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ backend-path = ["."]

[project]
name = "amplihack"
version = "0.6.16"
version = "0.6.17"
description = "Amplifier bundle for agentic coding with comprehensive skills, recipes, and workflows"
requires-python = ">=3.11"
dependencies = [
Expand Down
63 changes: 63 additions & 0 deletions tests/skills/test_dev_orchestrator_issue_3010_3011.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""Regression tests for issues #3010 and #3011.

Issue #3010: dev-orchestrator must allow report_intent in parallel with the
Bash launch call, not hard-require Bash as the *only* next tool call.

Issue #3011: dev-orchestrator must provide shell-policy-safe tmux restart
guidance that does not rely on ``tmux kill-session``.
"""

from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parents[2]
DEV_ORCHESTRATOR_SKILL = REPO_ROOT / ".claude" / "skills" / "dev-orchestrator" / "SKILL.md"


class TestIssue3010ReportIntentCompatibility:
"""The skill must not hard-require Bash as the sole next tool call."""

def setup_method(self):
self.content = DEV_ORCHESTRATOR_SKILL.read_text()

def test_no_hard_must_be_a_bash_tool_call(self):
"""The old phrasing 'MUST be a Bash tool call' is replaced."""
assert "MUST be a Bash tool call that" not in self.content

def test_allows_report_intent_in_parallel(self):
"""The skill explicitly mentions report_intent as acceptable."""
assert "report_intent" in self.content

def test_must_include_bash_launch(self):
"""The skill still requires a Bash launch — just not as the *sole* call."""
assert "MUST include a Bash tool call" in self.content

def test_next_tool_calls_plural_form(self):
"""The follow-up instruction uses the plural 'tool call(s)'."""
assert "next tool call(s)" in self.content


class TestIssue3011TmuxRestartGuidance:
"""The skill must provide shell-policy-safe tmux restart alternatives."""

def setup_method(self):
self.content = DEV_ORCHESTRATOR_SKILL.read_text()

def test_no_kill_session_as_primary_instruction(self):
"""The skill must not recommend ``tmux kill-session`` as the restart path."""
assert "tmux kill-session -t recipe-runner" not in self.content

def test_unique_session_name_option(self):
"""Option A: unique session name per run."""
assert "recipe-$(date +%s)" in self.content

def test_numeric_pid_option(self):
"""Option B: numeric PID termination."""
assert "#{pid}" in self.content

def test_send_exit_option(self):
"""Option C: send exit to panes."""
assert 'send-keys -t recipe-runner "exit"' in self.content

def test_shell_policy_safe_section_exists(self):
"""A dedicated section on restarting stale tmux sessions exists."""
assert "Restarting a stale tmux session" in self.content