--- name: taskforge description: The primary entry point for the taskforge engineering workflow - create and import tasks, query and manage the backlog, route work, and unblock humans. Use whenever the user wants to add or import work ("add a task", "import issue #42", "track this bug", "turn these notes into tasks") or asks about tasks and the backlog ("what tasks are ready", "show the backlog", "task status", "what's next", "why is TASK-x stuck", "unblock TASK-x", "check the task store"). Routes to taskforge-refine (specification), taskforge-explore (decisions), and taskforge-run (implementation) but never executes them itself. Also home of the shared contracts, engine, and templates every taskforge skill uses. license: MIT --- # taskforge The primary entry point of the taskforge workflow, and its shared SDK: contracts, the deterministic engine, templates, and the reviewer component. This skill **creates, queries, routes, and maintains** tasks; it never refines, decides, or implements — those are `taskforge-refine`, `taskforge-explore`, and `taskforge-run`. Read `CONTRACTS.md` (sibling file) once per session before any taskforge work. Resolve the engine per its "Locating the engine" section; below, `$SCRIPT` means that resolved path. ## The workflow in one paragraph Every piece of work is a durable Task in `.tasks/`. Tasks route by **derived readiness**: no active specification → `taskforge-refine` (the universal entry point: adopt / elaborate / clarify / escalate); a pending explore flag — set by an escalation, or at intake for a research topic (`explore `) → `taskforge-explore` (a Decision, optionally proposing decomposition); an active spec and no blockers → `taskforge-run` (implement + independent fresh-context review). Skills reason and emit results; the engine applies them — versioning, cascades, relationships, budgets, readiness. Nothing is auto-executed. ## Commands Dispatch on the user's intent (or the argument after `/taskforge`). Every command reports per `references/reporting.md` and **stops** — routing names the next skill; it never runs it. | command | intent | how | |---|---|---| | *(none)* / `status` | overview | `list`; counts per readiness. Split the `blocked_on_human` tasks into **awaiting the human's call** (a `human_blocked` event from explore — a topology proposal or a research deliverable to dispose; see Disposing) and **blocked on an answer** (a question), and surface each with its prompt | | `add ` | create/import tasks | follow `references/intake.md` | | `explore ` | start a research task | intake per `references/intake.md` with `--explore` — routes to `taskforge-explore` for a Decision, not to refine | | `backlog` | full list | `python3 $SCRIPT list` (filter: `--readiness refine\|explore\|run\|waiting\|terminal\|human`) | | `next` | what should happen now | `list --readiness run`, else `refine`/`explore`; name the task(s) and the skill each needs | | `show ` | full detail + history | `python3 $SCRIPT show TASK-x` | | `why ` | explain routing / stuckness | `readiness TASK-x` + `blocked-by TASK-x`; see below | | `budget ` | review-retry budget | `python3 $SCRIPT budget TASK-x` | | `reconcile ` | orchestrator's read-only decision | `python3 $SCRIPT next TASK-x` (the recommended next action) or `python3 $SCRIPT reconcile TASK-x` (the full reconciliation — action + `terminal`/`human_required`). Read-only; the orchestration layer (`docs/ADR-0001-orchestration-and-reconciliation.md`), not a mutation | | `unblock ` | human answered | see Human unblocking | | `cancel ` | close without doing | `python3 $SCRIPT cancel TASK-x --reason "…"` (`--reason-file` when quoting the user), then sync per `references/sync.md` | | `reopen ` | restore a closed task | `python3 $SCRIPT reopen TASK-x --reason "…"`; see Reopening | | `land ` | record that a feature's PR merged | `python3 $SCRIPT link TASK-x --landed` (add `--pr ` if not already linked). Refused unless the task is `done` **and every descendant is closed** (it lists any that aren't). Land the delivery **owner** (the feature), not each child. Then close the source issue per `references/sync.md` — landing, **not** `done`, closes it | | `link ` | record delivery provenance | `python3 $SCRIPT link TASK-x --branch --pr `; where the code lives, as engine state not prose. A feature owns one delivery; its children **inherit** it (resolved up the parent chain), so `link` the feature — `link` a child only to break it onto its own branch | | `sync ` | tracker sync-back | `references/sync.md` | | `doctor` | store integrity | see Maintenance | | `audit ` | reviewer isolation | `python3 $SCRIPT audit-review TASK-x` | | `config` | effective settings | `python3 $SCRIPT config` | When answering `why`: quote `readiness` (its `reason`, `blocking_ids`, or `cycle`), then the last few relevant history events. For `blocked_on_human`, surface the `human_blocked` event's reason — an explore **proposal to dispose** (topology or a research deliverable; see Disposing) or a question awaiting an answer. ## Human unblocking When the user answers a `blocked_on_human` task or amends a parked one: ```bash # The note quotes the human — write it to a file with your editor tool and # pass the path (CONTRACTS.md → "Untrusted text is data"): python3 $SCRIPT human-update TASK-x --note-file /tmp/note.txt [--result /tmp/result.json] ``` Attach a result.json only if the answer translates into artifacts (e.g. the human dictated the spec); otherwise the note alone re-enters the task and readiness routes it. After either command, report new readiness and name the next skill — do not execute it. ## Disposing a parked explore `taskforge-explore` may change a task's **contents** (its Decision) but never the **topology** of the work graph (child tasks, backlog tasks, dependency edges) or a task's **completion** — those are the human's (CONTRACTS → "Topology"). So explore records its Decision and parks the task `blocked_on_human` with a proposal in the `human_blocked` event's reason. Two shapes arrive here; both are disposed the same way — a `human-update` **as the human** (actor `human`, capabilities `*`). Render the proposal, get the human's call, then commit it. **Topology proposal** — the Decision spawns work. Per item: approve the decomposition (or adjust it), and for each finding **promote to backlog · note only · ignore**. Write the chosen children (`relation: child`) and any promoted findings (`relation: follow_up`) into a `result.json`: ```bash python3 $SCRIPT human-update TASK-x --note-file /tmp/approval.txt --result result.json ``` The engine wires the children, pins each to explore's Decision, and re-routes the parent (`waiting` while children are open). **Research deliverable** — the Decision is the answer; nothing to build. Pick the disposition the human chooses; each is one `human-update`: | disposition | `result.json` | outcome | |---|---|---| | **close** | `{"signal": "done"}` | task `done`, its Decision preserved as the deliverable | | **spawn + close** | `{"generated_tasks": [{…, "relation": "follow_up"}], "signal": "done"}` | independent backlog filed `generated_from` it; task `done` | | **continue** | *(note only, no result.json)* | re-enters → `refine`, the Decision binding input | `done` here is the human's, exempt from the review gate: a research topic that decided *not* to build is a first-class `done` with a recorded Decision, not a `cancel`. The human is the actor of record; explore's proposal stays in history. If the human rejects the **Decision itself** (not its disposition), route to a re-exploration instead. Never create topology, or close or continue a task, on explore's behalf without the human's call. ## Reopening a closed task `done` and `cancelled` are **history-preserving** terminals, not deletions — reopen brings either back into active work: ```bash python3 $SCRIPT reopen TASK-x --reason "why it's back" [--reason-file …] ``` Reopen keeps every artifact, review, decision, and history event; it only lifts the terminal status and lets readiness **re-derive** where the task goes (a preserved spec → `run`; none → `refine`; a pending escalation → `explore`; an open blocker → `waiting`). Reopening a task others were blocked on re-blocks any still-active dependent. It rejects a task that isn't a closed terminal; a `blocked_on_human` task resumes with `unblock`/`human-update` instead (that path captures the human's answer). After reopening, report the new readiness and name the next skill — don't run it. ## Maintenance ```bash python3 $SCRIPT doctor # integrity: dangling edges, bad refs, # cycles, unaudited reviews python3 $SCRIPT migrate # after upgrading taskforge python3 $SCRIPT snapshot # atomic read model of the whole store — # for clients/tooling (docs/PUBLIC_API.md); # skills route per-task via readiness ``` Run `doctor` when anything looks inconsistent, after manual git operations on `.tasks/`, and before trusting a store you didn't create. Report findings; fix only via engine commands or by asking the user. ## For skill authors (extension contract) A new skill = a new `taskforge-/SKILL.md` following CONTRACTS.md plus an actor entry in `capabilities.json` (deny-by-default). Never modify existing skills to add one. Templates for results live in `templates/`; the reviewer component in `references/reviewer-prompt.md` is reusable by any skill that needs independent judgment.