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
2 changes: 1 addition & 1 deletion plugins/dev-team/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dev-team",
"version": "1.2.2",
"version": "1.2.3",
"description": "Dev-team agent pipeline: researcher, developer, reviewer, and debugger agents for implementing Jira tasks and fixing GitHub issues.",
"commands": "./commands"
}
43 changes: 23 additions & 20 deletions plugins/dev-team/agents/task-runner.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ Parse the following fields from your prompt:

- `agent` — sub-agent type to spawn via the `Agent` tool (used for display/logging in
the context header only; does not affect routing or tool selection)
- `skill` — name of the skill the sub-agent should invoke
- `skill` — name of the skill the sub-agent should execute
- `plugin_root` — absolute path to the dev-team plugin directory (used to load skill files)
- `context_file` — absolute path to the pipeline context file
- `args` — (optional) positional arguments to present to the skill
- `read_sections` — comma-separated list of section names to read from the context file
Expand All @@ -40,30 +41,32 @@ Use the `Read` tool to read `context_file`. Extract the content of each section
`read_sections`. A section begins at `<!-- section:Name -->` and ends at the next
`<!-- section:` sentinel or end of file.

### Step 2 — Present context
### Step 2 — Load and substitute skill content

Present the extracted sections as a quoted block in your conversation before invoking
the skill. Format:
Using the `Read` tool, read: `<plugin_root>/commands/<skill>.md`

```
## Context from pipeline
Strip the YAML frontmatter — everything from the opening `---` line to the closing `---`
line (inclusive), plus any blank line immediately after.

### <Section Name>
<content>
```
Apply the following substitutions to the remaining content using the values already
extracted from the context file:

Also present the `args` value (if provided) as:
```
## Arguments
<args>
```
| Variable | Source |
|----------|--------|
| `$ARGUMENTS` | `args` field from this prompt |
| `$TASK_BRIEF` | "Researcher Brief" section content |
| `$WORK_SUMMARIES` | "Implementation Summary" section + all "Fix N" sections, concatenated with `\n\n---\n\n` |
| `$ISSUES` | "Last Failure" section content (or "Validate Result" if "Last Failure" is empty) |
| `$PR_URL` | "PR URL" section content |
| `$CONTEXT_FILE` | `context_file` path |

Set `$CONTEXT_FILE` to the value of `context_file` — skills that need mid-task reads
use this substitution.
Leave any variable with no matching value unchanged.

### Step 3 — Spawn the sub-agent

Spawn a sub-agent using the `Agent` tool:
Spawn a sub-agent using the `Agent` tool, passing the substituted skill content directly
as `## Instructions`. The sub-agent executes the instructions without needing to load any
skill files.

```
Agent(
Expand All @@ -77,13 +80,13 @@ Agent(
## Arguments
<args>

## Skill
<skill>
## Instructions
<substituted skill content>
"""
)
```

The sub-agent invokes the named skill and returns its full output. Capture that output
The sub-agent executes the instructions and returns its full output. Capture that output
as the skill result for Step 4.

### Step 4 — Write result to context file (Edit only — never Write)
Expand Down
15 changes: 15 additions & 0 deletions plugins/dev-team/agents/workspace-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: workspace-setup
description: >
Sets up the git workspace before a pipeline run. Finds the epic branch from
the spec or Jira, fetches latest, and creates the task branch.
model: haiku
tools:
- Read
- Bash
- mcp__08e9ccd3-4093-4425-adec-d98ea766a759__getJiraIssue
---

You are the workspace-setup agent for the dev-team pipeline.
Your only job is to set up the correct git branch before implementation begins.
Execute the instructions in `## Instructions` in your prompt.
22 changes: 8 additions & 14 deletions plugins/dev-team/commands/create-branch.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,25 @@
---
description: Ensure the current work runs on a feature branch derived from a work-item ID and title/brief text.
argument-hint: <work-item-id> "<issue-title-or-task-brief-sentence>"
description: Ensure the current work runs on a dev/claude/<work-item-id> branch.
argument-hint: <work-item-id>
user-invocable: false
---

## Inputs

- Work item ID: first token in `$ARGUMENTS` (e.g. `Issue-444`, `ADR-172`)
- Slug source text: remaining argument text (quoted when it includes spaces)
- Work item ID: `$ARGUMENTS` (e.g. `Issue-444`, `ADR-172`)

If either input is missing, stop and print:
If missing, stop and print:

> Usage: `/create-branch <work-item-id> "<issue-title-or-task-brief-sentence>"`
> Usage: `/create-branch <work-item-id>`

## Steps

1. Check the current branch:
```bash
git branch --show-current
```
2. If already on `dev/claude/<work-item-id>-*`, stop (nothing to do).
3. Derive a slug from the source text:
- lowercase
- replace spaces and underscores with hyphens
- remove non-alphanumeric/non-hyphen characters
- trim to 40 characters
4. Create and switch:
2. If already on `dev/claude/<work-item-id>`, stop (nothing to do).
3. Create and switch:
```bash
git checkout -b dev/claude/<work-item-id>-<slug>
git checkout -b dev/claude/<work-item-id>
```
1 change: 1 addition & 0 deletions plugins/dev-team/commands/dev-team.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ results = await [
Agent(subagent_type="task-runner", prompt="""
agent: <item.agent>
skill: <item.skill>
plugin_root: <CLAUDE_PLUGIN_ROOT>
context_file: <item.context_file>
args: <item.args or "">
read_sections: <item.read_sections joined by ", ">
Expand Down
10 changes: 5 additions & 5 deletions plugins/dev-team/commands/developer-implement.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ $TASK_BRIEF

## Steps

### 0 — Ensure feature branch
### 0 — Ensure task branch

Check the current branch:

```bash
git branch --show-current
```

If the branch name contains `$ARGUMENTS` (the work item ID, e.g. `Issue-123`), the correct
branch is already active — proceed to Step 1.
If the branch is `dev/claude/$ARGUMENTS`, proceed to Step 1 — the workspace is already
set up.

Otherwise, invoke the shared branch-creation skill:
Otherwise, create and switch to the task branch:

```bash
/create-branch $ARGUMENTS "<task brief first sentence>"
git checkout -b dev/claude/$ARGUMENTS
```

Do not push — the pipeline pushes after validation passes.
Expand Down
68 changes: 68 additions & 0 deletions plugins/dev-team/commands/workspace-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
description: Find the epic base branch and create the task branch for a pipeline run.
argument-hint: <work-item-id> <spec-path>
user-invocable: false
---

## Inputs

Work item ID: first token of `$ARGUMENTS`
Spec path: second token of `$ARGUMENTS`

## Steps

### 1 — Check if already set up

```bash
git branch --show-current
```

If already on `dev/claude/<work-item-id>`, output `setup_done` and stop.

### 2 — Find the epic ID

Read the spec file at the spec path. Look for an Epic reference — a Jira key pattern
(e.g. `ADR-200`) that appears in headings like `Epic:`, `Parent:`, or in the title block.

If not found in the spec, query Jira:
- Call `mcp__08e9ccd3-4093-4425-adec-d98ea766a759__getJiraIssue` with the work item ID
- Look for a `parent` or `epic` field on the issue

If no epic is found, proceed with `main` as the base branch.

### 3 — Find the base branch

If an epic ID was found (e.g. `ADR-200`):

```bash
git fetch origin
git branch -r | grep "feature/<epic-id>"
```

Use the first matching branch (e.g. `origin/feature/ADR-200-infrastructure`), stripping
the `origin/` prefix. If no match is found, fall back to `main`.

If no epic was found, check for the nearest `feature/*` ancestor of the current HEAD:

```bash
git branch -r --merged HEAD | grep "feature/"
```

Use the closest ancestor `feature/*` branch. If none, use `main`.

### 4 — Check out base branch and pull

```bash
git checkout <base-branch>
git pull origin <base-branch>
```

### 5 — Create task branch

```bash
git checkout -b dev/claude/<work-item-id>
```

### 6 — Output

Output exactly: `setup_done`
43 changes: 43 additions & 0 deletions plugins/dev-team/scripts/dev_team.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ class PipelineContext:
build_log: str = ""
test_log: str = ""
debug_report: str = ""
workspace_setup: str = ""
signoff_review: str = ""
signoff_research: str = ""
signoff_build_result: str = ""
Expand Down Expand Up @@ -239,6 +240,9 @@ def save(self, path: Path) -> None:
f"# {self.work_item_id} Dev Team Context",
]

if self.workspace_setup:
lines += ["", "<!-- section:Workspace Setup -->", "", self.workspace_setup.strip()]

if self.debug_report:
lines += ["", "<!-- section:Debug Report -->", "", self.debug_report.strip()]

Expand Down Expand Up @@ -308,6 +312,7 @@ def load(cls, path: Path) -> "PipelineContext":
pass

sections = _parse_sections(body)
ctx.workspace_setup = sections.get("Workspace Setup", "")
ctx.debug_report = sections.get("Debug Report", "")
ctx.brief = sections.get("Researcher Brief", "")

Expand Down Expand Up @@ -502,6 +507,43 @@ def handle_results(self) -> str:
...


class SetupWorkspaceStep(Step):
handles = "setting-up"
_PENDING_KEY = "setup"

def __init__(self, ctx: "PipelineContext", context_path: Path) -> None:
self._ctx = ctx
self._context_path = context_path

def get_actions(self) -> list[dict]:
ctx = self._ctx
if ctx.workspace_setup:
return []
return [{
"action": "spawn_agent",
"message": f"Setting up workspace branch for {ctx.work_item_id}.",
"agent": "workspace-setup",
"skill": "workspace-setup",
"args": f"{ctx.work_item_id} {ctx.spec_path}",
"context_file": str(self._context_path),
"read_sections": [],
"write_section": "Workspace Setup",
"result_format": "setup_done | failed",
}]

def handle_results(self) -> str:
ctx = self._ctx
if ctx.workspace_setup:
_handle_agent_success(ctx)
return "setup_done"
_handle_agent_failure(ctx)
_check_and_trigger_troubleshooter(
"consecutive_failures", CONSECUTIVE_FAILURES_THRESHOLD,
ctx.consecutive_failures, ctx, self._context_path,
)
return "failed"


class FindSpecStep(Step):
handles = "spec-finding"

Expand Down Expand Up @@ -1125,6 +1167,7 @@ def __init__(
self.machine = StateMachine(workflow.transitions, initial=ctx.state)
self.step_handlers: dict[str, Step] = {
"spec-finding": FindSpecStep(ctx),
"setting-up": SetupWorkspaceStep(ctx, context_path),
"debugging": DebugStep(ctx, context_path),
"researching": ResearchStep(research_skill, ctx, context_path),
"implementing": ImplementStep(ctx, context_path),
Expand Down
3 changes: 2 additions & 1 deletion plugins/dev-team/scripts/implement-task-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
stateDiagram-v2
[*] --> init
init --> spec-finding : start
spec-finding --> researching : spec_found
spec-finding --> setting-up : spec_found
setting-up --> researching : setup_done
researching --> implementing : research_done
implementing --> validating : impl_done
validating --> fixing : build_failed
Expand Down
Loading