whose-turn 1.0.0-alpha.7 → 1.0.0-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +6 -6
- package/config.example.json +0 -4
- package/dist/assets/bem-CST_YFrc.js +1 -0
- package/dist/assets/index-CEB3_bQv.css +1 -0
- package/dist/assets/index-DsQ_5Y-x.js +7 -0
- package/dist/assets/{report-BJ_aC1A7.js → report-Bar3ULi6.js} +1 -1
- package/dist/index.html +3 -3
- package/dist/report.html +2 -2
- package/lib/api.mjs +28 -23
- package/lib/compose.mjs +6 -8
- package/lib/config.mjs +38 -5
- package/lib/errors.mjs +0 -1
- package/lib/feedback.mjs +78 -110
- package/lib/linear-api.mjs +1 -1
- package/lib/notify.mjs +6 -2
- package/lib/registry.mjs +7 -2
- package/lib/text.mjs +3 -0
- package/lib/workspace.mjs +1 -1
- package/package.json +1 -1
- package/server.mjs +8 -6
- package/dist/assets/bem-zV6iDqYN.js +0 -1
- package/dist/assets/index-BLFgmJcy.js +0 -7
- package/dist/assets/index-CTrTp-xu.css +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
What changed for you in each version of Whose Turn. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow [Semantic Versioning](https://semver.org/). The window shows this list under What's new; the ids at the end of an entry are ours and the window leaves them out.
|
|
4
4
|
|
|
5
|
+
## [1.0.0-alpha.8] - 2026-11-04
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- A bell in the status bar, "Notifications on", turns desktop notifications off for the whole monitor and back on. When they are off the button turns red and says "Notifications off", and the choice is kept after a restart. RMA-283.
|
|
9
|
+
- Anyone can now send a report from the Report sheet and see its answer, without connecting anything. A report goes to the maintainer, and the sheet says so. RMA-280.
|
|
10
|
+
- A report now carries only the title and text you write, the monitor version and a short description of your system (OS, Node version, how the monitor was installed, browser, screen and window size, language, time zone, light or dark, app window or tab, and which kinds of source you use, such as github or linear); nothing from your workspaces, tickets, names or links is sent with it. RMA-291.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- The `feedback` settings for a Linear workspace, team, project and key are gone: reports no longer need them, and old values in your config are dropped the next time it is saved. RMA-280.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- An empty panel, such as Your move with nothing in it, now shrinks to its message instead of keeping the height you once dragged it to. The height comes back when rows appear. RMA-294.
|
|
17
|
+
|
|
5
18
|
## [1.0.0-alpha.7] - 2026-11-04
|
|
6
19
|
|
|
7
20
|
### Fixed
|
package/README.md
CHANGED
|
@@ -49,10 +49,10 @@ Nothing that names an employer, an account or a team process lives in this repos
|
|
|
49
49
|
|---|---|
|
|
50
50
|
| `port`, `poll_seconds`, `history_days` | the port, how often to poll, how far back the feed reaches |
|
|
51
51
|
| `stale_minutes`, `failing_polls` | health alerts: no data from any source for this many minutes (default 15), or one source failing this many polls in a row (default 3) |
|
|
52
|
-
| `feedback.workspace`, `team`, `project` | where the "to the backlog" button and the `whose_turn_feedback` MCP tool file bugs and improvements about the monitor: a Linear workspace slug, team key and project name; the key with issue-creation rights goes to the secret store under `feedback.token_service` (default `whose-turn-feedback`) and the workspace slug |
|
|
53
|
-
| `feedback.assign` | `false` leaves a filed issue unassigned for triage; by default it is assigned to the owner of the feedback key, so it shows up on that person's own dashboard |
|
|
54
52
|
| `feedback.composer` | the user's own agent that turns a remark into an issue: `{command, args}` of a CLI that reads the prompt on stdin and prints JSON (`{title, kind, body}`, or a wrapper with a `result` string that contains it); default `claude -p --output-format json --model claude-haiku-5-5`, so Claude Code on the user's subscription; `codex exec` or anything alike works the same way |
|
|
53
|
+
| `feedback.*` (retired keys) | `workspace`, `team`, `project`, `token_service` and `assign` are dropped from the file the next time the workspace list is saved: reports go through the relay since RMA-280 and need no tracker setup |
|
|
55
54
|
| `feedback.bug_words` | extra words, in any language, that make the fallback composer (used when the agent CLI gives no usable answer) call a remark a bug; matched as stems at a word start; the English defaults bug, broken, crash, error, fail, wrong always apply |
|
|
55
|
+
| `notifications.desktop` | `false` turns desktop notifications off for the whole monitor, `true` (the default) leaves them on; the bell in the status bar, "Notifications on/off", flips it, and so does `POST /api/notifications` with `{desktop: false}`, which answers `{notifications}`. `WHOSE_TURN_NOTIFY=off` still wins over it. The setting is stored in the config, so it survives a restart, and a change applies at once with no restart (RMA-283) |
|
|
56
56
|
| `workspaces[].id`, `name` | a short id used in the API and on disk (lowercase letters, digits and hyphens, up to 40, starting with a letter or digit; a missing id becomes `ws<n>`) and the display name |
|
|
57
57
|
| `workspaces[].key_pattern` | regex for ticket keys in PR titles and to-dos; the default matches any Jira-style key; a pattern that does not compile is refused on save |
|
|
58
58
|
| `workspaces[].connectors` | an object keyed by type, or a list of `{type, id?, label?, …}` entries when one type appears twice |
|
|
@@ -175,7 +175,7 @@ The monitor also alerts on its own polling: stale data, or a source that keeps f
|
|
|
175
175
|
|
|
176
176
|
## API, `127.0.0.1:<port>`
|
|
177
177
|
|
|
178
|
-
Requests must carry the local `Host`; a POST must be `application/json`. An error is a `google.rpc.Status` envelope: `{"error":{"code","status","message","details":[{"@type":"ErrorInfo","reason"}]}}`; branch on `reason`. The reasons: `NOT_FOUND` (unknown path, 404), `METHOD_NOT_ALLOWED` (405 with an `Allow: GET, POST` header, a method other than GET or POST), `NO_SUCH_WORKSPACE`, `NO_SUCH_TODO`, `CHANGELOG_UNAVAILABLE` (404), `NO_WORKSPACE` (412, a request that needs a workspace while none is configured; `/api/state` still answers 200 with an empty snapshot carrying `problems`, which the first-run card reads), `
|
|
178
|
+
Requests must carry the local `Host`; a POST must be `application/json`. An error is a `google.rpc.Status` envelope: `{"error":{"code","status","message","details":[{"@type":"ErrorInfo","reason"}]}}`; branch on `reason`. The reasons: `NOT_FOUND` (unknown path, 404), `METHOD_NOT_ALLOWED` (405 with an `Allow: GET, POST` header, a method other than GET or POST), `NO_SUCH_WORKSPACE`, `NO_SUCH_TODO`, `CHANGELOG_UNAVAILABLE` (404), `NO_WORKSPACE` (412, a request that needs a workspace while none is configured; `/api/state` still answers 200 with an empty snapshot carrying `problems`, which the first-run card reads), `UPSTREAM_FAILED` (502, the report relay failed or answered an error; the HTTP status is in the `ErrorInfo` metadata `upstream_status`), `RATE_LIMITED` (429), `UNKNOWN_ACTION`, `INVALID_BODY`, `INVALID_ARGUMENT` (an empty to-do or remark names the field `text` in a `BadRequest` detail; a report the relay refuses is the same reason), `INVALID_CONFIG` (400), `UPDATE_IN_PROGRESS` (409, an update is already installing), `UPDATE_UNAVAILABLE` (412, nothing to update: a checkout, or already the latest version), `FORBIDDEN_ORIGIN` (403) and `INTERNAL` (500, a fixed message; the raw exception text appears only in a `DebugInfo` detail when the server runs with `WHOSE_TURN_DEBUG=1`, and always in the server log).
|
|
179
179
|
|
|
180
180
|
- `GET /api/workspaces`: `[{id, name, key_pattern, links, connectors:[{id, type, label}], open_moves, theme, theme_seed, failing_sources}]`; `links` are the quick links, `theme` is `{light, dark}`, each a map of CSS variable to value, or `null` without a seed, `theme_seed` is the seed it grows from and `failing_sources` counts the sources with an error. `/api/summary` leaves `theme` out.
|
|
181
181
|
- `GET /api/state?ws=<id>`: one workspace, default the first: `turn` (the rows, each with `group` (`you`, `others`, `done`, or `gone` for a row the workspace's rules hide, which is never your move), `rank`, `next`, `why`, `url`, `ticket_url`, `source`, `status_group` (`backlog`, `passed`, `code_review`, `qa`, `on_hold` or empty) and `handled`), `counts` (`mine`, `others`, `failing`, `done`: the four header tiles), `feed`, `marks` (`{seen, base, handled: {row_id: iso}, info: {row_id: {note?, auto?, outcome?, event?}}}`; `info` carries the note of a mark, and for an automatic mark `auto: true`, the `outcome` phrase, the feed id of the `event` behind it and a `detail` with the assignee and status changes and the latest comment), `todos` (each with `ticket_url`), `errors`, `health`, `polled_at`, `me` (your name per source), `workspace`, plus `workspaces` and `problems`. With `&full=1` the merged raw collections come too: `tickets`, `comments`, `prs`, `activity`, `asks`, `events`.
|
|
@@ -189,10 +189,10 @@ Requests must carry the local `Host`; a POST must be `application/json`. An erro
|
|
|
189
189
|
- `POST /api/refresh` polls now.
|
|
190
190
|
- `GET /api/window` is the size the app window last reported, `{width, height}`, or `{}` before the first report; `POST /api/window` with `{width, height}` (whole pixels, 300 to 10000) stores it in `<data>/window.json`. `open.sh` reads it for `--window-size`.
|
|
191
191
|
- `POST /api/open` with `{mode: 'app' | 'browser'}` runs `open.sh` (with `--browser` for `browser`) on the machine the server runs on, with `WHOSE_TURN_PORT` set to this server's port; this is what the window's "Open as app" button calls. A second open of the same mode within 5 seconds is refused with `429` and reason `OPEN_TOO_SOON` (`retry_after_seconds` in the detail), so a double click opens one window; the button shows "Opening…" meanwhile.
|
|
192
|
-
- `GET /api/feedback`
|
|
192
|
+
- `GET /api/feedback` lists the reports filed from this machine (`<data>/reports.json`, the last hundred) with the state the report relay gives them, read in one call and cached for a minute, so a reporter without a Linear account can follow their reports in the Report sheet and on `/report?id=<identifier>`, the monitor's own page; `GET /api/feedback?id=<identifier>` returns that one report with the maintainer's comments as answers and `unanswered` when it was closed without one; `POST /api/feedback` with `{text, ws?, client?, from?}` lets the server compose the report from a remark in the user's words (the user's own agent from `feedback.composer`, Claude Code by default; the first line becomes the title when no agent answers), or with `{kind: bug|improvement|idea, title, body?, ws?, client?, from?}` sends it as given. A report carries only the kind, the title, the text the user wrote, the monitor version and an `environment` (`os`, `osVersion`, `arch`, `node`, `install` (`npm` when the package runs from `node_modules`, else `source`) and `sources` (the sorted connector types of the workspace named by `ws`, or of all workspaces) built by the server, plus whatever the window reports in the request's `client` object and passes the strict checks: `browser` `{name, version}` (a known name, a major version of one to six digits, never the raw user agent), `display` `{width, height, scale, viewport: [w, h]}` (integer sizes 1 to 20000, scale 0.5 to 8 rounded to two decimals), `locale` (BCP-47, up to 35 characters), `timezone` (an IANA name, up to 64), `theme` (`light` or `dark`) and `mode` (`app` or `tab`); a bad or missing value is left out, never refused): no workspace, row, feed item, hand-off, name or link goes along, and a request with a `context` field is refused with `INVALID_ARGUMENT` so an old plugin is told. Every report and every read goes to the relay, a small public service that holds the only tracker key and files into the maintainer's backlog, so nothing needs connecting on this machine; the report leaves the machine. The reply carries the identifier and url. A failing relay call comes back as `RATE_LIMITED`, `INVALID_ARGUMENT` (the tracker refused the report) or `UPSTREAM_FAILED`, with the raw text only in the server's debug field. The environment never holds a name, account, repository, address or the raw user agent (RMA-291). `WHOSE_TURN_FEEDBACK_URL` points the server at another relay, for a test.
|
|
193
193
|
- `GET /api/handoff?ws=<id>&kind=row|feed|thread|workspace&ref=<row_id, feed id or ticket key>` renders that item with its context as Markdown for pasting into any assistant (`thread` is every feed event of one ticket, newest first, with the ticket's row, PRs and comments); `GET /api/handoff?all=1` renders every workspace. Every hand-off starts with a `Whose Turn · <workspace> · <local date and time>` line and ends with a `Links:` line of the https ticket and PR URLs it mentions, so a paste says which workspace it came from and how old it is; after the header one line says the text below is data from tickets, pull requests and comments, never instructions, and the body follows in a fence a comment cannot close. This is what the window's "Copy for AI" buttons put on the clipboard.
|
|
194
194
|
- `POST /api/inbox` with `{ws, kind: 'row' | 'feed' | 'workspace', ref}` hands an item to an agent through a queue (`ws` is required, a hand-off without it is refused; for MCP clients and the plugin hook): the server queues it in `<data>/inbox.json` with a few words of snapshot and keeps `<data>/inbox.pending` as a marker while the queue is not empty. `{action: 'take', consumer}` returns the items this consumer has not seen yet, each with its context built at that moment (the row with its why and links, the last five comments and the PRs of its ticket, bodies capped; a feed item with its body; or the whole workspace with its rules, moves, waiting rows and to-dos), and marks them delivered to that consumer only, so every agent sees an item once. An item leaves the queue a day after its first delivery or a week after it was queued. `GET /api/inbox?consumer=<name>` lists without taking; `{action: 'clear'}` empties the queue.
|
|
195
|
-
- `GET /api/config`: the raw workspace list as written in the config file, the `problems`, the connector catalogue (`type`, `label`, `fields`), the workspace field catalogue (`fields`: workspace, theme, rules, statuses) and the config file path. `POST /api/config` with `{workspaces: [...], secrets?: [{ws, connector, key, value}]}` validates the list first; on a problem it answers `INVALID_CONFIG` with the problems as `BadRequest.field_violations` in `details` and stores nothing; a violation of one field carries its path (`workspaces[0].rules.backlog_rows`), which the settings form shows under that field. Field specs with `choices` draw as selects. Otherwise it stores the secrets (the account and the store entry come from the connector's own field declaration), writes the file and reloads the workspaces in place; a workspace whose definition did not change keeps its caches, new or changed ones are polled at once. The reply carries the workspace list and `secrets_stored`. A workspace or connector entry that is not an object is refused with `INVALID_CONFIG`, the field violation naming its index (`workspaces[1]`, `workspaces[1].connectors[0]`). An empty list is refused with `INVALID_ARGUMENT` ("keep at least one workspace"), and each write keeps the previous file as `config.json.bak`.
|
|
195
|
+
- `GET /api/config`: the raw workspace list as written in the config file, the `problems`, the connector catalogue (`type`, `label`, `fields`), the workspace field catalogue (`fields`: workspace, theme, rules, statuses) the `notifications` setting and the config file path. `POST /api/config` with `{workspaces: [...], secrets?: [{ws, connector, key, value}]}` validates the list first; on a problem it answers `INVALID_CONFIG` with the problems as `BadRequest.field_violations` in `details` and stores nothing; a violation of one field carries its path (`workspaces[0].rules.backlog_rows`), which the settings form shows under that field. Field specs with `choices` draw as selects. Otherwise it stores the secrets (the account and the store entry come from the connector's own field declaration), writes the file and reloads the workspaces in place; a workspace whose definition did not change keeps its caches, new or changed ones are polled at once. The reply carries the workspace list and `secrets_stored`. A body with `notifications: {desktop}` and no `workspaces` changes only that setting and answers `{notifications}`; `/api/state` and `/api/summary` report it too. A workspace or connector entry that is not an object is refused with `INVALID_CONFIG`, the field violation naming its index (`workspaces[1]`, `workspaces[1].connectors[0]`). An empty list is refused with `INVALID_ARGUMENT` ("keep at least one workspace"), and each write keeps the previous file as `config.json.bak`.
|
|
196
196
|
- `POST /api/secrets` with `{service, account, value}` stores a token on its own (Keychain on macOS, a 600-mode file `<data>/secrets/<service>@<account>` elsewhere); it never touches the config.
|
|
197
197
|
- Both write endpoints are reachable by any local process. A stored token is bound to its service, account and endpoint: a save that would point an existing token at a new endpoint, account or store entry is refused with `INVALID_CONFIG` unless the same request carries the token again, so a process without the token cannot redirect it. See AGENTS.md.
|
|
198
198
|
|
|
@@ -212,7 +212,7 @@ Open it at `http://127.0.0.1:<port>/` (or with `open.sh` as an app window). One
|
|
|
212
212
|
|
|
213
213
|
**Add a source.** First run shows one card with "Add a source". Later, the gear at the bottom of the rail opens Settings: the workspaces on the left, one workspace on the right with its sources, rule texts and colours. Save writes the config; a token goes to the secret store and never into the file. A failing source gets one line in the red banner above the panels, which opens Settings.
|
|
214
214
|
|
|
215
|
-
**Report a problem or a wish.** "Report" in the top bar takes one text field; Send
|
|
215
|
+
**Report a problem or a wish.** "Report" in the top bar takes one text field; Send passes it to the maintainer's tracker (the report leaves your machine; nothing needs connecting) and shows the link, and `/report?id=<issue>` shows the state and the answer.
|
|
216
216
|
|
|
217
217
|
**What's new.** The button above the gear at the bottom of the rail opens a sheet with CHANGELOG.md by version, newest first, the running version marked; a dot on the button says there are versions you have not read since you last opened it, and the "Updated to <version>" chip after an update opens the same sheet.
|
|
218
218
|
|
package/config.example.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const _=e=>fetch(e).then(t=>t.json(),()=>Promise.reject(new Error("unreachable"))),O=(e,t)=>fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})}).then(n=>n.json(),()=>Promise.reject(new Error("unreachable"))),d=(e,t)=>(e.details||[]).find(n=>n["@type"]===t),A=e=>{var t;return((t=d(e,"BadRequest"))==null?void 0:t.field_violations)||[]},y=e=>{var o,a;const t=d(e,"BadRequest");if(t&&t.field_violations)return t.field_violations.map(i=>i.description);const n=(a=(o=d(e,"ErrorInfo"))==null?void 0:o.metadata)==null?void 0:a.detail;return[n?String(n):e.message]},f=e=>{var t;return((t=d(e,"ErrorInfo"))==null?void 0:t.reason)||""},P=e=>fetch("/api/handoff?"+new URLSearchParams(e)).then(t=>t.ok?t.text():Promise.reject(new Error(String(t.status)))),N=e=>typeof e=="string"&&/^https:\/\//.test(e)?e:"",g="No workspace configured. Open Settings.",R=e=>e!=="",v=(e,t,n)=>e.some(o=>o.id===t&&o.open_moves!==n)?e.map(o=>o.id===t?{...o,open_moves:n}:o):e,D=(e,t,n={},o="")=>{const a=e.filter(s=>{var r;return s.group==="you"||s.handled&&((r=n[s.row_id])==null?void 0:r.auto)}).map(s=>({row:s,handled:s.group!=="you"||!!s.handled})).sort((s,r)=>s.row.rank-r.row.rank||String(s.row.updated).localeCompare(String(r.row.updated))),i=a.filter(s=>!s.handled).length,h=t==="handled";return{rows:a.filter(s=>s.handled===h||s.row.row_id===o),open:i,handled:a.length-i}},l=e=>String(e.status_since||e.updated),b=e=>e.filter(t=>t.group==="done").sort((t,n)=>l(n).localeCompare(l(t))).slice(0,15),k=e=>e.filter(t=>t.group==="others").sort((t,n)=>String(n.updated).localeCompare(String(t.updated))),u=e=>!e.ticket_url&&!!e.pr&&e.pr===e.key,U=e=>e.some(t=>t.pr&&!u(t)),C=e=>e==="failing"?"bad":e==="running"?"warn":e==="passing"?"ok":"",p={code_review:"info",qa:"info",on_hold:"hold"},L=e=>p[e||""]||"",j=e=>({open:"info",done:"ok",dropped:"warn"})[e||""]||"info",B=(e,t,n=1)=>e.filter(o=>o>t+n).length,m="unreachable",c="The local server is not answering",E=c+"; try again once it is back.",I=c+"; your text is kept.",T={NO_WORKSPACE:g,UPSTREAM_FAILED:"The tracker did not answer; try again in a minute.",RATE_LIMITED:"The source is rate-limited; the monitor backs off.",OPEN_TOO_SOON:"The app window is already opening; give it a few seconds.",UPDATE_IN_PROGRESS:"An update is already installing; the monitor restarts when it is done.",UPDATE_UNAVAILABLE:"There is no update to install right now.",INTERNAL:"The local server failed; see its log."},w=(e,t="Not saved")=>T[f(e)]||t+": "+(e.message||"the server refused the change."),M=(e,{refused:t="Not saved",unreachable:n=E}={})=>{if(e instanceof Error)return e.message===m?n:t+": "+e.message;if(!e||typeof e!="object"||Array.isArray(e))return"";const o=e.error;return o?w(o,t):""},x=e=>{const t=Math.round((Date.now()-new Date(e).getTime())/6e4);return isFinite(t)?t<1?"now":t<60?t+"m ago":t<2880?Math.round(t/60)+"h ago":new Date(e).toLocaleDateString("en-US",{month:"short",day:"numeric"}):""},W=e=>{const t=(Date.now()-new Date(e??"").getTime())/36e5;return!isFinite(t)||t<0?{text:"",old:!1,hours:0}:{text:t<1?"<1h":t<48?Math.floor(t)+"h":Math.floor(t/24)+"d",old:t>=24,hours:t}},q=e=>e?new Date(e).toLocaleString("en-US",{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"}):"",F=(e,t)=>t?`${e}--${t}`:"";export{c as S,I as T,R as a,M as b,y as c,x as d,w as e,C as f,_ as g,P as h,u as i,L as j,q as k,b as l,F as m,W as n,B as o,O as p,U as q,f as r,N as s,k as t,j as u,A as v,v as w,D as y};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.rail[data-v-ffe046bc]{position:fixed;inset:0 auto 0 0;z-index:30;box-sizing:border-box;display:flex;flex-direction:column;gap:4px;width:60px;padding:12px 8px;overflow:hidden;border-right:1px solid var(--glass-edge);background:rgb(var(--glass),.72);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);font-family:var(--md-font);color:var(--md-on-surface);transition:width .18s ease,box-shadow .18s ease}.rail[data-v-ffe046bc]:hover,.rail[data-v-ffe046bc]:has(:focus-visible){width:232px;box-shadow:12px 0 32px #0000001f}.app:has(.modal) .rail[data-v-ffe046bc]{z-index:0}.rail__item[data-v-ffe046bc]{position:relative;display:flex;align-items:center;gap:12px;height:44px;padding:0 4px;border-radius:12px;color:inherit;text-decoration:none;white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none}.rail__item[data-v-ffe046bc]:focus-visible{outline:var(--focus-ring);outline-offset:-2px}.rail__item--dragging[data-v-ffe046bc]{opacity:.4}.rail__item[data-drop=before][data-v-ffe046bc]{box-shadow:0 -2px 0 0 var(--md-primary)}.rail__item[data-drop=after][data-v-ffe046bc]{box-shadow:0 2px 0 0 var(--md-primary)}.rail__item[data-v-ffe046bc]:hover{background:var(--state-hover)}.rail__item[aria-selected=true][data-v-ffe046bc]{background:var(--md-secondary-container);color:var(--md-on-secondary-container)}.rail__icon[data-v-ffe046bc]{flex:none;display:block;width:36px;height:36px;border-radius:10px}.rail__gear[data-v-ffe046bc]{flex:none;display:grid;place-items:center;width:36px;height:36px;color:var(--md-on-surface-variant)}.rail__label[data-v-ffe046bc]{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:14px;font-weight:500;opacity:0;transition:opacity .12s ease}.rail:hover .rail__label[data-v-ffe046bc],.rail:has(:focus-visible) .rail__label[data-v-ffe046bc]{opacity:1}.rail__badge[data-v-ffe046bc]{position:absolute;top:2px;left:30px;box-sizing:border-box;min-width:18px;height:18px;padding:0 5px;border-radius:999px;background:var(--md-primary);color:var(--md-on-primary);font-size:10px;font-weight:700;line-height:18px;text-align:center}.rail:hover .rail__badge[data-v-ffe046bc],.rail:has(:focus-visible) .rail__badge[data-v-ffe046bc]{position:static;flex:none}.rail__warn[data-v-ffe046bc]{position:absolute;left:26px;top:26px;display:grid;place-items:center;width:14px;height:14px;border-radius:50%;background:var(--md-error);color:var(--md-on-error);font-size:10px;font-weight:800;line-height:1}.rail__dot[data-v-ffe046bc]{position:absolute;top:6px;left:28px;box-sizing:border-box;width:10px;height:10px;border:2px solid var(--md-surface);border-radius:50%;background:var(--md-primary)}.rail__spacer[data-v-ffe046bc]{flex:1}.ai-button[data-v-46197bdc]{position:relative;display:inline-grid;place-items:center;width:26px;height:26px;border-radius:50%;cursor:pointer;color:var(--md-primary);background:rgb(var(--md-state),.06);vertical-align:middle;transition:background .12s ease,transform .12s ease}.ai-button__icon[data-v-46197bdc]{width:15px;height:15px}.ai-button__badge[data-v-46197bdc]{position:absolute;right:-3px;top:-3px;width:12px;height:12px}.ai-button[data-v-46197bdc]:hover{background:var(--md-secondary-container);transform:scale(1.08)}.ai-button[data-v-46197bdc]:focus-visible{outline:var(--focus-ring);outline-offset:1px}.ai-button.ai-button--sent[data-v-46197bdc]{background:var(--md-tertiary-container);color:var(--md-on-tertiary-container)}.ai-button.ai-button--failed[data-v-46197bdc]{background:var(--md-error-container);color:var(--md-on-error-container)}.ai-button--big[data-v-46197bdc]{width:32px;height:32px;background:rgb(var(--glass),.7)}.ai-button--big .ai-button__icon[data-v-46197bdc]{width:18px;height:18px}.update-chip[data-v-c5c2c37f]{display:inline-flex;gap:8px;align-items:center;height:26px;padding:0 12px;font:inherit;color:var(--md-on-primary-container);white-space:nowrap;cursor:pointer;background:var(--md-primary-container);border:0;border-radius:var(--md-r-chip)}.update-chip--busy[data-v-c5c2c37f]{cursor:default}.update-chip--ready[data-v-c5c2c37f]{color:var(--md-on-primary);background:var(--md-primary)}.update-chip--failed[data-v-c5c2c37f]{color:var(--md-on-error-container);background:var(--md-error-container)}.update-chip__spinner[data-v-c5c2c37f]{width:12px;height:12px;border:2px solid currentcolor;border-top-color:transparent;border-radius:50%;animation:update-chip-spin-c5c2c37f .9s linear infinite}@media(prefers-reduced-motion:reduce){.update-chip__spinner[data-v-c5c2c37f]{animation:none}}.update-chip__link[data-v-c5c2c37f]{padding:0;font:inherit;color:inherit;text-decoration:underline;cursor:pointer;background:none;border:0}@keyframes update-chip-spin-c5c2c37f{to{transform:rotate(360deg)}}.notifications-toggle[data-v-6704e5f1]{gap:6px;height:26px;padding:0 12px;font-size:12px}.notifications-toggle--off[data-v-6704e5f1]{color:var(--md-on-error-container);background:var(--md-error-container)}.notifications-toggle__icon[data-v-6704e5f1]{width:16px;height:16px}.status-bar[data-v-940c94f2]{display:flex;align-items:center;gap:10px;margin:0 4px 8px;font-family:var(--md-font);font-size:12px;color:var(--md-on-surface-variant)}.status-bar__btn[data-v-940c94f2]{height:26px;padding:0 12px;font-size:12px;text-decoration:none}.status-bar__btn--busy[data-v-940c94f2]{opacity:.6;pointer-events:none}.status-bar__report[data-v-940c94f2]{gap:6px}.status-bar__icon[data-v-940c94f2]{width:16px;height:16px}.status-bar__live[data-v-940c94f2]{width:8px;height:8px;border-radius:50%;background:var(--live-on);box-shadow:0 0 0 0 var(--live-pulse-rest);animation:status-bar-pulse-940c94f2 2s infinite}.status-bar__live--off[data-v-940c94f2]{background:var(--live-off);animation:none}.status-bar__live--warn[data-v-940c94f2]{background:var(--live-warn);animation:none}.status-bar__notice[data-v-940c94f2]{color:var(--live-off)}.status-bar__ai-hint[data-v-940c94f2]{margin-left:-4px}@keyframes status-bar-pulse-940c94f2{0%{box-shadow:0 0 0 0 var(--live-pulse-from)}70%{box-shadow:0 0 0 8px var(--live-pulse-to)}to{box-shadow:0 0 0 0 var(--live-pulse-to)}}@media(prefers-reduced-motion:reduce){.status-bar__live[data-v-940c94f2]{animation:none}}.workspace-header[data-v-3421a7f0]{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(0,2fr) 32px;gap:8px;padding:8px;background:linear-gradient(135deg,var(--blob-1),var(--blob-2));color:var(--header-ink, var(--md-on-primary-container))}@media(prefers-reduced-transparency:reduce){.workspace-header[data-v-3421a7f0]{background:var(--md-s-low)}}.workspace-header__title[data-v-3421a7f0]{display:grid;align-content:center;gap:4px;padding:12px 16px}.workspace-header__name[data-v-3421a7f0]{margin:0;font-size:28px;font-weight:400;line-height:36px;color:var(--md-on-primary-container)}.workspace-header__line[data-v-3421a7f0]{margin:0;font-size:14px;opacity:.85}.workspace-header__count[data-v-3421a7f0]{font-weight:700;font-variant-numeric:tabular-nums}.workspace-header__give[data-v-3421a7f0]{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px;margin-top:8px;white-space:nowrap}.workspace-header__links[data-v-3421a7f0]{display:inline-flex;gap:6px}.workspace-header__links a[data-v-3421a7f0]{display:inline-flex;align-items:center;height:24px;padding:0 10px;border:1px solid var(--glass-edge);border-radius:999px;background:rgb(var(--glass),.55);color:inherit;font-size:12px;font-weight:500}.workspace-header__links a[data-v-3421a7f0]:hover{background:rgb(var(--glass),.85)}.workspace-header__fold[data-v-3421a7f0]{grid-row:1;grid-column:3;place-self:center center;margin:0;color:inherit}.workspace-header__tiles[data-v-3421a7f0]{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}.workspace-header__tile[data-v-3421a7f0]{display:grid;align-content:start;gap:4px;padding:12px 16px;border:1px solid var(--glass-edge);border-radius:var(--md-r-card);background:rgb(var(--glass),calc(var(--glass-a) + .1));-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);color:var(--md-on-surface)}@media(prefers-reduced-transparency:reduce){.workspace-header__tile[data-v-3421a7f0]{background:var(--md-s-low);-webkit-backdrop-filter:none;backdrop-filter:none}}.workspace-header__tile-label[data-v-3421a7f0]{color:var(--md-on-surface-variant);font-size:12px;font-weight:500;line-height:16px;letter-spacing:.03em}.workspace-header__tile-value[data-v-3421a7f0]{min-height:40px;font-size:32px;font-weight:400;line-height:40px;font-variant-numeric:tabular-nums}.workspace-header__tile--you[data-v-3421a7f0]{border-color:transparent;background:var(--md-primary);color:var(--md-on-primary)}.workspace-header__tile--you .workspace-header__tile-label[data-v-3421a7f0]{color:var(--md-on-primary);opacity:.85}.workspace-header__tile--fail .workspace-header__tile-value[data-v-3421a7f0]{color:var(--md-error)}.workspace-header--collapsed[data-v-3421a7f0]{grid-template-columns:minmax(0,1fr) 32px;padding:4px 8px}.workspace-header--collapsed .workspace-header__title[data-v-3421a7f0]{display:flex;flex-wrap:wrap;align-items:baseline;gap:14px;padding:4px 8px}.workspace-header--collapsed .workspace-header__name[data-v-3421a7f0]{font-size:18px;line-height:28px}.workspace-header--collapsed .workspace-header__tiles[data-v-3421a7f0],.workspace-header--collapsed .workspace-header__give[data-v-3421a7f0]{display:none}.workspace-header--collapsed .workspace-header__fold[data-v-3421a7f0]{grid-column:2}.workspace-header--collapsed .workspace-header__strip[data-v-3421a7f0]{font-size:13px}@media(max-width:900px){.workspace-header[data-v-3421a7f0],.workspace-header--collapsed[data-v-3421a7f0]{grid-template-columns:minmax(0,1fr) 32px}.workspace-header__fold[data-v-3421a7f0]{grid-column:2}.workspace-header__tiles[data-v-3421a7f0]{grid-column:1 / -1}}@media(max-width:640px){.workspace-header__tiles[data-v-3421a7f0]{grid-template-columns:repeat(2,minmax(0,1fr))}}.chevron[data-v-a14fa9ba]{flex:none;display:inline-grid;place-items:center;width:24px;height:24px;border-radius:50%;color:var(--md-on-surface-variant);cursor:pointer;-webkit-user-select:none;user-select:none}.chevron[data-v-a14fa9ba]:before{content:"";width:7px;height:7px;border-right:2px solid currentcolor;border-bottom:2px solid currentcolor;transform:translate(-1px) rotate(-45deg);transition:transform .15s ease}.chevron--open[data-v-a14fa9ba]:before{transform:translateY(-2px) rotate(45deg)}.chevron[data-v-a14fa9ba]:hover{background:var(--state-hover)}.chevron[data-v-a14fa9ba]:focus-visible{outline:var(--focus-ring)}.resize-handle[data-v-8e637688]{position:absolute;z-index:2;touch-action:none;border-radius:4px}.resize-handle[data-v-8e637688]:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;border-radius:2px;background:var(--md-outline-variant);opacity:0;transition:opacity .15s ease}.resize-handle[data-v-8e637688]:hover:after,.resize-handle[data-v-8e637688]:focus-visible:after{opacity:1}.resize-handle[data-v-8e637688]:focus-visible{outline:var(--focus-ring)}.resize-handle--y[data-v-8e637688]{right:0;bottom:0;left:0;height:10px;cursor:row-resize}.resize-handle--y.resize-handle--top[data-v-8e637688]{top:0;bottom:auto}.resize-handle--y[data-v-8e637688]:after{width:40px;height:4px}.resize-handle--x[data-v-8e637688]{top:0;bottom:0;left:0;width:10px;cursor:col-resize}.resize-handle--x[data-v-8e637688]:after{width:4px;height:40px}@media(max-width:900px){.resize-handle[data-v-8e637688]{display:none}}.island__head[data-v-53a904f0]{display:flex;flex-wrap:nowrap;align-items:center;justify-content:space-between;gap:8px;padding:12px 20px 12px 12px}.island__title[data-v-53a904f0]{flex:none;margin:0;font-size:16px;line-height:24px;font-weight:500;letter-spacing:.01em;white-space:nowrap}.island__note[data-v-53a904f0]{display:flex;flex:1 1 auto;align-items:center;justify-content:flex-end;gap:6px;min-width:0;margin:0;overflow:visible;color:var(--md-on-surface-variant);font-size:12px;line-height:16px;letter-spacing:.03em;text-align:right;white-space:nowrap;text-overflow:ellipsis}.island__note-text[data-v-53a904f0]{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.island__body[data-v-53a904f0]{padding:0 20px 12px}.island--column .island__head[data-v-53a904f0]{gap:4px}.island--column .island__body[data-v-53a904f0]{display:flex;flex-direction:column;min-height:0;padding-top:4px}.island.island--collapsed .island__body[data-v-53a904f0]{display:none}@media(min-width:901px){.dashboard--fit .dashboard__main .island__body[data-v-53a904f0]{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;padding-bottom:0}.dashboard--fit .dashboard__main .island.island--collapsed .island__body[data-v-53a904f0]{display:none}}.segmented[data-v-201d5e2f]{display:inline-flex;overflow:hidden;border:1px solid var(--md-outline);border-radius:999px;vertical-align:middle}.segmented--chips[data-v-201d5e2f]{flex:none;align-self:flex-start;background:rgb(var(--glass),.4)}.segmented__option[data-v-201d5e2f]{display:inline-flex;align-items:center;gap:5px;height:26px;padding:0 11px;border-left:1px solid var(--md-outline);font-size:12px;font-weight:500;color:var(--md-on-surface);cursor:pointer;-webkit-user-select:none;user-select:none}.segmented__option[data-v-201d5e2f]:first-child{border-left:0}.segmented__option[aria-pressed=true][data-v-201d5e2f]{background:var(--md-secondary-container);color:var(--md-on-secondary-container)}.segmented__option[data-v-201d5e2f]:focus-visible{outline:var(--focus-ring);outline-offset:-2px}.segmented--chips .segmented__option[data-v-201d5e2f]{gap:normal;height:32px;padding:0 14px;font-family:var(--md-font);font-size:14px;letter-spacing:.01em}.segmented--chips .segmented__option[data-v-201d5e2f]:hover{background:var(--state-hover)}.segmented--chips .segmented__option[aria-pressed=true][data-v-201d5e2f]{background:var(--md-secondary-container);color:var(--md-on-secondary-container)}.ticket-cell__summary[data-v-e2d11a0b]{display:block;max-width:44ch;margin-top:2px;color:var(--md-on-surface-variant);font-size:12px;line-height:16px;letter-spacing:.03em}.pr-cell[data-v-6078ccbd]{display:flex;flex-direction:column;align-items:flex-start;gap:4px}.pr-cell__link[data-v-6078ccbd]{max-width:100%;overflow-wrap:anywhere}.recently-done[data-v-68a4b78e]{position:relative;display:flex;flex:0 1 auto;flex-direction:column;min-height:33px;margin:0 -20px;padding:0 20px;overflow:hidden;border-top:1px solid var(--md-outline-variant)}.recently-done[open][data-v-68a4b78e]{min-height:128px}.recently-done__summary[data-v-68a4b78e]{display:flex;flex:none;align-items:center;gap:4px;min-height:40px;list-style:none;color:var(--md-on-surface-variant);font-size:14px;font-weight:500;cursor:pointer}.recently-done__summary[data-v-68a4b78e]::-webkit-details-marker{display:none}.recently-done__list[data-v-68a4b78e]{flex:1 1 auto;min-height:0;max-height:min(30vh,240px);margin:0 -20px;padding-bottom:8px;overflow:auto}.row-scroll[data-v-e7f699d1]{overflow-x:auto;margin:0 -20px}@media(min-width:901px){.dashboard--fit .dashboard__main .row-scroll[data-v-e7f699d1]{flex:1 1 auto;min-height:0;overflow:auto;scroll-padding-top:40px}.dashboard--fit .row-scroll[data-v-e7f699d1]::-webkit-scrollbar{width:8px;height:8px}.dashboard--fit .row-scroll[data-v-e7f699d1]::-webkit-scrollbar-thumb{border-radius:4px;background:var(--md-outline-variant)}}.dashboard--fit .dashboard__main .row-scroll--floor[data-v-e7f699d1]{min-height:5rem}.row-scroll__more[data-v-e7f699d1]{flex:none;display:block;margin:0 -20px;padding:4px 20px 6px;border-top:1px solid var(--md-outline-variant);color:var(--md-primary);font-size:13px;font-weight:500;cursor:pointer}.row-scroll__more[data-v-e7f699d1]:hover{background:rgb(var(--md-state),.06)}.row-scroll__more[data-v-e7f699d1]:focus-visible{outline:var(--focus-ring);outline-offset:-2px}.your-move__undo[data-v-3a6ca0d0]{margin:0;padding:4px 0;color:var(--md-on-surface-variant);font-size:13px}.your-move__undo-btn[data-v-3a6ca0d0]{color:var(--md-primary);font-weight:500;cursor:pointer}.your-move__view[data-v-3a6ca0d0]{margin-left:10px}.your-move__next[data-v-3a6ca0d0]{font-weight:500}.your-move__line-cell[data-v-3a6ca0d0]{max-width:0;padding-top:0}.your-move__line[data-v-3a6ca0d0]{display:flex;align-items:center;gap:8px;box-sizing:border-box;width:100%;min-width:0;height:24px;padding:0 10px 0 8px;border-left:2px solid var(--md-outline);border-radius:0 6px 6px 0;background:var(--md-s-high);color:var(--md-on-surface-variant);font-size:12px;line-height:16px;text-align:left;cursor:pointer}.your-move__line[data-v-3a6ca0d0]:hover{background:var(--md-s-highest)}.your-move__line[data-v-3a6ca0d0]:focus-visible{outline:var(--focus-ring);outline-offset:1px}.your-move__arrow[data-v-3a6ca0d0]{flex:none}.your-move__outcome[data-v-3a6ca0d0]{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.your-move__time[data-v-3a6ca0d0]{flex:none;margin-left:auto;font-variant-numeric:tabular-nums}.your-move__quote[data-v-3a6ca0d0]{max-width:48ch;color:var(--md-on-surface-variant);font-size:12px;line-height:16px}.your-move__quote a[data-v-3a6ca0d0]{color:var(--md-on-surface-variant)}.your-move__problem[data-v-3a6ca0d0]{margin:4px 0 0;padding:4px 10px;font-size:12px}.your-move__mark[data-v-3a6ca0d0]{display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 12px;border:1px solid var(--md-outline);border-radius:999px;color:var(--md-on-surface);font-size:12px;font-weight:600;white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none}.your-move__mark[data-v-3a6ca0d0]:hover{background:var(--state-hover)}.your-move__mark[data-v-3a6ca0d0]:before{content:"";width:9px;height:5px;border-bottom:2px solid currentcolor;border-left:2px solid currentcolor;transform:translateY(-2px) rotate(-45deg)}.your-move__mark--undo[data-v-3a6ca0d0]:before{display:none}.your-move__mark[data-v-3a6ca0d0]:focus-visible{outline:var(--focus-ring);outline-offset:2px}.your-move__row--lined td[data-v-3a6ca0d0]{border-bottom:0;padding-bottom:8px}.your-move__row--handled td[data-v-3a6ca0d0],.your-move__line-row--handled td[data-v-3a6ca0d0]{opacity:.55}.your-move__row--handled .your-move__next[data-v-3a6ca0d0]{text-decoration:line-through;text-decoration-color:var(--md-outline)}.your-move__row--handled .table__actions[data-v-3a6ca0d0]{opacity:1}.todos__view[data-v-6dbdbb66]{margin-left:10px}.todos__add[data-v-6dbdbb66]{display:flex;align-items:center;gap:8px;padding:8px 0}.todos__input[data-v-6dbdbb66]{flex:1;min-width:0;height:32px;padding:0 12px;background:rgb(var(--md-state),.04);font-size:14px}.todos__list[data-v-6dbdbb66]{margin:0 -20px;padding:0;overflow-y:auto;list-style:none}.todos__item[data-v-6dbdbb66]{display:grid;grid-template-columns:20px minmax(0,1fr) auto 20px 20px;align-items:center;gap:10px;padding:7px 20px;border-top:1px solid var(--md-outline-variant)}.todos__item[data-v-6dbdbb66]:first-child{border-top:0}.todos__item[data-v-6dbdbb66]:hover{background:rgb(var(--md-state),.06)}.todos__text[data-v-6dbdbb66]{overflow-wrap:anywhere}.todos__item--done .todos__text[data-v-6dbdbb66]{color:var(--md-on-surface-variant);text-decoration:line-through}.todos__empty[data-v-6dbdbb66]{display:block;padding:6px 20px 10px}.todos__check[data-v-6dbdbb66]{box-sizing:border-box;display:grid;place-items:center;width:18px;height:18px;border:2px solid var(--md-outline);border-radius:5px;cursor:pointer}.todos__check--on[data-v-6dbdbb66]{border-color:var(--md-primary);background:var(--md-primary)}.todos__check--on[data-v-6dbdbb66]:after{content:"";width:8px;height:4px;border-bottom:2px solid var(--md-on-primary);border-left:2px solid var(--md-on-primary);transform:translateY(-1px) rotate(-45deg)}.todos__meta[data-v-6dbdbb66]{color:var(--md-on-surface-variant);font-size:11px;white-space:nowrap}.todos__edit[data-v-6dbdbb66]{min-width:0;height:28px;padding:0 8px;font-size:14px}.todos__undo[data-v-6dbdbb66]{margin:0;padding:4px 0;color:var(--md-on-surface-variant);font-size:13px}.todos__undo-btn[data-v-6dbdbb66]{color:var(--md-primary);font-weight:500;cursor:pointer}.todos__pencil[data-v-6dbdbb66],.todos__delete[data-v-6dbdbb66]{color:var(--md-on-surface-variant);font-size:16px;line-height:1;text-align:center;cursor:pointer;opacity:0}.todos__pencil[data-v-6dbdbb66]:focus-visible,.todos__delete[data-v-6dbdbb66]:focus-visible{opacity:1}.todos__item:hover .todos__pencil[data-v-6dbdbb66],.todos__item:hover .todos__delete[data-v-6dbdbb66]{opacity:1}@media(min-width:901px){.dashboard--fit .dashboard__todo .todos__list[data-v-6dbdbb66]{flex:1 1 auto;min-height:0}.dashboard--fit .dashboard__todo .todos__list[data-v-6dbdbb66]:not(:has(.todos__item)){display:none}}.waiting__table[data-v-90e8bf77]{table-layout:fixed}.waiting__col--ticket[data-v-90e8bf77]{width:22%}.waiting__col--status[data-v-90e8bf77],.waiting__col--with[data-v-90e8bf77]{width:6.5rem}.waiting__col--pr[data-v-90e8bf77]{width:4.5rem}.waiting__col--actions[data-v-90e8bf77]{width:2rem}.waiting__reason[data-v-90e8bf77]{display:block;min-width:0;max-width:44ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.feed-item[data-v-8cc9dc10]{display:grid;grid-template-columns:32px minmax(0,1fr);align-items:start;gap:12px;padding:10px 20px;cursor:default}.feed-item[data-v-8cc9dc10]:hover{background:var(--state-hover)}.feed-item.feed-item--open[data-v-8cc9dc10]{background:rgb(var(--md-state),.05)}.feed-item.feed-item--new[data-v-8cc9dc10]{background:var(--new-bg);box-shadow:inset 4px 0 0 var(--new),inset 0 0 0 1px var(--new-edge)}.feed-item.feed-item--flash[data-v-8cc9dc10]{box-shadow:inset 0 0 0 2px var(--md-primary)}.feed-item__icon[data-v-8cc9dc10]{flex:none;display:grid;place-items:center;width:32px;height:32px;border-radius:50%;background:var(--md-s-highest);color:var(--md-on-surface-variant);font-size:11px;font-weight:700;letter-spacing:.02em}.feed-item__icon--jira[data-v-8cc9dc10]{background:var(--md-primary-container);color:var(--md-on-primary-container)}.feed-item__icon--bad[data-v-8cc9dc10]{background:var(--md-error-container);color:var(--md-on-error-container)}.feed-item__icon--ok[data-v-8cc9dc10]{background:var(--md-tertiary-container);color:var(--md-on-tertiary-container)}.feed-item__body[data-v-8cc9dc10]{display:grid;gap:2px;min-width:0}.feed-item__top[data-v-8cc9dc10]{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;font-size:14px}.feed-item__right[data-v-8cc9dc10]{flex:none;display:inline-flex;align-items:center;gap:4px;margin-left:auto}.feed-item__kind[data-v-8cc9dc10]{font-weight:500}.feed-item__kind--bad[data-v-8cc9dc10]{color:var(--md-error)}.feed-item__who[data-v-8cc9dc10]{color:var(--md-on-surface-variant)}.feed-item__text[data-v-8cc9dc10]{display:-webkit-box;overflow:hidden;color:var(--md-on-surface-variant);font-size:12px;line-height:16px;letter-spacing:.03em;overflow-wrap:anywhere;-webkit-line-clamp:2;-webkit-box-orient:vertical}.feed-item__full[data-v-8cc9dc10]{max-height:16rem;margin-top:6px;padding:10px 12px;overflow:auto;border:1px solid var(--glass-edge);border-radius:var(--md-r-chip);background:rgb(var(--glass),.55);color:var(--md-on-surface);font-size:13px;line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}.feed-item__actions[data-v-8cc9dc10]{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}.feed-item--new .feed-item__kind[data-v-8cc9dc10]{color:var(--md-on-surface);font-weight:700}.feed-item--new .feed-item__text[data-v-8cc9dc10]{color:var(--md-on-surface)}.feed-item--new .feed-item__icon[data-v-8cc9dc10]{box-shadow:0 0 0 2px var(--new)}.feed-item--new .feed-item__when[data-v-8cc9dc10]:before{content:"NEW";display:inline-block;margin-right:6px;padding:1px 6px;border-radius:4px;background:var(--new);color:var(--new-ink);font-size:10px;font-weight:800;letter-spacing:.06em;vertical-align:1px}.feed-item:not(.feed-item--new) .feed-item__body[data-v-8cc9dc10]{opacity:.78}@media(max-width:1500px){.feed[data-v-bbacc3b6] .island__note-text{display:none}}.feed__undo[data-v-bbacc3b6]{margin:0 0 4px;color:var(--md-on-surface-variant);font-size:13px}.feed__undo-btn[data-v-bbacc3b6]{color:var(--md-primary);font-weight:500;cursor:pointer}.feed__bar[data-v-bbacc3b6]{display:flex;flex:none;flex-wrap:nowrap;align-items:center;justify-content:space-between;gap:8px;margin:0 0 8px}.feed__new-count[data-v-bbacc3b6]{display:inline-flex;align-items:center;height:22px;padding:0 9px;border-radius:999px;background:var(--new);color:var(--new-ink);box-shadow:0 0 12px var(--new-glow);font-size:12px;font-weight:800}.feed__mark-read[data-v-bbacc3b6]{flex:none;padding:4px 8px;border-radius:999px;color:var(--md-primary);font-size:13px;font-weight:500;cursor:pointer;-webkit-user-select:none;user-select:none}.feed__mark-read[data-v-bbacc3b6]:hover{background:var(--state-hover)}.feed__mark-read[data-v-bbacc3b6]:focus-visible{outline:var(--focus-ring)}.feed__search[data-v-bbacc3b6]{display:flex;flex:none;align-items:center;gap:8px;margin:0 0 8px}.feed__search-input[data-v-bbacc3b6]{flex:1;min-width:0;height:30px;padding:0 10px;font-size:13px}.feed__search-count[data-v-bbacc3b6]{flex:none;color:var(--md-on-surface-variant);font-size:12px}.feed__list[data-v-bbacc3b6]{flex:1 1 auto;min-height:12rem;margin:0 -20px;padding:0 0 4px;overflow-y:auto;list-style:none}.feed__group[data-v-bbacc3b6]{display:grid;grid-template-columns:minmax(0,1fr);align-items:start;gap:0;padding:0;cursor:default}.feed__group[data-v-bbacc3b6]:hover{background:var(--state-hover)}.feed__group.feed__group--open[data-v-bbacc3b6]{background:rgb(var(--md-state),.05)}.feed__group.feed__group--new[data-v-bbacc3b6]{background:var(--new-bg);box-shadow:inset 4px 0 0 var(--new),inset 0 0 0 1px var(--new-edge)}.feed__group-head[data-v-bbacc3b6]{display:grid;grid-template-columns:24px minmax(0,1fr) auto;align-items:center;gap:12px;padding:10px 20px;cursor:pointer}.feed__group-copy[data-v-bbacc3b6]{opacity:.55}.feed__group-head:hover .feed__group-copy[data-v-bbacc3b6]{opacity:1}.feed__group-head[data-v-bbacc3b6]:hover{background:var(--state-hover)}.feed__group--new>.feed__group-head[data-v-bbacc3b6]{background:var(--new-bg);box-shadow:inset 4px 0 0 var(--new)}.feed__group--move[data-v-bbacc3b6],.feed__group--move>.feed__group-head[data-v-bbacc3b6]{box-shadow:inset 4px 0 0 var(--move)}.feed__group.feed__group--new.feed__group--move[data-v-bbacc3b6]{box-shadow:inset 4px 0 0 var(--move),inset 0 0 0 1px var(--new-edge)}.feed__group-text[data-v-bbacc3b6]{min-width:0}.feed__group-key[data-v-bbacc3b6]{display:flex;align-items:baseline;gap:8px;font-size:14px}.feed__group-ticket[data-v-bbacc3b6]{flex:none;font-weight:600}.feed__group-sum[data-v-bbacc3b6]{overflow:hidden;color:var(--md-on-surface-variant);font-size:13px;text-overflow:ellipsis;white-space:nowrap}.feed__group-meta[data-v-bbacc3b6]{display:flex;align-items:center;gap:8px;margin-top:2px;color:var(--md-on-surface-variant);font-size:12px}.feed__group-kinds[data-v-bbacc3b6]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.feed__group-when[data-v-bbacc3b6]{margin-left:auto}.feed__group-count[data-v-bbacc3b6]{flex:none;display:inline-flex;align-items:center;height:18px;padding:0 7px;border-radius:999px;background:var(--md-s-highest);color:var(--md-on-surface-variant);font-size:11px;font-weight:700}.feed__group-count--new[data-v-bbacc3b6]{background:var(--new);color:var(--new-ink)}.feed__children[data-v-bbacc3b6]{margin:0 0 0 31px;padding:0 0 4px;border-left:2px solid var(--md-outline-variant);list-style:none}.feed__children .feed-item[data-v-bbacc3b6]{padding-left:14px}@media(min-width:901px){.dashboard--fit .feed__list[data-v-bbacc3b6]::-webkit-scrollbar{width:8px;height:8px}.dashboard--fit .feed__list[data-v-bbacc3b6]::-webkit-scrollbar-thumb{border-radius:4px;background:var(--md-outline-variant)}}@media(max-width:900px){.feed__list[data-v-bbacc3b6]{max-height:28rem}}.first-run[data-v-84359c2d]{display:grid;place-self:start center;gap:14px;width:min(640px,100%);padding:28px 32px}.first-run__title[data-v-84359c2d]{margin:0;font-size:22px;font-weight:400;line-height:28px}.first-run__text[data-v-84359c2d]{margin:0;color:var(--md-on-surface-variant)}.first-run__actions[data-v-84359c2d]{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}.first-run__ai[data-v-84359c2d]{font-size:13px}.markdown-view[data-v-dcf42e95]{padding:16px 20px 20px;overflow:auto;overflow-wrap:anywhere;font-size:14px;line-height:1.6}.markdown-view[data-v-dcf42e95] h4,.markdown-view[data-v-dcf42e95] h5{margin:16px 0 6px;font-weight:600}.markdown-view[data-v-dcf42e95] h4{font-size:16px}.markdown-view[data-v-dcf42e95] h5{font-size:14px}.markdown-view[data-v-dcf42e95] p{margin:0 0 10px}.markdown-view[data-v-dcf42e95] ul,.markdown-view[data-v-dcf42e95] ol{margin:0 0 10px;padding-left:22px}.markdown-view[data-v-dcf42e95] li{margin:2px 0}.markdown-view[data-v-dcf42e95] code{padding:1px 5px;border-radius:4px;background:rgb(var(--md-state),.1);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9em}.markdown-view[data-v-dcf42e95] pre{margin:0 0 12px;padding:12px 14px;overflow:auto;border-radius:8px;background:#00000047}.markdown-view[data-v-dcf42e95] pre code{padding:0;background:none;font-size:12.5px;line-height:1.5;white-space:pre}.markdown-view[data-v-dcf42e95] blockquote{margin:0 0 10px;padding:4px 12px;border-left:3px solid var(--md-primary);color:var(--md-on-surface-variant)}.markdown-view[data-v-dcf42e95] strong{font-weight:600}.markdown-view[data-v-dcf42e95] .markdown-view__mention{color:var(--md-primary);font-weight:500}.modal__body[data-v-f2f8cfc9]{display:flex;flex-direction:column;gap:12px;padding:16px 20px;overflow:auto}.modal__body--flush[data-v-f2f8cfc9]{gap:0;padding:0}.modal__foot[data-v-f2f8cfc9]{display:flex;justify-content:flex-end;gap:8px;padding:12px 20px;border-top:1px solid var(--md-outline-variant)}.note-modal__summary[data-v-6fc1670a]{margin:0;color:var(--md-on-surface-variant);font-size:13px}.note-modal__facts[data-v-6fc1670a]{display:grid;grid-template-columns:max-content 1fr;gap:6px 16px;margin:0;font-size:13px}.note-modal__facts dt[data-v-6fc1670a]{color:var(--md-on-surface-variant)}.note-modal__facts dd[data-v-6fc1670a]{margin:0;overflow-wrap:anywhere}.note-modal__author[data-v-6fc1670a]{font-weight:500}.note-modal__label[data-v-6fc1670a]{color:var(--md-on-surface-variant);font-size:12px}.note-modal__text[data-v-6fc1670a]{width:100%;box-sizing:border-box;resize:vertical}.feedback-sheet__card[data-v-a76221de]{width:min(640px,100%)}.feedback-sheet__text[data-v-a76221de]{min-height:7rem;resize:vertical}.feedback-sheet__note[data-v-a76221de]{margin:0;color:var(--md-on-surface-variant);font-size:12px}.feedback-sheet__report[data-v-a76221de]{display:flex;align-items:baseline;gap:8px;padding:4px 0;border-top:1px solid var(--md-outline-variant);font-size:13px}.feedback-sheet__report-title[data-v-a76221de]{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.field-row[data-v-33714840]{display:grid;grid-template-columns:170px minmax(0,1fr);align-items:center;gap:4px 14px}.field-row__label[data-v-33714840]{color:var(--md-on-surface);font-size:13px}.field-row__hint[data-v-33714840]{grid-column:2;color:var(--md-on-surface-variant);font-size:11px}.field-row__error[data-v-33714840]{grid-column:2;color:var(--md-error);font-size:12px}.field-row__check[data-v-33714840]{display:flex;align-items:center;gap:8px;color:var(--md-on-surface-variant);font-size:11px}.field-row__colour[data-v-33714840]{width:44px;height:30px;padding:2px}.field-row__inline[data-v-33714840]{display:flex;align-items:center;gap:8px}.settings-sheet__card[data-v-8253a01a]{width:min(1040px,100%);height:min(760px,100%)}.settings-sheet__dirty[data-v-8253a01a]{color:var(--md-error);font-size:12px;font-weight:600}.settings-sheet__confirm[data-v-8253a01a]{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:12px 20px 0;padding:8px 12px;border-radius:10px;background:var(--md-warn-container);color:var(--md-on-warn-container);font-size:13px}.settings-sheet__confirm-text[data-v-8253a01a]{flex:1}.settings-sheet__alert[data-v-8253a01a]{margin:12px 20px 0}.settings-sheet__body[data-v-8253a01a]{display:grid;flex:1;grid-template-columns:220px minmax(0,1fr);gap:0;min-height:0}.settings-sheet__list[data-v-8253a01a]{display:flex;flex-direction:column;gap:4px;margin:0;padding:12px;overflow:auto;border-right:1px solid var(--md-outline-variant);list-style:none}.settings-sheet__workspace[data-v-8253a01a]{box-sizing:border-box;display:block;width:100%;padding:8px 12px;overflow:hidden;border-radius:10px;font-size:14px;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}.settings-sheet__workspace[data-v-8253a01a]:hover{background:var(--state-hover)}.settings-sheet__workspace[aria-current=true][data-v-8253a01a]{background:var(--md-secondary-container);color:var(--md-on-secondary-container)}.settings-sheet__workspace[data-v-8253a01a]:focus-visible{outline:var(--focus-ring);outline-offset:-2px}.settings-sheet__workspace--add[data-v-8253a01a]{color:var(--md-primary);font-weight:500}.settings-sheet__connector[data-v-8253a01a]{display:flex;flex-direction:column;gap:10px;padding:12px 14px;border:1px solid var(--md-outline-variant);border-radius:12px;background:rgb(var(--glass),.35)}.settings-sheet__connector-head[data-v-8253a01a]{display:flex;align-items:center;gap:10px}.settings-sheet__connector-name[data-v-8253a01a]{flex:1;font-weight:600}.settings-sheet__actions[data-v-8253a01a]{display:flex;flex-wrap:wrap;align-items:center;gap:10px}.settings-sheet__rules[data-v-8253a01a]{display:flex;flex-direction:column;gap:6px;margin:0;padding:0 0 0 28px;font-size:13px}.settings-sheet__rule[data-v-8253a01a]{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,2fr);gap:12px;padding:4px 0;border-bottom:1px solid var(--md-outline-variant)}.settings-sheet__rule-when[data-v-8253a01a]{color:var(--md-on-surface-variant);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;overflow-wrap:anywhere}.settings-sheet__rule-then[data-v-8253a01a]{overflow-wrap:anywhere}.settings-sheet__rules-note[data-v-8253a01a]{margin:0;color:var(--md-on-surface-variant)}.settings-sheet__rules-warning[data-v-8253a01a]{margin:0;padding:6px 10px;border-radius:8px;background:var(--md-warn-container);color:var(--md-on-warn-container)}.whats-new__version[data-v-78394e08]{padding:16px 0 4px;border-bottom:1px solid var(--md-outline-variant)}.whats-new__version[data-v-78394e08]:last-child{border-bottom:0}.whats-new__head[data-v-78394e08]{display:flex;gap:10px;align-items:baseline;padding:0 20px}.whats-new__name[data-v-78394e08]{margin:0;font-size:16px;font-weight:600}.whats-new__date[data-v-78394e08]{font-size:12px;color:var(--md-on-surface-variant)}.whats-new__tag[data-v-78394e08]{padding:1px 8px;font-size:11px;font-weight:600;color:var(--md-on-primary);background:var(--md-primary);border-radius:var(--md-r-chip)}.whats-new__tag--running[data-v-78394e08]{color:var(--md-on-secondary-container);background:var(--md-secondary-container)}.whats-new__empty[data-v-78394e08]{margin:6px 20px 14px;font-size:13px;color:var(--md-on-surface-variant)}.app__shell[data-v-580c2b4a]{box-sizing:border-box;display:flex;flex-direction:column;height:100%;padding:12px 12px 12px 72px}.app__shell>.dashboard[data-v-580c2b4a]{flex:1 1 auto;min-height:0}@media(min-width:901px){.app__shell>.dashboard.dashboard--fit[data-v-580c2b4a]{height:auto}}@media(max-width:900px){.app__shell[data-v-580c2b4a]{height:auto}}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{w as J,t as at,r as lt,s as As,c as E,n as _e,a as kt,b as B,d as q,o as i,e as c,F as W,f as X,g as ee,u as _,h as L,i as a,j as v,k as x,_ as j,l as it,m as G,p as N,q as K,v as Ms,x as Ue,y as Ne,z as me,A as Vt,B as et,C as te,D as Ts,E as be,G as ge,H as $e,I as zs,J as Wt,K as Is}from"./_plugin-vue_export-helper-DeQjDyQ9.js";import{s as Os,m as rt,u as Ut,a as Ht,r as Lt,p as Bs,b as Ds,i as bt,l as qt,c as Ns,M as ne,d as Be,e as Te,f as Ps,g as Ce,h as we,j as Fs,k as He,n as Vs,o as Ws,q as Us,t as ct,v as Hs,w as Ls,x as qs,y as js,z as Ys,A as $t,B as Ks}from"./scheme-BdlolNvz.js";import{g as Ee,r as Xs,a as Gs,e as Zs,w as jt,p as ie,b as ce,T as tt,S as xe,c as dt,d as re,h as Js,s as ut,i as Yt,m as Re,f as Qs,j as Kt,k as Le,l as en,n as ht,o as tn,y as sn,q as Xt,t as nn,u as on,v as an}from"./bem-CST_YFrc.js";const ke=Os(Lt),xt=(e,t)=>{const s=ne,n=new Float32Array(s*s);for(let l=0;l<n.length;l+=1)n[l]=e[l]===t?1e6:0;const o=(l,r,d)=>{n[r]+d<n[l]&&(n[l]=n[r]+d)};for(let l=0;l<s;l+=1)for(let r=0;r<s;r+=1){const d=l*s+r;r>0&&o(d,d-1,1),l>0&&o(d,d-s,1),r>0&&l>0&&o(d,d-s-1,Math.SQRT2),r<s-1&&l>0&&o(d,d-s+1,Math.SQRT2)}for(let l=s-1;l>=0;l-=1)for(let r=s-1;r>=0;r-=1){const d=l*s+r;r<s-1&&o(d,d+1,1),l<s-1&&o(d,d+s,1),r<s-1&&l<s-1&&o(d,d+s+1,Math.SQRT2),r>0&&l<s-1&&o(d,d+s-1,Math.SQRT2)}return n},Ge=e=>{const t=String(e||"").trim(),s=/^#([0-9a-f]{6})$/i.exec(t);if(s)return[0,2,4].map(o=>parseInt(s[1].slice(o,o+2),16));const n=t.match(/[\d.]+/g);return n&&n.length>=3?n.slice(0,3).map(Number):null},ln=e=>{const t=getComputedStyle(e),s=Ge(t.getPropertyValue("--md-primary"))||[44,86,151],n=Ge(t.getPropertyValue("--md-on-primary-container"))||s;return{core:bt()?s:s.map((o,l)=>qt(o,n[l],.35)),rim:Ge(t.getPropertyValue("--blob-3"))||[23,223,220],strength:bt()?.9:1}},rn=(e,t,s)=>({size:e.range(.85,1.05)*Math.min(t,s),right:e.chance(.4),bottom:e.chance(.7),overflowX:e.range(-.02,.06),overflowY:e.range(-.02,.04)}),cn=e=>{const t={minX:ne,maxX:0,minY:ne,maxY:0};for(let n=0;n<e.length;n+=1)if(e[n]){const o=n%ne,l=Math.floor(n/ne);t.minX=Math.min(t.minX,o),t.maxX=Math.max(t.maxX,o),t.minY=Math.min(t.minY,l),t.maxY=Math.max(t.maxY,l)}const s=n=>(n-ne/2)/Be;return{minX:s(t.minX),maxX:s(t.maxX),minY:s(t.minY),maxY:s(t.maxY)}},dn=(e,t,s,n)=>{const o=t.maxX-t.minX,l=t.maxY-t.minY,r=Math.min(e.size,2*s*.95/o,2*n*.98/l),d=r/2,w=-e.overflowX*r,f=-e.overflowY*r;return{size:r,centerX:e.right?s-w-t.maxX*d:w-t.minX*d,centerY:e.bottom?n-f-t.maxY*d:f-t.minY*d}},un=(e,t,s)=>"rgba("+e.core.map((o,l)=>Math.round(qt(o,e.rim[l],t))).join(",")+","+s.toFixed(3)+")",hn=(e,t,s)=>{const n=[],o=t.size/62,l=t.size/2/Be,r=t.size*Ps/4,d=o*.866;for(let w=0,f=t.centerY-r;f<t.centerY+r;w+=1,f+=d)for(let p=t.centerX-r+w%2*o/2;p<t.centerX+r;p+=o){const k=p+e.range(-.3,.3)*o,u=f+e.range(-.3,.3)*o,h=Math.floor((k-t.centerX)/l+ne/2),m=Math.floor((u-t.centerY)/l+ne/2);if(h<0||m<0||h>=ne||m>=ne)continue;const R=m*ne+h,P=e.next(),Y=e.range(.75,1.25),$=e.range(-.15,.15);if(s.inside[R]){const y=s.depth[R]/Be,C=Te(y/.035),A=Te(y/.3);if(P>.5+.5*C)continue;n.push({x:k,y:u,radius:o*.5*(.45+.55*C)*(.95+.3*A)*Y,alpha:.5+.25*C+.25*A,tint:Te(.65-.65*A+$)})}else{const y=s.gap[R]/Be;if(P>.14*Math.exp(-y/.05)+.004)continue;n.push({x:k,y:u,radius:o*e.range(.1,.24),alpha:.35,tint:Te(.8+$)})}}return n},pn=()=>document.getElementById("wt"),_n=()=>document.getElementById("backdrop"),Gt=()=>Math.floor(Math.random()*4294967296),ze={},H={workspace:"",seed:Gt(),species:"",wantedSpecies:"",wantedPose:"",built:null},fn=(e,t)=>{const s=Ns(H.seed),n=ke[Math.floor(s.next()*ke.length)];H.species=ke.includes(H.wantedSpecies)?H.wantedSpecies:n;const o=rn(s,e,t),l={facing:o.right?-1:1,tilt:s.range(-.07,.07),stretchX:s.range(.92,1.08),stretchY:s.range(.92,1.08)};s.chance(.25)&&(l.facing=-l.facing);const r=Bs(Ds(Lt,H.species,s,{pose:H.wantedPose}).shapes,l),d={inside:r,depth:xt(r,1),gap:xt(r,0)},w=dn(o,cn(r),e,t);return{key:H.seed+":"+H.species+":"+e+"x"+t,dots:hn(s,w,d)}},Pe=()=>{const e=_n();if(!e)return;const t=e.clientWidth,s=e.clientHeight,n=window.devicePixelRatio||1,o=Math.round(t*n),l=Math.round(s*n);(e.width!==o||e.height!==l)&&(e.width=o,e.height=l);const r=e.getContext("2d");if(!r||(r.setTransform(n,0,0,n,0,0),r.clearRect(0,0,t,s),!t||!s))return;const d=H.seed+":"+(H.wantedSpecies||"?")+":"+t+"x"+s;(!H.built||H.built.key.split(":")[0]!==String(H.seed)||!H.built.key.endsWith(t+"x"+s)||H.wantedSpecies&&H.species!==H.wantedSpecies)&&(H.built=fn(t,s));const w=pn();if(!w)return d;const f=ln(w);return H.built.dots.forEach(p=>{r.fillStyle=un(f,p.tint,p.alpha*f.strength),r.beginPath(),r.arc(p.x,p.y,p.radius,0,Math.PI*2),r.fill()}),d};window.whoseTurnBackdrop={species:ke.slice(),seeded:rt,get current(){return{workspace:H.workspace,species:H.species,seed:H.seed}},show:e=>{const t=e||{},s=String(t.workspace||"");ze[s]||(ze[s]=Gt());const n=t.seed!==void 0?Number(t.seed)>>>0:ze[s];ze[s]=n;const o=t.species&&ke.includes(t.species)?t.species:"",l=String(t.pose||"");return s===H.workspace&&n===H.seed&&o===H.wantedSpecies&&l===H.wantedPose&&H.built||(H.workspace=s,H.seed=n,H.wantedSpecies=o,H.wantedPose=l,H.built=null,Pe()),window.whoseTurnBackdrop.current},repaint:Pe};J(Ce,Pe);Ut(window,"resize",Ht(Pe,200));const{show:Zt,repaint:vn,seeded:jc}=window.whoseTurnBackdrop,mn="[data-tip-click]",St=e=>e instanceof Element?e.closest(mn):null,gn=e=>e.isConnected&&e.getClientRects().length>0,yn=()=>{if(!window.tippy)return()=>{};const e=new Set;let t=!1;const s=new Set,n=new MutationObserver(()=>k());let o=!1;const l=()=>{e.size&&!o?n.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["style","class","hidden"]}):!e.size&&o&&n.disconnect(),o=e.size>0},r=$=>{e.add($),l()},d=$=>{e.delete($),l()},w=$=>{s.delete($),$.hide()},f=$=>e.forEach(y=>{y.reference!==$&&w(y)}),p=()=>f(null),k=()=>{e.forEach($=>{$.reference.isConnected?gn($.reference)||w($):(d($),$.destroy())})},u=$=>{const y=St($.target);t=!y,f(y)},h=$=>{const y=St($.target),C=y==null?void 0:y._tippy;C&&(s.has(C)?w(C):(s.add(C),C.show()))},m=$=>{$.key==="Escape"&&p()},R=()=>{t=!1};window.tippy.delegate(document.body,{target:"[data-tip]",content:$=>$.dataset.tip||"",trigger:"mouseenter focus",delay:[0,80],duration:[120,80],interactive:!0,hideOnClick:!1,maxWidth:440,placement:"top",theme:"wt",appendTo:()=>document.body,onShow:$=>{if(t)return!1;r($)},onHide:$=>s.has($)?!1:void 0,onHidden:d,onDestroy:$=>{d($),s.delete($)}});const P=new ResizeObserver(p);P.observe(document.body);const Y=[[document,"pointerdown",u,!0],[document,"pointerup",R,!0],[document,"click",h,!0],[document,"keydown",m,!0],[document,"pointercancel",R,!0],[document,"dragstart",p,!0],[document,"scroll",p,!0],[window,"resize",p,!1]];return Y.forEach(([$,y,C,A])=>$.addEventListener(y,C,A)),()=>{n.disconnect(),P.disconnect(),Y.forEach(([$,y,C,A])=>$.removeEventListener(y,C,A))}},wn=()=>{let e=0;return{next:()=>++e,accepts:t=>t===e}},Ct=e=>{const t=structuredClone(at(e)),s=t.connectors||{},n=t.rules||{};return n.statuses=n.statuses||{},{...t,connectors:Array.isArray(s)?s:Object.entries(s).map(([o,l])=>({type:o,...l})),rules:n,theme:t.theme||{}}},kn=e=>{const t=structuredClone(at(e));return t.theme&&!Object.keys(t.theme).length&&delete t.theme,t.rules&&!Object.keys(t.rules.statuses||{}).length&&delete t.rules.statuses,t.rules&&!Object.keys(t.rules).length&&delete t.rules,t},Et=new WeakMap;let bn=0;const Ie=e=>{const t=at(e);let s=Et.get(t);return s||(s=++bn,Et.set(t,s)),s},Rt=e=>JSON.stringify(e),$n=(e,t)=>{const s=[];return e.forEach(n=>n.connectors.forEach(o=>{const l=t.get(o)||{};Object.keys(l).forEach(r=>{l[r]&&s.push({ws:n.id,connector:o.id||o.type,key:r,value:l[r]})})})),s},ue=(e,t,s)=>{typeof s=="boolean"||s&&s.length?e[t]=s:delete e[t]},xn=(e,t)=>{const s=n=>{const o=t.indexOf(n.id);return o<0?t.length:o};return[...e].sort((n,o)=>s(n)-s(o))},Sn=(e,t,s,n)=>{const o=e.filter(l=>l!==t);return o.splice(o.indexOf(s)+(n?0:1),0,t),o},Cn={backlog:"in the backlog",passed:"passed",code_review:"in review",qa:"in testing",on_hold:"on hold",todo:"to do",in_progress:"in progress",done:"done"},Jt=e=>Cn[e]||`in ${e.replace(/_/g," ")}`,En={you:"your move",reviewer:"the reviewer's move",qa:"the tester's move",them:"waiting on others"},pe=(e,t)=>{var s;return((s=e[t])==null?void 0:s.name)||t.replace(/[._]/g," ")},Rn=(e,t,s)=>e?t:s,An={approved:"the PR is approved",changes_requested:"changes are requested on the PR",none:"the PR has no review"},Mn=(e,t,s)=>{switch(t){case"ticket.status":return`the ticket is ${Jt(String(s))}`;case"ticket.assignee":return s==="me"?"the ticket is on you":`the ticket is assigned to ${s}`;case"pr.checks":return s==="none"?"the PR has no checks":`the PR checks are ${s}`;case"pr.review":return An[String(s)]||`the PR review is ${s}`;case"pr.base":return`the PR goes into ${s}`;default:return`${pe(e,t)} is ${s}`}},Tn=(e,t,s,n)=>{if(s==="present")return Rn(n,`${pe(e,t)} is given`,`${pe(e,t)} is missing`);if(s==="prefix")return t==="pr.base"?`the PR goes into a branch starting with ${n}`:`${pe(e,t)} starts with ${n}`;if(t==="unanswered_count"){const l=Number(n);return`${{gt:`more than ${l}`,gte:`at least ${l}`,lt:`fewer than ${l}`,lte:`at most ${l}`}[s]} mentions of you wait for an answer`}const o={gt:"more than",gte:"at least",lt:"less than",lte:"at most"};return`${pe(e,t)} is ${o[s]} ${n}`},zn=(e,t,s)=>{var o;if(Array.isArray(s))return t==="ticket.status"?`the ticket is ${s.map(l=>Jt(String(l))).join(" or ")}`:`${pe(e,t)} is ${s.join(" or ")}`;if(s&&typeof s=="object")return Object.entries(s).map(([l,r])=>Tn(e,t,l,r)).join(" and ");const n=(o=e[t])==null?void 0:o.says;return typeof s=="boolean"&&n?n[s?0:1]:Mn(e,t,s)},In=(e,t)=>t.replace(/\{([\w.]+)\}/g,(s,n)=>`{${pe(e,n)}}`),On=(e,t={})=>{const s=Object.entries(e.when).map(([o,l])=>zn(t,o,l)),n=e.then.whose==="hidden"?"not shown":`${En[e.then.whose]||e.then.whose}, "${In(t,e.then.next||"")}"`;return{when:s.length?`When ${s.join(" and ")}:`:"In every other case:",then:n}},Bn=e=>e.modal?"modal":e.note?"note":e.settings?"settings":e.feedback?"feedback":e.whatsNew?"whatsNew":null,Dn=(e,t)=>{const s=new URLSearchParams(e).get("mode");return s==="app"||s==="tab"?s:t==="app"?"app":"tab"},Nn=e=>"/?mode=tab"+(e?"&ws="+encodeURIComponent(e):""),Pn=e=>({width:e.outerWidth,height:e.outerHeight}),Qt={writeDefaults:!1},es=we("wt-ws","",Qt),ts=Fs("wt-mode","",Qt),g=As({workspaces:[],workspace:{id:"",name:"",connectors:[],links:[],key_pattern:"",theme:null},turn:[],feed:[],marks:{seen:[],base:0,handled:{},info:{}},counts:{mine:0,others:0,failing:0,done:0},todos:[],errors:{},health:{ok:!0,stale:!1,fresh_at:"",failing:[],alerts:[]},problems:[],polled_at:"",update:{current:"",latest:"",available:!1,state:"idle"},notifications:{desktop:!0}}),S=lt({ws:new URLSearchParams(location.search).get("ws")||es.value,open:new Set,mode:Dn(location.search,ts.value),live:!1,reconnects:0,status:"Connecting…",modal:null,note:"",feedback:!1,whatsNew:!1,settings:!1,settingsDirty:!1,settingsAsk:!1,settingsAt:"",focusFeed:""});ts.value=S.mode;const Fe=He("",6e3),de=(e,t)=>{const s=ce(e,t);return s&&(Fe.value=s),!s},Fn=()=>{S.mode==="app"&&Ut(window,"resize",Ht(()=>ie("/api/window",Pn(window)).catch(de),600))},ss={resume:()=>{}},fe=Ws({scheduler:e=>{const t=Us(e,3e4,{immediate:!1});return ss.resume=t.resume,t}}),Ze=E(()=>{const e=g.workspace.theme;return e&&e.light&&e.dark?e[Ce.value?"dark":"light"]:{}}),ae=E(()=>g.counts),At=E(()=>{const e=g.workspace.name,t=e?e+": ":"",s=Object.entries(g.errors||{}),n=g.health.failing||[],o=d=>n.find(({source:w})=>d===w||d.startsWith(w+".")),l=n.map(({source:d,polls:w})=>{const f=s.filter(([p])=>{var k;return((k=o(p))==null?void 0:k.source)===d}).map(([,p])=>p);return`Source ${d}: ${f.join(", ")||"failing"}, failed ${w} polls in a row`}),r=new Set(n.map(({source:d})=>"failing:"+d));return[...g.problems||[],...g.health.alerts.filter(d=>!r.has(d.id||"")).map(d=>d.text),...l,...s.filter(([d])=>!o(d)).map(([d,w])=>t+d+": "+w)]}),ns=(e="")=>{S.settingsAt=e,S.settings=!0},os=E(()=>Bn(S)),Vn=()=>{const e=os.value;if(e==="modal"&&(S.modal=null),e==="note"&&(S.note=""),e==="feedback"&&(S.feedback=!1),e==="whatsNew"&&(S.whatsNew=!1),e==="settings"){if(S.settingsDirty){S.settingsAsk=!0;return}S.settings=!1}},st=new Map,Wn=(e,t)=>{t&&st.set(e,document.activeElement)},Un=(e,t)=>{if(t)return;const s=st.get(e);st.delete(e),s instanceof HTMLElement&&s.focus()},Hn={modal:()=>!!S.modal,note:()=>!!S.note,settings:()=>S.settings,feedback:()=>S.feedback,whatsNew:()=>S.whatsNew};J(()=>g.turn.some(e=>e.row_id===S.note),e=>{e||(S.note="")},{flush:"sync"});Object.entries(Hn).forEach(([e,t])=>{J(t,s=>Wn(e,s),{flush:"sync"}),J(t,s=>Un(e,s),{flush:"post"})});let Ve=-1,nt=0;const Mt=wn(),Ae=(e=S.ws)=>{const t=Mt.next();return Ee("/api/state"+(e?"?ws="+encodeURIComponent(e):"")).then(s=>Mt.accepts(t)?s.error?Xs(s.error)!=="NO_SUCH_WORKSPACE"||!Gs(e)?(S.status=Zs(s.error,"Could not load"),g):Ae(""):(Object.assign(g,s),S.ws=g.workspace.id,S.status="",Zt({workspace:g.workspace.id}),document.title="Whose Turn · "+g.workspace.name,g):g)},as=()=>(Ve=-1,Ae()),Se=Vs("/api/stream",[],{immediate:!1,autoConnect:!1,autoReconnect:!0,serializer:{read:e=>JSON.parse(e||"null")}});J(Se.status,e=>{S.live=e==="OPEN",S.live&&(S.status="",S.reconnects++)},{flush:"sync"});J(Se.error,e=>{e&&(S.status="Disconnected from the local server, retrying…")},{flush:"sync"});J(Se.data,e=>{if(e){if("update"in e){g.update=e.update;return}typeof e.open_moves=="number"&&(g.workspaces=jt(g.workspaces,e.ws,e.open_moves)),!(g.workspace.id&&e.ws!==g.workspace.id)&&(S.status="",e.version!==Ve?(Ve=e.version,nt===0&&Ae()):g.polled_at=e.polled_at)}},{flush:"sync"});const Ln=()=>{Se.eventSource.value||Se.open()},qn=()=>(ss.resume(),Ae().then(Ln)),jn=e=>e===g.workspace.id?Promise.resolve():(Ve=-1,nt++,Ae(e).then(()=>{S.ws===e&&(es.value=S.ws,S.open.clear())},()=>{Fe.value=xe+"; staying on "+g.workspace.name+"."}).finally(()=>{nt--})),ls=(e,t)=>ie(e,{ws:g.workspace.id,...t}),ye=e=>ls("/api/marks",e).then(t=>{const s=ce(t);return s||(Object.assign(g,{marks:t.marks,turn:t.turn,counts:t.counts}),g.workspaces=jt(g.workspaces,g.workspace.id,t.counts.mine)),s},t=>ce(t)),Yn=e=>{S.focusFeed=e},Kn=e=>ls("/api/todos",e).then(t=>{const s=ce(t,{unreachable:tt});return!s&&Array.isArray(t)&&(g.todos=t),s},t=>ce(t,{unreachable:tt})),Tt=e=>Ee("/api/config").then(t=>ie("/api/config",{workspaces:xn(t.workspaces,e),secrets:[]})).then(t=>{de(t,{refused:"The order was not saved"})&&as()},t=>de(t,{refused:"The order was not saved"})),zt=()=>{S.status="Checking now…",ie("/api/refresh").catch(e=>{S.status="",de(e)}),Zt({workspace:g.workspace.id,seed:Math.floor(Math.random()*4294967296)})},Xn="M12 2.5l1.9 5.6 5.6 1.9-5.6 1.9L12 17.5l-1.9-5.6L4.5 10l5.6-1.9L12 2.5zM5 15l.9 2.6 2.6.9-2.6.9L5 22l-.9-2.6-2.6-.9 2.6-.9L5 15zm14-2l.7 2 2 .7-2 .7-.7 2-.7-2-2-.7 2-.7.7-2z",Gn="M16 1H6a2 2 0 0 0-2 2v12h2V3h10V1zm3 4H10a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2zm0 16h-9V7h9v14z",Zn="M19.4 13a7.6 7.6 0 0 0 0-2l2-1.5-2-3.4-2.4 1a7.5 7.5 0 0 0-1.7-1L15 3.5H9l-.3 2.6a7.5 7.5 0 0 0-1.7 1l-2.4-1-2 3.4 2 1.5a7.6 7.6 0 0 0 0 2l-2 1.5 2 3.4 2.4-1a7.5 7.5 0 0 0 1.7 1l.3 2.6h6l.3-2.6a7.5 7.5 0 0 0 1.7-1l2.4 1 2-3.4-2-1.5zM12 15.5a3.5 3.5 0 1 1 0-7 3.5 3.5 0 0 1 0 7z",Jn="M23 12l-2.4-2.8.3-3.7-3.6-.8-1.9-3.2L12 3 8.6 1.5 6.7 4.7l-3.6.8.3 3.7L1 12l2.4 2.8-.3 3.7 3.6.8 1.9 3.2L12 21l3.4 1.5 1.9-3.2 3.6-.8-.3-3.7L23 12zm-10 5h-2v-2h2v2zm0-4h-2V7h2v6z",Qn="M19 8h-1.8a5.9 5.9 0 0 0-1.3-1.9l1.6-1.6-1.4-1.4-1.9 1.9A5.7 5.7 0 0 0 12 4.5a5.7 5.7 0 0 0-2.2.5L7.9 3.1 6.5 4.5l1.6 1.6A5.9 5.9 0 0 0 6.8 8H5v2h1.2a7 7 0 0 0 0 1v1H5v2h1.3a6 6 0 0 0 11.4 0H19v-2h-1.2v-1a7 7 0 0 0 0-1H19V8zm-7 10a4 4 0 0 1-4-4v-3a4 4 0 0 1 8 0v3a4 4 0 0 1-4 4zm-1-7h2v5h-2z",eo=e=>{let t=2166136261;for(let s=0;s<e.length;s+=1)t^=e.charCodeAt(s),t=Math.imul(t,16777619);return t>>>0},is=e=>{const t=String(e||"").trim().split(/[\s_-]+/).filter(Boolean);return(t.length>=2?t.slice(0,3).map(n=>n.charAt(0)):(t[0]||"?").slice(0,2).split("")).join("").toUpperCase()},to=e=>({1:17,2:14,3:11})[e.length]||11,rs=(e,t)=>{const s=t(eo(e.id)),n=[],o=3+Math.floor(s()*3);for(let r=0;r<o;r+=1){const d=s()*Math.PI*2,w=9+s()*7;n.push({cx:(18+Math.cos(d)*w).toFixed(1),cy:(18+Math.sin(d)*w).toFixed(1),r:(1.6+s()*2.2).toFixed(1),opacity:(.35+s()*.4).toFixed(2)})}const l=is(e.name||e.id);return{dots:n,glyph:l,fontSize:to(l)}},so=(e,t)=>{const s=e.dots.map(l=>`<circle cx="${l.cx}" cy="${l.cy}" r="${l.r}" fill="${t.dot}" opacity="${l.opacity}"/>`).join(""),n=e.fontSize>=17?24:23,o=e.glyph.replace(/[&<>]/g,"");return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><rect width="36" height="36" rx="10" fill="${t.fill}"/>${s}<text x="18" y="${n}" text-anchor="middle" font-size="${e.fontSize}" font-weight="700" letter-spacing="-0.5" font-family="Roboto, Inter, system-ui, sans-serif" fill="${t.ink}">${o}</text></svg>`},no="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z",oo="M20 18.69L7.84 6.14 5.27 3.49 4 4.76l2.8 2.8v.01c-.52.99-.8 2.16-.8 3.42v5l-2 2v1h13.73l2 2L21 19.72l-1-1.03zM12 22c1.11 0 2-.89 2-2h-4c0 1.11.89 2 2 2zm6-7.32V11c0-3.08-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68c-.15.03-.29.08-.42.12-.1.03-.2.07-.3.11h-.01c-.01 0-.01 0-.02.01-.23.09-.46.2-.68.31 0 0-.01 0-.01.01L18 14.68z",It='a[href], button:not([disabled]), input:not([disabled]), select, textarea, [tabindex]:not([tabindex="-1"])',ao="input, textarea, select, [contenteditable]",lo=(e,t,s)=>{if(!e.length)return null;const n=s?e[0]:e[e.length-1];return t===n||!e.some(o=>o===t)?s?e[e.length-1]:e[0]:null},io=e=>{let t=null;J(e,s=>{s?(t=document.activeElement,_e(()=>{var l;const n=document.querySelectorAll(".modal"),o=n[n.length-1];o&&!o.contains(document.activeElement)&&((l=o.querySelector(It))==null||l.focus())})):(t==null||t.focus(),t=null)}),ct("Tab",s=>{if(!e.value)return;const n=document.querySelectorAll(".modal"),o=n[n.length-1],l=o?[...o.querySelectorAll(It)]:[],r=lo(l,document.activeElement,s.shiftKey);r&&(s.preventDefault(),r.focus())},{target:document})},Ot={"/":".feed__search-input",t:".todos__input"},ro=e=>ct(Object.keys(Ot),t=>{const s=t.target;if(e.value||t.metaKey||t.ctrlKey||t.altKey||s!=null&&s.closest(ao))return;const n=document.querySelector(Ot[t.key]);n&&(t.preventDefault(),n.focus())},{target:document}),co=30,Bt=(e,t,s)=>Math.round(Math.max(t,Math.min(s,e))),uo=(e,t)=>Math.ceil(e+(t>1?co:0)),ho=(e,t,s)=>e-t*s.length-s.reduce((n,o)=>n+(o.collapsed?o.height:o.floor),0),pt=e=>{const t=we("wt-panel-sizes",{},{writeDefaults:!1});return{size:E(()=>t.value[kt(e)]??null),set:o=>{const l=kt(e);if(!l)return;const{[l]:r,...d}=t.value;t.value=o===null?d:{...d,[l]:o}}}},po="Unreleased",_o=(e,t,s)=>{const n=e.filter(r=>r.version!==po),o=n.findIndex(r=>r.version===s);if(!t||o<0||t===s)return[];const l=n.findIndex(r=>r.version===t);return n.slice(o,l<0?o+1:l)},fo=e=>e.sections.map(t=>`### ${t.kind}
|
|
2
|
+
${t.items.map(s=>`- ${s}`).join(`
|
|
3
|
+
`)}`).join(`
|
|
4
|
+
|
|
5
|
+
`),vo="wt-seen-version",_t=Hs(()=>{const e=we(vo,""),t=B(null),s=B(""),n=E(()=>t.value?_o(t.value.versions,e.value,t.value.current):[]);return{changelog:t,problem:s,unseen:n,load:async()=>{s.value="";try{const r=await Ee("/api/changelog");if(r.error){s.value=dt(r.error).join(" · ");return}t.value=r,e.value||(e.value=r.current)}catch{s.value=xe}},markSeen:()=>{t.value&&(e.value=t.value.current)}}}),mo={class:"rail","aria-label":"Workspaces"},go=["data-drop","href","aria-label","aria-selected","onClick","onKeydown","onDragstart","onDragover","onDrop"],yo={viewBox:"0 0 36 36",class:"rail__icon","aria-hidden":"true"},wo=["fill"],ko=["cx","cy","r","fill","opacity"],bo=["y","font-size","fill"],$o={class:"rail__label"},xo={key:0,class:"rail__warn",title:"A source of this workspace fails"},So={key:1,class:"rail__badge"},Co={viewBox:"0 0 24 24",class:"rail__gear","aria-hidden":"true"},Eo=["d"],Ro={key:0,class:"rail__dot",title:"Unseen changes"},Ao={viewBox:"0 0 24 24",class:"rail__gear","aria-hidden":"true"},Mo=["d"],To=q({__name:"Rail",emits:["settings","whatsNew"],setup(e,{emit:t}){const s=t,{unseen:n}=_t(),o=E(()=>Object.fromEntries(g.workspaces.map(y=>[y.id,rs(y,rt)]))),l=E(()=>Object.fromEntries(g.workspaces.map(y=>{const C=y.theme?y.theme[Ce.value?"dark":"light"]:null;return[y.id,{fill:C?C["--md-primary-container"]:"var(--md-primary-container)",ink:C?C["--md-on-primary-container"]:"var(--md-on-primary-container)",dot:C?C["--md-primary"]:"var(--md-primary)"}]}))),r=y=>y.id===g.workspace.id?Object.keys(g.errors||{}).length>0:!!y.failing_sources,d=y=>{y.detail>0&&y.currentTarget.blur()},w=(y,C)=>{d(y),jn(C)},f=y=>{s("settings"),d(y)},p=y=>{s("whatsNew"),d(y)},k=async(y,C)=>{const A=y.key==="ArrowUp"?-1:y.key==="ArrowDown"?1:0,D=g.workspaces.map(U=>U.id),b=D.indexOf(C.id);if(!y.altKey||!A||b+A<0||b+A>=D.length)return;y.preventDefault();const F=y.currentTarget;D.splice(b+A,0,...D.splice(b,1)),await Tt(D),await _e(),F.focus()},u=B(""),h=B({}),m=y=>{const C=y.currentTarget;return y.clientY-C.getBoundingClientRect().top<C.offsetHeight/2},R=(y,C)=>{u.value=C.id,y.dataTransfer&&(y.dataTransfer.effectAllowed="move",y.dataTransfer.setData("text/plain",C.id))},P=()=>{u.value="",h.value={}},Y=(y,C)=>{if(!u.value||u.value===C.id)return;y.preventDefault(),y.dataTransfer&&(y.dataTransfer.dropEffect="move");const A=m(y)?"before":"after";(h.value.id!==C.id||h.value.side!==A)&&(h.value={id:C.id,side:A})},$=(y,C)=>{if(!u.value||u.value===C.id)return;y.preventDefault();const A=Sn(g.workspaces.map(D=>D.id),u.value,C.id,m(y));h.value={},Tt(A)};return(y,C)=>(i(),c("nav",mo,[(i(!0),c(W,null,X(_(g).workspaces,A=>(i(),c("a",{key:A.id,class:L(["rail__item",{"rail__item--dragging":u.value===A.id}]),"data-drop":h.value.id===A.id?h.value.side:null,href:"?ws="+encodeURIComponent(A.id),"aria-label":A.name,"aria-selected":A.id===_(g).workspace.id,draggable:"true",onClick:ee(D=>w(D,A.id),["prevent"]),onKeydown:D=>k(D,A),onDragstart:D=>R(D,A),onDragend:P,onDragover:D=>Y(D,A),onDragleave:C[0]||(C[0]=D=>h.value={}),onDrop:D=>$(D,A)},[(i(),c("svg",yo,[a("rect",{x:"0",y:"0",width:"36",height:"36",rx:"10",fill:l.value[A.id].fill},null,8,wo),(i(!0),c(W,null,X(o.value[A.id].dots,(D,b)=>(i(),c("circle",{key:b,cx:D.cx,cy:D.cy,r:D.r,fill:l.value[A.id].dot,opacity:D.opacity},null,8,ko))),128)),a("text",{x:"18",y:o.value[A.id].fontSize>=17?24:23,"text-anchor":"middle","font-size":o.value[A.id].fontSize,"font-weight":"700","letter-spacing":"-0.5","font-family":"Roboto, Inter, system-ui, sans-serif",fill:l.value[A.id].ink},v(o.value[A.id].glyph),9,bo)])),a("span",$o,v(A.name),1),r(A)?(i(),c("span",xo,"!")):x("",!0),A.open_moves?(i(),c("span",So,v(A.open_moves),1)):x("",!0)],42,go))),128)),C[3]||(C[3]=a("span",{class:"rail__spacer"},null,-1)),a("a",{class:"rail__item",href:"#whats-new","aria-label":"What's new",onClick:ee(p,["prevent"])},[(i(),c("svg",Co,[a("path",{d:_(Jn),fill:"currentColor"},null,8,Eo)])),C[1]||(C[1]=a("span",{class:"rail__label"},"What's new",-1)),_(n).length?(i(),c("span",Ro)):x("",!0)]),a("a",{class:"rail__item",href:"#settings","aria-label":"Settings",onClick:ee(f,["prevent"])},[(i(),c("svg",Ao,[a("path",{d:_(Zn),fill:"currentColor"},null,8,Mo)])),C[2]||(C[2]=a("span",{class:"rail__label"},"Settings",-1))])]))}}),zo=j(To,[["__scopeId","data-v-ffe046bc"]]),Je=" · checks every minute",cs=(e,t,s,n)=>{const o=e.failing.map(r=>r.source),l=t?re(t):"—";return o.length&&o.length>=s?{dot:"off",text:"No data: "+o.join(", ")+" failing · last data "+re(e.fresh_at),failing:o,noData:!0}:e.stale?{dot:"off",text:"Stale · last data "+re(e.fresh_at)+Je,failing:o,noData:!1}:o.length?{dot:n?"warn":"off",text:o.join(", ")+" failing · last check "+l+Je,failing:o,noData:!1}:{dot:n?"ok":"off",text:"Live · last check "+l+Je,failing:o,noData:!1}},Io=["data-tip"],Oo={class:"ai-button__icon",viewBox:"0 0 24 24","aria-hidden":"true"},Bo=["d"],Do={class:"ai-button__badge",viewBox:"0 0 24 24","aria-hidden":"true"},No=["d"],Po=q({__name:"AiButton",props:{query:{},big:{type:Boolean}},setup(e){const t=e,s={"":"Copy for AI: this with its context as text, ready to paste into Claude or any other assistant",sent:"Copied",failed:"Could not copy"},n=He("",1600),o=E(()=>s[n.value]),l=B(null);J(o,d=>{var w,f;return(f=(w=l.value)==null?void 0:w._tippy)==null?void 0:f.setContent(d)});const r=()=>Js(t.query).then(d=>navigator.clipboard.writeText(d)).then(()=>{n.value="sent"},()=>{n.value="failed"});return(d,w)=>(i(),c("button",{ref_key:"button",ref:l,type:"button",class:L(["ai-button",{"ai-button--big":e.big,"ai-button--sent":_(n)==="sent","ai-button--failed":_(n)==="failed"}]),"aria-label":"Copy for AI","data-tip":o.value,onClick:ee(r,["stop"])},[(i(),c("svg",Oo,[a("path",{d:_(Gn),fill:"currentColor"},null,8,Bo)])),(i(),c("svg",Do,[a("path",{d:_(Xn),fill:"currentColor"},null,8,No)]))],10,Io))}}),ve=j(Po,[["__scopeId","data-v-46197bdc"]]),ot="wt-updated-to",Fo=()=>window.location.reload(),Vo=e=>{try{sessionStorage.setItem(ot,e)}catch{}},Wo=()=>{try{const e=sessionStorage.getItem(ot)||"";return sessionStorage.removeItem(ot),e}catch{return""}},Uo={key:2,class:"update-chip update-chip--busy",role:"status"},Ho=["title"],Lo=15e3,qo=9e4,jo=q({__name:"UpdateChip",setup(e){const t=B("");let s="";const n=B(""),o=B(!1),l=He("",Lo),r=E(()=>g.update),d=E(()=>r.value.state==="restarting"||!!t.value&&!S.live),w=E(()=>!n.value&&(r.value.state==="installing"||d.value||!!t.value)),{start:f,stop:p}=Ls(()=>o.value=!0,qo,{immediate:!1});it(()=>{l.value=Wo()}),J(()=>r.value.current,h=>{if(h){if(!s){s=h;return}h!==s&&(n.value=h,t.value="",p())}},{immediate:!0});const k=()=>{if(w.value)return;o.value=!1,t.value=r.value.latest,f();const h=m=>{if(!de(m,{refused:"The update did not start"})){t.value="",p();return}g.update=m.update};ie("/api/update").then(h,h)},u=()=>{n.value&&Vo(n.value),Fo()};return(h,m)=>_(l)?(i(),c("button",{key:0,type:"button",class:"update-chip update-chip--done",title:"See what changed",onClick:m[0]||(m[0]=R=>_(S).whatsNew=!0)}," Updated to "+v(_(l)),1)):n.value?(i(),c("button",{key:1,type:"button",class:"update-chip update-chip--ready",title:"Reload the window to apply the changes",onClick:u}," Updated to "+v(n.value)+" · Reload ",1)):w.value?(i(),c("span",Uo,[m[1]||(m[1]=a("span",{class:"update-chip__spinner","aria-hidden":"true"},null,-1)),G(v(d.value?"Restarting…":`Installing ${t.value||r.value.latest}…`),1),o.value?(i(),c("button",{key:0,type:"button",class:"update-chip__link",title:"The restart is taking longer than usual",onClick:u}," Reload ")):x("",!0)])):r.value.available&&r.value.state==="failed"?(i(),c("button",{key:3,type:"button",class:"update-chip update-chip--failed",title:r.value.reason,onClick:k}," Update failed · Retry ",8,Ho)):r.value.available?(i(),c("button",{key:4,type:"button",class:"update-chip",onClick:k},v(r.value.latest)+" is out · Update ",1)):x("",!0)}}),Yo=j(jo,[["__scopeId","data-v-c5c2c37f"]]),Ko=["aria-checked","data-tip"],Xo={class:"notifications-toggle__icon",viewBox:"0 0 24 24","aria-hidden":"true"},Go=["d"],Zo=q({__name:"NotificationsToggle",setup(e){const t=E(()=>g.notifications.desktop),s=B(!1),n=async()=>{if(s.value)return;s.value=!0;const o=g.notifications;g.notifications={desktop:!o.desktop};const l=r=>{de(r,{refused:"The notification setting was not saved"})||(g.notifications=o)};await ie("/api/notifications",{desktop:g.notifications.desktop}).then(l,l),s.value=!1};return(o,l)=>(i(),c("button",{type:"button",role:"switch",class:L(["btn notifications-toggle",{"notifications-toggle--off":!t.value}]),"aria-checked":t.value,"data-tip":t.value?"Desktop notifications are on for every workspace. Click to turn them all off; the window and Claude's session summary keep updating.":"Desktop notifications are off for every workspace. The window and Claude's session summary still update. Click to turn them back on.",onClick:n},[(i(),c("svg",Xo,[a("path",{d:t.value?_(no):_(oo),fill:"currentColor"},null,8,Go)])),G(v(t.value?"Notifications on":"Notifications off"),1)],10,Ko))}}),Jo=j(Zo,[["__scopeId","data-v-6704e5f1"]]),Qo={class:"status-bar"},ea={class:"status-bar__icon",viewBox:"0 0 24 24","aria-hidden":"true"},ta=["d"],sa={key:0,class:"status-bar__notice",role:"alert"},na=["href"],oa=["aria-disabled"],aa=5e3,la=q({__name:"StatusBar",emits:["report"],setup(e,{emit:t}){const s=t,n=E(()=>(fe.value,cs(g.health,g.polled_at,g.workspace.connectors.length,S.live))),o=B(!1),l=B(!1),r=E(()=>l.value?"Opened in the app window. You can close this tab.":S.status||n.value.text),d=f=>de(f,{refused:"The app window did not open"}),w=()=>{if(o.value)return;o.value=!0,setTimeout(()=>o.value=!1,aa);const f=p=>{d(p),l.value=!ce(p)};ie("/api/open",{mode:"app"}).then(f,f)};return(f,p)=>(i(),c("div",Qo,[a("button",{type:"button",class:"btn status-bar__btn status-bar__report",title:"A bug or a wish about this monitor, straight to its backlog",onClick:p[0]||(p[0]=k=>s("report"))},[(i(),c("svg",ea,[a("path",{d:_(Qn),fill:"currentColor"},null,8,ta)])),p[2]||(p[2]=G("Report ",-1))]),a("span",{class:L(["status-bar__live",{"status-bar__live--off":n.value.dot==="off","status-bar__live--warn":n.value.dot==="warn"}])},null,2),a("span",null,v(r.value),1),_(Fe)?(i(),c("span",sa,v(_(Fe)),1)):x("",!0),N(Yo),N(Jo),a("button",{type:"button",class:"btn status-bar__btn",onClick:p[1]||(p[1]=(...k)=>_(zt)&&_(zt)(...k))},"Refresh now"),_(S).mode==="app"?(i(),c("a",{key:1,class:"btn status-bar__btn",href:_(Nn)(_(S).ws),target:"_blank",rel:"noopener"},"Open in browser",8,na)):(i(),c("button",{key:2,type:"button",class:L(["btn status-bar__btn",{"status-bar__btn--busy":o.value}]),"aria-disabled":o.value,onClick:w},v(o.value?"Opening…":"Open as app"),11,oa)),N(ve,{query:{all:"1"}}),p[3]||(p[3]=a("span",{class:"ai-hint status-bar__ai-hint"},"Copy for AI: everything",-1))]))}}),ia=j(la,[["__scopeId","data-v-940c94f2"]]),ds=e=>{const t=we("wt-collapsed",[],{writeDefaults:!1}),s=E(()=>t.value.includes(e));return{collapsed:s,toggle:()=>{t.value=s.value?t.value.filter(o=>o!==e):[...t.value,e]}}},ra=["href"],ca={key:1},le=q({__name:"ExtLink",props:{text:{default:""},url:{default:""}},setup(e){const t=e,s=E(()=>ut(t.url));return(n,o)=>s.value?(i(),c("a",{key:0,href:s.value,target:"_blank",rel:"noopener"},v(e.text),9,ra)):(i(),c("span",ca,v(e.text),1))}}),da={class:"workspace-header__title"},ua={class:"workspace-header__name"},ha={key:0,class:"workspace-header__line workspace-header__strip"},pa={class:"workspace-header__count"},_a={class:"workspace-header__count"},fa={class:"workspace-header__count"},va={class:"workspace-header__count"},ma={class:"workspace-header__line workspace-header__give"},ga={class:"workspace-header__links"},ya={class:"workspace-header__tiles"},wa={class:"workspace-header__tile-value"},ka={class:"workspace-header__tile"},ba={class:"workspace-header__tile-value"},$a={class:"workspace-header__tile-value"},xa={class:"workspace-header__tile"},Sa={class:"workspace-header__tile-value"},Ca=q({__name:"WorkspaceHeader",setup(e){const{collapsed:t,toggle:s}=ds("header");return(n,o)=>(i(),c("header",{id:"summary",class:L(["island workspace-header",{"workspace-header--collapsed":_(t)}])},[a("div",da,[a("h1",ua,v(_(g).workspace.name||"Whose Turn"),1),_(t)?(i(),c("p",ha,[o[1]||(o[1]=G(" Your move ",-1)),a("b",pa,v(_(ae).mine),1),o[2]||(o[2]=G(" · Waiting on others ",-1)),a("b",_a,v(_(ae).others),1),o[3]||(o[3]=G(" · Failing ",-1)),a("b",fa,v(_(ae).failing),1),o[4]||(o[4]=G(" · Done ",-1)),a("b",va,v(_(ae).done),1)])):x("",!0),a("p",ma,[N(ve,{query:{ws:_(g).workspace.id,kind:"workspace"},big:""},null,8,["query"]),o[5]||(o[5]=a("span",{class:"ai-hint"},"Copy for AI: this workspace",-1)),a("span",ga,[(i(!0),c(W,null,X(_(g).workspace.links||[],l=>(i(),K(le,{key:l.url,text:l.label,url:l.url,title:l.url},null,8,["text","url","title"]))),128))])])]),a("button",{type:"button",class:L(["fold-toggle workspace-header__fold",{"fold-toggle--folded":_(t)}]),"aria-label":"Fold the header","data-tip":"Fold the header; it stays folded until you open it again",onClick:o[0]||(o[0]=ee((...l)=>_(s)&&_(s)(...l),["stop"]))}," ▾ ",2),a("div",ya,[a("div",{class:L(["workspace-header__tile",{"workspace-header__tile--you":_(ae).mine>0}])},[o[6]||(o[6]=a("span",{class:"workspace-header__tile-label"},"Your move",-1)),a("strong",wa,v(_(ae).mine),1)],2),a("div",ka,[o[7]||(o[7]=a("span",{class:"workspace-header__tile-label"},"Waiting on others",-1)),a("strong",ba,v(_(ae).others),1)]),a("div",{class:L(["workspace-header__tile",{"workspace-header__tile--fail":_(ae).failing}])},[o[8]||(o[8]=a("span",{class:"workspace-header__tile-label"},"Open PRs with failing checks",-1)),a("strong",$a,v(_(ae).failing),1)],2),a("div",xa,[o[9]||(o[9]=a("span",{class:"workspace-header__tile-label"},"Done in the last 30 days",-1)),a("strong",Sa,v(_(ae).done),1)])])],2))}}),Ea=j(Ca,[["__scopeId","data-v-3421a7f0"]]),ft=e=>{J(()=>S.reconnects,e)},Ra=q({__name:"Chevron",props:{open:{type:Boolean},tag:{default:"button"}},setup(e){return(t,s)=>(i(),K(Ms(e.tag),{class:L(["chevron",{"chevron--open":e.open}]),type:e.tag==="button"?"button":void 0,"aria-expanded":e.tag==="button"?e.open:void 0},null,8,["class","type","aria-expanded"]))}}),qe=j(Ra,[["__scopeId","data-v-a14fa9ba"]]),Aa=["aria-orientation","aria-label"],Dt=16,Ma=q({__name:"ResizeHandle",props:{label:{},axis:{},bounds:{type:Function},grow:{},top:{type:Boolean}},emits:["resize","reset"],setup(e,{emit:t}){const s=e,n=t,o=s.grow??1;let l={pointer:0,size:0,min:0,max:0};const r=p=>s.axis==="y"?p.clientY:p.clientX,d=p=>{const{current:k,min:u,max:h}=s.bounds();l={pointer:r(p),size:k,min:u,max:h},p.currentTarget.setPointerCapture(p.pointerId)},w=p=>{if(!p.currentTarget.hasPointerCapture(p.pointerId))return;const k=(r(p)-l.pointer)*o;n("resize",Bt(l.size+k,l.min,l.max))},f=p=>{const k=s.axis==="y"?"ArrowDown":"ArrowRight",u=s.axis==="y"?"ArrowUp":"ArrowLeft";if(p.key!==k&&p.key!==u)return;p.preventDefault();const{current:h,min:m,max:R}=s.bounds(),P=(p.key===k?Dt:-Dt)*o;n("resize",Bt(h+P,m,R))};return(p,k)=>(i(),c("div",{class:L(["resize-handle",["resize-handle--"+e.axis,{"resize-handle--top":e.top}]]),role:"separator",tabindex:"0","aria-orientation":e.axis==="y"?"horizontal":"vertical","aria-label":e.label,"data-tip":"Drag to resize; double click to reset",onPointerdown:ee(d,["prevent"]),onPointermove:w,onKeydown:f,onDblclick:k[0]||(k[0]=u=>n("reset"))},null,42,Aa))}}),us=j(Ma,[["__scopeId","data-v-8e637688"]]),Ta=["id"],za={class:"island__head"},Ia={class:"island__title"},Oa={class:"island__note"},Ba={class:"island__note-text"},Da=["aria-label","data-tip"],Na={class:"island__body"},Pa=280,Fa=360,Va=q({__name:"Island",props:{id:{},sizeKey:{default:""},title:{},note:{default:""},tip:{default:""},column:{type:Boolean},resize:{default:"height"}},setup(e){const t=e,{collapsed:s,toggle:n}=ds(t.id),{size:o,set:l}=pt(()=>t.sizeKey),r=Ue("root"),d=B(0),w=B(!0),f=$=>parseFloat($)||0,p=($,y)=>{let C=0;for(let A=$.parentElement;A&&A!==y;A=A.parentElement)C+=A.scrollTop;return C},k=($,y)=>{const C=[...$.children].find(D=>D.contains(y));return(C?[...$.children].slice([...$.children].indexOf(C)+1):[]).filter(D=>!D.classList.contains("row-scroll__more")).reduce((D,b)=>{const F=b;return D+(f(getComputedStyle(F).minHeight)||F.offsetHeight)},0)},u=()=>{const $=r.value,y=$==null?void 0:$.querySelector(".island__body");if(!$||!y||s.value||t.resize!=="height")return;const C=y.querySelectorAll("tbody > tr, .todos__list > li"),A=w.value;w.value=C.length>0;const D=$.getBoundingClientRect().top,b=f(getComputedStyle(y).paddingBottom);if(!C.length){d.value=A?0:Math.ceil(y.offsetTop+y.scrollHeight);return}const F=C[0].getBoundingClientRect().bottom-D+p(C[0],$);d.value=uo(F+k(y,C[0])+b+2,C.length)};let h=0;const m=()=>{cancelAnimationFrame(h),h=requestAnimationFrame(u)};it(()=>{var y;const $=(y=r.value)==null?void 0:y.querySelector(".island__body");$&&(qs($,m,{childList:!0,subtree:!0}),js($,m)),m()});const R=E(()=>o.value!==null&&t.resize==="height"&&w.value),P=$=>{var y;return[...((y=$.parentElement)==null?void 0:y.children)??[]].filter(C=>C!==$&&C instanceof HTMLElement).map(C=>({collapsed:C.classList.contains("island--collapsed"),height:C.offsetHeight,floor:f(C.style.getPropertyValue("--island-floor"))}))},Y=()=>{const $=r.value;if(u(),t.resize==="width"){const A=$.parentElement,D=f(getComputedStyle(A).columnGap);return{current:$.offsetWidth,min:Pa,max:A.clientWidth-D-Fa}}const y=$.parentElement,C=f(getComputedStyle(y).rowGap);return{current:$.offsetHeight,min:d.value,max:Math.max(ho(y.clientHeight,C,P($)),y.clientHeight)}};return($,y)=>(i(),c("section",{id:e.id,ref_key:"root",ref:r,class:L(["island",{"island--collapsed":_(s),"island--column":e.column,"island--sized":R.value}]),style:Ne(e.resize==="height"?{"--island-floor":d.value+"px","--island-height":(R.value?_(o):0)+"px"}:void 0)},[a("div",za,[N(qe,{open:!_(s),"aria-label":"Fold "+e.title,"data-tip":"Fold this panel; it stays folded until you open it again",onClick:ee(_(n),["stop"])},null,8,["open","aria-label","onClick"]),a("h2",Ia,[G(v(e.title)+" ",1),me($.$slots,"head",{},void 0)]),a("p",Oa,[a("span",Ba,v(e.note),1),e.tip?(i(),c("button",{key:0,type:"button",class:"hint-icon","aria-label":"About "+e.title,"data-tip":e.tip,"data-tip-click":""}," ? ",8,Da)):x("",!0)])]),a("div",Na,[me($.$slots,"default",{},void 0)]),_(s)?x("",!0):(i(),K(us,{key:0,label:"Resize "+e.title,axis:e.resize==="width"?"x":"y",grow:e.resize==="width"?-1:1,bounds:Y,onResize:_(l),onReset:y[0]||(y[0]=C=>_(l)(null))},null,8,["label","axis","grow","onResize"]))],14,Ta))}}),je=j(Va,[["__scopeId","data-v-53a904f0"]]),Wa=["aria-label"],Ua=["aria-pressed","onClick"],Ha={key:0,class:"count"},La=q({__name:"Segmented",props:et({options:{},label:{default:""},chips:{type:Boolean}},{modelValue:{required:!0},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const t=Vt(e,"modelValue");return(s,n)=>(i(),c("span",{class:L(["segmented",{"segmented--chips":e.chips}]),role:"group","aria-label":e.label},[(i(!0),c(W,null,X(e.options,o=>(i(),c("button",{key:o.id,type:"button",class:"segmented__option","aria-pressed":t.value===o.id,onClick:l=>t.value=o.id},[G(v(o.label),1),o.count!==void 0?(i(),c("b",Ha,v(o.count),1)):x("",!0)],8,Ua))),128))],10,Wa))}}),We=j(La,[["__scopeId","data-v-201d5e2f"]]),qa={class:"ticket-cell"},ja={class:"ticket-cell__summary"},Ya=q({__name:"TicketCell",props:{row:{}},setup(e){return(t,s)=>(i(),c("td",qa,[N(le,{text:e.row.key,url:_(Yt)(e.row)?e.row.pr_url:e.row.ticket_url,class:"ticket-key"},null,8,["text","url"]),a("span",ja,v(e.row.summary),1)]))}}),vt=j(Ya,[["__scopeId","data-v-e2d11a0b"]]),Ka={key:0,class:"pr-cell"},Xa={key:1,class:"pill"},Ga=q({__name:"PrCell",props:{row:{}},setup(e){return(t,s)=>(i(),c("td",null,[e.row.pr&&!_(Yt)(e.row)?(i(),c("span",Ka,[N(le,{text:e.row.pr,url:e.row.pr_url,class:"pr-cell__link"},null,8,["text","url"]),e.row.pr_state==="OPEN"&&e.row.checks?(i(),c("span",{key:0,class:L(["pill",_(Re)("pill",_(Qs)(e.row.checks))])},v(e.row.checks),3)):e.row.pr_state?(i(),c("span",Xa,v(e.row.pr_state.toLowerCase()),1)):x("",!0)])):x("",!0)]))}}),hs=j(Ga,[["__scopeId","data-v-6078ccbd"]]),Za=["open"],Ja={class:"recently-done__summary"},Qa={class:"count"},el={class:"table"},tl=["data-tip"],sl={class:"table__actions"},nl=480,ol=q({__name:"RecentlyDone",setup(e){const{size:t,set:s}=pt(()=>`${g.workspace.id}:recently-done`),n=Ue("list"),o=f=>{var k;const p=(k=f.closest(".island__body"))==null?void 0:k.querySelector(".row-scroll");return p?Math.max(0,p.clientHeight-(parseFloat(getComputedStyle(p).minHeight)||0)):0},l=()=>{const f=n.value,k=(f.querySelector("tbody > tr")??f).getBoundingClientRect().bottom-f.getBoundingClientRect().top,u=parseFloat(getComputedStyle(f).paddingBottom)||0;return{current:f.offsetHeight,min:Math.ceil(k+f.scrollTop+u),max:Math.min(nl,f.offsetHeight+o(f))}},r=we("wt-recent-open",!1,{writeDefaults:!1,serializer:{read:f=>f==="1",write:f=>f?"1":"0"}}),d=f=>{r.value=f.target.open},w=E(()=>(fe.value,en(g.turn).map(f=>({row:f,since:ht(f.status_since||f.updated)}))));return(f,p)=>w.value.length?(i(),c("details",{key:0,class:"recently-done",open:_(r),onToggle:d},[a("summary",Ja,[N(qe,{tag:"span",open:_(r)},null,8,["open"]),p[1]||(p[1]=G(" Recently done ",-1)),a("span",Qa,v(w.value.length),1)]),a("div",{ref_key:"list",ref:n,class:"recently-done__list",style:Ne(_(t)===null?void 0:{maxHeight:_(t)+"px",height:_(t)+"px"})},[a("table",el,[p[2]||(p[2]=a("thead",null,[a("tr",null,[a("th",null,"Ticket"),a("th",null,"Status"),a("th",null,"Done"),a("th",{class:"table__actions-col"},[a("span",{class:"visually-hidden"},"Copy for AI")])])],-1)),a("tbody",null,[(i(!0),c(W,null,X(w.value,({row:k,since:u})=>(i(),c("tr",{key:k.row_id},[N(vt,{row:k},null,8,["row"]),a("td",null,[a("span",{class:L(["pill",_(Re)("pill",_(Kt)(k.status_group))])},v(k.status),3)]),a("td",null,[a("span",{class:"age","data-tip":"Done "+_(Le)(k.status_since||k.updated)},v(u.text),9,tl)]),a("td",sl,[N(ve,{class:"table__ai",query:{ws:_(g).workspace.id,kind:"row",ref:k.row_id}},null,8,["query"])])]))),128))])])],4),_(r)?(i(),K(us,{key:0,label:"Resize Recently done",axis:"y",top:"",grow:-1,bounds:l,onResize:_(s),onReset:p[0]||(p[0]=k=>_(s)(null))},null,8,["onResize"])):x("",!0)],40,Za)):x("",!0)}}),al=j(ol,[["__scopeId","data-v-68a4b78e"]]),ll=13,il=q({__name:"RowScroll",props:{floor:{type:Boolean}},setup(e){const t=B(null),s=B(null),{y:n}=Ys(t),{height:o}=$t(t),{height:l}=$t(s),r=()=>{var u,h,m;return[...((m=(h=(u=s.value)==null?void 0:u.querySelector("table"))==null?void 0:h.tBodies[0])==null?void 0:m.rows)||[]]},d=()=>r().filter(u=>!("rowTail"in u.dataset)),w=u=>{const h=u.nextElementSibling;return((h==null?void 0:h.dataset.rowTail)!==void 0?h:u).getBoundingClientRect().bottom},f=()=>{const u=t.value;return u?u.getBoundingClientRect().top+u.clientTop+u.clientHeight:0},p=E(()=>(n.value,o.value,l.value,tn(d().map(w),f(),ll))),k=()=>{var Y,$;const u=t.value,h=d(),m=h[h.length-p.value];if(!u||!m)return;const P=(($=(Y=s.value)==null?void 0:Y.querySelector("thead"))==null?void 0:$.getBoundingClientRect().bottom)??u.getBoundingClientRect().top;u.scrollBy({top:m.getBoundingClientRect().top-P,behavior:"smooth"})};return(u,h)=>(i(),c(W,null,[a("div",{ref_key:"scroller",ref:t,class:L(["row-scroll",{"row-scroll--floor":e.floor}])},[a("div",{ref_key:"content",ref:s},[me(u.$slots,"default",{},void 0)],512)],2),p.value?(i(),c("button",{key:0,type:"button",class:"row-scroll__more",onClick:k}," +"+v(p.value)+" more ",1)):x("",!0)],64))}}),ps=j(il,[["__scopeId","data-v-e7f699d1"]]),rl=B("open"),cl=()=>rl,dl={key:0,class:"your-move__undo",role:"status"},ul={class:"table"},hl={key:0},pl={key:1,class:"hide-narrow"},_l={class:"hint-row"},fl={class:"your-move__next"},vl=["data-tip"],ml=["data-tip"],gl=["data-tip"],yl={key:0,class:"alert alert--inline your-move__problem",role:"alert"},wl={class:"table__actions"},kl=["aria-label","onClick"],bl={colspan:"99",class:"your-move__line-cell"},$l=["onClick"],xl={class:"your-move__outcome"},Sl={class:"your-move__time"},Cl={key:1,class:"empty"},El=q({__name:"YourMove",setup(e){const t=cl(),s=E(()=>{fe.value;const u=sn(g.turn,t.value,g.marks.info,S.note),h=u.rows.map(m=>{const R=g.marks.info[m.row.row_id],P=!!(R!=null&&R.auto);return{...m,age:ht(m.row.activity_at),auto:P,lined:P||!!(R!=null&&R.note),line:(P?R==null?void 0:R.outcome:R==null?void 0:R.note)||""}});return{...u,rows:h}}),n=E(()=>Xt(s.value.rows.map(u=>u.row))),o=E(()=>s.value.rows.some(u=>u.row.comment)),l=E(()=>[{id:"open",label:"Open",count:s.value.open},{id:"handled",label:"Handled",count:s.value.handled}]),r=E(()=>{if(t.value==="handled")return"Nothing marked as handled.";const{noData:u,failing:h}=cs(g.health,g.polled_at,g.workspace.connectors.length,S.live);return u?"No data: "+h.join(", ")+(h.length===1?" is":" are")+" failing. Check Settings.":"Nothing is waiting on you."}),d=lt(new Map);ft(()=>d.clear());const w=u=>new Date(g.marks.handled[u.row.row_id]||"").toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"}),f=async u=>{const h=u.row.row_id,m=!u.handled,R=await ye({handled:{[h]:m?new Date().toISOString():null}});R?d.set(h,R):(d.delete(h),p.value=m?h:"",S.note=m?h:"")},p=He("",8e3),k=()=>{const u=p.value;return p.value="",ye({handled:{[u]:null}})};return(u,h)=>(i(),K(je,{id:"your-move","size-key":`${_(g).workspace.id}:your-move`,title:"Your move",note:"Next step is yours",tip:"Each row is something where the next step is yours. Ticket, PR and comment open in a new tab."},{head:te(()=>[N(We,{modelValue:_(t),"onUpdate:modelValue":h[0]||(h[0]=m=>Ts(t)?t.value=m:null),options:l.value,label:"Show",class:"your-move__view"},null,8,["modelValue","options"])]),default:te(()=>[_(p)?(i(),c("p",dl,[h[1]||(h[1]=G(" Marked handled. ",-1)),a("button",{type:"button",class:"your-move__undo-btn",onClick:k},"Undo")])):x("",!0),N(ps,{floor:""},{default:te(()=>[a("table",ul,[a("thead",null,[a("tr",null,[h[2]||(h[2]=a("th",null,"Ticket",-1)),h[3]||(h[3]=a("th",null,"Next step",-1)),n.value?(i(),c("th",hl,"PR")):x("",!0),o.value?(i(),c("th",pl,"Last comment")):x("",!0),h[4]||(h[4]=a("th",{class:"table__actions-col"},[a("span",{class:"visually-hidden"},"Mark")],-1))])]),a("tbody",null,[(i(!0),c(W,null,X(s.value.rows,m=>(i(),c(W,{key:m.row.row_id},[a("tr",{class:L(["your-move__row",{"your-move__row--handled":m.handled,"your-move__row--lined":m.lined}])},[N(vt,{row:m.row},null,8,["row"]),a("td",null,[a("span",_l,[a("span",fl,v(m.row.next),1),m.age.text?(i(),c("span",{key:0,class:L(["age",{"age--old":m.age.old}]),"data-tip":"Waiting since "+_(Le)(m.row.activity_at)},v(m.age.text),11,vl)):x("",!0),m.row.why?(i(),c("button",{key:1,type:"button",class:"hint-label","aria-label":"Why this is your move","data-tip":m.row.why,"data-tip-click":""}," why ",8,ml)):x("",!0),m.handled&&!m.auto?(i(),c("span",{key:2,class:"handled-chip","data-tip":"Marked "+_(re)(_(g).marks.handled[m.row.row_id]||"")+". Comes back in 7 days if it is still open, or sooner when something new happens."},"handled",8,gl)):x("",!0)]),d.get(m.row.row_id)?(i(),c("p",yl,v(d.get(m.row.row_id)),1)):x("",!0)]),n.value?(i(),K(hs,{key:0,row:m.row},null,8,["row"])):x("",!0),o.value?(i(),c("td",{key:1,class:L(["hide-narrow",{"your-move__quote":m.row.comment}])},[m.row.comment?(i(),K(le,{key:0,text:m.row.comment,url:m.row.comment_url},null,8,["text","url"])):x("",!0)],2)):x("",!0),a("td",wl,[N(ve,{class:"table__ai",query:{ws:_(g).workspace.id,kind:"row",ref:m.row.row_id}},null,8,["query"]),m.auto?x("",!0):(i(),c("button",{key:0,type:"button",class:L(["your-move__mark",{"your-move__mark--undo":m.handled}]),"aria-label":(m.handled?"Move back to open: ":"Mark as handled: ")+m.row.key,onClick:ee(R=>f(m),["stop"])},v(m.handled?"Undo":"Handled"),11,kl))])],2),m.lined?(i(),c("tr",{key:0,"data-row-tail":"",class:L(["your-move__line-row",{"your-move__line-row--handled":m.handled}])},[a("td",bl,[a("button",{type:"button",class:"your-move__line","data-tip":"Open the full text and edit the note",onClick:R=>_(S).note=m.row.row_id},[h[5]||(h[5]=a("span",{class:"your-move__arrow","aria-hidden":"true"},"→",-1)),a("span",xl,v(m.line),1),a("time",Sl,v(w(m)),1)],8,$l)])],2)):x("",!0)],64))),128))])])]),_:1}),s.value.rows.length?x("",!0):(i(),c("p",Cl,v(r.value),1)),_(t)==="open"?(i(),K(al,{key:2})):x("",!0)]),_:1},8,["size-key"]))}}),Rl=j(El,[["__scopeId","data-v-3a6ca0d0"]]),Al=B(!1),Ml=()=>Al,Tl={class:"todos__add"},zl={key:0,class:"alert alert--inline",role:"alert"},Il={key:1,class:"todos__undo",role:"status"},Ol={class:"todos__list"},Bl=["aria-checked","aria-label","onClick"],Dl=["onKeydown"],Nl=["onDblclick"],Pl={class:"todos__meta"},Fl=["onClick"],Vl=["onClick"],Wl={key:0,class:"empty todos__empty"},Ul=q({__name:"Todos",setup(e){const t=Ml(),s=B(""),n=E(()=>(g.todos||[]).filter(b=>!b.done)),o=E(()=>(g.todos||[]).filter(b=>b.done)),l=E(()=>new RegExp(g.workspace.key_pattern||"(?!)","g")),r=b=>{const F=[];let U=0;const se=b.text;for(const z of se.matchAll(l.value))z.index>U&&F.push({text:se.slice(U,z.index)}),F.push({text:z[0],url:z[0]===b.key?b.ticket_url:""}),U=z.index+z[0].length;return U<se.length&&F.push({text:se.slice(U)}),F},d=E(()=>(fe.value,(t.value?n.value.concat(o.value):n.value).map(b=>({todo:b,parts:r(b),meta:(b.by&&b.by!=="you"?b.by+" · ":"")+re(b.created)})))),w=B("");ft(()=>{w.value=""});const f=async b=>(w.value=await Kn(b),!w.value),p=async()=>{const b=s.value.trim();b&&await f({action:"add",text:b})&&s.value.trim()===b&&(s.value="")},k=b=>f({action:b.done?"undo":"done",id:b.id}),u=B(null),h=async b=>{await f({action:"delete",id:b.id})&&(u.value=b)},m=async()=>{const b=u.value;if(u.value=null,b&&await f({action:"add",text:b.text})&&b.done){const F=(g.todos||[]).find(U=>U.text===b.text&&!U.done);F&&await f({action:"done",id:F.id})}},R=B(""),P=B(""),Y=Ue("editBox"),$=async b=>{var F,U;R.value=b.id,P.value=b.text,await _e(),(U=(F=Y.value)==null?void 0:F[0])==null||U.focus()},y=()=>{R.value=""},C=async b=>{const F=P.value.trim();if(!F||F===b.text)return y();await f({action:"edit",id:b.id,text:F})&&y()},A=E({get:()=>t.value?"done":"open",set:b=>{t.value=b==="done"}}),D=E(()=>[{id:"open",label:"Open",count:n.value.length},{id:"done",label:"Done",count:o.value.length}]);return(b,F)=>(i(),K(je,{id:"todo","size-key":`${_(g).workspace.id}:todo`,title:"To do",note:"Your own notes",tip:'Your personal to-dos, kept on this machine. Add here, or ask Claude: "add to my to-do: …". A ticket key like PROJ-123 in the text becomes a link.'},{head:te(()=>[N(We,{modelValue:A.value,"onUpdate:modelValue":F[0]||(F[0]=U=>A.value=U),options:D.value,label:"Show",class:"todos__view"},null,8,["modelValue","options"])]),default:te(()=>[a("div",Tl,[be(a("input",{"onUpdate:modelValue":F[1]||(F[1]=U=>s.value=U),class:"input todos__input",type:"text",placeholder:"Add a to-do and press Enter","aria-label":"New to-do",autocomplete:"off",onKeydown:ge(p,["enter"])},null,544),[[$e,s.value]]),a("button",{type:"button",class:"btn btn--tonal",onClick:p},"Add")]),w.value?(i(),c("p",zl,v(w.value),1)):x("",!0),u.value?(i(),c("p",Il,[F[3]||(F[3]=G(" To-do deleted. ",-1)),a("button",{type:"button",class:"todos__undo-btn",onClick:m},"Undo")])):x("",!0),a("ul",Ol,[(i(!0),c(W,null,X(d.value,({todo:U,parts:se,meta:z})=>(i(),c("li",{key:U.id,class:L(["todos__item",{"todos__item--done":U.done}])},[a("button",{type:"button",class:L(["todos__check",{"todos__check--on":U.done}]),role:"checkbox","aria-checked":!!U.done,"aria-label":U.done?"Mark not done":"Mark done",onClick:V=>k(U)},null,10,Bl),R.value===U.id?be((i(),c("input",{key:0,ref_for:!0,ref_key:"editBox",ref:Y,"onUpdate:modelValue":F[2]||(F[2]=V=>P.value=V),class:"input todos__edit",type:"text",maxlength:"500","aria-label":"Edit to-do",autocomplete:"off",onKeydown:[ge(V=>C(U),["enter"]),ge(y,["esc"])],onBlur:y},null,40,Dl)),[[$e,P.value]]):(i(),c("span",{key:1,class:"todos__text",onDblclick:V=>$(U)},[(i(!0),c(W,null,X(se,(V,O)=>(i(),c(W,{key:O},[V.url!==void 0?(i(),K(le,{key:0,text:V.text,url:V.url},null,8,["text","url"])):(i(),c(W,{key:1},[G(v(V.text),1)],64))],64))),128))],40,Nl)),a("span",Pl,v(z),1),a("button",{type:"button",class:"todos__pencil","aria-label":"Edit to-do",onClick:V=>$(U)}," ✎ ",8,Fl),a("button",{type:"button",class:"todos__delete","aria-label":"Delete to-do",onClick:V=>h(U)}," × ",8,Vl)],2))),128)),d.value.length?x("",!0):(i(),c("span",Wl,v(_(t)?"Nothing here yet.":"Nothing to do. Add one above, or ask Claude."),1))])]),_:1},8,["size-key"]))}}),Hl=j(Ul,[["__scopeId","data-v-6dbdbb66"]]),Ll={key:0,class:"count"},ql={key:0,class:"empty"},jl={class:"table waiting__table"},Yl={key:0,class:"hide-narrow"},Kl={key:1,class:"waiting__col waiting__col--pr"},Xl=["data-tip"],Gl={key:0,class:"hide-narrow"},Zl={key:0,class:"hint-row"},Jl=["data-tip"],Ql={class:"table__actions"},ei=q({__name:"Waiting",setup(e){const t=E(()=>(fe.value,nn(g.turn).map(l=>({row:l,since:l.status_since?ht(l.status_since):null,own:l.status_group==="backlog"})))),s=E(()=>Xt(t.value.map(({row:l})=>l))),n=E(()=>t.value.some(({row:l,own:r})=>l.hold_url||!r&&l.next)),o=E(()=>t.value.length&&t.value.every(({own:l})=>l)?"Your backlog":"Someone else holds the next step");return(l,r)=>(i(),K(je,{id:"waiting","size-key":`${_(g).workspace.id}:waiting`,title:"Waiting on others",note:o.value,tip:"Tickets you touched in the last 30 days where someone else holds the next step: a reviewer, QA, or a new owner."},{head:te(()=>[t.value.length?(i(),c("span",Ll,v(t.value.length),1)):x("",!0)]),default:te(()=>[t.value.length?(i(),K(ps,{key:1},{default:te(()=>[a("table",jl,[a("thead",null,[a("tr",null,[r[0]||(r[0]=a("th",{class:"waiting__col waiting__col--ticket"},"Ticket",-1)),r[1]||(r[1]=a("th",{class:"waiting__col waiting__col--status"},"Status",-1)),r[2]||(r[2]=a("th",{class:"waiting__col waiting__col--with"},"With",-1)),n.value?(i(),c("th",Yl,"Waiting for")):x("",!0),s.value?(i(),c("th",Kl,"PR")):x("",!0),r[3]||(r[3]=a("th",{class:"table__actions-col waiting__col waiting__col--actions"},[a("span",{class:"visually-hidden"},"Copy for AI")],-1))])]),a("tbody",null,[(i(!0),c(W,null,X(t.value,({row:d,since:w,own:f})=>(i(),c("tr",{key:d.row_id},[N(vt,{row:d},null,8,["row"]),a("td",null,[a("span",{class:L(["pill",_(Re)("pill",_(Kt)(d.status_group))])},v(d.status),3)]),a("td",null,[G(v(f?"you":d.whose)+" ",1),w?(i(),c("span",{key:0,class:L(["age",{"age--old":w.hours>=72}]),"data-tip":d.status+" since "+_(Le)(d.status_since)},v(w.text),11,Xl)):x("",!0)]),n.value?(i(),c("td",Gl,[d.hold_url?(i(),c("span",Zl,[N(le,{text:d.next,url:d.hold_url,class:"waiting__reason"},null,8,["text","url"]),a("button",{type:"button",class:"hint-label","aria-label":"Full reason","data-tip":d.hold_full||d.next}," full ",8,Jl)])):f?x("",!0):(i(),c(W,{key:1},[G(v(d.next),1)],64))])):x("",!0),s.value?(i(),K(hs,{key:1,row:d},null,8,["row"])):x("",!0),a("td",Ql,[N(ve,{class:"table__ai",query:{ws:_(g).workspace.id,kind:"row",ref:d.row_id}},null,8,["query"])])]))),128))])])]),_:1})):(i(),c("p",ql,"Nothing is waiting on someone else."))]),_:1},8,["size-key","note"]))}}),ti=j(ei,[["__scopeId","data-v-90e8bf77"]]),si=(e,t)=>e.seen instanceof Set?e.seen.has(t):e.seen.includes(t),_s=(e,t)=>new Date(e.at).getTime()>(t.base||0)&&!si(t,e.id),ni=(e,t)=>{const s=String(t||"").toLowerCase().split(/\s+/).filter(Boolean);if(!s.length)return!0;const n=[e.ref,e.key,e.title,e.kind,e.who,e.text,e.body].join(" ").toLowerCase();return s.every(o=>n.includes(o))},oi=e=>e.key||e.ref||e.id,ai=(e,t)=>{const s=new Map;for(const n of e){const o=oi(n),l=s.get(o)||{id:o,items:[],newest:n.at,unread:0,title:""};s.set(o,l),l.items.push(n),l.title||(l.title=n.title||""),n.at>l.newest&&(l.newest=n.at),_s(n,t)&&(l.unread+=1)}return[...s.values()].sort((n,o)=>String(o.newest).localeCompare(String(n.newest)))},li=e=>new Set(e.filter(t=>t.group==="you"&&!t.handled).map(t=>t.key)),ii=(e,t=2)=>{const s=[...new Set(e.map(o=>o.kind))],n=s.length-t;return s.slice(0,t).join(" · ")+(n>0?` +${n}`:"")},ri=e=>/fail|changes/.test(e)?"bad":/approved|merged|passed/.test(e)?"ok":"",ci=e=>/comment|approved|changes|mentioned|review requested/.test(e.kind)&&String(e.body||"").trim()!=="",fs=e=>e.ref!==e.key&&(e.key||e.title)||"",di=e=>[fs(e),e.text===e.title?"":e.text].filter(Boolean).join(" · "),ui=e=>e.type==="github"&&e.label==="GitHub"?"GH":is(e.label),hi=["id"],pi={class:"feed-item__body"},_i={class:"feed-item__top"},fi={key:1,class:"feed-item__who"},vi={key:2,class:"at-you"},mi={class:"feed-item__right"},gi={class:"timestamp feed-item__when"},yi={key:0,class:"feed-item__text"},wi={class:"feed-item__full"},ki={class:"feed-item__actions"},bi={key:1,class:"feed-item__text"},$i=q({__name:"FeedItem",props:{item:{},source:{},fresh:{type:Boolean},flash:{type:Boolean},expanded:{type:Boolean}},emits:["open","toggle","seen"],setup(e,{emit:t}){const s=e,n=t,o=E(()=>ui(s.source)),l=E(()=>fs(s.item)),r=E(()=>di(s.item)),d=E(()=>ri(s.item.kind)),w=E(()=>d.value||(s.source.type==="github"?"":"jira")),f=E(()=>ci(s.item)),p=E(()=>f.value&&s.expanded),k=E(()=>(fe.value,re(s.item.at))),u=()=>{s.fresh&&n("seen",s.item.id)},h=()=>{n("toggle",s.item.id),u()};return(m,R)=>(i(),c("li",{id:"feed-"+e.item.id,class:L(["feed-item",{"feed-item--new":e.fresh,"feed-item--open":p.value,"feed-item--flash":e.flash}]),onClick:u},[a("span",{class:L(["feed-item__icon",_(Re)("feed-item__icon",w.value)])},v(o.value),3),a("div",pi,[a("div",_i,[f.value?(i(),K(qe,{key:0,open:p.value,"aria-label":p.value?"Collapse":"Expand",onClick:ee(h,["stop"])},null,8,["open","aria-label"])):x("",!0),N(le,{text:e.item.ref,url:e.item.url},null,8,["text","url"]),a("span",{class:L(["feed-item__kind",{"feed-item__kind--bad":d.value==="bad"}])},v(e.item.kind),3),e.item.who?(i(),c("span",fi,v(e.item.who),1)):x("",!0),e.item.mention?(i(),c("span",vi,"@you")):x("",!0),a("span",mi,[a("span",gi,v(k.value),1)])]),p.value?(i(),c(W,{key:0},[l.value?(i(),c("span",yi,v(l.value),1)):x("",!0),a("div",wi,v(e.item.body),1),a("div",ki,[a("button",{type:"button",class:"btn btn--tonal",onClick:R[0]||(R[0]=ee(P=>n("open",e.item),["stop"]))}," Open formatted "),N(ve,{query:{ws:_(g).workspace.id,kind:"feed",ref:e.item.id}},null,8,["query"]),N(le,{text:"Open in "+e.source.label,url:e.item.url,class:"btn"},null,8,["text","url"])])],64)):r.value?(i(),c("span",bi,v(r.value),1)):x("",!0)])],10,hi))}}),Nt=j($i,[["__scopeId","data-v-8cc9dc10"]]),xi=lt({source:"all",view:we("wt-feed-view","ticket",{writeDefaults:!1}),query:"",openGroups:new Set}),Si=()=>xi,Ci={key:0,class:"feed__new-count"},Ei={class:"feed__bar"},Ri={key:0,class:"alert alert--inline",role:"alert"},Ai={key:1,class:"feed__undo",role:"status"},Mi={class:"feed__search"},Ti={class:"feed__search-count"},zi={key:2,class:"empty"},Ii={key:3,class:"feed__list"},Oi=["title","onClick"],Bi={class:"feed__group-text"},Di={class:"feed__group-key"},Ni={key:0,class:"feed__group-sum"},Pi={class:"feed__group-meta"},Fi={class:"feed__group-kinds"},Vi={class:"timestamp feed__group-when"},Wi={key:0,class:"feed__children"},Ui=2500,Hi=q({__name:"Feed",emits:["open"],setup(e,{emit:t}){const s=t,n=Si(),o=[{id:"ticket",label:"By ticket"},{id:"flat",label:"Flat"}],l=E(()=>g.workspace.connectors||[]),r=E(()=>Object.fromEntries(l.value.map(z=>[z.id,z]))),d=z=>r.value[z]||{id:z,type:z,label:z},w=E(()=>l.value.length>1?[{id:"all",label:"All"}].concat(l.value.map(z=>({id:z.id,label:z.label}))):[]),f=E({get:()=>w.value.some(z=>z.id===n.source)?n.source:"all",set:z=>{n.source=z}});J(()=>g.workspace.id,()=>{n.query=""});const p=B("");J(()=>S.focusFeed,async z=>{var O;const V=g.feed.find(Q=>Q.id===z);S.focusFeed="",V&&(n.source="all",n.query="",n.openGroups.add(V.key||V.ref||V.id),p.value=z,await _e(),(O=document.getElementById(`feed-${z}`))==null||O.scrollIntoView({block:"center"}),setTimeout(()=>{p.value=""},Ui))});const k=E(()=>({base:g.marks.base,seen:new Set(g.marks.seen)})),u=z=>_s(z,k.value),h=E(()=>g.feed.filter(u).length),m=E(()=>g.feed.filter(z=>f.value==="all"||z.source===f.value)),R=E(()=>m.value.filter(z=>ni(z,n.query)).slice(0,200)),P=E(()=>new Map(g.turn.map(z=>[z.key,z]))),Y=E(()=>li(g.turn)),$=E(()=>(fe.value,ai(R.value,k.value).map(z=>({...z,row:P.value.get(z.id),move:Y.value.has(z.id),when:re(z.newest),kinds:ii(z.items),open:n.openGroups.has(z.id)||!!n.query})))),y=(z,V)=>{z.has(V)?z.delete(V):z.add(V)},C=z=>y(n.openGroups,z.id),A=z=>y(S.open,z),D=z=>ye({seen:[z]}).then(de),b=B("");ft(()=>{b.value=""});const F=B(null),U=async()=>{const z=new Set(g.marks.seen),V={base:g.marks.base,added:g.feed.map(O=>O.id).filter(O=>!z.has(O))};b.value=await ye({seen:g.feed.map(O=>O.id),base:Date.now()}),F.value=b.value?null:V},se=async()=>{const z=F.value;F.value=null,z&&(b.value=await ye({unseen:z.added,base:z.base}))};return(z,V)=>(i(),K(je,{id:"feed","size-key":`${_(g).workspace.id}:feed`,title:"What changed",note:"Newest first, every source",tip:"Newest first: comments, reviews, merges and failed checks on your PRs, and ticket changes. Each item opens where it happened.",class:"feed",column:"",resize:"width"},{head:te(()=>[h.value?(i(),c("span",Ci,v(h.value)+" new",1)):x("",!0)]),default:te(()=>[a("div",Ei,[w.value.length?(i(),K(We,{key:0,modelValue:f.value,"onUpdate:modelValue":V[0]||(V[0]=O=>f.value=O),options:w.value,label:"Feed source"},null,8,["modelValue","options"])):x("",!0),N(We,{modelValue:_(n).view,"onUpdate:modelValue":V[1]||(V[1]=O=>_(n).view=O),options:o,label:"Feed view"},null,8,["modelValue"])]),b.value?(i(),c("p",Ri,v(b.value),1)):x("",!0),F.value?(i(),c("p",Ai,[V[5]||(V[5]=G(" Marked all read. ",-1)),a("button",{type:"button",class:"feed__undo-btn",onClick:se},"Undo")])):x("",!0),a("div",Mi,[be(a("input",{"onUpdate:modelValue":V[2]||(V[2]=O=>_(n).query=O),class:"input feed__search-input",type:"search",placeholder:"Search the feed: key, author, words…","aria-label":"Search the feed",autocomplete:"off"},null,512),[[$e,_(n).query,void 0,{trim:!0}]]),a("span",Ti,v(_(n).query?R.value.length+" of "+m.value.length:""),1),a("button",{type:"button",class:"feed__mark-read",onClick:U},"Mark all read")]),_(g).feed.length?(i(),c("ol",Ii,[_(n).view==="ticket"?(i(!0),c(W,{key:0},X($.value,O=>(i(),c("li",{key:O.id,class:L(["feed__group",{"feed__group--new":O.unread,"feed__group--open":O.open,"feed__group--move":O.move}])},[a("div",{class:"feed__group-head",title:O.move?"Your move on this ticket":void 0,onClick:Q=>C(O)},[N(qe,{open:O.open,"aria-label":"Fold "+O.id},null,8,["open","aria-label"]),a("div",Bi,[a("div",Di,[N(le,{text:O.id,url:O.row?O.row.ticket_url:O.items[0].url,class:"ticket-key feed__group-ticket"},null,8,["text","url"]),O.row||O.title?(i(),c("span",Ni,v(O.row?O.row.summary:O.title),1)):x("",!0)]),a("div",Pi,[a("span",{class:L(["feed__group-count",{"feed__group-count--new":O.unread}])},v(O.unread?O.unread+" new":O.items.length+(O.items.length===1?" event":" events")),3),a("span",Fi,v(O.kinds),1),a("span",Vi,v(O.when),1)])]),N(ve,{class:"feed__group-copy",query:{ws:_(g).workspace.id,kind:"thread",ref:O.id}},null,8,["query"])],8,Oi),O.open?(i(),c("ul",Wi,[(i(!0),c(W,null,X(O.items,Q=>(i(),K(Nt,{key:Q.id,item:Q,source:d(Q.source),fresh:u(Q),flash:p.value===Q.id,expanded:_(S).open.has(Q.id),onOpen:V[3]||(V[3]=Ye=>s("open",Ye)),onToggle:A,onSeen:D},null,8,["item","source","fresh","flash","expanded"]))),128))])):x("",!0)],2))),128)):(i(!0),c(W,{key:1},X(R.value,O=>(i(),K(Nt,{key:O.id,item:O,source:d(O.source),fresh:u(O),flash:p.value===O.id,expanded:_(S).open.has(O.id),onOpen:V[4]||(V[4]=Q=>s("open",Q)),onToggle:A,onSeen:D},null,8,["item","source","fresh","flash","expanded"]))),128))])):(i(),c("p",zi," No changes yet. New comments, reviews and status changes show up here. "))]),_:1},8,["size-key"]))}}),Li=j(Hi,[["__scopeId","data-v-bbacc3b6"]]),qi={id:"first-run",class:"island first-run","aria-labelledby":"first-run-title"},ji={class:"first-run__text"},Yi=q({__name:"FirstRun",setup(e){const t=()=>ns("connectors");return(s,n)=>(i(),c("section",qi,[n[1]||(n[1]=a("h2",{id:"first-run-title",class:"first-run__title"}," Whose Turn watches your tickets and pull requests and shows what is waiting on you. ",-1)),a("p",ji,[a("b",null,v(_(g).workspace.name),1),n[0]||(n[0]=G(" has no sources yet, so there is nothing to watch. Connect a repository or a tracker. ",-1))]),a("div",{class:"first-run__actions"},[a("button",{type:"button",class:"btn btn--tonal",onClick:t},"Add a source")]),n[2]||(n[2]=a("p",{class:"first-run__text first-run__ai"},' Or ask Claude: "add my GitHub repository to Whose Turn." ',-1))]))}}),Ki=j(Yi,[["__scopeId","data-v-84359c2d"]]),Xi=new RegExp("(`[^`]{1,500}`)|(\\*\\*[^*]{1,500}\\*\\*)|(\\[[^\\]]{1,300}\\]\\(https?:\\/\\/[^)\\s]{1,2000}\\))|(https?:\\/\\/[^\\s<>()]{1,2000})|(@[A-Za-z0-9-]+(?: [A-Z][a-z]+)?)|((?<![A-Za-z0-9])\\*[^*\\s][^*]{0,500}\\*(?![A-Za-z0-9])|(?<![A-Za-z0-9])_[^_\\s][^_]{0,500}_(?![A-Za-z0-9]))","g"),Pt=(e,t)=>{const s=ut(t);return s?{type:"link",text:e,href:s}:{type:"text",text:e}},Gi=e=>{const t=e[0];if(e[1])return{type:"code",text:t.slice(1,-1)};if(e[2])return{type:"strong",text:t.slice(2,-2)};if(e[3]){const s=t.indexOf("](");return Pt(t.slice(1,s),t.slice(s+2,-1))}return e[4]?Pt(t,t):e[5]?{type:"mention",text:t}:{type:"em",text:t.slice(1,-1)}},Oe=e=>{const t=new RegExp(Xi),s=[];let n=0,o;for(;o=t.exec(e);)o.index>n&&s.push({type:"text",text:e.slice(n,o.index)}),s.push(Gi(o)),n=o.index+o[0].length;return n<e.length&&s.push({type:"text",text:e.slice(n)}),s},Zi=e=>{const t=String(e||"").replace(/<!--[\s\S]*?-->/g,"").split(`
|
|
6
|
+
`),s=[];let n=[],o=null;const l=()=>{n.length&&(s.push({type:"paragraph",lines:n.map(Oe)}),n=[]),o=null};for(let r=0;r<t.length;r++){const d=t[r];if(/^\s*```/.test(d)){l();const k=[];for(r++;r<t.length&&!/^\s*```/.test(t[r]);r++)k.push(t[r]);s.push({type:"fence",text:k.join(`
|
|
7
|
+
`)});continue}const w=d.match(/^(#{1,6})\s+(.*)$/);if(w){l(),s.push({type:"heading",level:w[1].length<=2?4:5,inline:Oe(w[2])});continue}const f=d.match(/^>\s?(.*)$/);if(f){l(),s.push({type:"quote",inline:Oe(f[1])});continue}const p=d.match(/^\s*([-*+]|\d+[.)])\s+(.*)$/);if(p){const k=o;n.length&&(l(),o=k);const u=/\d/.test(p[1]),h=o,m=h&&h.ordered===u?h:{type:"list",ordered:u,items:[]};m!==h&&s.push(m),o=m,m.items.push(Oe(p[2]));continue}if(!d.trim()){l();continue}o=null,n.push(d)}return l(),s},De=(e,t,s="")=>{const n=document.createElement(e);return n.textContent=t,s&&(n.className=s),n},Ji=e=>{if(e.type==="text")return document.createTextNode(e.text);if(e.type==="link"){const t=De("a",e.text);return t.setAttribute("href",e.href),t.setAttribute("target","_blank"),t.setAttribute("rel","noopener"),t}return e.type==="mention"?De("span",e.text,"markdown-view__mention"):De(e.type,e.text)},vs=(e,t)=>{e.forEach(s=>t.append(Ji(s)))},Qe=(e,t)=>{const s=document.createElement(e);return vs(t,s),s},Qi=e=>{if(e.type==="fence"){const s=document.createElement("pre");return s.append(De("code",e.text)),s}if(e.type==="heading")return Qe(`h${e.level}`,e.inline);if(e.type==="quote")return Qe("blockquote",e.inline);if(e.type==="list"){const s=document.createElement(e.ordered?"ol":"ul");return e.items.forEach(n=>s.append(Qe("li",n))),s}const t=document.createElement("p");return e.lines.forEach((s,n)=>{n&&t.append(document.createElement("br")),vs(s,t)}),t},er=e=>{const t=document.createDocumentFragment();return Zi(e).forEach(s=>t.append(Qi(s))),t},tr=q({__name:"MarkdownView",props:{source:{default:""}},setup(e){const t=e,s=B(null);return zs(()=>{s.value&&s.value.replaceChildren(er(t.source))}),(n,o)=>(i(),c("div",{ref_key:"host",ref:s,class:"markdown-view"},null,512))}}),ms=j(tr,[["__scopeId","data-v-dcf42e95"]]),sr={class:"modal__card"},nr={class:"modal__head"},or={id:"modal-title",class:"modal__title"},ar=["href"],lr=q({__name:"CommentModal",setup(e){const t=E(()=>S.modal),s=E(()=>t.value?[t.value.ref,t.value.kind,t.value.who].filter(Boolean).join(" · "):""),n=E(()=>t.value?ut(t.value.url):""),o=E(()=>{var d;const r=(g.workspace.connectors||[]).find(w=>{var f;return w.id===((f=t.value)==null?void 0:f.source)});return"Open in "+(r?r.label:(d=t.value)==null?void 0:d.source)}),l=()=>{S.modal=null};return(r,d)=>t.value?(i(),c("div",{key:0,class:"modal",role:"dialog","aria-modal":"true","aria-labelledby":"modal-title",onClick:ee(l,["self"])},[a("div",sr,[a("div",nr,[a("h3",or,v(s.value),1),n.value?(i(),c("a",{key:0,class:"btn",href:n.value,target:"_blank",rel:"noopener"},v(o.value),9,ar)):x("",!0),a("button",{type:"button",class:"btn",onClick:l},"Close")]),N(ms,{source:t.value.body||t.value.text||""},null,8,["source"])])])):x("",!0)}}),ir=["aria-labelledby"],rr={class:"modal__card"},cr={class:"modal__head"},dr=["id"],ur={key:0,class:"modal__foot"},hr=q({__name:"Modal",props:{title:{},labelId:{},flush:{type:Boolean}},emits:["close"],setup(e,{emit:t}){const s=t;return(n,o)=>(i(),c("div",{class:"modal",role:"dialog","aria-modal":"true","aria-labelledby":e.labelId,onClick:o[1]||(o[1]=ee(l=>s("close"),["self"]))},[a("div",rr,[a("div",cr,[a("h3",{id:e.labelId,class:"modal__title"},v(e.title),9,dr),me(n.$slots,"head",{},void 0),a("button",{type:"button",class:"btn",onClick:o[0]||(o[0]=l=>s("close"))},"Close")]),a("div",{class:L(["modal__body",{"modal__body--flush":e.flush}])},[me(n.$slots,"default",{},void 0)],2),n.$slots.footer?(i(),c("div",ur,[me(n.$slots,"footer",{},void 0)])):x("",!0)])],8,ir))}}),gs=j(hr,[["__scopeId","data-v-f2f8cfc9"]]),pr={class:"note-modal__summary"},_r={key:0,class:"note-modal__facts"},fr={class:"note-modal__author"},vr={class:"note-modal__label",for:"note-text"},mr=["onKeydown"],gr={key:1,class:"alert alert--inline",role:"alert"},yr=q({__name:"NoteModal",setup(e){const t=E(()=>g.turn.find(u=>u.row_id===S.note)),s=E(()=>g.marks.info[S.note]),n=E(()=>{var u;return((u=s.value)==null?void 0:u.note)||""}),o=B(""),l=B(""),r=B(null);J(()=>S.note,async u=>{var h;u&&(o.value=n.value,l.value="",await _e(),(h=r.value)==null||h.focus())},{immediate:!0,flush:"post"});const d=()=>{S.note=""},w=async()=>{const u=o.value.replace(/\s+/g," ").trim();if(u===n.value){d();return}l.value=await ye({notes:{[S.note]:u}}),l.value||d()},f=()=>{var h;const u=((h=s.value)==null?void 0:h.event)||"";d(),Yn(u)},p=E(()=>{var u;return(u=s.value)==null?void 0:u.detail}),k=E(()=>{var u,h;return((u=p.value)==null?void 0:u.what)||((h=s.value)==null?void 0:h.outcome)||""});return(u,h)=>{var m,R;return _(S).note&&t.value?(i(),K(gs,{key:0,title:t.value.key+" · "+((m=s.value)!=null&&m.auto?"Passed on":"Handled"),"label-id":"note-title",onClose:d},Wt({footer:te(()=>[a("button",{type:"button",class:"btn",onClick:d},v(n.value?"Cancel":"Skip"),1),a("button",{type:"button",class:"btn btn--tonal",onClick:w},"Save")]),default:te(()=>{var P,Y,$,y,C,A;return[a("p",pr,v(t.value.summary),1),(P=s.value)!=null&&P.auto?(i(),c("dl",_r,[h[5]||(h[5]=a("dt",null,"What happened",-1)),a("dd",null,v(k.value),1),(Y=p.value)!=null&&Y.assignee?(i(),c(W,{key:0},[h[1]||(h[1]=a("dt",null,"Assignee",-1)),a("dd",null,v(p.value.assignee),1)],64)):x("",!0),($=p.value)!=null&&$.status?(i(),c(W,{key:1},[h[2]||(h[2]=a("dt",null,"Status",-1)),a("dd",null,v(p.value.status),1)],64)):x("",!0),(y=p.value)!=null&&y.summary?(i(),c(W,{key:2},[h[3]||(h[3]=a("dt",null,"Event",-1)),a("dd",null,v(p.value.summary),1)],64)):x("",!0),(C=p.value)!=null&&C.comment?(i(),c(W,{key:3},[h[4]||(h[4]=a("dt",null,"Comment",-1)),a("dd",null,[a("span",fr,v(p.value.comment.author)+":",1),G(" "+v(p.value.comment.text),1)])],64)):x("",!0),h[6]||(h[6]=a("dt",null,"When",-1)),a("dd",null,v(_(Le)(_(g).marks.handled[_(S).note]||"")),1)])):x("",!0),a("label",vr,v((A=s.value)!=null&&A.auto?"Your note on top":"Note")+" (optional)",1),be(a("textarea",{id:"note-text",ref_key:"field",ref:r,"onUpdate:modelValue":h[0]||(h[0]=D=>o.value=D),class:"input note-modal__text",rows:"3",maxlength:"200",placeholder:"Add a note…",onKeydown:ge(ee(w,["prevent"]),["enter"])},null,40,mr),[[$e,o.value]]),l.value?(i(),c("p",gr,v(l.value),1)):x("",!0)]}),_:2},[(R=s.value)!=null&&R.auto?{name:"head",fn:te(()=>[s.value.event?(i(),c("button",{key:0,type:"button",class:"btn",onClick:f},"Open in feed")):x("",!0)]),key:"0"}:void 0]),1032,["title"])):x("",!0)}}}),wr=j(yr,[["__scopeId","data-v-6fc1670a"]]),kr={"Google Chrome":"Chrome","Microsoft Edge":"Edge",Opera:"Opera",Brave:"Brave",Chromium:"Chromium"},br=[[/Edg(?:e|A|iOS)?\/(\d+)/,"Edge"],[/OPR\/(\d+)/,"Opera"],[/(?:Firefox|FxiOS)\/(\d+)/,"Firefox"],[/(?:Chrome|CriOS)\/(\d+)/,"Chrome"],[/Version\/(\d+)[^]*Safari/,"Safari"]],Ft=e=>{var t;return((t=/^\d{1,6}/.exec(e))==null?void 0:t[0])??""},$r=e=>{var n;const t=(((n=e.userAgentData)==null?void 0:n.brands)??[]).filter(o=>!/^not.?a.?brand/i.test(o.brand.replace(/[^\w ]/g,""))),s=t.find(o=>o.brand!=="Chromium")??t[0];if(s&&Ft(s.version))return{name:kr[s.brand]??"Other",version:Ft(s.version)};for(const[o,l]of br){const r=o.exec(e.userAgent);if(r)return{name:l,version:r[1]}}return null},xr=e=>({browser:$r(e.navigator),display:{width:e.screen.width,height:e.screen.height,scale:e.devicePixelRatio,viewport:[e.innerWidth,e.innerHeight]},locale:e.navigator.language,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,theme:e.dark?"dark":"light",mode:e.mode}),Sr={class:"modal__card feedback-sheet__card"},Cr={class:"modal__head"},Er=["aria-disabled"],Rr={key:0,class:"alert"},Ar={class:"sheet-form"},Mr=["onKeydown"],Tr={key:0,class:"empty"},zr=["href"],Ir={key:1,class:"feedback-sheet__reports"},Or=["href"],Br={class:"feedback-sheet__report-title"},Dr={class:"timestamp"},Nr=q({__name:"FeedbackSheet",setup(e){const t=B(""),s=B(null),n=B(!1),o=B([]),l=B(null),r=B([]),d=k=>"/report?id="+encodeURIComponent(k),w=()=>Ee("/api/feedback").then(k=>{r.value=k.reports||[]},()=>{o.value=[xe+"; past reports cannot be loaded."]}),f=()=>{S.feedback=!1},p=()=>{if(n.value)return;const k=t.value.trim();if(!k){o.value=["Write at least one line."];return}n.value=!0,ie("/api/feedback",{text:k,from:"the window",ws:g.workspace.id,client:xr({navigator,screen,devicePixelRatio,innerWidth,innerHeight,dark:Ce.value,mode:S.mode})}).then(u=>{if(n.value=!1,u.error){o.value=dt(u.error);return}l.value=u.issue||null,t.value="",r.value=u.reports||r.value}).catch(u=>{n.value=!1,o.value=[ce(u,{refused:"Not sent",unreachable:tt})]})};return J(()=>S.feedback,k=>{k&&(o.value=[],l.value=null,w().then(()=>_e(()=>{var u;return(u=s.value)==null?void 0:u.focus()})))}),(k,u)=>_(S).feedback?(i(),c("div",{key:0,class:"modal",role:"dialog","aria-modal":"true","aria-labelledby":"feedback-title",onClick:ee(f,["self"])},[a("div",Sr,[a("div",Cr,[u[1]||(u[1]=a("h3",{id:"feedback-title",class:"modal__title"},"Report a problem or a wish",-1)),a("button",{type:"button",class:"btn btn--tonal","aria-disabled":n.value,onClick:p},v(n.value?"Composing…":"Send"),9,Er),a("button",{type:"button",class:"btn",onClick:f},"Close")]),o.value.length?(i(),c("div",Rr,v(o.value.join(" · ")),1)):x("",!0),a("div",Ar,[be(a("textarea",{ref_key:"field",ref:s,"onUpdate:modelValue":u[0]||(u[0]=h=>t.value=h),class:"input feedback-sheet__text",rows:"5",placeholder:"Describe the problem or the wish in your own words. Cmd+Enter sends.",autocomplete:"off",onKeydown:[ge(ee(p,["meta","prevent"]),["enter"]),ge(ee(p,["ctrl","prevent"]),["enter"])]},null,40,Mr),[[$e,t.value]]),u[4]||(u[4]=a("p",{class:"feedback-sheet__note"}," Only what you write, the monitor version and a description of your system are sent: OS and processor type, Node version, how the monitor was installed, browser, screen and window size, language, time zone, light or dark, app or tab, and which kinds of source you use. ",-1)),l.value?(i(),c("p",Tr,[u[2]||(u[2]=G(" Filed as ",-1)),a("a",{href:d(l.value.identifier),target:"_blank",rel:"noopener"},v(l.value.identifier),9,zr),G(" · "+v(l.value.title),1)])):x("",!0),r.value.length?(i(),c("div",Ir,[u[3]||(u[3]=a("h4",{class:"sheet-form__heading"},"Your reports",-1)),(i(!0),c(W,null,X(r.value,h=>(i(),c("div",{key:h.id,class:"feedback-sheet__report"},[a("a",{href:d(h.id),target:"_blank",rel:"noopener"},v(h.id),9,Or),a("span",Br,v(h.title),1),a("span",{class:L(["pill",_(Re)("pill",_(on)(h.outcome))])},v(h.state||"filed"),3),a("span",Dr,v(_(re)(h.changed_at||h.filed_at)),1)]))),128))])):x("",!0)])])])):x("",!0)}}),Pr=j(Nr,[["__scopeId","data-v-a76221de"]]),Fr={class:"field-row"},Vr={class:"field-row__label"},Wr={key:0,class:"field-row__check"},Ur=["checked"],Hr=["aria-invalid","value"],Lr={key:0,value:""},qr=["value"],jr=["value"],Yr={key:3,class:"field-row__inline"},Kr=["value"],Xr=["value"],Gr=["aria-invalid","value"],Zr=["aria-invalid","placeholder","value"],Jr={key:6,class:"field-row__error",role:"alert"},Qr={key:7,class:"field-row__hint"},ec=q({__name:"FieldRow",props:et({spec:{},placeholder:{default:""},hint:{default:""},error:{default:""}},{modelValue:{type:[String,Array,Boolean]},modelModifiers:{}}),emits:et(["secret"],["update:modelValue"]),setup(e,{emit:t}){const s=e,n=t,o=Vt(e,"modelValue"),l=/^#[0-9a-f]{6}$/i,r=()=>String(o.value??""),d=()=>o.value||[],w=h=>{o.value=h},f=()=>o.value??s.spec.default??!1,p=h=>{o.value=h===(s.spec.default??!1)?void 0:h},k=h=>h.target.value,u=h=>w(h.split(",").map(m=>m.trim()).filter(Boolean));return(h,m)=>(i(),c("div",Fr,[a("label",Vr,v(e.spec.label)+v(e.spec.required?" *":""),1),e.spec.boolean?(i(),c("label",Wr,[a("input",{type:"checkbox",checked:f(),onChange:m[0]||(m[0]=R=>p(R.target.checked))},null,40,Ur),G(" "+v(e.hint||e.spec.hint),1)])):e.spec.choices?(i(),c("select",{key:1,class:"input","aria-invalid":!!e.error,value:r(),onChange:m[1]||(m[1]=R=>w(k(R)))},[!e.spec.required&&!e.spec.choices.includes(r())?(i(),c("option",Lr,"(default)")):x("",!0),r()&&!e.spec.choices.includes(r())?(i(),c("option",{key:1,value:r()},v(r()),9,qr)):x("",!0),(i(!0),c(W,null,X(e.spec.choices,R=>(i(),c("option",{key:R,value:R},v(R),9,jr))),128))],40,Hr)):e.spec.secret?(i(),c("input",{key:2,class:"input",type:"password",placeholder:"paste to replace",autocomplete:"off",onInput:m[2]||(m[2]=R=>n("secret",e.spec.key,k(R)))},null,32)):e.spec.colour?(i(),c("div",Yr,[a("input",{class:"input field-row__colour",type:"color",value:l.test(r())?r():"#888888",onInput:m[3]||(m[3]=R=>w(k(R)))},null,40,Kr),a("input",{class:"input",type:"text",placeholder:"#rrggbb",value:r(),onInput:m[4]||(m[4]=R=>w(k(R)))},null,40,Xr),a("button",{type:"button",class:"btn",onClick:m[5]||(m[5]=R=>w(""))},"None")])):e.spec.list?(i(),c("input",{key:4,class:"input",type:"text","aria-invalid":!!e.error,value:d().join(", "),onInput:m[6]||(m[6]=R=>u(k(R)))},null,40,Gr)):(i(),c("input",{key:5,class:"input",type:"text","aria-invalid":!!e.error,placeholder:e.placeholder,value:r(),onInput:m[7]||(m[7]=R=>w(k(R)))},null,40,Zr)),e.error?(i(),c("small",Jr,v(e.error),1)):x("",!0),!e.spec.boolean&&(e.hint||e.spec.hint)?(i(),c("small",Qr,v(e.hint||e.spec.hint),1)):x("",!0)]))}}),he=j(ec,[["__scopeId","data-v-33714840"]]),tc={class:"modal__card settings-sheet__card"},sc={class:"modal__head"},nc={class:"modal__meta"},oc={key:0,class:"settings-sheet__dirty"},ac={key:0,class:"settings-sheet__confirm",role:"alertdialog"},lc={class:"settings-sheet__confirm-text"},ic={key:1,class:"alert settings-sheet__alert",role:"alert"},rc={key:2,class:"alert settings-sheet__alert"},cc={key:3,class:"settings-sheet__body"},dc={class:"settings-sheet__list"},uc=["aria-current","onClick"],hc={class:"sheet-form"},pc={key:0,class:"empty"},_c={ref:"connectors-head",class:"sheet-form__heading"},fc={class:"settings-sheet__connector-head"},vc={class:"settings-sheet__connector-name"},mc=["onClick"],gc={class:"settings-sheet__actions"},yc=["onClick"],wc={key:0,class:"settings-sheet__rules"},kc={class:"settings-sheet__rule-when"},bc={class:"settings-sheet__rule-then"},$c={key:1,class:"empty"},xc=q({__name:"SettingsSheet",setup(e){const t=B([]),s=B(0),n=B([]),o=B({workspace:[],theme:[],rules:[],statuses:[]}),l=B(""),r=B([]),d=B({}),w=new Map,f=B({}),p=B({}),k=B({}),u=Ue("connectors-head"),h=new Map,m=B(0),R=B(""),P=B(null),Y=B(""),$=E(()=>S.settings&&!Y.value&&(m.value>0||Rt(t.value)!==R.value)),y=M=>d.value[`workspaces[${s.value}].${M}`]||"",C=E(()=>{const M=b.value&&w.get(Ie(b.value));return M&&b.value&&M!==b.value.id?`Its to-dos and marks stay under the old id "${M}"; they do not follow the rename.`:""}),A={key:"id",label:"Source id"},D={key:"label",label:"Label"},b=E(()=>t.value[s.value]),F=E(()=>(b.value&&p.value[b.value.id]||[]).map(M=>On(M,f.value))),U=E(()=>b.value&&k.value[b.value.id]||[]),se=M=>n.value.find(I=>I.type===M.type)||{type:M.type,label:M.type,fields:[]},z=E(()=>t.value.map((M,I)=>({uid:Ie(M),label:M.name||M.id||"Workspace "+(I+1)}))),V=E(()=>{var M;return(((M=b.value)==null?void 0:M.connectors)||[]).map(I=>({entry:I,uid:Ie(I),spec:se(I)}))}),O=M=>{var T;const I=(T=g.workspaces.find(Z=>Z.id===M))==null?void 0:T.theme_seed;return I?`empty: ${I}, derived from the workspace id`:"empty derives one from the workspace id"},Q=(M,I)=>M[I],Ye=(M,I,T)=>{h.set(M,Object.assign(h.get(M)||{},{[I]:T})),m.value+=1},ys=(M,I,T)=>I==="id"?M.id=String(T??""):ue(M,I,T),ws=()=>{t.value.push(Ct({id:"new-"+(t.value.length+1),name:"New workspace"})),s.value=t.value.length-1},ks=()=>{t.value.splice(s.value,1),s.value=Math.max(0,s.value-1)},bs=()=>{b.value&&(P.value={text:`Delete ${b.value.name||b.value.id}? Its to-dos and marks stay on disk.`,yes:"Delete",no:"Keep",run:ks})},$s=M=>{var I;return(I=b.value)==null?void 0:I.connectors.push({type:M.type})},xs=M=>{b.value&&(h.delete(b.value.connectors[M]),b.value.connectors.splice(M,1))},Ss=M=>{if(!b.value)return;const I=se(b.value.connectors[M]).label;P.value={text:`Remove the ${I} source from ${b.value.name||b.value.id}?`,yes:"Remove",no:"Keep",run:()=>xs(M)}},Cs=()=>Ee("/api/config").then(M=>{Y.value="",t.value=(M.workspaces||[]).map(Ct),n.value=M.connectors||[],o.value=M.fields,h.clear(),m.value=0,P.value=null,s.value=Math.max(0,t.value.findIndex(I=>I.id===g.workspace.id)),l.value=M.config_file||"",r.value=M.problems||[],d.value={},w.clear(),t.value.forEach(I=>w.set(Ie(I),I.id)),f.value=M.facts||{},p.value=M.tables||{},k.value=M.table_warnings||{},R.value=Rt(t.value)}).catch(()=>{Y.value=xe+"; settings cannot be loaded."}).then(_e).then(()=>{var M;S.settingsAt==="connectors"&&((M=u.value)==null||M.scrollIntoView({block:"start"})),S.settingsAt=""}),Ke=()=>{S.settings=!1},mt=()=>{P.value={text:"Discard changes?",yes:"Discard",no:"Keep editing",run:Ke}},gt=()=>$.value?mt():Ke(),yt=M=>{const I=P.value;P.value=null,M&&(I==null||I.run())},Es=async()=>{try{const M=await ie("/api/config",{workspaces:t.value.map(I=>kn(I)),secrets:$n(t.value,h)});if(M.error){const I=an(M.error);d.value=Object.fromEntries(I.filter(T=>T.field!=="workspaces").map(T=>[T.field,T.description])),r.value=I.length?I.filter(T=>T.field==="workspaces").map(T=>T.description):dt(M.error),I.length&&!r.value.length&&(r.value=["Fix the marked fields; nothing was saved."]);return}Ke(),as()}catch(M){r.value=[ce(M,{unreachable:xe+"; your changes are kept, save again."})]}};return J($,M=>{S.settingsDirty=M},{immediate:!0}),J(()=>S.settingsAsk,M=>{M&&(S.settingsAsk=!1,mt())}),J(()=>S.settings,M=>{M&&Cs()}),(M,I)=>_(S).settings?(i(),c("div",{key:0,class:"modal",role:"dialog","aria-modal":"true","aria-labelledby":"settings-title",onClick:ee(gt,["self"])},[a("div",tc,[a("div",sc,[I[2]||(I[2]=a("h3",{id:"settings-title",class:"modal__title"},"Settings",-1)),a("span",nc,v(l.value),1),$.value?(i(),c("span",oc,"Unsaved changes")):x("",!0),Y.value?x("",!0):(i(),c("button",{key:1,type:"button",class:"btn btn--tonal",onClick:Es},"Save")),a("button",{type:"button",class:"btn",onClick:gt},"Close")]),P.value?(i(),c("div",ac,[a("span",lc,v(P.value.text),1),a("button",{type:"button",class:"btn btn--danger",onClick:I[0]||(I[0]=T=>yt(!0))},v(P.value.yes),1),a("button",{type:"button",class:"btn",onClick:I[1]||(I[1]=T=>yt(!1))},v(P.value.no),1)])):x("",!0),Y.value?(i(),c("div",ic,v(Y.value),1)):r.value.length?(i(),c("div",rc,v(r.value.join(" · ")),1)):x("",!0),Y.value?x("",!0):(i(),c("div",cc,[a("ul",dc,[(i(!0),c(W,null,X(z.value,(T,Z)=>(i(),c("li",{key:T.uid},[a("button",{type:"button",class:"settings-sheet__workspace","aria-current":Z===s.value,onClick:Me=>s.value=Z},v(T.label),9,uc)]))),128)),a("li",null,[a("button",{type:"button",class:"settings-sheet__workspace settings-sheet__workspace--add",onClick:ws}," + Add workspace ")])]),a("div",hc,[b.value?(i(),c(W,{key:1},[I[3]||(I[3]=a("h4",{class:"sheet-form__heading"},"Workspace",-1)),(i(!0),c(W,null,X(o.value.workspace,T=>(i(),K(he,{key:T.key,spec:T,hint:T.key==="id"?C.value:"",error:y(T.key),"model-value":Q(b.value,T.key),"onUpdate:modelValue":Z=>ys(b.value,T.key,Z)},null,8,["spec","hint","error","model-value","onUpdate:modelValue"]))),128)),I[4]||(I[4]=a("h4",{class:"sheet-form__heading"},"Theme",-1)),(i(!0),c(W,null,X(o.value.theme,T=>{var Z;return i(),K(he,{key:T.key,spec:T,hint:T.key==="seed"&&!((Z=b.value.theme)!=null&&Z.seed)?O(b.value.id):"","model-value":Q(b.value.theme,T.key),"onUpdate:modelValue":Me=>_(ue)(b.value.theme,T.key,Me)},null,8,["spec","hint","model-value","onUpdate:modelValue"])}),128)),a("h4",_c,"Sources",512),(i(!0),c(W,null,X(V.value,({entry:T,spec:Z,uid:Me},wt)=>(i(),c("div",{key:Me,class:"settings-sheet__connector"},[a("div",fc,[a("strong",vc,v(Z.label),1),a("button",{type:"button",class:"btn btn--danger",onClick:oe=>Ss(wt)}," Remove ",8,mc)]),N(he,{spec:A,placeholder:Z.type,hint:"only needed when one type appears twice","model-value":Q(T,"id"),"onUpdate:modelValue":oe=>_(ue)(T,"id",oe)},null,8,["placeholder","model-value","onUpdate:modelValue"]),N(he,{spec:D,placeholder:Z.label,hint:"its name in the feed","model-value":Q(T,"label"),"onUpdate:modelValue":oe=>_(ue)(T,"label",oe)},null,8,["placeholder","model-value","onUpdate:modelValue"]),(i(!0),c(W,null,X(Z.fields,oe=>(i(),K(he,{key:oe.key,spec:oe,error:y("connectors["+wt+"]."+oe.key),"model-value":Q(T,oe.key),"onUpdate:modelValue":Xe=>_(ue)(T,oe.key,Xe),onSecret:(Xe,Rs)=>Ye(T,Xe,Rs)},null,8,["spec","error","model-value","onUpdate:modelValue","onSecret"]))),128))]))),128)),a("div",gc,[(i(!0),c(W,null,X(n.value,T=>(i(),c("button",{key:T.type,type:"button",class:"btn",onClick:Z=>$s(T)}," + Add "+v(T.label)+" source ",9,yc))),128))]),I[5]||(I[5]=a("h4",{class:"sheet-form__heading"},"Rules",-1)),(i(!0),c(W,null,X(o.value.rules,T=>(i(),K(he,{key:T.key,spec:T,error:y("rules."+T.key),"model-value":Q(b.value.rules,T.key),"onUpdate:modelValue":Z=>_(ue)(b.value.rules,T.key,Z)},null,8,["spec","error","model-value","onUpdate:modelValue"]))),128)),(i(!0),c(W,null,X(o.value.statuses,T=>(i(),K(he,{key:T.key,spec:T,"model-value":Q(b.value.rules.statuses,T.key),"onUpdate:modelValue":Z=>_(ue)(b.value.rules.statuses,T.key,Z)},null,8,["spec","model-value","onUpdate:modelValue"]))),128)),I[6]||(I[6]=a("h4",{class:"sheet-form__heading"},"Whose turn table",-1)),I[7]||(I[7]=a("p",{class:"settings-sheet__rules-note"}," The rows in force, top to bottom: the first one that fits decides. Read-only here: ask Claude to change them. ",-1)),(i(!0),c(W,null,X(U.value,T=>(i(),c("p",{key:T,class:"settings-sheet__rules-warning"},v(T),1))),128)),F.value.length?(i(),c("ol",wc,[(i(!0),c(W,null,X(F.value,(T,Z)=>(i(),c("li",{key:Z,class:"settings-sheet__rule"},[a("span",kc,v(T.when),1),a("span",bc,v(T.then),1)]))),128))])):(i(),c("p",$c,"Save the workspace to see its rows.")),a("div",{class:"settings-sheet__actions"},[a("button",{type:"button",class:"btn btn--danger",onClick:bs}," Delete workspace ")])],64)):(i(),c("p",pc,"No workspaces yet. Add one on the left."))])]))])])):x("",!0)}}),Sc=j(xc,[["__scopeId","data-v-8253a01a"]]),Cc={class:"modal__meta"},Ec={key:0,class:"alert",role:"alert"},Rc={class:"whats-new__head"},Ac={class:"whats-new__name"},Mc={key:0,class:"whats-new__date"},Tc={key:1,class:"whats-new__tag whats-new__tag--running"},zc={key:2,class:"whats-new__tag"},Ic={key:1,class:"whats-new__empty"},Oc=q({__name:"WhatsNewSheet",setup(e){const{changelog:t,problem:s,unseen:n,load:o,markSeen:l}=_t(),r=B([]),d=()=>{S.whatsNew=!1};return J(()=>S.whatsNew,async w=>{w&&(t.value||await o(),r.value=n.value.map(f=>f.version),l())}),(w,f)=>_(S).whatsNew?(i(),K(gs,{key:0,title:"What's new","label-id":"whats-new-title",flush:"",onClose:d},Wt({default:te(()=>{var p;return[_(s)?(i(),c("div",Ec,v(_(s)),1)):x("",!0),(i(!0),c(W,null,X((p=_(t))==null?void 0:p.versions,k=>{var u;return i(),c("article",{key:k.version,class:"whats-new__version"},[a("header",Rc,[a("h4",Ac,v(k.version),1),k.date?(i(),c("span",Mc,v(k.date),1)):x("",!0),k.version===((u=_(t))==null?void 0:u.current)?(i(),c("span",Tc,"Running")):x("",!0),r.value.includes(k.version)?(i(),c("span",zc,"New")):x("",!0)]),k.sections.length?(i(),K(ms,{key:0,source:_(fo)(k)},null,8,["source"])):(i(),c("p",Ic,"No notes for this version."))])}),128))]}),_:2},[_(t)?{name:"head",fn:te(()=>[a("span",Cc,"Running "+v(_(t).current),1)]),key:"0"}:void 0]),1024)):x("",!0)}}),Bc=j(Oc,[["__scopeId","data-v-78394e08"]]),Dc={class:"app__shell"},Nc=["inert"],Pc={id:"wt",class:"dashboard dashboard--fit"},Fc=["inert"],Vc={class:"dashboard__main"},Wc=q({__name:"App",setup(e){const t=E(()=>!!g.workspace.id&&!g.workspace.connectors.length),{size:s}=pt(()=>`${g.workspace.id}:feed`),n=E(()=>s.value===null?void 0:{"--feed-width":s.value+"px"}),o=_t(),l=E(()=>os.value!==null);io(l),ro(l),J(Ze,vn,{flush:"post"});const r={light:{fill:"#d8e2ff",ink:"#001a41",dot:"#2c5697"},dark:{fill:"#2b4678",ink:"#d8e2ff",dot:"#adc6ff"}},d=E(()=>{const{id:w,name:f}=g.workspace;if(!w)return null;const p=Ze.value,k=r[Ce.value?"dark":"light"],u={fill:p["--md-primary-container"]||k.fill,ink:p["--md-on-primary-container"]||k.ink,dot:p["--md-primary"]||k.dot};return"data:image/svg+xml,"+encodeURIComponent(so(rs({id:w,name:f},rt),u))});return Ks(d),ct("Escape",Vn,{target:document}),it(()=>{Fn(),o.load()}),(w,f)=>(i(),c("div",{class:"app",style:Ne(_(Ze))},[N(zo,{inert:l.value,onSettings:f[0]||(f[0]=p=>_(S).settings=!0),onWhatsNew:f[1]||(f[1]=p=>_(S).whatsNew=!0)},null,8,["inert"]),a("div",Dc,[N(ia,{inert:l.value,onReport:f[2]||(f[2]=p=>_(S).feedback=!0)},null,8,["inert"]),_(At).length?(i(),c("div",{key:0,class:"alert",inert:l.value},[G(v(_(At).join(" · "))+" ",1),a("button",{type:"button",class:"alert__action",onClick:f[3]||(f[3]=p=>_(ns)())},"Open Settings")],8,Nc)):x("",!0),a("div",Pc,[f[5]||(f[5]=a("canvas",{id:"backdrop",class:"dashboard__backdrop","aria-hidden":"true"},null,-1)),N(Ea,{inert:l.value},null,8,["inert"]),t.value?(i(),K(Ki,{key:0,inert:l.value},null,8,["inert"])):(i(),c("div",{key:1,class:"dashboard__layout",style:Ne(n.value),inert:l.value},[a("div",Vc,[N(Rl,{class:"dashboard__move"}),N(Hl,{class:"dashboard__todo"}),N(ti,{class:"dashboard__waiting"})]),N(Li,{class:"dashboard__feed",onOpen:f[4]||(f[4]=p=>_(S).modal=p)})],12,Fc)),N(Pr),N(Sc),N(Bc),N(lr),N(wr)])])],4))}}),Uc=j(Wc,[["__scopeId","data-v-580c2b4a"]]);Is(Uc).mount("#app");qn();yn();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as v,l as f,o as s,e as o,j as a,F as c,i as t,h as k,u as p,m as u,k as h,f as w,b as g,_ as y,K as x}from"./_plugin-vue_export-helper-DeQjDyQ9.js";import{g as N,S as b,m as R,u as C,k as d}from"./bem-
|
|
1
|
+
import{d as v,l as f,o as s,e as o,j as a,F as c,i as t,h as k,u as p,m as u,k as h,f as w,b as g,_ as y,K as x}from"./_plugin-vue_export-helper-DeQjDyQ9.js";import{g as N,S as b,m as R,u as C,k as d}from"./bem-CST_YFrc.js";const B={class:"app report-page"},S={key:0,class:"report-page__note"},T={class:"report-page__head"},V={class:"report-page__id"},E={class:"report-page__title"},L={class:"report-page__meta"},P={class:"report-page__section"},W={class:"report-page__text"},A={class:"report-page__section"},D={key:0,class:"report-page__unanswered"},F={key:1,class:"empty"},I={class:"report-page__answer-meta"},U={class:"report-page__text"},j=v({__name:"ReportPage",setup(J){const n=new URLSearchParams(location.search).get("id")||"",e=g(null),i=g(n?"Loading…":"No report id in the link.");return f(()=>{n&&(document.title=n+" · Your report · Whose Turn",N("/api/feedback?id="+encodeURIComponent(n)).then(l=>{e.value=l.report||null,i.value=l.report?"":"No report "+n+" was filed from this machine."}).catch(()=>{i.value=b+"; reload this page once it is back."}))}),(l,r)=>(s(),o("main",B,[e.value?(s(),o(c,{key:1},[t("header",T,[t("span",V,a(e.value.id),1),t("h1",E,a(e.value.title),1),t("span",{class:k(["pill",p(R)("pill",p(C)(e.value.outcome))])},a(e.value.state||"filed, not yet seen"),3)]),t("p",L,[u(a(e.value.kind||"report")+" · filed "+a(p(d)(e.value.filed_at)),1),e.value.changed_at?(s(),o(c,{key:0},[u(" · last change "+a(p(d)(e.value.changed_at)),1)],64)):h("",!0)]),t("section",P,[r[0]||(r[0]=t("h2",{class:"report-page__heading"},"What you reported",-1)),t("p",W,a(e.value.body||"(no text kept)"),1)]),t("section",A,[r[1]||(r[1]=t("h2",{class:"report-page__heading"},"Answers",-1)),e.value.unanswered?(s(),o("p",D," Closed without an answer. The maintainer owes you a reason; this page will show it once it is written. ")):e.value.answers.length?h("",!0):(s(),o("p",F,"No answer yet.")),(s(!0),o(c,null,w(e.value.answers,(_,m)=>(s(),o("article",{key:m,class:"report-page__answer"},[t("p",I,a(_.by||"maintainer")+" · "+a(p(d)(_.at)),1),t("p",U,a(_.text),1)]))),128))])],64)):(s(),o("p",S,a(i.value),1)),r[2]||(r[2]=t("a",{class:"report-page__back",href:"/"},"Back to the window",-1))]))}}),z=y(j,[["__scopeId","data-v-16ea9dee"]]);x(z).mount("#app");
|
package/dist/index.html
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
<title>Whose Turn</title>
|
|
7
7
|
<script src="/vendor/popper.min.js"></script>
|
|
8
8
|
<script src="/vendor/tippy-bundle.umd.min.js"></script>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-DsQ_5Y-x.js"></script>
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-DeQjDyQ9.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/scheme-BdlolNvz.js">
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/bem-
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/bem-CST_YFrc.js">
|
|
13
13
|
<link rel="stylesheet" crossorigin href="/assets/_plugin-vue_export-helper-aQHODzfZ.css">
|
|
14
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CEB3_bQv.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body class="page">
|
|
17
17
|
<div id="app" class="page__mount"></div>
|
package/dist/report.html
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>Your report · Whose Turn</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/report-
|
|
7
|
+
<script type="module" crossorigin src="/assets/report-Bar3ULi6.js"></script>
|
|
8
8
|
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-DeQjDyQ9.js">
|
|
9
|
-
<link rel="modulepreload" crossorigin href="/assets/bem-
|
|
9
|
+
<link rel="modulepreload" crossorigin href="/assets/bem-CST_YFrc.js">
|
|
10
10
|
<link rel="stylesheet" crossorigin href="/assets/_plugin-vue_export-helper-aQHODzfZ.css">
|
|
11
11
|
<link rel="stylesheet" crossorigin href="/assets/report-D7II0AfP.css">
|
|
12
12
|
</head>
|