quadwork 1.17.3 → 1.18.1

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 (72) hide show
  1. package/out/404.html +1 -1
  2. package/out/__next.__PAGE__.txt +3 -3
  3. package/out/__next._full.txt +14 -14
  4. package/out/__next._head.txt +4 -4
  5. package/out/__next._index.txt +8 -8
  6. package/out/__next._tree.txt +2 -2
  7. package/out/_next/static/chunks/0ff8u_cv_ch08.js +3 -0
  8. package/out/_next/static/chunks/{0ewow-yz7dvp~.js → 0p70ihm9n4drm.js} +1 -1
  9. package/out/_next/static/chunks/{12ins7yi1imrc.css → 0tv48-.848bk7.css} +1 -1
  10. package/out/_next/static/chunks/{0sgw2ao.8pb6z.js → 0xwbrozjfr9d5.js} +7 -7
  11. package/out/_next/static/chunks/13fv-yi7.v52g.js +1 -0
  12. package/out/_not-found/__next._full.txt +13 -13
  13. package/out/_not-found/__next._head.txt +4 -4
  14. package/out/_not-found/__next._index.txt +8 -8
  15. package/out/_not-found/__next._not-found.__PAGE__.txt +2 -2
  16. package/out/_not-found/__next._not-found.txt +3 -3
  17. package/out/_not-found/__next._tree.txt +2 -2
  18. package/out/_not-found.html +1 -1
  19. package/out/_not-found.txt +13 -13
  20. package/out/app-shell/__next._full.txt +13 -13
  21. package/out/app-shell/__next._head.txt +4 -4
  22. package/out/app-shell/__next._index.txt +8 -8
  23. package/out/app-shell/__next._tree.txt +2 -2
  24. package/out/app-shell/__next.app-shell.__PAGE__.txt +2 -2
  25. package/out/app-shell/__next.app-shell.txt +3 -3
  26. package/out/app-shell.html +1 -1
  27. package/out/app-shell.txt +13 -13
  28. package/out/index.html +1 -1
  29. package/out/index.txt +14 -14
  30. package/out/project/_/__next._full.txt +14 -14
  31. package/out/project/_/__next._head.txt +4 -4
  32. package/out/project/_/__next._index.txt +8 -8
  33. package/out/project/_/__next._tree.txt +2 -2
  34. package/out/project/_/__next.project.$d$id.__PAGE__.txt +3 -3
  35. package/out/project/_/__next.project.$d$id.txt +3 -3
  36. package/out/project/_/__next.project.txt +3 -3
  37. package/out/project/_/queue/__next._full.txt +14 -14
  38. package/out/project/_/queue/__next._head.txt +4 -4
  39. package/out/project/_/queue/__next._index.txt +8 -8
  40. package/out/project/_/queue/__next._tree.txt +2 -2
  41. package/out/project/_/queue/__next.project.$d$id.queue.__PAGE__.txt +3 -3
  42. package/out/project/_/queue/__next.project.$d$id.queue.txt +3 -3
  43. package/out/project/_/queue/__next.project.$d$id.txt +3 -3
  44. package/out/project/_/queue/__next.project.txt +3 -3
  45. package/out/project/_/queue.html +1 -1
  46. package/out/project/_/queue.txt +14 -14
  47. package/out/project/_.html +1 -1
  48. package/out/project/_.txt +14 -14
  49. package/out/settings/__next._full.txt +14 -14
  50. package/out/settings/__next._head.txt +4 -4
  51. package/out/settings/__next._index.txt +8 -8
  52. package/out/settings/__next._tree.txt +2 -2
  53. package/out/settings/__next.settings.__PAGE__.txt +3 -3
  54. package/out/settings/__next.settings.txt +3 -3
  55. package/out/settings.html +1 -1
  56. package/out/settings.txt +14 -14
  57. package/out/setup/__next._full.txt +14 -14
  58. package/out/setup/__next._head.txt +4 -4
  59. package/out/setup/__next._index.txt +8 -8
  60. package/out/setup/__next._tree.txt +2 -2
  61. package/out/setup/__next.setup.__PAGE__.txt +3 -3
  62. package/out/setup/__next.setup.txt +3 -3
  63. package/out/setup.html +1 -1
  64. package/out/setup.txt +14 -14
  65. package/package.json +1 -1
  66. package/server/index.js +180 -108
  67. package/server/routes.js +14 -0
  68. package/out/_next/static/chunks/054b72jq_7mig.js +0 -3
  69. package/out/_next/static/chunks/0m48m-8no_mew.js +0 -1
  70. /package/out/_next/static/{VL6j_Q-L6f7tGZD4854DN → WDRw2uNz8RE4CDa5ntj1v}/_buildManifest.js +0 -0
  71. /package/out/_next/static/{VL6j_Q-L6f7tGZD4854DN → WDRw2uNz8RE4CDa5ntj1v}/_clientMiddlewareManifest.js +0 -0
  72. /package/out/_next/static/{VL6j_Q-L6f7tGZD4854DN → WDRw2uNz8RE4CDa5ntj1v}/_ssgManifest.js +0 -0
package/out/setup.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="preload" href="/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/chunks/12ins7yi1imrc.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/0ze4gu236oq96.js"/><script src="/_next/static/chunks/0.bbxho1vnxin.js" async=""></script><script src="/_next/static/chunks/0n~dq4kpx9xxx.js" async=""></script><script src="/_next/static/chunks/0zfotsowwll1x.js" async=""></script><script src="/_next/static/chunks/0pqt~8bl3ukh4.js" async=""></script><script src="/_next/static/chunks/turbopack-0qm-e3ifrz~2u.js" async=""></script><script src="/_next/static/chunks/0m48m-8no_mew.js" async=""></script><script src="/_next/static/chunks/0d3shmwh5_nmn.js" async=""></script><script src="/_next/static/chunks/0uz5svjlo9dwl.js" async=""></script><meta name="next-size-adjust" content=""/><title>QuadWork</title><meta name="description" content="Unified dashboard for multi-agent coding teams"/><link rel="icon" href="/favicon.ico?favicon.05o2q2p4kvnq_.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" aria-hidden="true"></header><div class="flex flex-1 min-h-0"><button type="button" class="fixed top-14 left-2 z-30 lg:hidden w-10 h-10 flex items-center justify-center bg-bg-surface border border-border text-text-muted hover:text-accent"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M3 5h14M3 10h14M3 15h14"></path></svg></button><aside class="fixed inset-y-0 left-0 z-50 w-52 bg-bg-surface border-r border-border flex flex-col py-3 px-2 items-stretch overflow-y-auto transition-transform duration-200 ease-in-out lg:hidden -translate-x-full"><button type="button" class="self-end shrink-0 w-10 h-10 flex items-center justify-center text-text-muted hover:text-accent mb-1"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M5 5l10 10M15 5L5 15"></path></svg></button><a class="flex items-center gap-2 rounded-sm transition-colors px-2 py-2 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><span class="text-xs">Home</span></a><div class="h-px bg-border my-2 "></div><div class="flex-1 flex flex-col gap-2 overflow-y-auto min-h-0 "><a class="flex items-center gap-2 rounded-full transition-colors px-2 py-2 border border-dashed border-border text-text-muted hover:text-text hover:bg-[#1a1a1a] rounded-sm" 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><span class="text-xs text-text-muted">New Project</span></a></div><div class="h-px bg-border my-2 "></div><a class="flex items-center gap-2 rounded-sm transition-colors px-2 py-2 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><span class="text-xs">Settings</span></a></aside><aside class="hidden lg:flex shrink-0 h-full border-r border-border bg-bg-surface flex-col py-3 transition-[width] duration-200 ease-in-out overflow-hidden w-16 items-center"><a class="flex items-center gap-2 rounded-sm transition-colors w-10 h-10 justify-center self-center 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="h-px bg-border my-2 w-6 self-center"></div><div class="flex-1 flex flex-col gap-2 overflow-y-auto min-h-0 items-center"><a class="flex items-center gap-2 rounded-full transition-colors w-10 h-10 justify-center border border-dashed border-border text-text-muted hover:text-text hover:bg-[#1a1a1a]" 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="h-px bg-border my-2 w-6 self-center"></div><a class="flex items-center gap-2 rounded-sm transition-colors w-10 h-10 justify-center self-center 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><div class="h-1"></div><button class="flex shrink-0 items-center justify-center w-10 h-10 rounded-sm border border-border text-text-muted hover:text-accent hover:border-accent/50 transition-colors self-center" title="Expand sidebar"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3l5 5-5 5"></path></svg></button></aside><main class="flex-1 min-w-0 overflow-auto"><div class="h-full overflow-y-auto"></div><!--$--><!--/$--></main></div><script src="/_next/static/chunks/0ze4gu236oq96.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[52368,[\"/_next/static/chunks/0m48m-8no_mew.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"LocaleProvider\"]\n3:I[43688,[\"/_next/static/chunks/0m48m-8no_mew.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n4:I[26704,[\"/_next/static/chunks/0m48m-8no_mew.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n5:I[22140,[\"/_next/static/chunks/0m48m-8no_mew.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n6:I[39756,[\"/_next/static/chunks/0m48m-8no_mew.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n7:I[37457,[\"/_next/static/chunks/0m48m-8no_mew.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n8:I[94810,[\"/_next/static/chunks/0m48m-8no_mew.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\",\"/_next/static/chunks/0uz5svjlo9dwl.js\"],\"default\"]\n9:I[97367,[\"/_next/static/chunks/0m48m-8no_mew.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"OutletBoundary\"]\na:\"$Sreact.suspense\"\nd:I[97367,[\"/_next/static/chunks/0m48m-8no_mew.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"ViewportBoundary\"]\nf:I[97367,[\"/_next/static/chunks/0m48m-8no_mew.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"MetadataBoundary\"]\n11:I[68027,[\"/_next/static/chunks/0m48m-8no_mew.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/12ins7yi1imrc.css\",\"style\"]\n:HL[\"/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"setup\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"setup\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/12ins7yi1imrc.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0m48m-8no_mew.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/0d3shmwh5_nmn.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,{\"children\":[[\"$\",\"$L3\",null,{}],[\"$\",\"$L4\",null,{}],[\"$\",\"div\",null,{\"className\":\"flex flex-1 min-h-0\",\"children\":[[\"$\",\"$L5\",null,{}],[\"$\",\"main\",null,{\"className\":\"flex-1 min-w-0 overflow-auto\",\"children\":[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",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,[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L8\",null,{}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0uz5svjlo9dwl.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L9\",null,{\"children\":[\"$\",\"$a\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@b\"}]}]]}],{},null,false,null]},null,false,\"$@c\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$Ld\",null,{\"children\":\"$Le\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lf\",null,{\"children\":[\"$\",\"$a\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L10\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$11\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/12ins7yi1imrc.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"VL6j_Q-L6f7tGZD4854DN\"}\n"])</script><script>self.__next_f.push([1,"12:[]\nc:\"$W12\"\n"])</script><script>self.__next_f.push([1,"e:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"13:I[27201,[\"/_next/static/chunks/0m48m-8no_mew.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"IconMark\"]\nb:null\n10:[[\"$\",\"title\",\"0\",{\"children\":\"QuadWork\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Unified dashboard for multi-agent coding teams\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.05o2q2p4kvnq_.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$L13\",\"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="preload" href="/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/chunks/0tv48-.848bk7.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/0ze4gu236oq96.js"/><script src="/_next/static/chunks/0.bbxho1vnxin.js" async=""></script><script src="/_next/static/chunks/0n~dq4kpx9xxx.js" async=""></script><script src="/_next/static/chunks/0zfotsowwll1x.js" async=""></script><script src="/_next/static/chunks/0pqt~8bl3ukh4.js" async=""></script><script src="/_next/static/chunks/turbopack-0qm-e3ifrz~2u.js" async=""></script><script src="/_next/static/chunks/13fv-yi7.v52g.js" async=""></script><script src="/_next/static/chunks/0d3shmwh5_nmn.js" async=""></script><script src="/_next/static/chunks/0uz5svjlo9dwl.js" async=""></script><meta name="next-size-adjust" content=""/><title>QuadWork</title><meta name="description" content="Unified dashboard for multi-agent coding teams"/><link rel="icon" href="/favicon.ico?favicon.05o2q2p4kvnq_.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" aria-hidden="true"></header><div class="flex flex-1 min-h-0"><button type="button" class="fixed top-14 left-2 z-30 lg:hidden w-10 h-10 flex items-center justify-center bg-bg-surface border border-border text-text-muted hover:text-accent"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M3 5h14M3 10h14M3 15h14"></path></svg></button><aside class="fixed inset-y-0 left-0 z-50 w-52 bg-bg-surface border-r border-border flex flex-col py-3 px-2 items-stretch overflow-y-auto transition-transform duration-200 ease-in-out lg:hidden -translate-x-full"><button type="button" class="self-end shrink-0 w-10 h-10 flex items-center justify-center text-text-muted hover:text-accent mb-1"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M5 5l10 10M15 5L5 15"></path></svg></button><a class="flex items-center gap-2 rounded-sm transition-colors px-2 py-2 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><span class="text-xs">Home</span></a><div class="h-px bg-border my-2 "></div><div class="flex-1 flex flex-col gap-2 overflow-y-auto min-h-0 "><a class="flex items-center gap-2 rounded-full transition-colors px-2 py-2 border border-dashed border-border text-text-muted hover:text-text hover:bg-[#1a1a1a] rounded-sm" 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><span class="text-xs text-text-muted">New Project</span></a></div><div class="h-px bg-border my-2 "></div><a class="flex items-center gap-2 rounded-sm transition-colors px-2 py-2 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><span class="text-xs">Settings</span></a></aside><aside class="hidden lg:flex shrink-0 h-full border-r border-border bg-bg-surface flex-col py-3 transition-[width] duration-200 ease-in-out overflow-hidden w-16 items-center"><a class="flex items-center gap-2 rounded-sm transition-colors w-10 h-10 justify-center self-center 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="h-px bg-border my-2 w-6 self-center"></div><div class="flex-1 flex flex-col gap-2 overflow-y-auto min-h-0 items-center"><a class="flex items-center gap-2 rounded-full transition-colors w-10 h-10 justify-center border border-dashed border-border text-text-muted hover:text-text hover:bg-[#1a1a1a]" 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="h-px bg-border my-2 w-6 self-center"></div><a class="flex items-center gap-2 rounded-sm transition-colors w-10 h-10 justify-center self-center 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><div class="h-1"></div><button class="flex shrink-0 items-center justify-center w-10 h-10 rounded-sm border border-border text-text-muted hover:text-accent hover:border-accent/50 transition-colors self-center" title="Expand sidebar"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3l5 5-5 5"></path></svg></button></aside><main class="flex-1 min-w-0 overflow-auto"><div class="h-full overflow-y-auto"></div><!--$--><!--/$--></main></div><script src="/_next/static/chunks/0ze4gu236oq96.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[52368,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"LocaleProvider\"]\n3:I[43688,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n4:I[26704,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n5:I[22140,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n6:I[39756,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n7:I[37457,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n8:I[94810,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\",\"/_next/static/chunks/0uz5svjlo9dwl.js\"],\"default\"]\n9:I[97367,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"OutletBoundary\"]\na:\"$Sreact.suspense\"\nd:I[97367,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"ViewportBoundary\"]\nf:I[97367,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"MetadataBoundary\"]\n11:I[68027,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/0tv48-.848bk7.css\",\"style\"]\n:HL[\"/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"setup\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"setup\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0tv48-.848bk7.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/13fv-yi7.v52g.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/0d3shmwh5_nmn.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,{\"children\":[[\"$\",\"$L3\",null,{}],[\"$\",\"$L4\",null,{}],[\"$\",\"div\",null,{\"className\":\"flex flex-1 min-h-0\",\"children\":[[\"$\",\"$L5\",null,{}],[\"$\",\"main\",null,{\"className\":\"flex-1 min-w-0 overflow-auto\",\"children\":[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",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,[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L8\",null,{}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0uz5svjlo9dwl.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L9\",null,{\"children\":[\"$\",\"$a\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@b\"}]}]]}],{},null,false,null]},null,false,\"$@c\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$Ld\",null,{\"children\":\"$Le\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lf\",null,{\"children\":[\"$\",\"$a\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L10\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$11\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0tv48-.848bk7.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"WDRw2uNz8RE4CDa5ntj1v\"}\n"])</script><script>self.__next_f.push([1,"12:[]\nc:\"$W12\"\n"])</script><script>self.__next_f.push([1,"e:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"13:I[27201,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"IconMark\"]\nb:null\n10:[[\"$\",\"title\",\"0\",{\"children\":\"QuadWork\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Unified dashboard for multi-agent coding teams\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.05o2q2p4kvnq_.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$L13\",\"3\",{}]]\n"])</script></body></html>
package/out/setup.txt CHANGED
@@ -1,22 +1,22 @@
1
1
  1:"$Sreact.fragment"
2
- 2:I[52368,["/_next/static/chunks/0m48m-8no_mew.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"LocaleProvider"]
3
- 3:I[43688,["/_next/static/chunks/0m48m-8no_mew.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
4
- 4:I[26704,["/_next/static/chunks/0m48m-8no_mew.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
5
- 5:I[22140,["/_next/static/chunks/0m48m-8no_mew.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
6
- 6:I[39756,["/_next/static/chunks/0m48m-8no_mew.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
7
- 7:I[37457,["/_next/static/chunks/0m48m-8no_mew.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
8
- 8:I[94810,["/_next/static/chunks/0m48m-8no_mew.js","/_next/static/chunks/0d3shmwh5_nmn.js","/_next/static/chunks/0uz5svjlo9dwl.js"],"default"]
9
- 9:I[97367,["/_next/static/chunks/0m48m-8no_mew.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"OutletBoundary"]
2
+ 2:I[52368,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"LocaleProvider"]
3
+ 3:I[43688,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
4
+ 4:I[26704,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
5
+ 5:I[22140,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
6
+ 6:I[39756,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
7
+ 7:I[37457,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
8
+ 8:I[94810,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js","/_next/static/chunks/0uz5svjlo9dwl.js"],"default"]
9
+ 9:I[97367,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"OutletBoundary"]
10
10
  a:"$Sreact.suspense"
11
- d:I[97367,["/_next/static/chunks/0m48m-8no_mew.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"ViewportBoundary"]
12
- f:I[97367,["/_next/static/chunks/0m48m-8no_mew.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"MetadataBoundary"]
13
- 11:I[68027,["/_next/static/chunks/0m48m-8no_mew.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default",1]
14
- :HL["/_next/static/chunks/12ins7yi1imrc.css","style"]
11
+ d:I[97367,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"ViewportBoundary"]
12
+ f:I[97367,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"MetadataBoundary"]
13
+ 11:I[68027,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default",1]
14
+ :HL["/_next/static/chunks/0tv48-.848bk7.css","style"]
15
15
  :HL["/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
16
- 0:{"P":null,"c":["","setup"],"q":"","i":false,"f":[[["",{"children":["setup",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/12ins7yi1imrc.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/0m48m-8no_mew.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/0d3shmwh5_nmn.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,{"children":[["$","$L3",null,{}],["$","$L4",null,{}],["$","div",null,{"className":"flex flex-1 min-h-0","children":[["$","$L5",null,{}],["$","main",null,{"className":"flex-1 min-w-0 overflow-auto","children":["$","$L6",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",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,["$","$L6",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[["$","$L8",null,{}],[["$","script","script-0",{"src":"/_next/static/chunks/0uz5svjlo9dwl.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$","$a",null,{"name":"Next.MetadataOutlet","children":"$@b"}]}]]}],{},null,false,null]},null,false,"$@c"]},null,false,null],["$","$1","h",{"children":[null,["$","$Ld",null,{"children":"$Le"}],["$","div",null,{"hidden":true,"children":["$","$Lf",null,{"children":["$","$a",null,{"name":"Next.Metadata","children":"$L10"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$11",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/12ins7yi1imrc.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"VL6j_Q-L6f7tGZD4854DN"}
16
+ 0:{"P":null,"c":["","setup"],"q":"","i":false,"f":[[["",{"children":["setup",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0tv48-.848bk7.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/13fv-yi7.v52g.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/0d3shmwh5_nmn.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,{"children":[["$","$L3",null,{}],["$","$L4",null,{}],["$","div",null,{"className":"flex flex-1 min-h-0","children":[["$","$L5",null,{}],["$","main",null,{"className":"flex-1 min-w-0 overflow-auto","children":["$","$L6",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",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,["$","$L6",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[["$","$L8",null,{}],[["$","script","script-0",{"src":"/_next/static/chunks/0uz5svjlo9dwl.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$","$a",null,{"name":"Next.MetadataOutlet","children":"$@b"}]}]]}],{},null,false,null]},null,false,"$@c"]},null,false,null],["$","$1","h",{"children":[null,["$","$Ld",null,{"children":"$Le"}],["$","div",null,{"hidden":true,"children":["$","$Lf",null,{"children":["$","$a",null,{"name":"Next.Metadata","children":"$L10"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$11",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0tv48-.848bk7.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"WDRw2uNz8RE4CDa5ntj1v"}
17
17
  12:[]
18
18
  c:"$W12"
19
19
  e:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
20
- 13:I[27201,["/_next/static/chunks/0m48m-8no_mew.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"IconMark"]
20
+ 13:I[27201,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"IconMark"]
21
21
  b:null
22
22
  10:[["$","title","0",{"children":"QuadWork"}],["$","meta","1",{"name":"description","content":"Unified dashboard for multi-agent coding teams"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.05o2q2p4kvnq_.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L13","3",{}]]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quadwork",
3
- "version": "1.17.3",
3
+ "version": "1.18.1",
4
4
  "description": "Unified dashboard for multi-agent coding teams — 4 AI agents, one terminal",
5
5
  "bin": {
6
6
  "quadwork": "./bin/quadwork.js"
package/server/index.js CHANGED
@@ -41,6 +41,17 @@ app.get("/api/health", (_req, res) => {
41
41
  res.json({ status: "ok" });
42
42
  });
43
43
 
44
+ // --- Safe PTY write helper (#670) ---
45
+
46
+ function safeWrite(term, data) {
47
+ if (!term) return false;
48
+ try { term.write(data); return true; }
49
+ catch (err) {
50
+ if (err.code === "EIO") return false;
51
+ throw err;
52
+ }
53
+ }
54
+
44
55
  // --- CLI status detection ---
45
56
 
46
57
  const { execFileSync } = require("child_process");
@@ -1305,6 +1316,88 @@ app.post("/api/agents/:project/reset", async (req, res) => {
1305
1316
  }
1306
1317
  });
1307
1318
 
1319
+ // --- Full Reset: restart all AC + agents across all projects (#657) ---
1320
+
1321
+ app.post("/api/full-reset", async (_req, res) => {
1322
+ const start = Date.now();
1323
+ console.log("[full-reset] starting...");
1324
+ try {
1325
+ const cfg = readConfig();
1326
+ const projects = (cfg.projects || []).filter((p) => !p.archived);
1327
+
1328
+ // 1. Stop all agent sessions
1329
+ console.log("[full-reset] stopping all agent sessions...");
1330
+ const sessionKeys = [...agentSessions.keys()];
1331
+ for (const key of sessionKeys) {
1332
+ await stopAgentSession(key);
1333
+ }
1334
+
1335
+ // 2. Stop Butler if running
1336
+ console.log("[full-reset] stopping Butler...");
1337
+ stopButlerPty();
1338
+
1339
+ // 3. Re-run startup migrations
1340
+ console.log("[full-reset] running startup migrations...");
1341
+ runStartupMigrations(cfg);
1342
+
1343
+ // 4. Restart each project's AC + agents
1344
+ let totalAgents = 0;
1345
+ const errors = [];
1346
+ for (const project of projects) {
1347
+ console.log(`[full-reset] restarting AC for ${project.id}...`);
1348
+ // Pre-mark reset as scheduled so AC restart's auto-reset timer is suppressed
1349
+ _acHealth.resetState.set(project.id, { status: "scheduled", timestamp: Date.now() });
1350
+ try {
1351
+ const acResp = await fetch(`http://127.0.0.1:${PORT}/api/agentchattr/${encodeURIComponent(project.id)}/restart`, {
1352
+ method: "POST",
1353
+ });
1354
+ if (!acResp.ok) {
1355
+ const errData = await acResp.json().catch(() => ({}));
1356
+ errors.push(`${project.id}: AC restart failed — ${errData.error || acResp.status}`);
1357
+ continue;
1358
+ }
1359
+ } catch (err) {
1360
+ errors.push(`${project.id}: AC — ${err.message}`);
1361
+ continue;
1362
+ }
1363
+ // Explicitly reset agents and await result
1364
+ try {
1365
+ const resetResp = await fetch(`http://127.0.0.1:${PORT}/api/agents/${encodeURIComponent(project.id)}/reset`, {
1366
+ method: "POST",
1367
+ });
1368
+ const resetData = await resetResp.json();
1369
+ if (resetData.ok) {
1370
+ totalAgents += resetData.restarted;
1371
+ } else {
1372
+ errors.push(`${project.id}: agent reset failed`);
1373
+ }
1374
+ } catch (err) {
1375
+ errors.push(`${project.id}: agent reset — ${err.message}`);
1376
+ }
1377
+ }
1378
+
1379
+ // 5. Restart Butler if enabled
1380
+ if (cfg.butler?.enabled) {
1381
+ console.log("[full-reset] restarting Butler...");
1382
+ const result = spawnButlerPty();
1383
+ if (!result.ok) errors.push(`butler: ${result.error}`);
1384
+ }
1385
+
1386
+ const duration = Date.now() - start;
1387
+ console.log(`[full-reset] complete in ${duration}ms — ${projects.length} projects, ${totalAgents} agents`);
1388
+ res.json({
1389
+ ok: errors.length === 0,
1390
+ projects: projects.length,
1391
+ agents: totalAgents,
1392
+ duration_ms: duration,
1393
+ ...(errors.length > 0 ? { errors } : {}),
1394
+ });
1395
+ } catch (err) {
1396
+ console.error(`[full-reset] failed: ${err.message}`);
1397
+ res.status(500).json({ ok: false, error: err.message });
1398
+ }
1399
+ });
1400
+
1308
1401
  // --- Lifecycle: start spawns PTY (visible in terminal panel) ---
1309
1402
 
1310
1403
  app.post("/api/agents/:project/:agent/start", async (req, res) => {
@@ -1473,6 +1566,23 @@ function spawnButlerPty() {
1473
1566
  }
1474
1567
  });
1475
1568
 
1569
+ // Auto-answer Claude's trust prompt if it appears within the first 10s
1570
+ if (command === "claude") {
1571
+ let trustHandled = false;
1572
+ const trustListener = term.onData((data) => {
1573
+ if (trustHandled) return;
1574
+ if (data.includes("trust") || data.includes("Yes,") || data.includes("1.")) {
1575
+ setTimeout(() => {
1576
+ if (!trustHandled && butlerSession.term === term) {
1577
+ safeWrite(term, "1\r");
1578
+ trustHandled = true;
1579
+ }
1580
+ }, 500);
1581
+ }
1582
+ });
1583
+ setTimeout(() => { trustListener.dispose(); trustHandled = true; }, 10000);
1584
+ }
1585
+
1476
1586
  term.onExit(({ exitCode }) => {
1477
1587
  if (butlerSession.term === term) {
1478
1588
  butlerSession.state = "stopped";
@@ -2069,7 +2179,7 @@ wss.on("connection:terminal", async (ws, req) => {
2069
2179
  return;
2070
2180
  }
2071
2181
  } catch {}
2072
- session.term.write(str);
2182
+ safeWrite(session.term, str);
2073
2183
  });
2074
2184
 
2075
2185
  ws.on("close", () => {
@@ -2127,7 +2237,7 @@ wss.on("connection:butler", async (ws) => {
2127
2237
  return;
2128
2238
  }
2129
2239
  } catch {}
2130
- butlerSession.term.write(str);
2240
+ safeWrite(butlerSession.term, str);
2131
2241
  });
2132
2242
 
2133
2243
  ws.on("close", () => {
@@ -2516,52 +2626,17 @@ function startAcHealthMonitor() {
2516
2626
  console.log("[health] AC health monitor started (30s interval, per-project 60s grace)");
2517
2627
  }
2518
2628
 
2519
- server.listen(PORT, "127.0.0.1", async () => {
2520
- console.log(`QuadWork server listening on http://127.0.0.1:${PORT}`);
2521
- syncTriggersFromConfig();
2522
- // #579: detect AC processes already running (spawned by cmdStart before
2523
- // the server module loaded). Without this, chattrProcesses is empty on
2524
- // boot and the health monitor can't track cmdStart-spawned ACs, while
2525
- // the dashboard's Start button would redundantly kill+respawn them.
2526
- const startupCfg = readConfig();
2527
- for (const p of (startupCfg.projects || [])) {
2528
- const { url: acUrl } = resolveProjectChattr(p.id);
2529
- const acPortMatch = acUrl.match(/:(\d+)/);
2530
- const acPort = acPortMatch ? parseInt(acPortMatch[1], 10) : 8300;
2531
- const alive = await isPortAlive(acPort);
2532
- if (alive && !chattrProcesses.has(p.id)) {
2533
- // AC is already running (e.g. spawned by cmdStart). Record it so
2534
- // the health monitor can track it and the dashboard shows the
2535
- // correct state. process is null because we don't own the child.
2536
- chattrProcesses.set(p.id, { process: null, state: "running", error: null, runningSince: Date.now() });
2537
- console.log(`[startup] ${p.id}: AC already alive on port ${acPort} — tracking`);
2538
- }
2539
- }
2540
- // Sync AgentChattr tokens for all projects on startup and backfill
2541
- // the sender-overflow CSS/JS patch (#402) so already-running AC
2542
- // instances receive the fix without requiring a restart.
2543
- // #448: retry after 5s for projects where AC isn't up yet at boot.
2544
- for (const p of (startupCfg.projects || [])) {
2545
- syncChattrToken(p.id).catch(() => {
2546
- setTimeout(() => syncChattrToken(p.id).catch(() => {}), 5000);
2547
- });
2548
- const { dir: acDir } = resolveProjectChattr(p.id);
2549
- if (acDir) patchAgentchattrCss(acDir);
2550
- }
2551
- // #457: migrate bridge slugs in AC configs on startup.
2552
- // Renames [agents.discord-bridge] → [agents.dc] and
2553
- // [agents.telegram-bridge] → [agents.tg] so bridges register
2554
- // under the short slug. Restarts AC ONLY for slug renames (not
2555
- // fresh block appends) — #616: script-only patches should not
2556
- // trigger AC restarts which kill bridge registration.
2557
- for (const p of (startupCfg.projects || [])) {
2629
+ // #657: extracted startup migrations so full-reset can re-run them
2630
+ function runStartupMigrations(cfg) {
2631
+ const projects = (cfg.projects || []).filter((p) => !p.archived);
2632
+ const acRestartNeeded = [];
2633
+
2634
+ // bridge-migrate
2635
+ for (const p of projects) {
2558
2636
  const acPath = projectAgentchattrConfigPath(p.id);
2559
2637
  if (!fs.existsSync(acPath)) continue;
2560
2638
  try {
2561
2639
  const before = fs.readFileSync(acPath, "utf-8");
2562
- // Track whether an actual slug RENAME happened (old → new).
2563
- // Fresh block appends don't need an AC restart — AC picks them
2564
- // up on its next natural start.
2565
2640
  const hadOldDc = /^\[agents\.discord-bridge\]\s*$/m.test(before);
2566
2641
  const hadOldTg = /^\[agents\.telegram-bridge\]\s*$/m.test(before);
2567
2642
  const dc = patchAgentchattrConfigForDiscordBridge(before);
@@ -2569,28 +2644,14 @@ server.listen(PORT, "127.0.0.1", async () => {
2569
2644
  if (dc.changed || tg.changed) {
2570
2645
  fs.writeFileSync(acPath, tg.text);
2571
2646
  console.log(`[bridge-migrate] ${p.id}: migrated AC config slugs`);
2572
- // Only restart AC when a slug was actually RENAMED — not when
2573
- // a fresh block was appended (#616).
2574
2647
  if (hadOldDc || hadOldTg) {
2575
- setTimeout(async () => {
2576
- try {
2577
- const r = await fetch(`http://127.0.0.1:${PORT}/api/agentchattr/${encodeURIComponent(p.id)}/restart`, {
2578
- method: "POST",
2579
- });
2580
- if (r.ok) console.log(`[bridge-migrate] ${p.id}: restarted AC`);
2581
- else console.warn(`[bridge-migrate] ${p.id}: AC restart returned ${r.status}`);
2582
- } catch (err) {
2583
- console.warn(`[bridge-migrate] ${p.id}: AC restart failed: ${err.message || err}`);
2584
- }
2585
- }, 3000);
2648
+ if (!acRestartNeeded.includes(p.id)) acRestartNeeded.push(p.id);
2586
2649
  }
2587
2650
  }
2588
2651
  } catch {}
2589
2652
  }
2590
- // #506: refresh Discord bridge script from the npm package on startup.
2591
- // The Telegram bridge uses git-fetch + pin, but Discord uses a file-copy
2592
- // pattern. Without this, upgrading QuadWork leaves a stale on-disk script
2593
- // missing fixes shipped in newer versions.
2653
+
2654
+ // bridge-refresh
2594
2655
  const DISCORD_BRIDGE_SRC = path.join(__dirname, "..", "bridges", "discord", "discord_bridge.py");
2595
2656
  const DISCORD_BRIDGE_DEST = path.join(os.homedir(), ".quadwork", "agentchattr-discord", "discord_bridge.py");
2596
2657
  if (fs.existsSync(DISCORD_BRIDGE_SRC) && fs.existsSync(path.dirname(DISCORD_BRIDGE_DEST))) {
@@ -2601,10 +2662,8 @@ server.listen(PORT, "127.0.0.1", async () => {
2601
2662
  console.warn(`[bridge-refresh] failed to refresh Discord bridge script: ${err.message || err}`);
2602
2663
  }
2603
2664
  }
2604
- // #470: patch stale bridge_sender defaults in on-disk bridge scripts.
2605
- // The AC config migration (#457) renames the agent sections, but the
2606
- // bridge scripts themselves may still have old defaults if the operator
2607
- // upgraded QuadWork without re-installing the bridges.
2665
+
2666
+ // bridge slug patches
2608
2667
  const BRIDGE_SLUG_PATCHES = [
2609
2668
  { file: path.join(os.homedir(), ".quadwork", "agentchattr-telegram", "telegram_bridge.py"), old: '"telegram-bridge"', replacement: '"tg"' },
2610
2669
  { file: path.join(os.homedir(), ".quadwork", "agentchattr-discord", "discord_bridge.py"), old: '"discord-bridge"', replacement: '"dc"' },
@@ -2618,20 +2677,15 @@ server.listen(PORT, "127.0.0.1", async () => {
2618
2677
  console.log(`[bridge-migrate] patched stale bridge_sender in ${path.basename(file)}`);
2619
2678
  } catch {}
2620
2679
  }
2621
- // #479: fix stale agent slugs in worktree AGENTS.md and CLAUDE.md on startup.
2622
- // Uses in-place replacement (not full template overwrite) to preserve
2623
- // reviewer auth credentials and other site-specific customisations.
2680
+
2681
+ // reseed stale slugs
2624
2682
  const SLUG_FIXES = [
2625
- [/@reviewer1/g, "@re1"],
2626
- [/@reviewer2/g, "@re2"],
2627
- [/@t2a/g, "@re1"],
2628
- [/@t2b/g, "@re2"],
2629
- [/@t1\b/g, "@head"],
2630
- [/@t3\b/g, "@dev"],
2631
- [/\breviewer1\b/g, "re1"],
2632
- [/\breviewer2\b/g, "re2"],
2683
+ [/@reviewer1/g, "@re1"], [/@reviewer2/g, "@re2"],
2684
+ [/@t2a/g, "@re1"], [/@t2b/g, "@re2"],
2685
+ [/@t1\b/g, "@head"], [/@t3\b/g, "@dev"],
2686
+ [/\breviewer1\b/g, "re1"], [/\breviewer2\b/g, "re2"],
2633
2687
  ];
2634
- for (const p of (startupCfg.projects || [])) {
2688
+ for (const p of projects) {
2635
2689
  if (!p.agents) continue;
2636
2690
  for (const [agentId, agentCfg] of Object.entries(p.agents)) {
2637
2691
  const wtDir = agentCfg.cwd;
@@ -2642,9 +2696,9 @@ server.listen(PORT, "127.0.0.1", async () => {
2642
2696
  try {
2643
2697
  let content = fs.readFileSync(filePath, "utf-8");
2644
2698
  let changed = false;
2645
- for (const [pattern, replacement] of SLUG_FIXES) {
2699
+ for (const [pattern, repl] of SLUG_FIXES) {
2646
2700
  const before = content;
2647
- content = content.replace(pattern, replacement);
2701
+ content = content.replace(pattern, repl);
2648
2702
  if (content !== before) changed = true;
2649
2703
  }
2650
2704
  if (changed) {
@@ -2657,30 +2711,23 @@ server.listen(PORT, "127.0.0.1", async () => {
2657
2711
  }
2658
2712
  }
2659
2713
  }
2660
- // #478 + #502: patch deployed AgentChattr instances to support force-replace
2661
- // on register and fix idle-agent crash timeout.
2662
- for (const p of (startupCfg.projects || [])) {
2714
+
2715
+ // ghost-fix + idle-fix
2716
+ for (const p of projects) {
2663
2717
  const acDir = resolveProjectChattr(p.id).dir;
2664
- // Patch registry.py: add force parameter to register()
2665
2718
  const regPath = path.join(acDir, "registry.py");
2666
2719
  if (fs.existsSync(regPath)) {
2667
2720
  try {
2668
2721
  let reg = fs.readFileSync(regPath, "utf-8");
2669
2722
  if (!reg.includes("force: bool")) {
2670
- // Add force parameter to register() signature
2671
2723
  reg = reg.replace(
2672
2724
  /def register\(self, base: str, label: str \| None = None\) -> dict \| None:/,
2673
2725
  "def register(self, base: str, label: str | None = None, force: bool = False) -> dict | None:",
2674
2726
  );
2675
- // Add force-replace logic after _expire_reserved()
2676
2727
  reg = reg.replace(
2677
2728
  " self._expire_reserved()\n\n # Find next free slot",
2678
2729
  " self._expire_reserved()\n\n" +
2679
- " # quadwork#478 + #502: force-replace — expire all existing slots\n" +
2680
- " # for this base so the new registration always lands at slot 1.\n" +
2681
- " # Also clear _reserved entries: after a crash-timeout the old name\n" +
2682
- " # lives only in _reserved, so without this the grace period still\n" +
2683
- " # blocks slot 1 and the agent gets a -2 suffix.\n" +
2730
+ " # quadwork#478 + #502: force-replace\n" +
2684
2731
  " if force:\n" +
2685
2732
  " ghosts = [n for n, i in self._instances.items() if i.base == base]\n" +
2686
2733
  " for name in ghosts:\n" +
@@ -2694,7 +2741,6 @@ server.listen(PORT, "127.0.0.1", async () => {
2694
2741
  fs.writeFileSync(regPath, reg);
2695
2742
  console.log(`[ghost-fix] ${p.id}: patched registry.py with force-replace support`);
2696
2743
  } else if (!reg.includes("stale_reserved")) {
2697
- // #502: upgrade existing force-replace patch to also clear _reserved
2698
2744
  reg = reg.replace(
2699
2745
  /( +)for name in ghosts:\n\1 del self\._instances\[name\]\n\1 self\._reserved\[name\] = time\.time\(\)/,
2700
2746
  "$1for name in ghosts:\n$1 del self._instances[name]\n" +
@@ -2710,7 +2756,6 @@ server.listen(PORT, "127.0.0.1", async () => {
2710
2756
  console.warn(`[ghost-fix] ${p.id}: failed to patch registry.py: ${err.message}`);
2711
2757
  }
2712
2758
  }
2713
- // Patch app.py: pass force from request body to registry.register()
2714
2759
  const appPath = path.join(acDir, "app.py");
2715
2760
  if (fs.existsSync(appPath)) {
2716
2761
  try {
@@ -2727,33 +2772,22 @@ server.listen(PORT, "127.0.0.1", async () => {
2727
2772
  console.warn(`[ghost-fix] ${p.id}: failed to patch app.py: ${err.message}`);
2728
2773
  }
2729
2774
  }
2730
- // #502 + #629: increase crash timeout from 15s to 120s.
2731
- // Uses the shared patchCrashTimeout() from install-agentchattr.js.
2732
- // For existing installs where AC is already running, the on-disk
2733
- // patch alone is useless (Python caches module-level values at import).
2734
- // Flag the project for AC restart so the running process picks it up.
2735
2775
  if (fs.existsSync(appPath)) {
2736
2776
  try {
2737
2777
  const app = fs.readFileSync(appPath, "utf-8");
2738
2778
  if (app.includes("_CRASH_TIMEOUT = 15")) {
2739
2779
  patchCrashTimeout(acDir);
2740
- console.log(`[idle-fix] ${p.id}: crash timeout patched on disk — AC restart required for running process to observe it (#629)`);
2741
- if (!startupCfg._acRestartNeeded) startupCfg._acRestartNeeded = [];
2742
- startupCfg._acRestartNeeded.push(p.id);
2780
+ console.log(`[idle-fix] ${p.id}: crash timeout patched on disk`);
2781
+ acRestartNeeded.push(p.id);
2743
2782
  }
2744
2783
  } catch (err) {
2745
2784
  console.warn(`[idle-fix] ${p.id}: failed to patch app.py crash timeout: ${err.message}`);
2746
2785
  }
2747
2786
  }
2748
2787
  }
2749
- // #596: add CLI-based agent sections to existing config.toml files.
2750
- // Follow-up to #592 (PR #594) which added these for new projects.
2751
- // Existing projects still have role-based-only sections; if their AC
2752
- // drifts to HEAD, registration fails with "unknown base". This
2753
- // migration appends [agents.claude]/[agents.codex] etc. sections so
2754
- // HEAD AC accepts CLI-named bases. No AC restart needed — AC reads
2755
- // config.toml on its own startup.
2756
- for (const p of (startupCfg.projects || [])) {
2788
+
2789
+ // CLI-based agent sections
2790
+ for (const p of projects) {
2757
2791
  const acPath = projectAgentchattrConfigPath(p.id);
2758
2792
  if (!fs.existsSync(acPath)) continue;
2759
2793
  try {
@@ -2780,6 +2814,44 @@ server.listen(PORT, "127.0.0.1", async () => {
2780
2814
  console.warn(`[#596] ${p.id}: config.toml migration failed: ${err.message}`);
2781
2815
  }
2782
2816
  }
2817
+
2818
+ return acRestartNeeded;
2819
+ }
2820
+
2821
+ server.listen(PORT, "127.0.0.1", async () => {
2822
+ console.log(`QuadWork server listening on http://127.0.0.1:${PORT}`);
2823
+ syncTriggersFromConfig();
2824
+ // #579: detect AC processes already running (spawned by cmdStart before
2825
+ // the server module loaded). Without this, chattrProcesses is empty on
2826
+ // boot and the health monitor can't track cmdStart-spawned ACs, while
2827
+ // the dashboard's Start button would redundantly kill+respawn them.
2828
+ const startupCfg = readConfig();
2829
+ for (const p of (startupCfg.projects || [])) {
2830
+ const { url: acUrl } = resolveProjectChattr(p.id);
2831
+ const acPortMatch = acUrl.match(/:(\d+)/);
2832
+ const acPort = acPortMatch ? parseInt(acPortMatch[1], 10) : 8300;
2833
+ const alive = await isPortAlive(acPort);
2834
+ if (alive && !chattrProcesses.has(p.id)) {
2835
+ // AC is already running (e.g. spawned by cmdStart). Record it so
2836
+ // the health monitor can track it and the dashboard shows the
2837
+ // correct state. process is null because we don't own the child.
2838
+ chattrProcesses.set(p.id, { process: null, state: "running", error: null, runningSince: Date.now() });
2839
+ console.log(`[startup] ${p.id}: AC already alive on port ${acPort} — tracking`);
2840
+ }
2841
+ }
2842
+ // Sync AgentChattr tokens for all projects on startup and backfill
2843
+ // the sender-overflow CSS/JS patch (#402) so already-running AC
2844
+ // instances receive the fix without requiring a restart.
2845
+ // #448: retry after 5s for projects where AC isn't up yet at boot.
2846
+ for (const p of (startupCfg.projects || [])) {
2847
+ syncChattrToken(p.id).catch(() => {
2848
+ setTimeout(() => syncChattrToken(p.id).catch(() => {}), 5000);
2849
+ });
2850
+ const { dir: acDir } = resolveProjectChattr(p.id);
2851
+ if (acDir) patchAgentchattrCss(acDir);
2852
+ }
2853
+ const acRestartNeeded = runStartupMigrations(startupCfg);
2854
+ startupCfg._acRestartNeeded = acRestartNeeded.length > 0 ? acRestartNeeded : undefined;
2783
2855
  // #629: restart AC for projects where idle-fix patched the on-disk file
2784
2856
  // so the running Python process picks up _CRASH_TIMEOUT = 120.
2785
2857
  // Use port-alive check instead of chattrProcesses — AC may be running
package/server/routes.js CHANGED
@@ -1798,6 +1798,20 @@ function summarizeItems(items) {
1798
1798
  return parts.join(" · ");
1799
1799
  }
1800
1800
 
1801
+ router.get("/api/batch-active", (req, res) => {
1802
+ const projectId = req.query.project;
1803
+ if (!projectId) return res.status(400).json({ error: "Missing project" });
1804
+ if (!getRepo(projectId)) return res.status(400).json({ error: "No repo configured for project" });
1805
+ const queuePath = path.join(CONFIG_DIR, projectId, "OVERNIGHT-QUEUE.md");
1806
+ let active = false;
1807
+ try {
1808
+ const text = fs.readFileSync(queuePath, "utf-8");
1809
+ const { issueNumbers } = parseActiveBatch(text);
1810
+ active = issueNumbers.length > 0;
1811
+ } catch {}
1812
+ return res.json({ active });
1813
+ });
1814
+
1801
1815
  router.get("/api/batch-progress", async (req, res) => {
1802
1816
  const projectId = req.query.project;
1803
1817
  if (!projectId) return res.status(400).json({ error: "Missing project" });