---
name: execute-task
description: "Operator task loop for outstanding work. Activate when the operator asks 'what's outstanding', 'what's on my plate', 'what should I work on', 'pick something to do', or names a specific open Task to run. Drives the canonical selection → ground → delegate → relate → complete loop against the Project/Task ontology; routes execution to domain skills and writes every artefact back to the Task. Never creates new Tasks (that surface is `work-create` / `project-create`)."
---

# Execute task

Invoked from `specialists:project-manager`.

The operator-facing wrapper around the `work-*`, `project-*`, and `session-*` tools. Drives one Task from selection to closure with every artefact tied back to the graph. Five clauses are binding; the skill is a contract, not a recipe.

## When to activate

- "What's outstanding?" / "What's on my plate?" / "What's ready?"
- "Pick something to do" / "What should I work on next?"
- "Let's do <task name>" / "Run task <id>" / "Work on the <X> task"
- Any session-start moment where the operator has open work and no other skill has taken the turn.

Do **not** activate for:

- Creating a new Task or Project — that is `work-create` / `project-create`.
- Pure status questions ("how's the kitchen project going?") — answer from `project-get` directly.
- Specialist seats — this skill is admin-only.

## Outcome contract

### 1. Selection

`work-ready` filtered by the active `accountId` is the only entry point. If `work-ready` returns nothing, fall back to `work-list` for the same account; never broaden across accounts.

Group the candidate set under its parent `:Project` so the operator sees the work in context, not as a flat list. Surface enough metadata — id, title, priority, due date, blockers cleared — for the operator to pick.

**The operator picks.** Never infer or auto-select. If the operator declines to pick, the turn ends.

Emit `[work.execute] select { accountId, candidateIds:[...], pickedId:<id|null> }`.

### 2. Grounding

Once a Task is picked, load it and its one-hop graph context before doing anything:

- `work-get` for the Task itself (full notes, status history, priority, due date).
- Parent `:Project` (via `PART_OF` / `HAS_TASK`).
- Related `:KnowledgeDocument` nodes (briefs, reference material, prior outputs).
- Prior `:Conversation` nodes on this Task (so the run continues the operator's thread, not a blank slate).

If the picked Task's `accountId` does not match the session, refuse immediately and emit `[work.execute] refuse { reason: "cross-account" }`. Do not read the node body. Do not surface its title.

Execution starts from this graph context, not from task prose alone. If the grounding read returns nothing where the Task description references attachments or prior work, surface that gap to the operator before delegating — silent missing context is the failure mode.

Emit `[work.execute] ground { taskId, projectId, relatedDocs:[...], relatedConvs:[...] }`.

### 3. Delegation

Route execution to the appropriate domain skill. The Task body and graph context tell you which:

- Research / market read → `deep-research`.
- Email reply / draft / triage → `email-composition`.
- Document drafting, brochure, report → `professional-document`, `property-brochure`, etc.
- Vendor / supplier comms → `vendor-updates`.
- Data ingestion → `document-ingest` (or the matching `*-import` skill).
- Anything covered by an installed skill → use that skill.

Never reimplement a domain workflow inline. If no domain skill fits and the work is genuinely freeform, do it from the admin seat but say so explicitly in the run.

Emit `[work.execute] delegate { taskId, targetSkill, reason }`.

### 4. Write-back

Every artefact the delegated skill produces — `:KnowledgeDocument`, `:Email`, `:Document`, anything node-shaped — gets a `work-relate` edge to the Task before the turn ends. The edge type names the relationship (`AFFECTS`, `PRODUCES`, `OUTPUT_OF`, etc. per the ontology); a Task with delegated output and no edge is an orphan artefact and the failure mode this clause exists to prevent.

Progress is recorded via `work-update` (`appendStep`) at each meaningful action phase — once per phase, not per micro-step. Status transitions to `in_progress` on first action and `complete` on closure via `work-complete`. A `complete` call without a prior `relate` is a silent completion; if no artefact was produced, append a closing step that names the outcome (`appendStep: "Closed without artefact — operator confirmed no output needed"`).

Emit one `[work.execute] relate { taskId, artefactNodeId, edgeType }` per artefact and `[work.execute] complete { taskId, status, durationMs }` at closure.

### 5. Account scope

Every read and every write carries the active `accountId`. `work-ready`, `work-list`, `work-get`, `work-update`, `work-relate`, `work-complete` all filter on `accountId`. A Task whose `accountId` differs from the session is invisible — never read, never written, never named. This is not a soft preference; cross-account access is a refuse, not a warn.

Emit `[work.execute] refuse { reason: "cross-account" | "no-pick" | "missing-task" }` for every refusal so the loop is auditable.

## Success signal

A turn that closes the loop emits, in order, with one `taskId` correlator:

```
[work.execute] select   { ..., pickedId }
[work.execute] ground   { taskId, ... }
[work.execute] delegate { taskId, targetSkill, ... }
[work.execute] relate   { taskId, artefactNodeId, ... }   (one per artefact)
[work.execute] complete { taskId, status, durationMs }
```

`delegate` without subsequent `relate` is an orphan artefact. `complete` without prior `relate` is a silent completion. Either pattern in `server.log` is a defect.

Diagnostic: `grep work.execute server.log | jq -r 'select(.taskId=="<id>")'` reconstructs one task run end to end.

## Out of scope

- Creating Projects or Tasks — `work-create` / `project-create` only.
- Retro-relating historical artefacts to existing Tasks.
- Cross-account execution.
- Any UI surface — this skill is PTY-stdout only.
- Specialist seats.
