# Planner Refine Assignments

> Refine elaborated assignments for a single phase via parallel L0 subagents (L1+L0 pattern), using per-phase context file with peer_summaries for cross-phase visibility

- Skill: `talont-org/planner-refine-assignments` (Agent Skill)
- Install (CLI): `npx skillmds@latest add talont-org/planner-refine-assignments`
- Raw SKILL.md: https://api.skillmd.com/api/skills/talont-org/planner-refine-assignments/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: TalonT-Org (https://skillmd.com/u/talont-org)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/talont-org/planner-refine-assignments

---


# planner-refine-assignments

L1 session that refines the assignments for a single phase by spawning one L0 subagent per
assignment in parallel (3–5 assignments per phase). Receives a per-phase context file produced
by `merge_tier_results` → `_write_refine_contexts`, which contains only this phase's assignments
and `peer_summaries` (id/name/goal stubs) for all other phases. Each L0 reviews its assignment
in the context of peer_summaries and `refined_plan.json`, returning structured suggestions. L1
applies suggestions, resolves intra-phase WP ownership conflicts, and writes the phase result
file to `$3/refine_contexts/{phase_id}_result.json`.

## When to Use

- Dispatched by the L2 planner recipe in parallel — one session per phase
- Accepts a per-phase context file from `$3/refine_contexts/context_{phase_id}.json` and `refined_plan.json` for phase context
- Produces `{phase_id}_result.json` as input for the downstream `merge_refined_assignments` step

## Arguments

- **$1** — Absolute path to the per-phase context file (`$3/refine_contexts/context_{phase_id}.json`). The file contains:
  - `phase_id` — identifier for the phase this session processes
  - `task_file_path` — path to the task description file (read from disk, not inline)
  - `assignments` — full AssignmentElaborated objects for this phase only (3–5 entries)
  - `peer_summaries` — `{id, name, goal}` stubs for all assignments in other phases
- **$2** — Absolute path to `refined_plan.json` (PlanDocument with phases as PhaseElaborated, for phase context)
- **$3** — Absolute path to the run-scoped planner directory (e.g., `{{AUTOSKILLIT_TEMP}}/planner/run-YYYYMMDD-HHMMSS`). Output is written to `$3/refine_contexts/{phase_id}_result.json`.

## Critical Constraints

**NEVER:**
- Write any file outside `$3/`
- Directly modify the context file ($1) — always write a new result file
- Allow an L0 subagent to write files directly (L0s return structured text only)
- Emit `phase_refined_path` before writing the result file
- Skip emitting `phase_refined_path` even if all L0s fail (write unchanged assignments, still emit)
- Spawn more than 6 L0s in a single parallel batch
- Read `{{AUTOSKILLIT_TEMP}}` artifacts not passed as positional arguments
- Run subagents in the background (`run_in_background: true` is prohibited)
- Write L0 prompts to intermediate `l0_prompts/` files and read them back into the L1 context — spawn L0 subagents directly from in-memory context packets
- Read source code files, test files, or recipe YAML files directly — codebase exploration is the L0 subagents' responsibility
- Run Bash, Grep, or Glob commands for codebase exploration between L0 spawns

**ALWAYS:**
- Read `phase_id` from the context file to construct the output path
- Validate each L0 response for `assignment_id`, `changes` (array), `dependency_corrections` (array), `wp_proposal_adjustments` (array)
- Log `WARNING` to stdout for any L0 response that fails validation (skip that assignment)
- Log `CRITICAL` to stdout for any L0 subagent that fails entirely (proceed with N-1, partial result)
- When two assignments propose WPs covering the same files, assign ownership to the numerically earlier assignment_id using natural sort on numeric suffixes (e.g. `P1-A1` beats `P1-A2`; `P1-A2` beats `P1-A10`); log each resolution
- Emit: `phase_refined_path = <absolute path to $3/refine_contexts/{phase_id}_result.json>`

## Workflow

### Step 1: Parse input and validate

Read `$1` (per-phase context file). Extract `phase_id`, `assignments`, `peer_summaries`, and
`task_file_path`. Fail immediately (exit non-zero) if `assignments` is empty or the file is
malformed — do not proceed to spawn L0s. The failure message must include the file path and the
parse/validation error string:
```
FATAL: failed to parse {path}: {error_detail}
```

Read `$2` (refined_plan.json). Build a map `phase_id → PhaseElaborated` for L0 context.

Input schema for the per-phase context file:
```json
{
  "phase_id": "P2",
  "task_file_path": "/path/to/task.md",
  "assignments": [
    {
      "id": "P2-A1",
      "phase_id": "P2",
      "name": "...",
      "goal": "...",
      "technical_approach": "...",
      "dependency_notes": "...",
      "work_packages": [...]
    }
  ],
  "peer_summaries": [
    {"id": "P1-A1", "name": "...", "goal": "..."},
    {"id": "P3-A1", "name": "...", "goal": "..."}
  ]
}
```

### Step 2: Build L0 context packets

For each assignment in `assignments`, build a context packet containing:
- The full serialized assignment object (AssignmentElaborated)
- The `peer_summaries` list for cross-phase dependency detection
- The `PhaseElaborated` entry for the assignment's `phase_id` from `$2`
- The `target_assignment_id`
- `task_file_path` — the path to the task description on disk (pass the path reference only; do NOT read the task text into the L1 context or embed it in the L0 prompt)
- Instructions: review the target assignment in light of peer_summaries; always read the task from disk at `task_file_path` for scope creep verification (flag scope creep if the assignment's goal, scope, or deliverables introduce work not requested by the task); return structured suggestions only — do NOT edit files

### Step 3: Spawn parallel L0 subagents

Since each phase has 3–5 assignments (always within the 6-L0 ceiling), spawn all in one
parallel batch via Agent/Task. Do not spawn more than 6 L0s in a single parallel batch:
if assignment count > 6 (unexpected), spawn sequential batches of 6. Between batches, emit
anti-prose guard line: `--- next batch ---`.

Reading `l0_prompts/*.txt` files back before spawning adds ~15K tokens to the L1 context per L0 with no benefit.

Each L0 must return structured text in this exact format:
```
assignment_id = P1-A2
changes = [
  {"field": "dependency_notes", "new_value": "Requires P1-A1-WP1 interface before starting"},
  {"field": "technical_approach", "new_value": "..."}
]
dependency_corrections = [
  {"missing_dep": "P1-A1-WP2", "reason": "Uses the auth token cache defined there"}
]
wp_proposal_adjustments = [
  {"wp_id_suffix": "WP1", "action": "remove", "reason": "Duplicate of P1-A1-WP3 which owns users.py"}
]
```

### Step 4: Validate L0 responses

For each L0 response:
- `assignment_id` must be present and match the expected assignment ID for that L0
- `changes` must be a valid JSON array (may be empty `[]`)
- `dependency_corrections` must be a valid JSON array (may be empty `[]`)
- `wp_proposal_adjustments` must be a valid JSON array (may be empty `[]`)

On `assignment_id` mismatch (field present but does not match expected ID):
```
WARNING: L0 response assignment_id mismatch — expected {expected}, got {actual} — skipping
```

On other validation failure (field absent or array invalid):
```
WARNING: L0 response for {assignment_id} failed validation — skipping
```

On L0 subagent complete failure (no response / timeout):
```
CRITICAL: L0 for {assignment_id} failed — proceeding with N-1 suggestions
```

### Step 5: Resolve WP proposal conflicts

Collect all `wp_proposal_adjustments` from validated L0 responses. Group by the
set of files each WP proposal covers (use `estimated_files` from the elaborated WP).
When two assignments both claim a file set: assign ownership to the assignment with
the numerically earlier `assignment_id` using natural sort on numeric suffixes
(e.g. `P1-A1` beats `P1-A2`; `P1-A2` beats `P1-A10`).
Log each resolution:
```
WP CONFLICT: {assignment_id_A} vs {assignment_id_B} — {field} assigned to {winner}
```
Apply the `remove` action from the losing assignment's `wp_proposal_adjustments`.

### Step 6: Apply changes

Apply all validated `changes` to the in-memory assignments document, in assignment
ID order. Apply conflict resolutions before applying changes for affected assignments.
Skip unrecognized field names:
```
WARNING: Unrecognized field '{field}' in changes for {assignment_id} — skipping
```
Apply `dependency_corrections` by appending to the `dependency_notes` field.

### Step 7: Write output

Write the phase result file to `$3/refine_contexts/{phase_id}_result.json`, where
`phase_id` is read from the context file. The output schema:
```json
{
  "schema_version": 1,
  "assignments": [...]
}
```
The `assignments` list contains only this phase's assignments (3–5 entries) with refinements applied.

### Step 8: Emit output token

```
phase_refined_path = <absolute path to $3/refine_contexts/{phase_id}_result.json>
```

