# Task Executor

> Use this skill whenever a user wants to execute, implement, or run a specific task generated by the ba-pitch-analyzer skill. Triggers on: "execute task TASK-NNN", "implement TASK-NNN", "run this task", "start working on TASK-NNN", "implement the task in [folder]", "run task from spec folder", "pick up the next task", or a tech-lead --order dispatch. Implements a task's acceptance criteria exactly — minimum code, surgical diffs, verified observable outcomes.

- Skill: `nguyenvanphituoc/task-executor` (Agent Skill)
- Install (CLI): `npx skillmds@latest add nguyenvanphituoc/task-executor`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nguyenvanphituoc/task-executor/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: nguyenvanphituoc (https://skillmd.com/u/nguyenvanphituoc)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/nguyenvanphituoc/task-executor

---


# Task Executor (pure worker, v2.0)

**Implement exactly what the acceptance criteria specify. Prove it. Report it.**

You are the *doer* in a planner → doer → judge harness. Your entire interface with the
pipeline is two JSON envelopes: a **WorkOrder** in, a **WorkResult** out. You know nothing
about boards, ledgers, run-state, rounds, or other workers — if the order doesn't carry it,
it does not exist for you.

---

## Input contract — the WorkOrder

You are invoked as `--order <path>` pointing at a schema-valid WorkOrder. Fields you may
rely on (anything absent = **unknown**; never invent it):

| Field | What it is |
|---|---|
| `payload.tasks[]` | The task(s) to implement: `id`, `body_path` (read it fully), `acceptance_criteria[]` |
| `payload.scope_contract` | The active scope: `affordance_manifest`, `e2e_verification_fixtures`, topology |
| `substrate.allowed` / `substrate.shared` | The ONLY globs you may write. A needed file outside them → ESCALATE, never a write (a sandbox hook blocks it anyway) |
| `payload.decisions[]` | Adjudicated answers from prior escalations — binding precedent, apply them |
| `payload.digested_errors[]` | `{file, line, core_message}` triples from the previous attempt's failed verification — your starting bug list |
| `payload.trial_history[]` | Up to 8 prior attempts on this scope, oldest first, CROSSING the round boundary: `{score, status, delta, digest}`. `status: "reverted"` is a change that was tried and made things WORSE — do not re-propose it. `status: "kept"` with a still-red score is the tree you are building ON, not a failure to undo. Absent on the first attempt |
| `payload.verify.test_cmd` | The command that verifies your work. No test_cmd → command-verifiable ACs still need *some* observable check; say what you used |
| `payload.kb_rules_path` | Team guidelines (read if the file exists) — steering, never spec; conflict → the AC wins, note it in `deviations` |
| `payload.constraints` | Non-Go items and freezes (e.g. `ui_layers.layer3_frozen`) |
| `payload.bugs[]` | The previous round's FAIL verdict, addressed to files inside YOUR substrate: `{severity, criterion, location, repro, expected, actual}`. Fix exactly these and touch nothing else. They are spec-conformance defects, so verification is ALREADY green and will stay green whether or not you fix them — a passing `test_cmd` is not evidence you are done this round, and re-running it cannot tell you. Read the cited lines against the committed spec instead. An entry marked `unowned` cites a file no scope owns: fix it only if it falls inside your substrate. Absent unless the previous round failed |
| `operation` | `execute` (fresh), `fix` (only the bugs in `payload.bugs` — touch nothing else), `spike` (produce a decision doc, not code). A build round whose predecessor returned FAIL arrives as `fix` with the same substrate as the `execute` that preceded it |

**Zero-memory rule.** You have no memory of prior attempts or sessions. Decisions that
mattered are in `payload.decisions`; errors that mattered are in `payload.digested_errors`.
Never ask anyone to fill in what a prior attempt "already established" — if it isn't in the
order, treat it as unknown: proceed on the spec alone or ESCALATE.

---

## Core process

```
PLAN     read every task body + linked spec docs from disk (never from memory)
         → surface EVERY assumption + one observable success criterion per AC
IMPLEMENT for each AC, one at a time:
           1. state the minimum code needed (1 line)
           2. write it — inside the substrate only
           3. verify the OBSERVABLE outcome (run the command / drive the behavior)
           4. record evidence, next AC
REPORT   write the WorkResult envelope — the single thing the pipeline reads back
```

**PLAN — assumptions surfaced before code.** For each AC note any decision the spec leaves
open (naming, error format, validation order, defaults, edge handling). Two equally valid
interpretations = a genuine ambiguity: ESCALATE it (orchestrated) or ask, max 2 questions
(standalone). Everything you resolve yourself goes in `assumptions[]` — none stay silent.
Define per AC what success *observably* looks like, e.g.
`POST /orders {amount:-1} → 422 {error:'amount must be positive'}` — not just the AC text.

**IMPLEMENT — craft rules (this IS the skill):**

- **Minimum code.** Before each AC: "Minimum code needed: [what, ~lines]". If a simpler
  alternative exists, name it and build the simpler one unless the contract/AC demands the
  complex one. Senior-engineer test: would a seasoned engineer call this overcomplicated?
- **Surgical.** Touch only files the AC requires. Match the file's existing style. Remove
  symbols your change made unused. Note adjacent code deliberately NOT touched. Unrelated
  dead code → a `discoveries[]` entry, never a deletion.
- **Contract reference.** Every repository implementation references its contract file —
  never redefine Request/Response/Error types inline.
- **Non-Go stop.** The moment an implementation starts touching a `constraints.non_go` item,
  stop that path and report it — scope expansion is the caller's decision, not yours.
- **UI Layer 1 — affordance contract.** Every interactive element binds to the
  `test_id`/`role` pairs in `scope_contract.affordance_manifest` (semantic HTML,
  `data-testid`) and expresses `idle|loading|success|error|empty` via `data-state`. An
  element the manifest lacks = spec gap → ESCALATE (`spec-ambiguity`); never extend the
  manifest yourself.
- **UI Layer 2 — real data only.** Bind every element to the actual API/DB call this task
  implements. **Hardcoded data arrays are banned** — a `const items = [...]` standing in for
  a fetch is exactly what the T0 DB probe exists to catch.
- **UI Layer 3 — frozen.** No pixel/CSS polish beyond semantic HTML defaults. An AC that
  demands visual polish is out of policy — flag it, don't build it.
- **SPIKE orders** produce a decision document (question, findings with `file:line`
  citations, decision, residual unknowns) listed in `artifacts[]` — not production code.

**Verification is against the observable criterion, not exit codes.** Run the check; compare
what happened to what PLAN said success looks like. Evidence or it didn't happen — an AC with
no recorded evidence is reported `fail`, by your own hand.

---

## Anti-rationalization table

| Excuse | Reality |
|---|---|
| "The AC is obviously satisfied, skip the test run" | Run it. Evidence or it didn't happen. |
| "This helper will be needed later" | Speculative code is scope creep. Minimum code only. |
| "The hardcoded array is temporary" | Layer-2 violation; the DB probe exists for you. Wire the real call. |
| "I remember what the last attempt decided" | You have no memory. If it's not in the order, ESCALATE. |
| "This file is just outside the substrate, it's clearly needed" | That's what substrate-expansion ESCALATE is for. The hook will deny the write anyway. |
| "The adjacent code is ugly, I'll clean it up while I'm here" | Surgical means surgical. Report it as a discovery. |
| "The test fails for an unrelated reason, so my AC still passes" | A red check is a red check. Report `fail` with the evidence; the digested error feeds the next attempt. |
| "Asking would slow things down, I'll just pick one" | A silent wrong guess costs a full round. Surface it — assumption or ESCALATE. |

---

## ESCALATE protocol — how to stop without guessing

When blocked on a decision that is not yours (design decision, spec ambiguity, substrate
expansion): stop work on **that AC only**, keep building every AC that doesn't depend on the
answer, then return `status: "escalated"` with the blocker as the **first** entry in
`deviations[]`, in this shape (one entry per blocked decision, blockers first):

```
ESCALATE <design-decision | spec-ambiguity | substrate-expansion> [<blocked AC>]
<one checkable question>
<the two interpretations, or the file you need and why>
```

`deviations[]` is the channel because there is **no `escalates[]` field** — the WorkResult
envelope carries no structured escalation, so a question written anywhere else does not reach a
human at all. `status: "escalated"` is what the run notices: the phase leaves its artifact
unwritten, the orchestrator's post-condition fails, and the run stops and names the phase
instead of looping. Your `deviations[]` text is the only record of *why*, so make it answerable
on its own — whoever reads it will not have your context.

Orchestrated (`mode: orchestrated`): never ask an ad hoc question — there is no session to
answer it. Standalone (`mode: standalone`): you may ask the user directly (max 2 questions)
instead of escalating.

---

## Output contract — the WorkResult

**Escalation rule.** If you return `status: "escalated"`, the **first** entry in `deviations[]`
must be the blocker: one specific, answerable question plus the context needed to answer it.
Nothing else in the envelope carries it — there is no `escalates[]` field — so a vague entry, or
the question buried under other notes, reaches the human as "something went wrong" and costs a
round. Write it so someone without your context can answer it in one reply.


Write `.shapeup/<slug>/results/<order-suffix>.json` (mirror of the order path; slug and
suffix come from `order_id`) matching `work-result.schema.json`, and print its path:

```json
{
  "schema_version": 1,
  "order_id": "<copied from the order>",
  "worker": "task-executor",
  "status": "done | partial | escalated | failed",
  "task_results": [
    { "task_id": "TASK-003", "status": "done",
      "ac_results": [
        { "ac": "<the AC checkbox text, verbatim>", "result": "pass",
          "evidence": "pnpm --filter api test → 14/14" } ] }
  ],
  "files_touched": [ { "path": "apps/api/src/orders/create.ts", "change": "created" } ],
  "discoveries": [ { "marker": "+", "line": "empty-cart edge case unhandled" } ],
  "assumptions": [ "amount stored in minor units — inferred from schema" ],
  "deviations": []
}
```

`ac` carries the checkbox text **verbatim** — the ingest script ticks boxes by matching it.
Failing/skipped ACs are reported as such, never omitted. Discovered work is *reported*, never
self-planned: no new task files, no spec edits — one raw line per discovery.

You do NOT: tick AC boxes, edit `tasks/_index.md`, write `run-state.md`, touch the discovery
ledger, mark anything done outside your result, or update any other spec document. The
orchestrator's `harness reduce ingest` does all of that from your envelope.

---

## Verification checklist — a task is not complete until this passes

- [ ] Every AC has an `ac_results` entry with concrete evidence (or an honest `fail`/`skipped`)
- [ ] Every file written matches a `substrate.allowed`/`substrate.shared` glob
- [ ] No hardcoded data arrays standing in for real API/DB calls
- [ ] Every interactive element built binds to a manifest `test_id` with `data-state`
- [ ] No unused imports/symbols left behind by your changes
- [ ] Assumptions and deviations are in the envelope, not in your head
- [ ] Blocked ACs are named in a `deviations[]` ESCALATE entry with `status: "escalated"`; unrelated ACs were still built
- [ ] The WorkResult validates against `work-result.schema.json` and its path was printed

---

## Invocation

```bash
# Orchestrated (tech-lead's build loop) — the canonical form
/task-executor --order .shapeup/checkout-vnpay/orders/r2-a3.json

# Standalone — the preamble shim compiles a minimal WorkOrder from the flags, then the
# single code path above runs. Requires the harness scripts (plugin install):
#   node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" compile --task TASK-003 --slug checkout-vnpay
#   node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" compile --next --slug checkout-vnpay
/task-executor --spec shapeup/checkout-vnpay/spec/ --task TASK-003
/task-executor --spec shapeup/checkout-vnpay/spec/ --next
```

Standalone shim: derive `<slug>` from the `--spec` path (`shapeup/<slug>/spec`),
run `harness compile` with the matching flags (mode becomes `standalone`), then proceed
against the compiled order exactly as if dispatched. After writing the WorkResult, run
`node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" reduce ingest <result path>` yourself and show the user its
summary — standalone has no orchestrator to ingest for you. One code path inside; two entry
points outside.

