Compare commits

...
8 Commits
Author SHA1 Message Date
jason.woltje 73df1a687f docs: BUILD-LOG for organizations landings #1876-#1881 (#1873) 2026-11-09 14:00:54 -06:00
jason.woltje fdd6658a65 fix(webui): refresh the Settings bus control on every org list read
E2E5 review P2. An open Settings page kept Done after the bus died
because only opening the organization reread bus health. display.js
now announces each fresh list read, org-create.js redraws the setup
steps when the selected org's bus state flips (choices kept, no draft
guard), and app.js reads the list before bus-status so a failed
bus-status read no longer skips it. Regression: healthy, Refresh down
shows Start, Refresh up hides it; red on 8a8edc44b.
2026-11-09 13:53:19 -06:00
jason.woltje 8a8edc44b6 Merge refactor 2bed0aebe into E2E5 fixes 2026-11-09 13:30:24 -06:00
jason.woltje d6eff452e3 fix(webui): recover archived organizations and console controls 2026-11-09 13:29:23 -06:00
jason.woltje 2bed0aebeb Merge refactor bad760ce0 into U0 samples 2026-11-09 13:26:39 -06:00
jason.woltje af674e14c1 docs(design): keep the WebUI four-tile logo in the U0 samples; record U0 approval (#1873)
Jason approved the U0 screens on 11-09 with one change: keep the temporary
logo the site already uses. The samples drew the design system's Relay
placeholder; they now draw the WebUI's four-tile mark with the same fills
as processing.css. The direction doc records the approval verbatim, the
deferred Montage name, and the open-question defaults phase U takes.
2026-11-09 13:26:39 -06:00
jason.woltje 1cc09a1cad docs(design): match U0 org dashboard sessions to the main dashboard count (#1873)
The org dashboard listed an idle chief as a session, so Distinctly
Digital showed four sessions there and three on the main dashboard.
The chief has no running session; it stays on the agents screen.
2026-11-09 12:38:03 -06:00
jason.woltje 36c8260d7d docs(design): add U0 unified workspace samples (#1873)
Eight static screens for PRD 1.20 phase U, for Jason's approval
before U1-U5 are built: sidebar with collapsible Organizations and
org marks, cross-org dashboard, org dashboard with docs, KPIs,
metrics, sessions and a settings index, projects across orgs, one
inbox, Kanban and list tasks with tracker badges, side-by-side panes,
and agents at root, org and project level.

Mock data only: three orgs (Home, Distinctly Digital, Forge), ten
projects, no real names or credentials. workspace.css imports
tokens.css and marks each extension EXT 1-10. render.mjs serves the
samples on 127.0.0.1 port 0 and renders 32 PNGs at 1440x900 and
390x844, light and dark, failing on script errors, failed requests,
sideways scroll or unloaded fonts. No WebUI code changes.
2026-11-09 12:36:28 -06:00
24 changed files with 1576 additions and 17 deletions

No files matched your search

+2
View File
@@ -6339,3 +6339,5 @@ R5 quote fallback room (#797 D3, 2026-11-06, MVP3 lead): r4 review P2 found that
2026-11-07 UTC | Organizations S1 — implementation evidence | Organization-root bus and launcher paths, guarded lifecycle and Console launch/stop were implemented locally. Focused Node 26 tests and host regressions passed; the fresh-organization notifier choice, shared-proxy S2 integration, and remaining instance-root consumers are not complete. Exact commands, inventory, failures and boundaries: /mnt/storage/scratch/mosaic-lead/uidev/org-release/report-s1.md. No push or deployment. Gitea issue creation was excluded by the no-network and no-external-communication limits.
2026-11-09 UTC | Unified workspace (#1873) — direction recorded | Before: the 11-07 rulings had one Console switch between organizations from Settings, tasks only in each org queue, and an agent bound to one organization (REQ-USER-1). After: Jason's 11-09 direction and answers recorded in docs/plans/2026-11-09_unified-workspace-owner-direction.md (all orgs visible at once, per-org task stores with a Vikunja option and an aggregated Kanban, root/org/project agents with one cross-org assistant, system type plug-ins, self-service restart and model switch). PRD 1.20 draft 1 written for his exact-text approval; the PRD itself is unchanged. The unpushed 11-07 rulings record (ad8140065) lands with it.
2026-11-09 UTC | Organizations friction round, landings #1876-#1881 (#1873) | Before: refactor 00ef0bd30. A Console launched by a relative path showed Request status unavailable, the overview printed the north star as raw markdown, packages/business and the business command spellings were the only names, Quick Setup ended with no route to a north star, an archived org could not be restored from a fresh page, and a dead bus after setup had no browser control. After, each through one Codex Sol xhigh review round plus a lead or builder fix round: #1876 re-execs a relative Console launch with its absolute script path (build 744753d7e, reproduced 121/0; review APPROVE 0/0/1). #1877 F1 renders the north star as sanitized markdown with a short preview (review APPROVE 0/0/1; live retest 4/0 twice). #1878 rename stage B moves packages/business to packages/organization and adds the org command spellings, keeping the business ones and their messages (builder 6828/6, see report; review CHANGES 0/1/0, fixed in e19db4009). #1879 F2 adds the onboarding interview after Quick Setup and on the project page, with human-only north-star approval (`mosaic project north-star --approve`) and no new agent grant (builder 411/0; review CHANGES 0/1/1: a refused start left its button disabled, fixed in 5937a977f along with the P3 stale approval capability). #1880 lands the U0 unified workspace samples, approved by Jason with the four-tile logo kept; the module names stay undecided at his request. #1881 E2E round 5 fixes restore from a fresh page, show an owner bus Start whenever the org list reads the bus down, say room changes are unavailable on org Consoles and recover the composer (builder 258/0; review CHANGES 0/1/0, 231/0: Settings kept Done after the bus died because only opening the org reread health). Lead fix fdd6658a6: every org list read is announced and the open setup redraws on a flip, and app.js reads the list before bus-status so a failed bus-status read cannot skip it; regression red on 8a8edc44b, 18 touched webui files 199/0 (Node 26.12.1, one file at a time). uiorg redeployed at fdd6658a6, 19:53Z. Open follow-ups: a down bus offers both the F3 banner Restart and the Settings Start, focus can move when setup redraws, and a Console stop also stops the org buses it started. Reports: /mnt/storage/scratch/mosaic-lead/reports/org-{reqget-2,f1,rename-b,f2,u0-design,e2e5}-*.md.
@@ -0,0 +1,98 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Sidebar · U0 sample</title>
<link rel="stylesheet" href="workspace.css">
</head>
<body>
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false"><symbol id="i-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol><symbol id="i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 10.5 12 4l8 6.5"/><path d="M6 9v10.5h12V9"/><path d="M10 19.5v-5h4v5"/></symbol><symbol id="i-folder" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 6.5a1 1 0 0 1 1-1h4.5l2 2h8.5a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1h-15a1 1 0 0 1-1-1z"/></symbol><symbol id="i-columns" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M12 4.5v15"/></symbol><symbol id="i-split" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M13 4.5v15M16.75 10.5v3M15.25 12h3"/></symbol><symbol id="i-restart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3"/><path d="M19.5 4.5v4h-4"/></symbol><symbol id="i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></symbol><symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/></symbol><symbol id="i-doc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 3.5h7l4 4v13h-11z"/><path d="M13.5 3.5v4h4M9 12h6M9 15.5h6"/></symbol></svg>
<div class="app drawer">
<header class="cmdbar">
<button class="menu" aria-label="Close navigation" aria-expanded="true"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-close"/></svg></button>
<a class="mk" href="02-dashboard.html"><svg class="mosaic-logo" viewBox="0 0 36 36" aria-hidden="true"><rect x="3" y="12" width="13" height="10" rx="2"/><rect x="18" y="3" width="13" height="12" rx="2"/><rect x="3" y="24" width="13" height="10" rx="2"/><rect x="18" y="17" width="13" height="12" rx="2"/></svg><span>Mosaic Stack</span></a>
<span class="sim" title="Static design sample">U0 sample</span>
<button class="cmdk"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-search"/></svg><span>Go to an org, project, task or decision</span><kbd>Ctrl K</kbd></button>
<div class="fresh"><span class="wide">Read <b>3 of 3</b> organization buses · 4 s ago</span><span class="me" title="Operator">OP</span></div>
</header>
<nav class="side" aria-label="Workspace">
<a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a>
<a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a>
<a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a>
<a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a>
<a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a>
<a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a>
<a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Organizations</span><span class="n">3</span><span class="add" title="New organization"><svg class="i sm" aria-hidden="true"><use href="#i-plus"/></svg></span></div>
<a class="nav org-row" href="03-org-dashboard.html" aria-current="page"><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="t">Distinctly Digital</span><span class="ic" title="Business"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="t">Forge</span><span class="ic" title="Coding"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-term"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="home" aria-hidden="true">HM</span><span class="t">Home</span><span class="ic" title="Personal"><svg class="i sm" aria-hidden="true"><use href="#i-home"/></svg></span></a>
</div>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Projects</span><span class="seg xs" role="group" aria-label="Project layout"><span aria-pressed="true">By org</span><span aria-pressed="false">Flat</span></span></div>
<div class="pgroup" data-org="ddigital"><div class="pgroup-h"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span>Distinctly Digital</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Spring launch</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">The Lantern Coast</span><span class="dot s-waiting" title="waiting"><b aria-hidden="true">◐</b><span class="sr">waiting</span></span></a><a class="nav proj" href="#"><span class="t">Brand refresh</span></a><a class="nav proj" href="#"><span class="t">Monthly newsletter</span></a></div></div>
<div class="pgroup" data-org="forge"><div class="pgroup-h"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span>Forge</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">API gateway</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">Web app</span><span class="dot s-error" title="error"><b aria-hidden="true">▲</b><span class="sr">error</span></span></a><a class="nav proj" href="#"><span class="t">CLI tools</span><span class="n">paused</span></a></div></div>
<div class="pgroup" data-org="home"><div class="pgroup-h"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span>Home</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Household admin</span><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span></a><a class="nav proj" href="#"><span class="t">Garden plan</span></a><a class="nav proj" href="#"><span class="t">Trip planning 2027</span><span class="n">paused</span></a></div></div>
</div>
<div class="foot"><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-settings"/></svg><span class="t">Settings</span></a></div>
</nav>
<nav class="strip" aria-label="Sections"><a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a><a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a><a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a><a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a><a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a><a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a></nav>
<main class="main ">
<div class="crumb">Shell</div>
<div class="vh"><h1>Sidebar</h1><p class="sub">Every organization stays in view. There is no organization switcher: selecting an organization opens its dashboard, and its projects sit in the group below.</p></div>
<div class="specimen">
<figure>
<div class="mini">
<div class="grp-h" aria-expanded="false"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Organizations</span><span class="n">3</span></div>
<div class="collapsed-marks"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span class="av xs" data-org="home" aria-hidden="true">HM</span></div>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Projects</span><span class="seg xs" role="group" aria-label="Project layout"><span aria-pressed="true">By org</span><span aria-pressed="false">Flat</span></span></div>
<div class="pgroup" data-org="forge"><div class="pgroup-h"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span>Forge</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">API gateway</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">Web app</span><span class="dot s-error" title="error"><b aria-hidden="true">▲</b><span class="sr">error</span></span></a><a class="nav proj" href="#"><span class="t">CLI tools</span><span class="n">paused</span></a></div></div>
</div>
</div>
<figcaption>Organizations collapsed. The row keeps the count and the three marks, so nothing disappears from view.</figcaption>
</figure>
<figure>
<div class="mini"><div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Projects</span><span class="seg xs" role="group" aria-label="Project layout"><span aria-pressed="false">By org</span><span aria-pressed="true">Flat</span></span></div>
<a class="nav proj flat" href="#"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span class="t">API gateway</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a>
<a class="nav proj flat" href="#"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span class="t">Spring launch</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a>
<a class="nav proj flat" href="#"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span class="t">Web app</span><span class="dot s-error" title="error"><b aria-hidden="true">▲</b><span class="sr">error</span></span></a>
<a class="nav proj flat" href="#" aria-current="page"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span class="t">The Lantern Coast</span><span class="dot s-waiting" title="waiting"><b aria-hidden="true">◐</b><span class="sr">waiting</span></span></a>
<a class="nav proj flat" href="#"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span class="t">Household admin</span><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span></a>
<a class="nav proj flat" href="#"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span class="t">Brand refresh</span></a>
<a class="nav proj flat" href="#"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span class="t">Garden plan</span></a>
<a class="nav proj flat" href="#"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span class="t">Monthly newsletter</span></a>
<a class="nav proj flat" href="#"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span class="t">CLI tools</span><span class="n">paused</span></a>
<a class="nav proj flat" href="#"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span class="t">Trip planning 2027</span><span class="n">paused</span></a>
</div></div>
<figcaption>Projects flat, sorted by activity. Each row leads with its organization's mark.</figcaption>
</figure>
<figure>
<div class="mini">
<div class="grp-h"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Organization states</span></div>
<a class="nav org-row" href="03-org-dashboard.html" aria-current="page"><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="t">Distinctly Digital</span><span class="ic" title="Business"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="t">Forge</span><span class="dot s-offline"><b aria-hidden="true">○</b>bus not read</span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="home" aria-hidden="true">HM</span><span class="t">Home</span><span class="dot s-waiting"><b aria-hidden="true">◐</b>needs you</span></a>
</div>
<figcaption>Selected, bus unreachable, and an item waiting. Status is a symbol plus a word, never colour alone.</figcaption>
</figure>
</div>
<ol class="callouts">
<li><b>The org mark</b> is a tile in the organization's theme colour with its initials (or an uploaded image), always beside the name. The type icon on the right (business, coding, personal) is the third cue the owner asked for.</li>
<li><b>Plus</b> on the Organizations row starts the organization editor (11-07 ruling 6); it is tied to <code>mosaic org create ID --from FILE</code>.</li>
<li><b>Settings</b> no longer holds an "Existing organization" select. Organization settings open from each org dashboard.</li>
<li><b>Open state</b> of each group and the By org / Flat choice are remembered per viewer.</li>
<li><b>On a phone</b> the sidebar becomes a drawer behind the menu button, with the same groups.</li>
</ol>
</main>
</div>
</body>
</html>
@@ -0,0 +1,87 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Dashboard · U0 sample</title>
<link rel="stylesheet" href="workspace.css">
</head>
<body>
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false"><symbol id="i-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol><symbol id="i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 10.5 12 4l8 6.5"/><path d="M6 9v10.5h12V9"/><path d="M10 19.5v-5h4v5"/></symbol><symbol id="i-folder" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 6.5a1 1 0 0 1 1-1h4.5l2 2h8.5a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1h-15a1 1 0 0 1-1-1z"/></symbol><symbol id="i-columns" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M12 4.5v15"/></symbol><symbol id="i-split" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M13 4.5v15M16.75 10.5v3M15.25 12h3"/></symbol><symbol id="i-restart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3"/><path d="M19.5 4.5v4h-4"/></symbol><symbol id="i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></symbol><symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/></symbol><symbol id="i-doc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 3.5h7l4 4v13h-11z"/><path d="M13.5 3.5v4h4M9 12h6M9 15.5h6"/></symbol></svg>
<div class="app ">
<header class="cmdbar">
<button class="menu" aria-label="Open navigation" aria-expanded="false"><svg class="i" aria-hidden="true"><use href="#i-menu"/></svg></button>
<a class="mk" href="02-dashboard.html"><svg class="mosaic-logo" viewBox="0 0 36 36" aria-hidden="true"><rect x="3" y="12" width="13" height="10" rx="2"/><rect x="18" y="3" width="13" height="12" rx="2"/><rect x="3" y="24" width="13" height="10" rx="2"/><rect x="18" y="17" width="13" height="12" rx="2"/></svg><span>Mosaic Stack</span></a>
<span class="sim" title="Static design sample">U0 sample</span>
<button class="cmdk"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-search"/></svg><span>Go to an org, project, task or decision</span><kbd>Ctrl K</kbd></button>
<div class="fresh"><span class="wide">Read <b>3 of 3</b> organization buses · 4 s ago</span><span class="me" title="Operator">OP</span></div>
</header>
<nav class="side" aria-label="Workspace">
<a class="nav" href="02-dashboard.html" aria-current="page"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a>
<a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a>
<a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a>
<a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a>
<a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a>
<a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a>
<a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Organizations</span><span class="n">3</span><span class="add" title="New organization"><svg class="i sm" aria-hidden="true"><use href="#i-plus"/></svg></span></div>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="t">Distinctly Digital</span><span class="ic" title="Business"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="t">Forge</span><span class="ic" title="Coding"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-term"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="home" aria-hidden="true">HM</span><span class="t">Home</span><span class="ic" title="Personal"><svg class="i sm" aria-hidden="true"><use href="#i-home"/></svg></span></a>
</div>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Projects</span><span class="seg xs" role="group" aria-label="Project layout"><span aria-pressed="true">By org</span><span aria-pressed="false">Flat</span></span></div>
<div class="pgroup" data-org="ddigital"><div class="pgroup-h"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span>Distinctly Digital</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Spring launch</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">The Lantern Coast</span><span class="dot s-waiting" title="waiting"><b aria-hidden="true">◐</b><span class="sr">waiting</span></span></a><a class="nav proj" href="#"><span class="t">Brand refresh</span></a><a class="nav proj" href="#"><span class="t">Monthly newsletter</span></a></div></div>
<div class="pgroup" data-org="forge"><div class="pgroup-h"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span>Forge</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">API gateway</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">Web app</span><span class="dot s-error" title="error"><b aria-hidden="true">▲</b><span class="sr">error</span></span></a><a class="nav proj" href="#"><span class="t">CLI tools</span><span class="n">paused</span></a></div></div>
<div class="pgroup" data-org="home"><div class="pgroup-h"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span>Home</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Household admin</span><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span></a><a class="nav proj" href="#"><span class="t">Garden plan</span></a><a class="nav proj" href="#"><span class="t">Trip planning 2027</span><span class="n">paused</span></a></div></div>
</div>
<div class="foot"><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-settings"/></svg><span class="t">Settings</span></a></div>
</nav>
<nav class="strip" aria-label="Sections"><a class="nav" href="02-dashboard.html" aria-current="page"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a><a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a><a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a><a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a><a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a><a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a></nav>
<main class="main ">
<div class="vh"><h1>Dashboard</h1><div class="right"><span class="seg" role="group" aria-label="Period"><span aria-pressed="false">Today</span><span aria-pressed="true">7 days</span><span aria-pressed="false">30 days</span></span></div>
<p class="sub">All 3 organizations and 10 projects. Totals add up every organization you belong to; each tile breaks them down by organization.</p></div>
<div class="grid g5 keep2">
<div class="tile"><span class="label">Needs you</span><span class="big">3<small>items</small></span>
<div class="bar" aria-hidden="true"><i data-org="ddigital" style="flex:0.333"></i><i data-org="forge" style="flex:0.333"></i><i data-org="home" style="flex:0.333"></i></div>
<div class="by"><span><span class="av " data-org="ddigital" aria-hidden="true">DD</span>1</span><span><span class="av " data-org="forge" aria-hidden="true">FG</span>1</span><span><span class="av " data-org="home" aria-hidden="true">HM</span>1</span></div><span class="delta">oldest 52 min</span></div>
<div class="tile"><span class="label">Sessions</span><span class="big">7<small>4 working</small></span>
<div class="bar" aria-hidden="true"><i data-org="ddigital" style="flex:0.429"></i><i data-org="forge" style="flex:0.286"></i><i data-org="home" style="flex:0.143"></i><i style="background:var(--muted);flex:0.143"></i></div>
<div class="by"><span><span class="av " data-org="ddigital" aria-hidden="true">DD</span>3</span><span><span class="av " data-org="forge" aria-hidden="true">FG</span>2</span><span><span class="av " data-org="home" aria-hidden="true">HM</span>1</span><span><span class="av all " aria-hidden="true" title="Assistant, all organizations"><svg class="mosaic-logo" viewBox="0 0 36 36" style="width:70%;height:auto" aria-hidden="true"><rect x="3" y="12" width="13" height="10" rx="2"/><rect x="18" y="3" width="13" height="12" rx="2"/><rect x="3" y="24" width="13" height="10" rx="2"/><rect x="18" y="17" width="13" height="12" rx="2"/></svg></span>1</span></div><span class="delta">1 waiting · 1 error · 1 idle</span></div>
<div class="tile"><span class="label">Open tasks</span><span class="big">10</span>
<div class="bar" aria-hidden="true"><i data-org="ddigital" style="flex:0.500"></i><i data-org="forge" style="flex:0.300"></i><i data-org="home" style="flex:0.200"></i></div>
<div class="by"><span><span class="av " data-org="ddigital" aria-hidden="true">DD</span>5</span><span><span class="av " data-org="forge" aria-hidden="true">FG</span>3</span><span><span class="av " data-org="home" aria-hidden="true">HM</span>2</span></div><span class="delta"><b>2</b> done this week</span></div>
<div class="tile"><span class="label">Projects</span><span class="big">10<small>8 active</small></span>
<div class="bar" aria-hidden="true"><i data-org="ddigital" style="flex:0.400"></i><i data-org="forge" style="flex:0.300"></i><i data-org="home" style="flex:0.300"></i></div>
<div class="by"><span><span class="av " data-org="ddigital" aria-hidden="true">DD</span>4</span><span><span class="av " data-org="forge" aria-hidden="true">FG</span>3</span><span><span class="av " data-org="home" aria-hidden="true">HM</span>3</span></div><span class="delta">2 paused</span></div>
<div class="tile"><span class="label">Model spend</span><span class="big">$38.40<small>7 days</small></span>
<div class="bar" aria-hidden="true"><i data-org="ddigital" style="flex:0.549"></i><i data-org="forge" style="flex:0.406"></i><i data-org="home" style="flex:0.044"></i></div>
<div class="by"><span><span class="av " data-org="ddigital" aria-hidden="true">DD</span>$21.10</span><span><span class="av " data-org="forge" aria-hidden="true">FG</span>$15.60</span><span><span class="av " data-org="home" aria-hidden="true">HM</span>$1.70</span></div><span class="delta">of $110 in weekly limits</span></div>
</div>
<div class="split" style="margin-top:4px">
<section>
<div class="sec-h"><h2>Activity across organizations</h2><span class="note">newest first, every bus</span><a href="#">All activity</a></div>
<ol class="trail"><li><time>14:32</time><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="what"><b>coder</b> pushed 3 commits on #41 Rate limiter <span class="src">· Forge · API gateway</span></span></li><li><time>14:28</time><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="what"><b>copywriter</b> saved V-112 Launch email, draft 2 <span class="src">· Distinctly Digital · Spring launch</span></span></li><li><time>14:21</time><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="what"><b>reviewer</b> stopped: model provider timed out <span class="src">· Forge · Web app</span></span></li><li><time>14:15</time><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="what"><b>editor</b> asked you: keep the revised ending? <span class="src">· Distinctly Digital · The Lantern Coast</span></span></li><li><time>14:02</time><span class="av " data-org="home" aria-hidden="true">HM</span><span class="what"><b>assistant</b> flagged the insurance renewal <span class="src">· Home · Household admin</span></span></li><li><time>13:55</time><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="what"><b>montage-producer</b> rendered teaser cut 3 of 4 <span class="src">· Distinctly Digital · Spring launch</span></span></li><li><time>13:40</time><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="what"><b>chief</b> raised a gated decision: merge the rate limiter <span class="src">· Forge · API gateway</span></span></li><li><time>13:12</time><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="what"><b>chief</b> created V-120 Logo shortlist in Vikunja <span class="src">· Distinctly Digital · Brand refresh</span></span></li><li><time>12:58</time><span class="av " data-org="home" aria-hidden="true">HM</span><span class="what"><b>you</b> closed #9 Order seed potatoes <span class="src">· Home · Garden plan</span></span></li></ol>
<div class="sec-h"><h2>Tasks by state</h2><span class="note">all trackers</span><a href="06-tasks.html">Open tasks</a></div>
<div class="panel tight states">
<div class="srow"><span class="sl">To do</span><span class="sn tnum">5</span><div class="bar" style="width:90%" aria-hidden="true"><i data-org="ddigital" style="flex:2"></i><i data-org="forge" style="flex:1"></i><i data-org="home" style="flex:2"></i></div><span class="by"><span><span class="av " data-org="ddigital" aria-hidden="true">DD</span>2</span><span><span class="av " data-org="forge" aria-hidden="true">FG</span>1</span><span><span class="av " data-org="home" aria-hidden="true">HM</span>2</span></span></div><div class="srow"><span class="sl">In progress</span><span class="sn tnum">3</span><div class="bar" style="width:54%" aria-hidden="true"><i data-org="ddigital" style="flex:2"></i><i data-org="forge" style="flex:1"></i></div><span class="by"><span><span class="av " data-org="ddigital" aria-hidden="true">DD</span>2</span><span><span class="av " data-org="forge" aria-hidden="true">FG</span>1</span></span></div><div class="srow"><span class="sl">Review</span><span class="sn tnum">2</span><div class="bar" style="width:36%" aria-hidden="true"><i data-org="ddigital" style="flex:1"></i><i data-org="forge" style="flex:1"></i></div><span class="by"><span><span class="av " data-org="ddigital" aria-hidden="true">DD</span>1</span><span><span class="av " data-org="forge" aria-hidden="true">FG</span>1</span></span></div><div class="srow"><span class="sl">Done this week</span><span class="sn tnum">2</span><div class="bar" style="width:36%" aria-hidden="true"><i data-org="forge" style="flex:1"></i><i data-org="home" style="flex:1"></i></div><span class="by"><span><span class="av " data-org="forge" aria-hidden="true">FG</span>1</span><span><span class="av " data-org="home" aria-hidden="true">HM</span>1</span></span></div>
</div>
</section>
<section>
<div class="sec-h"><h2>Needs you</h2><a href="05-inbox.html">Inbox</a></div>
<ul class="needs"><li class="edge" data-org="forge"><span class="av md" data-org="forge" aria-hidden="true">FG</span><span class="q">Merge the rate limiter branch into main?</span><span class="src">Forge · API gateway · chief</span><span class="chip gated">gated</span></li><li class="edge" data-org="ddigital"><span class="av md" data-org="ddigital" aria-hidden="true">DD</span><span class="q">Chapter 7: keep the revised ending?</span><span class="src">Distinctly Digital · The Lantern Coast · editor</span><span class="chip within">within-role</span></li><li class="edge" data-org="home"><span class="av md" data-org="home" aria-hidden="true">HM</span><span class="q">Home insurance renews in 12 days. Compare the two quotes now?</span><span class="src">Home · Household admin · assistant</span><span class="chip routine">routine</span></li></ul>
<div class="sec-h"><h2>Sessions now</h2><a href="08-agents.html">Agents</a></div>
<div class="tbl"><table class="sess"><thead><tr><th>Agent and project</th><th>Status</th></tr></thead><tbody>
<tr><td class="who"><span class="orgref"><span class="av all xs" aria-hidden="true" title="Assistant, all organizations"><svg class="mosaic-logo" viewBox="0 0 36 36" style="width:70%;height:auto" aria-hidden="true"><rect x="3" y="12" width="13" height="10" rx="2"/><rect x="18" y="3" width="13" height="12" rx="2"/><rect x="3" y="24" width="13" height="10" rx="2"/><rect x="18" y="17" width="13" height="12" rx="2"/></svg></span>assistant</span><span class="muted"> · All organizations</span></td><td class="st"><span class="dot s-working"><b aria-hidden="true">●</b>working</span> <span class="muted">with you</span></td></tr><tr><td class="who"><span class="orgref"><span class="av xs" data-org="forge" aria-hidden="true">FG</span>coder</span><span class="muted"> · API gateway</span></td><td class="st"><span class="dot s-working"><b aria-hidden="true">●</b>working</span> <span class="muted">65 min</span></td></tr><tr><td class="who"><span class="orgref"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span>copywriter</span><span class="muted"> · Spring launch</span></td><td class="st"><span class="dot s-working"><b aria-hidden="true">●</b>working</span> <span class="muted">38 min</span></td></tr><tr><td class="who"><span class="orgref"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span>montage-producer</span><span class="muted"> · Spring launch</span></td><td class="st"><span class="dot s-working"><b aria-hidden="true">●</b>working</span> <span class="muted">72 min</span></td></tr><tr><td class="who"><span class="orgref"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span>editor</span><span class="muted"> · The Lantern Coast</span></td><td class="st"><span class="dot s-waiting"><b aria-hidden="true">◐</b>waiting</span> <span class="muted">on you</span></td></tr><tr><td class="who"><span class="orgref"><span class="av xs" data-org="forge" aria-hidden="true">FG</span>reviewer</span><span class="muted"> · Web app</span></td><td class="st"><span class="dot s-error"><b aria-hidden="true">▲</b>error</span> <span class="muted">timeout</span></td></tr><tr><td class="who"><span class="orgref"><span class="av xs" data-org="home" aria-hidden="true">HM</span>planner</span><span class="muted"> · Household admin</span></td><td class="st"><span class="dot s-idle"><b aria-hidden="true">–</b>idle</span> <span class="muted">since 09:10</span></td></tr>
</tbody></table></div>
</section>
</div>
</main>
</div>
</body>
</html>
@@ -0,0 +1,91 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Distinctly Digital · U0 sample</title>
<link rel="stylesheet" href="workspace.css">
</head>
<body>
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false"><symbol id="i-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol><symbol id="i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 10.5 12 4l8 6.5"/><path d="M6 9v10.5h12V9"/><path d="M10 19.5v-5h4v5"/></symbol><symbol id="i-folder" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 6.5a1 1 0 0 1 1-1h4.5l2 2h8.5a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1h-15a1 1 0 0 1-1-1z"/></symbol><symbol id="i-columns" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M12 4.5v15"/></symbol><symbol id="i-split" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M13 4.5v15M16.75 10.5v3M15.25 12h3"/></symbol><symbol id="i-restart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3"/><path d="M19.5 4.5v4h-4"/></symbol><symbol id="i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></symbol><symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/></symbol><symbol id="i-doc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 3.5h7l4 4v13h-11z"/><path d="M13.5 3.5v4h4M9 12h6M9 15.5h6"/></symbol></svg>
<div class="app ">
<header class="cmdbar">
<button class="menu" aria-label="Open navigation" aria-expanded="false"><svg class="i" aria-hidden="true"><use href="#i-menu"/></svg></button>
<a class="mk" href="02-dashboard.html"><svg class="mosaic-logo" viewBox="0 0 36 36" aria-hidden="true"><rect x="3" y="12" width="13" height="10" rx="2"/><rect x="18" y="3" width="13" height="12" rx="2"/><rect x="3" y="24" width="13" height="10" rx="2"/><rect x="18" y="17" width="13" height="12" rx="2"/></svg><span>Mosaic Stack</span></a>
<span class="sim" title="Static design sample">U0 sample</span>
<button class="cmdk"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-search"/></svg><span>Go to an org, project, task or decision</span><kbd>Ctrl K</kbd></button>
<div class="fresh"><span class="wide">Read <b>3 of 3</b> organization buses · 4 s ago</span><span class="me" title="Operator">OP</span></div>
</header>
<nav class="side" aria-label="Workspace">
<a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a>
<a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a>
<a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a>
<a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a>
<a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a>
<a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a>
<a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Organizations</span><span class="n">3</span><span class="add" title="New organization"><svg class="i sm" aria-hidden="true"><use href="#i-plus"/></svg></span></div>
<a class="nav org-row" href="03-org-dashboard.html" aria-current="page"><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="t">Distinctly Digital</span><span class="ic" title="Business"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="t">Forge</span><span class="ic" title="Coding"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-term"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="home" aria-hidden="true">HM</span><span class="t">Home</span><span class="ic" title="Personal"><svg class="i sm" aria-hidden="true"><use href="#i-home"/></svg></span></a>
</div>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Projects</span><span class="seg xs" role="group" aria-label="Project layout"><span aria-pressed="true">By org</span><span aria-pressed="false">Flat</span></span></div>
<div class="pgroup" data-org="ddigital"><div class="pgroup-h"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span>Distinctly Digital</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Spring launch</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">The Lantern Coast</span><span class="dot s-waiting" title="waiting"><b aria-hidden="true">◐</b><span class="sr">waiting</span></span></a><a class="nav proj" href="#"><span class="t">Brand refresh</span></a><a class="nav proj" href="#"><span class="t">Monthly newsletter</span></a></div></div>
<div class="pgroup" data-org="forge"><div class="pgroup-h"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span>Forge</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">API gateway</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">Web app</span><span class="dot s-error" title="error"><b aria-hidden="true">▲</b><span class="sr">error</span></span></a><a class="nav proj" href="#"><span class="t">CLI tools</span><span class="n">paused</span></a></div></div>
<div class="pgroup" data-org="home"><div class="pgroup-h"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span>Home</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Household admin</span><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span></a><a class="nav proj" href="#"><span class="t">Garden plan</span></a><a class="nav proj" href="#"><span class="t">Trip planning 2027</span><span class="n">paused</span></a></div></div>
</div>
<div class="foot"><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-settings"/></svg><span class="t">Settings</span></a></div>
</nav>
<nav class="strip" aria-label="Sections"><a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a><a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a><a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a><a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a><a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a><a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a></nav>
<main class="main ">
<div class="crumb"><a href="#">Organizations</a> › Distinctly Digital</div>
<div class="orghead" data-org="ddigital">
<span class="av lg" data-org="ddigital" aria-hidden="true">DD</span>
<h1>Distinctly Digital <svg class="i" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></h1>
<div class="right">
<span class="btn" title="mosaic bus restart ddigital"><svg class="i" aria-hidden="true"><use href="#i-restart"/></svg>Restart bus</span>
<span class="btn"><svg class="i" aria-hidden="true"><use href="#i-doc"/></svg>Reload organization file</span>
<a class="btn pri" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-split"/></svg>Open in a pane</a>
</div>
<div class="meta"><span>Business</span><span>id <code>ddigital</code></span><span>Tracker: Vikunja</span><span><span class="dot s-working"><b aria-hidden="true">●</b>bus read 4 s ago</span></span><span>Restart and reload are trailed human actions; no agent can take them.</span></div>
</div>
<div class="typechips chips"><span class="label" style="margin-right:4px">System types</span><span class="chip outline">Coding</span><span class="chip outline">Creative writing</span><span class="chip outline">Marketing</span><span class="chip outline">Mosaic Montage</span><span class="chip outline">Business management</span><span class="note">Each project picks from these; none is required.</span></div>
<div class="docrow chips"><span class="label" style="margin-right:4px">Docs</span><a class="doc" href="#" title="org"><svg class="i sm" aria-hidden="true"><use href="#i-doc"/></svg>North star</a><a class="doc" href="#" title="org"><svg class="i sm" aria-hidden="true"><use href="#i-doc"/></svg>Brand voice guide</a><a class="doc" href="#" title="Spring launch"><svg class="i sm" aria-hidden="true"><use href="#i-doc"/></svg>Launch plan<small>Spring launch</small></a><a class="doc" href="#" title="The Lantern Coast"><svg class="i sm" aria-hidden="true"><use href="#i-doc"/></svg>Series bible<small>The Lantern Coast</small></a><a class="doc" href="#" title="org"><svg class="i sm" aria-hidden="true"><use href="#i-doc"/></svg>Operating notes</a><a href="#" class="more">All docs</a></div>
<div class="split" style="margin-top:6px">
<section>
<div class="sec-h"><h2>KPIs</h2><span class="note">defined in the organization file</span><a href="#">Edit KPIs</a></div>
<div class="grid g4 keep2">
<div class="tile"><span class="label">Subscribers</span><span class="big">2,480</span><span class="delta"><b>+6.2%</b> in 30 days · goal 3,000</span></div>
<div class="tile"><span class="label">Launch pieces</span><span class="big">7<small>of 12</small></span><div class="bar"><i data-org="ddigital" style="flex:7"></i><i style="flex:5;background:transparent"></i></div></div>
<div class="tile"><span class="label">Novel draft</span><span class="big">61,200<small>words</small></span><span class="delta">target 90,000 · 68%</span></div>
<div class="tile"><span class="label">Tasks closed</span><span class="big">18</span><span class="delta">30 days · <b>+4</b> on last month</span></div>
</div>
<div class="sec-h"><h2>Metrics</h2><span class="note">measured by the bus</span></div>
<div class="grid g4 keep2 metrics">
<div class="tile"><span class="label">Spend this week</span><span class="big">$21.10<small>of $60</small></span><div class="bar"><i data-org="ddigital" style="flex:21.1"></i><i style="flex:38.9;background:transparent"></i></div></div>
<div class="tile"><span class="label">Agent hours</span><span class="big">31.5<small>7 days</small></span></div>
<div class="tile"><span class="label">Decision wait</span><span class="big">22<small>min median</small></span></div>
<div class="tile"><span class="label">Open tasks</span><span class="big">5</span><span class="delta">2 in progress · 1 review</span></div>
</div>
<div class="sec-h"><h2>Active agent sessions</h2><span class="note">2 working, 1 waiting on you</span><a href="08-agents.html">All agents</a></div>
<div class="tbl"><table><thead><tr><th>Agent</th><th>Project and task</th><th class="hide-m">Model</th><th>Status</th></tr></thead><tbody>
<tr><td class="t1">copywriter</td><td>Spring launch<span class="t2">V-112 Launch email, draft 2</span></td><td class="hide-m mono">sonnet-5.5 <a href="#">Change</a></td><td><span class="dot s-working"><b aria-hidden="true">●</b>working</span> <span class="muted">38 min</span></td></tr>
<tr><td class="t1">montage-producer</td><td>Spring launch<span class="t2">V-118 Teaser reel, 30 s cut</span></td><td class="hide-m mono">sonnet-5.5 <a href="#">Change</a></td><td><span class="dot s-working"><b aria-hidden="true">●</b>working</span> <span class="muted">1 h 12 min</span></td></tr>
<tr><td class="t1">editor</td><td>The Lantern Coast<span class="t2">V-97 Chapter 7 revision</span></td><td class="hide-m mono">opus-5.5 <a href="#">Change</a></td><td><span class="dot s-waiting"><b aria-hidden="true">◐</b>waiting on you</span></td></tr>
</tbody></table></div>
</section>
<section>
<div class="sec-h"><h2>Settings</h2><span class="note">every setting, with where its value comes from</span></div>
<ul class="cfg one"><li><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg><span class="k">Identity</span><span class="v">Distinctly Digital · ddigital · Business</span><span class="src-tag">org file</span><a class="go" href="#">Open</a></li><li><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-flag"/></svg><span class="k">Appearance</span><span class="v">Rosewood theme · DD avatar</span><span class="src-tag">org file</span><a class="go" href="#">Open</a></li><li><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-runs"/></svg><span class="k">System types</span><span class="v">5 of 5 installed enabled</span><span class="src-tag">org file</span><a class="go" href="#">Open</a></li><li><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="k">Projects</span><span class="v">4 projects · 3 with a remote, 1 local only</span><span class="src-tag">org file</span><a class="go" href="#">Open</a></li><li><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="k">Agents and roles</span><span class="v">5 org · 2 project · 3 from your root</span><span class="src-tag">org + root</span><a class="go" href="#">Open</a></li><li><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-term"/></svg><span class="k">Models and providers</span><span class="v">Your shared proxy · editor runs opus-5.5</span><span class="src-tag">override</span><a class="go" href="#">Open</a></li><li><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="k">Task tracker</span><span class="v">Vikunja module · project DD</span><span class="src-tag">org file</span><a class="go" href="#">Open</a></li><li><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="k">Channels</span><span class="v">Discord off · daily email digest</span><span class="src-tag">org file</span><a class="go" href="#">Open</a></li><li><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-ledger"/></svg><span class="k">Launch limits</span><span class="v">4 sessions at once · $60 a week</span><span class="src-tag">org file</span><a class="go" href="#">Open</a></li><li><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-queue"/></svg><span class="k">Routing and arbiters</span><span class="v">chief routes · editor arbitrates copy</span><span class="src-tag">org file</span><a class="go" href="#">Open</a></li><li><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="k">Members and invites</span><span class="v">You (owner) · invites arrive in Phase M</span><span class="src-tag">not built</span><a class="go" href="#">Open</a></li><li><svg class="i" aria-hidden="true"><use href="#i-restart"/></svg><span class="k">Bus</span><span class="v">Running · local-only checkout</span><span class="src-tag">system</span><a class="go" href="#">Open</a></li><li class="danger"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-close"/></svg><span class="k">Archive or delete</span><span class="v">Removes this organization's tasks and data only</span><span class="src-tag">danger</span><a class="go" href="#">Open</a></li></ul>
</section>
</div>
</main>
</div>
</body>
</html>
@@ -0,0 +1,164 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Projects · U0 sample</title>
<link rel="stylesheet" href="workspace.css">
</head>
<body>
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false"><symbol id="i-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol><symbol id="i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 10.5 12 4l8 6.5"/><path d="M6 9v10.5h12V9"/><path d="M10 19.5v-5h4v5"/></symbol><symbol id="i-folder" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 6.5a1 1 0 0 1 1-1h4.5l2 2h8.5a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1h-15a1 1 0 0 1-1-1z"/></symbol><symbol id="i-columns" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M12 4.5v15"/></symbol><symbol id="i-split" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M13 4.5v15M16.75 10.5v3M15.25 12h3"/></symbol><symbol id="i-restart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3"/><path d="M19.5 4.5v4h-4"/></symbol><symbol id="i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></symbol><symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/></symbol><symbol id="i-doc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 3.5h7l4 4v13h-11z"/><path d="M13.5 3.5v4h4M9 12h6M9 15.5h6"/></symbol></svg>
<div class="app ">
<header class="cmdbar">
<button class="menu" aria-label="Open navigation" aria-expanded="false"><svg class="i" aria-hidden="true"><use href="#i-menu"/></svg></button>
<a class="mk" href="02-dashboard.html"><svg class="mosaic-logo" viewBox="0 0 36 36" aria-hidden="true"><rect x="3" y="12" width="13" height="10" rx="2"/><rect x="18" y="3" width="13" height="12" rx="2"/><rect x="3" y="24" width="13" height="10" rx="2"/><rect x="18" y="17" width="13" height="12" rx="2"/></svg><span>Mosaic Stack</span></a>
<span class="sim" title="Static design sample">U0 sample</span>
<button class="cmdk"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-search"/></svg><span>Go to an org, project, task or decision</span><kbd>Ctrl K</kbd></button>
<div class="fresh"><span class="wide">Read <b>3 of 3</b> organization buses · 4 s ago</span><span class="me" title="Operator">OP</span></div>
</header>
<nav class="side" aria-label="Workspace">
<a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a>
<a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a>
<a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a>
<a class="nav" href="04-projects.html" aria-current="page"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a>
<a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a>
<a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a>
<a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Organizations</span><span class="n">3</span><span class="add" title="New organization"><svg class="i sm" aria-hidden="true"><use href="#i-plus"/></svg></span></div>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="t">Distinctly Digital</span><span class="ic" title="Business"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="t">Forge</span><span class="ic" title="Coding"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-term"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="home" aria-hidden="true">HM</span><span class="t">Home</span><span class="ic" title="Personal"><svg class="i sm" aria-hidden="true"><use href="#i-home"/></svg></span></a>
</div>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Projects</span><span class="seg xs" role="group" aria-label="Project layout"><span aria-pressed="true">By org</span><span aria-pressed="false">Flat</span></span></div>
<div class="pgroup" data-org="ddigital"><div class="pgroup-h"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span>Distinctly Digital</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Spring launch</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">The Lantern Coast</span><span class="dot s-waiting" title="waiting"><b aria-hidden="true">◐</b><span class="sr">waiting</span></span></a><a class="nav proj" href="#"><span class="t">Brand refresh</span></a><a class="nav proj" href="#"><span class="t">Monthly newsletter</span></a></div></div>
<div class="pgroup" data-org="forge"><div class="pgroup-h"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span>Forge</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">API gateway</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">Web app</span><span class="dot s-error" title="error"><b aria-hidden="true">▲</b><span class="sr">error</span></span></a><a class="nav proj" href="#"><span class="t">CLI tools</span><span class="n">paused</span></a></div></div>
<div class="pgroup" data-org="home"><div class="pgroup-h"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span>Home</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Household admin</span><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span></a><a class="nav proj" href="#"><span class="t">Garden plan</span></a><a class="nav proj" href="#"><span class="t">Trip planning 2027</span><span class="n">paused</span></a></div></div>
</div>
<div class="foot"><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-settings"/></svg><span class="t">Settings</span></a></div>
</nav>
<nav class="strip" aria-label="Sections"><a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a><a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a><a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a><a class="nav" href="04-projects.html" aria-current="page"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a><a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a><a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a></nav>
<main class="main ">
<div class="vh"><h1>Projects</h1><div class="right"><span class="btn"><svg class="i" aria-hidden="true"><use href="#i-plus"/></svg>New project</span></div>
<p class="sub">10 projects in 3 organizations, sorted by latest activity. Every row names its organization by mark, colour edge and type icon.</p></div>
<div class="toolbar">
<span class="search"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-search"/></svg>Filter by name</span>
<div class="chips" role="group" aria-label="Organization"><span class="f plain" aria-pressed="true">All <span class="n">10</span></span><span class="f" aria-pressed="false"><span class="av " data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital<span class="n">4</span></span><span class="f" aria-pressed="false"><span class="av " data-org="forge" aria-hidden="true">FG</span>Forge<span class="n">3</span></span><span class="f" aria-pressed="false"><span class="av " data-org="home" aria-hidden="true">HM</span>Home<span class="n">3</span></span></div>
<span class="sel"><span class="label">Status</span>Active, paused<svg class="i sm" aria-hidden="true"><use href="#i-chevron"/></svg></span>
<div class="right"><span class="label hide-m">Sort</span><span class="seg" role="group" aria-label="Sort"><span aria-pressed="true">Activity</span><span aria-pressed="false">Name</span><span aria-pressed="false">Org</span><span aria-pressed="false">Status</span></span></div>
</div>
<div class="tbl"><table class="projects">
<thead><tr><th class="hide-m">Organization</th><th>Project</th><th>Status</th><th class="hide-m">System types</th><th class="hide-m">Sessions</th><th class="num hide-m">Open tasks</th><th class="num">Needs you</th><th class="sorted hide-m">Last activity<span class="ar">↓</span></th><th class="hide-m">Git</th></tr></thead>
<tbody>
<tr class="edge" data-org="forge">
<td class="hide-m"><span class="orgref"><span class="av " data-org="forge" aria-hidden="true">FG</span>Forge<span class="ic muted"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-term"/></svg></span></span></td>
<td><span class="t1 nm"><span class="av xs mob" data-org="forge" aria-hidden="true">FG</span>API gateway</span><span class="t2 mono hide-m">api-gateway</span><span class="t2 show-m">2 min ago · coder pushed 3 commits on #41</span></td>
<td><span class="dot s-ok"><b aria-hidden="true">●</b>active</span></td>
<td class="hide-m"><span class="chip outline">Coding</span></td>
<td class="hide-m"><span class="dot s-working"><b aria-hidden="true">●</b>1 working</span></td>
<td class="num hide-m">2</td>
<td class="num"><span class="n hot">1</span></td>
<td class="hide-m">2 min ago<span class="t2">coder pushed 3 commits on #41</span></td>
<td class="hide-m"><span class="chip outline">remote</span></td>
</tr><tr class="edge" data-org="ddigital">
<td class="hide-m"><span class="orgref"><span class="av " data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital<span class="ic muted"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></span></td>
<td><span class="t1 nm"><span class="av xs mob" data-org="ddigital" aria-hidden="true">DD</span>Spring launch</span><span class="t2 mono hide-m">spring-launch</span><span class="t2 show-m">4 min ago · copywriter saved draft 2</span></td>
<td><span class="dot s-ok"><b aria-hidden="true">●</b>active</span></td>
<td class="hide-m"><span class="chip outline">Marketing</span> <span class="chip outline">Creative writing</span> <span class="chip outline">Mosaic Montage</span></td>
<td class="hide-m"><span class="dot s-working"><b aria-hidden="true">●</b>2 working</span></td>
<td class="num hide-m">2</td>
<td class="num"><span class="muted">0</span></td>
<td class="hide-m">4 min ago<span class="t2">copywriter saved draft 2</span></td>
<td class="hide-m"><span class="chip outline">remote</span></td>
</tr><tr class="edge" data-org="forge">
<td class="hide-m"><span class="orgref"><span class="av " data-org="forge" aria-hidden="true">FG</span>Forge<span class="ic muted"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-term"/></svg></span></span></td>
<td><span class="t1 nm"><span class="av xs mob" data-org="forge" aria-hidden="true">FG</span>Web app</span><span class="t2 mono hide-m">webapp</span><span class="t2 show-m">11 min ago · reviewer stopped: provider timeout</span></td>
<td><span class="dot s-ok"><b aria-hidden="true">●</b>active</span></td>
<td class="hide-m"><span class="chip outline">Coding</span></td>
<td class="hide-m"><span class="dot s-error"><b aria-hidden="true">▲</b>1 error</span></td>
<td class="num hide-m">1</td>
<td class="num"><span class="muted">0</span></td>
<td class="hide-m">11 min ago<span class="t2">reviewer stopped: provider timeout</span></td>
<td class="hide-m"><span class="chip outline">remote</span></td>
</tr><tr class="edge" data-org="ddigital">
<td class="hide-m"><span class="orgref"><span class="av " data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital<span class="ic muted"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></span></td>
<td><span class="t1 nm"><span class="av xs mob" data-org="ddigital" aria-hidden="true">DD</span>The Lantern Coast</span><span class="t2 mono hide-m">novel-draft</span><span class="t2 show-m">17 min ago · editor asked about chapter 7</span></td>
<td><span class="dot s-ok"><b aria-hidden="true">●</b>active</span></td>
<td class="hide-m"><span class="chip outline">Creative writing</span></td>
<td class="hide-m"><span class="dot s-waiting"><b aria-hidden="true">◐</b>1 waiting</span></td>
<td class="num hide-m">1</td>
<td class="num"><span class="n hot">1</span></td>
<td class="hide-m">17 min ago<span class="t2">editor asked about chapter 7</span></td>
<td class="hide-m"><span class="chip outline">local only</span></td>
</tr><tr class="edge" data-org="home">
<td class="hide-m"><span class="orgref"><span class="av " data-org="home" aria-hidden="true">HM</span>Home<span class="ic muted"><svg class="i sm" aria-hidden="true"><use href="#i-home"/></svg></span></span></td>
<td><span class="t1 nm"><span class="av xs mob" data-org="home" aria-hidden="true">HM</span>Household admin</span><span class="t2 mono hide-m">household</span><span class="t2 show-m">30 min ago · assistant flagged a renewal</span></td>
<td><span class="dot s-ok"><b aria-hidden="true">●</b>active</span></td>
<td class="hide-m"><span class="chip outline">Business management</span></td>
<td class="hide-m"><span class="dot s-idle"><b aria-hidden="true">–</b>1 idle</span></td>
<td class="num hide-m">1</td>
<td class="num"><span class="n hot">1</span></td>
<td class="hide-m">30 min ago<span class="t2">assistant flagged a renewal</span></td>
<td class="hide-m"><span class="chip outline">local only</span></td>
</tr><tr class="edge" data-org="ddigital">
<td class="hide-m"><span class="orgref"><span class="av " data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital<span class="ic muted"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></span></td>
<td><span class="t1 nm"><span class="av xs mob" data-org="ddigital" aria-hidden="true">DD</span>Brand refresh</span><span class="t2 mono hide-m">brand-refresh</span><span class="t2 show-m">1 h ago · chief created V-120</span></td>
<td><span class="dot s-ok"><b aria-hidden="true">●</b>active</span></td>
<td class="hide-m"><span class="chip outline">Marketing</span> <span class="chip outline">Mosaic Montage</span></td>
<td class="hide-m"><span class="muted">none</span></td>
<td class="num hide-m">1</td>
<td class="num"><span class="muted">0</span></td>
<td class="hide-m">1 h ago<span class="t2">chief created V-120</span></td>
<td class="hide-m"><span class="chip outline">remote</span></td>
</tr><tr class="edge" data-org="home">
<td class="hide-m"><span class="orgref"><span class="av " data-org="home" aria-hidden="true">HM</span>Home<span class="ic muted"><svg class="i sm" aria-hidden="true"><use href="#i-home"/></svg></span></span></td>
<td><span class="t1 nm"><span class="av xs mob" data-org="home" aria-hidden="true">HM</span>Garden plan</span><span class="t2 mono hide-m">garden</span><span class="t2 show-m">1 h ago · #9 marked done</span></td>
<td><span class="dot s-ok"><b aria-hidden="true">●</b>active</span></td>
<td class="hide-m"><span class="muted">none</span></td>
<td class="hide-m"><span class="muted">none</span></td>
<td class="num hide-m">0</td>
<td class="num"><span class="muted">0</span></td>
<td class="hide-m">1 h ago<span class="t2">#9 marked done</span></td>
<td class="hide-m"><span class="chip outline">local only</span></td>
</tr><tr class="edge" data-org="ddigital">
<td class="hide-m"><span class="orgref"><span class="av " data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital<span class="ic muted"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></span></td>
<td><span class="t1 nm"><span class="av xs mob" data-org="ddigital" aria-hidden="true">DD</span>Monthly newsletter</span><span class="t2 mono hide-m">newsletter</span><span class="t2 show-m">yesterday · V-121 created</span></td>
<td><span class="dot s-ok"><b aria-hidden="true">●</b>active</span></td>
<td class="hide-m"><span class="chip outline">Marketing</span> <span class="chip outline">Creative writing</span></td>
<td class="hide-m"><span class="muted">none</span></td>
<td class="num hide-m">1</td>
<td class="num"><span class="muted">0</span></td>
<td class="hide-m">yesterday<span class="t2">V-121 created</span></td>
<td class="hide-m"><span class="chip outline">remote</span></td>
</tr><tr class="edge dim" data-org="forge">
<td class="hide-m"><span class="orgref"><span class="av " data-org="forge" aria-hidden="true">FG</span>Forge<span class="ic muted"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-term"/></svg></span></span></td>
<td><span class="t1 nm"><span class="av xs mob" data-org="forge" aria-hidden="true">FG</span>CLI tools</span><span class="t2 mono hide-m">cli-tools</span><span class="t2 show-m">12 days ago · #29 done</span></td>
<td><span class="dot s-idle"><b aria-hidden="true">–</b>paused</span></td>
<td class="hide-m"><span class="chip outline">Coding</span></td>
<td class="hide-m"><span class="muted">none</span></td>
<td class="num hide-m">0</td>
<td class="num"><span class="muted">0</span></td>
<td class="hide-m">12 days ago<span class="t2">#29 done</span></td>
<td class="hide-m"><span class="chip outline">remote</span></td>
</tr><tr class="edge dim" data-org="home">
<td class="hide-m"><span class="orgref"><span class="av " data-org="home" aria-hidden="true">HM</span>Home<span class="ic muted"><svg class="i sm" aria-hidden="true"><use href="#i-home"/></svg></span></span></td>
<td><span class="t1 nm"><span class="av xs mob" data-org="home" aria-hidden="true">HM</span>Trip planning 2027</span><span class="t2 mono hide-m">travel</span><span class="t2 show-m">3 weeks ago · #14 created</span></td>
<td><span class="dot s-idle"><b aria-hidden="true">–</b>paused</span></td>
<td class="hide-m"><span class="muted">none</span></td>
<td class="hide-m"><span class="muted">none</span></td>
<td class="num hide-m">1</td>
<td class="num"><span class="muted">0</span></td>
<td class="hide-m">3 weeks ago<span class="t2">#14 created</span></td>
<td class="hide-m"><span class="chip outline">local only</span></td>
</tr>
</tbody></table></div>
<p class="note" style="margin-top:10px">Sorting by Org groups the rows under each organization's header. Paused projects stay listed, dimmed, and the Status filter hides them.</p>
</main>
</div>
</body>
</html>
@@ -0,0 +1,83 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Inbox · U0 sample</title>
<link rel="stylesheet" href="workspace.css">
</head>
<body>
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false"><symbol id="i-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol><symbol id="i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 10.5 12 4l8 6.5"/><path d="M6 9v10.5h12V9"/><path d="M10 19.5v-5h4v5"/></symbol><symbol id="i-folder" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 6.5a1 1 0 0 1 1-1h4.5l2 2h8.5a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1h-15a1 1 0 0 1-1-1z"/></symbol><symbol id="i-columns" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M12 4.5v15"/></symbol><symbol id="i-split" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M13 4.5v15M16.75 10.5v3M15.25 12h3"/></symbol><symbol id="i-restart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3"/><path d="M19.5 4.5v4h-4"/></symbol><symbol id="i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></symbol><symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/></symbol><symbol id="i-doc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 3.5h7l4 4v13h-11z"/><path d="M13.5 3.5v4h4M9 12h6M9 15.5h6"/></symbol></svg>
<div class="app with-insp">
<header class="cmdbar">
<button class="menu" aria-label="Open navigation" aria-expanded="false"><svg class="i" aria-hidden="true"><use href="#i-menu"/></svg></button>
<a class="mk" href="02-dashboard.html"><svg class="mosaic-logo" viewBox="0 0 36 36" aria-hidden="true"><rect x="3" y="12" width="13" height="10" rx="2"/><rect x="18" y="3" width="13" height="12" rx="2"/><rect x="3" y="24" width="13" height="10" rx="2"/><rect x="18" y="17" width="13" height="12" rx="2"/></svg><span>Mosaic Stack</span></a>
<span class="sim" title="Static design sample">U0 sample</span>
<button class="cmdk"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-search"/></svg><span>Go to an org, project, task or decision</span><kbd>Ctrl K</kbd></button>
<div class="fresh"><span class="wide">Read <b>3 of 3</b> organization buses · 4 s ago</span><span class="me" title="Operator">OP</span></div>
</header>
<nav class="side" aria-label="Workspace">
<a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a>
<a class="nav" href="05-inbox.html" aria-current="page"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a>
<a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a>
<a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a>
<a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a>
<a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a>
<a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Organizations</span><span class="n">3</span><span class="add" title="New organization"><svg class="i sm" aria-hidden="true"><use href="#i-plus"/></svg></span></div>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="t">Distinctly Digital</span><span class="ic" title="Business"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="t">Forge</span><span class="ic" title="Coding"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-term"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="home" aria-hidden="true">HM</span><span class="t">Home</span><span class="ic" title="Personal"><svg class="i sm" aria-hidden="true"><use href="#i-home"/></svg></span></a>
</div>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Projects</span><span class="seg xs" role="group" aria-label="Project layout"><span aria-pressed="true">By org</span><span aria-pressed="false">Flat</span></span></div>
<div class="pgroup" data-org="ddigital"><div class="pgroup-h"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span>Distinctly Digital</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Spring launch</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">The Lantern Coast</span><span class="dot s-waiting" title="waiting"><b aria-hidden="true">◐</b><span class="sr">waiting</span></span></a><a class="nav proj" href="#"><span class="t">Brand refresh</span></a><a class="nav proj" href="#"><span class="t">Monthly newsletter</span></a></div></div>
<div class="pgroup" data-org="forge"><div class="pgroup-h"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span>Forge</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">API gateway</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">Web app</span><span class="dot s-error" title="error"><b aria-hidden="true">▲</b><span class="sr">error</span></span></a><a class="nav proj" href="#"><span class="t">CLI tools</span><span class="n">paused</span></a></div></div>
<div class="pgroup" data-org="home"><div class="pgroup-h"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span>Home</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Household admin</span><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span></a><a class="nav proj" href="#"><span class="t">Garden plan</span></a><a class="nav proj" href="#"><span class="t">Trip planning 2027</span><span class="n">paused</span></a></div></div>
</div>
<div class="foot"><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-settings"/></svg><span class="t">Settings</span></a></div>
</nav>
<nav class="strip" aria-label="Sections"><a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a><a class="nav" href="05-inbox.html" aria-current="page"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a><a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a><a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a><a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a><a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a></nav>
<main class="main ">
<div class="vh"><h1>Inbox</h1>
<p class="sub">3 items need you, from 3 organizations. Each row names where it came from. Seen is not resolution: an item leaves only when it is answered.</p></div>
<div class="toolbar">
<div class="chips" role="group" aria-label="Organization"><span class="f plain" aria-pressed="true">All <span class="n">3</span></span><span class="f" aria-pressed="false"><span class="av " data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital<span class="n">1</span></span><span class="f" aria-pressed="false"><span class="av " data-org="forge" aria-hidden="true">FG</span>Forge<span class="n">1</span></span><span class="f" aria-pressed="false"><span class="av " data-org="home" aria-hidden="true">HM</span>Home<span class="n">1</span></span></div>
<div class="right"><span class="seg" role="group" aria-label="State"><span aria-pressed="true">Needs you</span><span aria-pressed="false">Seen</span><span aria-pressed="false">Answered</span></span></div>
</div>
<div class="tbl"><table class="ibx">
<thead><tr><th class="hide-m">Source</th><th>Needs</th><th class="hide-m">Class</th><th class="num">Waiting</th></tr></thead>
<tbody>
<tr class="row edge" data-org="forge" aria-selected="true"><td class="src hide-m"><span class="orgref"><span class="av " data-org="forge" aria-hidden="true">FG</span>Forge</span><span class="via">API gateway · chief</span></td><td><span class="msrc show-m"><span class="av xs" data-org="forge" aria-hidden="true">FG</span>Forge · API gateway · chief</span><span class="q">Merge the rate limiter branch into main?</span><span class="via">decision 4f2a91 · seen 14:05</span><span class="show-m"><span class="chip gated">gated</span></span></td><td class="hide-m"><span class="chip gated">gated</span></td><td class="num">52 min</td></tr><tr class="row edge" data-org="ddigital"><td class="src hide-m"><span class="orgref"><span class="av " data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital</span><span class="via">The Lantern Coast · editor session</span></td><td><span class="msrc show-m"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital · The Lantern Coast · editor</span><span class="q">Chapter 7: keep the revised ending?</span><span class="via">decision 7c03e2 · not seen</span><span class="show-m"><span class="chip within">within-role</span></span></td><td class="hide-m"><span class="chip within">within-role</span></td><td class="num">17 min</td></tr><tr class="row edge" data-org="home"><td class="src hide-m"><span class="orgref"><span class="av " data-org="home" aria-hidden="true">HM</span>Home</span><span class="via">Household admin · assistant</span></td><td><span class="msrc show-m"><span class="av xs" data-org="home" aria-hidden="true">HM</span>Home · Household admin · assistant</span><span class="q">Home insurance renews in 12 days. Compare the two quotes now?</span><span class="via">decision b19d40 · not seen</span><span class="show-m"><span class="chip routine">routine</span></span></td><td class="hide-m"><span class="chip routine">routine</span></td><td class="num">30 min</td></tr>
</tbody></table></div>
<div class="sec-h"><h2>Answered today</h2><span class="note">kept for 24 hours, then in the trail</span></div>
<div class="tbl"><table class="ibx"><tbody>
<tr class="dim"><td class="src hide-m"><span class="orgref quiet"><span class="av " data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital</span><span class="via">Spring launch · copywriter</span></td><td><span class="msrc show-m"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital · Spring launch</span>Use the shorter subject line?<span class="via">answered 11:40 by you · option 2</span></td><td class="num">done</td></tr>
<tr class="dim"><td class="src hide-m"><span class="orgref quiet"><span class="av " data-org="forge" aria-hidden="true">FG</span>Forge</span><span class="via">Web app · reviewer session</span></td><td><span class="msrc show-m"><span class="av xs" data-org="forge" aria-hidden="true">FG</span>Forge · Web app</span>Retry with the fallback model?<span class="via">expired 10:02 · no answer needed</span></td><td class="num">expired</td></tr>
</tbody></table></div>
</main>
<aside class="insp" aria-label="Decision" data-org="forge">
<header><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="label">Decision 4f2a91</span><span class="chip gated">gated</span><span class="x" aria-label="Close"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-close"/></svg></span></header>
<div class="body">
<h3>Merge the rate limiter branch into main?</h3>
<div class="auth">Forge · API gateway · raised by <b>chief</b> at 13:40. Only you can answer a gated decision.</div>
<p class="note">Branch <code>rate-limiter-41</code> passes the suite (312 tests). The review is missing: the reviewer session stopped on a provider timeout at 14:21.</p>
<ul class="opts">
<li class="rec"><div class="row"><span class="k">1</span><b>Merge after a fresh review</b><span class="chip ok">chief recommends</span></div><span class="note">Restart the reviewer on the fallback model, then merge if it passes.</span><div class="row"><span class="btn pri">Answer 1…</span></div></li>
<li><div class="row"><span class="k">2</span><b>Merge now</b></div><span class="note">Skips review. The trail records the waiver.</span><div class="row"><span class="btn">Answer 2…</span></div></li>
<li><div class="row"><span class="k">3</span><b>Hold until Monday</b></div><div class="row"><span class="btn">Answer 3…</span></div></li>
</ul>
<div><span class="label">Answer from a terminal</span>
<div class="cmd" style="margin-top:6px"><code>mosaic decide 4f2a91 1 --org forge</code><span class="btn" title="Copy"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-copy"/></svg></span></div>
<p class="note" style="margin-top:6px">The inbox mixes organizations, so the copied command always names the organization's bus.</p></div>
<div><span class="label">History</span>
<ol class="hist" style="margin-top:6px"><li><time>13:40</time>chief raised it on the Forge bus</li><li><time>13:41</time>reached your inbox</li><li><time>14:05</time>seen by you (not an answer)</li></ol></div>
</div>
</aside>
</div>
</body>
</html>
@@ -0,0 +1,119 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Tasks · U0 sample</title>
<link rel="stylesheet" href="workspace.css">
</head>
<body>
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false"><symbol id="i-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol><symbol id="i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 10.5 12 4l8 6.5"/><path d="M6 9v10.5h12V9"/><path d="M10 19.5v-5h4v5"/></symbol><symbol id="i-folder" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 6.5a1 1 0 0 1 1-1h4.5l2 2h8.5a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1h-15a1 1 0 0 1-1-1z"/></symbol><symbol id="i-columns" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M12 4.5v15"/></symbol><symbol id="i-split" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M13 4.5v15M16.75 10.5v3M15.25 12h3"/></symbol><symbol id="i-restart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3"/><path d="M19.5 4.5v4h-4"/></symbol><symbol id="i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></symbol><symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/></symbol><symbol id="i-doc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 3.5h7l4 4v13h-11z"/><path d="M13.5 3.5v4h4M9 12h6M9 15.5h6"/></symbol></svg>
<div class="app ">
<header class="cmdbar">
<button class="menu" aria-label="Open navigation" aria-expanded="false"><svg class="i" aria-hidden="true"><use href="#i-menu"/></svg></button>
<a class="mk" href="02-dashboard.html"><svg class="mosaic-logo" viewBox="0 0 36 36" aria-hidden="true"><rect x="3" y="12" width="13" height="10" rx="2"/><rect x="18" y="3" width="13" height="12" rx="2"/><rect x="3" y="24" width="13" height="10" rx="2"/><rect x="18" y="17" width="13" height="12" rx="2"/></svg><span>Mosaic Stack</span></a>
<span class="sim" title="Static design sample">U0 sample</span>
<button class="cmdk"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-search"/></svg><span>Go to an org, project, task or decision</span><kbd>Ctrl K</kbd></button>
<div class="fresh"><span class="wide">Read <b>3 of 3</b> organization buses · 4 s ago</span><span class="me" title="Operator">OP</span></div>
</header>
<nav class="side" aria-label="Workspace">
<a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a>
<a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a>
<a class="nav" href="06-tasks.html" aria-current="page"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a>
<a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a>
<a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a>
<a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a>
<a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Organizations</span><span class="n">3</span><span class="add" title="New organization"><svg class="i sm" aria-hidden="true"><use href="#i-plus"/></svg></span></div>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="t">Distinctly Digital</span><span class="ic" title="Business"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="t">Forge</span><span class="ic" title="Coding"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-term"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="home" aria-hidden="true">HM</span><span class="t">Home</span><span class="ic" title="Personal"><svg class="i sm" aria-hidden="true"><use href="#i-home"/></svg></span></a>
</div>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Projects</span><span class="seg xs" role="group" aria-label="Project layout"><span aria-pressed="true">By org</span><span aria-pressed="false">Flat</span></span></div>
<div class="pgroup" data-org="ddigital"><div class="pgroup-h"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span>Distinctly Digital</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Spring launch</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">The Lantern Coast</span><span class="dot s-waiting" title="waiting"><b aria-hidden="true">◐</b><span class="sr">waiting</span></span></a><a class="nav proj" href="#"><span class="t">Brand refresh</span></a><a class="nav proj" href="#"><span class="t">Monthly newsletter</span></a></div></div>
<div class="pgroup" data-org="forge"><div class="pgroup-h"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span>Forge</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">API gateway</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">Web app</span><span class="dot s-error" title="error"><b aria-hidden="true">▲</b><span class="sr">error</span></span></a><a class="nav proj" href="#"><span class="t">CLI tools</span><span class="n">paused</span></a></div></div>
<div class="pgroup" data-org="home"><div class="pgroup-h"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span>Home</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Household admin</span><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span></a><a class="nav proj" href="#"><span class="t">Garden plan</span></a><a class="nav proj" href="#"><span class="t">Trip planning 2027</span><span class="n">paused</span></a></div></div>
</div>
<div class="foot"><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-settings"/></svg><span class="t">Settings</span></a></div>
</nav>
<nav class="strip" aria-label="Sections"><a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a><a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a><a class="nav" href="06-tasks.html" aria-current="page"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a><a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a><a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a><a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a></nav>
<main class="main ">
<div class="vh"><h1>Tasks</h1><div class="right"><span class="seg" role="group" aria-label="Layout"><span aria-pressed="true" class="kb">Kanban</span><span aria-pressed="false" class="ls">List</span></span><span class="btn"><svg class="i" aria-hidden="true"><use href="#i-plus"/></svg>New task</span></div>
<p class="sub">12 tasks from 3 organizations. Each organization keeps its own task store; this view reads all of them and writes each change back to the store it came from.</p></div>
<div class="trackers"><span class="label">Trackers</span><span><span class="av " data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital <span class="trk vik">Vikunja</span></span><span><span class="av " data-org="forge" aria-hidden="true">FG</span>Forge <span class="trk">built-in</span></span><span><span class="av " data-org="home" aria-hidden="true">HM</span>Home <span class="trk">built-in</span></span><span class="note">Ids keep their tracker's form: V-112 is Vikunja, #41 is built in. Archiving an organization removes only its tasks.</span></div>
<div class="toolbar">
<div class="chips" role="group" aria-label="Organization"><span class="f plain" aria-pressed="true">All <span class="n">12</span></span><span class="f" aria-pressed="false"><span class="av " data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital<span class="n">5</span></span><span class="f" aria-pressed="false"><span class="av " data-org="forge" aria-hidden="true">FG</span>Forge<span class="n">4</span></span><span class="f" aria-pressed="false"><span class="av " data-org="home" aria-hidden="true">HM</span>Home<span class="n">3</span></span></div>
<span class="sel"><span class="label">Project</span>All 10<svg class="i sm" aria-hidden="true"><use href="#i-chevron"/></svg></span>
<span class="sel"><span class="label">Assignee</span>Anyone<svg class="i sm" aria-hidden="true"><use href="#i-chevron"/></svg></span>
<div class="right"><span class="search"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-search"/></svg>Find a task</span></div>
</div>
<div class="board">
<section class="col"><div class="col-h"><h3>To do</h3><span class="n">5</span><span class="mix" title="Organizations in this column"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span class="av xs" data-org="home" aria-hidden="true">HM</span></span></div><article class="kcard edge" data-org="forge">
<div class="top"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span class="id">#44</span><span class="trk">built-in</span></div>
<div class="tt">Settings page: model picker</div>
<div class="bot"><span>Web app</span></div>
</article><article class="kcard edge" data-org="ddigital">
<div class="top"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span class="id">V-120</span><span class="trk vik">Vikunja</span></div>
<div class="tt">Logo shortlist</div>
<div class="bot"><span>Brand refresh</span></div>
</article><article class="kcard edge" data-org="ddigital">
<div class="top"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span class="id">V-121</span><span class="trk vik">Vikunja</span></div>
<div class="tt">November issue outline</div>
<div class="bot"><span>Monthly newsletter</span></div>
</article><article class="kcard edge you" data-org="home">
<div class="top"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span class="id">#12</span><span class="trk">built-in</span></div>
<div class="tt">Insurance renewal comparison</div>
<div class="bot"><span>Household admin</span><span class="chip warn">needs you</span></div>
</article><article class="kcard edge" data-org="home">
<div class="top"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span class="id">#14</span><span class="trk">built-in</span></div>
<div class="tt">Shortlist ferry dates</div>
<div class="bot"><span>Trip planning 2027</span></div>
</article></section>
<section class="col"><div class="col-h"><h3>In progress</h3><span class="n">3</span><span class="mix" title="Organizations in this column"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span></span></div><article class="kcard edge" data-org="forge">
<div class="top"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span class="id">#41</span><span class="trk">built-in</span></div>
<div class="tt">Rate limiter: per-key buckets</div>
<div class="bot"><span>API gateway</span><span class="dot s-working"><b aria-hidden="true">●</b>coder</span></div>
</article><article class="kcard edge" data-org="ddigital">
<div class="top"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span class="id">V-112</span><span class="trk vik">Vikunja</span></div>
<div class="tt">Launch email, draft 2</div>
<div class="bot"><span>Spring launch</span><span class="dot s-working"><b aria-hidden="true">●</b>copywriter</span></div>
</article><article class="kcard edge" data-org="ddigital">
<div class="top"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span class="id">V-118</span><span class="trk vik">Vikunja</span></div>
<div class="tt">Teaser reel, 30 s cut</div>
<div class="bot"><span>Spring launch</span><span class="dot s-working"><b aria-hidden="true">●</b>montage-producer</span></div>
</article></section>
<section class="col"><div class="col-h"><h3>Review</h3><span class="n">2</span><span class="mix" title="Organizations in this column"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span></span></div><article class="kcard edge" data-org="forge">
<div class="top"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span class="id">#38</span><span class="trk">built-in</span></div>
<div class="tt">Load test at 2k rps</div>
<div class="bot"><span>API gateway</span><span class="dot s-idle"><b aria-hidden="true">–</b>reviewer</span></div>
</article><article class="kcard edge" data-org="ddigital">
<div class="top"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span class="id">V-97</span><span class="trk vik">Vikunja</span></div>
<div class="tt">Chapter 7 revision</div>
<div class="bot"><span>The Lantern Coast</span><span class="dot s-waiting"><b aria-hidden="true">◐</b>editor, on you</span></div>
</article></section>
<section class="col"><div class="col-h"><h3>Done</h3><span class="n">2</span><span class="mix" title="Organizations in this column"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span class="av xs" data-org="home" aria-hidden="true">HM</span></span></div><article class="kcard edge" data-org="forge">
<div class="top"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span class="id">#29</span><span class="trk">built-in</span></div>
<div class="tt">zsh completion</div>
<div class="bot"><span>CLI tools</span></div>
</article><article class="kcard edge" data-org="home">
<div class="top"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span class="id">#9</span><span class="trk">built-in</span></div>
<div class="tt">Order seed potatoes</div>
<div class="bot"><span>Garden plan</span></div>
</article></section>
</div>
<section class="tasklist">
<div class="sec-h"><h2>List layout</h2><span class="note">same filters, one row per task, grouped by state</span></div>
<div class="tbl"><table><thead><tr><th>Org</th><th>Id</th><th>Task</th><th class="hide-m">Project</th><th>State</th><th class="hide-m">Assignee</th></tr></thead><tbody>
<tr class="edge" data-org="forge"><td><span class="av " data-org="forge" aria-hidden="true">FG</span></td><td class="mono">#44<span class="t2">built-in</span></td><td><span class="t1">Settings page: model picker</span><span class="t2 show-m">Web app</span></td><td class="hide-m">Web app</td><td>To do</td><td class="hide-m"><span class="muted">nobody</span></td></tr><tr class="edge" data-org="ddigital"><td><span class="av " data-org="ddigital" aria-hidden="true">DD</span></td><td class="mono">V-120<span class="t2">Vikunja</span></td><td><span class="t1">Logo shortlist</span><span class="t2 show-m">Brand refresh</span></td><td class="hide-m">Brand refresh</td><td>To do</td><td class="hide-m"><span class="muted">nobody</span></td></tr><tr class="edge" data-org="ddigital"><td><span class="av " data-org="ddigital" aria-hidden="true">DD</span></td><td class="mono">V-121<span class="t2">Vikunja</span></td><td><span class="t1">November issue outline</span><span class="t2 show-m">Monthly newsletter</span></td><td class="hide-m">Monthly newsletter</td><td>To do</td><td class="hide-m"><span class="muted">nobody</span></td></tr><tr class="edge" data-org="home"><td><span class="av " data-org="home" aria-hidden="true">HM</span></td><td class="mono">#12<span class="t2">built-in</span></td><td><span class="t1">Insurance renewal comparison</span><span class="t2 show-m">Household admin</span></td><td class="hide-m">Household admin</td><td>To do</td><td class="hide-m"><span class="chip warn">you</span></td></tr><tr class="edge" data-org="home"><td><span class="av " data-org="home" aria-hidden="true">HM</span></td><td class="mono">#14<span class="t2">built-in</span></td><td><span class="t1">Shortlist ferry dates</span><span class="t2 show-m">Trip planning 2027</span></td><td class="hide-m">Trip planning 2027</td><td>To do</td><td class="hide-m"><span class="muted">nobody</span></td></tr><tr class="edge" data-org="forge"><td><span class="av " data-org="forge" aria-hidden="true">FG</span></td><td class="mono">#41<span class="t2">built-in</span></td><td><span class="t1">Rate limiter: per-key buckets</span><span class="t2 show-m">API gateway</span></td><td class="hide-m">API gateway</td><td>In progress</td><td class="hide-m"><span class="dot s-working"><b aria-hidden="true">●</b>coder</span></td></tr><tr class="edge" data-org="ddigital"><td><span class="av " data-org="ddigital" aria-hidden="true">DD</span></td><td class="mono">V-112<span class="t2">Vikunja</span></td><td><span class="t1">Launch email, draft 2</span><span class="t2 show-m">Spring launch</span></td><td class="hide-m">Spring launch</td><td>In progress</td><td class="hide-m"><span class="dot s-working"><b aria-hidden="true">●</b>copywriter</span></td></tr><tr class="edge" data-org="ddigital"><td><span class="av " data-org="ddigital" aria-hidden="true">DD</span></td><td class="mono">V-118<span class="t2">Vikunja</span></td><td><span class="t1">Teaser reel, 30 s cut</span><span class="t2 show-m">Spring launch</span></td><td class="hide-m">Spring launch</td><td>In progress</td><td class="hide-m"><span class="dot s-working"><b aria-hidden="true">●</b>montage-producer</span></td></tr><tr class="edge" data-org="forge"><td><span class="av " data-org="forge" aria-hidden="true">FG</span></td><td class="mono">#38<span class="t2">built-in</span></td><td><span class="t1">Load test at 2k rps</span><span class="t2 show-m">API gateway</span></td><td class="hide-m">API gateway</td><td>Review</td><td class="hide-m"><span class="dot s-idle"><b aria-hidden="true">–</b>reviewer</span></td></tr><tr class="edge" data-org="ddigital"><td><span class="av " data-org="ddigital" aria-hidden="true">DD</span></td><td class="mono">V-97<span class="t2">Vikunja</span></td><td><span class="t1">Chapter 7 revision</span><span class="t2 show-m">The Lantern Coast</span></td><td class="hide-m">The Lantern Coast</td><td>Review</td><td class="hide-m"><span class="dot s-waiting"><b aria-hidden="true">◐</b>editor</span></td></tr><tr class="edge dim" data-org="forge"><td><span class="av " data-org="forge" aria-hidden="true">FG</span></td><td class="mono">#29<span class="t2">built-in</span></td><td><span class="t1">zsh completion</span><span class="t2 show-m">CLI tools</span></td><td class="hide-m">CLI tools</td><td>Done</td><td class="hide-m"><span class="muted">nobody</span></td></tr><tr class="edge dim" data-org="home"><td><span class="av " data-org="home" aria-hidden="true">HM</span></td><td class="mono">#9<span class="t2">built-in</span></td><td><span class="t1">Order seed potatoes</span><span class="t2 show-m">Garden plan</span></td><td class="hide-m">Garden plan</td><td>Done</td><td class="hide-m"><span class="muted">nobody</span></td></tr>
</tbody></table></div>
</section>
</main>
</div>
</body>
</html>
@@ -0,0 +1,88 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Side by side · U0 sample</title>
<link rel="stylesheet" href="workspace.css">
</head>
<body>
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false"><symbol id="i-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol><symbol id="i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 10.5 12 4l8 6.5"/><path d="M6 9v10.5h12V9"/><path d="M10 19.5v-5h4v5"/></symbol><symbol id="i-folder" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 6.5a1 1 0 0 1 1-1h4.5l2 2h8.5a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1h-15a1 1 0 0 1-1-1z"/></symbol><symbol id="i-columns" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M12 4.5v15"/></symbol><symbol id="i-split" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M13 4.5v15M16.75 10.5v3M15.25 12h3"/></symbol><symbol id="i-restart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3"/><path d="M19.5 4.5v4h-4"/></symbol><symbol id="i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></symbol><symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/></symbol><symbol id="i-doc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 3.5h7l4 4v13h-11z"/><path d="M13.5 3.5v4h4M9 12h6M9 15.5h6"/></symbol></svg>
<div class="app ">
<header class="cmdbar">
<button class="menu" aria-label="Open navigation" aria-expanded="false"><svg class="i" aria-hidden="true"><use href="#i-menu"/></svg></button>
<a class="mk" href="02-dashboard.html"><svg class="mosaic-logo" viewBox="0 0 36 36" aria-hidden="true"><rect x="3" y="12" width="13" height="10" rx="2"/><rect x="18" y="3" width="13" height="12" rx="2"/><rect x="3" y="24" width="13" height="10" rx="2"/><rect x="18" y="17" width="13" height="12" rx="2"/></svg><span>Mosaic Stack</span></a>
<span class="sim" title="Static design sample">U0 sample</span>
<button class="cmdk"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-search"/></svg><span>Go to an org, project, task or decision</span><kbd>Ctrl K</kbd></button>
<div class="fresh"><span class="wide">Read <b>3 of 3</b> organization buses · 4 s ago</span><span class="me" title="Operator">OP</span></div>
</header>
<nav class="side" aria-label="Workspace">
<a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a>
<a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a>
<a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a>
<a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a>
<a class="nav" href="07-side-by-side.html" aria-current="page"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a>
<a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a>
<a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Organizations</span><span class="n">3</span><span class="add" title="New organization"><svg class="i sm" aria-hidden="true"><use href="#i-plus"/></svg></span></div>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="t">Distinctly Digital</span><span class="ic" title="Business"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="t">Forge</span><span class="ic" title="Coding"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-term"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="home" aria-hidden="true">HM</span><span class="t">Home</span><span class="ic" title="Personal"><svg class="i sm" aria-hidden="true"><use href="#i-home"/></svg></span></a>
</div>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Projects</span><span class="seg xs" role="group" aria-label="Project layout"><span aria-pressed="true">By org</span><span aria-pressed="false">Flat</span></span></div>
<div class="pgroup" data-org="ddigital"><div class="pgroup-h"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span>Distinctly Digital</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Spring launch</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">The Lantern Coast</span><span class="dot s-waiting" title="waiting"><b aria-hidden="true">◐</b><span class="sr">waiting</span></span></a><a class="nav proj" href="#"><span class="t">Brand refresh</span></a><a class="nav proj" href="#"><span class="t">Monthly newsletter</span></a></div></div>
<div class="pgroup" data-org="forge"><div class="pgroup-h"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span>Forge</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">API gateway</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">Web app</span><span class="dot s-error" title="error"><b aria-hidden="true">▲</b><span class="sr">error</span></span></a><a class="nav proj" href="#"><span class="t">CLI tools</span><span class="n">paused</span></a></div></div>
<div class="pgroup" data-org="home"><div class="pgroup-h"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span>Home</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Household admin</span><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span></a><a class="nav proj" href="#"><span class="t">Garden plan</span></a><a class="nav proj" href="#"><span class="t">Trip planning 2027</span><span class="n">paused</span></a></div></div>
</div>
<div class="foot"><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-settings"/></svg><span class="t">Settings</span></a></div>
</nav>
<nav class="strip" aria-label="Sections"><a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a><a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a><a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a><a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a><a class="nav" href="07-side-by-side.html" aria-current="page"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a><a class="nav" href="08-agents.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a></nav>
<main class="main flush">
<div class="panebar"><h1>Side by side</h1><span class="note">2 panes · each pane reads its own organization's bus and keeps its own state</span>
<span class="seg pane-tabs" role="group" aria-label="Shown pane"><span aria-pressed="true"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span> Spring launch</span><span aria-pressed="false"><span class="av xs" data-org="forge" aria-hidden="true">FG</span> API gateway</span></span>
<span class="btn hide-m" style="margin-left:auto"><svg class="i" aria-hidden="true"><use href="#i-plus"/></svg>Add pane</span></div>
<div class="panes">
<section class="pane" data-org="ddigital">
<div class="pane-h"><span class="av md" data-org="ddigital" aria-hidden="true">DD</span><span class="ttl">Spring launch<small>Distinctly Digital</small></span><span class="tools"><span title="Open in full view"><svg class="i sm" aria-hidden="true"><use href="#i-split"/></svg></span><span title="Close pane"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-close"/></svg></span></span></div>
<div class="pane-body">
<div class="subtabs"><span aria-current="page">Overview</span><span>Tasks</span><span>Sessions</span><span>Docs</span></div>
<div class="grid g3 mini-tiles"><div class="tile"><span class="label">Open tasks</span><span class="big">2</span></div><div class="tile"><span class="label">Sessions</span><span class="big">2<small>working</small></span></div><div class="tile"><span class="label">Needs you</span><span class="big">0</span></div></div>
<div class="sec-h"><h3>copywriter · live</h3><span class="note">V-112 Launch email, draft 2</span></div>
<pre class="term"><span class="m">14:26</span> read brand-voice.md, launch-plan.md
<span class="m">14:27</span> drafted subject lines (3), kept the shortest
<span class="m">14:28</span> saved drafts/launch-email-v2.md 182 words
<span class="m">14:29</span> next: tighten the call to action
<span class="c">▍</span></pre>
<div class="sec-h"><h3>montage-producer · live</h3><span class="note">V-118 Teaser reel</span></div>
<pre class="term"><span class="m">13:55</span> rendered cut 3 of 4 00:30 1080x1920
<span class="m">14:10</span> waiting on the music bed licence check
<span class="c">▍</span></pre>
<div class="sec-h"><h3>Activity</h3></div>
<ol class="trail"><li><time>14:28</time><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="what"><b>copywriter</b> saved V-112 Launch email, draft 2 <span class="src">· Distinctly Digital · Spring launch</span></span></li><li><time>13:55</time><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="what"><b>montage-producer</b> rendered teaser cut 3 of 4 <span class="src">· Distinctly Digital · Spring launch</span></span></li><li><time>11:20</time><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="what"><b>chief</b> updated the launch plan <span class="src">· Distinctly Digital · Spring launch</span></span></li></ol></div>
</section>
<section class="pane alt" data-org="forge">
<div class="pane-h"><span class="av md" data-org="forge" aria-hidden="true">FG</span><span class="ttl">API gateway<small>Forge</small></span><span class="tools"><span title="Open in full view"><svg class="i sm" aria-hidden="true"><use href="#i-split"/></svg></span><span title="Close pane"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-close"/></svg></span></span></div>
<div class="pane-body">
<div class="subtabs"><span aria-current="page">Overview</span><span>Tasks</span><span>Sessions</span><span>Docs</span></div>
<div class="grid g3 mini-tiles"><div class="tile"><span class="label">Open tasks</span><span class="big">2</span></div><div class="tile"><span class="label">Sessions</span><span class="big">1<small>working</small></span></div><div class="tile"><span class="label">Needs you</span><span class="big">1<small>gated</small></span></div></div>
<ul class="needs" style="margin-top:12px"><li class="edge" data-org="forge"><span class="av md" data-org="forge" aria-hidden="true">FG</span><span class="q">Merge the rate limiter branch into main?</span><span class="src">chief · 52 min · <a href="05-inbox.html">Open in inbox</a></span><span class="chip gated">gated</span></li></ul>
<div class="sec-h"><h3>coder · live</h3><span class="note">#41 Rate limiter: per-key buckets</span></div>
<pre class="term"><span class="m">14:30</span> npm test 312 passed, 0 failed
<span class="m">14:31</span> bench: 2,140 rps at p99 41 ms
<span class="m">14:32</span> pushed 3 commits to rate-limiter-41
<span class="m">14:32</span> waiting for review
<span class="c">▍</span></pre>
<div class="sec-h"><h3>Activity</h3></div>
<ol class="trail"><li><time>14:32</time><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="what"><b>coder</b> pushed 3 commits on #41 Rate limiter <span class="src">· Forge · API gateway</span></span></li><li><time>13:40</time><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="what"><b>chief</b> raised a gated decision: merge the rate limiter <span class="src">· Forge · API gateway</span></span></li><li><time>12:40</time><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="what"><b>load-tester</b> finished run 7 of 7 <span class="src">· Forge · API gateway</span></span></li></ol></div>
</section>
</div>
</main>
</div>
</body>
</html>
@@ -0,0 +1,86 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Agents · U0 sample</title>
<link rel="stylesheet" href="workspace.css">
</head>
<body>
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false"><symbol id="i-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol><symbol id="i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 10.5 12 4l8 6.5"/><path d="M6 9v10.5h12V9"/><path d="M10 19.5v-5h4v5"/></symbol><symbol id="i-folder" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 6.5a1 1 0 0 1 1-1h4.5l2 2h8.5a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1h-15a1 1 0 0 1-1-1z"/></symbol><symbol id="i-columns" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M12 4.5v15"/></symbol><symbol id="i-split" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="1.5"/><path d="M13 4.5v15M16.75 10.5v3M15.25 12h3"/></symbol><symbol id="i-restart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3"/><path d="M19.5 4.5v4h-4"/></symbol><symbol id="i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></symbol><symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/></symbol><symbol id="i-doc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 3.5h7l4 4v13h-11z"/><path d="M13.5 3.5v4h4M9 12h6M9 15.5h6"/></symbol></svg>
<div class="app ">
<header class="cmdbar">
<button class="menu" aria-label="Open navigation" aria-expanded="false"><svg class="i" aria-hidden="true"><use href="#i-menu"/></svg></button>
<a class="mk" href="02-dashboard.html"><svg class="mosaic-logo" viewBox="0 0 36 36" aria-hidden="true"><rect x="3" y="12" width="13" height="10" rx="2"/><rect x="18" y="3" width="13" height="12" rx="2"/><rect x="3" y="24" width="13" height="10" rx="2"/><rect x="18" y="17" width="13" height="12" rx="2"/></svg><span>Mosaic Stack</span></a>
<span class="sim" title="Static design sample">U0 sample</span>
<button class="cmdk"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-search"/></svg><span>Go to an org, project, task or decision</span><kbd>Ctrl K</kbd></button>
<div class="fresh"><span class="wide">Read <b>3 of 3</b> organization buses · 4 s ago</span><span class="me" title="Operator">OP</span></div>
</header>
<nav class="side" aria-label="Workspace">
<a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a>
<a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a>
<a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a>
<a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a>
<a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a>
<a class="nav" href="08-agents.html" aria-current="page"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a>
<a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Organizations</span><span class="n">3</span><span class="add" title="New organization"><svg class="i sm" aria-hidden="true"><use href="#i-plus"/></svg></span></div>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="t">Distinctly Digital</span><span class="ic" title="Business"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-business"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="t">Forge</span><span class="ic" title="Coding"><svg class="i sm" aria-hidden="true"><use href="../../icons.svg#i-term"/></svg></span></a>
<a class="nav org-row" href="03-org-dashboard.html"><span class="av " data-org="home" aria-hidden="true">HM</span><span class="t">Home</span><span class="ic" title="Personal"><svg class="i sm" aria-hidden="true"><use href="#i-home"/></svg></span></a>
</div>
<hr>
<div class="grp">
<div class="grp-h" role="button" aria-expanded="true"><svg class="i chev" aria-hidden="true"><use href="#i-chevron"/></svg><span class="label">Projects</span><span class="seg xs" role="group" aria-label="Project layout"><span aria-pressed="true">By org</span><span aria-pressed="false">Flat</span></span></div>
<div class="pgroup" data-org="ddigital"><div class="pgroup-h"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span><span>Distinctly Digital</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Spring launch</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">The Lantern Coast</span><span class="dot s-waiting" title="waiting"><b aria-hidden="true">◐</b><span class="sr">waiting</span></span></a><a class="nav proj" href="#"><span class="t">Brand refresh</span></a><a class="nav proj" href="#"><span class="t">Monthly newsletter</span></a></div></div>
<div class="pgroup" data-org="forge"><div class="pgroup-h"><span class="av xs" data-org="forge" aria-hidden="true">FG</span><span>Forge</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">API gateway</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span></a><a class="nav proj" href="#"><span class="t">Web app</span><span class="dot s-error" title="error"><b aria-hidden="true">▲</b><span class="sr">error</span></span></a><a class="nav proj" href="#"><span class="t">CLI tools</span><span class="n">paused</span></a></div></div>
<div class="pgroup" data-org="home"><div class="pgroup-h"><span class="av xs" data-org="home" aria-hidden="true">HM</span><span>Home</span></div><div class="projs"><a class="nav proj" href="#"><span class="t">Household admin</span><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span></a><a class="nav proj" href="#"><span class="t">Garden plan</span></a><a class="nav proj" href="#"><span class="t">Trip planning 2027</span><span class="n">paused</span></a></div></div>
</div>
<div class="foot"><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-settings"/></svg><span class="t">Settings</span></a></div>
</nav>
<nav class="strip" aria-label="Sections"><a class="nav" href="02-dashboard.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-board"/></svg><span class="t">Dashboard</span></a><a class="nav" href="05-inbox.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-inbox"/></svg><span class="t">Inbox</span><span class="n hot">3</span></a><a class="nav" href="06-tasks.html"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-tasks"/></svg><span class="t">Tasks</span><span class="n">10</span></a><a class="nav" href="04-projects.html"><svg class="i" aria-hidden="true"><use href="#i-folder"/></svg><span class="t">Projects</span><span class="n">10</span></a><a class="nav" href="07-side-by-side.html"><svg class="i" aria-hidden="true"><use href="#i-columns"/></svg><span class="t">Side by side</span></a><a class="nav" href="08-agents.html" aria-current="page"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-agents"/></svg><span class="t">Agents</span></a><a class="nav" href="#"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-talk"/></svg><span class="t">Assistant</span><span class="dot s-working" title="working"><b aria-hidden="true">●</b></span></a></nav>
<main class="main ">
<div class="vh"><h1>Agents</h1><div class="right"><span class="btn"><svg class="i" aria-hidden="true"><use href="../../icons.svg#i-settings"/></svg>Edit root agents</span></div>
<p class="sub">Agents are defined at three levels. A project can use the union of your root agents, its organization's agents and its own. Every agent except the assistant works inside one organization.</p></div>
<div class="span-band"><span class="av all md" aria-hidden="true" title="Assistant, all organizations"><svg class="mosaic-logo" viewBox="0 0 36 36" style="width:70%;height:auto" aria-hidden="true"><rect x="3" y="12" width="13" height="10" rx="2"/><rect x="18" y="3" width="13" height="12" rx="2"/><rect x="3" y="24" width="13" height="10" rx="2"/><rect x="18" y="17" width="13" height="12" rx="2"/></svg></span><b>assistant</b><span class="lvl root">root</span><span class="dot s-working"><b aria-hidden="true">●</b>working</span><span>Works across</span><span class="orgs"><span class="av " data-org="ddigital" aria-hidden="true">DD</span><span class="av " data-org="forge" aria-hidden="true">FG</span><span class="av " data-org="home" aria-hidden="true">HM</span></span><span class="muted">One shared memory. Talks with you and hands each organization's work to its chief; it does not direct agents, create tasks or launch sessions.</span></div>
<div class="levels" style="margin-top:12px">
<div class="lh hide-m"></div><div class="oh hide-m" data-org="ddigital"><span class="av " data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital</div><div class="oh hide-m" data-org="forge"><span class="av " data-org="forge" aria-hidden="true">FG</span>Forge</div><div class="oh hide-m" data-org="home"><span class="av " data-org="home" aria-hidden="true">HM</span>Home</div>
<div class="lh"><span class="lvl root">root</span><small>Your root configuration. Only you change it. Each organization runs its own copy, with memory, files and credentials kept in that organization.</small></div>
<div data-org="ddigital"><span class="mlabel"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital</span><span class="agent "><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span>reviewer <small>copy</small></span><span class="agent "><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span>researcher <small>copy</small></span></div>
<div data-org="forge"><span class="mlabel"><span class="av xs" data-org="forge" aria-hidden="true">FG</span>Forge</span><span class="agent "><span class="dot s-error" title="error"><b aria-hidden="true">▲</b><span class="sr">error</span></span>reviewer <small>copy</small></span><span class="agent "><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span>researcher <small>copy</small></span></div>
<div data-org="home"><span class="mlabel"><span class="av xs" data-org="home" aria-hidden="true">HM</span>Home</span><span class="agent "><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span>researcher <small>copy</small></span><span class="note" style="display:block;margin-top:4px">reviewer turned off for Home</span></div>
<div class="lh"><span class="lvl org">org</span><small>Defined in the organization file. The chief hires and fires here; you can override any setting.</small></div>
<div data-org="ddigital"><span class="mlabel"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital</span><span class="agent cos"><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span>chief</span><span class="agent "><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span>copywriter</span><span class="agent "><span class="dot s-waiting" title="waiting"><b aria-hidden="true">◐</b><span class="sr">waiting</span></span>editor</span><span class="agent "><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span>montage-producer</span></div>
<div data-org="forge"><span class="mlabel"><span class="av xs" data-org="forge" aria-hidden="true">FG</span>Forge</span><span class="agent cos"><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span>chief</span><span class="agent "><span class="dot s-working" title="working"><b aria-hidden="true">●</b><span class="sr">working</span></span>coder</span></div>
<div data-org="home"><span class="mlabel"><span class="av xs" data-org="home" aria-hidden="true">HM</span>Home</span><span class="agent cos"><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span>chief</span><span class="agent "><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span>planner</span></div>
<div class="lh last"><span class="lvl proj">project</span><small>Defined in one project and available only there. The chief hires and fires here too.</small></div>
<div class="last" data-org="ddigital"><span class="mlabel"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span>Distinctly Digital</span><span class="agent "><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span>social-scheduler <small>Spring launch</small></span><span class="agent "><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span>continuity-checker <small>The Lantern Coast</small></span></div>
<div class="last" data-org="forge"><span class="mlabel"><span class="av xs" data-org="forge" aria-hidden="true">FG</span>Forge</span><span class="agent "><span class="dot s-idle" title="idle"><b aria-hidden="true">–</b><span class="sr">idle</span></span>load-tester <small>API gateway</small></span></div>
<div class="last" data-org="home"><span class="mlabel"><span class="av xs" data-org="home" aria-hidden="true">HM</span>Home</span><span class="muted">none</span></div>
</div>
<div class="split" style="margin-top:4px">
<section>
<div class="sec-h"><h2>Available in a project</h2><span class="sel"><span class="av xs" data-org="ddigital" aria-hidden="true">DD</span>Spring launch<svg class="i sm" aria-hidden="true"><use href="#i-chevron"/></svg></span></div>
<div class="tbl"><table><thead><tr><th>Agent</th><th>Level</th><th class="hide-m">Defined in</th><th class="hide-m">Memory</th><th>Status</th><th class="hide-m">Model</th></tr></thead><tbody>
<tr><td class="t1">assistant</td><td><span class="lvl root">root</span></td><td class="hide-m">Your root configuration</td><td class="hide-m">Shared across all organizations</td><td><span class="dot s-working"><b aria-hidden="true">●</b>working</span></td><td class="hide-m mono">opus-5.5 <a href="#">Change</a></td></tr><tr><td class="t1">reviewer</td><td><span class="lvl root">root</span></td><td class="hide-m">Your root configuration</td><td class="hide-m">This organization only</td><td><span class="dot s-idle"><b aria-hidden="true">–</b>idle</span></td><td class="hide-m mono">sonnet-5.5 <a href="#">Change</a></td></tr><tr><td class="t1">researcher</td><td><span class="lvl root">root</span></td><td class="hide-m">Your root configuration</td><td class="hide-m">This organization only</td><td><span class="dot s-idle"><b aria-hidden="true">–</b>idle</span></td><td class="hide-m mono">sonnet-5.5 <a href="#">Change</a></td></tr><tr><td class="t1">chief</td><td><span class="lvl org">org</span></td><td class="hide-m">Distinctly Digital file</td><td class="hide-m">This organization only</td><td><span class="dot s-idle"><b aria-hidden="true">–</b>idle</span></td><td class="hide-m mono">opus-5.5 <a href="#">Change</a></td></tr><tr><td class="t1">copywriter</td><td><span class="lvl org">org</span></td><td class="hide-m">Distinctly Digital file</td><td class="hide-m">This organization only</td><td><span class="dot s-working"><b aria-hidden="true">●</b>working</span></td><td class="hide-m mono">sonnet-5.5 <a href="#">Change</a></td></tr><tr><td class="t1">editor</td><td><span class="lvl org">org</span></td><td class="hide-m">Distinctly Digital file</td><td class="hide-m">This organization only</td><td><span class="dot s-waiting"><b aria-hidden="true">◐</b>waiting</span></td><td class="hide-m mono">opus-5.5 <a href="#">Change</a></td></tr><tr><td class="t1">montage-producer</td><td><span class="lvl org">org</span></td><td class="hide-m">Distinctly Digital file</td><td class="hide-m">This organization only</td><td><span class="dot s-working"><b aria-hidden="true">●</b>working</span></td><td class="hide-m mono">sonnet-5.5 <a href="#">Change</a></td></tr><tr><td class="t1">social-scheduler</td><td><span class="lvl proj">project</span></td><td class="hide-m">Spring launch project</td><td class="hide-m">This organization only</td><td><span class="dot s-idle"><b aria-hidden="true">–</b>idle</span></td><td class="hide-m mono">haiku-5.5 <a href="#">Change</a></td></tr>
</tbody></table></div>
<p class="note" style="margin-top:8px">Not available here: continuity-checker (The Lantern Coast only) and every Forge or Home agent.</p>
</section>
<section>
<div class="sec-h"><h2>Who changes what</h2></div>
<div class="panel tight rules">
<p><span class="lvl root">root</span> You add, change and remove root agents. The chief cannot.</p>
<p><span class="lvl org">org</span> <span class="lvl proj">project</span> The chief hires and fires to meet your needs, within the role rules. Each hire lands in the trail.</p>
<p><span class="lvl proj">override</span> You can change any agent's settings at any level, at any time. An override shows where it was set.</p>
<p class="note">Changing an agent's model is a trailed human action, applied to its running session on reload.</p>
</div>
</section>
</div>
</main>
</div>
</body>
</html>
@@ -0,0 +1,92 @@
// Renders the U0 samples to PNG with headless Chromium: every page at 1440x900 and 390x844,
// light and dark (prefers-color-scheme, no data-mode), 32 shots for 8 pages.
// Usage: node render.mjs <out-dir>
// Serves the repository over HTTP on 127.0.0.1, port 0, because Chromium refuses cross-file SVG
// <use> under file://. Only docs/design/ and the WebUI font directory are served.
// Checks each shot: no script error, no failed request, no sideways page scroll, fonts loaded.
import { createServer } from 'node:http';
import { readFile, mkdir } from 'node:fs/promises';
import { join, normalize, extname, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { browser } from '../../../../packages/webui/tests/browser.mjs';
const here = dirname(fileURLToPath(import.meta.url));
const repo = normalize(join(here, '../../../..'));
const out = process.argv[2];
if (!out) { console.error('usage: node render.mjs <out-dir>'); process.exit(2); }
await mkdir(out, { recursive: true });
const ALLOW = ['docs/design/', 'packages/webui/src/public/assets/fonts/'];
const TYPES = { '.html': 'text/html', '.css': 'text/css', '.svg': 'image/svg+xml', '.woff2': 'font/woff2', '.js': 'text/javascript' };
const failed = [];
const server = createServer(async (req, res) => {
const path = normalize(decodeURIComponent(new URL(req.url, 'http://x').pathname)).replace(/^\/+/, '');
if (path === 'favicon.ico') { res.writeHead(204).end(); return; }
if (path.includes('..') || !ALLOW.some((a) => path.startsWith(a))) { failed.push(`403 ${path}`); res.writeHead(403).end(); return; }
try {
const body = await readFile(join(repo, path));
res.writeHead(200, { 'content-type': TYPES[extname(path)] ?? 'application/octet-stream' }).end(body);
} catch { failed.push(`404 ${path}`); res.writeHead(404).end(); }
});
await new Promise((r) => server.listen(0, '127.0.0.1', r));
const base = `http://127.0.0.1:${server.address().port}/docs/design/samples/2026-11-09-unified-workspace/`;
const PAGES = ['01-sidebar', '02-dashboard', '03-org-dashboard', '04-projects', '05-inbox', '06-tasks', '07-side-by-side', '08-agents'];
const SIZES = [[1440, 900], [390, 844]];
const THEMES = ['light', 'dark'];
const CHECK = `(() => {
const vw = innerWidth, wide = [];
for (const el of document.querySelectorAll('body *')) {
const r = el.getBoundingClientRect();
if (!r.width || r.right <= vw + 1) continue;
let clipped = false;
for (let p = el.parentElement; p && p !== document.body; p = p.parentElement) {
const s = getComputedStyle(p);
if (/(auto|hidden|scroll|clip)/.test(s.overflowX) || s.position === 'fixed' && s.display === 'none') { clipped = true; break; }
}
if (!clipped && getComputedStyle(el).visibility !== 'hidden') wide.push(el.tagName.toLowerCase() + (el.className && typeof el.className === 'string' ? '.' + el.className.trim().split(/\\s+/).join('.') : ''));
}
const faces = [...document.fonts].map((f) => f.family.replace(/"/g, '') + ' ' + f.weight + ' ' + f.status);
return { sw: document.documentElement.scrollWidth, cw: document.documentElement.clientWidth, wide: wide.slice(0, 8), faces,
manrope800: document.fonts.check('800 16px Manrope'), dark: matchMedia('(prefers-color-scheme: dark)').matches,
canvas: getComputedStyle(document.body).backgroundColor };
})()`;
const b = await browser({ machine: false });
const errors = [];
b.on('Runtime.exceptionThrown', (p) => errors.push(p.exceptionDetails?.exception?.description ?? p.exceptionDetails?.text));
b.on('Runtime.consoleAPICalled', (p) => { if (p.type === 'error') errors.push(p.args.map((a) => a.value ?? a.description).join(' ')); });
const report = [];
let bad = 0;
try {
for (const [w, h] of SIZES) {
await b.viewport(w, h);
for (const theme of THEMES) {
await b.call('Emulation.setEmulatedMedia', { features: [{ name: 'prefers-color-scheme', value: theme }] });
for (const name of PAGES) {
errors.length = 0; failed.length = 0;
await b.navigate(base + name + '.html');
await new Promise((r) => setTimeout(r, 250));
const info = await b.evaluate(CHECK);
const file = `${name}-${w}-${theme}.png`;
await b.screenshot(join(out, file));
const problems = [];
if (errors.length) problems.push('script: ' + errors.join(' | '));
if (failed.length) problems.push('requests: ' + failed.join(', '));
if (info.sw > info.cw) problems.push(`sideways scroll ${info.sw}>${info.cw}`);
if (info.wide.length) problems.push('past the edge: ' + info.wide.join(', '));
if (info.faces.some((f) => !f.endsWith('loaded') && !f.endsWith('unloaded'))) problems.push('fonts: ' + info.faces.join(', '));
if (!info.faces.some((f) => f.startsWith('Manrope') && f.endsWith('loaded') && !f.endsWith('unloaded'))) problems.push('Manrope not loaded');
if (info.dark !== (theme === 'dark')) problems.push('theme emulation failed');
if (problems.length) bad++;
report.push({ file, canvas: info.canvas, problems });
}
}
}
} finally {
await b.close();
server.close();
}
for (const r of report) console.log(`${r.problems.length ? 'FAIL' : 'ok '} ${r.file} ${r.canvas}${r.problems.length ? '\n ' + r.problems.join('\n ') : ''}`);
console.log(`${report.length} shots, ${bad} with problems`);
process.exit(bad ? 1 : 0);
@@ -0,0 +1,450 @@
/* U0 unified workspace samples, 2026-11-09. Static mocks, not product code.
Colours, type, spacing and radii come from tokens.css. The few additions are marked EXT
and listed in the U0 design report; nothing here redefines a token. */
@import url("../../tokens.css");
/* Fonts: the WebUI's self-hosted files, so the samples render with no network. The four
manrope-*.woff2 files are one variable font (weights 200 to 800), so one face covers 400-800. */
@font-face{font-family:"Manrope";font-style:normal;font-weight:200 800;font-display:swap;src:url("../../../../packages/webui/src/public/assets/fonts/manrope-400.woff2") format("woff2")}
@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:400;font-display:swap;src:url("../../../../packages/webui/src/public/assets/fonts/jetbrains-mono-400.woff2") format("woff2")}
@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:500;font-display:swap;src:url("../../../../packages/webui/src/public/assets/fonts/jetbrains-mono-500.woff2") format("woff2")}
@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:700;font-display:swap;src:url("../../../../packages/webui/src/public/assets/fonts/jetbrains-mono-700.woff2") format("woff2")}
/* EXT 1: org identity colours. Each organization's mark takes the action colour of the palette
its theme uses (11-07 ruling 7), copied from tokens.json for the three sample palettes, with
that palette's onAction for the initials. The shell keeps the user's own palette. */
:root{--org-grove:#377752;--org-rosewood:#a53b72;--org-atlantic:#19719a;--org-on:#ffffff}
@media (prefers-color-scheme:dark){:root:not([data-mode="light"]):not([data-mode="dim"]){--org-grove:#8fcca9;--org-rosewood:#d487af;--org-atlantic:#73c3e8;--org-on:#10141a}}
:root[data-mode="dark"]{--org-grove:#8fcca9;--org-rosewood:#d487af;--org-atlantic:#73c3e8;--org-on:#10141a}
:root[data-mode="dim"]{--org-grove:#8fcca9;--org-rosewood:#dc9ebe;--org-atlantic:#73c3e8;--org-on:#10141a}
[data-org="home"]{--org:var(--org-grove)}
[data-org="ddigital"]{--org:var(--org-rosewood)}
[data-org="forge"]{--org:var(--org-atlantic)}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
html,body{height:100%}
body{margin:0;background:var(--canvas);color:var(--text);font:400 14px/1.5 var(--font)}
h1,h2,h3,h4{color:var(--strong);margin:0;line-height:1.2;text-wrap:balance}
p{margin:0}
a{color:var(--action)}
code,kbd,.mono{font-family:var(--mono);font-size:12.5px}
kbd{border:1px solid var(--line);border-bottom-width:2px;border-radius:4px;padding:0 .35em;background:var(--surface);color:var(--strong);white-space:nowrap;font-size:11px}
button,select,input{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
.tnum{font-variant-numeric:tabular-nums}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
svg.i{width:18px;height:18px;flex:none;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}
svg.i.sm{width:15px;height:15px}
.label{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.note{font-size:13px;color:var(--muted)}
.muted{color:var(--muted)}
.sim{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--accent);border:1px dashed var(--accent);border-radius:4px;padding:0 5px;white-space:nowrap}
/* ---------- shell: command bar, section list, main, inspector (d3 layout) ---------- */
.app{display:grid;grid-template-columns:240px minmax(0,1fr);grid-template-rows:auto minmax(0,1fr);height:100vh}
.app.with-insp{grid-template-columns:240px minmax(0,1fr) minmax(300px,360px)}
.cmdbar{grid-column:1/-1;display:flex;align-items:center;gap:12px;padding:8px 14px;border-bottom:1px solid var(--line);background:var(--surface);min-width:0}
.cmdbar .mk{display:flex;align-items:center;gap:8px;font-weight:800;color:var(--strong);letter-spacing:-.01em;white-space:nowrap;text-decoration:none}
.cmdbar .mk svg{width:24px;height:auto}
/* The WebUI's temporary four-tile logo (index.html, processing.css), kept by owner ruling 11-09 until a real mark is chosen. */
.mosaic-logo{flex:none;fill:var(--action)}.mosaic-logo rect:nth-child(2){fill:color-mix(in srgb,var(--action) 75%,var(--strong))}.mosaic-logo rect:nth-child(4){fill:color-mix(in srgb,var(--action) 45%,var(--canvas))}
.cmdbar .menu{display:none;border:1px solid var(--line);background:var(--canvas);border-radius:var(--r);padding:4px;color:var(--strong)}
.cmdk{flex:1;max-width:520px;display:flex;align-items:center;gap:8px;border:1px solid var(--line);background:var(--canvas);border-radius:var(--r);padding:5px 10px;color:var(--muted);text-align:left;min-width:0}
.cmdk span{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fresh{display:flex;align-items:center;gap:8px;margin-left:auto;font-size:12px;color:var(--muted);white-space:nowrap}
.fresh b{color:var(--success);font-weight:600}
.me{display:inline-grid;place-items:center;width:28px;height:28px;border-radius:50%;background:var(--raised);color:var(--strong);font-weight:700;font-size:12px;flex:none}
.side{border-right:1px solid var(--line);background:var(--surface);overflow:auto;scrollbar-width:thin;scrollbar-color:var(--line) transparent;padding:10px 8px 14px;display:flex;flex-direction:column;gap:2px;min-height:0}
.nav{display:flex;align-items:center;gap:9px;padding:5px 8px;border-radius:var(--r);color:var(--text);text-decoration:none;font-weight:600;font-size:13.5px;min-width:0}
.nav:hover{background:var(--raised)}
.nav[aria-current="page"]{background:color-mix(in srgb,var(--action) 13%,var(--surface));color:var(--strong)}
.nav[aria-current="page"] svg.i{color:var(--action)}
.nav .t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.n{margin-left:auto;font:600 11px var(--mono);color:var(--muted);font-variant-numeric:tabular-nums}
.n.hot{color:var(--surface);background:var(--danger);border-radius:999px;padding:0 6px}
.side hr,.specimen .mini hr{border:0;border-top:1px solid var(--line);margin:6px 4px}
.side .foot{margin-top:auto;padding-top:8px}
/* EXT 2: collapsible sidebar group. A label row with a chevron; closed groups keep their count. */
.grp{display:flex;flex-direction:column;gap:1px}
.grp-h{display:flex;align-items:center;gap:6px;padding:10px 8px 4px;color:var(--muted)}
.grp-h .label{flex:1}
.grp-h svg.i{width:14px;height:14px;transition:transform .15s}
.grp-h[aria-expanded="false"] svg.chev{transform:rotate(-90deg)}
.grp-h .seg{margin-left:auto}
.seg{display:inline-flex;border:1px solid var(--line);border-radius:var(--r);overflow:hidden;background:var(--surface)}
.seg > span,.seg > button{border:0;background:none;padding:2px 8px;color:var(--muted);font-size:12px;font-weight:600;display:inline-flex;align-items:center;gap:5px;white-space:nowrap}
.seg [aria-pressed="true"]{background:var(--action);color:var(--onAction)}
.seg.xs > span{padding:0 6px;font-size:11px}
/* EXT 3: org mark. Avatar tile in the org's colour with its initials (or image), always beside the
name or initials in text: colour is never the only cue. Sizes 16, 20, 28, 44. */
.av{display:inline-grid;place-items:center;flex:none;width:20px;height:20px;border-radius:5px;background:var(--org,var(--muted));color:var(--org-on);font:700 9.5px/1 var(--font);letter-spacing:.02em}
.av.xs{width:16px;height:16px;border-radius:4px;font-size:8.5px;letter-spacing:0}
.av.md{width:28px;height:28px;border-radius:7px;font-size:12px}
.av.lg{width:44px;height:44px;border-radius:10px;font-size:17px}
.av.all{background:var(--raised);color:var(--strong)}
.orgref{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;color:var(--strong);font-weight:600}
.orgref.quiet{color:var(--text);font-weight:500}
.org-row .ic{color:var(--muted)}
.org-row .ic svg.i{width:15px;height:15px}
/* Org edge: a 3px stripe in the org colour on cards, rows and panes that belong to one org. */
.edge{box-shadow:inset 3px 0 0 var(--org)}
.pgroup{display:flex;flex-direction:column;gap:1px;margin-bottom:4px}
.pgroup-h{display:flex;align-items:center;gap:7px;padding:4px 8px 2px;font-size:12px;font-weight:700;color:var(--strong)}
.pgroup-h svg.i{width:13px;height:13px;color:var(--muted)}
.proj{padding-left:20px;padding-top:3px;padding-bottom:3px;font-weight:500;font-size:13px}
.proj .dot-s{font:400 12px/1 var(--glyph);width:12px;text-align:center}
.main{overflow:auto;min-width:0;min-height:0;padding:18px 24px 28px}
.crumb{font-size:12.5px;color:var(--muted);margin-bottom:4px;display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.crumb a{color:var(--muted)}
.vh{display:flex;flex-wrap:wrap;gap:8px 14px;align-items:center;margin-bottom:14px}
.vh h1{font-size:28px;font-weight:800;letter-spacing:-.02em}
.vh .sub{flex-basis:100%;font-size:13.5px;color:var(--muted)}
.vh .right{margin-left:auto;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
h2.sec{font-size:20px;font-weight:800;letter-spacing:-.015em}
h3.q{font-size:16px;font-weight:700}
.sec-h{display:flex;align-items:baseline;gap:10px;margin:22px 0 8px;flex-wrap:wrap}
.sec-h h2,.sec-h h3{font-size:15px;font-weight:700}
.sec-h .note{flex:1}
.sec-h a{font-size:13px;font-weight:600;text-decoration:none}
.panel{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:16px;min-width:0}
.panel.tight{padding:12px 14px}
.grid{display:grid;gap:var(--gap)}
.g2{grid-template-columns:repeat(2,minmax(0,1fr))}
.g3{grid-template-columns:repeat(3,minmax(0,1fr))}
.g4{grid-template-columns:repeat(4,minmax(0,1fr))}
.g5{grid-template-columns:repeat(5,minmax(0,1fr))}
.split{display:grid;gap:16px;grid-template-columns:minmax(0,1.45fr) minmax(0,1fr);align-items:start}
/* status vocabulary: symbol plus word, never colour alone */
.dot{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
/* EXT 10, status glyph font: Manrope has no geometric shapes, and the generic fallback (Liberation Sans here)
draws the waiting half-circle at half the size of the dot. Name fonts that draw all five at one size. */
:root{--glyph:"DejaVu Sans","Segoe UI Symbol","Apple Symbols","Noto Sans Symbols 2",var(--font)}
.dot b{font:400 13px/1 var(--glyph);width:14px;text-align:center}
.s-working b{color:var(--success)}.s-waiting b{color:var(--warning)}.s-error b{color:var(--danger)}
.s-offline b,.s-idle b,.s-unknown b{color:var(--muted)}
.chip{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:600;padding:1px 7px;border-radius:4px;background:var(--raised);color:var(--strong);white-space:nowrap}
.chip.gated{background:color-mix(in srgb,var(--danger) 14%,var(--surface));color:var(--danger)}
.chip.block{background:var(--danger);color:var(--surface)}
.chip.cross{background:color-mix(in srgb,var(--accent) 16%,var(--surface));color:var(--accent)}
.chip.within,.chip.routine{background:var(--raised);color:var(--muted)}
.chip.warn{background:color-mix(in srgb,var(--warning) 16%,var(--surface));color:var(--warning)}
.chip.ok{background:color-mix(in srgb,var(--success) 15%,var(--surface));color:var(--success)}
.chip.outline{background:none;border:1px solid var(--line);color:var(--text);font-weight:500}
.chips{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.chips .f{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line);background:var(--surface);border-radius:999px;padding:2px 10px 2px 4px;font-size:12.5px;font-weight:600;color:var(--text);white-space:nowrap}
.chips .f.plain{padding-left:10px}
.chips .f[aria-pressed="true"]{background:var(--strong);color:var(--surface);border-color:var(--strong)}
.chips .f .av{width:18px;height:18px;border-radius:999px;font-size:8.5px;letter-spacing:0}
.chips .f .n{margin-left:2px;color:inherit;opacity:.8}
.btn{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line);background:var(--surface);border-radius:var(--r);padding:4px 10px;font-size:13px;font-weight:600;color:var(--strong);white-space:nowrap;text-decoration:none}
.btn.pri{background:var(--action);border-color:var(--action);color:var(--onAction)}
.btn.ghost{border-color:transparent;background:none;color:var(--muted)}
.btn svg.i{width:15px;height:15px}
.sel{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line);background:var(--surface);border-radius:var(--r);padding:3px 8px;font-size:13px;color:var(--strong);white-space:nowrap}
.sel .label{font-size:10px}
.sel svg.i{width:13px;height:13px;color:var(--muted)}
.search{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line);background:var(--surface);border-radius:var(--r);padding:3px 8px;color:var(--muted);font-size:13px;min-width:180px}
.toolbar{display:flex;flex-wrap:wrap;gap:8px 10px;align-items:center;margin-bottom:12px}
.toolbar .right{margin-left:auto;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
/* dense tables */
.tbl{overflow-x:auto;border:1px solid var(--line);border-radius:var(--r-table);background:var(--surface)}
table{border-collapse:collapse;width:100%;font-size:13px}
th{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);text-align:left;padding:7px 10px;border-bottom:1px solid var(--line);white-space:nowrap;background:var(--surface)}
th.sorted{color:var(--strong)}
th .ar{font-family:var(--mono);margin-left:3px;color:var(--action)}
td{padding:7px 10px;border-bottom:1px solid color-mix(in srgb,var(--line) 60%,transparent);vertical-align:middle}
tr:last-child td{border-bottom:0}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}
td.mono{font-family:var(--mono);font-size:12.5px;white-space:nowrap}
td .t1{color:var(--strong);font-weight:600}
td .t2{display:block;font-size:12px;color:var(--muted)}
tbody tr.row[aria-selected="true"]{background:color-mix(in srgb,var(--action) 10%,var(--surface));box-shadow:inset 3px 0 0 var(--action)}
tbody tr.dim td{color:var(--muted)}
/* EXT 4: metric tile with a per-org breakdown. The total is the headline; the stacked bar and the
labelled list under it carry the same numbers by org, so the bar is never read on colour alone. */
.tile{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-table);padding:12px 14px;min-width:0;display:grid;gap:6px;align-content:start}
.tile .big{font-size:24px;font-weight:800;color:var(--strong);letter-spacing:-.02em;font-variant-numeric:tabular-nums;line-height:1.1}
.tile .big small{font-size:13px;font-weight:600;color:var(--muted);letter-spacing:0;margin-left:4px}
.tile .delta{font-size:12px;color:var(--muted)}
.tile .delta b{color:var(--success);font-weight:600}
.tile .delta b.down{color:var(--danger)}
.bar{display:flex;height:6px;border-radius:3px;overflow:hidden;background:var(--raised);gap:2px}
.bar i{display:block;background:var(--org,var(--action))}
.by{display:flex;flex-wrap:wrap;gap:4px 10px;font-size:12px;color:var(--text)}
.by span{display:inline-flex;align-items:center;gap:4px;white-space:nowrap;font-variant-numeric:tabular-nums}
.by .av{width:14px;height:14px;border-radius:3px;font-size:7px}
/* activity trail across orgs */
.trail{list-style:none;margin:0;padding:0;border:1px solid var(--line);border-radius:var(--r-table);background:var(--surface)}
.trail li{display:grid;grid-template-columns:48px 20px minmax(0,1fr);gap:10px;padding:7px 12px;border-bottom:1px solid color-mix(in srgb,var(--line) 60%,transparent);font-size:13px;align-items:center}
.trail li:last-child{border-bottom:0}
.trail time{font-family:var(--mono);font-size:12px;color:var(--muted)}
.trail .what{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.trail .what b{color:var(--strong);font-weight:600}
.trail .what .src{color:var(--muted)}
/* needs-you list (inbox rows on dashboards) */
.needs{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.needs li{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:4px 10px;align-items:center;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-table);padding:9px 12px}
.needs .q{color:var(--strong);font-weight:600;font-size:13.5px}
.needs .src{grid-column:2;font-size:12px;color:var(--muted)}
.needs .chip{grid-row:1/3;grid-column:3}
.kv{display:grid;grid-template-columns:auto 1fr;gap:5px 12px;margin:0;font-size:13px}
.kv dt{color:var(--muted)}
.kv dd{margin:0;color:var(--strong);min-width:0;overflow-wrap:anywhere}
/* EXT 5: settings index. Every configurable is one row: group, current value, where the value comes
from, and a link to its editor. The dashboard reaches every setting without showing all inline. */
.cfg{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));border:1px solid var(--line);border-radius:var(--r-table);background:var(--surface);overflow:hidden}
.cfg li{display:grid;grid-template-columns:22px minmax(0,1fr) auto;gap:2px 10px;align-items:center;padding:9px 12px;border-bottom:1px solid color-mix(in srgb,var(--line) 60%,transparent);border-right:1px solid color-mix(in srgb,var(--line) 60%,transparent)}
.cfg li:nth-child(2n){border-right:0}
.cfg li:nth-last-child(-n+2){border-bottom:0}
.cfg svg.i{color:var(--muted);width:16px;height:16px}
.cfg .k{font-weight:600;color:var(--strong);font-size:13px}
.cfg .v{grid-column:2;font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cfg .go{grid-row:1/3;grid-column:3;font-size:12.5px;font-weight:600;text-decoration:none}
.src-tag{font:500 11px var(--mono);color:var(--accent)}
.docs{list-style:none;margin:0;padding:0;display:grid;gap:2px}
.docs li{display:grid;grid-template-columns:18px minmax(0,1fr) auto;gap:10px;align-items:center;padding:6px 4px;border-bottom:1px solid color-mix(in srgb,var(--line) 60%,transparent);font-size:13px}
.docs li:last-child{border-bottom:0}
.docs svg.i{width:16px;height:16px;color:var(--muted)}
.docs .d{color:var(--strong);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.docs time{font-size:12px;color:var(--muted);white-space:nowrap}
/* org header on the org dashboard */
.orghead{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:14px}
.orghead h1{font-size:28px;font-weight:800;letter-spacing:-.02em;display:flex;align-items:center;gap:10px}
.orghead h1 svg.i{width:20px;height:20px;color:var(--muted)}
.orghead .meta{flex-basis:100%;display:flex;flex-wrap:wrap;gap:4px 14px;font-size:13px;color:var(--muted);margin-top:-6px;padding-left:58px}
.orghead .right{margin-left:auto;display:flex;gap:8px;flex-wrap:wrap}
.typechips{display:flex;flex-wrap:wrap;gap:6px}
/* EXT 6: Kanban. Columns by state; a card carries the org mark, the task id from its tracker, the
project and the assignee's status. Cards from several orgs share one column. */
.board{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;align-items:start}
.col{background:color-mix(in srgb,var(--raised) 55%,var(--canvas));border:1px solid var(--line);border-radius:var(--r-lg);padding:8px;display:grid;gap:8px;min-width:0}
.col-h{display:flex;align-items:center;gap:8px;padding:2px 4px}
.col-h h3{font-size:13px;font-weight:700}
.col-h .n{margin-left:0}
.col-h .mix{margin-left:auto;display:flex;gap:2px}
.kcard{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-table);padding:8px 10px 8px 12px;display:grid;gap:5px;min-width:0}
.kcard .top{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted)}
.kcard .top .id{font:500 11.5px var(--mono);color:var(--muted)}
.kcard .top .trk{margin-left:auto}
.kcard .tt{color:var(--strong);font-weight:600;font-size:13px;line-height:1.35}
.kcard .bot{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--muted);flex-wrap:wrap}
.kcard.you{border-color:color-mix(in srgb,var(--warning) 55%,var(--line))}
/* EXT 7: tracker badge. Names the task tracker module behind an org: built-in or Vikunja. */
.trk{display:inline-flex;align-items:center;gap:4px;font:600 10.5px var(--mono);letter-spacing:.02em;padding:0 5px;border-radius:3px;border:1px solid var(--line);color:var(--muted);white-space:nowrap}
.trk.vik{border-style:dashed;color:var(--accent);border-color:color-mix(in srgb,var(--accent) 60%,var(--line))}
.trackers{display:flex;flex-wrap:wrap;gap:6px 16px;align-items:center;font-size:12.5px;color:var(--text);padding:8px 12px;border:1px solid var(--line);border-radius:var(--r-table);background:var(--surface);margin-bottom:12px}
.trackers > span{display:inline-flex;align-items:center;gap:6px}
/* EXT 8: side-by-side panes. Each pane has its own header with the org mark and edge, and its own
scroll; panes never share state. Two panes at 1440; one pane with a pane switcher on a phone. */
.panes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0;height:100%;min-height:0}
.pane{display:flex;flex-direction:column;min-width:0;min-height:0;border-right:1px solid var(--line)}
.pane:last-child{border-right:0}
.pane-h{display:flex;align-items:center;gap:8px;padding:8px 14px;border-bottom:1px solid var(--line);background:var(--surface);box-shadow:inset 0 3px 0 var(--org);min-width:0}
.pane-h .ttl{font-weight:700;color:var(--strong);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pane-h .ttl small{font-weight:500;color:var(--muted);margin-left:6px}
.pane-h .tools{margin-left:auto;display:flex;gap:2px}
.pane-h .tools span{display:inline-grid;place-items:center;width:26px;height:26px;border-radius:var(--r);color:var(--muted)}
.pane-body{overflow:auto;padding:14px;min-height:0;flex:1}
.pane-tabs{display:none}
.main.flush{padding:0;overflow:hidden;display:flex;flex-direction:column}
.panebar{display:flex;align-items:center;gap:10px;padding:8px 14px;border-bottom:1px solid var(--line);background:var(--canvas);flex-wrap:wrap}
.panebar h1{font-size:16px;font-weight:700}
/* EXT 9: agent level badge and the three-level map. */
.lvl{display:inline-flex;align-items:center;gap:4px;font:700 10.5px var(--font);letter-spacing:.06em;text-transform:uppercase;padding:1px 6px;border-radius:3px;white-space:nowrap}
.lvl.root{background:var(--strong);color:var(--surface)}
.lvl.org{background:color-mix(in srgb,var(--org,var(--action)) 18%,var(--surface));color:var(--strong);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--org,var(--action)) 50%,transparent)}
.lvl.proj{background:none;color:var(--text);box-shadow:inset 0 0 0 1px var(--line)}
.levels{display:grid;grid-template-columns:200px repeat(3,minmax(0,1fr));border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;background:var(--surface)}
.levels > div{padding:10px 12px;border-bottom:1px solid color-mix(in srgb,var(--line) 60%,transparent);border-right:1px solid color-mix(in srgb,var(--line) 60%,transparent);min-width:0}
.levels > div:nth-child(4n){border-right:0}
.levels .lh{background:color-mix(in srgb,var(--raised) 45%,var(--surface));display:grid;gap:4px;align-content:start}
.levels .lh small{font-size:11.5px;color:var(--muted);line-height:1.35}
.levels .lh .lvl{justify-self:start}
.levels .oh{display:flex;align-items:center;gap:8px;font-weight:700;color:var(--strong);background:color-mix(in srgb,var(--raised) 45%,var(--surface))}
.levels .span3{grid-column:2/5;border-right:0}
.levels .last{border-bottom:0}
.agent{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line);border-radius:999px;padding:2px 10px 2px 8px;font-size:12.5px;font-weight:600;color:var(--strong);background:var(--canvas);white-space:nowrap;margin:2px 4px 2px 0}
.agent .dot b{width:auto}
.agent.assist{border-color:var(--action);background:color-mix(in srgb,var(--action) 10%,var(--surface))}
.agent.cos{border-style:solid}
.agent small{font-weight:500;color:var(--muted)}
.inst{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px}
.span-band{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 12px;border-radius:var(--r-table);border:1px solid var(--action);background:color-mix(in srgb,var(--action) 8%,var(--surface));font-size:13px;color:var(--strong)}
.span-band .orgs{display:flex;gap:4px}
/* inspector */
.insp{border-left:1px solid var(--line);background:var(--surface);overflow:auto;min-height:0;display:flex;flex-direction:column}
.insp header{display:flex;align-items:center;gap:8px;padding:10px 14px;border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--surface);z-index:1}
.insp header .x{margin-left:auto;color:var(--muted);display:inline-flex}
.insp .body{padding:14px;display:grid;gap:14px}
.insp h3{font-size:16px;font-weight:700}
.opts{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.opts li{border:1px solid var(--line);border-radius:var(--r-table);padding:9px 10px;display:grid;gap:6px;background:var(--canvas)}
.opts li.rec{border-color:var(--action)}
.opts .k{font:700 13px var(--mono);color:var(--strong)}
.opts .row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.cmd{display:flex;gap:6px;align-items:center;min-width:0}
.cmd code{flex:1;min-width:0;overflow-x:auto;white-space:nowrap;background:var(--surface);border:1px solid var(--line);border-radius:4px;padding:3px 6px;font-size:12px;color:var(--strong)}
ol.hist{list-style:none;margin:0;padding:0;display:grid;gap:6px;font-size:12.5px}
ol.hist li{display:grid;grid-template-columns:48px 1fr;gap:8px}
ol.hist time{font-family:var(--mono);color:var(--muted)}
.auth{border:1px solid var(--line);border-left:3px solid var(--org,var(--action));border-radius:0 6px 6px 0;padding:8px 10px;background:var(--canvas);font-size:13px;color:var(--strong)}
/* inbox list */
.ibx td.src{white-space:nowrap}
.ibx .q{color:var(--strong);font-weight:600}
.ibx .via{display:block;font-size:12px;color:var(--muted)}
/* sidebar details: add button, collapsed marks, project rail */
.grp-h .add{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:var(--r);color:var(--muted);border:1px solid var(--line)}
.grp-h .n{margin-left:0}
.collapsed-marks{display:flex;gap:4px;padding:0 8px 6px 28px}
.pgroup .projs{margin-left:17px;border-left:2px solid var(--org);display:flex;flex-direction:column;gap:1px}
.pgroup .proj{padding-left:10px}
.proj.flat{padding-left:8px}
.proj .n{font-family:var(--font);font-weight:500;font-size:11px}
.s-ok b{color:var(--success)}
/* tasks by state on the main dashboard */
.states{display:grid;gap:8px}
.srow{display:grid;grid-template-columns:112px 24px minmax(0,1fr) auto;gap:10px;align-items:center;font-size:13px}
.srow .sl{color:var(--strong);font-weight:600}
.srow .sn{font:700 13px var(--mono);color:var(--strong);text-align:right}
.srow .bar{height:8px;max-width:100%}
.needs li > .av{grid-row:1/3}
/* settings index, one column, with the destructive row set apart */
.cfg.one{grid-template-columns:minmax(0,1fr)}
.cfg.one li{grid-template-columns:18px 132px minmax(0,1fr) auto auto;gap:0 10px;border-right:0;padding:7px 12px}
.cfg.one .v{grid-column:3;grid-row:1}
.cfg.one .src-tag{grid-column:4;grid-row:1}
.cfg.one .go{grid-column:5;grid-row:1}
.cfg.one li:nth-last-child(2){border-bottom:1px solid color-mix(in srgb,var(--line) 60%,transparent)}
.cfg li.danger .k,.cfg li.danger svg.i,.cfg li.danger .go{color:var(--danger)}
/* live transcript, mini tiles and sub tabs inside a pane */
.term{margin:0;font:400 12px/1.55 var(--mono);background:var(--canvas);color:var(--text);border:1px solid var(--line);border-radius:var(--r-table);padding:8px 10px;white-space:pre-wrap;overflow-wrap:anywhere}
.term .m{color:var(--muted)}
.term .c{color:var(--action)}
.mini-tiles .tile{padding:8px 10px;gap:2px}
.mini-tiles .tile .big{font-size:20px}
.subtabs{display:flex;gap:2px;border-bottom:1px solid var(--line);margin:-4px 0 12px}
.subtabs span{padding:4px 10px;font-size:13px;font-weight:600;color:var(--muted);border-bottom:2px solid transparent;margin-bottom:-1px}
.subtabs [aria-current="page"]{color:var(--strong);border-bottom-color:var(--org,var(--action))}
.rules{display:grid;gap:10px;font-size:13px}
.rules p{display:flex;gap:6px;flex-wrap:wrap;align-items:baseline}
/* one-line session rows on the main dashboard */
.sess td.who{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:0;width:100%}
.sess td.who .orgref{vertical-align:middle}
.sess td.st{white-space:nowrap}
/* docs row on the org dashboard */
.docrow{margin-top:8px}
.docrow .doc{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);background:var(--surface);border-radius:var(--r);padding:2px 8px;font-size:12.5px;font-weight:600;color:var(--strong);text-decoration:none;white-space:nowrap}
.docrow .doc svg.i{width:14px;height:14px;color:var(--muted)}
.docrow .doc small{font-weight:500;color:var(--muted)}
.docrow .more{font-size:13px;font-weight:600;text-decoration:none;margin-left:4px}
/* source line inside a row, used on a phone where the source column is hidden */
.msrc{align-items:center;gap:5px;font-size:12px;color:var(--muted);margin-bottom:2px}
.av.mob{display:none}
/* phone-only labels and rows; desktop hides them */
.show-m,.mlabel{display:none}
td .t2.show-m{display:none}
/* mobile strip and drawer */
.strip{display:none}
.specimen{display:grid;gap:14px;grid-template-columns:repeat(3,minmax(0,1fr));align-items:start}
.specimen .mini{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--surface);padding:8px;display:flex;flex-direction:column;gap:2px}
.specimen figcaption{font-size:12.5px;color:var(--muted);margin-top:6px}
.specimen figure{margin:0}
.callouts{margin:14px 0 0;padding:0 0 0 18px;display:grid;gap:6px;font-size:13px}
.callouts b{color:var(--strong)}
@media (max-width:1100px){
.app.with-insp{grid-template-columns:220px minmax(0,1fr)}
.app.with-insp .insp{position:fixed;right:0;top:49px;bottom:0;width:min(380px,100%);box-shadow:-12px 0 30px -12px color-mix(in srgb,#000 35%,transparent);z-index:10}
.g5{grid-template-columns:repeat(3,minmax(0,1fr))}
}
@media (max-width:760px){
.app,.app.with-insp{display:block;height:auto;min-height:100vh}
.cmdbar{position:sticky;top:0;z-index:20;gap:8px;padding:8px 12px}
.cmdbar .menu{display:inline-flex}
.cmdbar .mk span,.cmdbar .sim,.fresh .wide{display:none}
.cmdk{max-width:none}
.cmdk kbd{display:none}
.fresh{margin-left:0}
.side{display:none}
.strip{display:flex;gap:2px;overflow-x:auto;padding:6px 8px;border-bottom:1px solid var(--line);background:var(--surface)}
.strip .nav{white-space:nowrap;flex:none}
.app.drawer .side{display:flex;position:fixed;inset:49px 0 0 0;z-index:30;border-right:0;padding:10px 12px 20px}
.app.drawer .strip{display:none}
.main{padding:14px 16px 24px;overflow:visible}
.vh h1,.orghead h1{font-size:24px}
.g2,.g3,.g4,.g5,.split,.specimen{grid-template-columns:minmax(0,1fr)}
.g4.keep2,.g5.keep2{grid-template-columns:repeat(2,minmax(0,1fr))}
.app.with-insp .insp{position:static;display:flex;width:auto;box-shadow:none;border-left:0;border-top:1px solid var(--line);margin:0 0 24px}
.show-m,td .t2.show-m{display:block}
span.show-m{display:inline-flex}
span.msrc.show-m{display:flex}
.av.mob{display:inline-grid;margin-right:6px;vertical-align:-3px}
.strip{scrollbar-width:none}
.g5.keep2 > :last-child:nth-child(odd){grid-column:1/-1}
.sec-h .note{flex-basis:100%;order:3}
.grid.g3.mini-tiles{grid-template-columns:repeat(3,minmax(0,1fr))}
.mini-tiles .tile .big{font-size:18px}
.mini-tiles .tile .big small{display:block;margin-left:0;font-size:11.5px}
.cfg.one li{grid-template-columns:18px minmax(0,1fr) auto auto;gap:2px 10px}
.cfg.one .k{grid-column:2;grid-row:1}
.cfg.one .src-tag{grid-column:3;grid-row:1}
.cfg.one .go{grid-column:4;grid-row:1/3}
.cfg.one .v{grid-column:2/4;grid-row:2}
.mlabel{display:flex;align-items:center;gap:6px;font-size:12px;font-weight:700;color:var(--strong);margin-bottom:6px}
.board,.tasklist .sec-h{display:none}
.vh .seg .kb{background:none;color:var(--muted)}
.vh .seg .ls{background:var(--action);color:var(--onAction)}
.srow{grid-template-columns:92px 20px minmax(0,1fr)}
.srow .by{grid-column:1/-1}
.cfg{grid-template-columns:minmax(0,1fr)}
.cfg li{border-right:0}
.cfg li:nth-last-child(2){border-bottom:1px solid color-mix(in srgb,var(--line) 60%,transparent)}
.orghead .meta{padding-left:0;margin-top:0}
.orghead .right{margin-left:0}
.levels{grid-template-columns:minmax(0,1fr)}
.levels > div{border-right:0}
.levels .span3{grid-column:auto}
.levels .hide-m{display:none}
.panes{grid-template-columns:minmax(0,1fr);height:auto}
.pane{border-right:0}
.pane.alt{display:none}
.pane-tabs{display:flex}
.main.flush{overflow:visible}
.hide-m{display:none}
.trail li{grid-template-columns:42px 18px minmax(0,1fr);gap:8px}
.trail .what{white-space:normal}
.toolbar .right{margin-left:0}
.search{min-width:0;flex:1}
}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
@@ -231,9 +231,46 @@ into another user's organization, and access checks on the cross-org read
model. The design lands with Phase U so the read model has membership from
the start.
## U0 approval (11-09, 19:26Z)
Owner text, verbatim:
> The U0 screen designs look good. We need to retain the temporary logo
> already used in the site.
> I don't like these module names either. It isn't clicking for me. That may
> need to be a later decision.
What follows from it:
1. The samples in `docs/design/samples/2026-11-09-unified-workspace/` are the
acceptance target for U2 to U5.
2. The WebUI's four-tile mark stays the logo. The samples now draw it in
place of the design system's Relay placeholder, and the build does not
adopt Relay.
3. The Montage module name stays open. Two naming rounds produced no pick.
The label "Mosaic Montage" stays until Jason names it; nothing in phase U
depends on the name.
The ten open questions in the U0 report were not answered one by one. Under
the lead's standing authority to decide routine choices, phase U takes the
report's recommendations, and Jason can overturn any of them:
- Every decide command copied from a shared view carries `--org`.
- The chief may propose a root-level hire only as a gated inbox item the user
approves.
- An org's colour is its own theme's action colour, the same for every member.
- Side by side on a phone is a two-way switch with one pane visible.
- Sidebar projects default to By org, remembered per viewer.
- Tasks on a phone default to List, with Kanban one tap away.
- The CLI verbs for the new header controls are `mosaic org reload <id>` and
`mosaic console restart`, added before U2 wires the buttons.
- Members and invites shows in the settings index, labelled "not built".
- Messages becomes Assistant. Docs live on org dashboards and in panes. Queue
opens from each org dashboard.
## Open items
- The final name for the Mosaic Montage module.
- The final name for the Mosaic Montage module (deferred by Jason, 11-09).
- Which "sign-in (model proxy)" step Jason hit. F3 inventories every manual
step on the dev instance and reports it.
+6 -4
View File
@@ -486,12 +486,14 @@
// good load, from the status `mosaic bus start` left. textContent only. Nothing here retries.
async function busDown() {
const box = $('bus-down');
// E2E5 review P2: the organization list is read first and on its own, so a failed bus-status read
// (likely when the bus is down) still refreshes the list, its banner and the Settings Start control.
if (window.MosaicOrg) {
const org = (await window.MosaicOrg.readList()).find(row => row.id === window.MosaicOrg.id);
if (org?.busHealthy === false) { box.textContent = 'Bus unavailable'; box.hidden = false; return; }
}
try {
const s = await api('/api/bus-status');
if (window.MosaicOrg) {
const org = (await window.MosaicOrg.readList()).find(row => row.id === window.MosaicOrg.id);
if (org?.busHealthy === false) { box.textContent = 'Bus unavailable'; box.hidden = false; return; }
}
if (!s.down) { box.hidden = true; return; }
const b = s.boot;
box.replaceChildren(node('b', '', 'Bus down: organization file invalid. '), node('span', '', `${b.reason} `), node('span', 'small muted', `File ${b.file}. Refused at ${b.at}. Last good load: ${b.lastGood ?? 'none'}. Fix the file, then restart the bus.`));
+19
View File
@@ -1470,6 +1470,25 @@
if (path === '/business') { location.replace('#/settings/business'); return; }
if (path === '/settings/display') { location.replace('#/settings/appearance'); return; }
if (chatPath === '/chat' || chatPath.startsWith('/chat/') || /^\/projects\/[0-9a-f-]+\/(?:settings|conversations|tasks|requirements|files)$/i.test(chatPath)) {
// Re-read the scoped capability as the Console and bus recover. A failed read
// withdraws the control; the chat renderer retains the draft across repaint.
if (window.MosaicOrg && !isTester) {
try {
const response = await fetch('/api/config', { cache: 'no-store', redirect: 'manual' });
if (!current()) return;
if (response.type === 'opaqueredirect') { signOut(); return; }
if (response.status === 401) { signOutSso(); return; }
const config = response.ok ? await response.json() : null;
if (!current()) return;
if (response.ok) window.MosaicIcons.succeeded(); else window.MosaicIcons.failed();
chatSend = config?.chatSend === true;
window.MosaicOrgBusStopped = config?.devOwner === true && config?.orgSetup === true && config?.chatSend === false;
} catch {
if (!current()) return;
window.MosaicIcons.failed(); chatSend = false; window.MosaicOrgBusStopped = false;
}
if (!current()) return;
}
// Row 177 (#1675): the tester Console writes to its own threads.
const focusedHeading = document.activeElement === $('bus-view').querySelector('h1');
await window.MosaicChat.render({ path: chatPath, container: $('bus-view'), canSend: (window.MosaicOrg ? chatSend : canSend) || isTester, tester: isTester, navigated });
+3
View File
@@ -75,3 +75,6 @@
.chat-room-picker label { display: block; padding-block: .45rem; }
.chat-audience { margin: .25rem 0; }
.chat-projects .panel { border-radius: 4px; }
#chat-send-form textarea:disabled, #chat-room-send-form textarea:disabled { opacity: .55; cursor: not-allowed; }
#chat-send-form button:disabled, #chat-room-send-form button:disabled { opacity: .5; cursor: not-allowed; }
+3 -3
View File
@@ -319,7 +319,7 @@
}
const roomName = instance => current.members?.find(m => m.instance === instance)?.name || instance;
function roomOpenControl(project) {
if (window.MosaicOrg) return '<p>Room changes are unavailable.</p>';
if (window.MosaicOrg) return '<p>Room changes are unavailable on this Console.</p>';
if (!roomOwner()) return '';
if (current.projects.some(p => p.id === project && p.archived)) return `<p><a href="${roomPath(esc(project))}">Read room</a></p>`;
const f = form('room-open:' + project);
@@ -417,7 +417,7 @@
if (s.receiptIds?.every(id => s.rows.some(m => m.ids.includes(id)))) { s.receipt = 'Message shown in the room.'; s.receiptIds = null; }
} catch (err) {
if (g !== generation || out() || err.name === 'AbortError' || err.code === 'signed-out') return;
current.error = roomError(err);
current.error = window.MosaicOrg && err.code === 'room-not-open' ? 'Room changes are unavailable on this Console.' : roomError(err);
current.readFailed = true;
if (err.code === 'channel-disabled') current.channelDisabled = true;
if (err.status === 403 || err.status === 404) { s.rows = []; current.members = []; current.projects = []; }
@@ -630,7 +630,7 @@
} else {
html += heading('Projects') + '<p>Projects and their conversations.</p><div class="chat-projects">' + c.projects.map(p => `<section class="panel"><h2>${link('projects', p.id, p.name)}</h2>${p.repo ? `<p class="muted">Repository: ${txt(p.repo)}</p>` : ''}${threads(c.threads.filter(t => t.project === p.id && !t.shared))}</section>`).join('') + (c.projects.length ? '' : c.readFailed ? '<p>Projects unavailable.</p>' : '<p>No projects yet.</p>') + '</div><h2>Shared with me</h2>' + threads(c.threads.filter(t => t.shared)) + creation('project', 'projects');
}
if (!c.canSend) html += window.MosaicOrgBusStopped ? '<p class="muted">The bus is stopped. Use Start the bus to send messages.</p>' : '<p class="muted">Creating and sending require signed-in send mode. This Console only reads.</p>';
if (!c.canSend) html += window.MosaicOrgBusStopped ? '<p class="muted">The bus is stopped. Use Start the bus on Settings → Organizations to send messages.</p>' : '<p class="muted">Creating and sending require signed-in send mode. This Console only reads.</p>';
html += '</div>';
// Drafts already live in the focused textarea; their changing text is not a
// reason for a background read to replace the control.
+7 -1
View File
@@ -41,7 +41,13 @@ window.MosaicLocalTime = value => Number.isFinite(Date.parse(value)) ? new Date(
// A failed read keeps its reason, so the header can say why the list is empty.
let listError = null;
const readList = () => nativeFetch('/api/orgs', { cache: 'no-store', redirect: 'manual' }).then(async r => {
if (r.ok) { const rows = await r.json(); listError = null; return Array.isArray(rows) ? rows : []; }
if (r.ok) {
const body = await r.json(); listError = null;
const rows = Array.isArray(body) ? body : [];
// E2E5 review P2: an open panel (Settings > Organizations) follows every fresh list read, not only its own.
document.dispatchEvent(new CustomEvent('mosaic-org-list', { detail: { rows } }));
return rows;
}
const body = await r.json().catch(() => ({}));
listError = typeof body.message === 'string' && body.message ? body.message : 'Organization registry could not be read';
return [];
+2 -1
View File
@@ -4,7 +4,8 @@
.org-admin h4{font-size:14px;font-weight:700;margin:0 0 8px;color:var(--strong)}
.org-help{display:block;font-size:13px;color:var(--muted);margin:4px 0 0}
.org-field-err{display:block;font-size:13px;color:var(--danger);margin:4px 0 0}
.org-field-err code,.org-errors code,.org-verb code{overflow-wrap:anywhere}
.org-field-err code,.org-errors code{overflow-wrap:anywhere}
.org-verb code{overflow-wrap:normal;word-break:normal}
.org-start-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:24px;align-items:start}
.org-inline{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 8px;align-items:center}
.org-inline label{grid-column:1/-1;font-size:14px;font-weight:600;color:var(--strong)}
+27 -5
View File
@@ -75,6 +75,7 @@
<section id="org-archived" class="panel" tabindex="-1" hidden aria-labelledby="org-archived-title">
<h3 id="org-archived-title">Organization archived</h3>
<p>Editing and setup are unavailable while archived. Files remain in place; restoring does not start the bus.</p>
<p id="org-restore-verb" class="org-verb"></p>
<button type="button" id="org-restore" data-write>Restore organization</button>
</section>
<p id="org-archive-error" class="org-field-err" role="alert"></p>
@@ -247,6 +248,7 @@
editorDirty = false; setupDirty.clear(); $('org-new-id').value = '';
$('org-editor').hidden = false; $('org-delete').hidden = mode !== 'edit'; resetDelete(); resetArchive(); $('org-delete-success').hidden = true;
$('org-archive').hidden = mode !== 'edit' || state !== 'active'; $('org-archived').hidden = mode !== 'edit' || state !== 'archived';
$('org-restore-verb').textContent = state === 'archived' ? `Same as mosaic org restore ${id} --if-revision ${revision}` : '';
$('org-editor-title').textContent = mode === 'create' ? `New organization: ${id}` : `Organization: ${id}`;
$('org-editor-verb').innerHTML = verb ? `Same as <code>${txt(verb)}</code>` : '';
$('org-save').textContent = mode === 'create' ? 'Save organization' : 'Save changes';
@@ -416,6 +418,9 @@
if (!alive) return;
if (r.status !== 200) { st.setup = null; $('org-setup').hidden = false; $('org-steps').innerHTML = `<li class="panel org-step"><p class="org-field-err">Setup could not be read back (${txt(r.body.error || r.status)}). ${txt(r.body.message || '')}</p><button type="button" class="org-secondary" data-readback>Read back again</button></li>`; return; }
st.setup = r.body;
const orgs = window.MosaicOrg ? await window.MosaicOrg.readList() : [];
if (!alive) return;
st.busDown = orgs.find(org => org.id === id)?.busHealthy === false;
for (const key of [...st.unknown]) if (stepState(key)?.state !== 'unknown') st.unknown.delete(key);
renderSetup();
}
@@ -431,7 +436,7 @@
const keys = stepKeys(); let blocked = false, firstOpen = null;
$('org-setup').hidden = false;
$('org-steps').innerHTML = keys.map((key, i) => {
const s = { ...stepState(key) }; if (st.unknown.has(key) && s.state !== 'done') s.state = 'unknown';
const s = { ...stepState(key) }; if (st.unknown.has(key)) s.state = 'unknown';
if (s.lastError && s.state !== 'done') s.state = s.state === 'unknown' ? 'unknown' : 'failed';
const [stateLabel, cls] = STATE[s.state] || STATE.unknown;
const ready = !blocked && s.state !== 'done' && s.state !== 'unavailable';
@@ -455,7 +460,7 @@
<label class="org-risk"${remote ? ' hidden' : ''}><input type="checkbox" data-risk${c.risk ? ' checked' : ''}${!remote && s.lastError && !c.risk ? ' aria-invalid="true"' : ''}> I accept that a local-only history has no copy anywhere else and is lost with this disk.</label>
<div class="settings-actions"><button type="button" data-run="${txt(key)}">${busy ? 'Working… <span class="settings-spinner" aria-hidden="true"></span>' : key === 'queue' ? 'Set up checkout' : 'Set up repository'}</button></div>
</fieldset>` : ''}
${s.state !== 'done' && s.state !== 'unknown' && key === 'bus' ? `<div class="settings-actions"><button type="button" data-run="bus" ${ready && canWrite && !busy ? '' : 'disabled'}>${busy ? 'Starting… <span class="settings-spinner" aria-hidden="true"></span>' : 'Start the bus'}</button>${ready ? '' : '<span class="org-help">Finish the steps above first.</span>'}</div>` : ''}
${key === 'bus' && canWrite && !st.unknown.has(key) && (st.busDown || (s.state !== 'done' && s.state !== 'unknown')) ? `<div class="settings-actions"><button type="button" data-run="bus" ${(ready || st.busDown) && canWrite && !busy ? '' : 'disabled'}>${busy ? 'Starting… <span class="settings-spinner" aria-hidden="true"></span>' : 'Start the bus'}</button>${ready || st.busDown ? '' : '<span class="org-help">Finish the steps above first.</span>'}</div>` : ''}
</li>`;
}).join('');
for (const card of root.querySelectorAll('.org-step')) if (st.choice.has(card.dataset.step) && card.querySelector('.org-git')) showVerb(card);
@@ -491,6 +496,7 @@
else if (r.body.error === 'readback-failed') { st.unknown.add(key); s.lastError = r.body.message; }
else if (r.body.errors?.length) s.lastError = r.body.errors.map(e => `${e.field}: ${e.message}`).join(' ');
else s.lastError = r.body.message || `Refused (${r.body.error || r.status}).`;
if (key === 'bus' && r.status >= 400 && r.status < 500) s.lastError += ` If the host lock is stale, run mosaic bus recover ${id}.`;
status(`Step incomplete: ${s.lastError}`);
renderSetup(); root.querySelector(`[data-step="${CSS.escape(key)}"] h4`)?.setAttribute('tabindex', '-1'); root.querySelector(`[data-step="${CSS.escape(key)}"] h4`)?.focus();
}
@@ -531,7 +537,7 @@
function resetArchive() {
$('org-archive-confirm').hidden = true; $('org-archive-open').hidden = false;
$('org-archive-error').textContent = ''; $('org-archive-success').hidden = true;
$('org-archive-final').disabled = !canWrite; $('org-restore').disabled = !canWrite;
$('org-archive-final').disabled = !canWrite; $('org-archive-final').textContent = 'Archive'; $('org-restore').disabled = !canWrite;
}
async function refreshOrganizations() {
const rows = window.MosaicOrg ? await window.MosaicOrg.refreshList() : [];
@@ -545,7 +551,7 @@
}
async function runLifecycle(step) {
const id = st.id, revision = st.revision, button = $(step === 'archive' ? 'org-archive-final' : 'org-restore');
button.disabled = true; $('org-archive-error').textContent = '';
button.disabled = true; if (step === 'archive') button.textContent = 'Archiving…'; $('org-archive-error').textContent = '';
try {
const reply = await api('POST', `/api/orgs/${encodeURIComponent(id)}/${step}`, { revision });
if (!alive) return;
@@ -559,6 +565,7 @@
} else $('org-archived').focus();
status(`Organization ${step === 'archive' ? 'archived' : 'restored'}.`);
} catch {
if (step === 'archive') button.textContent = 'Archive';
$('org-archive-error').textContent = `The outcome is unknown. Inspect the organization before retrying: mosaic org ${step} ${id} --if-revision ${revision}.`;
}
}
@@ -587,8 +594,23 @@
} catch { $('org-delete-error').textContent = 'The outcome is unknown. Inspect the receipt and resume with the CLI.'; $('org-delete-progress').innerHTML = `<p>Resume with <code>${txt(`mosaic org delete ${id} --confirm ${id}`)}</code></p>`; }
}
// E2E5 review P2: a list read anywhere on the page (Refresh, the header, the bus banner) updates the
// bus Start affordance of the open organization. Only a change re-renders, and the typed setup choices
// are kept first, so a draft survives.
function onOrgList(e) {
if (!alive || !st.setup || !st.id || !Array.isArray(e.detail?.rows)) return;
const down = e.detail.rows.find(org => org.id === st.id)?.busHealthy === false;
if (down === Boolean(st.busDown)) return;
for (const card of root.querySelectorAll('.org-step')) {
if (!card.querySelector('.org-git')) continue;
const mode = card.querySelector('input[type=radio]:checked')?.value;
st.choice.set(card.dataset.step, { mode, remote: card.querySelector('[data-remote]')?.value ?? '', risk: !!card.querySelector('[data-risk]')?.checked });
}
st.busDown = down; renderSetup();
}
// ---- wiring -----------------------------------------------------------
const handlers = [
[document, 'mosaic-org-list', onOrgList],
[$('org-archive-open'), 'click', () => { $('org-archive-open').hidden = true; $('org-archive-confirm').hidden = false; $('org-archive-confirm').focus(); }],
[$('org-archive-cancel'), 'click', () => { resetArchive(); $('org-archive-open').focus(); }],
[$('org-archive-final'), 'click', () => runLifecycle('archive')],
@@ -621,7 +643,7 @@
[$('org-steps'), 'input', e => { const card = e.target.closest('.org-step'); if (card && e.target.matches('[data-remote]')) { keepChoice(card); showVerb(card); } }],
];
for (const [el, ev, fn] of handlers) el.addEventListener(ev, fn);
fetch('/api/config', { cache: 'no-store' }).then(r => r.json()).then(async config => {
fetch(new URL('/api/config', location.href), { cache: 'no-store' }).then(r => r.json()).then(async config => {
if (!alive) return;
canWrite = (config.orgSetup === true || config.send === true) && config.tester !== true && config.user !== true;
root.querySelectorAll('[data-write]').forEach(el => { el.disabled = !canWrite; });
@@ -329,6 +329,13 @@ async function userPage(t, config) {
return server.address().port;
}
test('a granted user opening an archived organization route has no enabled lifecycle controls', async t => {
const b = await browser(); t.after(() => b.close());
const port = await userPage(t, { user: true, send: true });
await b.navigate(`http://127.0.0.1:${port}/#/orgs/beta/settings/organizations?org=beta`);
assert.equal(await b.evaluate(`!!document.querySelector('#org-restore:not(:disabled), #org-delete-open:not(:disabled), #org-delete-final:not(:disabled)')`), false);
});
test('R6 G7 the hub label and plain peer links render from config on both pages', async t => {
const links = 'JSON.stringify({label:document.querySelector("#hub-label")?.textContent,hidden:document.querySelector("#federation").hidden,peers:[...document.querySelectorAll("#federation a")].map(a=>[a.getAttribute("href"),a.textContent,a.attributes.length])})';
const expected = { label: 'This Console: hub', hidden: false, peers: [['https://factory.example.test', 'Software factory', 2]] };
@@ -14,12 +14,12 @@ import { busStopForDelete } from '../../cli/src/org-bus.mjs';
import { browser } from './browser.mjs';
import { close } from './fixture.mjs';
async function fixture(t, ids = ['alpha', 'beta']) {
async function fixture(t, ids = ['alpha', 'beta'], { health = null } = {}) {
const dir = await mkdtemp(join(tmpdir(), 'archive-browser-'));
const configDir = join(dir, 'config'), dataRoot = join(dir, 'data'); await mkdir(configDir, { mode: 0o700 }); await mkdir(dataRoot, { mode: 0o700 });
const ctx = { configDir, dataRoot, instance: 'test', principal: { provider: 'local-dev', iss: 'local-dev', sub: 'local-dev-owner' } };
for (const id of ids) await service.createOrg(ctx, id, await service.templateRender(id));
const busStatus = async () => ({ healthy: false });
const busStatus = async () => ({ healthy: health ? health.up : false });
const organizations = organizationConsole({ ctx, listOrgs: registry.listOrgs, resolveOrg: registry.resolveOrg, showOrg: service.showOrg, orgPaths, busStatus, options: ({ id }) => ({ reads: { business: async () => ({ business: { id, projects: ['work'] } }), settings: async () => ({}) }, bus: {}, send: async () => ({}) }) });
const admin = createOrgAdmin({ service, registry, bus: { busStatus, busStopForDelete }, context: async () => ({ configDir, dataRoot, instance: 'test' }) });
const server = await startServer({ port: 0, sso: createDevOwner(), orgAdmin: admin, organizations, send: async () => ({}), board: 'http://127.0.0.1:9', log: () => {} });
@@ -69,6 +69,7 @@ test('archive does not announce success for an unexpected response', { timeout:
await f.b.evaluate(`const original=fetch.bind(window);window.fetch=(input,init)=>String(input).endsWith('/archive')?Promise.resolve(new Response(JSON.stringify({outcome:'done',step:'bus'}),{status:200})):original(input,init);document.querySelector('#org-archive-open').click();document.querySelector('#org-archive-final').click()`);
await f.wait(`!!document.querySelector('#org-archive-error').textContent`);
assert.match(await f.b.evaluate(`document.querySelector('#org-archive-error').textContent`), /outcome is unknown/i);
assert.equal(await f.b.evaluate(`document.querySelector('#org-archive-final').textContent`), 'Archive');
assert.equal(await f.b.evaluate(`document.querySelector('#org-archived').hidden`), true);
assert.equal((await registry.listOrgs(f.ctx)).find(e => e.id === 'beta').state, 'active');
});
@@ -109,3 +110,65 @@ test('archiving the last active organization shows the no-organization state', {
await f.wait(`window.MosaicOrg?.id === 'alpha'`);
assert.equal((await registry.listOrgs(f.ctx))[0].state, 'active');
});
test('fresh archived organization page offers owner restore while writes stay refused', { timeout: 45000 }, async t => {
const f = await fixture(t); await f.open('beta');
await f.b.evaluate(`document.querySelector('#org-archive-open').click();document.querySelector('#org-archive-final').click()`);
await f.wait(`!document.querySelector('#org-archived').hidden`);
await f.b.navigate(`http://127.0.0.1:${f.port}/#/orgs/beta/settings/organizations?org=beta`);
await f.wait(`document.querySelector('#org-archived') && !document.querySelector('#org-archived').hidden`);
assert.equal(await f.b.evaluate(`document.querySelector('#org-restore').disabled`), false);
assert.equal(await f.b.evaluate(`document.querySelector('#org-delete-open').disabled`), false);
assert.match(await f.b.evaluate(`document.querySelector('#org-archived').innerText`), /mosaic org restore beta --if-revision \d+/);
const refused = await f.b.evaluate(`Promise.all(['/api/orgs/beta/chat/projects','/api/orgs/beta/chat/threads/00000000-0000-0000-0000-000000000000/messages'].map(url=>fetch(url,{method:'POST',headers:{'content-type':'application/json'},body:'{}'}).then(r=>r.status)))`);
assert.deepEqual(refused, [409, 409]);
await f.b.evaluate(`document.querySelector('#org-restore').click()`);
await f.wait(`!document.querySelector('#org-archive-success').hidden`);
assert.equal((await registry.listOrgs(f.ctx)).find(e => e.id === 'beta').state, 'active');
});
test('owner can start a down bus after setup recorded done and sees recovery guidance on refusal', { timeout: 45000 }, async t => {
const f = await fixture(t);
await f.b.evaluate(`(()=>{const old=window.fetch;window.fetch=async (input,init={})=>{const u=String(input);if(u.endsWith('/setup') && (!init.method || init.method==='GET'))return new Response(JSON.stringify({notifications:{state:'done'},queue:{state:'done'},projects:[],bus:{state:'done',verb:'mosaic bus start alpha'}}),{status:200});if(u.endsWith('/setup/bus') && init.method==='POST')return new Response(JSON.stringify({error:'stale-lock',message:'stale bus host lock'}),{status:409});return old(input,init)}})()`);
await f.open('alpha');
assert.equal(await f.b.evaluate(`!!document.querySelector('[data-step="bus"] [data-run="bus"]:not(:disabled)')`), true);
await f.b.evaluate(`document.querySelector('[data-step="bus"] [data-run="bus"]').click()`);
await f.wait(`document.querySelector('[data-step="bus"]').innerText.includes('stale bus host lock')`);
assert.match(await f.b.evaluate(`document.querySelector('[data-step="bus"]').innerText`), /mosaic bus recover alpha/);
});
// E2E5 review P2: the list read by Refresh, not only opening the organization, decides whether Start shows.
test('an open Settings page offers Start when a refreshed org list reads the bus down after setup recorded done', { timeout: 45000 }, async t => {
const health = { up: true };
const f = await fixture(t, ['alpha', 'beta'], { health });
await f.b.evaluate(`(()=>{const old=window.fetch;window.fetch=async (input,init={})=>{const u=String(input);if(u.endsWith('/setup') && (!init.method || init.method==='GET'))return new Response(JSON.stringify({notifications:{state:'done'},queue:{state:'done'},projects:[],bus:{state:'done',verb:'mosaic bus start alpha'}}),{status:200});return old(input,init);};})()`);
await f.open('alpha');
await f.wait(`document.querySelector('[data-step="bus"]')?.textContent.includes('Done')`);
assert.equal(await f.b.evaluate(`!!document.querySelector('[data-step="bus"] [data-run="bus"]')`), false);
health.up = false;
await f.b.evaluate(`document.querySelector('#refresh').click()`);
await f.wait(`!!document.querySelector('[data-step="bus"] [data-run="bus"]:not(:disabled)')`);
health.up = true;
await f.b.evaluate(`document.querySelector('#refresh').click()`);
await f.wait(`!document.querySelector('[data-step="bus"] [data-run="bus"]')`);
});
for (const capability of [{ user:true, orgSetup:false }, { tester:true, orgSetup:false }, { orgSetup:false }]) {
test(`archived restore stays disabled without owner capability ${JSON.stringify(capability)}`, { timeout: 45000 }, async t => {
const f = await fixture(t); await f.open('beta');
await f.b.evaluate(`document.querySelector('#org-archive-open').click();document.querySelector('#org-archive-final').click()`);
await f.wait(`!document.querySelector('#org-archived').hidden`);
await f.b.call('Page.addScriptToEvaluateOnNewDocument', {source:`{const old=window.fetch;window.fetch=(input,init)=>input instanceof URL && input.pathname==='/api/config'?Promise.resolve(new Response(JSON.stringify(${JSON.stringify(capability)}),{status:200})):old(input,init)}`});
await f.b.navigate(`http://127.0.0.1:${f.port}/#/orgs/beta/settings/organizations?org=beta`);
await f.wait(`document.querySelector('#org-archived') && !document.querySelector('#org-archived').hidden`);
assert.equal(await f.b.evaluate(`document.querySelector('#org-restore').disabled`),true);
assert.equal(await f.b.evaluate(`document.querySelector('#org-delete-open').disabled`),true);
});
}
test('archive displays progress while its request is in flight', { timeout: 45000 }, async t => {
const f = await fixture(t); await f.open('beta');
await f.b.evaluate(`{const old=window.fetch;window.fetch=(input,init)=>String(input).endsWith('/archive')?new Promise(resolve=>window.releaseArchive=()=>old(input,init).then(resolve)):old(input,init);document.querySelector('#org-archive-open').click();document.querySelector('#org-archive-final').click()}`);
assert.equal(await f.b.evaluate(`document.querySelector('#org-archive-final').textContent`),'Archiving…');
await f.b.evaluate(`window.releaseArchive()`); await f.wait(`!document.querySelector('#org-archived').hidden`);
});
@@ -121,3 +121,14 @@ test('changed requirement content retains the disclosure and focused summary',as
const result=await run(()=>{const d=document.querySelector('[data-project-content] .project-columns section details');return {open:d.open,focused:document.activeElement===d.querySelector('summary')}});
assert.deepEqual(result,{open:true,focused:true});
});
test('closed room on an organization Console offers no unusable open action', async t => {
const {b,render,wait}=await setup(t,'/projects/rooms/'+P);
await b.evaluate(`window.MosaicOrg={id:'alpha',route:()=>'/projects/rooms/${P}'};window.reviewClosed=true`);
await render('/projects/rooms/'+P);
await wait(`document.querySelector('.chat-room')`);
const result=await b.evaluate(`({text:document.querySelector('.chat-area').innerText,open:!!document.querySelector('[data-room-open-inline],#chat-room-open')})`);
assert.match(result.text,/Room changes are unavailable on this Console\./);
assert.doesNotMatch(result.text,/Open the room before sending/);
assert.equal(result.open,false);
});
@@ -266,3 +266,18 @@ test('a stopped organization bus has truthful chat guidance', async t => {
assert.match(text, /bus is stopped.*Start the bus/i);
assert.doesNotMatch(text, /This Console only reads/);
});
test('organization conversation recovers send capability and preserves its draft after an outage', async t => {
const { fixture } = await import('./fixture.mjs');
const { P, T, stub } = await import('./helpers/projects-review-fixture.mjs');
const f=await fixture(); t.after(()=>f.close());
const b=await browser({machine:false}); t.after(()=>b.close());
await b.call('Page.addScriptToEvaluateOnNewDocument',{source:stub + `\nwindow.MosaicOrg={id:'alpha',route:()=>'/projects/threads/${T}',list:Promise.resolve([]),readList:async()=>[]};window.configUp=false;{const old=fetch;window.fetch=(url,init)=>String(url)==='/api/config'?Promise.resolve(new Response(JSON.stringify({chatSend:window.configUp,orgSetup:true,devOwner:true,sso:true}),{status:200})):old(url,init)}`});
await b.navigate(f.base+'/#/projects/threads/'+T);
const wait=expr=>b.evaluate(`(async()=>{for(let i=0;i<200;i++){if(${expr})return;await new Promise(r=>setTimeout(r,30))}throw Error(${JSON.stringify(expr)})})()`);
await wait(`document.querySelector('#chat-body')`);
assert.equal(await b.evaluate(`document.querySelector('#chat-body').disabled`),true);
await b.evaluate(`const el=document.querySelector('#chat-body');el.value='draft kept';el.dispatchEvent(new Event('input',{bubbles:true}));window.configUp=true;document.querySelector('#refresh').click()`);
await wait(`!document.querySelector('#chat-body').disabled`);
assert.equal(await b.evaluate(`document.querySelector('#chat-body').value`),'draft kept');
});
@@ -163,3 +163,16 @@ test('sidebar sprite is requested again after a failed read and recovery', async
const after = await b.evaluate(`document.querySelector('#sections use[href*="icons.svg"]').getAttribute('href')`);
assert.notEqual(after,before);
});
test('sidebar sprite is retried after an outage redraw before reads recover', async t => {
const {b,wait}=await setup(t,'/projects');
await wait(`document.querySelector('#sections use[href*="icons.svg"]')`);
const before=await b.evaluate(`document.querySelector('#sections use').getAttribute('href')`);
await b.evaluate(`{const old=window.fetch;window.netDown=true;window.fetch=(url,init)=>window.netDown && String(url).startsWith('/api/')?Promise.reject(new TypeError('offline')):old(url,init);document.querySelector('#refresh').click()}`);
await wait(`document.querySelector('.chat-error')`);
await b.evaluate(`document.querySelector('#refresh').click()`);
await b.evaluate(`new Promise(r=>setTimeout(r,100))`);
await b.evaluate(`window.netDown=false;document.querySelector('#refresh').click()`);
await wait(`!document.querySelector('.chat-error') && document.querySelector('#sections use[href*="?retry="]')`);
assert.notEqual(await b.evaluate(`document.querySelector('#sections use').getAttribute('href')`),before);
});