{
  "$schema": "https://pi-tui.ratstack.sh/schema/pattern.schema.json",
  "aka": [
    "Abortable dialog"
  ],
  "animated": false,
  "apis": [
    {
      "name": "ctx.ui.select",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/extensions.md#interact-with-the-user"
    },
    {
      "name": "ctx.ui.confirm",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/extensions.md#interact-with-the-user"
    },
    {
      "name": "ExtensionUIDialogOptions",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/extensions.md#interact-with-the-user"
    }
  ],
  "applicability": [
    "Use this when the owning task can end before a user answers."
  ],
  "category": "dialogs",
  "categoryLabel": "Overlays and dialogs",
  "consequences": [
    "The owning task can dismiss its pending prompt.",
    "Already-aborted and later-aborted signals both need cancellation handling."
  ],
  "family": "behavioral",
  "familyLabel": "Behavioral",
  "id": "abort-tether",
  "implementation": [
    "Handle an already-aborted signal.",
    "Do not leave the dialog promise pending on abort."
  ],
  "intent": "Tie a built-in dialog's lifetime to an operation's abort signal.",
  "jsonUrl": "https://pi-tui.ratstack.sh/patterns/abort-tether.json",
  "kind": "screen",
  "knownUses": [
    {
      "example": "nico-dialog-abort-signal",
      "moreRefs": 0,
      "refs": [
        {
          "file": "packages/coding-agent/src/core/extensions/types.ts",
          "lines": "50-64",
          "sha": "9771fa1e",
          "url": "https://github.com/earendil-works/pi/blob/9771fa1e447ca5f1d564bf49d2dbef2c7f79e334/packages/coding-agent/src/core/extensions/types.ts#L50-L64"
        }
      ],
      "repo": "earendil-works/pi",
      "repoUrl": "https://github.com/earendil-works/pi",
      "title": "Cancel extension dialogs with AbortSignal"
    }
  ],
  "linkedFrom": [
    {
      "how": "cancels a prompt instead of a loader",
      "id": "abort-lantern",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/abort-lantern.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/abort-lantern.md",
      "name": "Abort Lantern",
      "url": "https://pi-tui.ratstack.sh/patterns/abort-lantern/"
    }
  ],
  "links": {
    "agentGuide": "https://pi-tui.ratstack.sh/llms.txt",
    "index": "https://pi-tui.ratstack.sh/patterns.md",
    "skill": "https://pi-tui.ratstack.sh/skills/build-pi-tui-component.md"
  },
  "mdUrl": "https://pi-tui.ratstack.sh/patterns/abort-tether.md",
  "motivation": "Nico's upstream dialogs can outlive the task that requested them without a cancellation signal.",
  "name": "Abort Tether",
  "participants": [
    {
      "name": "ctx.ui.select",
      "role": "Returns a selected string or cancellation.",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/extensions.md#interact-with-the-user"
    },
    {
      "name": "ctx.ui.confirm",
      "role": "Returns a confirmation decision.",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/extensions.md#interact-with-the-user"
    },
    {
      "name": "ExtensionUIDialogOptions",
      "role": "Carries a timeout or abort signal for a built-in dialog.",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/extensions.md#interact-with-the-user"
    },
    {
      "name": "Abort signal",
      "role": "Ties the pending prompt to its owning operation.",
      "url": null
    }
  ],
  "pi": "1.0.3",
  "related": [
    {
      "how": "owns cancellation during work",
      "id": "abort-lantern",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/abort-lantern.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/abort-lantern.md",
      "name": "Abort Lantern",
      "url": "https://pi-tui.ratstack.sh/patterns/abort-lantern/"
    }
  ],
  "sampleCode": {
    "code": "// Abort Tether: a dialog's lifetime follows its owning operation's signal.\nimport type { ExtensionUIDialogOptions } from \"@earendil-works/pi-coding-agent\";\nimport type { PatternStory } from \"../../../src/pattern.ts\";\n\nexport const story: PatternStory = {\n  id: \"abort-tether\", title: \"Abort Tether\", kind: \"screen\",\n  apis: [\"ctx.ui.confirm\", \"ctx.ui.select\", \"ExtensionUIDialogOptions\"],\n  states: [\n    { id: \"open\", label: \"Pending prompt\" },\n    { id: \"aborted\", label: \"Owner cancelled\", steps: [\n      { type: \"action\", name: \"abort-owner\" }, { type: \"resize\", rows: 12 },\n    ] },\n    { id: \"already-aborted\", label: \"No pending prompt\", steps: [{ type: \"action\", name: \"pre-aborted\" }] },\n  ],\n  setup({ ui, theme, action }) {\n    const owner = new AbortController();\n    const options: ExtensionUIDialogOptions = { signal: owner.signal };\n    ui.setEditorText(\"Keep this draft\");\n    ui.setWidget(\"owner\", [theme.fg(\"muted\", \"Owner active · awaiting confirmation\")]);\n    ui.setStatus(\"owner\", theme.fg(\"muted\", \"active\"));\n    void ui.confirm(\"Apply task patch?\", \"The owner may cancel this prompt.\", options).then(confirmed => {\n      ui.setWidget(\"owner\", [\n        theme.fg(\"success\", \"Owner aborted · confirmation is \" + confirmed),\n        theme.fg(\"muted\", \"No patch applied · draft kept\"),\n      ]);\n      ui.setStatus(\"owner\", theme.fg(\"muted\", \"cancelled\"));\n    });\n    action(\"abort-owner\", () => owner.abort());\n    action(\"pre-aborted\", () => {\n      // Reusing the aborted signal resolves immediately without mounting a view.\n      void ui.select(\"This prompt must not open\", [\"Apply patch\"], options).then(selection => {\n        ui.setWidget(\"owner\", [\n          theme.fg(\"success\", \"Already aborted · immediate return\"),\n          theme.fg(\"muted\", \"Selection: \" + String(selection)),\n          theme.fg(\"dim\", \"No pending prompt · editor owns focus\"),\n        ]);\n      });\n    });\n    return () => owner.abort();\n  },\n};\n",
    "lang": "ts",
    "path": "stories/patterns/behavioral/abort-tether.ts"
  },
  "states": [
    {
      "dont": false,
      "expectFail": [],
      "frames": [
        {
          "alt": "Abort Tether, Pending prompt state, 40 columns, dark theme, 19 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 836,
          "rows": 19,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/open-40-dark.90f82a9df3c8.webp",
          "theme": "dark",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Abort Tether, Pending prompt state, 40 columns, light theme, 19 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 836,
          "rows": 19,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/open-40-light.054e73456d0d.webp",
          "theme": "light",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Abort Tether, Pending prompt state, 60 columns, dark theme, 19 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 836,
          "rows": 19,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/open-60-dark.3e474b44dd7b.webp",
          "theme": "dark",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Abort Tether, Pending prompt state, 60 columns, light theme, 19 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 836,
          "rows": 19,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/open-60-light.563faf533ec2.webp",
          "theme": "light",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Abort Tether, Pending prompt state, 80 columns, dark theme, 19 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 836,
          "rows": 19,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/open-80-dark.757c7da2870b.webp",
          "theme": "dark",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Abort Tether, Pending prompt state, 80 columns, light theme, 19 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 836,
          "rows": 19,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/open-80-light.779ad1bf5233.webp",
          "theme": "light",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Abort Tether, Pending prompt state, 120 columns, dark theme, 19 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 836,
          "rows": 19,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/open-120-dark.88dbf29df14f.webp",
          "theme": "dark",
          "w": 2400,
          "width": 120
        },
        {
          "alt": "Abort Tether, Pending prompt state, 120 columns, light theme, 19 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 836,
          "rows": 19,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/open-120-light.3003bf947d28.webp",
          "theme": "light",
          "w": 2400,
          "width": 120
        }
      ],
      "how": "Show a prompt while its synthetic owner is active.",
      "id": "open",
      "label": "Pending prompt",
      "problems": []
    },
    {
      "dont": false,
      "expectFail": [],
      "frames": [
        {
          "alt": "Abort Tether, Owner cancelled state, 40 columns, dark theme, 11 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 484,
          "rows": 11,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/aborted-40-dark.1d2ea23c844d.webp",
          "theme": "dark",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Abort Tether, Owner cancelled state, 40 columns, light theme, 11 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 484,
          "rows": 11,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/aborted-40-light.3d66c4de8c56.webp",
          "theme": "light",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Abort Tether, Owner cancelled state, 60 columns, dark theme, 11 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 484,
          "rows": 11,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/aborted-60-dark.aa50b1c5ff99.webp",
          "theme": "dark",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Abort Tether, Owner cancelled state, 60 columns, light theme, 11 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 484,
          "rows": 11,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/aborted-60-light.90e9a3e7c701.webp",
          "theme": "light",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Abort Tether, Owner cancelled state, 80 columns, dark theme, 11 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 484,
          "rows": 11,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/aborted-80-dark.aca8501a7787.webp",
          "theme": "dark",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Abort Tether, Owner cancelled state, 80 columns, light theme, 11 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 484,
          "rows": 11,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/aborted-80-light.107472bd6777.webp",
          "theme": "light",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Abort Tether, Owner cancelled state, 120 columns, dark theme, 11 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 484,
          "rows": 11,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/aborted-120-dark.7fe201d80879.webp",
          "theme": "dark",
          "w": 2400,
          "width": 120
        },
        {
          "alt": "Abort Tether, Owner cancelled state, 120 columns, light theme, 11 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 484,
          "rows": 11,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/aborted-120-light.8dd79678fdf9.webp",
          "theme": "light",
          "w": 2400,
          "width": 120
        }
      ],
      "how": "Cancel the owner and show the dialog's cancellation result.",
      "id": "aborted",
      "label": "Owner cancelled",
      "problems": []
    },
    {
      "dont": false,
      "expectFail": [],
      "frames": [
        {
          "alt": "Abort Tether, No pending prompt state, 40 columns, dark theme, 12 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 528,
          "rows": 12,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/already-aborted-40-dark.f42a08f35964.webp",
          "theme": "dark",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Abort Tether, No pending prompt state, 40 columns, light theme, 12 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 528,
          "rows": 12,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/already-aborted-40-light.739f12d36b7d.webp",
          "theme": "light",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Abort Tether, No pending prompt state, 60 columns, dark theme, 12 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 528,
          "rows": 12,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/already-aborted-60-dark.81d0b915a6d6.webp",
          "theme": "dark",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Abort Tether, No pending prompt state, 60 columns, light theme, 12 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 528,
          "rows": 12,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/already-aborted-60-light.31b83199e002.webp",
          "theme": "light",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Abort Tether, No pending prompt state, 80 columns, dark theme, 12 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 528,
          "rows": 12,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/already-aborted-80-dark.3d18d9d796e3.webp",
          "theme": "dark",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Abort Tether, No pending prompt state, 80 columns, light theme, 12 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 528,
          "rows": 12,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/already-aborted-80-light.3f9289450432.webp",
          "theme": "light",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Abort Tether, No pending prompt state, 120 columns, dark theme, 12 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 528,
          "rows": 12,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/already-aborted-120-dark.0fa91357abf6.webp",
          "theme": "dark",
          "w": 2400,
          "width": 120
        },
        {
          "alt": "Abort Tether, No pending prompt state, 120 columns, light theme, 12 rows",
          "animated": false,
          "animation": null,
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 528,
          "rows": 12,
          "still": "https://pi-tui.ratstack.sh/frames/abort-tether/already-aborted-120-light.a9ccbd3a3fe5.webp",
          "theme": "light",
          "w": 2400,
          "width": 120
        }
      ],
      "how": "Pass an already-aborted signal and show immediate cancellation.",
      "id": "already-aborted",
      "label": "No pending prompt",
      "problems": []
    }
  ],
  "structure": "owner signal -> dialog\nabort -> cancellation result",
  "thumbnails": {
    "dark": {
      "animation": null,
      "src": "https://pi-tui.ratstack.sh/thumbs/abort-tether/dark.306b8e1b80ac.webp"
    },
    "light": {
      "animation": null,
      "src": "https://pi-tui.ratstack.sh/thumbs/abort-tether/light.d779b90b2989.webp"
    }
  },
  "url": "https://pi-tui.ratstack.sh/patterns/abort-tether/",
  "widths": [
    40,
    60,
    80,
    120
  ]
}
