Skip to content
Back to skills

Mastermind Plan To Tasks

ASecurity

Mastermind plan-to-tasks — turn a written plan into assigned org issues with the right specialties, dependencies and parallelization.

  • 21 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 10, 2026
ai-agentspythongobashexpress

Works with

  • cli

Security analysis

A100/100

Scanned October 1, 2026

npx -y skills add monoes/monomind --skill mastermind-plan-to-tasks --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Mastermind Plan To Tasks?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Mastermind Plan To Tasks
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/monoes-mastermind-plan-to-tasks/badge)](https://www.skillsdirectory.com/skills/monoes-mastermind-plan-to-tasks)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: mastermind-plan-to-tasks
description: "Mastermind plan-to-tasks — turn a written plan into assigned org issues with the right specialties, dependencies and parallelization."
type: domain-skill
default_mode: confirm
---

# Mastermind Plan to Tasks

This skill is invoked directly via `/mastermind-plan-to-tasks`.

---

## Inputs

- `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
- `org_name`: org to create issues in (required)
- `plan`: the plan text (required — paste inline or pipe in)
- `project_id`: assign all issues to this project (optional)
- `workspace_id`: assign all issues to this workspace (optional)
- `dry_run`: true | false (default: false — if true, print plan without creating issues)
- `caller`: command | master

---

## Step 0 — Brain Load (standalone only)

If `caller` is not "command", load brain context following mastermind-protocol/SKILL.md Brain Load Procedure with namespace: `ops`.

---

## Step 1 — Validate Inputs

```bash
[ -z "$org_name" ] && { echo "ERROR: --org required."; exit 1; }
[ -z "$plan"     ] && { echo "ERROR: --plan required (the plan text to decompose)."; exit 1; }

orgFile=".monomind/orgs/${org_name}.json"
[ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
```

---

## Step 2 — Load Agents for Specialty Matching

```bash
echo "PLAN-TO-TASKS — $org_name"
echo "────────────────────────────────────────────────────────"
echo ""
echo "AGENTS IN ORG:"
jq -r '(.roles // [])[] | "  \(.id)  \(.title // "-")  [\(.adapter.type // "?")]"' "$orgFile"
echo ""
```

---

## Step 3 — Decompose Plan into Issues

Read the plan carefully and apply these rules:

**Planning principles (from Paperclip plan-to-tasks):**

1. **Plan deeply.** Capture real detail: goals, constraints, unknowns, success criteria, risks. A shallow plan becomes rework.
2. **Know your team.** Read the org's agents and their specialties (titles, roles, adapters) before assigning anything.
3. **Assign for specialty.** Hand each piece of work to the most relevant agent. If no agent fits, flag the gap.
4. **Take responsibility.** When you (the AI) are best-suited for a piece, assign it to yourself instead of delegating.
5. **Use the dependency tree.** Express every concrete deliverable as an issue. Wire real blockers via `blockedByIssueIds`. When done, dependents auto-wake.
6. **Order, then parallelize.** Sequence by real dependencies. Independent branches start in parallel.
7. **Enough is enough.** Plans unblock execution. Don't re-plan already clear work.

**Decomposition output:**

For each issue extracted from the plan, emit one object into a JSON array and write the
whole array to `.monomind/orgs/<org_name>-plan-decomposition.json` using the Write tool:

```json
[
  {
    "title": "Short imperative deliverable name",
    "description": "1-2 sentence summary of the deliverable",
    "assignee": "<agent-id from the org roster, or null if unassigned>",
    "priority": "low | medium | high | urgent",
    "blockedBy": ["<exact title of a blocking issue in this same array>"]
  }
]
```

Titles must be unique within the array — `blockedBy` is resolved by exact title match.
Use `[]` for `blockedBy` when an issue has no blockers.

**Quality checklist before creating:**
- [ ] Enough detail that assignees can act without re-asking
- [ ] Every concrete deliverable is an issue
- [ ] Each issue has a deliberate, specialty-matched assignee
- [ ] Each issue's real blockers are declared
- [ ] Independent branches can start in parallel
- [ ] Gaps (missing skills, decisions, external inputs) are surfaced, not hidden

---

## Step 4 — Create Issues (unless dry_run=true)

Reads the decomposition written in Step 3, assigns collision-free ids, validates assignees
against the org roster, resolves `blockedBy` titles into `blockedByIssueIds`, and appends
to the issues file atomically. Fails loudly on any unresolved or ambiguous reference —
an unresolved blocker silently dropped is exactly what produces a `blocked` issue with an
empty `blockedByIssueIds`, which `mastermind-liveness` reports as stalled.

```bash
issuesFile=".monomind/orgs/${org_name}-issues.json"
decompFile=".monomind/orgs/${org_name}-plan-decomposition.json"
[ ! -f "$issuesFile" ] && echo '{"issues":[]}' > "$issuesFile"
[ ! -f "$decompFile" ] && { echo "ERROR: $decompFile not found — Step 3 must write it first."; exit 1; }

ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)

python3 - "$issuesFile" "$decompFile" "$orgFile" "${project_id:-}" "${workspace_id:-}" "${dry_run:-false}" "$ts" <<'PYEOF'
import json, os, sys, time

issues_path, decomp_path, org_path, project_id, workspace_id, dry_run, ts = sys.argv[1:]
dry = dry_run == "true"

VALID_PRIORITY = {"low", "medium", "high", "urgent"}

decomp = json.load(open(decomp_path))
if not isinstance(decomp, list) or not decomp:
    print("ERROR: decomposition must be a non-empty JSON array.")
    sys.exit(1)

roster = {r.get("id") for r in json.load(open(org_path)).get("roles", [])}
data   = json.load(open(issues_path))
issues = data.setdefault("issues", [])

# --- Validate before mutating anything ---
errors, titles = [], {}
for n, item in enumerate(decomp, 1):
    title = (item.get("title") or "").strip()
    if not title:
        errors.append(f"item {n}: missing title")
        continue
    if title in titles:
        errors.append(f"item {n}: duplicate title {title!r} — titles must be unique to resolve blockedBy")
    titles[title] = None
    pri = item.get("priority") or "medium"
    if pri not in VALID_PRIORITY:
        errors.append(f"{title!r}: priority {pri!r} must be one of {sorted(VALID_PRIORITY)}")
    asgn = item.get("assignee")
    if asgn and asgn not in roster:
        errors.append(f"{title!r}: assignee {asgn!r} is not a role in this org (roster: {sorted(roster)})")

existing_by_title = {i.get("title"): i.get("id") for i in issues}
for item in decomp:
    for b in item.get("blockedBy") or []:
        if b not in titles and b not in existing_by_title:
            errors.append(f"{item.get('title')!r}: blockedBy {b!r} matches no issue in this batch or in the existing file")

if errors:
    print("ERROR: decomposition did not validate — no issues were created.")
    for e in errors:
        print(f"  · {e}")
    sys.exit(1)

# --- Assign ids (batch-stable, collision-free) ---
batch = int(time.time() * 1000)
for n, item in enumerate(decomp, 1):
    titles[item["title"].strip()] = f"issue-{batch}-{n:03d}"

def resolve(t):
    return titles.get(t) or existing_by_title[t]

created = []
for item in decomp:
    title = item["title"].strip()
    created.append({
        "id": titles[title],
        "title": title,
        "description": item.get("description") or "",
        "status": "todo",
        "priority": item.get("priority") or "medium",
        "assigneeId": item.get("assignee") or None,
        "assigneeAgentId": item.get("assignee") or None,
        "assigneeUserId": None,
        "parentId": None,
        "projectId": project_id or None,
        "workspaceId": workspace_id or None,
        "blockedByIssueIds": [resolve(b) for b in (item.get("blockedBy") or [])],
        "createdAt": ts,
        "updatedAt": ts,
    })

if dry:
    print("DRY RUN — no issues were created. Would create:")
    for c in created:
        blockers = ", ".join(c["blockedByIssueIds"]) or "none"
        print(f"  {c['id']}  [{c['priority']:<6}] {c['title']}")
        print(f"      assignee: {c['assigneeId'] or 'UNASSIGNED'}   blockedBy: {blockers}")
    print(f"\n  {len(created)} issue(s) would be created.")
    sys.exit(0)

issues.extend(created)
tmp = issues_path + ".tmp"
with open(tmp, "w") as f:
    json.dump(data, f, indent=2)
os.replace(tmp, issues_path)

print("CREATED ISSUES:")
for c in created:
    blockers = ", ".join(c["blockedByIssueIds"]) or "none"
    print(f"  {c['id']}  [{c['priority']:<6}] {c['title']}")
    print(f"      assignee: {c['assigneeId'] or 'UNASSIGNED'}   blockedBy: {blockers}")
print(f"\n  {len(created)} issue(s) created in {issues_path}")

roots = [c for c in created if not c["blockedByIssueIds"]]
print(f"  {len(roots)} issue(s) are unblocked and can start in parallel.")
PYEOF

rm -f "$decompFile"
```

> **These issues are not auto-consumed by the org runtime.** `OrgDaemon` builds its `TaskDag`
> fresh in memory on every start and never reads `<org>-issues.json` (verified: zero references
> in `packages/@monomind/cli/src/orgrt/`). Issues created here are tracked by the
> `mastermind-issues` / `mastermind-my-issues` / `mastermind-liveness` skills and shown in the
> dashboard, but running `monomind org run <org>` will not pick them up. Drive execution from
> this file with `mastermind-execute`, or pass work explicitly via `org run --task`.

---

## Step 5 — Return Output

```yaml
domain: ops
status: complete
action: plan-to-tasks
org_name: <org_name>
issues_created: <N>
dry_run: <true|false>
```

---

## Step 6 — Brain Write (standalone only)

If `caller` is not "command", follow mastermind-protocol/SKILL.md Brain Write Procedure for domain `ops`.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.