kew delegate — Assign-to-kew delegation watcher¶
kew delegate lets a human hand off a Linear issue to kew by assigning it to the kew
seat (or adding a configured label). kew delegate watch runs a foreground loop that
detects the assignment, claims the issue, and dispatches it as a one-node ephemeral epic
— reusing the same claim → dispatch → close path as kew epic run.
Status — supervised use is safe; unattended use is close. As of #966 the delegation reservation lifecycle is sound (terminal outcomes release their reservation, so the fleet no longer deadlocks after
[parallel] max_workerscompletions), and #971 hardens the refusal path for long unattended runs: kew comments once per refusal episode (not on every cooldown expiry), a failed unclaim leaves a reconcile retry surface instead of stranding the item, and an expired/revokedLINEAR_API_KEYterminates the watcher loudly (exit2) rather than retrying forever. Runningkew delegate watchunder supervision is safe today; fully unattended operation is pending the remainder of thedelegation-followupsepic (driver-side reservation reconcile and epic-driver lock liveness).--dry-runis always safe.
Refusal-episode comment semantics (#971)¶
When a budget/preflight pre-check refuses a delegated issue, kew writes a terminal
refusal row and posts one Linear comment naming the cap that bound and the knob
to raise. While the issue stays over budget the watcher keeps re-surfacing it (its
trigger label survives the unclaim), but kew comments only once per episode: a
repeat refusal updates state silently until the episode ends (a successful dispatch
or any non-refusal outcome resets it). Raise the named budget.*_usd limit and the
next re-claim proceeds. See [delegation].refusal_cooldown_s.
Requirements¶
[tracker].type = "linear"— delegation is a Linear-only feature.[delegation].assigneeset to the kew Linear member name — the watcher resolves this to a member ID at startup and refuses to start if it is blank.LINEAR_API_KEYenvironment variable set to a Linear personal API key.
kew delegate watch [--dry-run]¶
Usage: kew delegate watch [OPTIONS]
Options:
--dry-run Log 'would claim / would dispatch' without reserving or spending.
kew delegate watch # foreground watcher — Ctrl-C to stop
kew delegate watch --dry-run # preview mode: no claims, no spend
Starts a foreground polling loop (like kew ingest serve — no daemon, no autostart).
On each tick it reads the local event cursor from the run store (every
[delegation].fast_interval_s seconds) and polls Linear (at most once per
[delegation].poll_interval_s seconds) to find issues newly assigned to the kew member
that carry the configured delegation label. For each candidate it:
- Re-verifies the assignee and label against the live Linear API (not a snapshot).
- Claims the issue — transitions it to In Progress and reserves a fleet slot.
- Dispatches it as a one-node ephemeral epic under the
"delegation"pseudo-epic, sharing the[parallel] max_workersfleet cap withkew epic run --all.
Ctrl-C shuts down cleanly.
Configuration¶
See [delegation] in the configuration reference.
Key fields:
| Field | Default | Description |
|---|---|---|
assignee |
"" |
The kew Linear member name. Required at watch start. |
label |
"kew:ready" |
Linear label that signals a delegated issue is ready. |
poll_interval_s |
20 |
Throttled Linear API poll floor (seconds). |
fast_interval_s |
2 |
Local tracker-events read cadence (seconds). |
refusal_cooldown_s |
300 |
Skip re-claiming a budget-refused item for this long, damping the refuse→comment loop (0 disables). |
Exit codes¶
| Code | Meaning |
|---|---|
0 |
Clean shutdown (Ctrl-C). |
1 |
Misconfiguration (tracker.type not linear, delegation.assignee not set). |
2 |
LINEAR_API_KEY not set at startup, or Linear authentication failed at runtime (expired/revoked key) — the watcher terminates loudly rather than retrying forever (#971). |