select
Select
Intent
Pick a task source, refine it into dependency-aware atomic tasks, schedule parallel waves when safe, and emit an orchestration plan.
This skill is plan-only:
- It does not implement changes (no code edits; no running workers).
- It does not mutate the task source (no
SLICES.mdwrites, noplan-N.mdwrites); instead it emits explicit manual writeback steps when needed (e.g., "mark as in_progress"). - It is orchestration-agnostic: the output is a neutral plan schema (not tied to a specific executor).
It may also emit a small pipeline for driving planning artifacts into execution (manual steps; optionally loopable).
Swarm-ready planning
$select is optimized for parallel multi-agent execution, so it prefers plans that are explicit, decomposed, and lock-safe.
- Explore the codebase (read-only) when needed to ground tasks in real paths/components and to set tight
scopelocks. - Ask clarifying questions when multiple reasonable approaches exist; include a recommended default.
- Atomic tasks: each task should be independently executable by a single worker.
- Workstream shaping: identify major workstreams first, then map atomic tasks into those workstreams.
- Role-aware shaping: use role labels when useful (
contract,implementation,integration,checkpoint) to improve sequencing and review quality. - Explicit dependencies: prefer explicit edges over relying on implicit serialization via overlapping
scope. - Delegation metadata: include
scope(required for safe parallelism), pluslocationandvalidationwhenever possible. - Unit scope quality: mark scope as invalid when missing/unknown/overly broad; invalid scope units are not parallel-eligible.
- First-ready claim quality: when emitting
waves[0], include the full safe first wave only after dependency and scope checks pass. - Review before yielding: run a separate reviewer-mode pass for missing deps/order/lock overlaps/validation gaps.
Decomposition heuristics (parallelism quality)
When the selected source is coarse or linear, refine task structure before scheduling waves:
- Identify workstreams and keep task descriptions scoped to one workstream where possible.
- Create explicit
contracttasks for API/schema/interface/config decisions that unblock multiple downstream tasks. - Create explicit
checkpoint/integrationtasks as join points after parallel branches. - Keep medium granularity: each task should be independently PR-able.
- Prefer explicit dependency edges to document true prerequisites and avoid accidental serialization.
Dependency semantics (hard vs soft)
Use two dependency channels with distinct meaning:
depends_on: hard prerequisite; contributes to DAG readiness and wave scheduling.related_to: soft ordering/context edge; never gates readiness or wave eligibility.
If ordering is uncertain or advisory ("nice first", "reduces rework"), prefer related_to over depends_on.
Invocation directives (optional)
If present, interpret these directives from the invocation text:
mode:both|triage|newboth(default): triagein_progressfirst; then select new work.triage: only triagein_progressand recommend close/reopen/continue.new: skip triage and select new work (still warn aboutin_progress).
max_tasks:auto|<int>- If omitted: default
auto. - For
slices,automeans: keep any carried-forwardin_progresstask and add every additional dependency-independent task that safely fits inwaves[0]; it may still resolve to1when scope or dependencies only permit one task. - Applies after triage decisions.
- If omitted: default
review:required|auto|offrequired(default): run a reviewer pass and iterate until it passes (or stop+ask if blocked).auto: run one reviewer pass; fix what you can; proceed with remaining warnings.off: skip the reviewer pass.
Source precedence
When multiple sources exist, pick exactly one using this precedence:
- Explicit user-provided task list in the invocation text.
SLICES.md(if present and parseable).plan-N.md(highest N, repo root).
If the highest-precedence source exists but has no viable tasks, do not default to an empty plan.
- First try to select an unblocker (a blocked leaf task that would unlock future ready work).
- Only stop+ask about falling back if the source is empty/unparseable, or if everything is closed/unschedulable.
Source detection + preflight (how)
Detect sources without mutating them:
- Invocation task list:
- A numbered/bulleted list that follows an explicit phrase like "Use $select" / "$select:".
- If present, treat it as the source and do not look elsewhere.
SLICES.md:- Exists at repo root (
SLICES.md). - Parseable (each slice section contains exactly one YAML mapping).
- Exists at repo root (
plan-N.md:- Find files matching
plan-(\d+).mdin the repo root and pick the highestN.
- Find files matching
Preflight (best-effort):
- For the chosen source, collect candidate tasks + dependency edges.
- If a dependency refers to an unknown task ID, treat the referencing task as blocked; warn only after auto-remediation fails.
- If the dependency graph is cyclic/unschedulable, schedule any work outside the cycle (if possible) and emit a warning.
- If the source is present but unparseable/empty, stop and ask before falling back.
Warning auto-remediation (read-only)
Before emitting warnings, attempt safe, deterministic fixes that do not mutate sources.
Order (stop when resolved):
- ID normalization + aliasing:
- Canonicalize ids/depends_on/related_to (trim, lowercase, drop leading
#). - If a
depends_onis unknown, try to map it to a unique known id via a numeric suffix alias (e.g.,1->t-1,sl-1) or an exact canonical match. - If resolved, replace the dep with the canonical id and suppress the unknown-dep warning.
- Canonicalize ids/depends_on/related_to (trim, lowercase, drop leading
- Scope normalization (safe):
- Normalize each
scopeentry: trim whitespace; drop a leading./(normalize./to.); collapse repeated/; remove a trailing/(except/). - Record as
auto_fix: scope_normalizeif any scope entry changed.
- Normalize each
- Scope inference (conservative):
- If
scopeis missing, scanlocation,verification,id,title,description, andsubtasksfor explicit path or glob tokens (contain/,**, or a file extension). - Only adopt tokens that are existing paths or obvious globs; prefer file or module globs over directory roots, and keep the narrowest non-overlapping set that still makes ownership explicit.
- If inferred, set
scopeand suppress the missing-scope warning.
- If
- Orchestrator downgrade:
- If
agent: orchestratorlackssubtasks, downgrade toworker. - This is a semantic change; still emit a warning even after the fix.
- If
Record auto-fixes in the Decision Trace (auto_fix) and keep warnings for unresolved issues.
Source adapters (read one; do not improvise)
After you choose the source kind, read and apply exactly one adapter spec:
- list:
codex/skills/select/ADAPTER_LIST.md - slices:
codex/skills/select/ADAPTER_SLICES.md - plan:
codex/skills/select/ADAPTER_PLAN.md
Regression fixtures live in codex/skills/select/FIXTURES.md.
Parallelism rules (safety-first)
Parallelism is only scheduled when tasks provide enough metadata to make it defensible.
- The canonical lock-root contract lives in
codex/skills/select/references/lock-roots.md. - A task is eligible for parallel waves only if it has a non-empty
scopelist. - Two tasks may share a wave only if their
scopesets do not overlap.- Treat
scopeentries as exclusive locks. - Recommended lock style: tight file or module globs; use directory roots only when finer locks are unavailable.
- Conservative overlap check: compare lock roots, not raw strings.
- For each
scopeentry: normalize it (drop leading./; collapse/), drop a trailing/**or/**/*, then take the prefix up to the first glob metachar (*,?,[). - Treat overlap if any lock root is equal OR one lock root is a path-prefix of another.
- For each
- Treat
- Tasks missing
scopeare treated as overlapping everything and therefore scheduled alone.- Warn
missing_scopeonly when it affects this plan's wave packing. - Hint: add a narrow
scopelist (paths/globs) to unlock parallel waves.
- Warn
- Tasks with overly-broad
scopeare treated as overlapping everything and therefore scheduled alone.- Broad examples:
"",.,./,/,*,**,**/*. - Warn
broad_scopeonly when it affects this plan's wave packing.
- Broad examples:
- If tasks must be serialized due to overlapping lock roots, prefer an explicit
depends_onedge to make the order intentional.- Warn
implicit_orderonly when lock roots are nested (strict prefix), the tasks are otherwise dependency-independent (no DAG path), and the order was chosen by tie-breaks/stable order.
- Warn
Delegation readiness (recommended)
Parallel waves are only useful if each task is independently executable by a worker.
- Prefer tasks that include:
location: where to work (paths/globs; navigation only; does not affect scheduling)validation: how to prove done (commands/checks; does not affect scheduling)
- If emitting any wave with 2+ tasks and that wave contains at least one task with
validation, warnmissing_validationfor tasks in that wave that lackvalidation.
Claiming selected work (required)
When $select selects work to start now (i.e., the tasks in the first scheduled wave waves[0]), it must also emit a claim so other planners/executors do not pick the same work concurrently.
- If the chosen source supports status, the claim is: set the selected tasks to an in-progress status using the source's spelling.
- Canonical token:
in_progress - Accept common variants as equivalent when reading/triaging:
in progress,in-progress,in_progress - When emitting a claim, prefer the token already used by the source; otherwise default to
in_progress.
- Canonical token:
- If the source is
listorplan, emitclaim: none. - If the resulting OrchPlan will feed durable execution, the follow-through path is
st import-orchplanthenst claimbefore anyspawn_agentor$meshrun.
This is still plan-only: $select does not perform the writeback; it spells out what to change.
Orchestration-of-orchestration
Tasks may be delegated to an agent: orchestrator only when the user provided subtasks.
If agent: orchestrator is set but subtasks is empty/missing, downgrade to agent: worker, record an auto-fix, and warn.
Output: OrchPlan v1
Emit one YAML block with the canonical plan.
Schema (YAML; best-effort, omit unknown keys):
schema_version: 1
kind: OrchPlan
created_at: "<rfc3339>"
source:
kind: list|slices|plan
locator: "<freeform; e.g. 'invocation', 'SLICES.md', 'plan-3.md'>"
# Optional. If omitted, treat as "auto" (unbounded by cap; waves are dependency/lock driven).
cap: auto
# Optional. Human/worker context only (does not affect scheduling).
prereqs: []
risks: []
tasks:
- id: t-1
title: "..."
description: "..." # optional
workstream: "..." # optional
role: contract|implementation|integration|checkpoint # optional
parallelism_impact: "unlocks <n> tasks" # optional best-effort
agent: worker|orchestrator
scope: ["path/**"]
location: ["path/file"] # optional
validation: ["..."] # optional
depends_on: []
related_to: [] # optional non-gating links
subtasks: []
waves:
- id: w1
tasks: [t-1, t-2]
- id: w2
tasks: [t-3]
integration:
boundary: patch-first
order: [t-1, t-2, t-3]
conflict_policy: rebase-author
warnings:
- "..."
Decision Trace (required)
After the OrchPlan YAML, emit a short plaintext trace (tight and structured):
source: chosen source kind + locatormode: resolvedmode+ resolvedmax_taskstriage: if anyin_progresswas seen, state:continue <id>ORrecommend close <id>ORrecommend reopen <id>ORnoneclaim:mark <in_progress token> <id,...>ORalready <in_progress token> <id>ORnonecounts: totals for the chosen source (at minimum: leaf, ready, blocked, in_progress)fanout_possible: number of dependency-independent tasks that could safely fit inwaves[0]after scope checksfanout_selected: number of tasks actually placed intowaves[0]fanout_left_on_table:fanout_possible - fanout_selectedpick: selected task id + 3-10 word reasonnext2: next two candidates (ornone) + 3-10 word reason eachwaves: (recommended when tasks were scheduled)N+ a compact wave listing (e.g.w1[t-1,t-2]; w2[t-3])review:pass|warn|skipped|blocked+ 0-6 word notewarnings: list count + top 1-3 keys (e.g.unknown_deps,status_drift,cycle,broad_scope,implicit_order,underfilled_wave,missing_validation,linear_graph,missing_role,missing_checkpoint)auto_fix: list count + top 1-3 keys (e.g.dep_alias,scope_normalize,scope_infer)
Procedure (high-level)
- Resolve invocation directives (mode/max_tasks/cap).
- Source detection (pick exactly one; do not merge sources).
- Read the corresponding adapter spec (above) and extract tasks.
- If tasks are too coarse or missing metadata required for safe parallelism, refine them:
- Decompose into atomic tasks with explicit
depends_on. - Identify workstreams and annotate
workstreamwhere useful. - Insert
contracttasks when they can unlock parallel implementation branches. - Insert
checkpoint/integrationtasks as explicit join points across branches. - Encode soft ordering/context in
related_toinstead ofdepends_on. - Populate
scopelocks (tight paths/globs), pluslocationandvalidationwhere possible. - Keep each task independently PR-able (medium granularity).
- Explore the repo (read-only) and consult authoritative docs when needed.
- Stop and ask targeted questions if blocked by ambiguity.
- Decompose into atomic tasks with explicit
- Normalize tasks: ensure
id; apply orchestrator rule; treat unknown deps as blocked (pending auto-remediation). - Run warning auto-remediation (above); finalize warnings.
- Schedule waves using
depends_on+scopelocks. 7.5. If selecting new work, computeclaimfromwaves[0]; for source-backed flows emit manual status writeback, and for durable execution handoffs keep the first-wave ids ready forst import-orchplan+st claim. - Reviewer pass (per
review): check deps/order/locks/validation/delegation gaps; revise as needed.- Detect unnecessary linear chains and downgrade advisory edges from
depends_ontorelated_towhen safe. - If
waves[0]leaves safe ready work unclaimed andmax_taskswas not explicitly capped, treat it as a planning defect and revise untilfanout_left_on_table=0or emit a blocking explanation. - Require explicit roles/workstreams in multi-wave plans when inference is feasible.
- Require checkpoint/integration joins when multiple parallel implementation branches converge.
- In reviewer mode: do not expand scope; do not redesign; only close gaps and reduce risk.
- If
review=required: iterate untilreview: passOR stop+ask if blocked.
- Detect unnecessary linear chains and downgrade advisory edges from
- Emit OrchPlan v1 YAML (always) + Decision Trace (required). Add pipelines only when useful.
Scheduling algorithm (parallelism-first)
Build waves using dependency readiness and scope locks:
- Build a DAG from
depends_onedges only (related_tois non-gating and excluded from DAG readiness). - Maintain
ready= unscheduled tasks whose deps are all scheduled. - While tasks remain:
- Treat missing
scopeas overlapping everything (i.e. it can only be scheduled alone). - Treat overly-broad
scopelocks ("",.,./,/,*,**,**/*) as overlapping everything. - Pick a maximal subset of
readywhosescopelock roots do not overlap (greedy is fine). - When
capandmax_tasksareauto, keep the full maximal subset; do not trim to one task merely because the source isslices. - If
capis a number, limit the wave tocaptasks. - Remove scheduled tasks from the pool; proceed to next wave.
- Treat missing
When you must choose between conflicting tasks (overlapping scope or cap pressure), use scoring beyond priority:
- Risk/hardness/blast (if present): prefer lower risk, lower hardness, and smaller blast radius first.
- Priority (if present): 0/P0 first.
- Kind order (if present): task > bug > feature > chore > epic > docs > question.
- Parallelism impact (same risk tier): prefer
role=contract|checkpoint, thenintegration, thenimplementation. - Unlock count (same risk tier): prefer tasks that unblock more other tasks in this plan.
- Soft-order penalty: if a task has
related_toanother ready task, prefer the related-first ordering when it likely reduces rework. - Delegation readiness: prefer tighter
scopeand explicitvalidation. - Stable order: preserve the source order.
Emit warnings when unresolved (noise-controlled; warn only when it affects this OrchPlan):
missing_scope: a task missingscopeprevented adding at least one other ready task to the same wave.broad_scope: a task with overly-broadscopeprevented adding at least one other ready task to the same wave.implicit_order: two dependency-independent tasks had nested lock roots and were concurrently ready; order chosen by tie-breaks/stable order.missing_validation: a parallel wave mixed tasks with and withoutvalidation.unknown_deps: adepends_onpoints at an unknown ID.orchestrator_without_subtasks: a task declaredagent=orchestratorwithoutsubtasks.underfilled_wave:waves[0]left safe ready tasks unclaimed without an explicitmax_taskscap.linear_graph: the dependency graph is mostly chain-like and a safe split into workstreams/contracts/checkpoints appears possible.missing_role: multi-wave plan lacks role annotations where they are needed for reasoning/review.missing_checkpoint: multiple parallel implementation branches have no explicit integration/checkpoint join. If a warning is auto-remediated, omit it fromwarningsand list it underauto_fix(except orchestrator downgrade, which must still warn).
Examples (synthesized)
Example A: clean parallel wave (list source)
schema_version: 1
kind: OrchPlan
created_at: "2026-02-02T00:00:00Z"
source:
kind: list
locator: "invocation"
cap: auto
tasks:
- id: cfg
title: "Add config loader"
agent: worker
scope: ["src/config/**"]
location: ["src/config/loader.ts", "src/config/index.ts"]
validation: ["npm test -w config"]
depends_on: []
subtasks: []
- id: ui
title: "Update settings UI"
agent: worker
scope: ["src/ui/**"]
location: ["src/ui/Settings.tsx"]
validation: ["npm test -w ui"]
depends_on: []
subtasks: []
- id: wire
title: "Wire config into UI"
agent: worker
scope: ["src/app/**"]
location: ["src/app/bootstrap.ts"]
validation: ["npm test"]
depends_on: [cfg, ui]
subtasks: []
waves:
- id: w1
tasks: [cfg, ui]
- id: w2
tasks: [wire]
integration:
boundary: patch-first
order: [cfg, ui, wire]
conflict_policy: rebase-author
warnings: []
Decision Trace:
- source: list (invocation)
- mode: both; max_tasks=auto
- triage: none
- claim: none
- counts: leaf=3 ready=2 blocked=1 in_progress=0
- pick: cfg; unblocks wire; parallel-safe scope
- next2: ui; parallel-ready; disjoint scope
- waves: 2 w1[cfg,ui]; w2[wire]
- review: pass
- warnings: 0
- auto_fix: 0
Example B: parallel wave with mixed validation + broad scope
schema_version: 1
kind: OrchPlan
created_at: "2026-02-02T00:00:00Z"
source:
kind: list
locator: "invocation"
cap: auto
tasks:
- id: api
title: "Add /health endpoint"
agent: worker
scope: ["src/api/**"]
location: ["src/api/health.ts", "src/api/router.ts"]
validation: ["npm test -w api"]
depends_on: []
subtasks: []
- id: docs
title: "Document /health endpoint"
agent: worker
scope: ["docs/**"]
location: ["docs/api.md"]
depends_on: []
subtasks: []
- id: big
title: "Repo-wide rename OldName -> NewName"
agent: worker
scope: ["**"]
location: ["."]
validation: ["rg -n \"OldName\" . || true"]
depends_on: []
subtasks: []
waves:
- id: w1
tasks: [api, docs]
- id: w2
tasks: [big]
integration:
boundary: patch-first
order: [api, docs, big]
conflict_policy: rebase-author
warnings:
- "missing_validation: [docs]"
- "broad_scope: [big]"
Decision Trace:
- source: list (invocation)
- mode: both; max_tasks=auto
- triage: none
- claim: none
- counts: leaf=3 ready=3 blocked=0 in_progress=0
- pick: api; explicit validation; tight scope
- next2: docs; parallel-ready; missing validation
- waves: 2 w1[api,docs]; w2[big]
- review: warn missing_validation,broad_scope
- warnings: 2 missing_validation,broad_scope
- auto_fix: 0
Source adapters (extraction only)
Adapter specs live in:
codex/skills/select/ADAPTER_LIST.mdcodex/skills/select/ADAPTER_SLICES.mdcodex/skills/select/ADAPTER_PLAN.md
Pipelines
Pipelines live in codex/skills/select/PIPELINES.md.
Output
- Always emit OrchPlan v1 YAML, then Decision Trace.
- If no actionable source tasks exist, prefer selecting an unblocker; only then emit an empty plan + warnings.
- If the chosen source is empty/non-viable and a fallback source exists, stop and ask before falling back.