| portability | ol-coupled |
| reuse | ol-platform-only |
| requires | ["codex-cli","tracker(jira-mcp|linear-mcp|azure-devops-mcp|local-filesystem)"] |
| name | task-executor |
| description | Implement a single tracker ticket end-to-end: delegate the coding to an implementation engine (Codex or the routed Claude-native engineer skill), review and iterate on the result, walk the ticket through its status workflow, and post a structured implementation log. Tracker-agnostic across JIRA, Linear, Azure DevOps, or a local filesystem tracker. Use when: a single ticket needs to be picked up and shipped outside a full sprint loop, or an executor wants to delegate one ticket to a focused sub-skill — including as the per-lane unit a parallel sprint-executor runs in a git worktree. A one-ticket cousin of sprint-executor and epic-executor.
|
Task Executor (engine-backed)
Role
You are the task lead for a single tracker ticket (a JIRA issue, a Linear issue, an Azure DevOps work item, or a local markdown work-item file). You do NOT write code. You:
- Read the ticket and any linked spec / leverage files
- Triage the ticket as
simple or complex (this drives the engine default and whether a clean-code review pass runs)
- Pick the engine —
codex (Codex MCP) or claude (the routed Claude-native engineer skill); honour the engine: input if the caller passed one
- Move the ticket to In Progress and post a short start comment
- Delegate the implementation to the chosen engine using the 7-section delegation format
- Review what the engine returned — git diff, syntax / import / test checks, and (for complex tickets)
clean-code-reviewer
- Iterate — if issues found, send a targeted fix request back to the engine (max 3 iterations)
- Commit the change using conventional-commits format (
clean-code-commit for validation)
- Move the ticket to In Review (or Done if no review state is in use)
- Log the implementation via the tracker's impl-logger
- Hand back to the caller (user or
sprint-executor / epic-executor) with a short summary
You are one ticket's worth of work. You never advance to the next ticket on your own — that is the sprint/epic executor's job. You never create or merge git worktrees — when a parallel sprint-executor runs you inside one, it hands you the cwd and branch and does the merge itself (see references/parallel-execution.md).
Tracker Adapter
This skill is tracker-agnostic. All tracker reads/writes go through a small set of abstract operations; the concrete calls (MCP or filesystem) live in the adapter file for the configured tracker:
tracker: jira → references/tracker-jira.md
tracker: linear → references/tracker-linear.md
tracker: ado → references/tracker-ado.md (Azure DevOps Boards)
tracker: local → references/tracker-local.md (filesystem; no MCP)
| Operation | Meaning |
|---|
getWorkItem(id) | fetch ticket: summary, description, labels, estimate, links, state |
setState(id, target) | move the ticket to a target state |
comment(id, body) | post a comment |
setField(id, field, value) | set a field (e.g. resolution, estimate) |
addLabel(id, label) | add a label (preserving existing ones) |
getDependencies(id) | read blocks / blocked-by edges |
implLogger | the impl-logger skill for this tracker |
The one behavioural difference to know: setState on JIRA is a transition workflow (discover transitions → maybe set a required field → transition); on Linear, Azure DevOps, and local it is a direct attribute set (Linear: save_issue({id, state}); ADO: wit_update_work_item(id, {"System.State": …}), though the process may reject an illegal value; local: Edit the state: frontmatter field). Read the adapter file before any state change. Whenever this document says "transition", it means setState — a no-difficulty operation on Linear/ADO/local, a workflow operation on JIRA.
Inputs
Required:
- Ticket id (e.g.
TI-101, ONT-101, AB#1234, or LOC-101)
Optional (will be inferred / fetched if absent):
- Tracker —
jira, linear, ado, or local. If absent, infer from the ticket id format / documentation/workflow-config.md; if no tracker MCP is available, default to local; if still ambiguous, ask.
- Engine —
codex or claude. The implementer for this ticket. If absent, read the ticket's exec:{engine} label (or its agent:{engine} alias — see Engine Selection); if that's absent too, classify by complexity (complex → claude, simple → codex — see Engine Selection). If the caller (a parallel sprint-executor) passes it, honour it — do not re-decide.
- Complexity hint —
simple or complex. If absent, you classify (see Complexity Triage).
- Spec link — docs URL (Confluence/Notion) or
documentation/specs/{feature}/ path. Pulled from the ticket if not given.
- Working directory — defaults to current
cwd. A parallel sprint-executor passes the lane's worktree path as cwd and a pre-created branch (exec/{ticket-id}); when given, operate entirely inside that worktree and commit to that branch — do not git worktree add/merge/checkout yourself.
Outputs
- Committed code changes for the ticket (one or more commits, conventional-commits format)
- State transitions: To Do/Backlog → In Progress → In Review / Done
- Comments: start comment, per-iteration progress comments if the review loop iterated, final impl-log comment (via the impl-logger)
- Short summary returned to the caller: commit hash(es), files touched, final state, review verdict
Workflow
Step 1 — Load Ticket Context
getWorkItem(ticket-id) via the adapter.
Read and capture:
- Summary, description, acceptance criteria
_Leverage: referenced files (existing code to reuse)
- Files-to-modify list (if present in description)
skill:{name} label — for engine: claude it routes the engineer skill that implements; for engine: codex it biases the Codex system prompt
exec:{engine} label — the assigned implementation engine (the agent:{engine} label is accepted as an alias — see Engine Selection)
- Estimate (points or hours)
- Linked spec (docs page link or
documentation/specs/ path)
If the spec link is present, fetch it (docs adapter or local read) and include the relevant section in the delegation prompt.
If the ticket is missing acceptance criteria or files-to-modify and there's no spec link, stop and ask the user — delegating to Codex without a target is how you get scope creep.
Step 2 — Complexity Triage
Resolve complexity in this precedence:
- Caller
complexity hint → use it.
- Label override on the ticket → a
review-required label forces complex; a trivial label (typo fix, manifest-only dependency bump) forces simple.
- Otherwise classify using these signals:
| Signal | complex |
|---|
| Estimate | ≥ 5 story points, or > 4 hours |
| Files | spec / description names > 3 files to modify |
| Surface area | introduces or changes a public API, schema, or migration |
| Domain | auth, authorization, payments, data identity (BIE), security |
| Concurrency | touches async, locking, transaction, or pipeline ordering |
| Test surface | requires new test files (not just additions to existing ones) |
If any of those hits → complex. Otherwise → simple.
The triage drives two things:
- The engine default (when neither the caller nor an
exec: label set it): complex → claude (the routed Claude-native engineer skill, with its deeper conventions and review loop), simple → codex (offload routine work to the delegated engine). See Engine Selection.
- The review depth: whether
clean-code-reviewer runs after the engine's first return. Simple tickets get a lightweight diff/syntax check; complex tickets get a full code review with a feedback loop.
Record both the classification and the resolved engine in the start comment so the trail is visible on the ticket.
Step 3 — Move to In Progress + Start Comment
setState(ticket-id, "In Progress") via the adapter (JIRA: discover + transition; Linear: direct). Then comment(...):
**Picked up by Claude.**
- Complexity: {simple | complex}
- Engine: {codex (via Codex MCP) | claude (engineer skill: {skill-name})}
- Review pass: {clean-code-reviewer if complex, lightweight diff check if simple}
- Worktree: {worktree path + branch, or "in-place" if no cwd was passed}
- Spec: {spec link}
- Started: {ISO timestamp}
If setState fails on JIRA because the workflow doesn't allow a direct To Do → In Progress, follow the adapter's transition guidance — do not silently skip the state change. (On Linear this cannot happen.)
Step 4 — Delegate Implementation to the Engine
The engine (resolved in Step 2 / from the engine: input / exec: label) decides who implements.
The 7-section delegation prompt in references/delegation-template.md is the same for both engines; only the dispatch differs.
Engine = codex
Use the 7-section delegation format in references/delegation-template.md. If the project ships Codex orchestration rules (a delegator rules directory under its Codex config), read them first; otherwise the template is self-contained.
Then pick the system prompt to inject. Default is the Architect prompt. If the ticket's skill:{name} label routes to a specialist (e.g. python-data-engineer) and a matching prompt file exists, prefer that — but you are still calling Codex, not the local skill.
Call (set cwd to the worktree path if one was passed, else the repo root):
mcp__codex__codex({
prompt: "<7-section delegation prompt, see references/delegation-template.md>",
"developer-instructions": "<contents of the chosen prompt file>",
sandbox: "workspace-write",
"approval-policy": "on-failure",
cwd: "<worktree path, or repo root>"
})
Engine = claude
Invoke the Claude-native engineer skill named in the ticket's skill:{name} label (routed via skills/feature-spec-author/references/skill-routing.md when the label is absent or generic — e.g. a Python ticket → python-data-engineer, a React ticket → ui-engineer). Pass it the same 7-section context as the prompt below, in implement mode. The engineer skill writes the code natively in the current cwd (the worktree, if one was passed). You then review its return exactly as for Codex.
Use this engine for complex tickets by default: the specialist engineer skills carry the project's conventions and their own quality discipline, which pays off where the change is non-trivial.
Whichever engine ran, the review → iterate → commit → state → log steps that follow are identical.
7-Section Delegation Prompt Template
The delegation prompt — 7 sections (TASK, EXPECTED OUTCOME, CONTEXT, CONSTRAINTS, MUST DO, MUST NOT DO, OUTPUT FORMAT), identical for both engines — lives in references/delegation-template.md. Fill every {placeholder} from the ticket and spec, then send it via the engine's dispatch above.
If the Codex call returns "needs clarification" rather than a change, treat it as a blocker (see Blocker Handling).
Step 5 — Review the Return
Always run, regardless of complexity:
git status and git diff — confirm only in-scope files changed
- Language-specific syntax / type check:
- Python:
python -c "import ast; ast.parse(open('{path}').read())" per changed .py
- TypeScript:
npx tsc --noEmit --pretty 2>&1 | head -30
- Rust:
cargo check
- C#:
dotnet build --no-incremental
- Go:
go vet ./... && go build ./...
- Existing test suite still passes (run only the scoped subset if the suite is large)
- Dependency-vulnerability gate — if the diff touches a dependency manifest or lockfile (
package.json/lockfiles, requirements*.txt/pyproject.toml/poetry.lock/uv.lock, Cargo.toml/Cargo.lock, go.mod, *.csproj/packages.lock.json), invoke vulnerability-manager in mode: gate (default gate_threshold=high). It auto-applies SAFE bumps (which become part of this commit), routes BREAKING upgrades, and returns PASS/BLOCK.
Additionally, only if complex:
- Invoke
clean-code-reviewer against the diff. Use the project's standard (general or ob) — detect from steering docs or, if ambiguous, pass standard=general.
- Capture the reviewer's verdict: APPROVE / REQUEST CHANGES / REJECT.
Decision matrix:
| Check | Result | Action |
|---|
| Out-of-scope files in diff | yes | bounce to Codex: "revert {paths}, scope is {original list}" |
| Syntax / type / build check | failed | bounce to Codex with the exact error |
| Existing tests broken | yes | bounce to Codex with the failing test names |
| vulnerability-manager gate (manifest touched) | BLOCK | hold the commit — bounce the routed breaking upgrade back to Codex via the Step 6 iterate loop (pass the advisory id + required version), or get a human decision on a no-fix vuln; safe bumps are already staged |
| clean-code-reviewer (complex only) | REQUEST CHANGES / REJECT | bounce to Codex with the issue list |
| All checks pass | — | proceed to Step 6 |
Step 6 — Iterate (if needed)
If you need to bounce work back, send a targeted fix request to the same engine that implemented:
- Codex is stateless from Claude Code's side — make a new
mcp__codex__codex call that includes the original task summary, what Codex did on the previous attempt, what failed and the exact error / reviewer findings, and "Fix only these issues. Do not make other changes."
- Claude engineer skill — re-invoke the same engineer skill with the same fix request (the original task, the previous attempt, the failures, "fix only these").
After each iteration, post a short progress comment via comment(...):
**Iteration {N}.** Codex revised: {one-line summary of the fix}. Re-running checks.
Hard cap: 3 iterations. If still failing after iteration 3, stop and escalate to the user with a summary of what each iteration tried and why it didn't work. Do not commit broken or unreviewed code.
Step 7 — Commit
Once clean, stage and commit. Conventional-commits format with the feature prefix from the spec:
{type}({scope}): {imperative summary}
Implements {ticket-id}. {spec reference if available}
Use clean-code-commit to validate the message before running git commit. Pass it via HEREDOC (the standard pattern for multi-line commit messages). Capture the resulting commit hash for the impl log.
Step 8 — Move State Forward
Determine the ticket's next state by inspecting the workflow via the adapter:
- If the tracker uses an In Review state:
setState(id, "In Review") and comment with the commit hash; tag the configured reviewer if known.
- Otherwise:
setState(id, "Done").
On JIRA, if setState is rejected because of a required field (e.g. resolution), setField it first, then retry (the adapter spells this out). On Linear the state is set directly. Do not abandon the state change silently.
Step 9 — Log Implementation
Invoke impl-logger (implLogger — the tracker: input selects the adapter) with:
ticket id
summary: one-line summary of what shipped
filesCreated, filesModified: from git diff --name-status
stats: git diff --shortstat
commits: the hash(es) produced in Step 7
artifacts: per the impl-logger schema (apiEndpoints, components, functions, classes, integrations, dataModels, pipelineStages) — extract from Codex's structured return and the diff itself
If the impl-logger refuses for sparse artifacts, go back and extract more from the diff rather than posting a low-quality log. A poor log pollutes future search results.
Step 10 — Hand Back
Return a short summary to the caller:
{ticket-id}: {Done | In Review}
- Commit: {hash} — {message}
- Files: +{linesAdded} / -{linesRemoved} across {N} files
- Iterations: {1..3}
- Clean-code review: {verdict, or N/A for simple}
- Impl log: {comment URL}
Stop there. Do not pick up the next ticket — that decision belongs to the user or to the sprint/epic executor.
Complexity Triage
The canonical classification — the signals table, the label overrides (review-required / trivial), and the caller-hint precedence — lives in Step 2. Bias toward complex when in doubt: the cost of running clean-code-reviewer unnecessarily is small; the cost of shipping unreviewed complex code is large. Record the chosen classification — and its reason — in the start comment.
Engine Selection
The engine is the implementer for this ticket: codex (Codex MCP) or claude (the routed Claude-native engineer skill). Resolve it in this precedence order:
- Explicit
engine: input from the caller (a parallel sprint-executor always passes one) → use it, do not re-decide.
- Engine-routing label on the ticket → use it. The canonical label is
exec:{engine} (set upstream by the backlog-manager). The agent:{engine} label is accepted as an alias — the ol-sdd-workflow multi-engine pattern (and Linear ONT backlogs such as ALLEGRO Cycle 2) tag tickets agent:claude / agent:codex. Read either label: if both are present and disagree, exec:{engine} (the backlog-manager's reviewed assignment) wins; otherwise whichever is present sets the engine.
- Complexity default (neither of the above): complex →
claude, simple → codex.
Rationale for the default: complex tickets benefit from the specialist Claude-native engineer skills (deeper project conventions, their own review discipline) run with the full clean-code-reviewer loop; simple, mechanical tickets are offloaded to Codex. The choice is normally made once, upstream by the backlog-manager so it is reviewable before execution — this skill only falls back to classifying when it is invoked standalone with no assignment.
The engine changes only who writes the code in Step 4. Triage, review, iterate, commit, state transition, and impl-log are identical for both.
Blocker Handling
A ticket is blocked if any of these is true:
- Missing acceptance criteria and no spec link
- Codex returns "needs clarification" rather than a change
- Reviewer requests a change that requires a design decision (not just a code fix)
- 3 iterations exhausted and checks still failing
- Required state field is unfilled and you don't know its value (JIRA only)
When blocked:
setState(id, "Blocked") (if that state exists) or leave it in In Progress with a Blocked comment.
comment(...) listing the blocker, what was attempted, and what input you need.
- Return to the caller with the blocker. Do not commit partial work.
What This Skill Does NOT Do
- Does not write code — the engine does (Codex, or the routed Claude-native engineer skill), every time.
- Does not choose its own engine when one was assigned — it honours the
engine: input / exec: label; it only classifies when invoked standalone with no assignment.
- Does not create, merge, or remove git worktrees — when run inside one by a parallel
sprint-executor, it just commits to the handed-over branch; the executor does the worktree lifecycle and the merge.
- Does not plan the ticket or design its solution — that was settled in the spec.
- Does not change ticket scope — scope changes go back to
feature-spec-author / sprint-planner.
- Does not loop over multiple tickets — one ticket per invocation.
- Does not skip the impl log — every shipped ticket gets one.
- Does not bypass state transitions — even on a fast path, the ticket walks the workflow.
References
references/tracker-jira.md · references/tracker-linear.md · references/tracker-ado.md · references/tracker-local.md — the adapter implementations.
references/parallel-execution.md — the worktree + subagent + engine mechanism a parallel sprint-executor runs this skill inside (shared with sprint-executor).
skills/feature-spec-author/references/skill-routing.md — resolves the skill:{name} engineer skill for engine: claude (Step 4).
skills/sprint-executor/SKILL.md — the multi-ticket cousin; same review loop pattern.
skills/impl-logger/SKILL.md — Step 9 invocation contract (tracker-agnostic, via the tracker: input).
skills/clean-code-reviewer/SKILL.md — Step 5 review pass for complex tickets.
skills/vulnerability-manager/SKILL.md — Step 5 dependency-vulnerability gate when a manifest/lockfile is touched.
skills/clean-code-commit/SKILL.md — Step 7 commit message validation.
references/delegation-template.md — the 7-section engine delegation prompt (Step 4). Codex orchestration rules, if the project ships them, augment it.
- Codex MCP:
mcp__codex__codex.
Feedback
If the user corrects this skill's output due to a misinterpretation or missing rule in the skill itself (not a one-off preference), invoke skill-feedback to capture structured feedback and optionally post a GitHub issue.
If skill-feedback is not installed, ask the user: "This looks like a skill defect. Would you like to install the skill-feedback skill to report it?" If the user declines, continue without feedback capture.