[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6J9R049PRQ8TMFTWHBJC74E":3,"skill-same:01M6J9R049PRQ8TMFTWHBJC74E":71},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":42,"linkOnly":43,"markdownContent":44,"markdownBody":45,"frontMatter":46,"refName":49,"commitSha":50,"skillDirectory":51,"forksCount":52,"repositoryHtmlUrl":53,"repositoryHomepageUrl":54,"ownerHtmlUrl":55,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":56,"install":57,"resources":70},"01M6J9R049PRQ8TMFTWHBJC74E","harn-control-events",null,"Make an agent session answer stop and steer promptly, kill what it started, and leave a record that names the control.","burin-labs\u002Fharn","burin-labs","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F270508823?v=4","01M6J9MTN4TKZ12YF6BAX0DARN","Burin Labs","01M6J9MTSTW6RRQ2TWKYV1A3X1",31,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fburin-labs\u002Fharn\u002Fblob\u002Fmain\u002Fcrates\u002Fharn-skills\u002Fsrc\u002Fcorpus\u002Fharn-control-events\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41],"harn control events","events","control","agent session","work","running","when","steer","requests","answer","make","it","as","message","record","but","cancel","kill","stop","queue","say","use","session","2026-11-10 10:12:30",false,"---\nname: harn-control-events\nshort: Stop, steer, and queue as events a session must answer, not requests it may ignore.\ndescription: Make an agent session answer stop and steer promptly, kill what it started, and leave a record that names the control.\nwhen_to_use: Use when adding or auditing cancel, stop, steer, interrupt, or queued-message handling, or when a stop appears to work but leaves work running or a record that does not say it happened.\n---\n\n# Harn control events\n\nA control event is a person telling a running session to stop or to change\ncourse. It is an event the session must answer, not a request it may finish\nits current plan first and then consider.\n\nPair this skill with [[harn-orchestration]] for where the loop drains\ninjections, [[harn-agent]] for loop and terminal vocabulary, and\n[[harn-product-quality]] for what a host must show while a control is in\nflight.\n\n## The three things a stop has to do\n\nA stop that does one or two of these is not a stop. Check all three\nseparately, because the second and third fail silently while the first\nlooks correct.\n\n1. **The loop stops.** No further iteration, model call, or tool dispatch\n   after the control lands.\n2. **What the session started dies.** A cancelled agent that leaves a\n   backgrounded command running has moved the work, not stopped it. Kill the\n   handles owned by *that* session and no others.\n3. **The record names the control.** The run's terminal says a person\n   stopped it. Without this, a stopped run and a run that merely produced\n   nothing are the same row in every downstream report.\n\nPoint 3 is the one that rots. An accepted cancel **is answered** — the prompt\nreturns `stopReason: \"cancelled\"` — so the turn settles normally and any\ntagging that fires only when a turn fails to settle never fires at all. Seal\nthe terminal from the observed control, not from whether the turn looked\nfinished.\n\n## Absence must not read as success\n\nThe dangerous shape is a control that names something that is not there.\n\n- A cancel naming an unregistered session must be **loud**: warn, and emit a\n  `ControlOutcome` with `status: \"rejected\"` naming the session. Consuming\n  the frame silently makes \"nothing was cancelled\" indistinguishable from\n  \"everything was cancelled\".\n- Every control decision, accepted or rejected, gets a `ControlOutcome`\n  carrying method, outcome, status, actor, target, and reason. Read the\n  structured record; do not grep prose for the verdict.\n- A record that a control *arrived* is not a record that the loop *stopped*.\n  Assert the loop counters after the control, not the frame before it.\n\n## Delivery modes for a mid-turn message\n\nTyping while a session works means one of three things, and a runtime that\nassumes one of them is wrong two-thirds of the time. Make it a setting.\n\n| Mode | Wire value | Meaning |\n|---|---|---|\n| Steer | `steer` | Redirect the running turn at its next iteration or tool boundary. |\n| Interrupt | `interrupt_immediate` | Deliver as soon as the loop will take it, ahead of the next tool. |\n| Queue | `queue` | Hold it and start a new turn with it once this one ends. |\n\nOver ACP, steer and queue are `session\u002Fprompt` with `delivery: \"steer\"` or\n`\"queue\"`; interrupt is in-VM only. A stop (`session\u002Fcancel`) ends only the\nrunning turn: pending steers then open the next turn together and queued\nprompts follow, one turn each. \"Deliver now\" is a steer followed by a stop.\nOnly `$\u002Fcancel_request` withdraws a pending prompt.\n\nGive the setting a typed enum with one wire spelling per behavior. No aliases,\nand never fall back to a default in silence: a control policy that quietly\nreverts is one the operator believes is in force while it is not. Report the\nrejected value and the mode actually running.\n\n## Signals are controls too\n\nA headless or supervised run answers SIGINT and SIGTERM by sending one\n`session\u002Fcancel` on the running session — the same path an interactive stop\nuses, because that is the path the runtime already terminates cleanly on.\n\n- Race the signal at the **frame-receive point**, not around the whole drain,\n  so a cancel does not discard the frames the turn already accumulated. The\n  partial turn stays intact and still reports what it observed.\n- Bound the post-cancel wait so a wedged engine cannot hold the process open\n  after the operator said stop; a second signal skips the wait.\n- Distinguish the two signals in the recorded reason. A supervisor winding a\n  run down and an operator hitting Ctrl-C are different facts.\n\n## Verify\n\nDeterministic tests for the invariants; one re-runnable end-to-end check for\nthe claim.\n\n- **Positive**: a cancel mid-loop leaves zero further iteration, model-call,\n  and tool-dispatch events.\n- **Negative control, required**: a cancel naming an unknown session must\n  leave the live loop running. Without it, a fix that cancels everything\n  passes the positive test.\n- **Blast radius**: spawn two real background children on two sessions,\n  cancel one, poll for that pid to die, and assert the other is still alive.\n  Poll rather than reading once — the child is reaped a moment after the\n  agent goes, and a single immediate reading reports a working stop as a leak.\n- **Identity**: assert the id the background handles are keyed by equals the\n  session id the control names. A kill on a mismatched id is a silent no-op\n  that reads as success.\n- **End to end**: keep a script that stops a real run and checks all three\n  guarantees. Run it model-free with a mock provider so it stays free and\n  anyone can re-run it.\n","# Harn control events\n\nA control event is a person telling a running session to stop or to change\ncourse. It is an event the session must answer, not a request it may finish\nits current plan first and then consider.\n\nPair this skill with [[harn-orchestration]] for where the loop drains\ninjections, [[harn-agent]] for loop and terminal vocabulary, and\n[[harn-product-quality]] for what a host must show while a control is in\nflight.\n\n## The three things a stop has to do\n\nA stop that does one or two of these is not a stop. Check all three\nseparately, because the second and third fail silently while the first\nlooks correct.\n\n1. **The loop stops.** No further iteration, model call, or tool dispatch\n   after the control lands.\n2. **What the session started dies.** A cancelled agent that leaves a\n   backgrounded command running has moved the work, not stopped it. Kill the\n   handles owned by *that* session and no others.\n3. **The record names the control.** The run's terminal says a person\n   stopped it. Without this, a stopped run and a run that merely produced\n   nothing are the same row in every downstream report.\n\nPoint 3 is the one that rots. An accepted cancel **is answered** — the prompt\nreturns `stopReason: \"cancelled\"` — so the turn settles normally and any\ntagging that fires only when a turn fails to settle never fires at all. Seal\nthe terminal from the observed control, not from whether the turn looked\nfinished.\n\n## Absence must not read as success\n\nThe dangerous shape is a control that names something that is not there.\n\n- A cancel naming an unregistered session must be **loud**: warn, and emit a\n  `ControlOutcome` with `status: \"rejected\"` naming the session. Consuming\n  the frame silently makes \"nothing was cancelled\" indistinguishable from\n  \"everything was cancelled\".\n- Every control decision, accepted or rejected, gets a `ControlOutcome`\n  carrying method, outcome, status, actor, target, and reason. Read the\n  structured record; do not grep prose for the verdict.\n- A record that a control *arrived* is not a record that the loop *stopped*.\n  Assert the loop counters after the control, not the frame before it.\n\n## Delivery modes for a mid-turn message\n\nTyping while a session works means one of three things, and a runtime that\nassumes one of them is wrong two-thirds of the time. Make it a setting.\n\n| Mode | Wire value | Meaning |\n|---|---|---|\n| Steer | `steer` | Redirect the running turn at its next iteration or tool boundary. |\n| Interrupt | `interrupt_immediate` | Deliver as soon as the loop will take it, ahead of the next tool. |\n| Queue | `queue` | Hold it and start a new turn with it once this one ends. |\n\nOver ACP, steer and queue are `session\u002Fprompt` with `delivery: \"steer\"` or\n`\"queue\"`; interrupt is in-VM only. A stop (`session\u002Fcancel`) ends only the\nrunning turn: pending steers then open the next turn together and queued\nprompts follow, one turn each. \"Deliver now\" is a steer followed by a stop.\nOnly `$\u002Fcancel_request` withdraws a pending prompt.\n\nGive the setting a typed enum with one wire spelling per behavior. No aliases,\nand never fall back to a default in silence: a control policy that quietly\nreverts is one the operator believes is in force while it is not. Report the\nrejected value and the mode actually running.\n\n## Signals are controls too\n\nA headless or supervised run answers SIGINT and SIGTERM by sending one\n`session\u002Fcancel` on the running session — the same path an interactive stop\nuses, because that is the path the runtime already terminates cleanly on.\n\n- Race the signal at the **frame-receive point**, not around the whole drain,\n  so a cancel does not discard the frames the turn already accumulated. The\n  partial turn stays intact and still reports what it observed.\n- Bound the post-cancel wait so a wedged engine cannot hold the process open\n  after the operator said stop; a second signal skips the wait.\n- Distinguish the two signals in the recorded reason. A supervisor winding a\n  run down and an operator hitting Ctrl-C are different facts.\n\n## Verify\n\nDeterministic tests for the invariants; one re-runnable end-to-end check for\nthe claim.\n\n- **Positive**: a cancel mid-loop leaves zero further iteration, model-call,\n  and tool-dispatch events.\n- **Negative control, required**: a cancel naming an unknown session must\n  leave the live loop running. Without it, a fix that cancels everything\n  passes the positive test.\n- **Blast radius**: spawn two real background children on two sessions,\n  cancel one, poll for that pid to die, and assert the other is still alive.\n  Poll rather than reading once — the child is reaped a moment after the\n  agent goes, and a single immediate reading reports a working stop as a leak.\n- **Identity**: assert the id the background handles are keyed by equals the\n  session id the control names. A kill on a mismatched id is a silent no-op\n  that reads as success.\n- **End to end**: keep a script that stops a real run and checks all three\n  guarantees. Run it model-free with a mock provider so it stays free and\n  anyone can re-run it.\n",{"name":5,"short":47,"description":7,"when_to_use":48},"Stop, steer, and queue as events a session must answer, not requests it may ignore.","Use when adding or auditing cancel, stop, steer, interrupt, or queued-message handling, or when a stop appears to work but leaves work running or a record that does not say it happened.","main","a52b7979c25b6be41bc82c4a6e583959a048f618","crates\u002Fharn-skills\u002Fsrc\u002Fcorpus\u002Fharn-control-events",6,"https:\u002F\u002Fgithub.com\u002Fburin-labs\u002Fharn","https:\u002F\u002Fharnlang.com","https:\u002F\u002Fgithub.com\u002Fburin-labs","2026-11-11 12:45:49",{"source":8,"skillName":5,"commands":58,"prompt":68,"zipAvailable":69},[59,62,65],{"tool":60,"command":61},"npx","npx skills add burin-labs\u002Fharn --skill harn-control-events",{"tool":63,"command":64},"bunx","bunx skills add burin-labs\u002Fharn --skill harn-control-events",{"tool":66,"command":67},"pnpm","pnpm dlx skills add burin-labs\u002Fharn --skill harn-control-events","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fburin-labs\u002Fharn\u002Fblob\u002Fmain\u002Fcrates\u002Fharn-skills\u002Fsrc\u002Fcorpus\u002Fharn-control-events\u002FSKILL.md",true,[],[72,90,110,124,145,158],{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":78,"publishedAt":42},"01M6J9Y4B3NZ9C24GN47159AEQ","stream-fan-in","Stream trigger example for routing or grouping event batches.","https:\u002F\u002Fgithub.com\u002Fburin-labs\u002Fharn\u002Fblob\u002Fmain\u002Fexamples\u002Ftriggers\u002Fstream-fan-in\u002FSKILL.md",[],[79,80,81,82,83,84,85,86,87,20,88,89,40],"stream","stream fan in","routing","customize","trigger","pipeline","for","batches","event","grouping","example",{"skillNo":91,"name":92,"nameZh":6,"description":93,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":42},"01M6J9WNJHJV0K3CBZJFG8GD1R","github-stale-pr-nudger","Cron recipe for scanning repositories and nudging old pull requests.","https:\u002F\u002Fgithub.com\u002Fburin-labs\u002Fharn\u002Fblob\u002Fmain\u002Fexamples\u002Ftriggers\u002Fgithub-stale-pr-nudger\u002FSKILL.md",[],[97,98,99,100,27,85,101,102,103,104,105,40,106,107,108,82,109],"github stale pr nudger","stale","github","pr","scheduled","follow-up","recipe","up","scanning","cron","pull","pull request","pull requests",{"skillNo":111,"name":112,"nameZh":6,"description":113,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":114,"categories":115,"keywords":116,"publishedAt":42},"01M6J9Y7X1D3ZSWWAG1GXFTWWY","webhook-generic-hmac","Generic webhook recipe with signed inbound requests.","https:\u002F\u002Fgithub.com\u002Fburin-labs\u002Fharn\u002Fblob\u002Fmain\u002Fexamples\u002Ftriggers\u002Fwebhook-generic-hmac\u002FSKILL.md",[],[117,118,119,82,25,27,120,103,83,121,122,123,40],"generic","webhook","webhook generic hmac","with","webhook trigger","provider","webhooks",{"skillNo":125,"name":126,"nameZh":6,"description":127,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":128,"categories":129,"keywords":135,"publishedAt":42},"01M6J9Y10NVP86YMXCD9FQ2XZV","slack-thread-summarizer","Slack webhook recipe with a local summarize predicate.","https:\u002F\u002Fgithub.com\u002Fburin-labs\u002Fharn\u002Fblob\u002Fmain\u002Fexamples\u002Ftriggers\u002Fslack-thread-summarizer\u002FSKILL.md",[130],{"categoryNo":131,"categoryName":132,"taxonomyType":133,"taxonomyTypeDesc":134},"01JBSEEDCAT000000000000005","邮件与沟通","SCENARIO","使用场景",[136,137,138,139,140,141,25,142,143,120,118,103,83,82,144,40],"slack thread","slack thread summarizer","thread","summarizer","slack","local","summaries","threads","summarize",{"skillNo":146,"name":147,"nameZh":6,"description":148,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":149,"categories":150,"keywords":152,"publishedAt":42},"01M6J9XWKSBQJ881KBP2TGMN3Z","slack-reaction-action","Slack Events API recipe for reaction_added workflows.","https:\u002F\u002Fgithub.com\u002Fburin-labs\u002Fharn\u002Fblob\u002Fmain\u002Fexamples\u002Ftriggers\u002Fslack-reaction-action\u002FSKILL.md",[151],{"categoryNo":131,"categoryName":132,"taxonomyType":133,"taxonomyTypeDesc":134},[140,153,154,85,40,25,102,20,103,83,155,104,23,156,82,157],"action","slack reaction action","reactions","api","workflows",{"skillNo":159,"name":160,"nameZh":6,"description":161,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":162,"categories":163,"keywords":165,"publishedAt":42},"01M6J9XRE6PD3J99VKA1TYWS9Y","slack-keyword-router","Slack webhook recipe for routing messages by keyword.","https:\u002F\u002Fgithub.com\u002Fburin-labs\u002Fharn\u002Fblob\u002Fmain\u002Fexamples\u002Ftriggers\u002Fslack-keyword-router\u002FSKILL.md",[164],{"categoryNo":131,"categoryName":132,"taxonomyType":133,"taxonomyTypeDesc":134},[166,167,140,168,40,84,169,81,82,118,25,170,85,103],"slack keyword router","router","simple","messages","slack messages"]