Skip to main content
Glama

Task lifecycle

task

Task lifecycle. action = create | claim | complete | release | reopen | force_release | loop_finalize. Claim before you start and complete when done — these route through the atomic claim path that records accountability; never flip a task's status by hand. loop_finalize keeps correctness, independent review, and intent/scope verdicts separate. Cancelling a task and force-claiming one live in the destructive tool.

Input Schema

NameRequiredDescriptionDefault

No arguments

Output Schema

NameRequiredDescriptionDefault
dataYesThe action-specific result returned by Stele.
actionYesThe action that produced this result.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"create\": Create a task under a component. One task ≈ one PR. `success_criteria` is required — it is the contract the implementer and the reviewer both work against. Pass `check` only when a command can genuinely decide done without a human; for unattended certification also pass `check_paths`. Most tasks have neither, and that is fine. Give a markdown body with ## Why / ## How / ## Test plan — the canonical contract headings are written for you from the arguments.",
      -    "properties": {
      -      "action": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "anchor_files": {
      -        "description": "(create only) Repo-relative file paths this task is about. Anchoring an open task to the code it touches surfaces it when an agent later edits that file — so they don't step on toes or duplicate planned work.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "anchor_symbols": {
      -        "description": "(create only) Symbol names this task is about (function / class / constant / env var).",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "assignee_user_id": {
      -        "anyOf": [
      -          {
      -            "format": "uuid",
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "(create only) Pre-assign to a user uuid (NOT a shareable id); usually leave null."
      -      },
      -      "body": {
      -        "description": "(create only) Markdown body (optional). Write it in plain style: one idea per sentence, active voice, lead with the condition, one term per concept, exact technical names.",
      -        "type": "string"
      -      },
      -      "check": {
      -        "description": "OPTIONAL — a success criterion you can RUN: a command that decides done WITHOUT a human (e.g. a test command that must exit 0, or a script that prints a number to compare against a target). Appended under `## Check`. A task that has one is runnable by a loop; unattended certification additionally requires `check_paths` so the maker cannot silently modify its own verifier. The verdict then comes from the command, not from anyone's opinion. Most tasks have no runnable check, and that is fine: omit it and a human decides when it's done, which is the normal answer for anything whose 'done' is a judgment (design, architecture, docs, ambiguous work). Do not invent a check to fill this field in. A made-up check is worse than no check: it launders a guess into something that looks like a fact, and an agent will then iterate against it and merge on it.",
      -        "type": "string"
      -      },
      -      "check_paths": {
      -        "description": "OPTIONAL — repo-relative paths the declared check depends on: its test/script and every fixture or directory it reads. Required to CERTIFY an unattended loop: `stele loop verify` fails closed when a task has a check but no declared check paths. These paths are explicit because guessing them from an arbitrary shell command silently under-protects the verifier. Repeat paths as needed.",
      -        "items": {
      -          "minLength": 1,
      -          "type": "string"
      -        },
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "component_id": {
      -        "description": "REQUIRED for create — parent component shareable id.",
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "(create only) Task kind; defaults to 'task'. Non-'task' kinds are non-claimable containers that roll up from their `blocks`-children: 'epic' groups related tasks; 'objective' is a standing goal with ordered 'milestone' phases under it. Every kind still takes `success_criteria`: for an objective it is the end state that means the goal is reached.",
      -        "enum": [
      -          "task",
      -          "epic",
      -          "objective",
      -          "milestone"
      -        ],
      -        "type": "string"
      -      },
      -      "position": {
      -        "description": "(create only) Explicit ordering of a milestone within its objective (1-based).",
      -        "type": "integer"
      -      },
      -      "priority": {
      -        "anyOf": [
      -          {
      -            "enum": [
      -              "P0",
      -              "P1",
      -              "P2",
      -              "P3"
      -            ],
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "(create only) Priority P0 (most urgent) … P3. Omit/null = unprioritized."
      -      },
      -      "privacy_bypass": {
      -        "description": "true writes despite a privacy flag. Only meaningful after a flag; the user decides whether the content can be written.",
      -        "type": "boolean"
      -      },
      -      "privacy_false_positive": {
      -        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      -        "type": "boolean"
      -      },
      -      "privacy_judgement_id": {
      -        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      -        "type": "string"
      -      },
      -      "privacy_note": {
      -        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      -        "maxLength": 500,
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "scope": {
      -        "description": "(create only) Workspace scope. Omit or 'auto' = scope to the workspace mapped to the current git branch, else trunk (shared truth). 'trunk' = force shared truth even on a branch. Or pass a workspace name/id to target it. Branch-scoped writes are invisible to collaborators off that workspace.",
      -        "type": "string"
      -      },
      -      "success_criteria": {
      -        "description": "REQUIRED — how anyone (a person, or an agent picking this up cold) knows the task is DONE. State what must be TRUE when it's finished, not what you intend to do. Appended to the body under `## Success criteria`, which is the contract the implementer and the reviewer both work against — so a task without one is a task nobody can finish or check.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "target_date": {
      -        "description": "(create only) Optional soft target date — ISO date e.g. 2026-09-30. Valid on any kind: the date an objective or milestone is aimed at, and the date a plain task is expected by. Set it whenever someone committed to a deadline (\"I'll have it by Friday\"); a commitment with no date on it is a wish.",
      -        "type": "string"
      -      },
      -      "title": {
      -        "description": "REQUIRED for create — imperative one-liner (\"Add OAuth refresh\").",
      -        "maxLength": 300,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "topics": {
      -        "description": "(create only) Short tag list.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "component_id",
      -      "title",
      -      "success_criteria"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"claim\": Atomically claim a task (open → in_progress), recording you as owner. Claim before you start so others know you're on it. Returns the task, or { result: 'conflict' } if someone else holds it — no race window.",
      -    "properties": {
      -      "action": {
      -        "const": "claim",
      -        "type": "string"
      -      },
      -      "dispatched_with": {
      -        "description": "(claim only) Operator's full briefing prompt when this claim is from a dispatched sub-agent. It is stored with the claim, up to 16 KB; longer text is truncated with a warning.",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "REQUIRED for claim/complete/release/reopen/force_release — task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "parent_task_id": {
      -        "description": "(claim only) Operator's claimed task id (e.g. TASK-487) when this claim is from a sub-agent dispatched by the operator. Leave null for direct claims.",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"complete\": Mark a task done. REQUIRED `summary` is appended under ## Completion summary (what shipped, where it landed, what you learned). Also closes a container (epic/objective/milestone): no claim needed, but it is REFUSED while any child is unfinished, and the error names them. A container normally closes itself when its last child closes, so completing one is mainly how you record what it delivered — and it marks the close as yours, so a child reopening later won't undo it. The result may list nearby decision/architecture nodes to re-verify (still-true / edit / supersede); that part is advisory.",
      -    "properties": {
      -      "action": {
      -        "const": "complete",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "privacy_bypass": {
      -        "description": "true writes despite a privacy flag. Only meaningful after a flag; the user decides whether the content can be written.",
      -        "type": "boolean"
      -      },
      -      "privacy_false_positive": {
      -        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      -        "type": "boolean"
      -      },
      -      "privacy_judgement_id": {
      -        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      -        "type": "string"
      -      },
      -      "privacy_note": {
      -        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      -        "maxLength": 500,
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "summary": {
      -        "description": "REQUIRED — what actually happened. The graph only learns from what closing writes down: what shipped, where it landed, what you found out, what you'd warn the next person about. A task closed with nothing said is a task the next agent has to re-derive from the diff.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id",
      -      "summary"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"release\": Release a task you claimed (in_progress → open) so someone else can pick it up — use when you can't finish (out of context, blocked, wrong scope).",
      -    "properties": {
      -      "action": {
      -        "const": "release",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"reopen\": Recovery: send a closed task (done or cancelled) back to open and clear its completion metadata so it reads as unheld and claimable again. For a stuck in_progress task, use task(action=\"force_release\") instead (this is for closed tasks).",
      -    "properties": {
      -      "action": {
      -        "const": "reopen",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"force_release\": Admin recovery: release an in_progress task WITHOUT holding the claim, so it returns to open for others. The release is attributed to you in the claim history (not the prior claimer). For a closed task use task(action=\"reopen\"); to take a task over rather than free it, use destructive(action=\"force_claim_task\").",
      -    "properties": {
      -      "action": {
      -        "const": "force_release",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"loop_finalize\": Create the durable final loop envelope. Deterministic correctness comes only from the latest mechanically evidenced attempt; independent reviewer and operator intent/scope judgments remain separate fields. Approval requires all three, so model judgment can reject work but can never manufacture correctness.",
      -    "properties": {
      -      "action": {
      -        "const": "loop_finalize",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "The loop task to finalize (TASK-N).",
      -        "pattern": "^TASK-\\d+$",
      -        "type": "string"
      -      },
      -      "operator_summary": {
      -        "description": "Why the operator judged the change in or out of intent and scope.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "operator_verdict": {
      -        "description": "The operator's judgment of whether the change stays within the task's intent and scope.",
      -        "enum": [
      -          "approved",
      -          "rejected"
      -        ],
      -        "type": "string"
      -      },
      -      "privacy_bypass": {
      -        "description": "true writes despite a privacy flag. Only meaningful after a flag; the user decides whether the content can be written.",
      -        "type": "boolean"
      -      },
      -      "privacy_false_positive": {
      -        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      -        "type": "boolean"
      -      },
      -      "privacy_judgement_id": {
      -        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      -        "type": "string"
      -      },
      -      "privacy_note": {
      -        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      -        "maxLength": 500,
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "reviewer_summary": {
      -        "description": "Why the reviewer approved or rejected the change.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "reviewer_verdict": {
      -        "description": "The independent reviewer's judgment of the change.",
      -        "enum": [
      -          "approved",
      -          "rejected"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id",
      -      "reviewer_verdict",
      -      "reviewer_summary",
      -      "operator_verdict",
      -      "operator_summary"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "description": "task action \"create\".",
      +    "properties": {
      +      "action": {
      +        "const": "create",
      +        "description": "Run the create action.",
      +        "type": "string"
      +      },
      +      "anchor_files": {
      +        "description": "(create only) Repo-relative file paths this task is about. Anchoring an open task to the code it touches surfaces it when an agent later edits that file — so they don't step on toes or duplicate planned work.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "anchor_symbols": {
      +        "description": "(create only) Symbol names this task is about (function / class / constant / env var).",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "assignee_user_id": {
      +        "anyOf": [
      +          {
      +            "format": "uuid",
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "(create only) Pre-assign to a user uuid (NOT a shareable id); usually leave null."
      +      },
      +      "body": {
      +        "description": "(create only) Markdown body (optional). Write it in plain style: one idea per sentence, active voice, lead with the condition, one term per concept, exact technical names.",
      +        "type": "string"
      +      },
      +      "check": {
      +        "description": "OPTIONAL — a success criterion you can RUN: a command that decides done WITHOUT a human (e.g. a test command that must exit 0, or a script that prints a number to compare against a target). Appended under `## Check`. A task that has one is runnable by a loop; unattended certification additionally requires `check_paths` so the maker cannot silently modify its own verifier. The verdict then comes from the command, not from anyone's opinion. Most tasks have no runnable check, and that is fine: omit it and a human decides when it's done, which is the normal answer for anything whose 'done' is a judgment (design, architecture, docs, ambiguous work). Do not invent a check to fill this field in. A made-up check is worse than no check: it launders a guess into something that looks like a fact, and an agent will then iterate against it and merge on it.",
      +        "type": "string"
      +      },
      +      "check_paths": {
      +        "description": "OPTIONAL — repo-relative paths the declared check depends on: its test/script and every fixture or directory it reads. Required to CERTIFY an unattended loop: `stele loop verify` fails closed when a task has a check but no declared check paths. These paths are explicit because guessing them from an arbitrary shell command silently under-protects the verifier. Repeat paths as needed.",
      +        "items": {
      +          "minLength": 1,
      +          "type": "string"
      +        },
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "component_id": {
      +        "description": "REQUIRED for create — parent component shareable id.",
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "(create only) Task kind; defaults to 'task'. Non-'task' kinds are non-claimable containers that roll up from their `blocks`-children: 'epic' groups related tasks; 'objective' is a standing goal with ordered 'milestone' phases under it. Every kind still takes `success_criteria`: for an objective it is the end state that means the goal is reached.",
      +        "enum": [
      +          "task",
      +          "epic",
      +          "objective",
      +          "milestone"
      +        ],
      +        "type": "string"
      +      },
      +      "position": {
      +        "description": "(create only) Explicit ordering of a milestone within its objective (1-based).",
      +        "type": "integer"
      +      },
      +      "priority": {
      +        "anyOf": [
      +          {
      +            "enum": [
      +              "P0",
      +              "P1",
      +              "P2",
      +              "P3"
      +            ],
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "(create only) Priority P0 (most urgent) … P3. Omit/null = unprioritized."
      +      },
      +      "privacy_bypass": {
      +        "description": "true writes despite a privacy flag. Only meaningful after a flag; the user decides whether the content can be written.",
      +        "type": "boolean"
      +      },
      +      "privacy_false_positive": {
      +        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      +        "type": "boolean"
      +      },
      +      "privacy_judgement_id": {
      +        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      +        "type": "string"
      +      },
      +      "privacy_note": {
      +        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      +        "maxLength": 500,
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "scope": {
      +        "description": "(create only) Workspace scope. Omit or 'auto' = scope to the workspace mapped to the current git branch, else trunk (shared truth). 'trunk' = force shared truth even on a branch. Or pass a workspace name/id to target it. Branch-scoped writes are invisible to collaborators off that workspace.",
      +        "type": "string"
      +      },
      +      "success_criteria": {
      +        "description": "REQUIRED — how anyone (a person, or an agent picking this up cold) knows the task is DONE. State what must be TRUE when it's finished, not what you intend to do. Appended to the body under `## Success criteria`, which is the contract the implementer and the reviewer both work against — so a task without one is a task nobody can finish or check.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "target_date": {
      +        "description": "(create only) Optional soft target date — ISO date e.g. 2026-09-30. Valid on any kind: the date an objective or milestone is aimed at, and the date a plain task is expected by. Set it whenever someone committed to a deadline (\"I'll have it by Friday\"); a commitment with no date on it is a wish.",
      +        "type": "string"
      +      },
      +      "title": {
      +        "description": "REQUIRED for create — imperative one-liner (\"Add OAuth refresh\").",
      +        "maxLength": 300,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "topics": {
      +        "description": "(create only) Short tag list.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "component_id",
      +      "title",
      +      "success_criteria"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "task action \"claim\".",
      +    "properties": {
      +      "action": {
      +        "const": "claim",
      +        "description": "Run the claim action.",
      +        "type": "string"
      +      },
      +      "dispatched_with": {
      +        "description": "(claim only) Operator's full briefing prompt when this claim is from a dispatched sub-agent. It is stored with the claim, up to 16 KB; longer text is truncated with a warning.",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "REQUIRED for claim/complete/release/reopen/force_release — task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "parent_task_id": {
      +        "description": "(claim only) Operator's claimed task id (e.g. TASK-487) when this claim is from a sub-agent dispatched by the operator. Leave null for direct claims.",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "task action \"complete\".",
      +    "properties": {
      +      "action": {
      +        "const": "complete",
      +        "description": "Run the complete action.",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "privacy_bypass": {
      +        "description": "true writes despite a privacy flag. Only meaningful after a flag; the user decides whether the content can be written.",
      +        "type": "boolean"
      +      },
      +      "privacy_false_positive": {
      +        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      +        "type": "boolean"
      +      },
      +      "privacy_judgement_id": {
      +        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      +        "type": "string"
      +      },
      +      "privacy_note": {
      +        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      +        "maxLength": 500,
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "summary": {
      +        "description": "REQUIRED — what actually happened. The graph only learns from what closing writes down: what shipped, where it landed, what you found out, what you'd warn the next person about. A task closed with nothing said is a task the next agent has to re-derive from the diff.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id",
      +      "summary"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "task action \"release\".",
      +    "properties": {
      +      "action": {
      +        "const": "release",
      +        "description": "Run the release action.",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "task action \"reopen\".",
      +    "properties": {
      +      "action": {
      +        "const": "reopen",
      +        "description": "Run the reopen action.",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "task action \"force_release\".",
      +    "properties": {
      +      "action": {
      +        "const": "force_release",
      +        "description": "Run the force_release action.",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "task action \"loop_finalize\".",
      +    "properties": {
      +      "action": {
      +        "const": "loop_finalize",
      +        "description": "Run the loop_finalize action.",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "The loop task to finalize (TASK-N).",
      +        "pattern": "^TASK-\\d+$",
      +        "type": "string"
      +      },
      +      "operator_summary": {
      +        "description": "Why the operator judged the change in or out of intent and scope.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "operator_verdict": {
      +        "description": "The operator's judgment of whether the change stays within the task's intent and scope.",
      +        "enum": [
      +          "approved",
      +          "rejected"
      +        ],
      +        "type": "string"
      +      },
      +      "privacy_bypass": {
      +        "description": "true writes despite a privacy flag. Only meaningful after a flag; the user decides whether the content can be written.",
      +        "type": "boolean"
      +      },
      +      "privacy_false_positive": {
      +        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      +        "type": "boolean"
      +      },
      +      "privacy_judgement_id": {
      +        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      +        "type": "string"
      +      },
      +      "privacy_note": {
      +        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      +        "maxLength": 500,
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "reviewer_summary": {
      +        "description": "Why the reviewer approved or rejected the change.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "reviewer_verdict": {
      +        "description": "The independent reviewer's judgment of the change.",
      +        "enum": [
      +          "approved",
      +          "rejected"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id",
      +      "reviewer_verdict",
      +      "reviewer_summary",
      +      "operator_verdict",
      +      "operator_summary"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. Changed1 schema field changed
    • changedInput schema / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"create\": Create a task under a component. One task ≈ one PR. `success_criteria` is required — it is the contract the implementer and the reviewer both work against. Pass `check` only when a command can genuinely decide done without a human; for unattended certification also pass `check_paths`. Most tasks have neither, and that is fine. Give a markdown body with ## Why / ## How / ## Test plan — the canonical contract headings are written for you from the arguments.",
      -    "properties": {
      -      "action": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "anchor_files": {
      -        "description": "(create only) Repo-relative file paths this task is about. Anchoring an open task to the code it touches surfaces it when an agent later edits that file — so they don't step on toes or duplicate planned work.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "anchor_symbols": {
      -        "description": "(create only) Symbol names this task is about (function / class / constant / env var).",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "assignee_user_id": {
      -        "anyOf": [
      -          {
      -            "format": "uuid",
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "(create only) Pre-assign to a user uuid (NOT a shareable id); usually leave null."
      -      },
      -      "body": {
      -        "description": "(create only) Markdown body (optional). Write it in plain style: one idea per sentence, active voice, lead with the condition, one term per concept, exact technical names.",
      -        "type": "string"
      -      },
      -      "check": {
      -        "description": "OPTIONAL — a success criterion you can RUN: a command that decides done WITHOUT a human (e.g. a test command that must exit 0, or a script that prints a number to compare against a target). Appended under `## Check`. A task that has one is runnable by a loop; unattended certification additionally requires `check_paths` so the maker cannot silently modify its own verifier. The verdict then comes from the command, not from anyone's opinion. Most tasks have no runnable check, and that is fine: omit it and a human decides when it's done, which is the normal answer for anything whose 'done' is a judgment (design, architecture, docs, ambiguous work). Do not invent a check to fill this field in. A made-up check is worse than no check: it launders a guess into something that looks like a fact, and an agent will then iterate against it and merge on it.",
      -        "type": "string"
      -      },
      -      "check_paths": {
      -        "description": "OPTIONAL — repo-relative paths the declared check depends on: its test/script and every fixture or directory it reads. Required to CERTIFY an unattended loop: `stele loop verify` fails closed when a task has a check but no declared check paths. These paths are explicit because guessing them from an arbitrary shell command silently under-protects the verifier. Repeat paths as needed.",
      -        "items": {
      -          "minLength": 1,
      -          "type": "string"
      -        },
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "component_id": {
      -        "description": "REQUIRED for create — parent component shareable id.",
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "(create only) Task kind; defaults to 'task'. Non-'task' kinds are non-claimable containers that roll up from their `blocks`-children: 'epic' groups related tasks; 'objective' is a standing goal (end-state in its body) with ordered 'milestone' phases under it.",
      -        "enum": [
      -          "task",
      -          "epic",
      -          "objective",
      -          "milestone"
      -        ],
      -        "type": "string"
      -      },
      -      "position": {
      -        "description": "(create only) Explicit ordering of a milestone within its objective (1-based).",
      -        "type": "integer"
      -      },
      -      "priority": {
      -        "anyOf": [
      -          {
      -            "enum": [
      -              "P0",
      -              "P1",
      -              "P2",
      -              "P3"
      -            ],
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "(create only) Priority P0 (most urgent) … P3. Omit/null = unprioritized."
      -      },
      -      "privacy_bypass": {
      -        "description": "true writes despite a privacy flag on a public project. Only meaningful after a flag; the user decides whether the content can be public.",
      -        "type": "boolean"
      -      },
      -      "privacy_false_positive": {
      -        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      -        "type": "boolean"
      -      },
      -      "privacy_judgement_id": {
      -        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      -        "type": "string"
      -      },
      -      "privacy_note": {
      -        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      -        "maxLength": 500,
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "scope": {
      -        "description": "(create only) Workspace scope. Omit or 'auto' = scope to the workspace mapped to the current git branch, else trunk (shared truth). 'trunk' = force shared truth even on a branch. Or pass a workspace name/id to target it. Branch-scoped writes are invisible to collaborators off that workspace.",
      -        "type": "string"
      -      },
      -      "success_criteria": {
      -        "description": "REQUIRED — how anyone (a person, or an agent picking this up cold) knows the task is DONE. State what must be TRUE when it's finished, not what you intend to do. Appended to the body under `## Success criteria`, which is the contract the implementer and the reviewer both work against — so a task without one is a task nobody can finish or check.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "target_date": {
      -        "description": "(create only) Optional soft target date — ISO date e.g. 2026-09-30. Valid on any kind: the date an objective or milestone is aimed at, and the date a plain task is expected by. Set it whenever someone committed to a deadline (\"I'll have it by Friday\"); a commitment with no date on it is a wish.",
      -        "type": "string"
      -      },
      -      "title": {
      -        "description": "REQUIRED for create — imperative one-liner (\"Add OAuth refresh\").",
      -        "maxLength": 300,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "topics": {
      -        "description": "(create only) Short tag list.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "component_id",
      -      "title",
      -      "success_criteria"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"claim\": Atomically claim a task (open → in_progress), recording you as owner. Claim before you start so others know you're on it. Returns the task, or { result: 'conflict' } if someone else holds it — no race window.",
      -    "properties": {
      -      "action": {
      -        "const": "claim",
      -        "type": "string"
      -      },
      -      "dispatched_with": {
      -        "description": "(claim only) Operator's full briefing prompt when this claim is from a dispatched sub-agent. It is stored with the claim, up to 16 KB; longer text is truncated with a warning.",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "REQUIRED for claim/complete/release/reopen/force_release — task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "parent_task_id": {
      -        "description": "(claim only) Operator's claimed task id (e.g. TASK-487) when this claim is from a sub-agent dispatched by the operator. Leave null for direct claims.",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"complete\": Mark a task done. REQUIRED `summary` is appended under ## Completion summary (what shipped, where it landed, what you learned). Also closes a container (epic/objective/milestone): no claim needed, but it is REFUSED while any child is unfinished, and the error names them. A container normally closes itself when its last child closes, so completing one is mainly how you record what it delivered — and it marks the close as yours, so a child reopening later won't undo it. The result may list nearby decision/architecture nodes to re-verify (still-true / edit / supersede); that part is advisory.",
      -    "properties": {
      -      "action": {
      -        "const": "complete",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "privacy_bypass": {
      -        "description": "true writes despite a privacy flag on a public project. Only meaningful after a flag; the user decides whether the content can be public.",
      -        "type": "boolean"
      -      },
      -      "privacy_false_positive": {
      -        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      -        "type": "boolean"
      -      },
      -      "privacy_judgement_id": {
      -        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      -        "type": "string"
      -      },
      -      "privacy_note": {
      -        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      -        "maxLength": 500,
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "summary": {
      -        "description": "REQUIRED — what actually happened. The graph only learns from what closing writes down: what shipped, where it landed, what you found out, what you'd warn the next person about. A task closed with nothing said is a task the next agent has to re-derive from the diff.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id",
      -      "summary"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"release\": Release a task you claimed (in_progress → open) so someone else can pick it up — use when you can't finish (out of context, blocked, wrong scope).",
      -    "properties": {
      -      "action": {
      -        "const": "release",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"reopen\": Recovery: send a closed task (done or cancelled) back to open and clear its completion metadata so it reads as unheld and claimable again. For a stuck in_progress task, use task(action=\"force_release\") instead (this is for closed tasks).",
      -    "properties": {
      -      "action": {
      -        "const": "reopen",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"force_release\": Admin recovery: release an in_progress task WITHOUT holding the claim, so it returns to open for others. The release is attributed to you in the claim history (not the prior claimer). For a closed task use task(action=\"reopen\"); to take a task over rather than free it, use destructive(action=\"force_claim_task\").",
      -    "properties": {
      -      "action": {
      -        "const": "force_release",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"loop_finalize\": Create the durable final loop envelope. Deterministic correctness comes only from the latest mechanically evidenced attempt; independent reviewer and operator intent/scope judgments remain separate fields. Approval requires all three, so model judgment can reject work but can never manufacture correctness.",
      -    "properties": {
      -      "action": {
      -        "const": "loop_finalize",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "The loop task to finalize (TASK-N).",
      -        "pattern": "^TASK-\\d+$",
      -        "type": "string"
      -      },
      -      "operator_summary": {
      -        "description": "Why the operator judged the change in or out of intent and scope.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "operator_verdict": {
      -        "description": "The operator's judgment of whether the change stays within the task's intent and scope.",
      -        "enum": [
      -          "approved",
      -          "rejected"
      -        ],
      -        "type": "string"
      -      },
      -      "privacy_bypass": {
      -        "description": "true writes despite a privacy flag on a public project. Only meaningful after a flag; the user decides whether the content can be public.",
      -        "type": "boolean"
      -      },
      -      "privacy_false_positive": {
      -        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      -        "type": "boolean"
      -      },
      -      "privacy_judgement_id": {
      -        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      -        "type": "string"
      -      },
      -      "privacy_note": {
      -        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      -        "maxLength": 500,
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "reviewer_summary": {
      -        "description": "Why the reviewer approved or rejected the change.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "reviewer_verdict": {
      -        "description": "The independent reviewer's judgment of the change.",
      -        "enum": [
      -          "approved",
      -          "rejected"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id",
      -      "reviewer_verdict",
      -      "reviewer_summary",
      -      "operator_verdict",
      -      "operator_summary"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"create\": Create a task under a component. One task ≈ one PR. `success_criteria` is required — it is the contract the implementer and the reviewer both work against. Pass `check` only when a command can genuinely decide done without a human; for unattended certification also pass `check_paths`. Most tasks have neither, and that is fine. Give a markdown body with ## Why / ## How / ## Test plan — the canonical contract headings are written for you from the arguments.",
      +    "properties": {
      +      "action": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "anchor_files": {
      +        "description": "(create only) Repo-relative file paths this task is about. Anchoring an open task to the code it touches surfaces it when an agent later edits that file — so they don't step on toes or duplicate planned work.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "anchor_symbols": {
      +        "description": "(create only) Symbol names this task is about (function / class / constant / env var).",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "assignee_user_id": {
      +        "anyOf": [
      +          {
      +            "format": "uuid",
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "(create only) Pre-assign to a user uuid (NOT a shareable id); usually leave null."
      +      },
      +      "body": {
      +        "description": "(create only) Markdown body (optional). Write it in plain style: one idea per sentence, active voice, lead with the condition, one term per concept, exact technical names.",
      +        "type": "string"
      +      },
      +      "check": {
      +        "description": "OPTIONAL — a success criterion you can RUN: a command that decides done WITHOUT a human (e.g. a test command that must exit 0, or a script that prints a number to compare against a target). Appended under `## Check`. A task that has one is runnable by a loop; unattended certification additionally requires `check_paths` so the maker cannot silently modify its own verifier. The verdict then comes from the command, not from anyone's opinion. Most tasks have no runnable check, and that is fine: omit it and a human decides when it's done, which is the normal answer for anything whose 'done' is a judgment (design, architecture, docs, ambiguous work). Do not invent a check to fill this field in. A made-up check is worse than no check: it launders a guess into something that looks like a fact, and an agent will then iterate against it and merge on it.",
      +        "type": "string"
      +      },
      +      "check_paths": {
      +        "description": "OPTIONAL — repo-relative paths the declared check depends on: its test/script and every fixture or directory it reads. Required to CERTIFY an unattended loop: `stele loop verify` fails closed when a task has a check but no declared check paths. These paths are explicit because guessing them from an arbitrary shell command silently under-protects the verifier. Repeat paths as needed.",
      +        "items": {
      +          "minLength": 1,
      +          "type": "string"
      +        },
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "component_id": {
      +        "description": "REQUIRED for create — parent component shareable id.",
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "(create only) Task kind; defaults to 'task'. Non-'task' kinds are non-claimable containers that roll up from their `blocks`-children: 'epic' groups related tasks; 'objective' is a standing goal with ordered 'milestone' phases under it. Every kind still takes `success_criteria`: for an objective it is the end state that means the goal is reached.",
      +        "enum": [
      +          "task",
      +          "epic",
      +          "objective",
      +          "milestone"
      +        ],
      +        "type": "string"
      +      },
      +      "position": {
      +        "description": "(create only) Explicit ordering of a milestone within its objective (1-based).",
      +        "type": "integer"
      +      },
      +      "priority": {
      +        "anyOf": [
      +          {
      +            "enum": [
      +              "P0",
      +              "P1",
      +              "P2",
      +              "P3"
      +            ],
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "(create only) Priority P0 (most urgent) … P3. Omit/null = unprioritized."
      +      },
      +      "privacy_bypass": {
      +        "description": "true writes despite a privacy flag. Only meaningful after a flag; the user decides whether the content can be written.",
      +        "type": "boolean"
      +      },
      +      "privacy_false_positive": {
      +        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      +        "type": "boolean"
      +      },
      +      "privacy_judgement_id": {
      +        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      +        "type": "string"
      +      },
      +      "privacy_note": {
      +        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      +        "maxLength": 500,
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "scope": {
      +        "description": "(create only) Workspace scope. Omit or 'auto' = scope to the workspace mapped to the current git branch, else trunk (shared truth). 'trunk' = force shared truth even on a branch. Or pass a workspace name/id to target it. Branch-scoped writes are invisible to collaborators off that workspace.",
      +        "type": "string"
      +      },
      +      "success_criteria": {
      +        "description": "REQUIRED — how anyone (a person, or an agent picking this up cold) knows the task is DONE. State what must be TRUE when it's finished, not what you intend to do. Appended to the body under `## Success criteria`, which is the contract the implementer and the reviewer both work against — so a task without one is a task nobody can finish or check.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "target_date": {
      +        "description": "(create only) Optional soft target date — ISO date e.g. 2026-09-30. Valid on any kind: the date an objective or milestone is aimed at, and the date a plain task is expected by. Set it whenever someone committed to a deadline (\"I'll have it by Friday\"); a commitment with no date on it is a wish.",
      +        "type": "string"
      +      },
      +      "title": {
      +        "description": "REQUIRED for create — imperative one-liner (\"Add OAuth refresh\").",
      +        "maxLength": 300,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "topics": {
      +        "description": "(create only) Short tag list.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "component_id",
      +      "title",
      +      "success_criteria"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"claim\": Atomically claim a task (open → in_progress), recording you as owner. Claim before you start so others know you're on it. Returns the task, or { result: 'conflict' } if someone else holds it — no race window.",
      +    "properties": {
      +      "action": {
      +        "const": "claim",
      +        "type": "string"
      +      },
      +      "dispatched_with": {
      +        "description": "(claim only) Operator's full briefing prompt when this claim is from a dispatched sub-agent. It is stored with the claim, up to 16 KB; longer text is truncated with a warning.",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "REQUIRED for claim/complete/release/reopen/force_release — task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "parent_task_id": {
      +        "description": "(claim only) Operator's claimed task id (e.g. TASK-487) when this claim is from a sub-agent dispatched by the operator. Leave null for direct claims.",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"complete\": Mark a task done. REQUIRED `summary` is appended under ## Completion summary (what shipped, where it landed, what you learned). Also closes a container (epic/objective/milestone): no claim needed, but it is REFUSED while any child is unfinished, and the error names them. A container normally closes itself when its last child closes, so completing one is mainly how you record what it delivered — and it marks the close as yours, so a child reopening later won't undo it. The result may list nearby decision/architecture nodes to re-verify (still-true / edit / supersede); that part is advisory.",
      +    "properties": {
      +      "action": {
      +        "const": "complete",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "privacy_bypass": {
      +        "description": "true writes despite a privacy flag. Only meaningful after a flag; the user decides whether the content can be written.",
      +        "type": "boolean"
      +      },
      +      "privacy_false_positive": {
      +        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      +        "type": "boolean"
      +      },
      +      "privacy_judgement_id": {
      +        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      +        "type": "string"
      +      },
      +      "privacy_note": {
      +        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      +        "maxLength": 500,
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "summary": {
      +        "description": "REQUIRED — what actually happened. The graph only learns from what closing writes down: what shipped, where it landed, what you found out, what you'd warn the next person about. A task closed with nothing said is a task the next agent has to re-derive from the diff.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id",
      +      "summary"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"release\": Release a task you claimed (in_progress → open) so someone else can pick it up — use when you can't finish (out of context, blocked, wrong scope).",
      +    "properties": {
      +      "action": {
      +        "const": "release",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"reopen\": Recovery: send a closed task (done or cancelled) back to open and clear its completion metadata so it reads as unheld and claimable again. For a stuck in_progress task, use task(action=\"force_release\") instead (this is for closed tasks).",
      +    "properties": {
      +      "action": {
      +        "const": "reopen",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"force_release\": Admin recovery: release an in_progress task WITHOUT holding the claim, so it returns to open for others. The release is attributed to you in the claim history (not the prior claimer). For a closed task use task(action=\"reopen\"); to take a task over rather than free it, use destructive(action=\"force_claim_task\").",
      +    "properties": {
      +      "action": {
      +        "const": "force_release",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"loop_finalize\": Create the durable final loop envelope. Deterministic correctness comes only from the latest mechanically evidenced attempt; independent reviewer and operator intent/scope judgments remain separate fields. Approval requires all three, so model judgment can reject work but can never manufacture correctness.",
      +    "properties": {
      +      "action": {
      +        "const": "loop_finalize",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "The loop task to finalize (TASK-N).",
      +        "pattern": "^TASK-\\d+$",
      +        "type": "string"
      +      },
      +      "operator_summary": {
      +        "description": "Why the operator judged the change in or out of intent and scope.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "operator_verdict": {
      +        "description": "The operator's judgment of whether the change stays within the task's intent and scope.",
      +        "enum": [
      +          "approved",
      +          "rejected"
      +        ],
      +        "type": "string"
      +      },
      +      "privacy_bypass": {
      +        "description": "true writes despite a privacy flag. Only meaningful after a flag; the user decides whether the content can be written.",
      +        "type": "boolean"
      +      },
      +      "privacy_false_positive": {
      +        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      +        "type": "boolean"
      +      },
      +      "privacy_judgement_id": {
      +        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      +        "type": "string"
      +      },
      +      "privacy_note": {
      +        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      +        "maxLength": 500,
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "reviewer_summary": {
      +        "description": "Why the reviewer approved or rejected the change.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "reviewer_verdict": {
      +        "description": "The independent reviewer's judgment of the change.",
      +        "enum": [
      +          "approved",
      +          "rejected"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id",
      +      "reviewer_verdict",
      +      "reviewer_summary",
      +      "operator_verdict",
      +      "operator_summary"
      +    ],
      +    "type": "object"
      +  }
      +]
  3. Changed1 schema field changed
    • changedInput schema / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"create\": Create a task under a component. One task ≈ one PR. `success_criteria` is required — it is the contract the implementer and the reviewer both work against. Pass `check` only when a command can genuinely decide done without a human; for unattended certification also pass `check_paths`. Most tasks have neither, and that is fine. Give a markdown body with ## Why / ## How / ## Test plan — the canonical contract headings are written for you from the arguments.",
      -    "properties": {
      -      "action": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "anchor_files": {
      -        "description": "(create only) Repo-relative file paths this task is about. Anchoring an open task to the code it touches surfaces it when an agent later edits that file — so they don't step on toes or duplicate planned work.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "anchor_symbols": {
      -        "description": "(create only) Symbol names this task is about (function / class / constant / env var).",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "assignee_user_id": {
      -        "anyOf": [
      -          {
      -            "format": "uuid",
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "(create only) Pre-assign to a user uuid (NOT a shareable id); usually leave null."
      -      },
      -      "body": {
      -        "description": "(create only) Markdown body (optional). Write it in plain style: one idea per sentence, active voice, lead with the condition, one term per concept, exact technical names.",
      -        "type": "string"
      -      },
      -      "check": {
      -        "description": "OPTIONAL — a success criterion you can RUN: a command that decides done WITHOUT a human (e.g. a test command that must exit 0, or a script that prints a number to compare against a target). Appended under `## Check`. A task that has one is runnable by a loop; unattended certification additionally requires `check_paths` so the maker cannot silently modify its own verifier. The verdict then comes from the command, not from anyone's opinion. Most tasks have no runnable check, and that is fine: omit it and a human decides when it's done, which is the normal answer for anything whose 'done' is a judgment (design, architecture, docs, ambiguous work). Do not invent a check to fill this field in. A made-up check is worse than no check: it launders a guess into something that looks like a fact, and an agent will then iterate against it and merge on it.",
      -        "type": "string"
      -      },
      -      "check_paths": {
      -        "description": "OPTIONAL — repo-relative paths the declared check depends on: its test/script and every fixture or directory it reads. Required to CERTIFY an unattended loop: `stele loop verify` fails closed when a task has a check but no declared check paths. These paths are explicit because guessing them from an arbitrary shell command silently under-protects the verifier. Repeat paths as needed.",
      -        "items": {
      -          "minLength": 1,
      -          "type": "string"
      -        },
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "component_id": {
      -        "description": "REQUIRED for create — parent component shareable id.",
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "(create only) Task kind; defaults to 'task'. Non-'task' kinds are non-claimable containers that roll up from their `blocks`-children: 'epic' groups related tasks; 'objective' is a standing goal (end-state in its body) with ordered 'milestone' phases under it.",
      -        "enum": [
      -          "task",
      -          "epic",
      -          "objective",
      -          "milestone"
      -        ],
      -        "type": "string"
      -      },
      -      "position": {
      -        "description": "(create only) Explicit ordering of a milestone within its objective (1-based).",
      -        "type": "integer"
      -      },
      -      "priority": {
      -        "anyOf": [
      -          {
      -            "enum": [
      -              "P0",
      -              "P1",
      -              "P2",
      -              "P3"
      -            ],
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "(create only) Priority P0 (most urgent) … P3. Omit/null = unprioritized."
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "scope": {
      -        "description": "(create only) Workspace scope. Omit or 'auto' = scope to the workspace mapped to the current git branch, else trunk (shared truth). 'trunk' = force shared truth even on a branch. Or pass a workspace name/id to target it. Branch-scoped writes are invisible to collaborators off that workspace.",
      -        "type": "string"
      -      },
      -      "success_criteria": {
      -        "description": "REQUIRED — how anyone (a person, or an agent picking this up cold) knows the task is DONE. State what must be TRUE when it's finished, not what you intend to do. Appended to the body under `## Success criteria`, which is the contract the implementer and the reviewer both work against — so a task without one is a task nobody can finish or check.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "target_date": {
      -        "description": "(create only) Optional soft target date — ISO date e.g. 2026-09-30. Valid on any kind: the date an objective or milestone is aimed at, and the date a plain task is expected by. Set it whenever someone committed to a deadline (\"I'll have it by Friday\"); a commitment with no date on it is a wish.",
      -        "type": "string"
      -      },
      -      "title": {
      -        "description": "REQUIRED for create — imperative one-liner (\"Add OAuth refresh\").",
      -        "maxLength": 300,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "topics": {
      -        "description": "(create only) Short tag list.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "component_id",
      -      "title",
      -      "success_criteria"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"claim\": Atomically claim a task (open → in_progress), recording you as owner. Claim before you start so others know you're on it. Returns the task, or { result: 'conflict' } if someone else holds it — no race window.",
      -    "properties": {
      -      "action": {
      -        "const": "claim",
      -        "type": "string"
      -      },
      -      "dispatched_with": {
      -        "description": "(claim only) Operator's full briefing prompt when this claim is from a dispatched sub-agent. It is stored with the claim, up to 16 KB; longer text is truncated with a warning.",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "REQUIRED for claim/complete/release/reopen/force_release — task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "parent_task_id": {
      -        "description": "(claim only) Operator's claimed task id (e.g. TASK-487) when this claim is from a sub-agent dispatched by the operator. Leave null for direct claims.",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"complete\": Mark a task done. REQUIRED `summary` is appended under ## Completion summary (what shipped, where it landed, what you learned). Also closes a container (epic/objective/milestone): no claim needed, but it is REFUSED while any child is unfinished, and the error names them. A container normally closes itself when its last child closes, so completing one is mainly how you record what it delivered — and it marks the close as yours, so a child reopening later won't undo it. The result may list nearby decision/architecture nodes to re-verify (still-true / edit / supersede); that part is advisory.",
      -    "properties": {
      -      "action": {
      -        "const": "complete",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "summary": {
      -        "description": "REQUIRED — what actually happened. The graph only learns from what closing writes down: what shipped, where it landed, what you found out, what you'd warn the next person about. A task closed with nothing said is a task the next agent has to re-derive from the diff.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id",
      -      "summary"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"release\": Release a task you claimed (in_progress → open) so someone else can pick it up — use when you can't finish (out of context, blocked, wrong scope).",
      -    "properties": {
      -      "action": {
      -        "const": "release",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"reopen\": Recovery: send a closed task (done or cancelled) back to open and clear its completion metadata so it reads as unheld and claimable again. For a stuck in_progress task, use task(action=\"force_release\") instead (this is for closed tasks).",
      -    "properties": {
      -      "action": {
      -        "const": "reopen",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"force_release\": Admin recovery: release an in_progress task WITHOUT holding the claim, so it returns to open for others. The release is attributed to you in the claim history (not the prior claimer). For a closed task use task(action=\"reopen\"); to take a task over rather than free it, use destructive(action=\"force_claim_task\").",
      -    "properties": {
      -      "action": {
      -        "const": "force_release",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "action=\"loop_finalize\": Create the durable final loop envelope. Deterministic correctness comes only from the latest mechanically evidenced attempt; independent reviewer and operator intent/scope judgments remain separate fields. Approval requires all three, so model judgment can reject work but can never manufacture correctness.",
      -    "properties": {
      -      "action": {
      -        "const": "loop_finalize",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "The loop task to finalize (TASK-N).",
      -        "pattern": "^TASK-\\d+$",
      -        "type": "string"
      -      },
      -      "operator_summary": {
      -        "description": "Why the operator judged the change in or out of intent and scope.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "operator_verdict": {
      -        "description": "The operator's judgment of whether the change stays within the task's intent and scope.",
      -        "enum": [
      -          "approved",
      -          "rejected"
      -        ],
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "reviewer_summary": {
      -        "description": "Why the reviewer approved or rejected the change.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "reviewer_verdict": {
      -        "description": "The independent reviewer's judgment of the change.",
      -        "enum": [
      -          "approved",
      -          "rejected"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id",
      -      "reviewer_verdict",
      -      "reviewer_summary",
      -      "operator_verdict",
      -      "operator_summary"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"create\": Create a task under a component. One task ≈ one PR. `success_criteria` is required — it is the contract the implementer and the reviewer both work against. Pass `check` only when a command can genuinely decide done without a human; for unattended certification also pass `check_paths`. Most tasks have neither, and that is fine. Give a markdown body with ## Why / ## How / ## Test plan — the canonical contract headings are written for you from the arguments.",
      +    "properties": {
      +      "action": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "anchor_files": {
      +        "description": "(create only) Repo-relative file paths this task is about. Anchoring an open task to the code it touches surfaces it when an agent later edits that file — so they don't step on toes or duplicate planned work.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "anchor_symbols": {
      +        "description": "(create only) Symbol names this task is about (function / class / constant / env var).",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "assignee_user_id": {
      +        "anyOf": [
      +          {
      +            "format": "uuid",
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "(create only) Pre-assign to a user uuid (NOT a shareable id); usually leave null."
      +      },
      +      "body": {
      +        "description": "(create only) Markdown body (optional). Write it in plain style: one idea per sentence, active voice, lead with the condition, one term per concept, exact technical names.",
      +        "type": "string"
      +      },
      +      "check": {
      +        "description": "OPTIONAL — a success criterion you can RUN: a command that decides done WITHOUT a human (e.g. a test command that must exit 0, or a script that prints a number to compare against a target). Appended under `## Check`. A task that has one is runnable by a loop; unattended certification additionally requires `check_paths` so the maker cannot silently modify its own verifier. The verdict then comes from the command, not from anyone's opinion. Most tasks have no runnable check, and that is fine: omit it and a human decides when it's done, which is the normal answer for anything whose 'done' is a judgment (design, architecture, docs, ambiguous work). Do not invent a check to fill this field in. A made-up check is worse than no check: it launders a guess into something that looks like a fact, and an agent will then iterate against it and merge on it.",
      +        "type": "string"
      +      },
      +      "check_paths": {
      +        "description": "OPTIONAL — repo-relative paths the declared check depends on: its test/script and every fixture or directory it reads. Required to CERTIFY an unattended loop: `stele loop verify` fails closed when a task has a check but no declared check paths. These paths are explicit because guessing them from an arbitrary shell command silently under-protects the verifier. Repeat paths as needed.",
      +        "items": {
      +          "minLength": 1,
      +          "type": "string"
      +        },
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "component_id": {
      +        "description": "REQUIRED for create — parent component shareable id.",
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "(create only) Task kind; defaults to 'task'. Non-'task' kinds are non-claimable containers that roll up from their `blocks`-children: 'epic' groups related tasks; 'objective' is a standing goal (end-state in its body) with ordered 'milestone' phases under it.",
      +        "enum": [
      +          "task",
      +          "epic",
      +          "objective",
      +          "milestone"
      +        ],
      +        "type": "string"
      +      },
      +      "position": {
      +        "description": "(create only) Explicit ordering of a milestone within its objective (1-based).",
      +        "type": "integer"
      +      },
      +      "priority": {
      +        "anyOf": [
      +          {
      +            "enum": [
      +              "P0",
      +              "P1",
      +              "P2",
      +              "P3"
      +            ],
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "(create only) Priority P0 (most urgent) … P3. Omit/null = unprioritized."
      +      },
      +      "privacy_bypass": {
      +        "description": "true writes despite a privacy flag on a public project. Only meaningful after a flag; the user decides whether the content can be public.",
      +        "type": "boolean"
      +      },
      +      "privacy_false_positive": {
      +        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      +        "type": "boolean"
      +      },
      +      "privacy_judgement_id": {
      +        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      +        "type": "string"
      +      },
      +      "privacy_note": {
      +        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      +        "maxLength": 500,
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "scope": {
      +        "description": "(create only) Workspace scope. Omit or 'auto' = scope to the workspace mapped to the current git branch, else trunk (shared truth). 'trunk' = force shared truth even on a branch. Or pass a workspace name/id to target it. Branch-scoped writes are invisible to collaborators off that workspace.",
      +        "type": "string"
      +      },
      +      "success_criteria": {
      +        "description": "REQUIRED — how anyone (a person, or an agent picking this up cold) knows the task is DONE. State what must be TRUE when it's finished, not what you intend to do. Appended to the body under `## Success criteria`, which is the contract the implementer and the reviewer both work against — so a task without one is a task nobody can finish or check.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "target_date": {
      +        "description": "(create only) Optional soft target date — ISO date e.g. 2026-09-30. Valid on any kind: the date an objective or milestone is aimed at, and the date a plain task is expected by. Set it whenever someone committed to a deadline (\"I'll have it by Friday\"); a commitment with no date on it is a wish.",
      +        "type": "string"
      +      },
      +      "title": {
      +        "description": "REQUIRED for create — imperative one-liner (\"Add OAuth refresh\").",
      +        "maxLength": 300,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "topics": {
      +        "description": "(create only) Short tag list.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "component_id",
      +      "title",
      +      "success_criteria"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"claim\": Atomically claim a task (open → in_progress), recording you as owner. Claim before you start so others know you're on it. Returns the task, or { result: 'conflict' } if someone else holds it — no race window.",
      +    "properties": {
      +      "action": {
      +        "const": "claim",
      +        "type": "string"
      +      },
      +      "dispatched_with": {
      +        "description": "(claim only) Operator's full briefing prompt when this claim is from a dispatched sub-agent. It is stored with the claim, up to 16 KB; longer text is truncated with a warning.",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "REQUIRED for claim/complete/release/reopen/force_release — task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "parent_task_id": {
      +        "description": "(claim only) Operator's claimed task id (e.g. TASK-487) when this claim is from a sub-agent dispatched by the operator. Leave null for direct claims.",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"complete\": Mark a task done. REQUIRED `summary` is appended under ## Completion summary (what shipped, where it landed, what you learned). Also closes a container (epic/objective/milestone): no claim needed, but it is REFUSED while any child is unfinished, and the error names them. A container normally closes itself when its last child closes, so completing one is mainly how you record what it delivered — and it marks the close as yours, so a child reopening later won't undo it. The result may list nearby decision/architecture nodes to re-verify (still-true / edit / supersede); that part is advisory.",
      +    "properties": {
      +      "action": {
      +        "const": "complete",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "privacy_bypass": {
      +        "description": "true writes despite a privacy flag on a public project. Only meaningful after a flag; the user decides whether the content can be public.",
      +        "type": "boolean"
      +      },
      +      "privacy_false_positive": {
      +        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      +        "type": "boolean"
      +      },
      +      "privacy_judgement_id": {
      +        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      +        "type": "string"
      +      },
      +      "privacy_note": {
      +        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      +        "maxLength": 500,
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "summary": {
      +        "description": "REQUIRED — what actually happened. The graph only learns from what closing writes down: what shipped, where it landed, what you found out, what you'd warn the next person about. A task closed with nothing said is a task the next agent has to re-derive from the diff.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id",
      +      "summary"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"release\": Release a task you claimed (in_progress → open) so someone else can pick it up — use when you can't finish (out of context, blocked, wrong scope).",
      +    "properties": {
      +      "action": {
      +        "const": "release",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"reopen\": Recovery: send a closed task (done or cancelled) back to open and clear its completion metadata so it reads as unheld and claimable again. For a stuck in_progress task, use task(action=\"force_release\") instead (this is for closed tasks).",
      +    "properties": {
      +      "action": {
      +        "const": "reopen",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"force_release\": Admin recovery: release an in_progress task WITHOUT holding the claim, so it returns to open for others. The release is attributed to you in the claim history (not the prior claimer). For a closed task use task(action=\"reopen\"); to take a task over rather than free it, use destructive(action=\"force_claim_task\").",
      +    "properties": {
      +      "action": {
      +        "const": "force_release",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"loop_finalize\": Create the durable final loop envelope. Deterministic correctness comes only from the latest mechanically evidenced attempt; independent reviewer and operator intent/scope judgments remain separate fields. Approval requires all three, so model judgment can reject work but can never manufacture correctness.",
      +    "properties": {
      +      "action": {
      +        "const": "loop_finalize",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "The loop task to finalize (TASK-N).",
      +        "pattern": "^TASK-\\d+$",
      +        "type": "string"
      +      },
      +      "operator_summary": {
      +        "description": "Why the operator judged the change in or out of intent and scope.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "operator_verdict": {
      +        "description": "The operator's judgment of whether the change stays within the task's intent and scope.",
      +        "enum": [
      +          "approved",
      +          "rejected"
      +        ],
      +        "type": "string"
      +      },
      +      "privacy_bypass": {
      +        "description": "true writes despite a privacy flag on a public project. Only meaningful after a flag; the user decides whether the content can be public.",
      +        "type": "boolean"
      +      },
      +      "privacy_false_positive": {
      +        "description": "With privacy_bypass: true reports the privacy flag as wrong.",
      +        "type": "boolean"
      +      },
      +      "privacy_judgement_id": {
      +        "description": "With privacy_bypass: the judgement_id the privacy flag returned.",
      +        "type": "string"
      +      },
      +      "privacy_note": {
      +        "description": "With privacy_bypass: an optional short reason, kept with the bypass.",
      +        "maxLength": 500,
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "reviewer_summary": {
      +        "description": "Why the reviewer approved or rejected the change.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "reviewer_verdict": {
      +        "description": "The independent reviewer's judgment of the change.",
      +        "enum": [
      +          "approved",
      +          "rejected"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id",
      +      "reviewer_verdict",
      +      "reviewer_summary",
      +      "operator_verdict",
      +      "operator_summary"
      +    ],
      +    "type": "object"
      +  }
      +]
  4. Changed1 schema field changed
    • changedInput schema / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "description": "task action \"create\".",
      -    "properties": {
      -      "action": {
      -        "const": "create",
      -        "description": "Run the create action.",
      -        "type": "string"
      -      },
      -      "anchor_files": {
      -        "description": "(create only) Repo-relative file paths this task is about. Anchoring an open task to the code it touches surfaces it when an agent later edits that file — so they don't step on toes or duplicate planned work.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "anchor_symbols": {
      -        "description": "(create only) Symbol names this task is about (function / class / constant / env var).",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "assignee_user_id": {
      -        "anyOf": [
      -          {
      -            "format": "uuid",
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "(create only) Pre-assign to a user uuid (NOT a shareable id); usually leave null."
      -      },
      -      "body": {
      -        "description": "(create only) Markdown body (optional). Write it in plain style: one idea per sentence, active voice, lead with the condition, one term per concept, exact technical names.",
      -        "type": "string"
      -      },
      -      "check": {
      -        "description": "OPTIONAL — a success criterion you can RUN: a command that decides done WITHOUT a human (e.g. a test command that must exit 0, or a script that prints a number to compare against a target). Appended under `## Check`. A task that has one is runnable by a loop; unattended certification additionally requires `check_paths` so the maker cannot silently modify its own verifier. The verdict then comes from the command, not from anyone's opinion. Most tasks have no runnable check, and that is fine: omit it and a human decides when it's done, which is the normal answer for anything whose 'done' is a judgment (design, architecture, docs, ambiguous work). Do not invent a check to fill this field in. A made-up check is worse than no check: it launders a guess into something that looks like a fact, and an agent will then iterate against it and merge on it.",
      -        "type": "string"
      -      },
      -      "check_paths": {
      -        "description": "OPTIONAL — repo-relative paths the declared check depends on: its test/script and every fixture or directory it reads. Required to CERTIFY an unattended loop: `stele loop verify` fails closed when a task has a check but no declared check paths. These paths are explicit because guessing them from an arbitrary shell command silently under-protects the verifier. Repeat paths as needed.",
      -        "items": {
      -          "minLength": 1,
      -          "type": "string"
      -        },
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "component_id": {
      -        "description": "REQUIRED for create — parent component shareable id.",
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "(create only) Task kind; defaults to 'task'. Non-'task' kinds are non-claimable containers that roll up from their `blocks`-children: 'epic' groups related tasks; 'objective' is a standing goal (end-state in its body) with ordered 'milestone' phases under it.",
      -        "enum": [
      -          "task",
      -          "epic",
      -          "objective",
      -          "milestone"
      -        ],
      -        "type": "string"
      -      },
      -      "position": {
      -        "description": "(create only) Explicit ordering of a milestone within its objective (1-based).",
      -        "type": "integer"
      -      },
      -      "priority": {
      -        "anyOf": [
      -          {
      -            "enum": [
      -              "P0",
      -              "P1",
      -              "P2",
      -              "P3"
      -            ],
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "(create only) Priority P0 (most urgent) … P3. Omit/null = unprioritized."
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "scope": {
      -        "description": "(create only) Workspace scope. Omit or 'auto' = scope to the workspace mapped to the current git branch, else trunk (shared truth). 'trunk' = force shared truth even on a branch. Or pass a workspace name/id to target it. Branch-scoped writes are invisible to collaborators off that workspace.",
      -        "type": "string"
      -      },
      -      "success_criteria": {
      -        "description": "REQUIRED — how anyone (a person, or an agent picking this up cold) knows the task is DONE. State what must be TRUE when it's finished, not what you intend to do. Appended to the body under `## Success criteria`, which is the contract the implementer and the reviewer both work against — so a task without one is a task nobody can finish or check.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "target_date": {
      -        "description": "(create only) Optional soft target date — ISO date e.g. 2026-09-30. Valid on any kind: the date an objective or milestone is aimed at, and the date a plain task is expected by. Set it whenever someone committed to a deadline (\"I'll have it by Friday\"); a commitment with no date on it is a wish.",
      -        "type": "string"
      -      },
      -      "title": {
      -        "description": "REQUIRED for create — imperative one-liner (\"Add OAuth refresh\").",
      -        "maxLength": 300,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "topics": {
      -        "description": "(create only) Short tag list.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "component_id",
      -      "title",
      -      "success_criteria"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "task action \"claim\".",
      -    "properties": {
      -      "action": {
      -        "const": "claim",
      -        "description": "Run the claim action.",
      -        "type": "string"
      -      },
      -      "dispatched_with": {
      -        "description": "(claim only) Operator's full briefing prompt when this claim is from a dispatched sub-agent. It is stored with the claim, up to 16 KB; longer text is truncated with a warning.",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "REQUIRED for claim/complete/release/reopen/force_release — task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "parent_task_id": {
      -        "description": "(claim only) Operator's claimed task id (e.g. TASK-487) when this claim is from a sub-agent dispatched by the operator. Leave null for direct claims.",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "task action \"complete\".",
      -    "properties": {
      -      "action": {
      -        "const": "complete",
      -        "description": "Run the complete action.",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "summary": {
      -        "description": "REQUIRED — what actually happened. The graph only learns from what closing writes down: what shipped, where it landed, what you found out, what you'd warn the next person about. A task closed with nothing said is a task the next agent has to re-derive from the diff.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id",
      -      "summary"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "task action \"release\".",
      -    "properties": {
      -      "action": {
      -        "const": "release",
      -        "description": "Run the release action.",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "task action \"reopen\".",
      -    "properties": {
      -      "action": {
      -        "const": "reopen",
      -        "description": "Run the reopen action.",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "task action \"force_release\".",
      -    "properties": {
      -      "action": {
      -        "const": "force_release",
      -        "description": "Run the force_release action.",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "Task shareable id (e.g. TASK-42).",
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "task action \"loop_finalize\".",
      -    "properties": {
      -      "action": {
      -        "const": "loop_finalize",
      -        "description": "Run the loop_finalize action.",
      -        "type": "string"
      -      },
      -      "node_id": {
      -        "description": "The loop task to finalize (TASK-N).",
      -        "pattern": "^TASK-\\d+$",
      -        "type": "string"
      -      },
      -      "operator_summary": {
      -        "description": "Why the operator judged the change in or out of intent and scope.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "operator_verdict": {
      -        "description": "The operator's judgment of whether the change stays within the task's intent and scope.",
      -        "enum": [
      -          "approved",
      -          "rejected"
      -        ],
      -        "type": "string"
      -      },
      -      "project_slug": {
      -        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "reviewer_summary": {
      -        "description": "Why the reviewer approved or rejected the change.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "reviewer_verdict": {
      -        "description": "The independent reviewer's judgment of the change.",
      -        "enum": [
      -          "approved",
      -          "rejected"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "project_slug",
      -      "node_id",
      -      "reviewer_verdict",
      -      "reviewer_summary",
      -      "operator_verdict",
      -      "operator_summary"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"create\": Create a task under a component. One task ≈ one PR. `success_criteria` is required — it is the contract the implementer and the reviewer both work against. Pass `check` only when a command can genuinely decide done without a human; for unattended certification also pass `check_paths`. Most tasks have neither, and that is fine. Give a markdown body with ## Why / ## How / ## Test plan — the canonical contract headings are written for you from the arguments.",
      +    "properties": {
      +      "action": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "anchor_files": {
      +        "description": "(create only) Repo-relative file paths this task is about. Anchoring an open task to the code it touches surfaces it when an agent later edits that file — so they don't step on toes or duplicate planned work.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "anchor_symbols": {
      +        "description": "(create only) Symbol names this task is about (function / class / constant / env var).",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "assignee_user_id": {
      +        "anyOf": [
      +          {
      +            "format": "uuid",
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "(create only) Pre-assign to a user uuid (NOT a shareable id); usually leave null."
      +      },
      +      "body": {
      +        "description": "(create only) Markdown body (optional). Write it in plain style: one idea per sentence, active voice, lead with the condition, one term per concept, exact technical names.",
      +        "type": "string"
      +      },
      +      "check": {
      +        "description": "OPTIONAL — a success criterion you can RUN: a command that decides done WITHOUT a human (e.g. a test command that must exit 0, or a script that prints a number to compare against a target). Appended under `## Check`. A task that has one is runnable by a loop; unattended certification additionally requires `check_paths` so the maker cannot silently modify its own verifier. The verdict then comes from the command, not from anyone's opinion. Most tasks have no runnable check, and that is fine: omit it and a human decides when it's done, which is the normal answer for anything whose 'done' is a judgment (design, architecture, docs, ambiguous work). Do not invent a check to fill this field in. A made-up check is worse than no check: it launders a guess into something that looks like a fact, and an agent will then iterate against it and merge on it.",
      +        "type": "string"
      +      },
      +      "check_paths": {
      +        "description": "OPTIONAL — repo-relative paths the declared check depends on: its test/script and every fixture or directory it reads. Required to CERTIFY an unattended loop: `stele loop verify` fails closed when a task has a check but no declared check paths. These paths are explicit because guessing them from an arbitrary shell command silently under-protects the verifier. Repeat paths as needed.",
      +        "items": {
      +          "minLength": 1,
      +          "type": "string"
      +        },
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "component_id": {
      +        "description": "REQUIRED for create — parent component shareable id.",
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "(create only) Task kind; defaults to 'task'. Non-'task' kinds are non-claimable containers that roll up from their `blocks`-children: 'epic' groups related tasks; 'objective' is a standing goal (end-state in its body) with ordered 'milestone' phases under it.",
      +        "enum": [
      +          "task",
      +          "epic",
      +          "objective",
      +          "milestone"
      +        ],
      +        "type": "string"
      +      },
      +      "position": {
      +        "description": "(create only) Explicit ordering of a milestone within its objective (1-based).",
      +        "type": "integer"
      +      },
      +      "priority": {
      +        "anyOf": [
      +          {
      +            "enum": [
      +              "P0",
      +              "P1",
      +              "P2",
      +              "P3"
      +            ],
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "(create only) Priority P0 (most urgent) … P3. Omit/null = unprioritized."
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "scope": {
      +        "description": "(create only) Workspace scope. Omit or 'auto' = scope to the workspace mapped to the current git branch, else trunk (shared truth). 'trunk' = force shared truth even on a branch. Or pass a workspace name/id to target it. Branch-scoped writes are invisible to collaborators off that workspace.",
      +        "type": "string"
      +      },
      +      "success_criteria": {
      +        "description": "REQUIRED — how anyone (a person, or an agent picking this up cold) knows the task is DONE. State what must be TRUE when it's finished, not what you intend to do. Appended to the body under `## Success criteria`, which is the contract the implementer and the reviewer both work against — so a task without one is a task nobody can finish or check.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "target_date": {
      +        "description": "(create only) Optional soft target date — ISO date e.g. 2026-09-30. Valid on any kind: the date an objective or milestone is aimed at, and the date a plain task is expected by. Set it whenever someone committed to a deadline (\"I'll have it by Friday\"); a commitment with no date on it is a wish.",
      +        "type": "string"
      +      },
      +      "title": {
      +        "description": "REQUIRED for create — imperative one-liner (\"Add OAuth refresh\").",
      +        "maxLength": 300,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "topics": {
      +        "description": "(create only) Short tag list.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "component_id",
      +      "title",
      +      "success_criteria"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"claim\": Atomically claim a task (open → in_progress), recording you as owner. Claim before you start so others know you're on it. Returns the task, or { result: 'conflict' } if someone else holds it — no race window.",
      +    "properties": {
      +      "action": {
      +        "const": "claim",
      +        "type": "string"
      +      },
      +      "dispatched_with": {
      +        "description": "(claim only) Operator's full briefing prompt when this claim is from a dispatched sub-agent. It is stored with the claim, up to 16 KB; longer text is truncated with a warning.",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "REQUIRED for claim/complete/release/reopen/force_release — task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "parent_task_id": {
      +        "description": "(claim only) Operator's claimed task id (e.g. TASK-487) when this claim is from a sub-agent dispatched by the operator. Leave null for direct claims.",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"complete\": Mark a task done. REQUIRED `summary` is appended under ## Completion summary (what shipped, where it landed, what you learned). Also closes a container (epic/objective/milestone): no claim needed, but it is REFUSED while any child is unfinished, and the error names them. A container normally closes itself when its last child closes, so completing one is mainly how you record what it delivered — and it marks the close as yours, so a child reopening later won't undo it. The result may list nearby decision/architecture nodes to re-verify (still-true / edit / supersede); that part is advisory.",
      +    "properties": {
      +      "action": {
      +        "const": "complete",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "summary": {
      +        "description": "REQUIRED — what actually happened. The graph only learns from what closing writes down: what shipped, where it landed, what you found out, what you'd warn the next person about. A task closed with nothing said is a task the next agent has to re-derive from the diff.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id",
      +      "summary"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"release\": Release a task you claimed (in_progress → open) so someone else can pick it up — use when you can't finish (out of context, blocked, wrong scope).",
      +    "properties": {
      +      "action": {
      +        "const": "release",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"reopen\": Recovery: send a closed task (done or cancelled) back to open and clear its completion metadata so it reads as unheld and claimable again. For a stuck in_progress task, use task(action=\"force_release\") instead (this is for closed tasks).",
      +    "properties": {
      +      "action": {
      +        "const": "reopen",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"force_release\": Admin recovery: release an in_progress task WITHOUT holding the claim, so it returns to open for others. The release is attributed to you in the claim history (not the prior claimer). For a closed task use task(action=\"reopen\"); to take a task over rather than free it, use destructive(action=\"force_claim_task\").",
      +    "properties": {
      +      "action": {
      +        "const": "force_release",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "Task shareable id (e.g. TASK-42).",
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "action=\"loop_finalize\": Create the durable final loop envelope. Deterministic correctness comes only from the latest mechanically evidenced attempt; independent reviewer and operator intent/scope judgments remain separate fields. Approval requires all three, so model judgment can reject work but can never manufacture correctness.",
      +    "properties": {
      +      "action": {
      +        "const": "loop_finalize",
      +        "type": "string"
      +      },
      +      "node_id": {
      +        "description": "The loop task to finalize (TASK-N).",
      +        "pattern": "^TASK-\\d+$",
      +        "type": "string"
      +      },
      +      "operator_summary": {
      +        "description": "Why the operator judged the change in or out of intent and scope.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "operator_verdict": {
      +        "description": "The operator's judgment of whether the change stays within the task's intent and scope.",
      +        "enum": [
      +          "approved",
      +          "rejected"
      +        ],
      +        "type": "string"
      +      },
      +      "project_slug": {
      +        "description": "Project slug, e.g. \"acme-app\" — list(what=\"projects\") returns yours.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "reviewer_summary": {
      +        "description": "Why the reviewer approved or rejected the change.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "reviewer_verdict": {
      +        "description": "The independent reviewer's judgment of the change.",
      +        "enum": [
      +          "approved",
      +          "rejected"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "project_slug",
      +      "node_id",
      +      "reviewer_verdict",
      +      "reviewer_summary",
      +      "operator_verdict",
      +      "operator_summary"
      +    ],
      +    "type": "object"
      +  }
      +]
  5. First observed

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false, destructiveHint=false, openWorldHint=true; the description adds real context beyond them — that claim/complete 'route through the atomic claim path that records accountability' and that status must not be flipped by hand, plus that loop_finalize keeps correctness, review, and intent/scope verdicts separate. It stops short of failure modes (e.g. what happens when a claim is already held), and it correctly does not contradict the destructiveHint=false annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences, front-loaded with the action enum so the reader immediately sees the tool's surface. Every sentence carries information (workflow order, prohibition, loop_finalize semantics, sibling routing), though the loop_finalize clause is compact enough to read as cryptic without the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a seven-modal tool with an output schema present and 100% schema coverage, the description supplies the workflow policy the schema cannot: claim-before-start, complete-with-summary, and sibling routing for destructive actions. Remaining gaps (release/reopen semantics, error behavior) are secondary and partly inferable from the per-action schema titles.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the per-field semantics are already fully documented and the baseline would be 3. The description adds action-level meaning on top: it clarifies the ordering discipline for claim/complete and the non-obvious separation of concerns in loop_finalize, which is the meaning an agent most needs when choosing an action.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names the specific resource (task) and enumerates all seven lifecycle operations verbatim: 'create | claim | complete | release | reopen | force_release | loop_finalize'. It also distinguishes itself from the closest sibling by explicitly routing 'Cancelling a task and force-claiming one' to the `destructive` tool. An agent can tell this is the write-side task lifecycle tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit workflow guidance: 'Claim before you start and complete when done', a prohibition ('never flip a task's status by hand'), and names the alternative tool for cancel/force-claim. It does not explain the conditions that select release vs reopen vs force_release vs loop_finalize, so the guidance is strong but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.