quadwork 1.2.5 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +189 -82
  2. package/bin/quadwork.js +102 -0
  3. package/out/404.html +1 -1
  4. package/out/__next.__PAGE__.txt +3 -3
  5. package/out/__next._full.txt +12 -12
  6. package/out/__next._head.txt +4 -4
  7. package/out/__next._index.txt +6 -6
  8. package/out/__next._tree.txt +2 -2
  9. package/out/_next/static/chunks/006g3lco-9xqf.js +1 -0
  10. package/out/_next/static/chunks/035rt-n0oid7d.js +1 -0
  11. package/out/_next/static/chunks/{0e~ue9ca5zrep.js → 05ok82hwk0x-c.js} +1 -1
  12. package/out/_next/static/chunks/0u~7e4fgf-u06.css +2 -0
  13. package/out/_next/static/chunks/0zqyw6q.jp~1i.js +26 -0
  14. package/out/_next/static/chunks/17y2walb2um9w.js +1 -0
  15. package/out/_next/static/chunks/{16ell.n1p8o7d.js → 18cmux34jwe.p.js} +1 -1
  16. package/out/_not-found/__next._full.txt +11 -11
  17. package/out/_not-found/__next._head.txt +4 -4
  18. package/out/_not-found/__next._index.txt +6 -6
  19. package/out/_not-found/__next._not-found.__PAGE__.txt +2 -2
  20. package/out/_not-found/__next._not-found.txt +3 -3
  21. package/out/_not-found/__next._tree.txt +2 -2
  22. package/out/_not-found.html +1 -1
  23. package/out/_not-found.txt +11 -11
  24. package/out/app-shell/__next._full.txt +11 -11
  25. package/out/app-shell/__next._head.txt +4 -4
  26. package/out/app-shell/__next._index.txt +6 -6
  27. package/out/app-shell/__next._tree.txt +2 -2
  28. package/out/app-shell/__next.app-shell.__PAGE__.txt +2 -2
  29. package/out/app-shell/__next.app-shell.txt +3 -3
  30. package/out/app-shell.html +1 -1
  31. package/out/app-shell.txt +11 -11
  32. package/out/index.html +1 -1
  33. package/out/index.txt +12 -12
  34. package/out/project/_/__next._full.txt +12 -12
  35. package/out/project/_/__next._head.txt +4 -4
  36. package/out/project/_/__next._index.txt +6 -6
  37. package/out/project/_/__next._tree.txt +2 -2
  38. package/out/project/_/__next.project.$d$id.__PAGE__.txt +3 -3
  39. package/out/project/_/__next.project.$d$id.txt +3 -3
  40. package/out/project/_/__next.project.txt +3 -3
  41. package/out/project/_/memory/__next._full.txt +12 -12
  42. package/out/project/_/memory/__next._head.txt +4 -4
  43. package/out/project/_/memory/__next._index.txt +6 -6
  44. package/out/project/_/memory/__next._tree.txt +2 -2
  45. package/out/project/_/memory/__next.project.$d$id.memory.__PAGE__.txt +3 -3
  46. package/out/project/_/memory/__next.project.$d$id.memory.txt +3 -3
  47. package/out/project/_/memory/__next.project.$d$id.txt +3 -3
  48. package/out/project/_/memory/__next.project.txt +3 -3
  49. package/out/project/_/memory.html +1 -1
  50. package/out/project/_/memory.txt +12 -12
  51. package/out/project/_/queue/__next._full.txt +12 -12
  52. package/out/project/_/queue/__next._head.txt +4 -4
  53. package/out/project/_/queue/__next._index.txt +6 -6
  54. package/out/project/_/queue/__next._tree.txt +2 -2
  55. package/out/project/_/queue/__next.project.$d$id.queue.__PAGE__.txt +3 -3
  56. package/out/project/_/queue/__next.project.$d$id.queue.txt +3 -3
  57. package/out/project/_/queue/__next.project.$d$id.txt +3 -3
  58. package/out/project/_/queue/__next.project.txt +3 -3
  59. package/out/project/_/queue.html +1 -1
  60. package/out/project/_/queue.txt +12 -12
  61. package/out/project/_.html +1 -1
  62. package/out/project/_.txt +12 -12
  63. package/out/settings/__next._full.txt +12 -12
  64. package/out/settings/__next._head.txt +4 -4
  65. package/out/settings/__next._index.txt +6 -6
  66. package/out/settings/__next._tree.txt +2 -2
  67. package/out/settings/__next.settings.__PAGE__.txt +3 -3
  68. package/out/settings/__next.settings.txt +3 -3
  69. package/out/settings.html +1 -1
  70. package/out/settings.txt +12 -12
  71. package/out/setup/__next._full.txt +12 -12
  72. package/out/setup/__next._head.txt +4 -4
  73. package/out/setup/__next._index.txt +6 -6
  74. package/out/setup/__next._tree.txt +2 -2
  75. package/out/setup/__next.setup.__PAGE__.txt +3 -3
  76. package/out/setup/__next.setup.txt +3 -3
  77. package/out/setup.html +1 -1
  78. package/out/setup.txt +12 -12
  79. package/out/sounds/alert-tone.mp3 +0 -0
  80. package/out/sounds/click.mp3 +0 -0
  81. package/out/sounds/pluck.mp3 +0 -0
  82. package/out/sounds/soft-chime.mp3 +0 -0
  83. package/out/sounds/warm-bell.mp3 +0 -0
  84. package/package.json +5 -2
  85. package/server/config.js +43 -1
  86. package/server/index.js +268 -21
  87. package/server/routes.js +1103 -7
  88. package/templates/CLAUDE.md +1 -0
  89. package/templates/OVERNIGHT-QUEUE.md +1 -1
  90. package/templates/seeds/head.AGENTS.md +21 -2
  91. package/out/_next/static/chunks/0-yus965h3bk_.js +0 -24
  92. package/out/_next/static/chunks/0caq73v0knw_w.js +0 -1
  93. package/out/_next/static/chunks/0d.f~y5jeh785.css +0 -2
  94. package/out/_next/static/chunks/0md7hgvwnovzq.js +0 -1
  95. package/out/_next/static/chunks/0spbjcw4anq15.js +0 -1
  96. /package/out/_next/static/{Cpy01wZHv0vXd_j_HlrSf → 6uvV3nUfwr_t_JKrZJSP8}/_buildManifest.js +0 -0
  97. /package/out/_next/static/{Cpy01wZHv0vXd_j_HlrSf → 6uvV3nUfwr_t_JKrZJSP8}/_clientMiddlewareManifest.js +0 -0
  98. /package/out/_next/static/{Cpy01wZHv0vXd_j_HlrSf → 6uvV3nUfwr_t_JKrZJSP8}/_ssgManifest.js +0 -0
package/README.md CHANGED
@@ -1,11 +1,55 @@
1
+ <div align="center">
2
+
1
3
  # QuadWork
2
4
 
3
- Your AI dev team in a box. Four agents — one Head, one Dev, two Reviewers — that code, review, and ship while you sleep.
5
+ ### Your AI dev team while you sleep.
6
+
7
+ <p>
8
+ <a href="#-quick-start"><strong>Quick Start</strong></a> ·
9
+ <a href="#-how-it-works"><strong>How it Works</strong></a> ·
10
+ <a href="#-features"><strong>Features</strong></a> ·
11
+ <a href="#-external-tools"><strong>Credits</strong></a> ·
12
+ <a href="https://github.com/bcurts/agentchattr"><strong>Built on AgentChattr</strong></a>
13
+ </p>
14
+
15
+ <p>
16
+ <a href="https://www.npmjs.com/package/quadwork"><img src="https://img.shields.io/npm/v/quadwork" alt="npm version" /></a>
17
+ <a href="https://www.npmjs.com/package/quadwork"><img src="https://img.shields.io/npm/dm/quadwork" alt="npm downloads" /></a>
18
+ <a href="https://github.com/realproject7/quadwork/releases/latest"><img src="https://img.shields.io/github/v/release/realproject7/quadwork" alt="latest release" /></a>
19
+ <img src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey" alt="platform" />
20
+ <img src="https://img.shields.io/badge/runs-locally-00d4aa" alt="runs locally" />
21
+ <img src="https://img.shields.io/badge/agents-4-orange" alt="4 agents" />
22
+ <a href="https://github.com/bcurts/agentchattr"><img src="https://img.shields.io/badge/built_on-AgentChattr-8b5cf6" alt="AgentChattr" /></a>
23
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT License" /></a>
24
+ </p>
25
+
26
+ </div>
27
+
28
+ ---
29
+
30
+ ## Why QuadWork?
31
+
32
+ Manually reviewing every AI-generated PR is exhausting. Letting one AI agent
33
+ push straight to `main` is how you end up rolling back broken migrations at
34
+ 2am. QuadWork runs a **four-agent team** that enforces a real GitHub workflow
35
+ on each other — code, review, ship — autonomously, with safety rails.
36
+
37
+ - 🤖 **Runs 24/7** — agents keep working overnight while you rest
38
+ - 🛡️ **Always reviewed** — every PR needs **2 independent approvals** before merge
39
+ - 🔒 **Local-first** — the dashboard, terminals, chat server, and PTY sessions all run on your machine. The agents still make outbound calls to the LLM APIs you've configured (Claude / Codex / Gemini) and to GitHub, and the optional Telegram bridge mirrors chat to your phone. QuadWork itself doesn't host or proxy any of that traffic through a third party
4
40
 
5
- ## Getting Started
41
+ ## Who is QuadWork for?
42
+
43
+ - **Solo founders / indie hackers** who want to ship faster than they can review
44
+ - **Open-source maintainers** who get more PRs than they have hours to look at
45
+ - **Engineers** who want a team workflow without the overhead of hiring
46
+ - **Tinkerers** who've tried Claude Code / Codex and wished they had reviewers who pushed back
47
+
48
+ ## ─ Quick Start
6
49
 
7
50
  1. Install [Node.js 20+](https://nodejs.org) if you don't have it
8
- 2. Install [Homebrew](https://brew.sh) if you're on macOS: `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
51
+ 2. On macOS, install [Homebrew](https://brew.sh):
52
+ `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
9
53
  3. Open your terminal and run:
10
54
 
11
55
  ```bash
@@ -14,11 +58,14 @@ npx quadwork init
14
58
 
15
59
  4. The wizard installs everything else and opens your dashboard.
16
60
 
17
- That's it. The wizard handles Python, GitHub CLI, AI tools, and authentication — you just follow the prompts.
61
+ That's it. The wizard handles Python, GitHub CLI, AI tools, and
62
+ authentication — you just follow the prompts. Subsequent runs are one
63
+ command: `npx quadwork start`.
18
64
 
19
- ## How It Works
65
+ ## How it Works
20
66
 
21
- QuadWork runs a team of 4 AI agents on your local machine:
67
+ QuadWork runs a team of 4 AI agents on your local machine and enforces a
68
+ GitHub-native workflow on them:
22
69
 
23
70
  | Agent | Role | What it does |
24
71
  |-------|------|-------------|
@@ -27,81 +74,104 @@ QuadWork runs a team of 4 AI agents on your local machine:
27
74
  | **Reviewer1** | Reviewer | Independent code review with veto authority |
28
75
  | **Reviewer2** | Reviewer | Independent code review with veto authority |
29
76
 
30
- Every task follows a GitHub workflow: Issue → Branch → PR → 2 Reviews → Merge. Branch protection ensures no agent can skip the process.
31
-
32
- ## Dashboard
33
-
34
- ```
35
- +--------+----------------------------+----------------------------+
36
- | | Head Terminal | GitHub (Issues + PRs) |
37
- | Side- | (Coordinator) | |
38
- | bar +----------------------------+----------------------------+
39
- | | Agent Chat | Reviewer1 | Reviewer2 |
40
- | [Home] | (AgentChattr) | | |
41
- | [Proj] | +-------------+--------------+
42
- | [+] | | Dev Terminal |
43
- | [Set] | | (Builder) |
44
- +--------+----------------------------+----------------------------+
45
- | Keep Alive | Server: Stop Restart Reset | System: Keep Awake |
46
- +--------+----------------------------+----------------------------+
47
- ```
48
-
49
- ## Features
50
-
51
- - **Terminal panels** — Live terminals for each agent with PTY sessions
52
- - **Agent chat** — Real-time agent coordination via AgentChattr
53
- - **GitHub board** — Issues, PRs, and review status at a glance
54
- - **Task queue** — Build and dispatch work queues with one click
55
- - **Keep Alive** — Scheduled check-in messages to keep agents active (with auto-stop duration)
56
- - **Keep Awake** — Prevent your Mac from sleeping during overnight runs
57
- - **Multi-project** — Each project gets its own AgentChattr instance and ports
58
- - **Telegram bridge** — Optional mobile notifications via [agentchattr-telegram](https://github.com/realproject7/agentchattr-telegram)
59
-
60
- ## Commands
61
-
62
- | Command | Description |
63
- |---------|-------------|
64
- | `npx quadwork init` | One-time setup — installs prerequisites and opens the dashboard |
65
- | `npx quadwork start` | Start the dashboard server |
66
- | `npx quadwork stop` | Stop all processes |
67
- | `npx quadwork cleanup --project <id>` | Remove a project's AgentChattr clone and config entry |
68
- | `npx quadwork cleanup --legacy` | Remove the legacy `~/.quadwork/agentchattr/` install after migration |
69
-
70
- After init, create projects from the web UI at `http://127.0.0.1:8400/setup`.
71
-
72
- ### Disk usage
73
-
74
- Each project gets its own AgentChattr clone at `~/.quadwork/{project_id}/agentchattr/` (~77 MB). For example:
75
-
76
- | Projects | Disk |
77
- |---------:|-----:|
78
- | 1 | ~77 MB |
79
- | 5 | ~385 MB |
80
- | 10 | ~770 MB |
81
-
82
- Per-project clones are necessary so multiple projects can run AgentChattr simultaneously without port conflicts (each clone has its own `config.toml`, ports, and data directory).
77
+ Every task follows the same cycle: **Issue → Branch → PR → 2 Reviews → Merge**.
78
+ Branch protection ensures no agent can skip the process.
83
79
 
84
- To free space, delete unused projects from the dashboard or run:
80
+ ### The full autonomous loop
85
81
 
86
- ```sh
87
- npx quadwork cleanup --project <id>
88
82
  ```
89
-
90
- Existing v1 users are auto-migrated to per-project clones on the next `npx quadwork start`. After all projects are migrated, the legacy shared install can be removed with:
91
-
92
- ```sh
93
- npx quadwork cleanup --legacy
83
+ You: "@head start a batch for feature X"
84
+
85
+
86
+ Head: creates issues + queue, asks you to kick off the batch
87
+
88
+ ▼ (you click "Start Trigger" in the Operator panel)
89
+ Head: assigns the first issue to Dev
90
+
91
+
92
+ Dev: opens a PR with code
93
+
94
+
95
+ Reviewer1 + Reviewer2: independent reviews
96
+
97
+ ▼ (both approve)
98
+ Head: merges, picks the next issue
99
+
100
+ └──── repeat overnight ────┐
101
+
102
+
103
+ You wake up to merged PRs
94
104
  ```
95
105
 
96
- `cleanup --legacy` refuses to run unless every project already has its own working per-project clone, so it can never strand a project on a missing install.
97
-
98
- ## Configuration
99
-
100
- Config is stored at `~/.quadwork/config.json`:
106
+ ### A concrete example
107
+
108
+ 1. You drop a batch of 5 related tickets into chat: `@head start 5 sub-tickets under #123`.
109
+ 2. Head files the 5 issues on GitHub, writes them to `OVERNIGHT-QUEUE.md`, and asks you to click **Start Trigger**.
110
+ 3. You click it, close the laptop, and sleep.
111
+ 4. The Scheduled Trigger pulses the agents every 15 minutes. Each pulse, Head assigns the next queued issue to Dev.
112
+ 5. Dev opens a PR. Reviewer1 + Reviewer2 each review independently — approve, request changes, or veto. Dev iterates until both approve.
113
+ 6. Head merges and picks the next ticket. Loop until the queue is empty or the duration expires.
114
+ 7. You wake up to 5 merged PRs, a clean queue, and a chat transcript you can scroll.
115
+
116
+ ## ─ Features
117
+
118
+ ### Dashboard
119
+
120
+ - 📺 **4-quadrant project view** — chat, agent terminals (HEAD / DEV / RE1 / RE2), GitHub board, operator panel
121
+ - ⏰ **Scheduled Trigger** — recurring "queue check" pulses for autonomous overnight runs
122
+ - 📲 **Telegram bridge** — mirror the chat to your phone for remote monitoring
123
+ - 💾 **Project history export/import** — JSON snapshots of the full chat transcript
124
+ - 🧯 **Loop Guard control** — raise the hop limit and auto-resume stuck chains without restarting AC
125
+ - 🔔 **Notification sounds** — Web Audio chime on new agent messages with a background-only mode
126
+ - 🎞️ **Current Batch Progress panel** — per-issue progress bars computed from live GitHub state
127
+ - 🗂️ **Recently closed / merged feed** — so finished work doesn't disappear from the GitHub panel
128
+ - 💤 **Keep Mac Awake** — `caffeinate` wrapper so your laptop survives the night
129
+
130
+ ### Workflow
131
+
132
+ - 🧭 **Multi-project support** — each project has its own AgentChattr instance + isolated worktrees
133
+ - 📝 **Per-project `OVERNIGHT-QUEUE.md`** with auto-incrementing batch numbers
134
+ - 💬 **Slash commands** — `/continue`, `/clear`, `/summary`, `/poetry`, `/roastreview`
135
+ - 🏷️ **Chat polish** — threaded replies, colored `@mentions`, short reviewer labels (RE1/RE2)
136
+ - 🧰 **Operator identity** — set your chat display name in Settings
137
+
138
+ ### Safety
139
+
140
+ - 🚧 **GitHub branch protection** enforced on `main`
141
+ - ✅ **2-of-2 reviewer approval** required before merge
142
+ - 🛑 **Sender lockdown** — chat POSTs can't impersonate an agent (`head`, `dev`, …) from the UI
143
+ - 🗄️ **Auto-snapshot** of chat history to `~/.quadwork/{project}/history-snapshots/` before every AgentChattr restart, with an in-dashboard **Restore** button and an optional auto-restore-on-restart opt-in
144
+
145
+ ## ─ External Tools
146
+
147
+ QuadWork stands on top of some great open-source work. Explicit thanks:
148
+
149
+ - **[AgentChattr](https://github.com/bcurts/agentchattr)** — by [@bcurts](https://github.com/bcurts).
150
+ The local chat server + MCP tooling that lets QuadWork's agents talk to
151
+ each other. **QuadWork would not exist without it** — huge thanks to
152
+ bcurts for building such a clean foundation.
153
+ - **[GitHub CLI (`gh`)](https://cli.github.com)** — used by all four agents
154
+ for issues, PRs, reviews, and merges.
155
+ - **[Claude Code](https://github.com/anthropics/claude-code)** — Anthropic's
156
+ CLI. Recommended for the Dev / Reviewer2 roles.
157
+ - **[Codex CLI](https://github.com/openai/codex)** — OpenAI's CLI.
158
+ Recommended for the Head / Reviewer1 roles.
159
+ - **[Next.js](https://nextjs.org)** + **[Express](https://expressjs.com)** —
160
+ dashboard frontend + backend.
161
+ - **[node-pty](https://github.com/microsoft/node-pty)** — embeds the agent
162
+ terminals.
163
+ - **[xterm.js](https://xtermjs.org)** — in-browser terminal rendering.
164
+
165
+ ## ─ Configuration
166
+
167
+ Global config lives at `~/.quadwork/config.json`. Per-project AgentChattr
168
+ config lives at `~/.quadwork/{project_id}/agentchattr/config.toml`. The per-
169
+ project queue lives at `~/.quadwork/{project_id}/OVERNIGHT-QUEUE.md`.
101
170
 
102
171
  ```json
103
172
  {
104
173
  "port": 8400,
174
+ "operator_name": "user",
105
175
  "projects": [
106
176
  {
107
177
  "id": "my-project",
@@ -111,10 +181,13 @@ Config is stored at `~/.quadwork/config.json`:
111
181
  "agentchattr_url": "http://127.0.0.1:8300",
112
182
  "mcp_http_port": 8200,
113
183
  "mcp_sse_port": 8201,
184
+ "auto_continue_loop_guard": false,
185
+ "auto_continue_delay_sec": 30,
186
+ "auto_restore_after_restart": false,
114
187
  "agents": {
115
- "head": { "cwd": "/path/to/project-head", "command": "codex" },
116
- "dev": { "cwd": "/path/to/project-dev", "command": "claude" },
117
- "reviewer1": { "cwd": "/path/to/project-reviewer1", "command": "codex" },
188
+ "head": { "cwd": "/path/to/project-head", "command": "codex" },
189
+ "dev": { "cwd": "/path/to/project-dev", "command": "claude" },
190
+ "reviewer1": { "cwd": "/path/to/project-reviewer1", "command": "codex" },
118
191
  "reviewer2": { "cwd": "/path/to/project-reviewer2", "command": "claude" }
119
192
  }
120
193
  }
@@ -124,16 +197,50 @@ Config is stored at `~/.quadwork/config.json`:
124
197
 
125
198
  Each project gets its own AgentChattr instance, ports, and git worktrees.
126
199
 
127
- ## Architecture
200
+ ## Architecture
201
+
202
+ QuadWork runs as a single Express server on `127.0.0.1:8400`:
203
+
204
+ - **Static frontend** — pre-built Next.js export (the `out/` directory)
205
+ - **REST API** — agent lifecycle, config, GitHub proxy, chat proxy, triggers, loop guard, batch progress, project history
206
+ - **WebSocket** — xterm.js terminal PTY sessions + AgentChattr ws fan-out
128
207
 
129
- QuadWork runs a single Express server that serves:
208
+ Per-project AgentChattr clones live at `~/.quadwork/{project}/agentchattr/`,
209
+ each with their own ports. Per-project git worktrees sit next to the repo:
210
+ `{repo}-head`, `{repo}-dev`, `{repo}-reviewer1`, `{repo}-reviewer2`. The
211
+ dashboard's xterm.js tiles attach to node-pty sessions over a WebSocket;
212
+ nothing about the agent state is held client-side.
130
213
 
131
- - **Static frontend** — Pre-built Next.js export
132
- - **REST API** — Agent lifecycle, config, GitHub, chat proxy, triggers
133
- - **WebSocket** Terminal PTY sessions
214
+ ## Commands
215
+
216
+ | Command | Description |
217
+ |---------|-------------|
218
+ | `npx quadwork init` | One-time setup — installs prerequisites, opens the dashboard |
219
+ | `npx quadwork start` | Start the dashboard server |
220
+ | `npx quadwork stop` | Stop all processes |
221
+ | `npx quadwork cleanup --project <id>` | Remove a project's AgentChattr clone and config entry |
222
+ | `npx quadwork cleanup --legacy` | Remove the legacy `~/.quadwork/agentchattr/` install after migration |
223
+
224
+ After `init`, create projects from the web UI at `http://127.0.0.1:8400/setup`.
225
+
226
+ ### Disk usage
227
+
228
+ Each project gets its own AgentChattr clone at
229
+ `~/.quadwork/{project_id}/agentchattr/` (~77 MB per project):
230
+
231
+ | Projects | Disk |
232
+ |---------:|-----:|
233
+ | 1 | ~77 MB |
234
+ | 5 | ~385 MB |
235
+ | 10 | ~770 MB |
134
236
 
135
- All on one port (`127.0.0.1:8400`).
237
+ Per-project clones are necessary so multiple projects can run AgentChattr
238
+ simultaneously without port conflicts. Existing v1 users are auto-migrated
239
+ to per-project clones on the next `npx quadwork start`; once every project
240
+ has a working clone, the legacy shared install can be removed safely via
241
+ `npx quadwork cleanup --legacy` (which refuses to run if any project is
242
+ still on the legacy install).
136
243
 
137
- ## License
244
+ ## License
138
245
 
139
246
  MIT
package/bin/quadwork.js CHANGED
@@ -1172,6 +1172,14 @@ function writeQuadWorkConfig(setup) {
1172
1172
  header("Writing QuadWork Config");
1173
1173
 
1174
1174
  const config = readConfig();
1175
+ // #405 / quadwork#278: ensure the global config has an
1176
+ // operator_name slot. /api/chat reads this on every send and
1177
+ // sanitizes empty/missing values back to "user", so leaving it
1178
+ // unset is safe — but writing the default explicitly makes the
1179
+ // setting discoverable in the on-disk file.
1180
+ if (typeof config.operator_name !== "string") {
1181
+ config.operator_name = "user";
1182
+ }
1175
1183
 
1176
1184
  const project = {
1177
1185
  id: setup.projectName,
@@ -1480,6 +1488,92 @@ function migrateLegacyProjects(config) {
1480
1488
  return true;
1481
1489
  }
1482
1490
 
1491
+ /**
1492
+ * #403 / quadwork#274 migration: ensure every per-project config.toml
1493
+ * has `[routing] max_agent_hops = 30`. Idempotent + line-based so
1494
+ * existing comments and other keys in the [routing] section are
1495
+ * preserved.
1496
+ *
1497
+ * #415 / quadwork#298: previous version skipped projects that had
1498
+ * a [routing] section but no max_agent_hops key (e.g. only
1499
+ * `default = "none"`). Those projects silently retained AC's
1500
+ * default of 4 and kept firing the loop guard mid-cycle. This
1501
+ * version handles three cases:
1502
+ *
1503
+ * 1. max_agent_hops already set → no change
1504
+ * 2. [routing] section exists,
1505
+ * max_agent_hops missing → insert key under the header
1506
+ * 3. no [routing] section at all → append a fresh section
1507
+ */
1508
+ function migrateLoopGuardDefaults(config) {
1509
+ if (!config.projects || config.projects.length === 0) return;
1510
+ for (const project of config.projects) {
1511
+ if (!project.id) continue;
1512
+ const tomlPath = project.agentchattr_dir
1513
+ ? path.join(project.agentchattr_dir, "config.toml")
1514
+ : path.join(CONFIG_DIR, project.id, "agentchattr", "config.toml");
1515
+ if (!fs.existsSync(tomlPath)) continue;
1516
+ let content;
1517
+ try { content = fs.readFileSync(tomlPath, "utf-8"); } catch { continue; }
1518
+ // Case 1: key already present *inside* the [routing] section.
1519
+ // We must NOT short-circuit on a same-named key in some other
1520
+ // table (e.g. `[other]\nmax_agent_hops = 7`) because that would
1521
+ // leave a real partial [routing] section unpatched. Walk the
1522
+ // file line-by-line, find the [routing] header, and collect
1523
+ // lines until the next [section] header or EOF. JS regex has
1524
+ // no \z anchor and no reliable EOF lookahead inside /m, so a
1525
+ // line scan is the simplest correct approach and also keeps
1526
+ // pathological strings ("default = \"lazy\"") from confusing
1527
+ // anything in the matcher.
1528
+ const lines = content.split(/\r?\n/);
1529
+ let inRouting = false;
1530
+ let routingKeyPresent = false;
1531
+ for (const line of lines) {
1532
+ const headerMatch = line.match(/^\s*\[([^\]]+)\]/);
1533
+ if (headerMatch) {
1534
+ inRouting = headerMatch[1].trim() === "routing";
1535
+ continue;
1536
+ }
1537
+ if (inRouting && /^\s*max_agent_hops\s*=/.test(line)) {
1538
+ routingKeyPresent = true;
1539
+ break;
1540
+ }
1541
+ }
1542
+ if (routingKeyPresent) continue;
1543
+ let next;
1544
+ if (/^\s*\[routing\]/m.test(content)) {
1545
+ // Case 2: section exists, key missing. Insert the key on the
1546
+ // line right after the [routing] header so it's scoped to the
1547
+ // section regardless of what other keys / comments live there.
1548
+ // Anchored to ^ so a `[routing]` substring inside a string
1549
+ // value can't false-match. The header line is allowed to:
1550
+ // - have a trailing inline comment (`[routing] # keep me`)
1551
+ // - end the file with no trailing newline at all
1552
+ // The line-break group is captured separately and re-emitted,
1553
+ // synthesizing a `\n` if the file ended exactly at the header
1554
+ // (otherwise the new key would land glued to whatever the
1555
+ // bracket was sitting on).
1556
+ next = content.replace(
1557
+ /^(\s*\[routing\][^\r\n]*)(\r?\n|$)/m,
1558
+ (_match, header, lineBreak) => {
1559
+ const lb = lineBreak || "\n";
1560
+ return `${header}${lb}max_agent_hops = 30\n`;
1561
+ },
1562
+ );
1563
+ } else {
1564
+ // Case 3: no section. Append a fresh one at the end of the
1565
+ // file with both default + max_agent_hops.
1566
+ const trailing = content.endsWith("\n") ? "" : "\n";
1567
+ next = content + `${trailing}\n[routing]\ndefault = "none"\nmax_agent_hops = 30\n`;
1568
+ }
1569
+ if (next === content) continue;
1570
+ try {
1571
+ fs.writeFileSync(tomlPath, next);
1572
+ log(` Loop guard default → ${project.id} (max_agent_hops = 30)`);
1573
+ } catch { /* non-fatal */ }
1574
+ }
1575
+ }
1576
+
1483
1577
  function cmdStart() {
1484
1578
  console.log("\n QuadWork Start\n");
1485
1579
 
@@ -1493,6 +1587,14 @@ function cmdStart() {
1493
1587
  // Idempotent — a no-op once every project already has a working clone.
1494
1588
  migrateLegacyProjects(config);
1495
1589
 
1590
+ // Batch 30 / #403 / quadwork#274: ensure every existing project's
1591
+ // AgentChattr config.toml has [routing] max_agent_hops = 30 so the
1592
+ // loop guard doesn't fire mid-PR-cycle. Idempotent: leaves any
1593
+ // pre-existing routing section alone (only adds the section + key
1594
+ // when both are missing). Failures are non-fatal — the project
1595
+ // will just keep its current loop guard.
1596
+ migrateLoopGuardDefaults(config);
1597
+
1496
1598
  const quadworkDir = path.join(__dirname, "..");
1497
1599
  const port = config.port || 8400;
1498
1600
 
package/out/404.html CHANGED
@@ -1 +1 @@
1
- <!DOCTYPE html><html lang="en" class="geist_mono_8d43a2aa-module__8Li5zG__variable h-full"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/0d.f~y5jeh785.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/0z~0.4hivi.f2.js"/><script src="/_next/static/chunks/0ezniz80psxr6.js" async=""></script><script src="/_next/static/chunks/0r7t_sj_sejq9.js" async=""></script><script src="/_next/static/chunks/15i5_ay.0ap.6.js" async=""></script><script src="/_next/static/chunks/0excsn2a_5qsb.js" async=""></script><script src="/_next/static/chunks/turbopack-0wh29ykoy-rb5.js" async=""></script><script src="/_next/static/chunks/0e~ue9ca5zrep.js" async=""></script><script src="/_next/static/chunks/0ox7p_szjhn69.js" async=""></script><meta name="robots" content="noindex"/><meta name="next-size-adjust" content=""/><title>404: This page could not be found.</title><title>QuadWork</title><meta name="description" content="Unified dashboard for multi-agent coding teams"/><link rel="icon" href="/favicon.ico?favicon.0x3dzn~oxb6tn.ico" sizes="256x256" type="image/x-icon"/><script src="/_next/static/chunks/03~yq9q893hmn.js" noModule=""></script></head><body class="h-full flex flex-col"><div hidden=""><!--$--><!--/$--></div><header class="sticky top-0 z-40 flex h-12 items-center justify-between border-b border-white/10 bg-neutral-950/90 px-4 backdrop-blur"><div class="flex items-center gap-3 min-w-0"><a class="text-sm font-bold text-white hover:text-blue-400 shrink-0" href="/">QuadWork</a><span class="hidden sm:inline text-neutral-600">|</span><span class="hidden sm:inline text-[13px] text-neutral-400 truncate">Your AI dev team while you<!-- --> <span class="text-neutral-200"></span><span class="ml-0.5 inline-block w-[1px] h-[12px] align-middle bg-neutral-400 animate-qw-blink"></span></span></div><div class="flex items-center gap-3 shrink-0"><button type="button" aria-label="About QuadWork" class="rounded p-1 text-neutral-400 hover:bg-white/5 hover:text-white"><svg width="18" height="18" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="8"></circle><path d="M10 9v5" stroke-linecap="round"></path><circle cx="10" cy="6.5" r="0.8" fill="currentColor"></circle></svg></button><a href="https://github.com/realproject7/quadwork" target="_blank" rel="noopener noreferrer" class="text-[12px] text-neutral-400 hover:text-white">QuadWork github</a></div></header><div class="flex flex-1 min-h-0"><aside class="w-16 shrink-0 h-full border-r border-border bg-bg-surface flex flex-col items-center py-3"><a class="w-10 h-10 flex items-center justify-center rounded-sm transition-colors text-text-muted hover:text-text hover:bg-[#1a1a1a]" title="Home" href="/"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 10L10 3l7 7"></path><path d="M5 8.5V16h3.5v-4h3v4H15V8.5"></path></svg></a><div class="w-6 h-px bg-border my-2"></div><div class="flex-1 flex flex-col items-center gap-2 overflow-y-auto min-h-0"><a class="w-10 h-10 flex items-center justify-center rounded-full border border-dashed border-border text-text-muted hover:text-text hover:bg-[#1a1a1a] transition-colors" title="Add project" href="/setup"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M8 3v10M3 8h10"></path></svg></a></div><div class="w-6 h-px bg-border my-2"></div><a class="w-10 h-10 flex items-center justify-center rounded-sm transition-colors text-text-muted hover:text-text hover:bg-[#1a1a1a]" title="Settings" href="/settings"><svg width="18" height="18" viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="9" r="2.5"></circle><path d="M7.5 1.5h3l.4 2.1a5.5 5.5 0 011.3.7l2-.8 1.5 2.6-1.6 1.3a5.5 5.5 0 010 1.5l1.6 1.3-1.5 2.6-2-.8a5.5 5.5 0 01-1.3.7l-.4 2.1h-3l-.4-2.1a5.5 5.5 0 01-1.3-.7l-2 .8-1.5-2.6 1.6-1.3a5.5 5.5 0 010-1.5L2.3 6.1l1.5-2.6 2 .8a5.5 5.5 0 011.3-.7z"></path></svg></a></aside><main class="flex-1 min-w-0 overflow-auto"><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--></main></div><script src="/_next/static/chunks/0z~0.4hivi.f2.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[34852,[\"/_next/static/chunks/0e~ue9ca5zrep.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n3:I[86081,[\"/_next/static/chunks/0e~ue9ca5zrep.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n4:I[12527,[\"/_next/static/chunks/0e~ue9ca5zrep.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n5:I[59763,[\"/_next/static/chunks/0e~ue9ca5zrep.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n6:I[11717,[\"/_next/static/chunks/0e~ue9ca5zrep.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"OutletBoundary\"]\n7:\"$Sreact.suspense\"\na:I[11717,[\"/_next/static/chunks/0e~ue9ca5zrep.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"ViewportBoundary\"]\nc:I[11717,[\"/_next/static/chunks/0e~ue9ca5zrep.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"MetadataBoundary\"]\ne:I[92243,[\"/_next/static/chunks/0e~ue9ca5zrep.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/0d.f~y5jeh785.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"_not-found\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0d.f~y5jeh785.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0e~ue9ca5zrep.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/0ox7p_szjhn69.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"geist_mono_8d43a2aa-module__8Li5zG__variable h-full\",\"children\":[\"$\",\"body\",null,{\"className\":\"h-full flex flex-col\",\"children\":[[\"$\",\"$L2\",null,{}],[\"$\",\"div\",null,{\"className\":\"flex flex-1 min-h-0\",\"children\":[[\"$\",\"$L3\",null,{}],[\"$\",\"main\",null,{\"className\":\"flex-1 min-w-0 overflow-auto\",\"children\":[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}]]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:1:props:children:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L6\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@8\"}]}]]}],{},null,false,null]},null,false,\"$@9\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$La\",null,{\"children\":\"$Lb\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lc\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Ld\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$e\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0d.f~y5jeh785.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"Cpy01wZHv0vXd_j_HlrSf\"}\n"])</script><script>self.__next_f.push([1,"f:[]\n9:\"$Wf\"\n"])</script><script>self.__next_f.push([1,"b:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"10:I[80070,[\"/_next/static/chunks/0e~ue9ca5zrep.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"IconMark\"]\n8:null\nd:[[\"$\",\"title\",\"0\",{\"children\":\"QuadWork\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Unified dashboard for multi-agent coding teams\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.0x3dzn~oxb6tn.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$L10\",\"3\",{}]]\n"])</script></body></html>
1
+ <!DOCTYPE html><html lang="en" class="geist_mono_8d43a2aa-module__8Li5zG__variable h-full"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/0u~7e4fgf-u06.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/0z~0.4hivi.f2.js"/><script src="/_next/static/chunks/0ezniz80psxr6.js" async=""></script><script src="/_next/static/chunks/0r7t_sj_sejq9.js" async=""></script><script src="/_next/static/chunks/15i5_ay.0ap.6.js" async=""></script><script src="/_next/static/chunks/0excsn2a_5qsb.js" async=""></script><script src="/_next/static/chunks/turbopack-0wh29ykoy-rb5.js" async=""></script><script src="/_next/static/chunks/05ok82hwk0x-c.js" async=""></script><script src="/_next/static/chunks/0ox7p_szjhn69.js" async=""></script><meta name="robots" content="noindex"/><meta name="next-size-adjust" content=""/><title>404: This page could not be found.</title><title>QuadWork</title><meta name="description" content="Unified dashboard for multi-agent coding teams"/><link rel="icon" href="/favicon.ico?favicon.0x3dzn~oxb6tn.ico" sizes="256x256" type="image/x-icon"/><script src="/_next/static/chunks/03~yq9q893hmn.js" noModule=""></script></head><body class="h-full flex flex-col"><div hidden=""><!--$--><!--/$--></div><header class="sticky top-0 z-40 flex h-12 items-center justify-between border-b border-white/10 bg-neutral-950/90 px-4 backdrop-blur"><div class="flex items-center gap-3 min-w-0"><a class="text-sm font-bold text-white hover:text-blue-400 shrink-0" href="/">QuadWork</a><span class="hidden sm:inline text-neutral-600">|</span><span class="hidden sm:inline text-[13px] text-neutral-400 truncate">Your AI dev team while you<!-- --> <span class="text-neutral-200"></span><span class="ml-0.5 inline-block w-[1px] h-[12px] align-middle bg-neutral-400 animate-qw-blink"></span></span></div><div class="flex items-center gap-3 shrink-0"><button type="button" aria-label="About QuadWork" class="rounded p-1 text-neutral-400 hover:bg-white/5 hover:text-white"><svg width="18" height="18" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="8"></circle><path d="M10 9v5" stroke-linecap="round"></path><circle cx="10" cy="6.5" r="0.8" fill="currentColor"></circle></svg></button><a href="https://github.com/realproject7/quadwork" target="_blank" rel="noopener noreferrer" class="text-[12px] text-neutral-400 hover:text-white">QuadWork github</a></div></header><div class="flex flex-1 min-h-0"><aside class="w-16 shrink-0 h-full border-r border-border bg-bg-surface flex flex-col items-center py-3"><a class="w-10 h-10 flex items-center justify-center rounded-sm transition-colors text-text-muted hover:text-text hover:bg-[#1a1a1a]" title="Home" href="/"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 10L10 3l7 7"></path><path d="M5 8.5V16h3.5v-4h3v4H15V8.5"></path></svg></a><div class="w-6 h-px bg-border my-2"></div><div class="flex-1 flex flex-col items-center gap-2 overflow-y-auto min-h-0"><a class="w-10 h-10 flex items-center justify-center rounded-full border border-dashed border-border text-text-muted hover:text-text hover:bg-[#1a1a1a] transition-colors" title="Add project" href="/setup"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M8 3v10M3 8h10"></path></svg></a></div><div class="w-6 h-px bg-border my-2"></div><a class="w-10 h-10 flex items-center justify-center rounded-sm transition-colors text-text-muted hover:text-text hover:bg-[#1a1a1a]" title="Settings" href="/settings"><svg width="18" height="18" viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="9" r="2.5"></circle><path d="M7.5 1.5h3l.4 2.1a5.5 5.5 0 011.3.7l2-.8 1.5 2.6-1.6 1.3a5.5 5.5 0 010 1.5l1.6 1.3-1.5 2.6-2-.8a5.5 5.5 0 01-1.3.7l-.4 2.1h-3l-.4-2.1a5.5 5.5 0 01-1.3-.7l-2 .8-1.5-2.6 1.6-1.3a5.5 5.5 0 010-1.5L2.3 6.1l1.5-2.6 2 .8a5.5 5.5 0 011.3-.7z"></path></svg></a></aside><main class="flex-1 min-w-0 overflow-auto"><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--></main></div><script src="/_next/static/chunks/0z~0.4hivi.f2.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[34852,[\"/_next/static/chunks/05ok82hwk0x-c.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n3:I[86081,[\"/_next/static/chunks/05ok82hwk0x-c.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n4:I[12527,[\"/_next/static/chunks/05ok82hwk0x-c.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n5:I[59763,[\"/_next/static/chunks/05ok82hwk0x-c.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n6:I[11717,[\"/_next/static/chunks/05ok82hwk0x-c.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"OutletBoundary\"]\n7:\"$Sreact.suspense\"\na:I[11717,[\"/_next/static/chunks/05ok82hwk0x-c.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"ViewportBoundary\"]\nc:I[11717,[\"/_next/static/chunks/05ok82hwk0x-c.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"MetadataBoundary\"]\ne:I[92243,[\"/_next/static/chunks/05ok82hwk0x-c.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/0u~7e4fgf-u06.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"_not-found\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0u~7e4fgf-u06.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/05ok82hwk0x-c.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/0ox7p_szjhn69.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"geist_mono_8d43a2aa-module__8Li5zG__variable h-full\",\"children\":[\"$\",\"body\",null,{\"className\":\"h-full flex flex-col\",\"children\":[[\"$\",\"$L2\",null,{}],[\"$\",\"div\",null,{\"className\":\"flex flex-1 min-h-0\",\"children\":[[\"$\",\"$L3\",null,{}],[\"$\",\"main\",null,{\"className\":\"flex-1 min-w-0 overflow-auto\",\"children\":[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}]]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:1:props:children:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L6\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@8\"}]}]]}],{},null,false,null]},null,false,\"$@9\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$La\",null,{\"children\":\"$Lb\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lc\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Ld\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$e\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0u~7e4fgf-u06.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"6uvV3nUfwr_t_JKrZJSP8\"}\n"])</script><script>self.__next_f.push([1,"f:[]\n9:\"$Wf\"\n"])</script><script>self.__next_f.push([1,"b:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"10:I[80070,[\"/_next/static/chunks/05ok82hwk0x-c.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"IconMark\"]\n8:null\nd:[[\"$\",\"title\",\"0\",{\"children\":\"QuadWork\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Unified dashboard for multi-agent coding teams\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.0x3dzn~oxb6tn.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$L10\",\"3\",{}]]\n"])</script></body></html>
@@ -1,6 +1,6 @@
1
1
  1:"$Sreact.fragment"
2
- 2:I[16348,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js","/_next/static/chunks/0md7hgvwnovzq.js"],"default"]
3
- 3:I[11717,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"OutletBoundary"]
2
+ 2:I[16348,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js","/_next/static/chunks/006g3lco-9xqf.js"],"default"]
3
+ 3:I[11717,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"OutletBoundary"]
4
4
  4:"$Sreact.suspense"
5
- 0:{"rsc":["$","$1","c",{"children":[["$","$L2",null,{}],[["$","script","script-0",{"src":"/_next/static/chunks/0md7hgvwnovzq.js","async":true}]],["$","$L3",null,{"children":["$","$4",null,{"name":"Next.MetadataOutlet","children":"$@5"}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"Cpy01wZHv0vXd_j_HlrSf"}
5
+ 0:{"rsc":["$","$1","c",{"children":[["$","$L2",null,{}],[["$","script","script-0",{"src":"/_next/static/chunks/006g3lco-9xqf.js","async":true}]],["$","$L3",null,{"children":["$","$4",null,{"name":"Next.MetadataOutlet","children":"$@5"}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"6uvV3nUfwr_t_JKrZJSP8"}
6
6
  5:null
@@ -1,18 +1,18 @@
1
1
  1:"$Sreact.fragment"
2
- 2:I[34852,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
3
- 3:I[86081,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
4
- 4:I[12527,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
5
- 5:I[59763,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
6
- 6:I[16348,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js","/_next/static/chunks/0md7hgvwnovzq.js"],"default"]
7
- 7:I[11717,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"OutletBoundary"]
2
+ 2:I[34852,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
3
+ 3:I[86081,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
4
+ 4:I[12527,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
5
+ 5:I[59763,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
6
+ 6:I[16348,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js","/_next/static/chunks/006g3lco-9xqf.js"],"default"]
7
+ 7:I[11717,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"OutletBoundary"]
8
8
  8:"$Sreact.suspense"
9
- a:I[11717,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"ViewportBoundary"]
10
- c:I[11717,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"MetadataBoundary"]
11
- e:I[92243,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default",1]
12
- :HL["/_next/static/chunks/0d.f~y5jeh785.css","style"]
9
+ a:I[11717,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"ViewportBoundary"]
10
+ c:I[11717,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"MetadataBoundary"]
11
+ e:I[92243,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default",1]
12
+ :HL["/_next/static/chunks/0u~7e4fgf-u06.css","style"]
13
13
  :HL["/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
14
- 0:{"P":null,"c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0d.f~y5jeh785.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/0e~ue9ca5zrep.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/0ox7p_szjhn69.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"geist_mono_8d43a2aa-module__8Li5zG__variable h-full","children":["$","body",null,{"className":"h-full flex flex-col","children":[["$","$L2",null,{}],["$","div",null,{"className":"flex flex-1 min-h-0","children":[["$","$L3",null,{}],["$","main",null,{"className":"flex-1 min-w-0 overflow-auto","children":["$","$L4",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]]}]]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L6",null,{}],[["$","script","script-0",{"src":"/_next/static/chunks/0md7hgvwnovzq.js","async":true,"nonce":"$undefined"}]],["$","$L7",null,{"children":["$","$8",null,{"name":"Next.MetadataOutlet","children":"$@9"}]}]]}],{},null,false,null]},null,false,null],["$","$1","h",{"children":[null,["$","$La",null,{"children":"$Lb"}],["$","div",null,{"hidden":true,"children":["$","$Lc",null,{"children":["$","$8",null,{"name":"Next.Metadata","children":"$Ld"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$e",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0d.f~y5jeh785.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"Cpy01wZHv0vXd_j_HlrSf"}
14
+ 0:{"P":null,"c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0u~7e4fgf-u06.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/05ok82hwk0x-c.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/0ox7p_szjhn69.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"geist_mono_8d43a2aa-module__8Li5zG__variable h-full","children":["$","body",null,{"className":"h-full flex flex-col","children":[["$","$L2",null,{}],["$","div",null,{"className":"flex flex-1 min-h-0","children":[["$","$L3",null,{}],["$","main",null,{"className":"flex-1 min-w-0 overflow-auto","children":["$","$L4",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]]}]]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L6",null,{}],[["$","script","script-0",{"src":"/_next/static/chunks/006g3lco-9xqf.js","async":true,"nonce":"$undefined"}]],["$","$L7",null,{"children":["$","$8",null,{"name":"Next.MetadataOutlet","children":"$@9"}]}]]}],{},null,false,null]},null,false,null],["$","$1","h",{"children":[null,["$","$La",null,{"children":"$Lb"}],["$","div",null,{"hidden":true,"children":["$","$Lc",null,{"children":["$","$8",null,{"name":"Next.Metadata","children":"$Ld"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$e",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0u~7e4fgf-u06.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"6uvV3nUfwr_t_JKrZJSP8"}
15
15
  b:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
16
- f:I[80070,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"IconMark"]
16
+ f:I[80070,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"IconMark"]
17
17
  9:null
18
18
  d:[["$","title","0",{"children":"QuadWork"}],["$","meta","1",{"name":"description","content":"Unified dashboard for multi-agent coding teams"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$Lf","3",{}]]
@@ -1,6 +1,6 @@
1
1
  1:"$Sreact.fragment"
2
- 2:I[11717,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"ViewportBoundary"]
3
- 3:I[11717,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"MetadataBoundary"]
2
+ 2:I[11717,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"ViewportBoundary"]
3
+ 3:I[11717,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"MetadataBoundary"]
4
4
  4:"$Sreact.suspense"
5
- 5:I[80070,["/_next/static/chunks/0e~ue9ca5zrep.js","/_next/static/chunks/0ox7p_szjhn69.js"],"IconMark"]
6
- 0:{"rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"QuadWork"}],["$","meta","1",{"name":"description","content":"Unified dashboard for multi-agent coding teams"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L5","3",{}]]}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"Cpy01wZHv0vXd_j_HlrSf"}
5
+ 5:I[80070,["/_next/static/chunks/05ok82hwk0x-c.js","/_next/static/chunks/0ox7p_szjhn69.js"],"IconMark"]
6
+ 0:{"rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"QuadWork"}],["$","meta","1",{"name":"description","content":"Unified dashboard for multi-agent coding teams"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L5","3",{}]]}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"6uvV3nUfwr_t_JKrZJSP8"}