Skip to content
Draft
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
41 changes: 10 additions & 31 deletions plugins/dev-team/skills/concurrent-orchestrate/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,6 @@ and stopping on `"complete"` or `"blocked"`.

## Steps

### 0 — Verify `python3` is available

Every step below drives `concurrent_schedule.py` (and, transitively, every spawned
`workflow-orchestrate` run) through `python3` — nothing in this pipeline works without it.
Before running step 1 for the first time this session, confirm the interpreter is present:

```bash
command -v python3
```

If this reports nothing (a non-zero exit), stop immediately and report to the user that
`python3` is required but was not found on this system, rather than proceeding and failing on
the first script invocation with a less obvious "command not found" error.

### 1 — Reconcile against what's already running

Run once before entering the main loop (step 2) — the first thing this session does whether
Expand All @@ -82,11 +68,9 @@ This step detects that and respawns.

1. Take one non-blocking snapshot — `--max-poll-cycles 0` is a new invocation mode, distinct
from step 2a's default ~5-minute polling behavior, that returns after exactly one poll
instead of blocking until something becomes actionable:
```bash
python3 "<skill-dir>/scripts/concurrent_schedule.py" --up-to "<target>" --max-poll-cycles 0
```
or the `--list` form, matching whichever target mode this run uses.
instead of blocking until something becomes actionable. Use the `run-python-script` skill with
`--script "<skill-dir>/scripts/concurrent_schedule.py" --args '--up-to "<target>"
--max-poll-cycles 0'` (or the `--list` form, matching whichever target mode this run uses).
2. For each `{task_id, status, last_updated, worktree_path}` entry in the returned `running`
list, check whether this session already holds a live spawn handle for it — i.e. whether this
session itself spawned it via step 2c, in this run or an earlier one before a restart. Keep
Expand All @@ -110,19 +94,12 @@ Repeat the following until the script reports `"complete"` or `"blocked"`.

#### 2a — Run the scheduler script

```bash
python3 "<skill-dir>/scripts/concurrent_schedule.py" --up-to "<target>"
```

or, for the explicit-list form:

```bash
python3 "<skill-dir>/scripts/concurrent_schedule.py" --list "<target>"
```
Use the `run-python-script` skill with `--script "<skill-dir>/scripts/concurrent_schedule.py"
--args '--up-to "<target>"'` (or `--args '--list "<target>"'` for the explicit-list form).

The script blocks internally rather than returning the instant it sees nothing to do.
Invoke this `Bash` call with an explicit `timeout` of at least `330000`
(5.5 minutes) — comfortably past the script's own ~5-minute default polling budget.
The script blocks internally rather than returning the instant it sees nothing to do. Pass
`--timeout 330000` (5.5 minutes) to `run-python-script` — comfortably past the script's own
~5-minute default polling budget.

Capture stdout — a single JSON object
`{"status": ..., "spawn": [...], "blocked_tasks": [...], "running": [...]}`. If the script exits
Expand Down Expand Up @@ -243,3 +220,5 @@ step — there is no PR to monitor, so no `dev-team:monitor-pr` is spawned for i

- `use-context-file` — pre-populating `base_branch`, and recording `worktree_path` /
`worktree_branch`, on a spawned task's context file
- `run-python-script` — the `python3` availability check and every `concurrent_schedule.py`
invocation
7 changes: 2 additions & 5 deletions plugins/dev-team/skills/dev-spec-task-breakdown/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,8 @@ environment variable. `task_dependencies.py` lives in the sibling `workflow-orch
`scripts/` directory, reachable relative to `<skill-dir>` — this skill may run in a repo other
than the one containing these plugin files (e.g. as an installed plugin), so resolve the path
this way rather than assuming a particular repo layout or that the Bash tool's CWD is the repo
root. Run it via `Bash`:

```bash
python3 "<skill-dir>/../workflow-orchestrate/scripts/task_dependencies.py" "<path to spec file>"
```
root. Use the `run-python-script` skill with `--script
"<skill-dir>/../workflow-orchestrate/scripts/task_dependencies.py" --args "<path to spec file>"`.

If it exits non-zero, it printed a clear `Error: ...` message to stderr naming the offending task
and reference (a dangling reference or a dependency cycle). Surface that error to the user and
Expand Down
18 changes: 9 additions & 9 deletions plugins/dev-team/skills/ensure-working-branch/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ task's own dependencies from.

Otherwise:

1. Read this task's own dependency ids: invoke
`python3 "<skill-dir>/../workflow-orchestrate/scripts/task_dependencies.py" "<spec_path>"` via
`Bash`. It prints the whole spec's `{task_key: [dependency_ids]}` graph as JSON on success.
1. Read this task's own dependency ids: use the `run-python-script` skill with `--script
"<skill-dir>/../workflow-orchestrate/scripts/task_dependencies.py" --args "<spec_path>"`. It
prints the whole spec's `{task_key: [dependency_ids]}` graph as JSON on success.
Look up this task's own work-item-id key in that graph — that list is this task's own
dependency ids (an empty list if the task declares `— none —` or has no `Depends on:` line at
all). If the command exits non-zero, it prints a clear `Error: ...` message to stderr instead
Expand All @@ -107,12 +107,12 @@ Otherwise:
2. If that list is empty, skip the rest of this sub-step and fall through to 4c unchanged (no
dependencies means nothing for this step to override).

3. Otherwise, invoke
`python3 "<skill-dir>/../workflow-orchestrate/scripts/task_readiness.py" "<work-item-id>" "<dep1>,<dep2>,..."`
via `Bash`, passing this task's own dependency ids as a comma-separated list. It prints
`{"status": "eligible" | "waiting" | "blocked", "base_branch": <branch-name-or-null>}` as JSON
on success. If the command exits non-zero, it prints a clear `Error: ...` message to stderr
instead of JSON — stop and report that error in detail; do not fall through to 4c.
3. Otherwise, use the `run-python-script` skill with `--script
"<skill-dir>/../workflow-orchestrate/scripts/task_readiness.py" --args "<work-item-id>
<dep1>,<dep2>,..."`, passing this task's own dependency ids as a comma-separated list. It
prints `{"status": "eligible" | "waiting" | "blocked", "base_branch": <branch-name-or-null>}`
as JSON on success. If the command exits non-zero, it prints a clear `Error: ...` message to
stderr instead of JSON — stop and report that error in detail; do not fall through to 4c.

4. If `status` is `"eligible"` and `base_branch` is a real (non-null) branch name: write it to
the context file's `base_branch` field via `use-context-file`, then skip the rest of step 4
Expand Down
4 changes: 1 addition & 3 deletions plugins/dev-team/skills/get-project-configuration/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ Use this skill when:
skill" path shown when this skill was invoked. Resolve it to that literal path; it is
not an environment variable.

```bash
python3 "<skill-dir>/scripts/merge_config.py"
```
Use the `run-python-script` skill with `--script "<skill-dir>/scripts/merge_config.py"`.

Prints the merged configuration as JSON to stdout and exits 0. On failure (malformed YAML,
no repo root found) it prints `Error: ...` to stderr and exits non-zero — stop and report the
Expand Down
16 changes: 5 additions & 11 deletions plugins/dev-team/skills/implement-tdd/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,10 @@ whole thing:
`<skill-dir>` refers to this skill's own base directory — the "Base directory for this skill"
path shown when this skill was invoked. Resolve it to that literal path.

Pass the component prompt on the script's stdin (e.g. a heredoc), not as a file:

```bash
python3 "<skill-dir>/scripts/tdd_cycle.py" \
--component-name "<Component>" \
--repo-root <repo-root> \
--work-item-id <work-item-id> \
--state-file <state-path> <<'EOF'
<component prompt text>
EOF
```
Pass the component prompt on the script's stdin (e.g. a heredoc), not as a file. Use the
`run-python-script` skill with `--script "<skill-dir>/scripts/tdd_cycle.py" --args
"--component-name \"<Component>\" --repo-root <repo-root> --work-item-id <work-item-id>
--state-file <state-path>" --stdin "<component prompt text>"`.

Use a `<state-path>` unique to this component (e.g. under a scratch directory) — it's how the
script resumes a specific component's in-progress loop after you resolve an escalation. Every
Expand Down Expand Up @@ -129,3 +122,4 @@ builds/tests on their behalf.
against
- `implement-direct` — used for a `resolve_directly` Tier 2 escalation, before re-running the
script
- `run-python-script` — the `python3` availability check and the `tdd_cycle.py` invocation
8 changes: 5 additions & 3 deletions plugins/dev-team/skills/monitor-pr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,8 @@ Repeat the following indefinitely, until step 4b's `task_merged` case stops you,

#### 4a — Poll

```bash
python3 "<skill-dir>/../workflow-orchestrate/scripts/watch_pr_poll.py" <work-item-id>
```
Use the `run-python-script` skill with `--script
"<skill-dir>/../workflow-orchestrate/scripts/watch_pr_poll.py" --args "<work-item-id>"`.

Parse stdout as JSON. If it is the literal string `"no_change"`, go straight back to step 4a —
`watch_pr_poll.py` already blocked internally for its own bounded window; no additional wait is
Expand Down Expand Up @@ -250,3 +249,6 @@ the spawn's generic `successful` status:
argument
- `workflow-worker` — the mediated spawn pattern (`--context-file`/`--write-section`/`--skill`/
`--skill-args`) for nested `fix-pr` and `resolve-rebase-conflict` calls
- `run-python-script` — the `python3` availability check and the `watch_pr_poll.py` invocation
(step 4a); the rebase mechanic's inline `python3 -c` block (step 4c) is a documented carve-out,
not migrated — see `run-python-script/SKILL.md`'s "Carve-outs" section
99 changes: 99 additions & 0 deletions plugins/dev-team/skills/run-python-script/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
name: run-python-script
user-invocable: false
description: >
Shared skill that centralizes the `python3` availability check and script invocation. Verifies
`python3` is present (skipping the check if already verified earlier in this session) and stops
with a clear, stop-and-tell-the-user failure if missing, then runs a given Python script (with
its arguments) via `python3`. Every other skill that invokes a Python script should delegate to
this skill instead of inlining its own `python3 <script>` call, so there is exactly one place
to change the interpreter requirement later.
argument-hint: --script <path> [--python-flags "<flags>"] [--args "<arg1> <arg2> ..."] [--stdin "<text>"] [--timeout <ms>]
---

Use this skill when:
- You are about to run a Python script via `python3` as part of a skill's own steps

Do NOT use this skill when:
- The command you need to run is a pre-built shell string handed to you by a caller, not a
literal `python3 <script>` invocation you are constructing yourself — e.g. `workflow-script`'s
`--command` argument. That contract stays exactly as-is; see "Carve-outs" below.

## Arguments

- `--script` — the Python script to run, as a path already resolved by the caller (e.g.
`"<skill-dir>/scripts/foo.py"`) — this skill does not resolve `<skill-dir>` itself
- `--python-flags` — (optional) flags for the `python3` interpreter itself, placed before the
script path (e.g. `-u` for unbuffered stdout) — distinct from `--args`, which is placed after
the script path and passed to the script's own argv
- `--args` — (optional) the script's own arguments, exactly as they'd appear on the command line
- `--stdin` — (optional) text to pipe to the script's stdin (e.g. via a heredoc), for a script
that reads piped input rather than argv (e.g. `tdd_cycle.py`'s component prompt)
- `--timeout` — (optional) an explicit `Bash` tool timeout in milliseconds, for a script the
caller knows blocks internally past the default timeout (e.g. a polling script with its own
multi-minute internal wait budget). Omit to use the `Bash` tool's own default.

## Steps

### 1 — Verify `python3` is available (skip if already verified this session)

If you have already verified `python3` is present earlier in this same session — whether via an
earlier call to this skill, or an earlier explicit preflight check — skip straight to step 2.
There is no session-state file for this; it relies on the same in-context recall convention every
prior preflight step in this pipeline already used ("before running step 1 for the first time
this session").

Otherwise, confirm the interpreter is present:

```bash
command -v python3
```

If this reports nothing (a non-zero exit), stop immediately and report to the user that `python3`
is required but was not found on this system, rather than proceeding and failing on the script
invocation itself with a less obvious "command not found" error. Do not attempt to install
`python3`, fall back to a bare `python` command, or probe for any other interpreter — this
project standardizes fully on `python3`, no fallback-detection chain.

Otherwise, remember for the rest of this session that `python3` has been verified, so this step
is a no-op on every later call to this skill (or any other step in this session that would
otherwise re-check it).

### 2 — Run the script

```bash
python3 <python-flags> "<script>" <args>
```

Omit `<python-flags>` entirely when `--python-flags` was not given — do not insert an empty
argument in its place. If `--stdin` was given, pipe it in (e.g. via a heredoc) instead of running
the bare command. If `--timeout` was given, pass it as the `Bash` tool's own `timeout` parameter
for this call.

Capture stdout/stderr per the calling skill's own contract for this specific script — this skill
only ensures the interpreter is present and executes the script; it does not interpret, parse, or
reformat the script's output itself. The calling skill's own instructions for what to do with the
output (parse JSON, check exit code, treat a non-JSON last line a certain way, etc.) are unchanged
by routing the invocation through this skill.

## Carve-outs (not migrated to this skill)

- **`workflow-script`'s `--command` argument.** Its `<command>` is a pre-built shell string handed
in by the caller (sometimes literally `python3 ...`, sometimes built by `dev_team.py` using
`sys.executable`) — `workflow-script` runs whatever string it's given via `Bash`, it never
constructs a `python3 <script>` invocation itself the way every other skill migrated to this
skill does. No functional change; this is documented here as the intentional reason it stays
out of scope.
- **Inline `python3 -c "<code>"` blocks** (`workflow-orchestrate/SKILL.md`'s
`troubleshooter_input` write, `monitor-pr/SKILL.md`'s rebase-mechanic invocation). These run
inline code, not a script file at a path — outside this skill's `--script <path>` shape. Each
stays as a direct inline `python3 -c` call. Since both live in skills whose own earlier steps
already call this skill first in the same session (`workflow-orchestrate`'s step 1;
`monitor-pr`'s step 4a via the sibling `watch_pr_poll.py` call), `python3`'s availability is
already established in-session by the time either inline block runs — no separate preflight is
needed at these two call sites.
- **`dev_team.py`'s two generated command strings** (`_resolve_validation_script()`,
`BuildValidationStep.get_actions()`) — these already use `sys.executable`, not a literal
`python3` invocation, because that code path is real Python building a command string for a
later shell invocation, not agent-facing skill prose constructing a `python3 <script>` call
itself. This skill only wraps the latter; no change is needed here.
Comment on lines +79 to +99

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to call all of these out? They just don't delegate to the skill. Including them here makes ever agent that uses this skill think about all the places where it's not used. Why?

16 changes: 6 additions & 10 deletions plugins/dev-team/skills/update-project-configuration/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,9 @@ Resolve `<repo-root>` the same way `merge_config.py` does: walk up from the curr

- If a setting phrase was given (or is clear from conversation), go to **Step 3 — Single setting**.
- If the user explicitly asked for a full walkthrough/initialization, go to **Step 4 — Full walkthrough**.
- Otherwise, load the current merged config for context:

```bash
python3 "<get-project-configuration-skill-dir>/scripts/merge_config.py" --repo-root "<repo-root>"
```
- Otherwise, load the current merged config for context: use the `run-python-script` skill with
`--script "<get-project-configuration-skill-dir>/scripts/merge_config.py" --args "--repo-root
\"<repo-root>\""`.

`<get-project-configuration-skill-dir>` is that skill's own base directory — a sibling of this
skill's directory (both live directly under `plugins/dev-team/skills/`). Resolve it to the literal
Expand Down Expand Up @@ -241,11 +239,9 @@ existing formatting:
## Verifying a write

After writing, re-run `merge_config.py` against the same repo root and show the user the relevant part
of the merged result, confirming the change took effect as intended:

```bash
python3 "<get-project-configuration-skill-dir>/scripts/merge_config.py" --repo-root "<repo-root>"
```
of the merged result, confirming the change took effect as intended: use the `run-python-script`
skill with `--script "<get-project-configuration-skill-dir>/scripts/merge_config.py" --args
"--repo-root \"<repo-root>\""`.

If it exits non-zero (malformed YAML), report the exact error — the edit introduced a syntax problem
that must be fixed before the write can be considered done.
13 changes: 5 additions & 8 deletions plugins/dev-team/skills/use-context-file/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,14 @@ If no argument was given at all, use the `identify-project-work-items` skill to
this skill" path shown when this skill was invoked. Resolve it to that literal path; it
is not an environment variable.

```bash
python3 "<skill-dir>/scripts/compute-context-file.py" "<work-item-id>"
```
Use the `run-python-script` skill with `--script "<skill-dir>/scripts/compute-context-file.py"
--args "<work-item-id>"`.

If the script exits non-zero, stop and report the error.

Ensure the file exists (creates it with default frontmatter if missing):

```bash
python3 "<skill-dir>/scripts/init-context-file.py" "<work-item-id>" "<context-file>"
```
Ensure the file exists (creates it with default frontmatter if missing): use the
`run-python-script` skill with `--script "<skill-dir>/scripts/init-context-file.py" --args
"<work-item-id> <context-file>"`.

If the script exits non-zero, stop and report the error.

Expand Down
28 changes: 5 additions & 23 deletions plugins/dev-team/skills/workflow-orchestrate/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,38 +43,20 @@ compress your own report of a genuinely unexpected failure down to one line.

## Steps

### 0 — Verify `python3` is available

Every step below drives `dev_team.py` (and every script it delegates to) through `python3` —
nothing in this workflow works without it. Before running step 1 for the first time this
session, confirm the interpreter is present:

```bash
command -v python3
```

If this reports nothing (a non-zero exit), stop immediately and report to the user that
`python3` is required but was not found on this system, rather than proceeding and failing on
the first script invocation with a less obvious "command not found" error.

### 1 — Compute context file path

```bash
python3 "<skill-dir>/scripts/get_context_path.py" "<work-item-id>"
```
Use the `run-python-script` skill with `--script "<skill-dir>/scripts/get_context_path.py"
--args "<work-item-id>"`.

### 2 — Orchestration loop

Repeat the following until `action == "done"` or a terminal condition is reached.

#### 2a — Run the step machine

```bash
python3 -u <skill-dir>/scripts/dev_team.py <work-item-id> \
--workflow <skill-dir>/assets/<workflow>.md \
--research-skill <research-skill> \
--context-file <context_file>
```
Use the `run-python-script` skill with `--script "<skill-dir>/scripts/dev_team.py"
--python-flags "-u" --args "<work-item-id> --workflow <skill-dir>/assets/<workflow>.md
--research-skill <research-skill> --context-file <context_file>"`.

Capture all stdout. The last JSON array on stdout is the action descriptor list.

Expand Down
Loading
Loading