[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6HVCF65VGAHKCFTG3CKBJVG":3,"skill-same:01M6HVCF65VGAHKCFTG3CKBJVG":62},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":24,"linkOnly":25,"markdownContent":26,"markdownBody":27,"frontMatter":28,"refName":29,"commitSha":30,"skillDirectory":31,"forksCount":32,"repositoryHtmlUrl":33,"repositoryHomepageUrl":34,"ownerHtmlUrl":35,"ownerBlogUrl":6,"ownerDescription":36,"updatedAt":37,"install":38,"resources":51},"01M6HVCF65VGAHKCFTG3CKBJVG","task",null,"Tracks chat assignments, steering in a task thread, WORKER completions, and confirmations alongside task progress and results.","gtapps\u002Fhermitd","gtapps","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F16778396?v=4","01M6HTX8TNTPQN3NXRVA63VHTH","01M6HTX8Z23S531ZPPA5DKJVD0",84,"MIT","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Ftask\u002FSKILL.md",[],[5,18,19,20,21,22,23],"chat","progress","tracks","results","worker","thread","2026-11-10 10:12:30",false,"---\nname: task\ndescription: 'Tracks chat assignments, steering in a task thread, WORKER completions, and confirmations alongside task progress and results.'\n---\n\n# Tasks\n\nRead `.hermit\u002FTASKS.md` first for record threshold, wording and confirmation policy. Use `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask.ts \u003Cverb> .hermit ...` for every record operation. Never edit `tasks\u002F` directly. All `task.ts` shorthand below uses that full pinned command. Consult `..\u002F..\u002Fdocs\u002Ftask-records.md` for the command contract.\n\n## Commands\n- `task-note`: `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask.ts note .hermit`\n- `conversation`: `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Fconversation.ts .hermit`\n\n## Intake\nTyped terminal turn: `task answer \u003Cid> --local --reply \u003Ctoken>`, `task dismiss \u003Cid> --reason-stdin`; no prompt, bypass refuses `--local`. Chat turn: `--chat`\u002F`--user`.\nDecision replies: `task answer [\u003Cid>] --chat \u003Ckey> --user \u003Csender-id> --reply \u003Ctoken>` first. In any language, map to yes, no, a number or label. Respect `not_decider`, `consent_required`, `stale` and `ambiguous`. Input resumes `decision.resume`. Before task steering, run `task.ts list .hermit --open --conversation \u003CsourceKey>:\u003Cchat_id>`. Select via the task thread or hook's open-tasks line; on ambiguity, ask once naming candidates. Questions open nothing.\n\nUse `open --title ... --requester \u003CsourceKey>:\u003Cuser_id> --done ...` for assignments. Pass requester display name, origin message id, conversation, due date and explicitly named approver when available. A record's `--card` stays with the resident, which also hands it to a worker and takes it back with `note \u003Cid> --owner worker:\u003CagentId>` \u002F `--owner resident`; a worker never opens or closes a record itself. Resident readiness is handled by `\u002Fhermitd:resident-start`. Work whose definition of done the agent can observe gets a check, at `open` when the predicate is already known, otherwise with `note \u003Cid> --check` once the inputs have been read.\n\nDispatch independent new work at once, in parallel with running tasks. Only for work explicitly requested after the current work, open a resident record and state its queue position from the open-task ordering. After a close or cancel, continue with `next_queued` in the same turn when the digest names a record. In a chat without threads with two or more open tasks, resident-composed replies and cards name their task by handle.\n\n### Complete a task turn\n\nFor a task assignment or update, follow this order once the caller's authorization check has passed (`channel-responder\u002FSKILL.md` § 1c for a channel turn):\n\n1. **Accept an assignment.** Send the short \"On it\" acknowledgement through the channel, then create its record using the route § Channel task procedures selects. Do this before reading task inputs or doing substantive work.\n2. **Do the work.** Record progress on the selected record per § Progress and results.\n3. **Deliver and record the outcome.** Send the outcome through the channel. When it needs human acceptance, pipe that same outcome into `task.ts block .hermit \u003Cid> --result-stdin` before ending the turn. Require the returned digest to say `listing: \"unconfirmed\"` with a positive `result_rev`; this saves the result and waits on the named approver or requester.\n4. **Acknowledge updates.** After a requested record change succeeds, acknowledge it through the channel, including short bookkeeping-only turns. A terminal summary does not complete this step. Confirmed results close through § Closure's revision and actor checks.\n\nFinished recommendations, drafts and reviews awaiting acceptance require `--result-stdin`. The `--waiting-on` \u002F `--status-line` \u002F `--next` form records an unfinished-work stall, not a result. If a finished outcome returns a stall digest, run the result form before ending the turn.\n\nInspect each command's result. If delivery or recording fails, report what remains incomplete through the available channel; do not claim the failed step succeeded.\n\n## Applying proposal tasks\n\nAt intake, a `kind: proposal` record follows [proposal-create\u002Fapply.md](..\u002Fproposal-create\u002Fapply.md), which also says when an instruction is its consent. The resident can apply a one-line configuration edit; use `hermitd:task-worker` for larger work. Never open another task to implement it. A `done` worker response with a passing executable check closes through `task-check.ts`; authored content posts `block --result-stdin` on this record, opening an admin result decision. For `needs-input`, REJECT opens a new `consent` decision with the evidence; an unsettled implementation choice opens an `input` decision with options and `resume` naming the procedure. Pass `--decision` JSON to `block`, plus status and next step for an unfinished wait.\n\n## Channel task procedures\n\n- **Task thread**: a thread holds one open task; chats without threads share records named by the hook’s open-tasks line. With `[task thread \u003Ckey>: …]`, continuations steer that record; unrelated one-offs answered in this reply open nothing. Unrelated work meeting TASKS.md’s threshold opens its own task. When unsure, ask once. Steering to watch something goes to `\u002Fhermitd:watch \u003Cinstruction>` in this turn.\n  - **Open the thread.** Run `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Fconversation.ts .hermit thread-open --source '\u003CsourceKey>' --chat-id '\u003Cchat_id>' --message-id '\u003Cmessage_id>' --name '\u003Ctitle>'`, adding `--thread-id '\u003Cvalue>'` when the tag carries the thread attribute. The title is 1 to 100 characters, distinguishing detail (subject or id) first and shared details (model, effort) last. Its JSON `key` is `\u003Ckey>`, `chat_id` is the destination chat, and any `reply` parameters go on every reply in the task thread. On `thread_busy`, Read [branches.md](branches.md) § Busy thread and follow it before posting a card. On `error`, report it and create no record.\n  - **Several assignments in one message.** One message is one task unless the requester asks for separate tasks; only then does each get its own record, thread, card and worker. Run one `thread-open` per assignment with the same `--message-id` and batch the independent calls. Inside a thread, finish each assignment’s `thread-open` and `open` before the next `thread-open`; the first takes a free thread and later ones get `thread_busy`. End the turn only after the last dispatch.\n  - **Acknowledge, then record.** Reply “On it: \u003Csummary>” with the channel's reply tool in the destination, with `reply_to` set to the incoming message when no thread was opened. That reply is the progress card. Run `task.ts open .hermit --owner resident --conversation \u003Ckey> --card '{\"chat_id\":\"\u003Cdestination-chat-id>\",\"message_id\":\"\u003Csent-id>\"}' --requester \u003CsourceKey>:\u003Cuser_id> --origin-message-id \u003Cmessage_id> --title ... --done ...`. Omit `--card` when the channel returned no message id; do not invent one. On `thread_required`, you skipped the thread: open it from the assignment's origin `--message-id`, post the card in the destination, and retry `open` with the returned key. On `thread_busy`, follow [branches.md](branches.md) § Busy thread.\n  - **Choose at intake.** Only if the requester asks for a session, run `\u002Fhermitd:spawn-session` in this record's turn; never offer one. Else **Dispatch the worker**.\n  - **Dispatch the worker.** Download the message's attachments first. Dispatch `hermitd:task-worker` with the `Agent` tool in the background, passing the record id, the brief, `\u003Ckey>`, and the attachment paths. When the requester names an effort level for the work (`low`, `medium`, `high`, `xhigh` or `max`), pass it as the Agent call's `effort`; otherwise omit `effort` so the worker's default applies. Then run `task.ts note .hermit \u003Cid> --owner worker:\u003CagentId>` with the id the dispatch returned, and end the turn.\n  - **Steer the running worker.** For a continuation of a record whose owner is a worker, `SendMessage` the body to the id in the record's `owner`, including after a resident `\u002Fclear` (the worker survives it and delivery lands at its next tool round). On success pipe the steer into `task.ts note .hermit \u003Cid>` and end the turn.\n  - **Replace an unreachable worker.** Only when that send fails, Read [branches.md](branches.md) § Replace an unreachable worker and follow it.\n  - **Take the worker's result.** A subagent completion ending in `WORKER \u003Ctask-id> done \u003Cid>` or `WORKER \u003Ctask-id> needs-input \u003Cid>` belongs to the named record; ignore it when the completing agent's id is not that record's `owner`. Otherwise run `task.ts note .hermit \u003Ctask-id> --owner resident` first. For `done`, reply in `\u003Ckey>` with exactly `[[helper-report \u003Ctask-id> \u003Cid>]]` (the relay hook substitutes the file), then run `task.ts block .hermit \u003Ctask-id> --result-stdin \u003C .hermit\u002Fhelper-reports\u002F\u003Cid>.md`, so the requester's confirmation closes it through § Closure; a check follows § Progress and results. For `needs-input`, post the same placeholder and run `task.ts block .hermit \u003Ctask-id> --waiting-on \u003Crequester> --status-line ... --next ...`; if an `Unreachable:` line precedes `WORKER`, send it as a maintainer-only notice and wait on `maintainer` instead.\n  - **Steer the bound session.** For a selected helper-owned record or `[bound tasks]` route, confirmations and parking work as for `owner=resident`; `!` commands follow **Conversation command**. `SendMessage` other messages to the `owner` session, with `notify_when_idle: true`; unless a live `peer-idle` entry has it, register it via [watch\u002Fsession-watch.md](..\u002Fwatch\u002Fsession-watch.md) § Registering an existing idle subscription with `record`. Note the steer. Not listed: take the **No row** branch of [spawn-session\u002Freuse-spawned-helper.md](..\u002Fspawn-session\u002Freuse-spawned-helper.md) with the latest `Handed to helper \u003Cn> (\u003Csid>)` note's sid and this message as brief, then watch it with only `--id \u003Cbg-id> --record \u003Cid>`. If it cannot resume, run `task.ts note .hermit \u003Cid> --owner resident`, say so, offer a worker. Approvals happen in the session (`claude attach \u003Cid>` or Remote Control), never relayed. A confirmation asking for the next phase closes the record, opens the next, binds it with `task.ts note .hermit \u003Cnew-id> --owner helper:\u003Cn>`, and sends the brief.\n  - **Park the task.** A message asking to park, pause or hold the thread's task, on an `owner=resident` or `owner=helper` thread, is a stall: run `task.ts block .hermit \u003Cid> --waiting-on \u003Crequester> --status-line ... --next ...` and confirm in the thread.\n  - **Answer a waiting record.** For a non-command message continuing a resident-owned waiting record, the resident may answer the waiting record itself when the work fits this turn, ending the turn with the applicable record commands on the injected `[waiting task ...]` line. For work that outlasts the turn, Read [branches.md](branches.md) § Replace an unreachable worker, write its history file, and build its brief plus `\u003Ckey>` and the requester's message, since a resumed worker may have lost its context. When the annotation carries `last_worker`, `SendMessage` that brief to that id and, on success, run `task.ts note .hermit \u003Cid> --owner worker:\u003Clast_worker> --clear-waiting`. On a refused send or no `last_worker`, dispatch as that section says, adding `--clear-waiting` to its owner note.\n  - Terminal assignments never go through here; they follow § Complete a task turn.\n\n- **Conversation command**: execute only the hook's `[conversation command: \u003Cname>]` annotation after the caller's authorization check has passed (`channel-responder\u002FSKILL.md` § 1c for a channel turn). A `[conversation command: restart needs a handle: …]` annotation gets a short reply naming those handles and starts nothing. A `[conversation command refused: …]` annotation gets that plain refusal; never invoke the harness command. A `[conversation command outside a task thread]` annotation gets a short explanation that the command needs an open task thread, and starts nothing.\n  - For `helper-switch`, `help`, `mute`, `unmute` or `restart`, Read [branches.md](branches.md) § Conversation command and follow it.\n  - Return after the command; do not mutate another record or continue into another classification.\n\nAll conversation script arguments are shell-quoted values. `history` includes admitted inbound senders and all outbound rows. `history` and `thread-open` take no key, only `--source`, `--chat-id`, `--message-id`, `--thread-id`, `--name`, and `--limit` options. Parse each command's result before moving on; pass message text as quoted arguments, never interpolate it into executable code.\n\n- **New instruction** (\"work on X\", \"switch to Y\", \"prioritize Z\")\n  - In an open **Task thread**, apply its continuation \u002F one-off \u002F separate-work rule above.\n  - In a chat without threads, new independent work gets a new record and immediate dispatch; a continuation steers the selected record. If unsure which record it continues, ask once naming them.\n  - If no record is selected: treat as a new **Task thread** (above)\n  - If compatible with current task: pipe the steering into `task.ts note .hermit \u003Cid> --actor \u003CsourceKey>:\u003Cuser_id>` and confirm; the existing progress card, if any, picks the change up at its next milestone\n  - If it would replace the current task: confirm with the operator before switching. The replacement follows the **Task thread** rule and gets its own card; the old card's id is never reused\n  - After confirmation of replacement, use `task.ts cancel .hermit \u003Cold-id> --actor \u003CsourceKey>:\u003Cuser_id> --reason-stdin` or `task.ts block .hermit \u003Cold-id> --waiting-on \u003Chuman> --status-line ... --next ...`, then follow **Open the thread** and **Acknowledge, then record** for the replacement.\n  - An ask to do work after the current task follows **Open the thread** and **Acknowledge, then record**; § Intake covers its queue position.\n  - Never silently abandon work in progress\n\n## Worker status\n\n  - Read `task.ts list .hermit --open --owner 'worker:*' --json` and summarize what each worker is carrying. A trusted controller may see every row; another allowed sender gets only this chat's records. Do not disclose another chat's task text. This is the model-composed status reply; the deterministic `!status` hook keeps its existing behavior.\n\n## Progress and results\nPipe one progress line into `note \u003Cid>`, pairing it with milestone card edits. Metadata flags include `--due`, `--card`, `--clear-waiting`, `--decision`, and `--approval \"\u003Cactor>: \u003Cwhat>\"`. When the operator or the work changes direction on an open record (scope dropped, date moved, approach swapped), pipe `\u003Cwhat changed>, \u003Cwhy>` into `note \u003Cid> --decision`. Ordinary progress stays a plain note. A changed definition uses `note \u003Cid> --done ... --actor \u003Chuman identity>`: it increments result_rev and clears the old result and check.\n\nRecord every outcome, not only one awaiting acceptance, with § Complete a task turn step 3's command and digest check; terminal-origin work posts in the terminal. After that, a record with a check runs `task-check.ts \u003Cid>` in the same turn; a pass closes it and the reply names the close with the proof; a fail, refused run or permission prompt leaves it unconfirmed, not retried that turn, for the daily run.\n\nA stall in unfinished work requires `--waiting-on`, `--status-line` and `--next`; post the digest's one status\u002Fnext-step message to its requester in its conversation.\n\n## Closure\nWhen a close digest carries `next`, follow it to read [learn.md](learn.md) and review once in the main session before the close reply. The review is best effort; a lost review is not resumed.\nStored status is only `open` or `closed`; closed_by is only `check`, `confirmed`, `cancelled` or null. `close`, `cancel`, and a passing `task-check.ts` run close records. Never infer closure from harness idleness.\n\nUse `close \u003Cid> --by confirmed --actor \u003CsourceKey>:\u003Cuser_id> --result-rev \u003Ccurrent> --reason-stdin` for confirmation of a posted result; with none posted, close without `--result-rev` when the requester explicitly says the work is done (an acknowledgement is not). `TASKS.md` defines what counts as confirmation. Close with a reason quoting the message that confirmed; the reply names the close so the requester can object. When one message both accepts the result and asks for new work, close the accepted record first, then classify the new request. The revision must match and a named approver must be the actor. Typed decisions use the decider-or-admin rule enforced by `task answer`; protected close or clear-wait operations carry `--chat --user`. Other records retain shared human control. There is no owner list.\n\nUse `close \u003Cid> --by check --actor hermit --claim \u003Clinked claim>` only when the later claim is held. A resolved duty uses its matching `duty:\u003Cname>` actor and dedupe key. Free-text proof alone cannot close a task. Use `cancel \u003Cid> --actor \u003Chuman identity> --reason-stdin` with a nonempty reason to cancel.\n\n## Standup and duties\nBefore reading `standup --json` output or acting on a duty, Read [branches.md](branches.md) § Standup and duties.\n\n## Lessons and executable checks\nBefore closing, pipe any lesson into `task.ts lesson .hermit \u003Cid>`. Omit this operation when there is no lesson. When a lesson recorded earlier on the record turned out wrong, add a lesson that names the correction.\n\nSet a command with `open --check '\u003Ccommand>'` or `note \u003Cid> --check '\u003Ccommand>'`; `--check clear` removes it. The command exits 0 only when the whole definition of done holds (a pull request is merged, not merely fetchable). It only observes and never writes, deletes, sends or deploys. A named approver may still require confirmation after a check passes. On an approved proposal, attaching the first check preserves consent; replacing or clearing an existing check or changing `--done` requires new consent. A changed definition of done clears the check, so the same `note` supplies a replacement when one still applies. Run `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask-check.ts \u003Cid>` to evaluate it from the project root, subject to the normal command permission gate. Exit 0 closes by `check`; a nonzero exit records progress.\n","# Tasks\n\nRead `.hermit\u002FTASKS.md` first for record threshold, wording and confirmation policy. Use `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask.ts \u003Cverb> .hermit ...` for every record operation. Never edit `tasks\u002F` directly. All `task.ts` shorthand below uses that full pinned command. Consult `..\u002F..\u002Fdocs\u002Ftask-records.md` for the command contract.\n\n## Commands\n- `task-note`: `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask.ts note .hermit`\n- `conversation`: `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Fconversation.ts .hermit`\n\n## Intake\nTyped terminal turn: `task answer \u003Cid> --local --reply \u003Ctoken>`, `task dismiss \u003Cid> --reason-stdin`; no prompt, bypass refuses `--local`. Chat turn: `--chat`\u002F`--user`.\nDecision replies: `task answer [\u003Cid>] --chat \u003Ckey> --user \u003Csender-id> --reply \u003Ctoken>` first. In any language, map to yes, no, a number or label. Respect `not_decider`, `consent_required`, `stale` and `ambiguous`. Input resumes `decision.resume`. Before task steering, run `task.ts list .hermit --open --conversation \u003CsourceKey>:\u003Cchat_id>`. Select via the task thread or hook's open-tasks line; on ambiguity, ask once naming candidates. Questions open nothing.\n\nUse `open --title ... --requester \u003CsourceKey>:\u003Cuser_id> --done ...` for assignments. Pass requester display name, origin message id, conversation, due date and explicitly named approver when available. A record's `--card` stays with the resident, which also hands it to a worker and takes it back with `note \u003Cid> --owner worker:\u003CagentId>` \u002F `--owner resident`; a worker never opens or closes a record itself. Resident readiness is handled by `\u002Fhermitd:resident-start`. Work whose definition of done the agent can observe gets a check, at `open` when the predicate is already known, otherwise with `note \u003Cid> --check` once the inputs have been read.\n\nDispatch independent new work at once, in parallel with running tasks. Only for work explicitly requested after the current work, open a resident record and state its queue position from the open-task ordering. After a close or cancel, continue with `next_queued` in the same turn when the digest names a record. In a chat without threads with two or more open tasks, resident-composed replies and cards name their task by handle.\n\n### Complete a task turn\n\nFor a task assignment or update, follow this order once the caller's authorization check has passed (`channel-responder\u002FSKILL.md` § 1c for a channel turn):\n\n1. **Accept an assignment.** Send the short \"On it\" acknowledgement through the channel, then create its record using the route § Channel task procedures selects. Do this before reading task inputs or doing substantive work.\n2. **Do the work.** Record progress on the selected record per § Progress and results.\n3. **Deliver and record the outcome.** Send the outcome through the channel. When it needs human acceptance, pipe that same outcome into `task.ts block .hermit \u003Cid> --result-stdin` before ending the turn. Require the returned digest to say `listing: \"unconfirmed\"` with a positive `result_rev`; this saves the result and waits on the named approver or requester.\n4. **Acknowledge updates.** After a requested record change succeeds, acknowledge it through the channel, including short bookkeeping-only turns. A terminal summary does not complete this step. Confirmed results close through § Closure's revision and actor checks.\n\nFinished recommendations, drafts and reviews awaiting acceptance require `--result-stdin`. The `--waiting-on` \u002F `--status-line` \u002F `--next` form records an unfinished-work stall, not a result. If a finished outcome returns a stall digest, run the result form before ending the turn.\n\nInspect each command's result. If delivery or recording fails, report what remains incomplete through the available channel; do not claim the failed step succeeded.\n\n## Applying proposal tasks\n\nAt intake, a `kind: proposal` record follows [proposal-create\u002Fapply.md](..\u002Fproposal-create\u002Fapply.md), which also says when an instruction is its consent. The resident can apply a one-line configuration edit; use `hermitd:task-worker` for larger work. Never open another task to implement it. A `done` worker response with a passing executable check closes through `task-check.ts`; authored content posts `block --result-stdin` on this record, opening an admin result decision. For `needs-input`, REJECT opens a new `consent` decision with the evidence; an unsettled implementation choice opens an `input` decision with options and `resume` naming the procedure. Pass `--decision` JSON to `block`, plus status and next step for an unfinished wait.\n\n## Channel task procedures\n\n- **Task thread**: a thread holds one open task; chats without threads share records named by the hook’s open-tasks line. With `[task thread \u003Ckey>: …]`, continuations steer that record; unrelated one-offs answered in this reply open nothing. Unrelated work meeting TASKS.md’s threshold opens its own task. When unsure, ask once. Steering to watch something goes to `\u002Fhermitd:watch \u003Cinstruction>` in this turn.\n  - **Open the thread.** Run `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Fconversation.ts .hermit thread-open --source '\u003CsourceKey>' --chat-id '\u003Cchat_id>' --message-id '\u003Cmessage_id>' --name '\u003Ctitle>'`, adding `--thread-id '\u003Cvalue>'` when the tag carries the thread attribute. The title is 1 to 100 characters, distinguishing detail (subject or id) first and shared details (model, effort) last. Its JSON `key` is `\u003Ckey>`, `chat_id` is the destination chat, and any `reply` parameters go on every reply in the task thread. On `thread_busy`, Read [branches.md](branches.md) § Busy thread and follow it before posting a card. On `error`, report it and create no record.\n  - **Several assignments in one message.** One message is one task unless the requester asks for separate tasks; only then does each get its own record, thread, card and worker. Run one `thread-open` per assignment with the same `--message-id` and batch the independent calls. Inside a thread, finish each assignment’s `thread-open` and `open` before the next `thread-open`; the first takes a free thread and later ones get `thread_busy`. End the turn only after the last dispatch.\n  - **Acknowledge, then record.** Reply “On it: \u003Csummary>” with the channel's reply tool in the destination, with `reply_to` set to the incoming message when no thread was opened. That reply is the progress card. Run `task.ts open .hermit --owner resident --conversation \u003Ckey> --card '{\"chat_id\":\"\u003Cdestination-chat-id>\",\"message_id\":\"\u003Csent-id>\"}' --requester \u003CsourceKey>:\u003Cuser_id> --origin-message-id \u003Cmessage_id> --title ... --done ...`. Omit `--card` when the channel returned no message id; do not invent one. On `thread_required`, you skipped the thread: open it from the assignment's origin `--message-id`, post the card in the destination, and retry `open` with the returned key. On `thread_busy`, follow [branches.md](branches.md) § Busy thread.\n  - **Choose at intake.** Only if the requester asks for a session, run `\u002Fhermitd:spawn-session` in this record's turn; never offer one. Else **Dispatch the worker**.\n  - **Dispatch the worker.** Download the message's attachments first. Dispatch `hermitd:task-worker` with the `Agent` tool in the background, passing the record id, the brief, `\u003Ckey>`, and the attachment paths. When the requester names an effort level for the work (`low`, `medium`, `high`, `xhigh` or `max`), pass it as the Agent call's `effort`; otherwise omit `effort` so the worker's default applies. Then run `task.ts note .hermit \u003Cid> --owner worker:\u003CagentId>` with the id the dispatch returned, and end the turn.\n  - **Steer the running worker.** For a continuation of a record whose owner is a worker, `SendMessage` the body to the id in the record's `owner`, including after a resident `\u002Fclear` (the worker survives it and delivery lands at its next tool round). On success pipe the steer into `task.ts note .hermit \u003Cid>` and end the turn.\n  - **Replace an unreachable worker.** Only when that send fails, Read [branches.md](branches.md) § Replace an unreachable worker and follow it.\n  - **Take the worker's result.** A subagent completion ending in `WORKER \u003Ctask-id> done \u003Cid>` or `WORKER \u003Ctask-id> needs-input \u003Cid>` belongs to the named record; ignore it when the completing agent's id is not that record's `owner`. Otherwise run `task.ts note .hermit \u003Ctask-id> --owner resident` first. For `done`, reply in `\u003Ckey>` with exactly `[[helper-report \u003Ctask-id> \u003Cid>]]` (the relay hook substitutes the file), then run `task.ts block .hermit \u003Ctask-id> --result-stdin \u003C .hermit\u002Fhelper-reports\u002F\u003Cid>.md`, so the requester's confirmation closes it through § Closure; a check follows § Progress and results. For `needs-input`, post the same placeholder and run `task.ts block .hermit \u003Ctask-id> --waiting-on \u003Crequester> --status-line ... --next ...`; if an `Unreachable:` line precedes `WORKER`, send it as a maintainer-only notice and wait on `maintainer` instead.\n  - **Steer the bound session.** For a selected helper-owned record or `[bound tasks]` route, confirmations and parking work as for `owner=resident`; `!` commands follow **Conversation command**. `SendMessage` other messages to the `owner` session, with `notify_when_idle: true`; unless a live `peer-idle` entry has it, register it via [watch\u002Fsession-watch.md](..\u002Fwatch\u002Fsession-watch.md) § Registering an existing idle subscription with `record`. Note the steer. Not listed: take the **No row** branch of [spawn-session\u002Freuse-spawned-helper.md](..\u002Fspawn-session\u002Freuse-spawned-helper.md) with the latest `Handed to helper \u003Cn> (\u003Csid>)` note's sid and this message as brief, then watch it with only `--id \u003Cbg-id> --record \u003Cid>`. If it cannot resume, run `task.ts note .hermit \u003Cid> --owner resident`, say so, offer a worker. Approvals happen in the session (`claude attach \u003Cid>` or Remote Control), never relayed. A confirmation asking for the next phase closes the record, opens the next, binds it with `task.ts note .hermit \u003Cnew-id> --owner helper:\u003Cn>`, and sends the brief.\n  - **Park the task.** A message asking to park, pause or hold the thread's task, on an `owner=resident` or `owner=helper` thread, is a stall: run `task.ts block .hermit \u003Cid> --waiting-on \u003Crequester> --status-line ... --next ...` and confirm in the thread.\n  - **Answer a waiting record.** For a non-command message continuing a resident-owned waiting record, the resident may answer the waiting record itself when the work fits this turn, ending the turn with the applicable record commands on the injected `[waiting task ...]` line. For work that outlasts the turn, Read [branches.md](branches.md) § Replace an unreachable worker, write its history file, and build its brief plus `\u003Ckey>` and the requester's message, since a resumed worker may have lost its context. When the annotation carries `last_worker`, `SendMessage` that brief to that id and, on success, run `task.ts note .hermit \u003Cid> --owner worker:\u003Clast_worker> --clear-waiting`. On a refused send or no `last_worker`, dispatch as that section says, adding `--clear-waiting` to its owner note.\n  - Terminal assignments never go through here; they follow § Complete a task turn.\n\n- **Conversation command**: execute only the hook's `[conversation command: \u003Cname>]` annotation after the caller's authorization check has passed (`channel-responder\u002FSKILL.md` § 1c for a channel turn). A `[conversation command: restart needs a handle: …]` annotation gets a short reply naming those handles and starts nothing. A `[conversation command refused: …]` annotation gets that plain refusal; never invoke the harness command. A `[conversation command outside a task thread]` annotation gets a short explanation that the command needs an open task thread, and starts nothing.\n  - For `helper-switch`, `help`, `mute`, `unmute` or `restart`, Read [branches.md](branches.md) § Conversation command and follow it.\n  - Return after the command; do not mutate another record or continue into another classification.\n\nAll conversation script arguments are shell-quoted values. `history` includes admitted inbound senders and all outbound rows. `history` and `thread-open` take no key, only `--source`, `--chat-id`, `--message-id`, `--thread-id`, `--name`, and `--limit` options. Parse each command's result before moving on; pass message text as quoted arguments, never interpolate it into executable code.\n\n- **New instruction** (\"work on X\", \"switch to Y\", \"prioritize Z\")\n  - In an open **Task thread**, apply its continuation \u002F one-off \u002F separate-work rule above.\n  - In a chat without threads, new independent work gets a new record and immediate dispatch; a continuation steers the selected record. If unsure which record it continues, ask once naming them.\n  - If no record is selected: treat as a new **Task thread** (above)\n  - If compatible with current task: pipe the steering into `task.ts note .hermit \u003Cid> --actor \u003CsourceKey>:\u003Cuser_id>` and confirm; the existing progress card, if any, picks the change up at its next milestone\n  - If it would replace the current task: confirm with the operator before switching. The replacement follows the **Task thread** rule and gets its own card; the old card's id is never reused\n  - After confirmation of replacement, use `task.ts cancel .hermit \u003Cold-id> --actor \u003CsourceKey>:\u003Cuser_id> --reason-stdin` or `task.ts block .hermit \u003Cold-id> --waiting-on \u003Chuman> --status-line ... --next ...`, then follow **Open the thread** and **Acknowledge, then record** for the replacement.\n  - An ask to do work after the current task follows **Open the thread** and **Acknowledge, then record**; § Intake covers its queue position.\n  - Never silently abandon work in progress\n\n## Worker status\n\n  - Read `task.ts list .hermit --open --owner 'worker:*' --json` and summarize what each worker is carrying. A trusted controller may see every row; another allowed sender gets only this chat's records. Do not disclose another chat's task text. This is the model-composed status reply; the deterministic `!status` hook keeps its existing behavior.\n\n## Progress and results\nPipe one progress line into `note \u003Cid>`, pairing it with milestone card edits. Metadata flags include `--due`, `--card`, `--clear-waiting`, `--decision`, and `--approval \"\u003Cactor>: \u003Cwhat>\"`. When the operator or the work changes direction on an open record (scope dropped, date moved, approach swapped), pipe `\u003Cwhat changed>, \u003Cwhy>` into `note \u003Cid> --decision`. Ordinary progress stays a plain note. A changed definition uses `note \u003Cid> --done ... --actor \u003Chuman identity>`: it increments result_rev and clears the old result and check.\n\nRecord every outcome, not only one awaiting acceptance, with § Complete a task turn step 3's command and digest check; terminal-origin work posts in the terminal. After that, a record with a check runs `task-check.ts \u003Cid>` in the same turn; a pass closes it and the reply names the close with the proof; a fail, refused run or permission prompt leaves it unconfirmed, not retried that turn, for the daily run.\n\nA stall in unfinished work requires `--waiting-on`, `--status-line` and `--next`; post the digest's one status\u002Fnext-step message to its requester in its conversation.\n\n## Closure\nWhen a close digest carries `next`, follow it to read [learn.md](learn.md) and review once in the main session before the close reply. The review is best effort; a lost review is not resumed.\nStored status is only `open` or `closed`; closed_by is only `check`, `confirmed`, `cancelled` or null. `close`, `cancel`, and a passing `task-check.ts` run close records. Never infer closure from harness idleness.\n\nUse `close \u003Cid> --by confirmed --actor \u003CsourceKey>:\u003Cuser_id> --result-rev \u003Ccurrent> --reason-stdin` for confirmation of a posted result; with none posted, close without `--result-rev` when the requester explicitly says the work is done (an acknowledgement is not). `TASKS.md` defines what counts as confirmation. Close with a reason quoting the message that confirmed; the reply names the close so the requester can object. When one message both accepts the result and asks for new work, close the accepted record first, then classify the new request. The revision must match and a named approver must be the actor. Typed decisions use the decider-or-admin rule enforced by `task answer`; protected close or clear-wait operations carry `--chat --user`. Other records retain shared human control. There is no owner list.\n\nUse `close \u003Cid> --by check --actor hermit --claim \u003Clinked claim>` only when the later claim is held. A resolved duty uses its matching `duty:\u003Cname>` actor and dedupe key. Free-text proof alone cannot close a task. Use `cancel \u003Cid> --actor \u003Chuman identity> --reason-stdin` with a nonempty reason to cancel.\n\n## Standup and duties\nBefore reading `standup --json` output or acting on a duty, Read [branches.md](branches.md) § Standup and duties.\n\n## Lessons and executable checks\nBefore closing, pipe any lesson into `task.ts lesson .hermit \u003Cid>`. Omit this operation when there is no lesson. When a lesson recorded earlier on the record turned out wrong, add a lesson that names the correction.\n\nSet a command with `open --check '\u003Ccommand>'` or `note \u003Cid> --check '\u003Ccommand>'`; `--check clear` removes it. The command exits 0 only when the whole definition of done holds (a pull request is merged, not merely fetchable). It only observes and never writes, deletes, sends or deploys. A named approver may still require confirmation after a check passes. On an approved proposal, attaching the first check preserves consent; replacing or clearing an existing check or changing `--done` requires new consent. A changed definition of done clears the check, so the same `note` supplies a replacement when one still applies. Run `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask-check.ts \u003Cid>` to evaluate it from the project root, subject to the normal command permission gate. Exit 0 closes by `check`; a nonzero exit records progress.\n",{"name":5,"description":7},"main","9ad858aaec20d1087625e634b51ab70c993f22cd","plugins\u002Fhermitd\u002Fskills\u002Ftask",16,"https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd","https:\u002F\u002Fhermitd.dev","https:\u002F\u002Fgithub.com\u002Fgtapps","Software engineer from Portugal.\r\nBuilding and deploying agents for real companies.","2026-11-11 08:46:23",{"source":8,"skillName":5,"commands":39,"prompt":49,"zipAvailable":50},[40,43,46],{"tool":41,"command":42},"npx","npx skills add gtapps\u002Fhermitd --skill task",{"tool":44,"command":45},"bunx","bunx skills add gtapps\u002Fhermitd --skill task",{"tool":47,"command":48},"pnpm","pnpm dlx skills add gtapps\u002Fhermitd --skill task","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Ftask\u002FSKILL.md",true,[52,58],{"path":53,"resourceType":54,"resourceTypeDesc":55,"sizeBytes":56,"sourceHtmlUrl":57},"branches.md","REFERENCE","参考文档",2919,"https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Ftask\u002Fbranches.md",{"path":59,"resourceType":54,"resourceTypeDesc":55,"sizeBytes":60,"sourceHtmlUrl":61},"learn.md",3463,"https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Ftask\u002Flearn.md",[63,79,95,121,137,146],{"skillNo":64,"name":65,"nameZh":6,"description":66,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":67,"categories":68,"keywords":69,"publishedAt":24},"01M718AB18DTYHVGXA6VF1VVR2","dream","Nightly memory maintenance from transcript ground truth. Verifies, enriches and tidies auto-memory and topic pages with snapshot validation and undo. Also handles 'undo the dream'.","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fdream\u002FSKILL.md",[],[65,70,71,72,73,74,75,76,77,78],"with","maintenance","memory","validation","snapshot","pages","auto","memory maintenance","transcript",{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":85,"publishedAt":24},"01M6HVD4WX8RB5EKH49HM66M8X","when-done-switch-to","Arm a deferred model or effort switch. Use for \"when done switch to\", \"after this drop to sonnet\", or \"switch model when idle\".","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fwhen-done-switch-to\u002FSKILL.md",[],[86,87,88,89,90,91,92,93,94],"when","done","switch","when done switch to","for","model","use","drop","sonnet",{"skillNo":96,"name":97,"nameZh":6,"description":98,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":101,"publishedAt":24},"01M6HVD0ZA2Q1RD7CA0X8VWF3T","weekly-review","Generate the weekly review report for the current ISO week. Writes to .hermit\u002Fcompiled\u002Freview-weekly-YYYY-Www.md (dev-facing detail) and sends a plain-language channel summary (Delivered \u002F Decisions \u002F Waiting on you \u002F Spend). Runs every Sunday at 23:00 via routine.","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fweekly-review\u002FSKILL.md",[],[102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,90,117,118,119,120],"weekly review","review","weekly","hermit","plain","routine","channel","summary","report","at","generate","via","decisions","you","detail","iso","review report","dev","plain-language",{"skillNo":122,"name":123,"nameZh":6,"description":124,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":125,"categories":126,"keywords":127,"publishedAt":24},"01M6HVCW8PHZXSPYAZQBZXB9DX","watch","Background events via the config watch monitor or ad-hoc Monitor tool. Quiet watches cost zero tokens.","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fwatch\u002FSKILL.md",[],[123,128,129,130,131,132,133,134,135,113,136],"monitor","ZeRO","tokens","tool","cost","ad","config","background","events",{"skillNo":138,"name":139,"nameZh":6,"description":140,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":141,"categories":142,"keywords":143,"publishedAt":24},"01M6HVCRMG53K3Y63WAH59YVFJ","watch-activate","Activate the config watch monitor.","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fwatch-activate\u002FSKILL.md",[],[123,144,145,128,134],"activate","watch activate",{"skillNo":147,"name":148,"nameZh":6,"description":149,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":150,"categories":151,"keywords":157,"publishedAt":24},"01M6HVCK6782RD4D9ADQY0ENKD","voice-notes","Transcribe and respond to voice notes. Activates when any channel message carries an audio attachment, or when asked to transcribe an inbound voice message.","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fvoice-notes\u002FSKILL.md",[152],{"categoryNo":153,"categoryName":154,"taxonomyType":155,"taxonomyTypeDesc":156},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",[158,159,160,161,162,163,164,165,166,167,105,86,168,169,170,171,172,173,115,174],"notes","voice","voice notes","SET","Audio","transcribe","operator","understand","transcription","my","read","message","can","telegram","channel message","discord","up"]